couchdb-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From beno...@apache.org
Subject [50/57] [abbrv] [partial] inital move to rebar compilation
Date Tue, 07 Jan 2014 00:37:10 GMT
http://git-wip-us.apache.org/repos/asf/couchdb/blob/add91738/apps/couch/priv/couch_js/help.h
----------------------------------------------------------------------
diff --git a/apps/couch/priv/couch_js/help.h b/apps/couch/priv/couch_js/help.h
new file mode 100644
index 0000000..f4ddb24
--- /dev/null
+++ b/apps/couch/priv/couch_js/help.h
@@ -0,0 +1,82 @@
+// 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 COUCHJS_HELP_H
+#define COUCHJS_HELP_H
+
+#include "config.h"
+
+static const char VERSION_TEMPLATE[] =
+    "%s - %s\n"
+    "\n"
+    "Licensed under the Apache License, Version 2.0 (the \"License\"); you may "
+        "not use\n"
+    "this file except in compliance with the License. You may obtain a copy of"
+        "the\n"
+    "License at\n"
+    "\n"
+    "  http://www.apache.org/licenses/LICENSE-2.0\n"
+    "\n"
+    "Unless required by applicable law or agreed to in writing, software "
+        "distributed\n"
+    "under the License is distributed on an \"AS IS\" BASIS, WITHOUT "
+        "WARRANTIES OR\n"
+    "CONDITIONS OF ANY KIND, either express or implied. See the License "
+        "for the\n"
+    "specific language governing permissions and limitations under the "
+        "License.\n";
+
+static const char USAGE_TEMPLATE[] =
+    "Usage: %s [FILE]\n"
+    "\n"
+    "The %s command runs the %s JavaScript interpreter.\n"
+    "\n"
+    "The exit status is 0 for success or 1 for failure.\n"
+    "\n"
+    "Options:\n"
+    "\n"
+    "  -h          display a short help message and exit\n"
+    "  -V          display version information and exit\n"
+    "  -H          enable %s cURL bindings (only avaiable\n"
+    "              if package was built with cURL available)\n"
+    "  -S SIZE     specify that the runtime should allow at\n"
+    "              most SIZE bytes of memory to be allocated\n"
+    "  -u FILE     path to a .uri file containing the address\n"
+    "              (or addresses) of one or more servers\n"
+    "\n"
+    "Report bugs at <%s>.\n";
+
+#define BASENAME COUCHJS_NAME
+
+#define couch_version(basename)  \
+    fprintf(                     \
+            stdout,              \
+            VERSION_TEMPLATE,    \
+            basename,            \
+            PACKAGE_STRING)
+
+#define DISPLAY_VERSION couch_version(BASENAME)
+
+
+#define couch_usage(basename) \
+    fprintf(                                    \
+            stdout,                             \
+            USAGE_TEMPLATE,                     \
+            basename,                           \
+            basename,                           \
+            PACKAGE_NAME,                       \
+            basename,                           \
+            PACKAGE_BUGREPORT)
+
+#define DISPLAY_USAGE couch_usage(BASENAME)
+
+#endif // Included help.h

http://git-wip-us.apache.org/repos/asf/couchdb/blob/add91738/apps/couch/priv/couch_js/http.c
----------------------------------------------------------------------
diff --git a/apps/couch/priv/couch_js/http.c b/apps/couch/priv/couch_js/http.c
new file mode 100644
index 0000000..c66b5da
--- /dev/null
+++ b/apps/couch/priv/couch_js/http.c
@@ -0,0 +1,698 @@
+// 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 <sys/types.h>
+#include <sys/stat.h>
+#include <jsapi.h>
+#include "config.h"
+#include "utf8.h"
+#include "util.h"
+
+// Soft dependency on cURL bindings because they're
+// only used when running the JS tests from the
+// command line which is rare.
+#ifndef HAVE_CURL
+
+void
+http_check_enabled()
+{
+    fprintf(stderr, "HTTP API was disabled at compile time.\n");
+    exit(3);
+}
+
+
+JSBool
+http_ctor(JSContext* cx, JSObject* req)
+{
+    return JS_FALSE;
+}
+
+
+JSBool
+http_dtor(JSContext* cx, JSObject* req)
+{
+    return JS_FALSE;
+}
+
+
+JSBool
+http_open(JSContext* cx, JSObject* req, jsval mth, jsval url, jsval snc)
+{
+    return JS_FALSE;
+}
+
+
+JSBool
+http_set_hdr(JSContext* cx, JSObject* req, jsval name, jsval val)
+{
+    return JS_FALSE;
+}
+
+
+JSBool
+http_send(JSContext* cx, JSObject* req, jsval body)
+{
+    return JS_FALSE;
+}
+
+
+int
+http_status(JSContext* cx, JSObject* req, jsval body)
+{
+    return -1;
+}
+
+JSBool
+http_uri(JSContext* cx, JSObject* req, couch_args* args, jsval* uri_val)
+{
+    return JS_FALSE;
+}
+
+
+#else
+#include <curl/curl.h>
+#include <unistd.h>
+
+
+void
+http_check_enabled()
+{
+    return;
+}
+
+
+// Map some of the string function names to things which exist on Windows
+#ifdef XP_WIN
+#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", "OPTIONS", NULL};
+
+
+#define GET     0
+#define HEAD    1
+#define POST    2
+#define PUT     3
+#define DELETE  4
+#define COPY    5
+#define OPTIONS 6
+
+
+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);
+
+
+JSBool
+http_ctor(JSContext* cx, JSObject* req)
+{
+    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, req, 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;
+}
+
+
+void
+http_dtor(JSContext* cx, JSObject* obj)
+{
+    HTTPData* http = (HTTPData*) JS_GetPrivate(cx, obj);
+    if(http) { 
+        if(http->url) free(http->url);
+        if(http->req_headers) curl_slist_free_all(http->req_headers);
+        free(http);
+    }
+}
+
+
+JSBool
+http_open(JSContext* cx, JSObject* req, jsval mth, jsval url, jsval snc)
+{
+    HTTPData* http = (HTTPData*) JS_GetPrivate(cx, req);
+    char* method = NULL;
+    int methid;
+    JSBool ret = JS_FALSE;
+
+    if(!http) {
+        JS_ReportError(cx, "Invalid CouchHTTP instance.");
+        goto done;
+    }
+
+    if(JSVAL_IS_VOID(mth)) {
+        JS_ReportError(cx, "You must specify a method.");
+        goto done;
+    }
+
+    method = enc_string(cx, mth, 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 > OPTIONS) {
+        JS_ReportError(cx, "Invalid method specified.");
+        goto done;
+    }
+
+    http->method = methid;
+
+    if(JSVAL_IS_VOID(url)) {
+        JS_ReportError(cx, "You must specify a URL.");
+        goto done;
+    }
+
+    if(http->url != NULL) {
+        free(http->url);
+        http->url = NULL;
+    }
+
+    http->url = enc_string(cx, url, NULL);
+    if(http->url == NULL) {
+        JS_ReportError(cx, "Failed to encode URL.");
+        goto done;
+    }
+    
+    if(JSVAL_IS_BOOLEAN(snc) && JSVAL_TO_BOOLEAN(snc)) {
+        JS_ReportError(cx, "Synchronous flag must be false.");
+        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;
+}
+
+
+JSBool
+http_set_hdr(JSContext* cx, JSObject* req, jsval name, jsval val)
+{
+    HTTPData* http = (HTTPData*) JS_GetPrivate(cx, req);
+    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(JSVAL_IS_VOID(name))
+    {
+        JS_ReportError(cx, "You must speciy a header name.");
+        goto done;
+    }
+
+    keystr = enc_string(cx, name, NULL);
+    if(!keystr)
+    {
+        JS_ReportError(cx, "Failed to encode header name.");
+        goto done;
+    }
+    
+    if(JSVAL_IS_VOID(val))
+    {
+        JS_ReportError(cx, "You must specify a header value.");
+        goto done;
+    }
+    
+    valstr = enc_string(cx, val, 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;
+}
+
+JSBool
+http_send(JSContext* cx, JSObject* req, jsval body)
+{
+    HTTPData* http = (HTTPData*) JS_GetPrivate(cx, req);
+    char* bodystr = NULL;
+    size_t bodylen = 0;
+    JSBool ret = JS_FALSE;
+    
+    if(!http) {
+        JS_ReportError(cx, "Invalid CouchHTTP instance.");
+        goto done;
+    }
+
+    if(!JSVAL_IS_VOID(body)) {
+        bodystr = enc_string(cx, body, &bodylen);
+        if(!bodystr) {
+            JS_ReportError(cx, "Failed to encode body.");
+            goto done;
+        }
+    }
+
+    ret = go(cx, req, http, bodystr, bodylen);
+
+done:
+    if(bodystr) free(bodystr);
+    return ret;
+}
+
+int
+http_status(JSContext* cx, JSObject* req)
+{
+    HTTPData* http = (HTTPData*) JS_GetPrivate(cx, req);
+    
+    if(!http) {
+        JS_ReportError(cx, "Invalid CouchHTTP instance.");
+        return JS_FALSE;
+    }
+
+    return http->last_status;
+}
+
+JSBool
+http_uri(JSContext* cx, JSObject* req, couch_args* args, jsval* uri_val)
+{
+    FILE* uri_fp = NULL;
+    JSString* uri_str;
+
+    // Default is http://localhost:5984/ when no uri file is specified
+    if (!args->uri_file) {
+        uri_str = JS_InternString(cx, "http://localhost:5984/");
+        *uri_val = STRING_TO_JSVAL(uri_str);
+        return JS_TRUE;
+    }
+
+    // Else check to see if the base url is cached in a reserved slot
+    if (JS_GetReservedSlot(cx, req, 0, uri_val) && !JSVAL_IS_VOID(*uri_val)) {
+        return JS_TRUE;
+    }
+
+    // Read the first line of the couch.uri file.
+    if(!((uri_fp = fopen(args->uri_file, "r")) &&
+         (uri_str = couch_readline(cx, uri_fp)))) {
+        JS_ReportError(cx, "Failed to read couch.uri file.");
+        goto error;
+    }
+
+    fclose(uri_fp);
+    *uri_val = STRING_TO_JSVAL(uri_str);
+    JS_SetReservedSlot(cx, req, 0, *uri_val);
+    return JS_TRUE;
+
+error:
+    if(uri_fp) fclose(uri_fp);
+    return JS_FALSE;
+}
+
+
+// Curl Helpers
+
+typedef struct {
+    HTTPData*   http;
+    JSContext*  cx;
+    JSObject*   resp_headers;
+    char*       sendbuf;
+    size_t      sendlen;
+    size_t      sent;
+    int         sent_once;
+    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;
+    char* referer;
+    JSString* jsbody;
+    JSBool ret = JS_FALSE;
+    jsval tmp;
+    
+    state.cx = cx;
+    state.http = http;
+    
+    state.sendbuf = body;
+    state.sendlen = bodylen;
+    state.sent = 0;
+    state.sent_once = 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(!JS_GetReservedSlot(cx, obj, 0, &tmp)) {
+      JS_ReportError(cx, "Failed to readreserved slot.");
+      goto done;
+    }
+
+    if(!(referer = enc_string(cx, tmp, NULL))) {
+      JS_ReportError(cx, "Failed to encode referer.");
+      goto done;
+    }
+    curl_easy_setopt(HTTP_HANDLE, CURLOPT_REFERER, referer);
+    free(referer);
+
+    if(http->method < 0 || http->method > OPTIONS) {
+        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) {
+        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;
+
+    // Assume this is cURL trying to resend a request that
+    // failed.
+    if(towrite == 0 && state->sent_once == 0) {
+        state->sent_once = 1;
+        return 0;
+    } else if(towrite == 0) {
+        state->sent = 0;
+        state->sent_once = 0;
+        towrite = state->sendlen;
+    }
+
+    if(length < towrite) towrite = length;
+
+    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;
+    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;
+}
+
+#endif /* HAVE_CURL */

http://git-wip-us.apache.org/repos/asf/couchdb/blob/add91738/apps/couch/priv/couch_js/http.h
----------------------------------------------------------------------
diff --git a/apps/couch/priv/couch_js/http.h b/apps/couch/priv/couch_js/http.h
new file mode 100644
index 0000000..63d45bd
--- /dev/null
+++ b/apps/couch/priv/couch_js/http.h
@@ -0,0 +1,27 @@
+// 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
+
+#include "util.h"
+
+void http_check_enabled();
+JSBool http_ctor(JSContext* cx, JSObject* req);
+void http_dtor(JSContext* cx, JSObject* req);
+JSBool http_open(JSContext* cx, JSObject* req, jsval mth, jsval url, jsval snc);
+JSBool http_set_hdr(JSContext* cx, JSObject* req, jsval name, jsval val);
+JSBool http_send(JSContext* cx, JSObject* req, jsval body);
+int http_status(JSContext* cx, JSObject* req);
+JSBool http_uri(JSContext* cx, JSObject *req, couch_args* args, jsval* uri);
+
+#endif

http://git-wip-us.apache.org/repos/asf/couchdb/blob/add91738/apps/couch/priv/couch_js/main.c
----------------------------------------------------------------------
diff --git a/apps/couch/priv/couch_js/main.c b/apps/couch/priv/couch_js/main.c
new file mode 100644
index 0000000..209bb02
--- /dev/null
+++ b/apps/couch/priv/couch_js/main.c
@@ -0,0 +1,21 @@
+// 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"
+
+#if defined(SM185)
+#include "sm185.c"
+#elif defined(SM180)
+#include "sm180.c"
+#else
+#include "sm170.c"
+#endif

http://git-wip-us.apache.org/repos/asf/couchdb/blob/add91738/apps/couch/priv/couch_js/sm170.c
----------------------------------------------------------------------
diff --git a/apps/couch/priv/couch_js/sm170.c b/apps/couch/priv/couch_js/sm170.c
new file mode 100644
index 0000000..51e4f4d
--- /dev/null
+++ b/apps/couch/priv/couch_js/sm170.c
@@ -0,0 +1,398 @@
+// 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 <jsapi.h>
+#include "http.h"
+#include "utf8.h"
+#include "util.h"
+
+
+#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
+req_ctor(JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval)
+{
+    return http_ctor(cx, obj);
+}
+
+
+static void 
+req_dtor(JSContext* cx, JSObject* obj)
+{
+    http_dtor(cx, obj);
+}
+
+
+static JSBool
+req_open(JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval)
+{
+    JSBool ret = JS_FALSE;
+
+    if(argc == 2) {
+        ret = http_open(cx, obj, argv[0], argv[1], JSVAL_FALSE);
+    } else if(argc == 3) {
+        ret = http_open(cx, obj, argv[0], argv[1], argv[2]);
+    } else {
+        JS_ReportError(cx, "Invalid call to CouchHTTP.open");
+    }
+
+    *rval = JSVAL_VOID;
+    return ret;
+}
+
+
+static JSBool
+req_set_hdr(JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval)
+{
+    JSBool ret = JS_FALSE;
+    if(argc == 2) {
+        ret = http_set_hdr(cx, obj, argv[0], argv[1]);
+    } else {
+        JS_ReportError(cx, "Invalid call to CouchHTTP.set_header");
+    }
+
+    *rval = JSVAL_VOID;
+    return ret;
+}
+
+
+static JSBool
+req_send(JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval)
+{
+    JSBool ret = JS_FALSE;
+    if(argc == 1) {
+        ret = http_send(cx, obj, argv[0]);
+    } else {
+        JS_ReportError(cx, "Invalid call to CouchHTTP.send");
+    }
+
+    *rval = JSVAL_VOID;
+    return ret;
+}
+
+
+static JSBool
+req_status(JSContext* cx, JSObject* obj, jsval idval, jsval* rval)
+{
+    int status = http_status(cx, obj);
+    if(status < 0)
+        return JS_FALSE;
+
+    if(INT_FITS_IN_JSVAL(status)) {
+        *rval = INT_TO_JSVAL(status);
+        return JS_TRUE;
+    } else {
+        JS_ReportError(cx, "Invalid HTTP status.");
+        return JS_FALSE;
+    }
+}
+
+
+static JSBool
+base_url(JSContext *cx, JSObject* obj, jsval idval, jsval* rval)
+{
+    couch_args *args = (couch_args*)JS_GetContextPrivate(cx);
+    return http_uri(cx, obj, args, rval);
+}
+
+
+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;
+    char *name = NULL;
+
+    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(argc > 2) {
+      name = enc_string(cx, argv[2], NULL);
+    }
+
+    if(srclen == 0) {
+        *rval = OBJECT_TO_JSVAL(sandbox);
+    } else {
+        JS_EvaluateUCScript(subcx, sandbox, src, srclen, name, 1, rval);
+    }
+    
+    ret = JS_TRUE;
+
+done:
+    if(name) JS_free(cx, name);
+    FINISH_REQUEST(subcx);
+    JS_DestroyContext(subcx);
+    return ret;
+}
+
+
+static JSBool
+gc(JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval)
+{
+    JS_GC(cx);
+    *rval = JSVAL_VOID;
+    return JS_TRUE;
+}
+
+
+static JSBool
+print(JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval)
+{
+    couch_print(cx, argc, argv);
+    *rval = JSVAL_VOID;
+    return JS_TRUE;
+}
+
+
+static JSBool
+quit(JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval)
+{
+    int exit_code = 0;
+    JS_ConvertArguments(cx, argc, argv, "/i", &exit_code);
+    exit(exit_code);
+}
+
+
+static JSBool
+readline(JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval)
+{
+    JSString* line;
+
+    /* GC Occasionally */
+    JS_MaybeGC(cx);
+
+    line = couch_readline(cx, stdin);
+    if(line == NULL) return JS_FALSE;
+
+    *rval = STRING_TO_JSVAL(line);
+    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) {
+        *rval = JSVAL_VOID;
+        return JS_TRUE;
+    }
+
+    if(JS_SealObject(cx, target, deep) != JS_TRUE)
+        return JS_FALSE;
+
+    *rval = JSVAL_VOID;
+    return JS_TRUE;
+}
+
+
+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,
+    req_dtor,
+    JSCLASS_NO_OPTIONAL_MEMBERS
+};
+
+
+JSPropertySpec CouchHTTPProperties[] = {
+    {"status", 0, JSPROP_READONLY, req_status, NULL},
+    {"base_url", 0, JSPROP_READONLY | JSPROP_SHARED, base_url, NULL},
+    {0, 0, 0, 0, 0}
+};
+
+
+JSFunctionSpec CouchHTTPFunctions[] = {
+    {"_open", req_open, 3, 0, 0},
+    {"_setRequestHeader", req_set_hdr, 2, 0, 0},
+    {"_send", req_send, 1, 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
+};
+
+
+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}
+};
+
+
+int
+main(int argc, const char* argv[])
+{
+    JSRuntime* rt = NULL;
+    JSContext* cx = NULL;
+    JSObject* global = NULL;
+    JSObject* klass = NULL;
+    JSScript* script;
+    JSString* scriptsrc;
+    jschar* schars;
+    size_t slen;
+    jsval sroot;
+    jsval result;
+    int i;
+
+    couch_args* args = couch_parse_args(argc, argv);
+
+    rt = JS_NewRuntime(args->stack_size);
+    if(rt == NULL)
+        return 1;
+
+    cx = JS_NewContext(rt, 8L * 1024L);
+    if(cx == NULL)
+        return 1;
+
+    JS_SetErrorReporter(cx, couch_error);
+    JS_ToggleOptions(cx, JSOPTION_XML);
+    JS_SetContextPrivate(cx, args);
+    
+    SETUP_REQUEST(cx);
+
+    global = JS_NewObject(cx, &global_class, NULL, NULL);
+    if(global == NULL)
+        return 1;
+
+    JS_SetGlobalObject(cx, global);
+    
+    if(!JS_InitStandardClasses(cx, global))
+        return 1;
+
+    if(couch_load_funcs(cx, global, global_functions) != JS_TRUE)
+        return 1;
+ 
+    if(args->use_http) {
+        http_check_enabled();
+
+        klass = JS_InitClass(
+            cx, global,
+            NULL,
+            &CouchHTTPClass, req_ctor,
+            0,
+            CouchHTTPProperties, CouchHTTPFunctions,
+            NULL, NULL
+        );
+
+        if(!klass)
+        {
+            fprintf(stderr, "Failed to initialize CouchHTTP class.\n");
+            exit(2);
+        }
+    } 
+
+    for (i = 0 ; args->scripts[i] ; i++) {
+        // Convert script source to jschars.
+        scriptsrc = couch_readfile(cx, args->scripts[i]);
+        if(!scriptsrc)
+            return 1;
+
+        schars = JS_GetStringChars(scriptsrc);
+        slen = JS_GetStringLength(scriptsrc);
+
+        // Root it so GC doesn't collect it.
+        sroot = STRING_TO_JSVAL(scriptsrc);
+        if(JS_AddRoot(cx, &sroot) != JS_TRUE) {
+            fprintf(stderr, "Internal root error.\n");
+            return 1;
+        }
+
+        // Compile and run
+        script = JS_CompileUCScript(cx, global, schars, slen,
+                                    args->scripts[i], 1);
+        if(!script) {
+            fprintf(stderr, "Failed to compile script.\n");
+            return 1;
+        }
+
+        JS_ExecuteScript(cx, global, script, &result);
+
+        // Warning message if we don't remove it.
+        JS_RemoveRoot(cx, &sroot);
+    }
+
+    FINISH_REQUEST(cx);
+    JS_DestroyContext(cx);
+    JS_DestroyRuntime(rt);
+    JS_ShutDown();
+
+    return 0;
+}

http://git-wip-us.apache.org/repos/asf/couchdb/blob/add91738/apps/couch/priv/couch_js/sm180.c
----------------------------------------------------------------------
diff --git a/apps/couch/priv/couch_js/sm180.c b/apps/couch/priv/couch_js/sm180.c
new file mode 100644
index 0000000..5fb8ce0
--- /dev/null
+++ b/apps/couch/priv/couch_js/sm180.c
@@ -0,0 +1,407 @@
+// 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 <jsapi.h>
+#include "http.h"
+#include "utf8.h"
+#include "util.h"
+
+
+#define SETUP_REQUEST(cx) \
+    JS_SetContextThread(cx); \
+    JS_BeginRequest(cx);
+#define FINISH_REQUEST(cx) \
+    JS_EndRequest(cx); \
+    JS_ClearContextThread(cx);
+
+
+static JSBool
+req_ctor(JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval)
+{
+    return http_ctor(cx, obj);
+}
+
+
+static void 
+req_dtor(JSContext* cx, JSObject* obj)
+{
+    http_dtor(cx, obj);
+}
+
+
+static JSBool
+req_open(JSContext* cx, uintN argc, jsval* vp)
+{
+    JSObject* obj = JS_THIS_OBJECT(cx, vp);
+    jsval* argv = JS_ARGV(cx, vp);
+    JSBool ret = JS_FALSE;
+
+    if(argc == 2) {
+        ret = http_open(cx, obj, argv[0], argv[1], JSVAL_FALSE);
+    } else if(argc == 3) {
+        ret = http_open(cx, obj, argv[0], argv[1], argv[2]);
+    } else {
+        JS_ReportError(cx, "Invalid call to CouchHTTP.open");
+    }
+
+    JS_SET_RVAL(cx, vp, JSVAL_VOID);
+    return ret;
+}
+
+
+static JSBool
+req_set_hdr(JSContext* cx, uintN argc, jsval* vp)
+{
+    JSObject* obj = JS_THIS_OBJECT(cx, vp);
+    jsval* argv = JS_ARGV(cx, vp);
+    JSBool ret = JS_FALSE;
+
+    if(argc == 2) {
+        ret = http_set_hdr(cx, obj, argv[0], argv[1]);
+    } else {
+        JS_ReportError(cx, "Invalid call to CouchHTTP.set_header");
+    }
+
+    JS_SET_RVAL(cx, vp, JSVAL_VOID);
+    return ret;
+}
+
+
+static JSBool
+req_send(JSContext* cx, uintN argc, jsval* vp)
+{
+    JSObject* obj = JS_THIS_OBJECT(cx, vp);
+    jsval* argv = JS_ARGV(cx, vp);
+    JSBool ret = JS_FALSE;
+
+    if(argc == 1) {
+        ret = http_send(cx, obj, argv[0]);
+    } else {
+        JS_ReportError(cx, "Invalid call to CouchHTTP.send");
+    }
+
+    JS_SET_RVAL(cx, vp, JSVAL_VOID);
+    return ret;
+}
+
+
+static JSBool
+req_status(JSContext* cx, JSObject* obj, jsval idval, jsval* vp)
+{
+    int status = http_status(cx, obj);
+    if(status < 0)
+        return JS_FALSE;
+
+    if(INT_FITS_IN_JSVAL(status)) {
+        JS_SET_RVAL(cx, vp, INT_TO_JSVAL(status));
+        return JS_TRUE;
+    } else {
+        JS_ReportError(cx, "Invalid HTTP status.");
+        return JS_FALSE;
+    }
+}
+
+
+static JSBool
+base_url(JSContext *cx, JSObject* obj, jsid pid, jsval* vp)
+{
+    couch_args *args = (couch_args*)JS_GetContextPrivate(cx);
+    return http_uri(cx, obj, args, &JS_RVAL(cx, vp));
+}
+
+
+static JSBool
+evalcx(JSContext *cx, uintN argc, jsval* vp)
+{
+    jsval* argv = JS_ARGV(cx, vp);
+    JSString *str;
+    JSObject *sandbox;
+    JSContext *subcx;
+    const jschar *src;
+    size_t srclen;
+    jsval rval;
+    JSBool ret = JS_FALSE;
+    char *name = NULL;
+
+    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(argc > 2) {
+      name = enc_string(cx, argv[2], NULL);
+    }
+
+    if(srclen == 0) {
+        JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(sandbox));
+    } else {
+        JS_EvaluateUCScript(subcx, sandbox, src, srclen, name, 1, &rval);
+        JS_SET_RVAL(cx, vp, rval);
+    }
+    
+    ret = JS_TRUE;
+
+done:
+    if(name) JS_free(cx, name);
+    FINISH_REQUEST(subcx);
+    JS_DestroyContext(subcx);
+    return ret;
+}
+
+
+static JSBool
+gc(JSContext* cx, uintN argc, jsval* vp)
+{
+    JS_GC(cx);
+    JS_SET_RVAL(cx, vp, JSVAL_VOID);
+    return JS_TRUE;
+}
+
+
+static JSBool
+print(JSContext* cx, uintN argc, jsval* vp)
+{
+    jsval* argv = JS_ARGV(cx, vp);
+    couch_print(cx, argc, argv);
+    JS_SET_RVAL(cx, vp, JSVAL_VOID);
+    return JS_TRUE;
+}
+
+
+static JSBool
+quit(JSContext* cx, uintN argc, jsval* vp)
+{
+    jsval* argv = JS_ARGV(cx, vp);
+    int exit_code = 0;
+    JS_ConvertArguments(cx, argc, argv, "/i", &exit_code);
+    exit(exit_code);
+}
+
+
+static JSBool
+readline(JSContext* cx, uintN argc, jsval* vp)
+{
+    JSString* line;
+
+    /* GC Occasionally */
+    JS_MaybeGC(cx);
+
+    line = couch_readline(cx, stdin);
+    if(line == NULL) return JS_FALSE;
+
+    JS_SET_RVAL(cx, vp, STRING_TO_JSVAL(line));
+    return JS_TRUE;
+}
+
+
+static JSBool
+seal(JSContext* cx, uintN argc, jsval* vp)
+{
+    jsval* argv = JS_ARGV(cx, vp);
+    JSObject *target;
+    JSBool deep = JS_FALSE;
+
+    if(!JS_ConvertArguments(cx, argc, argv, "o/b", &target, &deep))
+        return JS_FALSE;
+
+    if(!target) {
+        JS_SET_RVAL(cx, vp, JSVAL_VOID);
+        return JS_TRUE;
+    }
+
+    if(JS_SealObject(cx, target, deep) != JS_TRUE)
+        return JS_FALSE;
+
+    JS_SET_RVAL(cx, vp, JSVAL_VOID);
+    return JS_TRUE;
+}
+
+
+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,
+    req_dtor,
+    JSCLASS_NO_OPTIONAL_MEMBERS
+};
+
+
+JSPropertySpec CouchHTTPProperties[] = {
+    {"status", 0, JSPROP_READONLY, req_status, NULL},
+    {"base_url", 0, JSPROP_READONLY | JSPROP_SHARED, base_url, NULL},
+    {0, 0, 0, 0, 0}
+};
+
+
+JSFunctionSpec CouchHTTPFunctions[] = {
+    JS_FS("_open", (JSNative) req_open, 3, JSFUN_FAST_NATIVE, 0),
+    JS_FS("_setRequestHeader", (JSNative) req_set_hdr, 2, JSFUN_FAST_NATIVE, 0),
+    JS_FS("_send", (JSNative) req_send, 1, JSFUN_FAST_NATIVE, 0),
+    JS_FS_END
+};
+
+
+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
+};
+
+
+static JSFunctionSpec global_functions[] = {
+    JS_FS("evalcx", (JSNative) evalcx, 0, JSFUN_FAST_NATIVE, 0),
+    JS_FS("gc", (JSNative) gc, 0, JSFUN_FAST_NATIVE, 0),
+    JS_FS("print", (JSNative) print, 0, JSFUN_FAST_NATIVE, 0),
+    JS_FS("quit", (JSNative) quit, 0, JSFUN_FAST_NATIVE, 0),
+    JS_FS("readline", (JSNative) readline, 0, JSFUN_FAST_NATIVE, 0),
+    JS_FS("seal", (JSNative) seal, 0, JSFUN_FAST_NATIVE, 0),
+    JS_FS_END
+};
+
+
+int
+main(int argc, const char* argv[])
+{
+    JSRuntime* rt = NULL;
+    JSContext* cx = NULL;
+    JSObject* global = NULL;
+    JSObject* klass = NULL;
+    JSScript* script;
+    JSString* scriptsrc;
+    jschar* schars;
+    size_t slen;
+    jsval sroot;
+    jsval result;
+    int i;
+
+    couch_args* args = couch_parse_args(argc, argv);
+
+    rt = JS_NewRuntime(args->stack_size);
+    if(rt == NULL)
+        return 1;
+
+    cx = JS_NewContext(rt, 8L * 1024L);
+    if(cx == NULL)
+        return 1;
+
+    JS_SetErrorReporter(cx, couch_error);
+    JS_ToggleOptions(cx, JSOPTION_XML);
+    JS_SetContextPrivate(cx, args);
+    
+    SETUP_REQUEST(cx);
+
+    global = JS_NewObject(cx, &global_class, NULL, NULL);
+    if(global == NULL)
+        return 1;
+
+    JS_SetGlobalObject(cx, global);
+    
+    if(!JS_InitStandardClasses(cx, global))
+        return 1;
+
+    if(couch_load_funcs(cx, global, global_functions) != JS_TRUE)
+        return 1;
+ 
+    if(args->use_http) {
+        http_check_enabled();
+
+        klass = JS_InitClass(
+            cx, global,
+            NULL,
+            &CouchHTTPClass, req_ctor,
+            0,
+            CouchHTTPProperties, CouchHTTPFunctions,
+            NULL, NULL
+        );
+
+        if(!klass)
+        {
+            fprintf(stderr, "Failed to initialize CouchHTTP class.\n");
+            exit(2);
+        }
+    } 
+
+    for (i = 0 ; args->scripts[i] ; i++) {
+        // Convert script source to jschars.
+        scriptsrc = couch_readfile(cx, args->scripts[i]);
+        if(!scriptsrc)
+            return 1;
+
+        schars = JS_GetStringChars(scriptsrc);
+        slen = JS_GetStringLength(scriptsrc);
+
+        // Root it so GC doesn't collect it.
+        sroot = STRING_TO_JSVAL(scriptsrc);
+        if(JS_AddRoot(cx, &sroot) != JS_TRUE) {
+            fprintf(stderr, "Internal root error.\n");
+            return 1;
+        }
+
+        // Compile and run
+        script = JS_CompileUCScript(cx, global, schars, slen,
+                                    args->scripts[i], 1);
+        if(!script) {
+            fprintf(stderr, "Failed to compile script.\n");
+            return 1;
+        }
+
+        JS_ExecuteScript(cx, global, script, &result);
+
+        // Warning message if we don't remove it.
+        JS_RemoveRoot(cx, &sroot);
+    }
+
+    FINISH_REQUEST(cx);
+    JS_DestroyContext(cx);
+    JS_DestroyRuntime(rt);
+    JS_ShutDown();
+
+    return 0;
+}

http://git-wip-us.apache.org/repos/asf/couchdb/blob/add91738/apps/couch/priv/couch_js/sm185.c
----------------------------------------------------------------------
diff --git a/apps/couch/priv/couch_js/sm185.c b/apps/couch/priv/couch_js/sm185.c
new file mode 100644
index 0000000..c378d4a
--- /dev/null
+++ b/apps/couch/priv/couch_js/sm185.c
@@ -0,0 +1,431 @@
+// 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 <jsapi.h>
+#include "http.h"
+#include "utf8.h"
+#include "util.h"
+
+
+#define SETUP_REQUEST(cx) \
+    JS_SetContextThread(cx); \
+    JS_BeginRequest(cx);
+#define FINISH_REQUEST(cx) \
+    JS_EndRequest(cx); \
+    JS_ClearContextThread(cx);
+
+
+static JSClass global_class = {
+    "GlobalClass",
+    JSCLASS_GLOBAL_FLAGS,
+    JS_PropertyStub,
+    JS_PropertyStub,
+    JS_PropertyStub,
+    JS_StrictPropertyStub,
+    JS_EnumerateStub,
+    JS_ResolveStub,
+    JS_ConvertStub,
+    JS_FinalizeStub,
+    JSCLASS_NO_OPTIONAL_MEMBERS
+};
+
+
+static JSBool
+req_ctor(JSContext* cx, uintN argc, jsval* vp)
+{
+    JSBool ret;
+    JSObject* obj = JS_NewObjectForConstructor(cx, vp);
+    if(!obj) {
+        JS_ReportError(cx, "Failed to create CouchHTTP instance.\n");
+        return JS_FALSE;
+    }
+    ret = http_ctor(cx, obj);
+    JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(obj));
+    return ret;
+}
+
+
+static void 
+req_dtor(JSContext* cx, JSObject* obj)
+{
+    http_dtor(cx, obj);
+}
+
+
+static JSBool
+req_open(JSContext* cx, uintN argc, jsval* vp)
+{
+    JSObject* obj = JS_THIS_OBJECT(cx, vp);
+    jsval* argv = JS_ARGV(cx, vp);
+    JSBool ret = JS_FALSE;
+
+    if(argc == 2) {
+        ret = http_open(cx, obj, argv[0], argv[1], JSVAL_FALSE);
+    } else if(argc == 3) {
+        ret = http_open(cx, obj, argv[0], argv[1], argv[2]);
+    } else {
+        JS_ReportError(cx, "Invalid call to CouchHTTP.open");
+    }
+
+    JS_SET_RVAL(cx, vp, JSVAL_VOID);
+    return ret;
+}
+
+
+static JSBool
+req_set_hdr(JSContext* cx, uintN argc, jsval* vp)
+{
+    JSObject* obj = JS_THIS_OBJECT(cx, vp);
+    jsval* argv = JS_ARGV(cx, vp);
+    JSBool ret = JS_FALSE;
+
+    if(argc == 2) {
+        ret = http_set_hdr(cx, obj, argv[0], argv[1]);
+    } else {
+        JS_ReportError(cx, "Invalid call to CouchHTTP.set_header");
+    }
+
+    JS_SET_RVAL(cx, vp, JSVAL_VOID);
+    return ret;
+}
+
+
+static JSBool
+req_send(JSContext* cx, uintN argc, jsval* vp)
+{
+    JSObject* obj = JS_THIS_OBJECT(cx, vp);
+    jsval* argv = JS_ARGV(cx, vp);
+    JSBool ret = JS_FALSE;
+
+    if(argc == 1) {
+        ret = http_send(cx, obj, argv[0]);
+    } else {
+        JS_ReportError(cx, "Invalid call to CouchHTTP.send");
+    }
+
+    JS_SET_RVAL(cx, vp, JSVAL_VOID);
+    return ret;
+}
+
+
+static JSBool
+req_status(JSContext* cx, JSObject* obj, jsid pid, jsval* vp)
+{
+    int status = http_status(cx, obj);
+    if(status < 0)
+        return JS_FALSE;
+
+    JS_SET_RVAL(cx, vp, INT_TO_JSVAL(status));
+    return JS_TRUE;
+}
+
+
+static JSBool
+base_url(JSContext *cx, JSObject* obj, jsid pid, jsval* vp)
+{
+    couch_args *args = (couch_args*)JS_GetContextPrivate(cx);
+    return http_uri(cx, obj, args, &JS_RVAL(cx, vp));
+}
+
+
+static JSBool
+evalcx(JSContext *cx, uintN argc, jsval* vp)
+{
+    jsval* argv = JS_ARGV(cx, vp);
+    JSString* str;
+    JSObject* sandbox;
+    JSObject* global;
+    JSContext* subcx;
+    JSCrossCompartmentCall* call = NULL;
+    const jschar* src;
+    size_t srclen;
+    jsval rval;
+    JSBool ret = JS_FALSE;
+    char *name = NULL;
+
+    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_GetStringCharsAndLength(cx, str, &srclen);
+
+    // Re-use the compartment associated with the main context,
+    // rather than creating a new compartment */
+    global = JS_GetGlobalObject(cx);
+    if(global == NULL) goto done;
+    call = JS_EnterCrossCompartmentCall(subcx, global);
+
+    if(!sandbox) {
+        sandbox = JS_NewGlobalObject(subcx, &global_class);
+        if(!sandbox || !JS_InitStandardClasses(subcx, sandbox)) {
+            goto done;
+        }
+    }
+
+    if(argc > 2) {
+        name = enc_string(cx, argv[2], NULL);
+    }
+
+    if(srclen == 0) {
+        JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(sandbox));
+    } else {
+        JS_EvaluateUCScript(subcx, sandbox, src, srclen, name, 1, &rval);
+        JS_SET_RVAL(cx, vp, rval);
+    }
+    
+    ret = JS_TRUE;
+
+done:
+    if(name) JS_free(cx, name);
+    JS_LeaveCrossCompartmentCall(call);
+    FINISH_REQUEST(subcx);
+    JS_DestroyContext(subcx);
+    return ret;
+}
+
+
+static JSBool
+gc(JSContext* cx, uintN argc, jsval* vp)
+{
+    JS_GC(cx);
+    JS_SET_RVAL(cx, vp, JSVAL_VOID);
+    return JS_TRUE;
+}
+
+
+static JSBool
+print(JSContext* cx, uintN argc, jsval* vp)
+{
+    jsval* argv = JS_ARGV(cx, vp);
+    couch_print(cx, argc, argv);
+    JS_SET_RVAL(cx, vp, JSVAL_VOID);
+    return JS_TRUE;
+}
+
+
+static JSBool
+quit(JSContext* cx, uintN argc, jsval* vp)
+{
+    jsval* argv = JS_ARGV(cx, vp);
+    int exit_code = 0;
+    JS_ConvertArguments(cx, argc, argv, "/i", &exit_code);
+    exit(exit_code);
+}
+
+
+static JSBool
+readline(JSContext* cx, uintN argc, jsval* vp)
+{
+    JSString* line;
+
+    /* GC Occasionally */
+    JS_MaybeGC(cx);
+
+    line = couch_readline(cx, stdin);
+    if(line == NULL) return JS_FALSE;
+
+    JS_SET_RVAL(cx, vp, STRING_TO_JSVAL(line));
+    return JS_TRUE;
+}
+
+
+static JSBool
+seal(JSContext* cx, uintN argc, jsval* vp)
+{
+    jsval* argv = JS_ARGV(cx, vp);
+    JSObject *target;
+    JSBool deep = JS_FALSE;
+    JSBool ret;
+
+    if(!JS_ConvertArguments(cx, argc, argv, "o/b", &target, &deep))
+        return JS_FALSE;
+
+    if(!target) {
+        JS_SET_RVAL(cx, vp, JSVAL_VOID);
+        return JS_TRUE;
+    }
+
+    
+    ret = deep ? JS_DeepFreezeObject(cx, target) : JS_FreezeObject(cx, target);
+    JS_SET_RVAL(cx, vp, JSVAL_VOID);
+    return ret;
+}
+
+
+JSClass CouchHTTPClass = {
+    "CouchHTTP",
+    JSCLASS_HAS_PRIVATE
+        | JSCLASS_CONSTRUCT_PROTOTYPE
+        | JSCLASS_HAS_RESERVED_SLOTS(2),
+    JS_PropertyStub,
+    JS_PropertyStub,
+    JS_PropertyStub,
+    JS_StrictPropertyStub,
+    JS_EnumerateStub,
+    JS_ResolveStub,
+    JS_ConvertStub,
+    req_dtor,
+    JSCLASS_NO_OPTIONAL_MEMBERS
+};
+
+
+JSPropertySpec CouchHTTPProperties[] = {
+    {"status", 0, JSPROP_READONLY, req_status, NULL},
+    {"base_url", 0, JSPROP_READONLY | JSPROP_SHARED, base_url, NULL},
+    {0, 0, 0, 0, 0}
+};
+
+
+JSFunctionSpec CouchHTTPFunctions[] = {
+    JS_FS("_open", req_open, 3, 0),
+    JS_FS("_setRequestHeader", req_set_hdr, 2, 0),
+    JS_FS("_send", req_send, 1, 0),
+    JS_FS_END
+};
+
+
+static JSFunctionSpec global_functions[] = {
+    JS_FS("evalcx", evalcx, 0, 0),
+    JS_FS("gc", gc, 0, 0),
+    JS_FS("print", print, 0, 0),
+    JS_FS("quit", quit, 0, 0),
+    JS_FS("readline", readline, 0, 0),
+    JS_FS("seal", seal, 0, 0),
+    JS_FS_END
+};
+
+
+int
+main(int argc, const char* argv[])
+{
+    JSRuntime* rt = NULL;
+    JSContext* cx = NULL;
+    JSObject* global = NULL;
+    JSCrossCompartmentCall *call = NULL;
+    JSObject* klass = NULL;
+    JSSCRIPT_TYPE script;
+    JSString* scriptsrc;
+    const jschar* schars;
+    size_t slen;
+    jsval sroot;
+    jsval result;
+    int i;
+
+    couch_args* args = couch_parse_args(argc, argv);
+
+    rt = JS_NewRuntime(args->stack_size);
+    if(rt == NULL)
+        return 1;
+
+    cx = JS_NewContext(rt, 8L * 1024L);
+    if(cx == NULL)
+        return 1;
+
+    JS_SetErrorReporter(cx, couch_error);
+    JS_ToggleOptions(cx, JSOPTION_XML);
+    JS_SetOptions(cx, JSOPTION_METHODJIT);
+#ifdef JSOPTION_TYPE_INFERENCE
+    JS_SetOptions(cx, JSOPTION_TYPE_INFERENCE);
+#endif
+    JS_SetContextPrivate(cx, args);
+    
+    SETUP_REQUEST(cx);
+
+    global = JS_NewCompartmentAndGlobalObject(cx, &global_class, NULL);
+    if(global == NULL)
+        return 1;
+
+    call = JS_EnterCrossCompartmentCall(cx, global);
+
+    JS_SetGlobalObject(cx, global);
+    
+    if(!JS_InitStandardClasses(cx, global))
+        return 1;
+
+    if(couch_load_funcs(cx, global, global_functions) != JS_TRUE)
+        return 1;
+ 
+    if(args->use_http) {
+        http_check_enabled();
+
+        klass = JS_InitClass(
+            cx, global,
+            NULL,
+            &CouchHTTPClass, req_ctor,
+            0,
+            CouchHTTPProperties, CouchHTTPFunctions,
+            NULL, NULL
+        );
+
+        if(!klass)
+        {
+            fprintf(stderr, "Failed to initialize CouchHTTP class.\n");
+            exit(2);
+        }
+    } 
+
+    for(i = 0 ; args->scripts[i] ; i++) {
+        // Convert script source to jschars.
+        scriptsrc = couch_readfile(cx, args->scripts[i]);
+        if(!scriptsrc)
+            return 1;
+
+        schars = JS_GetStringCharsAndLength(cx, scriptsrc, &slen);
+
+        // Root it so GC doesn't collect it.
+        sroot = STRING_TO_JSVAL(scriptsrc);
+        if(JS_AddValueRoot(cx, &sroot) != JS_TRUE) {
+            fprintf(stderr, "Internal root error.\n");
+            return 1;
+        }
+
+        // Compile and run
+        script = JS_CompileUCScript(cx, global, schars, slen,
+                                    args->scripts[i], 1);
+        if(!script) {
+            fprintf(stderr, "Failed to compile script.\n");
+            return 1;
+        }
+
+        if(JS_ExecuteScript(cx, global, script, &result) != JS_TRUE) {
+            fprintf(stderr, "Failed to execute script.\n");
+            return 1;
+        }
+
+        // Warning message if we don't remove it.
+        JS_RemoveValueRoot(cx, &sroot);
+
+        // Give the GC a chance to run.
+        JS_MaybeGC(cx);
+    }
+
+    JS_LeaveCrossCompartmentCall(call);
+    FINISH_REQUEST(cx);
+    JS_DestroyContext(cx);
+    JS_DestroyRuntime(rt);
+    JS_ShutDown();
+
+    return 0;
+}

http://git-wip-us.apache.org/repos/asf/couchdb/blob/add91738/apps/couch/priv/couch_js/utf8.c
----------------------------------------------------------------------
diff --git a/apps/couch/priv/couch_js/utf8.c b/apps/couch/priv/couch_js/utf8.c
new file mode 100644
index 0000000..2d23cc2
--- /dev/null
+++ b/apps/couch/priv/couch_js/utf8.c
@@ -0,0 +1,294 @@
+// 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 <jsapi.h>
+#include "config.h"
+
+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 <= 0xD7FF || c >= 0xE000)
+        {
+            v = (uint32) c;
+        }
+        else if(c >= 0xD800 && c <= 0xDBFF)
+        {
+            if(srclen < 1) goto buffer_too_small;
+            c2 = *src++;
+            srclen--;
+            if(c2 >= 0xDC00 && c2 <= 0xDFFF)
+            {
+                v = (uint32) (((c - 0xD800) << 10) + (c2 - 0xDC00) + 0x10000);
+            }
+            else
+            {
+                // Invalid second half of surrogate pair
+                v = (uint32) 0xFFFD;
+            }
+        }
+        else
+        {
+            // Invalid first half surrogate pair
+            v = (uint32) 0xFFFD;
+        }
+
+        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;
+
+buffer_too_small:
+    *dstlenp = (origDstlen - dstlen);
+    return JS_FALSE;
+}
+
+char*
+enc_string(JSContext* cx, jsval arg, size_t* buflen)
+{
+    JSString* str = NULL;
+    const jschar* src = NULL;
+    char* bytes = NULL;
+    size_t srclen = 0;
+    size_t byteslen = 0;
+    
+    str = JS_ValueToString(cx, arg);
+    if(!str) goto error;
+
+#ifdef HAVE_JS_GET_STRING_CHARS_AND_LENGTH
+    src = JS_GetStringCharsAndLength(cx, str, &srclen);
+#else
+    src = JS_GetStringChars(str);
+    srclen = JS_GetStringLength(str);
+#endif
+
+    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;
+}

http://git-wip-us.apache.org/repos/asf/couchdb/blob/add91738/apps/couch/priv/couch_js/utf8.h
----------------------------------------------------------------------
diff --git a/apps/couch/priv/couch_js/utf8.h b/apps/couch/priv/couch_js/utf8.h
new file mode 100644
index 0000000..c5cb86c
--- /dev/null
+++ b/apps/couch/priv/couch_js/utf8.h
@@ -0,0 +1,19 @@
+// 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

http://git-wip-us.apache.org/repos/asf/couchdb/blob/add91738/apps/couch/priv/couch_js/util.c
----------------------------------------------------------------------
diff --git a/apps/couch/priv/couch_js/util.c b/apps/couch/priv/couch_js/util.c
new file mode 100644
index 0000000..b4700de
--- /dev/null
+++ b/apps/couch/priv/couch_js/util.c
@@ -0,0 +1,294 @@
+// 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 <string.h>
+
+#include <jsapi.h>
+
+#include "help.h"
+#include "util.h"
+#include "utf8.h"
+
+
+size_t
+slurp_file(const char* file, char** outbuf_p)
+{
+    FILE* fp;
+    char fbuf[16384];
+    char *buf = NULL;
+    char* tmp;
+    size_t nread = 0;
+    size_t buflen = 0;
+
+    if(strcmp(file, "-") == 0) {
+        fp = stdin;
+    } else {
+        fp = fopen(file, "r");
+        if(fp == NULL) {
+            fprintf(stderr, "Failed to read file: %s\n", file);
+            exit(3);
+        }
+    }
+
+    while((nread = fread(fbuf, 1, 16384, fp)) > 0) {
+        if(buf == NULL) {
+            buf = (char*) malloc(nread + 1);
+            if(buf == NULL) {
+                fprintf(stderr, "Out of memory.\n");
+                exit(3);
+            }
+            memcpy(buf, fbuf, nread);
+        } else {
+            tmp = (char*) malloc(buflen + nread + 1);
+            if(tmp == NULL) {
+                fprintf(stderr, "Out of memory.\n");
+                exit(3);
+            }
+            memcpy(tmp, buf, buflen);
+            memcpy(tmp+buflen, fbuf, nread);
+            free(buf);
+            buf = tmp;
+        }
+        buflen += nread;
+        buf[buflen] = '\0';
+    }
+    *outbuf_p = buf;
+    return buflen + 1;
+}
+
+couch_args*
+couch_parse_args(int argc, const char* argv[])
+{
+    couch_args* args;
+    int i = 1;
+
+    args = (couch_args*) malloc(sizeof(couch_args));
+    if(args == NULL)
+        return NULL;
+
+    memset(args, '\0', sizeof(couch_args));
+    args->stack_size = 64L * 1024L * 1024L;
+
+    while(i < argc) {
+        if(strcmp("-h", argv[i]) == 0) {
+            DISPLAY_USAGE;
+            exit(0);
+        } else if(strcmp("-V", argv[i]) == 0) {
+            DISPLAY_VERSION;
+            exit(0);
+        } else if(strcmp("-H", argv[i]) == 0) {
+            args->use_http = 1;
+        } else if(strcmp("-S", argv[i]) == 0) {
+            args->stack_size = atoi(argv[++i]);
+            if(args->stack_size <= 0) {
+                fprintf(stderr, "Invalid stack size.\n");
+                exit(2);
+            }
+        } else if(strcmp("-u", argv[i]) == 0) {
+            args->uri_file = argv[++i];
+        } else if(strcmp("--", argv[i]) == 0) {
+            i++;
+            break;
+        } else {
+            break;
+        }
+        i++;
+    }
+
+    if(i >= argc) {
+        DISPLAY_USAGE;
+        exit(3);
+    }
+    args->scripts = argv + i;
+
+    return args;
+}
+
+
+int
+couch_fgets(char* buf, int size, FILE* fp)
+{
+    int n, i, c;
+
+    if(size <= 0) return -1;
+    n = size - 1;
+
+    for(i = 0; i < n && (c = getc(fp)) != EOF; i++) {
+        buf[i] = c;
+        if(c == '\n') {
+            i++;
+            break;
+        }
+    }
+
+    buf[i] = '\0';
+    return i;
+}
+
+
+JSString*
+couch_readline(JSContext* cx, FILE* fp)
+{
+    JSString* str;
+    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 = couch_fgets(bytes+used, byteslen-used, fp)) > 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;
+    }
+
+    // Treat empty strings specially
+    if(used == 0) {
+        JS_free(cx, bytes);
+        return JSVAL_TO_STRING(JS_GetEmptyStringValue(cx));
+    }
+
+    // Shring the buffer to the actual data size
+    tmp = JS_realloc(cx, bytes, used);
+    if(!tmp) {
+        JS_free(cx, bytes);
+        return NULL;
+    }
+    bytes = tmp;
+    byteslen = used;
+
+    str = dec_string(cx, bytes, byteslen);
+    JS_free(cx, bytes);
+    return str;
+}
+
+
+JSString*
+couch_readfile(JSContext* cx, const char* filename)
+{
+    JSString *string;
+    size_t byteslen;
+    char *bytes;
+
+    if((byteslen = slurp_file(filename, &bytes))) {
+        string = dec_string(cx, bytes, byteslen);
+
+        free(bytes);
+        return string;
+    }
+    return NULL;    
+}
+
+
+void
+couch_print(JSContext* cx, uintN argc, jsval* argv)
+{
+    char *bytes = NULL;
+    FILE *stream = stdout;
+
+    if (argc) {
+        if (argc > 1 && argv[1] == JSVAL_TRUE) {
+          stream = stderr;
+        }
+        bytes = enc_string(cx, argv[0], NULL);
+        if(!bytes) return;
+        fprintf(stream, "%s", bytes);
+        JS_free(cx, bytes);
+    }
+
+    fputc('\n', stream);
+    fflush(stream);
+}
+
+
+void
+couch_error(JSContext* cx, const char* mesg, JSErrorReport* report)
+{
+    jsval v, replace;
+    char* bytes;
+    JSObject* regexp, *stack;
+    jsval re_args[2];
+
+    if(!report || !JSREPORT_IS_WARNING(report->flags))
+    {
+        fprintf(stderr, "%s\n", mesg);
+
+        // Print a stack trace, if available.
+        if (JSREPORT_IS_EXCEPTION(report->flags) &&
+            JS_GetPendingException(cx, &v))
+        {
+            // Clear the exception before an JS method calls or the result is
+            // infinite, recursive error report generation.
+            JS_ClearPendingException(cx);
+
+            // Use JS regexp to indent the stack trace.
+            // If the regexp can't be created, don't JS_ReportError since it is
+            // probably not productive to wind up here again.
+#ifdef SM185
+            if(JS_GetProperty(cx, JSVAL_TO_OBJECT(v), "stack", &v) &&
+               (regexp = JS_NewRegExpObjectNoStatics(
+                   cx, "^(?=.)", 6, JSREG_GLOB | JSREG_MULTILINE)))
+#else
+            if(JS_GetProperty(cx, JSVAL_TO_OBJECT(v), "stack", &v) &&
+               (regexp = JS_NewRegExpObject(
+                   cx, "^(?=.)", 6, JSREG_GLOB | JSREG_MULTILINE)))
+#endif
+            {
+                // Set up the arguments to ``String.replace()``
+                re_args[0] = OBJECT_TO_JSVAL(regexp);
+                re_args[1] = STRING_TO_JSVAL(JS_InternString(cx, "\t"));
+
+                // Perform the replacement
+                if(JS_ValueToObject(cx, v, &stack) &&
+                   JS_GetProperty(cx, stack, "replace", &replace) &&
+                   JS_CallFunctionValue(cx, stack, replace, 2, re_args, &v))
+                {
+                    // Print the result
+                    bytes = enc_string(cx, v, NULL);
+                    fprintf(stderr, "Stacktrace:\n%s", bytes);
+                    JS_free(cx, bytes);
+                }
+            }
+        }
+    }
+}
+
+
+JSBool
+couch_load_funcs(JSContext* cx, JSObject* obj, JSFunctionSpec* funcs)
+{
+    JSFunctionSpec* f;
+    for(f = funcs; f->name != NULL; f++) {
+        if(!JS_DefineFunction(cx, obj, f->name, f->call, f->nargs, f->flags)) {
+            fprintf(stderr, "Failed to create function: %s\n", f->name);
+            return JS_FALSE;
+        }
+    }
+    return JS_TRUE;
+}

http://git-wip-us.apache.org/repos/asf/couchdb/blob/add91738/apps/couch/priv/couch_js/util.h
----------------------------------------------------------------------
diff --git a/apps/couch/priv/couch_js/util.h b/apps/couch/priv/couch_js/util.h
new file mode 100644
index 0000000..65a2a06
--- /dev/null
+++ b/apps/couch/priv/couch_js/util.h
@@ -0,0 +1,35 @@
+// 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 COUCHJS_UTIL_H
+#define COUCHJS_UTIL_H
+
+#include <jsapi.h>
+
+typedef struct {
+    int          use_http;
+    int          stack_size;
+    const char** scripts;
+    const char*  uri_file;
+    JSString*    uri;
+} couch_args;
+
+couch_args* couch_parse_args(int argc, const char* argv[]);
+int couch_fgets(char* buf, int size, FILE* fp);
+JSString* couch_readline(JSContext* cx, FILE* fp);
+JSString* couch_readfile(JSContext* cx, const char* filename);
+void couch_print(JSContext* cx, uintN argc, jsval* argv);
+void couch_error(JSContext* cx, const char* mesg, JSErrorReport* report);
+JSBool couch_load_funcs(JSContext* cx, JSObject* obj, JSFunctionSpec* funcs);
+
+
+#endif // Included util.h

http://git-wip-us.apache.org/repos/asf/couchdb/blob/add91738/apps/couch/priv/spawnkillable/couchspawnkillable.sh
----------------------------------------------------------------------
diff --git a/apps/couch/priv/spawnkillable/couchspawnkillable.sh b/apps/couch/priv/spawnkillable/couchspawnkillable.sh
new file mode 100644
index 0000000..f8d042e
--- /dev/null
+++ b/apps/couch/priv/spawnkillable/couchspawnkillable.sh
@@ -0,0 +1,20 @@
+#! /bin/sh -e
+
+# 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.
+
+# The purpose of this script is to echo an OS specific command before launching
+# the actual process. This provides a way for Erlang to hard-kill its external
+# processes.
+
+echo "kill -9 $$"
+exec $*

http://git-wip-us.apache.org/repos/asf/couchdb/blob/add91738/apps/couch/priv/spawnkillable/couchspawnkillable_win.c
----------------------------------------------------------------------
diff --git a/apps/couch/priv/spawnkillable/couchspawnkillable_win.c b/apps/couch/priv/spawnkillable/couchspawnkillable_win.c
new file mode 100644
index 0000000..0678231
--- /dev/null
+++ b/apps/couch/priv/spawnkillable/couchspawnkillable_win.c
@@ -0,0 +1,145 @@
+// 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.
+
+// Do what 2 lines of shell script in couchspawnkillable does...
+// * Create a new suspended process with the same (duplicated) standard 
+//   handles as us.
+// * Write a line to stdout, consisting of the path to ourselves, plus
+//   '--kill {pid}' where {pid} is the PID of the newly created process.
+// * Un-suspend the new process.
+// * Wait for the process to terminate.
+// * Terminate with the child's exit-code.
+
+// Later, couch will call us with --kill and the PID, so we dutifully
+// terminate the specified PID.
+
+#include <stdlib.h>
+#include "windows.h"
+
+char *get_child_cmdline(int argc, char **argv)
+{
+    // make a new command-line, but skipping me.
+    // XXX - todo - spaces etc in args???
+    int i;
+    char *p, *cmdline;
+    int nchars = 0;
+    int nthis = 1;
+    for (i=1;i<argc;i++)
+        nchars += strlen(argv[i])+1;
+    cmdline = p = malloc(nchars+1);
+    if (!cmdline)
+        return NULL;
+    for (i=1;i<argc;i++) {
+        nthis = strlen(argv[i]);
+        strncpy(p, argv[i], nthis);
+        p[nthis] = ' ';
+        p += nthis+1;
+    }
+    // Replace the last space we added above with a '\0'
+    cmdline[nchars-1] = '\0';
+    return cmdline;
+}
+
+// create the child process, returning 0, or the exit-code we will
+// terminate with.
+int create_child(int argc, char **argv, PROCESS_INFORMATION *pi)
+{
+    char buf[1024];
+    DWORD dwcreate;
+    STARTUPINFO si;
+    char *cmdline;
+    if (argc < 2)
+        return 1;
+    cmdline = get_child_cmdline(argc, argv);
+    if (!cmdline)
+        return 2;
+
+    memset(&si, 0, sizeof(si));
+    si.cb = sizeof(si);
+    // depending on how *our* parent is started, we may or may not have
+    // a valid stderr stream - so although we try and duplicate it, only
+    // failing to duplicate stdin and stdout are considered fatal.
+    if (!DuplicateHandle(GetCurrentProcess(),
+                       GetStdHandle(STD_INPUT_HANDLE),
+                       GetCurrentProcess(),
+                       &si.hStdInput,
+                       0,
+                       TRUE, // inheritable
+                       DUPLICATE_SAME_ACCESS) ||
+       !DuplicateHandle(GetCurrentProcess(),
+                       GetStdHandle(STD_OUTPUT_HANDLE),
+                       GetCurrentProcess(),
+                       &si.hStdOutput,
+                       0,
+                       TRUE, // inheritable
+                       DUPLICATE_SAME_ACCESS)) {
+        return 3;
+    }
+    DuplicateHandle(GetCurrentProcess(),
+                   GetStdHandle(STD_ERROR_HANDLE),
+                   GetCurrentProcess(),
+                   &si.hStdError,
+                   0,
+                   TRUE, // inheritable
+                   DUPLICATE_SAME_ACCESS);
+
+    si.dwFlags = STARTF_USESTDHANDLES;
+    dwcreate = CREATE_SUSPENDED;
+    if (!CreateProcess( NULL, cmdline,
+                        NULL,
+                        NULL,
+                        TRUE, // inherit handles
+                        dwcreate,
+                        NULL, // environ
+                        NULL, // cwd
+                        &si,
+                        pi))
+        return 4;
+    return 0;
+}
+
+// and here we go...
+int main(int argc, char **argv)
+{
+    char out_buf[1024];
+    int rc;
+    DWORD cbwritten;
+    DWORD exitcode;
+    PROCESS_INFORMATION pi;
+    if (argc==3 && strcmp(argv[1], "--kill")==0) {
+        HANDLE h = OpenProcess(PROCESS_TERMINATE, 0, atoi(argv[2]));
+        if (!h)
+            return 1;
+        if (!TerminateProcess(h, 0))
+            return 2;
+        CloseHandle(h);
+        return 0;
+    }
+    // spawn the new suspended process
+    rc = create_child(argc, argv, &pi);
+    if (rc)
+        return rc;
+    // Write the 'terminate' command, which includes this PID, back to couch.
+    // *sob* - what about spaces etc?
+    sprintf_s(out_buf, sizeof(out_buf), "%s --kill %d\n", 
+              argv[0], pi.dwProcessId);
+    WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), out_buf, strlen(out_buf), 
+              &cbwritten, NULL);
+    // Let the child process go...
+    ResumeThread(pi.hThread);
+    // Wait for the process to terminate so we can reflect the exit code
+    // back to couch.
+    WaitForSingleObject(pi.hProcess, INFINITE);
+    if (!GetExitCodeProcess(pi.hProcess, &exitcode))
+        return 6;
+    return exitcode;
+}

http://git-wip-us.apache.org/repos/asf/couchdb/blob/add91738/apps/couch/priv/stat_descriptions.cfg.in
----------------------------------------------------------------------
diff --git a/apps/couch/priv/stat_descriptions.cfg.in b/apps/couch/priv/stat_descriptions.cfg.in
new file mode 100644
index 0000000..b80d768
--- /dev/null
+++ b/apps/couch/priv/stat_descriptions.cfg.in
@@ -0,0 +1,50 @@
+%% 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.
+
+% Style guide for descriptions: Start with a lowercase letter & do not add
+% a trailing full-stop / period
+% Please keep this in alphabetical order
+
+{couchdb, database_writes, "number of times a database was changed"}.
+{couchdb, database_reads, "number of times a document was read from a database"}.
+{couchdb, open_databases, "number of open databases"}.
+{couchdb, open_os_files, "number of file descriptors CouchDB has open"}.
+{couchdb, request_time, "length of a request inside CouchDB without MochiWeb"}.
+{couchdb, auth_cache_hits, "number of authentication cache hits"}.
+{couchdb, auth_cache_misses, "number of authentication cache misses"}.
+
+{httpd, bulk_requests, "number of bulk requests"}.
+{httpd, requests, "number of HTTP requests"}.
+{httpd, temporary_view_reads, "number of temporary view reads"}.
+{httpd, view_reads, "number of view reads"}.
+{httpd, clients_requesting_changes, "number of clients for continuous _changes"}.
+
+{httpd_request_methods, 'COPY', "number of HTTP COPY requests"}.
+{httpd_request_methods, 'DELETE', "number of HTTP DELETE requests"}.
+{httpd_request_methods, 'GET', "number of HTTP GET requests"}.
+{httpd_request_methods, 'HEAD', "number of HTTP HEAD requests"}.
+{httpd_request_methods, 'POST', "number of HTTP POST requests"}.
+{httpd_request_methods, 'PUT', "number of HTTP PUT requests"}.
+
+{httpd_status_codes, '200', "number of HTTP 200 OK responses"}.
+{httpd_status_codes, '201', "number of HTTP 201 Created responses"}.
+{httpd_status_codes, '202', "number of HTTP 202 Accepted responses"}.
+{httpd_status_codes, '301', "number of HTTP 301 Moved Permanently responses"}.
+{httpd_status_codes, '304', "number of HTTP 304 Not Modified responses"}.
+{httpd_status_codes, '400', "number of HTTP 400 Bad Request responses"}.
+{httpd_status_codes, '401', "number of HTTP 401 Unauthorized responses"}.
+{httpd_status_codes, '403', "number of HTTP 403 Forbidden responses"}.
+{httpd_status_codes, '404', "number of HTTP 404 Not Found responses"}.
+{httpd_status_codes, '405', "number of HTTP 405 Method Not Allowed responses"}.
+{httpd_status_codes, '409', "number of HTTP 409 Conflict responses"}.
+{httpd_status_codes, '412', "number of HTTP 412 Precondition Failed responses"}.
+{httpd_status_codes, '500', "number of HTTP 500 Internal Server Error responses"}.

http://git-wip-us.apache.org/repos/asf/couchdb/blob/add91738/apps/couch/src/Makefile.am
----------------------------------------------------------------------
diff --git a/apps/couch/src/Makefile.am b/apps/couch/src/Makefile.am
new file mode 100644
index 0000000..9fe19bc
--- /dev/null
+++ b/apps/couch/src/Makefile.am
@@ -0,0 +1,198 @@
+## 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.
+
+SUBDIRS = priv
+
+# devdocdir = $(localdocdir)/developer/couchdb
+couchlibdir = $(localerlanglibdir)/couch-$(version)
+couchincludedir = $(couchlibdir)/include
+couchebindir = $(couchlibdir)/ebin
+
+couchinclude_DATA = couch_db.hrl couch_js_functions.hrl
+couchebin_DATA = $(compiled_files)
+
+# dist_devdoc_DATA = $(doc_base) $(doc_modules)
+
+CLEANFILES = $(compiled_files) $(doc_base)
+
+# CLEANFILES = $(doc_modules) edoc-info
+
+source_files = \
+    couch.erl \
+    couch_app.erl \
+    couch_auth_cache.erl \
+    couch_btree.erl \
+    couch_changes.erl \
+    couch_compaction_daemon.erl \
+    couch_compress.erl \
+    couch_config.erl \
+    couch_config_writer.erl \
+    couch_db.erl \
+    couch_db_update_notifier.erl \
+    couch_db_update_notifier_sup.erl \
+    couch_doc.erl \
+    couch_drv.erl \
+    couch_ejson_compare.erl \
+    couch_event_sup.erl \
+    couch_external_manager.erl \
+    couch_external_server.erl \
+    couch_file.erl \
+    couch_httpd.erl \
+    couch_httpd_db.erl \
+    couch_httpd_auth.erl \
+    couch_httpd_cors.erl \
+    couch_httpd_oauth.erl \
+    couch_httpd_external.erl \
+    couch_httpd_misc_handlers.erl \
+    couch_httpd_proxy.erl \
+    couch_httpd_rewrite.erl \
+    couch_httpd_stats_handlers.erl \
+    couch_httpd_vhost.erl \
+    couch_key_tree.erl \
+    couch_log.erl \
+    couch_native_process.erl \
+    couch_os_daemons.erl \
+    couch_os_process.erl \
+    couch_passwords.erl \
+    couch_primary_sup.erl \
+    couch_query_servers.erl \
+    couch_ref_counter.erl \
+    couch_secondary_sup.erl \
+    couch_server.erl \
+    couch_server_sup.erl \
+    couch_stats_aggregator.erl \
+    couch_stats_collector.erl \
+    couch_stream.erl \
+    couch_task_status.erl \
+    couch_users_db.erl \
+    couch_util.erl \
+    couch_uuids.erl \
+    couch_db_updater.erl \
+    couch_work_queue.erl \
+    json_stream_parse.erl
+
+EXTRA_DIST = $(source_files) couch_db.hrl couch_js_functions.hrl
+
+compiled_files = \
+    couch.app \
+    couch.beam \
+    couch_app.beam \
+    couch_auth_cache.beam \
+    couch_btree.beam \
+    couch_changes.beam \
+    couch_compaction_daemon.beam \
+    couch_compress.beam \
+    couch_config.beam \
+    couch_config_writer.beam \
+    couch_db.beam \
+    couch_db_update_notifier.beam \
+    couch_db_update_notifier_sup.beam \
+    couch_doc.beam \
+    couch_drv.beam \
+    couch_ejson_compare.beam \
+    couch_event_sup.beam \
+    couch_external_manager.beam \
+    couch_external_server.beam \
+    couch_file.beam \
+    couch_httpd.beam \
+    couch_httpd_db.beam \
+    couch_httpd_auth.beam \
+    couch_httpd_oauth.beam \
+    couch_httpd_cors.beam \
+    couch_httpd_proxy.beam \
+    couch_httpd_external.beam \
+    couch_httpd_misc_handlers.beam \
+    couch_httpd_rewrite.beam \
+    couch_httpd_stats_handlers.beam \
+    couch_httpd_vhost.beam \
+    couch_key_tree.beam \
+    couch_log.beam \
+    couch_native_process.beam \
+    couch_os_daemons.beam \
+    couch_os_process.beam \
+    couch_passwords.beam \
+    couch_primary_sup.beam \
+    couch_query_servers.beam \
+    couch_ref_counter.beam \
+    couch_secondary_sup.beam \
+    couch_server.beam \
+    couch_server_sup.beam \
+    couch_stats_aggregator.beam \
+    couch_stats_collector.beam \
+    couch_stream.beam \
+    couch_task_status.beam \
+    couch_users_db.beam \
+    couch_util.beam \
+    couch_uuids.beam \
+    couch_db_updater.beam \
+    couch_work_queue.beam \
+    json_stream_parse.beam
+
+# doc_base = \
+#     erlang.png \
+#     index.html \
+#     modules-frame.html \
+#     overview-summary.html \
+#     packages-frame.html \
+#     stylesheet.css
+
+# doc_modules = \
+#     couch_btree.html \
+#     couch_config.html \
+#     couch_config_writer.html \
+#     couch_db.html \
+#     couch_db_update_notifier.html \
+#     couch_db_update_notifier_sup.html \
+#     couch_doc.html \
+#     couch_event_sup.html \
+#     couch_file.html \
+#     couch_httpd.html \
+#     couch_key_tree.html \
+#     couch_log.html \
+#     couch_query_servers.html \
+#     couch_rep.html \
+#     couch_rep_sup.html \
+#     couch_server.html \
+#     couch_server_sup.html \
+#     couch_stream.html \
+#     couch_util.html
+
+if WINDOWS
+couch.app: couch.app.tpl
+	modules=`find . -name "*.erl" \! -name ".*" -exec basename {} .erl \; | tr '\n' ',' | sed "s/,$$//"`; \
+	sed -e "s|%package_name%|@package_name@|g" \
+			-e "s|%version%|@version@|g" \
+			-e "s|@modules@|$$modules|g" \
+			-e "s|%localconfdir%|../etc/couchdb|g" \
+			-e "s|@defaultini@|default.ini|g" \
+			-e "s|@localini@|local.ini|g" > \
+	$@ < $<
+else
+couch.app: couch.app.tpl
+	modules=`{ find . -name "*.erl" \! -name ".*" -exec basename {} .erl \; | tr '\n' ','; echo ''; } | sed "s/,$$//"`; \
+	sed -e "s|%package_name%|@package_name@|g" \
+			-e "s|%version%|@version@|g" \
+			-e "s|@modules@|$$modules|g" \
+			-e "s|%localconfdir%|@localconfdir@|g" \
+			-e "s|@defaultini@|default.ini|g" \
+			-e "s|@localini@|local.ini|g" > \
+	$@ < $<
+	chmod +x $@
+endif
+
+# $(dist_devdoc_DATA): edoc-info
+
+# $(ERL) -noshell -run edoc_run files [\"$<\"]
+
+%.beam: %.erl couch_db.hrl couch_js_functions.hrl
+	$(ERLC) $(ERLC_FLAGS) ${TEST} $<;
+

http://git-wip-us.apache.org/repos/asf/couchdb/blob/add91738/apps/couch/src/couch.app.src
----------------------------------------------------------------------
diff --git a/apps/couch/src/couch.app.src b/apps/couch/src/couch.app.src
new file mode 100644
index 0000000..2d14148
--- /dev/null
+++ b/apps/couch/src/couch.app.src
@@ -0,0 +1,23 @@
+{application, couch, [
+    {description, "@package_name@"},
+    {vsn, "@version@"},
+    {registered, [
+        couch_config,
+        couch_db_update,
+        couch_db_update_notifier_sup,
+        couch_external_manager,
+        couch_httpd,
+        couch_log,
+        couch_primary_services,
+        couch_query_servers,
+        couch_secondary_services,
+        couch_server,
+        couch_server_sup,
+        couch_stats_aggregator,
+        couch_stats_collector,
+        couch_task_status
+    ]},
+    {mod, {couch_app, []}},
+    {applications, [kernel, stdlib, crypto, sasl, public_key, ssl,
+                    inets, oauth, ibrowse, mochiweb, os_mon]}
+]}.


Mime
View raw message