static OP_STATUS XMLWriteToFileEscaped (OpFile &file, const uni_char *string) { if (*string) { TempBuffer buffer; while (*string) { if (*string == '&') RETURN_IF_ERROR (buffer.Append ("&")); else if (*string == '<') RETURN_IF_ERROR (buffer.Append ("<")); else if (*string == '\'') RETURN_IF_ERROR (buffer.Append ("")); else RETURN_IF_ERROR (buffer.Append (*string)); ++string; } return XMLWriteToFile (file, buffer.GetStorage ()); } else return OpStatus::OK; }
double XPath_ConversionExpressionHelper::GetNumberL (XPath_Context *context, BOOL initial) { OP_ASSERT (!numberexpression); StartL (context, initial); TempBuffer buffer; ANCHOR (TempBuffer, buffer); if (GetStringValueL (context, initial, buffer)) return XPath_Value::AsNumber (buffer.GetStorage ()); else if (booleanexpression) return booleanexpression->EvaluateToBooleanL (context, initial) ? 1. : 0.; else if (stringexpression) return XPath_Value::AsNumber (stringexpression->EvaluateToStringL (context, initial, buffer)); #ifdef XPATH_EXTENSION_SUPPORT OP_ASSERT (unknown); XPath_Value *value = unknown->EvaluateL (context, initial); double number = value->AsNumberL (); XPath_Value::DecRef (context, value); return number; #else // XPATH_EXTENSION_SUPPORT OP_ASSERT (FALSE); return op_nan (0); #endif // XPATH_EXTENSION_SUPPORT }
/* static */ OP_STATUS DOM_LSInput::GetStringData(const uni_char *&stringData, ES_Object *input, DOM_EnvironmentImpl *environment) { DOM_Runtime *runtime = environment->GetDOMRuntime(); OP_BOOLEAN result; ES_Value value; stringData = NULL; RETURN_IF_ERROR(result = runtime->GetName(input, UNI_L("characterStream"), &value)); if (result == OpBoolean::IS_TRUE && value.type != VALUE_NULL && value.type != VALUE_UNDEFINED && !(value.type == VALUE_STRING && *value.value.string)) return OpStatus::OK; RETURN_IF_ERROR(result = runtime->GetName(input, UNI_L("byteStream"), &value)); if (result == OpBoolean::IS_TRUE && value.type != VALUE_NULL && value.type != VALUE_UNDEFINED && !(value.type == VALUE_STRING && *value.value.string)) return OpStatus::OK; RETURN_IF_ERROR(result = runtime->GetName(input, UNI_L("stringData"), &value)); if (result == OpBoolean::IS_TRUE && value.type == VALUE_STRING && *value.value.string) { TempBuffer *buffer = environment->GetWindow()->GetEmptyTempBuf(); RETURN_IF_ERROR(buffer->Append(value.value.string)); stringData = buffer->GetStorage(); } return OpStatus::OK; }
/* static */ double XPath_Value::AsNumberL (const uni_char *string, unsigned string_length) { TempBuffer buffer; ANCHOR (TempBuffer, buffer); buffer.AppendL (string, string_length); uni_char *endptr; return uni_strtod (buffer.GetStorage (), &endptr); }
XMLTreeAccessor::Node * XPath_Node::GetTreeNodeByIdL (const uni_char *id, unsigned id_length) { TempBuffer buffer; ANCHOR (TempBuffer, buffer); buffer.AppendL (id, id_length); XMLTreeAccessor::Node *node; LEAVE_IF_ERROR (tree->GetElementById (node, buffer.GetStorage ())); return node; }
OP_STATUS DOM_CSSStyleDeclaration::MutationState::AfterChange() { if (send_attrmodified) { TempBuffer newBuffer; StyleAttribute* styleattr = element->GetThisElement()->GetStyleAttribute(); if (styleattr) OpStatus::Ignore(styleattr->ToString(&newBuffer)); const uni_char *prevValue = prevBuffer.GetStorage(), *newValue = newBuffer.GetStorage(); if (!(prevValue == newValue || prevValue && newValue && uni_strcmp(prevValue, newValue) == 0)) { DOM_Attr* attr; PUT_FAILED_IF_ERROR(element->GetAttributeNode(attr, ATTR_XML, UNI_L("style"), NS_IDX_DEFAULT, TRUE, TRUE, TRUE)); if (attr) PUT_FAILED_IF_ERROR(element->SendAttrModified(DOM_Object::GetCurrentThread(origining_runtime), attr, prevValue, newValue)); } } return OpStatus::OK; }
/* static */ BOOL ES_DebugBuiltins::getObjectDemographics(ES_Execution_Context *context, unsigned argc, ES_Value_Internal *argv, ES_Value_Internal *return_value) { return_value->SetNull(); if (argc == 1) { if (!argv[0].ToNumber(context) || !argv[0].IsUInt32()) return FALSE; if (ES_Heap *heap = g_ecmaManager->GetHeapById(argv[0].GetNumAsUInt32())) { TempBuffer *buffer = g_ecmaManager->GetHeapDebuggerBuffer(); buffer->Clear(); buffer->Append("{ "); unsigned *live_objects = heap->live_objects; for (unsigned index = 0; index < GCTAG_UNINITIALIZED; ++index) { if (index != 0) buffer->Append(", "); buffer->Append("\""); buffer->Append(g_ecmaClassName[index]); buffer->Append("\": "); buffer->AppendUnsignedLong(live_objects[index]); } buffer->Append(" }"); return_value->SetString(JString::Make(context, buffer->GetStorage(), buffer->Length())); } } return TRUE; }
/* static */ OP_STATUS DOM_LSInput::GetSystemId(const uni_char *&systemId, ES_Object *input, DOM_EnvironmentImpl *environment) { OP_BOOLEAN result; ES_Value value; systemId = NULL; const uni_char *stringData; RETURN_IF_ERROR(GetStringData(stringData, input, environment)); if (stringData) return OpStatus::OK; RETURN_IF_ERROR(result = environment->GetDOMRuntime()->GetName(input, UNI_L("systemId"), &value)); if (result == OpBoolean::IS_TRUE && value.type == VALUE_STRING && *value.value.string) { TempBuffer *buffer = environment->GetWindow()->GetEmptyTempBuf(); RETURN_IF_ERROR(buffer->Append(value.value.string)); systemId = buffer->GetStorage(); } return OpStatus::OK; }
/* static */ OP_STATUS JS_Console::FormatString(ES_Value* argv, int argc, OpString &str) { if (argc == 0) return OpStatus::OK; // Holds the formatted string. TempBuffer buf; // The argument which will be stringified next. int argument = 0; // If the first argument is a string, check if it contains placeholders. if (argv[0].type == VALUE_STRING) { // The first argument is the format string. It may or may not contain // formatting placeholders (%). const uni_char *placeholder = argv[0].value.string; const uni_char *stored = placeholder; // Skip the formatting string. ++argument; while ((placeholder = uni_strchr(placeholder, '%')) != NULL) { // Calculate the length until the '%'. int length = (placeholder - stored); // Skip the '%', and check that 'placeholder' now points to // a supported character. if (!JS_Console::IsSupportedPlaceholder(++placeholder)) continue; // Append everything up until the '%'. if (length > 0) RETURN_IF_ERROR(buf.Append(stored, length)); // If the character after the first '%' is another '%', then output // a single '%'. if (*placeholder == '%') RETURN_IF_ERROR(buf.Append("%")); // Otherwise, append the string representation of the ES_Value. else if (argument < argc) RETURN_IF_ERROR(JS_Console::AppendValue(argv[argument++], buf)); // Or, if we don't have more arguments, output the original placeholder. else RETURN_IF_ERROR(buf.Append(placeholder - 1, 2)); // Skip the character following the %, but only if not at the // end of string. if (*placeholder != '\0') ++placeholder; stored = placeholder; } // Append the rest of the formatting string, if any. if (*stored != '\0') RETURN_IF_ERROR(buf.Append(stored)); } // If we have more arguments, append them in a space delimited list. while (argument < argc) { // Never start a string with a space. if (argument > 0) RETURN_IF_ERROR(buf.Append(" ")); RETURN_IF_ERROR(AppendValue(argv[argument++], buf)); } return str.Set(buf.GetStorage()); }
/* static */ BOOL ES_DebugBuiltins::getHeapInformation(ES_Execution_Context *context, unsigned argc, ES_Value_Internal *argv, ES_Value_Internal *return_value) { Head *active, *inactive, *destroy; g_ecmaManager->GetHeapLists(active, inactive, destroy); TempBuffer *buffer = g_ecmaManager->GetHeapDebuggerBuffer(); buffer->Clear(); buffer->Append("{ \"heaps\": { "); ES_Heap *heads[3] = { static_cast<ES_Heap *>(active->First()), static_cast<ES_Heap *>(inactive->First()), static_cast<ES_Heap *>(destroy->First()) }; for (unsigned head = 0; head < 3; ++head) for (ES_Heap *heap = heads[head]; heap; heap = static_cast<ES_Heap *>(heap->Suc())) { buffer->AppendFormat(UNI_L("\"%u\": { \"bytesLive\": %u, \"bytesLivePeak\": %u, \"bytesLimit\": %u, \"runtimes\": ["), heap->Id(), heap->GetBytesLive(), heap->GetBytesLivePeak(), heap->GetBytesLimit()); ES_Runtime *runtime = heap->GetFirstRuntime(); while (runtime) { #ifndef _STANDALONE ES_Object *global_object = runtime->GetGlobalObject(); if (global_object->IsHostObject() && ES_Runtime::GetHostObject(global_object)->IsA(DOM_TYPE_WINDOW)) { OpString url; DOM_Utils::GetOriginURL(DOM_Utils::GetDOM_Runtime(runtime)).GetAttribute(URL::KUniName, url); for (unsigned index = 0; index < static_cast<unsigned>(url.Length()); ++index) if (url.CStr()[index] == '"') url.Insert(index++, "\\"); buffer->AppendFormat(UNI_L("\"%s\""), url.CStr()); } else #endif // _STANDALONE buffer->Append("\"<unidentified runtime>\""); runtime = g_ecmaManager->GetNextRuntimePerHeap(runtime); if (runtime) buffer->Append(", "); } buffer->Append("] }, "); } buffer->AppendFormat(UNI_L("\"count\": %u }, \"allocators\": ["), active->Cardinal() + inactive->Cardinal() + destroy->Cardinal()); for (ES_PageAllocator *allocator = static_cast<ES_PageAllocator *>(g_ecmaPageAllocatorList->First()); allocator; allocator = static_cast<ES_PageAllocator *>(allocator->Suc())) { buffer->AppendFormat(UNI_L("{ \"chunks\": %u, \"chunkSize\": %u, \"pages\": %u, \"pageSize\": %u, \"heaps\": ["), allocator->CountChunks(), allocator->ChunkSize(), allocator->CountPages(), allocator->PageSize()); for (ES_HeapHandle *heaph = allocator->GetFirstHeapHandle(); heaph; heaph = static_cast<ES_HeapHandle *>(heaph->Suc())) { buffer->AppendUnsignedLong(heaph->heap->Id()); if (heaph->Suc()) buffer->Append(", "); } buffer->Append("] }"); if (allocator->Suc()) buffer->Append(", "); } buffer->Append("], \"cachedPrograms\": ["); for (Link *link = RT_DATA.program_cache->GetCachedPrograms()->First(); link; link = link->Suc()) { ES_ProgramCodeStatic *program = static_cast<ES_ProgramCodeStatic *>(link); buffer->AppendFormat(UNI_L("{ \"url\": \"\", \"length\": %u }"), program->source.GetSource()->length); if (link->Suc()) buffer->Append(", "); } buffer->Append("] }"); return_value->SetString(JString::Make(context, buffer->GetStorage(), buffer->Length())); return TRUE; }
void XPath_Node::GetStringValueL (TempBuffer &value) { XMLTreeAccessor::Node *iter = treenode, *first = 0; const uni_char *data = 0; BOOL id, specified; switch (type) { case XP_NODE_ROOT: case XP_NODE_ELEMENT: LEAVE_IF_ERROR (tree->GetCharacterDataContent (data, treenode, &value)); break; case XP_NODE_TEXT: while (XPath_Utils::GetNodeType (tree, iter) == XP_NODE_TEXT) { first = iter; if (XMLTreeAccessor::Node *previous = tree->GetPreviousSibling (iter)) iter = previous; else break; } while (first && XPath_Utils::GetNodeType (tree, first) == XP_NODE_TEXT) { LEAVE_IF_ERROR (tree->GetData (data, first, &value)); if (data != value.GetStorage ()) /* Tree accessor returned text without generating into 'value' as an optimization. But we really want it in 'value'. */ value.AppendL (data); first = tree->GetNextSibling (first); } return; case XP_NODE_ATTRIBUTE: LEAVE_IF_ERROR (tree->GetAttribute (tree->GetAttributes (treenode, FALSE, TRUE), name, data, id, specified, &value)); break; case XP_NODE_NAMESPACE: { const uni_char *uri = name.GetUri (); if (uri) value.AppendL (uri); return; } case XP_NODE_PI: case XP_NODE_COMMENT: LEAVE_IF_ERROR (tree->GetData (data, iter, &value)); break; } /* Common case for XP_NODE_ROOT, XP_NODE_ELEMENT, XP_NODE_ATTRIBUTE, XP_NODE_PI and XP_NODE_COMMENT: check if the tree accessor generated the returned string into the buffer or if it returned a pointer to a string owned by the tree accessor. */ if (data != value.GetStorage ()) value.AppendL (data); }
void SetDataFromItemData(const BookmarkItemData* item_data, BookmarkItem* bookmark) { if (!bookmark || !item_data) return; // these 2 attributes must exist, as they have a different default value with others. (-1) ::SetAttribute(bookmark, BOOKMARK_PERSONALBAR_POS, -1); ::SetAttribute(bookmark, BOOKMARK_PANEL_POS, -1); ::SetAttribute(bookmark, BOOKMARK_URL, item_data->url); ::SetAttribute(bookmark, BOOKMARK_TITLE, item_data->name); ::SetAttribute(bookmark, BOOKMARK_DESCRIPTION, item_data->description); ::SetAttribute(bookmark, BOOKMARK_SHORTNAME, item_data->shortname); ::SetAttribute(bookmark, BOOKMARK_CREATED, item_data->created); ::SetAttribute(bookmark, BOOKMARK_VISITED, item_data->visited); ::SetAttribute(bookmark, BOOKMARK_TARGET, item_data->target); ::SetAttribute(bookmark, BOOKMARK_PERSONALBAR_POS,item_data->personalbar_position); ::SetAttribute(bookmark, BOOKMARK_PANEL_POS, item_data->panel_position); ::SetAttribute(bookmark, BOOKMARK_ACTIVE, item_data->active); ::SetAttribute(bookmark, BOOKMARK_EXPANDED, item_data->expanded); ::SetAttribute(bookmark, BOOKMARK_SMALLSCREEN, item_data->small_screen); ::SetAttribute(bookmark, BOOKMARK_SHOW_IN_PERSONAL_BAR,item_data->personalbar_position >= 0); ::SetAttribute(bookmark, BOOKMARK_SHOW_IN_PANEL,item_data->panel_position >= 0); ::SetAttribute(bookmark, BOOKMARK_PARTNER_ID, item_data->partner_id); ::SetAttribute(bookmark, BOOKMARK_DISPLAY_URL, item_data->display_url); // icon Image icon = g_favicon_manager->Get(item_data->url); OpString16 base64; OpBitmap *bitmap = icon.GetBitmap(NULL); if (bitmap) { TempBuffer buffer; if(OpStatus::IsSuccess(GetOpBitmapAsBase64PNG(bitmap, &buffer))) { if(OpStatus::IsSuccess(base64.Set(buffer.GetStorage(), buffer.Length()))) { ::SetAttribute(bookmark, BOOKMARK_FAVICON_FILE, base64); } } icon.ReleaseBitmap(); } if (item_data->unique_id.HasContent()) { OpString tmp; tmp.Set(item_data->unique_id); uni_char* uni_unique_id = OP_NEWA(uni_char, (tmp.Length()+1)); if (uni_unique_id) { uni_strcpy(uni_unique_id, tmp.CStr()); bookmark->SetUniqueId(uni_unique_id); } } bookmark->SetMaxCount(item_data->max_count); bookmark->SetMoveIsCopy(item_data->move_is_copy); bookmark->SetSubFoldersAllowed(item_data->subfolders_allowed); bookmark->SetSeparatorsAllowed(item_data->separators_allowed); bookmark->SetDeletable(item_data->deletable); bookmark->SetFolderType(item_data->type); }
/* static */ const uni_char * XPath_Value::AsStringL (double number, TempBuffer &buffer) { char *storage8; buffer.ExpandL (33); buffer.SetCachedLengthPolicy (TempBuffer::UNTRUSTED); storage8 = reinterpret_cast<char *> (buffer.GetStorage ()); if (op_isnan (number)) return UNI_L ("NaN"); else if (number == 0) return UNI_L ("0"); else { if (!OpDoubleFormat::ToString (storage8, number)) LEAVE (OpStatus::ERR_NO_MEMORY); char *e = 0, *p = 0; for (unsigned index = 0; storage8[index]; ++index) if (storage8[index] == '.') p = &storage8[index]; else if (storage8[index] == 'e' || storage8[index] == 'E') e = &storage8[index]; if (e) { TempBuffer b; ANCHOR (TempBuffer, b); if (number < 0) b.AppendL ("-"); int exp = op_atoi (e + 1), index; *e = 0; if (exp > 0) { if (storage8[0] != '0') b.AppendL (storage8[0]); if (p) { b.AppendL (p + 1, MIN (e - (p + 1), exp)); if (exp < e - (p + 1)) { b.AppendL ("."); b.AppendL (p + 1 + exp, e - (p + 1 + exp)); } else if (e - (p + 1) < exp) for (index = exp; index < e - (p + 1); ++index) b.AppendL ("0"); } else for (index = 0; index < exp; ++index) b.AppendL ("0"); } else if (exp < 0) { b.AppendL ("0."); for (index = 1; index < -exp; ++index) b.AppendL ("0"); for (index = 0; storage8[index]; ++index) if (op_isdigit (storage8[index]) && storage8[index] != '0') break; for (; storage8[index]; ++index) if (op_isdigit (storage8[index])) b.AppendL (storage8[index]); } buffer.Clear (); buffer.AppendL (b.GetStorage ()); } else make_doublebyte_in_place (buffer.GetStorage (), op_strlen (storage8)); } return buffer.GetStorage (); }
/* virtual */ ES_PutState DOM_CSSStyleDeclaration::PutName(OpAtom property_name, ES_Value *value, ES_Runtime *origining_runtime) { #ifdef NS4P_COMPONENT_PLUGINS if (FramesDocument* doc = style->GetEnvironment()->GetFramesDocument()) if (LayoutWorkplace* wp = doc->GetLayoutWorkplace()) if (wp->IsTraversing() || wp->IsReflowing()) return PUT_FAILED; #endif // NS4P_COMPONENT_PLUGINS int css_property = DOM_AtomToCssProperty(property_name); BOOL is_pos = FALSE, is_pixel = FALSE; CSS_DOMException exception = CSS_DOMEXCEPTION_NONE; OP_STATUS status = OpStatus::OK; OpStatus::Ignore(status); switch (property_name) { case OP_ATOM_posLeft: case OP_ATOM_posRight: case OP_ATOM_posTop: case OP_ATOM_posBottom: case OP_ATOM_posWidth: case OP_ATOM_posHeight: is_pos = TRUE; break; case OP_ATOM_pixelHeight: case OP_ATOM_pixelLeft: case OP_ATOM_pixelTop: case OP_ATOM_pixelWidth: case OP_ATOM_pixelBottom: case OP_ATOM_pixelRight: is_pixel = TRUE; break; case OP_ATOM_length: return PUT_READ_ONLY; case OP_ATOM_cssText: if (value->type == VALUE_NULL) DOMSetString(value); else if (value->type != VALUE_STRING) return PUT_NEEDS_STRING; if (type == DOM_ST_INLINE) PUT_FAILED_IF_ERROR(element->SetAttribute(ATTR_XML, UNI_L("style"), NS_IDX_DEFAULT, value->value.string, value->GetStringLength(), TRUE, origining_runtime)); else if (type == DOM_ST_RULE) { OP_STATUS stat = style->SetText(value->value.string, exception); if (stat == OpStatus::ERR_NO_MEMORY) return PUT_NO_MEMORY; else if (stat == OpStatus::ERR) { if (exception == CSS_DOMEXCEPTION_NO_MODIFICATION_ALLOWED_ERR) return PUT_READ_ONLY; else if (exception == CSS_DOMEXCEPTION_SYNTAX_ERR) return DOM_PUTNAME_DOMEXCEPTION(SYNTAX_ERR); } } return PUT_SUCCESS; default: if (css_property != -1) { if (value->type == VALUE_NULL) DOMSetString(value); else if (value->type != VALUE_STRING) return PUT_NEEDS_STRING; #ifdef DOM2_MUTATION_EVENTS MutationState mutationstate(element, (DOM_Runtime *) origining_runtime); if (element) { PUT_FAILED_IF_ERROR(mutationstate.BeforeChange()); } #endif // DOM2_MUTATION_EVENTS status = style->SetProperty(css_property, value->value.string, exception); #ifdef DOM2_MUTATION_EVENTS if (OpStatus::IsSuccess(status) && element) PUT_FAILED_IF_ERROR(mutationstate.AfterChange()); #endif // DOM2_MUTATION_EVENTS goto handle_status; } else return PUT_FAILED; } if (is_pos || is_pixel) { OP_ASSERT(css_property != -1); if (value->type != VALUE_NUMBER) return PUT_NEEDS_NUMBER; if (is_pixel) value->value.number = op_floor(value->value.number); TempBuffer *buffer = GetEmptyTempBuf(); PUT_FAILED_IF_ERROR(buffer->Expand(33)); char *number8 = reinterpret_cast<char *>(buffer->GetStorage()); char *result = OpDoubleFormat::ToString(number8, value->value.number); if (!result) return PUT_NO_MEMORY; make_doublebyte_in_place(buffer->GetStorage(), op_strlen(number8)); if (is_pos) status = style->SetPosValue(css_property, buffer->GetStorage(), exception); else status = style->SetPixelValue(css_property, buffer->GetStorage(), exception); } handle_status: if (OpStatus::IsMemoryError(status)) return PUT_NO_MEMORY; else if (OpStatus::IsError(status)) if (exception == CSS_DOMEXCEPTION_NO_MODIFICATION_ALLOWED_ERR) return PUT_READ_ONLY; else if (exception == CSS_DOMEXCEPTION_SYNTAX_ERR) return DOM_PUTNAME_DOMEXCEPTION(SYNTAX_ERR); return PUT_SUCCESS; }
/* virtual */ ES_PutState JS_Location::PutName(OpAtom property_name, ES_Value* value, ES_Runtime* origining_runtime) { if (GetName(property_name, NULL, origining_runtime) != GET_SUCCESS) return PUT_FAILED; FramesDocument *frames_doc = GetFramesDocument(); if (!frames_doc) return PUT_SUCCESS; if (value->type != VALUE_STRING) return PUT_NEEDS_STRING; const uni_char *value_string = value->value.string; while (value_string[0] == ' ') ++value_string; if (property_name == OP_ATOM_href) if (value_string[0] == '#') property_name = OP_ATOM_hash; else if (value_string[0] == '?') property_name = OP_ATOM_search; URL url; DocumentReferrer ref_url(GetStandardRefURL(frames_doc, origining_runtime)); TempBuffer buffer; URL current_url = ref_url.url; #ifdef SELFTEST if (!do_navigation) current_url = this->current_url; #endif // SELFTEST switch (property_name) { case OP_ATOM_href: case OP_ATOM_protocol: case OP_ATOM_host: case OP_ATOM_hostname: case OP_ATOM_port: case OP_ATOM_pathname: BOOL allowed; if (OpStatus::IsError(OpSecurityManager::CheckSecurity(OpSecurityManager::DOM_ALLOWED_TO_NAVIGATE, static_cast<DOM_Runtime *>(origining_runtime), GetRuntime(), allowed)) || !allowed) return PUT_SECURITY_VIOLATION; } switch (property_name) { case OP_ATOM_protocol: { unsigned length = uni_strlen(value_string); while (length > 0 && value_string[length - 1] == ':') length--; if (length > 0) { const uni_char *current_url_string = current_url.GetAttribute(URL::KUniName_Username_Password_NOT_FOR_UI).CStr(); const uni_char *current_scheme_end = uni_strchr(current_url_string, ':'); if (!current_scheme_end) return PUT_SUCCESS; PUT_FAILED_IF_ERROR(buffer.Append(value_string, length)); PUT_FAILED_IF_ERROR(buffer.Append(current_scheme_end)); url = GetEncodedURL(origining_runtime->GetFramesDocument(), buffer.GetStorage()); BOOL allowed; if (url.Type() == URL_JAVASCRIPT) if (OpStatus::IsError(OpSecurityManager::CheckSecurity(OpSecurityManager::DOM_STANDARD, static_cast<DOM_Runtime *>(origining_runtime), GetRuntime(), allowed)) || !allowed) return PUT_SUCCESS; } break; } case OP_ATOM_host: { const uni_char *current_url_string = current_url.GetAttribute(URL::KUniName_Username_Password_NOT_FOR_UI).CStr(); const uni_char *current_scheme_end = uni_strchr(current_url_string, ':'); // URL must be an "authority-based URL" if (current_scheme_end && current_scheme_end[1] == '/' && current_scheme_end[2] == '/') { OpString hostname; PUT_FAILED_IF_ERROR(current_url.GetAttribute(URL::KUniHostName, hostname)); /* Just bail if the URL doesn't have a hostname after all. */ if (!hostname.CStr()) return PUT_SUCCESS; uni_char *hostname_start = uni_strstr(current_url_string, hostname.CStr()); OP_ASSERT(hostname_start); uni_char *hostname_end = hostname_start + hostname.Length(); unsigned short port = current_url.GetAttribute(URL::KServerPort); if (port > 0 && *hostname_end == ':') { hostname_end++; while (uni_isdigit(*hostname_end)) hostname_end++; } PUT_FAILED_IF_ERROR(buffer.Append(current_url_string, hostname_start - current_url_string)); PUT_FAILED_IF_ERROR(buffer.Append(value_string)); PUT_FAILED_IF_ERROR(buffer.Append(hostname_end)); url = GetEncodedURL(origining_runtime->GetFramesDocument(), buffer.GetStorage()); } break; } case OP_ATOM_hostname: { while (*value_string == '/') value_string++; const uni_char *current_url_string = current_url.GetAttribute(URL::KUniName_Username_Password_NOT_FOR_UI).CStr(); const uni_char *current_scheme_end = uni_strchr(current_url_string, ':'); // URL must be an "authority-based URL" if (*value_string && current_scheme_end && current_scheme_end[1] == '/' && current_scheme_end[2] == '/') { OpString hostname; PUT_FAILED_IF_ERROR(current_url.GetAttribute(URL::KUniHostName, hostname)); /* Just bail if the URL doesn't have a hostname after all. */ if (!hostname.CStr()) return PUT_SUCCESS; uni_char *hostname_start = uni_strstr(current_url_string, hostname.CStr()); OP_ASSERT(hostname_start); uni_char *hostname_end = hostname_start + hostname.Length(); PUT_FAILED_IF_ERROR(buffer.Append(current_url_string, hostname_start - current_url_string)); PUT_FAILED_IF_ERROR(buffer.Append(value_string)); PUT_FAILED_IF_ERROR(buffer.Append(hostname_end)); url = GetEncodedURL(origining_runtime->GetFramesDocument(), buffer.GetStorage()); } break; } case OP_ATOM_port: { const uni_char *current_url_string = current_url.GetAttribute(URL::KUniName_Username_Password_NOT_FOR_UI).CStr(); const uni_char *current_scheme_end = uni_strchr(current_url_string, ':'); // URL must be an "authority-based URL" if (current_scheme_end && current_scheme_end[1] == '/' && current_scheme_end[2] == '/') { while (*value_string == '0') value_string++; int port = 0; if (uni_isdigit(*value_string)) port = uni_atoi(value_string); if (port <= 0 || port > 65535) break; OpString hostname; PUT_FAILED_IF_ERROR(current_url.GetAttribute(URL::KUniHostName, hostname)); /* Just bail if the URL doesn't have a hostname after all. */ if (!hostname.CStr()) return PUT_SUCCESS; uni_char *hostname_start = uni_strstr(current_scheme_end, hostname.CStr()); OP_ASSERT(hostname_start); uni_char *hostname_end = hostname_start + hostname.Length(); PUT_FAILED_IF_ERROR(buffer.Append(current_url_string, hostname_end - current_url_string)); PUT_FAILED_IF_ERROR(buffer.Append(":")); if (*hostname_end == ':') { hostname_end++; while (uni_isdigit(*hostname_end)) hostname_end++; } PUT_FAILED_IF_ERROR(buffer.AppendLong(port)); PUT_FAILED_IF_ERROR(buffer.Append(hostname_end)); url = GetEncodedURL(origining_runtime->GetFramesDocument(), buffer.GetStorage()); } break; } case OP_ATOM_href: case OP_ATOM_pathname: { url = GetEncodedURL(origining_runtime->GetFramesDocument(), value_string); BOOL allowed; // Stricter security for javascript urls. It's possible this check should move into DocumentManager in the future. if (url.Type() == URL_JAVASCRIPT) if (OpStatus::IsError(OpSecurityManager::CheckSecurity(OpSecurityManager::DOM_STANDARD, static_cast<DOM_Runtime *>(origining_runtime), GetRuntime(), allowed)) || !allowed) return PUT_SUCCESS; break; } case OP_ATOM_search: { const uni_char *current_url_string = current_url.GetAttribute(URL::KUniName_Username_Password_NOT_FOR_UI).CStr(); int current_len; const uni_char *current_search_start = uni_strchr(current_url_string, '?'); if (current_search_start) current_len = current_search_start - current_url_string; else current_len = uni_strlen(current_url_string); if (value_string[0] == '?') ++value_string; PUT_FAILED_IF_ERROR(buffer.Expand(current_len + uni_strlen(value_string) + 2)); OpStatus::Ignore(buffer.Append(current_url_string, current_len)); // buffer is successfully expanded above OpStatus::Ignore(buffer.Append("?")); OpStatus::Ignore(buffer.Append(value_string)); url = GetEncodedURL(origining_runtime->GetFramesDocument(), buffer.GetStorage()); break; } case OP_ATOM_hash: if (value_string[0] == '#') ++value_string; // Strip trailing whitespace if (unsigned length = uni_strlen(value_string)) { if (value_string[length - 1] == ' ') { PUT_FAILED_IF_ERROR(buffer.Append(value_string)); uni_char *string = buffer.GetStorage(); while (length > 0 && string[length - 1] == ' ') --length; string[length] = 0; value_string = string; } } #ifdef SELFTEST url = URL(!do_navigation ? current_url : frames_doc->GetURL(), value_string); #else url = URL(frames_doc->GetURL(), value_string); #endif // SELFTEST break; } if (url.Type() != URL_NULL_TYPE) { #ifdef GADGET_SUPPORT switch (property_name) { case OP_ATOM_href: case OP_ATOM_protocol: case OP_ATOM_host: case OP_ATOM_hostname: case OP_ATOM_port: case OP_ATOM_pathname: { BOOL allowed; if (frames_doc->GetWindow()->GetGadget()) if (OpStatus::IsError(OpSecurityManager::CheckSecurity(OpSecurityManager::GADGET_ALLOWED_TO_NAVIGATE, OpSecurityContext(frames_doc), url, allowed)) || !allowed) return PUT_SECURITY_VIOLATION; } } #endif // GADGET_SUPPORT return SetTheURL(frames_doc, ref_url, url, GetCurrentThread(origining_runtime), property_name == OP_ATOM_hash); } else return PUT_SUCCESS; }
/* virtual */ ES_GetState JS_Location::GetName(OpAtom property_name, ES_Value* value, ES_Runtime* origining_runtime) { TempBuffer *buffer = GetEmptyTempBuf(); URL url; if (fakewindow) url = fakewindow->GetURL(); #ifdef SELFTEST else if (!do_navigation) url = current_url; #endif // SELFTEST else if (FramesDocument *frames_doc = GetFramesDocument()) { url = frames_doc->GetURL(); // The anchors (hash) might be better in DocumentManager URL doc_man_url = frames_doc->GetDocManager()->GetCurrentURL(); if (doc_man_url == url) // Doesn't compare anchors url = doc_man_url; } #ifdef DOM_WEBWORKERS_SUPPORT /* No FramesDocument to query, so consult the origin DocumentManager for the Worker */ if (!GetFramesDocument()) { DOM_WebWorkerController *web_workers = GetEnvironment()->GetWorkerController(); if (DOM_WebWorker *ww = web_workers->GetWorkerObject()) url = ww->GetLocationURL(); else if (DocumentManager *doc = web_workers->GetWorkerDocManager()) url = doc->GetCurrentURL(); OP_ASSERT(!url.IsEmpty()); } #endif // DOM_WEBWORKERS_SUPPORT switch (property_name) { case OP_ATOM_href: DOMSetString(value, url.GetAttribute(URL::KUniName_With_Fragment_Escaped).CStr()); return GET_SUCCESS; case OP_ATOM_protocol: if (value) { const char *protocol = url.GetAttribute(URL::KProtocolName).CStr(); if (protocol) { GET_FAILED_IF_ERROR(buffer->Append(protocol)); GET_FAILED_IF_ERROR(buffer->Append(":")); } DOMSetString(value, buffer); } return GET_SUCCESS; case OP_ATOM_host: case OP_ATOM_hostname: if (value) { const uni_char *name = url.GetServerName() ? url.GetServerName()->UniName() : NULL; if (property_name == OP_ATOM_host) { unsigned short port = url.GetServerPort(); if (port) { GET_FAILED_IF_ERROR(buffer->Append(name)); GET_FAILED_IF_ERROR(buffer->Append(":")); GET_FAILED_IF_ERROR(buffer->AppendUnsignedLong(port)); name = buffer->GetStorage(); } } DOMSetString(value, name); } return GET_SUCCESS; case OP_ATOM_port: if (value) { unsigned short port = url.GetServerPort(); if (port) GET_FAILED_IF_ERROR(buffer->AppendUnsignedLong(port)); DOMSetString(value, buffer); } return GET_SUCCESS; case OP_ATOM_pathname: if (value) { const uni_char *path = url.GetAttribute(URL::KUniPath).CStr(); if (path) { GET_FAILED_IF_ERROR(buffer->Append(path)); uni_char *path_tmp = buffer->GetStorage(); /* It isn't obvious from the JS spec and the relevant RFC, but in Javascript the 'pathname' excludes any arguments passed to the page. */ if (uni_char *query_start = uni_strchr(path_tmp, '?')) { path = path_tmp; *query_start = 0; } } DOMSetString(value, path); } return GET_SUCCESS; case OP_ATOM_search: if (value) { const uni_char *name = url.GetAttribute(URL::KUniName).CStr(); if (name) name = uni_strchr(name, '?'); DOMSetString(value, name); } return GET_SUCCESS; case OP_ATOM_hash: if (value) { const uni_char *fragment = url.UniRelName(); // MSIE emits "#" for the empty fragment (as in http://www.opera.com/# ) but no other // browser does that and neither will we. if (fragment && *fragment) { GET_FAILED_IF_ERROR(buffer->Append('#')); GET_FAILED_IF_ERROR(buffer->Append(fragment)); fragment = buffer->GetStorage(); } DOMSetString(value, fragment); } return GET_SUCCESS; } return GET_FAILED; }