From 07cc4e305e806a7bb236fbb8f6d9893a2011d85e Mon Sep 17 00:00:00 2001 From: Micah Anderson Date: Wed, 15 Jan 2014 18:14:23 +0000 Subject: initial debianization --- debian/README.Debian | 6 + debian/README.build | 10 + debian/bigcouch.lintian-overrides | 1 + debian/bigcouch.postinst | 26 + debian/bigcouch.postrm | 24 + debian/bigcouch.prerm | 12 + debian/changelog | 36 + debian/compat | 1 + debian/control | 16 + debian/copyright | 47 + debian/docs | 1 + debian/etc/sv/bigcouch/log/run | 2 + debian/etc/sv/bigcouch/run | 4 + debian/patches/bigcouch-configuration-changes | 2950 +++++++++++++++++++++++++ debian/patches/disable_embedded_rebar | 82 + debian/patches/disable_embedded_scons | 20 + debian/patches/fix-body_too_large-error | 16 + debian/patches/remove_external_dependencies | 32 + debian/patches/series | 7 + debian/patches/support-destdir.patch | 25 + debian/patches/update-pthread-linking-flags | 27 + debian/rules | 19 + debian/source/format | 1 + 23 files changed, 3365 insertions(+) create mode 100644 debian/README.Debian create mode 100644 debian/README.build create mode 100644 debian/bigcouch.lintian-overrides create mode 100644 debian/bigcouch.postinst create mode 100644 debian/bigcouch.postrm create mode 100644 debian/bigcouch.prerm create mode 100644 debian/changelog create mode 100644 debian/compat create mode 100644 debian/control create mode 100644 debian/copyright create mode 100644 debian/docs create mode 100644 debian/etc/sv/bigcouch/log/run create mode 100644 debian/etc/sv/bigcouch/run create mode 100644 debian/patches/bigcouch-configuration-changes create mode 100644 debian/patches/disable_embedded_rebar create mode 100644 debian/patches/disable_embedded_scons create mode 100644 debian/patches/fix-body_too_large-error create mode 100644 debian/patches/remove_external_dependencies create mode 100644 debian/patches/series create mode 100644 debian/patches/support-destdir.patch create mode 100644 debian/patches/update-pthread-linking-flags create mode 100755 debian/rules create mode 100644 debian/source/format diff --git a/debian/README.Debian b/debian/README.Debian new file mode 100644 index 00000000..28e0e728 --- /dev/null +++ b/debian/README.Debian @@ -0,0 +1,6 @@ +bigcouch for Debian +------------------- + +First package attempt using standard tools. + + -- Robert Newson Tue, 05 Apr 2011 20:53:35 +0100 diff --git a/debian/README.build b/debian/README.build new file mode 100644 index 00000000..b928e380 --- /dev/null +++ b/debian/README.build @@ -0,0 +1,10 @@ +To build this package you will need to create ../bigcouch-$VERSION.tar.gz as follows + +1) git clone git://github.com/cloudant/bigcouch.git +2) git archive --format=tar bigcouch-$VERSION | gzip > bigcouch_$VERSION.orig.tar.gz +3) move that file to the directory above this one. +4) untar that file into *this* directory. + +Now build the package; + +4) debuild -us -uc diff --git a/debian/bigcouch.lintian-overrides b/debian/bigcouch.lintian-overrides new file mode 100644 index 00000000..9473130b --- /dev/null +++ b/debian/bigcouch.lintian-overrides @@ -0,0 +1 @@ +bigcouch: dir-or-file-in-opt diff --git a/debian/bigcouch.postinst b/debian/bigcouch.postinst new file mode 100644 index 00000000..59f9d86e --- /dev/null +++ b/debian/bigcouch.postinst @@ -0,0 +1,26 @@ +#!/bin/sh -e + +case $1 in + configure) + if ! getent passwd bigcouch > /dev/null; then + adduser --system --quiet --home /home/bigcouch \ + --shell /bin/bash --group bigcouch + fi + if test "`id -u bigcouch`" -eq 0; then + echo "The bigcouch administrative user must not be root." >&2 + false + fi + if test "`id -g bigcouch`" -eq 0; then + echo "The bigcouch administrative group must not be root." >&2 + false + fi + chown -R bigcouch:bigcouch /opt/bigcouch + mkdir -p /home/bigcouch + chown -R bigcouch:bigcouch /home/bigcouch + chown -R bigcouch:bigcouch /opt/bigcouch + chown -R root:root /etc/sv/bigcouch + ln -sf /etc/sv/bigcouch /etc/service/ + ;; +esac + +#DEBHELPER# diff --git a/debian/bigcouch.postrm b/debian/bigcouch.postrm new file mode 100644 index 00000000..7b0e651a --- /dev/null +++ b/debian/bigcouch.postrm @@ -0,0 +1,24 @@ +#!/bin/sh -e + +case $1 in + purge) + if test -d "/etc/sv/bigcouch"; then + rm -r -f "/etc/sv/bigcouch" + fi + if test -d "/opt/bigcouch"; then + rm -r -f "/opt/bigcouch" + fi + if getent passwd bigcouch > /dev/null && which deluser > /dev/null; then + for PID in `ps --no-headers -u bigcouch -opid` + do + kill $PID + done + deluser bigcouch + fi + if getent group bigcouch > /dev/null && which delgroup > /dev/null; then + delgroup bigcouch + fi + ;; +esac + +#DEBHELPER# diff --git a/debian/bigcouch.prerm b/debian/bigcouch.prerm new file mode 100644 index 00000000..bcb054da --- /dev/null +++ b/debian/bigcouch.prerm @@ -0,0 +1,12 @@ +#!/bin/sh -e + +case $1 in + remove) + if test -d "/etc/service/bigcouch"; then + sv down bigcouch + rm -r -f /etc/service/bigcouch + fi + ;; +esac + +#DEBHELPER# diff --git a/debian/changelog b/debian/changelog new file mode 100644 index 00000000..a119cd7d --- /dev/null +++ b/debian/changelog @@ -0,0 +1,36 @@ +bigcouch (0.4.2-0.1) UNRELEASED; urgency=low + + * replace embedded rebar with Build-dependency on backported version + * add remove_external_dependencies patch to stop pulling the + dependencies via git + * embed the dependencies that were previously pulled in via git from + rebar.config + * refreshed the support-destdir patch + * add fix-body_too_large-error patch to fix problem with POSTing large + data to update handlers + * add update-pthread-linking-flags patch to fix pthread linking + * add disable_embedded_scons patch + * add scons to Build-dependencies + * add patch to hardcode version instead of invoking git + * add patch to add configuration files that are generated by building + process and should be present in the tarball + + -- Micah Anderson Wed, 15 Jan 2014 17:30:31 +0000 + +bigcouch (0.4.2-1) unstable; urgency=low + + * Updated build for 0.4.2 + + -- Robert Newson Fri, 15 Feb 2013 18:02:32 +0000 + +bigcouch (0.4.0-1) unstable; urgency=low + + * Updated build for 0.4.0 + + -- Paul Davis Tue, 01 Nov 2011 16:17:18 +0600 + +bigcouch (0.3.1-1) unstable; urgency=low + + * Initial release (Closes: #nnnn) + + -- Robert Newson Tue, 05 Apr 2011 20:53:35 +0100 diff --git a/debian/compat b/debian/compat new file mode 100644 index 00000000..7f8f011e --- /dev/null +++ b/debian/compat @@ -0,0 +1 @@ +7 diff --git a/debian/control b/debian/control new file mode 100644 index 00000000..3c25dd62 --- /dev/null +++ b/debian/control @@ -0,0 +1,16 @@ +Source: bigcouch +Section: misc +Priority: extra +Maintainer: Cloudant Support +Build-Depends: debhelper, quilt, autotools-dev, libmozjs185-dev, libicu-dev, git | git-core, python, libcurl4-openssl-dev, erlang-dev, erlang-crypto, erlang-inets, erlang-xmerl, erlang-eunit, erlang-os-mon, erlang-ssl, erlang-syntax-tools, erlang-tools, erlang-reltool, rebar, scons +Standards-Version: 3.8.4 +Homepage: http://cloudant.com/ +Vcs-Git: git://github.com/cloudant/bigcouch.git +Vcs-Browser: http://github.com/cloudant/bigcouch + +Package: bigcouch +Architecture: any +Depends: ${shlibs:Depends}, ${misc:Depends}, libmozjs185-1.0, runit +Conflicts: couchdb +Description: BigCouch is a dynamo-style implementation of Apache CouchDB + diff --git a/debian/copyright b/debian/copyright new file mode 100644 index 00000000..d5453d10 --- /dev/null +++ b/debian/copyright @@ -0,0 +1,47 @@ +This work was packaged for Debian by: + + Robert Newson on Tue, 05 Apr 2011 20:53:35 +0100 + +It was downloaded from http://cloudant.com + +Copyright: + + Copyright Cloudant + +License: + + 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. + +On Debian systems, the complete text of the Apache version 2.0 license +can be found in `/usr/share/common-licenses/Apache-2.0'. + +The Debian packaging is: + + Copyright (C) 2011 Robert Newson + +License: + + 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. + +On Debian systems, the complete text of the Apache version 2.0 license +can be found in `/usr/share/common-licenses/Apache-2.0'. diff --git a/debian/docs b/debian/docs new file mode 100644 index 00000000..b43bf86b --- /dev/null +++ b/debian/docs @@ -0,0 +1 @@ +README.md diff --git a/debian/etc/sv/bigcouch/log/run b/debian/etc/sv/bigcouch/log/run new file mode 100644 index 00000000..3195b018 --- /dev/null +++ b/debian/etc/sv/bigcouch/log/run @@ -0,0 +1,2 @@ +#!/bin/sh +exec chpst svlogd -tt ./main diff --git a/debian/etc/sv/bigcouch/run b/debian/etc/sv/bigcouch/run new file mode 100644 index 00000000..875c3f02 --- /dev/null +++ b/debian/etc/sv/bigcouch/run @@ -0,0 +1,4 @@ +#!/bin/bash +exec 2>&1 +export HOME=/home/bigcouch +exec chpst -u bigcouch /opt/bigcouch/bin/bigcouch diff --git a/debian/patches/bigcouch-configuration-changes b/debian/patches/bigcouch-configuration-changes new file mode 100644 index 00000000..0862ca6b --- /dev/null +++ b/debian/patches/bigcouch-configuration-changes @@ -0,0 +1,2950 @@ +Description: building bigcouch generates a bunch of configuration files + When building bigcouch, a handful of configuration files are generated + that normally would have been generated upstream before releasing into + a tarball + . +Author: Micah Anderson + +--- +The information above should follow the Patch Tagging Guidelines, please +checkout http://dep.debian.net/deps/dep3/ to learn about the format. Here +are templates for supplementary fields that you might want to add: + +Origin: , +Bug: +Bug-Debian: http://bugs.debian.org/ +Bug-Ubuntu: https://launchpad.net/bugs/ +Forwarded: +Reviewed-By: +Last-Update: + +Index: bigcouch-0.4.2.leap/install.mk +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ bigcouch-0.4.2.leap/install.mk 2014-01-17 10:53:54.345591440 -0500 +@@ -0,0 +1,5 @@ ++# The contents of this file are auto-generated by configure ++prefix = /opt/bigcouch ++data_dir = /opt/bigcouch/var/lib ++view_dir = /opt/bigcouch/var/lib ++user = root +Index: bigcouch-0.4.2.leap/couchjs/config.log +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ bigcouch-0.4.2.leap/couchjs/config.log 2014-01-17 10:53:54.345591440 -0500 +@@ -0,0 +1,136 @@ ++file /root/cloudant/bigcouch-0.4.2.leap/couchjs/build/SConscript,line 52: ++ Configure(confdir = .sconf_temp) ++scons: Configure: Checking for C library m... ++.sconf_temp/conftest_0.c <- ++ | ++ | ++ | ++ |int ++ |main() { ++ | ++ |return 0; ++ |} ++ | ++c++ -o .sconf_temp/conftest_0.o -c -g -O2 -DXP_UNIX .sconf_temp/conftest_0.c ++c++ -o .sconf_temp/conftest_0 -pthread .sconf_temp/conftest_0.o -lm ++scons: Configure: yes ++ ++scons: Configure: Checking for C library pthread... ++.sconf_temp/conftest_1.c <- ++ | ++ | ++ | ++ |int ++ |main() { ++ | ++ |return 0; ++ |} ++ | ++c++ -o .sconf_temp/conftest_1.o -c -g -O2 -DXP_UNIX .sconf_temp/conftest_1.c ++c++ -o .sconf_temp/conftest_1 -pthread .sconf_temp/conftest_1.o -lm -lpthread ++scons: Configure: yes ++ ++scons: Configure: Checking for C library nspr4... ++.sconf_temp/conftest_2.c <- ++ | ++ | ++ | ++ |int ++ |main() { ++ | ++ |return 0; ++ |} ++ | ++c++ -o .sconf_temp/conftest_2.o -c -g -O2 -DXP_UNIX .sconf_temp/conftest_2.c ++c++ -o .sconf_temp/conftest_2 -pthread .sconf_temp/conftest_2.o -lm -lpthread -lnspr4 ++scons: Configure: yes ++ ++scons: Configure: Checking for C header file mozjs/jsapi.h... ++.sconf_temp/conftest_3.c <- ++ | ++ |#include ++ | ++ | ++c++ -o .sconf_temp/conftest_3.o -c -g -O2 -DXP_UNIX .sconf_temp/conftest_3.c ++.sconf_temp/conftest_3.c:2:25: fatal error: mozjs/jsapi.h: No such file or directory ++compilation terminated. ++scons: Configure: no ++ ++scons: Configure: Checking for C header file js/jsapi.h... ++.sconf_temp/conftest_4.c <- ++ | ++ |#include ++ | ++ | ++c++ -o .sconf_temp/conftest_4.o -c -g -O2 -DXP_UNIX .sconf_temp/conftest_4.c ++scons: Configure: yes ++ ++scons: Configure: Checking for C library mozjs185-1.0... ++.sconf_temp/conftest_5.c <- ++ | ++ | ++ |#include "js/jsapi.h" ++ | ++ |int ++ |main() { ++ | ++ |return 0; ++ |} ++ | ++c++ -o .sconf_temp/conftest_5.o -c -g -O2 -DXP_UNIX .sconf_temp/conftest_5.c ++c++ -o .sconf_temp/conftest_5 -pthread .sconf_temp/conftest_5.o -lm -lpthread -lnspr4 -lmozjs185-1.0 ++scons: Configure: yes ++ ++scons: Configure: Checking whether JS_NewCompartmentAndGlobalObject is declared... ++.sconf_temp/conftest_6.c <- ++ |#include ++ |int main() ++ |{ ++ |#ifndef JS_NewCompartmentAndGlobalObject ++ | (void) JS_NewCompartmentAndGlobalObject; ++ |#endif ++ | ; ++ | return 0; ++ |} ++ | ++c++ -o .sconf_temp/conftest_6.o -c -g -O2 -DXP_UNIX .sconf_temp/conftest_6.c ++scons: Configure: yes ++ ++scons: Configure: Checking for C type JSScript*... ++.sconf_temp/conftest_7.c <- ++ | ++ | ++ |#include "js/jsapi.h" ++ | ++ |int main() { ++ | if ((JSScript* *) 0) ++ | return 0; ++ | if (sizeof (JSScript*)) ++ | return 0; ++ |} ++ | ++c++ -o .sconf_temp/conftest_7.o -c -g -O2 -DXP_UNIX .sconf_temp/conftest_7.c ++.sconf_temp/conftest_7.c: In function 'int main()': ++.sconf_temp/conftest_7.c:6:8: error: 'JSScript' was not declared in this scope ++.sconf_temp/conftest_7.c:6:19: error: expected primary-expression before ')' token ++.sconf_temp/conftest_7.c:6:21: error: expected ')' before numeric constant ++.sconf_temp/conftest_7.c:8:15: error: 'JSScript' was not declared in this scope ++.sconf_temp/conftest_7.c:8:24: error: expected primary-expression before ')' token ++scons: Configure: no ++ ++scons: Configure: Checking for C library curl... ++.sconf_temp/conftest_8.c <- ++ | ++ | ++ | ++ |int ++ |main() { ++ | ++ |return 0; ++ |} ++ | ++c++ -o .sconf_temp/conftest_8.o -c -g -O2 -DXP_UNIX .sconf_temp/conftest_8.c ++c++ -o .sconf_temp/conftest_8 -pthread .sconf_temp/conftest_8.o -lm -lpthread -lnspr4 -lmozjs185-1.0 -lcurl ++scons: Configure: yes ++ ++ +Index: bigcouch-0.4.2.leap/couchjs/build/http.c +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ bigcouch-0.4.2.leap/couchjs/build/http.c 2014-01-17 10:53:54.345591440 -0500 +@@ -0,0 +1,638 @@ ++// 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 ++#include ++#include ++#include "config.h" ++#include "sm.h" ++#include "utf8.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_LIBCURL ++ ++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) ++{ ++ return -1; ++} ++ ++ ++#else ++#include ++ ++ ++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; ++ ++ ++const 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); ++ ++ ++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 > COPY) { ++ 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; ++} ++ ++// 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; ++ 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(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) { ++ 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 = (char*) 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 = (char*) 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 */ +Index: bigcouch-0.4.2.leap/couchjs/build/sm170.c +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ bigcouch-0.4.2.leap/couchjs/build/sm170.c 2014-01-17 10:53:54.345591440 -0500 +@@ -0,0 +1,381 @@ ++// 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 ++#include ++#include ++ ++#include "http.h" ++#include "sm.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 ++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; ++ ++ couch_args* args = (couch_args*) JS_GetContextPrivate(cx); ++ ++ sandbox = NULL; ++ if(!JS_ConvertArguments(cx, argc, argv, "S / o", &str, &sandbox)) { ++ return JS_FALSE; ++ } ++ ++ subcx = JS_NewContext(JS_GetRuntime(cx), args->stack_size); ++ 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); ++ *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}, ++ {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; ++ ++ couch_args* args = couch_parse_args(argc, argv); ++ ++ rt = JS_NewRuntime(64L * 1024L * 1024L); ++ if(rt == NULL) ++ return 1; ++ ++ cx = JS_NewContext(rt, args->stack_size); ++ if(cx == NULL) ++ return 1; ++ ++ JS_SetContextPrivate(cx, args); ++ JS_SetErrorReporter(cx, couch_error); ++ JS_ToggleOptions(cx, JSOPTION_XML); ++ ++ 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); ++ } ++ } ++ ++ // Convert script source to jschars. ++ scriptsrc = dec_string(cx, args->script, strlen(args->script)); ++ 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->script_name, 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; ++} +Index: bigcouch-0.4.2.leap/couchjs/build/SConscript +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ bigcouch-0.4.2.leap/couchjs/build/SConscript 2014-01-17 10:54:17.384970595 -0500 +@@ -0,0 +1,116 @@ ++# Copyright 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. ++import os ++import commands ++ ++def require_lib(name): ++ if not conf.CheckLib(name): ++ print 'Could not find required library', name ++ Exit(1) ++ ++def runcmd(cmd): ++ return commands.getstatusoutput(cmd) ++ ++env = Environment(CC="c++", CCFLAGS='-g -O2 -DXP_UNIX', ++ CPPPATH=os.getenv("CPPPATH"), ++ LINKFLAGS="-pthread") ++ ++if os.uname()[0] == 'SunOS': ++ env['CC'] = '/usr/sfw/bin/gcc' ++ env['CCFLAGS'] += ' -I/opt/local/include' ++ env.Append(LINKFLAGS=['-L/opt/local/lib']) ++ ++if os.uname()[0] == 'FreeBSD': ++ env['CCFLAGS'] += ' -I/usr/local/include' ++ env.Append(LINKFLAGS=['-L/usr/local/lib']) ++ env['LIB_DL'] = env['LIB_RT'] = '' ++ env['LIB_COMPAT'] = 'compat' ++ ++if os.path.exists('/usr/bin/pkg-config'): ++ for pkg in ["mozilla-js-185", "mozilla-js"]: ++ (s1, output) = runcmd("/usr/bin/pkg-config %s --cflags" % pkg) ++ if s1 == 0: ++ env.Append(CCFLAGS=" " + output) ++ (s2, output) = runcmd("/usr/bin/pkg-config %s --libs-only-L" % pkg) ++ if s2 == 0: ++ env.Append(LINKFLAGS=output) ++ if s1 == 0 or s2 == 0: ++ break ++ ++if not env.GetOption('clean'): ++ conf = Configure(env, config_h='config.h') ++ ++ require_lib('m') ++ require_lib('pthread') ++ require_lib('nspr4') ++ ++ ## check for SpiderMonkey development header ++ if conf.CheckHeader('mozjs/jsapi.h'): ++ jsapi = 'mozjs/jsapi.h' ++ elif conf.CheckHeader('js/jsapi.h'): ++ jsapi = 'js/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('mozjs185-1.0', jsapi, 'c', autoadd=1): ++ 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) ++ ++ ## Detect the version of SpiderMonkey we're using ++ jsheader = "#include <%s>" % jsapi ++ versions = [ ++ ("JS_NewCompartmentAndGlobalObject", "SM185"), ++ ("JS_ThrowStopIteration", "SM180"), ++ ("JS_GetStringCharsAndLength", "SM170") ++ ] ++ for func, vsn in versions: ++ if conf.CheckDeclaration(func, jsheader): ++ conf.Define(vsn) ++ break ++ ++ ## Find the proper type for JS script objects ++ ++ if conf.CheckType("JSScript*", '#include "%s"' % jsapi): ++ conf.Define("JSSCRIPT_TYPE", "JSScript*") ++ else: ++ conf.Define("JSSCRIPT_TYPE", "JSObject*") ++ ++ ## Check if curl is available ++ try: ++ vsn = runcmd("curl-config --version")[1] ++ vsn = vsn.split()[-1].strip().split(".") ++ vsn = tuple(map(int, vsn)) ++ if vsn > (7, 18, 0): ++ require_lib('curl') ++ except: ++ pass ++ ++ ## Define properties for -h / -V ++ ++ vsn = "1.1.1-792-gc8a44ff" ++ conf.Define("PACKAGE_STRING", '"%s"' % vsn.rstrip()) ++ conf.Define("PACKAGE_NAME", '"Cloudant BigCouch"') ++ conf.Define("PACKAGE_BUGREPORT", '"https://github.com/cloudant/bigcouch/issues"') ++ ++ env = conf.Finish() ++ ++env.Program('couchjs', ['main.c', 'http.c', 'utf8.c', 'util.c']) +Index: bigcouch-0.4.2.leap/couchjs/build/sm.h +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ bigcouch-0.4.2.leap/couchjs/build/sm.h 2014-01-17 10:53:54.345591440 -0500 +@@ -0,0 +1,13 @@ ++#ifndef COUCHJS_SM_H ++#define COUCHJS_SM_H ++ ++#include "config.h" ++#ifdef HAVE_JS_JSAPI_H ++#include ++#elif HAVE_MOZJS_JSAPI_H ++#include ++#else ++#include ++#endif ++ ++#endif // included sm.h +Index: bigcouch-0.4.2.leap/couchjs/build/main.c +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ bigcouch-0.4.2.leap/couchjs/build/main.c 2014-01-17 10:53:54.345591440 -0500 +@@ -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 +Index: bigcouch-0.4.2.leap/couchjs/build/sm180.c +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ bigcouch-0.4.2.leap/couchjs/build/sm180.c 2014-01-17 10:53:54.345591440 -0500 +@@ -0,0 +1,390 @@ ++// 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 ++#include ++#include ++ ++#include "http.h" ++#include "sm.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 ++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; ++ ++ couch_args* args = (couch_args*) JS_GetContextPrivate(cx); ++ ++ sandbox = NULL; ++ if(!JS_ConvertArguments(cx, argc, argv, "S / o", &str, &sandbox)) { ++ return JS_FALSE; ++ } ++ ++ subcx = JS_NewContext(JS_GetRuntime(cx), args->stack_size); ++ 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) { ++ JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(sandbox)); ++ } else { ++ JS_EvaluateUCScript(subcx, sandbox, src, srclen, NULL, 0, &rval); ++ JS_SET_RVAL(cx, vp, rval); ++ } ++ ++ ret = JS_TRUE; ++ ++done: ++ 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}, ++ {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; ++ ++ couch_args* args = couch_parse_args(argc, argv); ++ ++ rt = JS_NewRuntime(64L * 1024L * 1024L); ++ if(rt == NULL) ++ return 1; ++ ++ cx = JS_NewContext(rt, args->stack_size); ++ if(cx == NULL) ++ return 1; ++ ++ JS_SetContextPrivate(cx, args); ++ JS_SetErrorReporter(cx, couch_error); ++ JS_ToggleOptions(cx, JSOPTION_XML); ++ ++ 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); ++ } ++ } ++ ++ // Convert script source to jschars. ++ scriptsrc = dec_string(cx, args->script, strlen(args->script)); ++ 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->script_name, 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; ++} +Index: bigcouch-0.4.2.leap/couchjs/build/help.h +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ bigcouch-0.4.2.leap/couchjs/build/help.h 2014-01-17 10:53:54.345591440 -0500 +@@ -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 ++ ++#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 interpreter should set the\n" ++ " stack quota for JS contexts to SIZE bytes\n" ++ "\n" ++ "Report bugs at <%s>.\n"; ++ ++#define BASENAME basename((char*)argv[0]) ++ ++#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 +Index: bigcouch-0.4.2.leap/couchjs/build/utf8.c +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ bigcouch-0.4.2.leap/couchjs/build/utf8.c 2014-01-17 10:53:54.345591440 -0500 +@@ -0,0 +1,291 @@ ++// 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" ++#include "sm.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 >= 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; ++ 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 SM185 ++ 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 = (char*) 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 = (jschar*) 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; ++} +Index: bigcouch-0.4.2.leap/couchjs/build/util.c +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ bigcouch-0.4.2.leap/couchjs/build/util.c 2014-01-17 10:53:54.345591440 -0500 +@@ -0,0 +1,250 @@ ++// 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 ++#include ++ ++#include "help.h" ++#include "util.h" ++#include "utf8.h" ++ ++ ++char* ++slurp_file(char* buf, const char* file) ++{ ++ FILE* fp; ++ char fbuf[16384]; ++ 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) { ++ buflen = nread; ++ buf = (char*) malloc(nread + 1); ++ if(buf == NULL) { ++ fprintf(stderr, "Out of memory.\n"); ++ exit(3); ++ } ++ memcpy(buf, fbuf, buflen); ++ buf[buflen] = '\0'; ++ } else { ++ buflen = strlen(buf); ++ 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); ++ tmp[buflen+nread] = '\0'; ++ free(buf); ++ buf = tmp; ++ } ++ } ++ return buf; ++} ++ ++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 = 8L * 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("--", argv[i]) == 0) { ++ i++; ++ break; ++ } else { ++ break; ++ } ++ i++; ++ } ++ ++ while(i < argc) { ++ args->script = slurp_file(args->script, argv[i]); ++ if(args->script_name == NULL) { ++ if(strcmp(argv[i], "-") == 0) { ++ args->script_name = ""; ++ } else { ++ args->script_name = argv[i]; ++ } ++ } else { ++ args->script_name = ""; ++ } ++ i++; ++ } ++ ++ if(args->script_name == NULL || args->script == NULL) { ++ DISPLAY_USAGE; ++ exit(3); ++ } ++ ++ 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 = (char*) 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 = (char*) 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 = (char*) 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; ++} ++ ++ ++JSObject* ++couch_readfile(JSContext* cx, FILE* fp) ++{ ++ return NULL; ++} ++ ++ ++void ++couch_print(JSContext* cx, uintN argc, jsval* argv) ++{ ++ char *bytes; ++ uintN i; ++ ++ for(i = 0; i < argc; i++) ++ { ++ bytes = enc_string(cx, argv[i], NULL); ++ if(!bytes) return; ++ ++ fprintf(stdout, "%s%s", i ? " " : "", bytes); ++ JS_free(cx, bytes); ++ } ++ ++ fputc('\n', stdout); ++ fflush(stdout); ++} ++ ++ ++void ++couch_error(JSContext* cx, const char* mesg, JSErrorReport* report) ++{ ++ if(!report || !JSREPORT_IS_WARNING(report->flags)) ++ { ++ fprintf(stderr, "[couchjs] %s\n", mesg); ++ } ++} ++ ++ ++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; ++} ++ +Index: bigcouch-0.4.2.leap/couchjs/build/http.h +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ bigcouch-0.4.2.leap/couchjs/build/http.h 2014-01-17 10:53:54.345591440 -0500 +@@ -0,0 +1,26 @@ ++// 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 "sm.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); ++ ++#endif +Index: bigcouch-0.4.2.leap/couchjs/build/sm185.c +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ bigcouch-0.4.2.leap/couchjs/build/sm185.c 2014-01-17 10:53:54.345591440 -0500 +@@ -0,0 +1,404 @@ ++// 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 ++#include ++#include ++ ++#include "http.h" ++#include "sm.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 ++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; ++ ++ couch_args* args = (couch_args*) JS_GetContextPrivate(cx); ++ ++ sandbox = NULL; ++ if(!JS_ConvertArguments(cx, argc, argv, "S / o", &str, &sandbox)) { ++ return JS_FALSE; ++ } ++ ++ subcx = JS_NewContext(JS_GetRuntime(cx), args->stack_size); ++ 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(srclen == 0) { ++ JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(sandbox)); ++ } else { ++ JS_EvaluateUCScript(subcx, sandbox, src, srclen, NULL, 0, &rval); ++ JS_SET_RVAL(cx, vp, rval); ++ } ++ ++ ret = JS_TRUE; ++ ++done: ++ 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}, ++ {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; ++ ++ couch_args* args = couch_parse_args(argc, argv); ++ ++ rt = JS_NewRuntime(64L * 1024L * 1024L); ++ if(rt == NULL) ++ return 1; ++ ++ cx = JS_NewContext(rt, args->stack_size); ++ if(cx == NULL) ++ return 1; ++ ++ JS_SetContextPrivate(cx, args); ++ JS_SetErrorReporter(cx, couch_error); ++ JS_ToggleOptions(cx, JSOPTION_XML); ++ ++ 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); ++ } ++ } ++ ++ // Convert script source to jschars. ++ scriptsrc = dec_string(cx, args->script, strlen(args->script)); ++ 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->script_name, 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_RemoveValueRoot(cx, &sroot); ++ ++ JS_LeaveCrossCompartmentCall(call); ++ FINISH_REQUEST(cx); ++ JS_DestroyContext(cx); ++ JS_DestroyRuntime(rt); ++ JS_ShutDown(); ++ ++ return 0; ++} +Index: bigcouch-0.4.2.leap/couchjs/build/utf8.h +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ bigcouch-0.4.2.leap/couchjs/build/utf8.h 2014-01-17 10:53:54.345591440 -0500 +@@ -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 +\ No newline at end of file +Index: bigcouch-0.4.2.leap/couchjs/build/util.h +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ bigcouch-0.4.2.leap/couchjs/build/util.h 2014-01-17 10:53:54.345591440 -0500 +@@ -0,0 +1,33 @@ ++// 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 "sm.h" ++ ++typedef struct { ++ int use_http; ++ int stack_size; ++ const char* script_name; ++ char* script; ++} 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); ++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 +Index: bigcouch-0.4.2.leap/rel/dev1.config +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ bigcouch-0.4.2.leap/rel/dev1.config 2014-01-17 10:53:54.345591440 -0500 +@@ -0,0 +1,7 @@ ++{prefix, "/root/cloudant/bigcouch-0.4.2.leap/rel/dev1"}. ++{data_dir, "/root/cloudant/bigcouch-0.4.2.leap/rel/tmpdata/dev1"}. ++{view_dir, "/root/cloudant/bigcouch-0.4.2.leap/rel/tmpdata/dev1"}. ++{node_name, "-name dev1@127.0.0.1"}. ++{cluster_port, 15984}. ++{cluster_ssl, 16984}. ++{backend_port, 15986}. +Index: bigcouch-0.4.2.leap/rel/dev2.config +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ bigcouch-0.4.2.leap/rel/dev2.config 2014-01-17 10:53:54.345591440 -0500 +@@ -0,0 +1,7 @@ ++{prefix, "/root/cloudant/bigcouch-0.4.2.leap/rel/dev2"}. ++{data_dir, "/root/cloudant/bigcouch-0.4.2.leap/rel/tmpdata/dev2"}. ++{view_dir, "/root/cloudant/bigcouch-0.4.2.leap/rel/tmpdata/dev2"}. ++{node_name, "-name dev2@127.0.0.1"}. ++{cluster_port, 25984}. ++{cluster_ssl, 26984}. ++{backend_port, 25986}. +Index: bigcouch-0.4.2.leap/rel/bigcouch.config +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ bigcouch-0.4.2.leap/rel/bigcouch.config 2014-01-17 10:53:54.345591440 -0500 +@@ -0,0 +1,8 @@ ++{prefix, "/opt/bigcouch"}. ++{data_dir, "/opt/bigcouch/var/lib"}. ++{view_dir, "/opt/bigcouch/var/lib"}. ++{user, "root"}. ++{node_name, "-name bigcouch"}. ++{cluster_port, 5984}. ++{cluster_ssl, 6984}. ++{backend_port, 5986}. +Index: bigcouch-0.4.2.leap/rel/dev3.config +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ bigcouch-0.4.2.leap/rel/dev3.config 2014-01-17 10:53:54.345591440 -0500 +@@ -0,0 +1,7 @@ ++{prefix, "/root/cloudant/bigcouch-0.4.2.leap/rel/dev3"}. ++{data_dir, "/root/cloudant/bigcouch-0.4.2.leap/rel/tmpdata/dev3"}. ++{view_dir, "/root/cloudant/bigcouch-0.4.2.leap/rel/tmpdata/dev3"}. ++{node_name, "-name dev3@127.0.0.1"}. ++{cluster_port, 35984}. ++{cluster_ssl, 36984}. ++{backend_port, 35986}. diff --git a/debian/patches/disable_embedded_rebar b/debian/patches/disable_embedded_rebar new file mode 100644 index 00000000..95677029 --- /dev/null +++ b/debian/patches/disable_embedded_rebar @@ -0,0 +1,82 @@ +Index: cloudant_bigcouch/configure +=================================================================== +--- cloudant_bigcouch.orig/configure 2014-01-17 07:06:10.581791425 -0500 ++++ cloudant_bigcouch/configure 2014-01-17 07:06:10.577791533 -0500 +@@ -88,4 +88,4 @@ + done + + mkdir -p apps/couch/ebin +-./rebar get-deps && ./rebar update-deps && cat rel/bigcouch.config ++rebar get-deps && rebar update-deps && cat rel/bigcouch.config +Index: cloudant_bigcouch/deps/ibrowse/Makefile +=================================================================== +--- cloudant_bigcouch.orig/deps/ibrowse/Makefile 2014-01-17 07:06:10.581791425 -0500 ++++ cloudant_bigcouch/deps/ibrowse/Makefile 2014-01-17 07:06:10.577791533 -0500 +@@ -1,17 +1,17 @@ + IBROWSE_VSN = $(shell sed -n 's/.*{vsn,.*"\(.*\)"}.*/\1/p' src/ibrowse.app.src) + + all: +- ./rebar compile ++ rebar compile + + clean: +- ./rebar clean ++ rebar clean + + install: all + mkdir -p $(DESTDIR)/lib/ibrowse-$(IBROWSE_VSN)/ + cp -r ebin $(DESTDIR)/lib/ibrowse-$(IBROWSE_VSN)/ + + test: all +- ./rebar eunit ++ rebar eunit + (cd test; make) + erl -noshell -pa ebin -pa test -s ibrowse -s ibrowse_test unit_tests \ + -s ibrowse_test verify_chunked_streaming \ +Index: cloudant_bigcouch/Makefile +=================================================================== +--- cloudant_bigcouch.orig/Makefile 2014-01-17 07:06:05.041940708 -0500 ++++ cloudant_bigcouch/Makefile 2014-01-17 07:06:35.241126925 -0500 +@@ -18,23 +18,23 @@ + compile: + @echo "==> couchjs (compile)" + @cd couchjs && python scons/scons.py +- @./rebar compile ++ @rebar compile + @cat $(appfile) | sed s/%VSN%/`echo 1.1.1-792-gc8a44ff`/ > $(appfile) + + clean: + @echo "==> couchjs (clean)" + @cd couchjs && python scons/scons.py --clean + @rm -rf couchjs/.sconf_temp couchjs/.sconsign.dblite +- @./rebar clean ++ @rebar clean + + # compile is required here because of cross-dependencies between apps + check: compile +- @./rebar eunit ++ @rebar eunit + @ERL_FLAGS="-pa `pwd`/apps/couch/ebin" prove apps/couch/test/etap/*.t + + dist: compile + @rm -rf rel/bigcouch +- @./rebar generate ++ @rebar generate + + distclean: clean + @rm -rf rel/bigcouch +@@ -53,11 +53,11 @@ + dev: compile + @rm -rf rel/dev1 rel/dev2 rel/dev3 + @echo "==> Building development node #1 (ports 15984/15986)" +- @./rebar generate target_dir=dev1 overlay_vars=dev1.config ++ @rebar generate target_dir=dev1 overlay_vars=dev1.config + @echo "==> Building development node #2 (ports 25984/25986)" +- @./rebar generate target_dir=dev2 overlay_vars=dev2.config ++ @rebar generate target_dir=dev2 overlay_vars=dev2.config + @echo "==> Building development node #3 (ports 35984/35986)" +- @./rebar generate target_dir=dev3 overlay_vars=dev3.config ++ @rebar generate target_dir=dev3 overlay_vars=dev3.config + @echo "\n\ + Development nodes are built, and can be started using ./rel/dev[123]/bin/bigcouch.\n\ + Once the nodes are started, they must be joined together by editing the local\n\ diff --git a/debian/patches/disable_embedded_scons b/debian/patches/disable_embedded_scons new file mode 100644 index 00000000..91f57399 --- /dev/null +++ b/debian/patches/disable_embedded_scons @@ -0,0 +1,20 @@ +Index: cloudant_bigcouch/Makefile +=================================================================== +--- cloudant_bigcouch.orig/Makefile 2014-01-17 07:09:37.100226333 -0500 ++++ cloudant_bigcouch/Makefile 2014-01-17 07:10:27.906857239 -0500 +@@ -17,13 +17,13 @@ + appfile = apps/couch/ebin/couch.app + compile: + @echo "==> couchjs (compile)" +- @cd couchjs && python scons/scons.py ++ @cd couchjs && /usr/bin/scons + @rebar compile + @cat $(appfile) | sed s/%VSN%/`echo 1.1.1-792-gc8a44ff`/ > $(appfile) + + clean: + @echo "==> couchjs (clean)" +- @cd couchjs && python scons/scons.py --clean ++ @cd couchjs && /usr/bin/scons --clean + @rm -rf couchjs/.sconf_temp couchjs/.sconsign.dblite + @rebar clean + diff --git a/debian/patches/fix-body_too_large-error b/debian/patches/fix-body_too_large-error new file mode 100644 index 00000000..2cdc03ff --- /dev/null +++ b/debian/patches/fix-body_too_large-error @@ -0,0 +1,16 @@ +Index: bigcouch/deps/chttpd/src/chttpd_external.erl +=================================================================== +--- bigcouch.orig/deps/chttpd/src/chttpd_external.erl 2014-01-15 17:02:27.578395002 +0000 ++++ bigcouch/deps/chttpd/src/chttpd_external.erl 2014-01-15 17:07:01.986394813 +0000 +@@ -65,7 +65,10 @@ + req_body=ReqBody + }, Db, DocId) -> + Body = case ReqBody of +- undefined -> Req:recv_body(); ++ undefined -> ++ MaxSize = list_to_integer( ++ couch_config:get("couchdb", "max_document_size", "4294967296")), ++ Req:recv_body(MaxSize); + Else -> Else + end, + ParsedForm = case Req:get_primary_header_value("content-type") of diff --git a/debian/patches/remove_external_dependencies b/debian/patches/remove_external_dependencies new file mode 100644 index 00000000..6ffbaeb1 --- /dev/null +++ b/debian/patches/remove_external_dependencies @@ -0,0 +1,32 @@ +Index: bigcouch-0.4.2.leap/rebar.config +=================================================================== +--- bigcouch-0.4.2.leap.orig/rebar.config 2014-01-15 17:25:15.799547067 -0200 ++++ bigcouch-0.4.2.leap/rebar.config 2014-01-16 13:53:31.533534156 -0200 +@@ -13,20 +13,13 @@ + % the License. + + {deps, [ +- {oauth, ".*", {git, "https://github.com/cloudant/erlang-oauth.git", +- {tag, "BigCouch-0.4.0"}}}, +- {ibrowse, ".*", {git, "https://github.com/cloudant/ibrowse.git", +- {tag, "CouchDB-1.1.0"}}}, +- {mochiweb, ".*", {git, "https://github.com/cloudant/mochiweb.git", +- {tag, "CouchDB-1.1.0"}}}, +- {rexi, ".*", {git, "https://github.com/cloudant/rexi.git", +- {tag, "1.5.5"}}}, +- {fabric, ".*", {git, "https://github.com/cloudant/fabric.git", +- {tag, "2.0.7"}}}, +- {mem3, ".*", {git, "https://github.com/cloudant/mem3.git", +- {tag, "2.0.0"}}}, +- {chttpd, ".*", {git, "https://github.com/cloudant/chttpd.git", +- {tag, "1.4.3"}}} ++ oauth, ++ ibrowse, ++ mochiweb, ++ rexi, ++ fabric, ++ mem3, ++ chttpd + ]}. + % needed for a clean transition to the deps model + {clean_files, [ diff --git a/debian/patches/series b/debian/patches/series new file mode 100644 index 00000000..72c856b4 --- /dev/null +++ b/debian/patches/series @@ -0,0 +1,7 @@ +fix-body_too_large-error +update-pthread-linking-flags +disable_embedded_rebar +disable_embedded_scons +remove_external_dependencies +support-destdir.patch +bigcouch-configuration-changes diff --git a/debian/patches/support-destdir.patch b/debian/patches/support-destdir.patch new file mode 100644 index 00000000..ffea35a1 --- /dev/null +++ b/debian/patches/support-destdir.patch @@ -0,0 +1,25 @@ +Support $(DESTDIR) in Makefile. + +Index: bigcouch/Makefile +=================================================================== +--- bigcouch.orig/Makefile 2014-01-15 16:45:52.258395008 +0000 ++++ bigcouch/Makefile 2014-01-15 16:47:42.970395009 +0000 +@@ -41,14 +41,10 @@ + + include install.mk + install: dist +- @mkdir -p $(prefix) +- @cp -R rel/bigcouch/* $(prefix) +- @mkdir -p $(data_dir) +- @chown $(user) $(data_dir) +- @mkdir -p $(view_dir) +- @chown $(user) $(view_dir) +- @touch $(prefix)/var/log/bigcouch.log +- @chown $(user) $(prefix)/var/log/bigcouch.log ++ @mkdir -p $(DESTDIR)/$(prefix) ++ @cp -R rel/bigcouch/* $(DESTDIR)/$(prefix) ++ @mkdir -p $(DESTDIR)/etc/sv ++ @cp -R rel/sv/bigcouch $(DESTDIR)/etc/sv/ + + dev: compile + @rm -rf rel/dev1 rel/dev2 rel/dev3 diff --git a/debian/patches/update-pthread-linking-flags b/debian/patches/update-pthread-linking-flags new file mode 100644 index 00000000..46faaab6 --- /dev/null +++ b/debian/patches/update-pthread-linking-flags @@ -0,0 +1,27 @@ +Index: cloudant_bigcouch/apps/couch/rebar.config +=================================================================== +--- cloudant_bigcouch.orig/apps/couch/rebar.config 2014-01-17 07:02:54.167084249 -0500 ++++ cloudant_bigcouch/apps/couch/rebar.config 2014-01-17 07:02:54.163084356 -0500 +@@ -1,7 +1,7 @@ + {so_name, "couch_icu_driver.so"}. + {port_envs, [ + {"DRV_CFLAGS", "$DRV_CFLAGS -DPIC -O2 -fno-common"}, +- {"DRV_LDFLAGS", "$DRV_LDFLAGS -lm -licuuc -licudata -licui18n -lpthread"}, ++ {"DRV_LDFLAGS", "$DRV_LDFLAGS -lm -licuuc -licudata -licui18n -pthread"}, + {"linux", "DRV_LDFLAGS", "$DRV_LDFLAGS -lcrypt"}, + {"freebsd", "DRV_CFLAGS", "$DRV_CFLAGS -I/usr/local/include"}, + {"freebsd", "DRV_LDFLAGS", "$DRV_LDFLAGS -L/usr/local/lib"}, +Index: cloudant_bigcouch/couchjs/c_src/SConscript +=================================================================== +--- cloudant_bigcouch.orig/couchjs/c_src/SConscript 2014-01-17 07:02:54.167084249 -0500 ++++ cloudant_bigcouch/couchjs/c_src/SConscript 2014-01-17 07:02:54.163084356 -0500 +@@ -23,7 +23,8 @@ + return commands.getstatusoutput(cmd) + + env = Environment(CC="c++", CCFLAGS='-g -O2 -DXP_UNIX', +- CPPPATH=os.getenv("CPPPATH")) ++ CPPPATH=os.getenv("CPPPATH"), ++ LINKFLAGS="-pthread") + + if os.uname()[0] == 'SunOS': + env['CC'] = '/usr/sfw/bin/gcc' diff --git a/debian/rules b/debian/rules new file mode 100755 index 00000000..ac687016 --- /dev/null +++ b/debian/rules @@ -0,0 +1,19 @@ +#!/usr/bin/make -f +# -*- makefile -*- +# Sample debian/rules that uses debhelper. +# This file was originally written by Joey Hess and Craig Small. +# As a special exception, when this file is copied by dh-make into a +# dh-make output file, you may use that output file without restriction. +# This special exception was added by Craig Small in version 0.37 of dh-make. + +# Uncomment this to turn on verbose mode. +#export DH_VERBOSE=1 + +%: + dh $@ + +override_dh_auto_configure: + ./configure -p /opt/bigcouch + +override_dh_auto_test: + echo "skipping tests" diff --git a/debian/source/format b/debian/source/format new file mode 100644 index 00000000..163aaf8d --- /dev/null +++ b/debian/source/format @@ -0,0 +1 @@ +3.0 (quilt) -- cgit v1.2.3