/* 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;
}
Example #2
0
/* 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;
}