bindutil.cpp 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877
  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. #include "platform.h"
  15. #define BINDUTIL_EXPORT DECL_EXPORT
  16. #include <map>
  17. #include <string>
  18. #include "esp.hpp"
  19. #include "bindutil.hpp"
  20. #include "espcontext.hpp"
  21. #define URL_MAX 512
  22. static const unsigned char charmap[] = {
  23. 0000, 0001, 0002, 0003, 0004, 0005, 0006, 0007,
  24. 0010, 0011, 0012, 0013, 0014, 0015, 0016, 0017,
  25. 0020, 0021, 0022, 0023, 0024, 0025, 0026, 0027,
  26. 0030, 0031, 0032, 0033, 0034, 0035, 0036, 0037,
  27. 0040, 0041, 0042, 0043, 0044, 0045, 0046, 0047,
  28. 0050, 0051, 0052, 0053, 0054, 0055, 0056, 0057,
  29. 0060, 0061, 0062, 0063, 0064, 0065, 0066, 0067,
  30. 0070, 0071, 0072, 0073, 0074, 0075, 0076, 0077,
  31. 0100, 0141, 0142, 0143, 0144, 0145, 0146, 0147,
  32. 0150, 0151, 0152, 0153, 0154, 0155, 0156, 0157,
  33. 0160, 0161, 0162, 0163, 0164, 0165, 0166, 0167,
  34. 0170, 0171, 0172, 0133, 0134, 0135, 0136, 0137,
  35. 0140, 0141, 0142, 0143, 0144, 0145, 0146, 0147,
  36. 0150, 0151, 0152, 0153, 0154, 0155, 0156, 0157,
  37. 0160, 0161, 0162, 0163, 0164, 0165, 0166, 0167,
  38. 0170, 0171, 0172, 0173, 0174, 0175, 0176, 0177,
  39. 0200, 0201, 0202, 0203, 0204, 0205, 0206, 0207,
  40. 0210, 0211, 0212, 0213, 0214, 0215, 0216, 0217,
  41. 0220, 0221, 0222, 0223, 0224, 0225, 0226, 0227,
  42. 0230, 0231, 0232, 0233, 0234, 0235, 0236, 0237,
  43. 0240, 0241, 0242, 0243, 0244, 0245, 0246, 0247,
  44. 0250, 0251, 0252, 0253, 0254, 0255, 0256, 0257,
  45. 0260, 0261, 0262, 0263, 0264, 0265, 0266, 0267,
  46. 0270, 0271, 0272, 0273, 0274, 0275, 0276, 0277,
  47. 0300, 0301, 0302, 0303, 0304, 0305, 0306, 0307,
  48. 0310, 0311, 0312, 0313, 0314, 0315, 0316, 0317,
  49. 0320, 0321, 0322, 0323, 0324, 0325, 0326, 0327,
  50. 0330, 0331, 0332, 0333, 0334, 0335, 0336, 0337,
  51. 0340, 0341, 0342, 0343, 0344, 0345, 0346, 0347,
  52. 0350, 0351, 0352, 0353, 0354, 0355, 0356, 0357,
  53. 0360, 0361, 0362, 0363, 0364, 0365, 0366, 0367,
  54. 0370, 0371, 0372, 0373, 0374, 0375, 0376, 0377,
  55. };
  56. unsigned int Utils::hash (const char *str, unsigned int len)
  57. {
  58. static unsigned short asso_values[] =
  59. {
  60. 4484, 4484, 4484, 4484, 4484, 4484, 4484, 4484, 4484, 4484,
  61. 4484, 4484, 4484, 4484, 4484, 4484, 4484, 4484, 4484, 4484,
  62. 4484, 4484, 4484, 4484, 4484, 4484, 4484, 4484, 4484, 4484,
  63. 4484, 4484, 4484, 4484, 4484, 4484, 4484, 4484, 4484, 4484,
  64. 4484, 4484, 4484, 4484, 4484, 4484, 4484, 4484, 0, 10,
  65. 125, 10, 360, 0, 65, 435, 555, 895, 4484, 4484,
  66. 4484, 4484, 4484, 4484, 4484, 0, 330, 0, 130, 0,
  67. 130, 0, 325, 0, 0, 400, 5, 315, 110, 0,
  68. 65, 0, 20, 1195, 5, 4484, 4484, 4484, 4484, 20,
  69. 5, 4484, 4484, 4484, 4484, 4484, 4484, 4484, 4484, 4484,
  70. 4484, 4484, 4484, 4484, 4484, 4484, 4484, 4484, 4484, 4484,
  71. 4484, 4484, 4484, 4484, 4484, 4484, 4484, 4484, 4484, 4484,
  72. 4484, 4484, 4484, 4484, 4484, 4484, 4484, 4484, 4484, 4484,
  73. 4484, 4484, 4484, 4484, 4484, 4484, 4484, 4484, 4484, 4484,
  74. 4484, 4484, 4484, 4484, 4484, 4484, 4484, 4484, 4484, 4484,
  75. 4484, 4484, 4484, 4484, 4484, 4484, 4484, 4484, 4484, 4484,
  76. 4484, 4484, 4484, 4484, 4484, 4484, 4484, 4484, 4484, 4484,
  77. 4484, 4484, 4484, 4484, 4484, 4484, 4484, 4484, 4484, 4484,
  78. 4484, 4484, 4484, 4484, 4484, 4484, 4484, 4484, 4484, 4484,
  79. 4484, 4484, 4484, 4484, 4484, 4484, 4484, 4484, 4484, 4484,
  80. 4484, 4484, 4484, 4484, 4484, 4484, 4484, 4484, 4484, 4484,
  81. 4484, 4484, 4484, 4484, 4484, 4484, 4484, 4484, 4484, 4484,
  82. 4484, 4484, 4484, 4484, 4484, 4484, 4484, 4484, 4484, 4484,
  83. 4484, 4484, 4484, 4484, 4484, 4484, 4484, 4484, 4484, 4484,
  84. 4484, 4484, 4484, 4484, 4484, 4484, 4484, 4484, 4484, 4484,
  85. 4484, 4484, 4484, 4484, 4484, 4484
  86. };
  87. unsigned int result = len;
  88. for(int i = len - 1; i >= 0; i--)
  89. {
  90. result += asso_values[(unsigned char)str[i]];
  91. }
  92. return result;
  93. }
  94. bool isLWS(char c)
  95. {
  96. if(c == ' ' || c== '\t' || c == 13 || c == 10)
  97. return true;
  98. return false;
  99. }
  100. // oneline must be NULL terminated
  101. const char* Utils::getWord(const char* oneline, StringBuffer& oneword)
  102. {
  103. if(*oneline == 0)
  104. return oneline;
  105. while(*oneline && isLWS(*oneline))
  106. oneline++;
  107. while(*oneline && !isLWS(*oneline))
  108. {
  109. oneword.append(*oneline);
  110. oneline++;
  111. }
  112. return oneline;
  113. }
  114. bool isSeparator(char c, const char* separators)
  115. {
  116. while(*separators != '\0')
  117. {
  118. if(*separators == c)
  119. return true;
  120. separators++;
  121. }
  122. return false;
  123. }
  124. // oneline must be NULL terminated
  125. char* Utils::getWord(char* oneline, char* & oneword, const char* separators, bool tws)
  126. {
  127. if(oneline == NULL || *oneline == 0)
  128. {
  129. oneword = NULL;
  130. return oneline;
  131. }
  132. while(*oneline != '\0' && (isSeparator(*oneline, separators) || (tws && isLWS(*oneline))))
  133. oneline++;
  134. oneword = oneline;
  135. while(*oneline != '\0' && !isSeparator(*oneline, separators))
  136. oneline++;
  137. if(*oneline != '\0')
  138. {
  139. *oneline = '\0';
  140. oneline++;
  141. }
  142. return oneline;
  143. }
  144. void Utils::parseNVPair(const char* nv, StringBuffer& name, StringBuffer& value)
  145. {
  146. name.clear();
  147. value.clear();
  148. if(nv == NULL || *nv == '\0')
  149. return;
  150. const char* ptr = nv;
  151. while(ptr != NULL && *ptr == ' ')
  152. {
  153. ptr++;
  154. }
  155. if(ptr == NULL || *ptr == '\0')
  156. return;
  157. const char* nptr = ptr;
  158. const char* vptr = NULL;
  159. int nlen = 0;
  160. while(ptr != NULL && *ptr != '\0' && *ptr != '=')
  161. {
  162. ptr++;
  163. nlen++;
  164. }
  165. if(nlen <= 0)
  166. return;
  167. if(ptr != NULL && *ptr != '\0')
  168. vptr = ptr + 1;
  169. while(vptr != NULL && *vptr == ' ')
  170. vptr++;
  171. while(nlen > 0 && nptr[nlen - 1] == ' ')
  172. nlen--;
  173. if(nlen > 0)
  174. name.append(nlen, nptr);
  175. if(!vptr)
  176. return;
  177. if(vptr[0] == '"')
  178. vptr++;
  179. int vlen = strlen(vptr);
  180. while(vlen > 0 && vptr[vlen - 1] == ' ')
  181. vlen--;
  182. if(vlen > 0 && vptr[vlen - 1] == '"')
  183. vlen--;
  184. if(vlen > 0)
  185. value.append(vlen, vptr);
  186. }
  187. // buf DOESN'T have to be NULL terminated
  188. int Utils::getLine(int total_len, int cur_pos, const char* buf, int& oneline_len)
  189. {
  190. oneline_len = 0;
  191. if(cur_pos >= total_len)
  192. {
  193. return total_len;
  194. }
  195. while(cur_pos < total_len && buf[cur_pos] != '\r' && buf[cur_pos] != '\n')
  196. {
  197. oneline_len++;
  198. cur_pos++;
  199. }
  200. if(cur_pos == total_len)
  201. return total_len;
  202. if(buf[cur_pos] == '\r')
  203. {
  204. cur_pos++;
  205. }
  206. if(cur_pos == total_len)
  207. return total_len;
  208. if(buf[cur_pos] == '\n')
  209. {
  210. cur_pos++;
  211. }
  212. return cur_pos;
  213. }
  214. __int64 Utils::getLine(__int64 total_len, __int64 cur_pos, const char* buf, int& oneline_len)
  215. {
  216. oneline_len = 0;
  217. if(cur_pos >= total_len)
  218. {
  219. return total_len;
  220. }
  221. while(cur_pos < total_len && buf[cur_pos] != '\r' && buf[cur_pos] != '\n')
  222. {
  223. oneline_len++;
  224. cur_pos++;
  225. }
  226. if(cur_pos == total_len)
  227. return total_len;
  228. if(buf[cur_pos] == '\r')
  229. {
  230. cur_pos++;
  231. }
  232. if(cur_pos == total_len)
  233. return total_len;
  234. if(buf[cur_pos] == '\n')
  235. {
  236. cur_pos++;
  237. }
  238. return cur_pos;
  239. }
  240. int Utils::strncasecmp(const char* s1, const char* s2, size32_t n)
  241. {
  242. bool s1isnull = (s1 == NULL);
  243. bool s2isnull = (s2 == NULL);
  244. if(s1isnull || s2isnull)
  245. return s1isnull - s2isnull;
  246. if (n != 0)
  247. {
  248. const unsigned char *cm = charmap,
  249. *us1 = (const unsigned char *)s1,
  250. *us2 = (const unsigned char *)s2;
  251. do
  252. {
  253. if (cm[*us1] != cm[*us2++])
  254. return (cm[*us1] - cm[*--us2]);
  255. }
  256. while ((*us1++ != '\0') && (--n != 0));
  257. }
  258. return (0);
  259. }
  260. const char *Utils::stristr(const char *haystack, const char *needle)
  261. {
  262. if(!haystack || !*haystack || !needle || !*needle)
  263. return NULL;
  264. int len = strlen(needle);
  265. for(const char* ptr = haystack; *ptr; ptr++)
  266. {
  267. if(strncasecmp(ptr, needle, len) == 0)
  268. return ptr;
  269. }
  270. return NULL;
  271. }
  272. int Utils::strcasecmp(const char* s1, const char* s2)
  273. {
  274. bool s1isnull = (s1 == NULL);
  275. bool s2isnull = (s2 == NULL);
  276. if(s1isnull || s2isnull)
  277. return s1isnull - s2isnull;
  278. const unsigned char *cm = charmap,
  279. *us1 = (const unsigned char *)s1,
  280. *us2 = (const unsigned char *)s2;
  281. do
  282. {
  283. if (cm[*us1] != cm[*us2++])
  284. return (cm[*us1] - cm[*--us2]);
  285. }
  286. while (*us1++ != '\0');
  287. return (0);
  288. }
  289. static const char BASE64_enc[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
  290. "abcdefghijklmnopqrstuvwxyz"
  291. "0123456789+/";
  292. static const char pad = '=';
  293. //
  294. // Encode the input in a base64 format
  295. //
  296. // const void * data -> data to be encoded
  297. // long length -> length in bytes of this data
  298. // returns StringBuffer& -> the encoded string
  299. //
  300. /*static*/
  301. StringBuffer& Utils::base64encode(const void *data, long length, StringBuffer& result)
  302. {
  303. double olend = 1.5 * (length + (length % 2));
  304. int olen = (int)olend;
  305. char *out = new char[olen + ((olen % 80) * 2) + 2];
  306. const unsigned char *in = static_cast<const unsigned char *>(data);
  307. unsigned char one;
  308. unsigned char two;
  309. unsigned char three;
  310. long i, j;
  311. for(i = 0, j = 0; i < length && length - i >= 3;)
  312. {
  313. one = *(in + i++);
  314. two = *(in + i++);
  315. three = *(in + i++);
  316. // 0x30 -> 0011 0000 b
  317. // 0x3c -> 0011 1100 b
  318. // 0x3f -> 0011 1111 b
  319. //
  320. out[j++] = BASE64_enc[one >> 2];
  321. out[j++] = BASE64_enc[((one << 4) & 0x30) | (two >> 4)];
  322. out[j++] = BASE64_enc[((two << 2) & 0x3c) | (three >> 6)];
  323. out[j++] = BASE64_enc[three & 0x3f];
  324. if(i % 54 == 0)
  325. {
  326. out[j++] = '\n';
  327. }
  328. }
  329. switch(length - i)
  330. {
  331. case 2:
  332. one = *(in + i++);
  333. two = *(in + i++);
  334. out[j++] = BASE64_enc[one >> 2];
  335. out[j++] = BASE64_enc[((one << 4) & 0x30) | (two >> 4)];
  336. out[j++] = BASE64_enc[(two << 2) & 0x3c];
  337. out[j++] = pad;
  338. break;
  339. case 1:
  340. one = *(in + i++);
  341. out[j++] = BASE64_enc[one >> 2];
  342. out[j++] = BASE64_enc[(one << 4) & 0x30];
  343. out[j++] = pad;
  344. out[j++] = pad;
  345. break;
  346. }
  347. out[j++] = '\n';
  348. out[j] = '\0';
  349. result.append(out);
  350. delete[] out;
  351. return result;
  352. }
  353. //
  354. // Decode the input in a base64 format
  355. //
  356. // const char *in -> NUL terminated string to be decoded
  357. // void * out -> Decoded string here
  358. //
  359. /*static*/
  360. int Utils::base64decode(int inlen, const char *in, StringBuffer& data)
  361. {
  362. static unsigned char BASE64_dec[256] = {0};
  363. static bool initialized = false;
  364. if(!initialized)
  365. {
  366. for(int i = 0; i < 64; ++i)
  367. {
  368. BASE64_dec[BASE64_enc[i]] = i;
  369. }
  370. initialized = true;
  371. }
  372. //unsigned char *data = static_cast<unsigned char *>(out);
  373. unsigned char c1, c2, c3, c4;
  374. unsigned char d1, d2, d3, d4;
  375. int len = strlen(in), count = 0;
  376. for(int i = 0; i < len; )
  377. {
  378. if(in[i] == '\n')
  379. {
  380. ++i;
  381. continue;
  382. }
  383. c1 = in[i++];
  384. c2 = in[i++];
  385. c3 = in[i++];
  386. c4 = in[i++];
  387. d1 = BASE64_dec[c1];
  388. d2 = BASE64_dec[c2];
  389. d3 = BASE64_dec[c3];
  390. d4 = BASE64_dec[c4];
  391. //data[count++] = (d1 << 2) | (d2 >> 4);
  392. data.appendf("%c", (d1 << 2) | (d2 >> 4));
  393. count++;
  394. if(c3 == pad)
  395. break;
  396. //data[count++] = (d2 << 4) | (d3 >> 2);
  397. data.appendf("%c", (d2 << 4) | (d3 >> 2));
  398. count++;
  399. if(c4 == pad)
  400. break;
  401. //data[count++] = (d3 << 6) | d4;
  402. data.appendf("%c", (d3 << 6) | d4);
  403. count++;
  404. }
  405. //data[count] = '\0';
  406. return count;
  407. }
  408. IPropertyTree *getBindingConfig(IPropertyTree *tree, const char *binding, const char *process)
  409. {
  410. if (tree==NULL)
  411. return NULL;
  412. const char *topname=tree->queryName();
  413. if (!strcmp("Environment", topname) || !strcmp("Software", topname))
  414. {
  415. if (process!=NULL && *process!=0 && binding!=NULL && *binding!=0)
  416. {
  417. StringBuffer xpath;
  418. xpath.appendf("//EspProcess[@name=\"%s\"]/EspBinding[@name=\"%s\"]", process, binding);
  419. return tree->getPropTree(xpath.str());
  420. }
  421. }
  422. else if (!strcmp(topname, "EspProcess"))
  423. {
  424. if (binding!=NULL && *binding!=0)
  425. {
  426. if (strcmp(tree->queryProp("@name"), process)==0)
  427. {
  428. StringBuffer xpath;
  429. xpath.appendf("EspBinding[@name=\"%s\"]", binding);
  430. return tree->getPropTree(xpath.str());
  431. }
  432. }
  433. }
  434. else if (!strcmp(topname, "EspBinding"))
  435. {
  436. if (strcmp(tree->queryProp("@name"), binding)==0)
  437. {
  438. tree->Link();
  439. return tree;
  440. }
  441. }
  442. return NULL;
  443. }
  444. IPropertyTree *getServiceConfig(IPropertyTree *tree, const char *srv, const char *process)
  445. {
  446. if (tree==NULL)
  447. return NULL;
  448. const char *topname=tree->queryName();
  449. if (!strcmp("Environment", topname) || !strcmp("Software", topname))
  450. {
  451. if (process!=NULL && *process!=0 && srv && *srv)
  452. {
  453. StringBuffer xpath;
  454. xpath.appendf("//EspProcess[@name=\"%s\"]/EspService[@name=\"%s\"]", process, srv);
  455. return tree->getPropTree(xpath.str());
  456. }
  457. }
  458. else if (!strcmp(topname, "EspProcess"))
  459. {
  460. if (srv!=NULL && *srv!=0)
  461. {
  462. if (strcmp(tree->queryProp("@name"), process)==0)
  463. {
  464. StringBuffer xpath;
  465. xpath.appendf("EspService[@name=\"%s\"]", srv);
  466. return tree->getPropTree(xpath.str());
  467. }
  468. }
  469. }
  470. else if (!strcmp(topname, "EspService"))
  471. {
  472. if (strcmp(tree->queryProp("@name"), srv)==0)
  473. {
  474. tree->Link();
  475. return tree;
  476. }
  477. }
  478. return NULL;
  479. }
  480. IPropertyTree *getProcessConfig(IPropertyTree *tree, const char *process)
  481. {
  482. if (tree==NULL)
  483. return NULL;
  484. const char *topname=tree->queryName();
  485. if (!strcmp("Environment", topname) || !strcmp("Software", topname))
  486. {
  487. if (process!=NULL && *process!=0)
  488. {
  489. StringBuffer xpath;
  490. xpath.appendf("//EspProcess[@name=\"%s\"]", process);
  491. return tree->getPropTree(xpath.str());
  492. }
  493. }
  494. else if (!strcmp(topname, "EspProcess"))
  495. {
  496. if (strcmp(tree->queryProp("@name"), process)==0)
  497. return LINK(tree);
  498. }
  499. return NULL;
  500. }
  501. IPropertyTree *getProtocolConfig(IPropertyTree *tree, const char *prot, const char *process)
  502. {
  503. if (tree==NULL)
  504. return NULL;
  505. const char *topname=tree->queryName();
  506. if (!strcmp("Environment", topname) || !strcmp("Software", topname))
  507. {
  508. if (process && *process && prot && *prot)
  509. {
  510. StringBuffer xpath;
  511. xpath.appendf("//EspProcess[@name=\"%s\"]/EspProtocol[@name=\"%s\"]", process, prot);
  512. return tree->getPropTree(xpath.str());
  513. }
  514. }
  515. else if (!strcmp(topname, "EspProcess"))
  516. {
  517. if (prot && *prot)
  518. {
  519. if (strcmp(tree->queryProp("@name"), process)==0)
  520. {
  521. StringBuffer xpath;
  522. xpath.appendf("EspProtocol[@name=\"%s\"]", prot);
  523. return tree->getPropTree(xpath.str());
  524. }
  525. }
  526. }
  527. else if (!strcmp(topname, "EspProtocol"))
  528. {
  529. if (strcmp(tree->queryProp("@name"), prot)==0)
  530. {
  531. tree->Link();
  532. return tree;
  533. }
  534. }
  535. return NULL;
  536. }
  537. static unsigned char isValidUrlChar[96] =
  538. {
  539. 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x1,0x1,0x0, /* !"#$%&'()*+,-./ */
  540. 0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0, /* 0123456789:;<=>? */
  541. 0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1, /* @ABCDEFGHIJKLMNO */
  542. 0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x1, /* PQRSTUVWXYZ[\]^_ */
  543. 0x0,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1, /* `abcdefghijklmno */
  544. 0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0 /* pqrstuvwxyz{\}~DEL */
  545. };
  546. StringBuffer &Utils::url_encode(const char* url, StringBuffer& encoded_url)
  547. {
  548. if(!url)
  549. return encoded_url;
  550. unsigned char c;
  551. int i = 0;
  552. while((c = url[i]) != 0)
  553. {
  554. if(c == ' ')
  555. encoded_url.append('+');
  556. else if(c >= 32 && c < 128 && isValidUrlChar[c - 32])
  557. encoded_url.append(c);
  558. else
  559. encoded_url.appendf("%%%02X", c);
  560. i++;
  561. }
  562. return encoded_url;
  563. }
  564. int Utils::url_decode(const char* url, StringBuffer& result)
  565. {
  566. appendDecodedURL(result, url);
  567. return 0;
  568. }
  569. void Utils::SplitURL(const char* url, StringBuffer& protocol,StringBuffer& UserName,StringBuffer& Password,StringBuffer& host, StringBuffer& port, StringBuffer& path)
  570. {
  571. int protlen = 0;
  572. if(!url || strlen(url) <= 7)
  573. throw MakeStringException(-1, "Invalid URL %s", url);
  574. else if(Utils::strncasecmp(url, "HTTP://", 7) == 0)
  575. {
  576. protocol.append("HTTP");
  577. protlen = 7;
  578. }
  579. else if(Utils::strncasecmp(url, "HTTPS://", 8) == 0)
  580. {
  581. protocol.append("HTTPS");
  582. protlen = 8;
  583. }
  584. else
  585. {
  586. throw MakeStringException(-1, "Please specify protocol HTTP or HTTPS");
  587. }
  588. char buf[URL_MAX+1];
  589. int len = strlen(url);
  590. const char *param = strchr(url + protlen, '?');
  591. if (param)
  592. len = param - url;
  593. if(len > URL_MAX)
  594. len = URL_MAX;
  595. strncpy(buf, url, len);
  596. buf[len] = 0;
  597. char* hostptr;
  598. char *username = NULL;
  599. char* atsign = strchr(buf, '@');
  600. if(atsign)
  601. {
  602. username = buf + protlen;
  603. hostptr = atsign + 1;
  604. *atsign = '\0';
  605. }
  606. else
  607. {
  608. hostptr = buf + protlen;
  609. }
  610. char* pathptr = strchr(hostptr, '/');
  611. if(pathptr)
  612. {
  613. *pathptr = 0;
  614. pathptr++;
  615. }
  616. char* portptr = strchr(hostptr, ':');
  617. if(portptr)
  618. {
  619. *portptr = 0;
  620. portptr++;
  621. }
  622. if(username)
  623. {
  624. char* semicln = strchr(username, ':');
  625. if(semicln)
  626. {
  627. Password.append(semicln+1);
  628. *semicln = '\0';
  629. }
  630. UserName.append(username);
  631. }
  632. if(hostptr)
  633. host.append(hostptr);
  634. if(portptr)
  635. port.append(portptr);
  636. path.append("/");
  637. if(pathptr)
  638. path.append(pathptr);
  639. if(param)
  640. path.append(param);
  641. }
  642. class CStringIntMap : public CInterface,
  643. implements IEspStringIntMap
  644. {
  645. std::map<std::string, int> c_map;
  646. public:
  647. IMPLEMENT_IINTERFACE;
  648. int queryValue(const char *key){return c_map[key];}
  649. void setValue(const char *key, int value){c_map[key]=value;}
  650. };
  651. IEspStringIntMap *createStringIntMap()
  652. {
  653. return new CStringIntMap;
  654. }
  655. void buildArrayHint(StringBuffer& s, int indents, const char* tag, const char* cls)
  656. {
  657. s.pad(indents).appendf("<%s>\\n", tag);
  658. s.pad(indents+1).append("<RawArray>\\n");
  659. if (cls)
  660. {
  661. s.pad(indents+2).append("<Item>\\n");
  662. s.append(cls);
  663. s.pad(indents+2).append("</Item>\\n");
  664. }
  665. else
  666. s.pad(indents+2).append("<Item></Item>\\n");
  667. s.pad(indents+1).append("</RawArray>\\n");
  668. s.pad(indents).appendf("</%s>\\n", tag);
  669. }
  670. void xslTransformHelper(IXslProcessor *xslp, const char* xml, const char* xslFile, StringBuffer& output, IProperties *params)
  671. {
  672. if (xslp)
  673. {
  674. Owned<IXslTransform> xform = xslp->createXslTransform();
  675. StringBuffer xslpath;
  676. if (!strnicmp(xslFile, "/esp/xslt/", 10))
  677. if (!checkFileExists(xslpath.append(getCFD()).append("smc_xslt/").append(xslFile+10).str()) && !checkFileExists(xslpath.append(getCFD()).append("xslt/").append(xslFile+10).str()))
  678. return;
  679. xform->loadXslFromFile((xslpath.length()) ? xslpath.str() : xslFile);
  680. xform->setXmlSource(xml, strlen(xml)+1);
  681. if (params) xform->copyParameters(params);
  682. xform->transform(output.clear());
  683. }
  684. }
  685. const char *mimeTypeFromFileExt(const char *ext)
  686. {
  687. if (!ext)
  688. return "application/octet-stream";
  689. if (*ext=='.')
  690. ext++;
  691. if (strieq(ext, "html") || strieq(ext, "htm"))
  692. return "text/html";
  693. if (strieq(ext, "xml") || strieq(ext, "xsl") || strieq(ext, "xslt"))
  694. return "application/xml";
  695. if (strieq(ext, "js"))
  696. return "text/javascript";
  697. if (strieq(ext, "css"))
  698. return "text/css";
  699. if (strieq(ext, "jpeg") || strieq(ext, "jpg"))
  700. return "image/jpeg";
  701. if (strieq(ext, "gif"))
  702. return "image/gif";
  703. if (strieq(ext, "png"))
  704. return "image/png";
  705. if (strieq(ext, "svg"))
  706. return "image/svg+xml";
  707. if (strieq(ext, "txt") || strieq(ext, "text"))
  708. return "text/plain";
  709. if (strieq(ext, "zip"))
  710. return "application/zip";
  711. if (strieq(ext, "pdf"))
  712. return "application/pdf";
  713. if (strieq(ext, "xpi"))
  714. return "application/x-xpinstall";
  715. if (strieq(ext, "exe") || strieq(ext, "class"))
  716. return "application/octet-stream";
  717. return "application/octet-stream";
  718. }
  719. class DECL_EXCEPTION CEspHttpException: public IEspHttpException, public CInterface
  720. {
  721. public:
  722. IMPLEMENT_IINTERFACE;
  723. CEspHttpException(int code, const char *_msg, const char* _httpstatus) : errcode(code), msg(_msg), httpstatus(_httpstatus){ };
  724. int errorCode() const { return (errcode); };
  725. StringBuffer & errorMessage(StringBuffer &str) const
  726. {
  727. return str.append("CEspHttpException: (").append(msg).append(")");
  728. };
  729. MessageAudience errorAudience() const { return (MSGAUD_user); };
  730. virtual const char* getHttpStatus() {return httpstatus.get(); }
  731. private:
  732. int errcode;
  733. StringAttr msg;
  734. StringAttr httpstatus;
  735. };
  736. IEspHttpException* createEspHttpException(int code, const char *_msg, const char* _httpstatus)
  737. {
  738. return new CEspHttpException(code, _msg, _httpstatus);
  739. }