/**
* ======================== legal notice ======================
*
* File: HTTPRequest.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
#include
#include
cHTTPRequest::cHTTPRequest(const char *MessageBuf)
: method(INVALID)
, url(NULL)
{
ParseMessage(MessageBuf);
}
cHTTPRequest::cHTTPRequest(cHTTPRequest::HTTPRequestMethod Method, const char* Url)
: method(Method)
, url(Url)
{
}
cHTTPRequest::cHTTPRequest(const cHTTPResponse &res, const char *Url)
: method(cHTTPRequest::GET)
, url(Url)
{
SetAuthorization(new cAuthorization(*res.Authorization()));
Authorization()->SetUri(Url);
}
cHTTPRequest::~cHTTPRequest()
{
}
const char *requestMethod2String(cHTTPRequest::HTTPRequestMethod Method)
{
switch (Method) {
case cHTTPRequest::GET: return "GET";
case cHTTPRequest::POST: return "POST";
default: return "unknown/unsupported";
}
}
void cHTTPRequest::SetURL(const char *Url)
{
url.ParseURL(Url);
}
const char *cHTTPRequest::ClientHost(void ) const
{
return (const char *) Headers().get("Host");
}
const char *cHTTPRequest::UserAgent() const
{
return (const char *) Headers().get("User-Agent");
}
void cHTTPRequest::SetUser(const char *UserID, const char *Password)
{
char *uri = Url().ToString();
this->Authorization()->CalculateResponse(uri, UserID, Password);
free(uri);
}
static const char *fetchLine(char *Buf, int BufSize, const char *Source)
{
const char *end = strchr(Source, '\r');
int len = 0;
if (!end) end = strchr(Source, '\n');
if (!end) end = Source + strlen(Source);
len = end - Source;
if (len > BufSize) len = BufSize - 1;
strncpy(Buf, Source, len);
Buf[len] = 0;
end = Source + len;
return end;
}
void cHTTPRequest::ParseMessage(const char *RequestBuf)
{
char scratch[512];
const char *start = RequestBuf, *end = strchr(start, ' ');
const char *name;
char *value;
if (strncasecmp("GET", start, end - start)) SetMethod(GET);
else if (strncasecmp("POST", start, end - start)) SetMethod(POST);
start = end;
while (*start == ' ') ++start;
end = strchr(start, ' ');
// printf("request-URI %*.*s\n", (int)(end - start), (int)(end - start), start);
if ((end - start) >= (int)sizeof(scratch)) {
esyslog("URI exhausted buffer - abort request!");
return;
}
else {
strncpy(scratch, start, end - start);
scratch[end - start] = 0;
SetURL(scratch);
}
start = end;
while (*start == ' ') ++start;
end = strchr(start, '\r');
if (!end) end = strchr(start, '\n');
// printf("http-protocol %*.*s\n", (int)(end - start), (int)(end - start), start);
if (!strncmp("HTTP/1.1", start, end - start)) SetProtocol(HTTP_1_1);
else SetProtocol(HTTP_1_0);
for (start = end; start && *start; start = end) {
if (*start == '\r') ++start;
if (*start == '\n') ++start;
if (!*start) break;
end = fetchLine(scratch, sizeof(scratch), start);
// printf("a line from request (%03d) [%s]\n", strlen(scratch), scratch);
name = scratch;
value = strchr((char *)name, ':');
if (value) {
if (value) *value++ = 0;
if (*value == ' ') *value++ = 0;
SetHeader(name, value);
}
else {
// printf("possibly end of header ...\n");
continue;
}
// printf("\nresult - name [%s] => |>%s<|\n", name, value);
}
}
size_t cHTTPRequest::WriteFirstLine(char* Buffer, size_t BufSize)
{
size_t n = snprintf(Buffer, BufSize, "%s ", requestMethod2String(Method()));
int tmp = url.WriteBuf(Buffer + n, BufSize - n);
if (tmp > 0) n += tmp;
n += snprintf(Buffer + n, BufSize - n, " %s\n", ProtocolString());
return n;
}