OPeNDAP Hyrax Back End Server (BES) Updated for version 3.8.3
|
00001 // BESApacheInterface.cc 00002 00003 // This file is part of bes, A C++ back-end server implementation framework 00004 // for the OPeNDAP Data Access Protocol. 00005 00006 // Copyright (c) 2004-2009 University Corporation for Atmospheric Research 00007 // Author: Patrick West <pwest@ucar.edu> and Jose Garcia <jgarcia@ucar.edu> 00008 // 00009 // This library is free software; you can redistribute it and/or 00010 // modify it under the terms of the GNU Lesser General Public 00011 // License as published by the Free Software Foundation; either 00012 // version 2.1 of the License, or (at your option) any later version. 00013 // 00014 // This library is distributed in the hope that it will be useful, 00015 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00017 // Lesser General Public License for more details. 00018 // 00019 // You should have received a copy of the GNU Lesser General Public 00020 // License along with this library; if not, write to the Free Software 00021 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00022 // 00023 // You can contact University Corporation for Atmospheric Research at 00024 // 3080 Center Green Drive, Boulder, CO 80301 00025 00026 // (c) COPYRIGHT University Corporation for Atmospheric Research 2004-2005 00027 // Please read the full copyright statement in the file COPYRIGHT_UCAR. 00028 // 00029 // Authors: 00030 // pwest Patrick West <pwest@ucar.edu> 00031 // jgarcia Jose Garcia <jgarcia@ucar.edu> 00032 00033 #include <iostream> 00034 00035 using std::cout ; 00036 using std::endl ; 00037 using std::flush ; 00038 00039 #include "BESApacheInterface.h" 00040 #include "BESMemoryManager.h" 00041 00042 #include "BESLog.h" 00043 #include "TheBESKeys.h" 00044 #include "BESMemoryGlobalArea.h" 00045 #include "BESInternalError.h" 00046 #include "BESUtil.h" 00047 #include "BESBasicHttpTransmitter.h" 00048 #include "BESAggregationServer.h" 00049 #include "BESDataNames.h" 00050 #include "BESDebug.h" 00051 00052 #define DEFAULT_ADMINISTRATOR "cedar_db@hao.ucar.edu" 00053 #define INCORRECT_REQUEST (BES_NOT_FOUND_ERROR + 1) 00054 #define INCORRECT_REQUEST_MSG "undefined request" 00055 00063 BESApacheInterface::BESApacheInterface( const BESDataRequestInterface &dri ) 00064 : BESCmdInterface( "", &cout ) 00065 { 00066 _dri = &dri ; 00067 } 00068 00069 BESApacheInterface::~BESApacheInterface() 00070 { 00071 clean() ; 00072 } 00073 00084 int 00085 BESApacheInterface::execute_request() 00086 { 00087 BESMemoryManager::register_global_pool() ; 00088 00089 int status = BESCmdInterface::execute_request( "cedar" ) ; 00090 00091 if( !BESMemoryManager::unregister_global_pool() ) 00092 return BES_INTERNAL_FATAL_ERROR ; 00093 00094 return status; 00095 } 00096 00104 void 00105 find_user_from_cookie( const char *cookie, string &user ) 00106 { 00107 if( cookie ) 00108 { 00109 string s_cookie = cookie ; 00110 string var = "OpenDAP.remoteuser=" ; 00111 int user_var = s_cookie.find( var ) ; 00112 if( user_var >= 0 ) 00113 { 00114 string s_user_var = s_cookie.substr( user_var + var.length(), 00115 s_cookie.length() ) ; 00116 int semi = s_user_var.find( ";" ) ; 00117 if( semi < 0 ) 00118 { 00119 user = s_user_var ; 00120 } 00121 else 00122 { 00123 user = s_user_var.substr( 0, semi ) ; 00124 } 00125 } 00126 } 00127 } 00128 00147 void 00148 BESApacheInterface::initialize() 00149 { 00150 BESMemoryManager::initialize_memory_pool() ; 00151 00152 string https = _dri->server_protocol ; 00153 std::string::size_type http = https.find("HTTP"); 00154 if( http == string::npos ) 00155 { 00156 _dhi.transmit_protocol = _dri->server_protocol ; 00157 } 00158 else 00159 { 00160 _dhi.transmit_protocol = "HTTP" ; 00161 } 00162 00163 _dhi.data[USER_ADDRESS] = _dri->user_address ; 00164 _dhi.data[DATA_REQUEST] = _dri->request ; 00165 00166 string user = "undef" ; 00167 if( _dri->cookie ) 00168 { 00169 find_user_from_cookie( _dri->cookie, user ) ; 00170 } 00171 00172 _dhi.data[USER_NAME] = user ; 00173 _dhi.data[USER_TOKEN] = _dri->token ; 00174 00175 if( BESLog::TheLog() && BESLog::TheLog()->is_verbose() ) 00176 { 00177 *(BESLog::TheLog()) << "Data Request Interface:" << endl ; 00178 *(BESLog::TheLog()) << " server_name = " << _dri->server_name << endl ; 00179 *(BESLog::TheLog()) << " server_address = " << _dri->server_address << endl ; 00180 *(BESLog::TheLog()) << " server_protocol = " << _dri->server_protocol << endl ; 00181 *(BESLog::TheLog()) << " server_port = " << _dri->server_port << endl ; 00182 *(BESLog::TheLog()) << " script_name = " << _dri->script_name << endl ; 00183 *(BESLog::TheLog()) << " user_address = " << _dri->user_address << endl ; 00184 *(BESLog::TheLog()) << " user_agent = " << _dri->user_agent << endl ; 00185 *(BESLog::TheLog()) << " request = " << _dri->request << endl ; 00186 if( _dri->cookie ) 00187 *(BESLog::TheLog()) << " cookie = " << _dri->cookie << endl ; 00188 else 00189 *(BESLog::TheLog()) << " cookie = no cookie set" << endl ; 00190 } 00191 00192 BESDEBUG( "apache", "BESApacheInterface dhi = " << _dhi << endl ) 00193 00194 BESCmdInterface::initialize() ; 00195 } 00196 00199 void 00200 BESApacheInterface::validate_data_request() 00201 { 00202 if (!_dri->server_name) 00203 { 00204 BESInternalError e("undefined server name", __FILE__, __LINE__ ); 00205 e.set_error_type( INCORRECT_REQUEST ) ; 00206 throw e ; 00207 } 00208 if(!_dri->server_address) 00209 { 00210 BESInternalError e("undefined server address", __FILE__, __LINE__ ); 00211 e.set_error_type( INCORRECT_REQUEST ) ; 00212 throw e ; 00213 } 00214 if(!_dri->server_protocol) 00215 { 00216 BESInternalError e("undefined server protocol", __FILE__, __LINE__ ); 00217 e.set_error_type( INCORRECT_REQUEST ) ; 00218 throw e ; 00219 } 00220 if(!_dri->server_port) 00221 { 00222 BESInternalError e("undefined server port", __FILE__, __LINE__ ); 00223 e.set_error_type( INCORRECT_REQUEST ) ; 00224 throw e ; 00225 } 00226 if(!_dri->script_name) 00227 { 00228 BESInternalError e("undefined script name", __FILE__, __LINE__ ); 00229 e.set_error_type( INCORRECT_REQUEST ) ; 00230 throw e ; 00231 } 00232 if(!_dri->user_address) 00233 { 00234 BESInternalError e("undefined user address", __FILE__, __LINE__ ); 00235 e.set_error_type( INCORRECT_REQUEST ) ; 00236 throw e ; 00237 } 00238 if(!_dri->user_agent) 00239 { 00240 BESInternalError e("undefined user agent", __FILE__, __LINE__ ); 00241 e.set_error_type( INCORRECT_REQUEST ) ; 00242 throw e ; 00243 } 00244 if(!_dri->request) 00245 { 00246 BESInternalError e(INCORRECT_REQUEST_MSG, __FILE__, __LINE__ ); 00247 e.set_error_type( INCORRECT_REQUEST ) ; 00248 throw e ; 00249 } 00250 } 00251 00269 int 00270 BESApacheInterface::exception_manager( BESError &e ) 00271 { 00272 bool ishttp = false ; 00273 if( _dhi.transmit_protocol == "HTTP" ) 00274 ishttp = true ; 00275 00276 if( e.get_error_type() == INCORRECT_REQUEST ) 00277 { 00278 if( e.get_message() == INCORRECT_REQUEST_MSG ) 00279 { 00280 // Everything is OK but BESDataRequestInterface::request is null. 00281 if( ishttp ) 00282 { 00283 welcome_browser(); 00284 } 00285 } 00286 else 00287 { 00288 return BESCmdInterface::exception_manager( e ) ; 00289 } 00290 return BES_INTERNAL_ERROR ; 00291 } 00292 return BESCmdInterface::exception_manager( e ) ; 00293 } 00294 00295 void 00296 BESApacheInterface::welcome_browser() 00297 { 00298 string who = _dri->user_address ; 00299 string agent = _dri->user_agent ; 00300 if( BESLog::TheLog() ) 00301 (*BESLog::TheLog()) << "Incoming request from " << who.c_str() << " using " << agent.c_str() << endl; 00302 00303 // see if request comes from the Netscape or the HotJava... 00304 int mo=agent.find("Mozilla"); 00305 int ho=agent.find("HotJava"); 00306 if ((mo<0)&&(ho<0)) // No, sorry. For you just a message and good bye :-( 00307 { 00308 BESUtil::set_mime_text( cout ) ; 00309 bool found = false ; 00310 string administrator = 00311 TheBESKeys::TheKeys()->get_key( "BES.ServerAdministrator", found ) ; 00312 if(administrator=="") 00313 cout << "BES: internal server error please contact" 00314 << DEFAULT_ADMINISTRATOR 00315 << "with the following message:\n" ; 00316 else 00317 cout << "BES: internal server error please contact" 00318 << administrator.c_str() 00319 << "with the following message:\n" ; 00320 cout << "BES: cannot interact with browser" << agent.c_str() << endl ; 00321 } 00322 else // Yes, _agent contains the signature of a browser 00323 { 00324 bool found = false ; 00325 string method = 00326 TheBESKeys::TheKeys()->get_key( "BES.DefaultResponseMethod", found ) ; 00327 if( (method!="GET") && (method!="POST") ) 00328 { 00329 BESUtil::set_mime_text( cout ) ; 00330 found = false ; 00331 string administrator = 00332 TheBESKeys::TheKeys()->get_key( "BES.ServerAdministrator", found ) ; 00333 if(administrator=="") 00334 cout << "BES: internal server error please contact" 00335 << DEFAULT_ADMINISTRATOR 00336 << "with the following message:\n" ; 00337 else 00338 cout << "BES: internal server error please contact" 00339 << administrator.c_str() 00340 << "with the following message:\n" ; 00341 cout << "BES: fatal, cannot get/understand the key BES.DefaultResponseMethod" 00342 << endl ; 00343 } 00344 else 00345 { 00346 cout << "HTTP/1.0 200 OK\n" ; 00347 cout << "Content-type: text/html\n\n" ; 00348 cout << flush ; 00349 00350 cout << "<HTML>\n" ; 00351 cout << "<HEAD>\n" ; 00352 cout << "<TITLE> Request to the BES server</TITLE>\n" ; 00353 cout << "<BODY>\n" ; 00354 if (method=="GET") 00355 cout << "<form action=\"http://" << _dri->server_name 00356 << ":" << _dri->server_port << _dri->script_name 00357 << "\" method=get>\n" ; 00358 else if (method=="POST") 00359 cout << "<form action=\"http://" << _dri->server_name 00360 << ":" << _dri->server_port << _dri->script_name 00361 << "\" method=post>\n" ; 00362 00363 cout << "<p>Request: <br><textarea name=\"request\" cols=85 rows=11 size=40,4 wrap=\"virtual\" ></textarea></p>\n" ; 00364 cout << "<input type=\"submit\" value=\"Submit to BES\">\n" ; 00365 cout << "<input type=\"reset\" value=\"Clean Text Field\">\n" ; 00366 cout << "</form>\n" ; 00367 cout << "</body>\n" ; 00368 cout << "</html>\n" ; 00369 } 00370 } 00371 } 00372