示例#1
0
bool JsonSerializer::input(Pair &pair)
{
	String key;
	if(!input(key)) return false;
	AssertIO(mStream->last() == ':');
	LineSerializer keySerializer(&key);
	pair.deserializeKey(keySerializer);
	AssertIO(pair.deserializeValue(*this));
	return true;
}
示例#2
0
void Resource::fetch(const BinaryString &digest, bool localOnly)
{
	delete mIndexBlock;
	delete mIndexRecord;
	mIndexRecord = NULL;
	mIndexBlock = NULL;
	
	if(localOnly && !Store::Instance->hasBlock(digest))
		throw Exception(String("Local resource not found: ") + digest.toString());
	
	//LogDebug("Resource::fetch", "Fetching resource " + digest.toString());
	
	try {
		mIndexBlock = new Block(digest);
		mIndexRecord = new IndexRecord;
		
		//LogDebug("Resource::fetch", "Reading index block for " + digest.toString());
		
		BinarySerializer serializer(mIndexBlock);
		AssertIO(static_cast<Serializer*>(&serializer)->input(mIndexRecord));
	}
	catch(const std::exception &e)
	{
		delete mIndexBlock;
		delete mIndexRecord;
		mIndexRecord = NULL;
		mIndexBlock = NULL;
		throw Exception(String("Unable to fetch resource index block: ") + e.what());
	}

}
示例#3
0
void Http::Request::recv(Stream *stream, bool parsePost)
{
	Assert(stream);
	this->stream = stream;

	clear();

	// Read first line
	String line;
	if(!stream->readLine(line)) throw NetException("Connection closed");
	method.clear();
	url.clear();
	line.readString(method);
	line.readString(url);

	String protocol;
	line.readString(protocol);
	version = protocol.cut('/');

	if(url.empty() || version.empty() || protocol != "HTTP")
		throw 400;

	if(method != "GET" && method != "POST" && method != "HEAD")
		throw 405;

	// Read headers
	while(true)
	{
		String line;
		AssertIO(stream->readLine(line));
		if(line.empty()) break;

		String value = line.cut(':');
		line.trim();
		value.trim();
		headers.insert(line,value);
	}

	// Read cookies
	String cookie;
	if(headers.get("Cookie", cookie))
	{
		while(!cookie.empty())
		{
			String next = cookie.cut(';');
			String value = cookie.cut('=');
			cookie.trim();
			value.trim();
			cookies.insert(cookie,value);
			cookie = next;
		}
	}

	fullUrl = url;
	
	// Read URL variables
	String getData = url.cut('?');
	if(!getData.empty())
	{
		List<String> exploded;
		getData.explode(exploded,'&');
		for(	List<String>::iterator it = exploded.begin();
				it != exploded.end();
				++it)
		{
			String value = it->cut('=').urlDecode();
			get.insert(it->urlDecode(), value);
		}
	}

	url = url.urlDecode();
	
	String expect;
	if((headers.get("Expect",expect) && expect.toLower() == "100-continue")
		|| (method == "POST" && version == "1.1"))
	{
		stream->write("HTTP/1.1 100 Continue\r\n\r\n");
	}
	
	// Read post variables
	if(method == "POST" && parsePost)
	{
		if(!headers.contains("Content-Length"))
			throw Exception("Missing Content-Length header in POST request");

		size_t contentLength = 0;
		headers["Content-Length"].extract(contentLength);
		
		String contentType;
		if(headers.get("Content-Type", contentType))
		{
			String parameters = contentType.cut(';');
			contentType.trim();
			
			if(contentType == "application/x-www-form-urlencoded")
			{
				String data;
				if(stream->read(data, contentLength) != contentLength)
					throw NetException("Connection unexpectedly closed");
			  
				List<String> exploded;
				data.explode(exploded,'&');
				for(	List<String>::iterator it = exploded.begin();
						it != exploded.end();
						++it)
				{
					String value = it->cut('=').urlDecode();
					post.insert(it->urlDecode(), value);
				}
			}
			else if(contentType == "multipart/form-data")
			{
				String boundary;
				while(true)
				{
					String key;
			  		if(!parameters.readUntil(key,';')) break;
					String value = key.cut('=');
					key.trim();
					value.trim();
					value.trimQuotes();
					if(key == "boundary") boundary = String("--") + value;
				}
				
				Assert(!boundary.empty());
				
				String line;
				while(line.empty()) AssertIO(stream->readLine(line));
				Assert(line == boundary);
				
				bool finished = false;
				while(!finished)
				{
					StringMap mimeHeaders;
					while(true)
					{
						String line;
						AssertIO(stream->readLine(line));
						if(line.empty()) break;
						
						String value = line.cut(':');
						line.trim();
						value.trim();
						mimeHeaders.insert(line,value);
					}
					
					String contentType;
					if(mimeHeaders.get("Content-Type", contentType))
					{
						String parameters = contentType.cut(';');
						contentType.trim();
					}
					
					String contentDisposition;
					if(!mimeHeaders.get("Content-Disposition", contentDisposition))
						throw Exception("Missing Content-Disposition header in multipart POST request");
					
					String parameters = contentDisposition.cut(';');
					contentDisposition.trim();
					
					String name, fileName;
					while(true)
					{
						String key;
			  			if(!parameters.readUntil(key,';')) break;
						String value = key.cut('=');
						key.trim();
						value.trim();
						value.trimQuotes();
						if(key == "name") name = value;
						else if(key == "filename") fileName = value;
					}
					
					Stream *output = NULL;
					if(fileName.empty()) output = &post[name];
					else {
						post[name] = fileName;
						TempFile *tempFile = new TempFile();
						files[name] = tempFile;
						output = tempFile;
						LogDebug("Http::Request", String("File upload: ") + fileName);
					}
	
					String contentLength;
					if(mimeHeaders.get("Content-Length", contentLength))
					{
						int64_t size = 0;
						contentLength >> size;
						stream->read(*output,size);
						
						String line;
						AssertIO(stream->readLine(line));
						AssertIO(stream->readLine(line));
						if(line == boundary + "--") finished = true;
						else AssertIO(line == boundary);
					}
					else {
					  	/*String line;
						while(stream->readLine(line))
						{
							if(line == boundary) break;
							output->write(line);
							line.clear();
						}*/
						
						// TODO: This must be replaced with Boyer-Moore algorithm for performance
						String bound = String("\r\n") + boundary;
						char *buffer = new char[bound.size()];
						try {
							int size = 0;
							int c = 0;
							int i = 0;
							while(true)
							{
								if(c == size)
								{
									c = 0;
									size = stream->readData(buffer,bound.size()-i);
									AssertIO(size);
								}
								
								if(buffer[c] == bound[i])
								{
									++i; ++c;
									if(i == bound.size())
									{
										// If we are here there is no data left in buffer
										String line;
										AssertIO(stream->readLine(line));
										if(line == "--") finished = true;
										break;
									}
								}
								else {
									if(i) output->writeData(bound.data(), i);
									int d = c;
									while(c != size && buffer[c] != bound[0]) ++c;
									if(c != d) output->writeData(buffer + d, c - d);
									i = 0;
								}
							}
						}	  
						catch(...)
						{
							delete[] buffer;
							throw;
						}
						delete[] buffer;
					}
				}
示例#4
0
bool JsonSerializer::input(String &str)
{
	const String fieldDelimiters = ",:]}";
	
	str.clear();
	
	char chr;
	if(!mStream->get(chr)) return false;
	while(Stream::BlankCharacters.contains(chr))
		if(!mStream->get(chr)) return false;
	
	if(fieldDelimiters.contains(chr))
	{
		if(chr == '}' || chr == ']')
		{
			do {
				if(!mStream->get(chr)) 
					return false;
			}
			while(Stream::BlankCharacters.contains(chr));
		}
		return false;
	}
		
	// Special case: read map or array in string
	if(chr == '{' || chr == '[')
	{
		char opening = chr;
		char closing;
		if(opening ==  '{') closing = '}';
		else closing = ']';
		
		int count = 1;
		str+= chr;
		while(count)
		{
			AssertIO(mStream->get(chr));
			str+= chr;
			
			if(chr == opening) ++count;
			else if(chr == closing) --count;
		}
		
		do {
			if(!mStream->get(chr)) 
				return true;
		}
		while(Stream::BlankCharacters.contains(chr));
		
		AssertIO(fieldDelimiters.contains(chr));
		return true;
	}
		
	bool quotes = (chr == '\'' || chr == '\"');
	
	String delimiters;
	if(quotes)
	{
		delimiters = String(chr);
		AssertIO(mStream->get(chr));
	}
	else {
		str+= chr;
		delimiters = Stream::BlankCharacters;
		delimiters+=fieldDelimiters;
		if(!mStream->get(chr)) return true;
	}

	while(!delimiters.contains(chr))
	{
		if(chr == '\\')
		{
			AssertIO(mStream->get(chr));
			switch(chr)
			{
			case 'b': 	chr = '\b';	break;
			case 'f': 	chr = '\f';	break;
			case 'n': 	chr = '\n';	break;
			case 'r': 	chr = '\r';	break;
			case 't': 	chr = '\t';	break;
			case 'u':
			{
				String tmp;
				AssertIO(mStream->read(tmp, 4));
				
				unsigned u = 0;
				tmp.hexaMode(true);
				tmp >> u;

				wchar_t wstr[2];
				wstr[0] = wchar_t(u);
				wstr[1] = 0;
				
				str+= String(wstr);
				chr = 0;
				break;
			}
			default: 
				if(isalpha(chr) || isdigit(chr)) 
					chr = 0; // unknown escape sequence
				break;
			}
		}

		if(chr) str+= chr;
		if(!mStream->get(chr))
		{
			if(quotes) throw IOException();
			else break;
		}
	}