#include "THttpCallArg.h"
#include <string.h>
#include "RZip.h"
ClassImp(THttpCallArg)
THttpCallArg::THttpCallArg() :
TObject(),
fTopName(),
fMethod(),
fPathName(),
fFileName(),
fUserName(),
fQuery(),
fPostData(0),
fPostDataLength(0),
fCond(),
fContentType(),
fRequestHeader(),
fHeader(),
fContent(),
fZipping(0),
fBinData(0),
fBinDataLength(0)
{
}
THttpCallArg::~THttpCallArg()
{
if (fPostData) {
free(fPostData);
fPostData = 0;
}
if (fBinData) {
free(fBinData);
fBinData = 0;
}
}
TString THttpCallArg::AccessHeader(TString& buf, const char* name, const char* value, Bool_t doing_set)
{
if (name==0) return TString();
Int_t curr = 0;
while (curr < buf.Length()-2) {
Int_t next = buf.Index("\r\n", curr);
if (next == kNPOS) break;
if (buf.Index(name, curr) != curr) {
curr = next + 2;
continue;
}
if ((value==0) && doing_set) {
buf.Remove(curr, next-curr+2);
return TString();
}
curr += strlen(name);
while ((curr < next) && (buf[curr] != ':')) curr++;
curr++;
while ((curr < next) && (buf[curr] == ' ')) curr++;
if (value==0) return buf(curr, next-curr);
buf.Remove(curr, next-curr);
buf.Insert(curr, value);
return TString(value);
}
if (value==0) return TString();
buf.Append(TString::Format("%s: %s\r\n", name, value));
return TString(value);
}
TString THttpCallArg::CountHeader(const TString& buf, Int_t number) const
{
Int_t curr(0), cnt(0);
while (curr < buf.Length()-2) {
Int_t next = buf.Index("\r\n", curr);
if (next == kNPOS) break;
if (cnt == number) {
Int_t separ = curr + 1;
while ((separ < next) && (buf[separ] != ':')) separ++;
return buf(curr, separ-curr);
}
curr = next + 2;
cnt++;
}
if (number == -1111) return TString::Format("%d", cnt);
return TString();
}
void THttpCallArg::SetPostData(void *data, Long_t length)
{
if (fPostData) free(fPostData);
if (data!=0) *(((char*) data) + length) = 0;
fPostData = data;
fPostDataLength = length;
}
void THttpCallArg::SetBinData(void *data, Long_t length)
{
if (fBinData) free(fBinData);
fBinData = data;
fBinDataLength = length;
fContent.Clear();
}
void THttpCallArg::SetPathAndFileName(const char *fullpath)
{
fPathName.Clear();
fFileName.Clear();
if (fullpath == 0) return;
const char *rslash = strrchr(fullpath, '/');
if (rslash == 0) {
fFileName = fullpath;
} else {
while ((fullpath != rslash) && (*fullpath == '/')) fullpath++;
fPathName.Append(fullpath, rslash - fullpath);
if (fPathName == "/") fPathName.Clear();
fFileName = rslash + 1;
}
}
TString THttpCallArg::GetHeader(const char* name)
{
if ((name == 0) || (*name == 0)) return TString();
if (strcmp(name,"Content-Type") == 0) return fContentType;
if (strcmp(name,"Content-Length") == 0) return TString::Format("%ld", GetContentLength());
return AccessHeader(fHeader, name);
}
void THttpCallArg::AddHeader(const char *name, const char *value)
{
if ((name == 0) || (*name == 0) || (strcmp(name,"Content-Length") == 0)) return;
if (strcmp(name,"Content-Type") == 0)
SetContentType(value);
else
AccessHeader(fHeader, name, value, kTRUE);
}
void THttpCallArg::FillHttpHeader(TString &hdr, const char *kind)
{
if (kind == 0) kind = "HTTP/1.1";
if ((fContentType.Length() == 0) || Is404()) {
hdr.Form("%s 404 Not Found\r\n"
"Content-Length: 0\r\n"
"Connection: close\r\n\r\n", kind);
} else {
hdr.Form("%s 200 OK\r\n"
"Content-Type: %s\r\n"
"Connection: keep-alive\r\n"
"Content-Length: %ld\r\n"
"%s\r\n",
kind,
GetContentType(),
GetContentLength(),
fHeader.Data());
}
}
Bool_t THttpCallArg::CompressWithGzip()
{
char *objbuf = (char *) GetContent();
Long_t objlen = GetContentLength();
unsigned long objcrc = R__crc32(0, NULL, 0);
objcrc = R__crc32(objcrc, (const unsigned char *) objbuf, objlen);
Int_t buflen = 10 + objlen + 8;
if (buflen < 512) buflen = 512;
void *buffer = malloc(buflen);
char *bufcur = (char *) buffer;
*bufcur++ = 0x1f;
*bufcur++ = 0x8b;
*bufcur++ = 0x08;
*bufcur++ = 0x00;
*bufcur++ = 0;
*bufcur++ = 0;
*bufcur++ = 0;
*bufcur++ = 0;
*bufcur++ = 0;
*bufcur++ = 3;
char dummy[8];
memcpy(dummy, bufcur - 6, 6);
unsigned long ziplen = R__memcompress(bufcur - 6, objlen + 6, objbuf, objlen);
memcpy(bufcur - 6, dummy, 6);
bufcur += (ziplen - 6);
*bufcur++ = objcrc & 0xff;
*bufcur++ = (objcrc >> 8) & 0xff;
*bufcur++ = (objcrc >> 16) & 0xff;
*bufcur++ = (objcrc >> 24) & 0xff;
*bufcur++ = objlen & 0xff;
*bufcur++ = (objlen >> 8) & 0xff;
*bufcur++ = (objlen >> 16) & 0xff;
*bufcur++ = (objlen >> 24) & 0xff;
SetBinData(buffer, bufcur - (char *) buffer);
SetEncoding("gzip");
return kTRUE;
}