예제 #1
0
			bool setupNextStream()
			{
				if ( Vinnext != Vin.end() )
				{
					libmaus2::lz::SnappyInputStream::unique_ptr_type tSIS(new libmaus2::lz::SnappyInputStream(**(Vinnext++)));
					pSIS = UNIQUE_PTR_MOVE(tSIS);
					return true;
				}
				else
				{
					return false;
				}
			}
예제 #2
0
파일: HttpHeader.hpp 프로젝트: dkj/libmaus2
			void init(
				std::string method, 
				std::string addreq, 
				std::string host, 
				std::string path, unsigned int port = 80, bool ssl = false
			)
			{
				bool headercomplete = false;
				
				std::set<InitParameters> seen;

				while ( ! headercomplete )
				{
					InitParameters const initparams(method,addreq,host,path,port,ssl);
					
					if ( seen.find(initparams) != seen.end() )
					{
						libmaus2::exception::LibMausException lme;
						lme.getStream() << "HttpHeader: redirect loop detected, method=" << method << " host=" << host << " path=" << path << " port=" << port << " ssl=" << ssl << std::endl;
						lme.finish();
						throw lme;	
					}
					
					seen.insert(initparams);
				
					fields.clear();
					
					CS.reset();
					OS.reset();
					SIS.reset();
					GTLSIOS.reset();
					SIOS = 0;
					
					bool const hasproxy =
						(ssl && hasHttpsProxy())
						||
						((!ssl) && hasHttpProxy());
						
					if ( hasproxy )
					{
						HttpAbsoluteUrl proxyurl =
							ssl ? HttpAbsoluteUrl(getenv("https_proxy")) : HttpAbsoluteUrl(getenv("http_proxy"));
						
						// std::cerr << "[D] using proxy " << proxyurl << std::endl;
							
						if ( proxyurl.ssl )
						{
							#if defined(LIBMAUS2_HAVE_GNUTLS)
							libmaus2::network::GnuTLSSocket::unique_ptr_type tGTLSIOS(new libmaus2::network::GnuTLSSocket(proxyurl.host,proxyurl.port,"/etc/ssl/certs/ca-certificates.crt","/etc/ssl/certs",true));
							GTLSIOS = UNIQUE_PTR_MOVE(tGTLSIOS);
							SIOS = GTLSIOS.get();
							#else	
							libmaus2::network::OpenSSLSocket::unique_ptr_type tOS(new libmaus2::network::OpenSSLSocket(proxyurl.host,proxyurl.port,0,"/etc/ssl/certs",true));
							OS = UNIQUE_PTR_MOVE(tOS);						
							SIOS = OS.get();
							#endif

							libmaus2::network::SocketInputStream::unique_ptr_type tSIS(new libmaus2::network::SocketInputStream(*SIOS,64*1024));
							SIS = UNIQUE_PTR_MOVE(tSIS);
						}
						else
						{
							libmaus2::network::ClientSocket::unique_ptr_type tCS(new libmaus2::network::ClientSocket(proxyurl.port,proxyurl.host.c_str()));
							CS = UNIQUE_PTR_MOVE(tCS);

							SIOS = CS.get();
						
							libmaus2::network::SocketInputStream::unique_ptr_type tSIS(new libmaus2::network::SocketInputStream(*CS,64*1024));
							SIS = UNIQUE_PTR_MOVE(tSIS);
						}						
					}
					else
					{
						if ( ssl )
						{
							#if defined(LIBMAUS2_HAVE_GNUTLS)
							libmaus2::network::GnuTLSSocket::unique_ptr_type tGTLSIOS(new libmaus2::network::GnuTLSSocket(host,port,"/etc/ssl/certs/ca-certificates.crt","/etc/ssl/certs",true));
							GTLSIOS = UNIQUE_PTR_MOVE(tGTLSIOS);
							
							SIOS = GTLSIOS.get();
							#else
							libmaus2::network::OpenSSLSocket::unique_ptr_type tOS(new libmaus2::network::OpenSSLSocket(host,port,0,"/etc/ssl/certs",true));
							OS = UNIQUE_PTR_MOVE(tOS);
						
							SIOS = OS.get();
							#endif

							libmaus2::network::SocketInputStream::unique_ptr_type tSIS(new libmaus2::network::SocketInputStream(*SIOS,64*1024));
							SIS = UNIQUE_PTR_MOVE(tSIS);
						}
						else
						{
							libmaus2::network::ClientSocket::unique_ptr_type tCS(new libmaus2::network::ClientSocket(port,host.c_str()));
							CS = UNIQUE_PTR_MOVE(tCS);

							SIOS = CS.get();
						
							libmaus2::network::SocketInputStream::unique_ptr_type tSIS(new libmaus2::network::SocketInputStream(*CS,64*1024));
							SIS = UNIQUE_PTR_MOVE(tSIS);
						}
					}
					
					std::ostringstream reqastr;

					if ( hasproxy )
					{
						reqastr << method << " " 
							<< (ssl ? "https" : "http")
							<< "://"
							<< host
							<< ":"
							<< port
							<< path 
							<< " HTTP/1.1\r\n";
						reqastr << "Connection: close\r\n";
					}
					else
					{
						reqastr << method << " " << path << " HTTP/1.1\r\n";
						reqastr << "Host: " << host << "\r\n";
					}

					reqastr << addreq;
					reqastr << "\r\n";

					// send request
					std::string const reqa = reqastr.str();
					SIOS->write(reqa.c_str(),reqa.size());

					libmaus2::autoarray::AutoArray<char> c(128,false);
					char last4[4] = {0,0,0,0};
					bool done = false;
					
					std::ostringstream headstr;
					
					while ( !done )
					{
						SIS->readsome(c.begin(),c.size());
						ssize_t r = SIS->gcount();
						
						// buffer is empty, try to fill it
						if ( ! r )
						{
							SIS->read(c.begin(),1);
							r = SIS->gcount();
							
							if ( ! r )
							{
								libmaus2::exception::LibMausException lme;
								lme.getStream() << "HttpHeader: unexpected EOF/error while reading header" << std::endl;
								lme.finish();
								throw lme;	
							}
							else
							{
								SIS->unget();
								continue;
							}
						}
						
						for ( ssize_t i = 0; (!done) && i < r; ++i )
						{
							headstr.put(c[i]);
							
							last4[0] = last4[1];
							last4[1] = last4[2];
							last4[2] = last4[3];
							last4[3] = c[i];
						
							if ( 
								last4[0] == '\r' && 
								last4[1] == '\n' && 
								last4[2] == '\r' && 
								last4[3] == '\n'
							)
							{
								for ( ssize_t j = i+1; j < r; ++j )
									SIS->unget();

								// SIS->clear();
								done = true;
							}
						}			
					}
					
					std::istringstream linestr(headstr.str());
					std::vector<std::string> lines;
					while ( linestr )
					{
						std::string line;
						std::getline(linestr,line);
						
						while ( line.size() && isspace(line[line.size()-1]) )
						{
							line = line.substr(0,line.size()-1);
						}
						
						if ( line.size() )
							lines.push_back(line);
					}
					
					if ( ! lines.size() )
					{
						libmaus2::exception::LibMausException lme;
						lme.getStream() << "HttpHeader: unable to get header" << std::endl;
						lme.finish();
						throw lme;
					}
					
					statusline = lines[0];
					std::vector<std::string> statustokens;
					for ( uint64_t i = 0; i < statusline.size(); )
					{
						while ( i < statusline.size() && isspace(statusline[i]) )
							++i;

						uint64_t j = i;					
						while ( j < statusline.size() && (!isspace(statusline[j])) )
							++j;
							
						std::string const token = statusline.substr(i,j-i);
						
						i = j;
						
						statustokens.push_back(token);
					}
					
					if ( statustokens.size() < 2 )
					{			
						libmaus2::exception::LibMausException lme;
						lme.getStream() << "HttpHeader: status line " << statusline << " invalid" << std::endl;
						lme.finish();
						throw lme;
					}
				
					std::string const replyformat = statustokens[0];	
					std::istringstream statuscodeistr(statustokens[1]);
					uint64_t statuscode;
					statuscodeistr >> statuscode;
					
					if ( ! statuscodeistr )
					{
						libmaus2::exception::LibMausException lme;
						lme.getStream() << "HttpHeader: invalid status code " << statustokens[1] << std::endl;
						lme.finish();
						throw lme;			
					}
					
					if (
						replyformat != "HTTP/1.0"
						&&
						replyformat != "HTTP/1.1"
					)
					{
						libmaus2::exception::LibMausException lme;
						lme.getStream() << "HttpHeader: unknown reply format " << replyformat << std::endl;
						lme.finish();
						throw lme;						
					}
					
					// std::cerr << "status code " << statuscode << std::endl;
					
					for ( uint64_t i = 1; i < lines.size(); ++i )
					{
						std::string const line = lines[i];
						
						uint64_t col = 0;
						while ( col < line.size() && line[col] != ':' )
							++col;
						
						if ( ! col || col == line.size() )
						{
							libmaus2::exception::LibMausException lme;
							lme.getStream() << "HttpHeader: invalid key value pair " << line << std::endl;
							lme.finish();
							throw lme;						
						}
						
						std::string const key = tolower(despace(line.substr(0,col)));
						std::string const val = despace(line.substr(col+1));
						
						fields[key] = val;
					}
					
					switch ( statuscode )
					{
						case 301:
						case 302:
						case 307:
						case 308:
						{				
							std::map<std::string,std::string>::const_iterator it = fields.end();
							
							if ( it == fields.end() )
								it = fields.find("Location");
							if ( it == fields.end() )
								it = fields.find("location");
							
							if ( it == fields.end() )
							{	
								libmaus2::exception::LibMausException lme;
								lme.getStream() << "HttpHeader: redirect status code " << statuscode << " but no location given" << std::endl;
								lme.finish();
								throw lme;						
							}
							
							std::string location = it->second;

							// std::cerr << "redirecting " << statuscode << " to " << location << std::endl;
							
							if ( 
								::libmaus2::network::HttpAbsoluteUrl::isHttpAbsoluteUrl(location) 
								||
								::libmaus2::network::HttpAbsoluteUrl::isHttpsAbsoluteUrl(location) 
							)
							{
								::libmaus2::network::HttpAbsoluteUrl url(location);
								host = url.host;
								port = url.port;
								path = url.path;
								ssl = url.ssl;
							}
							else if ( ::libmaus2::network::HttpAbsoluteUrl::isAbsoluteUrl(location) )
							{
								libmaus2::exception::LibMausException lme;
								lme.getStream() << "HttpHeader: unsupported protocol in location " << location << std::endl;
								lme.finish();
								throw lme;						
							}
							else
							{
								path = location;
							}
							
							break;
						}
						default:
						{
							headercomplete = true;
							break;
						}
					}	
				}	
				
				#if 0
				std::cerr << statusline << std::endl;
				for ( std::map<std::string,std::string>::const_iterator ita = fields.begin(); ita != fields.end(); ++ita )
				{
					std::cerr << ita->first << ": " << ita->second << std::endl;
				}
				#endif
				
				url.host = host;
				url.port = port;
				url.path = path;
				url.ssl = ssl;		
			}