static void OnData(CFSocketRef socket, CFSocketCallBackType type, CFDataRef address, const void *value, void *info) { switch (type) { case kCFSocketDataCallBack: CFDataRef data(reinterpret_cast<CFDataRef>(value)); Client *client(reinterpret_cast<Client *>(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 do_upload__string( SG_context* pCtx, const char* pszUrl, const char* psz_method, SG_pathname* pPath, const char* psz_username, const char* psz_password, SG_string** ppstr ) { SG_string* pstr = NULL; CFHTTPMessageRef myRequest = NULL; CFHTTPMessageRef myResponse = NULL; CFStringRef s_username = NULL; CFStringRef s_password = NULL; SG_ERR_CHECK( make_request(pCtx, pszUrl, psz_method, NULL, &myRequest) ); SG_ERR_CHECK( perform_upload_request__string(pCtx, myRequest, pPath, &myResponse, &pstr) ); #if 0 { CFDataRef d = CFHTTPMessageCopySerializedMessage(myResponse); fprintf(stderr, "%s\n", CFDataGetBytePtr(d)); CFRelease(d); } #endif UInt32 statusCode = CFHTTPMessageGetResponseStatusCode(myResponse); if ( psz_username && psz_password && (statusCode == 401 || statusCode == 407) ) { s_username = CFStringCreateWithCString(kCFAllocatorDefault, psz_username, kCFStringEncodingUTF8); s_password = CFStringCreateWithCString(kCFAllocatorDefault, psz_password, kCFStringEncodingUTF8); if (!CFHTTPMessageAddAuthentication(myRequest, myResponse, s_username, s_password, kCFHTTPAuthenticationSchemeDigest, FALSE)) { SG_ERR_THROW2(SG_ERR_UNSPECIFIED, (pCtx, "CFHTTPMessageAddAuthentication failed")); } #if 0 { CFDataRef d = CFHTTPMessageCopySerializedMessage(myRequest); fprintf(stderr, "%s\n", CFDataGetBytePtr(d)); CFRelease(d); } #endif CFRelease(s_username); s_username = NULL; CFRelease(s_password); s_password = NULL; CFRelease(myResponse); myResponse = NULL; SG_STRING_NULLFREE(pCtx, pstr); SG_ERR_CHECK( perform_upload_request__string(pCtx, myRequest, pPath, &myResponse, &pstr) ); #if 0 { CFDataRef d = CFHTTPMessageCopySerializedMessage(myResponse); fprintf(stderr, "%s\n", CFDataGetBytePtr(d)); CFRelease(d); } #endif statusCode = CFHTTPMessageGetResponseStatusCode(myResponse); } if (statusCode != 200) { SG_ERR_THROW2_RETURN(SG_ERR_SERVER_HTTP_ERROR, (pCtx, "%d", (int) statusCode)); } *ppstr = pstr; pstr = NULL; /* fall through */ fail: if (s_username) { CFRelease(s_username); s_username = NULL; } if (s_password) { CFRelease(s_password); s_password = NULL; } if (myRequest) { CFRelease(myRequest); myRequest = NULL; } if (myResponse) { CFRelease(myResponse); myResponse = NULL; } SG_STRING_NULLFREE(pCtx, pstr); }
// TODO give this a better name. It gets used outside this file now. void do_url( SG_context* pCtx, const char* pszUrl, const char* psz_method, const char* psz_data, const char* psz_username, const char* psz_password, SG_string** ppstr, SG_pathname* pPath, SG_bool b_progress ) { SG_string* pstr = NULL; CFHTTPMessageRef myRequest = NULL; CFHTTPMessageRef myResponse = NULL; CFStringRef s_username = NULL; CFStringRef s_password = NULL; if (pPath && ppstr) { SG_ERR_RESET_THROW2(SG_ERR_INVALIDARG, (pCtx, "do_url() returns into a string or a file, but not both")); } if (!pPath && !ppstr) { SG_ERR_RESET_THROW2(SG_ERR_INVALIDARG, (pCtx, "do_url() returns into a string or a file, one or the other")); } SG_ERR_CHECK( make_request(pCtx, pszUrl, psz_method, psz_data, &myRequest) ); #if 0 { CFDataRef d = CFHTTPMessageCopySerializedMessage(myRequest); fprintf(stderr, "%s\n", CFDataGetBytePtr(d)); CFRelease(d); } #endif if (pPath) { SG_ERR_CHECK( perform_request__file(pCtx, myRequest, &myResponse, pPath, b_progress) ); } else { SG_ERR_CHECK( perform_request__string(pCtx, myRequest, &myResponse, &pstr) ); } if (!myResponse) { SG_ERR_THROW2(SG_ERR_UNSPECIFIED, (pCtx, "No response from server")); } //fprintf(stderr, "\n%s\n", SG_string__sz(pstr)); UInt32 statusCode = CFHTTPMessageGetResponseStatusCode(myResponse); #if 0 { CFDataRef d = CFHTTPMessageCopySerializedMessage(myResponse); fprintf(stderr, "%s\n", CFDataGetBytePtr(d)); CFRelease(d); } #endif if ( psz_username && psz_password && (statusCode == 401 || statusCode == 407) ) { s_username = CFStringCreateWithCString(kCFAllocatorDefault, psz_username, kCFStringEncodingUTF8); s_password = CFStringCreateWithCString(kCFAllocatorDefault, psz_password, kCFStringEncodingUTF8); if (!CFHTTPMessageAddAuthentication(myRequest, myResponse, s_username, s_password, kCFHTTPAuthenticationSchemeDigest, FALSE)) { SG_ERR_THROW2(SG_ERR_UNSPECIFIED, (pCtx, "CFHTTPMessageAddAuthentication failed")); } #if 0 { CFDataRef d = CFHTTPMessageCopySerializedMessage(myRequest); fprintf(stderr, "%s\n", CFDataGetBytePtr(d)); CFRelease(d); } #endif CFRelease(s_username); s_username = NULL; CFRelease(s_password); s_password = NULL; CFRelease(myResponse); myResponse = NULL; if (pPath) { SG_ERR_IGNORE( SG_fsobj__remove__pathname(pCtx, pPath) ); SG_ERR_CHECK( perform_request__file(pCtx, myRequest, &myResponse, pPath, b_progress) ); } else { SG_STRING_NULLFREE(pCtx, pstr); SG_ERR_CHECK( perform_request__string(pCtx, myRequest, &myResponse, &pstr) ); } #if 0 { CFDataRef d = CFHTTPMessageCopySerializedMessage(myResponse); fprintf(stderr, "%s\n", CFDataGetBytePtr(d)); CFRelease(d); } #endif statusCode = CFHTTPMessageGetResponseStatusCode(myResponse); } if (statusCode != 200) { if (401 == statusCode) { SG_ERR_THROW(SG_ERR_HTTP_401); } else if (404 == statusCode) { SG_ERR_THROW(SG_ERR_HTTP_404); } else if (502 == statusCode) { SG_ERR_THROW(SG_ERR_HTTP_502); } else { SG_ERR_THROW2(SG_ERR_SERVER_HTTP_ERROR, (pCtx, "%d", (int) statusCode)); } } if (ppstr) { *ppstr = pstr; pstr = NULL; } /* fall through */ fail: if (s_username) { CFRelease(s_username); s_username = NULL; } if (s_password) { CFRelease(s_password); s_password = NULL; } if (myRequest) { CFRelease(myRequest); myRequest = NULL; } if (myResponse) { CFRelease(myResponse); myResponse = NULL; } SG_STRING_NULLFREE(pCtx, pstr); }