diff options
Diffstat (limited to 'source4/scripting/ejs/literal.c')
-rw-r--r-- | source4/scripting/ejs/literal.c | 323 |
1 files changed, 233 insertions, 90 deletions
diff --git a/source4/scripting/ejs/literal.c b/source4/scripting/ejs/literal.c index 4eeb35c423..d50e5afdb9 100644 --- a/source4/scripting/ejs/literal.c +++ b/source4/scripting/ejs/literal.c @@ -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(¤t); @@ -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(¤t); + 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(¤t); + return mprCreateUndefinedVar(); + } + mprDestroyVar(¤t); + mprCopyVar(¤t, &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(¤t, "year", obj); + break; + case date_field_month: + mprSetVar(¤t, "month", obj); + break; + case date_field_day: + mprSetVar(¤t, "day", obj); + break; + case date_field_hour: + mprSetVar(¤t, "hour", obj); + break; + case date_field_minute: + mprSetVar(¤t, "minute", obj); + break; + case date_field_second: + mprSetVar(¤t, "second", obj); + break; + case date_field_millisecond: + mprSetVar(¤t, "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(¤t); + 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(¤t); + *err_p = err; + return mprCreateUndefinedVar(); } - mprDestroyVar(¤t); - *err_p = err; - return mprCreateUndefinedVar(); } |