📄 dom_smjs.c
字号:
/*append value*/ else { char *new_val = malloc(sizeof(char) * (strlen(ctx->headers[nb_hdr+1])+strlen(val)+3)); sprintf(new_val, "%s, %s", ctx->headers[nb_hdr+1], val); free(ctx->headers[nb_hdr+1]); ctx->headers[nb_hdr+1] = new_val; return; } nb_hdr+=2; } } nb_hdr = 0; if (ctx->headers) { while (ctx->headers[nb_hdr]) nb_hdr+=2; } ctx->headers = realloc(ctx->headers, sizeof(char*)*(nb_hdr+3)); ctx->headers[nb_hdr] = strdup(hdr); ctx->headers[nb_hdr+1] = strdup(val ? val : ""); ctx->headers[nb_hdr+2] = NULL;}static void xml_http_reset_recv_hdr(XMLHTTPContext *ctx){ u32 nb_hdr = 0; if (ctx->recv_headers) { while (ctx->recv_headers[nb_hdr]) { free(ctx->recv_headers[nb_hdr]); free(ctx->recv_headers[nb_hdr+1]); nb_hdr+=2; } free(ctx->recv_headers); ctx->recv_headers = NULL; }}static void xml_http_append_recv_header(XMLHTTPContext *ctx, char *hdr, char *val){ u32 nb_hdr = 0; if (ctx->recv_headers) { while (ctx->recv_headers[nb_hdr]) nb_hdr+=2; } ctx->recv_headers = realloc(ctx->recv_headers, sizeof(char*)*(nb_hdr+3)); ctx->recv_headers[nb_hdr] = strdup(hdr); ctx->recv_headers[nb_hdr+1] = strdup(val ? val : ""); ctx->recv_headers[nb_hdr+2] = NULL;}static void xml_http_reset(XMLHTTPContext *ctx){ u32 nb_hdr = 0; if (ctx->method) { free(ctx->method); ctx->method = NULL; } if (ctx->url) { free(ctx->url); ctx->url = NULL; } xml_http_reset_recv_hdr(ctx); if (ctx->headers) { while (ctx->headers[nb_hdr]) { free(ctx->headers[nb_hdr]); free(ctx->headers[nb_hdr+1]); nb_hdr+=2; } free(ctx->headers); ctx->headers = NULL; } if (ctx->sess) { gf_dm_sess_del(ctx->sess); ctx->sess = NULL; } if (ctx->data) { free(ctx->data); ctx->data = NULL; } if (ctx->statusText) { free(ctx->statusText); ctx->statusText = NULL; } if (ctx->url) { free(ctx->url); ctx->url = NULL; } if (ctx->sax) { gf_xml_sax_del(ctx->sax); ctx->sax = NULL; } if (ctx->node_stack) { gf_list_del(ctx->node_stack); ctx->node_stack = NULL; } if (ctx->document) { gf_node_unregister(ctx->document->RootNode, NULL); /*we're sure the graph is a "nomade" one since we initially put the refcount to 1 ourselves*/ ctx->document->reference_count--; if (!ctx->document->reference_count) { gf_sg_del(ctx->document); } } ctx->document = NULL; ctx->size = 0; ctx->async = 0; ctx->readyState = 0; ctx->cur_header = 0; ctx->ret_code = 0; ctx->html_status = 0;}static void xml_http_finalize(JSContext *c, JSObject *obj){ XMLHTTPContext *ctx; if (!JS_InstanceOf(c, obj, &dom_rt->xmlHTTPRequestClass, NULL) ) return; ctx = (XMLHTTPContext *)JS_GetPrivate(c, obj); if (ctx) { xml_http_reset(ctx); free(ctx); }}static JSBool xml_http_constructor(JSContext *c, JSObject *obj, uintN argc, jsval *argv, jsval *rval){ XMLHTTPContext *p; if (!JS_InstanceOf(c, obj, &dom_rt->xmlHTTPRequestClass, NULL) ) return JS_FALSE; GF_SAFEALLOC(p, XMLHTTPContext); p->c = c; p->_this = obj; JS_SetPrivate(c, obj, p); *rval = OBJECT_TO_JSVAL(obj); return JS_TRUE;}static void xml_http_state_change(XMLHTTPContext *ctx){ jsval rval; //GF_SceneGraph *scene = (GF_SceneGraph *) xml_get_scenegraph(ctx->c); if (ctx->onreadystatechange) JS_CallFunction(ctx->c, ctx->_this, ctx->onreadystatechange, 0, NULL, &rval); /*todo - fire event*/}static JSBool xml_http_open(JSContext *c, JSObject *obj, uintN argc, jsval *argv, jsval *rval){ char *val; GF_JSAPIParam par; XMLHTTPContext *ctx; GF_SceneGraph *scene; if (!JS_InstanceOf(c, obj, &dom_rt->xmlHTTPRequestClass, NULL) ) return JS_FALSE; ctx = (XMLHTTPContext *)JS_GetPrivate(c, obj); if (!ctx) return JS_FALSE; /*reset*/ if (ctx->readyState) xml_http_reset(ctx); if (argc<2) return JS_FALSE; /*method is a string*/ if (!JSVAL_IS_STRING(argv[0])) return JS_FALSE; /*url is a string*/ if (!JSVAL_IS_STRING(argv[1])) return JS_FALSE; xml_http_reset(ctx); val = JS_GetStringBytes(JSVAL_TO_STRING(argv[0])); if (strcmp(val, "GET") && strcmp(val, "POST") && strcmp(val, "HEAD") && strcmp(val, "PUT") && strcmp(val, "DELETE") && strcmp(val, "OPTIONS") ) return JS_FALSE; ctx->method = strdup(val); val = JS_GetStringBytes(JSVAL_TO_STRING(argv[1])); /*concatenate URL*/ scene = xml_get_scenegraph(c); ScriptAction(scene, GF_JSAPI_OP_GET_SCENE_URI, scene->RootNode, &par); if (par.uri.url) ctx->url = gf_url_concatenate(par.uri.url, val); if (!ctx->url) ctx->url = strdup(val); /*async defaults to true*/ ctx->async = 1; if (argc>2) { ctx->async = (JSVAL_TO_BOOLEAN(argv[2])==JS_TRUE) ? 1 : 0; if (argc>3) { if (!JSVAL_IS_STRING(argv[3])) return JS_FALSE; val = JS_GetStringBytes(JSVAL_TO_STRING(argv[3])); /*TODO*/ if (argc>4) { if (!JSVAL_IS_STRING(argv[3])) return JS_FALSE; val = JS_GetStringBytes(JSVAL_TO_STRING(argv[3])); /*TODO*/ } } } /*OPEN success*/ ctx->readyState = 1; xml_http_state_change(ctx); return JS_TRUE;}static JSBool xml_http_set_header(JSContext *c, JSObject *obj, uintN argc, jsval *argv, jsval *rval){ char *hdr, *val; XMLHTTPContext *ctx; if (!JS_InstanceOf(c, obj, &dom_rt->xmlHTTPRequestClass, NULL) ) return JS_FALSE; ctx = (XMLHTTPContext *)JS_GetPrivate(c, obj); if (!ctx) return JS_FALSE; if (ctx->readyState!=1) return JS_FALSE; if (argc!=2) return JS_FALSE; if (!JSVAL_IS_STRING(argv[0])) return JS_FALSE; if (!JSVAL_IS_STRING(argv[1])) return JS_FALSE; hdr = JS_GetStringBytes(JSVAL_TO_STRING(argv[0])); val = JS_GetStringBytes(JSVAL_TO_STRING(argv[1])); xml_http_append_send_header(ctx, hdr, val); return JS_TRUE;}static void xml_http_sax_start(void *sax_cbck, const char *node_name, const char *name_space, const GF_XMLAttribute *attributes, u32 nb_attributes){ u32 i; GF_DOMFullAttribute *prev = NULL; GF_DOMFullNode *par; XMLHTTPContext *ctx = (XMLHTTPContext *)sax_cbck; GF_DOMFullNode *node = (GF_DOMFullNode *) gf_node_new(ctx->document, TAG_DOMFullNode); node->name = strdup(node_name); for (i=0; i<nb_attributes; i++) { GF_DOMFullAttribute *att; GF_SAFEALLOC(att, GF_DOMFullAttribute); att->tag = TAG_DOM_ATTRIBUTE_FULL; att->name = strdup(attributes[i].name); att->data = strdup(attributes[i].value); if (prev) prev->next = (GF_DOMAttribute*)att; else node->attributes = (GF_DOMAttribute*)att; prev = att; } par = gf_list_last(ctx->node_stack); gf_node_register((GF_Node*)node, (GF_Node*)par); if (par) { gf_node_list_add_child(&par->children, (GF_Node*)node); } else { assert(!ctx->document->RootNode); ctx->document->RootNode = (GF_Node*)node; } gf_list_add(ctx->node_stack, node);}static void xml_http_sax_end(void *sax_cbck, const char *node_name, const char *name_space){ XMLHTTPContext *ctx = (XMLHTTPContext *)sax_cbck; GF_DOMFullNode *par = gf_list_last(ctx->node_stack); if (par) { /*depth mismatch*/ if (strcmp(par->name, node_name)) return; gf_list_rem_last(ctx->node_stack); }}static void xml_http_sax_text(void *sax_cbck, const char *content, Bool is_cdata){ XMLHTTPContext *ctx = (XMLHTTPContext *)sax_cbck; GF_DOMFullNode *par = gf_list_last(ctx->node_stack); if (par) { u32 i, len; GF_DOMText *txt; /*basic check, remove all empty text nodes*/ len = strlen(content); for (i=0; i<len; i++) { if (!strchr(" \n\r\t", content[i])) break; } if (i==len) return; txt = gf_dom_add_text_node((GF_Node *)par, strdup(content) ); txt->is_cdata = is_cdata; }}static void xml_http_on_data(void *usr_cbk, GF_NETIO_Parameter *parameter){ XMLHTTPContext *ctx = (XMLHTTPContext *)usr_cbk; /*if session not set, we've had an abort*/ if (!ctx->sess) return; switch (parameter->msg_type) { case GF_NETIO_SETUP: /*nothing to do*/ return; case GF_NETIO_CONNECTED: /*nothing to do*/ return; case GF_NETIO_WAIT_FOR_REPLY: /*reset send() state (data, current header) and prepare recv headers*/ if (ctx->data) free(ctx->data); ctx->data = NULL; ctx->size = 0; ctx->cur_header = 0; ctx->html_status = 0; if (ctx->statusText) { free(ctx->statusText); ctx->statusText = NULL; } xml_http_reset_recv_hdr(ctx); ctx->readyState = 2; xml_http_state_change(ctx); return; /*this is signaled sent AFTER headers*/ case GF_NETIO_PARSE_REPLY: ctx->html_status = parameter->reply; if (parameter->value) { ctx->statusText = strdup(parameter->value); } ctx->readyState = 3; xml_http_state_change(ctx); return; case GF_NETIO_GET_METHOD: parameter->name = ctx->method; return; case GF_NETIO_GET_HEADER: if (ctx->headers && ctx->headers[2*ctx->cur_header]) { parameter->name = ctx->headers[2*ctx->cur_header]; parameter->value = ctx->headers[2*ctx->cur_header+1]; ctx->cur_header++; } return; case GF_NETIO_GET_CONTENT: if (ctx->data) { parameter->data = ctx->data; parameter->size = strlen(ctx->data); } return; case GF_NETIO_PARSE_HEADER: xml_http_append_recv_header(ctx, parameter->name, parameter->value); /*prepare DOM*/ if (strcmp(parameter->name, "Content-Type")) return; if (!strcmp(parameter->value, "application/xml") || !strcmp(parameter->value, "text/xml") || strstr(parameter->value, "+xml") ) { assert(!ctx->sax); ctx->sax = gf_xml_sax_new(xml_http_sax_start, xml_http_sax_end, xml_http_sax_text, ctx); ctx->node_stack = gf_list_new(); ctx->document = gf_sg_new(); /*mark this doc as "nomade", and let it leave until all references to it are destroyed*/ ctx->document->reference_count = 1; } return; case GF_NETIO_DATA_EXCHANGE: if (parameter->data && parameter->size) { if (ctx->sax) { GF_Err e; if (!ctx->size) e = gf_xml_sax_init(ctx->sax, parameter->data); else e = gf_xml_sax_parse(ctx->sax, parameter->data); if (e) { gf_xml_sax_del(ctx->sax); ctx->sax = NULL; } } ctx->data = realloc(ctx->data, sizeof(char)*(ctx->size+parameter->size+1)); memcpy(ctx->data + ctx->size, parameter->data, sizeof(char)*parameter->size); ctx->size += parameter->size; ctx->data[ctx->size] = 0; } return; case GF_NETIO_DATA_TRANSFERED: break; case GF_NETIO_DISCONNECTED: return; case GF_NETIO_STATE_ERROR: ctx->ret_code = parameter->error; break; } /*if we get here, destroy downloader - FIXME we'll need a mutex here for sync case...*/ if (ctx->sess) { gf_dm_sess_del(ctx->sess); ctx->sess = NULL; } /*error, complete reset*/ if (parameter->error) { xml_http_reset(ctx); } /*but stay in loaded mode*/ ctx->readyState = 4; xml_http_state_change(ctx);}static JSBool xml_http_send(JSContext *c, JSObject *obj, uintN argc, jsval *argv, jsval *rval){ GF_JSAPIParam par; GF_SceneGraph *scene; char *data = NULL; XMLHTTPContext *ctx; GF_Err e; if (!JS_InstanceOf(c, obj, &dom_rt->xmlHTTPRequestClass, NULL) ) return JS_FALSE; ctx = (XMLHTTPContext *)JS_GetPrivate(c, obj); if (!ctx) return JS_FALSE; if (ctx->readyState!=1) return JS_FALSE; if (ctx->sess) return JS_FALSE; if (argc) { if (JSVAL_IS_OBJECT(argv[0])) {// if (!JS_InstanceOf(c, JSVAL_TO_OBJECT(argv[0]), &documentClass, NULL) ) return JS_FALSE; /*NOT SUPPORTED YET, we must serialize the sg*/ return JS_FALSE; } else { if (!JSVAL_IS_STRING(argv[0])) return JS_FALSE; data = JS_GetStringBytes(JSVAL_TO_STRING(argv[0])); } } scene = xml_get_scenegraph(c); par.dnld_man = NULL; ScriptAction(scene, GF_JSAPI_OP_GET_DOWNLOAD_MANAGER, NULL, &par); if (!par.dnld_man) return JS_FALSE; /*reset previous text*/ if (ctx->data) free(ctx->data); ctx->data = data ? strdup(data) : NULL; ctx->sess = gf_dm_sess_new(par.dnld_man, ctx->url, GF_NETIO_SESSION_NOT_CACHED, xml_http_on_data, ctx, &e); if (!ctx->sess) return JS_FALSE; /*just wait for destruction*/ if (!ctx->async) { while (ctx->sess) { gf_sleep(20); } } return JS_TRUE;}static JSBool xml_http_abort(JSContext *c, JSObject *obj, uintN argc, jsval *argv, jsval *rval){ GF_DownloadSession *sess; XMLHTTPContext *ctx; if (!JS_InstanceOf(c, obj, &dom_rt->xmlHTTPRequestClass, NULL) ) return JS_FALSE; ctx = (XMLHTTPContext *)JS_GetP
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -