123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427 |
- /*##############################################################################
- HPCC SYSTEMS software Copyright (C) 2012 HPCC Systems.
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
- http://www.apache.org/licenses/LICENSE-2.0
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- ############################################################################## */
- #pragma warning(disable : 4786)
- #ifdef WIN32
- #ifdef ESPHTTP_EXPORTS
- #define esp_http_decl __declspec(dllexport)
- #endif
- #endif
- //Jlib
- #include "jliball.hpp"
- //ESP Binidings
- #include "http/platform/httptransport.ipp"
- #include "bindutil.hpp"
- IEspHttpException* createEspHttpException(int code, const char *_msg, const char* _httpstatus)
- {
- return new CEspHttpException(code, _msg, _httpstatus);
- }
- bool httpContentFromFile(const char *filepath, StringBuffer &mimetype, MemoryBuffer &fileContents, bool &checkModifiedTime, StringBuffer &lastModified, StringBuffer &etag)
- {
- StringBuffer strfile(filepath);
- if (!checkFileExists(strfile.str()))
- if (!checkFileExists(strfile.toUpperCase().str()))
- if (!checkFileExists(strfile.toLowerCase().str()))
- return false;
- Owned<IFile> file = createIFile(strfile.str());
- if (file && file->isFile())
- {
- if (checkModifiedTime)
- {
- CDateTime createTime, accessedTime, modifiedTime;
- file->getTime( &createTime, &modifiedTime, &accessedTime);
- if (etag.length() || !lastModified.length())
- {
- StringBuffer etagSource, etagForThisFile;
- modifiedTime.getString(lastModified.clear());
- etagSource.appendf("%s+%s", filepath, lastModified.str());
- etagForThisFile.append(hashc((unsigned char *)etagSource.str(), etagSource.length(), 0));
- if ( !streq(etagForThisFile.str(), etag.str()))
- etag.set(etagForThisFile);
- else
- {
- checkModifiedTime = false;
- return true;
- }
- }
- else
- {
- StringBuffer lastModifiedForThisFile;
- modifiedTime.getString(lastModifiedForThisFile);
- if ( !streq(lastModifiedForThisFile.str(), lastModified.str()))
- lastModified.set(lastModifiedForThisFile);
- else
- {
- checkModifiedTime = false;
- return true;
- }
- }
- }
- Owned<IFileIO> io = file->open(IFOread);
- if (io)
- {
- size32_t filesize = (size32_t)io->size();
- io->read(0, filesize, fileContents.reserveTruncate(filesize));
- mimetype.clear();
- const char *ext = strrchr(filepath, '.');
- if (ext)
- {
- ext++;
- if (!stricmp(ext, "html") || !stricmp(ext, "htm"))
- mimetype.append("text/html");
- else if (!stricmp(ext, "js"))
- mimetype.append("text/javascript");
- else if (!stricmp(ext, "jpeg") || !stricmp(ext, "jpg"))
- mimetype.append("image/gif");
- else if (!stricmp(ext, "gif"))
- mimetype.append("image/gif");
- else if (!stricmp(ext, "png"))
- mimetype.append("image/png");
- else if (!stricmp(ext, "xml") || !stricmp(ext, "xsl") || !stricmp(ext, "xslt"))
- mimetype.append("application/xml");
- else if (!stricmp(ext, "txt") || !stricmp(ext, "text"))
- mimetype.append("text/plain");
- else if (!stricmp(ext, "zip"))
- mimetype.append("application/zip");
- else if (!stricmp(ext, "pdf"))
- mimetype.append("application/pdf");
- else if (!stricmp(ext, "pdf"))
- mimetype.append("application/pdf");
- else if (!stricmp(ext, "xpi"))
- mimetype.append("application/x-xpinstall");
- else if (!stricmp(ext, "exe") || !stricmp(ext, "class"))
- mimetype.append("application/octet-stream");
- else if (!stricmp(ext, "css"))
- mimetype.append("text/css");
- else if (!stricmp(ext, "svg"))
- mimetype.append("image/svg+xml");
- }
-
- if (!mimetype.length())
- mimetype.append("application/octet-stream");
- return true;
- }
- }
-
- return false;
- }
- bool xmlContentFromFile(const char *filepath, const char *stylesheet, StringBuffer &fileContents)
- {
- StringBuffer strfile(filepath);
- if (!checkFileExists(strfile.str()))
- if (!checkFileExists(strfile.toUpperCase().str()))
- if (!checkFileExists(strfile.toLowerCase().str()))
- return false;
- fileContents.loadFile(strfile.str());
- if (stylesheet && *stylesheet)
- {
- StringBuffer stylesheetLine;
- stylesheetLine.appendf("<?xml-stylesheet type=\"text/xsl\" href=\"%s\"?>\n", stylesheet);
- unsigned fileSize = fileContents.length();
- const char* ptr0 = fileContents.str();
- char* ptr = (char*) ptr0;
- while (*ptr)
- {
- if((ptr[0] == '<') && (ptr[1] != '!'))
- {
- if (ptr[1] != '?')
- {
- fileContents.insert(ptr - ptr0, stylesheetLine);
- break;
- }
- else
- {
- if ((strncmp(ptr, "<?xml-stylesheet ", 17)==0) || (strncmp(ptr, "<?xml-stylesheet?", 17)==0))
- {//Found the line to be replaced
- char* ptr1 = ptr + 17;
- while (*ptr1)
- {
- if (ptr1[0] == '>')
- {
- if (ptr1[1] != '\n')
- fileContents.remove(ptr - ptr0, ptr1 - ptr + 1);
- else
- fileContents.remove(ptr - ptr0, ptr1 - ptr + 2);
- fileContents.insert(ptr - ptr0, stylesheetLine);
- break;
- }
- ptr1++;
- }
- break;
- }
- }
- }
- ptr++;
- }
- }
- return true;
- }
- enum SOAPTag
- {
- NONE = 0,
- ENVELOPE = 1,
- HEADER = 2,
- SECURITY = 3,
- USERNAMETOKEN = 4,
- PASSWORD = 5,
- BODY = 6
- };
- class SOAPMessageLog : public CInterface, implements IPTreeNotifyEvent
- {
- public:
- IMPLEMENT_IINTERFACE;
- SOAPMessageLog() : m_readNext(true), m_foundPassword(false), m_lastTagFound(NONE), m_pPassword(NULL), m_pStart(NULL)
- {
- m_messageForLog.clear();
- m_skipTag.clear();
- };
- void logMessage(const char* message, const char* prefix)
- {
- if (!message || !*message)
- return;
- m_message = message;
- m_pStart = (char*) message;
- Owned<IPullPTreeReader> reader = createPullXMLStringReader(m_message, *this, ptr_ignoreNameSpaces);
- while(m_readNext && reader->next())
- {
- if (m_foundPassword)
- {
- m_pPassword = (char*) m_message + reader->queryOffset();
- m_foundPassword = false; //for another password
- }
- }
- if ((m_pStart == message) || (m_messageForLog.length() < 1))
- logNow(message, prefix);
- else
- {
- m_messageForLog.append(m_pStart);
- logNow(m_messageForLog.str(), prefix);
- }
- return;
- }
- virtual void beginNode(const char *tag, offset_t startOffset)
- {
- if (m_skipTag.length() > 0)
- return;
- if (strieq(tag, "Body"))
- {//no more password
- m_readNext = false;
- return;
- }
- switch (m_lastTagFound)
- {
- case NONE:
- if (!strieq(tag, "Envelope"))
- m_readNext = false;
- else
- m_lastTagFound = ENVELOPE;
- break;
- case ENVELOPE:
- if (!strieq(tag, "Header"))
- m_skipTag.append(tag);
- else
- m_lastTagFound = HEADER;
- break;
- case HEADER:
- if (!strieq(tag, "Security"))
- m_skipTag.append(tag);
- else
- m_lastTagFound = SECURITY;
- break;
- case SECURITY:
- if (!strieq(tag, "UsernameToken"))
- m_skipTag.append(tag);
- else
- m_lastTagFound = USERNAMETOKEN;
- break;
- case USERNAMETOKEN:
- if (!strieq(tag, "Password"))
- m_skipTag.append(tag);
- else
- m_lastTagFound = PASSWORD;
- break;
- default:
- m_skipTag.append(tag);
- break;
- }
- }
- virtual void endNode(const char *tag, unsigned length, const void *value, bool binary, offset_t endOffset)
- {
- if (m_skipTag.length() > 0)
- {
- if (strieq(tag, m_skipTag.str()))
- m_skipTag.clear();
- return;
- }
- switch (m_lastTagFound)
- {
- case SECURITY:
- if (strieq(tag, "Security"))
- m_readNext = false;
- break;
- case USERNAMETOKEN:
- if (strieq(tag, "UsernameToken"))
- m_lastTagFound = SECURITY;
- break;
- case PASSWORD:
- if (!strieq(tag, "Password") || !m_pPassword || !m_pStart)
- {//should not happen
- m_readNext = false;
- return;
- }
- m_messageForLog.append(m_pStart, 0, m_pPassword - m_pStart);
- m_messageForLog.append("(hidden)");
- m_pStart = m_pPassword + length; //remember the rest of message
- //Go back to SuerNameToken node
- m_lastTagFound = USERNAMETOKEN;
- break;
- }
- return;
- }
- virtual void beginNodeContent(const char *tag)
- {
- if (m_skipTag.length() > 0)
- return;
- if (m_lastTagFound == PASSWORD)
- m_foundPassword = true;
- return;
- }
- virtual void newAttribute(const char *name, const char *value)
- {
- return;
- }
- private:
- void logNow(const char* message, const char* prefix)
- {
- if (prefix && *prefix)
- DBGLOG("%s%s", prefix, message);
- else
- DBGLOG("%s", message);
- return;
- }
- private:
- StringBuffer m_messageForLog;
- StringBuffer m_skipTag;
- SOAPTag m_lastTagFound;
- const char *m_message;
- char *m_pStart;
- char *m_pPassword;
- bool m_foundPassword;
- bool m_readNext;
- };
- /***************************************************************************
- CHttpMessage Implementation
- This class implements common functions shared by both CHttpRequest
- and CHttpResponse
- ****************************************************************************/
- CHttpMessage::CHttpMessage(ISocket& socket) : m_socket(socket)
- {
- m_bufferedsocket.setown(createBufferedSocket(&socket));
- m_content_length = -1;
- m_content_length64 = -1;
- m_port = 80;
- m_paramCount = 0;
- m_attachCount = 0;
- m_supportClientXslt=-1;
- m_isForm = false;
- };
- CHttpMessage::~CHttpMessage()
- {
- try
- {
- m_bufferedsocket.clear();
- m_context.clear();
- m_queryparams.clear();
- m_content_stream.clear();
- }
- catch(...)
- {
- ERRLOG("In CHttpMessage::~CHttpMessage() -- Unknown exception.");
- }
- };
- int CHttpMessage::parseOneHeader(char* oneline)
- {
- if(!oneline)
- return -1;
- char* name = oneline;
- while(*name == ' ')
- name++;
- char* end = name;
- while(*end != '\0' && *end != ':')
- end++;
- char* value;
- if (*end == ':')
- {
- *end = '\0';
- value = end + 1;
- }
- else
- value = end;
- while(*value == ' ')
- value++;
-
- if(!stricmp(name, "Content-Type"))
- {
- m_content_type.set(value);
- }
- else if(!stricmp(name, "Content-Length"))
- {
- if(value != NULL)
- {
- m_content_length = atoi(value);
- m_content_length64 = atoi64_l(value,strlen(value));
- }
- }
- else if(!stricmp(name, "Host"))
- {
- if(value != NULL)
- {
- char* colon = strchr(value, ':');
- if(colon != NULL)
- {
- *colon = '\0';
- char* port = colon + 1;
- if(port != NULL)
- {
- m_port = atoi(port);
- }
- }
- m_host.set(value);
- }
- }
- else if(!stricmp(name, "Set-Cookie") || !stricmp(name, "Cookie"))
- {
- parseCookieHeader(value);
- }
- else
- {
- addHeader(name, value); //Insert into headers hashtable
- }
- return 0;
- }
- bool CHttpMessage::supportClientXslt()
- {
- if (m_supportClientXslt==-1)
- {
- bool ie6=false;
- bool moz5=false;
- bool opera=false;
- bool ff=false;
- StringBuffer uastr;
- getHeader("User-Agent", uastr);
-
- char *uagent=strdup(uastr.str());
- char *saveptr;
- char *token = strtok_r(uagent, "();", &saveptr);
- while(token)
- {
- while (*token==' ') token++;
- if (!strnicmp(token, "msie", 4))
- ie6=(token[5]>='6');
- else if (!strnicmp(token, "mozilla", 7))
- moz5=(token[8]>='5');
- else if (!strnicmp(token, "opera", 5))
- opera=true;
- else if (!strnicmp(token, "firefox", 7))
- ff=true;
- token = strtok_r( NULL, "();" , &saveptr);
- }
- free(uagent);
- m_supportClientXslt=(ff || moz5 || (ie6 && !opera)) ? 1 : 0;
- }
- return m_supportClientXslt==1;
- }
- void CHttpMessage::addParameter(const char* paramname, const char *value)
- {
- if (!m_queryparams)
- m_queryparams.setown(createProperties(false));
- if (strcmp(paramname,"form")==0)
- m_isForm = true;
- if (!m_isForm)
- {
- // remove the leading '.'
- if (*paramname=='.')
- paramname++;
- }
- m_queryparams->setProp(paramname, value);
- m_paramCount++;
- }
- StringBuffer& CHttpMessage::getParameter(const char* paramname, StringBuffer& paramval)
- {
- if (m_queryparams)
- {
- const char *value = m_queryparams->queryProp(paramname);
- if (value)
- paramval.append(value);
- }
- return paramval;
- }
- void CHttpMessage::addAttachment(const char* name, StringBuffer& value)
- {
- if(name != NULL)
- {
- m_attachments.setValue(name, value);
- m_attachCount++;
- }
- }
- StringBuffer& CHttpMessage::getAttachment(const char* name, StringBuffer& attachment)
- {
- StringBuffer *value = m_attachments.getValue(name);
- if (value)
- {
- attachment.append(value->length(), value->str());
- }
- return attachment;
- }
- StringBuffer& CHttpMessage::getParamStr(StringBuffer& ret)
- {
- return ret.append(m_paramstr);
- }
- IProperties *CHttpMessage::queryParameters()
- {
- if (!m_queryparams)
- m_queryparams.setown(createProperties(false));
- return m_queryparams.get();
- }
- IProperties *CHttpMessage::getParameters()
- {
- if (!m_queryparams)
- m_queryparams.setown(createProperties(false));
- return m_queryparams.getLink();
- }
- int CHttpMessage::processHeaders(IMultiException *me)
- {
- return 0;
- }
- int CHttpMessage::readContent()
- {
- char buf[1024 + 1];
- int buflen = 1024;
- if(m_content_length > 0)
- {
- int totallen = m_content_length;
- if(buflen > totallen)
- buflen = totallen;
- int readlen = 0;
- for(;;)
- {
- readlen = m_bufferedsocket->read(buf, buflen);
- if(readlen < 0)
- {
- DBGLOG(">> Socket timed out because of incorrect Content-Length passed in from the other side");
- break;
- }
- if(readlen == 0)
- break;
- buf[readlen] = 0;
- m_content.append(readlen, buf);
- totallen -= readlen;
- if(totallen <= 0)
- break;
- if(buflen > totallen)
- buflen = totallen;
- }
-
- return 0;
- }
- return 0;
- }
- int CHttpMessage::readContentTillSocketClosed()
- {
- const int buflen = 1024;
- char buf[buflen + 1];
- StringBuffer headerValue;
- getHeader("Transfer-Encoding", headerValue);
- if (!stricmp(headerValue.str(), "chunked"))//Transfer-Encoding: chunked
- {
- for(;;)
- {
- int readlen = m_bufferedsocket->readline(buf, buflen, NULL);
- if(readlen <= 0)
- break;
- buf[readlen] = 0;
- int chunkSize;
- sscanf(buf, "%x", &chunkSize);
- if (chunkSize<=0)
- break;
- while (chunkSize > 0)
- {
- const int len = min(chunkSize, buflen);
- readlen = m_bufferedsocket->read(buf, len);
- if(readlen <= 0)
- break;
- chunkSize -= readlen;
- m_content.append(readlen, buf);
- }
- if (m_bufferedsocket->read(buf, 2) <= 0)//CR/LF
- break;
- }
- }
- else
- {
- for(;;)
- {
- int readlen = m_bufferedsocket->read(buf, buflen);
- if(readlen <= 0)
- break;
- buf[readlen] = 0;
- m_content.append(readlen, buf);
- }
- }
- return 0;
- }
- int CHttpMessage::receive(bool alwaysReadContent, IMultiException *me)
- {
- if (processHeaders(me)==-1)
- return -1;
- if (getEspLogLevel()>LogNormal)
- DBGLOG("Headers processed! content_length = %d", m_content_length);
-
- if (isUpload())
- return 0;
- m_context->addTraceSummaryValue("contLen", m_content_length);
- if(m_content_length > 0)
- {
- readContent();
- if (getEspLogLevel()>LogNormal)
- DBGLOG("length of content read = %d", m_content.length());
- }
- else if (alwaysReadContent && m_content_length == -1)
- {
- //HTTP protocol does not require a content length: read until socket closed
- readContentTillSocketClosed();
- if (getEspLogLevel()>LogNormal)
- DBGLOG("length of content read = %d", m_content.length());
- }
- if (getEspLogRequests() || getEspLogLevel()>LogNormal)
- logMessage(LOGCONTENT, "HTTP content received:\n");
- return 0;
- }
- StringBuffer& CHttpMessage::getContent(StringBuffer& content)
- {
- content.append(m_content.length(), m_content.str());
- return content;
- }
- void CHttpMessage::setContent(const char* content)
- {
- m_content.clear();
- m_content.append(content);
- m_content_length = strlen(content);
- }
- void CHttpMessage::setContent(unsigned len, const char* content)
- {
- m_content.clear();
- m_content.append(len, content);
- m_content_length = len;
- }
- void CHttpMessage::setownContent(char* content)
- {
- size32_t len=strlen(content);
- m_content.setBuffer(len+1, content, len);
- m_content_length = len;
- }
- void CHttpMessage::setownContent(unsigned len, char* content)
- {
- m_content.setBuffer(len+1, content, len);
- m_content_length = len;
- }
- void CHttpMessage::setContent(IFileIOStream* stream)
- {
- if(stream != NULL)
- {
- m_content.clear();
- m_content_length = (int)stream->size();
- m_content_length64 = stream->size();
- m_content_stream.setown(stream);
- }
- }
- /*
- void CHttpMessage::appendContent(const char* content)
- {
- m_content.append(content);
- m_content_length += strlen(content);
- }
- */
- StringBuffer& CHttpMessage::getContentType(StringBuffer& contenttype)
- {
- contenttype.append(m_content_type);
- return contenttype;
- }
- void CHttpMessage::setContentType(const char* contenttype)
- {
- m_content_type.set(contenttype);
- }
- void CHttpMessage::setVersion(const char* version)
- {
- m_version.set(version);
- }
- int CHttpMessage::parseFirstLine(char* oneline)
- {
- return 0;
- }
- void CHttpMessage::parseCookieHeader(char* cookiestr)
- {
- }
- StringBuffer& CHttpMessage::constructHeaderBuffer(StringBuffer& headerbuf, bool inclLen)
- {
- return headerbuf;
- }
- void CHttpMessage::logMessage(const char* message, const char* prefix, const char* find, const char* replace)
- {
- if (!message || !*message)
- return;
- if (!find || !*find || !replace || !*replace)
- {
- if (prefix && *prefix)
- DBGLOG("%s%s", prefix, message);
- else
- DBGLOG("%s", message);
- return;
- }
- RegExpr auth(find, true);
- StringBuffer messageToLog = message;
- if (auth.find(messageToLog.str()))
- auth.replace(replace, messageToLog.length() + strlen(replace) - strlen(find));
- if (prefix && *prefix)
- DBGLOG("%s%s", prefix, messageToLog.str());
- else
- DBGLOG("%s", messageToLog.str());
- return;
- }
- void CHttpMessage::logSOAPMessage(const char* message, const char* prefix)
- {
- SOAPMessageLog messageLog;
- messageLog.logMessage(message, prefix);
- return;
- }
- void CHttpMessage::logMessage(MessageLogFlag messageLogFlag, const char *prefix)
- {
- try
- {
- if (((messageLogFlag == LOGHEADERS) || (messageLogFlag == LOGALL)) && (m_header.length() > 0))
- logMessage(m_header.str(), prefix, "Authorization:[~\r\n]*", "Authorization: (hidden)");
- if (((messageLogFlag == LOGCONTENT) || (messageLogFlag == LOGALL)) && (m_content.length() > 0))
- {//log content
- if ((m_header.length() > 0) && (startsWith(m_header.str(), "POST /ws_access/AddUser")
- || startsWith(m_header.str(), "POST /ws_access/UserResetPass") || startsWith(m_header.str(), "POST /ws_account/UpdateUser")))
- DBGLOG("%s<For security, ESP does not log the content of this request.>", prefix);
- else if (isSoapMessage())
- logSOAPMessage(m_content.str(), prefix);
- else if(!isTextMessage())
- DBGLOG("%s<non-text content or content type not specified>", prefix);
- else if ((m_content_type.length() > 0) && (strieq(m_content_type.get(), "text/css") || strieq(m_content_type.get(), "text/javascript")))
- DBGLOG("%s<content_type: %s>", prefix, m_content_type.get());
- else
- logMessage(m_content.str(), prefix);
- }
- }
- catch (IException *e)
- {
- StringBuffer msg;
- ERRLOG("EXCEPTION %s when logging the message: %s", e->errorMessage(msg).str(), m_content.str());
- if (m_content_type.length() > 0)
- ERRLOG("EXCEPTION %s when logging the message (m_content_type:%s):%s", e->errorMessage(msg).str(), m_content_type.get(), m_content.str());
- else
- ERRLOG("EXCEPTION %s when logging the message: %s", e->errorMessage(msg).str(), m_content.str());
- e->Release();
- }
- return;
- }
- int CHttpMessage::send()
- {
- StringBuffer headers;
- constructHeaderBuffer(headers, true);
-
- int retcode = 0;
- // If m_content is empty but m_content_stream is set, the stream will not be logged here.
- if (getEspLogResponses() || getEspLogLevel(queryContext())>LogNormal)
- {
- logMessage(headers.str(), "Sending out HTTP headers:\n", "Authorization:[~\r\n]*", "Authorization: (hidden)");
- if(m_content_length > 0 && m_content.length() > 0)
- logMessage(LOGCONTENT, "Sending out HTTP content:\n");
- }
- try
- {
- m_socket.write(headers.str(), headers.length());
- if(m_content_length > 0 && m_content.length() > 0)
- m_socket.write(m_content.str(), m_content.length());
- }
- catch (IException *e)
- {
- StringBuffer estr;
- DBGLOG("In CHttpMessage::send(%d) -- Exception(%d, %s) writing to socket(%d).", __LINE__, e->errorCode(), e->errorMessage(estr).str(), m_socket.OShandle());
- e->Release();
- return -1;
- }
- catch(...)
- {
- ERRLOG("In CHttpMessage::send(%d) -- Unknown exception writing to socket(%d).", __LINE__, m_socket.OShandle());
- return -1;
- }
- // When m_content is empty but the stream was set, read content from the stream.
- if(((m_content_length > 0 && m_content.length() == 0) || (m_content_length64 > 0)) && m_content_stream.get() != NULL)
- {
- //Read the file and send out 20K at a time.
- __int64 content_length = m_content_length;
- if ((m_content_length64 > 0) && (content_length != m_content_length64))
- content_length = m_content_length64;
- int buflen = 20*1024;
- if(buflen > content_length)
- buflen = (int) content_length;
- char* buffer = new char[buflen + 1];
- __int64 sizesent = 0;
- while(sizesent < content_length)
- {
- int sizeread = m_content_stream->read(buflen, buffer);
- if(sizeread > 0)
- {
- sizesent += sizeread;
- try
- {
- m_socket.write(buffer, sizeread);
- }
- catch (IException *e)
- {
- StringBuffer estr;
- LOG(MCexception(e), "In CHttpMessage::send(%d) -- Exception(%d, %s) writing to socket(%d).", __LINE__, e->errorCode(), e->errorMessage(estr).str(), m_socket.OShandle());
- e->Release();
- retcode = -1;
- break;
- }
- catch(...)
- {
- ERRLOG("In CHttpMessage::send(%d) -- Unknown exception writing to socket(%d).", __LINE__, m_socket.OShandle());
- retcode = -1;
- break;
- }
- }
- else
- {
- ERRLOG("Error read from file");
- break;
- }
- }
- delete buffer;
- }
- return retcode;
- }
- int CHttpMessage::startSend()
- {
- StringBuffer sendbuf;
- constructHeaderBuffer(sendbuf, false);
-
- if (getEspLogLevel(queryContext())>LogNormal)
- DBGLOG("Start Sending chunked HTTP message:\n %s", sendbuf.str());
- try
- {
- m_socket.write(sendbuf.str(), sendbuf.length());
- }
- catch (IException *e)
- {
- StringBuffer estr;
- DBGLOG("In CHttpMessage::send() -- Exception(%d, %s) writing to socket(%d).", e->errorCode(), e->errorMessage(estr).str(), m_socket.OShandle());
- e->Release();
- return -1;
- }
- catch(...)
- {
- ERRLOG("In CHttpMessage::send() -- Unknown exception writing to socket(%d).", m_socket.OShandle());
- return -1;
- }
- return 0;
- }
- int CHttpMessage::sendChunk(const char *chunk)
- {
- if (getEspLogLevel(queryContext())>LogNormal)
- DBGLOG("Sending HTTP chunk:\n %s", chunk);
- try
- {
- m_socket.write(chunk, strlen(chunk));
- }
- catch (IException *e)
- {
- StringBuffer estr;
- DBGLOG("In CHttpMessage::send() -- Exception(%d, %s) writing to socket(%d).", e->errorCode(), e->errorMessage(estr).str(), m_socket.OShandle());
- e->Release();
- return -1;
- }
- catch(...)
- {
- ERRLOG("In CHttpMessage::send() -- Unknown exception writing to socket(%d).", m_socket.OShandle());
- return -1;
- }
- return 0;
- }
- int CHttpMessage::sendFinalChunk(const char *chunk)
- {
- if (getEspLogLevel(queryContext())>LogNormal)
- DBGLOG("Sending HTTP Final chunk:\n %s", chunk);
- try
- {
- m_socket.write(chunk, strlen(chunk));
- m_socket.close();
- }
- catch (IException *e)
- {
- StringBuffer estr;
- DBGLOG("In CHttpMessage::send() -- Exception(%d, %s) writing to socket(%d).", e->errorCode(), e->errorMessage(estr).str(), m_socket.OShandle());
- e->Release();
- return -1;
- }
- catch(...)
- {
- ERRLOG("In CHttpMessage::send() -- Unknown exception writing to socket(%d).", m_socket.OShandle());
- return -1;
- }
- return 0;
- }
- int CHttpMessage::close()
- {
- int ret = 0;
- try
- {
- if(&m_socket != NULL)
- {
- m_socket.shutdown();
- m_socket.close();
- }
- }
- catch (IException *e)
- {
- StringBuffer estr;
- ERRLOG("Exception(%d, %s) - CHttpMessage::close(), closing socket.", e->errorCode(), e->errorMessage(estr).str());
- e->Release();
- ret = -1;
- }
- catch(...)
- {
- ERRLOG("General Exception - CHttpMessage::close(), closing socket.");
- ret = -1;
- }
- return ret;
- }
- void CHttpMessage::setHeader(const char* headername, const char* headerval)
- {
- if(!headername || !*headername)
- return;
- StringBuffer val;
- val.append(headername).append(": ").append(headerval);
- ForEachItemIn(x, m_headers)
- {
- const char* curst = m_headers.item(x);
- if(!curst)
- continue;
- const char* colon = strchr(curst, ':');
- if(!colon)
- continue;
- if(!strnicmp(headername, curst, colon - curst))
- {
- m_headers.replace(val.str(), x);
- return;
- }
- }
- m_headers.append(val.str());
- }
- void CHttpMessage::addHeader(const char* headername, const char* headerval)
- {
- if(headername == NULL || strlen(headername) == 0)
- return;
- StringBuffer header;
- header.append(headername);
- header.append(": ");
- header.append(headerval);
- m_headers.append(header.str());
- }
- StringBuffer& CHttpMessage::getHeader(const char* headername, StringBuffer& headerval)
- {
- if(headername == NULL || strlen(headername) == 0)
- return headerval;
- ForEachItemIn(x, m_headers)
- {
- const char* header = m_headers.item(x);
- if(header == NULL)
- continue;
- const char* colon = strchr(header, ':');
- if(colon == NULL)
- continue;
- if(strncmp(headername, header, colon - header) == 0)
- {
- headerval.append(colon + 2);
- break;
- }
- }
- return headerval;
- }
- bool isSoapContentType(const char* contenttype)
- {
- if(contenttype == NULL)
- return false;
- else
- return Utils::strncasecmp(contenttype, HTTP_TYPE_TEXT_XML, strlen(HTTP_TYPE_TEXT_XML)) == 0 ||
- Utils::strncasecmp(contenttype, HTTP_TYPE_SOAP, strlen(HTTP_TYPE_SOAP)) == 0;
- }
- bool CHttpMessage::isSoapMessage()
- {
- if(m_content_type.get() == NULL)
- return false;
- else if(Utils::strncasecmp(m_content_type.get(), HTTP_TYPE_MULTIPART_RELATED, strlen(HTTP_TYPE_MULTIPART_RELATED)) == 0)
- {
- CMimeMultiPart* mpart = queryMultiPart();
- if(mpart == NULL)
- return false;
- CMimeBodyPart* bpart = mpart->queryRootPart();
- if(bpart != NULL && isSoapContentType(bpart->getContentType()))
- return true;
- else
- return false;
- }
- else
- return isSoapContentType(m_content_type.get());
- }
- bool CHttpMessage::isFormSubmission()
- {
- return ((hasContentType(NULL) && (m_paramCount + m_attachCount) > 0) ||
- hasContentType(HTTP_TYPE_MULTIPART_FORMDATA) ||
- hasContentType(HTTP_TYPE_FORM_ENCODED));
- }
- /******************************************************************************
- CHttpRequest Implementation
- *******************************************************************************/
- CHttpRequest::CHttpRequest(ISocket& socket) : CHttpMessage(socket), m_pathIsParsed(false),
- m_sstype(sub_serv_unknown), m_MaxRequestEntityLength(0)
- {
- };
- CHttpRequest::~CHttpRequest()
- {
- };
- StringBuffer& CHttpRequest::getMethod(StringBuffer & method)
- {
- return method.append(m_httpMethod.str());
- }
- void CHttpRequest::setMethod(const char* method)
- {
- m_httpMethod.clear().append(method);
- }
- StringBuffer& CHttpRequest::getPath(StringBuffer & path)
- {
- return path.append(m_httpPath.str());
- }
- void CHttpRequest::setPath(const char* path)
- {
- m_httpPath.clear().append(path);
- }
- void CHttpRequest::parseQueryString(const char* querystr)
- {
- if(!querystr || !*querystr)
- return;
- bool useHeap = false;
- int querystrlen = strlen(querystr);
- if(querystrlen >= 0x80000)
- useHeap = true;
- char* querystrbuf = NULL;
- if(useHeap)
- querystrbuf = (char*)malloc(querystrlen + 1);
- else
- querystrbuf = (char*)alloca(querystrlen + 1);
- strcpy(querystrbuf, querystr);
- char* ptr = querystrbuf;
- char* curname = ptr;
- char* curvalue = NULL;
- while(true)
- {
- while(*ptr != '\0' && *ptr != '=' && *ptr != '&')
- ptr++;
-
- if(*ptr == '\0')
- {
- StringBuffer nameval;
- Utils::url_decode(curname, nameval);
- addParameter(nameval.str(), "");
- break;
- }
- else if(*ptr == '=')
- {
- *ptr = '\0';
- ptr++;
- if(*ptr == '\0')
- {
- StringBuffer nameval;
- Utils::url_decode(curname, nameval);
- addParameter(nameval.str(), "");
- break;
- }
- else if(*ptr == '&')
- {
- StringBuffer nameval;
- Utils::url_decode(curname, nameval);
- addParameter(nameval.str(), "");
- ptr++;
- if(*ptr == '\0')
- break;
- else
- curname = ptr;
- }
- else
- {
- curvalue = ptr;
- while(*ptr != '\0' && *ptr != '&')
- ptr++;
- if(*ptr == '\0')
- {
- StringBuffer nameval;
- StringBuffer valueval;
- Utils::url_decode(curname, nameval);
- Utils::url_decode(curvalue, valueval);
- addParameter(nameval.str(), valueval.str());
- break;
- }
- else //*ptr == '&'
- {
- *ptr = '\0';
- ptr++;
- StringBuffer nameval;
- StringBuffer valueval;
- Utils::url_decode(curname, nameval);
- Utils::url_decode(curvalue, valueval);
- addParameter(nameval.str(), valueval.str());
- if(*ptr == '\0')
- break;
- else
- curname = ptr;
- }
- }
- }
- else if(*ptr == '&')
- {
- *ptr=0;
- StringBuffer nameval;
- Utils::url_decode(curname, nameval);
- addParameter(nameval.str(), "");
- ptr++;
- if(!*ptr)
- break;
- else
- curname = ptr;
- }
- }
- if(useHeap && querystrbuf != NULL)
- delete querystrbuf;
- }
- int CHttpRequest::parseFirstLine(char* oneline)
- {
- //if (getEspLogLevel()>LogNormal)
- // DBGLOG("First Line of request=%s", oneline);
- DBGLOG("HTTP First Line: %s", oneline);
- if(*oneline == 0)
- return -1;
- const char* curptr = oneline;
- StringBuffer method;
- curptr = Utils::getWord(curptr, method);
- if(!stricmp(method.str(), POST_METHOD))
- {
- setMethod(POST_METHOD);
- }
- else if(!stricmp(method.str(), GET_METHOD))
- {
- setMethod(GET_METHOD);
- }
- else if(!stricmp(method.str(), HEAD_METHOD))
- {
- setMethod(HEAD_METHOD);
- }
- StringBuffer pathbuf;
- curptr = Utils::getWord(curptr, pathbuf);
-
- int len = pathbuf.length();
- char* buff;
- if(len == 0)
- {
- buff = new char[2];
- buff[0] = '/';
- buff[1] = '\0';
- }
- else
- {
- if(pathbuf.charAt(0) != '/')
- {
- buff = new char[len + 2];
- buff[0] = '/';
- strcpy(buff + 1, pathbuf.str());
- }
- else
- {
- buff = new char[len + 1];
- strcpy(buff, pathbuf.str());
- }
- }
- char* qmark = strchr(buff, '?');
- if(qmark != NULL)
- {
- *qmark = '\0';
- }
- // Decode path
- StringBuffer path;
- Utils::url_decode(buff, path);
- setPath(path.str());
- // Parse and decode parameters
- if(qmark != NULL)
- {
- char* querystr = qmark + 1;
- m_paramstr.set(querystr);
- addParameter("__querystring", querystr); //MORE- requested by dimitri
- parseQueryString(querystr);
- }
- delete[] buff;
- return 0;
- }
- void CHttpRequest::parseCookieHeader(char* cookiestr)
- {
- if(cookiestr == NULL)
- return;
- int version;
- char* curword;
- char* curptr = cookiestr;
- const char* separators = ",;";
-
- curptr = Utils::getWord(curptr, curword, separators);
- StringBuffer name, value;
- Utils::parseNVPair(curword, name, value);
- CEspCookie* cookie = NULL;
- if(name.length() == 0 || stricmp(name.str(), "$Version"))
- {
- version = 0;
- cookie = new CEspCookie(name.str(), value.str());
- cookie->setVersion(version);
- m_cookies.append(*cookie);
- }
- else
- {
- version = atoi(value.str());
- }
- while(curptr != NULL && *curptr != 0)
- {
- curptr = Utils::getWord(curptr, curword, separators);
- if(curword == NULL)
- break;
- StringBuffer name, value;
- Utils::parseNVPair(curword, name, value);
- if(name.length() == 0)
- continue;
- if(name.charAt(0) != '$')
- {
- cookie = new CEspCookie(name.str(), value.str());
- cookie->setVersion(version);
- m_cookies.append(*cookie);
- }
- else if(stricmp(name.str(), "$Path") == 0 && cookie != NULL)
- cookie->setPath(value.str());
- else if(stricmp(name.str(), "$Domain") == 0 && cookie != NULL)
- cookie->setDomain(value.str());
- else if(stricmp(name.str(), "$Port") == 0 && cookie != NULL)
- cookie->setPorts(value.str());
- }
- }
- ESPSerializationFormat lookupResponseFormatByExtension(const char *ext)
- {
- if (!ext || !*ext)
- return ESPSerializationANY;
- if (strieq(ext, ".xml"))
- return ESPSerializationXML;
- if (strieq(ext, ".json"))
- return ESPSerializationJSON;
- return ESPSerializationANY;
- }
- void CHttpRequest::parseEspPathInfo()
- {
- if (!m_pathIsParsed)
- {
- m_espPathEx.clear();
- m_espMethodName.clear();
- m_espServiceName.clear();
- if (queryParameters()->hasProp("rawxml_"))
- m_context->setResponseFormat(ESPSerializationXML);
- else if (isSoapMessage())
- m_context->setResponseFormat(ESPSerializationXML);
- size32_t pathlen=m_httpPath.length();
- if (!pathlen)
- m_sstype=(m_queryparams && m_queryparams->hasProp("main")) ? sub_serv_main : sub_serv_root;
- else
- {
- char *pathstr = strdup(m_httpPath.str());
- char *finger = pathstr;
-
- if (!strnicmp(finger, "http://", 7))
- finger+=7;
- char *thumb=finger;
- while (*thumb!=0 && *thumb!='/')
- {
- if (*thumb=='@' || *thumb==':')
- {
- finger=strchr(thumb, '/');
- break;
- }
- thumb++;
- }
- bool missingTrailSlash = false;
- if (finger)
- {
- while (*finger == '/')
- finger++;
- //look for the service and method names
- //
- if (finger && finger[0] != '\0')
- {
- thumb=strchr(finger, '/');
- if (thumb)
- {
- char *pathex = strchr(thumb+1, '/');
- if (pathex)
- {
- *pathex=0;
- m_espPathEx.append(pathex+1);
- }
-
- *thumb=0;
- m_espMethodName.append(++thumb);
- const char *tail = strrchr(thumb, '.');
- ESPSerializationFormat fmt = lookupResponseFormatByExtension(tail);
- if (fmt!=ESPSerializationANY)
- {
- m_context->setResponseFormat(fmt);
- m_espMethodName.setLength(tail-thumb);
- }
- }
- else
- missingTrailSlash = true;
- m_espServiceName.append(finger);
- }
- }
-
- free(pathstr);
- if (m_espMethodName.length())
- {
- if (!stricmp(m_espMethodName.str(), "files_"))
- m_sstype=sub_serv_files;
- else if (!stricmp(m_espMethodName.str(), "content_"))
- m_sstype=sub_serv_content;
- else if (!stricmp(m_espMethodName.str(), "result_"))
- m_sstype=sub_serv_result;
- else if (!stricmp(m_espMethodName.str(), "iframe"))
- m_sstype=sub_serv_iframe;
- else if (!stricmp(m_espMethodName.str(), "itext"))
- m_sstype=sub_serv_itext;
- else if (!stricmp(m_espMethodName.str(), "version_"))
- m_sstype=sub_serv_getversion;
- }
- //not a special service URL, determine the action type
- if (m_sstype==sub_serv_unknown)
- {
- if (m_queryparams && (m_queryparams->hasProp("wsdl") || m_queryparams->hasProp("wsdl_ext")))
- m_sstype=sub_serv_wsdl;
- else if (m_queryparams && (m_queryparams->hasProp("xsd")))
- m_sstype=sub_serv_xsd;
- else if (m_queryparams && (m_queryparams->hasProp("reqxml_")))
- m_sstype=sub_serv_reqsamplexml;
- else if (m_queryparams && (m_queryparams->hasProp("respxml_")))
- m_sstype=sub_serv_respsamplexml;
- else if (m_queryparams && (m_queryparams->hasProp("soap_builder_")))
- m_sstype=sub_serv_soap_builder;
- else if (m_queryparams && m_queryparams->hasProp("config_"))
- m_sstype=sub_serv_config;
- else if (m_espServiceName.length()==0)
- m_sstype=(m_queryparams && m_queryparams->hasProp("main")) ? sub_serv_main : sub_serv_root;
- else if (m_espMethodName.length()==0)
- m_sstype = missingTrailSlash ? sub_serv_index_redirect : sub_serv_index;
- else if (m_queryparams && m_queryparams->hasProp("form_"))
- m_sstype=sub_serv_form;
- else if (m_queryparams && m_queryparams->hasProp("form"))
- m_sstype=sub_serv_xform;
- else if (isUpload())
- m_sstype=sub_serv_file_upload;
- else if (getParameterCount())// queryParamStr()!=NULL && *queryParamStr()!=0)
- m_sstype=sub_serv_query;
- else
- m_sstype=sub_serv_method;
- }
- }
- m_pathIsParsed=true;
- }
- }
- void CHttpRequest::getEspPathInfo(sub_service &sstype, StringBuffer *pathEx, StringBuffer *service, StringBuffer *method, bool upcase)
- {
- parseEspPathInfo();
- sstype = m_sstype;
- if (pathEx)
- {
- pathEx->clear().append(m_espPathEx);
- if (upcase)
- pathEx->toUpperCase();
- }
- if (service)
- {
- service->clear().append(m_espServiceName);
- service->toUpperCase();
- }
- if (method)
- {
- method->clear().append(m_espMethodName);
- method->toUpperCase();
- }
- }
-
- void CHttpRequest::getBasicRealm(StringBuffer& realm)
- {
- StringBuffer authheader;
- getHeader("WWW-Authenticate", authheader);
- if(authheader.length() == 0)
- return;
-
- if(Utils::strncasecmp(authheader.str(), "Basic ", strlen("Basic ")) != 0)
- return;
- const char* strt = strchr(authheader.str(), '\"');
- ++strt;
- if (strt)
- {
- const char* end = strchr(strt, '\"');
- if (end)
- {
- realm.append(strt, 0, end - strt);
- }
- }
- }
- int CHttpRequest::getPeerPort()
- {
- char peername[256];
- return m_socket.peer_name(peername, 256);
- }
- StringBuffer& CHttpRequest::getPeer(StringBuffer& Peer)
- {
- StringBuffer ForwardIPs;
- getHeader("X-Forwarded-For", ForwardIPs);
-
- if(ForwardIPs.length() != 0)
- {
- //IPs will ne in the form xxx.xxx.xxx.xxx,yyy.yyy.yyy.yyy,zzz.zzz.zzz.zzz
- //We want to take the first IP in the list
- const char* strt = strchr(ForwardIPs.str(), ',');
- if(strt!= NULL)
- Peer.append(strt - ForwardIPs.str(),ForwardIPs.str());
- else
- Peer.appendf("%s",ForwardIPs.str());
- }
- else
- {
- char peerchr[256];
- int port = m_socket.peer_name(peerchr, 256);
- Peer.append(peerchr);
- }
- return Peer;
- }
- void CHttpRequest::getBasicAuthorization(StringBuffer& userid, StringBuffer& password,StringBuffer& realm)
- {
- StringBuffer authheader;
- getHeader("Authorization", authheader);
- if(authheader.length() == 0)
- return;
- if(Utils::strncasecmp(authheader.str(), "Basic ", strlen("Basic ")) != 0)
- return;
- StringBuffer uidpair;
- Utils::base64decode(authheader.length() - strlen("Basic "), authheader.str() + strlen("Basic "), uidpair);
-
- const char* pairstr = strchr(uidpair.str(), '\\');
- if(pairstr!=NULL)
- {
- realm.append(pairstr - uidpair.str(),uidpair.str());
- pairstr++;
- }
- else
- {
- pairstr = uidpair.str();
- getBasicRealm(realm);
- }
-
- const char* colon = strchr(pairstr, ':');
- if(colon == NULL)
- {
- userid.append(pairstr);
- }
- else
- {
- userid.append(colon - pairstr, pairstr);
- password.append(colon + 1);
- }
- }
- int CHttpRequest::receive(IMultiException *me)
- {
- if (CHttpMessage::receive(false, me)==-1)
- return -1;
-
- //if(hasContentType("application/x-www-form-urlencoded"))
- if(hasContentType(HTTP_TYPE_FORM_ENCODED))
- {
- parseQueryString(m_content.str());
- }
- else if(hasContentType(HTTP_TYPE_MULTIPART_FORMDATA) && !isUpload())
- {
- CMimeMultiPart* mpart = queryMultiPart();
- if(mpart != NULL)
- {
- int count = mpart->getBodyCount();
- for(int i = 0; i < count; i++)
- {
- CMimeBodyPart* bpart = mpart->queryBodyPart(i);
- if(bpart == NULL)
- continue;
- const char* cdisp = bpart->getContentDisposition();
- StringBuffer contentbuf;
- bpart->getContent(contentbuf);
- StringBuffer namebuf;
- char* curword = NULL;
- char* curptr = (char*)cdisp;
- const char* separators = ";";
-
- bool isFile = false;
- StringBuffer filename;
- while(curptr != NULL && *curptr != 0)
- {
- curptr = Utils::getWord(curptr, curword, separators, true);
- if(curword == NULL)
- break;
- StringBuffer name, value;
- Utils::parseNVPair(curword, name, value);
- if(name.length() > 0 && stricmp(name.str(), "name") == 0)
- {
- namebuf.append(value.str());
- }
- else if(name.length() > 0 && stricmp(name.str(), "filename") == 0)
- {
- value.swapWith(filename);
- isFile = true;
- }
- }
- if(!isFile)
- addParameter(namebuf.str(), contentbuf.str());
- else
- {
- addParameter(namebuf.str(), filename.str());
- addAttachment(namebuf.str(), contentbuf);
- }
- }
- }
- }
- m_context->addTraceSummaryTimeStamp("rcv");
- return 0;
- }
- void CHttpRequest::updateContext()
- {
- if(m_context)
- {
- m_context->setContextPath(m_httpPath.str());
- StringBuffer temp;
- getPeer(temp);
- if(temp.length())
- m_context->setPeer(temp.str());
- m_context->setRequestParameters(queryParameters());
- short servPort;
- temp.clear();
- getServAddress(temp, servPort);
- m_context->setServAddress(temp.str(), servPort);
- StringBuffer userid, password, realm;
- getBasicAuthorization(userid, password, realm);
- if(userid.length() > 0)
- {
- m_context->setUserID(userid.str());
- m_context->setPassword(password.str());
- m_context->setRealm(realm.str());
- }
- if (m_queryparams)
- {
- if (m_queryparams->getPropInt("no_ns_"))
- m_context->addOptions(ESPCTX_NO_NAMESPACES);
- if (m_queryparams->hasProp("wsdl"))
- m_context->addOptions(ESPCTX_WSDL);
- if (m_queryparams->hasProp("wsdl_ext"))
- m_context->addOptions(ESPCTX_WSDL|ESPCTX_WSDL_EXT);
- if (m_queryparams->hasProp("no_annot_"))
- m_context->addOptions(ESPCTX_NO_ANNOTATION);
- if (m_queryparams->hasProp("all_annot_"))
- m_context->addOptions(ESPCTX_ALL_ANNOTATION);
- }
- // set client version
- StringBuffer action;
- getHeader("SOAPAction", action);
- // URL first, then SOAPAction
- const char *verstr = queryParameters()->queryProp("ver_");
- if (verstr && *verstr)
- m_context->setClientVersion(atof(verstr));
- else
- {
- verstr=strstr(action.str(), "ver_=");
- if (verstr)
- m_context->setClientVersion(atof(verstr+5));
- else
- m_context->setClientVersion(0.0);
- }
- StringBuffer useragent;
- getHeader("User-Agent", useragent);
- m_context->setUseragent(useragent.str());
- }
- }
- StringBuffer& CHttpRequest::constructHeaderBuffer(StringBuffer& headerbuf, bool inclLength)
- {
- if(m_httpMethod.length() > 0)
- headerbuf.append(queryMethod()).append(" ");
- else
- headerbuf.append("POST ");
- if(m_httpPath.length() > 0)
- headerbuf.append(queryPath()).append(" ");
- else
- headerbuf.append("/ ");
- if(m_version.length() > 0)
- headerbuf.append(m_version.get());
- else
- headerbuf.append(HTTP_VERSION);
- headerbuf.append("\r\n");
- if(m_host.length() > 0)
- {
- headerbuf.append("Host: ").append(m_host.get());
- if(m_port != 80)
- {
- headerbuf.append(":").append(m_port);
- }
- headerbuf.append("\r\n");
- }
- headerbuf.append("Content-Type: ");
- if(m_content_type.length() > 0)
- headerbuf.append(m_content_type.get());
- else
- headerbuf.append("text/xml; charset=UTF-8");
- headerbuf.append("\r\n");
- if(inclLength && m_content_length > 0)
- headerbuf.append("Content-Length: ").append(m_content_length).append("\r\n");
- if(m_cookies.length() > 0)
- {
- headerbuf.append("Cookie: ");
- int version = m_cookies.item(0).getVersion();
- if(version >= 1)
- headerbuf.append("$Version=").append('"').append(version).append('"').append(',');
- ForEachItemIn(x, m_cookies)
- {
- CEspCookie* cookie = &m_cookies.item(x);
- if(cookie == NULL)
- continue;
- cookie->appendToRequestHeader(headerbuf);
- }
- headerbuf.append("\r\n");
- }
-
- ForEachItemIn(x, m_headers)
- {
- const char* oneheader = (const char*)m_headers.item(x);
- headerbuf.append(oneheader).append("\r\n");
- }
- headerbuf.append("\r\n");
- return headerbuf;
- }
- int CHttpRequest::processHeaders(IMultiException *me)
- {
- char oneline[MAX_HTTP_HEADER_LEN + 2];
- int lenread = m_bufferedsocket->readline(oneline, MAX_HTTP_HEADER_LEN + 1, me);
- if(lenread <= 0) //special case client connected and disconnected, load balancer ping?
- return -1;
- else if (lenread > MAX_HTTP_HEADER_LEN)
- throw createEspHttpException(HTTP_STATUS_BAD_REQUEST_CODE, "Bad Request", HTTP_STATUS_BAD_REQUEST);
- m_header.set(oneline);
- parseFirstLine(oneline);
-
- lenread = m_bufferedsocket->readline(oneline, MAX_HTTP_HEADER_LEN + 1, me);
- while(lenread >= 0 && oneline[0] != '\0')
- {
- if(lenread > MAX_HTTP_HEADER_LEN)
- throw createEspHttpException(HTTP_STATUS_BAD_REQUEST_CODE, "Bad Request", HTTP_STATUS_BAD_REQUEST);
- m_header.append('\n').append(oneline);
- parseOneHeader(oneline);
- lenread = m_bufferedsocket->readline(oneline, MAX_HTTP_HEADER_LEN + 1, me);
- }
- if (getEspLogRequests() || getEspLogLevel()>LogNormal)
- logMessage(LOGHEADERS, "HTTP request headers received:\n");
- if(m_content_length > 0 && m_MaxRequestEntityLength > 0 && m_content_length > m_MaxRequestEntityLength && (!isUpload()))
- throw createEspHttpException(HTTP_STATUS_BAD_REQUEST_CODE, "The request length was too long.", HTTP_STATUS_BAD_REQUEST);
- return 0;
- }
- bool CHttpRequest::readContentToBuffer(MemoryBuffer& buffer, __int64& bytesNotRead)
- {
- char buf[1024 + 1];
- __int64 buflen = 1024;
- if (buflen > bytesNotRead)
- buflen = bytesNotRead;
- int readlen = m_bufferedsocket->read(buf, (int) buflen);
- if(readlen < 0)
- DBGLOG("Failed to read from socket");
- if(readlen <= 0)
- return false;
- buf[readlen] = 0;
- buffer.append(readlen, buf);//'buffer' may have some left-over from previous read
- bytesNotRead -= readlen;
- return true;
- }
- bool CHttpRequest::readUploadFileName(CMimeMultiPart* mimemultipart, StringBuffer& fileName, MemoryBuffer& contentBuffer, __int64& bytesNotRead)
- {
- if (contentBuffer.length())
- mimemultipart->readUploadFileName(contentBuffer, fileName);
- while((fileName.length() < 1) && (bytesNotRead > 0))
- {
- if (!readContentToBuffer(contentBuffer, bytesNotRead))
- break;
- mimemultipart->readUploadFileName(contentBuffer, fileName);
- }
- return (fileName.length() > 0);
- }
- IFile* CHttpRequest::createUploadFile(StringBuffer netAddress, const char* filePath, StringBuffer& fileName)
- {
- StringBuffer name(fileName), tmpFileName;
- char* str = (char*) name.reverse().str();
- char* pStr = (char*) strchr(str, '\\');
- if (!pStr)
- pStr = strchr(str, '/');
- if (pStr)
- {
- pStr[0] = 0;
- fileName.clear().append(str).reverse();
- }
- tmpFileName.appendf("%s/%s.part", filePath, fileName.str());
- RemoteFilename rfn;
- SocketEndpoint ep;
- ep.set(netAddress.str());
- rfn.setPath(ep, tmpFileName.str());
- return createIFile(rfn);
- }
- int CHttpRequest::readContentToFiles(StringBuffer netAddress, StringBuffer path, StringArray& fileNames)
- {
- const char* contentType = m_content_type.get();
- if (!contentType || !*contentType)
- throw MakeStringException(-1, "Content Type not found.");
- Owned<CMimeMultiPart> multipart = new CMimeMultiPart("1.0", contentType, "", "", "");
- multipart->parseContentType(contentType);
- MemoryBuffer fileContent, moreContent;
- __int64 bytesNotRead = m_content_length64;
- while (1)
- {
- StringBuffer fileName;
- if (!readUploadFileName(multipart, fileName, fileContent, bytesNotRead))
- {
- DBGLOG("No file name found for upload");
- break;
- }
- fileNames.append(fileName);
- Owned<IFile> file = createUploadFile(netAddress, path, fileName);
- if (!file)
- {
- DBGLOG("Uploaded file %s cannot be created", fileName.str());
- break;
- }
- Owned<IFileIO> fileio = file->open(IFOcreate);
- if (!fileio)
- {
- DBGLOG("Uploaded file %s cannot be opened", fileName.str());
- break;
- }
- __int64 writeOffset = 0;
- bool writeError = false;
- bool foundAnotherFile = false;
- while (1)
- {
- foundAnotherFile = multipart->separateMultiParts(fileContent, moreContent, bytesNotRead);
- if (fileContent.length() > 0)
- {
- if (fileio->write(writeOffset, fileContent.length(), fileContent.toByteArray()) != fileContent.length())
- {
- DBGLOG("Failed to write Uploaded file %s", fileName.str());
- writeError = true;
- break;
- }
- writeOffset += fileContent.length();
- }
- fileContent.clear();
- if (moreContent.length() > 0)
- {
- fileContent.append(moreContent.length(), (void*) moreContent.toByteArray());
- moreContent.clear();
- }
- if(foundAnotherFile || (bytesNotRead <= 0) || !readContentToBuffer(fileContent, bytesNotRead))
- break;
- }
- if (writeError)
- break;
- StringBuffer fileNameWithPath;
- fileNameWithPath.appendf("%s/%s", path.str(), fileName.str());
- file->rename(fileNameWithPath.str());
- if (!foundAnotherFile)
- break;
- }
- return 0;
- }
- /******************************************************************************
- CHttpResponse Implementation
- *******************************************************************************/
- CHttpResponse::CHttpResponse(ISocket& socket) : CHttpMessage(socket), m_timeout(BSOCKET_CLIENT_READ_TIMEOUT)
- {
- }
- CHttpResponse::~CHttpResponse()
- {
- }
- void CHttpResponse::setTimeOut(unsigned int timeout)
- {
- m_timeout = timeout;
- }
- void CHttpResponse::setStatus(const char* status)
- {
- m_status.set(status);
- }
- StringBuffer& CHttpResponse::getStatus(StringBuffer& status)
- {
- status.append(m_status.get());
- return status;
- }
- StringBuffer& CHttpResponse::constructHeaderBuffer(StringBuffer& headerbuf, bool inclLen)
- {
- if(m_version.length() > 0)
- headerbuf.append(m_version.get()).append(" ");
- else
- headerbuf.append(HTTP_VERSION).append(" ");
- if(m_status.length() > 0)
- headerbuf.append(m_status.get());
- else
- headerbuf.append(HTTP_STATUS_OK);
- headerbuf.append("\r\n");
-
- headerbuf.append("Content-Type: ");
- if(m_content_type.length() > 0)
- headerbuf.append(m_content_type.get());
- else
- headerbuf.append("text/xml; charset=UTF-8");
- headerbuf.append("\r\n");
- if(inclLen && m_content_length > 0)
- headerbuf.append("Content-Length: ").append(m_content_length).append("\r\n");
- headerbuf.append("Connection: close\r\n");
-
- ForEachItemIn(x, m_cookies)
- {
- CEspCookie* cookie = &m_cookies.item(x);
- if(cookie == NULL)
- continue;
- StringBuffer cookiehn;
- cookie->getSetCookieHeaderName(cookiehn);
- headerbuf.append(cookiehn.str()).append(": ");
- cookie->appendToResponseHeader(headerbuf);
- headerbuf.append("\r\n");
- }
- ForEachItemIn(i, m_headers)
- {
- const char* oneheader = (const char*)m_headers.item(i);
- headerbuf.append(oneheader).append("\r\n");
- }
-
- if(m_context.get())
- {
- StringArray& customHeaders = m_context->queryCustomHeaders();
- ForEachItemIn(j, customHeaders)
- {
- const char* oneheader = (const char*)customHeaders.item(j);
- if(oneheader && *oneheader)
- headerbuf.append(oneheader).append("\r\n");
- }
- }
- headerbuf.append("\r\n");
- return headerbuf;
- }
- int CHttpResponse::parseFirstLine(char* oneline)
- {
- if(*oneline == 0)
- return -1;
- if (getEspLogLevel()>LogNormal)
- DBGLOG("http response status = %s", oneline);
- char* ptr = oneline;
- while(*ptr != '\0' && *ptr != ' ')
- ptr++;
- if(*ptr != '\0')
- {
- *ptr = 0;
- ptr++;
- }
- m_version.set(oneline);
- while(*ptr == ' ')
- ptr++;
- m_status.set(ptr);
- return 0;
- }
- void CHttpResponse::parseOneCookie(char* cookiestr)
- {
- if(cookiestr == NULL)
- return;
- char* curword;
- char* curptr = cookiestr;
- CEspCookie* cookie = NULL;
- curptr = Utils::getWord(curptr, curword, ";");
- StringBuffer name, value;
- Utils::parseNVPair(curword, name, value);
- if(name.length() == 0)
- return;
- cookie = new CEspCookie(name.str(), value.str());
- m_cookies.append(*cookie);
- while(curptr != NULL && *curptr != 0)
- {
- curptr = Utils::getWord(curptr, curword, ";");
- if(curword == NULL)
- break;
- StringBuffer name, value;
- Utils::parseNVPair(curword, name, value);
- if(name.length() == 0)
- continue;
- else if(stricmp(name.str(), "Version") == 0)
- cookie->setVersion(atoi(value.str()));
- else if(stricmp(name.str(), "Path") == 0)
- cookie->setPath(value.str());
- else if(stricmp(name.str(), "Domain") == 0)
- cookie->setDomain(value.str());
- else if(stricmp(name.str(), "Port") == 0)
- cookie->setPorts(value.str());
- else if(stricmp(name.str(), "Max-Age") == 0)
- cookie->setMaxAge(atoi(value.str()));
- else if(stricmp(name.str(), "Discard") == 0)
- cookie->setDiscard(true);
- else if(stricmp(name.str(), "Secure") == 0)
- cookie->setSecure(true);
- else if(stricmp(name.str(), "Comment") == 0)
- cookie->setComment(value.str());
- else if(stricmp(name.str(), "CommentURL") == 0)
- cookie->setCommentURL(value.str());
-
- }
- }
- void CHttpResponse::parseCookieHeader(char* cookiestr)
- {
- if(cookiestr == NULL)
- return;
- //TODO: for now assume each Set-Cookie only has one cookie.
- parseOneCookie(cookiestr);
- }
- void CHttpResponse::sendBasicChallenge(const char* realm, bool includeContent)
- {
- StringBuffer authheader;
- authheader.appendf("Basic realm=\"%s\"", realm);
- addHeader("WWW-Authenticate", authheader.str());
- if (includeContent)
- {
- setContentType("text/html; charset=UTF-8");
- setContent(
- "<html xmlns=\"http://www.w3.org/1999/xhtml\">"
- "<head>"
- "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"/>"
- "<title>ESP - Access Denied</title>"
- "<script type='text/javascript'>"
- "function closeWin() { top.opener=top; top.close(); }"
- "</script>"
- "</head>"
- "<body onload=\"javascript:closeWin();\">"
- "<b>Access Denied -- Valid username and password required!</b>"
- "</body>"
- "</html>"
- );
- }
- setStatus(HTTP_STATUS_UNAUTHORIZED);
- send();
- }
- void CHttpResponse::sendBasicChallenge(const char* realm, const char* content)
- {
- StringBuffer authheader;
- authheader.appendf("Basic realm=\"%s\"", realm);
- addHeader("WWW-Authenticate", authheader.str());
- if (content != NULL && *content != '\0')
- {
- setContentType("text/html; charset=UTF-8");
- setContent(content);
- }
- setStatus(HTTP_STATUS_UNAUTHORIZED);
- send();
- }
- int CHttpResponse::processHeaders(IMultiException *me)
- {
- char oneline[MAX_HTTP_HEADER_LEN + 1];
- int lenread = m_bufferedsocket->readline(oneline, MAX_HTTP_HEADER_LEN, me);
- if(lenread <= 0)
- return -1;
-
- // Process "100 Continue" headers
- // Some HTTP/1.1 webservers may send back "100 Continue" before it reads the posted request body.
- while(Utils::strncasecmp(oneline, "HTTP/1.1 100", strlen("HTTP/1.1 100")) == 0)
- {
- //Read until empty line, meaning the end of "100 Continue" part
- while(lenread >= 0 && oneline[0] != '\0')
- {
- lenread = m_bufferedsocket->readline(oneline, MAX_HTTP_HEADER_LEN, me);
- }
-
- // Read the next line, should be the status line.
- lenread = m_bufferedsocket->readline(oneline, MAX_HTTP_HEADER_LEN, me);
- if(lenread <= 0)
- return 0;
- }
- parseFirstLine(oneline);
- lenread = m_bufferedsocket->readline(oneline, MAX_HTTP_HEADER_LEN, me);
- while(lenread >= 0 && oneline[0] != '\0')
- {
- parseOneHeader(oneline);
- lenread = m_bufferedsocket->readline(oneline, MAX_HTTP_HEADER_LEN, me);
- }
- return 0;
- }
- bool CHttpResponse::httpContentFromFile(const char *filepath)
- {
- StringBuffer mimetype, etag, lastModified;
- MemoryBuffer content;
- //Set 'modified = false' here since this is called by CMySoapBinding::onGetFile() which does
- //not need to check and set both 'etag' and 'lastModified' inside httpContentFromFile().
- bool modified = false;
- bool ok = ::httpContentFromFile(filepath, mimetype, content, modified, lastModified, etag);
- if (ok)
- {
- setContent(content.length(), content.toByteArray());
- setContentType(mimetype.str());
- setStatus(HTTP_STATUS_OK);
- }
- else
- {
- setStatus(HTTP_STATUS_NOT_FOUND);
- }
- return ok;
- }
- void CHttpResponse::setETagCacheControl(const char *etag, const char *contenttype)
- {
- if (etag && *etag)
- addHeader("Etag", etag);
- if (!strncmp(contenttype, "image/", 6))
- {
- //if file being requested is an image file then set its expiration to a year
- //so browser does not keep reloading it
- addHeader("Cache-control", "max-age=31536000");
- }
- else
- addHeader("Cache-control", "max-age=300");
- }
- void CHttpResponse::CheckModifiedHTTPContent(bool modified, const char *lastmodified, const char *etag, const char *contenttype, MemoryBuffer &content)
- {
- if (!modified)
- {
- if (etag && *etag)
- setETagCacheControl(etag, contenttype);
- setStatus(HTTP_STATUS_NOT_MODIFIED);
- }
- else
- {
- addHeader("Last-Modified", lastmodified);
- setETagCacheControl(etag, contenttype);
- setContent(content.length(), content.toByteArray());
- setContentType(contenttype);
- setStatus(HTTP_STATUS_OK);
- }
- }
- int CHttpResponse::receive(IMultiException *me)
- {
- // If it's receiving a response, it's behaving as the client side of this conversation.
- if(m_bufferedsocket.get() != NULL)
- m_bufferedsocket->setReadTimeout(m_timeout);
-
- return CHttpMessage::receive(me);
- }
- int CHttpResponse::receive(bool alwaysReadContent, IMultiException *me)
- {
- // If it's receiving a response, it's behaving as the client side of this conversation.
- if(m_bufferedsocket.get() != NULL)
- m_bufferedsocket->setReadTimeout(m_timeout);
-
- if (processHeaders(me)==-1)
- return -1;
- if (getEspLogLevel()>LogNormal)
- DBGLOG("Response headers processed! content_length = %d", m_content_length);
-
- char status_class = '2';
- if(m_status.length() > 0)
- status_class = *(m_status.get());
- if(m_content_length > 0)
- {
- readContent();
- if (getEspLogLevel()>LogNormal)
- DBGLOG("length of response content read = %d", m_content.length());
- }
- else if(alwaysReadContent && status_class != '4' && status_class != '5' && m_content_length == -1)
- {
- //HTTP protocol does not require a content length: read until socket closed
- readContentTillSocketClosed();
- if (getEspLogLevel()>LogNormal)
- DBGLOG("length of content read = %d", m_content.length());
- }
-
- if ((getEspLogRequests() || getEspLogLevel()>LogNormal))
- logMessage(LOGCONTENT, "HTTP response content received:\n");
- return 0;
- }
- int CHttpResponse::sendException(IEspHttpException* e)
- {
- StringBuffer msg;
- e->errorMessage(msg);
- setStatus(e->getHttpStatus());
- setContentType(HTTP_TYPE_TEXT_PLAIN);
- setContent(msg.str());
- send();
- return 0;
- }
- StringBuffer &toJSON(StringBuffer &json, IMultiException *me, const char *callback)
- {
- IArrayOf<IException> &exs = me->getArray();
- if (callback && *callback)
- json.append(callback).append('(');
- appendJSONName(json.append("{"), "Exceptions").append("{");
- appendJSONValue(json, "Source", me->source());
- appendJSONName(json, "Exception").append("[");
- ForEachItemIn(i, exs)
- {
- IException &e = exs.item(i);
- if (i>0)
- json.append(",");
- StringBuffer msg;
- appendJSONValue(json.append("{"), "Code", e.errorCode());
- appendJSONValue(json, "Message", e.errorMessage(msg).str());
- json.append("}");
- }
- json.append("]}}");
- if (callback && *callback)
- json.append(");");
- return json;
- }
- bool CHttpResponse::handleExceptions(IXslProcessor *xslp, IMultiException *me, const char *serv, const char *meth, const char *errorXslt)
- {
- IEspContext *context=queryContext();
- if (me->ordinality()>0)
- {
- StringBuffer msg;
- WARNLOG("Exception(s) in %s::%s - %s", serv, meth, me->errorMessage(msg).append('\n').str());
- StringBuffer content;
- switch (context->getResponseFormat())
- {
- case ESPSerializationJSON:
- {
- setContentType(HTTP_TYPE_APPLICATION_JSON_UTF8);
- toJSON(content, me, context->queryRequestParameters()->queryProp("jsonp"));
- break;
- }
- case ESPSerializationXML:
- setContentType(HTTP_TYPE_APPLICATION_XML);
- me->serialize(content);
- break;
- case ESPSerializationANY:
- default:
- {
- if (!errorXslt || !*errorXslt)
- return false;
- setContentType("text/html");
- StringBuffer xml;
- xslTransformHelper(xslp, me->serialize(xml), errorXslt, content, context->queryXslParameters());
- }
- }
- setContent(content);
- send();
- return true;
- }
- return false;
- }
|