OPeNDAP Hyrax Back End Server (BES)  Updated for version 3.8.3
mod_opendap.cc
Go to the documentation of this file.
1 // mod_opendap.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 <unistd.h>
34 #include <iostream>
35 
36 using std::cerr ;
37 using std::endl ;
38 using std::cout ;
39 using std::flush ;
40 
41 #include "httpd.h"
42 #include "http_config.h"
43 #include "http_core.h"
44 #include "http_log.h"
45 #include "http_protocol.h"
46 #include "http_request.h"
47 #include "http_main.h"
48 #include "util_script.h"
49 #include "util_md5.h"
50 
52 #include "BESApacheWrapper.h"
53 
54 char * ltoa(long val, char *buf,int base)
55 {
56  ldiv_t r; /* result of val / base */
57  if (base > 36 || base < 2) /* no conversion if wrong base */
58  {
59  *buf = '\0';
60  return buf;
61  }
62  if (val < 0)
63  *buf++ = '-';
64  r = ldiv (labs(val), base);
65  /* output digits of val/base first */
66  if (r.quot > 0)
67  buf = ltoa ( r.quot, buf, base);
68 
69  /* output last digit */
70 
71  *buf++ = "0123456789abcdefghijklmnopqrstuvwxyz"[(int)r.rem];
72  *buf = '\0';
73  return buf;
74 }
75 
76 
77 static int util_read(request_rec *r, const char **rbuf)
78 {
79  int rc = OK;
80 
81  if ((rc = ap_setup_client_block(r, REQUEST_CHUNKED_ERROR)))
82  {
83  return rc;
84  }
85 
86  if (ap_should_client_block(r))
87  {
88  char argsbuffer[HUGE_STRING_LEN];
89  int rsize, len_read, rpos=0;
90  long length = r->remaining;
91  *rbuf = (char*) ap_pcalloc(r->pool, length + 1);
92 
93  ap_hard_timeout("util_read", r);
94 
95  while((len_read = ap_get_client_block(r, argsbuffer, sizeof(argsbuffer))) > 0)
96  {
97  ap_reset_timeout(r);
98  if ((rpos + len_read) > length)
99  {
100  rsize = length - rpos;
101  }
102  else
103  {
104  rsize = len_read;
105  }
106  memcpy((char*)*rbuf + rpos, argsbuffer, rsize);
107  rpos += rsize;
108  }
109 
110  ap_kill_timeout(r);
111  }
112  return rc;
113 }
114 
115 static int
116 header_trace( void *data, const char *key, const char *val )
117 {
118  request_rec *r = (request_rec *)data ;
119  cerr << "Header Field '" << key << "' = '" << val << "'" << endl ;
120  return TRUE ;
121 }
122 
123 static void
124 list_headers( request_rec *r )
125 {
126  ap_table_do( header_trace, r, r->headers_in, NULL ) ;
127 }
128 
129 static int opendap_handler(request_rec *r)
130 {
131  char port_number_buffer[80];
132  dup2(r->connection->client->fd,STDOUT_FILENO);
134 
135  // BEGIN Initialize all data request elements correctly to a null pointer
136  rq.server_name=0;
137  rq.server_address=0;
138  rq.server_protocol=0;
139  rq.server_port=0;
140  rq.script_name=0;
141  rq.user_address=0;
142  rq.user_agent=0;
143  rq.request=0;
144  // END Initialize all the data request elements correctly to a null pointer
145 
146  rq.server_name=ap_get_server_name(r);
147  rq.server_address="jose";
148  rq.server_protocol=r->protocol;
149  ltoa(ap_get_server_port(r), port_number_buffer, 10);
150  rq.server_port=port_number_buffer;
151  rq.script_name=r->uri;
152  rq.user_address=r->connection->remote_ip;
153  rq.user_agent = ap_table_get(r->headers_in, "User-Agent");
154 
155  const char* m_method = r->method;
156  if (!m_method)
157  {
158  cerr << "mod_opendap: Fatal, Cannot load request method" << endl;
159  return SERVER_ERROR;
160  }
161 
162  BESApacheWrapper wrapper;
163  if ( strcmp(m_method, "GET") == 0 )
164  {
165  if(r->parsed_uri.query)
166  {
167  wrapper.process_request(r->parsed_uri.query);
168  rq.cookie=wrapper.process_user(r->parsed_uri.query);
169  rq.token=wrapper.process_token(r->parsed_uri.query);
170  }
171  else
172  {
173  rq.request=0;
174  rq.cookie=0;
175  rq.token=0;
176  }
177  }
178  else if (strcmp(m_method, "POST") == 0 )
179  {
180  const char *post_data=0;
181  util_read(r, &post_data);
182  wrapper.process_request(post_data);
183  rq.cookie=wrapper.process_user(post_data);
184  rq.token=wrapper.process_token(r->parsed_uri.query);
185  }
186  else
187  {
188  rq.request=0;
189  rq.cookie=0;
190  rq.token=0;
191  }
192 
193  // These two lines will print out the header information to the error
194  // log
195  // list_headers( r ) ;
196  // exit( 0 ) ;
197 
198  if( !rq.cookie || !strcmp(rq.cookie,"") )
199  {
200  rq.cookie = ap_table_get( r->headers_in, "Cookie" ) ;
201  }
202 
203  int status = 0 ;
204  rq.request = wrapper.get_first_request() ;
205  while( rq.request && status == 0 )
206  {
207  status = wrapper.call_BES(rq);
208  rq.request = wrapper.get_next_request() ;
209  }
210 
211  // always flush the socket at the end...
212  // and since stdout is now the tcp/ip socket for this connection
213  cout.flush() ;
214 
215  // exit instead of returning
216  exit( 0 ) ;
217 
218  return OK;
219 }
220 
221 /* Make the name of the content handler known to Apache */
222 static handler_rec opendap_handlers[] =
223 {
224  {"opendap-handler", opendap_handler},
225  {NULL}
226 };
227 
228 /* Tell Apache what phases of the transaction we handle */
229 module MODULE_VAR_EXPORT opendap_module =
230 {
231  STANDARD_MODULE_STUFF,
232  NULL, /* module initializer */
233  NULL, /* per-directory config creator */
234  NULL, /* dir config merger */
235  NULL, /* server config creator */
236  NULL, /* server config merger */
237  NULL, /* command table */
238  opendap_handlers, /* [7] content handlers */
239  NULL, /* [2] URI-to-filename translation */
240  NULL, /* [5] check/validate user_id */
241  NULL, /* [6] check user_id is valid *here* */
242  NULL, /* [4] check access by host address */
243  NULL, /* [7] MIME type checker/setter */
244  NULL, /* [8] fixups */
245  NULL, /* [9] logger */
246  NULL, /* [3] header parser */
247  NULL, /* process initialization */
248  NULL, /* process exit/cleanup */
249  NULL /* [1] post read_request handling */
250 };
251