*/
#include <substrate.h>
+#include <sys/sysctl.h>
#import <GraphicsServices/GraphicsServices.h>
#import <UIKit/UIKit.h>
/* }}} */
/* Cydget-PHP:// Protocol {{{ */
@interface CydgetPHPURLProtocol : NSURLProtocol {
+ pid_t pid_;
+ CFHTTPMessageRef http_;
}
@end
return request;
}
+- (id) initWithRequest:(NSURLRequest *)request cachedResponse:(NSCachedURLResponse *)response client:(id<NSURLProtocolClient>)client {
+ if ((self = [super initWithRequest:request cachedResponse:response client:client]) != nil) {
+ pid_ = -1;
+ } return self;
+}
+
- (void) startLoading {
id<NSURLProtocolClient> client([self client]);
NSURLRequest *request([self request]);
return;
}
- NSLog(@"%@::%@", path, [url query]);
-
int fds[2];
_assert(pipe(fds) != -1);
- pid_t pid(fork());
- if (pid == 0) {
+ _assert(pid_ == -1);
+ pid_ = fork();
+ if (pid_ == -1) {
+ _assert(close(fds[0]) != -1);
+ _assert(close(fds[1]) != -1);
+ [client URLProtocol:self didFailWithError:[NSError errorWithDomain:NSURLErrorDomain code:NSURLErrorResourceUnavailable userInfo:nil]];
+ return;
+ }
+
+ if (pid_ == 0) {
setenv("GATEWAY_INTERFACE", "CGI/1.1", true);
setenv("SCRIPT_FILENAME", [path UTF8String], true);
NSString *query([url query]);
_assert(close(fds[1]) != -1);
- CFHTTPMessageRef http(CFHTTPMessageCreateEmpty(kCFAllocatorDefault, FALSE));
+ _assert(http_ == NULL);
+ http_ = CFHTTPMessageCreateEmpty(kCFAllocatorDefault, FALSE);
+ CFHTTPMessageAppendBytes(http_, (const uint8_t *) "HTTP/1.1 200 OK\r\n", 17);
- CFHTTPMessageAppendBytes(http, (const uint8_t *) "HTTP/1.1 200 OK\r\n", 17);
+ NSFileHandle *handle([[NSFileHandle alloc] initWithFileDescriptor:fds[0] closeOnDealloc:YES]);
- if (FILE *file = fdopen(fds[0], "r")) {
- uint8_t buffer[16*1024];
- read:
- size_t count(fread(buffer, 1, sizeof(buffer), file));
- if (count != 0) {
- fwrite(buffer, 1, count, stderr);
- CFHTTPMessageAppendBytes(http, buffer, count);
- }
- if (count == sizeof(buffer))
- goto read;
- if (ferror(file)) {
- [client URLProtocol:self didFailWithError:[NSError errorWithDomain:NSURLErrorDomain code:NSURLErrorNetworkConnectionLost userInfo:nil]];
- fclose(file);
- goto fail;
- }
- fclose(file);
- } else _assert(close(fds[0]));
+ [[NSNotificationCenter defaultCenter]
+ addObserver:self
+ selector:@selector(onRead:)
+ name:@"NSFileHandleReadCompletionNotification"
+ object:handle
+ ];
- {
- CFStringRef mime(CFHTTPMessageCopyHeaderFieldValue(http, CFSTR("Content-type")));
- if (mime == NULL) {
- [client URLProtocol:self didFailWithError:[NSError errorWithDomain:NSURLErrorDomain code:NSURLErrorBadServerResponse userInfo:nil]];
- goto fail;
- }
+ [handle readInBackgroundAndNotify];
- NSURLResponse *response([[[NSURLResponse alloc] initWithURL:[request URL] MIMEType:(NSString *)mime expectedContentLength:-1 textEncodingName:nil] autorelease]);
- CFRelease(mime);
+ [handle release];
+}
- [client URLProtocol:self didReceiveResponse:response cacheStoragePolicy:NSURLCacheStorageNotAllowed];
+- (void) onRead:(NSNotification *)notification {
+ NSFileHandle *handle([notification object]);
- CFDataRef data(CFHTTPMessageCopyBody(http));
- [client URLProtocol:self didLoadData:(NSData *)data];
- CFRelease(data);
+ NSData *data([[notification userInfo] objectForKey:NSFileHandleNotificationDataItem]);
- [client URLProtocolDidFinishLoading:self];
- }
+ if (size_t length = [data length]) {
+ CFHTTPMessageAppendBytes(http_, reinterpret_cast<const UInt8 *>([data bytes]), length);
+ [handle readInBackgroundAndNotify];
+ } else {
+ id<NSURLProtocolClient> client([self client]);
+
+ CFStringRef mime(CFHTTPMessageCopyHeaderFieldValue(http_, CFSTR("Content-type")));
+ if (mime == NULL)
+ [client URLProtocol:self didFailWithError:[NSError errorWithDomain:NSURLErrorDomain code:NSURLErrorBadServerResponse userInfo:nil]];
+ else {
+ NSURLRequest *request([self request]);
+
+ NSURLResponse *response([[[NSURLResponse alloc] initWithURL:[request URL] MIMEType:(NSString *)mime expectedContentLength:-1 textEncodingName:nil] autorelease]);
+ CFRelease(mime);
- fail:
- CFRelease(http);
+ [client URLProtocol:self didReceiveResponse:response cacheStoragePolicy:NSURLCacheStorageNotAllowed];
- int status;
- _syscall(waitpid(pid, &status, 0));
+ CFDataRef body(CFHTTPMessageCopyBody(http_));
+ [client URLProtocol:self didLoadData:(NSData *)body];
+ CFRelease(body);
+
+ [client URLProtocolDidFinishLoading:self];
+ }
+
+ CFRelease(http_);
+ http_ = NULL;
+ }
}
+ //[client URLProtocol:self didFailWithError:[NSError errorWithDomain:NSURLErrorDomain code:NSURLErrorNetworkConnectionLost userInfo:nil]];
+
- (void) stopLoading {
+ if (pid_ != -1) {
+ kill(pid_, SIGTERM);
+ int status;
+ _syscall(waitpid(pid_, &status, 0));
+ pid_ = -1;
+ }
}
@end
@implementation WebCycriptLockScreenController
+ (void) initialize {
+ int maxproc;
+ size_t size(sizeof(maxproc));
+ if (sysctlbyname("kern.maxproc", &maxproc, &size, NULL, 0) == -1)
+ NSLog(@"sysctlbyname(\"kern.maxproc\", ?)");
+ else if (maxproc < 72) {
+ maxproc = 72;
+ if (sysctlbyname("kern.maxproc", NULL, NULL, &maxproc, sizeof(maxproc)) == -1)
+ NSLog(@"sysctlbyname(\"kern.maxproc\", #)");
+ }
+
apr_initialize();
[NSURLProtocol registerClass:[CydgetURLProtocol class]];