diff options
Diffstat (limited to 'src/couch/priv/couch_js/68/http.cpp')
-rw-r--r-- | src/couch/priv/couch_js/68/http.cpp | 214 |
1 files changed, 77 insertions, 137 deletions
diff --git a/src/couch/priv/couch_js/68/http.cpp b/src/couch/priv/couch_js/68/http.cpp index a0c73bdc6..5153a126e 100644 --- a/src/couch/priv/couch_js/68/http.cpp +++ b/src/couch/priv/couch_js/68/http.cpp @@ -19,7 +19,6 @@ #include <js/Initialization.h> #include <js/MemoryFunctions.h> #include "config.h" -#include "utf8.h" #include "util.h" // Soft dependency on cURL bindings because they're @@ -101,7 +100,6 @@ http_check_enabled() #ifdef XP_WIN #define strcasecmp _strcmpi #define strncasecmp _strnicmp -#define snprintf _snprintf #endif @@ -110,7 +108,7 @@ typedef struct curl_slist CurlHeaders; typedef struct { int method; - char* url; + std::string url; CurlHeaders* req_headers; int16_t last_status; } HTTPData; @@ -128,22 +126,15 @@ const char* METHODS[] = {"GET", "HEAD", "POST", "PUT", "DELETE", "COPY", "OPTION #define OPTIONS 6 -static bool -go(JSContext* cx, JSObject* obj, HTTPData* http, char* body, size_t blen); - - -/*static JSString* -str_from_binary(JSContext* cx, char* data, size_t length); -*/ +static bool go(JSContext* cx, JSObject* obj, HTTPData* http, std::string& body); bool http_ctor(JSContext* cx, JSObject* req) { - HTTPData* http = NULL; + HTTPData* http = new HTTPData(); bool ret = false; - http = (HTTPData*) malloc(sizeof(HTTPData)); if(!http) { JS_ReportErrorUTF8(cx, "Failed to create CouchHTTP instance."); @@ -151,7 +142,6 @@ http_ctor(JSContext* cx, JSObject* req) } http->method = -1; - http->url = NULL; http->req_headers = NULL; http->last_status = -1; @@ -161,7 +151,7 @@ http_ctor(JSContext* cx, JSObject* req) goto success; error: - if(http) free(http); + if(http) delete http; success: return ret; @@ -173,9 +163,8 @@ http_dtor(JSFreeOp* fop, JSObject* obj) { HTTPData* http = (HTTPData*) JS_GetPrivate(obj); if(http) { - if(http->url) free(http->url); if(http->req_headers) curl_slist_free_all(http->req_headers); - free(http); + delete http; } } @@ -184,56 +173,50 @@ bool http_open(JSContext* cx, JSObject* req, JS::Value mth, JS::Value url, JS::Value snc) { HTTPData* http = (HTTPData*) JS_GetPrivate(req); - char* method = NULL; int methid; - bool ret = false; if(!http) { JS_ReportErrorUTF8(cx, "Invalid CouchHTTP instance."); - goto done; + return false; } - if(mth.isUndefined()) { - JS_ReportErrorUTF8(cx, "You must specify a method."); - goto done; + if(!mth.isString()) { + JS_ReportErrorUTF8(cx, "Method must be a string."); + return false; } - method = enc_string(cx, mth, NULL); - if(!method) { + std::string method; + if(!js_to_string(cx, JS::RootedValue(cx, mth), method)) { JS_ReportErrorUTF8(cx, "Failed to encode method."); - goto done; + return false; } for(methid = 0; METHODS[methid] != NULL; methid++) { - if(strcasecmp(METHODS[methid], method) == 0) break; + if(strcasecmp(METHODS[methid], method.c_str()) == 0) break; } if(methid > OPTIONS) { JS_ReportErrorUTF8(cx, "Invalid method specified."); - goto done; + return false; } http->method = methid; - if(url.isUndefined()) { - JS_ReportErrorUTF8(cx, "You must specify a URL."); - goto done; - } - - if(http->url != NULL) { - free(http->url); - http->url = NULL; + if(!url.isString()) { + JS_ReportErrorUTF8(cx, "URL must be a string"); + return false; } - http->url = enc_string(cx, url, NULL); - if(http->url == NULL) { + std::string urlstr; + if(!js_to_string(cx, JS::RootedValue(cx, url), urlstr)) { JS_ReportErrorUTF8(cx, "Failed to encode URL."); - goto done; + return false; } + http->url = urlstr; if(snc.isBoolean() && snc.isTrue()) { JS_ReportErrorUTF8(cx, "Synchronous flag must be false."); - goto done; + return false; } if(http->req_headers) { @@ -244,11 +227,7 @@ http_open(JSContext* cx, JSObject* req, JS::Value mth, JS::Value url, JS::Value // Disable Expect: 100-continue http->req_headers = curl_slist_append(http->req_headers, "Expect:"); - ret = true; - -done: - if(method) free(method); - return ret; + return true; } @@ -256,88 +235,60 @@ bool http_set_hdr(JSContext* cx, JSObject* req, JS::Value name, JS::Value val) { HTTPData* http = (HTTPData*) JS_GetPrivate(req); - char* keystr = NULL; - char* valstr = NULL; - char* hdrbuf = NULL; - size_t hdrlen = -1; - bool ret = false; if(!http) { JS_ReportErrorUTF8(cx, "Invalid CouchHTTP instance."); - goto done; + return false; } - if(name.isUndefined()) + if(!name.isString()) { - JS_ReportErrorUTF8(cx, "You must speciy a header name."); - goto done; + JS_ReportErrorUTF8(cx, "Header names must be strings."); + return false; } - keystr = enc_string(cx, name, NULL); - if(!keystr) + std::string keystr; + if(!js_to_string(cx, JS::RootedValue(cx, name), keystr)) { JS_ReportErrorUTF8(cx, "Failed to encode header name."); - goto done; + return false; } - if(val.isUndefined()) + if(!val.isString()) { - JS_ReportErrorUTF8(cx, "You must specify a header value."); - goto done; + JS_ReportErrorUTF8(cx, "Header values must be strings."); + return false; } - valstr = enc_string(cx, val, NULL); - if(!valstr) - { + std::string valstr; + if(!js_to_string(cx, JS::RootedValue(cx, val), valstr)) { JS_ReportErrorUTF8(cx, "Failed to encode header value."); - goto done; - } - - hdrlen = strlen(keystr) + strlen(valstr) + 3; - hdrbuf = (char*) malloc(hdrlen * sizeof(char)); - if(!hdrbuf) { - JS_ReportErrorUTF8(cx, "Failed to allocate header buffer."); - goto done; + return false; } - snprintf(hdrbuf, hdrlen, "%s: %s", keystr, valstr); - http->req_headers = curl_slist_append(http->req_headers, hdrbuf); - - ret = true; + std::string header = keystr + ": " + valstr; + http->req_headers = curl_slist_append(http->req_headers, header.c_str()); -done: - if(keystr) free(keystr); - if(valstr) free(valstr); - if(hdrbuf) free(hdrbuf); - return ret; + return true; } bool http_send(JSContext* cx, JSObject* req, JS::Value body) { HTTPData* http = (HTTPData*) JS_GetPrivate(req); - char* bodystr = NULL; - size_t bodylen = 0; - bool ret = false; if(!http) { JS_ReportErrorUTF8(cx, "Invalid CouchHTTP instance."); - goto done; + return false; } - if(!body.isUndefined()) { - bodystr = enc_string(cx, body, &bodylen); - if(!bodystr) { - JS_ReportErrorUTF8(cx, "Failed to encode body."); - goto done; - } + std::string bodystr; + if(!js_to_string(cx, JS::RootedValue(cx, body), bodystr)) { + JS_ReportErrorUTF8(cx, "Failed to encode body."); + return false; } - ret = go(cx, req, http, bodystr, bodylen); - -done: - if(bodystr) free(bodystr); - return ret; + return go(cx, req, http, bodystr); } int @@ -397,7 +348,7 @@ typedef struct { HTTPData* http; JSContext* cx; JSObject* resp_headers; - char* sendbuf; + const char* sendbuf; size_t sendlen; size_t sent; int sent_once; @@ -419,10 +370,9 @@ static size_t recv_body(void *ptr, size_t size, size_t nmem, void *data); static size_t recv_header(void *ptr, size_t size, size_t nmem, void *data); static bool -go(JSContext* cx, JSObject* obj, HTTPData* http, char* body, size_t bodylen) +go(JSContext* cx, JSObject* obj, HTTPData* http, std::string& body) { CurlState state; - char* referer; JSString* jsbody; bool ret = false; JS::Value tmp; @@ -433,8 +383,8 @@ go(JSContext* cx, JSObject* obj, HTTPData* http, char* body, size_t bodylen) state.cx = cx; state.http = http; - state.sendbuf = body; - state.sendlen = bodylen; + state.sendbuf = body.c_str(); + state.sendlen = body.size(); state.sent = 0; state.sent_once = 0; @@ -465,13 +415,13 @@ go(JSContext* cx, JSObject* obj, HTTPData* http, char* body, size_t bodylen) tmp = JS_GetReservedSlot(obj, 0); - if(!(referer = enc_string(cx, tmp, NULL))) { + std::string referer; + if(!js_to_string(cx, JS::RootedValue(cx, tmp), referer)) { JS_ReportErrorUTF8(cx, "Failed to encode referer."); if(state.recvbuf) JS_free(cx, state.recvbuf); - return ret; + return ret; } - curl_easy_setopt(HTTP_HANDLE, CURLOPT_REFERER, referer); - free(referer); + curl_easy_setopt(HTTP_HANDLE, CURLOPT_REFERER, referer.c_str()); if(http->method < 0 || http->method > OPTIONS) { JS_ReportErrorUTF8(cx, "INTERNAL: Unknown method."); @@ -492,15 +442,15 @@ go(JSContext* cx, JSObject* obj, HTTPData* http, char* body, size_t bodylen) curl_easy_setopt(HTTP_HANDLE, CURLOPT_FOLLOWLOCATION, 0); } - if(body && bodylen) { - curl_easy_setopt(HTTP_HANDLE, CURLOPT_INFILESIZE, bodylen); + if(body.size() > 0) { + curl_easy_setopt(HTTP_HANDLE, CURLOPT_INFILESIZE, body.size()); } else { curl_easy_setopt(HTTP_HANDLE, CURLOPT_INFILESIZE, 0); } // curl_easy_setopt(HTTP_HANDLE, CURLOPT_VERBOSE, 1); - curl_easy_setopt(HTTP_HANDLE, CURLOPT_URL, http->url); + curl_easy_setopt(HTTP_HANDLE, CURLOPT_URL, http->url.c_str()); curl_easy_setopt(HTTP_HANDLE, CURLOPT_HTTPHEADER, http->req_headers); curl_easy_setopt(HTTP_HANDLE, CURLOPT_READDATA, &state); curl_easy_setopt(HTTP_HANDLE, CURLOPT_SEEKDATA, &state); @@ -534,7 +484,8 @@ go(JSContext* cx, JSObject* obj, HTTPData* http, char* body, size_t bodylen) if(state.recvbuf) { state.recvbuf[state.read] = '\0'; - jsbody = dec_string(cx, state.recvbuf, state.read+1); + std::string bodystr(state.recvbuf, state.read); + jsbody = string_to_js(cx, bodystr); if(!jsbody) { // If we can't decode the body as UTF-8 we forcefully // convert it to a string by just forcing each byte @@ -574,7 +525,7 @@ go(JSContext* cx, JSObject* obj, HTTPData* http, char* body, size_t bodylen) static size_t send_body(void *ptr, size_t size, size_t nmem, void *data) { - CurlState* state = (CurlState*) data; + CurlState* state = static_cast<CurlState*>(data); size_t length = size * nmem; size_t towrite = state->sendlen - state->sent; @@ -600,19 +551,19 @@ send_body(void *ptr, size_t size, size_t nmem, void *data) static int seek_body(void* ptr, curl_off_t offset, int origin) { - CurlState* state = (CurlState*) ptr; + CurlState* state = static_cast<CurlState*>(ptr); if(origin != SEEK_SET) return -1; - state->sent = (size_t) offset; - return (int) state->sent; + state->sent = static_cast<size_t>(offset); + return static_cast<int>(state->sent); } static size_t recv_header(void *ptr, size_t size, size_t nmem, void *data) { - CurlState* state = (CurlState*) data; + CurlState* state = static_cast<CurlState*>(data); char code[4]; - char* header = (char*) ptr; + char* header = static_cast<char*>(ptr); size_t length = size * nmem; JSString* hdr = NULL; uint32_t hdrlen; @@ -640,7 +591,8 @@ recv_header(void *ptr, size_t size, size_t nmem, void *data) } // Append the new header to our array. - hdr = dec_string(state->cx, header, length); + std::string hdrstr(header, length); + hdr = string_to_js(state->cx, hdrstr); if(!hdr) { return CURLE_WRITE_ERROR; } @@ -661,14 +613,17 @@ recv_header(void *ptr, size_t size, size_t nmem, void *data) static size_t recv_body(void *ptr, size_t size, size_t nmem, void *data) { - CurlState* state = (CurlState*) data; + CurlState* state = static_cast<CurlState*>(data); size_t length = size * nmem; char* tmp = NULL; if(!state->recvbuf) { state->recvlen = 4096; state->read = 0; - state->recvbuf = static_cast<char *>(JS_malloc(state->cx, state->recvlen)); + state->recvbuf = static_cast<char*>(JS_malloc( + state->cx, + state->recvlen + )); } if(!state->recvbuf) { @@ -678,7 +633,12 @@ recv_body(void *ptr, size_t size, size_t nmem, void *data) // +1 so we can add '\0' back up in the go function. size_t oldlen = state->recvlen; while(length+1 > state->recvlen - state->read) state->recvlen *= 2; - tmp = static_cast<char *>(JS_realloc(state->cx, state->recvbuf, oldlen, state->recvlen)); + tmp = static_cast<char*>(JS_realloc( + state->cx, + state->recvbuf, + oldlen, + state->recvlen + )); if(!tmp) return CURLE_WRITE_ERROR; state->recvbuf = tmp; @@ -687,24 +647,4 @@ recv_body(void *ptr, size_t size, size_t nmem, void *data) return length; } -/*JSString* -str_from_binary(JSContext* cx, char* data, size_t length) -{ - char16_t* conv = static_cast<char16_t *>(JS_malloc(cx, length * sizeof(char16_t))); - JSString* ret = NULL; - size_t i; - - if(!conv) return NULL; - - for(i = 0; i < length; i++) { - conv[i] = (char16_t) data[i]; - } - - ret = JS_NewUCString(cx, conv, length); - if(!ret) JS_free(cx, conv); - - return ret; -} -*/ - #endif /* HAVE_CURL */ |