| /* |
| |
| Licensed under the Apache License, Version 2.0 (the "License"); you may not use |
| this file except in compliance with the License. You may obtain a copy of the |
| License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software distributed |
| under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR |
| CONDITIONS OF ANY KIND, either express or implied. See the License for the |
| specific language governing permissions and limitations under the License. |
| |
| */ |
| |
| #include <stdlib.h> |
| #include <stdio.h> |
| #include <string.h> |
| #include "curlhelper.h" |
| #include <jsapi.h> |
| #include <curl/curl.h> |
| |
| #ifndef CURLOPT_COPYPOSTFIELDS |
| #define CURLOPT_COPYPOSTFIELDS 10165 |
| #endif |
| |
| int gExitCode = 0; |
| int gStackChunkSize = 8L * 1024L; |
| |
| int |
| EncodeChar(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; |
| } |
| |
| JSBool |
| EncodeString(const jschar *src, size_t srclen, char *dst, size_t *dstlenp) { |
| size_t i, utf8Len, dstlen = *dstlenp, origDstlen = dstlen; |
| jschar c, c2; |
| uint32 v; |
| uint8 utf8buf[6]; |
| |
| if (!dst) |
| dstlen = origDstlen = (size_t) -1; |
| |
| while (srclen) { |
| c = *src++; |
| srclen--; |
| if ((c >= 0xDC00) && (c <= 0xDFFF)) |
| goto badSurrogate; |
| if (c < 0xD800 || c > 0xDBFF) { |
| v = c; |
| } else { |
| if (srclen < 1) |
| goto bufferTooSmall; |
| c2 = *src++; |
| srclen--; |
| if ((c2 < 0xDC00) || (c2 > 0xDFFF)) { |
| c = c2; |
| goto badSurrogate; |
| } |
| v = ((c - 0xD800) << 10) + (c2 - 0xDC00) + 0x10000; |
| } |
| if (v < 0x0080) { |
| /* no encoding necessary - performance hack */ |
| if (!dstlen) |
| goto bufferTooSmall; |
| if (dst) |
| *dst++ = (char) v; |
| utf8Len = 1; |
| } else { |
| utf8Len = EncodeChar(utf8buf, v); |
| if (utf8Len > dstlen) |
| goto bufferTooSmall; |
| if (dst) { |
| for (i = 0; i < utf8Len; i++) |
| *dst++ = (char) utf8buf[i]; |
| } |
| } |
| dstlen -= utf8Len; |
| } |
| *dstlenp = (origDstlen - dstlen); |
| return JS_TRUE; |
| |
| badSurrogate: |
| *dstlenp = (origDstlen - dstlen); |
| return JS_FALSE; |
| |
| bufferTooSmall: |
| *dstlenp = (origDstlen - dstlen); |
| return JS_FALSE; |
| } |
| |
| static uint32 |
| DecodeChar(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; |
| } |
| |
| JSBool |
| DecodeString(const char *src, size_t srclen, jschar *dst, size_t *dstlenp) { |
| uint32 v; |
| size_t offset = 0, j, n, dstlen = *dstlenp, 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 bufferTooSmall; |
| if (n == 1 || n > 6) |
| goto badCharacter; |
| for (j = 1; j < n; j++) { |
| if ((src[j] & 0xC0) != 0x80) |
| goto badCharacter; |
| } |
| v = DecodeChar((const uint8 *) src, n); |
| if (v >= 0x10000) { |
| v -= 0x10000; |
| if (v > 0xFFFFF || dstlen < 2) { |
| *dstlenp = (origDstlen - dstlen); |
| return JS_FALSE; |
| } |
| if (dstlen < 2) |
| goto bufferTooSmall; |
| if (dst) { |
| *dst++ = (jschar)((v >> 10) + 0xD800); |
| v = (jschar)((v & 0x3FF) + 0xDC00); |
| } |
| dstlen--; |
| } |
| } |
| if (!dstlen) |
| goto bufferTooSmall; |
| if (dst) |
| *dst++ = (jschar) v; |
| dstlen--; |
| offset += n; |
| src += n; |
| srclen -= n; |
| } |
| *dstlenp = (origDstlen - dstlen); |
| return JS_TRUE; |
| |
| badCharacter: |
| *dstlenp = (origDstlen - dstlen); |
| return JS_FALSE; |
| |
| bufferTooSmall: |
| *dstlenp = (origDstlen - dstlen); |
| return JS_FALSE; |
| } |
| |
| static JSBool |
| EvalInContext(JSContext *context, JSObject *obj, uintN argc, jsval *argv, |
| jsval *rval) { |
| JSString *str; |
| JSObject *sandbox; |
| JSContext *sub_context; |
| const jschar *src; |
| size_t srclen; |
| JSBool ok; |
| jsval v; |
| |
| sandbox = NULL; |
| if (!JS_ConvertArguments(context, argc, argv, "S / o", &str, &sandbox)) |
| return JS_FALSE; |
| |
| sub_context = JS_NewContext(JS_GetRuntime(context), gStackChunkSize); |
| if (!sub_context) { |
| JS_ReportOutOfMemory(context); |
| return JS_FALSE; |
| } |
| |
| src = JS_GetStringChars(str); |
| srclen = JS_GetStringLength(str); |
| |
| if (!sandbox) { |
| sandbox = JS_NewObject(sub_context, NULL, NULL, NULL); |
| if (!sandbox || !JS_InitStandardClasses(sub_context, sandbox)) { |
| ok = JS_FALSE; |
| goto out; |
| } |
| } |
| |
| if (srclen == 0) { |
| *rval = OBJECT_TO_JSVAL(sandbox); |
| ok = JS_TRUE; |
| } else { |
| ok = JS_EvaluateUCScript(sub_context, sandbox, src, srclen, NULL, 0, |
| rval); |
| ok = JS_TRUE; |
| } |
| |
| out: |
| JS_DestroyContext(sub_context); |
| return ok; |
| } |
| |
| static JSBool |
| GC(JSContext *context, JSObject *obj, uintN argc, jsval *argv, jsval *rval) { |
| JS_GC(context); |
| return JS_TRUE; |
| } |
| |
| static JSBool |
| Print(JSContext *context, JSObject *obj, uintN argc, jsval *argv, jsval *rval) { |
| uintN i, n; |
| size_t cl, bl; |
| JSString *str; |
| jschar *chars; |
| char *bytes; |
| |
| for (i = n = 0; i < argc; i++) { |
| str = JS_ValueToString(context, argv[i]); |
| if (!str) |
| return JS_FALSE; |
| chars = JS_GetStringChars(str); |
| cl = JS_GetStringLength(str); |
| if (!EncodeString(chars, cl, NULL, &bl)) |
| return JS_FALSE; |
| bytes = JS_malloc(context, bl + 1); |
| bytes[bl] = '\0'; |
| if (!EncodeString(chars, cl, bytes, &bl)) { |
| JS_free(context, bytes); |
| return JS_FALSE; |
| } |
| fprintf(stdout, "%s%s", i ? " " : "", bytes); |
| JS_free(context, bytes); |
| } |
| n++; |
| if (n) |
| fputc('\n', stdout); |
| fflush(stdout); |
| return JS_TRUE; |
| } |
| |
| static JSBool |
| Quit(JSContext *context, JSObject *obj, uintN argc, jsval *argv, jsval *rval) { |
| JS_ConvertArguments(context, argc, argv, "/ i", &gExitCode); |
| return JS_FALSE; |
| } |
| |
| static JSBool |
| ReadLine(JSContext *context, JSObject *obj, uintN argc, jsval *argv, jsval *rval) { |
| char *bytes, *tmp; |
| jschar *chars; |
| size_t bufsize, byteslen, charslen, readlen; |
| JSString *str; |
| |
| JS_MaybeGC(context); |
| |
| byteslen = 0; |
| bufsize = 256; |
| bytes = JS_malloc(context, bufsize); |
| if (!bytes) |
| return JS_FALSE; |
| |
| while ((readlen = js_fgets(bytes + byteslen, bufsize - byteslen, stdin)) > 0) { |
| byteslen += readlen; |
| |
| /* Are we done? */ |
| if (bytes[byteslen - 1] == '\n') { |
| bytes[byteslen - 1] = '\0'; |
| break; |
| } |
| |
| /* Else, grow our buffer for another pass */ |
| tmp = JS_realloc(context, bytes, bufsize * 2); |
| if (!tmp) { |
| JS_free(context, bytes); |
| return JS_FALSE; |
| } |
| |
| bufsize *= 2; |
| bytes = tmp; |
| } |
| |
| /* Treat the empty string specially */ |
| if (byteslen == 0) { |
| *rval = JS_GetEmptyStringValue(context); |
| JS_free(context, bytes); |
| return JS_TRUE; |
| } |
| |
| /* Shrink the buffer to the real size */ |
| tmp = JS_realloc(context, bytes, byteslen); |
| if (!tmp) { |
| JS_free(context, bytes); |
| return JS_FALSE; |
| } |
| bytes = tmp; |
| |
| /* Decode the string from UTF-8 */ |
| if (!DecodeString(bytes, byteslen, NULL, &charslen)) { |
| JS_free(context, bytes); |
| return JS_FALSE; |
| } |
| chars = JS_malloc(context, (charslen + 1) * sizeof(jschar)); |
| if (!DecodeString(bytes, byteslen, chars, &charslen)) { |
| JS_free(context, bytes); |
| JS_free(context, chars); |
| return JS_FALSE; |
| } |
| JS_free(context, bytes); |
| chars[charslen] = '\0'; |
| |
| /* Initialize a JSString object */ |
| str = JS_NewUCString(context, chars, charslen - 1); |
| if (!str) { |
| JS_free(context, chars); |
| return JS_FALSE; |
| } |
| |
| *rval = STRING_TO_JSVAL(str); |
| return JS_TRUE; |
| } |
| |
| static JSBool |
| Seal(JSContext *context, JSObject *obj, uintN argc, jsval *argv, jsval *rval) { |
| JSObject *target; |
| JSBool deep = JS_FALSE; |
| |
| if (!JS_ConvertArguments(context, argc, argv, "o/b", &target, &deep)) |
| return JS_FALSE; |
| if (!target) |
| return JS_TRUE; |
| return JS_SealObject(context, target, deep); |
| } |
| |
| static void |
| ExecuteScript(JSContext *context, JSObject *obj, const char *filename) { |
| FILE *file; |
| JSScript *script; |
| jsval result; |
| |
| if (!filename || strcmp(filename, "-") == 0) { |
| file = stdin; |
| } else { |
| file = fopen(filename, "r"); |
| if (!file) { |
| fprintf(stderr, "could not open script file %s\n", filename); |
| gExitCode = 1; |
| return; |
| } |
| } |
| |
| script = JS_CompileFileHandle(context, obj, filename, file); |
| if (script) { |
| JS_ExecuteScript(context, obj, script, &result); |
| JS_DestroyScript(context, script); |
| } |
| } |
| |
| static uint32 gBranchCount = 0; |
| |
| static void |
| PrintError(JSContext *context, const char *message, JSErrorReport *report) { |
| if (!report || !JSREPORT_IS_WARNING(report->flags)) |
| 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_FOLLOWLOCATION,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_POST,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_POSTFIELDSIZE,strlen(body)); |
| curl_easy_setopt(handle,CURLOPT_POSTFIELDS,body); // Curl wants '\0' terminated, we oblige |
| |
| 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(body); |
| free(url); |
| free_Buffer(b); |
| curl_easy_cleanup(handle); |
| return JS_FALSE; |
| } |
| |
| free(body); |
| 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)); |
| readlen = strlen(data); |
| |
| |
| |
| // TODO: remove strlen |
| append_Buffer(b_data->buffer,data,readlen); |
| |
| 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_easy_setopt(handle,CURLOPT_INFILESIZE,readlen); |
| |
| |
| |
| // 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; |
| JSContext *context; |
| JSObject *global; |
| |
| runtime = JS_NewRuntime(64L * 1024L * 1024L); |
| if (!runtime) |
| return 1; |
| context = JS_NewContext(runtime, gStackChunkSize); |
| if (!context) |
| return 1; |
| JS_SetErrorReporter(context, PrintError); |
| JS_ToggleOptions(context, JSOPTION_XML); |
| |
| global = JS_NewObject(context, NULL, NULL, NULL); |
| if (!global) |
| return 1; |
| if (!JS_InitStandardClasses(context, global)) |
| return 1; |
| if (!JS_DefineFunction(context, global, "evalcx", EvalInContext, 0, 0) |
| || !JS_DefineFunction(context, global, "gc", GC, 0, 0) |
| || !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, "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) { |
| fprintf(stderr, "incorrect number of arguments\n\n"); |
| fprintf(stderr, "usage: %s <scriptfile>\n", argv[0]); |
| return 2; |
| } |
| |
| ExecuteScript(context, global, argv[1]); |
| |
| JS_DestroyContext(context); |
| JS_DestroyRuntime(runtime); |
| JS_ShutDown(); |
| |
| return gExitCode; |
| } |