r19055: JSON-RPC is working! It passes the small qooxdoo JSON-RPC test suite
authorDerrell Lipman <derrell@samba.org>
Tue, 3 Oct 2006 02:38:08 +0000 (02:38 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 19:20:32 +0000 (14:20 -0500)
perfectly.

This check in covers the remaining fixes and enhancements to complete the
server.  In a subsequent check-in, I need to learn about the new qooxdoo
packaging mechanism.  Although it'd be nice to have the whole source tree,
that's huge and needn't be in samba svn.  It's now supposed to be very easy to
package qooxdoo, so I'll figure out how that's done and then check in the
relevant small number of files.

Steps after that involve generating the stubs to allow various ejs functions
to be called via JSON-RPC.

Derrell

jsonrpc/json.esp
jsonrpc/jsondate.esp
jsonrpc/qooxdoo/test.esp
jsonrpc/request.esp
source/scripting/ejs/literal.c
source/scripting/ejs/smbcalls.c

index 32f0fa776a6467232ac2bde131b678b759418f91..8234ad7be323045e2e4c90b56149759cab5efe08 100644 (file)
@@ -112,6 +112,10 @@ function _encode(o)
             }
             buf = buf + "]";
         }
+        else if (o["__type"] == "_JSON_Date")
+        {
+            buf = "" + o.encoding();
+        }
         else
         {
             /* No length field, so it must be an ordinary object */
index b2f2b9ec11ce1d2e7c7a76865c473cb0591f46c9..42418eaef204d44bfed7c8cb0ba30faa8d412f1a 100644 (file)
@@ -16,6 +16,7 @@
 function _JSON_Date_create(secondsSinceEpoch)
 {
     var o = new Object();
+    o.__type = "_JSON_Date";
 
     function _setUtcDateTimeFields(year, month, day, hour, minute, second, millisecond)
     {
@@ -137,7 +138,7 @@ function _JSON_Date_create(secondsSinceEpoch)
     }
     o.getUtcMillisecond = _getUtcMillisecond;
 
-    function getEpochTime()
+    function _getEpochTime()
     {
         var tm = new Object();
         tm.tm_sec = this.second;
@@ -151,8 +152,9 @@ function _JSON_Date_create(secondsSinceEpoch)
         tm.isdst = 0;
         return gmmktime(tm);
     }
+    o.getEpochTime = _getEpochTime;
 
-    function encoding()
+    function _encoding()
     {
         /* Encode the date in a well-documented fashion */
         return sprintf("new Date(Date.UTC(%d,%d,%d,%d,%d,%d,%d))",
@@ -164,6 +166,7 @@ function _JSON_Date_create(secondsSinceEpoch)
                        this.second,
                        this.millisecond);
     }
+    o.encoding = _encoding;
 
     if (! secondsSinceEpoch)
     {
@@ -174,13 +177,13 @@ function _JSON_Date_create(secondsSinceEpoch)
     {
         o.setEpochTime(secondsSinceEpoch);
     }
-    o.year = null;
-    o.month = null;
-    o.day = null;
-    o.hour = null;
-    o.minute = null;
-    o.second = null;
-    o.millisecond = null;
+    o.year = 0;
+    o.month = 0;
+    o.day = 0;
+    o.hour = 0;
+    o.minute = 0;
+    o.second = 0;
+    o.millisecond = 0;
     return o;
 }
 
index 5fd893c21796a125bc45a1dc5d9d334ec8b1344d..03c2d824ba180a326a95c46589a31fd6bdbbed92 100644 (file)
@@ -31,7 +31,7 @@ function _echo(params, error)
 {
     if (params.length != 1)
     {
-        error.SetError(JsonRpcError_ParameterMismatch,
+        error.setError(JsonRpcError_ParameterMismatch,
                        "Expected 1 parameter; got " + params.length);
         return error;
     }
@@ -75,9 +75,9 @@ function _sleep(params, error)
 {
     if (params.length != 1)
     {
-        error.SetError(JsonRpcError_ParameterMismatch,
+        error.setError(JsonRpcError_ParameterMismatch,
                        "Expected 1 parameter; got " + params.length);
-        return null;
+        return error;
     }
     
     sleep(params[0]);
@@ -222,7 +222,7 @@ jsonrpc.method.getCurrentTimestamp = _getCurrentTimestamp;
 
 function _getError(params, error)
 {
-    error.SetError(23, "This is an application-provided error");
+    error.setError(23, "This is an application-provided error");
     return error;
 }      
 jsonrpc.method.getError = _getError;
index 984ee4663e044264a9bbcc455a08abe0aac0f36d..5a1408df62280e7d6cacf9889c14658380c64e73 100644 (file)
@@ -209,14 +209,14 @@ function _JsonRpcError_create(origin, code, message)
 
     function _origin(origin)
     {
-        this.origin = origin;
+        this.data.origin = origin;
     }
     o.setOrigin = _origin;
 
     function _setError(code, message)
     {
-        this.code = code;
-        this.message = message;
+        this.data.code = code;
+        this.data.message = message;
     }
     o.setError = _setError;
 
@@ -236,7 +236,7 @@ function _JsonRpcError_create(origin, code, message)
     {
         var error = this;
         var id = this.id;
-        var ret = new Array(2);
+        var ret = new Object();
         ret.error = this.data;
         ret.id = this.id;
         sendReply(Json.encode(ret), this.scriptTransportId);
@@ -444,12 +444,7 @@ error.setOrigin(jsonrpc.Constant.ErrorOrigin.Application);
 var retval = method(jsonInput.params, error);
 
 /* See if the result of the function was actually an error object */
-var wasError = (retval["__type"] != undefined);
-if (wasError)
-{
-    wasError = retval.__type == "_JsonRpcError";
-}
-if (wasError)
+if (retval["__type"] == "_JsonRpcError")
 {
     /* Yup, it was.  Return the error */
     retval.Send();
index 4eeb35c42367e51c1569aa7164554af202fa7747..d50e5afdb916e97281c7f36d00cf0ebe39115faf 100644 (file)
@@ -20,6 +20,7 @@ enum json_tokener_error {
         json_tokener_error_oom, /* out of memory */
         json_tokener_error_parse_unexpected,
         json_tokener_error_parse_null,
+        json_tokener_error_parse_date,
         json_tokener_error_parse_boolean,
         json_tokener_error_parse_number,
         json_tokener_error_parse_array,
@@ -30,27 +31,40 @@ enum json_tokener_error {
 };
 
 enum json_tokener_state {
-        json_tokener_state_eatws,               /* 0 */
-        json_tokener_state_start,               /* 1 */
-        json_tokener_state_finish,              /* 2 */
-        json_tokener_state_null,                /* 3 */
-        json_tokener_state_comment_start,       /* 4 */
-        json_tokener_state_comment,             /* 5 */
-        json_tokener_state_comment_eol,         /* 6 */
-        json_tokener_state_comment_end,         /* 7 */
-        json_tokener_state_string,              /* 8 */
-        json_tokener_state_string_escape,       /* 9 */
-        json_tokener_state_escape_unicode,      /* 10 */
-        json_tokener_state_boolean,             /* 11 */
-        json_tokener_state_number,              /* 12 */
-        json_tokener_state_array,               /* 13 */
-        json_tokener_state_array_sep,           /* 14 */
-        json_tokener_state_object,              /* 15 */
-        json_tokener_state_object_field_start,  /* 16 */
-        json_tokener_state_object_field,        /* 17 */
-        json_tokener_state_object_field_end,    /* 18 */
-        json_tokener_state_object_value,        /* 19 */
-        json_tokener_state_object_sep           /* 20 */
+        json_tokener_state_eatws,
+        json_tokener_state_start,
+        json_tokener_state_finish,
+        json_tokener_state_null,
+        json_tokener_state_date,
+        json_tokener_state_comment_start,
+        json_tokener_state_comment,
+        json_tokener_state_comment_eol,
+        json_tokener_state_comment_end,
+        json_tokener_state_string,
+        json_tokener_state_string_escape,
+        json_tokener_state_escape_unicode,
+        json_tokener_state_boolean,
+        json_tokener_state_number,
+        json_tokener_state_array,
+        json_tokener_state_datelist,
+        json_tokener_state_array_sep,
+        json_tokener_state_datelist_sep,
+        json_tokener_state_object,
+        json_tokener_state_object_field_start,
+        json_tokener_state_object_field,
+        json_tokener_state_object_field_end,
+        json_tokener_state_object_value,
+        json_tokener_state_object_sep
+};
+
+enum date_field {
+        date_field_year,
+        date_field_month,
+        date_field_day,
+        date_field_hour,
+        date_field_minute,
+        date_field_second,
+        date_field_millisecond
 };
 
 struct json_tokener
@@ -145,11 +159,16 @@ static void *append_string(void *ctx,
 static struct MprVar json_tokener_do_parse(struct json_tokener *this,
                                            enum json_tokener_error *err_p)
 {
-        enum json_tokener_state state, saved_state;
+        enum json_tokener_state state;
+        enum json_tokener_state saved_state;
+        enum date_field date_field;
         struct MprVar current = mprCreateUndefinedVar();
+        struct MprVar tempObj;
         struct MprVar obj;
         enum json_tokener_error err = json_tokener_success;
+        char date_script[] = "JSON_Date.create(0);";
         char *obj_field_name = NULL;
+        char *emsg = NULL;
         char quote_char;
         int deemed_double;
         int start_offset;
@@ -190,8 +209,12 @@ static struct MprVar json_tokener_do_parse(struct json_tokener *this,
                                 break;
                         case 'N':
                         case 'n':
-                                state = json_tokener_state_null;
                                 start_offset = this->pos++;
+                                if (this->source[this->pos] == 'e') {
+                                    state = json_tokener_state_date;
+                                } else {
+                                    state = json_tokener_state_null;
+                                }
                                 break;
                         case '"':
                         case '\'':
@@ -241,7 +264,8 @@ static struct MprVar json_tokener_do_parse(struct json_tokener *this,
                         goto out;
                         
                 case json_tokener_state_null:
-                        if(strncasecmp("null", this->source + start_offset,
+                        if(strncasecmp("null",
+                                       this->source + start_offset,
                                        this->pos - start_offset)) {
                                 *err_p = json_tokener_error_parse_null;
                                 mprDestroyVar(&current);
@@ -258,6 +282,38 @@ static struct MprVar json_tokener_do_parse(struct json_tokener *this,
                         }
                         break;
                         
+                case json_tokener_state_date:
+                        if (this->pos - start_offset <= 18) {
+                                if (strncasecmp("new Date(Date.UTC(",
+                                                this->source + start_offset,
+                                                this->pos - start_offset)) {
+                                        *err_p = json_tokener_error_parse_date;
+                                        mprDestroyVar(&current);
+                                        return mprCreateUndefinedVar();
+                                } else {
+                                        this->pos++;
+                                        break;
+                                }
+                        }
+                        
+                        this->pos--;            /* we went one too far */
+                        state = json_tokener_state_eatws;
+                        saved_state = json_tokener_state_datelist;
+
+                        /* Create a JsonDate object */
+                        if (ejsEvalScript(0,
+                                          date_script,
+                                          &tempObj,
+                                          &emsg) != 0) {
+                                *err_p = json_tokener_error_parse_date;
+                                mprDestroyVar(&current);
+                                return mprCreateUndefinedVar();
+                        }
+                        mprDestroyVar(&current);
+                        mprCopyVar(&current, &tempObj, MPR_DEEP_COPY);
+                        date_field = date_field_year;
+                        break;
+                        
                 case json_tokener_state_comment_start:
                         if(c == '*') {
                                 state = json_tokener_state_comment;
@@ -293,11 +349,12 @@ static struct MprVar json_tokener_do_parse(struct json_tokener *this,
                         
                 case json_tokener_state_string:
                         if(c == quote_char) {
-                                if ((this->pb = append_string(
-                                             this->ctx,
-                                             this->pb,
-                                             this->source + start_offset,
-                                             this->pos - start_offset)) == NULL) {
+                                this->pb = append_string(
+                                        this->ctx,
+                                        this->pb,
+                                        this->source + start_offset,
+                                        this->pos - start_offset);
+                                if (this->pb == NULL) {
                                         err = json_tokener_error_oom;
                                         goto out;
                                 }
@@ -315,11 +372,12 @@ static struct MprVar json_tokener_do_parse(struct json_tokener *this,
                         switch(c) {
                         case '"':
                         case '\\':
-                                if ((this->pb = append_string(
-                                             this->ctx,
-                                             this->pb,
-                                             this->source + start_offset,
-                                             this->pos - start_offset - 1)) == NULL) {
+                                this->pb = append_string(
+                                        this->ctx,
+                                        this->pb,
+                                        this->source + start_offset,
+                                        this->pos - start_offset - 1);
+                                if (this->pb == NULL) {
                                         err = json_tokener_error_oom;
                                         goto out;
                                 }
@@ -330,11 +388,12 @@ static struct MprVar json_tokener_do_parse(struct json_tokener *this,
                         case 'n':
                         case 'r':
                         case 't':
-                                if ((this->pb = append_string(
-                                             this->ctx,
-                                             this->pb,
-                                             this->source + start_offset,
-                                             this->pos - start_offset - 1)) == NULL) {
+                                this->pb = append_string(
+                                        this->ctx,
+                                        this->pb,
+                                        this->source + start_offset,
+                                        this->pos - start_offset - 1);
+                                if (this->pb == NULL) {
                                         err = json_tokener_error_oom;
                                         goto out;
                                 }
@@ -345,41 +404,41 @@ static struct MprVar json_tokener_do_parse(struct json_tokener *this,
                                          * pass string constant.
                                          */
                                         char buf[] = "\b";
-                                        if ((this->pb = append_string(
-                                                     this->ctx,
-                                                     this->pb,
-                                                     buf,
-                                                     1)) == NULL) {
+                                        this->pb = append_string(this->ctx,
+                                                                 this->pb,
+                                                                 buf,
+                                                                 1);
+                                        if (this->pb == NULL) {
                                                 err = json_tokener_error_oom;
                                                 goto out;
                                         }
                                 } else if (c == 'n') {
                                         char buf[] = "\n";
-                                        if ((this->pb = append_string(
-                                                     this->ctx,
-                                                     this->pb,
-                                                     buf,
-                                                     1)) == NULL) {
+                                        this->pb = append_string(this->ctx,
+                                                                 this->pb,
+                                                                 buf,
+                                                                 1);
+                                        if (this->pb == NULL) {
                                                 err = json_tokener_error_oom;
                                                 goto out;
                                         }
                                 } else if (c == 'r') {
                                         char buf[] = "\r";
-                                        if ((this->pb = append_string(
-                                                     this->ctx,
-                                                     this->pb,
-                                                     buf,
-                                                     1)) == NULL) {
+                                        this->pb = append_string(this->ctx,
+                                                                 this->pb,
+                                                                 buf,
+                                                                 1);
+                                        if (this->pb == NULL) {
                                                 err = json_tokener_error_oom;
                                                 goto out;
                                         }
                                 } else if (c == 't') {
                                         char buf[] = "\t";
-                                        if ((this->pb = append_string(
-                                                     this->ctx,
-                                                     this->pb,
-                                                     buf,
-                                                     1)) == NULL) {
+                                        this->pb = append_string(this->ctx,
+                                                                 this->pb,
+                                                                 buf,
+                                                                 1);
+                                        if (this->pb == NULL) {
                                                 err = json_tokener_error_oom;
                                                 goto out;
                                         }
@@ -388,11 +447,12 @@ static struct MprVar json_tokener_do_parse(struct json_tokener *this,
                                 state = saved_state;
                                 break;
                         case 'u':
-                                if ((this->pb = append_string(
-                                             this->ctx,
-                                             this->pb,
-                                             this->source + start_offset,
-                                             this->pos - start_offset - 1)) == NULL) {
+                                this->pb = append_string(
+                                        this->ctx,
+                                        this->pb,
+                                        this->source + start_offset,
+                                        this->pos - start_offset - 1);
+                                if (this->pb == NULL) {
                                         err = json_tokener_error_oom;
                                         goto out;
                                 }
@@ -417,22 +477,24 @@ static struct MprVar json_tokener_do_parse(struct json_tokener *this,
                                                 hexdigit(*(this->source + start_offset + 3));
                                         if (ucs_char < 0x80) {
                                                 utf_out[0] = ucs_char;
-                                                if ((this->pb = append_string(
-                                                             this->ctx,
-                                                             this->pb,
-                                                             (char *) utf_out,
-                                                             1)) == NULL) {
+                                                this->pb = append_string(
+                                                        this->ctx,
+                                                        this->pb,
+                                                        (char *) utf_out,
+                                                        1);
+                                                if (this->pb == NULL) {
                                                         err = json_tokener_error_oom;
                                                         goto out;
                                                 }
                                         } else if (ucs_char < 0x800) {
                                                 utf_out[0] = 0xc0 | (ucs_char >> 6);
                                                 utf_out[1] = 0x80 | (ucs_char & 0x3f);
-                                                if ((this->pb = append_string(
-                                                             this->ctx,
-                                                             this->pb,
-                                                             (char *) utf_out,
-                                                             2)) == NULL) {
+                                                this->pb = append_string(
+                                                        this->ctx,
+                                                        this->pb,
+                                                        (char *) utf_out,
+                                                        2);
+                                                if (this->pb == NULL) {
                                                         err = json_tokener_error_oom;
                                                         goto out;
                                                 }
@@ -440,11 +502,12 @@ static struct MprVar json_tokener_do_parse(struct json_tokener *this,
                                                 utf_out[0] = 0xe0 | (ucs_char >> 12);
                                                 utf_out[1] = 0x80 | ((ucs_char >> 6) & 0x3f);
                                                 utf_out[2] = 0x80 | (ucs_char & 0x3f);
-                                                if ((this->pb = append_string(
-                                                             this->ctx,
-                                                             this->pb,
-                                                             (char *) utf_out,
-                                                             3)) == NULL) {
+                                                this->pb = append_string(
+                                                        this->ctx,
+                                                        this->pb,
+                                                        (char *) utf_out,
+                                                        3);
+                                                if (this->pb == NULL) {
                                                         err = json_tokener_error_oom;
                                                         goto out;
                                                 }
@@ -536,6 +599,63 @@ static struct MprVar json_tokener_do_parse(struct json_tokener *this,
                         }
                         break;
                         
+                case json_tokener_state_datelist:
+                        if(c == ')') {
+                                if (this->source[this->pos+1] == ')') {
+                                        this->pos += 2;
+                                        saved_state = json_tokener_state_finish;
+                                        state = json_tokener_state_eatws;
+                                } else {
+                                        err = json_tokener_error_parse_date;
+                                        goto out;
+                                }
+                        } else {
+                                obj = json_tokener_do_parse(this, &err);
+                                if (err != json_tokener_success) {
+                                        goto out;
+                                }
+
+                                /* date list items must be integers */
+                                if (obj.type != MPR_TYPE_INT) {
+                                        err = json_tokener_error_parse_date;
+                                        goto out;
+                                }
+                                
+                                switch(date_field) {
+                                case date_field_year:
+                                        mprSetVar(&current, "year", obj);
+                                        break;
+                                case date_field_month:
+                                        mprSetVar(&current, "month", obj);
+                                        break;
+                                case date_field_day:
+                                        mprSetVar(&current, "day", obj);
+                                        break;
+                                case date_field_hour:
+                                        mprSetVar(&current, "hour", obj);
+                                        break;
+                                case date_field_minute:
+                                        mprSetVar(&current, "minute", obj);
+                                        break;
+                                case date_field_second:
+                                        mprSetVar(&current, "second", obj);
+                                        break;
+                                case date_field_millisecond:
+                                        mprSetVar(&current, "millisecond", obj);
+                                        break;
+                                default:
+                                        err = json_tokener_error_parse_date;
+                                        goto out;
+                                }
+
+                                /* advance to the next date field */
+                                date_field++;
+
+                                saved_state = json_tokener_state_datelist_sep;
+                                state = json_tokener_state_eatws;
+                        }
+                        break;
+                        
                 case json_tokener_state_array_sep:
                         if(c == ']') {
                                 this->pos++;
@@ -552,6 +672,27 @@ static struct MprVar json_tokener_do_parse(struct json_tokener *this,
                         }
                         break;
                         
+                case json_tokener_state_datelist_sep:
+                        if(c == ')') {
+                                if (this->source[this->pos+1] == ')') {
+                                        this->pos += 2;
+                                        saved_state = json_tokener_state_finish;
+                                        state = json_tokener_state_eatws;
+                                } else {
+                                        err = json_tokener_error_parse_date;
+                                        goto out;
+                                }
+                        } else if(c == ',') {
+                                this->pos++;
+                                saved_state = json_tokener_state_datelist;
+                                state = json_tokener_state_eatws;
+                        } else {
+                                *err_p = json_tokener_error_parse_date;
+                                mprDestroyVar(&current);
+                                return mprCreateUndefinedVar();
+                        }
+                        break;
+                        
                 case json_tokener_state_object:
                         state = json_tokener_state_object_field_start;
                         start_offset = this->pos;
@@ -580,17 +721,18 @@ static struct MprVar json_tokener_do_parse(struct json_tokener *this,
                         
                 case json_tokener_state_object_field:
                         if(c == quote_char) {
-                                if ((this->pb = append_string(
-                                             this->ctx,
-                                             this->pb,
-                                             this->source + start_offset,
-                                             this->pos - start_offset)) == NULL) {
+                                this->pb = append_string(
+                                        this->ctx,
+                                        this->pb,
+                                        this->source + start_offset,
+                                        this->pos - start_offset);
+                                if (this->pb == NULL) {
                                         err = json_tokener_error_oom;
                                         goto out;
                                 }
-                                if ((obj_field_name =
-                                     talloc_strdup(this->ctx,
-                                                   this->pb)) == NULL) {
+                                obj_field_name = talloc_strdup(this->ctx,
+                                                               this->pb);
+                                if (obj_field_name == NULL) {
                                         err = json_tokener_error_oom;
                                         goto out;
                                 }
@@ -653,10 +795,11 @@ out:
         talloc_free(obj_field_name);
         if(err == json_tokener_success) {
                 return current;
+        } else {
+                mprDestroyVar(&current);
+                *err_p = err;
+                return mprCreateUndefinedVar();
         }
-        mprDestroyVar(&current);
-        *err_p = err;
-        return mprCreateUndefinedVar();
 }
 
 
index 815b3e2b5d8f1cd5246bbb2620cb9df1e57803a5..b0df390427f7ba441430daa82ce31dd46acffcf7 100644 (file)
@@ -203,39 +203,6 @@ static int jsonrpc_include(int eid, int argc, char **argv)
 }
 
 
-static int ejs_debug(int eid, int argc, char **argv)
-{
-        int i;
-        int level;
-        void *ctx = mprMemCtx();
-        char *msg;
-
-
-        if (argc < 2) {
-               return -1;
-        }
-
-        level = atoi(argv[0]);
-
-        msg = talloc_zero_size(ctx, 1);
-        if (msg == NULL) {
-                DEBUG(0, ("out of memory in debug()\n"));
-                return 0;
-        }
-
-        for (i = 1; i < argc; i++) {
-                msg = talloc_append_string(ctx, msg, argv[i]);
-                if (msg == NULL) {
-                        DEBUG(0, ("out of memory in debug()\n"));
-                        return 0;
-                }
-        }
-
-        DEBUG(level, ("%s", msg));
-        talloc_free(msg);
-       return 0;
-}
-
 static void (*ejs_exception_handler) (const char *) = NULL;
 
 _PUBLIC_ void ejs_exception(const char *reason)
@@ -273,6 +240,5 @@ void smb_setup_ejs_functions(void (*exception_handler)(const char *))
        ejsDefineStringCFunction(-1, "libinclude", ejs_libinclude, NULL, MPR_VAR_SCRIPT_HANDLE);
        ejsDefineCFunction(-1, "version", ejs_version, NULL, MPR_VAR_SCRIPT_HANDLE);
        ejsDefineStringCFunction(-1, "jsonrpc_include", jsonrpc_include, NULL, MPR_VAR_SCRIPT_HANDLE);
-       ejsDefineStringCFunction(-1, "debug", ejs_debug, NULL, MPR_VAR_SCRIPT_HANDLE);
 }