metaproxy  1.21.0
Classes | Public Member Functions | Private Attributes | List of all members
metaproxy_1::filter::CGI Class Reference

#include <filter_cgi.hpp>

Inheritance diagram for metaproxy_1::filter::CGI:
Inheritance graph
Collaboration diagram for metaproxy_1::filter::CGI:
Collaboration graph

Classes

class  Exec
 
class  Rep
 

Public Member Functions

 CGI ()
 
 ~CGI ()
 
void process (metaproxy_1::Package &package) const
 
void configure (const xmlNode *ptr, bool test_only, const char *path)
 

Private Attributes

boost::scoped_ptr< Repm_p
 

Detailed Description

Definition at line 28 of file filter_cgi.hpp.

Constructor & Destructor Documentation

◆ CGI()

mp::filter::CGI::CGI ( )

Definition at line 60 of file filter_cgi.cpp.

60  : m_p(new Rep)
61 {
62 
63 }
boost::scoped_ptr< Rep > m_p
Definition: filter_cgi.hpp:30

◆ ~CGI()

mp::filter::CGI::~CGI ( )

Definition at line 74 of file filter_cgi.cpp.

75 {
76 }

Member Function Documentation

◆ configure()

void mp::filter::CGI::configure ( const xmlNode *  ptr,
bool  test_only,
const char *  path 
)

Definition at line 294 of file filter_cgi.cpp.

295 {
296  yaz_log(YLOG_LOG, "cgi::configure path=%s", path);
297  for (ptr = ptr->children; ptr; ptr = ptr->next)
298  {
299  if (ptr->type != XML_ELEMENT_NODE)
300  continue;
301  if (!strcmp((const char *) ptr->name, "map"))
302  {
303  CGI::Exec exec;
304 
305  const struct _xmlAttr *attr;
306  for (attr = ptr->properties; attr; attr = attr->next)
307  {
308  if (!strcmp((const char *) attr->name, "path"))
309  exec.path = mp::xml::get_text(attr->children);
310  else if (!strcmp((const char *) attr->name, "exec"))
311  exec.program = mp::xml::get_text(attr->children);
312  else
313  throw mp::filter::FilterException
314  ("Bad attribute "
315  + std::string((const char *) attr->name)
316  + " in cgi section");
317  }
318  m_p->exec_map.push_back(exec);
319  }
320  else if (!strcmp((const char *) ptr->name, "env"))
321  {
322  std::string name, value;
323 
324  const struct _xmlAttr *attr;
325  for (attr = ptr->properties; attr; attr = attr->next)
326  {
327  if (!strcmp((const char *) attr->name, "name"))
328  name = mp::xml::get_text(attr->children);
329  else if (!strcmp((const char *) attr->name, "value"))
330  value = mp::xml::get_text(attr->children);
331  else
332  throw mp::filter::FilterException
333  ("Bad attribute "
334  + std::string((const char *) attr->name)
335  + " in cgi section");
336  }
337  if (name.length() > 0)
338  m_p->env_map[name] = value;
339  }
340  else if (!strcmp((const char *) ptr->name, "documentroot"))
341  {
342  m_p->documentroot = path;
343  }
344  else
345  {
346  throw mp::filter::FilterException("Bad element "
347  + std::string((const char *)
348  ptr->name));
349  }
350  }
351  if (m_p->documentroot.length() == 0)
352  m_p->documentroot = ".";
353 }

References metaproxy_1::filter::CGI::Exec::path, and metaproxy_1::filter::CGI::Exec::program.

◆ process()

void mp::filter::CGI::process ( metaproxy_1::Package &  package) const

Definition at line 147 of file filter_cgi.cpp.

148 {
149  Z_GDU *zgdu_req = package.request().get();
150  Z_GDU *zgdu_res = 0;
151 
152  if (!zgdu_req || zgdu_req->which != Z_GDU_HTTP_Request)
153  {
154  package.move();
155  return;
156  }
157  std::list<CGI::Exec>::const_iterator it;
158  metaproxy_1::odr odr;
159  Z_HTTP_Request *hreq = zgdu_req->u.HTTP_Request;
160  const char *path_cstr = hreq->path;
161  for (it = m_p->exec_map.begin(); it != m_p->exec_map.end(); it++)
162  {
163  if (strncmp(it->path.c_str(), path_cstr, it->path.length()) == 0)
164  {
165  int fds_response[2];
166  int r = pipe(fds_response);
167  if (r == -1)
168  {
169  zgdu_res = odr.create_HTTP_Response(
170  package.session(), hreq, 400);
171  package.response() = zgdu_res;
172  continue;
173  }
174  int fds_request[2];
175  r = pipe(fds_request);
176  if (r == -1)
177  {
178  zgdu_res = odr.create_HTTP_Response(
179  package.session(), hreq, 400);
180  package.response() = zgdu_res;
181  close(fds_response[0]);
182  close(fds_response[1]);
183  continue;
184  }
185 
186  int status;
187  pid_t pid = ::fork();
188  switch (pid)
189  {
190  case 0: /* child */
191  /* POSTed content */
192  close(0);
193  dup(fds_request[0]);
194  close(fds_request[1]);
195  /* response */
196  close(1);
197  close(fds_response[0]);
198  dup(fds_response[1]);
199  m_p->child(hreq, &(*it));
200  break;
201  case -1: /* error */
202  close(fds_request[0]);
203  close(fds_request[1]);
204  close(fds_response[0]);
205  close(fds_response[1]);
206  zgdu_res = odr.create_HTTP_Response(
207  package.session(), hreq, 400);
208  package.response() = zgdu_res;
209  break;
210  default: /* parent */
211  close(fds_response[1]);
212  close(fds_request[0]);
213  if (pid)
214  {
215  boost::mutex::scoped_lock lock(m_p->m_mutex);
216  m_p->children[pid] = pid;
217  }
218  WRBUF w = wrbuf_alloc();
219  wrbuf_puts(w, "HTTP/1.1 200 OK\r\n");
220  fcntl(fds_response[0], F_SETFL, O_NONBLOCK);
221  fcntl(fds_request[1], F_SETFL, O_NONBLOCK);
222  int no_write = 0;
223  while (1)
224  {
225  int num = 1;
226  struct yaz_poll_fd fds[2];
227  fds[0].fd = fds_response[0];
228  fds[0].input_mask = yaz_poll_read;
229  if (no_write < hreq->content_len)
230  {
231  fds[1].fd = fds_request[1];
232  fds[1].input_mask = yaz_poll_write;
233  num = 2;
234  }
235  int r = yaz_poll(fds, num, 60, 0);
236  if (r <= 0)
237  break;
238  if (fds[0].output_mask & (yaz_poll_read|yaz_poll_except))
239  {
240  char buf[512];
241  ssize_t rd = read(fds_response[0], buf, sizeof buf);
242  if (rd <= 0)
243  break;
244  wrbuf_write(w, buf, rd);
245  }
246  if (num == 2 && fds[1].output_mask & yaz_poll_write)
247  {
248  ssize_t wd = write(fds_request[1],
249  hreq->content_buf + no_write,
250  hreq->content_len - no_write);
251  if (wd <= 0)
252  break;
253  no_write += wd;
254  }
255  }
256  close(fds_request[1]);
257  close(fds_response[0]);
258  waitpid(pid, &status, 0);
259 
260  if (pid)
261  {
262  boost::mutex::scoped_lock lock(m_p->m_mutex);
263  m_p->children.erase(pid);
264  }
265  ODR dec = odr_createmem(ODR_DECODE);
266  odr_setbuf(dec, wrbuf_buf(w), wrbuf_len(w), 0);
267  r = z_GDU(dec, &zgdu_res, 0, 0);
268  if (r && zgdu_res)
269  {
270  package.response() = zgdu_res;
271  }
272  else
273  {
274  zgdu_res = odr.create_HTTP_Response(
275  package.session(), zgdu_req->u.HTTP_Request, 400);
276  Z_HTTP_Response *hres = zgdu_res->u.HTTP_Response;
277  z_HTTP_header_add(odr, &hres->headers,
278  "Content-Type", "text/plain");
279  hres->content_buf =
280  odr_strdup(odr, "Invalid script from script");
281  hres->content_len = strlen(hres->content_buf);
282  }
283  package.response() = zgdu_res;
284  odr_destroy(dec);
285  wrbuf_destroy(w);
286  break;
287  }
288  return;
289  }
290  }
291  package.move();
292 }

Member Data Documentation

◆ m_p

boost::scoped_ptr<Rep> metaproxy_1::filter::CGI::m_p
private

Definition at line 31 of file filter_cgi.hpp.


The documentation for this class was generated from the following files: