+
+
+class ApacheStreamBuf: public Poco::BufferedStreamBuf
+ /// This is the streambuf class used for reading from and writing to a socket.
+{
+public:
+ ApacheStreamBuf(ApacheRequestRec* pApacheRequest, bool haveData = false);
+ /// Creates a ApacheStreamBuf with the given socket.
+
+ ~ApacheStreamBuf();
+ /// Destroys the SocketStreamBuf.
+
+protected:
+ int readFromDevice(char* buffer, std::streamsize length);
+ int writeToDevice(const char* buffer, std::streamsize length);
+
+private:
+ enum
+ {
+ STREAM_BUFFER_SIZE = 1024
+ };
+
+ ApacheRequestRec* _pApacheRequest;
+ bool _haveData;
+};
+
+
+class ApacheIOS: public virtual std::ios
+ /// The base class for ApacheStream, ApacheInputStream and
+ /// ApacheOutputStream.
+ ///
+ /// This class is needed to ensure the correct initialization
+ /// order of the stream buffer and base classes.
+{
+public:
+ ApacheIOS(ApacheRequestRec* pApacheRequest, bool haveData = false);
+ /// Creates the ApacheIOS with the given socket.
+
+ ~ApacheIOS();
+ /// Destroys the ApacheIOS.
+ ///
+ /// Flushes the buffer, but does not close the socket.
+
+ ApacheStreamBuf* rdbuf();
+ /// Returns a pointer to the internal ApacheStreamBuf.
+
+ void close();
+ /// Flushes the stream.
+
+protected:
+ ApacheStreamBuf _buf;
+};
+
+
+class ApacheOutputStream: public ApacheIOS, public std::ostream
+ /// An output stream for writing to an Apache response.
+{
+public:
+ ApacheOutputStream(ApacheRequestRec* pApacheRequest);
+ /// Creates the ApacheOutputStream with the given socket.
+
+ ~ApacheOutputStream();
+ /// Destroys the ApacheOutputStream.
+ ///
+ /// Flushes the buffer.
+};
+
+
+class ApacheInputStream: public ApacheIOS, public std::istream
+ /// An input stream for reading from an Apache request.
+ ///
+ /// Using formatted input from a ApacheInputStream
+ /// is not recommended, due to the read-ahead behavior of
+ /// istream with formatted reads.
+{
+public:
+ ApacheInputStream(ApacheRequestRec* pApacheRequest);
+ /// Creates the ApacheInputStream with the given socket.
+
+ ~ApacheInputStream();
+ /// Destroys the ApacheInputStream.
+};
+
+
+#endif // ApacheConnector_ApacheStream_INCLUDED
diff --git a/ApacheConnector/samples/FormServer/FormServer_vs71.vcproj b/ApacheConnector/samples/FormServer/FormServer_vs71.vcproj
new file mode 100644
index 000000000..b08085081
--- /dev/null
+++ b/ApacheConnector/samples/FormServer/FormServer_vs71.vcproj
@@ -0,0 +1,152 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ApacheConnector/samples/FormServer/FormServer_vs80.vcproj b/ApacheConnector/samples/FormServer/FormServer_vs80.vcproj
new file mode 100644
index 000000000..ce671367c
--- /dev/null
+++ b/ApacheConnector/samples/FormServer/FormServer_vs80.vcproj
@@ -0,0 +1,218 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ApacheConnector/samples/FormServer/Makefile b/ApacheConnector/samples/FormServer/Makefile
new file mode 100644
index 000000000..ae3db3330
--- /dev/null
+++ b/ApacheConnector/samples/FormServer/Makefile
@@ -0,0 +1,17 @@
+#
+# Makefile
+#
+# $Id: //poco/Main/ApacheConnector/samples/FormServer/Makefile#1 $
+#
+# Makefile for Poco ApacheConnector sample
+#
+
+include $(POCO_BASE)/build/rules/global
+
+objects = FormServer
+
+target = FormServer
+target_version = 1
+target_libs = PocoFoundation PocoNet
+
+include $(POCO_BASE)/build/rules/dylib
diff --git a/ApacheConnector/samples/FormServer/src/FormServer.cpp b/ApacheConnector/samples/FormServer/src/FormServer.cpp
new file mode 100644
index 000000000..c5d83e5c3
--- /dev/null
+++ b/ApacheConnector/samples/FormServer/src/FormServer.cpp
@@ -0,0 +1,188 @@
+//
+// FormServer.cpp
+//
+// $Id: //poco/Main/ApacheConnector/samples/FormServer/src/FormServer.cpp#2 $
+//
+// Copyright (c) 2007, Applied Informatics Software Engineering GmbH.
+// All rights reserved.
+//
+// This is unpublished proprietary source code of Applied Informatics.
+// The contents of this file may not be disclosed to third parties,
+// copied or duplicated in any form, in whole or in part.
+//
+
+
+#include "Poco/Net/HTTPServer.h"
+#include "Poco/Net/HTTPRequestHandler.h"
+#include "Poco/Net/HTTPRequestHandlerFactory.h"
+#include "Poco/Net/HTTPServerRequest.h"
+#include "Poco/Net/HTTPServerResponse.h"
+#include "Poco/Net/HTMLForm.h"
+#include "Poco/Net/PartHandler.h"
+#include "Poco/CountingStream.h"
+#include "Poco/NullStream.h"
+#include "Poco/StreamCopier.h"
+#include "Poco/ClassLibrary.h"
+
+
+using Poco::Net::HTTPRequestHandler;
+using Poco::Net::HTTPRequestHandlerFactory;
+using Poco::Net::HTTPServerRequest;
+using Poco::Net::HTTPServerResponse;
+using Poco::Net::MessageHeader;
+using Poco::Net::HTMLForm;
+using Poco::Net::NameValueCollection;
+using Poco::CountingInputStream;
+using Poco::NullOutputStream;
+using Poco::StreamCopier;
+
+
+class MyPartHandler: public Poco::Net::PartHandler
+{
+public:
+ MyPartHandler():
+ _length(0)
+ {
+ }
+
+ void handlePart(const MessageHeader& header, std::istream& stream)
+ {
+ _type = header.get("Content-Type", "(unspecified)");
+ if (header.has("Content-Disposition"))
+ {
+ std::string disp;
+ NameValueCollection params;
+ MessageHeader::splitParameters(header["Content-Disposition"], disp, params);
+ _name = params.get("name", "(unnamed)");
+ _fileName = params.get("filename", "(unnamed)");
+ }
+
+ CountingInputStream istr(stream);
+ NullOutputStream ostr;
+ StreamCopier::copyStream(istr, ostr);
+ _length = istr.chars();
+ }
+
+ int length() const
+ {
+ return _length;
+ }
+
+ const std::string& name() const
+ {
+ return _name;
+ }
+
+ const std::string& fileName() const
+ {
+ return _fileName;
+ }
+
+ const std::string& contentType() const
+ {
+ return _type;
+ }
+
+private:
+ int _length;
+ std::string _type;
+ std::string _name;
+ std::string _fileName;
+};
+
+
+class FormRequestHandler: public HTTPRequestHandler
+ /// Return a HTML document with the current date and time.
+{
+public:
+ FormRequestHandler()
+ {
+ }
+
+ void handleRequest(HTTPServerRequest& request, HTTPServerResponse& response)
+ {
+ MyPartHandler partHandler;
+ HTMLForm form(request, request.stream(), partHandler);
+
+ response.setChunkedTransferEncoding(true);
+ response.setContentType("text/html");
+
+ std::ostream& ostr = response.send();
+
+ ostr <<
+ "\n"
+ "\n"
+ "POCO Form Server Sample\n"
+ "\n"
+ "\n"
+ "POCO Form Server Sample
\n"
+ "GET Form
\n"
+ "\n"
+ "POST Form
\n"
+ "\n"
+ "File Upload
\n"
+ "\n";
+
+ ostr << "Request
\n";
+ ostr << "Method: " << request.getMethod() << "
\n";
+ ostr << "URI: " << request.getURI() << "
\n";
+ NameValueCollection::ConstIterator it = request.begin();
+ NameValueCollection::ConstIterator end = request.end();
+ for (; it != end; ++it)
+ {
+ ostr << it->first << ": " << it->second << "
\n";
+ }
+ ostr << "
";
+
+ if (!form.empty())
+ {
+ ostr << "Form
\n";
+ it = form.begin();
+ end = form.end();
+ for (; it != end; ++it)
+ {
+ ostr << it->first << ": " << it->second << "
\n";
+ }
+ ostr << "
";
+ }
+
+ if (!partHandler.name().empty())
+ {
+ ostr << "Upload
\n";
+ ostr << "Name: " << partHandler.name() << "
\n";
+ ostr << "File Name: " << partHandler.fileName() << "
\n";
+ ostr << "Type: " << partHandler.contentType() << "
\n";
+ ostr << "Size: " << partHandler.length() << "
\n";
+ ostr << "
";
+ }
+ ostr << "\n";
+ }
+};
+
+
+class FormRequestHandlerFactory: public HTTPRequestHandlerFactory
+{
+public:
+ FormRequestHandlerFactory()
+ {
+ }
+
+ HTTPRequestHandler* createRequestHandler(const HTTPServerRequest& request)
+ {
+ return new FormRequestHandler;
+ }
+};
+
+
+POCO_BEGIN_MANIFEST(HTTPRequestHandlerFactory)
+ POCO_EXPORT_CLASS(FormRequestHandlerFactory)
+POCO_END_MANIFEST
diff --git a/ApacheConnector/samples/Makefile b/ApacheConnector/samples/Makefile
new file mode 100644
index 000000000..f04d2ecf8
--- /dev/null
+++ b/ApacheConnector/samples/Makefile
@@ -0,0 +1,13 @@
+#
+# Makefile
+#
+# $Id: //poco/Main/ApacheConnector/samples/Makefile#1 $
+#
+# Makefile for Poco ApacheConnector Samples
+#
+
+.PHONY: projects
+clean all: projects
+projects:
+ $(MAKE) -C TimeServer $(MAKECMDGOALS)
+ $(MAKE) -C FormServer $(MAKECMDGOALS)
diff --git a/ApacheConnector/samples/TimeServer/Makefile b/ApacheConnector/samples/TimeServer/Makefile
new file mode 100644
index 000000000..be171bb9e
--- /dev/null
+++ b/ApacheConnector/samples/TimeServer/Makefile
@@ -0,0 +1,17 @@
+#
+# Makefile
+#
+# $Id: //poco/Main/ApacheConnector/samples/TimeServer/Makefile#1 $
+#
+# Makefile for Poco ApacheConnector sample
+#
+
+include $(POCO_BASE)/build/rules/global
+
+objects = TimeServer
+
+target = TimeServer
+target_version = 1
+target_libs = PocoFoundation PocoNet
+
+include $(POCO_BASE)/build/rules/dylib
diff --git a/ApacheConnector/samples/TimeServer/TimeServer_vs71.vcproj b/ApacheConnector/samples/TimeServer/TimeServer_vs71.vcproj
new file mode 100644
index 000000000..81e4c1fd0
--- /dev/null
+++ b/ApacheConnector/samples/TimeServer/TimeServer_vs71.vcproj
@@ -0,0 +1,152 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ApacheConnector/samples/TimeServer/TimeServer_vs80.vcproj b/ApacheConnector/samples/TimeServer/TimeServer_vs80.vcproj
new file mode 100644
index 000000000..e5205c565
--- /dev/null
+++ b/ApacheConnector/samples/TimeServer/TimeServer_vs80.vcproj
@@ -0,0 +1,218 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ApacheConnector/samples/TimeServer/src/TimeServer.cpp b/ApacheConnector/samples/TimeServer/src/TimeServer.cpp
new file mode 100644
index 000000000..0f734683e
--- /dev/null
+++ b/ApacheConnector/samples/TimeServer/src/TimeServer.cpp
@@ -0,0 +1,77 @@
+//
+// TimeServer.cpp
+//
+// $Id: //poco/Main/ApacheConnector/samples/TimeServer/src/TimeServer.cpp#1 $
+//
+// Copyright (c) 2007, Applied Informatics Software Engineering GmbH.
+// All rights reserved.
+//
+// This is unpublished proprietary source code of Applied Informatics.
+// The contents of this file may not be disclosed to third parties,
+// copied or duplicated in any form, in whole or in part.
+//
+
+
+#include "Poco/Net/HTTPServer.h"
+#include "Poco/Net/HTTPRequestHandler.h"
+#include "Poco/Net/HTTPRequestHandlerFactory.h"
+#include "Poco/Net/HTTPServerRequest.h"
+#include "Poco/Net/HTTPServerResponse.h"
+#include "Poco/Timestamp.h"
+#include "Poco/DateTimeFormatter.h"
+#include "Poco/DateTimeFormat.h"
+#include "Poco/ClassLibrary.h"
+
+
+using Poco::Net::HTTPRequestHandler;
+using Poco::Net::HTTPRequestHandlerFactory;
+using Poco::Net::HTTPServerRequest;
+using Poco::Net::HTTPServerResponse;
+using Poco::Timestamp;
+using Poco::DateTimeFormatter;
+using Poco::DateTimeFormat;
+
+
+class TimeRequestHandler: public HTTPRequestHandler
+ /// Return a HTML document with the current date and time.
+{
+public:
+ TimeRequestHandler()
+ {
+ }
+
+ void handleRequest(HTTPServerRequest& request, HTTPServerResponse& response)
+ {
+ Timestamp now;
+ std::string dt(DateTimeFormatter::format(now, DateTimeFormat::SORTABLE_FORMAT));
+
+ response.setChunkedTransferEncoding(true);
+ response.setContentType("text/html");
+
+ std::ostream& ostr = response.send();
+ ostr << "TimeServer powered by POCO ApacheConnector";
+ ostr << "";
+ ostr << "";
+ ostr << dt;
+ ostr << "
";
+ }
+};
+
+
+class TimeRequestHandlerFactory: public HTTPRequestHandlerFactory
+{
+public:
+ TimeRequestHandlerFactory()
+ {
+ }
+
+ HTTPRequestHandler* createRequestHandler(const HTTPServerRequest& request)
+ {
+ return new TimeRequestHandler;
+ }
+};
+
+
+POCO_BEGIN_MANIFEST(HTTPRequestHandlerFactory)
+ POCO_EXPORT_CLASS(TimeRequestHandlerFactory)
+POCO_END_MANIFEST
diff --git a/ApacheConnector/samples/dependencies b/ApacheConnector/samples/dependencies
new file mode 100644
index 000000000..5704ae3ff
--- /dev/null
+++ b/ApacheConnector/samples/dependencies
@@ -0,0 +1,4 @@
+Net
+Util
+XML
+Foundation
diff --git a/ApacheConnector/samples/samples_vs71.sln b/ApacheConnector/samples/samples_vs71.sln
new file mode 100644
index 000000000..ed6c79d0f
--- /dev/null
+++ b/ApacheConnector/samples/samples_vs71.sln
@@ -0,0 +1,39 @@
+Microsoft Visual Studio Solution File, Format Version 8.00
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TimeServer", "TimeServer\TimeServer_vs71.vcproj", "{7720D4EF-F5DD-4265-91C5-83980CB70B84}"
+ ProjectSection(ProjectDependencies) = postProject
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FormServer", "FormServer\FormServer_vs71.vcproj", "{198BFE74-AD16-4D8B-81F7-F700B3B6456F}"
+ ProjectSection(ProjectDependencies) = postProject
+ EndProjectSection
+EndProject
+Global
+ GlobalSection(SolutionConfiguration) = preSolution
+ debug_shared = debug_shared
+ debug_static = debug_static
+ release_shared = release_shared
+ release_static = release_static
+ EndGlobalSection
+ GlobalSection(ProjectConfiguration) = postSolution
+ {7720D4EF-F5DD-4265-91C5-83980CB70B84}.debug_shared.ActiveCfg = debug_shared|Win32
+ {7720D4EF-F5DD-4265-91C5-83980CB70B84}.debug_shared.Build.0 = debug_shared|Win32
+ {7720D4EF-F5DD-4265-91C5-83980CB70B84}.debug_static.ActiveCfg = debug_shared|Win32
+ {7720D4EF-F5DD-4265-91C5-83980CB70B84}.debug_static.Build.0 = debug_shared|Win32
+ {7720D4EF-F5DD-4265-91C5-83980CB70B84}.release_shared.ActiveCfg = release_shared|Win32
+ {7720D4EF-F5DD-4265-91C5-83980CB70B84}.release_shared.Build.0 = release_shared|Win32
+ {7720D4EF-F5DD-4265-91C5-83980CB70B84}.release_static.ActiveCfg = release_shared|Win32
+ {7720D4EF-F5DD-4265-91C5-83980CB70B84}.release_static.Build.0 = release_shared|Win32
+ {198BFE74-AD16-4D8B-81F7-F700B3B6456F}.debug_shared.ActiveCfg = debug_shared|Win32
+ {198BFE74-AD16-4D8B-81F7-F700B3B6456F}.debug_shared.Build.0 = debug_shared|Win32
+ {198BFE74-AD16-4D8B-81F7-F700B3B6456F}.debug_static.ActiveCfg = debug_shared|Win32
+ {198BFE74-AD16-4D8B-81F7-F700B3B6456F}.debug_static.Build.0 = debug_shared|Win32
+ {198BFE74-AD16-4D8B-81F7-F700B3B6456F}.release_shared.ActiveCfg = release_shared|Win32
+ {198BFE74-AD16-4D8B-81F7-F700B3B6456F}.release_shared.Build.0 = release_shared|Win32
+ {198BFE74-AD16-4D8B-81F7-F700B3B6456F}.release_static.ActiveCfg = release_shared|Win32
+ {198BFE74-AD16-4D8B-81F7-F700B3B6456F}.release_static.Build.0 = release_shared|Win32
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ EndGlobalSection
+ GlobalSection(ExtensibilityAddIns) = postSolution
+ EndGlobalSection
+EndGlobal
diff --git a/ApacheConnector/samples/samples_vs80.sln b/ApacheConnector/samples/samples_vs80.sln
new file mode 100644
index 000000000..314434083
--- /dev/null
+++ b/ApacheConnector/samples/samples_vs80.sln
@@ -0,0 +1,25 @@
+Microsoft Visual Studio Solution File, Format Version 9.00
+# Visual Studio 2005
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TimeServer", "TimeServer\TimeServer_vs80.vcproj", "{7720D4EF-F5DD-4265-91C5-83980CB70B84}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FormServer", "FormServer\FormServer_vs80.vcproj", "{198BFE74-AD16-4D8B-81F7-F700B3B6456F}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ debug_shared|Win32 = debug_shared|Win32
+ release_shared|Win32 = release_shared|Win32
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {7720D4EF-F5DD-4265-91C5-83980CB70B84}.debug_shared|Win32.ActiveCfg = debug_shared|Win32
+ {7720D4EF-F5DD-4265-91C5-83980CB70B84}.debug_shared|Win32.Build.0 = debug_shared|Win32
+ {7720D4EF-F5DD-4265-91C5-83980CB70B84}.release_shared|Win32.ActiveCfg = release_shared|Win32
+ {7720D4EF-F5DD-4265-91C5-83980CB70B84}.release_shared|Win32.Build.0 = release_shared|Win32
+ {198BFE74-AD16-4D8B-81F7-F700B3B6456F}.debug_shared|Win32.ActiveCfg = debug_shared|Win32
+ {198BFE74-AD16-4D8B-81F7-F700B3B6456F}.debug_shared|Win32.Build.0 = debug_shared|Win32
+ {198BFE74-AD16-4D8B-81F7-F700B3B6456F}.release_shared|Win32.ActiveCfg = release_shared|Win32
+ {198BFE74-AD16-4D8B-81F7-F700B3B6456F}.release_shared|Win32.Build.0 = release_shared|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/ApacheConnector/src/ApacheApplication.cpp b/ApacheConnector/src/ApacheApplication.cpp
new file mode 100644
index 000000000..167fdd337
--- /dev/null
+++ b/ApacheConnector/src/ApacheApplication.cpp
@@ -0,0 +1,57 @@
+//
+// ApacheApplication.cpp
+//
+// $Id: //poco/Main/ApacheConnector/src/ApacheApplication.cpp#2 $
+//
+// Copyright (c) 2007, Applied Informatics Software Engineering GmbH.
+// All rights reserved.
+//
+// This is unpublished proprietary source code of Applied Informatics.
+// The contents of this file may not be disclosed to third parties,
+// copied or duplicated in any form, in whole or in part.
+//
+
+
+#include "ApacheApplication.h"
+#include "ApacheChannel.h"
+#include "Poco/Logger.h"
+#include "Poco/SingletonHolder.h"
+#include
+
+
+using Poco::Logger;
+using Poco::FastMutex;
+
+
+ApacheApplication::ApacheApplication():
+ _ready(false)
+{
+ Logger::root().setChannel(new ApacheChannel);
+}
+
+
+ApacheApplication::~ApacheApplication()
+{
+ Logger::shutdown();
+}
+
+
+void ApacheApplication::setup()
+{
+ FastMutex::ScopedLock lock(_mutex);
+
+ if (!_ready)
+ {
+ std::vector cmdLine;
+ cmdLine.push_back("mod_poco");
+ init(cmdLine);
+ _ready = true;
+ }
+}
+
+
+ApacheApplication& ApacheApplication::instance()
+{
+ static Poco::SingletonHolder sh;
+ return *sh.get();
+}
diff --git a/ApacheConnector/src/ApacheChannel.cpp b/ApacheConnector/src/ApacheChannel.cpp
new file mode 100644
index 000000000..cd03f9013
--- /dev/null
+++ b/ApacheConnector/src/ApacheChannel.cpp
@@ -0,0 +1,33 @@
+//
+// ApacheApplication.cpp
+//
+// $Id: //poco/Main/ApacheConnector/src/ApacheChannel.cpp#1 $
+//
+// Copyright (c) 2007, Applied Informatics Software Engineering GmbH.
+// All rights reserved.
+//
+// This is unpublished proprietary source code of Applied Informatics.
+// The contents of this file may not be disclosed to third parties,
+// copied or duplicated in any form, in whole or in part.
+//
+
+
+#include "ApacheChannel.h"
+#include "ApacheConnector.h"
+#include "Poco/Message.h"
+
+
+ApacheChannel::ApacheChannel()
+{
+}
+
+
+ApacheChannel::~ApacheChannel()
+{
+}
+
+
+void ApacheChannel::log(const Poco::Message& msg)
+{
+ ApacheConnector::log(msg.getSource().c_str(), 0, msg.getPriority(), 0, msg.getText().c_str());
+}
diff --git a/ApacheConnector/src/ApacheConnector.cpp b/ApacheConnector/src/ApacheConnector.cpp
new file mode 100644
index 000000000..9b2094f8b
--- /dev/null
+++ b/ApacheConnector/src/ApacheConnector.cpp
@@ -0,0 +1,290 @@
+//
+// ApacheConnector.cpp
+//
+// $Id: //poco/Main/ApacheConnector/src/ApacheConnector.cpp#6 $
+//
+// Copyright (c) 2007, Applied Informatics Software Engineering GmbH.
+// All rights reserved.
+//
+// This is unpublished proprietary source code of Applied Informatics.
+// The contents of this file may not be disclosed to third parties,
+// copied or duplicated in any form, in whole or in part.
+//
+
+
+#include "ApacheConnector.h"
+#include "ApacheApplication.h"
+#include "ApacheServerRequest.h"
+#include "ApacheServerResponse.h"
+#include "ApacheRequestHandlerFactory.h"
+#include "Poco/Net/HTTPRequestHandler.h"
+#include "httpd.h"
+#include "http_connection.h"
+#include "http_config.h"
+#include "http_core.h"
+#include "http_protocol.h"
+#include "http_log.h"
+#include "apr.h"
+#include "apr_lib.h"
+#include "apr_strings.h"
+#include "apr_buckets.h"
+#include "apr_file_info.h"
+#include "apr_hash.h"
+#define APR_WANT_STRFUNC
+#include "apr_want.h"
+#include "http_request.h"
+#include "util_filter.h"
+
+
+using Poco::Net::HTTPServerRequest;
+using Poco::Net::HTTPServerResponse;
+using Poco::Net::HTTPRequestHandler;
+using Poco::Net::HTTPResponse;
+
+
+extern "C" module AP_MODULE_DECLARE_DATA poco_module;
+
+
+ApacheRequestRec::ApacheRequestRec(request_rec* pRec):
+ _pRec(pRec)
+{
+}
+
+
+bool ApacheRequestRec::haveRequestBody()
+{
+ return ap_should_client_block(_pRec) != 0;
+}
+
+
+int ApacheRequestRec::readRequest(char* buffer, int length)
+{
+ return ap_get_client_block(_pRec, buffer, length);
+}
+
+
+void ApacheRequestRec::writeResponse(const char* buffer, int length)
+{
+ ap_rwrite(buffer, length, _pRec);
+}
+
+
+void ApacheRequestRec::redirect(const std::string& uri)
+{
+ apr_table_set(_pRec->headers_out, "Location", uri.c_str());
+ _pRec->connection->keepalive = AP_CONN_CLOSE;
+ _pRec->status = 302;
+ ap_set_keepalive(_pRec);
+ ap_send_error_response(_pRec, 0);
+}
+
+
+void ApacheRequestRec::sendErrorResponse(int status)
+{
+ _pRec->connection->keepalive = AP_CONN_CLOSE;
+ _pRec->status = status;
+ ap_set_keepalive(_pRec);
+
+ ap_send_error_response(_pRec, 0);
+}
+
+
+void ApacheRequestRec::addHeader(const std::string& key, const std::string& value)
+{
+ const apr_array_header_t *arr = apr_table_elts(_pRec->headers_out);
+ apr_table_add(const_cast(reinterpret_cast(arr)), key.c_str(), value.c_str());
+}
+
+
+void ApacheRequestRec::setContentType(const std::string& mediaType)
+{
+ ap_set_content_type(_pRec, mediaType.c_str());
+}
+
+
+int ApacheRequestRec::sendFile(const std::string& path, unsigned int fileSize, const std::string& mediaType)
+{
+ apr_file_t *thefile = 0;
+ apr_finfo_t finfo;
+ apr_size_t nBytes;
+
+ // setting content-type
+ ap_set_content_type(_pRec, mediaType.c_str());
+
+ // opening file
+ if (apr_file_open(&thefile, path.c_str(), APR_READ, APR_UREAD | APR_GREAD, _pRec->pool) == APR_SUCCESS)
+ {
+ // getting fileinfo
+ apr_file_info_get(&finfo, APR_FINFO_NORM, thefile);
+
+ // setting last-updated & co
+ ap_update_mtime(_pRec, finfo.mtime);
+ ap_set_last_modified(_pRec);
+ ap_set_content_length(_pRec, fileSize);
+
+ // sending file
+ ap_send_fd(thefile, _pRec, 0, fileSize, &nBytes);
+
+ // well done
+ return 0;
+ }
+
+ // file not opened successfully -> produce an exception in C++ code
+ return 1;
+}
+
+
+void ApacheRequestRec::copyHeaders(ApacheServerRequest& request)
+{
+ const apr_array_header_t* arr = apr_table_elts(_pRec->headers_in);
+ const apr_table_entry_t* elts = (const apr_table_entry_t *)arr->elts;
+
+ request.setMethod(_pRec->method);
+ request.setURI(_pRec->unparsed_uri);
+
+ // iterating over raw-headers and printing them
+ for (int i = 0; i < arr->nelts; i++)
+ {
+ request.add(elts[i].key, elts[i].val);
+ }
+}
+
+
+void ApacheConnector::log(const char* file, int line, int level, int status, const char *text)
+{
+ ap_log_error(file, line, level, 0, NULL, text);
+}
+
+
+extern "C" int ApacheConnector_handler(request_rec *r)
+{
+ ApacheRequestRec rec(r);
+ ApacheApplication& app(ApacheApplication::instance());
+
+ try
+ {
+ // ensure application is ready
+ app.setup();
+
+ // if the ApacheRequestHandler declines handling - we stop
+ // request handling here and let other modules do their job!
+ if (!app.factory().mustHandle(r->uri))
+ return DECLINED;
+
+ apr_status_t rv;
+ if ((rv = ap_setup_client_block(r, REQUEST_CHUNKED_DECHUNK)))
+ return rv;
+
+ std::auto_ptr pRequest(new ApacheServerRequest(
+ &rec,
+ r->connection->local_ip,
+ r->connection->local_addr->port,
+ r->connection->remote_ip,
+ r->connection->remote_addr->port));
+
+ std::auto_ptr pResponse(new ApacheServerResponse(pRequest.get()));
+
+ // add header information to request
+ rec.copyHeaders(*pRequest);
+
+ try
+ {
+ std::auto_ptr pHandler(app.factory().createRequestHandler(*pRequest));
+
+ if (pHandler.get())
+ {
+ pHandler->handleRequest(*pRequest, *pResponse);
+ }
+ else
+ {
+ pResponse->sendErrorResponse(HTTP_NOT_IMPLEMENTED);
+ }
+ }
+ catch (...)
+ {
+ pResponse->sendErrorResponse(HTTP_INTERNAL_SERVER_ERROR);
+ throw;
+ }
+ }
+ catch (Poco::Exception& exc)
+ {
+ ApacheConnector::log(__FILE__, __LINE__, ApacheConnector::PRIO_ERROR, 0, exc.displayText().c_str());
+ }
+ catch (...)
+ {
+ ApacheConnector::log(__FILE__, __LINE__, ApacheConnector::PRIO_ERROR, 0, "Unknown exception");
+ }
+ return OK;
+}
+
+
+extern "C" void ApacheConnector_register_hooks(apr_pool_t *p)
+{
+ ap_hook_handler(ApacheConnector_handler, NULL, NULL, APR_HOOK_MIDDLE);
+}
+
+
+extern "C" const char* ApacheConnector_uris(cmd_parms *cmd, void *in_dconf, const char *in_str)
+{
+ try
+ {
+ ApacheApplication::instance().factory().handleURIs(in_str);
+ }
+ catch (Poco::Exception& exc)
+ {
+ ApacheConnector::log(__FILE__, __LINE__, ApacheConnector::PRIO_ERROR, 0, exc.displayText().c_str());
+ }
+ catch (...)
+ {
+ ApacheConnector::log(__FILE__, __LINE__, ApacheConnector::PRIO_ERROR, 0, "Unknown exception");
+ }
+ return 0;
+}
+
+
+extern "C" const char* ApacheConnector_config(cmd_parms *cmd, void *in_dconf, const char *in_str)
+{
+ try
+ {
+ ApacheApplication::instance().loadConfiguration(in_str);
+ }
+ catch (Poco::Exception& exc)
+ {
+ ApacheConnector::log(__FILE__, __LINE__, ApacheConnector::PRIO_ERROR, 0, exc.displayText().c_str());
+ }
+ catch (...)
+ {
+ ApacheConnector::log(__FILE__, __LINE__, ApacheConnector::PRIO_ERROR, 0, "Unknown exception");
+ }
+ return 0;
+}
+
+
+extern "C" const command_rec ApacheConnector_cmds[] =
+{
+ AP_INIT_RAW_ARGS(
+ "AddPocoRequestHandler",
+ reinterpret_cast(ApacheConnector_uris),
+ NULL,
+ RSRC_CONF,
+ "POCO RequestHandlerFactory class name followed by shared library path followed by a list of ' ' separated URIs that must be handled by this module."),
+ AP_INIT_RAW_ARGS(
+ "AddPocoConfig",
+ reinterpret_cast(ApacheConnector_config),
+ NULL,
+ RSRC_CONF,
+ "Path of the POCO configuration file."),
+ { NULL }
+};
+
+
+module AP_MODULE_DECLARE_DATA poco_module =
+{
+ STANDARD20_MODULE_STUFF,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ ApacheConnector_cmds,
+ ApacheConnector_register_hooks
+};
diff --git a/ApacheConnector/src/ApacheRequestHandlerFactory.cpp b/ApacheConnector/src/ApacheRequestHandlerFactory.cpp
new file mode 100644
index 000000000..21f24d759
--- /dev/null
+++ b/ApacheConnector/src/ApacheRequestHandlerFactory.cpp
@@ -0,0 +1,118 @@
+//
+// ApacheRequestHandlerFactory.cpp
+//
+// $Id: //poco/Main/ApacheConnector/src/ApacheRequestHandlerFactory.cpp#8 $
+//
+// Copyright (c) 2007, Applied Informatics Software Engineering GmbH.
+// All rights reserved.
+//
+// This is unpublished proprietary source code of Applied Informatics.
+// The contents of this file may not be disclosed to third parties,
+// copied or duplicated in any form, in whole or in part.
+//
+
+
+#include "ApacheRequestHandlerFactory.h"
+#include "ApacheConnector.h"
+#include "Poco/Net/HTTPRequestHandler.h"
+#include "Poco/StringTokenizer.h"
+#include "Poco/Manifest.h"
+#include "Poco/File.h"
+#include
+
+
+using Poco::StringTokenizer;
+using Poco::FastMutex;
+
+
+ApacheRequestHandlerFactory::ApacheRequestHandlerFactory()
+{
+}
+
+
+ApacheRequestHandlerFactory::~ApacheRequestHandlerFactory()
+{
+}
+
+
+Poco::Net::HTTPRequestHandler* ApacheRequestHandlerFactory::createRequestHandler(const Poco::Net::HTTPServerRequest& request)
+{
+ FastMutex::ScopedLock lock(_mutex);
+
+ // only if the given uri is found in _uris we are
+ // handling this request.
+ RequestHandlerFactories::iterator it = _requestHandlers.begin();
+ RequestHandlerFactories::iterator itEnd = _requestHandlers.end();
+ std::string uri = request.getURI();
+
+ // if any uri in our map is found at the beginning of the given
+ // uri -> then we handle it!!
+ for (; it != itEnd; it++)
+ {
+ if (uri.find(it->first) == 0 || it->first.find(uri) == 0)
+ {
+ return it->second->createRequestHandler(request);
+ }
+ }
+
+ return 0;
+}
+
+
+void ApacheRequestHandlerFactory::handleURIs(const std::string& uris)
+{
+ FastMutex::ScopedLock lock(_mutex);
+
+ StringTokenizer st(uris, " ", StringTokenizer::TOK_TRIM);
+ StringTokenizer::Iterator it = st.begin();
+ StringTokenizer::Iterator itEnd = st.end();
+ std::string factoryName = (*it);
+ it++;
+ std::string dllName = (*it);
+ it++;
+
+ for (; it != itEnd; it++)
+ {
+ addRequestHandlerFactory(dllName, factoryName, *it);
+ }
+}
+
+
+void ApacheRequestHandlerFactory::addRequestHandlerFactory(const std::string& dllPath, const std::string& factoryName, const std::string& uri)
+{
+ try
+ {
+ _loader.loadLibrary(dllPath);
+ Poco::Net::HTTPRequestHandlerFactory* pFactory = _loader.classFor(factoryName).create();
+ _requestHandlers.insert(std::make_pair(uri, pFactory));
+ }
+ catch (Poco::Exception& exc)
+ {
+ ApacheConnector::log(__FILE__, __LINE__, ApacheConnector::PRIO_ERROR, 0, exc.displayText().c_str());
+ }
+}
+
+
+bool ApacheRequestHandlerFactory::mustHandle(const std::string& uri)
+{
+ FastMutex::ScopedLock lock(_mutex);
+
+ // only if the given uri is found in _uris we are
+ // handling this request.
+ RequestHandlerFactories::iterator it = _requestHandlers.begin();
+ RequestHandlerFactories::iterator itEnd = _requestHandlers.end();
+
+ // if any uri in our map is found at the beginning of the given
+ // uri -> then we handle it!!
+ for (; it != itEnd; it++)
+ {
+ // dealing with both cases:
+ // handler is registered with: /download
+ // uri: /download/xyz
+ // uri: /download
+ if (uri.find(it->first) == 0 || it->first.find(uri) == 0)
+ return true;
+ }
+
+ return false;
+}
diff --git a/ApacheConnector/src/ApacheServerRequest.cpp b/ApacheConnector/src/ApacheServerRequest.cpp
new file mode 100644
index 000000000..6d0601757
--- /dev/null
+++ b/ApacheConnector/src/ApacheServerRequest.cpp
@@ -0,0 +1,64 @@
+//
+// ApacheServerRequest.cpp
+//
+// $Id: //poco/Main/ApacheConnector/src/ApacheServerRequest.cpp#9 $
+//
+// Copyright (c) 2007, Applied Informatics Software Engineering GmbH.
+// All rights reserved.
+//
+// This is unpublished proprietary source code of Applied Informatics.
+// The contents of this file may not be disclosed to third parties,
+// copied or duplicated in any form, in whole or in part.
+//
+
+
+#include "ApacheServerRequest.h"
+#include "ApacheServerResponse.h"
+#include "ApacheRequestHandlerFactory.h"
+#include "Poco/Exception.h"
+#include
+
+
+ApacheServerRequest::ApacheServerRequest(
+ ApacheRequestRec* pApacheRequest,
+ const char* serverName,
+ int serverPort,
+ const char* clientName,
+ int clientPort):
+ _pApacheRequest(pApacheRequest),
+ _pResponse(0),
+ _pStream(new ApacheInputStream(_pApacheRequest)),
+ _serverAddress(serverName, serverPort),
+ _clientAddress(clientName, clientPort)
+{
+}
+
+
+ApacheServerRequest::~ApacheServerRequest()
+{
+ delete _pStream;
+}
+
+
+const Poco::Net::HTTPServerParams& ApacheServerRequest::serverParams() const
+{
+ throw Poco::NotImplementedException("No HTTPServerParams available in Apache modules.");
+}
+
+
+Poco::Net::HTTPServerResponse& ApacheServerRequest::response() const
+{
+ return *_pResponse;
+}
+
+
+void ApacheServerRequest::setResponse(ApacheServerResponse* pResponse)
+{
+ _pResponse = pResponse;
+}
+
+
+bool ApacheServerRequest::expectContinue() const
+{
+ return false;
+}
diff --git a/ApacheConnector/src/ApacheServerResponse.cpp b/ApacheConnector/src/ApacheServerResponse.cpp
new file mode 100644
index 000000000..ff9a22969
--- /dev/null
+++ b/ApacheConnector/src/ApacheServerResponse.cpp
@@ -0,0 +1,133 @@
+//
+// ApacheServerResponse.cpp
+//
+// $Id: //poco/Main/ApacheConnector/src/ApacheServerResponse.cpp#8 $
+//
+// Copyright (c) 2007, Applied Informatics Software Engineering GmbH.
+// All rights reserved.
+//
+// This is unpublished proprietary source code of Applied Informatics.
+// The contents of this file may not be disclosed to third parties,
+// copied or duplicated in any form, in whole or in part.
+//
+
+
+#include "ApacheServerResponse.h"
+#include "ApacheServerRequest.h"
+#include "ApacheStream.h"
+#include "ApacheConnector.h"
+#include "Poco/Net/HTTPCookie.h"
+#include "Poco/File.h"
+#include "Poco/Exception.h"
+#include
+#include
+
+
+using Poco::File;
+using Poco::OpenFileException;
+using Poco::Net::HTTPCookie;
+
+
+ApacheServerResponse::ApacheServerResponse(ApacheServerRequest* pRequest):
+ _pStream(0),
+ _pApacheRequest(pRequest->_pApacheRequest)
+{
+ setVersion(pRequest->getVersion());
+ setKeepAlive(pRequest->getKeepAlive());
+
+ pRequest->setResponse(this);
+}
+
+
+ApacheServerResponse::~ApacheServerResponse()
+{
+ delete _pStream;
+}
+
+
+void ApacheServerResponse::initApacheOutputStream()
+{
+ poco_assert (!_pStream);
+
+ _pApacheRequest->setContentType(getContentType());
+
+ std::vector cookies;
+ getCookies(cookies);
+
+ std::size_t cnt = cookies.size();
+ for (int c = 0; c < cnt; c++)
+ {
+ _pApacheRequest->addHeader("Set-Cookie", cookies[c].toString());
+ }
+
+ _pStream = new ApacheOutputStream(_pApacheRequest);
+}
+
+
+void ApacheServerResponse::sendContinue()
+{
+ // should be handled by Apache
+}
+
+
+std::ostream& ApacheServerResponse::send()
+{
+ poco_assert (!_pStream);
+
+ initApacheOutputStream();
+
+ return *_pStream;
+}
+
+
+void ApacheServerResponse::sendFile(const std::string& path, const std::string& mediaType)
+{
+ poco_assert (!_pStream);
+
+ initApacheOutputStream();
+
+ File f(path);
+ if (_pApacheRequest->sendFile(path, static_cast(f.getSize()), mediaType) != 0)
+ throw OpenFileException(path);
+}
+
+
+void ApacheServerResponse::sendBuffer(const void* pBuffer, std::size_t length)
+{
+ poco_assert (!_pStream);
+
+ initApacheOutputStream();
+
+ _pStream->write(static_cast(pBuffer), static_cast(length));
+}
+
+
+void ApacheServerResponse::redirect(const std::string& uri)
+{
+ poco_assert (!_pStream);
+
+ initApacheOutputStream();
+
+ try
+ {
+ _pApacheRequest->redirect(uri);
+ }
+ catch (Poco::Exception&)
+ {
+ ApacheConnector::log(__FILE__, __LINE__, 7 , 0, "caught exception in ApacheServerResponse::redirect - ignoring\n");
+ }
+}
+
+
+void ApacheServerResponse::sendErrorResponse(int status)
+{
+ initApacheOutputStream();
+
+ _pApacheRequest->sendErrorResponse(status);
+}
+
+
+void ApacheServerResponse::requireAuthentication(const std::string& realm)
+{
+ // should be handled by Apache
+}
diff --git a/ApacheConnector/src/ApacheStream.cpp b/ApacheConnector/src/ApacheStream.cpp
new file mode 100644
index 000000000..1c331b243
--- /dev/null
+++ b/ApacheConnector/src/ApacheStream.cpp
@@ -0,0 +1,124 @@
+//
+// ApacheStream.h
+//
+// $Id: //poco/Main/ApacheConnector/src/ApacheStream.cpp#9 $
+//
+// Copyright (c) 2007, Applied Informatics Software Engineering GmbH.
+// All rights reserved.
+//
+// This is unpublished proprietary source code of Applied Informatics.
+// The contents of this file may not be disclosed to third parties,
+// copied or duplicated in any form, in whole or in part.
+//
+
+
+#include "ApacheStream.h"
+#include "ApacheConnector.h"
+#include "Poco/Exception.h"
+
+
+using Poco::BufferedStreamBuf;
+
+
+//
+// ApacheStreamBuf
+//
+
+
+ApacheStreamBuf::ApacheStreamBuf(ApacheRequestRec* pApacheRequest, bool haveData):
+ BufferedStreamBuf(STREAM_BUFFER_SIZE, std::ios::in | std::ios::out),
+ _pApacheRequest(pApacheRequest),
+ _haveData(haveData)
+{
+}
+
+
+ApacheStreamBuf::~ApacheStreamBuf()
+{
+}
+
+
+int ApacheStreamBuf::readFromDevice(char* buffer, std::streamsize len)
+{
+ if (_haveData)
+ return _pApacheRequest->readRequest(buffer, static_cast(len));
+ else
+ return 0;
+}
+
+
+int ApacheStreamBuf::writeToDevice(const char* buffer, std::streamsize length)
+{
+ _pApacheRequest->writeResponse(buffer, length);
+ return length;
+}
+
+
+//
+// ApacheIOS
+//
+
+
+ApacheIOS::ApacheIOS(ApacheRequestRec* pApacheRequest, bool haveData):
+ _buf(pApacheRequest, haveData)
+{
+ poco_ios_init(&_buf);
+}
+
+
+ApacheIOS::~ApacheIOS()
+{
+ try
+ {
+ _buf.sync();
+ }
+ catch (...)
+ {
+ }
+}
+
+
+ApacheStreamBuf* ApacheIOS::rdbuf()
+{
+ return &_buf;
+}
+
+
+void ApacheIOS::close()
+{
+ _buf.sync();
+}
+
+
+//
+// ApacheOutputStream
+//
+
+
+ApacheOutputStream::ApacheOutputStream(ApacheRequestRec* pApacheRequest):
+ ApacheIOS(pApacheRequest),
+ std::ostream(&_buf)
+{
+}
+
+
+ApacheOutputStream::~ApacheOutputStream()
+{
+}
+
+
+//
+// ApacheInputStream
+//
+
+
+ApacheInputStream::ApacheInputStream(ApacheRequestRec* pApacheRequest):
+ ApacheIOS(pApacheRequest, pApacheRequest->haveRequestBody()),
+ std::istream(&_buf)
+{
+}
+
+
+ApacheInputStream::~ApacheInputStream()
+{
+}