summaryrefslogtreecommitdiff
path: root/project2/cgi
diff options
context:
space:
mode:
authorrandomdan <randomdan@localhost>2011-12-08 16:46:11 +0000
committerrandomdan <randomdan@localhost>2011-12-08 16:46:11 +0000
commitc9990b16272d9c9a55f1f7be1fdef5b625ad27aa (patch)
tree15b804e78d42233d736351569ec893280d1d7a5f /project2/cgi
parentSend the expiry time to CouchDB when deleting old sessions (it's time seems o... (diff)
downloadproject2-c9990b16272d9c9a55f1f7be1fdef5b625ad27aa.tar.bz2
project2-c9990b16272d9c9a55f1f7be1fdef5b625ad27aa.tar.xz
project2-c9990b16272d9c9a55f1f7be1fdef5b625ad27aa.zip
Drop Boost::program_options in favour of our own, pluggable system which integrates application platforms properly
Diffstat (limited to 'project2/cgi')
-rw-r--r--project2/cgi/Jamfile.jam3
-rw-r--r--project2/cgi/cgiAppEngine.cpp26
-rw-r--r--project2/cgi/cgiAppEngine.h5
-rw-r--r--project2/cgi/cgiCommon.cpp2
-rw-r--r--project2/cgi/cgiEnvironment.cpp94
-rw-r--r--project2/cgi/cgiEnvironment.h18
-rw-r--r--project2/cgi/cgiOutputOptions.cpp18
-rw-r--r--project2/cgi/cgiOutputOptions.h7
-rw-r--r--project2/cgi/cgiStageFail.cpp1
-rw-r--r--project2/cgi/pch.hpp2
-rw-r--r--project2/cgi/testCgi.cpp105
11 files changed, 151 insertions, 130 deletions
diff --git a/project2/cgi/Jamfile.jam b/project2/cgi/Jamfile.jam
index 261e992..48225cb 100644
--- a/project2/cgi/Jamfile.jam
+++ b/project2/cgi/Jamfile.jam
@@ -2,7 +2,6 @@ alias libxmlpp : : : :
<cflags>"`pkg-config --cflags libxml++-2.6`"
<linkflags>"`pkg-config --libs libxml++-2.6`" ;
lib boost_filesystem : : <name>boost_filesystem ;
-lib boost_program_options : : <name>boost_program_options ;
lib cgicc : : <name>cgicc ;
lib fcgi : : <name>fcgi ;
lib fcgi++ : : <name>fcgi++ ;
@@ -12,7 +11,6 @@ cpp-pch pch : pch.hpp :
<library>cgicc
<library>libxmlpp
<library>../common//p2common
- <library>boost_program_options
<library>boost_filesystem
<library>../xml//p2xml
;
@@ -24,7 +22,6 @@ lib p2web :
<library>cgicc
<library>libxmlpp
<library>../common//p2common
- <library>boost_program_options
<library>boost_filesystem
<library>../xml//p2xml
: :
diff --git a/project2/cgi/cgiAppEngine.cpp b/project2/cgi/cgiAppEngine.cpp
index 779b25a..7fd7c33 100644
--- a/project2/cgi/cgiAppEngine.cpp
+++ b/project2/cgi/cgiAppEngine.cpp
@@ -9,7 +9,6 @@
#include <boost/foreach.hpp>
#include "ostreamWrapper.h"
#include <boost/date_time/microsec_time_clock.hpp>
-#include <glibmm/regex.h>
const std::string SESSIONID = "sessionID";
typedef UUID SIDKey;
@@ -27,7 +26,6 @@ getSessionID(const std::vector<cgicc::HTTPCookie> & cookies) {
return UUID();
}
CgiApplicationEngine::CgiApplicationEngine(const CgiEnvironment * e, std::ostream & io) :
- ApplicationEngine("web/host"),
_env(e),
sessionsContainer(LoaderBase::getLoader<SessionContainerLoader, NotSupported>(e->sessionModule)->open()),
IO(io)
@@ -200,27 +198,3 @@ CgiApplicationEngine::session() const
return cursession;
}
-bool
-CgiApplicationEngine::checkDomain(const DomainPlatforms::value_type & i) const
-{
- Glib::RefPtr<Glib::Regex> reg = Glib::Regex::create(i.first, Glib::REGEX_CASELESS | Glib::REGEX_DOTALL);
- return reg->match(_env->getServerName());
-}
-
-Glib::ustring
-CgiApplicationEngine::resolveCurrentConfig() const
-{
- DomainPlatforms::const_iterator i = std::find_if(domplat.begin(), domplat.end(), boost::bind(&CgiApplicationEngine::checkDomain, this, _1));
- if (i != domplat.end()) {
- return i->second;
- }
- throw UnknownDomain(_env->getServerName());
-}
-
-void
-CgiApplicationEngine::loadEngineSection(const xmlpp::Element * e) const
-{
- domplat.push_back(DomainPlatforms::value_type(e->get_attribute_value("name"), e->get_attribute_value("platform")));
-}
-
-
diff --git a/project2/cgi/cgiAppEngine.h b/project2/cgi/cgiAppEngine.h
index e837b9d..25d3b93 100644
--- a/project2/cgi/cgiAppEngine.h
+++ b/project2/cgi/cgiAppEngine.h
@@ -36,7 +36,6 @@ class CgiApplicationEngine : public ApplicationEngine, public TransformChainLink
void process() const;
const Environment * env() const;
SessionPtr session() const;
- virtual Glib::ustring resolveCurrentConfig() const;
void addAppData(const MultiRowSetPresenter * p, OutputOptionsPtr) const;
void addEnvData(const MultiRowSetPresenter * p, OutputOptionsPtr) const;
const CgiEnvironment * _env;
@@ -44,10 +43,6 @@ class CgiApplicationEngine : public ApplicationEngine, public TransformChainLink
private:
mutable boost::posix_time::ptime startTime;
mutable boost::posix_time::ptime endTime;
- typedef std::pair<Glib::ustring, Glib::ustring> DomainPlatform;
- typedef std::list<DomainPlatform> DomainPlatforms;
- mutable DomainPlatforms domplat;
- bool checkDomain(const DomainPlatforms::value_type & i) const;
void loadEngineSection(const xmlpp::Element *) const;
SessionContainerPtr sessionsContainer;
// Helpers
diff --git a/project2/cgi/cgiCommon.cpp b/project2/cgi/cgiCommon.cpp
index 579e3f4..3664e9f 100644
--- a/project2/cgi/cgiCommon.cpp
+++ b/project2/cgi/cgiCommon.cpp
@@ -34,7 +34,7 @@ doExceptionReporting(const E & e, std::ostream & IO)
IO << "Kaboom!" << std::endl
<< std::endl
<< buf << std::endl
- << e.what() << std::endl;
+ << "what '" << e.what() << "'" << std::endl;
free(buf);
}
diff --git a/project2/cgi/cgiEnvironment.cpp b/project2/cgi/cgiEnvironment.cpp
index 541e7ae..ae7ad52 100644
--- a/project2/cgi/cgiEnvironment.cpp
+++ b/project2/cgi/cgiEnvironment.cpp
@@ -1,9 +1,11 @@
#include <pch.hpp>
+#include <boost/version.hpp>
#include "cgiEnvironment.h"
#include "appEngine.h"
#include "exceptions.h"
#include <map>
#include <cgicc/Cgicc.h>
+#include <glibmm/regex.h>
std::vector<std::string>
makeVector(const boost::filesystem::path & y)
@@ -22,53 +24,56 @@ makeVector(const boost::filesystem::path & y)
}
CgiEnvironment::CgiEnvironment(cgicc::Cgicc * c) :
- Environment(0, NULL),
cgicc::CgiEnvironment(c->getEnvironment()),
elems(makeVector(boost::filesystem::path(getRedirectURL()))),
- cgi(c)
+ cgi(c),
+ cgiOptions("Project2 CGI options"),
+ hpi(new HostnamePlatformIdentifier())
{
-}
-
-CgiEnvironment::~CgiEnvironment()
-{
-}
-
-boost::program_options::options_description
-CgiEnvironment::addOptions(boost::program_options::positional_options_description &)
-{
- boost::program_options::options_description cgi("Project2 CGI options");
- cgi.add_options()
- ("defaultpresenter", boost::program_options::value(&defaultPresenter)->default_value("xml"),
+ cgiOptions
+ ("cgi.defaultPresenter", Options::value(&defaultPresenter, "xml"),
"The default engine for formatting presentations")
- ("defaultpresent", boost::program_options::value(&defaultPresent)->default_value("index"),
+ ("cgi.defaultPresent", Options::value(&defaultPresent, "index"),
"The present script to use when no other is specified")
- ("presentroot", boost::program_options::value(&presentRoot)->default_value("present"),
+ ("cgi.presentRoot", Options::value(&presentRoot, "present"),
"The folder in which to find presentation scripts")
- ("requestroot", boost::program_options::value(&requestRoot)->default_value("request"),
+ ("cgi.requestRoot", Options::value(&requestRoot, "request"),
"The folder in which to find request scripts")
- ("errorpresentroot", boost::program_options::value(&errorPresentRoot)->default_value("error"),
+ ("cgi.errorPresentRoot", Options::value(&errorPresentRoot, "error"),
"The folder in which to find presentation scripts for error handling")
- ("errorcontenttype", boost::program_options::value(&errorContentType)->default_value("text/xml"),
+ ("cgi.errorContentType", Options::value(&errorContentType, "text/xml"),
"The Content-Type to use in HTTP headers in event of an error")
- ("errortransformstyle", boost::program_options::value(&errorTransformStyle),
+ ("cgi.errorTransformStyle", Options::value(&errorTransformStyle),
"The xml-stylesheet to specify in the data document in event of an error")
- ("notfoundpresent", boost::program_options::value(&notFoundPresent),
+ ("cgi.notFoundPresent", Options::value(&notFoundPresent),
"The present script to use when the requested script does not exist")
- ("onerrorpresent", boost::program_options::value(&onErrorPresent),
+ ("cgi.onErrorPresent", Options::value(&onErrorPresent),
"The present script to use when the requested script (or child) fails")
- ("dumpdatadoc", boost::program_options::value(&dumpdatadoc),
+ ("cgi.dumpDataDoc", Options::value(&dumpdatadoc),
"Write a copy of the data document before sending it to the web server")
- ("sessionModule", boost::program_options::value(&sessionModule)->default_value("xml"),
+ ("cgi.sessionModule", Options::value(&sessionModule, "xml"),
"The module with which to implement session management")
+ ("cgi.hostRegex", hpi,
+ "Regular expression used to define a hostname -> platform association")
;
- return cgi;
}
-void
-CgiEnvironment::postinit(const boost::program_options::options_description &, const boost::program_options::variables_map &)
+const Options &
+CgiEnvironment::engineOptions() const {
+ return cgiOptions;
+}
+
+CgiEnvironment::~CgiEnvironment()
+{
+}
+
+const Glib::ustring &
+CgiEnvironment::platform() const
{
+ return hpi->derivedPlatform();
}
+
Glib::ustring
CgiEnvironment::getParamUri(unsigned int p) const
{
@@ -88,3 +93,38 @@ CgiEnvironment::getParamQuery(const std::string & p) const
return (*cgi)(p);
}
+HostnamePlatformIdentifier::HostnamePlatformIdentifier() :
+ platform(NULL)
+{
+}
+
+HostnamePlatformIdentifier::~HostnamePlatformIdentifier()
+{
+ reset();
+}
+
+const Glib::ustring &
+HostnamePlatformIdentifier::derivedPlatform() const
+{
+ if (platform) {
+ return *platform;
+ }
+ throw NoSuchPlatform(Environment::getCurrent()->getServerName());
+}
+
+void
+HostnamePlatformIdentifier::reset() const
+{
+ if (platform) {
+ delete platform;
+ }
+}
+
+void
+HostnamePlatformIdentifier::consume(const Glib::ustring & p, const Glib::ustring & r) const
+{
+ if (!platform && Glib::Regex::create(r, Glib::REGEX_CASELESS | Glib::REGEX_DOTALL)->match(Environment::getCurrent()->getServerName())) {
+ platform = new Glib::ustring(p);
+ }
+}
+
diff --git a/project2/cgi/cgiEnvironment.h b/project2/cgi/cgiEnvironment.h
index fe99f5e..654f772 100644
--- a/project2/cgi/cgiEnvironment.h
+++ b/project2/cgi/cgiEnvironment.h
@@ -10,6 +10,17 @@ namespace cgicc {
class Cgicc;
}
+class HostnamePlatformIdentifier : public Options::Target {
+ public:
+ HostnamePlatformIdentifier();
+ virtual ~HostnamePlatformIdentifier();
+ void reset() const;
+ void consume(const Glib::ustring &, const Glib::ustring &) const;
+ const Glib::ustring & derivedPlatform() const;
+ private:
+ mutable Glib::ustring * platform;
+};
+
class CgiEnvironment : public Environment, public cgicc::CgiEnvironment {
public:
CgiEnvironment(cgicc::Cgicc *);
@@ -24,8 +35,11 @@ class CgiEnvironment : public Environment, public cgicc::CgiEnvironment {
const cgicc::Cgicc * const cgi;
private:
- boost::program_options::options_description addOptions(boost::program_options::positional_options_description &);
- void postinit(const boost::program_options::options_description &, const boost::program_options::variables_map &);
+ const Options & engineOptions() const;
+ const Glib::ustring & platform() const;
+ Options cgiOptions;
+ boost::intrusive_ptr<HostnamePlatformIdentifier> hpi;
+
public:
std::string dumpdatadoc;
Glib::ustring errorContentType;
diff --git a/project2/cgi/cgiOutputOptions.cpp b/project2/cgi/cgiOutputOptions.cpp
index eb07b25..add1671 100644
--- a/project2/cgi/cgiOutputOptions.cpp
+++ b/project2/cgi/cgiOutputOptions.cpp
@@ -20,13 +20,13 @@ OutputOptions::OutputOptions(const xmlpp::Element * p) :
OutputOptionsLoader::OutputOptionsLoader() :
opts("CGI default output options")
{
- opts.add_options()
- ("cgi.output.core", po::value(&OutputOptions::core)->default_value(true), "Core messages")
- ("cgi.output.session", po::value(&OutputOptions::core)->default_value(true), "Session values")
- ("cgi.output.timing", po::value(&OutputOptions::core)->default_value(true), "Timing")
- ("cgi.output.environment", po::value(&OutputOptions::core)->default_value(true), "Environment")
- ("cgi.output.url", po::value(&OutputOptions::core)->default_value(true), "URL breakdown")
- ("cgi.output.parameters", po::value(&OutputOptions::core)->default_value(true), "Parameters")
+ opts
+ ("cgi.output.core", Options::value(&OutputOptions::core, true), "Core messages")
+ ("cgi.output.session", Options::value(&OutputOptions::core, true), "Session values")
+ ("cgi.output.timing", Options::value(&OutputOptions::core, true), "Timing")
+ ("cgi.output.environment", Options::value(&OutputOptions::core, true), "Environment")
+ ("cgi.output.url", Options::value(&OutputOptions::core, true), "URL breakdown")
+ ("cgi.output.parameters", Options::value(&OutputOptions::core, true), "Parameters")
;
}
@@ -35,8 +35,8 @@ OutputOptionsLoader::createFrom(const xmlpp::Element * e) const {
return new OutputOptions(e);
}
-po::options_description *
-OutputOptionsLoader::options()
+const Options *
+OutputOptionsLoader::options() const
{
return &opts;
}
diff --git a/project2/cgi/cgiOutputOptions.h b/project2/cgi/cgiOutputOptions.h
index 540764e..a1ff62d 100644
--- a/project2/cgi/cgiOutputOptions.h
+++ b/project2/cgi/cgiOutputOptions.h
@@ -2,7 +2,7 @@
#define OUTPUTOPTIONS_H
#include "intrusivePtrBase.h"
-#include <boost/program_options.hpp>
+#include "options.h"
#include "variables.h"
namespace xmlpp {
@@ -32,15 +32,14 @@ class OutputOptions : public IntrusivePtrBase {
};
typedef boost::intrusive_ptr<OutputOptions> OutputOptionsPtr;
-namespace po = boost::program_options;
class OutputOptionsLoader : public ComponentLoader {
public:
OutputOptionsLoader();
OutputOptionsPtr createFrom(const xmlpp::Element * e) const;
- po::options_description * options();
+ const Options * options() const;
private:
- po::options_description opts;
+ Options opts;
};
#endif
diff --git a/project2/cgi/cgiStageFail.cpp b/project2/cgi/cgiStageFail.cpp
index 97ac22a..87aba66 100644
--- a/project2/cgi/cgiStageFail.cpp
+++ b/project2/cgi/cgiStageFail.cpp
@@ -1,4 +1,5 @@
#include <pch.hpp>
+#include <boost/lexical_cast.hpp>
#include "cgiAppEngine.h"
#include "cgiEnvironment.h"
#include "cgiHttpHeader.h"
diff --git a/project2/cgi/pch.hpp b/project2/cgi/pch.hpp
index b3c7108..ff0b175 100644
--- a/project2/cgi/pch.hpp
+++ b/project2/cgi/pch.hpp
@@ -13,7 +13,7 @@
#include "xmlObjectLoader.h"
#include <boost/bind.hpp>
#include <boost/foreach.hpp>
-#include <boost/program_options.hpp>
+#include "options.h"
#include <cgicc/CgiEnvironment.h>
#include <cgicc/Cgicc.h>
#include <cgicc/HTTPContentHeader.h>
diff --git a/project2/cgi/testCgi.cpp b/project2/cgi/testCgi.cpp
index 438e1b0..c2e8d4e 100644
--- a/project2/cgi/testCgi.cpp
+++ b/project2/cgi/testCgi.cpp
@@ -1,70 +1,71 @@
#include <iostream>
-#include <boost/program_options.hpp>
-#include <boost/filesystem/convenience.hpp>
+#include <boost/bind.hpp>
+#include <map>
+#include "options.h"
+#include "safeMapFind.h"
#include "cgiCommon.h"
+#include "../files/optionsSource.h"
-namespace po = boost::program_options;
-
+#define TESTOPT(name, def, desc) \
+ (name, Options::value(optStore.insert(OptStore::value_type(name, new std::string())).first->second, def), desc)
class TestInput : public cgicc::CgiInput {
public:
- TestInput(int argc, char ** argv)
+ typedef std::string * StrPtr;
+ typedef std::map<std::string, StrPtr> OptStore;
+ OptStore optStore;
+ TestInput() :
+ opts("Project2 CGI test options")
{
- po::options_description test("Project2 CGI test options");
- test.add_options()
- ("help,h", "Print usage and exit")
- ("SERVER_NAME", "FQDN of web service")
- ("SERVER_SOFTWARE", po::value<std::string>()->default_value("Apache"), "")
- ("GATEWAY_INTERFACE", po::value<std::string>()->default_value("CGI/1.1"), "")
- ("SERVER_PROTOCOL", po::value<std::string>()->default_value("HTTP/1.1"), "")
- ("SERVER_PORT", po::value<std::string>()->default_value("80"), "")
- ("REQUEST_METHOD", po::value<std::string>()->default_value("GET"), "")
- ("PATH_INFO", "")
- ("PATH_TRANSLATED", "")
- ("SCRIPT_NAME", po::value<std::string>()->default_value("p2fcgi"), "")
- ("QUERY_STRING", "")
- ("REMOTE_HOST", "")
- ("REMOTE_ADDR", "")
- ("AUTH_TYPE", "")
- ("REMOTE_USER", "")
- ("REMOTE_IDENT", "")
- ("CONTENT_TYPE", "")
- ("CONTENT_LENGTH", "")
- ("HTTP_ACCEPT", po::value<std::string>()->default_value("text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"), "")
- ("HTTP_USER_AGENT", po::value<std::string>()->default_value("Mozilla/5.0"), "")
- ("REDIRECT_REQUEST", "")
- ("REDIRECT_URL", "")
- ("REDIRECT_STATUS", "")
- ("HTTP_REFERER", "")
- ("HTTP_COOKIE", "")
- ("HTTPS", po::value<std::string>()->default_value("No"), "")
+ opts
+ TESTOPT("SERVER_NAME", "localhost", "FQDN of web service")
+ TESTOPT("SERVER_SOFTWARE", "Apache", "Web server version string")
+ TESTOPT("GATEWAY_INTERFACE", "CGI/1.1", "Web server/script interface version")
+ TESTOPT("SERVER_PROTOCOL", "HTTP/1.1", "Web server/client interface version")
+ TESTOPT("SERVER_PORT", "80", "Server Port")
+ TESTOPT("REQUEST_METHOD", "GET", "Request method")
+ TESTOPT("PATH_INFO", "", "Path info")
+ TESTOPT("PATH_TRANSLATED", "", "Path translated")
+ TESTOPT("SCRIPT_NAME", "p2fcgi", "Script name")
+ TESTOPT("QUERY_STRING", "", "Query string")
+ TESTOPT("REMOTE_HOST", "", "Remote host")
+ TESTOPT("REMOTE_ADDR", "", "Remote address")
+ TESTOPT("AUTH_TYPE", "", "Authentication type")
+ TESTOPT("REMOTE_USER", "", "Remote user")
+ TESTOPT("REMOTE_IDENT", "", "Remote ident")
+ TESTOPT("CONTENT_TYPE", "", "Content type")
+ TESTOPT("CONTENT_LENGTH", "", "Content length")
+ TESTOPT("HTTP_ACCEPT", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", "Accepted MIME types")
+ TESTOPT("HTTP_USER_AGENT", "Mozilla/5.0", "User agent")
+ TESTOPT("REDIRECT_REQUEST", "", "Redirect request")
+ TESTOPT("REDIRECT_URL", "", "Redirect URL")
+ TESTOPT("REDIRECT_STATUS", "", "Redirect status")
+ TESTOPT("HTTP_REFERER", "", "Referrer")
+ TESTOPT("HTTP_COOKIE", "", "Cookie")
+ TESTOPT("HTTPS", "No", "HTTPS?")
;
- po::parsed_options parsed = po::command_line_parser(argc, argv).options(test).allow_unregistered().run();
- po::store(parsed, settings);
- if (boost::filesystem::exists("testCgi.settings")) {
- std::ifstream f("testCgi.settings");
- po::store(po::parse_config_file(f, test, true), settings);
- }
- po::notify(settings);
- if (settings.count("help")) {
- std::cout << test;
- exit(1);
- }
+ FileOptions fo(".testCgi.settings");
+ opts.reset();
+ fo.loadInto(boost::bind(&Options::consume, &opts, _1, _2, _3));
+ }
+
+ const Options * options() const {
+ return &opts;
}
- virtual std::string getenv(const char *varName)
+
+ virtual std::string getenv(const char * varName)
{
- if (settings.count(varName)) {
- return settings[varName].as<std::string>();
- }
- return "";
+ StrPtr def(new std::string());
+ return *defaultMapFind(optStore, varName, def);
}
+
private:
- po::variables_map settings;
+ Options opts;
};
int
-main(int argc, char ** argv)
+main(int, char **)
{
- TestInput ti(argc, argv);
+ TestInput ti;
cgiServe(&ti, std::cout);
}