/**
* ======================== legal notice ======================
*
* File: HTTPMessage.cc
* Created: 3. Juli 2012, 17
* Author: Geronimo
* Project: libnetworking: classes for tcp/ip sockets and http-protocol handling
*
* CMP - compound media player
*
* is a client/server mediaplayer intended to play any media from any workstation
* without the need to export or mount shares. cmps is an easy to use backend
* with a (ready to use) HTML-interface. Additionally the backend supports
* authentication via HTTP-digest authorization.
* cmpc is a client with vdr-like osd-menues.
*
* Copyright (c) 2012 Reinhard Mantey, some rights reserved!
* published under Creative Commons by-sa
* For details see http://creativecommons.org/licenses/by-sa/3.0/
*
* The cmp project's homepage is at http://projects.vdr-developer.org/projects/cmp
*
* --------------------------------------------------------------
*/
#include
#include
#include
#include
#include
static void freeHeaderCallback(void *elem)
{
free(elem);
}
cHTTPMessage::cHTTPMessage(HTTPProtocol Proto)
: protocol(Proto)
, timeStamp(0)
, header(freeHeaderCallback)
, auth(NULL)
, contentSize(0)
, contentType(NULL)
{
}
cHTTPMessage::~cHTTPMessage()
{
if (auth) delete auth;
FREE(contentType);
}
char *cHTTPMessage::FormatTime(time_t timeStamp)
{
struct tm *t = gmtime(&timeStamp);
char buf[128];
strftime(buf, sizeof(buf), "%a, %d %b %Y %H:%M:%S GMT", t);
return strdup(buf);
}
void cHTTPMessage::SetHeader(const char *Name, const char *Value)
{
header.put(Name, Value ? strdup(Value) : NULL);
}
const char *cHTTPMessage::GetHeader(const char* Name) const
{
return (const char *) header.get(Name);
}
size_t cHTTPMessage::WritePrefix(char *Buffer, size_t BufSize)
///< writes message prefix to existing buffer. Prefix is the message without
///< the content body, so internal and external content will be processed
///< separately.
///< IMPORTANT: content size and content type has to be set before this call!
///< or this information needs to be added by custom call.
{
cManagedMap::const_iterator it = Headers().begin();
size_t n = WriteFirstLine(Buffer, BufSize);
strcpy(Buffer + n, "Date: ");
n += 6;
n += WriteTime(Buffer + n, BufSize - n);
while (it != Headers().end()) {
n += snprintf(Buffer + n, BufSize - n, "%s: %s\r\n", it->first.c_str(), (const char *) it->second);
++it;
}
if (auth) n += auth->Write(Buffer + n, BufSize - n);
if (ContentSize() > 0) {
n += snprintf(Buffer + n, BufSize - n, "Content-Type: %s\r\n", ContentType());
n += snprintf(Buffer + n, BufSize - n, "Content-Length: %ld\r\n", ContentSize());
if (n < BufSize - 3) {
Buffer[n++] = '\n'; // this is the separator between header and content!
Buffer[n] = 0;
}
}
return n;
}
int cHTTPMessage::WriteTime(char *Buffer, size_t BufSize)
{
if (!timeStamp) timeStamp = time(NULL);
struct tm *t = gmtime(&timeStamp);
return strftime(Buffer, BufSize, "%a, %d %b %Y %H:%M:%S GMT\r\n", t);
}
void cHTTPMessage::Reset()
{
header.clear();
contentSize = 0;
}
size_t cHTTPMessage::ContentSize() const
{
return contentSize;
}
void cHTTPMessage::SetContentType(const char* ContentType)
{
FREE(contentType);
contentType = ContentType ? strdup(ContentType) : NULL;
}
void cHTTPMessage::SetAuthorization(cAuthorization* Authorization)
{
if (auth) {
delete auth;
auth = NULL;
}
auth = Authorization;
}
const char *cHTTPMessage::ProtocolString(void) {
switch (protocol) {
case HTTP_1_0: return "HTTP/1.0";
case HTTP_1_1: return "HTTP/1.1";
default: return "Unknown/Unsupported";
}
}
void cHTTPMessage::Dump(void )
{
cManagedMap::const_iterator it = Headers().begin();
char buf[1024];
WriteFirstLine(buf, sizeof(buf));
printf("=========== Dump HTTP message ==============\n");
printf("Protocol: %s\n", ProtocolString());
printf("first line: %s\n", buf);
printf("header entries:\n");
while (it != Headers().end()) {
printf("\t[%s] ==> >|%s|<\n", it->first.c_str(), (const char *) it->second);
++it;
}
if (auth) auth->Dump();
if (ContentSize()) {
printf("---------- content (%ld Bytes of type %s) -------------\n"
, ContentSize(), ContentType());
}
else printf(">>> NO Content!\n");
printf("========== End Dump HTTP message ===========\n");
}