/* * synergy -- mouse and keyboard sharing utility * Copyright (C) 2002 Chris Schoeneman * * This package is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * found in the file COPYING that should have accompanied this file. * * This package is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ #ifndef CHTTPPROTOCOL_H #define CHTTPPROTOCOL_H #include "CString.h" #include "CStringUtil.h" #include "BasicTypes.h" #include "stdlist.h" #include "stdmap.h" #include "stdvector.h" class IInputStream; class IOutputStream; //! HTTP request type /*! This class encapsulates an HTTP request. */ class CHTTPRequest { private: typedef std::list > CHeaderList; public: //! Iterator on headers /*! An iterator on the headers. Each element is a std::pair; first is the header name as a CString, second is the header value as a CString. */ typedef CHeaderList::const_iterator const_iterator; CHTTPRequest(); ~CHTTPRequest(); //! @name manipulators //@{ //! Insert header /*! Add a header by name replacing the existing header, if any. Headers are sent in the order they're inserted. Replacing a header does not change its original position in the order. */ void insertHeader(const CString& name, const CString& value); //! Append header /*! Append a header. Equivalent to insertHeader() if the header doesn't exist, otherwise it appends a comma and the value to the existing header. */ void appendHeader(const CString& name, const CString& value); //! Remove header /*! Remove a header by name. Does nothing if the header doesn't exist. */ void eraseHeader(const CString& name); //@} //! @name accessors //@{ //! Check header existence /*! Returns true iff the header exists. */ bool isHeader(const CString& name) const; //! Get header /*! Get a header by name. Returns the empty string if the header doesn't exist. */ CString getHeader(const CString& name) const; // headers are iterated in the order they were added. //! Get beginning header iterator const_iterator begin() const { return m_headers.begin(); } //! Get ending header iterator const_iterator end() const { return m_headers.end(); } //@} public: // note -- these members are public for convenience //! The HTTP method CString m_method; //! The HTTP URI CString m_uri; //! The HTTP major version number SInt32 m_majorVersion; //! The HTTP minor version number SInt32 m_minorVersion; //! The HTTP body, after transfer decoding CString m_body; private: typedef std::map CHeaderMap; CHeaderList m_headers; CHeaderMap m_headerByName; }; //! HTTP reply type /*! This class encapsulates an HTTP reply. */ class CHTTPReply { public: //! Header list /*! The type of the reply header list. Each pair is the header name and value, respectively for first and second. */ typedef std::vector > CHeaderList; // note -- these members are public for convenience //! The HTTP major version number SInt32 m_majorVersion; //! The HTTP minor version number SInt32 m_minorVersion; //! The HTTP status code SInt32 m_status; //! The HTTP reason phrase CString m_reason; //! The HTTP method CString m_method; //! The HTTP headers CHeaderList m_headers; //! The HTTP body CString m_body; }; //! HTTP protocol utilities /*! This class provides utility functions for HTTP. */ class CHTTPProtocol { public: //! Multipart form parts /*! Each element is the contents of a multipart form part indexed by it's name. */ typedef std::map CFormParts; //! Read HTTP request /*! Read and parse an HTTP request. The result is returned in a CHTTPRequest which the client must delete. Throws an XHTTP if there was a parse error. Throws an XIO exception if there was a read error. If \c maxSize is greater than zero and the request is larger than \c maxSize bytes then throws XHTTP(413) (request entity too large). */ static CHTTPRequest* readRequest(IInputStream*, UInt32 maxSize = 0); //! Send HTTP response /*! Send an HTTP reply. The Content-Length and Date headers are set automatically. */ static void reply(IOutputStream*, CHTTPReply&); //! Parse multipart form data /*! Parse a multipart/form-data body into its parts. Returns true iff the entire body was correctly parsed. */ // FIXME -- name/value pairs insufficient to save part headers static bool parseFormData(const CHTTPRequest&, CFormParts& parts); private: static CString readLine(IInputStream*, CString& tmpBuffer); static CString readBlock(IInputStream*, UInt32 numBytes, CString& tmpBuffer); static CString readChunk(IInputStream*, CString& tmpBuffer, UInt32* maxSize); static void readHeaders(IInputStream*, CHTTPRequest*, bool isFooter, CString& tmpBuffer, UInt32* maxSize); static bool isValidToken(const CString&); }; #endif