[mw-devel] MW3 r955 - trunk/src
psycodom at sucs.org
psycodom at sucs.org
Thu Apr 26 14:58:18 BST 2007
Author: psycodom
Date: 2007-04-26 14:58:18 +0100 (Thu, 26 Apr 2007)
New Revision: 955
Modified:
trunk/src/iconv.c
trunk/src/iconv.h
trunk/src/js.c
Log:
Stops the javascript dbquery() from segving.
Fixes javascript dbquery() for UTF-8 compatibility.
Implements a new convert_string_charset function in iconv.c that removes lots of code duplication in iconv functions.
Cleans up the javscript UTF-8 conversion code using new convert_string_charset to remove a mass of code duplication.
Modified: trunk/src/iconv.c
===================================================================
--- trunk/src/iconv.c 2007-04-26 13:39:31 UTC (rev 954)
+++ trunk/src/iconv.c 2007-04-26 13:58:18 UTC (rev 955)
@@ -6,6 +6,8 @@
#include <iconv.h>
#include <locale.h>
+#include "iconv.h"
+
#ifdef TEST_ICONV
# define DEBUG_ICONV
#endif
@@ -16,9 +18,233 @@
static char * local_charset = NULL;
+/**** convert_string_charset ****
+ a generic iconv function to convert a string from any charset to another
+ expects memory to be allocated for output_buffer
+
+ returns: 0 if successful.
+ +ve if something was converted but errors occured in the conversion
+ -ve if the conversion fails.
+ input_buffer: pointer to the string you want to convert.
+ input_charset: the iconv encoding description string of the input string
+ input_length: the length in bytes of the input string
+ output_buffer: pointer to the memory to put the converted string into (must be allocated)
+ output_charset: the iconv encoding description string of the output string
+ output_buffer_length: the number of bytes allocated for output_buffer
+ unconverted_bytes: on _toolong_ the number of bytes in input buffer that were not converted.
+ output_bytes_used: on success/toolong/invalchars the number of bytes used in output_buffer
+ invalid_count: on invalchars the number of invalid chars that were discovered in the string
+ irreversible_count: on _success_ the number of chars that were converted in an irreversible way
+ substitute: if an invalid char is discovered replace it with this ***UTF-8*** string
+ (the utf8 string is converted into your desired charset)
+
+ for sanities sake this function always attempts to put '\0' (in the converted charset)
+ at the end of the output buffer even if there was not a '\0' in the input string.
+
+ it is assumed this function is used on a system that understands UTF-8!
+ if not you will get EOUTPUTNOTSUPPORTED.
+*/
+int convert_string_charset(char *input_buffer, char *input_charset, size_t input_length,
+ char *output_buffer, char *output_charset, size_t output_buffer_length,
+ size_t *output_bytes_used, size_t *irreversible_count,
+ size_t *unconverted_bytes, size_t *invalid_count, char *substitute)
+{
+ char *input_ptr, *output_ptr;
+ iconv_t conversion_descriptor;
+ size_t input_bytes_left, output_bytes_left, not_conv_count=0;
+
+ char converted_null[8], null_string[1]="";
+ char *converted_substitute=NULL;
+ size_t converted_substitute_length=output_buffer_length, converted_null_length;
+ size_t nconv;
+ int local_invalid_count=0;
+ int i, too_big=0, iconv_failed=0, retval=0;
+
+
+ if(output_charset==NULL) {
+ return ENOOUTPUTCS;
+ }
+ if(input_charset==NULL) {
+ return ENOINPUTCS;
+ }
+ if(output_buffer==NULL) {
+ return ENOINPUTBUFF;
+ }
+ if(input_buffer==NULL) {
+ return ENOINPUTBUFF;
+ }
+ if(input_length<1) {
+ return EZEROLENTGHINPUT;
+ }
+
+ if( strcmp(output_charset,"LOCAL")==0 ) {
+ if(local_charset!=NULL) {
+ output_charset = local_charset;
+ } else {
+ output_charset = null_string;
+ }
+ }
+
+ if( strcmp(input_charset,"LOCAL")==0 ) {
+ if(local_charset!=NULL) {
+ input_charset = local_charset;
+ } else {
+ input_charset = null_string;
+ }
+ }
+
+ conversion_descriptor = iconv_open(output_charset, "UTF-8");
+ if(conversion_descriptor == (iconv_t)-1) {
+ if(errno == EINVAL) {
+ return EOUTPUTNOTSUPPORTED;
+ } else {
+ return EUTFCONVERTFAILED;
+ }
+ }
+ /* convert '\0' to local charsets representation */
+ input_bytes_left=1;
+ output_bytes_left=8;
+ input_ptr=null_string;
+ output_ptr=converted_null;
+ nconv = iconv( conversion_descriptor,
+ &input_ptr, &input_bytes_left,
+ &output_ptr, &output_bytes_left );
+ if(nconv!=0) {
+ iconv_close(conversion_descriptor);
+ return ECONVERTNULLFAILED;
+ }
+ converted_null_length = 8-output_bytes_left;
+ if(converted_null_length > output_buffer_length)
+ {
+ iconv_close(conversion_descriptor);
+ return EOUTPUTBUFFMUCHTOOSHORT;
+ }
+
+ /* if the caller specified a invalid char substitute string convert that to the output format */
+ if(substitute!=NULL) {
+ output_bytes_left = sizeof(char) * strlen(substitute) * converted_null_length;
+ converted_substitute = malloc(output_bytes_left);
+ if(converted_substitute==NULL) {
+ iconv_close(conversion_descriptor);
+ return EMALLOCSUBS;
+ }
+ input_bytes_left = strlen(substitute);
+ input_ptr=substitute;
+ output_ptr=converted_substitute;
+ nconv = iconv( conversion_descriptor,
+ &input_ptr, &input_bytes_left,
+ &output_ptr, &output_bytes_left );
+ if(nconv!=0) {
+ free(converted_substitute);
+ iconv_close(conversion_descriptor);
+ return ECONVERTSUBSFAILED;
+ }
+ converted_substitute_length = (size_t)(output_ptr - converted_substitute);
+ }
+ iconv_close(conversion_descriptor);
+
+ /* open an iconv convertor for the main conversion */
+ conversion_descriptor = iconv_open(output_charset, input_charset);
+ if(conversion_descriptor == (iconv_t)-1) {
+ if(errno == EINVAL) {
+ free(converted_substitute);
+ return EINPUTNOTSUPPORTED;
+ } else {
+ free(converted_substitute);
+ return EOPENCONVERTFAILED;
+ }
+ }
+
+ input_ptr = input_buffer;
+ output_ptr = output_buffer;
+ input_bytes_left = input_length;
+ /* we tell iconv the buffer is shorter than it really is so we always have space to put a null on the end of it */
+ output_bytes_left = output_buffer_length - converted_null_length;
+
+ while(input_bytes_left > 0) {
+ nconv = iconv( conversion_descriptor,
+ &input_ptr, &input_bytes_left,
+ &output_ptr, &output_bytes_left );
+ if(nconv == -1) {
+ if(errno == EILSEQ || errno == EINVAL) {
+ /* invalid input sequence, we skip over its in the input buffer */
+ local_invalid_count++;
+ input_ptr++;
+ input_bytes_left--;
+ if(converted_substitute!=NULL) {
+ /* if the caller specified a substitute string we add it here */
+ if(output_bytes_left >= converted_substitute_length) {
+ for(i=0; i<converted_substitute_length ; i++) {
+ output_ptr[0]=converted_substitute[i];
+ output_ptr++;
+ output_bytes_left--;
+ }
+ } else {
+ too_big=1;
+ }
+ }
+
+ } else if (errno == E2BIG) {
+ /* this happens if the output buffer if not big enough, we truncate to this point but warn the caller */
+ too_big=1;
+ not_conv_count=input_bytes_left;
+ input_bytes_left=0;
+ }
+ else {
+ /* some other error occured, we truncate to this point but warn the user */
+ iconv_failed=1;
+ not_conv_count=input_bytes_left;
+ input_bytes_left=0;
+
+ }
+ errno=0;
+ }
+ }
+ /* put a null on the end of the converted string */
+ for(i=0; i<converted_null_length; i++) {
+ output_ptr[0]=converted_null[i];
+ output_ptr++;
+ }
+ if(local_invalid_count>0) {
+ retval += WINVALIDCHARS;
+ }
+
+ if(invalid_count!=NULL) {
+ *invalid_count = local_invalid_count;
+ }
+
+ if(too_big) {
+ retval += WOUTPUTTOOSHORT;
+ }
+
+ if(unconverted_bytes!=NULL) {
+ *unconverted_bytes=not_conv_count;
+ }
+
+ if(iconv_failed) {
+ retval += WICONVFAIL;
+ }
+
+ if(output_bytes_used!=NULL) {
+ *output_bytes_used = output_buffer_length - output_bytes_left;
+ }
+
+ if(irreversible_count!=NULL) {
+ if(retval==0) {
+ *irreversible_count=nconv;
+ } else {
+ *irreversible_count=0;
+ }
+ }
+
+ free(converted_substitute);
+ iconv_close(conversion_descriptor);
+
+ return retval;
+}
+
/* convert string in given encoding to wide string */
-wchar_t *
-any2wcs(char * s, char * charset, int report_error)
+wchar_t * any2wcs(char * s, char * charset, int report_error)
{
char * local, * localcpy;
char * wcs; /* needs to be char * for passing to iconv */
Modified: trunk/src/iconv.h
===================================================================
--- trunk/src/iconv.h 2007-04-26 13:39:31 UTC (rev 954)
+++ trunk/src/iconv.h 2007-04-26 13:58:18 UTC (rev 955)
@@ -1,33 +1,57 @@
#include <wchar.h>
+int convert_string_charset(char *input_buffer, char *input_charset, size_t input_length,
+ char *output_buffer, char *output_charset, size_t output_buffer_length,
+ size_t *output_bytes_used, size_t *irreversible_count,
+ size_t *unconverted_bytes, size_t *invalid_count, char *substitute);
+
+
/* convert string in given encoding to wide string */
-wchar_t * any2wcs(char * s, char * charset);
+//wchar_t * any2wcs(char * s, char * charset);
/* convert wide string to string in given encoding */
-char * wcs2any(wchar_t * ws, char * charset);
+//char * wcs2any(wchar_t * ws, char * charset);
/* convert string in local encoding to wide string */
-extern wchar_t * local2wcs(char * s);
+// wchar_t * local2wcs(char * s);
/* convert wide string to local encoding */
-extern char * wcs2local(wchar_t * ws);
+// char * wcs2local(wchar_t * ws);
/* convert UTF-8 encoded string to wide string */
-wchar_t * utf82wcs(char * s);
+//wchar_t * utf82wcs(char * s);
/* convert wide string to UTF-8 encoded string */
-char * wcs2utf8(wchar_t * ws);
+//char * wcs2utf8(wchar_t * ws);
/* set local charset independently of locale */
-extern int set_local_charset(char * set);
+ int set_local_charset(char * set);
/* query local charset */
-extern char * get_local_charset(void);
+ char * get_local_charset(void);
/* wrapper around set_locale printing failure messages */
int locale_mesgs(char * locale);
/* set locale */
-extern int set_locale(char * locale);
+ int set_locale(char * locale);
-extern void init_locale(void);
+ void init_locale(void);
+
+#define ENOOUTPUTCS -1
+#define ENOINPUTCS -2
+#define ENOOUTPUTBUFF -3
+#define ENOINPUTBUFF -4
+#define EZEROLENTGHINPUT -5
+#define EOUTPUTNOTSUPPORTED -6
+#define EUTFCONVERTFAILED -7
+#define ECONVERTNULLFAILED -8
+#define EMALLOCSUBS -9
+#define ECONVERTSUBSFAILED -10
+#define EINPUTNOTSUPPORTED -11
+#define EOPENCONVERTFAILED -12
+#define EOUTPUTBUFFMUCHTOOSHORT -13
+
+#define WOUTPUTTOOSHORT 1
+#define WINVALIDCHARS 2
+#define WICONVFAIL 4
Modified: trunk/src/js.c
===================================================================
--- trunk/src/js.c 2007-04-26 13:39:31 UTC (rev 954)
+++ trunk/src/js.c 2007-04-26 13:58:18 UTC (rev 955)
@@ -18,6 +18,7 @@
#include "chattable.h"
#include "script.h"
#include "talker_privs.h"
+#include "iconv.h"
extern struct person *user;
extern long userposn;
@@ -51,184 +52,53 @@
JSCLASS_NO_OPTIONAL_MEMBERS
};
-// currently assuming all scripts and script arguments will be in utf8
-// if the users client is not utf8 then that issue needs to be dealt with elsewhere
-char *jsstring_to_utf8(jschar *the_jsstring, size_t len)
+// turns a jsval into a utf-8 string that mw can handle
+// expects the utf8_buffer to have been allocated and be at least buffer_length long
+// used to reduce mass code duplication
+int jsval_to_utf8string(JSContext *cx, jsval the_jsval, char *utf8_buffer, size_t buffer_length)
{
- char * utf8_string;
- char * utf8_string_tmp;
-
- char * jsstring_ptr;
- char * utf8_ptr;
-
- iconv_t conv;
- size_t nconv;
-
- size_t utf8_bytes_left;
- size_t jsstring_bytes_left;
- size_t utf8_length;
-
- conv = iconv_open("UTF-8", "UCS-2");
- if (conv == (iconv_t)-1) {
- fprintf(stderr, "jsstring_to_utf8: iconv_open() failed.\n");
- return NULL;
- }
+ JSString *the_jsstring;
+ size_t ucs2_length;
+ jschar *ucs2_string;
+ int retval;
- utf8_bytes_left = (len) * sizeof(char) * 4; /* Urgh, x4 is kludge (x2 isn't big enough, some utf8 chars require 4 bytes and in a worst case scenario we'd run out) */
- jsstring_bytes_left = (len) * sizeof(jschar);
- utf8_string_tmp = (char *)malloc(utf8_bytes_left);
+ the_jsstring = JS_ValueToString(cx, the_jsval);
+ ucs2_length=JS_GetStringLength(the_jsstring);
+ ucs2_string=JS_GetStringChars(the_jsstring);
- if (utf8_string_tmp == NULL) {
- fprintf(stderr, "jsstring_to_utf8: Could not allocate memory for iconv\n");
- return NULL;
- }
+ retval=convert_string_charset((char *)ucs2_string, "UCS-2", ucs2_length*sizeof(jschar), utf8_buffer, "UTF-8", buffer_length, NULL, NULL, NULL, NULL, NULL);
- utf8_ptr = utf8_string_tmp;
- jsstring_ptr = (char *)the_jsstring;
-
- while (jsstring_bytes_left > 0) {
-/* printf("Before: localbytesleft: %d utf16bytesleft: %d\n",
- (int)localbytesleft, (int)utf16bytesleft); */
- nconv = iconv(conv,
- &jsstring_ptr, &jsstring_bytes_left,
- &utf8_ptr, &utf8_bytes_left);
-/* printf("After: localbytesleft: %d utf16bytesleft: %d\n",
- (int)localbytesleft, (int)jsstring_bytes_left); */
- if (nconv == (size_t)-1) {
- fprintf(stderr, "jsstring_to_utf8: iconv() barfed with error %d - ", errno);
- /* iconv barfed, but why? */
- if (errno == EILSEQ || errno == EINVAL) {
- /* invalid input sequence, skip it */
- fprintf(stderr, "Invalid input sequence\n");
- jsstring_ptr++;
- jsstring_bytes_left--;
- errno = 0;
- continue;
- } else {
- /* some other error, recover what we can */
- *(char *)utf8_ptr = '\0';
- perror("iconv");
- errno = 0;
- break;
- }
- }
+ if(retval<0) {
+ fprintf(stderr, "jsval_to_utf8string: convert_string_charset failed with error: %d\n", retval);
}
- iconv_close(conv);
- utf8_length=(len*4)-utf8_bytes_left;
-
- utf8_string=(char *)malloc(sizeof(char)*(utf8_length+1));
- if(utf8_string==NULL) {
- fprintf(stderr, "jsstring_to_utf8: Could not allocate memory for the utf8_string\n");
- return NULL;
- }
- strncpy(utf8_string, utf8_string_tmp, utf8_length);
- utf8_string[utf8_length]='\0';
- free(utf8_string_tmp);
-
- return utf8_string;
+ return retval;
}
-jschar *utf8_to_jsstring(char *utf8_string, size_t *length, int *utferror)
-{
- char * the_jsstring; // iconv uses char*, we'll cast to jschar* at the end.
- char * jsstring_ptr;
- char * utf8_ptr;
- iconv_t conv;
- size_t nconv;
-
- size_t utf8_bytes_left;
- size_t jsstring_bytes_left;
-
- *utferror=0;
- conv = iconv_open("UCS-2", "UTF-8");
- if (conv == (iconv_t)-1) {
- fprintf(stderr, "utf8_to_jsstring: iconv_open() failed.\n");
- return NULL;
- }
-
- utf8_bytes_left = (strlen(utf8_string)+1) * sizeof(char);
- jsstring_bytes_left = (strlen(utf8_string)+1) * sizeof(jschar);
- the_jsstring = (char *)malloc(jsstring_bytes_left);
-
- if (the_jsstring == NULL) {
- fprintf(stderr, "utf8_to_jsstring: Could not allocate memory for iconv\n");
- return NULL;
- }
-
- utf8_ptr = utf8_string;
- jsstring_ptr = the_jsstring;
-
- while (utf8_bytes_left > 0) {
-/* printf("Before: localbytesleft: %d utf16bytesleft: %d\n",
- (int)localbytesleft, (int)utf16bytesleft); */
- nconv = iconv(conv,
- &utf8_ptr, &utf8_bytes_left,
- &jsstring_ptr, &jsstring_bytes_left);
-/* printf("After: localbytesleft: %d utf16bytesleft: %d\n",
- (int)localbytesleft, (int)jsstring_bytes_left); */
- if (nconv == (size_t)-1) {
- fprintf(stderr, "utf8_to_jsstring: iconv() barfed with error %d - ", errno);
- /* iconv barfed, but why? */
- if (errno == EILSEQ || errno == EINVAL) {
- /* invalid input sequence, skip it */
- fprintf(stderr, "Invalid input sequence\n");
- utf8_ptr++;
- utf8_bytes_left--;
- errno = 0;
- *utferror=1;
- continue;
- } else {
- /* some other error, recover what we can */
- /**(char *)jsstring_ptr = '\0';
- jsstring_ptr++;
- *(char *)jsstring_ptr = '\0';*/
- perror("iconv");
- errno = 0;
- break;
- }
- }
- }
- iconv_close(conv);
-
- *length=strlen(utf8_string)-(jsstring_bytes_left/(sizeof(jschar)));
-
- return (jschar *)the_jsstring;
-}
-
-
-
/* Function for printing to standard out from javascript (helpful for
* debugging and demonstrates how to call C from js)
*/
-static JSBool
-js_print(JSContext *cx, JSObject __attribute__((unused)) *obj, uintN argc, jsval *argv, jsval __attribute__((unused)) *rval) {
- JSString *jsmsg;
- jschar *ucmsg;
- size_t len;
+static JSBool js_print(JSContext *cx, JSObject __attribute__((unused)) *obj, uintN argc, jsval *argv, jsval __attribute__((unused)) *rval)
+{
uintN i;
-
-// jschar * ucmsg;
- char * msg;
+ int conversion_result;
+ char msg[MAXTEXTLENGTH];
if (argc < 1) {
return JS_TRUE;
}
for (i = 0; i<argc; i++) {
if (JSVAL_IS_STRING(argv[i])) {
- jsmsg = JS_ValueToString(cx,argv[i]);
- len = JS_GetStringLength(jsmsg);
- ucmsg = JS_GetStringChars(jsmsg);
- msg = jsstring_to_utf8(ucmsg, len);
- if(msg==NULL) {
- printf("js_print: failed to convert jsstring to utf8\n");
+ conversion_result=jsval_to_utf8string(cx, argv[0], msg, MAXTEXTLENGTH);
+ if( conversion_result >= 0) {
+ if( conversion_result & WOUTPUTTOOSHORT ) {
+ printf("JavaScript print() command produced too much text. It was truncated\n");
+ }
+ display_message(msg, 0, 1);
+ } else {
return JS_FALSE;
}
- //msg = JS_GetStringBytes(jsmsg);
- display_message(msg, 0, 1);
- free(msg);
- //printf("%s",msg);
} else
if (JSVAL_IS_NULL(argv[i])) {
display_message("jsval is NULL",0,1);
@@ -244,42 +114,32 @@
}
/* execute a talker command */
-static JSBool
-js_mwexec(JSContext *cx, JSObject __attribute__((unused)) *obj, uintN argc, jsval *argv, jsval __attribute__((unused)) *rval) {
- JSString *jsmsg;
- jschar *ucmsg;
- size_t len;
- char * msg;
+static JSBool js_mwexec(JSContext *cx, JSObject __attribute__((unused)) *obj, uintN argc, jsval *argv, jsval __attribute__((unused)) *rval)
+{
+ char msg[MAXTEXTLENGTH];
+ int conversion_result;
if (argc < 1) {
return JS_FALSE;
}
if (JSVAL_IS_STRING(argv[0])) {
- jsmsg = JS_ValueToString(cx,argv[0]);
- len = JS_GetStringLength(jsmsg);
- ucmsg = JS_GetStringChars(jsmsg);
- msg = jsstring_to_utf8(ucmsg, len);
- if(msg==NULL) {
- printf("js_mwexec: failed to convert jsstring to utf8\n");
- return JS_FALSE;
+ conversion_result=jsval_to_utf8string(cx, argv[0], msg, MAXTEXTLENGTH);
+ if( conversion_result >= 0) {
+ if( conversion_result & WOUTPUTTOOSHORT ) {
+ printf("JavaScript exec() command produced too much text. It was truncated\n");
+ }
+ DoCommand(msg, chattable);
+ return JS_TRUE;
}
- //msg = strdup(JS_GetStringBytes(jsmsg));
- DoCommand(msg, chattable);
- free(msg);
- return JS_TRUE;
}
return JS_FALSE;
}
/* say to the talker */
-static JSBool
-js_say(JSContext *cx, JSObject __attribute__((unused)) *obj, uintN argc, jsval *argv, jsval __attribute__((unused)) *rval) {
- JSString *jsmsg;
- jschar *ucmsg;
- size_t len;
- char * msg;
- char saymsg[MAXTEXTLENGTH];
-
+static JSBool js_say(JSContext *cx, JSObject __attribute__((unused)) *obj, uintN argc, jsval *argv, jsval __attribute__((unused)) *rval)
+{
+ char msg[MAXTEXTLENGTH];
+ int conversion_result;
if (argc < 1) {
return JS_FALSE;
}
@@ -291,89 +151,20 @@
}
if (JSVAL_IS_STRING(argv[0])) {
- jsmsg = JS_ValueToString(cx,argv[0]);
- len = JS_GetStringLength(jsmsg);
- ucmsg = JS_GetStringChars(jsmsg);
-
- msg = jsstring_to_utf8(ucmsg, len);
- if(msg==NULL) {
- printf("js_say: failed to convert jsstring to utf8\n");
- return JS_FALSE;
+ conversion_result=jsval_to_utf8string(cx, argv[0], msg, MAXTEXTLENGTH);
+ if( conversion_result >= 0) {
+ if( conversion_result & WOUTPUTTOOSHORT ) {
+ printf("JavaScript say() command produced too much text. It was truncated\n");
+ }
+ chat_say(msg);
+ return JS_TRUE;
}
- //msg = strdup(JS_GetStringBytes(jsmsg));
-
- // things passed to chatsay may end up being passed to apply_gag which expects a buffer MAXTEXTLENGTH long.
- strncpy(saymsg,msg,MAXTEXTLENGTH-1);
- saymsg[MAXTEXTLENGTH]='\0';
- chat_say(saymsg);
- free(msg);
- return JS_TRUE;
}
return JS_FALSE;
}
-// Create a javascript array of strings from a struct db_data
-JSObject *
-dbdata_to_jsarray(JSContext *cx, struct db_data *data, int ncols) {
- JSObject *jsdata;
- JSString *jsstr;
- jsval jv;
- int i;
-
- if (data == NULL || ncols < 1) return NULL;
-
- jsdata = JS_NewArrayObject(cx, 0, NULL);
- JS_AddRoot(cx, jsdata);
-
- for (i = 0; i < ncols; i++) {
- printf("dbdata_to_jsarray: data @ %p", (void *)data->field[i]);
- jsstr = JS_NewStringCopyZ(cx, data->field[i]);
- JS_AddRoot(cx, jsstr);
- printf(" -> JSString @ %p\n", (void *)jsstr);
- jv = STRING_TO_JSVAL(jsstr);
- JS_SetElement(cx, jsdata, i, &jv);
- }
- JS_RemoveRoot(cx, jsdata);
-
- return jsdata;
-}
-
-// Create a javascript array of arrays (see dbdata_to_jsarray()) from
-// a struct db_result
-JSObject *
-dbresult_to_jsarray(JSContext *cx, struct db_result *data) {
- JSObject *jsarray;
- JSObject *jsnode;
- jsval jv;
- struct db_data *node;
- int i;
-
- if (data == NULL) return NULL;
-
- jsarray = JS_NewArrayObject(cx, 0, NULL);
- JS_AddRoot(cx, jsarray);
- JS_SetArrayLength(cx, jsarray, data->cols);
-
-/* printf("Making Array(%d)\n", data->cols); */
- i = 0;
- node = data->data;
- while (node) {
- printf("dbresult_to_jsarray: node @ %p\n", (void *)node);
- jsnode = dbdata_to_jsarray(cx, node, data->cols);
- jv = OBJECT_TO_JSVAL(jsnode);
- JS_SetElement(cx, jsarray, i, &jv);
-
- node = node->next;
- i++;
- }
- JS_RemoveRoot(cx, jsarray);
-
- return jsarray;
-}
-
// Provides a javascript function to query the wholist
-static JSBool
-js_wholist(JSContext *cx, JSObject __attribute__((unused)) *obj, uintN argc, jsval *argv, jsval *rval) {
+static JSBool js_wholist(JSContext *cx, JSObject __attribute__((unused)) *obj, uintN argc, jsval *argv, jsval *rval) {
struct person u;
struct who w;
int ufile, wfile;
@@ -435,16 +226,95 @@
return JS_TRUE;
}
+// Create a javascript array of strings from a struct db_data
+JSObject *dbdata_to_jsarray(JSContext *cx, struct db_data *data, int ncols) {
+ JSObject *jsdata;
+ JSString *jsstr;
+ jsval jv;
+ jschar *ucsstr;
+ int i, conv_error;
+ size_t data_length;
+
+ if (data == NULL || ncols < 1) return NULL;
+ jsdata = JS_NewArrayObject(cx, 0, NULL);
+ JS_AddRoot(cx, jsdata);
+
+ for (i = 0; i < ncols; i++) {
+// printf("dbdata_to_jsarray: data @ %p -", (void *)data->field[i]);
+// printf("%s", data->field[i]);
+ data_length = sizeof(jschar) * (strlen(data->field[i]) + 1);
+
+ ucsstr = malloc( data_length );
+ if(ucsstr!=NULL) {
+
+ conv_error=convert_string_charset(data->field[i], "UTF-8", strlen(data->field[i]),
+ (char *)ucsstr, "UCS-2", data_length,
+ NULL, NULL, NULL, NULL, NULL);
+ if(conv_error>=0) {
+ jsstr = JS_NewUCStringCopyZ(cx, ucsstr);
+ } else {
+ jsstr = JS_NewStringCopyZ(cx, "(garbled string)");
+ }
+ free(ucsstr);
+ } else {
+ jsstr = JS_NewStringCopyZ(cx, "(garbled string)");
+ }
+ //JS_AddRoot(cx, jsstr);
+// printf(" -> JSString @ %p\n", (void *)jsstr);
+ jv = STRING_TO_JSVAL(jsstr);
+ JS_SetElement(cx, jsdata, i, &jv);
+ }
+ JS_RemoveRoot(cx, jsdata);
+
+ return jsdata;
+}
+
+// Create a javascript array of arrays (see dbdata_to_jsarray()) from
+// a struct db_result
+JSObject *dbresult_to_jsarray(JSContext *cx, struct db_result *data) {
+ JSObject *jsarray;
+ JSObject *jsnode;
+ jsval jv;
+ struct db_data *node;
+ int i;
+
+ if (data == NULL) return NULL;
+
+ jsarray = JS_NewArrayObject(cx, 0, NULL);
+ JS_AddRoot(cx, jsarray);
+// JS_SetArrayLength(cx, jsarray, data->cols);
+
+/* printf("Making Array(%d)\n", data->cols); */
+ i = 0;
+ node = data->data;
+ while (node) {
+// printf("dbresult_to_jsarray: node @ %p\n", (void *)node);
+ jsnode = dbdata_to_jsarray(cx, node, data->cols);
+ jv = OBJECT_TO_JSVAL(jsnode);
+ JS_SetElement(cx, jsarray, i, &jv);
+
+ node = node->next;
+ i++;
+ }
+ JS_RemoveRoot(cx, jsarray);
+
+ return jsarray;
+}
+
+
+
// Provides a javascript function to query an sqlite3 database
-static JSBool
-js_doquery(JSContext *cx, JSObject __attribute__((unused)) *obj, uintN argc, jsval *argv, jsval *rval) {
+// This probably wants updating to not return JS_FALSE as that halts js execution
+// far better to return an error code in rsval which the javascript can handle
+static JSBool js_doquery(JSContext *cx, JSObject __attribute__((unused)) *obj, uintN argc, jsval *argv, jsval *rval) {
struct db_result *dbres;
char *dbname;
- char *query;
- JSObject *result; // result object were creating
+ char query[MAXTEXTLENGTH*2]; // for now queries will be at most 4096 bytes or will fail.
+ // if this becomes a problem dynamic allocation of the utf8 buffer might be needed although getting the right size is a pita
+ //JSObject *result; // result object were creating
JSObject *resarray;
- int myid;
+ int myid, conversion_result;
char path[1024];
struct passwd *pw;
@@ -467,8 +337,12 @@
}
dbname = JS_GetStringBytes(JS_ValueToString(cx, argv[0]));
- query = JS_GetStringBytes(JS_ValueToString(cx, argv[1]));
-
+ conversion_result=jsval_to_utf8string(cx, argv[1], query, MAXTEXTLENGTH*2);
+ //query = JS_GetStringBytes(JS_ValueToString(cx, argv[1]));
+ if(conversion_result != 0) {
+ return JS_FALSE;
+ }
+
if (dbname[0] == '/'
|| strncmp(dbname, "../", 3)==0
|| strstr(dbname, "/../")) {
@@ -495,14 +369,18 @@
if (!resarray) {
return JS_FALSE;
}
- result = JS_NewObject(cx, &js_dbresultclass, NULL, NULL);
-
+/* result = JS_NewObject(cx, &js_dbresultclass, NULL, NULL);
+ // seems pointless to create an object with a data array and a numrows when the array itself has a .length.
+ // also something here was making mw segv so it's being done wrong.
+ // so now we just return the array.
+
JS_DefineProperty(cx, result, "numrows", INT_TO_JSVAL(dbres->rows), NULL, NULL, JSPROP_READONLY | JSPROP_PERMANENT);
JS_DefineProperty(cx, result, "data", OBJECT_TO_JSVAL(resarray), NULL, NULL, JSPROP_READONLY | JSPROP_PERMANENT | JSPROP_ENUMERATE);
- JS_SetPrivate(cx, result, dbres);
-
- *rval = OBJECT_TO_JSVAL(result);
+ //JS_SetPrivate(cx, result, dbres);
+*/
+ db_free(dbres);
+ *rval = OBJECT_TO_JSVAL(resarray);
return JS_TRUE;
}
@@ -532,15 +410,16 @@
/* Execute some javascript commands */
int js_exec(char * name, int argc, char **argvc) {
int i;
- jschar * js_string;
+// jschar * js_string;
jsval rval;
jsval *argv;
JSBool ret;
- jschar *ucarg;
- size_t uclen;
+ //jschar *ucarg;
+ jschar unicode_arg[MAXTEXTLENGTH];
+ //size_t uclen;
int utferror;
- js_string = NULL;
+// js_string = NULL;
argv=calloc(argc,sizeof(jsval));
for (i=0;i<argc;i++) {
@@ -548,33 +427,37 @@
fprintf(stderr, "js_exec: argc %d was NULL!\n",i);
continue;
}
- js_string = (jschar *)JS_malloc(jscx, sizeof(jschar) * strlen(argvc[i]));
- if (!js_string || js_string == NULL) {
- fprintf(stderr, "Could not allocate memory for string. Aborting slang_exec(%s)\n", name);
- return -1;
+ //ucarg=utf8_to_jsstring(argvc[i], &uclen, &utferror);
+ utferror=convert_string_charset(argvc[i], "UTF-8", strlen(argvc[i]), (char *)unicode_arg, "UCS-2", sizeof(jschar) * MAXTEXTLENGTH, NULL, NULL, NULL, NULL, "?");
+ if(utferror>=0) {
+ if(utferror & WOUTPUTTOOSHORT) {
+ printf("Argument %d for javascript function '%s' was too long and has been truncated.\n", i, name);
}
- // js_string = local2jschars(argvc[i]);
- if (js_string != NULL) {
- ucarg=utf8_to_jsstring(argvc[i], &uclen, &utferror);
- argv[i] = STRING_TO_JSVAL(JS_NewUCStringCopyZ(jscx, ucarg));
- // argv[i] = STRING_TO_JSVAL(JS_NewStringCopyZ(jscx, argvc[i]));
- } else {
- argv[i] = STRING_TO_JSVAL(JS_NewStringCopyZ(jscx, "(Garbled string)"));
+ if(utferror & WINVALIDCHARS) {
+ printf("Argument %d for javascript function '%s' contained invalid characters which have been replaced by '?'\n", i, name);
}
- if (js_string) JS_free(jscx, js_string);
+ if(utferror & WICONVFAIL) {
+ printf("An iconv error occured processing argument %d for javascript function '%s' and the argument may have been truncated.\n", i, name);
+ }
+
+ argv[i] = STRING_TO_JSVAL(JS_NewUCStringCopyZ(jscx, unicode_arg));
+ } else {
+ printf("A major error %d occured converting argument %d for javascript function '%s' to unicode.\n", utferror, i, name);
+ argv[i] = STRING_TO_JSVAL(JS_NewStringCopyZ(jscx, "(error argument)"));
+ }
+
}
ret = JS_CallFunctionName(jscx, jsroot, name, argc, argv, &rval);
- if (!ret) {
- printf("JS function '%s' (args: %d) not found.\n", name, argc);
+ if (ret) {
+ if (JSVAL_IS_BOOLEAN(rval) && JSVAL_TO_BOOLEAN(rval)==0) {
+ script_output=0;
+ }
}
//show_type("js_exec(rval)", rval);
- if (JSVAL_IS_BOOLEAN(rval) && JSVAL_TO_BOOLEAN(rval)==0) {
- script_output=0;
- }
free(argv);
JS_GC(jscx); // do we still need to do this now the actual bug has been found?
- return ret ? 1 : 0;
+ return ret;
}
/* Prints error reports to stdout when a javascript error occurs */
@@ -648,17 +531,27 @@
fread(body, 1, len, f);
body[len]=0;
/*convert the script into jsstring, scripts assumed to be utf8*/
- unicode_body=utf8_to_jsstring(body, &length, &utferror);
- if(unicode_body==NULL)
- {
- fprintf(stderr, "load_jsfile: failed to convert script into javascript compatible unicode\n");
+ unicode_body=malloc(sizeof(jschar) * (len+1));
+
+ /*unicode_body=utf8_to_jsstring(body, &length, &utferror);*/
+
+ if(unicode_body==NULL) {
+ fprintf(stderr, "load_jsfile: failed to allocate memory for javascript file\n");
return 0;
}
- if(utferror)
+ utferror = convert_string_charset( body, "UTF-8", len, (char *)unicode_body, "UCS-2", sizeof(jschar) * (len+1), &length, NULL, NULL, NULL, NULL);
+ if(utferror<0)
{
+ fprintf(stderr, "load_jsfile: failed to convert script to jschar string. Error %d\n", utferror);
+ return 0;
+ }
+
+ if(utferror & WINVALIDCHARS) {
printf("The script '%s' does not appear to be utf-8. Some characters may have been discared. Please ensure this file is saved as UTF-8\n", filename);
}
+
+ length=(length/sizeof(jschar))-1;
/* Compile the js file specified */
/* script = JS_CompileScript(jscx, jsroot, body, len, filename, lineno); */
script = JS_CompileUCScript(jscx, jsroot, unicode_body, length, filename, lineno);
More information about the mw-devel
mailing list