X-Git-Url: https://git.saurik.com/cycript.git/blobdiff_plain/8a199b13bf5ee472fbf9338eab33db123b81c10f..dc68b74c75a69f269748d1c28bbfa8b20b6d9e9f:/Server.cpp diff --git a/Server.cpp b/Server.cpp new file mode 100644 index 0000000..bf7c17c --- /dev/null +++ b/Server.cpp @@ -0,0 +1,160 @@ +/* Cycript - Remove Execution Server and Disassembler + * Copyright (C) 2009 Jay Freeman (saurik) +*/ + +/* Modified BSD License {{{ */ +/* + * Redistribution and use in source and binary + * forms, with or without modification, are permitted + * provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the + * above copyright notice, this list of conditions + * and the following disclaimer. + * 2. Redistributions in binary form must reproduce the + * above copyright notice, this list of conditions + * and the following disclaimer in the documentation + * and/or other materials provided with the + * distribution. + * 3. The name of the author may not be used to endorse + * or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +/* }}} */ + +#include + +#include + +#include +#include + +#include +#include +#include +#include + +struct Client { + CFHTTPMessageRef message_; + CFSocketRef socket_; +}; + +static void OnData(CFSocketRef socket, CFSocketCallBackType type, CFDataRef address, const void *value, void *info) { + switch (type) { + case kCFSocketDataCallBack: + CFDataRef data(reinterpret_cast(value)); + Client *client(reinterpret_cast(info)); + + if (client->message_ == NULL) + client->message_ = CFHTTPMessageCreateEmpty(kCFAllocatorDefault, TRUE); + + if (!CFHTTPMessageAppendBytes(client->message_, CFDataGetBytePtr(data), CFDataGetLength(data))) + CFLog(kCFLogLevelError, CFSTR("CFHTTPMessageAppendBytes()")); + else if (CFHTTPMessageIsHeaderComplete(client->message_)) { + CFURLRef url(CFHTTPMessageCopyRequestURL(client->message_)); + Boolean absolute; + CFStringRef path(CFURLCopyStrictPath(url, &absolute)); + CFRelease(client->message_); + + CFStringRef code(CFURLCreateStringByReplacingPercentEscapes(kCFAllocatorDefault, path, CFSTR(""))); + CFRelease(path); + + JSStringRef script(JSStringCreateWithCFString(code)); + CFRelease(code); + + JSValueRef result(JSEvaluateScript(CYGetJSContext(), script, NULL, NULL, 0, NULL)); + JSStringRelease(script); + + CFHTTPMessageRef response(CFHTTPMessageCreateResponse(kCFAllocatorDefault, 200, NULL, kCFHTTPVersion1_1)); + CFHTTPMessageSetHeaderFieldValue(response, CFSTR("Content-Type"), CFSTR("application/json; charset=utf-8")); + + CFStringRef json(CYCopyJSONString(CYGetJSContext(), result, NULL)); + CFDataRef body(CFStringCreateExternalRepresentation(kCFAllocatorDefault, json, kCFStringEncodingUTF8, NULL)); + CFRelease(json); + + CFStringRef length(CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%u"), CFDataGetLength(body))); + CFHTTPMessageSetHeaderFieldValue(response, CFSTR("Content-Length"), length); + CFRelease(length); + + CFHTTPMessageSetBody(response, body); + CFRelease(body); + + CFDataRef serialized(CFHTTPMessageCopySerializedMessage(response)); + CFRelease(response); + + CFSocketSendData(socket, NULL, serialized, 0); + CFRelease(serialized); + + CFRelease(url); + } + break; + } +} + +static void OnAccept(CFSocketRef socket, CFSocketCallBackType type, CFDataRef address, const void *value, void *info) { + switch (type) { + case kCFSocketAcceptCallBack: + Client *client(new Client()); + + client->message_ = NULL; + + CFSocketContext context; + context.version = 0; + context.info = client; + context.retain = NULL; + context.release = NULL; + context.copyDescription = NULL; + + client->socket_ = CFSocketCreateWithNative(kCFAllocatorDefault, *reinterpret_cast(value), kCFSocketDataCallBack, &OnData, &context); + + CFRunLoopAddSource(CFRunLoopGetCurrent(), CFSocketCreateRunLoopSource(kCFAllocatorDefault, client->socket_, 0), kCFRunLoopDefaultMode); + break; + } +} + +int main(int argc, char *argv[]) { + { + struct sockaddr_in address; + address.sin_len = sizeof(address); + address.sin_family = AF_INET; + address.sin_addr.s_addr = INADDR_ANY; + address.sin_port = htons(787); + + CFDataRef data(CFDataCreate(kCFAllocatorDefault, reinterpret_cast(&address), sizeof(address))); + + CFSocketSignature signature; + signature.protocolFamily = AF_INET; + signature.socketType = SOCK_STREAM; + signature.protocol = IPPROTO_TCP; + signature.address = data; + + CFSocketRef socket(CFSocketCreateWithSocketSignature(kCFAllocatorDefault, &signature, kCFSocketAcceptCallBack, &OnAccept, NULL)); + CFRunLoopAddSource(CFRunLoopGetCurrent(), CFSocketCreateRunLoopSource(kCFAllocatorDefault, socket, 0), kCFRunLoopDefaultMode); + } + + { + CYServer *server(new CYServer()); + server->socket_ = _syscall(socket(PF_UNIX, SOCK_STREAM, 0)); + + struct sockaddr_un address; + memset(&address, 0, sizeof(address)); + address.sun_family = AF_UNIX; + + sprintf(address.sun_path, "/tmp/.s.cy"); + } +}