691 lines
21 KiB
C++
691 lines
21 KiB
C++
// Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
|
|
// Copyright (C) 2010 Winch Gate Property Limited
|
|
//
|
|
// This program is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU Affero General Public License as
|
|
// published by the Free Software Foundation, either version 3 of the
|
|
// License, or (at your option) any later version.
|
|
//
|
|
// This program 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 Affero General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU Affero General Public License
|
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
|
|
|
#include "stdpch.h"
|
|
|
|
// LibWWW
|
|
extern "C"
|
|
{
|
|
#include "WWWLib.h" /* Global Library Include file */
|
|
#include "WWWApp.h"
|
|
#include "WWWInit.h"
|
|
}
|
|
|
|
#include "interface_v3/group_html.h"
|
|
#include "game_share/ryzom_version.h"
|
|
|
|
#include "interface_v3/libwww_nel_stream.h"
|
|
|
|
using namespace NLMISC;
|
|
|
|
/// the cookie value for session identification (nel cookie)
|
|
std::string CurrentCookie;
|
|
|
|
/// store all cookies we receive and resent them depending of the domain
|
|
std::map<std::string, std::map<std::string, std::string> > HTTPCookies;
|
|
std::string HTTPCurrentDomain; // The current domain that will be used to get which cookies to send
|
|
|
|
// ***************************************************************************
|
|
|
|
// The HText structure for libwww
|
|
struct _HText
|
|
{
|
|
CGroupHTML *Parent;
|
|
};
|
|
|
|
// ***************************************************************************
|
|
|
|
// Some DTD table
|
|
|
|
// Here, modify the DTD table to change the HTML parser (add new tags for examples)
|
|
|
|
#undef HTML_ATTR
|
|
#define HTML_ATTR(a,b) { (char*) #b }
|
|
|
|
HTAttr a_attr[] =
|
|
{
|
|
HTML_ATTR(A,ACCESSKEY),
|
|
HTML_ATTR(A,CHARSET),
|
|
HTML_ATTR(A,CLASS),
|
|
HTML_ATTR(A,COORDS),
|
|
HTML_ATTR(A,DIR),
|
|
HTML_ATTR(A,HREF),
|
|
HTML_ATTR(A,HREFLANG),
|
|
HTML_ATTR(A,ID),
|
|
HTML_ATTR(A,NAME),
|
|
HTML_ATTR(A,REL),
|
|
HTML_ATTR(A,REV),
|
|
HTML_ATTR(A,SHAPE),
|
|
HTML_ATTR(A,STYLE),
|
|
HTML_ATTR(A,TABINDEX),
|
|
HTML_ATTR(A,TARGET),
|
|
HTML_ATTR(A,TYPE),
|
|
HTML_ATTR(A,TITLE),
|
|
HTML_ATTR(A,Z_ACTION_CATEGORY),
|
|
HTML_ATTR(A,Z_ACTION_PARAMS),
|
|
HTML_ATTR(A,Z_ACTION_SHORTCUT),
|
|
{ 0 }
|
|
};
|
|
|
|
HTAttr table_attr[] =
|
|
{
|
|
HTML_ATTR(TABLE,ALIGN),
|
|
HTML_ATTR(TABLE,BGCOLOR),
|
|
HTML_ATTR(TABLE,BORDER),
|
|
HTML_ATTR(TABLE,CELLPADDING),
|
|
HTML_ATTR(TABLE,CELLSPACING),
|
|
HTML_ATTR(TABLE,CLASS),
|
|
HTML_ATTR(TABLE,DIR),
|
|
HTML_ATTR(TABLE,FRAME),
|
|
HTML_ATTR(TABLE,ID),
|
|
HTML_ATTR(TABLE,L_MARGIN),
|
|
HTML_ATTR(TABLE,LANG),
|
|
HTML_ATTR(TABLE,NOWRAP),
|
|
HTML_ATTR(TABLE,RULES),
|
|
HTML_ATTR(TABLE,SUMMARY),
|
|
HTML_ATTR(TABLE,STYLE),
|
|
HTML_ATTR(TABLE,TITLE),
|
|
HTML_ATTR(TABLE,VALIGN),
|
|
HTML_ATTR(TABLE,WIDTH),
|
|
{ 0 }
|
|
};
|
|
|
|
HTAttr tr_attr[] =
|
|
{
|
|
HTML_ATTR(TR,ALIGN),
|
|
HTML_ATTR(TR,BGCOLOR),
|
|
HTML_ATTR(TR,L_MARGIN),
|
|
HTML_ATTR(TR,NOWRAP),
|
|
HTML_ATTR(TR,VALIGN),
|
|
{ 0 }
|
|
};
|
|
|
|
HTAttr td_attr[] =
|
|
{
|
|
HTML_ATTR(TD,ABBR),
|
|
HTML_ATTR(TD,ALIGN),
|
|
HTML_ATTR(TD,AXIS),
|
|
HTML_ATTR(TD,BGCOLOR),
|
|
HTML_ATTR(TD,CHAR),
|
|
HTML_ATTR(TD,CHAROFF),
|
|
HTML_ATTR(TD,CLASS),
|
|
HTML_ATTR(TD,COLSPAN),
|
|
HTML_ATTR(TD,DIR),
|
|
HTML_ATTR(TD,ID),
|
|
HTML_ATTR(TD,HEADERS),
|
|
HTML_ATTR(TD,HEIGHT),
|
|
HTML_ATTR(TD,L_MARGIN),
|
|
HTML_ATTR(TD,LANG),
|
|
HTML_ATTR(TD,NOWRAP),
|
|
HTML_ATTR(TD,ROWSPAN),
|
|
HTML_ATTR(TD,SCOPE),
|
|
HTML_ATTR(TD,STYLE),
|
|
HTML_ATTR(TD,TITLE),
|
|
HTML_ATTR(TD,VALIGN),
|
|
HTML_ATTR(TD,WIDTH),
|
|
{ 0 }
|
|
};
|
|
|
|
HTAttr img_attr[] =
|
|
{
|
|
HTML_ATTR(IMG,ALIGN),
|
|
HTML_ATTR(IMG,ALT),
|
|
HTML_ATTR(IMG,BORDER),
|
|
HTML_ATTR(IMG,CLASS),
|
|
HTML_ATTR(IMG,DIR),
|
|
HTML_ATTR(IMG,GLOBAL_COLOR),
|
|
HTML_ATTR(IMG,HEIGHT),
|
|
HTML_ATTR(IMG,HSPACE),
|
|
HTML_ATTR(IMG,ID),
|
|
HTML_ATTR(IMG,ISMAP),
|
|
HTML_ATTR(IMG,LANG),
|
|
HTML_ATTR(IMG,LONGDESC),
|
|
HTML_ATTR(IMG,SRC),
|
|
HTML_ATTR(IMG,STYLE),
|
|
HTML_ATTR(IMG,TITLE),
|
|
HTML_ATTR(IMG,USEMAP),
|
|
HTML_ATTR(IMG,VSPACE),
|
|
HTML_ATTR(IMG,WIDTH),
|
|
{ 0 }
|
|
};
|
|
|
|
HTAttr input_attr[] =
|
|
{
|
|
HTML_ATTR(INPUT,ACCEPT),
|
|
HTML_ATTR(INPUT,ACCESSKEY),
|
|
HTML_ATTR(INPUT,ALIGN),
|
|
HTML_ATTR(INPUT,ALT),
|
|
HTML_ATTR(INPUT,CHECKED),
|
|
HTML_ATTR(INPUT,CLASS),
|
|
HTML_ATTR(INPUT,DIR),
|
|
HTML_ATTR(INPUT,DISABLED),
|
|
HTML_ATTR(INPUT,GLOBAL_COLOR),
|
|
HTML_ATTR(INPUT,ID),
|
|
HTML_ATTR(INPUT,LANG),
|
|
HTML_ATTR(INPUT,MAXLENGTH),
|
|
HTML_ATTR(INPUT,NAME),
|
|
HTML_ATTR(INPUT,READONLY),
|
|
HTML_ATTR(INPUT,SIZE),
|
|
HTML_ATTR(INPUT,SRC),
|
|
HTML_ATTR(INPUT,STYLE),
|
|
HTML_ATTR(INPUT,TABINDEX),
|
|
HTML_ATTR(INPUT,TITLE),
|
|
HTML_ATTR(INPUT,TYPE),
|
|
HTML_ATTR(INPUT,USEMAP),
|
|
HTML_ATTR(INPUT,VALUE),
|
|
HTML_ATTR(INPUT,Z_BTN_TMPL),
|
|
HTML_ATTR(INPUT,Z_INPUT_TMPL),
|
|
HTML_ATTR(INPUT,Z_INPUT_WIDTH),
|
|
{ 0 }
|
|
};
|
|
|
|
HTAttr textarea_attr[] =
|
|
{
|
|
HTML_ATTR(TEXTAREA,CLASS),
|
|
HTML_ATTR(TEXTAREA,COLS),
|
|
HTML_ATTR(TEXTAREA,DIR),
|
|
HTML_ATTR(TEXTAREA,DISABLED),
|
|
HTML_ATTR(TEXTAREA,ID),
|
|
HTML_ATTR(TEXTAREA,LANG),
|
|
HTML_ATTR(TEXTAREA,NAME),
|
|
HTML_ATTR(TEXTAREA,READONLY),
|
|
HTML_ATTR(TEXTAREA,ROWS),
|
|
HTML_ATTR(TEXTAREA,STYLE),
|
|
HTML_ATTR(TEXTAREA,TABINDEX),
|
|
HTML_ATTR(TEXTAREA,TITLE),
|
|
HTML_ATTR(TEXTAREA,Z_INPUT_TMPL),
|
|
{ 0 }
|
|
};
|
|
|
|
|
|
HTAttr p_attr[] =
|
|
{
|
|
HTML_ATTR(P,QUICK_HELP_CONDITION),
|
|
HTML_ATTR(P,QUICK_HELP_EVENTS),
|
|
HTML_ATTR(P,QUICK_HELP_LINK),
|
|
{ 0 }
|
|
};
|
|
|
|
// ***************************************************************************
|
|
|
|
void _VerifyLibWWW(const char *function, bool ok, const char *file, int line)
|
|
{
|
|
if (!ok)
|
|
nlwarning("%s(%d) : LIBWWW %s returned a bad status", file, line, function);
|
|
}
|
|
#define VerifyLibWWW(a,b) _VerifyLibWWW(a,(b)!=FALSE,__FILE__,__LINE__)
|
|
|
|
// ***************************************************************************
|
|
|
|
int NelPrinter (const char * fmt, va_list pArgs)
|
|
{
|
|
nlinfo (fmt, pArgs);
|
|
return 0;
|
|
}
|
|
|
|
// ***************************************************************************
|
|
|
|
int NelTracer (const char * fmt, va_list pArgs)
|
|
{
|
|
nlwarning (fmt, pArgs);
|
|
return 0;
|
|
}
|
|
|
|
// ***************************************************************************
|
|
|
|
HText * TextNew (HTRequest * request,
|
|
HTParentAnchor * /* anchor */,
|
|
HTStream * /* output_stream */)
|
|
{
|
|
HText *text = new HText;
|
|
text->Parent = (CGroupHTML *) HTRequest_context(request);
|
|
return text;
|
|
}
|
|
|
|
// ***************************************************************************
|
|
|
|
BOOL TextDelete (HText * me)
|
|
{
|
|
delete me;
|
|
return YES;
|
|
}
|
|
|
|
// ***************************************************************************
|
|
|
|
void TextBuild (HText * me, HTextStatus status)
|
|
{
|
|
// Do the work in the class
|
|
if (status == HTEXT_BEGIN)
|
|
me->Parent->beginBuild ();
|
|
else if (status == HTEXT_END)
|
|
me->Parent->endBuild ();
|
|
}
|
|
|
|
// ***************************************************************************
|
|
|
|
void TextAdd (HText * me, const char * buf, int len)
|
|
{
|
|
// Do the work in the class
|
|
me->Parent->addText (buf, len);
|
|
}
|
|
|
|
// ***************************************************************************
|
|
|
|
void TextLink (HText * me,
|
|
int element_number,
|
|
int attribute_number,
|
|
HTChildAnchor * anchor,
|
|
const BOOL * present,
|
|
const char ** value)
|
|
{
|
|
// Do the work in the class
|
|
me->Parent->addLink (element_number, attribute_number, anchor, present, value);
|
|
}
|
|
|
|
// ***************************************************************************
|
|
|
|
// Read a width HTML parameter. "100" or "100%". Returns true if percent (0 ~ 1) else false
|
|
bool getPercentage (sint32 &width, float &percent, const char *str)
|
|
{
|
|
// Percent ?
|
|
const char *percentChar;
|
|
if ((percentChar = strchr (str, '%')) != NULL)
|
|
{
|
|
std::string toto = str;
|
|
toto = toto.substr (0, percentChar - str);
|
|
fromString(toto, percent);
|
|
percent /= 100.f;
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
fromString(str, width);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// ***************************************************************************
|
|
|
|
CRGBA getColor (const char *color)
|
|
{
|
|
if (strlen (color) != 7 && strlen (color) != 9 )
|
|
return CRGBA::White;
|
|
char tmp[3] = {0,0,0};
|
|
CRGBA dst;
|
|
int value;
|
|
tmp[0] = color[1];
|
|
tmp[1] = color[2];
|
|
sscanf (tmp, "%x", &value);
|
|
dst.R = uint8(value);
|
|
tmp[0] = color[3];
|
|
tmp[1] = color[4];
|
|
sscanf (tmp, "%x", &value);
|
|
dst.G = uint8(value);
|
|
tmp[0] = color[5];
|
|
tmp[1] = color[6];
|
|
sscanf (tmp, "%x", &value);
|
|
dst.B = uint8(value);
|
|
if (strlen (color) == 9)
|
|
{
|
|
tmp[0] = color[7];
|
|
tmp[1] = color[8];
|
|
sscanf (tmp, "%x", &value);
|
|
dst.A = uint8(value);
|
|
}
|
|
else
|
|
{
|
|
// extension to html ; try to parse an additional alpha
|
|
dst.A = 255;
|
|
}
|
|
return dst;
|
|
}
|
|
|
|
// ***************************************************************************
|
|
|
|
void TextBeginElement (HText *me, int element_number, const BOOL *present, const char **value)
|
|
{
|
|
// Do the work in the class
|
|
me->Parent->beginElement (element_number, present, value);
|
|
}
|
|
|
|
// ***************************************************************************
|
|
|
|
void TextEndElement (HText *me, int element_number)
|
|
{
|
|
// Do the work in the class
|
|
me->Parent->endElement (element_number);
|
|
}
|
|
|
|
// ***************************************************************************
|
|
void TextBeginUnparsedElement(HText *me, const char *buffer, int length)
|
|
{
|
|
me->Parent->beginUnparsedElement(buffer, length);
|
|
}
|
|
|
|
// ***************************************************************************
|
|
void TextEndUnparsedElement(HText *me, const char *buffer, int length)
|
|
{
|
|
me->Parent->endUnparsedElement(buffer, length);
|
|
}
|
|
|
|
// ***************************************************************************
|
|
void TextUnparsedEntity (HText * /* HText */, const char *buffer, int length)
|
|
{
|
|
std::string str(buffer, buffer+length);
|
|
nlinfo("Unparsed entity '%s'", str.c_str());
|
|
}
|
|
|
|
// ***************************************************************************
|
|
int requestTerminater (HTRequest * request, HTResponse * /* response */,
|
|
void * param, int /* status */)
|
|
{
|
|
/*
|
|
Yoyo and Boris: we had to make the request terminate by UID and not by pointer (param is an uid).
|
|
Because this method was called at mainLoop time, but for GroupHTML created/deleted at login time !!!
|
|
=> Memory Crash.
|
|
*/
|
|
|
|
// TestYoyo
|
|
//nlinfo("** requestTerminater(): uid%d", (uint32)param);
|
|
|
|
// the parameter is actually an uint32
|
|
if (param != 0)
|
|
{
|
|
CGroupHTML::TGroupHtmlByUIDMap::iterator it= CGroupHTML::_GroupHtmlByUID.find((uint32)(size_t)param);
|
|
if(it!=CGroupHTML::_GroupHtmlByUID.end())
|
|
{
|
|
// get the pointer. NB: the refptr should not be NULL
|
|
// since object removed from map when deleted
|
|
CGroupHTML *gh = it->second;
|
|
nlassert(gh);
|
|
|
|
// callback the browser
|
|
gh->requestTerminated(request);
|
|
}
|
|
}
|
|
return HT_OK;
|
|
}
|
|
|
|
|
|
// callback called when receiving a cookie
|
|
BOOL receiveCookie (HTRequest * /* request */, HTCookie * cookie, void * /* param */)
|
|
{
|
|
if (strcmp(HTCookie_name(cookie), "ryzomId") == 0)
|
|
{
|
|
// we receive the ryzom id cookie, store it
|
|
CurrentCookie = HTCookie_value(cookie);
|
|
}
|
|
else
|
|
{
|
|
// store the id/value cookie
|
|
HTTPCookies[HTTPCurrentDomain][HTCookie_name(cookie)] = HTCookie_value(cookie);
|
|
// nlwarning("get cookie for domain %s %s=%s", HTTPCurrentDomain.c_str(), HTCookie_name(cookie), HTCookie_value(cookie));
|
|
}
|
|
|
|
return YES;
|
|
}
|
|
|
|
// callback called to add cookie to a request before sending it to the server
|
|
HTAssocList *sendCookie (HTRequest * /* request */, void * /* param */)
|
|
{
|
|
HTAssocList * alist = 0;
|
|
if (!CurrentCookie.empty())
|
|
{
|
|
if(alist == 0) alist = HTAssocList_new(); /* Is deleted by the cookie module */
|
|
HTAssocList_addObject(alist, "ryzomId", CurrentCookie.c_str());
|
|
}
|
|
|
|
if(!HTTPCookies[HTTPCurrentDomain].empty())
|
|
{
|
|
if(alist == 0) alist = HTAssocList_new();
|
|
for(std::map<std::string, std::string>::iterator it = HTTPCookies[HTTPCurrentDomain].begin(); it != HTTPCookies[HTTPCurrentDomain].end(); it++)
|
|
{
|
|
HTAssocList_addObject(alist, it->first.c_str(), it->second.c_str());
|
|
// nlwarning("set cookie for domain '%s' %s=%s", HTTPCurrentDomain.c_str(), it->first.c_str(), it->second.c_str());
|
|
}
|
|
}
|
|
return alist;
|
|
}
|
|
|
|
|
|
// ***************************************************************************
|
|
|
|
HTAnchor * TextFindAnchor (HText * /* me */, int /* index */)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
int HTMIME_location_custom (HTRequest * request, HTResponse * response, char * token, char * value)
|
|
{
|
|
char * location = HTStrip(value);
|
|
|
|
std::string finalLocation;
|
|
|
|
//nlinfo("redirect to '%s' '%s'", value, location);
|
|
|
|
// If not absolute URI (Error) then find the base
|
|
if (!HTURL_isAbsolute(location))
|
|
{
|
|
char * base = HTAnchor_address((HTAnchor *) HTRequest_anchor(request));
|
|
location = HTParse(location, base, PARSE_ALL);
|
|
//redirection = HTAnchor_findAddress(location);
|
|
finalLocation = location;
|
|
HT_FREE(base);
|
|
HT_FREE(location);
|
|
}
|
|
else
|
|
{
|
|
finalLocation = location;
|
|
}
|
|
//nlinfo("final location '%s'", finalLocation.c_str());
|
|
|
|
CGroupHTML *gh = (CGroupHTML *) HTRequest_context(request);
|
|
|
|
gh->setURL(finalLocation);
|
|
|
|
return HT_OK;
|
|
}
|
|
|
|
|
|
// ***************************************************************************
|
|
|
|
void setCurrentDomain(const std::string &url)
|
|
{
|
|
if(url.find("http://") == 0)
|
|
{
|
|
HTTPCurrentDomain = url.substr(7, url.find('/', 7)-7);
|
|
// nlinfo("****cd: %s", HTTPCurrentDomain.c_str());
|
|
}
|
|
else
|
|
{
|
|
HTTPCurrentDomain.clear();
|
|
// nlinfo("****cd: clear the domain");
|
|
}
|
|
}
|
|
|
|
|
|
void initLibWWW()
|
|
{
|
|
static bool initialized = false;
|
|
if (!initialized)
|
|
{
|
|
//HTProfile_newNoCacheClient("Ryzom", "1.1");
|
|
|
|
/* Need our own trace and print functions */
|
|
HTPrint_setCallback(NelPrinter);
|
|
HTTrace_setCallback(NelTracer);
|
|
|
|
/* Initiate libwww */
|
|
|
|
HTLib_setAppName("Ryzom");
|
|
HTLib_setAppVersion(RYZOM_VERSION);
|
|
|
|
/* Set up TCP as transport */
|
|
VerifyLibWWW("HTTransport_add", HTTransport_add("buffered_tcp", HT_TP_SINGLE, HTReader_new, HTBufferWriter_new));
|
|
VerifyLibWWW("HTTransport_add", HTTransport_add("local", HT_TP_SINGLE, HTNeLReader_new, HTWriter_new));
|
|
// VerifyLibWWW("HTTransport_add", HTTransport_add("local", HT_TP_SINGLE, HTANSIReader_new, HTWriter_new));
|
|
// VerifyLibWWW("HTTransport_add", HTTransport_add("local", HT_TP_SINGLE, HTReader_new, HTWriter_new));
|
|
|
|
/* Set up HTTP as protocol */
|
|
VerifyLibWWW("HTProtocol_add", HTProtocol_add("http", "buffered_tcp", 80, NO, HTLoadHTTP, NULL));
|
|
VerifyLibWWW("HTProtocol_add", HTProtocol_add("file", "local", 0, YES, HTLoadNeLFile, NULL));
|
|
//VerifyLibWWW("HTProtocol_add", HTProtocol_add("file", "local", 0, YES, HTLoadFile, NULL));
|
|
// HTProtocol_add("cache", "local", 0, NO, HTLoadCache, NULL);
|
|
|
|
HTBind_init();
|
|
// HTCacheInit(NULL, 20);
|
|
|
|
/* Setup up transfer coders */
|
|
HTFormat_addTransferCoding((char*)"chunked", HTChunkedEncoder, HTChunkedDecoder, 1.0);
|
|
|
|
/* Setup MIME stream converters */
|
|
HTFormat_addConversion("message/rfc822", "*/*", HTMIMEConvert, 1.0, 0.0, 0.0);
|
|
HTFormat_addConversion("message/x-rfc822-foot", "*/*", HTMIMEFooter, 1.0, 0.0, 0.0);
|
|
HTFormat_addConversion("message/x-rfc822-head", "*/*", HTMIMEHeader, 1.0, 0.0, 0.0);
|
|
HTFormat_addConversion("message/x-rfc822-cont", "*/*", HTMIMEContinue, 1.0, 0.0, 0.0);
|
|
HTFormat_addConversion("message/x-rfc822-partial","*/*", HTMIMEPartial, 1.0, 0.0, 0.0);
|
|
HTFormat_addConversion("multipart/*", "*/*", HTBoundary, 1.0, 0.0, 0.0);
|
|
|
|
/* Setup HTTP protocol stream */
|
|
HTFormat_addConversion("text/x-http", "*/*", HTTPStatus_new, 1.0, 0.0, 0.0);
|
|
|
|
/* Setup the HTML parser */
|
|
HTFormat_addConversion("text/html", "www/present", HTMLPresent, 1.0, 0.0, 0.0);
|
|
|
|
/* Setup black hole stream */
|
|
HTFormat_addConversion("*/*", "www/debug", HTBlackHoleConverter, 1.0, 0.0, 0.0);
|
|
HTFormat_addConversion("*/*", "www/present", HTBlackHoleConverter, 0.3, 0.0, 0.0);
|
|
|
|
/* Set max number of sockets we want open simultaneously */
|
|
HTNet_setMaxSocket(32);
|
|
|
|
/* Register our HTML parser callbacks */
|
|
VerifyLibWWW("HText_registerCDCallback", HText_registerCDCallback (TextNew, TextDelete));
|
|
VerifyLibWWW("HText_registerBuildCallback", HText_registerBuildCallback (TextBuild));
|
|
VerifyLibWWW("HText_registerTextCallback", HText_registerTextCallback(TextAdd));
|
|
VerifyLibWWW("HText_registerLinkCallback", HText_registerLinkCallback (TextLink));
|
|
VerifyLibWWW("HText_registerElementCallback", HText_registerElementCallback (TextBeginElement, TextEndElement));
|
|
VerifyLibWWW("HText_registerUnparsedElementCallback", HText_registerUnparsedElementCallback(TextBeginUnparsedElement, TextEndUnparsedElement));
|
|
VerifyLibWWW("HText_registerUnparsedEntityCallback ", HText_registerUnparsedEntityCallback (TextUnparsedEntity ));
|
|
|
|
|
|
/* Register the default set of MIME header parsers */
|
|
struct {
|
|
const char * string;
|
|
HTParserCallback * pHandler;
|
|
} fixedHandlers[] = {
|
|
{"accept", &HTMIME_accept},
|
|
{"accept-charset", &HTMIME_acceptCharset},
|
|
{"accept-encoding", &HTMIME_acceptEncoding},
|
|
{"accept-language", &HTMIME_acceptLanguage},
|
|
{"accept-ranges", &HTMIME_acceptRanges},
|
|
{"authorization", NULL},
|
|
{"cache-control", &HTMIME_cacheControl},
|
|
{"connection", &HTMIME_connection},
|
|
{"content-encoding", &HTMIME_contentEncoding},
|
|
{"content-length", &HTMIME_contentLength},
|
|
{"content-range", &HTMIME_contentRange},
|
|
{"content-transfer-encoding", &HTMIME_contentTransferEncoding},
|
|
{"content-type", &HTMIME_contentType},
|
|
{"digest-MessageDigest", &HTMIME_messageDigest},
|
|
{"keep-alive", &HTMIME_keepAlive},
|
|
{"link", &HTMIME_link},
|
|
{"location", &HTMIME_location_custom},
|
|
{"max-forwards", &HTMIME_maxForwards},
|
|
{"mime-version", NULL},
|
|
{"pragma", &HTMIME_pragma},
|
|
{"protocol", &HTMIME_protocol},
|
|
{"protocol-info", &HTMIME_protocolInfo},
|
|
{"protocol-request", &HTMIME_protocolRequest},
|
|
{"proxy-authenticate", &HTMIME_authenticate},
|
|
{"proxy-authorization", &HTMIME_proxyAuthorization},
|
|
{"public", &HTMIME_public},
|
|
{"range", &HTMIME_range},
|
|
{"referer", &HTMIME_referer},
|
|
{"retry-after", &HTMIME_retryAfter},
|
|
{"server", &HTMIME_server},
|
|
{"trailer", &HTMIME_trailer},
|
|
{"transfer-encoding", &HTMIME_transferEncoding},
|
|
{"upgrade", &HTMIME_upgrade},
|
|
{"user-agent", &HTMIME_userAgent},
|
|
{"vary", &HTMIME_vary},
|
|
{"via", &HTMIME_via},
|
|
{"warning", &HTMIME_warning},
|
|
{"www-authenticate", &HTMIME_authenticate},
|
|
{"authentication-info", &HTMIME_authenticationInfo},
|
|
{"proxy-authentication-info", &HTMIME_proxyAuthenticationInfo}
|
|
};
|
|
|
|
for (uint i = 0; i < sizeof(fixedHandlers)/sizeof(fixedHandlers[0]); i++)
|
|
HTHeader_addParser(fixedHandlers[i].string, NO, fixedHandlers[i].pHandler);
|
|
|
|
/* Set up default event loop */
|
|
HTEventInit();
|
|
|
|
/* Add our own request terminate handler */
|
|
HTNet_addAfter(requestTerminater, NULL, 0, HT_ALL, HT_FILTER_LAST);
|
|
|
|
/* Setup cookies */
|
|
HTCookie_init();
|
|
HTCookie_setCookieMode(HTCookieMode(HT_COOKIE_ACCEPT | HT_COOKIE_SEND));
|
|
HTCookie_setCallbacks(receiveCookie, NULL, sendCookie, NULL);
|
|
|
|
/* Start the first request */
|
|
|
|
/* Go into the event loop... */
|
|
// HTEventList_newLoop();
|
|
|
|
// App_delete(app);
|
|
|
|
HTBind_add("htm", "text/html", NULL, "8bit", NULL, 1.0); /* HTML */
|
|
HTBind_add("html", "text/html", NULL, "8bit", NULL, 1.0); /* HTML */
|
|
|
|
HTBind_caseSensitive(NO);
|
|
|
|
// Change the HTML DTD
|
|
SGML_dtd *HTML_DTD = HTML_dtd ();
|
|
HTML_DTD->tags[HTML_TABLE].attributes = table_attr;
|
|
HTML_DTD->tags[HTML_TABLE].number_of_attributes = sizeof(table_attr) / sizeof(HTAttr) - 1;
|
|
HTML_DTD->tags[HTML_TR].attributes = tr_attr;
|
|
HTML_DTD->tags[HTML_TR].number_of_attributes = sizeof(tr_attr) / sizeof(HTAttr) - 1;
|
|
HTML_DTD->tags[HTML_TD].attributes = td_attr;
|
|
HTML_DTD->tags[HTML_TD].number_of_attributes = sizeof(td_attr) / sizeof(HTAttr) - 1;
|
|
HTML_DTD->tags[HTML_IMG].attributes = img_attr;
|
|
HTML_DTD->tags[HTML_IMG].number_of_attributes = sizeof(img_attr) / sizeof(HTAttr) - 1;
|
|
HTML_DTD->tags[HTML_INPUT].attributes = input_attr;
|
|
HTML_DTD->tags[HTML_INPUT].number_of_attributes = sizeof(input_attr) / sizeof(HTAttr) - 1;
|
|
HTML_DTD->tags[HTML_TEXTAREA].attributes = textarea_attr;
|
|
HTML_DTD->tags[HTML_TEXTAREA].number_of_attributes = sizeof(textarea_attr) / sizeof(HTAttr) - 1;
|
|
HTML_DTD->tags[HTML_P].attributes = p_attr;
|
|
HTML_DTD->tags[HTML_P].number_of_attributes = sizeof(p_attr) / sizeof(HTAttr) - 1;
|
|
HTML_DTD->tags[HTML_A].attributes = a_attr;
|
|
HTML_DTD->tags[HTML_A].number_of_attributes = sizeof(a_attr) / sizeof(HTAttr) - 1;
|
|
//HTML_DTD->tags[HTML_I].attributes = a_attr;
|
|
HTML_DTD->tags[HTML_I].number_of_attributes = 0;
|
|
|
|
// Set a request timeout
|
|
// HTHost_setEventTimeout (30000);
|
|
// HTHost_setActiveTimeout (30000);
|
|
// HTHost_setPersistTimeout (30000);
|
|
|
|
// Initialized
|
|
initialized = true;
|
|
}
|
|
}
|
|
|
|
// ***************************************************************************
|