diff --git a/ApacheConnector/include/ApacheApplication.h b/ApacheConnector/include/ApacheApplication.h index cf08f21cf..0aabd1eae 100644 --- a/ApacheConnector/include/ApacheApplication.h +++ b/ApacheConnector/include/ApacheApplication.h @@ -1,60 +1,78 @@ -// -// ApacheApplication.h -// -// $Id: //poco/Main/ApacheConnector/include/ApacheApplication.h#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. -// - - -#ifndef ApacheConnector_ApacheApplication_INCLUDED -#define ApacheConnector_ApacheApplication_INCLUDED - - -#include "ApacheRequestHandlerFactory.h" -#include "Poco/Util/Application.h" -#include "Poco/Mutex.h" - - -class ApacheApplication: public Poco::Util::Application -{ -public: - ApacheApplication(); - /// Creates the ApacheApplication and sets the - /// ApacheChannel as the root logger channel. - - ~ApacheApplication(); - /// Destroys the ApacheApplication. - - void setup(); - /// Initializes the application if called for the first - /// time; does nothing in later calls. - - ApacheRequestHandlerFactory& factory(); - /// Returns the ApacheRequestHandlerFactory. - - static ApacheApplication& instance(); - /// Returns the application instance. - -private: - bool _ready; - ApacheRequestHandlerFactory _factory; - Poco::FastMutex _mutex; -}; - - -// -// inlines -// -inline ApacheRequestHandlerFactory& ApacheApplication::factory() -{ - return _factory; -} - - -#endif // ApacheConnector_ApacheApplication_INCLUDED +// +// ApacheApplication.h +// +// $Id: //poco/1.4/ApacheConnector/include/ApacheApplication.h#2 $ +// +// Copyright (c) 2006-2011, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef ApacheConnector_ApacheApplication_INCLUDED +#define ApacheConnector_ApacheApplication_INCLUDED + + +#include "ApacheRequestHandlerFactory.h" +#include "Poco/Util/Application.h" +#include "Poco/Mutex.h" + + +class ApacheApplication: public Poco::Util::Application +{ +public: + ApacheApplication(); + /// Creates the ApacheApplication and sets the + /// ApacheChannel as the root logger channel. + + ~ApacheApplication(); + /// Destroys the ApacheApplication. + + void setup(); + /// Initializes the application if called for the first + /// time; does nothing in later calls. + + ApacheRequestHandlerFactory& factory(); + /// Returns the ApacheRequestHandlerFactory. + + static ApacheApplication& instance(); + /// Returns the application instance. + +private: + bool _ready; + ApacheRequestHandlerFactory _factory; + Poco::FastMutex _mutex; +}; + + +// +// inlines +// +inline ApacheRequestHandlerFactory& ApacheApplication::factory() +{ + return _factory; +} + + +#endif // ApacheConnector_ApacheApplication_INCLUDED diff --git a/ApacheConnector/include/ApacheChannel.h b/ApacheConnector/include/ApacheChannel.h index 128f6ebc3..8cf3f266a 100644 --- a/ApacheConnector/include/ApacheChannel.h +++ b/ApacheConnector/include/ApacheChannel.h @@ -1,34 +1,52 @@ -// -// ApacheChannel.h -// -// $Id: //poco/Main/ApacheConnector/include/ApacheChannel.h#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. -// - - -#ifndef ApacheConnector_ApacheChannel_INCLUDED -#define ApacheConnector_ApacheChannel_INCLUDED - - -#include "Poco/Channel.h" - - -class ApacheChannel: public Poco::Channel - /// This class implements a logging channel - /// that uses the Apache logging facilities. -{ -public: - ApacheChannel(); - ~ApacheChannel(); - - void log(const Poco::Message& msg); -}; - - -#endif // ApacheConnector_ApacheChannel_INCLUDED +// +// ApacheChannel.h +// +// $Id: //poco/1.4/ApacheConnector/include/ApacheChannel.h#2 $ +// +// Copyright (c) 2006-2011, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef ApacheConnector_ApacheChannel_INCLUDED +#define ApacheConnector_ApacheChannel_INCLUDED + + +#include "Poco/Channel.h" + + +class ApacheChannel: public Poco::Channel + /// This class implements a logging channel + /// that uses the Apache logging facilities. +{ +public: + ApacheChannel(); + ~ApacheChannel(); + + void log(const Poco::Message& msg); +}; + + +#endif // ApacheConnector_ApacheChannel_INCLUDED diff --git a/ApacheConnector/include/ApacheConnector.h b/ApacheConnector/include/ApacheConnector.h index aeb8ec489..4fa9d5f03 100644 --- a/ApacheConnector/include/ApacheConnector.h +++ b/ApacheConnector/include/ApacheConnector.h @@ -1,90 +1,108 @@ -// -// ApacheConnector.h -// -// $Id: //poco/Main/ApacheConnector/include/ApacheConnector.h#3 $ -// -// 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. -// - - -#ifndef ApacheConnector_ApacheConnector_INCLUDED -#define ApacheConnector_ApacheConnector_INCLUDED - - -#include - - -struct request_rec; -class ApacheServerRequest; - - -class ApacheRequestRec - /// This class wraps an Apache request_rec. -{ -public: - ApacheRequestRec(request_rec* _pRec); - /// Creates the ApacheRequestRec; - - bool haveRequestBody(); - /// Returns true if the request contains a body. - - int readRequest(char* buffer, int length); - /// Read up to length bytes from request body into buffer. - /// Returns the number of bytes read, 0 if eof or -1 if an error occured. - - void writeResponse(const char* buffer, int length); - /// Writes the given characters as response to the given request_rec. - - void addHeader(const std::string& key, const std::string& value); - /// Adds the given key / value pair to the outgoing headers of the - /// http response. - - void setContentType(const std::string& mediaType); - /// Sets the response content type. - - void redirect(const std::string& uri); - /// Redirects the response to the given uri. - - void sendErrorResponse(int status); - /// Sends an error response with the given HTTP status code. - - int sendFile(const std::string& path, unsigned int fileSize, const std::string& mediaType); - /// Sends the file given by fileName as response. - - void copyHeaders(ApacheServerRequest& request); - /// Copies the request uri and header fields from the Apache request - /// to the ApacheServerRequest. - -private: - request_rec* _pRec; -}; - - -class ApacheConnector - /// This class provides static methods wrapping the - /// Apache API. -{ -public: - enum LogLevel - { - PRIO_FATAL = 1, /// A fatal error. The application will most likely terminate. This is the highest priority. - PRIO_CRITICAL, /// A critical error. The application might not be able to continue running successfully. - PRIO_ERROR, /// An error. An operation did not complete successfully, but the application as a whole is not affected. - PRIO_WARNING, /// A warning. An operation completed with an unexpected result. - PRIO_NOTICE, /// A notice, which is an information with just a higher priority. - PRIO_INFORMATION, /// An informational message, usually denoting the successful completion of an operation. - PRIO_DEBUG, /// A debugging message. - PRIO_TRACE /// A tracing message. This is the lowest priority. - }; - - static void log(const char* file, int line, int level, int status, const char* text); - /// Log the given message. -}; - - -#endif // ApacheConnector_ApacheConnector_INCLUDED +// +// ApacheConnector.h +// +// $Id: //poco/1.4/ApacheConnector/include/ApacheConnector.h#2 $ +// +// Copyright (c) 2006-2011, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef ApacheConnector_ApacheConnector_INCLUDED +#define ApacheConnector_ApacheConnector_INCLUDED + + +#include + + +struct request_rec; +class ApacheServerRequest; + + +class ApacheRequestRec + /// This class wraps an Apache request_rec. +{ +public: + ApacheRequestRec(request_rec* _pRec); + /// Creates the ApacheRequestRec; + + bool haveRequestBody(); + /// Returns true if the request contains a body. + + int readRequest(char* buffer, int length); + /// Read up to length bytes from request body into buffer. + /// Returns the number of bytes read, 0 if eof or -1 if an error occured. + + void writeResponse(const char* buffer, int length); + /// Writes the given characters as response to the given request_rec. + + void addHeader(const std::string& key, const std::string& value); + /// Adds the given key / value pair to the outgoing headers of the + /// http response. + + void setContentType(const std::string& mediaType); + /// Sets the response content type. + + void redirect(const std::string& uri, int status); + /// Redirects the response to the given uri. + + void sendErrorResponse(int status); + /// Sends an error response with the given HTTP status code. + + int sendFile(const std::string& path, unsigned int fileSize, const std::string& mediaType); + /// Sends the file given by fileName as response. + + void copyHeaders(ApacheServerRequest& request); + /// Copies the request uri and header fields from the Apache request + /// to the ApacheServerRequest. + +private: + request_rec* _pRec; +}; + + +class ApacheConnector + /// This class provides static methods wrapping the + /// Apache API. +{ +public: + enum LogLevel + { + PRIO_FATAL = 1, /// A fatal error. The application will most likely terminate. This is the highest priority. + PRIO_CRITICAL, /// A critical error. The application might not be able to continue running successfully. + PRIO_ERROR, /// An error. An operation did not complete successfully, but the application as a whole is not affected. + PRIO_WARNING, /// A warning. An operation completed with an unexpected result. + PRIO_NOTICE, /// A notice, which is an information with just a higher priority. + PRIO_INFORMATION, /// An informational message, usually denoting the successful completion of an operation. + PRIO_DEBUG, /// A debugging message. + PRIO_TRACE /// A tracing message. This is the lowest priority. + }; + + static void log(const char* file, int line, int level, int status, const char* text); + /// Log the given message. +}; + + +#endif // ApacheConnector_ApacheConnector_INCLUDED diff --git a/ApacheConnector/include/ApacheRequestHandlerFactory.h b/ApacheConnector/include/ApacheRequestHandlerFactory.h index 9769dadd4..d746c0e22 100644 --- a/ApacheConnector/include/ApacheRequestHandlerFactory.h +++ b/ApacheConnector/include/ApacheRequestHandlerFactory.h @@ -1,59 +1,77 @@ -// -// ApacheRequestHandlerFactory.h -// -// $Id: //poco/Main/ApacheConnector/include/ApacheRequestHandlerFactory.h#5 $ -// -// 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. -// - - -#ifndef ApacheConnector_ApacheRequestHandlerFactory_INCLUDED -#define ApacheConnector_ApacheRequestHandlerFactory_INCLUDED - - -#include "ApacheServerRequest.h" -#include "Poco/Net/HTTPRequestHandlerFactory.h" -#include "Poco/ClassLoader.h" -#include "Poco/Mutex.h" -#include - - -class ApacheRequestHandlerFactory: public Poco::Net::HTTPRequestHandlerFactory -{ -public: - ApacheRequestHandlerFactory(); - /// Constructs the ApacheRequestHandlerFactory - - ~ApacheRequestHandlerFactory(); - /// Destructor of the ApacheRequestHandlerFactory - - Poco::Net::HTTPRequestHandler* createRequestHandler(const Poco::Net::HTTPServerRequest& request); - /// Creates a new request handler for the given HTTP request. - - bool mustHandle(const std::string& uri); - /// Returns 1 if the given uri must be handled by the - /// poco_mapper module, 0 otherwise. - - void handleURIs(const std::string& uris); - /// Parses the given string for dllName, factoryName and the URIs to handle - /// by the request-handler - - void addRequestHandlerFactory(const std::string& dllPath, const std::string& factoryName, const std::string& uri); - /// Adds the request handler from the given dll with the given name and - /// registers that handler with the given uri - -private: - typedef std::map RequestHandlerFactories; - - RequestHandlerFactories _requestHandlers; - Poco::ClassLoader _loader; - Poco::FastMutex _mutex; -}; - - -#endif // ApacheConnector_ApacheRequestHandlerFactory_INCLUDED +// +// ApacheRequestHandlerFactory.h +// +// $Id: //poco/1.4/ApacheConnector/include/ApacheRequestHandlerFactory.h#2 $ +// +// Copyright (c) 2006-2011, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef ApacheConnector_ApacheRequestHandlerFactory_INCLUDED +#define ApacheConnector_ApacheRequestHandlerFactory_INCLUDED + + +#include "ApacheServerRequest.h" +#include "Poco/Net/HTTPRequestHandlerFactory.h" +#include "Poco/ClassLoader.h" +#include "Poco/Mutex.h" +#include + + +class ApacheRequestHandlerFactory: public Poco::Net::HTTPRequestHandlerFactory +{ +public: + ApacheRequestHandlerFactory(); + /// Constructs the ApacheRequestHandlerFactory + + ~ApacheRequestHandlerFactory(); + /// Destructor of the ApacheRequestHandlerFactory + + Poco::Net::HTTPRequestHandler* createRequestHandler(const Poco::Net::HTTPServerRequest& request); + /// Creates a new request handler for the given HTTP request. + + bool mustHandle(const std::string& uri); + /// Returns 1 if the given uri must be handled by the + /// poco_mapper module, 0 otherwise. + + void handleURIs(const std::string& uris); + /// Parses the given string for dllName, factoryName and the URIs to handle + /// by the request-handler + + void addRequestHandlerFactory(const std::string& dllPath, const std::string& factoryName, const std::string& uri); + /// Adds the request handler from the given dll with the given name and + /// registers that handler with the given uri + +private: + typedef std::map RequestHandlerFactories; + + RequestHandlerFactories _requestHandlers; + Poco::ClassLoader _loader; + Poco::FastMutex _mutex; +}; + + +#endif // ApacheConnector_ApacheRequestHandlerFactory_INCLUDED diff --git a/ApacheConnector/include/ApacheServerRequest.h b/ApacheConnector/include/ApacheServerRequest.h index 0671e88ca..ef05f6dd7 100644 --- a/ApacheConnector/include/ApacheServerRequest.h +++ b/ApacheConnector/include/ApacheServerRequest.h @@ -1,102 +1,120 @@ -// -// ApacheServerRequest.h -// -// $Id: //poco/Main/ApacheConnector/include/ApacheServerRequest.h#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. -// - - -#ifndef ApacheConnector_ApacheServerRequest_INCLUDED -#define ApacheConnector_ApacheServerRequest_INCLUDED - - -#include "ApacheConnector.h" -#include "ApacheStream.h" -#include "Poco/Net/HTTPServerRequest.h" -#include - - -class ApacheServerResponse; - - -class ApacheServerRequest: public Poco::Net::HTTPServerRequest -{ -public: - ApacheServerRequest( - ApacheRequestRec* pApacheRequest, - const char* serverName, - int serverPort, - const char* clientName, - int clientPort); - /// Creates a new ApacheServerRequest. - - ~ApacheServerRequest(); - /// Destroys the ApacheServerRequest. - - std::istream& stream(); - /// Returns the input stream for reading - /// the request body. - /// - /// The stream is valid until the HTTPServerRequest - /// object is destroyed. - - bool expectContinue() const; - /// Returns true if the client expects a - /// 100 Continue response. - - const Poco::Net::SocketAddress& clientAddress() const; - /// Returns the client's address. - - const Poco::Net::SocketAddress& serverAddress() const; - /// Returns the server's address. - - const Poco::Net::HTTPServerParams& serverParams() const; - /// Returns a reference to the server parameters. - - Poco::Net::HTTPServerResponse& response() const; - /// Returns a reference to the associated response - -protected: - void setResponse(ApacheServerResponse* pResponse); - -private: - ApacheRequestRec* _pApacheRequest; - ApacheServerResponse* _pResponse; - ApacheInputStream* _pStream; - Poco::Net::SocketAddress _serverAddress; - Poco::Net::SocketAddress _clientAddress; - - friend class ApacheServerResponse; -}; - - -// -// inlines -// -inline std::istream& ApacheServerRequest::stream() -{ - poco_check_ptr (_pStream); - - return *_pStream; -} - - -inline const Poco::Net::SocketAddress& ApacheServerRequest::clientAddress() const -{ - return _clientAddress; -} - - -inline const Poco::Net::SocketAddress& ApacheServerRequest::serverAddress() const -{ - return _serverAddress; -} - - -#endif // ApacheConnector_ApacheServerRequest_INCLUDED +// +// ApacheServerRequest.h +// +// $Id: //poco/1.4/ApacheConnector/include/ApacheServerRequest.h#2 $ +// +// Copyright (c) 2006-2011, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef ApacheConnector_ApacheServerRequest_INCLUDED +#define ApacheConnector_ApacheServerRequest_INCLUDED + + +#include "ApacheConnector.h" +#include "ApacheStream.h" +#include "Poco/Net/HTTPServerRequest.h" +#include + + +class ApacheServerResponse; + + +class ApacheServerRequest: public Poco::Net::HTTPServerRequest +{ +public: + ApacheServerRequest( + ApacheRequestRec* pApacheRequest, + const char* serverName, + int serverPort, + const char* clientName, + int clientPort); + /// Creates a new ApacheServerRequest. + + ~ApacheServerRequest(); + /// Destroys the ApacheServerRequest. + + std::istream& stream(); + /// Returns the input stream for reading + /// the request body. + /// + /// The stream is valid until the HTTPServerRequest + /// object is destroyed. + + bool expectContinue() const; + /// Returns true if the client expects a + /// 100 Continue response. + + const Poco::Net::SocketAddress& clientAddress() const; + /// Returns the client's address. + + const Poco::Net::SocketAddress& serverAddress() const; + /// Returns the server's address. + + const Poco::Net::HTTPServerParams& serverParams() const; + /// Returns a reference to the server parameters. + + Poco::Net::HTTPServerResponse& response() const; + /// Returns a reference to the associated response + +protected: + void setResponse(ApacheServerResponse* pResponse); + +private: + ApacheRequestRec* _pApacheRequest; + ApacheServerResponse* _pResponse; + ApacheInputStream* _pStream; + Poco::Net::SocketAddress _serverAddress; + Poco::Net::SocketAddress _clientAddress; + + friend class ApacheServerResponse; +}; + + +// +// inlines +// +inline std::istream& ApacheServerRequest::stream() +{ + poco_check_ptr (_pStream); + + return *_pStream; +} + + +inline const Poco::Net::SocketAddress& ApacheServerRequest::clientAddress() const +{ + return _clientAddress; +} + + +inline const Poco::Net::SocketAddress& ApacheServerRequest::serverAddress() const +{ + return _serverAddress; +} + + +#endif // ApacheConnector_ApacheServerRequest_INCLUDED diff --git a/ApacheConnector/include/ApacheServerResponse.h b/ApacheConnector/include/ApacheServerResponse.h index 46516f648..c24bab31a 100644 --- a/ApacheConnector/include/ApacheServerResponse.h +++ b/ApacheConnector/include/ApacheServerResponse.h @@ -1,124 +1,144 @@ -// -// ApacheServerResponse.h -// -// $Id: //poco/Main/ApacheConnector/include/ApacheServerResponse.h#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. -// - - -#ifndef ApacheConnector_ApacheServerResponse_INCLUDED -#define ApacheConnector_ApacheServerResponse_INCLUDED - - -#include "ApacheConnector.h" -#include "ApacheStream.h" -#include "Poco/Net/Net.h" -#include "Poco/Net/HTTPServerResponse.h" - - -class ApacheServerRequest; - - -class ApacheServerResponse: public Poco::Net::HTTPServerResponse - /// This subclass of HTTPResponse is used for - /// representing server-side HTTP responses for apache. - /// - /// A ApacheServerResponse is passed to the - /// handleRequest() method of HTTPRequestHandler. - /// - /// handleRequest() must set a status code - /// and optional reason phrase, set headers - /// as necessary, and provide a message body. -{ -public: - ApacheServerResponse(ApacheServerRequest* pRequest); - /// Creates the ApacheServerResponse. - - ~ApacheServerResponse(); - /// Destroys the ApacheServerResponse. - - void sendContinue(); - /// Sends a 100 Continue response to the - /// client. - - void sendErrorResponse(int status); - /// Sends an error response with the given - /// status back to the client. - - std::ostream& send(); - /// Sends the response header to the client and - /// returns an output stream for sending the - /// response body. - /// - /// The returned stream is valid until the response - /// object is destroyed. - /// - /// Must not be called after sendFile(), sendBuffer() - /// or redirect() has been called. - - void sendFile(const std::string& path, const std::string& mediaType); - /// Sends the response header to the client, followed - /// by the content of the given file. - /// - /// Must not be called after send(), sendBuffer() - /// or redirect() has been called. - /// - /// Throws a FileNotFoundException if the file - /// cannot be found, or an OpenFileException if - /// the file cannot be opened. - - void sendBuffer(const void* pBuffer, std::size_t length); - /// Sends the response header to the client, followed - /// by the contents of the given buffer. - /// - /// The Content-Length header of the response is set - /// to length and chunked transfer encoding is disabled. - /// - /// If both the HTTP message header and body (from the - /// given buffer) fit into one single network packet, the - /// complete response can be sent in one network packet. - /// - /// Must not be called after send(), sendFile() - /// or redirect() has been called. - - void redirect(const std::string& uri); - /// Sets the status code to 302 (Found) - /// and sets the "Location" header field - /// to the given URI, which according to - /// the HTTP specification, must be absolute. - /// - /// Must not be called after send() has been called. - - void requireAuthentication(const std::string& realm); - /// Sets the status code to 401 (Unauthorized) - /// and sets the "WWW-Authenticate" header field - /// according to the given realm. - - bool sent() const; - /// Returns true if the response (header) has been sent. - -private: - void initApacheOutputStream(); - /// Initializes the ApacheOutputStram - - ApacheOutputStream* _pStream; - ApacheRequestRec* _pApacheRequest; -}; - - -// -// inlines -// -inline bool ApacheServerResponse::sent() const -{ - return _pStream != 0; -} - - -#endif // ApacheConnector_ApacheServerResponse_INCLUDED +// +// ApacheServerResponse.h +// +// $Id: //poco/1.4/ApacheConnector/include/ApacheServerResponse.h#2 $ +// +// Copyright (c) 2006-2011, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef ApacheConnector_ApacheServerResponse_INCLUDED +#define ApacheConnector_ApacheServerResponse_INCLUDED + + +#include "ApacheConnector.h" +#include "ApacheStream.h" +#include "Poco/Net/Net.h" +#include "Poco/Net/HTTPServerResponse.h" + + +class ApacheServerRequest; + + +class ApacheServerResponse: public Poco::Net::HTTPServerResponse + /// This subclass of HTTPResponse is used for + /// representing server-side HTTP responses for apache. + /// + /// A ApacheServerResponse is passed to the + /// handleRequest() method of HTTPRequestHandler. + /// + /// handleRequest() must set a status code + /// and optional reason phrase, set headers + /// as necessary, and provide a message body. +{ +public: + ApacheServerResponse(ApacheServerRequest* pRequest); + /// Creates the ApacheServerResponse. + + ~ApacheServerResponse(); + /// Destroys the ApacheServerResponse. + + void sendContinue(); + /// Sends a 100 Continue response to the + /// client. + + void sendErrorResponse(int status); + /// Sends an error response with the given + /// status back to the client. + + std::ostream& send(); + /// Sends the response header to the client and + /// returns an output stream for sending the + /// response body. + /// + /// The returned stream is valid until the response + /// object is destroyed. + /// + /// Must not be called after sendFile(), sendBuffer() + /// or redirect() has been called. + + void sendFile(const std::string& path, const std::string& mediaType); + /// Sends the response header to the client, followed + /// by the content of the given file. + /// + /// Must not be called after send(), sendBuffer() + /// or redirect() has been called. + /// + /// Throws a FileNotFoundException if the file + /// cannot be found, or an OpenFileException if + /// the file cannot be opened. + + void sendBuffer(const void* pBuffer, std::size_t length); + /// Sends the response header to the client, followed + /// by the contents of the given buffer. + /// + /// The Content-Length header of the response is set + /// to length and chunked transfer encoding is disabled. + /// + /// If both the HTTP message header and body (from the + /// given buffer) fit into one single network packet, the + /// complete response can be sent in one network packet. + /// + /// Must not be called after send(), sendFile() + /// or redirect() has been called. + + void redirect(const std::string& uri, Poco::Net::HTTPResponse::HTTPStatus status); + /// Sets the status code, which must be one of + /// HTTP_MOVED_PERMANENTLY (301), HTTP_FOUND (302), + /// or HTTP_SEE_OTHER (303), + /// and sets the "Location" header field + /// to the given URI, which according to + /// the HTTP specification, must be absolute. + /// + /// Must not be called after send() has been called. + + void requireAuthentication(const std::string& realm); + /// Sets the status code to 401 (Unauthorized) + /// and sets the "WWW-Authenticate" header field + /// according to the given realm. + + bool sent() const; + /// Returns true if the response (header) has been sent. + +private: + void initApacheOutputStream(); + /// Initializes the ApacheOutputStram + + ApacheOutputStream* _pStream; + ApacheRequestRec* _pApacheRequest; +}; + + +// +// inlines +// +inline bool ApacheServerResponse::sent() const +{ + return _pStream != 0; +} + + +#endif // ApacheConnector_ApacheServerResponse_INCLUDED diff --git a/ApacheConnector/include/ApacheStream.h b/ApacheConnector/include/ApacheStream.h index 3fc8089fc..8b26c9c8b 100644 --- a/ApacheConnector/include/ApacheStream.h +++ b/ApacheConnector/include/ApacheStream.h @@ -1,107 +1,125 @@ -// -// ApacheStream.h -// -// $Id: //poco/Main/ApacheConnector/include/ApacheStream.h#5 $ -// -// 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. -// - - -#ifndef ApacheConnector_ApacheStream_INCLUDED -#define ApacheConnector_ApacheStream_INCLUDED - - -#include "ApacheConnector.h" -#include "Poco/BufferedStreamBuf.h" -#include -#include - - -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 +// +// ApacheStream.h +// +// $Id: //poco/1.4/ApacheConnector/include/ApacheStream.h#2 $ +// +// Copyright (c) 2006-2011, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef ApacheConnector_ApacheStream_INCLUDED +#define ApacheConnector_ApacheStream_INCLUDED + + +#include "ApacheConnector.h" +#include "Poco/BufferedStreamBuf.h" +#include +#include + + +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/src/FormServer.cpp b/ApacheConnector/samples/FormServer/src/FormServer.cpp index c5d83e5c3..04992d352 100644 --- a/ApacheConnector/samples/FormServer/src/FormServer.cpp +++ b/ApacheConnector/samples/FormServer/src/FormServer.cpp @@ -1,188 +1,206 @@ -// -// 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" - "\n" - "\n" - "
\n" - "

POST Form

\n" - "
\n" - "\n" - "\n" - "
\n" - "

File Upload

\n" - "
\n" - " \n" - "\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 +// +// FormServer.cpp +// +// $Id: //poco/1.4/ApacheConnector/samples/FormServer/src/FormServer.cpp#2 $ +// +// Copyright (c) 2006-2011, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#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" + "\n" + "\n" + "
\n" + "

POST Form

\n" + "
\n" + "\n" + "\n" + "
\n" + "

File Upload

\n" + "
\n" + " \n" + "\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/TimeServer/src/TimeServer.cpp b/ApacheConnector/samples/TimeServer/src/TimeServer.cpp index 0f734683e..9c41565f4 100644 --- a/ApacheConnector/samples/TimeServer/src/TimeServer.cpp +++ b/ApacheConnector/samples/TimeServer/src/TimeServer.cpp @@ -1,77 +1,95 @@ -// -// 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 +// +// TimeServer.cpp +// +// $Id: //poco/1.4/ApacheConnector/samples/TimeServer/src/TimeServer.cpp#2 $ +// +// Copyright (c) 2006-2011, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#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/src/ApacheApplication.cpp b/ApacheConnector/src/ApacheApplication.cpp index 167fdd337..e5b3830e8 100644 --- a/ApacheConnector/src/ApacheApplication.cpp +++ b/ApacheConnector/src/ApacheApplication.cpp @@ -1,57 +1,75 @@ -// -// 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(); -} +// +// ApacheApplication.cpp +// +// $Id: //poco/1.4/ApacheConnector/src/ApacheApplication.cpp#2 $ +// +// Copyright (c) 2006-2011, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#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 index cd03f9013..4c8d603de 100644 --- a/ApacheConnector/src/ApacheChannel.cpp +++ b/ApacheConnector/src/ApacheChannel.cpp @@ -1,33 +1,51 @@ -// -// 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()); -} +// +// ApacheApplication.cpp +// +// $Id: //poco/1.4/ApacheConnector/src/ApacheChannel.cpp#2 $ +// +// Copyright (c) 2006-2011, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#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 index b23c6b837..62eb29ba8 100644 --- a/ApacheConnector/src/ApacheConnector.cpp +++ b/ApacheConnector/src/ApacheConnector.cpp @@ -1,291 +1,309 @@ -// -// 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" - -#include - -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 -}; +// +// ApacheConnector.cpp +// +// $Id: //poco/1.4/ApacheConnector/src/ApacheConnector.cpp#2 $ +// +// Copyright (c) 2006-2011, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "ApacheConnector.h" +#include "ApacheApplication.h" +#include "ApacheServerRequest.h" +#include "ApacheServerResponse.h" +#include "ApacheRequestHandlerFactory.h" +#include "Poco/Net/HTTPRequestHandler.h" +#include +#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, int status) +{ + apr_table_set(_pRec->headers_out, "Location", uri.c_str()); + _pRec->connection->keepalive = AP_CONN_CLOSE; + _pRec->status = status; + 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, "%s", 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 index 21f24d759..18e1832ca 100644 --- a/ApacheConnector/src/ApacheRequestHandlerFactory.cpp +++ b/ApacheConnector/src/ApacheRequestHandlerFactory.cpp @@ -1,118 +1,136 @@ -// -// 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; -} +// +// ApacheRequestHandlerFactory.cpp +// +// $Id: //poco/1.4/ApacheConnector/src/ApacheRequestHandlerFactory.cpp#2 $ +// +// Copyright (c) 2006-2011, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#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 index 6d0601757..a836f74ad 100644 --- a/ApacheConnector/src/ApacheServerRequest.cpp +++ b/ApacheConnector/src/ApacheServerRequest.cpp @@ -1,64 +1,82 @@ -// -// 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; -} +// +// ApacheServerRequest.cpp +// +// $Id: //poco/1.4/ApacheConnector/src/ApacheServerRequest.cpp#2 $ +// +// Copyright (c) 2006-2011, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#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 index ff9a22969..3906bac8b 100644 --- a/ApacheConnector/src/ApacheServerResponse.cpp +++ b/ApacheConnector/src/ApacheServerResponse.cpp @@ -1,133 +1,151 @@ -// -// 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 -} +// +// ApacheServerResponse.cpp +// +// $Id: //poco/1.4/ApacheConnector/src/ApacheServerResponse.cpp#3 $ +// +// Copyright (c) 2006-2011, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#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, HTTPStatus status) +{ + poco_assert (!_pStream); + + initApacheOutputStream(); + + try + { + _pApacheRequest->redirect(uri, status); + } + 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 index 1c331b243..3ec484045 100644 --- a/ApacheConnector/src/ApacheStream.cpp +++ b/ApacheConnector/src/ApacheStream.cpp @@ -1,124 +1,142 @@ -// -// 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() -{ -} +// +// ApacheStream.h +// +// $Id: //poco/1.4/ApacheConnector/src/ApacheStream.cpp#2 $ +// +// Copyright (c) 2006-2011, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#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() +{ +} diff --git a/CMakeLists.txt b/CMakeLists.txt index f150f20d7..3aed09318 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,7 +17,7 @@ SET(PROJECT_VERSION ${COMPLETE_VERSION}) if(NOT MSVC_IDE) if(NOT CMAKE_BUILD_TYPE) - set(CMAKE_BUILD_TYPE Debug CACHE STRING + set(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING "Choose the type of build, options are: None Debug Release" FORCE) endif() message(STATUS "Setting Poco build type - ${CMAKE_BUILD_TYPE}") diff --git a/Crypto/src/OpenSSLInitializer.cpp b/Crypto/src/OpenSSLInitializer.cpp index 0f6bd4a16..a107f9dbc 100644 --- a/Crypto/src/OpenSSLInitializer.cpp +++ b/Crypto/src/OpenSSLInitializer.cpp @@ -41,7 +41,7 @@ #include #include #include -#if SSLEAY_VERSION_NUMBER >= 0x0907000L +#if OPENSSL_VERSION_NUMBER >= 0x0907000L #include #endif @@ -61,7 +61,7 @@ int OpenSSLInitializer::_rc(0); OpenSSLInitializer::OpenSSLInitializer() { - initialize(); + initialize(); } diff --git a/Data/MySQL/Makefile b/Data/MySQL/Makefile index 0c188a8aa..d061e8291 100644 --- a/Data/MySQL/Makefile +++ b/Data/MySQL/Makefile @@ -16,7 +16,7 @@ objects = Binder Extractor SessionImpl Connector \ MySQLStatementImpl ResultMetadata MySQLException \ SessionHandle StatementExecutor -target = PocoMySQL +target = PocoDataMySQL target_version = $(LIBVERSION) target_libs = PocoData PocoFoundation diff --git a/Data/ODBC/Makefile b/Data/ODBC/Makefile index 9b8e58bce..27aa16bf7 100644 --- a/Data/ODBC/Makefile +++ b/Data/ODBC/Makefile @@ -44,7 +44,7 @@ objects = Binder ConnectionHandle Connector EnvironmentHandle \ Extractor ODBCMetaColumn ODBCException ODBCStatementImpl \ Parameter Preparator SessionImpl TypeInfo Unicode Utility -target = PocoODBC +target = PocoDataODBC target_version = $(LIBVERSION) target_libs = PocoData PocoFoundation diff --git a/Data/SQLite/Makefile b/Data/SQLite/Makefile index 0ab83cb51..3c0354a93 100644 --- a/Data/SQLite/Makefile +++ b/Data/SQLite/Makefile @@ -17,7 +17,7 @@ objects = Binder Extractor SessionImpl Connector \ SQLiteException SQLiteStatementImpl Utility \ sqlite3 -target = PocoSQLite +target = PocoDataSQLite target_version = $(LIBVERSION) target_libs = PocoData PocoFoundation diff --git a/Foundation/include/Poco/Config.h b/Foundation/include/Poco/Config.h index db034bef4..7a0e6d12d 100644 --- a/Foundation/include/Poco/Config.h +++ b/Foundation/include/Poco/Config.h @@ -60,6 +60,10 @@ // #define POCO_NO_SHAREDMEMORY +// Define if no header is available (such as on WinCE) +// #define POCO_NO_LOCALE + + // Define to desired default thread stack size // Zero means OS default #ifndef POCO_THREAD_STACK_SIZE diff --git a/Foundation/include/Poco/Environment_WINCE.h b/Foundation/include/Poco/Environment_WINCE.h index 1059e269c..71f646a93 100644 --- a/Foundation/include/Poco/Environment_WINCE.h +++ b/Foundation/include/Poco/Environment_WINCE.h @@ -52,12 +52,13 @@ public: typedef UInt8 NodeId[6]; /// Ethernet address. static std::string getImpl(const std::string& name); - static bool hasImpl(const std::string& name); - static void setImpl(const std::string& name, const std::string& value); - static std::string osNameImpl(); - static std::string osVersionImpl(); - static std::string osArchitectureImpl(); - static std::string nodeNameImpl(); + static bool hasImpl(const std::string& name); + static void setImpl(const std::string& name, const std::string& value); + static std::string osNameImpl(); + static std::string osDisplayNameImpl(); + static std::string osVersionImpl(); + static std::string osArchitectureImpl(); + static std::string nodeNameImpl(); static void nodeIdImpl(NodeId& id); static unsigned processorCountImpl(); diff --git a/Foundation/include/Poco/Format.h b/Foundation/include/Poco/Format.h index c738f2f05..c385db82f 100644 --- a/Foundation/include/Poco/Format.h +++ b/Foundation/include/Poco/Format.h @@ -59,20 +59,20 @@ std::string Foundation_API format(const std::string& fmt, const Any& value); /// /// The format string can consist of any sequence of characters; certain /// characters have a special meaning. Characters without a special meaning - /// are copied verbatim to the result. A percent sign (%) marks the beginning - /// of a format specification. Format specifications have the following syntax: - /// - /// %[][][][.][] - /// - /// Index, flags, width, precision and prefix are optional. The only required part of - /// the format specification, apart from the percent sign, is the type. - /// - /// The optional index argument has the format "[]" and allows to - /// address an argument by its zero-based position (see the example below). - /// - /// Following are valid type specifications and their meaning: - /// - /// * b boolean (true = 1, false = 0) + /// are copied verbatim to the result. A percent sign (%) marks the beginning + /// of a format specification. Format specifications have the following syntax: + /// + /// %[][][][.][] + /// + /// Index, flags, width, precision and prefix are optional. The only required part of + /// the format specification, apart from the percent sign, is the type. + /// + /// The optional index argument has the format "[]" and allows to + /// address an argument by its zero-based position (see the example below). + /// + /// Following are valid type specifications and their meaning: + /// + /// * b boolean (true = 1, false = 0) /// * c character /// * d signed decimal integer /// * i signed decimal integer @@ -86,13 +86,13 @@ std::string Foundation_API format(const std::string& fmt, const Any& value); /// * s std::string /// * z std::size_t /// - /// The following flags are supported: - /// - /// * - left align the result within the given field width - /// * + prefix the output value with a sign (+ or -) if the output value is of a signed type - /// * 0 if width is prefixed with 0, zeros are added until the minimum width is reached - /// * # For o, x, X, the # flag prefixes any nonzero output value with 0, 0x, or 0X, respectively; - /// for e, E, f, the # flag forces the output value to contain a decimal point in all cases. + /// The following flags are supported: + /// + /// * - left align the result within the given field width + /// * + prefix the output value with a sign (+ or -) if the output value is of a signed type + /// * 0 if width is prefixed with 0, zeros are added until the minimum width is reached + /// * # For o, x, X, the # flag prefixes any nonzero output value with 0, 0x, or 0X, respectively; + /// for e, E, f, the # flag forces the output value to contain a decimal point in all cases. /// /// The following modifiers are supported: /// @@ -106,20 +106,23 @@ std::string Foundation_API format(const std::string& fmt, const Any& value); /// If the number of characters in the output value is less than the specified width, blanks or /// leading zeros are added, according to the specified flags (-, +, 0). /// - /// Precision is a nonnegative decimal integer, preceded by a period (.), which specifies the number of characters + /// Precision is a nonnegative decimal integer, preceded by a period (.), which specifies the number of characters /// to be printed, the number of decimal places, or the number of significant digits. /// - /// Throws a BadCastException if an argument does not correspond to the type of its format specification. /// Throws an InvalidArgumentException if an argument index is out of range. + /// + /// Starting with release 1.4.3, an argument that does not match the format + /// specifier no longer results in a BadCastException. The string [ERRFMT] is + /// written to the result string instead. /// /// If there are more format specifiers than values, the format specifiers without a corresponding value /// are copied verbatim to output. /// - /// If there are more values than format specifiers, the superfluous values are ignored. - /// - /// Usage Examples: - /// std::string s1 = format("The answer to life, the universe, and everything is %d", 42); - /// std::string s2 = format("second: %[1]d, first: %[0]d", 1, 2); + /// If there are more values than format specifiers, the superfluous values are ignored. + /// + /// Usage Examples: + /// std::string s1 = format("The answer to life, the universe, and everything is %d", 42); + /// std::string s2 = format("second: %[1]d, first: %[0]d", 1, 2); std::string Foundation_API format(const std::string& fmt, const Any& value1, const Any& value2); std::string Foundation_API format(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3); diff --git a/Foundation/include/Poco/Logger.h b/Foundation/include/Poco/Logger.h index c9969abf1..195c6d99f 100644 --- a/Foundation/include/Poco/Logger.h +++ b/Foundation/include/Poco/Logger.h @@ -337,16 +337,16 @@ public: static std::string format(const std::string& fmt, const std::string& arg0, const std::string& arg1, const std::string& arg2, const std::string& arg3); /// Replaces all occurences of $ in fmt with the string given in arg and - /// returns the result. To include a dollar sign in the result string, - /// specify two dollar signs ($$) in the format string. + /// returns the result. To include a dollar sign in the result string, + /// specify two dollar signs ($$) in the format string. - static void formatDump(std::string& message, const void* buffer, std::size_t length); - /// Creates a hex-dump of the given buffer and appends it to the - /// given message string. - - static void setLevel(const std::string& name, int level); - /// Sets the given log level on all loggers that are - /// descendants of the Logger with the given name. + static void formatDump(std::string& message, const void* buffer, std::size_t length); + /// Creates a hex-dump of the given buffer and appends it to the + /// given message string. + + static void setLevel(const std::string& name, int level); + /// Sets the given log level on all loggers that are + /// descendants of the Logger with the given name. static void setChannel(const std::string& name, Channel* pChannel); /// Attaches the given Channel to all loggers that are @@ -396,11 +396,28 @@ public: /// Loggers. static void names(std::vector& names); - /// Fills the given vector with the names - /// of all currently defined loggers. - - static const std::string ROOT; /// The name of the root logger (""). - + /// Fills the given vector with the names + /// of all currently defined loggers. + + static int parseLevel(const std::string& level); + /// Parses a symbolic log level from a string and + /// returns the resulting numeric level. + /// + /// Valid symbolic levels are: + /// - none (turns off logging) + /// - fatal + /// - critical + /// - error + /// - warning + /// - notice + /// - information + /// - debug + /// - trace + /// + /// The level is not case sensitive. + + static const std::string ROOT; /// The name of the root logger (""). + protected: typedef std::map LoggerMap; @@ -408,12 +425,12 @@ protected: ~Logger(); void log(const std::string& text, Message::Priority prio); - void log(const std::string& text, Message::Priority prio, const char* file, int line); + void log(const std::string& text, Message::Priority prio, const char* file, int line); - static std::string format(const std::string& fmt, int argc, std::string argv[]); - static Logger& parent(const std::string& name); - static void add(Logger* pLogger); - static Logger* find(const std::string& name); + static std::string format(const std::string& fmt, int argc, std::string argv[]); + static Logger& parent(const std::string& name); + static void add(Logger* pLogger); + static Logger* find(const std::string& name); private: Logger(); diff --git a/Foundation/include/Poco/Process.h b/Foundation/include/Poco/Process.h index 851dc938a..3c0ce82fe 100644 --- a/Foundation/include/Poco/Process.h +++ b/Foundation/include/Poco/Process.h @@ -151,12 +151,18 @@ public: /// int rc = ph.wait(); static int wait(const ProcessHandle& handle); - /// Waits for the process specified by handle to terminate - /// and returns the exit code of the process. - - static void kill(PID pid); - /// Kills the process with the given pid. - + /// Waits for the process specified by handle to terminate + /// and returns the exit code of the process. + + static void kill(const ProcessHandle& handle); + /// Kills the process specified by handle. + /// + /// This is preferable on Windows where process IDs + /// may be reused. + + static void kill(PID pid); + /// Kills the process with the given pid. + static void requestTermination(PID pid); /// Requests termination of the process with the give PID. /// diff --git a/Foundation/include/Poco/Process_UNIX.h b/Foundation/include/Poco/Process_UNIX.h index 800ed61f7..7bd1eafa6 100644 --- a/Foundation/include/Poco/Process_UNIX.h +++ b/Foundation/include/Poco/Process_UNIX.h @@ -72,11 +72,12 @@ public: typedef pid_t PIDImpl; typedef std::vector ArgsImpl; - static PIDImpl idImpl(); - static void timesImpl(long& userTime, long& kernelTime); - static ProcessHandleImpl* launchImpl(const std::string& command, const ArgsImpl& args, Pipe* inPipe, Pipe* outPipe, Pipe* errPipe); - static void killImpl(PIDImpl pid); - static void requestTerminationImpl(PIDImpl pid); + static PIDImpl idImpl(); + static void timesImpl(long& userTime, long& kernelTime); + static ProcessHandleImpl* launchImpl(const std::string& command, const ArgsImpl& args, Pipe* inPipe, Pipe* outPipe, Pipe* errPipe); + static void killImpl(const ProcessHandleImpl& handle); + static void killImpl(PIDImpl pid); + static void requestTerminationImpl(PIDImpl pid); }; diff --git a/Foundation/include/Poco/Process_VX.h b/Foundation/include/Poco/Process_VX.h index f73cc9553..3d6a48c2f 100644 --- a/Foundation/include/Poco/Process_VX.h +++ b/Foundation/include/Poco/Process_VX.h @@ -74,11 +74,12 @@ public: typedef int PIDImpl; typedef std::vector ArgsImpl; - static PIDImpl idImpl(); - static void timesImpl(long& userTime, long& kernelTime); - static ProcessHandleImpl* launchImpl(const std::string& command, const ArgsImpl& args, Pipe* inPipe, Pipe* outPipe, Pipe* errPipe); - static void killImpl(PIDImpl pid); - static void requestTerminationImpl(PIDImpl pid); + static PIDImpl idImpl(); + static void timesImpl(long& userTime, long& kernelTime); + static ProcessHandleImpl* launchImpl(const std::string& command, const ArgsImpl& args, Pipe* inPipe, Pipe* outPipe, Pipe* errPipe); + static void killImpl(const ProcessHandleImpl& handle); + static void killImpl(PIDImpl pid); + static void requestTerminationImpl(PIDImpl pid); }; diff --git a/Foundation/include/Poco/Process_WIN32.h b/Foundation/include/Poco/Process_WIN32.h index 3a2853d8e..6ca4d04eb 100644 --- a/Foundation/include/Poco/Process_WIN32.h +++ b/Foundation/include/Poco/Process_WIN32.h @@ -56,11 +56,12 @@ class Foundation_API ProcessHandleImpl: public RefCountedObject { public: ProcessHandleImpl(HANDLE _hProcess, UInt32 pid); - ~ProcessHandleImpl(); - - UInt32 id() const; - int wait() const; - + ~ProcessHandleImpl(); + + UInt32 id() const; + HANDLE process() const; + int wait() const; + private: HANDLE _hProcess; UInt32 _pid; @@ -76,12 +77,13 @@ public: typedef UInt32 PIDImpl; typedef std::vector ArgsImpl; - static PIDImpl idImpl(); - static void timesImpl(long& userTime, long& kernelTime); - static ProcessHandleImpl* launchImpl(const std::string& command, const ArgsImpl& args, Pipe* inPipe, Pipe* outPipe, Pipe* errPipe); - static void killImpl(PIDImpl pid); - static void requestTerminationImpl(PIDImpl pid); - static std::string terminationEventName(PIDImpl pid); + static PIDImpl idImpl(); + static void timesImpl(long& userTime, long& kernelTime); + static ProcessHandleImpl* launchImpl(const std::string& command, const ArgsImpl& args, Pipe* inPipe, Pipe* outPipe, Pipe* errPipe); + static void killImpl(const ProcessHandleImpl& handle); + static void killImpl(PIDImpl pid); + static void requestTerminationImpl(PIDImpl pid); + static std::string terminationEventName(PIDImpl pid); }; diff --git a/Foundation/include/Poco/Process_WIN32U.h b/Foundation/include/Poco/Process_WIN32U.h index d32f5d543..737daf60b 100644 --- a/Foundation/include/Poco/Process_WIN32U.h +++ b/Foundation/include/Poco/Process_WIN32U.h @@ -56,11 +56,12 @@ class Foundation_API ProcessHandleImpl: public RefCountedObject { public: ProcessHandleImpl(HANDLE _hProcess, UInt32 pid); - ~ProcessHandleImpl(); - - UInt32 id() const; - int wait() const; - + ~ProcessHandleImpl(); + + UInt32 id() const; + HANDLE process() const; + int wait() const; + private: HANDLE _hProcess; UInt32 _pid; @@ -76,12 +77,13 @@ public: typedef UInt32 PIDImpl; typedef std::vector ArgsImpl; - static PIDImpl idImpl(); - static void timesImpl(long& userTime, long& kernelTime); - static ProcessHandleImpl* launchImpl(const std::string& command, const ArgsImpl& args, Pipe* inPipe, Pipe* outPipe, Pipe* errPipe); - static void killImpl(PIDImpl pid); - static void requestTerminationImpl(PIDImpl pid); - static std::string terminationEventName(PIDImpl pid); + static PIDImpl idImpl(); + static void timesImpl(long& userTime, long& kernelTime); + static ProcessHandleImpl* launchImpl(const std::string& command, const ArgsImpl& args, Pipe* inPipe, Pipe* outPipe, Pipe* errPipe); + static void killImpl(const ProcessHandleImpl& handle); + static void killImpl(PIDImpl pid); + static void requestTerminationImpl(PIDImpl pid); + static std::string terminationEventName(PIDImpl pid); }; diff --git a/Foundation/include/Poco/Process_WINCE.h b/Foundation/include/Poco/Process_WINCE.h index c9c40a097..909b1b48a 100644 --- a/Foundation/include/Poco/Process_WINCE.h +++ b/Foundation/include/Poco/Process_WINCE.h @@ -56,11 +56,12 @@ class Foundation_API ProcessHandleImpl: public RefCountedObject { public: ProcessHandleImpl(HANDLE _hProcess, UInt32 pid); - ~ProcessHandleImpl(); - - UInt32 id() const; - int wait() const; - + ~ProcessHandleImpl(); + + UInt32 id() const; + HANDLE process() const; + int wait() const; + private: HANDLE _hProcess; UInt32 _pid; @@ -76,12 +77,13 @@ public: typedef UInt32 PIDImpl; typedef std::vector ArgsImpl; - static PIDImpl idImpl(); - static void timesImpl(long& userTime, long& kernelTime); - static ProcessHandleImpl* launchImpl(const std::string& command, const ArgsImpl& args, Pipe* inPipe, Pipe* outPipe, Pipe* errPipe); - static void killImpl(PIDImpl pid); - static void requestTerminationImpl(PIDImpl pid); - static std::string terminationEventName(PIDImpl pid); + static PIDImpl idImpl(); + static void timesImpl(long& userTime, long& kernelTime); + static ProcessHandleImpl* launchImpl(const std::string& command, const ArgsImpl& args, Pipe* inPipe, Pipe* outPipe, Pipe* errPipe); + static void killImpl(const ProcessHandleImpl& handle); + static void killImpl(PIDImpl pid); + static void requestTerminationImpl(PIDImpl pid); + static std::string terminationEventName(PIDImpl pid); }; diff --git a/Foundation/include/Poco/ScopedLock.h b/Foundation/include/Poco/ScopedLock.h index 54ee3d66a..11652f133 100644 --- a/Foundation/include/Poco/ScopedLock.h +++ b/Foundation/include/Poco/ScopedLock.h @@ -48,20 +48,27 @@ namespace Poco { template class ScopedLock - /// A class that simplifies thread synchronization - /// with a mutex. - /// The constructor accepts a Mutex and locks it. - /// The destructor unlocks the mutex. + /// A class that simplifies thread synchronization + /// with a mutex. + /// The constructor accepts a Mutex (and optionally + /// a timeout value in milliseconds) and locks it. + /// The destructor unlocks the mutex. { public: - inline ScopedLock(M& mutex): _mutex(mutex) - { - _mutex.lock(); - } - inline ~ScopedLock() - { - _mutex.unlock(); - } + explicit ScopedLock(M& mutex): _mutex(mutex) + { + _mutex.lock(); + } + + ScopedLock(M& mutex, long milliseconds): _mutex(mutex) + { + _mutex.lock(milliseconds); + } + + ~ScopedLock() + { + _mutex.unlock(); + } private: M& _mutex; @@ -74,22 +81,28 @@ private: template class ScopedLockWithUnlock - /// A class that simplifies thread synchronization - /// with a mutex. - /// The constructor accepts a Mutex and locks it. - /// The destructor unlocks the mutex. - /// The unlock() member function allows for manual - /// unlocking of the mutex. + /// A class that simplifies thread synchronization + /// with a mutex. + /// The constructor accepts a Mutex (and optionally + /// a timeout value in milliseconds) and locks it. + /// The destructor unlocks the mutex. + /// The unlock() member function allows for manual + /// unlocking of the mutex. { public: - ScopedLockWithUnlock(M& mutex): _pMutex(&mutex) - { - _pMutex->lock(); - } - - ~ScopedLockWithUnlock() - { - unlock(); + explicit ScopedLockWithUnlock(M& mutex): _pMutex(&mutex) + { + _pMutex->lock(); + } + + ScopedLockWithUnlock(M& mutex, long milliseconds): _pMutex(&mutex) + { + _pMutex->lock(milliseconds); + } + + ~ScopedLockWithUnlock() + { + unlock(); } void unlock() diff --git a/Foundation/include/Poco/zconf.h b/Foundation/include/Poco/zconf.h index a69fcc98f..3697a13c6 100644 --- a/Foundation/include/Poco/zconf.h +++ b/Foundation/include/Poco/zconf.h @@ -360,9 +360,11 @@ typedef uLong FAR uLongf; # define Z_HAVE_UNISTD_H #endif +#ifndef _WIN32_WCE #ifdef STDC # include /* for off_t */ #endif +#endif /* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and * "#define _LARGEFILE64_SOURCE 1" as requesting 64-bit operations, (even diff --git a/Foundation/src/Format.cpp b/Foundation/src/Format.cpp index adbec511a..09adf4d33 100644 --- a/Foundation/src/Format.cpp +++ b/Foundation/src/Format.cpp @@ -38,7 +38,9 @@ #include "Poco/Exception.h" #include "Poco/Ascii.h" #include +#if !defined(POCO_NO_LOCALE) #include +#endif #include @@ -167,72 +169,81 @@ namespace void formatOne(std::string& result, std::string::const_iterator& itFmt, const std::string::const_iterator& endFmt, std::vector::const_iterator& itVal) { std::ostringstream str; +#if !defined(POCO_NO_LOCALE) str.imbue(std::locale::classic()); - parseFlags(str, itFmt, endFmt); - parseWidth(str, itFmt, endFmt); - parsePrec(str, itFmt, endFmt); - char mod = parseMod(itFmt, endFmt); - if (itFmt != endFmt) - { - char type = *itFmt++; - prepareFormat(str, type); - switch (type) +#endif + try + { + parseFlags(str, itFmt, endFmt); + parseWidth(str, itFmt, endFmt); + parsePrec(str, itFmt, endFmt); + char mod = parseMod(itFmt, endFmt); + if (itFmt != endFmt) { - case 'b': - str << AnyCast(*itVal++); - break; - case 'c': - str << AnyCast(*itVal++); - break; - case 'd': - case 'i': - switch (mod) + char type = *itFmt++; + prepareFormat(str, type); + switch (type) { - case 'l': str << AnyCast(*itVal++); break; - case 'L': str << AnyCast(*itVal++); break; - case 'h': str << AnyCast(*itVal++); break; - case '?': writeAnyInt(str, *itVal++); break; - default: str << AnyCast(*itVal++); break; - } - break; - case 'o': - case 'u': - case 'x': - case 'X': - switch (mod) - { - case 'l': str << AnyCast(*itVal++); break; - case 'L': str << AnyCast(*itVal++); break; - case 'h': str << AnyCast(*itVal++); break; - case '?': writeAnyInt(str, *itVal++); break; - default: str << AnyCast(*itVal++); break; - } - break; - case 'e': - case 'E': - case 'f': - switch (mod) - { - case 'l': str << AnyCast(*itVal++); break; - case 'L': str << AnyCast(*itVal++); break; - case 'h': str << AnyCast(*itVal++); break; - default: str << AnyCast(*itVal++); break; - } - break; - case 's': - str << RefAnyCast(*itVal++); - break; - case 'z': - str << AnyCast(*itVal++); - break; - case 'I': - case 'D': - default: - str << type; - } - } - result.append(str.str()); - } + case 'b': + str << AnyCast(*itVal++); + break; + case 'c': + str << AnyCast(*itVal++); + break; + case 'd': + case 'i': + switch (mod) + { + case 'l': str << AnyCast(*itVal++); break; + case 'L': str << AnyCast(*itVal++); break; + case 'h': str << AnyCast(*itVal++); break; + case '?': writeAnyInt(str, *itVal++); break; + default: str << AnyCast(*itVal++); break; + } + break; + case 'o': + case 'u': + case 'x': + case 'X': + switch (mod) + { + case 'l': str << AnyCast(*itVal++); break; + case 'L': str << AnyCast(*itVal++); break; + case 'h': str << AnyCast(*itVal++); break; + case '?': writeAnyInt(str, *itVal++); break; + default: str << AnyCast(*itVal++); break; + } + break; + case 'e': + case 'E': + case 'f': + switch (mod) + { + case 'l': str << AnyCast(*itVal++); break; + case 'L': str << AnyCast(*itVal++); break; + case 'h': str << AnyCast(*itVal++); break; + default: str << AnyCast(*itVal++); break; + } + break; + case 's': + str << RefAnyCast(*itVal++); + break; + case 'z': + str << AnyCast(*itVal++); + break; + case 'I': + case 'D': + default: + str << type; + } + } + } + catch (Poco::BadCastException&) + { + str << "[ERRFMT]"; + } + result.append(str.str()); + } } diff --git a/Foundation/src/Logger.cpp b/Foundation/src/Logger.cpp index 0c5d300c1..15447e12a 100644 --- a/Foundation/src/Logger.cpp +++ b/Foundation/src/Logger.cpp @@ -39,6 +39,7 @@ #include "Poco/LoggingRegistry.h" #include "Poco/Exception.h" #include "Poco/NumberFormatter.h" +#include "Poco/String.h" namespace Poco { @@ -83,26 +84,7 @@ void Logger::setLevel(int level) void Logger::setLevel(const std::string& level) { - if (level == "none") - setLevel(0); - else if (level == "fatal") - setLevel(Message::PRIO_FATAL); - else if (level == "critical") - setLevel(Message::PRIO_CRITICAL); - else if (level == "error") - setLevel(Message::PRIO_ERROR); - else if (level == "warning") - setLevel(Message::PRIO_WARNING); - else if (level == "notice") - setLevel(Message::PRIO_NOTICE); - else if (level == "information") - setLevel(Message::PRIO_INFORMATION); - else if (level == "debug") - setLevel(Message::PRIO_DEBUG); - else if (level == "trace") - setLevel(Message::PRIO_TRACE); - else - throw InvalidArgumentException("Not a valid log level", level); + setLevel(parseLevel(level)); } @@ -449,6 +431,31 @@ Logger& Logger::parent(const std::string& name) } +int Logger::parseLevel(const std::string& level) +{ + if (icompare(level, "none") == 0) + return 0; + else if (icompare(level, "fatal") == 0) + return Message::PRIO_FATAL; + else if (icompare(level, "critical") == 0) + return Message::PRIO_CRITICAL; + else if (icompare(level, "error") == 0) + return Message::PRIO_ERROR; + else if (icompare(level, "warning") == 0) + return Message::PRIO_WARNING; + else if (icompare(level, "notice") == 0) + return Message::PRIO_NOTICE; + else if (icompare(level, "information") == 0) + return Message::PRIO_INFORMATION; + else if (icompare(level, "debug") == 0) + return Message::PRIO_DEBUG; + else if (icompare(level, "trace") == 0) + return Message::PRIO_TRACE; + else + throw InvalidArgumentException("Not a valid log level", level); +} + + class AutoLoggerShutdown { public: diff --git a/Foundation/src/NumberFormatter.cpp b/Foundation/src/NumberFormatter.cpp index 692b8cf8b..5feb473e8 100644 --- a/Foundation/src/NumberFormatter.cpp +++ b/Foundation/src/NumberFormatter.cpp @@ -37,7 +37,9 @@ #include "Poco/NumberFormatter.h" #include "Poco/MemoryStream.h" #include +#if !defined(POCO_NO_LOCALE) #include +#endif #include #include @@ -361,9 +363,11 @@ void NumberFormatter::append(std::string& str, float value) { char buffer[64]; Poco::MemoryOutputStream ostr(buffer, sizeof(buffer)); +#if !defined(POCO_NO_LOCALE) ostr.imbue(std::locale::classic()); +#endif ostr << std::setprecision(8) << value; - str.append(buffer, ostr.charsWritten()); + str.append(buffer, static_cast(ostr.charsWritten())); } @@ -371,33 +375,39 @@ void NumberFormatter::append(std::string& str, double value) { char buffer[64]; Poco::MemoryOutputStream ostr(buffer, sizeof(buffer)); +#if !defined(POCO_NO_LOCALE) ostr.imbue(std::locale::classic()); +#endif ostr << std::setprecision(16) << value; - str.append(buffer, ostr.charsWritten()); + str.append(buffer, static_cast(ostr.charsWritten())); } void NumberFormatter::append(std::string& str, double value, int precision) { - poco_assert (precision >= 0 && precision < 32); + poco_assert (precision >= 0 && precision < 32); char buffer[64]; Poco::MemoryOutputStream ostr(buffer, sizeof(buffer)); +#if !defined(POCO_NO_LOCALE) ostr.imbue(std::locale::classic()); +#endif ostr << std::fixed << std::showpoint << std::setprecision(precision) << value; - str.append(buffer, ostr.charsWritten()); + str.append(buffer, static_cast(ostr.charsWritten())); } void NumberFormatter::append(std::string& str, double value, int width, int precision) { - poco_assert (width > 0 && width < 64 && precision >= 0 && precision < width); + poco_assert (width > 0 && width < 64 && precision >= 0 && precision < width); char buffer[64]; Poco::MemoryOutputStream ostr(buffer, sizeof(buffer)); +#if !defined(POCO_NO_LOCALE) ostr.imbue(std::locale::classic()); +#endif ostr << std::fixed << std::showpoint << std::setw(width) << std::setprecision(precision) << value; - str.append(buffer, ostr.charsWritten()); + str.append(buffer, static_cast(ostr.charsWritten())); } diff --git a/Foundation/src/NumberParser.cpp b/Foundation/src/NumberParser.cpp index 800fd3ccc..0405c4756 100644 --- a/Foundation/src/NumberParser.cpp +++ b/Foundation/src/NumberParser.cpp @@ -1,7 +1,7 @@ // // NumberParser.cpp // -// $Id: //poco/svn/Foundation/src/NumberParser.cpp#2 $ +// $Id: //poco/1.4/Foundation/src/NumberParser.cpp#4 $ // // Library: Foundation // Package: Core @@ -38,15 +38,19 @@ #include "Poco/Exception.h" #include "Poco/MemoryStream.h" #include "Poco/String.h" +#ifdef POCO_LOCALE #include +#endif #include #include -#if defined(_MSC_VER) - #define I64_FMT "I64" +#if defined(POCO_LONG_IS_64_BIT) + #define I64_FMT "l" +#elif defined(_MSC_VER) + #define I64_FMT "I64" #elif defined(__APPLE__) - #define I64_FMT "q" + #define I64_FMT "q" #else #define I64_FMT "ll" #endif @@ -175,10 +179,12 @@ double NumberParser::parseFloat(const std::string& s) bool NumberParser::tryParseFloat(const std::string& s, double& value) { - Poco::MemoryInputStream istr(s.data(), s.size()); - istr.imbue(std::locale::classic()); - istr >> value; - return istr.eof() && !istr.fail(); + Poco::MemoryInputStream istr(s.data(), s.size()); +#if !defined(POCO_NO_LOCALE) + istr.imbue(std::locale::classic()); +#endif + istr >> value; + return istr.eof() && !istr.fail(); } diff --git a/Foundation/src/Process.cpp b/Foundation/src/Process.cpp index 24fb43d37..387dbe857 100644 --- a/Foundation/src/Process.cpp +++ b/Foundation/src/Process.cpp @@ -127,9 +127,15 @@ int Process::wait(const ProcessHandle& handle) } +void Process::kill(const ProcessHandle& handle) +{ + killImpl(*handle._pImpl); +} + + void Process::kill(PID pid) { - killImpl(pid); + killImpl(pid); } diff --git a/Foundation/src/Process_UNIX.cpp b/Foundation/src/Process_UNIX.cpp index 9fa1d5b8a..63f321c58 100644 --- a/Foundation/src/Process_UNIX.cpp +++ b/Foundation/src/Process_UNIX.cpp @@ -169,9 +169,15 @@ ProcessHandleImpl* ProcessImpl::launchImpl(const std::string& command, const Arg } +void ProcessImpl::killImpl(const ProcessHandleImpl& handle) +{ + killImpl(handle.id()); +} + + void ProcessImpl::killImpl(PIDImpl pid) { - if (kill(pid, SIGKILL) != 0) + if (kill(pid, SIGKILL) != 0) { switch (errno) { diff --git a/Foundation/src/Process_VMS.cpp b/Foundation/src/Process_VMS.cpp index c38faf9aa..e5b01749f 100644 --- a/Foundation/src/Process_VMS.cpp +++ b/Foundation/src/Process_VMS.cpp @@ -125,9 +125,15 @@ ProcessHandleImpl* ProcessImpl::launchImpl(const std::string& command, const Arg } +void ProcessImpl::killImpl(const ProcessHandleImpl& handle) +{ + killImpl(handle.id()); +} + + void ProcessImpl::killImpl(PIDImpl pid) { - if (kill(pid, SIGKILL) != 0) + if (kill(pid, SIGKILL) != 0) { switch (errno) { diff --git a/Foundation/src/Process_VX.cpp b/Foundation/src/Process_VX.cpp index bf97994d8..c307ba172 100644 --- a/Foundation/src/Process_VX.cpp +++ b/Foundation/src/Process_VX.cpp @@ -89,9 +89,15 @@ ProcessHandleImpl* ProcessImpl::launchImpl(const std::string& command, const Arg } +void ProcessImpl::killImpl(const ProcessHandleImpl& handle) +{ + throw Poco::NotImplementedException("Process::kill()"); +} + + void ProcessImpl::killImpl(PIDImpl pid) { - throw Poco::NotImplementedException("Process::kill()"); + throw Poco::NotImplementedException("Process::kill()"); } diff --git a/Foundation/src/Process_WIN32.cpp b/Foundation/src/Process_WIN32.cpp index bbde7c0bf..29e6b460b 100644 --- a/Foundation/src/Process_WIN32.cpp +++ b/Foundation/src/Process_WIN32.cpp @@ -66,9 +66,15 @@ UInt32 ProcessHandleImpl::id() const } +HANDLE ProcessHandleImpl::process() const +{ + return _hProcess; +} + + int ProcessHandleImpl::wait() const { - DWORD rc = WaitForSingleObject(_hProcess, INFINITE); + DWORD rc = WaitForSingleObject(_hProcess, INFINITE); if (rc != WAIT_OBJECT_0) throw SystemException("Wait failed for process", NumberFormatter::format(_pid)); @@ -176,9 +182,20 @@ ProcessHandleImpl* ProcessImpl::launchImpl(const std::string& command, const Arg } +void ProcessImpl::killImpl(const ProcessHandleImpl& handle) +{ + if (TerminateProcess(handle.process(), 0) == 0) + { + CloseHandle(handle.process()); + throw SystemException("cannot kill process"); + } + CloseHandle(handle.process()); +} + + void ProcessImpl::killImpl(PIDImpl pid) { - HANDLE hProc = OpenProcess(PROCESS_TERMINATE, FALSE, pid); + HANDLE hProc = OpenProcess(PROCESS_TERMINATE, FALSE, pid); if (hProc) { if (TerminateProcess(hProc, 0) == 0) diff --git a/Foundation/src/Process_WIN32U.cpp b/Foundation/src/Process_WIN32U.cpp index 08a6a347d..158a5e17a 100644 --- a/Foundation/src/Process_WIN32U.cpp +++ b/Foundation/src/Process_WIN32U.cpp @@ -67,9 +67,15 @@ UInt32 ProcessHandleImpl::id() const } +HANDLE ProcessHandleImpl::process() const +{ + return _hProcess; +} + + int ProcessHandleImpl::wait() const { - DWORD rc = WaitForSingleObject(_hProcess, INFINITE); + DWORD rc = WaitForSingleObject(_hProcess, INFINITE); if (rc != WAIT_OBJECT_0) throw SystemException("Wait failed for process", NumberFormatter::format(_pid)); @@ -180,9 +186,20 @@ ProcessHandleImpl* ProcessImpl::launchImpl(const std::string& command, const Arg } +void ProcessImpl::killImpl(const ProcessHandleImpl& handle) +{ + if (TerminateProcess(handle.process(), 0) == 0) + { + CloseHandle(handle.process()); + throw SystemException("cannot kill process"); + } + CloseHandle(handle.process()); +} + + void ProcessImpl::killImpl(PIDImpl pid) { - HANDLE hProc = OpenProcess(PROCESS_TERMINATE, FALSE, pid); + HANDLE hProc = OpenProcess(PROCESS_TERMINATE, FALSE, pid); if (hProc) { if (TerminateProcess(hProc, 0) == 0) diff --git a/Foundation/src/zconf.h b/Foundation/src/zconf.h index 02ce56c43..ec723a874 100644 --- a/Foundation/src/zconf.h +++ b/Foundation/src/zconf.h @@ -360,9 +360,11 @@ typedef uLong FAR uLongf; # define Z_HAVE_UNISTD_H #endif +#ifndef _WIN32_WCE #ifdef STDC # include /* for off_t */ #endif +#endif /* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and * "#define _LARGEFILE64_SOURCE 1" as requesting 64-bit operations, (even diff --git a/Net/Makefile b/Net/Makefile index 39ef96ed5..4f464991b 100644 --- a/Net/Makefile +++ b/Net/Makefile @@ -20,7 +20,8 @@ objects = \ HTTPFixedLengthStream HTTPServerRequest HTTPServerRequestImpl MultipartWriter StreamSocketImpl \ HTTPHeaderStream HTTPServerResponse HTTPServerResponseImpl NameValueCollection TCPServer \ HTTPMessage HTTPServerSession NetException TCPServerConnection HTTPBufferAllocator \ - HTTPRequest HTTPSession HTTPSessionInstantiator HTTPSessionFactory NetworkInterface TCPServerConnectionFactory \ + HTTPCredentials HTTPDigestCredentials HTTPAuthenticationParams TCPServerConnectionFactory \ + HTTPRequest HTTPSession HTTPSessionInstantiator HTTPSessionFactory NetworkInterface \ HTTPRequestHandler HTTPStream HTTPIOStream ServerSocket TCPServerDispatcher \ HTTPRequestHandlerFactory HTTPStreamFactory ServerSocketImpl TCPServerParams \ QuotedPrintableEncoder QuotedPrintableDecoder StringPartSource \ @@ -29,7 +30,8 @@ objects = \ MailRecipient MailMessage MailStream SMTPClientSession POP3ClientSession \ RawSocket RawSocketImpl ICMPClient ICMPEventArgs ICMPPacket ICMPPacketImpl \ ICMPSocket ICMPSocketImpl ICMPv4PacketImpl \ - RemoteSyslogChannel RemoteSyslogListener SMTPChannel + RemoteSyslogChannel RemoteSyslogListener SMTPChannel \ + WebSocket WebSocketImpl target = PocoNet target_version = $(LIBVERSION) diff --git a/Net/include/Poco/Net/HTTPClientSession.h b/Net/include/Poco/Net/HTTPClientSession.h index 9dbdb584a..b02431a1a 100644 --- a/Net/include/Poco/Net/HTTPClientSession.h +++ b/Net/include/Poco/Net/HTTPClientSession.h @@ -269,12 +269,20 @@ protected: /// proxy username and password have been set. void proxyAuthenticateImpl(HTTPRequest& request); - /// Sets the proxy credentials (Proxy-Authorization header), if - /// proxy username and password have been set. + /// Sets the proxy credentials (Proxy-Authorization header), if + /// proxy username and password have been set. + + StreamSocket proxyConnect(); + /// Sends a CONNECT request to the proxy server and returns + /// a StreamSocket for the resulting connection. + + void proxyTunnel(); + /// Calls proxyConnect() and attaches the resulting StreamSocket + /// to the HTTPClientSession. private: - std::string _host; - Poco::UInt16 _port; + std::string _host; + Poco::UInt16 _port; std::string _proxyHost; Poco::UInt16 _proxyPort; std::string _proxyUsername; @@ -286,9 +294,11 @@ private: bool _expectResponseBody; std::ostream* _pRequestStream; std::istream* _pResponseStream; - - HTTPClientSession(const HTTPClientSession&); - HTTPClientSession& operator = (const HTTPClientSession&); + + HTTPClientSession(const HTTPClientSession&); + HTTPClientSession& operator = (const HTTPClientSession&); + + friend class WebSocket; }; diff --git a/Net/include/Poco/Net/HTTPCredentials.h b/Net/include/Poco/Net/HTTPCredentials.h index 9e3e925d9..2177837f8 100644 --- a/Net/include/Poco/Net/HTTPCredentials.h +++ b/Net/include/Poco/Net/HTTPCredentials.h @@ -5,7 +5,7 @@ // // Library: Net // Package: HTTP -// Module: HTTPCredentials +// Module: HTTPCredentials // // Definition of the HTTPCredentials class. // @@ -58,91 +58,107 @@ class HTTPResponse; class Net_API HTTPCredentials - /// This is a utility class for working with HTTP - /// authentication (basic or digest) in HTTPRequest objects. - /// - /// Usage is as follows: - /// First, create a HTTPCredentials object containing - /// the username and password. - /// Poco::Net::HTTPCredentials creds("user", "s3cr3t"); - /// - /// Second, send the HTTP request with Poco::Net::HTTPClientSession. - /// Poco::Net::HTTPClientSession session("pocoproject.org"); - /// Poco::Net::HTTPRequest request(HTTPRequest::HTTP_GET, "/index.html", HTTPMessage::HTTP_1_1); - /// session.sendRequest(request); - /// Poco::Net::HTTPResponse; - /// std::istream& istr = session.receiveResponse(response); - /// - /// If the server responds with a 401 status, authenticate the - /// request and resend it: - /// if (response.getStatus() == Poco::Net::HTTPResponse::HTTP_UNAUTHORIZED) - /// { - /// creds.authenticate(request, response); - /// session.sendRequest(request); - /// ... - /// } - /// - /// To perform multiple authenticated requests, call updateAuthInfo() - /// instead of authenticate() on subsequent requests. - /// creds.updateAuthInfo(request); - /// session.sendRequest(request); - /// ... - /// - /// Note: Do not forget to read the entire response stream from the 401 response - /// before sending the authenticated request, otherwise there may be - /// problems if a persistent connection is used. + /// This is a utility class for working with HTTP + /// authentication (basic or digest) in HTTPRequest objects. + /// + /// Usage is as follows: + /// First, create a HTTPCredentials object containing + /// the username and password. + /// Poco::Net::HTTPCredentials creds("user", "s3cr3t"); + /// + /// Second, send the HTTP request with Poco::Net::HTTPClientSession. + /// Poco::Net::HTTPClientSession session("pocoproject.org"); + /// Poco::Net::HTTPRequest request(HTTPRequest::HTTP_GET, "/index.html", HTTPMessage::HTTP_1_1); + /// session.sendRequest(request); + /// Poco::Net::HTTPResponse; + /// std::istream& istr = session.receiveResponse(response); + /// + /// If the server responds with a 401 status, authenticate the + /// request and resend it: + /// if (response.getStatus() == Poco::Net::HTTPResponse::HTTP_UNAUTHORIZED) + /// { + /// creds.authenticate(request, response); + /// session.sendRequest(request); + /// ... + /// } + /// + /// To perform multiple authenticated requests, call updateAuthInfo() + /// instead of authenticate() on subsequent requests. + /// creds.updateAuthInfo(request); + /// session.sendRequest(request); + /// ... + /// + /// Note: Do not forget to read the entire response stream from the 401 response + /// before sending the authenticated request, otherwise there may be + /// problems if a persistent connection is used. { public: - HTTPCredentials(); - /// Creates an empty HTTPCredentials object. + HTTPCredentials(); + /// Creates an empty HTTPCredentials object. - HTTPCredentials(const std::string& username, const std::string& password); - /// Creates an HTTPCredentials object with the given username and password. + HTTPCredentials(const std::string& username, const std::string& password); + /// Creates an HTTPCredentials object with the given username and password. ~HTTPCredentials(); /// Destroys the HTTPCredentials. + void fromUserInfo(const std::string& userInfo); + /// Parses username:password string and sets username and password of + /// the credentials object. + /// Throws SyntaxException on invalid user information. + + void fromURI(const URI& uri); + /// Extracts username and password from the given URI and sets username + /// and password of the credentials object. + /// Does nothing if URI has no user info part. + void setUsername(const std::string& username); /// Sets the username. - const std::string& getUsername() const; - /// Returns the username. + const std::string& getUsername() const; + /// Returns the username. - void setPassword(const std::string& password); - /// Sets the password. + void setPassword(const std::string& password); + /// Sets the password. - const std::string& getPassword() const; - /// Returns the password. + const std::string& getPassword() const; + /// Returns the password. - void authenticate(HTTPRequest& request, const HTTPResponse& response); - /// Inspects authenticate header of the response, initializes - /// the internal state (in case of digest authentication) and - /// adds required information to the given HTTPRequest. - /// - /// Does nothing if there is no authentication header in the - /// HTTPResponse. + void authenticate(HTTPRequest& request, const HTTPResponse& response); + /// Inspects authenticate header of the response, initializes + /// the internal state (in case of digest authentication) and + /// adds required information to the given HTTPRequest. + /// + /// Does nothing if there is no authentication header in the + /// HTTPResponse. - void updateAuthInfo(HTTPRequest& request); - /// Updates internal state (in case of digest authentication) and - /// replaces authentication information in the request accordingly. + void updateAuthInfo(HTTPRequest& request); + /// Updates internal state (in case of digest authentication) and + /// replaces authentication information in the request accordingly. - static bool isBasicCredentials(const std::string& header); - /// Returns true if authentication header is for Basic authentication. + static bool isBasicCredentials(const std::string& header); + /// Returns true if authentication header is for Basic authentication. static bool isDigestCredentials(const std::string& header); /// Returns true if authentication header is for Digest authentication. + static bool hasBasicCredentials(const HTTPRequest& request); + /// Returns true if Authorization with Basic credentials header is present in the request. + + static bool hasDigestCredentials(const HTTPRequest& request); + /// Returns true if Authorization with Digest credentials header is present in the request. + static void extractCredentials(const std::string& userInfo, std::string& username, std::string& password); /// Extracts username and password from user:password information string. - static void extractCredentials(const Poco::URI& uri, std::string& username, std::string& password); - /// Extracts username and password from the given URI (e.g.: "http://user:pass@sample.com/secret"). + static void extractCredentials(const Poco::URI& uri, std::string& username, std::string& password); + /// Extracts username and password from the given URI (e.g.: "http://user:pass@sample.com/secret"). private: - HTTPCredentials(const HTTPCredentials&); - HTTPCredentials& operator = (const HTTPCredentials&); + HTTPCredentials(const HTTPCredentials&); + HTTPCredentials& operator = (const HTTPCredentials&); - HTTPDigestCredentials _digest; + HTTPDigestCredentials _digest; }; @@ -151,25 +167,25 @@ private: // inline void HTTPCredentials::setUsername(const std::string& username) { - _digest.setUsername(username); + _digest.setUsername(username); } inline const std::string& HTTPCredentials::getUsername() const { - return _digest.getUsername(); + return _digest.getUsername(); } - + inline void HTTPCredentials::setPassword(const std::string& password) { - _digest.setPassword(password); + _digest.setPassword(password); } inline const std::string& HTTPCredentials::getPassword() const { - return _digest.getPassword(); + return _digest.getPassword(); } diff --git a/Net/include/Poco/Net/NetException.h b/Net/include/Poco/Net/NetException.h index c88a47112..ad1d019b2 100644 --- a/Net/include/Poco/Net/NetException.h +++ b/Net/include/Poco/Net/NetException.h @@ -70,6 +70,7 @@ POCO_DECLARE_EXCEPTION(Net_API, SMTPException, NetException) POCO_DECLARE_EXCEPTION(Net_API, POP3Exception, NetException) POCO_DECLARE_EXCEPTION(Net_API, ICMPException, NetException) POCO_DECLARE_EXCEPTION(Net_API, HTMLFormException, NetException) +POCO_DECLARE_EXCEPTION(Net_API, WebSocketException, NetException) } } // namespace Poco::Net diff --git a/Net/src/HTTPClientSession.cpp b/Net/src/HTTPClientSession.cpp index 4bb0fadc2..529820a1a 100644 --- a/Net/src/HTTPClientSession.cpp +++ b/Net/src/HTTPClientSession.cpp @@ -415,4 +415,30 @@ void HTTPClientSession::proxyAuthenticateImpl(HTTPRequest& request) } +StreamSocket HTTPClientSession::proxyConnect() +{ + HTTPClientSession proxySession(getProxyHost(), getProxyPort()); + proxySession.setTimeout(getTimeout()); + SocketAddress targetAddress(getHost(), getPort()); + HTTPRequest proxyRequest(HTTPRequest::HTTP_CONNECT, targetAddress.toString(), HTTPMessage::HTTP_1_1); + HTTPResponse proxyResponse; + proxyRequest.set("Proxy-Connection", "keep-alive"); + proxyRequest.set("Host", getHost()); + proxyAuthenticateImpl(proxyRequest); + proxySession.setKeepAlive(true); + proxySession.sendRequest(proxyRequest); + proxySession.receiveResponse(proxyResponse); + if (proxyResponse.getStatus() != HTTPResponse::HTTP_OK) + throw HTTPException("Cannot establish proxy connection", proxyResponse.getReason()); + return proxySession.detachSocket(); +} + + +void HTTPClientSession::proxyTunnel() +{ + StreamSocket ss = proxyConnect(); + attachSocket(ss); +} + + } } // namespace Poco::Net diff --git a/Net/src/HTTPCredentials.cpp b/Net/src/HTTPCredentials.cpp index d674c1925..703d1ede1 100644 --- a/Net/src/HTTPCredentials.cpp +++ b/Net/src/HTTPCredentials.cpp @@ -5,7 +5,7 @@ // // Library: Net // Package: HTTP -// Module: HTTPCredentials +// Module: HTTPCredentials // // Copyright (c) 2011, Anton V. Yabchinskiy (arn at bestmx dot ru). // Copyright (c) 2012, Applied Informatics Software Engineering GmbH. @@ -42,6 +42,7 @@ #include "Poco/Net/HTTPResponse.h" #include "Poco/Net/NetException.h" #include "Poco/String.h" +#include "Poco/Ascii.h" #include "Poco/URI.h" @@ -58,7 +59,7 @@ HTTPCredentials::HTTPCredentials() HTTPCredentials::HTTPCredentials(const std::string& username, const std::string& password): - _digest(username, password) + _digest(username, password) { } @@ -68,77 +69,113 @@ HTTPCredentials::~HTTPCredentials() } +void HTTPCredentials::fromUserInfo(const std::string& userInfo) +{ + std::string username; + std::string password; + + extractCredentials(userInfo, username, password); + setUsername(username); + setPassword(password); + // TODO: Reset digest state? +} + + +void HTTPCredentials::fromURI(const URI& uri) +{ + std::string username; + std::string password; + + extractCredentials(uri, username, password); + setUsername(username); + setPassword(password); + // TODO: Reset digest state? +} + + void HTTPCredentials::authenticate(HTTPRequest& request, const HTTPResponse& response) { for (HTTPResponse::ConstIterator iter = response.find("WWW-Authenticate"); iter != response.end(); ++iter) - { - if (isBasicCredentials(iter->second)) - { - HTTPBasicCredentials(_digest.getUsername(), _digest.getPassword()).authenticate(request); - return; - } - else if (isDigestCredentials(iter->second)) - { - _digest.authenticate(request, HTTPAuthenticationParams(iter->second.substr(7))); - return; - } - } + { + if (isBasicCredentials(iter->second)) + { + HTTPBasicCredentials(_digest.getUsername(), _digest.getPassword()).authenticate(request); + return; + } + else if (isDigestCredentials(iter->second)) + { + _digest.authenticate(request, HTTPAuthenticationParams(iter->second.substr(7))); + return; + } + } } void HTTPCredentials::updateAuthInfo(HTTPRequest& request) { - if (request.has("Authorization")) + if (request.has(HTTPRequest::AUTHORIZATION)) { - const std::string& authorization = request.get("Authorization"); + const std::string& authorization = request.get(HTTPRequest::AUTHORIZATION); if (isBasicCredentials(authorization)) { - HTTPBasicCredentials(_digest.getUsername(), _digest.getPassword()).authenticate(request); - } - else if (isDigestCredentials(authorization)) - { - _digest.updateAuthInfo(request); - } - } + HTTPBasicCredentials(_digest.getUsername(), _digest.getPassword()).authenticate(request); + } + else if (isDigestCredentials(authorization)) + { + _digest.updateAuthInfo(request); + } + } } bool HTTPCredentials::isBasicCredentials(const std::string& header) { - return icompare(header, 0, 6, "Basic ") == 0; + return icompare(header, 0, 5, "Basic") == 0 && (header.size() > 5 ? Poco::Ascii::isSpace(header[5]) : true); } bool HTTPCredentials::isDigestCredentials(const std::string& header) { - return icompare(header, 0, 7, "Digest ") == 0; + return icompare(header, 0, 6, "Digest") == 0 && (header.size() > 6 ? Poco::Ascii::isSpace(header[6]) : true); +} + + +bool HTTPCredentials::hasBasicCredentials(const HTTPRequest& request) +{ + return request.has(HTTPRequest::AUTHORIZATION) && isBasicCredentials(request.get(HTTPRequest::AUTHORIZATION)); +} + + +bool HTTPCredentials::hasDigestCredentials(const HTTPRequest& request) +{ + return request.has(HTTPRequest::AUTHORIZATION) && isDigestCredentials(request.get(HTTPRequest::AUTHORIZATION)); } void HTTPCredentials::extractCredentials(const std::string& userInfo, std::string& username, std::string& password) { - const std::string::size_type p = userInfo.find(':'); + const std::string::size_type p = userInfo.find(':'); - if (p != std::string::npos) - { - username.assign(userInfo, 0, p); - password.assign(userInfo, p + 1, std::string::npos); - } - else - { - username.assign(userInfo); - password.clear(); - } + if (p != std::string::npos) + { + username.assign(userInfo, 0, p); + password.assign(userInfo, p + 1, std::string::npos); + } + else + { + username.assign(userInfo); + password.clear(); + } } void HTTPCredentials::extractCredentials(const Poco::URI& uri, std::string& username, std::string& password) { - if (!uri.getUserInfo().empty()) - { - extractCredentials(uri.getUserInfo(), username, password); - } + if (!uri.getUserInfo().empty()) + { + extractCredentials(uri.getUserInfo(), username, password); + } } diff --git a/Net/src/HTTPDigestCredentials.cpp b/Net/src/HTTPDigestCredentials.cpp index fd4a61e48..86a3b06bc 100644 --- a/Net/src/HTTPDigestCredentials.cpp +++ b/Net/src/HTTPDigestCredentials.cpp @@ -5,7 +5,7 @@ // // Library: Net // Package: HTTP -// Module: HTTPDigestCredentials +// Module: HTTPDigestCredentials // // Copyright (c) 2011, Anton V. Yabchinskiy (arn at bestmx dot ru). // Copyright (c) 2012, Applied Informatics Software Engineering GmbH. @@ -49,39 +49,39 @@ namespace { - std::string digest(Poco::DigestEngine& engine, - const std::string& a, - const std::string& b, - const std::string& c = std::string(), - const std::string& d = std::string(), - const std::string& e = std::string(), - const std::string& f = std::string()) - { - engine.reset(); - engine.update(a); - engine.update(':'); - engine.update(b); - if (!c.empty()) - { - engine.update(':'); - engine.update(c); - if (!d.empty()) - { - engine.update(':'); - engine.update(d); - engine.update(':'); - engine.update(e); - engine.update(':'); - engine.update(f); - } - } - return Poco::DigestEngine::digestToHex(engine.digest()); - } - - std::string formatNonceCounter(int counter) - { - return Poco::NumberFormatter::formatHex(counter, 8); - } + std::string digest(Poco::DigestEngine& engine, + const std::string& a, + const std::string& b, + const std::string& c = std::string(), + const std::string& d = std::string(), + const std::string& e = std::string(), + const std::string& f = std::string()) + { + engine.reset(); + engine.update(a); + engine.update(':'); + engine.update(b); + if (!c.empty()) + { + engine.update(':'); + engine.update(c); + if (!d.empty()) + { + engine.update(':'); + engine.update(d); + engine.update(':'); + engine.update(e); + engine.update(':'); + engine.update(f); + } + } + return Poco::DigestEngine::digestToHex(engine.digest()); + } + + std::string formatNonceCounter(int counter) + { + return Poco::NumberFormatter::formatHex(counter, 8); + } } @@ -111,10 +111,10 @@ HTTPDigestCredentials::HTTPDigestCredentials() { } - + HTTPDigestCredentials::HTTPDigestCredentials(const std::string& username, const std::string& password): - _username(username), - _password(password) + _username(username), + _password(password) { } @@ -126,67 +126,67 @@ HTTPDigestCredentials::~HTTPDigestCredentials() void HTTPDigestCredentials::setUsername(const std::string& username) { - _username = username; + _username = username; } - + void HTTPDigestCredentials::setPassword(const std::string& password) { - _password = password; + _password = password; } void HTTPDigestCredentials::authenticate(HTTPRequest& request, const HTTPResponse& response) { - authenticate(request, HTTPAuthenticationParams(response)); + authenticate(request, HTTPAuthenticationParams(response)); } void HTTPDigestCredentials::authenticate(HTTPRequest& request, const HTTPAuthenticationParams& responseAuthParams) { - createAuthParams(request, responseAuthParams); - request.setCredentials(SCHEME, _requestAuthParams.toString()); + createAuthParams(request, responseAuthParams); + request.setCredentials(SCHEME, _requestAuthParams.toString()); } void HTTPDigestCredentials::updateAuthInfo(HTTPRequest& request) { - updateAuthParams(request); - request.setCredentials(SCHEME, _requestAuthParams.toString()); + updateAuthParams(request); + request.setCredentials(SCHEME, _requestAuthParams.toString()); } std::string HTTPDigestCredentials::createNonce() { - Poco::FastMutex::ScopedLock lock(_nonceMutex); + Poco::FastMutex::ScopedLock lock(_nonceMutex); - MD5Engine md5; - Timestamp::TimeVal now = Timestamp().epochMicroseconds(); + MD5Engine md5; + Timestamp::TimeVal now = Timestamp().epochMicroseconds(); - md5.update(&_nonceCounter, sizeof(_nonceCounter)); - md5.update(&now, sizeof(now)); + md5.update(&_nonceCounter, sizeof(_nonceCounter)); + md5.update(&now, sizeof(now)); - ++_nonceCounter; + ++_nonceCounter; - return DigestEngine::digestToHex(md5.digest()); + return DigestEngine::digestToHex(md5.digest()); } void HTTPDigestCredentials::createAuthParams(const HTTPRequest& request, const HTTPAuthenticationParams& responseAuthParams) { - // Not implemented: "domain" auth parameter and integrity protection. + // Not implemented: "domain" auth parameter and integrity protection. - if (!responseAuthParams.has(NONCE_PARAM) || !responseAuthParams.has(REALM_PARAM)) - throw InvalidArgumentException("Invalid HTTP authentication parameters"); + if (!responseAuthParams.has(NONCE_PARAM) || !responseAuthParams.has(REALM_PARAM)) + throw InvalidArgumentException("Invalid HTTP authentication parameters"); - const std::string& algorithm = responseAuthParams.get(ALGORITHM_PARAM, DEFAULT_ALGORITHM); + const std::string& algorithm = responseAuthParams.get(ALGORITHM_PARAM, DEFAULT_ALGORITHM); - if (icompare(algorithm, DEFAULT_ALGORITHM) != 0) - throw NotImplementedException("Unsupported digest algorithm", algorithm); + if (icompare(algorithm, DEFAULT_ALGORITHM) != 0) + throw NotImplementedException("Unsupported digest algorithm", algorithm); - const std::string& nonce = responseAuthParams.get(NONCE_PARAM); - const std::string& qop = responseAuthParams.get(QOP_PARAM, DEFAULT_QOP); - const std::string& realm = responseAuthParams.getRealm(); + const std::string& nonce = responseAuthParams.get(NONCE_PARAM); + const std::string& qop = responseAuthParams.get(QOP_PARAM, DEFAULT_QOP); + const std::string& realm = responseAuthParams.getRealm(); _requestAuthParams.clear(); _requestAuthParams.set(USERNAME_PARAM, _username); @@ -194,104 +194,108 @@ void HTTPDigestCredentials::createAuthParams(const HTTPRequest& request, const H _requestAuthParams.set(NONCE_PARAM, nonce); _requestAuthParams.setRealm(realm); if (responseAuthParams.has(OPAQUE_PARAM)) - { - _requestAuthParams.set(OPAQUE_PARAM, responseAuthParams.get(OPAQUE_PARAM)); - } + { + _requestAuthParams.set(OPAQUE_PARAM, responseAuthParams.get(OPAQUE_PARAM)); + } if (qop.empty()) { - MD5Engine engine; - - const std::string ha1 = digest(engine, _username, realm, _password); - const std::string ha2 = digest(engine, request.getMethod(), request.getURI()); - - _requestAuthParams.set(RESPONSE_PARAM, digest(engine, ha1, nonce, ha2)); + updateAuthParams(request); } else { - Poco::StringTokenizer tok(qop, ",", Poco::StringTokenizer::TOK_TRIM); - bool qopSupported = false; - for (Poco::StringTokenizer::Iterator it = tok.begin(); it != tok.end(); ++it) - { - if (icompare(*it, AUTH_PARAM) == 0) - { - qopSupported = true; - _requestAuthParams.set(CNONCE_PARAM, createNonce()); - _requestAuthParams.set(QOP_PARAM, *it); - updateAuthParams(request); - break; + Poco::StringTokenizer tok(qop, ",", Poco::StringTokenizer::TOK_TRIM); + bool qopSupported = false; + for (Poco::StringTokenizer::Iterator it = tok.begin(); it != tok.end(); ++it) + { + if (icompare(*it, AUTH_PARAM) == 0) + { + qopSupported = true; + _requestAuthParams.set(CNONCE_PARAM, createNonce()); + _requestAuthParams.set(QOP_PARAM, *it); + updateAuthParams(request); + break; } } - if (!qopSupported) - NotImplementedException("Unsupported QoP requested", qop); + if (!qopSupported) + throw NotImplementedException("Unsupported QoP requested", qop); } } void HTTPDigestCredentials::updateAuthParams(const HTTPRequest& request) { + MD5Engine engine; const std::string& qop = _requestAuthParams.get(QOP_PARAM, DEFAULT_QOP); - if (icompare(qop, AUTH_PARAM) == 0) - { - MD5Engine engine; + const std::string& realm = _requestAuthParams.getRealm(); + const std::string& nonce = _requestAuthParams.get(NONCE_PARAM); - const std::string& nonce = _requestAuthParams.get(NONCE_PARAM); - const std::string& realm = _requestAuthParams.getRealm(); + _requestAuthParams.set(URI_PARAM, request.getURI()); + + if (qop.empty()) + { + const std::string ha1 = digest(engine, _username, realm, _password); + const std::string ha2 = digest(engine, request.getMethod(), request.getURI()); + + _requestAuthParams.set(RESPONSE_PARAM, digest(engine, ha1, nonce, ha2)); + } + else if (icompare(qop, AUTH_PARAM) == 0) + { const std::string& cnonce = _requestAuthParams.get(CNONCE_PARAM); const std::string ha1 = digest(engine, _username, realm, _password); - const std::string ha2 = digest(engine, request.getMethod(), request.getURI()); - const std::string nc = formatNonceCounter(updateNonceCounter(nonce)); + const std::string ha2 = digest(engine, request.getMethod(), request.getURI()); + const std::string nc = formatNonceCounter(updateNonceCounter(nonce)); - _requestAuthParams.set(NC_PARAM, nc); - _requestAuthParams.set(RESPONSE_PARAM, digest(engine, ha1, nonce, nc, cnonce, qop, ha2)); - } + _requestAuthParams.set(NC_PARAM, nc); + _requestAuthParams.set(RESPONSE_PARAM, digest(engine, ha1, nonce, nc, cnonce, qop, ha2)); + } } bool HTTPDigestCredentials::verifyAuthInfo(const HTTPRequest& request) const { - HTTPAuthenticationParams params(request); - return verifyAuthParams(request, params); + HTTPAuthenticationParams params(request); + return verifyAuthParams(request, params); } bool HTTPDigestCredentials::verifyAuthParams(const HTTPRequest& request, const HTTPAuthenticationParams& params) const { - const std::string& nonce = params.get(NONCE_PARAM); - const std::string& realm = params.getRealm(); - const std::string& qop = params.get(QOP_PARAM, DEFAULT_QOP); - std::string response; - MD5Engine engine; - if (qop.empty()) - { - const std::string ha1 = digest(engine, _username, realm, _password); - const std::string ha2 = digest(engine, request.getMethod(), request.getURI()); - response = digest(engine, ha1, nonce, ha2); - } - else if (icompare(qop, AUTH_PARAM) == 0) - { - const std::string& cnonce = params.get(CNONCE_PARAM); - const std::string& nc = params.get(NC_PARAM); - const std::string ha1 = digest(engine, _username, realm, _password); - const std::string ha2 = digest(engine, request.getMethod(), request.getURI()); - response = digest(engine, ha1, nonce, nc, cnonce, qop, ha2); - } - return response == params.get(RESPONSE_PARAM); + const std::string& nonce = params.get(NONCE_PARAM); + const std::string& realm = params.getRealm(); + const std::string& qop = params.get(QOP_PARAM, DEFAULT_QOP); + std::string response; + MD5Engine engine; + if (qop.empty()) + { + const std::string ha1 = digest(engine, _username, realm, _password); + const std::string ha2 = digest(engine, request.getMethod(), request.getURI()); + response = digest(engine, ha1, nonce, ha2); + } + else if (icompare(qop, AUTH_PARAM) == 0) + { + const std::string& cnonce = params.get(CNONCE_PARAM); + const std::string& nc = params.get(NC_PARAM); + const std::string ha1 = digest(engine, _username, realm, _password); + const std::string ha2 = digest(engine, request.getMethod(), request.getURI()); + response = digest(engine, ha1, nonce, nc, cnonce, qop, ha2); + } + return response == params.get(RESPONSE_PARAM); } int HTTPDigestCredentials::updateNonceCounter(const std::string& nonce) { - NonceCounterMap::iterator iter = _nc.find(nonce); + NonceCounterMap::iterator iter = _nc.find(nonce); - if (iter == _nc.end()) - { - iter = _nc.insert(NonceCounterMap::value_type(nonce, 0)).first; - } - iter->second++; + if (iter == _nc.end()) + { + iter = _nc.insert(NonceCounterMap::value_type(nonce, 0)).first; + } + iter->second++; - return iter->second; + return iter->second; } diff --git a/Net/src/NetException.cpp b/Net/src/NetException.cpp index 9aea57f8c..fe2c384e2 100644 --- a/Net/src/NetException.cpp +++ b/Net/src/NetException.cpp @@ -67,6 +67,7 @@ POCO_IMPLEMENT_EXCEPTION(SMTPException, NetException, "SMTP Exception") POCO_IMPLEMENT_EXCEPTION(POP3Exception, NetException, "POP3 Exception") POCO_IMPLEMENT_EXCEPTION(ICMPException, NetException, "ICMP Exception") POCO_IMPLEMENT_EXCEPTION(HTMLFormException, NetException, "HTML Form Exception") +POCO_IMPLEMENT_EXCEPTION(WebSocketException, NetException, "WebSocket Exception") } } // namespace Poco::Net diff --git a/Util/src/Application.cpp b/Util/src/Application.cpp index 7d7ce6372..87ad19aab 100644 --- a/Util/src/Application.cpp +++ b/Util/src/Application.cpp @@ -299,14 +299,16 @@ void Application::stopOptionsProcessing() int Application::run() { - int rc = EXIT_SOFTWARE; - initialize(*this); - try - { - rc = main(_args); - } - catch (Poco::Exception& exc) - { + int rc = EXIT_CONFIG; + try + { + initialize(*this); + rc = EXIT_SOFTWARE; + rc = main(_args); + uninitialize(); + } + catch (Poco::Exception& exc) + { logger().log(exc); } catch (std::exception& exc) @@ -314,11 +316,10 @@ int Application::run() logger().error(exc.what()); } catch (...) - { - logger().fatal("system exception"); - } - uninitialize(); - return rc; + { + logger().fatal("system exception"); + } + return rc; } @@ -368,13 +369,13 @@ void Application::processOptions() while (it != _args.end() && !_stopOptionsProcessing) { std::string name; - std::string value; - if (processor.process(*it, name, value)) - { - if (!name.empty()) // "--" option to end options processing or deferred argument - { - handleOption(name, value); - } + std::string value; + if (processor.process(*it, name, value)) + { + if (!name.empty()) // "--" option to end options processing or deferred argument + { + handleOption(name, value); + } it = _args.erase(it); } else ++it; diff --git a/Util/src/ServerApplication.cpp b/Util/src/ServerApplication.cpp index c01056bdf..d86c916c6 100644 --- a/Util/src/ServerApplication.cpp +++ b/Util/src/ServerApplication.cpp @@ -388,12 +388,12 @@ void ServerApplication::registerService() else service.registerService(path, _displayName); if (_startup == "auto") - service.setStartup(WinService::SVC_AUTO_START); - else if (_startup == "manual") - service.setStartup(WinService::SVC_MANUAL_START); - if (!_description.empty()) - service.setDescription(_description); - logger().information("The application has been successfully registered as a service."); + service.setStartup(WinService::SVC_AUTO_START); + else if (_startup == "manual") + service.setStartup(WinService::SVC_MANUAL_START); + if (!_description.empty()) + service.setDescription(_description); + logger().information("The application has been successfully registered as a service."); } @@ -428,19 +428,19 @@ void ServerApplication::defineOptions(OptionSet& options) .required(false) .repeatable(false) .argument("name") - .callback(OptionCallback(this, &ServerApplication::handleDisplayName))); + .callback(OptionCallback(this, &ServerApplication::handleDisplayName))); - options.addOption( - Option("description", "", "Specify a description for the service (only with /registerService).") - .required(false) - .repeatable(false) - .argument("text") - .callback(OptionCallback(this, &ServerApplication::handleDescription))); + options.addOption( + Option("description", "", "Specify a description for the service (only with /registerService).") + .required(false) + .repeatable(false) + .argument("text") + .callback(OptionCallback(this, &ServerApplication::handleDescription))); - options.addOption( - Option("startup", "", "Specify the startup mode for the service (only with /registerService).") - .required(false) - .repeatable(false) + options.addOption( + Option("startup", "", "Specify the startup mode for the service (only with /registerService).") + .required(false) + .repeatable(false) .argument("automatic|manual") .callback(OptionCallback(this, &ServerApplication::handleStartup))); } @@ -466,13 +466,13 @@ void ServerApplication::handleDisplayName(const std::string& name, const std::st void ServerApplication::handleDescription(const std::string& name, const std::string& value) { - _description = value; + _description = value; } void ServerApplication::handleStartup(const std::string& name, const std::string& value) { - if (Poco::icompare(value, 4, std::string("auto")) == 0) + if (Poco::icompare(value, 4, std::string("auto")) == 0) _startup = "auto"; else if (Poco::icompare(value, std::string("manual")) == 0) _startup = "manual"; @@ -496,20 +496,10 @@ int ServerApplication::run(int argc, char** argv) } catch (Exception& exc) { - logger().log(exc); - return EXIT_CONFIG; - } - int rc = run(); - try - { - uninitialize(); - } - catch (Exception& exc) - { - logger().log(exc); - rc = EXIT_CONFIG; - } - return rc; + logger().log(exc); + return EXIT_CONFIG; + } + return run(); } @@ -521,20 +511,10 @@ int ServerApplication::run(const std::vector& args) } catch (Exception& exc) { - logger().log(exc); - return EXIT_CONFIG; - } - int rc = run(); - try - { - uninitialize(); - } - catch (Exception& exc) - { - logger().log(exc); - rc = EXIT_CONFIG; - } - return rc; + logger().log(exc); + return EXIT_CONFIG; + } + return run(); } @@ -547,20 +527,10 @@ int ServerApplication::run(int argc, wchar_t** argv) } catch (Exception& exc) { - logger().log(exc); - return EXIT_CONFIG; - } - int rc = run(); - try - { - uninitialize(); - } - catch (Exception& exc) - { - logger().log(exc); - rc = EXIT_CONFIG; - } - return rc; + logger().log(exc); + return EXIT_CONFIG; + } + return run(); } #endif diff --git a/Util/src/WinRegistryKey.cpp b/Util/src/WinRegistryKey.cpp index b93441793..3433d5554 100644 --- a/Util/src/WinRegistryKey.cpp +++ b/Util/src/WinRegistryKey.cpp @@ -53,9 +53,35 @@ namespace Poco { namespace Util { +namespace +{ + class AutoHandle + { + public: + AutoHandle(HMODULE h): + _h(h) + { + } + + ~AutoHandle() + { + FreeLibrary(_h); + } + + HMODULE handle() + { + return _h; + } + + private: + HMODULE _h; + }; +} + + WinRegistryKey::WinRegistryKey(const std::string& key, bool readOnly, REGSAM extraSam): - _hKey(0), - _readOnly(readOnly), + _hKey(0), + _readOnly(readOnly), _extraSam(extraSam) { std::string::size_type pos = key.find('\\'); @@ -266,17 +292,53 @@ void WinRegistryKey::deleteKey() std::string subKey(_subKey); subKey += "\\"; subKey += *it; - WinRegistryKey subRegKey(_hRootKey, subKey); - subRegKey.deleteKey(); - } + WinRegistryKey subRegKey(_hRootKey, subKey); + subRegKey.deleteKey(); + } + + // NOTE: RegDeleteKeyEx is only available on Windows XP 64-bit SP3, Windows Vista or later. + // We cannot call it directly as this would prevent the code running on Windows XP 32-bit. + // Therefore, if we need to call RegDeleteKeyEx (_extraSam != 0) we need to check for + // its existence in ADVAPI32.DLL and call it indirectly. #if defined(POCO_WIN32_UTF8) - std::wstring usubKey; - Poco::UnicodeConverter::toUTF16(_subKey, usubKey); - if (RegDeleteKeyW(_hRootKey, usubKey.c_str()) != ERROR_SUCCESS) - throw NotFoundException(key()); + std::wstring usubKey; + Poco::UnicodeConverter::toUTF16(_subKey, usubKey); + + typedef LONG (WINAPI *RegDeleteKeyExWFunc)(HKEY hKey, const wchar_t* lpSubKey, REGSAM samDesired, DWORD Reserved); + if (_extraSam != 0) + { + AutoHandle advAPI32(LoadLibraryW(L"ADVAPI32.DLL")); + if (advAPI32.handle()) + { + RegDeleteKeyExWFunc pRegDeleteKeyExW = reinterpret_cast(GetProcAddress(advAPI32.handle() , "RegDeleteKeyExW")); + if (pRegDeleteKeyExW) + { + if ((*pRegDeleteKeyExW)(_hRootKey, usubKey.c_str(), _extraSam, 0) != ERROR_SUCCESS) + throw NotFoundException(key()); + return; + } + } + } + if (RegDeleteKeyW(_hRootKey, usubKey.c_str()) != ERROR_SUCCESS) + throw NotFoundException(key()); #else - if (RegDeleteKey(_hRootKey, _subKey.c_str()) != ERROR_SUCCESS) - throw NotFoundException(key()); + typedef LONG (WINAPI *RegDeleteKeyExAFunc)(HKEY hKey, const char* lpSubKey, REGSAM samDesired, DWORD Reserved); + if (_extraSam != 0) + { + AutoHandle advAPI32(LoadLibraryA("ADVAPI32.DLL")); + if (advAPI32.handle()) + { + RegDeleteKeyExAFunc pRegDeleteKeyExA = reinterpret_cast(GetProcAddress(advAPI32.handle() , "RegDeleteKeyExA")); + if (pRegDeleteKeyExA) + { + if ((*pRegDeleteKeyExA)(_hRootKey, _subKey.c_str(), _extraSam, 0) != ERROR_SUCCESS) + throw NotFoundException(key()); + return; + } + } + } + if (RegDeleteKey(_hRootKey, _subKey.c_str()) != ERROR_SUCCESS) + throw NotFoundException(key()); #endif }