2002-05-30 16:13:16 +00:00
|
|
|
#ifndef CHTTPPROTOCOL_H
|
|
|
|
#define CHTTPPROTOCOL_H
|
|
|
|
|
|
|
|
#include "BasicTypes.h"
|
|
|
|
#include "CString.h"
|
2002-06-02 13:34:35 +00:00
|
|
|
#include "stdlist.h"
|
2002-06-01 19:26:11 +00:00
|
|
|
#include "stdmap.h"
|
|
|
|
#include "stdvector.h"
|
2002-05-30 16:13:16 +00:00
|
|
|
|
|
|
|
class IInputStream;
|
|
|
|
class IOutputStream;
|
|
|
|
|
|
|
|
class CHTTPUtil {
|
|
|
|
public:
|
|
|
|
class CaselessCmp {
|
|
|
|
public:
|
|
|
|
bool operator()(const CString&, const CString&) const;
|
|
|
|
static bool less(const CString&, const CString&);
|
|
|
|
static bool equal(const CString&, const CString&);
|
|
|
|
static bool cmpLess(const CString::value_type&,
|
|
|
|
const CString::value_type&);
|
|
|
|
static bool cmpEqual(const CString::value_type&,
|
|
|
|
const CString::value_type&);
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
class CHTTPRequest {
|
|
|
|
public:
|
2002-06-02 13:34:35 +00:00
|
|
|
typedef std::list<std::pair<CString, CString> > CHeaderList;
|
|
|
|
typedef std::map<CString, CHeaderList::iterator,
|
|
|
|
CHTTPUtil::CaselessCmp> CHeaderMap;
|
|
|
|
typedef CHeaderList::const_iterator const_iterator;
|
2002-05-30 16:13:16 +00:00
|
|
|
|
2002-06-02 13:34:35 +00:00
|
|
|
CHTTPRequest();
|
|
|
|
~CHTTPRequest();
|
|
|
|
|
|
|
|
// manipulators
|
|
|
|
|
|
|
|
// add a header by name. replaces 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 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 a header by name. does nothing if no such header.
|
|
|
|
void eraseHeader(const CString& name);
|
|
|
|
|
|
|
|
// accessors
|
|
|
|
|
|
|
|
// returns true iff the header exists
|
|
|
|
bool isHeader(const CString& name) const;
|
|
|
|
|
|
|
|
// get a header by name. returns the empty string if no such header.
|
|
|
|
CString getHeader(const CString& name) const;
|
|
|
|
|
|
|
|
// get iterator over all headers in the order they were added
|
|
|
|
const_iterator begin() const { return m_headers.begin(); }
|
|
|
|
const_iterator end() const { return m_headers.end(); }
|
|
|
|
|
|
|
|
public:
|
|
|
|
// note -- these members are public for convenience
|
2002-05-30 16:13:16 +00:00
|
|
|
CString m_method;
|
|
|
|
CString m_uri;
|
|
|
|
SInt32 m_majorVersion;
|
|
|
|
SInt32 m_minorVersion;
|
2002-06-02 13:34:35 +00:00
|
|
|
CString m_body;
|
2002-05-30 16:13:16 +00:00
|
|
|
|
2002-06-02 13:34:35 +00:00
|
|
|
private:
|
2002-05-30 16:13:16 +00:00
|
|
|
CHeaderList m_headers;
|
2002-06-02 13:34:35 +00:00
|
|
|
CHeaderMap m_headerByName;
|
2002-05-30 16:13:16 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
class CHTTPReply {
|
|
|
|
public:
|
|
|
|
typedef std::vector<std::pair<CString, CString> > CHeaderList;
|
|
|
|
|
|
|
|
SInt32 m_majorVersion;
|
|
|
|
SInt32 m_minorVersion;
|
|
|
|
SInt32 m_status;
|
|
|
|
CString m_reason;
|
|
|
|
CString m_method;
|
|
|
|
|
|
|
|
CHeaderList m_headers;
|
|
|
|
|
|
|
|
CString m_body;
|
|
|
|
};
|
|
|
|
|
|
|
|
class CHTTPProtocol {
|
|
|
|
public:
|
|
|
|
// read and parse an HTTP request. result is returned in a
|
|
|
|
// CHTTPRequest which the client must delete. throws an
|
2002-06-02 13:34:35 +00:00
|
|
|
// XHTTP if there was a parse error. throws an XIO exception
|
|
|
|
// if there was a read error. if maxSize is greater than
|
|
|
|
// zero and the request is larger than maxSize bytes then
|
|
|
|
// throws XHTTP(413).
|
|
|
|
static CHTTPRequest* readRequest(IInputStream*, UInt32 maxSize = 0);
|
2002-05-30 16:13:16 +00:00
|
|
|
|
|
|
|
// send an HTTP reply on the stream
|
|
|
|
static void reply(IOutputStream*, CHTTPReply&);
|
|
|
|
|
|
|
|
// 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
|
|
|
|
typedef std::map<CString, CString> CFormParts;
|
|
|
|
static bool parseFormData(const CHTTPRequest&,
|
|
|
|
CFormParts& parts);
|
|
|
|
|
|
|
|
private:
|
|
|
|
static CString readLine(IInputStream*, CString& tmpBuffer);
|
|
|
|
static CString readBlock(IInputStream*,
|
|
|
|
UInt32 numBytes, CString& tmpBuffer);
|
2002-06-02 13:34:35 +00:00
|
|
|
static CString readChunk(IInputStream*, CString& tmpBuffer,
|
|
|
|
UInt32* maxSize);
|
2002-05-30 16:13:16 +00:00
|
|
|
static void readHeaders(IInputStream*,
|
|
|
|
CHTTPRequest*, bool isFooter,
|
2002-06-02 13:34:35 +00:00
|
|
|
CString& tmpBuffer,
|
|
|
|
UInt32* maxSize);
|
2002-05-30 16:13:16 +00:00
|
|
|
|
|
|
|
static bool isValidToken(const CString&);
|
|
|
|
};
|
|
|
|
|
|
|
|
#endif
|