From 74d16c70e558c6b5fb0ff5b057a047d4da6d5a66 Mon Sep 17 00:00:00 2001 From: Adam Dickmeiss Date: Tue, 16 Mar 2010 13:39:35 +0100 Subject: [PATCH] Beginnings of CGI filter --- etc/Makefile.am | 3 +- etc/cgi.sh | 7 ++ etc/config-cgi.xml | 22 ++++++ src/Makefile.am | 1 + src/factory_static.cpp | 2 + src/filter_cgi.cpp | 181 ++++++++++++++++++++++++++++++++++++++++++++++++ src/filter_cgi.hpp | 54 +++++++++++++++ win/makefile | 1 + 8 files changed, 270 insertions(+), 1 deletion(-) create mode 100755 etc/cgi.sh create mode 100644 etc/config-cgi.xml create mode 100644 src/filter_cgi.cpp create mode 100644 src/filter_cgi.hpp diff --git a/etc/Makefile.am b/etc/Makefile.am index fa62b18..5d70da1 100644 --- a/etc/Makefile.am +++ b/etc/Makefile.am @@ -19,6 +19,7 @@ xmlconfig = $(srcdir)/config-bytarget.xml \ $(srcdir)/config3.xml \ $(srcdir)/config4.xml \ $(srcdir)/config5.xml \ + $(srcdir)/config-cgi.xml \ $(srcdir)/retrieval-info.xml config = example.simple-auth example.target-auth pqf2pqf.xsl explain.xml @@ -29,7 +30,7 @@ xsd = $(srcdir)/../xml/schema/metaproxy.xsd etcdata_DATA = $(xmlconfig) $(config) -EXTRA_DIST = $(etcdata_DATA) +EXTRA_DIST = $(etcdata_DATA) cgi.sh .PHONY: check_rng check_rng: diff --git a/etc/cgi.sh b/etc/cgi.sh new file mode 100755 index 0000000..2fbc75e --- /dev/null +++ b/etc/cgi.sh @@ -0,0 +1,7 @@ +#!/bin/sh +echo "Content-Type: text/plain" +echo "" + +echo "hello, world." +sleep 5 + diff --git a/etc/config-cgi.xml b/etc/config-cgi.xml new file mode 100644 index 0000000..46204fe --- /dev/null +++ b/etc/config-cgi.xml @@ -0,0 +1,22 @@ + + + + + + + @:9000 + + + + + + + + + + + + + + diff --git a/src/Makefile.am b/src/Makefile.am index 66883f4..ec2f27a 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -21,6 +21,7 @@ libmetaproxy_la_SOURCES = \ filter_auth_simple.cpp filter_auth_simple.hpp \ filter_backend_test.cpp filter_backend_test.hpp \ filter_bounce.cpp filter_bounce.hpp \ + filter_cgi.cpp filter_cgi.hpp \ filter_cql_to_rpn.cpp filter_cql_to_rpn.hpp \ filter_frontend_net.cpp filter_frontend_net.hpp \ filter_http_file.cpp filter_http_file.hpp \ diff --git a/src/factory_static.cpp b/src/factory_static.cpp index 0101819..59709e5 100644 --- a/src/factory_static.cpp +++ b/src/factory_static.cpp @@ -30,6 +30,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "filter_auth_simple.hpp" #include "filter_backend_test.hpp" #include "filter_bounce.hpp" +#include "filter_cgi.hpp" #include "filter_cql_to_rpn.hpp" #include "filter_frontend_net.hpp" #include "filter_http_file.hpp" @@ -54,6 +55,7 @@ mp::FactoryStatic::FactoryStatic() &metaproxy_1_filter_auth_simple, &metaproxy_1_filter_backend_test, &metaproxy_1_filter_bounce, + &metaproxy_1_filter_cgi, &metaproxy_1_filter_cql_to_rpn, &metaproxy_1_filter_frontend_net, &metaproxy_1_filter_http_file, diff --git a/src/filter_cgi.cpp b/src/filter_cgi.cpp new file mode 100644 index 0000000..3747e63 --- /dev/null +++ b/src/filter_cgi.cpp @@ -0,0 +1,181 @@ +/* This file is part of Metaproxy. + Copyright (C) 2005-2010 Index Data + +Metaproxy is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 2, or (at your option) any later +version. + +Metaproxy is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "filter_cgi.hpp" +#include +#include +#include "gduutil.hpp" +#include +#include + +#include +#include +#include + +#include "config.hpp" + +namespace mp = metaproxy_1; +namespace yf = mp::filter; + +namespace metaproxy_1 { + namespace filter { + class CGI::Exec { + friend class Rep; + friend class CGI; + std::string path; + std::string program; + }; + class CGI::Rep { + friend class CGI; + std::list exec_map; + }; + } +} + +yf::CGI::CGI() : m_p(new Rep) +{ + +} + +yf::CGI::~CGI() +{ // must have a destructor because of boost::scoped_ptr +} + +void yf::CGI::process(mp::Package &package) const +{ + Z_GDU *zgdu_req = package.request().get(); + Z_GDU *zgdu_res = 0; + + if (!zgdu_req) + return; + + if (zgdu_req->which != Z_GDU_HTTP_Request) + { + package.move(); + return; + } + std::string path_info; + std::string query_string; + const char *path = zgdu_req->u.HTTP_Request->path; + yaz_log(YLOG_LOG, "path=%s", path); + const char *p_cp = strchr(path, '?'); + if (p_cp) + { + path_info.assign(path, p_cp - path); + query_string.assign(p_cp+1); + } + else + path_info.assign(path); + + std::list::const_iterator it; + metaproxy_1::odr odr; + for (it = m_p->exec_map.begin(); it != m_p->exec_map.end(); it++) + { + if (it->path.compare(path_info) == 0) + { + int r; + pid_t pid; + int status; + + pid = ::fork(); + switch (pid) + { + case 0: /* child */ + setenv("PATH_INFO", path_info.c_str(), 1); + setenv("QUERY_STRING", query_string.c_str(), 1); + r = execl(it->program.c_str(), it->program.c_str(), (char *) 0); + if (r == -1) + exit(1); + exit(0); + break; + case -1: /* error */ + zgdu_res = odr.create_HTTP_Response( + package.session(), zgdu_req->u.HTTP_Request, 400); + package.response() = zgdu_res; + break; + default: /* parent */ + waitpid(pid, &status, 0); + + zgdu_res = odr.create_HTTP_Response( + package.session(), zgdu_req->u.HTTP_Request, 200); + package.response() = zgdu_res; + break; + } + return; + } + } + package.move(); +} + +void yf::CGI::configure(const xmlNode *ptr, bool test_only) +{ + for (ptr = ptr->children; ptr; ptr = ptr->next) + { + if (ptr->type != XML_ELEMENT_NODE) + continue; + if (!strcmp((const char *) ptr->name, "map")) + { + CGI::Exec exec; + + const struct _xmlAttr *attr; + for (attr = ptr->properties; attr; attr = attr->next) + { + if (!strcmp((const char *) attr->name, "path")) + exec.path = mp::xml::get_text(attr->children); + else if (!strcmp((const char *) attr->name, "exec")) + exec.program = mp::xml::get_text(attr->children); + else + throw mp::filter::FilterException + ("Bad attribute " + + std::string((const char *) attr->name) + + " in cgi section"); + } + m_p->exec_map.push_back(exec); + } + else + { + throw mp::filter::FilterException("Bad element " + + std::string((const char *) + ptr->name)); + } + } +} + +static mp::filter::Base* filter_creator() +{ + return new mp::filter::CGI; +} + +extern "C" { + struct metaproxy_1_filter_struct metaproxy_1_filter_cgi = { + 0, + "cgi", + filter_creator + }; +} + + +/* + * Local variables: + * c-basic-offset: 4 + * c-file-style: "Stroustrup" + * indent-tabs-mode: nil + * End: + * vim: shiftwidth=4 tabstop=8 expandtab + */ + diff --git a/src/filter_cgi.hpp b/src/filter_cgi.hpp new file mode 100644 index 0000000..480e235 --- /dev/null +++ b/src/filter_cgi.hpp @@ -0,0 +1,54 @@ +/* This file is part of Metaproxy. + Copyright (C) 2005-2010 Index Data + +Metaproxy is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 2, or (at your option) any later +version. + +Metaproxy is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef FILTER_CGI_HPP +#define FILTER_CGI_HPP + +#include + +#include + +namespace metaproxy_1 { + namespace filter { + class CGI : public Base { + class Rep; + class Exec; + boost::scoped_ptr m_p; + public: + CGI(); + ~CGI(); + void process(metaproxy_1::Package & package) const; + void configure(const xmlNode * ptr, bool test_only); + }; + } +} + +extern "C" { + extern struct metaproxy_1_filter_struct metaproxy_1_filter_cgi; +} + +#endif +/* + * Local variables: + * c-basic-offset: 4 + * c-file-style: "Stroustrup" + * indent-tabs-mode: nil + * End: + * vim: shiftwidth=4 tabstop=8 expandtab + */ + diff --git a/win/makefile b/win/makefile index 684340d..714185c 100644 --- a/win/makefile +++ b/win/makefile @@ -224,6 +224,7 @@ PROJECT_DLL_OBJS = \ $(OBJDIR)\factory_static.obj \ $(OBJDIR)\filter.obj \ $(OBJDIR)\filter_auth_simple.obj \ + $(OBJDIR)\filter_cgi.obj \ $(OBJDIR)\filter_backend_test.obj \ $(OBJDIR)\filter_bounce.obj \ $(OBJDIR)\filter_cql_to_rpn.obj \ -- 1.7.10.4