diff options
Diffstat (limited to 'apps/couch/c_src')
-rw-r--r-- | apps/couch/c_src/couch_js/SConscript | 53 | ||||
-rw-r--r-- | apps/couch/c_src/couch_js/http.c | 684 | ||||
-rw-r--r-- | apps/couch/c_src/couch_js/http.h | 18 | ||||
-rw-r--r-- | apps/couch/c_src/couch_js/main.c | 345 | ||||
-rw-r--r-- | apps/couch/c_src/couch_js/utf8.c | 293 | ||||
-rw-r--r-- | apps/couch/c_src/couch_js/utf8.h | 19 |
6 files changed, 0 insertions, 1412 deletions
diff --git a/apps/couch/c_src/couch_js/SConscript b/apps/couch/c_src/couch_js/SConscript deleted file mode 100644 index b459ee94..00000000 --- a/apps/couch/c_src/couch_js/SConscript +++ /dev/null @@ -1,53 +0,0 @@ -# Copyright (c) 2010 Cloudant -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -def require_lib(name): - if not conf.CheckLib(name): - print 'Could not find required library', name - Exit(1) - -env = Environment(CCFLAGS='-g -O2 -DXP_UNIX') -if not env.GetOption('clean'): - conf = Configure(env, config_h='config.h') - - require_lib('m') - require_lib('pthread') - require_lib('curl') - - ## check for SpiderMonkey development header - if conf.CheckHeader('js/jsapi.h'): - jsapi = 'js/jsapi.h' - elif conf.CheckHeader('mozjs/jsapi.h'): - jsapi = 'mozjs/jsapi.h' - elif conf.CheckHeader('jsapi.h'): - jsapi = 'jsapi.h' - else: - print 'Could not find jsapi.h.', \ - 'Are Mozilla SpiderMonkey headers installed?' - Exit(1) - - ## check for SpiderMonkey library as libjs or libmozjs - if not conf.CheckLibWithHeader('mozjs', jsapi, 'c', autoadd=1): - if not conf.CheckLibWithHeader('js', jsapi, 'c', autoadd=1): - print 'Could not find JS library.', \ - 'Is Mozilla SpiderMonkey installed?' - Exit(1) - - ## SpiderMonkey 1.8 has this callback we use for memory management - if conf.CheckDeclaration('JS_SetOperationCallback', '#include <%s>' % jsapi): - conf.Define('USE_JS_SETOPCB') - - env = conf.Finish() - -env.Program('couchjs', ['main.c', 'http.c', 'utf8.c']) diff --git a/apps/couch/c_src/couch_js/http.c b/apps/couch/c_src/couch_js/http.c deleted file mode 100644 index b781f0ef..00000000 --- a/apps/couch/c_src/couch_js/http.c +++ /dev/null @@ -1,684 +0,0 @@ -// Licensed under the Apache License, Version 2.0 (the "License"); you may not -// use this file except in compliance with the License. You may obtain a copy of -// the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -// License for the specific language governing permissions and limitations under -// the License. - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include "config.h" -#ifdef HAVE_JS_JSAPI_H -#include <js/jsapi.h> -#elif HAVE_MOZJS_JSAPI_H -#include <mozjs/jsapi.h> -#else -#include <jsapi.h> -#endif - -#include <curl/curl.h> - -#include "utf8.h" - -#ifdef XP_WIN -// Map some of the string function names to things which exist on Windows -#define strcasecmp _strcmpi -#define strncasecmp _strnicmp -#define snprintf _snprintf -#endif - -typedef struct curl_slist CurlHeaders; - -typedef struct { - int method; - char* url; - CurlHeaders* req_headers; - jsint last_status; -} HTTPData; - -char* METHODS[] = {"GET", "HEAD", "POST", "PUT", "DELETE", "COPY", NULL}; - -#define GET 0 -#define HEAD 1 -#define POST 2 -#define PUT 3 -#define DELETE 4 -#define COPY 5 - -static JSBool -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 JSBool -constructor(JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval) -{ - HTTPData* http = NULL; - JSBool ret = JS_FALSE; - - http = (HTTPData*) malloc(sizeof(HTTPData)); - if(!http) - { - JS_ReportError(cx, "Failed to create CouchHTTP instance."); - goto error; - } - - http->method = -1; - http->url = NULL; - http->req_headers = NULL; - http->last_status = -1; - - if(!JS_SetPrivate(cx, obj, http)) - { - JS_ReportError(cx, "Failed to set private CouchHTTP data."); - goto error; - } - - ret = JS_TRUE; - goto success; - -error: - if(http) free(http); - -success: - return ret; -} - -static void -destructor(JSContext* cx, JSObject* obj) -{ - HTTPData* http = (HTTPData*) JS_GetPrivate(cx, obj); - if(!http) - { - fprintf(stderr, "Unable to destroy invalid CouchHTTP instance.\n"); - } - else - { - if(http->url) free(http->url); - if(http->req_headers) curl_slist_free_all(http->req_headers); - free(http); - } -} - -static JSBool -open(JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval) -{ - HTTPData* http = (HTTPData*) JS_GetPrivate(cx, obj); - char* method = NULL; - char* url = NULL; - JSBool ret = JS_FALSE; - int methid; - - if(!http) - { - JS_ReportError(cx, "Invalid CouchHTTP instance."); - goto done; - } - - if(argv[0] == JSVAL_VOID) - { - JS_ReportError(cx, "You must specify a method."); - goto done; - } - - method = enc_string(cx, argv[0], NULL); - if(!method) - { - JS_ReportError(cx, "Failed to encode method."); - goto done; - } - - for(methid = 0; METHODS[methid] != NULL; methid++) - { - if(strcasecmp(METHODS[methid], method) == 0) break; - } - - if(methid > COPY) - { - JS_ReportError(cx, "Invalid method specified."); - goto done; - } - - http->method = methid; - - if(argv[1] == JSVAL_VOID) - { - JS_ReportError(cx, "You must specify a URL."); - goto done; - } - - if(http->url) - { - free(http->url); - http->url = NULL; - } - - http->url = enc_string(cx, argv[1], NULL); - if(!http->url) - { - JS_ReportError(cx, "Failed to encode URL."); - goto done; - } - - if(argv[2] != JSVAL_VOID && argv[2] != JSVAL_FALSE) - { - JS_ReportError(cx, "Synchronous flag must be false if specified."); - goto done; - } - - if(http->req_headers) - { - curl_slist_free_all(http->req_headers); - http->req_headers = NULL; - } - - // Disable Expect: 100-continue - http->req_headers = curl_slist_append(http->req_headers, "Expect:"); - - ret = JS_TRUE; - -done: - if(method) free(method); - return ret; -} - -static JSBool -setheader(JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval) -{ - HTTPData* http = (HTTPData*) JS_GetPrivate(cx, obj); - char* keystr = NULL; - char* valstr = NULL; - char* hdrbuf = NULL; - size_t hdrlen = -1; - JSBool ret = JS_FALSE; - - if(!http) - { - JS_ReportError(cx, "Invalid CouchHTTP instance."); - goto done; - } - - if(argv[0] == JSVAL_VOID) - { - JS_ReportError(cx, "You must speciy a header name."); - goto done; - } - - keystr = enc_string(cx, argv[0], NULL); - if(!keystr) - { - JS_ReportError(cx, "Failed to encode header name."); - goto done; - } - - if(argv[1] == JSVAL_VOID) - { - JS_ReportError(cx, "You must specify a header value."); - goto done; - } - - valstr = enc_string(cx, argv[1], NULL); - if(!valstr) - { - JS_ReportError(cx, "Failed to encode header value."); - goto done; - } - - hdrlen = strlen(keystr) + strlen(valstr) + 3; - hdrbuf = (char*) malloc(hdrlen * sizeof(char)); - if(!hdrbuf) - { - JS_ReportError(cx, "Failed to allocate header buffer."); - goto done; - } - - snprintf(hdrbuf, hdrlen, "%s: %s", keystr, valstr); - http->req_headers = curl_slist_append(http->req_headers, hdrbuf); - - ret = JS_TRUE; - -done: - if(keystr) free(keystr); - if(valstr) free(valstr); - if(hdrbuf) free(hdrbuf); - - return ret; -} - -static JSBool -sendreq(JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval) -{ - HTTPData* http = (HTTPData*) JS_GetPrivate(cx, obj); - char* body = NULL; - size_t bodylen = 0; - JSBool ret = JS_FALSE; - - if(!http) - { - JS_ReportError(cx, "Invalid CouchHTTP instance."); - goto done; - } - - if(argv[0] != JSVAL_VOID && argv[0] != JS_GetEmptyStringValue(cx)) - { - body = enc_string(cx, argv[0], &bodylen); - if(!body) - { - JS_ReportError(cx, "Failed to encode body."); - goto done; - } - } - - ret = go(cx, obj, http, body, bodylen); - -done: - if(body) free(body); - return ret; -} - -static JSBool -status(JSContext* cx, JSObject* obj, jsval idval, jsval* vp) -{ - HTTPData* http = (HTTPData*) JS_GetPrivate(cx, obj); - - if(!http) - { - JS_ReportError(cx, "Invalid CouchHTTP instance."); - return JS_FALSE; - } - - if(INT_FITS_IN_JSVAL(http->last_status)) - { - *vp = INT_TO_JSVAL(http->last_status); - return JS_TRUE; - } - else - { - JS_ReportError(cx, "INTERNAL: Invalid last_status"); - return JS_FALSE; - } -} - -JSClass CouchHTTPClass = { - "CouchHTTP", - JSCLASS_HAS_PRIVATE - | JSCLASS_CONSTRUCT_PROTOTYPE - | JSCLASS_HAS_RESERVED_SLOTS(2), - JS_PropertyStub, - JS_PropertyStub, - JS_PropertyStub, - JS_PropertyStub, - JS_EnumerateStub, - JS_ResolveStub, - JS_ConvertStub, - destructor, - JSCLASS_NO_OPTIONAL_MEMBERS -}; - -JSPropertySpec CouchHTTPProperties[] = { - {"status", 0, JSPROP_READONLY, status, NULL}, - {0, 0, 0, 0, 0} -}; - -JSFunctionSpec CouchHTTPFunctions[] = { - {"_open", open, 3, 0, 0}, - {"_setRequestHeader", setheader, 2, 0, 0}, - {"_send", sendreq, 1, 0, 0}, - {0, 0, 0, 0, 0} -}; - -JSObject* -install_http(JSContext* cx, JSObject* glbl) -{ - JSObject* klass = NULL; - HTTPData* http = NULL; - - klass = JS_InitClass( - cx, - glbl, - NULL, - &CouchHTTPClass, - constructor, - 0, - CouchHTTPProperties, - CouchHTTPFunctions, - NULL, - NULL - ); - - if(!klass) - { - fprintf(stderr, "Failed to initialize CouchHTTP class.\n"); - return NULL; - } - - return klass; -} - - -// Curl Helpers - -typedef struct { - HTTPData* http; - JSContext* cx; - JSObject* resp_headers; - char* sendbuf; - size_t sendlen; - size_t sent; - char* recvbuf; - size_t recvlen; - size_t read; -} CurlState; - -/* - * I really hate doing this but this doesn't have to be - * uber awesome, it just has to work. - */ -CURL* HTTP_HANDLE = NULL; -char ERRBUF[CURL_ERROR_SIZE]; - -static size_t send_body(void *ptr, size_t size, size_t nmem, void *data); -static int seek_body(void *ptr, curl_off_t offset, int origin); -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 JSBool -go(JSContext* cx, JSObject* obj, HTTPData* http, char* body, size_t bodylen) -{ - CurlState state; - JSString* jsbody; - JSBool ret = JS_FALSE; - jsval tmp; - - state.cx = cx; - state.http = http; - - state.sendbuf = body; - state.sendlen = bodylen; - state.sent = 0; - - state.recvbuf = NULL; - state.recvlen = 0; - state.read = 0; - - if(HTTP_HANDLE == NULL) - { - HTTP_HANDLE = curl_easy_init(); - curl_easy_setopt(HTTP_HANDLE, CURLOPT_READFUNCTION, send_body); - curl_easy_setopt(HTTP_HANDLE, CURLOPT_SEEKFUNCTION, - (curl_seek_callback) seek_body); - curl_easy_setopt(HTTP_HANDLE, CURLOPT_HEADERFUNCTION, recv_header); - curl_easy_setopt(HTTP_HANDLE, CURLOPT_WRITEFUNCTION, recv_body); - curl_easy_setopt(HTTP_HANDLE, CURLOPT_NOPROGRESS, 1); - curl_easy_setopt(HTTP_HANDLE, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4); - curl_easy_setopt(HTTP_HANDLE, CURLOPT_ERRORBUFFER, ERRBUF); - curl_easy_setopt(HTTP_HANDLE, CURLOPT_COOKIEFILE, ""); - curl_easy_setopt(HTTP_HANDLE, CURLOPT_USERAGENT, - "CouchHTTP Client - Relax"); - } - - if(!HTTP_HANDLE) - { - JS_ReportError(cx, "Failed to initialize cURL handle."); - goto done; - } - - if(http->method < 0 || http->method > COPY) - { - JS_ReportError(cx, "INTERNAL: Unknown method."); - goto done; - } - - curl_easy_setopt(HTTP_HANDLE, CURLOPT_CUSTOMREQUEST, METHODS[http->method]); - curl_easy_setopt(HTTP_HANDLE, CURLOPT_NOBODY, 0); - curl_easy_setopt(HTTP_HANDLE, CURLOPT_FOLLOWLOCATION, 1); - curl_easy_setopt(HTTP_HANDLE, CURLOPT_UPLOAD, 0); - - if(http->method == HEAD) - { - curl_easy_setopt(HTTP_HANDLE, CURLOPT_NOBODY, 1); - curl_easy_setopt(HTTP_HANDLE, CURLOPT_FOLLOWLOCATION, 0); - } - else if(http->method == POST || http->method == PUT) - { - curl_easy_setopt(HTTP_HANDLE, CURLOPT_UPLOAD, 1); - curl_easy_setopt(HTTP_HANDLE, CURLOPT_FOLLOWLOCATION, 0); - } - - if(body && bodylen) - { - curl_easy_setopt(HTTP_HANDLE, CURLOPT_INFILESIZE, bodylen); - } - 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_HTTPHEADER, http->req_headers); - curl_easy_setopt(HTTP_HANDLE, CURLOPT_READDATA, &state); - curl_easy_setopt(HTTP_HANDLE, CURLOPT_SEEKDATA, &state); - curl_easy_setopt(HTTP_HANDLE, CURLOPT_WRITEHEADER, &state); - curl_easy_setopt(HTTP_HANDLE, CURLOPT_WRITEDATA, &state); - - if(curl_easy_perform(HTTP_HANDLE) != 0) - { - JS_ReportError(cx, "Failed to execute HTTP request: %s", ERRBUF); - goto done; - } - - if(!state.resp_headers) - { - JS_ReportError(cx, "Failed to recieve HTTP headers."); - goto done; - } - - tmp = OBJECT_TO_JSVAL(state.resp_headers); - if(!JS_DefineProperty( - cx, - obj, - "_headers", - tmp, - NULL, - NULL, - JSPROP_READONLY - )) - { - JS_ReportError(cx, "INTERNAL: Failed to set response headers."); - goto done; - } - - if(state.recvbuf) // Is good enough? - { - state.recvbuf[state.read] = '\0'; - jsbody = dec_string(cx, state.recvbuf, state.read+1); - if(!jsbody) - { - // If we can't decode the body as UTF-8 we forcefully - // convert it to a string by just forcing each byte - // to a jschar. - jsbody = str_from_binary(cx, state.recvbuf, state.read); - if(!jsbody) { - if(!JS_IsExceptionPending(cx)) { - JS_ReportError(cx, "INTERNAL: Failed to decode body."); - } - goto done; - } - } - tmp = STRING_TO_JSVAL(jsbody); - } - else - { - tmp = JS_GetEmptyStringValue(cx); - } - - if(!JS_DefineProperty( - cx, - obj, - "responseText", - tmp, - NULL, - NULL, - JSPROP_READONLY - )) - { - JS_ReportError(cx, "INTERNAL: Failed to set responseText."); - goto done; - } - - ret = JS_TRUE; - -done: - if(state.recvbuf) JS_free(cx, state.recvbuf); - return ret; -} - -static size_t -send_body(void *ptr, size_t size, size_t nmem, void *data) -{ - CurlState* state = (CurlState*) data; - size_t length = size * nmem; - size_t towrite = state->sendlen - state->sent; - if(towrite == 0) - { - return 0; - } - - if(length < towrite) towrite = length; - - //fprintf(stderr, "%lu %lu %lu %lu\n", state->bodyused, state->bodyread, length, towrite); - - memcpy(ptr, state->sendbuf + state->sent, towrite); - state->sent += towrite; - - return towrite; -} - -static int -seek_body(void* ptr, curl_off_t offset, int origin) -{ - CurlState* state = (CurlState*) ptr; - if(origin != SEEK_SET) return -1; - - state->sent = (size_t) offset; - return (int) state->sent; -} - -static size_t -recv_header(void *ptr, size_t size, size_t nmem, void *data) -{ - CurlState* state = (CurlState*) data; - char code[4]; - char* header = (char*) ptr; - size_t length = size * nmem; - size_t index = 0; - JSString* hdr = NULL; - jsuint hdrlen; - jsval hdrval; - - if(length > 7 && strncasecmp(header, "HTTP/1.", 7) == 0) - { - if(length < 12) - { - return CURLE_WRITE_ERROR; - } - - memcpy(code, header+9, 3*sizeof(char)); - code[3] = '\0'; - state->http->last_status = atoi(code); - - state->resp_headers = JS_NewArrayObject(state->cx, 0, NULL); - if(!state->resp_headers) - { - return CURLE_WRITE_ERROR; - } - - return length; - } - - // We get a notice at the \r\n\r\n after headers. - if(length <= 2) - { - return length; - } - - // Append the new header to our array. - hdr = dec_string(state->cx, header, length); - if(!hdr) - { - return CURLE_WRITE_ERROR; - } - - if(!JS_GetArrayLength(state->cx, state->resp_headers, &hdrlen)) - { - return CURLE_WRITE_ERROR; - } - - hdrval = STRING_TO_JSVAL(hdr); - if(!JS_SetElement(state->cx, state->resp_headers, hdrlen, &hdrval)) - { - return CURLE_WRITE_ERROR; - } - - return length; -} - -static size_t -recv_body(void *ptr, size_t size, size_t nmem, void *data) -{ - CurlState* state = (CurlState*) data; - size_t length = size * nmem; - char* tmp = NULL; - - if(!state->recvbuf) - { - state->recvlen = 4096; - state->read = 0; - state->recvbuf = JS_malloc(state->cx, state->recvlen); - } - - if(!state->recvbuf) - { - return CURLE_WRITE_ERROR; - } - - // +1 so we can add '\0' back up in the go function. - while(length+1 > state->recvlen - state->read) state->recvlen *= 2; - tmp = JS_realloc(state->cx, state->recvbuf, state->recvlen); - if(!tmp) return CURLE_WRITE_ERROR; - state->recvbuf = tmp; - - memcpy(state->recvbuf + state->read, ptr, length); - state->read += length; - return length; -} - -JSString* -str_from_binary(JSContext* cx, char* data, size_t length) -{ - jschar* conv = (jschar*) JS_malloc(cx, length * sizeof(jschar)); - JSString* ret = NULL; - size_t i; - - if(!conv) return NULL; - - for(i = 0; i < length; i++) - { - conv[i] = (jschar) data[i]; - } - - ret = JS_NewUCString(cx, conv, length); - if(!ret) JS_free(cx, conv); - - return ret; -} diff --git a/apps/couch/c_src/couch_js/http.h b/apps/couch/c_src/couch_js/http.h deleted file mode 100644 index b5f8c70f..00000000 --- a/apps/couch/c_src/couch_js/http.h +++ /dev/null @@ -1,18 +0,0 @@ -// Licensed under the Apache License, Version 2.0 (the "License"); you may not -// use this file except in compliance with the License. You may obtain a copy of -// the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -// License for the specific language governing permissions and limitations under -// the License. - -#ifndef COUCH_JS_HTTP_H -#define COUCH_JS_HTTP_H - -JSObject* install_http(JSContext* cx, JSObject* global); - -#endif
\ No newline at end of file diff --git a/apps/couch/c_src/couch_js/main.c b/apps/couch/c_src/couch_js/main.c deleted file mode 100644 index 25acaf55..00000000 --- a/apps/couch/c_src/couch_js/main.c +++ /dev/null @@ -1,345 +0,0 @@ -// Licensed under the Apache License, Version 2.0 (the "License"); you may not -// use this file except in compliance with the License. You may obtain a copy of -// the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -// License for the specific language governing permissions and limitations under -// the License. - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> - -#include "config.h" -#ifdef HAVE_JS_JSAPI_H -#include <js/jsapi.h> -#elif HAVE_MOZJS_JSAPI_H -#include <mozjs/jsapi.h> -#else -#include <jsapi.h> -#endif - -#include "utf8.h" -#include "http.h" - -int gExitCode = 0; - -#ifdef JS_THREADSAFE -#define SETUP_REQUEST(cx) \ - JS_SetContextThread(cx); \ - JS_BeginRequest(cx); -#define FINISH_REQUEST(cx) \ - JS_EndRequest(cx); \ - JS_ClearContextThread(cx); -#else -#define SETUP_REQUEST(cx) -#define FINISH_REQUEST(cx) -#endif - -static JSBool -evalcx(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - JSString *str; - JSObject *sandbox; - JSContext *subcx; - const jschar *src; - size_t srclen; - JSBool ret = JS_FALSE; - jsval v; - - sandbox = NULL; - if(!JS_ConvertArguments(cx, argc, argv, "S / o", &str, &sandbox)) - { - return JS_FALSE; - } - - subcx = JS_NewContext(JS_GetRuntime(cx), 8L * 1024L); - if(!subcx) - { - JS_ReportOutOfMemory(cx); - return JS_FALSE; - } - - SETUP_REQUEST(subcx); - - src = JS_GetStringChars(str); - srclen = JS_GetStringLength(str); - - if(!sandbox) - { - sandbox = JS_NewObject(subcx, NULL, NULL, NULL); - if(!sandbox || !JS_InitStandardClasses(subcx, sandbox)) goto done; - } - - if(srclen == 0) - { - *rval = OBJECT_TO_JSVAL(sandbox); - } - else - { - JS_EvaluateUCScript(subcx, sandbox, src, srclen, NULL, 0, rval); - } - - ret = JS_TRUE; - -done: - FINISH_REQUEST(subcx); - JS_DestroyContext(subcx); - return ret; -} - -static JSBool -gc(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - JS_GC(cx); - return JS_TRUE; -} - -static JSBool -print(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - uintN i; - char *bytes; - - for(i = 0; i < argc; i++) - { - bytes = enc_string(cx, argv[i], NULL); - if(!bytes) return JS_FALSE; - - fprintf(stdout, "%s%s", i ? " " : "", bytes); - JS_free(cx, bytes); - } - - fputc('\n', stdout); - fflush(stdout); - return JS_TRUE; -} - -static JSBool -quit(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - JS_ConvertArguments(cx, argc, argv, "/ i", &gExitCode); - return JS_FALSE; -} - -static char* -readfp(JSContext* cx, FILE* fp, size_t* buflen) -{ - char* bytes = NULL; - char* tmp = NULL; - size_t used = 0; - size_t byteslen = 256; - size_t readlen = 0; - - bytes = JS_malloc(cx, byteslen); - if(bytes == NULL) return NULL; - - while((readlen = js_fgets(bytes+used, byteslen-used, stdin)) > 0) - { - used += readlen; - - if(bytes[used-1] == '\n') - { - bytes[used-1] = '\0'; - break; - } - - // Double our buffer and read more. - byteslen *= 2; - tmp = JS_realloc(cx, bytes, byteslen); - if(!tmp) - { - JS_free(cx, bytes); - return NULL; - } - bytes = tmp; - } - - *buflen = used; - return bytes; -} - -static JSBool -readline(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) { - jschar *chars; - JSString *str; - char* bytes; - char* tmp; - size_t byteslen; - - /* GC Occasionally */ - JS_MaybeGC(cx); - - bytes = readfp(cx, stdin, &byteslen); - if(!bytes) return JS_FALSE; - - /* Treat the empty string specially */ - if(byteslen == 0) - { - *rval = JS_GetEmptyStringValue(cx); - JS_free(cx, bytes); - return JS_TRUE; - } - - /* Shrink the buffer to the real size */ - tmp = JS_realloc(cx, bytes, byteslen); - if(!tmp) - { - JS_free(cx, bytes); - return JS_FALSE; - } - bytes = tmp; - - str = dec_string(cx, bytes, byteslen); - JS_free(cx, bytes); - - if(!str) return JS_FALSE; - - *rval = STRING_TO_JSVAL(str); - - return JS_TRUE; -} - -static JSBool -seal(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) { - JSObject *target; - JSBool deep = JS_FALSE; - - if (!JS_ConvertArguments(cx, argc, argv, "o/b", &target, &deep)) - return JS_FALSE; - if (!target) - return JS_TRUE; - return JS_SealObject(cx, target, deep); -} - -static void -execute_script(JSContext *cx, JSObject *obj, const char *filename) { - FILE *file; - JSScript *script; - jsval result; - - if(!filename || strcmp(filename, "-") == 0) - { - file = stdin; - } - else - { - file = fopen(filename, "r"); - if (!file) - { - fprintf(stderr, "could not open script file %s\n", filename); - gExitCode = 1; - return; - } - } - - script = JS_CompileFileHandle(cx, obj, filename, file); - if(script) - { - JS_ExecuteScript(cx, obj, script, &result); - JS_DestroyScript(cx, script); - } -} - -static void -printerror(JSContext *cx, const char *mesg, JSErrorReport *report) -{ - if(!report || !JSREPORT_IS_WARNING(report->flags)) - { - fprintf(stderr, "%s\n", mesg); - } -} - -static JSFunctionSpec global_functions[] = { - {"evalcx", evalcx, 0, 0, 0}, - {"gc", gc, 0, 0, 0}, - {"print", print, 0, 0, 0}, - {"quit", quit, 0, 0, 0}, - {"readline", readline, 0, 0, 0}, - {"seal", seal, 0, 0, 0}, - {0, 0, 0, 0, 0} -}; - -static JSClass global_class = { - "GlobalClass", - JSCLASS_GLOBAL_FLAGS, - JS_PropertyStub, - JS_PropertyStub, - JS_PropertyStub, - JS_PropertyStub, - JS_EnumerateStub, - JS_ResolveStub, - JS_ConvertStub, - JS_FinalizeStub, - JSCLASS_NO_OPTIONAL_MEMBERS -}; - -int -main(int argc, const char * argv[]) -{ - JSRuntime* rt = NULL; - JSContext* cx = NULL; - JSObject* global = NULL; - JSFunctionSpec* sp = NULL; - int i = 0; - - rt = JS_NewRuntime(64L * 1024L * 1024L); - if (!rt) return 1; - - cx = JS_NewContext(rt, 8L * 1024L); - if (!cx) return 1; - - JS_SetErrorReporter(cx, printerror); - JS_ToggleOptions(cx, JSOPTION_XML); - - SETUP_REQUEST(cx); - - global = JS_NewObject(cx, &global_class, NULL, NULL); - if (!global) return 1; - if (!JS_InitStandardClasses(cx, global)) return 1; - - for(sp = global_functions; sp->name != NULL; sp++) - { - if(!JS_DefineFunction(cx, global, - sp->name, sp->call, sp->nargs, sp->flags)) - { - fprintf(stderr, "Failed to create function: %s\n", sp->name); - return 1; - } - } - - if(!install_http(cx, global)) - { - return 1; - } - - JS_SetGlobalObject(cx, global); - - if(argc > 2) - { - fprintf(stderr, "incorrect number of arguments\n\n"); - fprintf(stderr, "usage: %s <scriptfile>\n", argv[0]); - return 2; - } - - if(argc == 0) - { - execute_script(cx, global, NULL); - } - else - { - execute_script(cx, global, argv[1]); - } - - FINISH_REQUEST(cx); - - JS_DestroyContext(cx); - JS_DestroyRuntime(rt); - JS_ShutDown(); - - return gExitCode; -} diff --git a/apps/couch/c_src/couch_js/utf8.c b/apps/couch/c_src/couch_js/utf8.c deleted file mode 100644 index 57928ba9..00000000 --- a/apps/couch/c_src/couch_js/utf8.c +++ /dev/null @@ -1,293 +0,0 @@ -// Licensed under the Apache License, Version 2.0 (the "License"); you may not -// use this file except in compliance with the License. You may obtain a copy of -// the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -// License for the specific language governing permissions and limitations under -// the License. - -#include "config.h" -#ifdef HAVE_JS_JSAPI_H -#include <js/jsapi.h> -#elif HAVE_MOZJS_JSAPI_H -#include <mozjs/jsapi.h> -#else -#include <jsapi.h> -#endif - -static int -enc_char(uint8 *utf8Buffer, uint32 ucs4Char) -{ - int utf8Length = 1; - - if (ucs4Char < 0x80) - { - *utf8Buffer = (uint8)ucs4Char; - } - else - { - int i; - uint32 a = ucs4Char >> 11; - utf8Length = 2; - while(a) - { - a >>= 5; - utf8Length++; - } - i = utf8Length; - while(--i) - { - utf8Buffer[i] = (uint8)((ucs4Char & 0x3F) | 0x80); - ucs4Char >>= 6; - } - *utf8Buffer = (uint8)(0x100 - (1 << (8-utf8Length)) + ucs4Char); - } - - return utf8Length; -} - -static JSBool -enc_charbuf(const jschar* src, size_t srclen, char* dst, size_t* dstlenp) -{ - size_t i; - size_t utf8Len; - size_t dstlen = *dstlenp; - size_t origDstlen = dstlen; - jschar c; - jschar c2; - uint32 v; - uint8 utf8buf[6]; - - if(!dst) - { - dstlen = origDstlen = (size_t) -1; - } - - while(srclen) - { - c = *src++; - srclen--; - - if((c >= 0xDC00) && (c <= 0xDFFF)) goto bad_surrogate; - - if(c < 0xD800 || c > 0xDBFF) - { - v = c; - } - else - { - if(srclen < 1) goto buffer_too_small; - c2 = *src++; - srclen--; - if ((c2 < 0xDC00) || (c2 > 0xDFFF)) - { - c = c2; - goto bad_surrogate; - } - v = ((c - 0xD800) << 10) + (c2 - 0xDC00) + 0x10000; - } - if(v < 0x0080) - { - /* no encoding necessary - performance hack */ - if(!dstlen) goto buffer_too_small; - if(dst) *dst++ = (char) v; - utf8Len = 1; - } - else - { - utf8Len = enc_char(utf8buf, v); - if(utf8Len > dstlen) goto buffer_too_small; - if(dst) - { - for (i = 0; i < utf8Len; i++) - { - *dst++ = (char) utf8buf[i]; - } - } - } - dstlen -= utf8Len; - } - - *dstlenp = (origDstlen - dstlen); - return JS_TRUE; - -bad_surrogate: - *dstlenp = (origDstlen - dstlen); - return JS_FALSE; - -buffer_too_small: - *dstlenp = (origDstlen - dstlen); - return JS_FALSE; -} - -char* -enc_string(JSContext* cx, jsval arg, size_t* buflen) -{ - JSString* str = NULL; - jschar* src = NULL; - char* bytes = NULL; - size_t srclen = 0; - size_t byteslen = 0; - - str = JS_ValueToString(cx, arg); - if(!str) goto error; - - src = JS_GetStringChars(str); - srclen = JS_GetStringLength(str); - - if(!enc_charbuf(src, srclen, NULL, &byteslen)) goto error; - - bytes = JS_malloc(cx, (byteslen) + 1); - bytes[byteslen] = 0; - - if(!enc_charbuf(src, srclen, bytes, &byteslen)) goto error; - - if(buflen) *buflen = byteslen; - goto success; - -error: - if(bytes != NULL) JS_free(cx, bytes); - bytes = NULL; - -success: - return bytes; -} - -static uint32 -dec_char(const uint8 *utf8Buffer, int utf8Length) -{ - uint32 ucs4Char; - uint32 minucs4Char; - - /* from Unicode 3.1, non-shortest form is illegal */ - static const uint32 minucs4Table[] = { - 0x00000080, 0x00000800, 0x0001000, 0x0020000, 0x0400000 - }; - - if (utf8Length == 1) - { - ucs4Char = *utf8Buffer; - } - else - { - ucs4Char = *utf8Buffer++ & ((1<<(7-utf8Length))-1); - minucs4Char = minucs4Table[utf8Length-2]; - while(--utf8Length) - { - ucs4Char = ucs4Char<<6 | (*utf8Buffer++ & 0x3F); - } - if(ucs4Char < minucs4Char || ucs4Char == 0xFFFE || ucs4Char == 0xFFFF) - { - ucs4Char = 0xFFFD; - } - } - - return ucs4Char; -} - -static JSBool -dec_charbuf(const char *src, size_t srclen, jschar *dst, size_t *dstlenp) -{ - uint32 v; - size_t offset = 0; - size_t j; - size_t n; - size_t dstlen = *dstlenp; - size_t origDstlen = dstlen; - - if(!dst) dstlen = origDstlen = (size_t) -1; - - while(srclen) - { - v = (uint8) *src; - n = 1; - - if(v & 0x80) - { - while(v & (0x80 >> n)) - { - n++; - } - - if(n > srclen) goto buffer_too_small; - if(n == 1 || n > 6) goto bad_character; - - for(j = 1; j < n; j++) - { - if((src[j] & 0xC0) != 0x80) goto bad_character; - } - - v = dec_char((const uint8 *) src, n); - if(v >= 0x10000) - { - v -= 0x10000; - - if(v > 0xFFFFF || dstlen < 2) - { - *dstlenp = (origDstlen - dstlen); - return JS_FALSE; - } - - if(dstlen < 2) goto buffer_too_small; - - if(dst) - { - *dst++ = (jschar)((v >> 10) + 0xD800); - v = (jschar)((v & 0x3FF) + 0xDC00); - } - dstlen--; - } - } - - if(!dstlen) goto buffer_too_small; - if(dst) *dst++ = (jschar) v; - - dstlen--; - offset += n; - src += n; - srclen -= n; - } - - *dstlenp = (origDstlen - dstlen); - return JS_TRUE; - -bad_character: - *dstlenp = (origDstlen - dstlen); - return JS_FALSE; - -buffer_too_small: - *dstlenp = (origDstlen - dstlen); - return JS_FALSE; -} - -JSString* -dec_string(JSContext* cx, const char* bytes, size_t byteslen) -{ - JSString* str = NULL; - jschar* chars = NULL; - size_t charslen; - - if(!dec_charbuf(bytes, byteslen, NULL, &charslen)) goto error; - - chars = JS_malloc(cx, (charslen + 1) * sizeof(jschar)); - if(!chars) return NULL; - chars[charslen] = 0; - - if(!dec_charbuf(bytes, byteslen, chars, &charslen)) goto error; - - str = JS_NewUCString(cx, chars, charslen - 1); - if(!str) goto error; - - goto success; - -error: - if(chars != NULL) JS_free(cx, chars); - str = NULL; - -success: - return str; -} diff --git a/apps/couch/c_src/couch_js/utf8.h b/apps/couch/c_src/couch_js/utf8.h deleted file mode 100644 index 00f6b736..00000000 --- a/apps/couch/c_src/couch_js/utf8.h +++ /dev/null @@ -1,19 +0,0 @@ -// Licensed under the Apache License, Version 2.0 (the "License"); you may not -// use this file except in compliance with the License. You may obtain a copy of -// the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -// License for the specific language governing permissions and limitations under -// the License. - -#ifndef COUCH_JS_UTF_8_H -#define COUCH_JS_UTF_8_H - -char* enc_string(JSContext* cx, jsval arg, size_t* buflen); -JSString* dec_string(JSContext* cx, const char* buf, size_t buflen); - -#endif
\ No newline at end of file |