Esempio n. 1
0
/* like strcasecmp(s1.raw_buf(),s2.raw_buf()) but for unicode
 * TODO: slow! */
int tiny_string::strcasecmp(tiny_string& s2) const
{
	char* str1 = g_utf8_casefold(this->raw_buf(),this->numBytes());
	char* str2 = g_utf8_casefold(s2.raw_buf(),s2.numBytes());
	int ret = g_utf8_collate(str1,str2);
	g_free(str1);
	g_free(str2);
	return ret;
}
Esempio n. 2
0
/* start is an index of characters.
 * returns index of character */
uint32_t tiny_string::find(const tiny_string& needle, uint32_t start) const
{
	//TODO: omit copy into std::string
	size_t bytestart = g_utf8_offset_to_pointer(buf,start) - buf;
	size_t bytepos = std::string(*this).find(needle.raw_buf(),bytestart,needle.numBytes());
	if(bytepos == std::string::npos)
		return npos;
	else
		return g_utf8_pointer_to_offset(buf,buf+bytepos);
}
Esempio n. 3
0
tiny_string Vector::toJSON(std::vector<ASObject *> &path, IFunction *replacer, const tiny_string &spaces, const tiny_string &filter)
{
	bool ok;
	tiny_string res = call_toJSON(ok,path,replacer,spaces,filter);
	if (ok)
		return res;
	// check for cylic reference
	if (std::find(path.begin(),path.end(), this) != path.end())
		throwError<TypeError>(kJSONCyclicStructure);

	path.push_back(this);
	res += "[";
	bool bfirst = true;
	tiny_string newline = (spaces.empty() ? "" : "\n");
	for (unsigned int i =0;  i < vec.size(); i++)
	{
		tiny_string subres;
		ASObject* o = vec[i];
		if (!o)
			o = getSystemState()->getNullRef();
		if (replacer != NULL)
		{
			ASObject* params[2];
			
			params[0] = abstract_di(getSystemState(),i);
			params[0]->incRef();
			params[1] = o;
			params[1]->incRef();
			ASObject *funcret=replacer->call(getSystemState()->getNullRef(), params, 2);
			if (funcret)
				subres = funcret->toJSON(path,NULL,spaces,filter);
		}
		else
		{
			subres = o->toJSON(path,replacer,spaces,filter);
		}
		if (!subres.empty())
		{
			if (!bfirst)
				res += ",";
			res += newline+spaces;
			
			bfirst = false;
			res += subres;
		}
	}
	if (!bfirst)
		res += newline+spaces.substr_bytes(0,spaces.numBytes()/2);
	res += "]";
	path.pop_back();
	return res;
}
Esempio n. 4
0
const tiny_string multiname::qualifiedString(SystemState* sys) const
{
	assert_and_throw(ns.size()>=1);
	assert_and_throw(name_type==NAME_STRING);
	const tiny_string nsName=sys->getStringFromUniqueId(ns[0].nsNameId);
	const tiny_string& name=sys->getStringFromUniqueId(name_s_id);
	if(nsName.empty())
		return name;
	else
	{
		tiny_string ret=nsName;
		ret+="::";
		ret+=name;
		return ret;
	}
}
Esempio n. 5
0
tiny_string multiname::qualifiedString() const
{
	assert_and_throw(ns.size()==1);
	assert_and_throw(name_type==NAME_STRING);
	const tiny_string nsName=ns[0].getImpl().name;
	const tiny_string& name=getSys()->getStringFromUniqueId(name_s_id);
	if(nsName.empty())
		return name;
	else
	{
		tiny_string ret=nsName;
		ret+="::";
		ret+=name;
		return ret;
	}
}
Esempio n. 6
0
int JSON::parseNumber(const tiny_string &jsonstring, int pos, ASObject** parent, const multiname& key)
{
	int len = jsonstring.numBytes();
	tiny_string res;
	bool done = false;
	while (!done && pos < len)
	{
		char c = jsonstring.charAt(pos);
		switch(c)
		{
			case '0':
			case '1':
			case '2':
			case '3':
			case '4':
			case '5':
			case '6':
			case '7':
			case '8':
			case '9':
			case '-':
			case '+':
			case '.':
			case 'E':
			case 'e':
				res += c;
				pos++;
				break;
			default:
				done = true;
				break;
		}
	}
	ASString* numstr = Class<ASString>::getInstanceS(res);
	number_t num = numstr->toNumber();

	if (std::isnan(num))
		throwError<SyntaxError>(kJSONInvalidParseInput);

	if (*parent == NULL)
		*parent = Class<Number>::getInstanceS(num);
	else 
	{
		(*parent)->setVariableByMultiname(key,Class<Number>::getInstanceS(num),ASObject::CONST_NOT_ALLOWED);
	}
	return pos;
}
Esempio n. 7
0
int JSON::parseArray(const tiny_string &jsonstring, int pos, ASObject** parent, const multiname& key, IFunction *reviver)
{
	int len = jsonstring.numChars();
	pos++; // ignore '['
	ASObject* subobj = Class<Array>::getInstanceS();
	if (*parent == NULL)
		*parent = subobj;
	else 
		(*parent)->setVariableByMultiname(key,subobj,ASObject::CONST_NOT_ALLOWED);
	multiname name(NULL);
	name.name_type=multiname::NAME_INT;
	name.name_i = 0;
	name.ns.push_back(nsNameAndKind("",NAMESPACE));
	name.isAttribute = false;
	bool done = false;
	bool needdata = false;
	while (!done && pos < len)
	{
		while (jsonstring.charAt(pos) == ' ' ||
			   jsonstring.charAt(pos) == '\t' ||
			   jsonstring.charAt(pos) == '\n' ||
			   jsonstring.charAt(pos) == '\r'
			   )
			pos++;
		char c = jsonstring.charAt(pos);
		switch(c)
		{
			case ']':
				done = true;
				pos++;
				break;
			case ',':
				name.name_i++;
				needdata = true;
				pos++;
				break;
			default:
				pos = parse(jsonstring,pos,&subobj,name, reviver);
				needdata = false;
				break;
		}
	}
	if (!done || needdata)
		throwError<SyntaxError>(kJSONInvalidParseInput);

	return pos;
}
Esempio n. 8
0
void JSON::parseAll(const tiny_string &jsonstring, ASObject** parent , const multiname& key, IFunction *reviver)
{
	int len = jsonstring.numBytes();
	int pos = 0;
	while (pos < len)
	{
		if (*parent && (*parent)->isPrimitive())
			throwError<SyntaxError>(kJSONInvalidParseInput);
		pos = parse(jsonstring, pos, parent , key, reviver);
		while (jsonstring.charAt(pos) == ' ' ||
			   jsonstring.charAt(pos) == '\t' ||
			   jsonstring.charAt(pos) == '\n' ||
			   jsonstring.charAt(pos) == '\r'
			   )
			pos++;
	}
}
Esempio n. 9
0
XMLDocument::XMLDocument(Class_base* c, tiny_string s)
  : XMLNode(c),rootNode(NULL),ignoreWhite(false)
{
	if(!s.empty())
	{
		parseXMLImpl(s);
	}
}
Esempio n. 10
0
bool Array::isValidQName(const tiny_string& name, const tiny_string& ns, unsigned int& index)
{
	if(ns!="")
		return false;
	assert_and_throw(!name.empty());
	index=0;
	//First we try to convert the string name to an index, at the first non-digit
	//we bail out
	for(auto i=name.begin(); i!=name.end(); ++i)
	{
		if(!i.isdigit())
			return false;

		index*=10;
		index+=i.digit_value();
	}
	return true;
}
Esempio n. 11
0
bool Array::isIntegerWithoutLeadingZeros(const tiny_string& value)
{
	if (value.empty())
		return false;
	else if (value == "0")
		return true;

	bool first = true;
	for (CharIterator it=value.begin(); it!=value.end(); ++it)
	{
		if (!it.isdigit() || (first && *it == '0'))
			return false;

		first = false;
	}
	
	return true;
}
Esempio n. 12
0
CurlDownloader::CurlDownloader(const tiny_string& u)
{
	//TODO: Url encode the string
	std::string tmp2;
	tmp2.reserve(u.len()*2);
	for(int i=0;i<u.len();i++)
	{
		if(u[i]==' ')
		{
			char buf[4];
			sprintf(buf,"%%%x",(unsigned char)u[i]);
			tmp2+=buf;
		}
		else
			tmp2.push_back(u[i]);
	}
	url=tmp2;
}
Esempio n. 13
0
bool Array::isValidQName(const tiny_string& name, const tiny_string& ns, unsigned int& index)
{
	if(ns!="")
		return false;
	assert_and_throw(name.len()!=0);
	index=0;
	//First we try to convert the string name to an index, at the first non-digit
	//we bail out
	for(int i=0;i<name.len();i++)
	{
		if(!isdigit(name[i]))
			return false;

		index*=10;
		index+=(name[i]-'0');
	}
	return true;
}
Esempio n. 14
0
void nsPluginInstance::openLink(const tiny_string& url, const tiny_string& window)
{
	assert(!window.empty());

	linkOpenData *data = new linkOpenData;
	data->instance = mInstance;
	data->url = url;
	data->window = window;
	NPN_PluginThreadAsyncCall(mInstance, asyncOpenPage, data);
}
Esempio n. 15
0
void XMLSocket::connect(tiny_string host, int port)
{
	if (port <= 0 || port > 65535)
		throw Class<SecurityError>::getInstanceS(getSystemState(),"Invalid port");

	if (host.empty())
		host = getSys()->mainClip->getOrigin().getHostname();

	if (isConnected())
		throw Class<IOError>::getInstanceS(getSystemState(),"Already connected");

	// Host shouldn't contain scheme or port
	if (host.strchr(':') != NULL)
		throw Class<SecurityError>::getInstanceS(getSystemState(),"Invalid hostname");

	// Check sandbox and policy file
	size_t buflen = host.numBytes() + 22;
	char *urlbuf = g_newa(char, buflen);
	snprintf(urlbuf, buflen, "xmlsocket://%s:%d", host.raw_buf(), port);
	URLInfo url(urlbuf);

	getSystemState()->securityManager->checkURLStaticAndThrow(url,
		~(SecurityManager::LOCAL_WITH_FILE),
		SecurityManager::LOCAL_WITH_FILE | SecurityManager::LOCAL_TRUSTED,
		true);

	SecurityManager::EVALUATIONRESULT evaluationResult;
	evaluationResult = getSys()->securityManager->evaluateSocketConnection(url, true);
	if(evaluationResult != SecurityManager::ALLOWED)
	{
		incRef();
		getVm(getSystemState())->addEvent(_MR(this), _MR(Class<SecurityErrorEvent>::getInstanceS(getSystemState(),"No policy file allows socket connection")));
		return;
	}

	incRef();
	XMLSocketThread *thread = new XMLSocketThread(_MR(this), host, port, timeout);
	getSys()->addJob(thread);
	job = thread;
}
Esempio n. 16
0
tiny_string XMLBase::removeWhitespace(tiny_string val)
{
	bool bwhite = true;
	uint32_t start = 0;
	CharIterator it = val.begin();
	CharIterator itend = val.begin();
	while (it != val.end())
	{
		if (!g_unichar_isspace(*it))
		{
			itend=it;
			itend++;
			bwhite = false;
		}
		else if (bwhite)
			start++;
		it++;
	}
	if (bwhite)
		return "";
	return val.substr(start,itend);
}
Esempio n. 17
0
const tiny_string XMLBase::encodeToXML(const tiny_string value, bool bIsAttribute)
{

	tiny_string res;
	auto it = value.begin();
	while (it != value.end())
	{
		switch (*it)
		{
			case '<':
				res += "&lt;";
				break;
			case '>':
				res += bIsAttribute ? ">" : "&gt;";
				break;
			case '&':
				res += "&amp;";
				break;
			case '\"':
				res += bIsAttribute ? "&quot;" : "\"";
				break;
			case '\r':
				res += bIsAttribute ? "&#xD;" : "\r";
				break;
			case '\n':
				res += bIsAttribute ? "&#xA;" : "\n";
				break;
			case '\t':
				res += bIsAttribute ? "&#x9;" : "\t";
				break;
			default:
				res += *it;
				break;
		}
		it++;
	}
	return res;
}
Esempio n. 18
0
int JSON::parseNull(const tiny_string &jsonstring, int pos,ASObject** parent,const multiname& key)
{
	int len = jsonstring.numBytes();
	if (len >= pos+4)
	{
		if (jsonstring.charAt(pos) == 'n' && 
				jsonstring.charAt(pos + 1) == 'u' &&
				jsonstring.charAt(pos + 2) == 'l' && 
				jsonstring.charAt(pos + 3) == 'l')
		{
			pos += 4;
			if (*parent == NULL)
				*parent = getSys()->getNullRef();
			else 
				(*parent)->setVariableByMultiname(key,getSys()->getNullRef(),ASObject::CONST_NOT_ALLOWED);
		}
		else
			throwError<SyntaxError>(kJSONInvalidParseInput);
	}
	else
		throwError<SyntaxError>(kJSONInvalidParseInput);
	return pos;
}
Esempio n. 19
0
int JSON::parseTrue(const tiny_string &jsonstring, int pos,ASObject** parent,const multiname& key)
{
	int len = jsonstring.numBytes();
	if (len >= pos+4)
	{
		if (jsonstring.charAt(pos) == 't' && 
				jsonstring.charAt(pos + 1) == 'r' &&
				jsonstring.charAt(pos + 2) == 'u' && 
				jsonstring.charAt(pos + 3) == 'e')
		{
			pos += 4;
			if (*parent == NULL)
				*parent = abstract_b(true);
			else 
				(*parent)->setVariableByMultiname(key,abstract_b(true),ASObject::CONST_NOT_ALLOWED);
		}
		else
			throwError<SyntaxError>(kJSONInvalidParseInput);
	}
	else
		throwError<SyntaxError>(kJSONInvalidParseInput);
	return pos;
}
Esempio n. 20
0
bool SocketIO::connect(const tiny_string& hostname, int port)
{
	struct addrinfo hints;
	struct addrinfo *servinfo;
	struct addrinfo *p;

	if (fd != -1)
		return false;
	fd = -1;

	if (port <= 0 || port > 65535)
		return false;

	memset(&hints, 0, sizeof hints);
	hints.ai_family = AF_UNSPEC;
	hints.ai_socktype = SOCK_STREAM;

	tiny_string portstr = Integer::toString(port);
	if (getaddrinfo(hostname.raw_buf(), portstr.raw_buf(), &hints, &servinfo) != 0)
	{
		return false;
	}

	for(p = servinfo; p != NULL; p = p->ai_next)
	{
		if ((fd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1)
			continue;

		// TODO: timeout on connect

		if (::connect(fd, p->ai_addr, p->ai_addrlen) == -1)
		{
			::close(fd);
			continue;
		}

		break;
	}

	freeaddrinfo(servinfo);

	if (!p)
		fd = -1;

	return fd != -1;
}
Esempio n. 21
0
void ByteArray::writeUTF(const tiny_string& str)
{
	getBuffer(position+str.numBytes()+2,true);
	if(str.numBytes() > 65535)
	{
		throwError<RangeError>(kParamRangeError);
	}
	uint16_t numBytes=endianIn((uint16_t)str.numBytes());
	memcpy(bytes+position,&numBytes,2);
	memcpy(bytes+position+2,str.raw_buf(),str.numBytes());
	position+=str.numBytes()+2;
}
Esempio n. 22
0
const pugi::xml_node XMLBase::buildFromString(const tiny_string& str,
										unsigned int xmlparsemode,
										const tiny_string& default_ns)
{
	tiny_string buf = quirkEncodeNull(removeWhitespace(str));
	if (buf.numBytes() > 0 && buf.charAt(0) == '<')
	{
		pugi::xml_parse_result res = xmldoc.load_buffer((void*)buf.raw_buf(),buf.numBytes(),xmlparsemode);
		switch (res.status)
		{
			case pugi::status_ok:
				break;
			case pugi::status_end_element_mismatch:
				throwError<TypeError>(kXMLUnterminatedElementTag);
				break;
			case pugi::status_unrecognized_tag:
				throwError<TypeError>(kXMLMalformedElement);
				break;
			case pugi::status_bad_pi:
				throwError<TypeError>(kXMLUnterminatedXMLDecl);
				break;
			case pugi::status_bad_attribute:
				throwError<TypeError>(kXMLUnterminatedAttribute);
				break;
			case pugi::status_bad_cdata:
				throwError<TypeError>(kXMLUnterminatedCData);
				break;
			case pugi::status_bad_doctype:
				throwError<TypeError>(kXMLUnterminatedDocTypeDecl);
				break;
			case pugi::status_bad_comment:
				throwError<TypeError>(kXMLUnterminatedComment);
				break;
			default:
				LOG(LOG_ERROR,"xml parser error:"<<buf<<" "<<res.status<<" "<<res.description());
				break;
		}
	}
	else
	{
		pugi::xml_node n = xmldoc.append_child(pugi::node_pcdata);
		n.set_value(str.raw_buf());
	}
	return xmldoc.root();
}
Esempio n. 23
0
int JSON::parse(const tiny_string &jsonstring, int pos, ASObject** parent , const multiname& key, IFunction *reviver)
{
	while (jsonstring.charAt(pos) == ' ' ||
		   jsonstring.charAt(pos) == '\t' ||
		   jsonstring.charAt(pos) == '\n' ||
		   jsonstring.charAt(pos) == '\r'
		   )
		   pos++;
	int len = jsonstring.numBytes();
	if (pos < len)
	{
		char c = jsonstring.charAt(pos);
		switch(c)
		{
			case '{':
				pos = parseObject(jsonstring,pos,parent,key, reviver);
				break;
			case '[': 
				pos = parseArray(jsonstring,pos,parent,key, reviver);
				break;
			case '"':
				pos = parseString(jsonstring,pos,parent,key);
				break;
			case '0':
			case '1':
			case '2':
			case '3':
			case '4':
			case '5':
			case '6':
			case '7':
			case '8':
			case '9':
			case '-':
				pos = parseNumber(jsonstring,pos,parent,key);
				break;
			case 't':
				pos = parseTrue(jsonstring,pos,parent,key);
				break;
			case 'f':
				pos = parseFalse(jsonstring,pos,parent,key);
				break;
			case 'n':
				pos = parseNull(jsonstring,pos,parent,key);
				break;
			default:
				throwError<SyntaxError>(kJSONInvalidParseInput);
		}
	}
	if (reviver)
	{
		bool haskey = key.name_type!= multiname::NAME_OBJECT;
		ASObject* params[2];
		
		if (haskey)
		{
			params[0] = Class<ASString>::getInstanceS(key.normalizedName());
			if ((*parent)->hasPropertyByMultiname(key,true,false))
			{
				params[1] = (*parent)->getVariableByMultiname(key).getPtr();
				params[1]->incRef();
			}
			else
				params[1] = getSys()->getNullRef();
		}
		else
		{
			params[0] = Class<ASString>::getInstanceS("");
			params[1] = *parent;
			params[1]->incRef();
		}

		ASObject *funcret=reviver->call(getSys()->getNullRef(), params, 2);
		if(funcret)
		{
			if (haskey)
			{
				if (funcret->is<Undefined>())
				{
					(*parent)->deleteVariableByMultiname(key);
					funcret->decRef();
				}
				else
				{
					(*parent)->setVariableByMultiname(key,funcret,ASObject::CONST_NOT_ALLOWED);
				}
			}
			else 
				*parent= funcret;
		}
	}
	return pos;
}
Esempio n. 24
0
ASString::ASString(const tiny_string& s):data(s.raw_buf())
{
	type=T_STRING;
}
Esempio n. 25
0
int JSON::parseObject(const tiny_string &jsonstring, int pos,ASObject** parent,const multiname& key, IFunction *reviver)
{
	int len = jsonstring.numChars();
	pos++; // ignore '{' or ','
	ASObject* subobj = Class<ASObject>::getInstanceS();
	if (*parent == NULL)
		*parent = subobj;
	else 
		(*parent)->setVariableByMultiname(key,subobj,ASObject::CONST_NOT_ALLOWED);
	multiname name(NULL);
	name.name_type=multiname::NAME_STRING;
	name.ns.push_back(nsNameAndKind("",NAMESPACE));
	name.isAttribute = false;
	bool done = false;
	bool bfirst = true;
	bool needkey = true;
	bool needvalue = false;

	while (!done && pos < len)
	{
		while (jsonstring.charAt(pos) == ' ' ||
			   jsonstring.charAt(pos) == '\t' ||
			   jsonstring.charAt(pos) == '\n' ||
			   jsonstring.charAt(pos) == '\r'
			   )
			pos++;
		char c = jsonstring.charAt(pos);
		switch(c)
		{
			case '}':
				if (!bfirst && (needkey || needvalue))
					throwError<SyntaxError>(kJSONInvalidParseInput);
				done = true;
				pos++;
				break;
			case '\"':
				{
					tiny_string keyname;
					pos = parseString(jsonstring,pos,NULL,name,&keyname);
					name.name_s_id=getSys()->getUniqueStringId(keyname);
					needkey = false;
					needvalue = true;
				}
				break;
			case ',':
				if (needkey || needvalue)
					throwError<SyntaxError>(kJSONInvalidParseInput);
				pos++;
				name.name_s_id=0;
				needkey = true;
				break;
			case ':':
				pos++;
				pos = parse(jsonstring,pos,&subobj,name,reviver);
				needvalue = false;
				break;
			default:
				throwError<SyntaxError>(kJSONInvalidParseInput);
		}
		bfirst=false;
	}
	if (!done)
		throwError<SyntaxError>(kJSONInvalidParseInput);

	return pos;
}
Esempio n. 26
0
int JSON::parseString(const tiny_string &jsonstring, int pos,ASObject** parent,const multiname& key, tiny_string* result)
{
	pos++; // ignore starting quotes
	int len = jsonstring.numChars();
	if (pos >= len)
		throwError<SyntaxError>(kJSONInvalidParseInput);

	tiny_string sub = jsonstring.substr(pos,len-pos);
	
	tiny_string res;
	bool done = false;
	for (CharIterator it=sub.begin(); it!=sub.end(); it++)
	{
		pos++;
		if (*it == '\"')
		{
			done = true;
			break;
		}
		else if(*it == '\\')
		{
			it++;
			pos++;
			if(it == sub.end())
				break;
			if(*it == '\"')
				res += '\"';
			else if(*it == '\\')
				res += '\\';
			else if(*it == '/')
				res += '/';
			else if(*it == 'b')
				res += '\b';
			else if(*it == 'f')
				res += '\f';
			else if(*it == 'n')
				res += '\n';
			else if(*it == 'r')
				res += '\r';
			else if(*it == 't')
				res += '\t';
			else if(*it == 'u')
			{
				tiny_string strhex;
				for (int i = 0; i < 4; i++)
				{
					it++; pos++; 
					if (it==sub.end()) 
						throwError<SyntaxError>(kJSONInvalidParseInput);
					switch(*it)
					{
						case '0':
						case '1':
						case '2':
						case '3':
						case '4':
						case '5':
						case '6':
						case '7':
						case '8':
						case '9':
						case 'a':
						case 'b':
						case 'c':
						case 'd':
						case 'e':
						case 'f':
						case 'A':
						case 'B':
						case 'C':
						case 'D':
						case 'E':
						case 'F':
							strhex += *it;
							break;
						default:
							throwError<SyntaxError>(kJSONInvalidParseInput);
					}
					if (it==sub.end()) 
						throwError<SyntaxError>(kJSONInvalidParseInput);
				}
				int64_t hexnum;
				if (Integer::fromStringFlashCompatible(strhex.raw_buf(),hexnum,16))
				{
					if (hexnum < 0x20 && hexnum != 0xf)
						throwError<SyntaxError>(kJSONInvalidParseInput);
					res += tiny_string::fromChar(hexnum);
				}
				else
					break;
			}
			else
				throwError<SyntaxError>(kJSONInvalidParseInput);
		}
		else if (*it < 0x20)
		{
			throwError<SyntaxError>(kJSONInvalidParseInput);
		}
		else
		{
			res += *it;
		}
	}
	if (!done)
		throwError<SyntaxError>(kJSONInvalidParseInput);
	
	if (parent != NULL)
	{
		if (*parent == NULL)
			*parent = Class<ASString>::getInstanceS(res);
		else 
			(*parent)->setVariableByMultiname(key,Class<ASString>::getInstanceS(res),ASObject::CONST_NOT_ALLOWED);
	}
	if (result)
		*result =res;
	return pos;
}
Esempio n. 27
0
void URLVariables::decode(const tiny_string& s)
{
	const char* nameStart=NULL;
	const char* nameEnd=NULL;
	const char* valueStart=NULL;
	const char* valueEnd=NULL;
	const char* cur=s.raw_buf();
	while(1)
	{
		if(nameStart==NULL)
			nameStart=cur;
		if(*cur == '=')
		{
			if(nameStart==NULL || valueStart!=NULL) //Skip this
			{
				nameStart=NULL;
				nameEnd=NULL;
				valueStart=NULL;
				valueEnd=NULL;
				cur++;
				continue;
			}
			nameEnd=cur;
			valueStart=cur+1;
		}
		else if(*cur == '&' || *cur==0)
		{
			if(nameStart==NULL || nameEnd==NULL || valueStart==NULL || valueEnd!=NULL)
			{
				nameStart=NULL;
				nameEnd=NULL;
				valueStart=NULL;
				valueEnd=NULL;
				cur++;
				continue;
			}
			valueEnd=cur;
			char* name=g_uri_unescape_segment(nameStart,nameEnd,NULL);
			char* value=g_uri_unescape_segment(valueStart,valueEnd,NULL);
			nameStart=NULL;
			nameEnd=NULL;
			valueStart=NULL;
			valueEnd=NULL;
			//Check if the variable already exists
			multiname propName;
			propName.name_type=multiname::NAME_STRING;
			propName.name_s=name;
			propName.ns.push_back(nsNameAndKind("",NAMESPACE));
			ASObject* curValue=getVariableByMultiname(propName);
			if(curValue)
			{
				//If the variable already exists we have to create an Array of values
				Array* arr=NULL;
				if(curValue->getObjectType()!=T_ARRAY)
				{
					arr=Class<Array>::getInstanceS();
					curValue->incRef();
					arr->push(curValue);
					setVariableByMultiname(propName,arr);
				}
				else
					arr=Class<Array>::cast(curValue);

				arr->push(Class<ASString>::getInstanceS(value));
			}
			else
				setVariableByMultiname(propName,Class<ASString>::getInstanceS(value));

			g_free(name);
			g_free(value);
			if(*cur==0)
				break;
		}
		cur++;
	}
}
Esempio n. 28
0
/**
 * \brief Checks URL policy files to see if the player is allowed to send a given request header 
 * as part of a request for the given URL
 *
 * Waits for mutex at start and releases mutex when finished
 * \param url The URL of the request to which the request header belongs
 * \param header The request header to evaluate
 * \param loadPendingPolicies Whether or not to load (and thus check) pending policy files
 * \return \c ALLOWED if allowed or otherwise \c NA_HEADER
 */
SecurityManager::EVALUATIONRESULT SecurityManager::evaluateHeader(const URLInfo& url,
		const tiny_string& header, bool loadPendingPolicies)
{
	//This check doesn't apply to local files
	if(url.getProtocol() == "file" && getSys()->getOrigin().getProtocol() == "file")
		return ALLOWED;

	LOG(LOG_INFO, _("SECURITY: Evaluating header for cross domain policies ('") << header << "'):");
	LOG(LOG_INFO, _("SECURITY: --> URL: ") << url);
	LOG(LOG_INFO, _("SECURITY: --> Origin: ") << getSys()->getOrigin());

	string headerStrLower(header.raw_buf());
	transform(headerStrLower.begin(), headerStrLower.end(), headerStrLower.begin(), ::tolower);
	string headerStr = headerStrLower;
	if(headerStr.find("_") != string::npos)
		headerStr.replace(headerStr.find("_"), 1, "-");

	//Disallowed headers, in any case
	if(headerStr == "accept-charset" &&	headerStr == "accept-encoding" &&	headerStr == "accept-ranges" &&
			headerStr == "age" &&	headerStr == "allow" && headerStr == "allowed" && headerStr == "authorization" &&
			headerStr == "charge-to" && headerStr == "connect" && headerStr == "connection" &&
			headerStr == "content-length" && headerStr == "content-location" && headerStr == "content-range" &&
			headerStr == "cookie" && headerStr == "date" && headerStr == "delete" && headerStr == "etag" &&
			headerStr == "expect" && headerStr == "get" && headerStr == "head" && headerStr == "host" &&
			headerStr == "if-modified-since" && headerStr == "keep-alive" && headerStr == "last-modified" &&
			headerStr == "location" && headerStr == "max-forwards" && headerStr == "options" &&
			headerStr == "origin" && headerStr == "post" && headerStr == "proxy-authenticate" &&
			headerStr == "proxy-authorization" && headerStr == "proxy-connection" && headerStr == "public" &&
			headerStr == "put" && headerStr == "range" && headerStr == "referer" && headerStr == "request-range" &&
			headerStr == "retry-after" && headerStr == "server" && headerStr == "te" && headerStr == "trace" &&
			headerStr == "trailer" && headerStr == "transfer-encoding" && headerStr == "upgrade" &&
			headerStr == "uri" && headerStr == "user-agent" && headerStr == "vary" && headerStr == "via" &&
			headerStr == "warning" && headerStr == "www-authenticate" && headerStr == "x-flash-version")
	{
		LOG(LOG_INFO, _("SECURITY: DISALLOWED: Header is restricted"));
		return NA_HEADER;
	}

	//The URL has exactly the same domain name as the origin, always allowed
	if(url.getProtocol() == getSys()->getOrigin().getProtocol() &&
			url.getHostname() == getSys()->getOrigin().getHostname())
	{
		LOG(LOG_INFO, _("SECURITY: ALLOWED: Same hostname as origin"));
		return ALLOWED;
	}

	//Search for the policy files to check
	URLPFileList* files = searchURLPolicyFiles(url, loadPendingPolicies);

	RecMutex::Lock l(mutex);

	//Check the policy files
	if(files != NULL)
	{
		URLPFileListConstIt it = files->begin();
		for(; it != files->end(); ++it)
		{
			if((*it)->allowsHTTPRequestHeaderFrom(getSys()->getOrigin(), url, headerStrLower))
			{
				LOG(LOG_INFO, _("SECURITY: ALLOWED: A policy file explicitly allowed the header"));
				delete files;
				return ALLOWED;
			}
		}
	}

	LOG(LOG_INFO, _("SECURITY: DISALLOWED: No policy file explicitly allowed the header"));
	delete files;

	return NA_CROSSDOMAIN_POLICY;
}