httptransport.cpp 70 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427
  1. /*##############################################################################
  2. HPCC SYSTEMS software Copyright (C) 2012 HPCC Systems.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. ############################################################################## */
  13. #pragma warning(disable : 4786)
  14. #ifdef WIN32
  15. #ifdef ESPHTTP_EXPORTS
  16. #define esp_http_decl __declspec(dllexport)
  17. #endif
  18. #endif
  19. //Jlib
  20. #include "jliball.hpp"
  21. //ESP Binidings
  22. #include "http/platform/httptransport.ipp"
  23. #include "bindutil.hpp"
  24. IEspHttpException* createEspHttpException(int code, const char *_msg, const char* _httpstatus)
  25. {
  26. return new CEspHttpException(code, _msg, _httpstatus);
  27. }
  28. bool httpContentFromFile(const char *filepath, StringBuffer &mimetype, MemoryBuffer &fileContents, bool &checkModifiedTime, StringBuffer &lastModified, StringBuffer &etag)
  29. {
  30. StringBuffer strfile(filepath);
  31. if (!checkFileExists(strfile.str()))
  32. if (!checkFileExists(strfile.toUpperCase().str()))
  33. if (!checkFileExists(strfile.toLowerCase().str()))
  34. return false;
  35. Owned<IFile> file = createIFile(strfile.str());
  36. if (file && file->isFile())
  37. {
  38. if (checkModifiedTime)
  39. {
  40. CDateTime createTime, accessedTime, modifiedTime;
  41. file->getTime( &createTime, &modifiedTime, &accessedTime);
  42. if (etag.length() || !lastModified.length())
  43. {
  44. StringBuffer etagSource, etagForThisFile;
  45. modifiedTime.getString(lastModified.clear());
  46. etagSource.appendf("%s+%s", filepath, lastModified.str());
  47. etagForThisFile.append(hashc((unsigned char *)etagSource.str(), etagSource.length(), 0));
  48. if ( !streq(etagForThisFile.str(), etag.str()))
  49. etag.set(etagForThisFile);
  50. else
  51. {
  52. checkModifiedTime = false;
  53. return true;
  54. }
  55. }
  56. else
  57. {
  58. StringBuffer lastModifiedForThisFile;
  59. modifiedTime.getString(lastModifiedForThisFile);
  60. if ( !streq(lastModifiedForThisFile.str(), lastModified.str()))
  61. lastModified.set(lastModifiedForThisFile);
  62. else
  63. {
  64. checkModifiedTime = false;
  65. return true;
  66. }
  67. }
  68. }
  69. Owned<IFileIO> io = file->open(IFOread);
  70. if (io)
  71. {
  72. size32_t filesize = (size32_t)io->size();
  73. io->read(0, filesize, fileContents.reserveTruncate(filesize));
  74. mimetype.clear();
  75. const char *ext = strrchr(filepath, '.');
  76. if (ext)
  77. {
  78. ext++;
  79. if (!stricmp(ext, "html") || !stricmp(ext, "htm"))
  80. mimetype.append("text/html");
  81. else if (!stricmp(ext, "js"))
  82. mimetype.append("text/javascript");
  83. else if (!stricmp(ext, "jpeg") || !stricmp(ext, "jpg"))
  84. mimetype.append("image/gif");
  85. else if (!stricmp(ext, "gif"))
  86. mimetype.append("image/gif");
  87. else if (!stricmp(ext, "png"))
  88. mimetype.append("image/png");
  89. else if (!stricmp(ext, "xml") || !stricmp(ext, "xsl") || !stricmp(ext, "xslt"))
  90. mimetype.append("application/xml");
  91. else if (!stricmp(ext, "txt") || !stricmp(ext, "text"))
  92. mimetype.append("text/plain");
  93. else if (!stricmp(ext, "zip"))
  94. mimetype.append("application/zip");
  95. else if (!stricmp(ext, "pdf"))
  96. mimetype.append("application/pdf");
  97. else if (!stricmp(ext, "pdf"))
  98. mimetype.append("application/pdf");
  99. else if (!stricmp(ext, "xpi"))
  100. mimetype.append("application/x-xpinstall");
  101. else if (!stricmp(ext, "exe") || !stricmp(ext, "class"))
  102. mimetype.append("application/octet-stream");
  103. else if (!stricmp(ext, "css"))
  104. mimetype.append("text/css");
  105. else if (!stricmp(ext, "svg"))
  106. mimetype.append("image/svg+xml");
  107. }
  108. if (!mimetype.length())
  109. mimetype.append("application/octet-stream");
  110. return true;
  111. }
  112. }
  113. return false;
  114. }
  115. bool xmlContentFromFile(const char *filepath, const char *stylesheet, StringBuffer &fileContents)
  116. {
  117. StringBuffer strfile(filepath);
  118. if (!checkFileExists(strfile.str()))
  119. if (!checkFileExists(strfile.toUpperCase().str()))
  120. if (!checkFileExists(strfile.toLowerCase().str()))
  121. return false;
  122. fileContents.loadFile(strfile.str());
  123. if (stylesheet && *stylesheet)
  124. {
  125. StringBuffer stylesheetLine;
  126. stylesheetLine.appendf("<?xml-stylesheet type=\"text/xsl\" href=\"%s\"?>\n", stylesheet);
  127. unsigned fileSize = fileContents.length();
  128. const char* ptr0 = fileContents.str();
  129. char* ptr = (char*) ptr0;
  130. while (*ptr)
  131. {
  132. if((ptr[0] == '<') && (ptr[1] != '!'))
  133. {
  134. if (ptr[1] != '?')
  135. {
  136. fileContents.insert(ptr - ptr0, stylesheetLine);
  137. break;
  138. }
  139. else
  140. {
  141. if ((strncmp(ptr, "<?xml-stylesheet ", 17)==0) || (strncmp(ptr, "<?xml-stylesheet?", 17)==0))
  142. {//Found the line to be replaced
  143. char* ptr1 = ptr + 17;
  144. while (*ptr1)
  145. {
  146. if (ptr1[0] == '>')
  147. {
  148. if (ptr1[1] != '\n')
  149. fileContents.remove(ptr - ptr0, ptr1 - ptr + 1);
  150. else
  151. fileContents.remove(ptr - ptr0, ptr1 - ptr + 2);
  152. fileContents.insert(ptr - ptr0, stylesheetLine);
  153. break;
  154. }
  155. ptr1++;
  156. }
  157. break;
  158. }
  159. }
  160. }
  161. ptr++;
  162. }
  163. }
  164. return true;
  165. }
  166. enum SOAPTag
  167. {
  168. NONE = 0,
  169. ENVELOPE = 1,
  170. HEADER = 2,
  171. SECURITY = 3,
  172. USERNAMETOKEN = 4,
  173. PASSWORD = 5,
  174. BODY = 6
  175. };
  176. class SOAPMessageLog : public CInterface, implements IPTreeNotifyEvent
  177. {
  178. public:
  179. IMPLEMENT_IINTERFACE;
  180. SOAPMessageLog() : m_readNext(true), m_foundPassword(false), m_lastTagFound(NONE), m_pPassword(NULL), m_pStart(NULL)
  181. {
  182. m_messageForLog.clear();
  183. m_skipTag.clear();
  184. };
  185. void logMessage(const char* message, const char* prefix)
  186. {
  187. if (!message || !*message)
  188. return;
  189. m_message = message;
  190. m_pStart = (char*) message;
  191. Owned<IPullPTreeReader> reader = createPullXMLStringReader(m_message, *this, ptr_ignoreNameSpaces);
  192. while(m_readNext && reader->next())
  193. {
  194. if (m_foundPassword)
  195. {
  196. m_pPassword = (char*) m_message + reader->queryOffset();
  197. m_foundPassword = false; //for another password
  198. }
  199. }
  200. if ((m_pStart == message) || (m_messageForLog.length() < 1))
  201. logNow(message, prefix);
  202. else
  203. {
  204. m_messageForLog.append(m_pStart);
  205. logNow(m_messageForLog.str(), prefix);
  206. }
  207. return;
  208. }
  209. virtual void beginNode(const char *tag, offset_t startOffset)
  210. {
  211. if (m_skipTag.length() > 0)
  212. return;
  213. if (strieq(tag, "Body"))
  214. {//no more password
  215. m_readNext = false;
  216. return;
  217. }
  218. switch (m_lastTagFound)
  219. {
  220. case NONE:
  221. if (!strieq(tag, "Envelope"))
  222. m_readNext = false;
  223. else
  224. m_lastTagFound = ENVELOPE;
  225. break;
  226. case ENVELOPE:
  227. if (!strieq(tag, "Header"))
  228. m_skipTag.append(tag);
  229. else
  230. m_lastTagFound = HEADER;
  231. break;
  232. case HEADER:
  233. if (!strieq(tag, "Security"))
  234. m_skipTag.append(tag);
  235. else
  236. m_lastTagFound = SECURITY;
  237. break;
  238. case SECURITY:
  239. if (!strieq(tag, "UsernameToken"))
  240. m_skipTag.append(tag);
  241. else
  242. m_lastTagFound = USERNAMETOKEN;
  243. break;
  244. case USERNAMETOKEN:
  245. if (!strieq(tag, "Password"))
  246. m_skipTag.append(tag);
  247. else
  248. m_lastTagFound = PASSWORD;
  249. break;
  250. default:
  251. m_skipTag.append(tag);
  252. break;
  253. }
  254. }
  255. virtual void endNode(const char *tag, unsigned length, const void *value, bool binary, offset_t endOffset)
  256. {
  257. if (m_skipTag.length() > 0)
  258. {
  259. if (strieq(tag, m_skipTag.str()))
  260. m_skipTag.clear();
  261. return;
  262. }
  263. switch (m_lastTagFound)
  264. {
  265. case SECURITY:
  266. if (strieq(tag, "Security"))
  267. m_readNext = false;
  268. break;
  269. case USERNAMETOKEN:
  270. if (strieq(tag, "UsernameToken"))
  271. m_lastTagFound = SECURITY;
  272. break;
  273. case PASSWORD:
  274. if (!strieq(tag, "Password") || !m_pPassword || !m_pStart)
  275. {//should not happen
  276. m_readNext = false;
  277. return;
  278. }
  279. m_messageForLog.append(m_pStart, 0, m_pPassword - m_pStart);
  280. m_messageForLog.append("(hidden)");
  281. m_pStart = m_pPassword + length; //remember the rest of message
  282. //Go back to SuerNameToken node
  283. m_lastTagFound = USERNAMETOKEN;
  284. break;
  285. }
  286. return;
  287. }
  288. virtual void beginNodeContent(const char *tag)
  289. {
  290. if (m_skipTag.length() > 0)
  291. return;
  292. if (m_lastTagFound == PASSWORD)
  293. m_foundPassword = true;
  294. return;
  295. }
  296. virtual void newAttribute(const char *name, const char *value)
  297. {
  298. return;
  299. }
  300. private:
  301. void logNow(const char* message, const char* prefix)
  302. {
  303. if (prefix && *prefix)
  304. DBGLOG("%s%s", prefix, message);
  305. else
  306. DBGLOG("%s", message);
  307. return;
  308. }
  309. private:
  310. StringBuffer m_messageForLog;
  311. StringBuffer m_skipTag;
  312. SOAPTag m_lastTagFound;
  313. const char *m_message;
  314. char *m_pStart;
  315. char *m_pPassword;
  316. bool m_foundPassword;
  317. bool m_readNext;
  318. };
  319. /***************************************************************************
  320. CHttpMessage Implementation
  321. This class implements common functions shared by both CHttpRequest
  322. and CHttpResponse
  323. ****************************************************************************/
  324. CHttpMessage::CHttpMessage(ISocket& socket) : m_socket(socket)
  325. {
  326. m_bufferedsocket.setown(createBufferedSocket(&socket));
  327. m_content_length = -1;
  328. m_content_length64 = -1;
  329. m_port = 80;
  330. m_paramCount = 0;
  331. m_attachCount = 0;
  332. m_supportClientXslt=-1;
  333. m_isForm = false;
  334. };
  335. CHttpMessage::~CHttpMessage()
  336. {
  337. try
  338. {
  339. m_bufferedsocket.clear();
  340. m_context.clear();
  341. m_queryparams.clear();
  342. m_content_stream.clear();
  343. }
  344. catch(...)
  345. {
  346. ERRLOG("In CHttpMessage::~CHttpMessage() -- Unknown exception.");
  347. }
  348. };
  349. int CHttpMessage::parseOneHeader(char* oneline)
  350. {
  351. if(!oneline)
  352. return -1;
  353. char* name = oneline;
  354. while(*name == ' ')
  355. name++;
  356. char* end = name;
  357. while(*end != '\0' && *end != ':')
  358. end++;
  359. char* value;
  360. if (*end == ':')
  361. {
  362. *end = '\0';
  363. value = end + 1;
  364. }
  365. else
  366. value = end;
  367. while(*value == ' ')
  368. value++;
  369. if(!stricmp(name, "Content-Type"))
  370. {
  371. m_content_type.set(value);
  372. }
  373. else if(!stricmp(name, "Content-Length"))
  374. {
  375. if(value != NULL)
  376. {
  377. m_content_length = atoi(value);
  378. m_content_length64 = atoi64_l(value,strlen(value));
  379. }
  380. }
  381. else if(!stricmp(name, "Host"))
  382. {
  383. if(value != NULL)
  384. {
  385. char* colon = strchr(value, ':');
  386. if(colon != NULL)
  387. {
  388. *colon = '\0';
  389. char* port = colon + 1;
  390. if(port != NULL)
  391. {
  392. m_port = atoi(port);
  393. }
  394. }
  395. m_host.set(value);
  396. }
  397. }
  398. else if(!stricmp(name, "Set-Cookie") || !stricmp(name, "Cookie"))
  399. {
  400. parseCookieHeader(value);
  401. }
  402. else
  403. {
  404. addHeader(name, value); //Insert into headers hashtable
  405. }
  406. return 0;
  407. }
  408. bool CHttpMessage::supportClientXslt()
  409. {
  410. if (m_supportClientXslt==-1)
  411. {
  412. bool ie6=false;
  413. bool moz5=false;
  414. bool opera=false;
  415. bool ff=false;
  416. StringBuffer uastr;
  417. getHeader("User-Agent", uastr);
  418. char *uagent=strdup(uastr.str());
  419. char *saveptr;
  420. char *token = strtok_r(uagent, "();", &saveptr);
  421. while(token)
  422. {
  423. while (*token==' ') token++;
  424. if (!strnicmp(token, "msie", 4))
  425. ie6=(token[5]>='6');
  426. else if (!strnicmp(token, "mozilla", 7))
  427. moz5=(token[8]>='5');
  428. else if (!strnicmp(token, "opera", 5))
  429. opera=true;
  430. else if (!strnicmp(token, "firefox", 7))
  431. ff=true;
  432. token = strtok_r( NULL, "();" , &saveptr);
  433. }
  434. free(uagent);
  435. m_supportClientXslt=(ff || moz5 || (ie6 && !opera)) ? 1 : 0;
  436. }
  437. return m_supportClientXslt==1;
  438. }
  439. void CHttpMessage::addParameter(const char* paramname, const char *value)
  440. {
  441. if (!m_queryparams)
  442. m_queryparams.setown(createProperties(false));
  443. if (strcmp(paramname,"form")==0)
  444. m_isForm = true;
  445. if (!m_isForm)
  446. {
  447. // remove the leading '.'
  448. if (*paramname=='.')
  449. paramname++;
  450. }
  451. m_queryparams->setProp(paramname, value);
  452. m_paramCount++;
  453. }
  454. StringBuffer& CHttpMessage::getParameter(const char* paramname, StringBuffer& paramval)
  455. {
  456. if (m_queryparams)
  457. {
  458. const char *value = m_queryparams->queryProp(paramname);
  459. if (value)
  460. paramval.append(value);
  461. }
  462. return paramval;
  463. }
  464. void CHttpMessage::addAttachment(const char* name, StringBuffer& value)
  465. {
  466. if(name != NULL)
  467. {
  468. m_attachments.setValue(name, value);
  469. m_attachCount++;
  470. }
  471. }
  472. StringBuffer& CHttpMessage::getAttachment(const char* name, StringBuffer& attachment)
  473. {
  474. StringBuffer *value = m_attachments.getValue(name);
  475. if (value)
  476. {
  477. attachment.append(value->length(), value->str());
  478. }
  479. return attachment;
  480. }
  481. StringBuffer& CHttpMessage::getParamStr(StringBuffer& ret)
  482. {
  483. return ret.append(m_paramstr);
  484. }
  485. IProperties *CHttpMessage::queryParameters()
  486. {
  487. if (!m_queryparams)
  488. m_queryparams.setown(createProperties(false));
  489. return m_queryparams.get();
  490. }
  491. IProperties *CHttpMessage::getParameters()
  492. {
  493. if (!m_queryparams)
  494. m_queryparams.setown(createProperties(false));
  495. return m_queryparams.getLink();
  496. }
  497. int CHttpMessage::processHeaders(IMultiException *me)
  498. {
  499. return 0;
  500. }
  501. int CHttpMessage::readContent()
  502. {
  503. char buf[1024 + 1];
  504. int buflen = 1024;
  505. if(m_content_length > 0)
  506. {
  507. int totallen = m_content_length;
  508. if(buflen > totallen)
  509. buflen = totallen;
  510. int readlen = 0;
  511. for(;;)
  512. {
  513. readlen = m_bufferedsocket->read(buf, buflen);
  514. if(readlen < 0)
  515. {
  516. DBGLOG(">> Socket timed out because of incorrect Content-Length passed in from the other side");
  517. break;
  518. }
  519. if(readlen == 0)
  520. break;
  521. buf[readlen] = 0;
  522. m_content.append(readlen, buf);
  523. totallen -= readlen;
  524. if(totallen <= 0)
  525. break;
  526. if(buflen > totallen)
  527. buflen = totallen;
  528. }
  529. return 0;
  530. }
  531. return 0;
  532. }
  533. int CHttpMessage::readContentTillSocketClosed()
  534. {
  535. const int buflen = 1024;
  536. char buf[buflen + 1];
  537. StringBuffer headerValue;
  538. getHeader("Transfer-Encoding", headerValue);
  539. if (!stricmp(headerValue.str(), "chunked"))//Transfer-Encoding: chunked
  540. {
  541. for(;;)
  542. {
  543. int readlen = m_bufferedsocket->readline(buf, buflen, NULL);
  544. if(readlen <= 0)
  545. break;
  546. buf[readlen] = 0;
  547. int chunkSize;
  548. sscanf(buf, "%x", &chunkSize);
  549. if (chunkSize<=0)
  550. break;
  551. while (chunkSize > 0)
  552. {
  553. const int len = min(chunkSize, buflen);
  554. readlen = m_bufferedsocket->read(buf, len);
  555. if(readlen <= 0)
  556. break;
  557. chunkSize -= readlen;
  558. m_content.append(readlen, buf);
  559. }
  560. if (m_bufferedsocket->read(buf, 2) <= 0)//CR/LF
  561. break;
  562. }
  563. }
  564. else
  565. {
  566. for(;;)
  567. {
  568. int readlen = m_bufferedsocket->read(buf, buflen);
  569. if(readlen <= 0)
  570. break;
  571. buf[readlen] = 0;
  572. m_content.append(readlen, buf);
  573. }
  574. }
  575. return 0;
  576. }
  577. int CHttpMessage::receive(bool alwaysReadContent, IMultiException *me)
  578. {
  579. if (processHeaders(me)==-1)
  580. return -1;
  581. if (getEspLogLevel()>LogNormal)
  582. DBGLOG("Headers processed! content_length = %d", m_content_length);
  583. if (isUpload())
  584. return 0;
  585. m_context->addTraceSummaryValue("contLen", m_content_length);
  586. if(m_content_length > 0)
  587. {
  588. readContent();
  589. if (getEspLogLevel()>LogNormal)
  590. DBGLOG("length of content read = %d", m_content.length());
  591. }
  592. else if (alwaysReadContent && m_content_length == -1)
  593. {
  594. //HTTP protocol does not require a content length: read until socket closed
  595. readContentTillSocketClosed();
  596. if (getEspLogLevel()>LogNormal)
  597. DBGLOG("length of content read = %d", m_content.length());
  598. }
  599. if (getEspLogRequests() || getEspLogLevel()>LogNormal)
  600. logMessage(LOGCONTENT, "HTTP content received:\n");
  601. return 0;
  602. }
  603. StringBuffer& CHttpMessage::getContent(StringBuffer& content)
  604. {
  605. content.append(m_content.length(), m_content.str());
  606. return content;
  607. }
  608. void CHttpMessage::setContent(const char* content)
  609. {
  610. m_content.clear();
  611. m_content.append(content);
  612. m_content_length = strlen(content);
  613. }
  614. void CHttpMessage::setContent(unsigned len, const char* content)
  615. {
  616. m_content.clear();
  617. m_content.append(len, content);
  618. m_content_length = len;
  619. }
  620. void CHttpMessage::setownContent(char* content)
  621. {
  622. size32_t len=strlen(content);
  623. m_content.setBuffer(len+1, content, len);
  624. m_content_length = len;
  625. }
  626. void CHttpMessage::setownContent(unsigned len, char* content)
  627. {
  628. m_content.setBuffer(len+1, content, len);
  629. m_content_length = len;
  630. }
  631. void CHttpMessage::setContent(IFileIOStream* stream)
  632. {
  633. if(stream != NULL)
  634. {
  635. m_content.clear();
  636. m_content_length = (int)stream->size();
  637. m_content_length64 = stream->size();
  638. m_content_stream.setown(stream);
  639. }
  640. }
  641. /*
  642. void CHttpMessage::appendContent(const char* content)
  643. {
  644. m_content.append(content);
  645. m_content_length += strlen(content);
  646. }
  647. */
  648. StringBuffer& CHttpMessage::getContentType(StringBuffer& contenttype)
  649. {
  650. contenttype.append(m_content_type);
  651. return contenttype;
  652. }
  653. void CHttpMessage::setContentType(const char* contenttype)
  654. {
  655. m_content_type.set(contenttype);
  656. }
  657. void CHttpMessage::setVersion(const char* version)
  658. {
  659. m_version.set(version);
  660. }
  661. int CHttpMessage::parseFirstLine(char* oneline)
  662. {
  663. return 0;
  664. }
  665. void CHttpMessage::parseCookieHeader(char* cookiestr)
  666. {
  667. }
  668. StringBuffer& CHttpMessage::constructHeaderBuffer(StringBuffer& headerbuf, bool inclLen)
  669. {
  670. return headerbuf;
  671. }
  672. void CHttpMessage::logMessage(const char* message, const char* prefix, const char* find, const char* replace)
  673. {
  674. if (!message || !*message)
  675. return;
  676. if (!find || !*find || !replace || !*replace)
  677. {
  678. if (prefix && *prefix)
  679. DBGLOG("%s%s", prefix, message);
  680. else
  681. DBGLOG("%s", message);
  682. return;
  683. }
  684. RegExpr auth(find, true);
  685. StringBuffer messageToLog = message;
  686. if (auth.find(messageToLog.str()))
  687. auth.replace(replace, messageToLog.length() + strlen(replace) - strlen(find));
  688. if (prefix && *prefix)
  689. DBGLOG("%s%s", prefix, messageToLog.str());
  690. else
  691. DBGLOG("%s", messageToLog.str());
  692. return;
  693. }
  694. void CHttpMessage::logSOAPMessage(const char* message, const char* prefix)
  695. {
  696. SOAPMessageLog messageLog;
  697. messageLog.logMessage(message, prefix);
  698. return;
  699. }
  700. void CHttpMessage::logMessage(MessageLogFlag messageLogFlag, const char *prefix)
  701. {
  702. try
  703. {
  704. if (((messageLogFlag == LOGHEADERS) || (messageLogFlag == LOGALL)) && (m_header.length() > 0))
  705. logMessage(m_header.str(), prefix, "Authorization:[~\r\n]*", "Authorization: (hidden)");
  706. if (((messageLogFlag == LOGCONTENT) || (messageLogFlag == LOGALL)) && (m_content.length() > 0))
  707. {//log content
  708. if ((m_header.length() > 0) && (startsWith(m_header.str(), "POST /ws_access/AddUser")
  709. || startsWith(m_header.str(), "POST /ws_access/UserResetPass") || startsWith(m_header.str(), "POST /ws_account/UpdateUser")))
  710. DBGLOG("%s<For security, ESP does not log the content of this request.>", prefix);
  711. else if (isSoapMessage())
  712. logSOAPMessage(m_content.str(), prefix);
  713. else if(!isTextMessage())
  714. DBGLOG("%s<non-text content or content type not specified>", prefix);
  715. else if ((m_content_type.length() > 0) && (strieq(m_content_type.get(), "text/css") || strieq(m_content_type.get(), "text/javascript")))
  716. DBGLOG("%s<content_type: %s>", prefix, m_content_type.get());
  717. else
  718. logMessage(m_content.str(), prefix);
  719. }
  720. }
  721. catch (IException *e)
  722. {
  723. StringBuffer msg;
  724. ERRLOG("EXCEPTION %s when logging the message: %s", e->errorMessage(msg).str(), m_content.str());
  725. if (m_content_type.length() > 0)
  726. ERRLOG("EXCEPTION %s when logging the message (m_content_type:%s):%s", e->errorMessage(msg).str(), m_content_type.get(), m_content.str());
  727. else
  728. ERRLOG("EXCEPTION %s when logging the message: %s", e->errorMessage(msg).str(), m_content.str());
  729. e->Release();
  730. }
  731. return;
  732. }
  733. int CHttpMessage::send()
  734. {
  735. StringBuffer headers;
  736. constructHeaderBuffer(headers, true);
  737. int retcode = 0;
  738. // If m_content is empty but m_content_stream is set, the stream will not be logged here.
  739. if (getEspLogResponses() || getEspLogLevel(queryContext())>LogNormal)
  740. {
  741. logMessage(headers.str(), "Sending out HTTP headers:\n", "Authorization:[~\r\n]*", "Authorization: (hidden)");
  742. if(m_content_length > 0 && m_content.length() > 0)
  743. logMessage(LOGCONTENT, "Sending out HTTP content:\n");
  744. }
  745. try
  746. {
  747. m_socket.write(headers.str(), headers.length());
  748. if(m_content_length > 0 && m_content.length() > 0)
  749. m_socket.write(m_content.str(), m_content.length());
  750. }
  751. catch (IException *e)
  752. {
  753. StringBuffer estr;
  754. DBGLOG("In CHttpMessage::send(%d) -- Exception(%d, %s) writing to socket(%d).", __LINE__, e->errorCode(), e->errorMessage(estr).str(), m_socket.OShandle());
  755. e->Release();
  756. return -1;
  757. }
  758. catch(...)
  759. {
  760. ERRLOG("In CHttpMessage::send(%d) -- Unknown exception writing to socket(%d).", __LINE__, m_socket.OShandle());
  761. return -1;
  762. }
  763. // When m_content is empty but the stream was set, read content from the stream.
  764. if(((m_content_length > 0 && m_content.length() == 0) || (m_content_length64 > 0)) && m_content_stream.get() != NULL)
  765. {
  766. //Read the file and send out 20K at a time.
  767. __int64 content_length = m_content_length;
  768. if ((m_content_length64 > 0) && (content_length != m_content_length64))
  769. content_length = m_content_length64;
  770. int buflen = 20*1024;
  771. if(buflen > content_length)
  772. buflen = (int) content_length;
  773. char* buffer = new char[buflen + 1];
  774. __int64 sizesent = 0;
  775. while(sizesent < content_length)
  776. {
  777. int sizeread = m_content_stream->read(buflen, buffer);
  778. if(sizeread > 0)
  779. {
  780. sizesent += sizeread;
  781. try
  782. {
  783. m_socket.write(buffer, sizeread);
  784. }
  785. catch (IException *e)
  786. {
  787. StringBuffer estr;
  788. LOG(MCexception(e), "In CHttpMessage::send(%d) -- Exception(%d, %s) writing to socket(%d).", __LINE__, e->errorCode(), e->errorMessage(estr).str(), m_socket.OShandle());
  789. e->Release();
  790. retcode = -1;
  791. break;
  792. }
  793. catch(...)
  794. {
  795. ERRLOG("In CHttpMessage::send(%d) -- Unknown exception writing to socket(%d).", __LINE__, m_socket.OShandle());
  796. retcode = -1;
  797. break;
  798. }
  799. }
  800. else
  801. {
  802. ERRLOG("Error read from file");
  803. break;
  804. }
  805. }
  806. delete buffer;
  807. }
  808. return retcode;
  809. }
  810. int CHttpMessage::startSend()
  811. {
  812. StringBuffer sendbuf;
  813. constructHeaderBuffer(sendbuf, false);
  814. if (getEspLogLevel(queryContext())>LogNormal)
  815. DBGLOG("Start Sending chunked HTTP message:\n %s", sendbuf.str());
  816. try
  817. {
  818. m_socket.write(sendbuf.str(), sendbuf.length());
  819. }
  820. catch (IException *e)
  821. {
  822. StringBuffer estr;
  823. DBGLOG("In CHttpMessage::send() -- Exception(%d, %s) writing to socket(%d).", e->errorCode(), e->errorMessage(estr).str(), m_socket.OShandle());
  824. e->Release();
  825. return -1;
  826. }
  827. catch(...)
  828. {
  829. ERRLOG("In CHttpMessage::send() -- Unknown exception writing to socket(%d).", m_socket.OShandle());
  830. return -1;
  831. }
  832. return 0;
  833. }
  834. int CHttpMessage::sendChunk(const char *chunk)
  835. {
  836. if (getEspLogLevel(queryContext())>LogNormal)
  837. DBGLOG("Sending HTTP chunk:\n %s", chunk);
  838. try
  839. {
  840. m_socket.write(chunk, strlen(chunk));
  841. }
  842. catch (IException *e)
  843. {
  844. StringBuffer estr;
  845. DBGLOG("In CHttpMessage::send() -- Exception(%d, %s) writing to socket(%d).", e->errorCode(), e->errorMessage(estr).str(), m_socket.OShandle());
  846. e->Release();
  847. return -1;
  848. }
  849. catch(...)
  850. {
  851. ERRLOG("In CHttpMessage::send() -- Unknown exception writing to socket(%d).", m_socket.OShandle());
  852. return -1;
  853. }
  854. return 0;
  855. }
  856. int CHttpMessage::sendFinalChunk(const char *chunk)
  857. {
  858. if (getEspLogLevel(queryContext())>LogNormal)
  859. DBGLOG("Sending HTTP Final chunk:\n %s", chunk);
  860. try
  861. {
  862. m_socket.write(chunk, strlen(chunk));
  863. m_socket.close();
  864. }
  865. catch (IException *e)
  866. {
  867. StringBuffer estr;
  868. DBGLOG("In CHttpMessage::send() -- Exception(%d, %s) writing to socket(%d).", e->errorCode(), e->errorMessage(estr).str(), m_socket.OShandle());
  869. e->Release();
  870. return -1;
  871. }
  872. catch(...)
  873. {
  874. ERRLOG("In CHttpMessage::send() -- Unknown exception writing to socket(%d).", m_socket.OShandle());
  875. return -1;
  876. }
  877. return 0;
  878. }
  879. int CHttpMessage::close()
  880. {
  881. int ret = 0;
  882. try
  883. {
  884. if(&m_socket != NULL)
  885. {
  886. m_socket.shutdown();
  887. m_socket.close();
  888. }
  889. }
  890. catch (IException *e)
  891. {
  892. StringBuffer estr;
  893. ERRLOG("Exception(%d, %s) - CHttpMessage::close(), closing socket.", e->errorCode(), e->errorMessage(estr).str());
  894. e->Release();
  895. ret = -1;
  896. }
  897. catch(...)
  898. {
  899. ERRLOG("General Exception - CHttpMessage::close(), closing socket.");
  900. ret = -1;
  901. }
  902. return ret;
  903. }
  904. void CHttpMessage::setHeader(const char* headername, const char* headerval)
  905. {
  906. if(!headername || !*headername)
  907. return;
  908. StringBuffer val;
  909. val.append(headername).append(": ").append(headerval);
  910. ForEachItemIn(x, m_headers)
  911. {
  912. const char* curst = m_headers.item(x);
  913. if(!curst)
  914. continue;
  915. const char* colon = strchr(curst, ':');
  916. if(!colon)
  917. continue;
  918. if(!strnicmp(headername, curst, colon - curst))
  919. {
  920. m_headers.replace(val.str(), x);
  921. return;
  922. }
  923. }
  924. m_headers.append(val.str());
  925. }
  926. void CHttpMessage::addHeader(const char* headername, const char* headerval)
  927. {
  928. if(headername == NULL || strlen(headername) == 0)
  929. return;
  930. StringBuffer header;
  931. header.append(headername);
  932. header.append(": ");
  933. header.append(headerval);
  934. m_headers.append(header.str());
  935. }
  936. StringBuffer& CHttpMessage::getHeader(const char* headername, StringBuffer& headerval)
  937. {
  938. if(headername == NULL || strlen(headername) == 0)
  939. return headerval;
  940. ForEachItemIn(x, m_headers)
  941. {
  942. const char* header = m_headers.item(x);
  943. if(header == NULL)
  944. continue;
  945. const char* colon = strchr(header, ':');
  946. if(colon == NULL)
  947. continue;
  948. if(strncmp(headername, header, colon - header) == 0)
  949. {
  950. headerval.append(colon + 2);
  951. break;
  952. }
  953. }
  954. return headerval;
  955. }
  956. bool isSoapContentType(const char* contenttype)
  957. {
  958. if(contenttype == NULL)
  959. return false;
  960. else
  961. return Utils::strncasecmp(contenttype, HTTP_TYPE_TEXT_XML, strlen(HTTP_TYPE_TEXT_XML)) == 0 ||
  962. Utils::strncasecmp(contenttype, HTTP_TYPE_SOAP, strlen(HTTP_TYPE_SOAP)) == 0;
  963. }
  964. bool CHttpMessage::isSoapMessage()
  965. {
  966. if(m_content_type.get() == NULL)
  967. return false;
  968. else if(Utils::strncasecmp(m_content_type.get(), HTTP_TYPE_MULTIPART_RELATED, strlen(HTTP_TYPE_MULTIPART_RELATED)) == 0)
  969. {
  970. CMimeMultiPart* mpart = queryMultiPart();
  971. if(mpart == NULL)
  972. return false;
  973. CMimeBodyPart* bpart = mpart->queryRootPart();
  974. if(bpart != NULL && isSoapContentType(bpart->getContentType()))
  975. return true;
  976. else
  977. return false;
  978. }
  979. else
  980. return isSoapContentType(m_content_type.get());
  981. }
  982. bool CHttpMessage::isFormSubmission()
  983. {
  984. return ((hasContentType(NULL) && (m_paramCount + m_attachCount) > 0) ||
  985. hasContentType(HTTP_TYPE_MULTIPART_FORMDATA) ||
  986. hasContentType(HTTP_TYPE_FORM_ENCODED));
  987. }
  988. /******************************************************************************
  989. CHttpRequest Implementation
  990. *******************************************************************************/
  991. CHttpRequest::CHttpRequest(ISocket& socket) : CHttpMessage(socket), m_pathIsParsed(false),
  992. m_sstype(sub_serv_unknown), m_MaxRequestEntityLength(0)
  993. {
  994. };
  995. CHttpRequest::~CHttpRequest()
  996. {
  997. };
  998. StringBuffer& CHttpRequest::getMethod(StringBuffer & method)
  999. {
  1000. return method.append(m_httpMethod.str());
  1001. }
  1002. void CHttpRequest::setMethod(const char* method)
  1003. {
  1004. m_httpMethod.clear().append(method);
  1005. }
  1006. StringBuffer& CHttpRequest::getPath(StringBuffer & path)
  1007. {
  1008. return path.append(m_httpPath.str());
  1009. }
  1010. void CHttpRequest::setPath(const char* path)
  1011. {
  1012. m_httpPath.clear().append(path);
  1013. }
  1014. void CHttpRequest::parseQueryString(const char* querystr)
  1015. {
  1016. if(!querystr || !*querystr)
  1017. return;
  1018. bool useHeap = false;
  1019. int querystrlen = strlen(querystr);
  1020. if(querystrlen >= 0x80000)
  1021. useHeap = true;
  1022. char* querystrbuf = NULL;
  1023. if(useHeap)
  1024. querystrbuf = (char*)malloc(querystrlen + 1);
  1025. else
  1026. querystrbuf = (char*)alloca(querystrlen + 1);
  1027. strcpy(querystrbuf, querystr);
  1028. char* ptr = querystrbuf;
  1029. char* curname = ptr;
  1030. char* curvalue = NULL;
  1031. while(true)
  1032. {
  1033. while(*ptr != '\0' && *ptr != '=' && *ptr != '&')
  1034. ptr++;
  1035. if(*ptr == '\0')
  1036. {
  1037. StringBuffer nameval;
  1038. Utils::url_decode(curname, nameval);
  1039. addParameter(nameval.str(), "");
  1040. break;
  1041. }
  1042. else if(*ptr == '=')
  1043. {
  1044. *ptr = '\0';
  1045. ptr++;
  1046. if(*ptr == '\0')
  1047. {
  1048. StringBuffer nameval;
  1049. Utils::url_decode(curname, nameval);
  1050. addParameter(nameval.str(), "");
  1051. break;
  1052. }
  1053. else if(*ptr == '&')
  1054. {
  1055. StringBuffer nameval;
  1056. Utils::url_decode(curname, nameval);
  1057. addParameter(nameval.str(), "");
  1058. ptr++;
  1059. if(*ptr == '\0')
  1060. break;
  1061. else
  1062. curname = ptr;
  1063. }
  1064. else
  1065. {
  1066. curvalue = ptr;
  1067. while(*ptr != '\0' && *ptr != '&')
  1068. ptr++;
  1069. if(*ptr == '\0')
  1070. {
  1071. StringBuffer nameval;
  1072. StringBuffer valueval;
  1073. Utils::url_decode(curname, nameval);
  1074. Utils::url_decode(curvalue, valueval);
  1075. addParameter(nameval.str(), valueval.str());
  1076. break;
  1077. }
  1078. else //*ptr == '&'
  1079. {
  1080. *ptr = '\0';
  1081. ptr++;
  1082. StringBuffer nameval;
  1083. StringBuffer valueval;
  1084. Utils::url_decode(curname, nameval);
  1085. Utils::url_decode(curvalue, valueval);
  1086. addParameter(nameval.str(), valueval.str());
  1087. if(*ptr == '\0')
  1088. break;
  1089. else
  1090. curname = ptr;
  1091. }
  1092. }
  1093. }
  1094. else if(*ptr == '&')
  1095. {
  1096. *ptr=0;
  1097. StringBuffer nameval;
  1098. Utils::url_decode(curname, nameval);
  1099. addParameter(nameval.str(), "");
  1100. ptr++;
  1101. if(!*ptr)
  1102. break;
  1103. else
  1104. curname = ptr;
  1105. }
  1106. }
  1107. if(useHeap && querystrbuf != NULL)
  1108. delete querystrbuf;
  1109. }
  1110. int CHttpRequest::parseFirstLine(char* oneline)
  1111. {
  1112. //if (getEspLogLevel()>LogNormal)
  1113. // DBGLOG("First Line of request=%s", oneline);
  1114. DBGLOG("HTTP First Line: %s", oneline);
  1115. if(*oneline == 0)
  1116. return -1;
  1117. const char* curptr = oneline;
  1118. StringBuffer method;
  1119. curptr = Utils::getWord(curptr, method);
  1120. if(!stricmp(method.str(), POST_METHOD))
  1121. {
  1122. setMethod(POST_METHOD);
  1123. }
  1124. else if(!stricmp(method.str(), GET_METHOD))
  1125. {
  1126. setMethod(GET_METHOD);
  1127. }
  1128. else if(!stricmp(method.str(), HEAD_METHOD))
  1129. {
  1130. setMethod(HEAD_METHOD);
  1131. }
  1132. StringBuffer pathbuf;
  1133. curptr = Utils::getWord(curptr, pathbuf);
  1134. int len = pathbuf.length();
  1135. char* buff;
  1136. if(len == 0)
  1137. {
  1138. buff = new char[2];
  1139. buff[0] = '/';
  1140. buff[1] = '\0';
  1141. }
  1142. else
  1143. {
  1144. if(pathbuf.charAt(0) != '/')
  1145. {
  1146. buff = new char[len + 2];
  1147. buff[0] = '/';
  1148. strcpy(buff + 1, pathbuf.str());
  1149. }
  1150. else
  1151. {
  1152. buff = new char[len + 1];
  1153. strcpy(buff, pathbuf.str());
  1154. }
  1155. }
  1156. char* qmark = strchr(buff, '?');
  1157. if(qmark != NULL)
  1158. {
  1159. *qmark = '\0';
  1160. }
  1161. // Decode path
  1162. StringBuffer path;
  1163. Utils::url_decode(buff, path);
  1164. setPath(path.str());
  1165. // Parse and decode parameters
  1166. if(qmark != NULL)
  1167. {
  1168. char* querystr = qmark + 1;
  1169. m_paramstr.set(querystr);
  1170. addParameter("__querystring", querystr); //MORE- requested by dimitri
  1171. parseQueryString(querystr);
  1172. }
  1173. delete[] buff;
  1174. return 0;
  1175. }
  1176. void CHttpRequest::parseCookieHeader(char* cookiestr)
  1177. {
  1178. if(cookiestr == NULL)
  1179. return;
  1180. int version;
  1181. char* curword;
  1182. char* curptr = cookiestr;
  1183. const char* separators = ",;";
  1184. curptr = Utils::getWord(curptr, curword, separators);
  1185. StringBuffer name, value;
  1186. Utils::parseNVPair(curword, name, value);
  1187. CEspCookie* cookie = NULL;
  1188. if(name.length() == 0 || stricmp(name.str(), "$Version"))
  1189. {
  1190. version = 0;
  1191. cookie = new CEspCookie(name.str(), value.str());
  1192. cookie->setVersion(version);
  1193. m_cookies.append(*cookie);
  1194. }
  1195. else
  1196. {
  1197. version = atoi(value.str());
  1198. }
  1199. while(curptr != NULL && *curptr != 0)
  1200. {
  1201. curptr = Utils::getWord(curptr, curword, separators);
  1202. if(curword == NULL)
  1203. break;
  1204. StringBuffer name, value;
  1205. Utils::parseNVPair(curword, name, value);
  1206. if(name.length() == 0)
  1207. continue;
  1208. if(name.charAt(0) != '$')
  1209. {
  1210. cookie = new CEspCookie(name.str(), value.str());
  1211. cookie->setVersion(version);
  1212. m_cookies.append(*cookie);
  1213. }
  1214. else if(stricmp(name.str(), "$Path") == 0 && cookie != NULL)
  1215. cookie->setPath(value.str());
  1216. else if(stricmp(name.str(), "$Domain") == 0 && cookie != NULL)
  1217. cookie->setDomain(value.str());
  1218. else if(stricmp(name.str(), "$Port") == 0 && cookie != NULL)
  1219. cookie->setPorts(value.str());
  1220. }
  1221. }
  1222. ESPSerializationFormat lookupResponseFormatByExtension(const char *ext)
  1223. {
  1224. if (!ext || !*ext)
  1225. return ESPSerializationANY;
  1226. if (strieq(ext, ".xml"))
  1227. return ESPSerializationXML;
  1228. if (strieq(ext, ".json"))
  1229. return ESPSerializationJSON;
  1230. return ESPSerializationANY;
  1231. }
  1232. void CHttpRequest::parseEspPathInfo()
  1233. {
  1234. if (!m_pathIsParsed)
  1235. {
  1236. m_espPathEx.clear();
  1237. m_espMethodName.clear();
  1238. m_espServiceName.clear();
  1239. if (queryParameters()->hasProp("rawxml_"))
  1240. m_context->setResponseFormat(ESPSerializationXML);
  1241. else if (isSoapMessage())
  1242. m_context->setResponseFormat(ESPSerializationXML);
  1243. size32_t pathlen=m_httpPath.length();
  1244. if (!pathlen)
  1245. m_sstype=(m_queryparams && m_queryparams->hasProp("main")) ? sub_serv_main : sub_serv_root;
  1246. else
  1247. {
  1248. char *pathstr = strdup(m_httpPath.str());
  1249. char *finger = pathstr;
  1250. if (!strnicmp(finger, "http://", 7))
  1251. finger+=7;
  1252. char *thumb=finger;
  1253. while (*thumb!=0 && *thumb!='/')
  1254. {
  1255. if (*thumb=='@' || *thumb==':')
  1256. {
  1257. finger=strchr(thumb, '/');
  1258. break;
  1259. }
  1260. thumb++;
  1261. }
  1262. bool missingTrailSlash = false;
  1263. if (finger)
  1264. {
  1265. while (*finger == '/')
  1266. finger++;
  1267. //look for the service and method names
  1268. //
  1269. if (finger && finger[0] != '\0')
  1270. {
  1271. thumb=strchr(finger, '/');
  1272. if (thumb)
  1273. {
  1274. char *pathex = strchr(thumb+1, '/');
  1275. if (pathex)
  1276. {
  1277. *pathex=0;
  1278. m_espPathEx.append(pathex+1);
  1279. }
  1280. *thumb=0;
  1281. m_espMethodName.append(++thumb);
  1282. const char *tail = strrchr(thumb, '.');
  1283. ESPSerializationFormat fmt = lookupResponseFormatByExtension(tail);
  1284. if (fmt!=ESPSerializationANY)
  1285. {
  1286. m_context->setResponseFormat(fmt);
  1287. m_espMethodName.setLength(tail-thumb);
  1288. }
  1289. }
  1290. else
  1291. missingTrailSlash = true;
  1292. m_espServiceName.append(finger);
  1293. }
  1294. }
  1295. free(pathstr);
  1296. if (m_espMethodName.length())
  1297. {
  1298. if (!stricmp(m_espMethodName.str(), "files_"))
  1299. m_sstype=sub_serv_files;
  1300. else if (!stricmp(m_espMethodName.str(), "content_"))
  1301. m_sstype=sub_serv_content;
  1302. else if (!stricmp(m_espMethodName.str(), "result_"))
  1303. m_sstype=sub_serv_result;
  1304. else if (!stricmp(m_espMethodName.str(), "iframe"))
  1305. m_sstype=sub_serv_iframe;
  1306. else if (!stricmp(m_espMethodName.str(), "itext"))
  1307. m_sstype=sub_serv_itext;
  1308. else if (!stricmp(m_espMethodName.str(), "version_"))
  1309. m_sstype=sub_serv_getversion;
  1310. }
  1311. //not a special service URL, determine the action type
  1312. if (m_sstype==sub_serv_unknown)
  1313. {
  1314. if (m_queryparams && (m_queryparams->hasProp("wsdl") || m_queryparams->hasProp("wsdl_ext")))
  1315. m_sstype=sub_serv_wsdl;
  1316. else if (m_queryparams && (m_queryparams->hasProp("xsd")))
  1317. m_sstype=sub_serv_xsd;
  1318. else if (m_queryparams && (m_queryparams->hasProp("reqxml_")))
  1319. m_sstype=sub_serv_reqsamplexml;
  1320. else if (m_queryparams && (m_queryparams->hasProp("respxml_")))
  1321. m_sstype=sub_serv_respsamplexml;
  1322. else if (m_queryparams && (m_queryparams->hasProp("soap_builder_")))
  1323. m_sstype=sub_serv_soap_builder;
  1324. else if (m_queryparams && m_queryparams->hasProp("config_"))
  1325. m_sstype=sub_serv_config;
  1326. else if (m_espServiceName.length()==0)
  1327. m_sstype=(m_queryparams && m_queryparams->hasProp("main")) ? sub_serv_main : sub_serv_root;
  1328. else if (m_espMethodName.length()==0)
  1329. m_sstype = missingTrailSlash ? sub_serv_index_redirect : sub_serv_index;
  1330. else if (m_queryparams && m_queryparams->hasProp("form_"))
  1331. m_sstype=sub_serv_form;
  1332. else if (m_queryparams && m_queryparams->hasProp("form"))
  1333. m_sstype=sub_serv_xform;
  1334. else if (isUpload())
  1335. m_sstype=sub_serv_file_upload;
  1336. else if (getParameterCount())// queryParamStr()!=NULL && *queryParamStr()!=0)
  1337. m_sstype=sub_serv_query;
  1338. else
  1339. m_sstype=sub_serv_method;
  1340. }
  1341. }
  1342. m_pathIsParsed=true;
  1343. }
  1344. }
  1345. void CHttpRequest::getEspPathInfo(sub_service &sstype, StringBuffer *pathEx, StringBuffer *service, StringBuffer *method, bool upcase)
  1346. {
  1347. parseEspPathInfo();
  1348. sstype = m_sstype;
  1349. if (pathEx)
  1350. {
  1351. pathEx->clear().append(m_espPathEx);
  1352. if (upcase)
  1353. pathEx->toUpperCase();
  1354. }
  1355. if (service)
  1356. {
  1357. service->clear().append(m_espServiceName);
  1358. service->toUpperCase();
  1359. }
  1360. if (method)
  1361. {
  1362. method->clear().append(m_espMethodName);
  1363. method->toUpperCase();
  1364. }
  1365. }
  1366. void CHttpRequest::getBasicRealm(StringBuffer& realm)
  1367. {
  1368. StringBuffer authheader;
  1369. getHeader("WWW-Authenticate", authheader);
  1370. if(authheader.length() == 0)
  1371. return;
  1372. if(Utils::strncasecmp(authheader.str(), "Basic ", strlen("Basic ")) != 0)
  1373. return;
  1374. const char* strt = strchr(authheader.str(), '\"');
  1375. ++strt;
  1376. if (strt)
  1377. {
  1378. const char* end = strchr(strt, '\"');
  1379. if (end)
  1380. {
  1381. realm.append(strt, 0, end - strt);
  1382. }
  1383. }
  1384. }
  1385. int CHttpRequest::getPeerPort()
  1386. {
  1387. char peername[256];
  1388. return m_socket.peer_name(peername, 256);
  1389. }
  1390. StringBuffer& CHttpRequest::getPeer(StringBuffer& Peer)
  1391. {
  1392. StringBuffer ForwardIPs;
  1393. getHeader("X-Forwarded-For", ForwardIPs);
  1394. if(ForwardIPs.length() != 0)
  1395. {
  1396. //IPs will ne in the form xxx.xxx.xxx.xxx,yyy.yyy.yyy.yyy,zzz.zzz.zzz.zzz
  1397. //We want to take the first IP in the list
  1398. const char* strt = strchr(ForwardIPs.str(), ',');
  1399. if(strt!= NULL)
  1400. Peer.append(strt - ForwardIPs.str(),ForwardIPs.str());
  1401. else
  1402. Peer.appendf("%s",ForwardIPs.str());
  1403. }
  1404. else
  1405. {
  1406. char peerchr[256];
  1407. int port = m_socket.peer_name(peerchr, 256);
  1408. Peer.append(peerchr);
  1409. }
  1410. return Peer;
  1411. }
  1412. void CHttpRequest::getBasicAuthorization(StringBuffer& userid, StringBuffer& password,StringBuffer& realm)
  1413. {
  1414. StringBuffer authheader;
  1415. getHeader("Authorization", authheader);
  1416. if(authheader.length() == 0)
  1417. return;
  1418. if(Utils::strncasecmp(authheader.str(), "Basic ", strlen("Basic ")) != 0)
  1419. return;
  1420. StringBuffer uidpair;
  1421. Utils::base64decode(authheader.length() - strlen("Basic "), authheader.str() + strlen("Basic "), uidpair);
  1422. const char* pairstr = strchr(uidpair.str(), '\\');
  1423. if(pairstr!=NULL)
  1424. {
  1425. realm.append(pairstr - uidpair.str(),uidpair.str());
  1426. pairstr++;
  1427. }
  1428. else
  1429. {
  1430. pairstr = uidpair.str();
  1431. getBasicRealm(realm);
  1432. }
  1433. const char* colon = strchr(pairstr, ':');
  1434. if(colon == NULL)
  1435. {
  1436. userid.append(pairstr);
  1437. }
  1438. else
  1439. {
  1440. userid.append(colon - pairstr, pairstr);
  1441. password.append(colon + 1);
  1442. }
  1443. }
  1444. int CHttpRequest::receive(IMultiException *me)
  1445. {
  1446. if (CHttpMessage::receive(false, me)==-1)
  1447. return -1;
  1448. //if(hasContentType("application/x-www-form-urlencoded"))
  1449. if(hasContentType(HTTP_TYPE_FORM_ENCODED))
  1450. {
  1451. parseQueryString(m_content.str());
  1452. }
  1453. else if(hasContentType(HTTP_TYPE_MULTIPART_FORMDATA) && !isUpload())
  1454. {
  1455. CMimeMultiPart* mpart = queryMultiPart();
  1456. if(mpart != NULL)
  1457. {
  1458. int count = mpart->getBodyCount();
  1459. for(int i = 0; i < count; i++)
  1460. {
  1461. CMimeBodyPart* bpart = mpart->queryBodyPart(i);
  1462. if(bpart == NULL)
  1463. continue;
  1464. const char* cdisp = bpart->getContentDisposition();
  1465. StringBuffer contentbuf;
  1466. bpart->getContent(contentbuf);
  1467. StringBuffer namebuf;
  1468. char* curword = NULL;
  1469. char* curptr = (char*)cdisp;
  1470. const char* separators = ";";
  1471. bool isFile = false;
  1472. StringBuffer filename;
  1473. while(curptr != NULL && *curptr != 0)
  1474. {
  1475. curptr = Utils::getWord(curptr, curword, separators, true);
  1476. if(curword == NULL)
  1477. break;
  1478. StringBuffer name, value;
  1479. Utils::parseNVPair(curword, name, value);
  1480. if(name.length() > 0 && stricmp(name.str(), "name") == 0)
  1481. {
  1482. namebuf.append(value.str());
  1483. }
  1484. else if(name.length() > 0 && stricmp(name.str(), "filename") == 0)
  1485. {
  1486. value.swapWith(filename);
  1487. isFile = true;
  1488. }
  1489. }
  1490. if(!isFile)
  1491. addParameter(namebuf.str(), contentbuf.str());
  1492. else
  1493. {
  1494. addParameter(namebuf.str(), filename.str());
  1495. addAttachment(namebuf.str(), contentbuf);
  1496. }
  1497. }
  1498. }
  1499. }
  1500. m_context->addTraceSummaryTimeStamp("rcv");
  1501. return 0;
  1502. }
  1503. void CHttpRequest::updateContext()
  1504. {
  1505. if(m_context)
  1506. {
  1507. m_context->setContextPath(m_httpPath.str());
  1508. StringBuffer temp;
  1509. getPeer(temp);
  1510. if(temp.length())
  1511. m_context->setPeer(temp.str());
  1512. m_context->setRequestParameters(queryParameters());
  1513. short servPort;
  1514. temp.clear();
  1515. getServAddress(temp, servPort);
  1516. m_context->setServAddress(temp.str(), servPort);
  1517. StringBuffer userid, password, realm;
  1518. getBasicAuthorization(userid, password, realm);
  1519. if(userid.length() > 0)
  1520. {
  1521. m_context->setUserID(userid.str());
  1522. m_context->setPassword(password.str());
  1523. m_context->setRealm(realm.str());
  1524. }
  1525. if (m_queryparams)
  1526. {
  1527. if (m_queryparams->getPropInt("no_ns_"))
  1528. m_context->addOptions(ESPCTX_NO_NAMESPACES);
  1529. if (m_queryparams->hasProp("wsdl"))
  1530. m_context->addOptions(ESPCTX_WSDL);
  1531. if (m_queryparams->hasProp("wsdl_ext"))
  1532. m_context->addOptions(ESPCTX_WSDL|ESPCTX_WSDL_EXT);
  1533. if (m_queryparams->hasProp("no_annot_"))
  1534. m_context->addOptions(ESPCTX_NO_ANNOTATION);
  1535. if (m_queryparams->hasProp("all_annot_"))
  1536. m_context->addOptions(ESPCTX_ALL_ANNOTATION);
  1537. }
  1538. // set client version
  1539. StringBuffer action;
  1540. getHeader("SOAPAction", action);
  1541. // URL first, then SOAPAction
  1542. const char *verstr = queryParameters()->queryProp("ver_");
  1543. if (verstr && *verstr)
  1544. m_context->setClientVersion(atof(verstr));
  1545. else
  1546. {
  1547. verstr=strstr(action.str(), "ver_=");
  1548. if (verstr)
  1549. m_context->setClientVersion(atof(verstr+5));
  1550. else
  1551. m_context->setClientVersion(0.0);
  1552. }
  1553. StringBuffer useragent;
  1554. getHeader("User-Agent", useragent);
  1555. m_context->setUseragent(useragent.str());
  1556. }
  1557. }
  1558. StringBuffer& CHttpRequest::constructHeaderBuffer(StringBuffer& headerbuf, bool inclLength)
  1559. {
  1560. if(m_httpMethod.length() > 0)
  1561. headerbuf.append(queryMethod()).append(" ");
  1562. else
  1563. headerbuf.append("POST ");
  1564. if(m_httpPath.length() > 0)
  1565. headerbuf.append(queryPath()).append(" ");
  1566. else
  1567. headerbuf.append("/ ");
  1568. if(m_version.length() > 0)
  1569. headerbuf.append(m_version.get());
  1570. else
  1571. headerbuf.append(HTTP_VERSION);
  1572. headerbuf.append("\r\n");
  1573. if(m_host.length() > 0)
  1574. {
  1575. headerbuf.append("Host: ").append(m_host.get());
  1576. if(m_port != 80)
  1577. {
  1578. headerbuf.append(":").append(m_port);
  1579. }
  1580. headerbuf.append("\r\n");
  1581. }
  1582. headerbuf.append("Content-Type: ");
  1583. if(m_content_type.length() > 0)
  1584. headerbuf.append(m_content_type.get());
  1585. else
  1586. headerbuf.append("text/xml; charset=UTF-8");
  1587. headerbuf.append("\r\n");
  1588. if(inclLength && m_content_length > 0)
  1589. headerbuf.append("Content-Length: ").append(m_content_length).append("\r\n");
  1590. if(m_cookies.length() > 0)
  1591. {
  1592. headerbuf.append("Cookie: ");
  1593. int version = m_cookies.item(0).getVersion();
  1594. if(version >= 1)
  1595. headerbuf.append("$Version=").append('"').append(version).append('"').append(',');
  1596. ForEachItemIn(x, m_cookies)
  1597. {
  1598. CEspCookie* cookie = &m_cookies.item(x);
  1599. if(cookie == NULL)
  1600. continue;
  1601. cookie->appendToRequestHeader(headerbuf);
  1602. }
  1603. headerbuf.append("\r\n");
  1604. }
  1605. ForEachItemIn(x, m_headers)
  1606. {
  1607. const char* oneheader = (const char*)m_headers.item(x);
  1608. headerbuf.append(oneheader).append("\r\n");
  1609. }
  1610. headerbuf.append("\r\n");
  1611. return headerbuf;
  1612. }
  1613. int CHttpRequest::processHeaders(IMultiException *me)
  1614. {
  1615. char oneline[MAX_HTTP_HEADER_LEN + 2];
  1616. int lenread = m_bufferedsocket->readline(oneline, MAX_HTTP_HEADER_LEN + 1, me);
  1617. if(lenread <= 0) //special case client connected and disconnected, load balancer ping?
  1618. return -1;
  1619. else if (lenread > MAX_HTTP_HEADER_LEN)
  1620. throw createEspHttpException(HTTP_STATUS_BAD_REQUEST_CODE, "Bad Request", HTTP_STATUS_BAD_REQUEST);
  1621. m_header.set(oneline);
  1622. parseFirstLine(oneline);
  1623. lenread = m_bufferedsocket->readline(oneline, MAX_HTTP_HEADER_LEN + 1, me);
  1624. while(lenread >= 0 && oneline[0] != '\0')
  1625. {
  1626. if(lenread > MAX_HTTP_HEADER_LEN)
  1627. throw createEspHttpException(HTTP_STATUS_BAD_REQUEST_CODE, "Bad Request", HTTP_STATUS_BAD_REQUEST);
  1628. m_header.append('\n').append(oneline);
  1629. parseOneHeader(oneline);
  1630. lenread = m_bufferedsocket->readline(oneline, MAX_HTTP_HEADER_LEN + 1, me);
  1631. }
  1632. if (getEspLogRequests() || getEspLogLevel()>LogNormal)
  1633. logMessage(LOGHEADERS, "HTTP request headers received:\n");
  1634. if(m_content_length > 0 && m_MaxRequestEntityLength > 0 && m_content_length > m_MaxRequestEntityLength && (!isUpload()))
  1635. throw createEspHttpException(HTTP_STATUS_BAD_REQUEST_CODE, "The request length was too long.", HTTP_STATUS_BAD_REQUEST);
  1636. return 0;
  1637. }
  1638. bool CHttpRequest::readContentToBuffer(MemoryBuffer& buffer, __int64& bytesNotRead)
  1639. {
  1640. char buf[1024 + 1];
  1641. __int64 buflen = 1024;
  1642. if (buflen > bytesNotRead)
  1643. buflen = bytesNotRead;
  1644. int readlen = m_bufferedsocket->read(buf, (int) buflen);
  1645. if(readlen < 0)
  1646. DBGLOG("Failed to read from socket");
  1647. if(readlen <= 0)
  1648. return false;
  1649. buf[readlen] = 0;
  1650. buffer.append(readlen, buf);//'buffer' may have some left-over from previous read
  1651. bytesNotRead -= readlen;
  1652. return true;
  1653. }
  1654. bool CHttpRequest::readUploadFileName(CMimeMultiPart* mimemultipart, StringBuffer& fileName, MemoryBuffer& contentBuffer, __int64& bytesNotRead)
  1655. {
  1656. if (contentBuffer.length())
  1657. mimemultipart->readUploadFileName(contentBuffer, fileName);
  1658. while((fileName.length() < 1) && (bytesNotRead > 0))
  1659. {
  1660. if (!readContentToBuffer(contentBuffer, bytesNotRead))
  1661. break;
  1662. mimemultipart->readUploadFileName(contentBuffer, fileName);
  1663. }
  1664. return (fileName.length() > 0);
  1665. }
  1666. IFile* CHttpRequest::createUploadFile(StringBuffer netAddress, const char* filePath, StringBuffer& fileName)
  1667. {
  1668. StringBuffer name(fileName), tmpFileName;
  1669. char* str = (char*) name.reverse().str();
  1670. char* pStr = (char*) strchr(str, '\\');
  1671. if (!pStr)
  1672. pStr = strchr(str, '/');
  1673. if (pStr)
  1674. {
  1675. pStr[0] = 0;
  1676. fileName.clear().append(str).reverse();
  1677. }
  1678. tmpFileName.appendf("%s/%s.part", filePath, fileName.str());
  1679. RemoteFilename rfn;
  1680. SocketEndpoint ep;
  1681. ep.set(netAddress.str());
  1682. rfn.setPath(ep, tmpFileName.str());
  1683. return createIFile(rfn);
  1684. }
  1685. int CHttpRequest::readContentToFiles(StringBuffer netAddress, StringBuffer path, StringArray& fileNames)
  1686. {
  1687. const char* contentType = m_content_type.get();
  1688. if (!contentType || !*contentType)
  1689. throw MakeStringException(-1, "Content Type not found.");
  1690. Owned<CMimeMultiPart> multipart = new CMimeMultiPart("1.0", contentType, "", "", "");
  1691. multipart->parseContentType(contentType);
  1692. MemoryBuffer fileContent, moreContent;
  1693. __int64 bytesNotRead = m_content_length64;
  1694. while (1)
  1695. {
  1696. StringBuffer fileName;
  1697. if (!readUploadFileName(multipart, fileName, fileContent, bytesNotRead))
  1698. {
  1699. DBGLOG("No file name found for upload");
  1700. break;
  1701. }
  1702. fileNames.append(fileName);
  1703. Owned<IFile> file = createUploadFile(netAddress, path, fileName);
  1704. if (!file)
  1705. {
  1706. DBGLOG("Uploaded file %s cannot be created", fileName.str());
  1707. break;
  1708. }
  1709. Owned<IFileIO> fileio = file->open(IFOcreate);
  1710. if (!fileio)
  1711. {
  1712. DBGLOG("Uploaded file %s cannot be opened", fileName.str());
  1713. break;
  1714. }
  1715. __int64 writeOffset = 0;
  1716. bool writeError = false;
  1717. bool foundAnotherFile = false;
  1718. while (1)
  1719. {
  1720. foundAnotherFile = multipart->separateMultiParts(fileContent, moreContent, bytesNotRead);
  1721. if (fileContent.length() > 0)
  1722. {
  1723. if (fileio->write(writeOffset, fileContent.length(), fileContent.toByteArray()) != fileContent.length())
  1724. {
  1725. DBGLOG("Failed to write Uploaded file %s", fileName.str());
  1726. writeError = true;
  1727. break;
  1728. }
  1729. writeOffset += fileContent.length();
  1730. }
  1731. fileContent.clear();
  1732. if (moreContent.length() > 0)
  1733. {
  1734. fileContent.append(moreContent.length(), (void*) moreContent.toByteArray());
  1735. moreContent.clear();
  1736. }
  1737. if(foundAnotherFile || (bytesNotRead <= 0) || !readContentToBuffer(fileContent, bytesNotRead))
  1738. break;
  1739. }
  1740. if (writeError)
  1741. break;
  1742. StringBuffer fileNameWithPath;
  1743. fileNameWithPath.appendf("%s/%s", path.str(), fileName.str());
  1744. file->rename(fileNameWithPath.str());
  1745. if (!foundAnotherFile)
  1746. break;
  1747. }
  1748. return 0;
  1749. }
  1750. /******************************************************************************
  1751. CHttpResponse Implementation
  1752. *******************************************************************************/
  1753. CHttpResponse::CHttpResponse(ISocket& socket) : CHttpMessage(socket), m_timeout(BSOCKET_CLIENT_READ_TIMEOUT)
  1754. {
  1755. }
  1756. CHttpResponse::~CHttpResponse()
  1757. {
  1758. }
  1759. void CHttpResponse::setTimeOut(unsigned int timeout)
  1760. {
  1761. m_timeout = timeout;
  1762. }
  1763. void CHttpResponse::setStatus(const char* status)
  1764. {
  1765. m_status.set(status);
  1766. }
  1767. StringBuffer& CHttpResponse::getStatus(StringBuffer& status)
  1768. {
  1769. status.append(m_status.get());
  1770. return status;
  1771. }
  1772. StringBuffer& CHttpResponse::constructHeaderBuffer(StringBuffer& headerbuf, bool inclLen)
  1773. {
  1774. if(m_version.length() > 0)
  1775. headerbuf.append(m_version.get()).append(" ");
  1776. else
  1777. headerbuf.append(HTTP_VERSION).append(" ");
  1778. if(m_status.length() > 0)
  1779. headerbuf.append(m_status.get());
  1780. else
  1781. headerbuf.append(HTTP_STATUS_OK);
  1782. headerbuf.append("\r\n");
  1783. headerbuf.append("Content-Type: ");
  1784. if(m_content_type.length() > 0)
  1785. headerbuf.append(m_content_type.get());
  1786. else
  1787. headerbuf.append("text/xml; charset=UTF-8");
  1788. headerbuf.append("\r\n");
  1789. if(inclLen && m_content_length > 0)
  1790. headerbuf.append("Content-Length: ").append(m_content_length).append("\r\n");
  1791. headerbuf.append("Connection: close\r\n");
  1792. ForEachItemIn(x, m_cookies)
  1793. {
  1794. CEspCookie* cookie = &m_cookies.item(x);
  1795. if(cookie == NULL)
  1796. continue;
  1797. StringBuffer cookiehn;
  1798. cookie->getSetCookieHeaderName(cookiehn);
  1799. headerbuf.append(cookiehn.str()).append(": ");
  1800. cookie->appendToResponseHeader(headerbuf);
  1801. headerbuf.append("\r\n");
  1802. }
  1803. ForEachItemIn(i, m_headers)
  1804. {
  1805. const char* oneheader = (const char*)m_headers.item(i);
  1806. headerbuf.append(oneheader).append("\r\n");
  1807. }
  1808. if(m_context.get())
  1809. {
  1810. StringArray& customHeaders = m_context->queryCustomHeaders();
  1811. ForEachItemIn(j, customHeaders)
  1812. {
  1813. const char* oneheader = (const char*)customHeaders.item(j);
  1814. if(oneheader && *oneheader)
  1815. headerbuf.append(oneheader).append("\r\n");
  1816. }
  1817. }
  1818. headerbuf.append("\r\n");
  1819. return headerbuf;
  1820. }
  1821. int CHttpResponse::parseFirstLine(char* oneline)
  1822. {
  1823. if(*oneline == 0)
  1824. return -1;
  1825. if (getEspLogLevel()>LogNormal)
  1826. DBGLOG("http response status = %s", oneline);
  1827. char* ptr = oneline;
  1828. while(*ptr != '\0' && *ptr != ' ')
  1829. ptr++;
  1830. if(*ptr != '\0')
  1831. {
  1832. *ptr = 0;
  1833. ptr++;
  1834. }
  1835. m_version.set(oneline);
  1836. while(*ptr == ' ')
  1837. ptr++;
  1838. m_status.set(ptr);
  1839. return 0;
  1840. }
  1841. void CHttpResponse::parseOneCookie(char* cookiestr)
  1842. {
  1843. if(cookiestr == NULL)
  1844. return;
  1845. char* curword;
  1846. char* curptr = cookiestr;
  1847. CEspCookie* cookie = NULL;
  1848. curptr = Utils::getWord(curptr, curword, ";");
  1849. StringBuffer name, value;
  1850. Utils::parseNVPair(curword, name, value);
  1851. if(name.length() == 0)
  1852. return;
  1853. cookie = new CEspCookie(name.str(), value.str());
  1854. m_cookies.append(*cookie);
  1855. while(curptr != NULL && *curptr != 0)
  1856. {
  1857. curptr = Utils::getWord(curptr, curword, ";");
  1858. if(curword == NULL)
  1859. break;
  1860. StringBuffer name, value;
  1861. Utils::parseNVPair(curword, name, value);
  1862. if(name.length() == 0)
  1863. continue;
  1864. else if(stricmp(name.str(), "Version") == 0)
  1865. cookie->setVersion(atoi(value.str()));
  1866. else if(stricmp(name.str(), "Path") == 0)
  1867. cookie->setPath(value.str());
  1868. else if(stricmp(name.str(), "Domain") == 0)
  1869. cookie->setDomain(value.str());
  1870. else if(stricmp(name.str(), "Port") == 0)
  1871. cookie->setPorts(value.str());
  1872. else if(stricmp(name.str(), "Max-Age") == 0)
  1873. cookie->setMaxAge(atoi(value.str()));
  1874. else if(stricmp(name.str(), "Discard") == 0)
  1875. cookie->setDiscard(true);
  1876. else if(stricmp(name.str(), "Secure") == 0)
  1877. cookie->setSecure(true);
  1878. else if(stricmp(name.str(), "Comment") == 0)
  1879. cookie->setComment(value.str());
  1880. else if(stricmp(name.str(), "CommentURL") == 0)
  1881. cookie->setCommentURL(value.str());
  1882. }
  1883. }
  1884. void CHttpResponse::parseCookieHeader(char* cookiestr)
  1885. {
  1886. if(cookiestr == NULL)
  1887. return;
  1888. //TODO: for now assume each Set-Cookie only has one cookie.
  1889. parseOneCookie(cookiestr);
  1890. }
  1891. void CHttpResponse::sendBasicChallenge(const char* realm, bool includeContent)
  1892. {
  1893. StringBuffer authheader;
  1894. authheader.appendf("Basic realm=\"%s\"", realm);
  1895. addHeader("WWW-Authenticate", authheader.str());
  1896. if (includeContent)
  1897. {
  1898. setContentType("text/html; charset=UTF-8");
  1899. setContent(
  1900. "<html xmlns=\"http://www.w3.org/1999/xhtml\">"
  1901. "<head>"
  1902. "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"/>"
  1903. "<title>ESP - Access Denied</title>"
  1904. "<script type='text/javascript'>"
  1905. "function closeWin() { top.opener=top; top.close(); }"
  1906. "</script>"
  1907. "</head>"
  1908. "<body onload=\"javascript:closeWin();\">"
  1909. "<b>Access Denied -- Valid username and password required!</b>"
  1910. "</body>"
  1911. "</html>"
  1912. );
  1913. }
  1914. setStatus(HTTP_STATUS_UNAUTHORIZED);
  1915. send();
  1916. }
  1917. void CHttpResponse::sendBasicChallenge(const char* realm, const char* content)
  1918. {
  1919. StringBuffer authheader;
  1920. authheader.appendf("Basic realm=\"%s\"", realm);
  1921. addHeader("WWW-Authenticate", authheader.str());
  1922. if (content != NULL && *content != '\0')
  1923. {
  1924. setContentType("text/html; charset=UTF-8");
  1925. setContent(content);
  1926. }
  1927. setStatus(HTTP_STATUS_UNAUTHORIZED);
  1928. send();
  1929. }
  1930. int CHttpResponse::processHeaders(IMultiException *me)
  1931. {
  1932. char oneline[MAX_HTTP_HEADER_LEN + 1];
  1933. int lenread = m_bufferedsocket->readline(oneline, MAX_HTTP_HEADER_LEN, me);
  1934. if(lenread <= 0)
  1935. return -1;
  1936. // Process "100 Continue" headers
  1937. // Some HTTP/1.1 webservers may send back "100 Continue" before it reads the posted request body.
  1938. while(Utils::strncasecmp(oneline, "HTTP/1.1 100", strlen("HTTP/1.1 100")) == 0)
  1939. {
  1940. //Read until empty line, meaning the end of "100 Continue" part
  1941. while(lenread >= 0 && oneline[0] != '\0')
  1942. {
  1943. lenread = m_bufferedsocket->readline(oneline, MAX_HTTP_HEADER_LEN, me);
  1944. }
  1945. // Read the next line, should be the status line.
  1946. lenread = m_bufferedsocket->readline(oneline, MAX_HTTP_HEADER_LEN, me);
  1947. if(lenread <= 0)
  1948. return 0;
  1949. }
  1950. parseFirstLine(oneline);
  1951. lenread = m_bufferedsocket->readline(oneline, MAX_HTTP_HEADER_LEN, me);
  1952. while(lenread >= 0 && oneline[0] != '\0')
  1953. {
  1954. parseOneHeader(oneline);
  1955. lenread = m_bufferedsocket->readline(oneline, MAX_HTTP_HEADER_LEN, me);
  1956. }
  1957. return 0;
  1958. }
  1959. bool CHttpResponse::httpContentFromFile(const char *filepath)
  1960. {
  1961. StringBuffer mimetype, etag, lastModified;
  1962. MemoryBuffer content;
  1963. //Set 'modified = false' here since this is called by CMySoapBinding::onGetFile() which does
  1964. //not need to check and set both 'etag' and 'lastModified' inside httpContentFromFile().
  1965. bool modified = false;
  1966. bool ok = ::httpContentFromFile(filepath, mimetype, content, modified, lastModified, etag);
  1967. if (ok)
  1968. {
  1969. setContent(content.length(), content.toByteArray());
  1970. setContentType(mimetype.str());
  1971. setStatus(HTTP_STATUS_OK);
  1972. }
  1973. else
  1974. {
  1975. setStatus(HTTP_STATUS_NOT_FOUND);
  1976. }
  1977. return ok;
  1978. }
  1979. void CHttpResponse::setETagCacheControl(const char *etag, const char *contenttype)
  1980. {
  1981. if (etag && *etag)
  1982. addHeader("Etag", etag);
  1983. if (!strncmp(contenttype, "image/", 6))
  1984. {
  1985. //if file being requested is an image file then set its expiration to a year
  1986. //so browser does not keep reloading it
  1987. addHeader("Cache-control", "max-age=31536000");
  1988. }
  1989. else
  1990. addHeader("Cache-control", "max-age=300");
  1991. }
  1992. void CHttpResponse::CheckModifiedHTTPContent(bool modified, const char *lastmodified, const char *etag, const char *contenttype, MemoryBuffer &content)
  1993. {
  1994. if (!modified)
  1995. {
  1996. if (etag && *etag)
  1997. setETagCacheControl(etag, contenttype);
  1998. setStatus(HTTP_STATUS_NOT_MODIFIED);
  1999. }
  2000. else
  2001. {
  2002. addHeader("Last-Modified", lastmodified);
  2003. setETagCacheControl(etag, contenttype);
  2004. setContent(content.length(), content.toByteArray());
  2005. setContentType(contenttype);
  2006. setStatus(HTTP_STATUS_OK);
  2007. }
  2008. }
  2009. int CHttpResponse::receive(IMultiException *me)
  2010. {
  2011. // If it's receiving a response, it's behaving as the client side of this conversation.
  2012. if(m_bufferedsocket.get() != NULL)
  2013. m_bufferedsocket->setReadTimeout(m_timeout);
  2014. return CHttpMessage::receive(me);
  2015. }
  2016. int CHttpResponse::receive(bool alwaysReadContent, IMultiException *me)
  2017. {
  2018. // If it's receiving a response, it's behaving as the client side of this conversation.
  2019. if(m_bufferedsocket.get() != NULL)
  2020. m_bufferedsocket->setReadTimeout(m_timeout);
  2021. if (processHeaders(me)==-1)
  2022. return -1;
  2023. if (getEspLogLevel()>LogNormal)
  2024. DBGLOG("Response headers processed! content_length = %d", m_content_length);
  2025. char status_class = '2';
  2026. if(m_status.length() > 0)
  2027. status_class = *(m_status.get());
  2028. if(m_content_length > 0)
  2029. {
  2030. readContent();
  2031. if (getEspLogLevel()>LogNormal)
  2032. DBGLOG("length of response content read = %d", m_content.length());
  2033. }
  2034. else if(alwaysReadContent && status_class != '4' && status_class != '5' && m_content_length == -1)
  2035. {
  2036. //HTTP protocol does not require a content length: read until socket closed
  2037. readContentTillSocketClosed();
  2038. if (getEspLogLevel()>LogNormal)
  2039. DBGLOG("length of content read = %d", m_content.length());
  2040. }
  2041. if ((getEspLogRequests() || getEspLogLevel()>LogNormal))
  2042. logMessage(LOGCONTENT, "HTTP response content received:\n");
  2043. return 0;
  2044. }
  2045. int CHttpResponse::sendException(IEspHttpException* e)
  2046. {
  2047. StringBuffer msg;
  2048. e->errorMessage(msg);
  2049. setStatus(e->getHttpStatus());
  2050. setContentType(HTTP_TYPE_TEXT_PLAIN);
  2051. setContent(msg.str());
  2052. send();
  2053. return 0;
  2054. }
  2055. StringBuffer &toJSON(StringBuffer &json, IMultiException *me, const char *callback)
  2056. {
  2057. IArrayOf<IException> &exs = me->getArray();
  2058. if (callback && *callback)
  2059. json.append(callback).append('(');
  2060. appendJSONName(json.append("{"), "Exceptions").append("{");
  2061. appendJSONValue(json, "Source", me->source());
  2062. appendJSONName(json, "Exception").append("[");
  2063. ForEachItemIn(i, exs)
  2064. {
  2065. IException &e = exs.item(i);
  2066. if (i>0)
  2067. json.append(",");
  2068. StringBuffer msg;
  2069. appendJSONValue(json.append("{"), "Code", e.errorCode());
  2070. appendJSONValue(json, "Message", e.errorMessage(msg).str());
  2071. json.append("}");
  2072. }
  2073. json.append("]}}");
  2074. if (callback && *callback)
  2075. json.append(");");
  2076. return json;
  2077. }
  2078. bool CHttpResponse::handleExceptions(IXslProcessor *xslp, IMultiException *me, const char *serv, const char *meth, const char *errorXslt)
  2079. {
  2080. IEspContext *context=queryContext();
  2081. if (me->ordinality()>0)
  2082. {
  2083. StringBuffer msg;
  2084. WARNLOG("Exception(s) in %s::%s - %s", serv, meth, me->errorMessage(msg).append('\n').str());
  2085. StringBuffer content;
  2086. switch (context->getResponseFormat())
  2087. {
  2088. case ESPSerializationJSON:
  2089. {
  2090. setContentType(HTTP_TYPE_APPLICATION_JSON_UTF8);
  2091. toJSON(content, me, context->queryRequestParameters()->queryProp("jsonp"));
  2092. break;
  2093. }
  2094. case ESPSerializationXML:
  2095. setContentType(HTTP_TYPE_APPLICATION_XML);
  2096. me->serialize(content);
  2097. break;
  2098. case ESPSerializationANY:
  2099. default:
  2100. {
  2101. if (!errorXslt || !*errorXslt)
  2102. return false;
  2103. setContentType("text/html");
  2104. StringBuffer xml;
  2105. xslTransformHelper(xslp, me->serialize(xml), errorXslt, content, context->queryXslParameters());
  2106. }
  2107. }
  2108. setContent(content);
  2109. send();
  2110. return true;
  2111. }
  2112. return false;
  2113. }