static JSBool url_get_coord(JSContext *cx, JSURL *url, jsint slot, jsval *vp) { int32 coord; LO_AnchorData *anchor_data; MWContext *context; LO_LockLayout(); context = url->url_decoder->window_context; anchor_data = LO_GetLinkByIndex(context, url->layer_id, url->index); if (anchor_data && anchor_data->element) { switch (slot) { case URL_X: coord = anchor_data->element->lo_any.x; break; case URL_Y: coord = anchor_data->element->lo_any.y; break; default: LO_UnlockLayout(); return JS_FALSE; } *vp = INT_TO_JSVAL(coord); LO_UnlockLayout(); return JS_TRUE; } *vp = JSVAL_NULL; LO_UnlockLayout(); return JS_TRUE; }
anchor_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp) { JSAnchor *named_anchor; lo_NameList *name_rec; jsint slot; if (!JSVAL_IS_INT(id)) return JS_TRUE; slot = JSVAL_TO_INT(id); named_anchor = JS_GetInstancePrivate(cx, obj, &lm_anchor_class, NULL); if (!named_anchor) return JS_TRUE; LO_LockLayout(); name_rec = LO_GetNamedAnchorByIndex(named_anchor->decoder->window_context, named_anchor->layer_id, named_anchor->index); if (!name_rec) { LO_UnlockLayout(); return JS_TRUE; /* Try to handle this case gracefully. */ } switch (slot) { case ANCHOR_TEXT: if (named_anchor->text) *vp = STRING_TO_JSVAL(named_anchor->text); else *vp = JSVAL_NULL; break; case ANCHOR_NAME: if (named_anchor->name) *vp = STRING_TO_JSVAL(named_anchor->name); else *vp = JSVAL_NULL; break; case ANCHOR_X: *vp = INT_TO_JSVAL(name_rec->element->lo_any.x); break; case ANCHOR_Y: *vp = INT_TO_JSVAL(name_rec->element->lo_any.y); break; default: /* Don't mess with a user-defined or method property. */ break; } LO_UnlockLayout(); return JS_TRUE; }
link_array_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp) { JSObjectArray *array; MochaDecoder *decoder; MWContext *context; jsint count, slot; LO_AnchorData *anchor_data; int32 active_layer_id; if (!JSVAL_IS_INT(id)) return JS_TRUE; slot = JSVAL_TO_INT(id); array = JS_GetInstancePrivate(cx, obj, &lm_link_array_class, NULL); if (!array) return JS_TRUE; decoder = array->decoder; context = decoder->window_context; if (!context) return JS_TRUE; LO_LockLayout(); switch (slot) { case ANCHOR_ARRAY_LENGTH: active_layer_id = LM_GetActiveLayer(context); LM_SetActiveLayer(context, array->layer_id); count = LO_EnumerateLinks(context, array->layer_id); LM_SetActiveLayer(context, active_layer_id); if (count > array->length) array->length = count; *vp = INT_TO_JSVAL(count); break; default: if (slot < 0) { /* Don't mess with user-defined or method properties. */ LO_UnlockLayout(); return JS_TRUE; } if (slot >= array->length) array->length = slot + 1; anchor_data = LO_GetLinkByIndex(context, array->layer_id, (uint)slot); if (anchor_data) { *vp = OBJECT_TO_JSVAL(LM_ReflectLink(context, anchor_data, NULL, array->layer_id, (uint)slot)); } break; } LO_UnlockLayout(); return JS_TRUE; }
url_finalize(JSContext *cx, JSObject *obj) { JSURL *url; MochaDecoder *decoder; MWContext *context; LO_AnchorData *anchor_data; url = JS_GetPrivate(cx, obj); if (!url) return; decoder = url->url_decoder; if (url->index != URL_NOT_INDEXED) { context = decoder->window_context; if (context) { LO_LockLayout(); anchor_data = LO_GetLinkByIndex(context, url->layer_id, url->index); if (anchor_data && anchor_data->mocha_object == obj) anchor_data->mocha_object = NULL; LO_UnlockLayout(); } } DROP_BACK_COUNT(decoder); JS_RemoveRoot(cx, &url->href); JS_RemoveRoot(cx, &url->target); JS_RemoveRoot(cx, &url->text); XP_DELETE(url); }
anchor_finalize(JSContext *cx, JSObject *obj) { JSAnchor *named_anchor; MochaDecoder *decoder; MWContext *context; lo_NameList *name_rec; named_anchor = JS_GetPrivate(cx, obj); if (!named_anchor) return; decoder = named_anchor->decoder; context = decoder->window_context; if (context) { LO_LockLayout(); name_rec = LO_GetNamedAnchorByIndex(context, named_anchor->layer_id, named_anchor->index); if (name_rec && name_rec->mocha_object == obj) name_rec->mocha_object = NULL; LO_UnlockLayout(); } DROP_BACK_COUNT(decoder); JS_UnlockGCThing(cx, named_anchor->text); JS_UnlockGCThing(cx, named_anchor->name); JS_free(cx, named_anchor); }
anchor_array_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp) { JSObjectArray *array; MochaDecoder *decoder; MWContext *context; jsint count, slot; lo_NameList *name_rec; int32 active_layer_id; if (!JSVAL_IS_INT(id)) return JS_TRUE; slot = JSVAL_TO_INT(id); array = JS_GetInstancePrivate(cx, obj, &lm_anchor_array_class, NULL); if (!array) return JS_TRUE; decoder = array->decoder; context = decoder->window_context; if (!context) return JS_TRUE; LO_LockLayout(); switch (slot) { case ANCHOR_ARRAY_LENGTH: active_layer_id = LM_GetActiveLayer(context); LM_SetActiveLayer(context, array->layer_id); count = LO_EnumerateNamedAnchors(context, array->layer_id); LM_SetActiveLayer(context, active_layer_id); if (count > array->length) array->length = count; *vp = INT_TO_JSVAL(count); break; default: if (slot >= array->length) array->length = slot + 1; name_rec = LO_GetNamedAnchorByIndex(context, array->layer_id, (uint)slot); if (name_rec) { *vp = OBJECT_TO_JSVAL(LM_ReflectNamedAnchor(context, name_rec, NULL, array->layer_id, (uint)slot)); } break; } LO_UnlockLayout(); return JS_TRUE; }
const char * lm_CheckURL(JSContext *cx, const char *url_string, JSBool checkFile) { char *protocol, *absolute; JSObject *obj; MochaDecoder *decoder; protocol = NET_ParseURL(url_string, GET_PROTOCOL_PART); if (!protocol || *protocol == '\0') { lo_TopState *top_state; obj = JS_GetGlobalObject(cx); decoder = JS_GetPrivate(cx, obj); LO_LockLayout(); top_state = lo_GetMochaTopState(decoder->window_context); if (top_state && top_state->base_url) { absolute = NET_MakeAbsoluteURL(top_state->base_url, (char *)url_string); /*XXX*/ /* * Temporarily unlock layout so that we don't hold the lock * across a call (lm_CheckPermissions) that may result in * synchronous event handling. */ LO_UnlockLayout(); if (!lm_CheckPermissions(cx, obj, JSTARGET_UNIVERSAL_BROWSER_READ)) { /* Don't leak information about the url of this page. */ XP_FREEIF(absolute); return NULL; } LO_LockLayout(); } else { absolute = NULL; } if (absolute) { if (protocol) XP_FREE(protocol); protocol = NET_ParseURL(absolute, GET_PROTOCOL_PART); } LO_UnlockLayout(); } else { absolute = JS_strdup(cx, url_string); if (!absolute) { XP_FREE(protocol); return NULL; } decoder = NULL; } if (absolute) { /* Make sure it's a safe URL type. */ switch (NET_URL_Type(protocol)) { case FILE_TYPE_URL: if (checkFile) { const char *subjectOrigin = lm_GetSubjectOriginURL(cx); if (subjectOrigin == NULL) { XP_FREE(protocol); return NULL; } if (NET_URL_Type(subjectOrigin) != FILE_TYPE_URL && !lm_CanAccessTarget(cx, JSTARGET_UNIVERSAL_FILE_READ)) { XP_FREE(absolute); absolute = NULL; } } break; case FTP_TYPE_URL: case GOPHER_TYPE_URL: case HTTP_TYPE_URL: case MAILTO_TYPE_URL: case NEWS_TYPE_URL: case RLOGIN_TYPE_URL: case TELNET_TYPE_URL: case TN3270_TYPE_URL: case WAIS_TYPE_URL: case SECURE_HTTP_TYPE_URL: case URN_TYPE_URL: case NFS_TYPE_URL: case MOCHA_TYPE_URL: case VIEW_SOURCE_TYPE_URL: case NETHELP_TYPE_URL: case WYSIWYG_TYPE_URL: case LDAP_TYPE_URL: #ifdef JAVA case MARIMBA_TYPE_URL: #endif /* These are "safe". */ break; case ABOUT_TYPE_URL: if (XP_STRCASECMP(absolute, "about:blank") == 0) break; if (XP_STRNCASECMP(absolute, "about:pics", 10) == 0) break; /* these are OK if we are signed */ if (lm_CanAccessTarget(cx, JSTARGET_UNIVERSAL_BROWSER_READ)) break; /* FALL THROUGH */ default: /* All others are naughty. */ XP_FREE(absolute); absolute = NULL; break; } } if (!absolute) { JS_ReportError(cx, "illegal URL method '%s'", protocol && *protocol ? protocol : url_string); } if (protocol) XP_FREE(protocol); return absolute; }
embed_array_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp) { JSObjectArray *array; MochaDecoder *decoder; MWContext *context; jsint count, slot; LO_EmbedStruct *embed_data; int32 active_layer_id; if (!JSVAL_IS_INT(id)) return JS_TRUE; slot = JSVAL_TO_INT(id); array = JS_GetInstancePrivate(cx, obj, &lm_embed_array_class, NULL); if (!array) return JS_TRUE; decoder = array->decoder; context = decoder->window_context; if (!context) return JS_TRUE; if (LM_MOJA_OK != ET_InitMoja(context)) return JS_FALSE; LO_LockLayout(); switch (slot) { case EMBED_ARRAY_LENGTH: active_layer_id = LM_GetActiveLayer(context); LM_SetActiveLayer(context, array->layer_id); count = LO_EnumerateEmbeds(context, array->layer_id); LM_SetActiveLayer(context, active_layer_id); if (count > array->length) array->length = count; *vp = INT_TO_JSVAL(array->length); break; default: if (slot < 0) { /* Don't mess with user-defined or method properties. */ LO_UnlockLayout(); return JS_TRUE; } embed_data = LO_GetEmbedByIndex(context, array->layer_id, (uint)slot); if (embed_data) { JSObject *mo = LM_ReflectEmbed(context, embed_data, NULL, array->layer_id, (uint)slot); if (!mo) { JS_ReportError(cx, "unable to reflect embed with index %d - not loaded yet?", (uint) slot); goto err; } *vp = OBJECT_TO_JSVAL(mo); XP_ASSERT(slot < array->length); } else { JS_ReportError(cx, "no embed with index %d\n"); goto err; } break; } LO_UnlockLayout(); return JS_TRUE; err: LO_UnlockLayout(); return JS_FALSE; }
JSObject * LM_ReflectNamedAnchor(MWContext *context, lo_NameList *name_rec, PA_Tag * tag, int32 layer_id, uint index) { JSObject *obj, *array_obj, *document; MochaDecoder *decoder; JSContext *cx; JSObjectArray *array; JSAnchor *named_anchor; lo_TopState *top_state; PRHashTable *map; JSString *str; obj = name_rec->mocha_object; if (obj) return obj; decoder = LM_GetMochaDecoder(context); if (!decoder) return NULL; cx = decoder->js_context; top_state = lo_GetMochaTopState(context); if (top_state->resize_reload) { map = lm_GetIdToObjectMap(decoder); if (map) obj = (JSObject *)PR_HashTableLookup(map, LM_GET_MAPPING_KEY(LM_NAMEDANCHORS, layer_id, index)); if (obj) { name_rec->mocha_object = obj; LM_PutMochaDecoder(decoder); return obj; } } /* Get the document object that will hold this anchor */ document = lm_GetDocumentFromLayerId(decoder, layer_id); if (!document) { LM_PutMochaDecoder(decoder); return NULL; } array_obj = lm_GetNameArray(decoder, document); if (!array_obj) { LM_PutMochaDecoder(decoder); return NULL; } array = JS_GetPrivate(cx, array_obj); if (!array) { LM_PutMochaDecoder(decoder); return NULL; } named_anchor = JS_malloc(cx, sizeof *named_anchor); if (!named_anchor) { LM_PutMochaDecoder(decoder); return NULL; } XP_BZERO(named_anchor, sizeof *named_anchor); obj = JS_NewObject(cx, &lm_anchor_class, decoder->anchor_prototype, document); if (!obj || !JS_SetPrivate(cx, obj, named_anchor)) { JS_free(cx, named_anchor); LM_PutMochaDecoder(decoder); return NULL; } /* Put obj into the document.anchors array. */ JS_DefineProperty(cx, array_obj, (char *) name_rec->name, OBJECT_TO_JSVAL(obj), NULL, NULL, JSPROP_ENUMERATE|JSPROP_READONLY); JS_AliasElement(cx, array_obj, (char *) name_rec->name, index); /* Put it in the index to object hash table */ map = lm_GetIdToObjectMap(decoder); if (map) { PR_HashTableAdd(map, LM_GET_MAPPING_KEY(LM_NAMEDANCHORS, layer_id, index), obj); } if ((jsint) index >= array->length) array->length = index + 1; named_anchor->decoder = HOLD_BACK_COUNT(decoder); named_anchor->layer_id = layer_id; named_anchor->index = index; if (name_rec->element && name_rec->element->type == LO_TEXT) { str = lm_LocalEncodingToStr(context, (char *) name_rec->element->lo_text.text); if (!str || !JS_LockGCThing(cx, str)) { LM_PutMochaDecoder(decoder); return NULL; } named_anchor->text = str; } str = JS_NewStringCopyZ(cx, (char *) name_rec->name); if (!str || !JS_LockGCThing(cx, str)) { LM_PutMochaDecoder(decoder); return NULL; } named_anchor->name = str; name_rec->mocha_object = obj; /* see if there are any attributes for event handlers */ if(tag) { PA_Block onlocate, id; /* don't hold the layout lock across compiles */ LO_UnlockLayout(); onlocate = lo_FetchParamValue(context, tag, PARAM_ONLOCATE); id = lo_FetchParamValue(context, tag, PARAM_ID); if (onlocate) { (void) lm_CompileEventHandler(decoder, id, tag->data, tag->newline_count, obj, PARAM_ONLOCATE, onlocate); PA_FREE(onlocate); } if (id) PA_FREE(id); LO_LockLayout(); } LM_PutMochaDecoder(decoder); return obj; }
JSObject * LM_ReflectLink(MWContext *context, LO_AnchorData *anchor_data, PA_Tag * tag, int32 layer_id, uint index) { JSObject *obj, *array_obj, *document; MochaDecoder *decoder; JSContext *cx; JSURL *url; lo_TopState *top_state; PRHashTable *map; anchor_data = LO_GetLinkByIndex(context, layer_id, index); if (!anchor_data) return NULL; obj = anchor_data->mocha_object; if (obj) return obj; decoder = LM_GetMochaDecoder(context); if (!decoder) return NULL; cx = decoder->js_context; top_state = lo_GetMochaTopState(context); if (top_state->resize_reload) { map = lm_GetIdToObjectMap(decoder); if (map) obj = (JSObject *)PR_HashTableLookup(map, LM_GET_MAPPING_KEY(LM_LINKS, layer_id, index)); if (obj) { anchor_data->mocha_object = obj; LM_PutMochaDecoder(decoder); return obj; } } /* Get the document object that will hold this link */ document = lm_GetDocumentFromLayerId(decoder, layer_id); if (!document) { LM_PutMochaDecoder(decoder); return NULL; } array_obj = lm_GetLinkArray(decoder, document); if (!array_obj) { LM_PutMochaDecoder(decoder); return NULL; } url = lm_NewURL(cx, decoder, anchor_data, document); if (!url) { LM_PutMochaDecoder(decoder); return NULL; } url->index = index; url->layer_id = layer_id; obj = url->url_object; /* XXX should find a name/id to pass in */ /* put it in the links array */ if (!lm_AddObjectToArray(cx, array_obj, NULL, index, obj)) { LM_PutMochaDecoder(decoder); return NULL; } /* Put it in the index to object hash table */ map = lm_GetIdToObjectMap(decoder); if (map) PR_HashTableAdd(map, LM_GET_MAPPING_KEY(LM_LINKS, layer_id, index), obj); anchor_data->mocha_object = obj; LM_PutMochaDecoder(decoder); /* see if there are any event handlers we need to reflect */ if(tag) { PA_Block onclick, onmouseover, onmouseout, onmousedown, onmouseup, ondblclick, id; /* don't hold the layout lock across compiles */ LO_UnlockLayout(); onclick = lo_FetchParamValue(context, tag, PARAM_ONCLICK); onmouseover = lo_FetchParamValue(context, tag, PARAM_ONMOUSEOVER); onmouseout = lo_FetchParamValue(context, tag, PARAM_ONMOUSEOUT); onmousedown = lo_FetchParamValue(context, tag, PARAM_ONMOUSEDOWN); onmouseup = lo_FetchParamValue(context, tag, PARAM_ONMOUSEUP); ondblclick = lo_FetchParamValue(context, tag, PARAM_ONDBLCLICK); id = lo_FetchParamValue(context, tag, PARAM_ID); if (onclick) { (void) lm_CompileEventHandler(decoder, id, tag->data, tag->newline_count, url->url_object, PARAM_ONCLICK, onclick); PA_FREE(onclick); anchor_data->event_handler_present = TRUE; } if (onmouseover) { (void) lm_CompileEventHandler(decoder, id, tag->data, tag->newline_count, url->url_object, PARAM_ONMOUSEOVER, onmouseover); PA_FREE(onmouseover); anchor_data->event_handler_present = TRUE; } if (onmouseout) { (void) lm_CompileEventHandler(decoder, id, tag->data, tag->newline_count, url->url_object, PARAM_ONMOUSEOUT, onmouseout); PA_FREE(onmouseout); anchor_data->event_handler_present = TRUE; } if (onmousedown) { (void) lm_CompileEventHandler(decoder, id, tag->data, tag->newline_count, url->url_object, PARAM_ONMOUSEDOWN, onmousedown); PA_FREE(onmousedown); anchor_data->event_handler_present = TRUE; } if (onmouseup) { (void) lm_CompileEventHandler(decoder, id, tag->data, tag->newline_count, url->url_object, PARAM_ONMOUSEUP, onmouseup); PA_FREE(onmouseup); anchor_data->event_handler_present = TRUE; } if (ondblclick) { (void) lm_CompileEventHandler(decoder, id, tag->data, tag->newline_count, url->url_object, PARAM_ONDBLCLICK, ondblclick); PA_FREE(ondblclick); anchor_data->event_handler_present = TRUE; } if (id) PA_FREE(id); LO_LockLayout(); } return obj; }