OPeNDAP Hyrax Back End Server (BES)  Updated for version 3.8.3
BESApacheInterface.cc
Go to the documentation of this file.
1 // BESApacheInterface.cc
2 
3 // This file is part of bes, A C++ back-end server implementation framework
4 // for the OPeNDAP Data Access Protocol.
5 
6 // Copyright (c) 2004-2009 University Corporation for Atmospheric Research
7 // Author: Patrick West <pwest@ucar.edu> and Jose Garcia <jgarcia@ucar.edu>
8 //
9 // This library is free software; you can redistribute it and/or
10 // modify it under the terms of the GNU Lesser General Public
11 // License as published by the Free Software Foundation; either
12 // version 2.1 of the License, or (at your option) any later version.
13 //
14 // This library is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 // Lesser General Public License for more details.
18 //
19 // You should have received a copy of the GNU Lesser General Public
20 // License along with this library; if not, write to the Free Software
21 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 //
23 // You can contact University Corporation for Atmospheric Research at
24 // 3080 Center Green Drive, Boulder, CO 80301
25 
26 // (c) COPYRIGHT University Corporation for Atmospheric Research 2004-2005
27 // Please read the full copyright statement in the file COPYRIGHT_UCAR.
28 //
29 // Authors:
30 // pwest Patrick West <pwest@ucar.edu>
31 // jgarcia Jose Garcia <jgarcia@ucar.edu>
32 
33 #include <iostream>
34 
35 using std::cout ;
36 using std::endl ;
37 using std::flush ;
38 
39 #include "BESApacheInterface.h"
40 #include "BESMemoryManager.h"
41 
42 #include "BESLog.h"
43 #include "TheBESKeys.h"
44 #include "BESMemoryGlobalArea.h"
45 #include "BESInternalError.h"
46 #include "BESUtil.h"
48 #include "BESAggregationServer.h"
49 #include "BESDataNames.h"
50 #include "BESDebug.h"
51 
52 #define DEFAULT_ADMINISTRATOR "cedar_db@hao.ucar.edu"
53 #define INCORRECT_REQUEST (BES_NOT_FOUND_ERROR + 1)
54 #define INCORRECT_REQUEST_MSG "undefined request"
55 
64  : BESCmdInterface( "", &cout )
65 {
66  _dri = &dri ;
67 }
68 
70 {
71  clean() ;
72 }
73 
84 int
86 {
88 
89  int status = BESCmdInterface::execute_request( "cedar" ) ;
90 
93 
94  return status;
95 }
96 
104 void
105 find_user_from_cookie( const char *cookie, string &user )
106 {
107  if( cookie )
108  {
109  string s_cookie = cookie ;
110  string var = "OpenDAP.remoteuser=" ;
111  int user_var = s_cookie.find( var ) ;
112  if( user_var >= 0 )
113  {
114  string s_user_var = s_cookie.substr( user_var + var.length(),
115  s_cookie.length() ) ;
116  int semi = s_user_var.find( ";" ) ;
117  if( semi < 0 )
118  {
119  user = s_user_var ;
120  }
121  else
122  {
123  user = s_user_var.substr( 0, semi ) ;
124  }
125  }
126  }
127 }
128 
147 void
149 {
151 
152  string https = _dri->server_protocol ;
153  std::string::size_type http = https.find("HTTP");
154  if( http == string::npos )
155  {
156  _dhi.transmit_protocol = _dri->server_protocol ;
157  }
158  else
159  {
160  _dhi.transmit_protocol = "HTTP" ;
161  }
162 
163  _dhi.data[USER_ADDRESS] = _dri->user_address ;
164  _dhi.data[DATA_REQUEST] = _dri->request ;
165 
166  string user = "undef" ;
167  if( _dri->cookie )
168  {
169  find_user_from_cookie( _dri->cookie, user ) ;
170  }
171 
172  _dhi.data[USER_NAME] = user ;
173  _dhi.data[USER_TOKEN] = _dri->token ;
174 
175  if( BESLog::TheLog() && BESLog::TheLog()->is_verbose() )
176  {
177  *(BESLog::TheLog()) << "Data Request Interface:" << endl ;
178  *(BESLog::TheLog()) << " server_name = " << _dri->server_name << endl ;
179  *(BESLog::TheLog()) << " server_address = " << _dri->server_address << endl ;
180  *(BESLog::TheLog()) << " server_protocol = " << _dri->server_protocol << endl ;
181  *(BESLog::TheLog()) << " server_port = " << _dri->server_port << endl ;
182  *(BESLog::TheLog()) << " script_name = " << _dri->script_name << endl ;
183  *(BESLog::TheLog()) << " user_address = " << _dri->user_address << endl ;
184  *(BESLog::TheLog()) << " user_agent = " << _dri->user_agent << endl ;
185  *(BESLog::TheLog()) << " request = " << _dri->request << endl ;
186  if( _dri->cookie )
187  *(BESLog::TheLog()) << " cookie = " << _dri->cookie << endl ;
188  else
189  *(BESLog::TheLog()) << " cookie = no cookie set" << endl ;
190  }
191 
192  BESDEBUG( "apache", "BESApacheInterface dhi = " << _dhi << endl )
193 
194  BESCmdInterface::initialize() ;
195 }
196 
199 void
201 {
202  if (!_dri->server_name)
203  {
204  BESInternalError e("undefined server name", __FILE__, __LINE__ );
206  throw e ;
207  }
208  if(!_dri->server_address)
209  {
210  BESInternalError e("undefined server address", __FILE__, __LINE__ );
212  throw e ;
213  }
214  if(!_dri->server_protocol)
215  {
216  BESInternalError e("undefined server protocol", __FILE__, __LINE__ );
218  throw e ;
219  }
220  if(!_dri->server_port)
221  {
222  BESInternalError e("undefined server port", __FILE__, __LINE__ );
224  throw e ;
225  }
226  if(!_dri->script_name)
227  {
228  BESInternalError e("undefined script name", __FILE__, __LINE__ );
230  throw e ;
231  }
232  if(!_dri->user_address)
233  {
234  BESInternalError e("undefined user address", __FILE__, __LINE__ );
236  throw e ;
237  }
238  if(!_dri->user_agent)
239  {
240  BESInternalError e("undefined user agent", __FILE__, __LINE__ );
242  throw e ;
243  }
244  if(!_dri->request)
245  {
246  BESInternalError e(INCORRECT_REQUEST_MSG, __FILE__, __LINE__ );
248  throw e ;
249  }
250 }
251 
269 int
271 {
272  bool ishttp = false ;
273  if( _dhi.transmit_protocol == "HTTP" )
274  ishttp = true ;
275 
276  if( e.get_error_type() == INCORRECT_REQUEST )
277  {
279  {
280  // Everything is OK but BESDataRequestInterface::request is null.
281  if( ishttp )
282  {
283  welcome_browser();
284  }
285  }
286  else
287  {
288  return BESCmdInterface::exception_manager( e ) ;
289  }
290  return BES_INTERNAL_ERROR ;
291  }
292  return BESCmdInterface::exception_manager( e ) ;
293 }
294 
295 void
296 BESApacheInterface::welcome_browser()
297 {
298  string who = _dri->user_address ;
299  string agent = _dri->user_agent ;
300  if( BESLog::TheLog() )
301  (*BESLog::TheLog()) << "Incoming request from " << who.c_str() << " using " << agent.c_str() << endl;
302 
303  // see if request comes from the Netscape or the HotJava...
304  int mo=agent.find("Mozilla");
305  int ho=agent.find("HotJava");
306  if ((mo<0)&&(ho<0)) // No, sorry. For you just a message and good bye :-(
307  {
308  BESUtil::set_mime_text( cout ) ;
309  bool found = false ;
310  string administrator =
311  TheBESKeys::TheKeys()->get_key( "BES.ServerAdministrator", found ) ;
312  if(administrator=="")
313  cout << "BES: internal server error please contact"
315  << "with the following message:\n" ;
316  else
317  cout << "BES: internal server error please contact"
318  << administrator.c_str()
319  << "with the following message:\n" ;
320  cout << "BES: cannot interact with browser" << agent.c_str() << endl ;
321  }
322  else // Yes, _agent contains the signature of a browser
323  {
324  bool found = false ;
325  string method =
326  TheBESKeys::TheKeys()->get_key( "BES.DefaultResponseMethod", found ) ;
327  if( (method!="GET") && (method!="POST") )
328  {
329  BESUtil::set_mime_text( cout ) ;
330  found = false ;
331  string administrator =
332  TheBESKeys::TheKeys()->get_key( "BES.ServerAdministrator", found ) ;
333  if(administrator=="")
334  cout << "BES: internal server error please contact"
335  << DEFAULT_ADMINISTRATOR
336  << "with the following message:\n" ;
337  else
338  cout << "BES: internal server error please contact"
339  << administrator.c_str()
340  << "with the following message:\n" ;
341  cout << "BES: fatal, cannot get/understand the key BES.DefaultResponseMethod"
342  << endl ;
343  }
344  else
345  {
346  cout << "HTTP/1.0 200 OK\n" ;
347  cout << "Content-type: text/html\n\n" ;
348  cout << flush ;
349 
350  cout << "<HTML>\n" ;
351  cout << "<HEAD>\n" ;
352  cout << "<TITLE> Request to the BES server</TITLE>\n" ;
353  cout << "<BODY>\n" ;
354  if (method=="GET")
355  cout << "<form action=\"http://" << _dri->server_name
356  << ":" << _dri->server_port << _dri->script_name
357  << "\" method=get>\n" ;
358  else if (method=="POST")
359  cout << "<form action=\"http://" << _dri->server_name
360  << ":" << _dri->server_port << _dri->script_name
361  << "\" method=post>\n" ;
362 
363  cout << "<p>Request: <br><textarea name=\"request\" cols=85 rows=11 size=40,4 wrap=\"virtual\" ></textarea></p>\n" ;
364  cout << "<input type=\"submit\" value=\"Submit to BES\">\n" ;
365  cout << "<input type=\"reset\" value=\"Clean Text Field\">\n" ;
366  cout << "</form>\n" ;
367  cout << "</body>\n" ;
368  cout << "</html>\n" ;
369  }
370  }
371 }
372 
#define USER_ADDRESS
Definition: BESDataNames.h:47
const char * user_address
remote ip address of client machine
#define USER_TOKEN
Definition: BESDataNames.h:49
#define DATA_REQUEST
Definition: BESDataNames.h:36
#define DEFAULT_ADMINISTRATOR
exception thrown if inernal error encountered
#define BES_INTERNAL_ERROR
Definition: BESError.h:42
virtual int execute_request()
Override execute_request in order to register memory pool.
#define INCORRECT_REQUEST
virtual void set_error_type(int type)
Set the return code for this particular error class.
Definition: BESError.h:112
const char * server_port
TCP port number where the server running Apache is listening.
void find_user_from_cookie(const char *cookie, string &user)
Find and set the user from the cookie set in the browser.
static BESMemoryGlobalArea * initialize_memory_pool()
const char * script_name
uri of the request
#define INCORRECT_REQUEST_MSG
virtual int get_error_type()
Return the return code for this error class.
Definition: BESError.h:120
virtual string get_message()
get the error message for this exception
Definition: BESError.h:91
const char * server_name
name of server running Apache server
Structure storing information from the Apache module.
Abstract exception class for the BES with basic string message.
Definition: BESError.h:51
const char * server_address
not used
static void set_mime_text(ostream &strm)
Generate an HTTP 1.0 response header for a text document.
Definition: BESUtil.cc:65
const char * request
BES request string.
virtual void initialize()
Initialize the BES object from the apache environment.
#define BES_INTERNAL_FATAL_ERROR
Definition: BESError.h:43
#define USER_NAME
Definition: BESDataNames.h:48
const char * token
session token passed in URL
const char * cookie
server cookies set in users browser
static BESLog * TheLog()
Definition: BESLog.cc:347
#define BESDEBUG(x, y)
macro used to send debug information to the debug stream
Definition: BESDebug.h:64
virtual int exception_manager(BESError &e)
Handle any exceptions generated from the request.
static void register_global_pool()
const char * user_agent
information about the user agent originating the request, e.g.
static BESKeys * TheKeys()
Definition: TheBESKeys.cc:48
static bool unregister_global_pool()
BESApacheInterface(const BESDataRequestInterface &dri)
Instantiate a BESApacheInterface object.
const char * server_protocol
protocol of the request, such as "HTTP/0.9" or "HTTP/1.1"
virtual void validate_data_request()
Validate the information in the BESDataRequestInterface.