From 5b2760e14a60e7447f04b58879fcdbc0c45c04df Mon Sep 17 00:00:00 2001 From: John Christopher Anderson Date: Thu, 9 Oct 2008 22:04:46 +0000 Subject: make check now runs the JavaScript test suite git-svn-id: https://svn.apache.org/repos/asf/incubator/couchdb/trunk@703276 13f79535-47bb-0310-9956-ffa450edef68 --- src/couchdb/Makefile.am | 3 +- src/couchdb/couch_js.c | 796 ++++++++++++++++++++++++++++++++++++++++++++++- src/couchdb/curlhelper.c | 261 ++++++++++++++++ src/couchdb/curlhelper.h | 49 +++ 4 files changed, 1107 insertions(+), 2 deletions(-) create mode 100644 src/couchdb/curlhelper.c create mode 100644 src/couchdb/curlhelper.h (limited to 'src') diff --git a/src/couchdb/Makefile.am b/src/couchdb/Makefile.am index 83220a57..28fd418f 100644 --- a/src/couchdb/Makefile.am +++ b/src/couchdb/Makefile.am @@ -24,7 +24,8 @@ couch_erl_driver_la_CFLAGS = $(ICU_LOCAL_FLAGS) couch_erl_driver_la_LIBADD = -licuuc -licudata -licui18n locallibbin_PROGRAMS = couchjs -couchjs_SOURCES = couch_js.c +couchjs_SOURCES = couch_js.c curlhelper.c +couchjs_LDADD = -lcurl -lgssapi_krb5 couchinclude_DATA = couch_db.hrl diff --git a/src/couchdb/couch_js.c b/src/couchdb/couch_js.c index 8481bc50..21faac1c 100644 --- a/src/couchdb/couch_js.c +++ b/src/couchdb/couch_js.c @@ -13,8 +13,16 @@ specific language governing permissions and limitations under the License. */ +#include #include +#include +#include "curlhelper.h" #include +#include + +#ifndef CURLOPT_COPYPOSTFIELDS + #define CURLOPT_COPYPOSTFIELDS 10165 +#endif int gExitCode = 0; int gStackChunkSize = 8L * 1024L; @@ -401,6 +409,785 @@ PrintError(JSContext *context, const char *message, JSErrorReport *report) { fprintf(stderr, "%s\n", message); } +JSBool ThrowError(JSContext *cx, const char *message) +{ + void *mark; + jsval *args; + jsval exc; + + printf("%s\n",message); + + args = JS_PushArguments(cx, &mark, "s", message); + if (args) { + if (JS_CallFunctionName(cx, JS_GetGlobalObject(cx), + "Error", 1, args, &exc)) + JS_SetPendingException(cx, exc); + JS_PopArguments(cx, mark); + } + + return JS_FALSE; +} + +typedef struct buffer_counter { + Buffer buffer; + int pos; +}* BufferCount; + +size_t curl_read(void *ptr, size_t size, size_t nmemb, void *stream) { + if( size == 0 || nmemb == 0) { + return 0; + } + + char* databuffer = (char*)ptr; + Buffer b = ((BufferCount)stream)->buffer; + int* pos = &(((BufferCount)stream)->pos); + + if((b->count - *pos) == 0) { + return 0; + } + + int readlength = size*nmemb; + int spaceleft = b->count - *pos; + int i; + + if(readlength < spaceleft) { + copy_Buffer(b,databuffer,*pos,readlength); + *(pos) += readlength; + return readlength; + } else { + copy_Buffer(b,databuffer,*pos,spaceleft); + *(pos) += spaceleft; + return spaceleft; + } +} + +size_t curl_write(void *ptr, size_t size, size_t nmemb, void *stream) { + if( size == 0 || nmemb == 0 ) + return 0; + + char *data, *tmp; + Buffer b; + + data = (char *)ptr; + b = (Buffer)stream; + + append_Buffer(b,data,size*nmemb); + + return size*nmemb; +} + +// This uses MALLOC dont forget to free +char* JSValToChar(JSContext* context, jsval* arg) { + if(!JSVAL_IS_STRING(*arg)) { + return NULL; + } + + char *c, *tmp; + JSString *jsmsg; + size_t len; + + jsmsg = JS_ValueToString(context,*arg); + len = JS_GetStringLength(jsmsg); + tmp = JS_GetStringBytes(jsmsg); + + c = (char*)malloc(len+1); + c[len] = '\0'; + + int i; + + for(i = 0;i < len;i++) { + c[i] = tmp[i]; + } + + return c; +} + +JSBool BufferToJSVal(JSContext *context, Buffer b, jsval *rval) { + char* c; + JSString *str; + + // Important for char* to be JS_malloced, otherwise js wont let you use it in the NewString method + c = JS_malloc(context, b->count * sizeof(char)); + copy_Buffer(b,c,0,b->count); + + + /* Initialize a JSString object */ + str = JS_NewString(context, c, b->count); + + if (!str) { + JS_free(context, c); + return JS_FALSE; + } + + // Set Return Value + *rval = STRING_TO_JSVAL(str); + if(rval == NULL) { + return JS_FALSE; + } + return JS_TRUE; +} + +struct curl_slist* generateCurlHeaders(JSContext* context,jsval* arg) { + // If arg is an object then we go the header-hash route else return NULL + + if(!JSVAL_IS_NULL(*arg)) { + + struct curl_slist *slist = NULL; + JSObject* header_obj; + + // If we fail to convert arg2 to an object. Error! + if(!JS_ValueToObject(context,*arg,&header_obj)) { + return NULL; + } + + JSObject* iterator = JS_NewPropertyIterator(context,header_obj); + + jsval *jsProperty = JS_malloc(context,sizeof(jsval)); + jsval *jsValue = JS_malloc(context,sizeof(jsval)); + jsid *jsId = JS_malloc(context,sizeof(jsid)); + + while(JS_NextProperty(context,iterator,jsId) == JS_TRUE) { + + if(*jsId == JSVAL_VOID) { + break; + } + + // TODO: Refactor this maybe make a JSValAppendBuffer method b/c that is what you really want to do. + + Buffer bTmp = init_Buffer(); + JS_IdToValue(context,*jsId,jsProperty); + char* jsPropertyName = JSValToChar(context,jsProperty); + + // TODO: Remove strlen =/ + append_Buffer(bTmp,jsPropertyName,strlen(jsPropertyName)); + append_Buffer(bTmp,": ",2); + + JS_GetProperty(context,header_obj,jsPropertyName,jsValue); + char* jsPropertyValue = JSValToChar(context,jsValue); + // TODO: Remove strlen =/ + append_Buffer(bTmp,jsPropertyValue,strlen(jsPropertyValue)); + append_Buffer(bTmp,"",1); + + slist = curl_slist_append(slist,bTmp->data); + + free_Buffer(bTmp); + free(jsPropertyValue); + free(jsPropertyName); + } + + JS_free(context,jsProperty); + JS_free(context,jsValue); + JS_free(context,jsId); + + return slist; + + } else { + return NULL; + } +} + +static JSBool +GetHttp(JSContext *context, JSObject *obj, uintN argc, jsval *argv, jsval *rval) { + CURL* handle; + Buffer b; + char *url; + size_t charslen, readlen; + + // Run GC + JS_MaybeGC(context); + + // Init Curl + if((handle = curl_easy_init()) == NULL) { + return JS_FALSE; + } + + // Get URL + url = JSValToChar(context,argv); + if( url == NULL ) { + return ThrowError(context,"Unable to convert url (argument 0) to a string"); + } + + b = init_Buffer(); // Allocate buffer that will store the get resultant + + // Configuration + curl_easy_setopt(handle,CURLOPT_WRITEFUNCTION,curl_write); + curl_easy_setopt(handle,CURLOPT_WRITEDATA,b); + curl_easy_setopt(handle,CURLOPT_HEADERFUNCTION,curl_write); + curl_easy_setopt(handle,CURLOPT_WRITEHEADER,b); + curl_easy_setopt(handle,CURLOPT_URL,url); + curl_easy_setopt(handle,CURLOPT_HTTPGET,1); + curl_easy_setopt(handle,CURLOPT_NOPROGRESS,1); + curl_easy_setopt(handle,CURLOPT_IPRESOLVE,CURL_IPRESOLVE_V4); + + struct curl_slist *slist = generateCurlHeaders(context,argv+1); + if(slist != NULL) { + curl_easy_setopt(handle,CURLOPT_HTTPHEADER,slist); + } + + // Perform + int exitcode; + + if((exitcode = curl_easy_perform(handle)) != 0) { + if(slist != NULL) { + curl_slist_free_all(slist); + } + curl_easy_cleanup(handle); + free(url); + free_Buffer(b); + return JS_FALSE; + } + + free(url); + if(slist != NULL) { + curl_slist_free_all(slist); + } + + /* Treat the empty string specially */ + if (b->count == 0) { + free_Buffer(b); + *rval = JS_GetEmptyStringValue(context); + curl_easy_cleanup(handle); + return JS_TRUE; + } + + /* Shrink the buffer to the real size and store its value in rval */ + shrink_Buffer(b); + BufferToJSVal(context,b,rval); + + // Free Buffer + free_Buffer(b); + + if(rval == NULL) { + curl_easy_cleanup(handle); + return JS_FALSE; + } + + JS_MaybeGC(context); + + curl_easy_cleanup(handle); + + return JS_TRUE; +} + +static JSBool +HeadHttp(JSContext *context, JSObject *obj, uintN argc, jsval *argv, jsval *rval) { + CURL* handle; + Buffer b; + char *url; + size_t charslen, readlen; + + // Run GC + JS_MaybeGC(context); + + // Init Curl + if((handle = curl_easy_init()) == NULL) { + return JS_FALSE; + } + + // Get URL + url = JSValToChar(context,argv); + if( url == NULL ) { + return ThrowError(context,"Unable to convert url (argument 0) to a string"); + } + + b = init_Buffer(); // Allocate buffer that will store the get resultant + + // Configuration + // curl_easy_setopt(handle,CURLOPT_WRITEFUNCTION,curl_write); + // curl_easy_setopt(handle,CURLOPT_WRITEDATA,b); + curl_easy_setopt(handle,CURLOPT_HEADERFUNCTION,curl_write); + curl_easy_setopt(handle,CURLOPT_WRITEHEADER,b); + curl_easy_setopt(handle,CURLOPT_URL,url); + curl_easy_setopt(handle,CURLOPT_HTTPGET,0); + curl_easy_setopt(handle,CURLOPT_NOBODY,1); + curl_easy_setopt(handle,CURLOPT_NOPROGRESS,1); + curl_easy_setopt(handle,CURLOPT_IPRESOLVE,CURL_IPRESOLVE_V4); + + struct curl_slist *slist = generateCurlHeaders(context,argv+1); + if(slist != NULL) { + curl_easy_setopt(handle,CURLOPT_HTTPHEADER,slist); + } + + // fprintf(stderr, "about to run HEAD request\n"); + + // Perform + int exitcode; + + if((exitcode = curl_easy_perform(handle)) != 0) { + if(slist != NULL) { + curl_slist_free_all(slist); + } + curl_easy_cleanup(handle); + free(url); + free_Buffer(b); + return JS_FALSE; + } + // fprintf(stderr, "ran ok HEAD request\n"); + + free(url); + if(slist != NULL) { + curl_slist_free_all(slist); + } + + /* Treat the empty string specially */ + if (b->count == 0) { + free_Buffer(b); + *rval = JS_GetEmptyStringValue(context); + curl_easy_cleanup(handle); + return JS_TRUE; + } + + /* Shrink the buffer to the real size and store its value in rval */ + shrink_Buffer(b); + BufferToJSVal(context,b,rval); + + // Free Buffer + free_Buffer(b); + + if(rval == NULL) { + curl_easy_cleanup(handle); + return JS_FALSE; + } + + JS_MaybeGC(context); + + curl_easy_cleanup(handle); + + return JS_TRUE; +} + + +static JSBool +PostHttp(JSContext *context, JSObject *obj, uintN argc, jsval *argv, jsval *rval) { + CURL* handle; + Buffer b; + char *url, *body; + size_t charslen, readlen; + + // Run GC + JS_MaybeGC(context); + + // Init Curl + if((handle = curl_easy_init()) == NULL) { + return JS_FALSE; + } + + // Get URL + if((url = JSValToChar(context,argv)) == NULL) { + curl_easy_cleanup(handle); + return JS_FALSE; + } + + // Initialize buffer + b = init_Buffer(); + + curl_easy_setopt(handle,CURLOPT_WRITEFUNCTION,curl_write); // function that recieves data + curl_easy_setopt(handle,CURLOPT_WRITEDATA,b); // buffer to write the data to + curl_easy_setopt(handle,CURLOPT_HEADERFUNCTION,curl_write); + curl_easy_setopt(handle,CURLOPT_WRITEHEADER,b); + curl_easy_setopt(handle,CURLOPT_URL,url); // url + curl_easy_setopt(handle,CURLOPT_HTTPPOST,1); // Set Op. to post + curl_easy_setopt(handle,CURLOPT_NOPROGRESS,1); // No Progress Meter + curl_easy_setopt(handle,CURLOPT_IPRESOLVE,CURL_IPRESOLVE_V4); // only ipv4 + + if((body = JSValToChar(context,argv+1)) == NULL) { // Convert arg1 to a string + free(url); + free_Buffer(b); + curl_easy_cleanup(handle); + return JS_FALSE; + } + + curl_easy_setopt(handle,CURLOPT_COPYPOSTFIELDS,body); // Curl wants '\0' terminated, we oblige + free(body); + + struct curl_slist *slist = generateCurlHeaders(context,argv+2); // Initialize Headers + if(slist != NULL) { + curl_easy_setopt(handle,CURLOPT_HTTPHEADER,slist); + } + + int exitcode; + + if((exitcode = curl_easy_perform(handle)) != 0) { // Perform + curl_slist_free_all(slist); + free(url); + free_Buffer(b); + curl_easy_cleanup(handle); + return JS_FALSE; + } + + free(url); + curl_slist_free_all(slist); + + // Convert response back to javascript value and then clean + BufferToJSVal(context,b,rval); + free_Buffer(b); + curl_easy_cleanup(handle); + + JS_MaybeGC(context); + + if( rval == NULL ) { + return JS_FALSE; + } + + return JS_TRUE; +} + +#define CLEAN \ + free_Buffer(b); \ + free_Buffer(b_data->buffer); \ + free(b_data); \ + free(url) + +static JSBool +PutHttp(JSContext *context, JSObject *obj, uintN argc, jsval *argv, jsval *rval){ + + Buffer b; + BufferCount b_data; + char *url, *data; + size_t charslen, readlen; + JSObject* header_obj; + + // Run GC + JS_MaybeGC(context); + + // Get URL + url = JSValToChar(context,argv); + + // Allocate buffer that will store the get resultant + b = init_Buffer(); + + // Allocate data buffer and move data into them + b_data = (BufferCount)malloc(sizeof(Buffer) + sizeof(int)); + b_data->buffer = init_Buffer(); + b_data->pos = 0; + + data = JSValToChar(context,(argv+1)); + // TODO: remove strlen + append_Buffer(b_data->buffer,data,strlen(data)); + + free(data); + + CURL* handle; + + // Init Curl + + if((handle = curl_easy_init()) == NULL) { + CLEAN; + return JS_FALSE; + } + + // Configuration + curl_easy_setopt(handle,CURLOPT_WRITEFUNCTION,curl_write); + curl_easy_setopt(handle,CURLOPT_WRITEDATA,b); + curl_easy_setopt(handle,CURLOPT_HEADERFUNCTION,curl_write); + curl_easy_setopt(handle,CURLOPT_WRITEHEADER,b); + curl_easy_setopt(handle,CURLOPT_READFUNCTION,curl_read); + curl_easy_setopt(handle,CURLOPT_READDATA,b_data); + curl_easy_setopt(handle,CURLOPT_URL,url); + curl_easy_setopt(handle,CURLOPT_UPLOAD,1); + + // Curl structure + struct curl_slist *slist = generateCurlHeaders(context,argv+2); + if(slist != NULL) { + curl_easy_setopt(handle,CURLOPT_HTTPHEADER,slist); + } + + // Little Things + // No progress meter + curl_easy_setopt(handle,CURLOPT_NOPROGRESS,1); + // Use only ipv4 + curl_easy_setopt(handle,CURLOPT_IPRESOLVE,CURL_IPRESOLVE_V4); + + // Perform + int exitcode; + + if((exitcode = curl_easy_perform(handle)) != 0) { + if(slist != NULL) + curl_slist_free_all(slist); + curl_easy_cleanup(handle); + CLEAN; + return JS_FALSE; + } + + if(slist != NULL) + curl_slist_free_all(slist); + free_Buffer(b_data->buffer); + free(b_data); + free(url); + + /* Treat the empty string specially */ + if (b->count == 0) { + *rval = JS_GetEmptyStringValue(context); + curl_easy_cleanup(handle); + free_Buffer(b); + return JS_TRUE; + } + + /* Shrink the buffer to the real size */ + shrink_Buffer(b); + + BufferToJSVal(context,b,rval); + + free_Buffer(b); + + if(rval == NULL) { + curl_easy_cleanup(handle); + return JS_FALSE; + } + + JS_MaybeGC(context); + + curl_easy_cleanup(handle); + + return JS_TRUE; +} + +static JSBool +DelHttp(JSContext *context, JSObject *obj, uintN argc, jsval *argv, jsval *rval) { + Buffer b; + char *url; + size_t charslen, readlen; + char header_name[7]; + strcpy(header_name,"DELETE"); + + // Run GC + JS_MaybeGC(context); + + // Get URL + url = JSValToChar(context,argv); + + // Allocate buffer that will store the del resultant + b = init_Buffer(); + + CURL* handle; + + // Init Curl + if((handle = curl_easy_init()) == NULL) { + free_Buffer(b); + return JS_FALSE; + } + + // Configuration + curl_easy_setopt(handle,CURLOPT_WRITEFUNCTION,curl_write); + curl_easy_setopt(handle,CURLOPT_WRITEDATA,b); + curl_easy_setopt(handle,CURLOPT_HEADERFUNCTION,curl_write); + curl_easy_setopt(handle,CURLOPT_WRITEHEADER,b); + curl_easy_setopt(handle,CURLOPT_URL,url); + curl_easy_setopt(handle,CURLOPT_CUSTOMREQUEST,header_name); + curl_easy_setopt(handle,CURLOPT_NOPROGRESS,1); + curl_easy_setopt(handle,CURLOPT_IPRESOLVE,CURL_IPRESOLVE_V4); + + // Curl structure + struct curl_slist *slist = NULL; + if((slist = generateCurlHeaders(context,argv+1)) != NULL) { + curl_easy_setopt(handle,CURLOPT_HTTPHEADER,slist); + } + + // Perform + int exitcode; + + if((exitcode = curl_easy_perform(handle)) != 0) { + if(slist != NULL) + curl_slist_free_all(slist); + curl_easy_cleanup(handle); + free(url); + free_Buffer(b); + return JS_FALSE; + } + + if(slist != NULL) + curl_slist_free_all(slist); + free(url); + + /* Treat the empty string specially */ + if (b->count == 0) { + *rval = JS_GetEmptyStringValue(context); + curl_easy_cleanup(handle); + free_Buffer(b); + return JS_TRUE; + } + + /* Shrink the buffer to the real size */ + shrink_Buffer(b); + + BufferToJSVal(context,b,rval); + + if(rval == NULL) { + curl_easy_cleanup(handle); + return JS_FALSE; + } + + JS_MaybeGC(context); + + curl_easy_cleanup(handle); + + return JS_TRUE; +} + +static JSBool +CopyHttp(JSContext *context, JSObject *obj, uintN argc, jsval *argv, jsval *rval) { + Buffer b; + char *url; + size_t charslen, readlen; + char header_name[5]; + strcpy(header_name,"COPY"); + + // Run GC + JS_MaybeGC(context); + + // Get URL + url = JSValToChar(context,argv); + + // Allocate buffer that will store the del resultant + b = init_Buffer(); + + CURL* handle; + + // Init Curl + if((handle = curl_easy_init()) == NULL) { + free_Buffer(b); + return JS_FALSE; + } + + // Configuration + curl_easy_setopt(handle,CURLOPT_WRITEFUNCTION,curl_write); + curl_easy_setopt(handle,CURLOPT_WRITEDATA,b); + curl_easy_setopt(handle,CURLOPT_HEADERFUNCTION,curl_write); + curl_easy_setopt(handle,CURLOPT_WRITEHEADER,b); + curl_easy_setopt(handle,CURLOPT_URL,url); + curl_easy_setopt(handle,CURLOPT_CUSTOMREQUEST,header_name); + curl_easy_setopt(handle,CURLOPT_NOPROGRESS,1); + curl_easy_setopt(handle,CURLOPT_IPRESOLVE,CURL_IPRESOLVE_V4); + + // Curl structure + struct curl_slist *slist = NULL; + if((slist = generateCurlHeaders(context,argv+1)) != NULL) { + curl_easy_setopt(handle,CURLOPT_HTTPHEADER,slist); + } + + // Perform + int exitcode; + + if((exitcode = curl_easy_perform(handle)) != 0) { + if(slist != NULL) + curl_slist_free_all(slist); + curl_easy_cleanup(handle); + free(url); + free_Buffer(b); + return JS_FALSE; + } + + if(slist != NULL) + curl_slist_free_all(slist); + free(url); + + /* Treat the empty string specially */ + if (b->count == 0) { + *rval = JS_GetEmptyStringValue(context); + curl_easy_cleanup(handle); + free_Buffer(b); + return JS_TRUE; + } + + /* Shrink the buffer to the real size */ + shrink_Buffer(b); + + BufferToJSVal(context,b,rval); + + if(rval == NULL) { + curl_easy_cleanup(handle); + return JS_FALSE; + } + + JS_MaybeGC(context); + + curl_easy_cleanup(handle); + + return JS_TRUE; +} + +static JSBool +MoveHttp(JSContext *context, JSObject *obj, uintN argc, jsval *argv, jsval *rval) { + Buffer b; + char *url; + size_t charslen, readlen; + char header_name[5]; + strcpy(header_name,"MOVE"); + + // Run GC + JS_MaybeGC(context); + + // Get URL + url = JSValToChar(context,argv); + + // Allocate buffer that will store the del resultant + b = init_Buffer(); + + CURL* handle; + + // Init Curl + if((handle = curl_easy_init()) == NULL) { + free_Buffer(b); + return JS_FALSE; + } + + // Configuration + curl_easy_setopt(handle,CURLOPT_WRITEFUNCTION,curl_write); + curl_easy_setopt(handle,CURLOPT_WRITEDATA,b); + curl_easy_setopt(handle,CURLOPT_HEADERFUNCTION,curl_write); + curl_easy_setopt(handle,CURLOPT_WRITEHEADER,b); + curl_easy_setopt(handle,CURLOPT_URL,url); + curl_easy_setopt(handle,CURLOPT_CUSTOMREQUEST,header_name); + curl_easy_setopt(handle,CURLOPT_NOPROGRESS,1); + curl_easy_setopt(handle,CURLOPT_IPRESOLVE,CURL_IPRESOLVE_V4); + + // Curl structure + struct curl_slist *slist = NULL; + if((slist = generateCurlHeaders(context,argv+1)) != NULL) { + curl_easy_setopt(handle,CURLOPT_HTTPHEADER,slist); + } + + // Perform + int exitcode; + + if((exitcode = curl_easy_perform(handle)) != 0) { + if(slist != NULL) + curl_slist_free_all(slist); + curl_easy_cleanup(handle); + free(url); + free_Buffer(b); + return JS_FALSE; + } + + if(slist != NULL) + curl_slist_free_all(slist); + free(url); + + /* Treat the empty string specially */ + if (b->count == 0) { + *rval = JS_GetEmptyStringValue(context); + curl_easy_cleanup(handle); + free_Buffer(b); + return JS_TRUE; + } + + /* Shrink the buffer to the real size */ + shrink_Buffer(b); + + BufferToJSVal(context,b,rval); + + if(rval == NULL) { + curl_easy_cleanup(handle); + return JS_FALSE; + } + + JS_MaybeGC(context); + + curl_easy_cleanup(handle); + + return JS_TRUE; +} + int main(int argc, const char * argv[]) { JSRuntime *runtime; @@ -428,7 +1215,14 @@ main(int argc, const char * argv[]) { || !JS_DefineFunction(context, global, "print", Print, 0, 0) || !JS_DefineFunction(context, global, "quit", Quit, 0, 0) || !JS_DefineFunction(context, global, "readline", ReadLine, 0, 0) - || !JS_DefineFunction(context, global, "seal", Seal, 0, 0)) + || !JS_DefineFunction(context, global, "seal", Seal, 0, 0) + || !JS_DefineFunction(context, global, "gethttp", GetHttp, 1, 0) + || !JS_DefineFunction(context, global, "headhttp", HeadHttp, 1, 0) + || !JS_DefineFunction(context, global, "posthttp", PostHttp, 2, 0) + || !JS_DefineFunction(context, global, "puthttp", PutHttp, 2, 0) + || !JS_DefineFunction(context, global, "delhttp", DelHttp, 1, 0) + || !JS_DefineFunction(context, global, "movehttp", MoveHttp, 1, 0) + || !JS_DefineFunction(context, global, "copyhttp", CopyHttp, 1, 0)) return 1; if (argc != 2) { diff --git a/src/couchdb/curlhelper.c b/src/couchdb/curlhelper.c new file mode 100644 index 00000000..99b2e6ab --- /dev/null +++ b/src/couchdb/curlhelper.c @@ -0,0 +1,261 @@ +/* + +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 "curlhelper.h" + +#define TRUE 1 +#define FALSE 0 + +Buffer init_Buffer() { + Buffer b; + + if((b = (Buffer)malloc(sizeof(char*) + sizeof(int)*2)) == NULL) { + return NULL; + } + + b->count = 0; + b->capacity = 50; + + if(b->data = (char*)malloc(sizeof(char)*b->capacity)) { + return b; + } else { + return NULL; + } +} + +void free_Buffer(Buffer b) { + if(b == NULL) + return; + if(b->data != NULL) + free(b->data); + free(b); +} + +int append_Buffer(Buffer b, char* c, int length) { + int capacity_changed; + int new_count; + + capacity_changed = FALSE; + new_count = b->count + length; + + if(new_count > b->capacity) { + capacity_changed = TRUE; + b->capacity *= 2; + } + + while(new_count > b->capacity) { + b->capacity *= 2; + } + + if(capacity_changed) { + if((b->data = (char*)realloc(b->data,b->capacity)) == NULL) { + return FALSE; + } + } + + int i; + + for(i = 0;i < length;i++) { + *(b->data + b->count + i) = *(c + i); + } + + b->count = new_count; + + return TRUE; +} + +char* toString_Buffer(Buffer b) { + char* result; + + if((result = (char*)malloc(sizeof(char)*(b->count+1))) == NULL) { + return NULL; + } + + result[b->count] = '\0'; + + int i; + + for(i = 0;i < b->count;i++) { + result[i] = b->data[i]; + } + + return result; +} + +int print_Buffer(Buffer b) { + char* c; + + if((c = toString_Buffer(b)) == NULL) { + return FALSE; + } + + printf("%s\n",c); + + free(c); + + return TRUE; +} + + +int shrink_Buffer(Buffer b) { + b->capacity = b->count; + + if((b->data = realloc(b->data,sizeof(char)*b->capacity)) == NULL) { + return FALSE; + } else { + return TRUE; + } +} + +void copy_Buffer(Buffer b, char* c, int pos, int length) { + if((pos + length) > b->count) + return; + + int i; + + for(i = 0; i < length;i++) { + *(c + i) = *(b->data + pos + i); + } +} + + +List init_List(int capacity) { + if(capacity < 5) + capacity = 5; + + List l; + + if((l = (List)malloc(sizeof(void**)+sizeof(int)*2)) == NULL) { + return NULL; + } + + l->count = 0; + l->capacity = capacity; + + if((l->elements = (void**)malloc(sizeof(void*)*l->capacity)) == NULL) { + return NULL; + } + + return l; +} + +void free_List(List l) { + if(l == NULL) + return; + if(l->elements != NULL) + free(l->elements); + free(l); +} + +void* get_List(List l, int pos) { + if(pos > (l->count - 1)) { + return NULL; + } + return *(l->elements + pos); +} + +void* pull_List(List l) { + void* r = *(l->elements); + + int i; + + for(i = 1; i < (l->count-1);i++) { + l->elements[i] = l->elements[i+1]; + } + l->count -= 1; + return r; +} + +int set_List(List l, int pos, void* ptr) { + if(pos > (l->count - 1)) { + return FALSE; + } + + *(l->elements + pos) = ptr; + + return TRUE; +} + +int append_List(List l, void* ptr, int length) { + int capacity_changed; + int new_count; + + capacity_changed = FALSE; + new_count = l->count + length; + + if(new_count > l->capacity) { + capacity_changed = TRUE; + l->capacity *= 2; + } + + while(new_count > l->capacity) { + l->capacity *= 2; + } + + if(capacity_changed) { + if((l->elements = (void*)realloc(l->elements,l->capacity)) == NULL) { + return FALSE; + } + } + + int i; + + for(i = 0;i < length;i++) { + *(l->elements + l->count + i) = ptr + i; + } + + l->count = new_count; + + return TRUE; +} + +int push_List(List l, void* ptr, int length) { + int capacity_changed; + int new_count; + + capacity_changed = FALSE; + new_count = l->count + length; + + if(new_count > l->capacity) { + capacity_changed = TRUE; + l->capacity *= 2; + } + + while(new_count > l->capacity) { + l->capacity *= 2; + } + + if(capacity_changed) { + if((l->elements = (void*)realloc(l->elements,l->capacity)) == NULL) { + return FALSE; + } + } + + int i; + + for(i = 0;i < length;i++) { + *(l->elements + l->count + i) = *(l->elements + i); + } + + for(i = 0;i < length;i++) { + *(l->elements + i) = ptr+i; + } + + l->count = new_count; + + return TRUE; +} diff --git a/src/couchdb/curlhelper.h b/src/couchdb/curlhelper.h new file mode 100644 index 00000000..c04c2c92 --- /dev/null +++ b/src/couchdb/curlhelper.h @@ -0,0 +1,49 @@ +/* + +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 CURLHELPER_H +#define CURLHELPER_H + +typedef struct { + char* data; + int count; + int capacity; +}* Buffer; + +Buffer init_Buffer(); +void free_Buffer(Buffer b); +int append_Buffer(Buffer b,char* c,int length); +// WARNING USES MALLOC DONT FORGET TO FREE +char* toString_Buffer(Buffer b); +int print_Buffer(Buffer b); +int shrink_Buffer(Buffer b); +void copy_Buffer(Buffer b, char* c, int pos, int length); + + +typedef struct { + void** elements; + int count; + int capacity; +}* List; + +List init_List(int capacity); +void free_List(List l); +void* get_List(List l, int pos); +void* pull_List(List l); +int set_List(List l, int pos, void* ptr); +int append_List(List l, void* ptr, int length); +int push_List(List l, void* ptr, int length); + +#endif -- cgit v1.2.3