36 #ifndef _uhal_utilities_files_hpp_
37 #define _uhal_utilities_files_hpp_
47 #include <boost/filesystem/path.hpp>
48 #include <boost/filesystem/operations.hpp>
49 #include <boost/asio/error.hpp>
50 #include <boost/asio/io_service.hpp>
51 #include <boost/asio/ip/tcp.hpp>
52 #include <boost/asio/ip/udp.hpp>
53 #include <boost/asio/streambuf.hpp>
54 #include <boost/asio/read.hpp>
55 #include <boost/asio/write.hpp>
56 #include <boost/spirit/home/qi/parse.hpp>
57 #include <boost/spirit/include/qi_char_.hpp>
58 #include <boost/bind/bind.hpp>
69 #include "boost/unordered_map.hpp"
78 UHAL_DEFINE_EXCEPTION_CLASS ( UriListParsingError ,
"Exception class to handle the case where the string is not a comma-delimiter list of URIs." )
80 UHAL_DEFINE_EXCEPTION_CLASS ( NonSupportedUriProtocol , "Exception class to handle the case where a URI contains a non-supported protocol." )
86 UHAL_DEFINE_EXCEPTION_CLASS ( ExpandingShellExpressionFailed , "Exception class to handle the case where expanding a shell expression failed." )
96 void ParseSemicolonDelimitedUriList (
const std::string& aSemicolonDelimitedUriList , std::vector< std::pair<std::string, std::string> >& aUriList );
114 void ShellExpandFilenameExpr (
const std::string& aFilenameExpr ,
const boost::filesystem::path& aParentPath , std::vector< boost::filesystem::path >& aFiles );
132 template <
bool DebugInfo >
139 log (
Info() ,
"Retrieving URL http://" , aURL );
141 catch (
const std::exception& aExc )
147 std::pair<std::string, std::string> lURLPair;
152 boost::spirit::qi::phrase_parse ( aURL.begin() ,
154 + ( boost::spirit::qi::char_ -
"/" ) >> -boost::spirit::qi::lit (
"/" ) >> + ( boost::spirit::qi::char_ ) ,
155 boost::spirit::ascii::space ,
158 catch (
const std::exception& aExc )
164 boost::system::error_code lErrorCode ( boost::asio::error::host_not_found );
166 boost::asio::io_service io_service;
168 boost::asio::ip::tcp::resolver resolver ( io_service );
169 boost::asio::ip::tcp::resolver::query query ( lURLPair.first ,
"http" );
170 boost::asio::ip::tcp::resolver::iterator endpoint_iterator = resolver.resolve ( query );
171 boost::asio::ip::tcp::resolver::iterator end;
173 boost::asio::ip::tcp::socket socket ( io_service );
177 while ( lErrorCode && endpoint_iterator != end )
180 socket.connect ( *endpoint_iterator++, lErrorCode );
185 throw boost::system::system_error ( lErrorCode );
188 catch (
const std::exception& aExc )
194 boost::asio::streambuf request;
195 std::ostream request_stream ( &request );
196 request_stream <<
"GET /" << lURLPair.second <<
" HTTP/1.0\r\n";
197 request_stream <<
"Host: " << lURLPair.first <<
"\r\n";
198 request_stream <<
"Accept: */*\r\n";
199 request_stream <<
"Connection: close\r\n\r\n";
208 throw boost::system::system_error ( lErrorCode );
211 catch (
const std::exception& aExc )
217 static const int mDefaultBufferSize ( 65536 );
218 typedef std::vector<uint8_t> BufferType;
219 BufferType mBuffer ( mDefaultBufferSize , uint8_t ( 0 ) );
220 std::size_t lSize ( 0 );
227 lSize += boost::asio::read ( socket, boost::asio::buffer ( &mBuffer[lSize] , mDefaultBufferSize ) , lErrorCode );
231 if ( lErrorCode == boost::asio::error::eof )
237 throw boost::system::system_error ( lErrorCode );
241 mBuffer.insert ( mBuffer.end() , mDefaultBufferSize , uint8_t ( 0 ) );
244 catch (
const std::exception& aExc )
249 mBuffer.resize ( lSize );
251 grammars::HttpResponseGrammar lGrammar2;
252 boost::spirit::qi::phrase_parse ( mBuffer.begin() , mBuffer.end() , lGrammar2 , boost::spirit::ascii::space , aResponse );
258 log (
Info() ,
"HTTP response parsed as:\n" , aResponse );
260 catch (
const std::exception& aExc )
262 log (
Error() ,
"EXCEPTION: " , aExc.what() ,
" caught in " ,
ThisLocation() ,
" Continuing." );
267 if ( aResponse.
method !=
"HTTP" || aResponse.
status != 200 )
291 template <
typename R ,
typename F ,
typename L>
292 void OpenFileLocal (
const std::string& aFilenameExpr ,
const boost::filesystem::path& aParentPath , boost::_bi::bind_t<R,F,L> aBinder )
294 std::vector< boost::filesystem::path > lFilePaths;
297 for ( std::vector< boost::filesystem::path >::iterator lIt2 = lFilePaths.begin() ; lIt2 != lFilePaths.end() ; ++ lIt2 )
299 std::ifstream lStr ( lIt2->c_str() );
301 if ( !lStr.is_open() )
303 uhal::exception::CannotOpenFile lExc;
304 log ( lExc ,
"Failed to open file " ,
Quote ( lIt2->c_str() ) );
309 lStr.seekg ( 0, std::ios::end );
310 std::vector<uint8_t> lFile ( lStr.tellg() , 0 );
311 lStr.seekg ( 0, std::ios::beg );
312 lStr.read ( (
char* ) & ( lFile[0] ) , lFile.size() );
313 aBinder ( std::string (
"file" ) , *lIt2 , boost::ref ( lFile ) );
327 template <
typename R ,
typename F ,
typename L>
328 void OpenFileHttp (
const std::string& aURL , boost::_bi::bind_t<R,F,L> aBinder )
332 if ( ! uhal::utilities::HttpGet<true> ( aURL , lHttpResponse ) )
334 uhal::exception::CannotOpenFile lExc;
335 log ( lExc ,
"Failed to download file " ,
Quote ( aURL ) );
339 boost::filesystem::path lFilePath = boost::filesystem::path ( aURL );
340 aBinder ( std::string (
"http" ) , lFilePath , boost::ref ( lHttpResponse.
content ) );
352 template <
typename R ,
typename F ,
typename L>
353 void OpenFile (
const std::string& aProtocol ,
const std::string& aFilenameExpr ,
const boost::filesystem::path& aParentPath , boost::_bi::bind_t<R,F,L> aBinder )
355 if ( aProtocol ==
"file" )
359 else if ( aProtocol ==
"http" )
365 uhal::exception::NonSupportedUriProtocol lExc;
366 log ( lExc ,
"The protocol " ,
Quote ( aProtocol ) ,
" for file " ,
Quote ( aFilenameExpr ) ,
" is not supported." );
367 log ( lExc ,
"The supported protocols are " ,
Quote (
"file://" ) ,
" and " ,
Quote (
"http://" ) );