BBS2chProxyHttpHeaders.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540
  1. #include <algorithm>
  2. #include <string.h>
  3. #include "BBS2chProxyHttpHeaders.h"
  4. const std::string& BBS2chProxyHttpHeaderEntry::getName(void)
  5. {
  6. return _name;
  7. }
  8. std::string BBS2chProxyHttpHeaderEntry::getLowercasedName(void)
  9. {
  10. std::string lowerName = _name;
  11. std::transform(_name.begin(), _name.end(), lowerName.begin(), tolower);
  12. return lowerName;
  13. }
  14. std::string BBS2chProxyHttpHeaderEntry::getValue(void)
  15. {
  16. std::string ret;
  17. for (std::vector<std::string>::iterator it = _values.begin(); it != _values.end(); it++) {
  18. if (!ret.empty()) ret += ", ";
  19. ret += *it;
  20. }
  21. return ret;
  22. }
  23. std::string BBS2chProxyHttpHeaderEntry::getFull(void)
  24. {
  25. std::string ret = _name;
  26. ret += ": ";
  27. ret += getValue();
  28. return ret;
  29. }
  30. std::vector<std::string>& BBS2chProxyHttpHeaderEntry::getValueList(void)
  31. {
  32. return _values;
  33. }
  34. void BBS2chProxyHttpHeaderEntry::add(const std::string &value)
  35. {
  36. _values.push_back(value);
  37. }
  38. void BBS2chProxyHttpHeaderEntry::set(const std::string &value)
  39. {
  40. _values.clear();
  41. _values.push_back(value);
  42. }
  43. bool BBS2chProxyHttpHeaderEntry::has(const std::string &value)
  44. {
  45. for (std::vector<std::string>::iterator it = _values.begin(); it != _values.end(); it++) {
  46. if (*it == value) return true;
  47. }
  48. return false;
  49. }
  50. bool BBS2chProxyHttpHeaderEntry::contains(const std::string &value)
  51. {
  52. for (std::vector<std::string>::iterator it = _values.begin(); it != _values.end(); it++) {
  53. if (it->find(value) != std::string::npos) return true;
  54. }
  55. return false;
  56. }
  57. std::string BBS2chProxyHttpHeaders::get(const std::string &name)
  58. {
  59. if (!has(name)) return "";
  60. std::string lowerName = name;
  61. std::transform(name.begin(), name.end(), lowerName.begin(), tolower);
  62. return _headers[lowerName]->getValue();
  63. }
  64. bool BBS2chProxyHttpHeaders::has(const std::string &name)
  65. {
  66. if (_headers.empty()) return false;
  67. std::string lowerName = name;
  68. std::transform(name.begin(), name.end(), lowerName.begin(), tolower);
  69. return _headers.count(lowerName) != 0;
  70. }
  71. bool BBS2chProxyHttpHeaders::hasNameAndValue(const std::string &name, const std::string &value)
  72. {
  73. if (_headers.empty()) return false;
  74. std::string lowerName = name;
  75. std::transform(name.begin(), name.end(), lowerName.begin(), tolower);
  76. if (!_headers.count(lowerName)) return false;
  77. PBBS2chProxyHttpHeaderEntry entry = _headers[lowerName];
  78. return entry->has(value);
  79. }
  80. void BBS2chProxyHttpHeaders::add(const std::string &name, const std::string &value)
  81. {
  82. if (name.empty()) return;
  83. if (!has(name)) return set(name, value);
  84. std::string lowerName = name;
  85. std::transform(name.begin(), name.end(), lowerName.begin(), tolower);
  86. PBBS2chProxyHttpHeaderEntry entry = _headers[lowerName];
  87. entry->add(value);
  88. }
  89. void BBS2chProxyHttpHeaders::add(const char *field)
  90. {
  91. const char *ptr = field;
  92. while (*ptr == ' ' || *ptr == '\t') ptr++;
  93. const char *start = ptr;
  94. while (*ptr != ':' && *ptr != 0) ptr++;
  95. if (*ptr != ':' || ptr == start) return;
  96. const char *next = ptr + 1;
  97. ptr--;
  98. while (*ptr == ' ' && ptr > start) ptr--;
  99. std::string name(start, ptr-start+1);
  100. ptr = next;
  101. while (*ptr == ' ' || *ptr == '\t') ptr++;
  102. start = ptr;
  103. while (*ptr != '\r' && *ptr != '\n' && *ptr != 0) ptr++;
  104. std::string value(start, ptr-start);
  105. add(name, value);
  106. }
  107. void BBS2chProxyHttpHeaders::add(const char *field, size_t length)
  108. {
  109. const char *ptr = field;
  110. const char *end = field + length;
  111. while (ptr < end && (*ptr == ' ' || *ptr == '\t')) ptr++;
  112. if (ptr == end) return;
  113. const char *start = ptr;
  114. while (*ptr != ':' && ptr < end) ptr++;
  115. if (ptr == end || ptr == start) return;
  116. const char *next = ptr + 1;
  117. ptr--;
  118. while (*ptr == ' ' && ptr > start) ptr--;
  119. std::string name(start, ptr-start+1);
  120. ptr = next;
  121. while (ptr < end && (*ptr == ' ' || *ptr == '\t')) ptr++;
  122. start = ptr;
  123. while (ptr < end && *ptr != '\r' && *ptr != '\n') ptr++;
  124. std::string value(start, ptr-start);
  125. add(name, value);
  126. }
  127. void BBS2chProxyHttpHeaders::set(const std::string &name, const std::string &value)
  128. {
  129. if (name.empty()) return;
  130. std::string lowerName = name;
  131. std::transform(name.begin(), name.end(), lowerName.begin(), tolower);
  132. _headers.erase(lowerName);
  133. PBBS2chProxyHttpHeaderEntry entry(new BBS2chProxyHttpHeaderEntry(name, value));
  134. _headers.insert(std::make_pair(lowerName, entry));
  135. }
  136. void BBS2chProxyHttpHeaders::remove(const std::string &name)
  137. {
  138. if (name.empty()) return;
  139. std::string lowerName = name;
  140. std::transform(name.begin(), name.end(), lowerName.begin(), tolower);
  141. _headers.erase(lowerName);
  142. }
  143. void BBS2chProxyHttpHeaders::clear(void)
  144. {
  145. _headers.clear();
  146. }
  147. curl_slist* BBS2chProxyHttpHeaders::appendToCurlSlist(curl_slist *list)
  148. {
  149. for (std::map<std::string, PBBS2chProxyHttpHeaderEntry>::iterator it = _headers.begin(); it != _headers.end(); it++) {
  150. std::vector<std::string>& values = it->second->getValueList();
  151. for (std::vector<std::string>::iterator it2 = values.begin(); it2 != values.end(); it2++) {
  152. std::string header = it->second->getName();
  153. header += ": ";
  154. header += *it2;
  155. list = curl_slist_append(list, header.c_str());
  156. }
  157. }
  158. return list;
  159. }
  160. curl_slist* BBS2chProxyHttpHeaders::appendToCurlSlist(curl_slist *list, const std::string &name)
  161. {
  162. if (name.empty()) return list;
  163. std::string lowerName = name;
  164. std::transform(name.begin(), name.end(), lowerName.begin(), tolower);
  165. if (_headers.count(lowerName)) {
  166. PBBS2chProxyHttpHeaderEntry& entry = _headers[lowerName];
  167. std::vector<std::string>& values = entry->getValueList();
  168. for (std::vector<std::string>::iterator it = values.begin(); it != values.end(); it++) {
  169. std::string header = entry->getName();
  170. header += ": ";
  171. header += *it;
  172. list = curl_slist_append(list, header.c_str());
  173. }
  174. }
  175. return list;
  176. }
  177. std::map<std::string, PBBS2chProxyHttpHeaderEntry>& BBS2chProxyHttpHeaders::getMap(void)
  178. {
  179. return _headers;
  180. }
  181. PBBS2chProxyHttpHeaderEntry BBS2chProxyHttpHeaders::parse(const char *field, size_t length)
  182. {
  183. PBBS2chProxyHttpHeaderEntry entry;
  184. const char *ptr = field;
  185. const char *end = field + length;
  186. while (ptr < end && (*ptr == ' ' || *ptr == '\t')) ptr++;
  187. if (ptr == end) return entry;
  188. const char *start = ptr;
  189. while (*ptr != ':' && ptr < end) ptr++;
  190. if (ptr == end || ptr == start) return entry;
  191. const char *next = ptr + 1;
  192. ptr--;
  193. while (*ptr == ' ' && ptr > start) ptr--;
  194. std::string name(start, ptr-start+1);
  195. ptr = next;
  196. while (ptr < end && (*ptr == ' ' || *ptr == '\t')) ptr++;
  197. start = ptr;
  198. while (ptr < end && *ptr != '\r' && *ptr != '\n') ptr++;
  199. std::string value(start, ptr-start);
  200. entry.reset(new BBS2chProxyHttpHeaderEntry(name, value));
  201. return entry;
  202. }
  203. #ifdef USE_LUA
  204. static bool lua_isValidUserdata(lua_State *l, int idx)
  205. {
  206. if (!lua_getmetatable(l, idx)) {
  207. return false;
  208. }
  209. if (lua_getfield(l, -1, "_type") != LUA_TSTRING) {
  210. lua_pop(l, 2);
  211. return false;
  212. }
  213. bool isValid = !strcmp(lua_tostring(l, -1), "HttpHeaders");
  214. lua_pop(l, 2);
  215. return isValid;
  216. }
  217. static int lua_httpHeadersGet(lua_State *l)
  218. {
  219. BBS2chProxyHttpHeaders *headers = NULL;
  220. const char *name = luaL_checkstring(l, 2);
  221. void *obj = lua_touserdata(l, 1);
  222. if (!obj) {
  223. lua_pushnil(l);
  224. return 1;
  225. }
  226. if (lua_isValidUserdata(l, 1)) {
  227. headers = *((BBS2chProxyHttpHeaders **)obj);
  228. }
  229. if (headers && headers->has(name)) {
  230. lua_pushstring(l, headers->get(name).c_str());
  231. }
  232. else {
  233. lua_pushnil(l);
  234. }
  235. return 1;
  236. }
  237. static int lua_httpHeadersSet(lua_State *l)
  238. {
  239. BBS2chProxyHttpHeaders *headers = NULL;
  240. const char *name = luaL_checkstring(l, 2);
  241. const char *value = NULL;
  242. if (!lua_isnoneornil(l, 3)) {
  243. value = luaL_checkstring(l, 3);
  244. }
  245. void *obj = lua_touserdata(l, 1);
  246. if (!obj) {
  247. return 0;
  248. }
  249. if (lua_isValidUserdata(l, 1)) {
  250. headers = *((BBS2chProxyHttpHeaders **)obj);
  251. }
  252. if (headers) {
  253. if (value) headers->set(name, value);
  254. else headers->remove(name);
  255. }
  256. return 0;
  257. }
  258. static int lua_httpHeadersAdd(lua_State *l)
  259. {
  260. BBS2chProxyHttpHeaders *headers = NULL;
  261. const char *name = luaL_checkstring(l, 2);
  262. const char *value = NULL;
  263. if (!lua_isnoneornil(l, 3)) {
  264. value = luaL_checkstring(l, 3);
  265. }
  266. void *obj = lua_touserdata(l, 1);
  267. if (!obj) {
  268. return 0;
  269. }
  270. if (lua_isValidUserdata(l, 1)) {
  271. headers = *((BBS2chProxyHttpHeaders **)obj);
  272. }
  273. if (headers && value) {
  274. headers->add(name, value);
  275. }
  276. return 0;
  277. }
  278. static int lua_httpHeadersHas(lua_State *l)
  279. {
  280. BBS2chProxyHttpHeaders *headers = NULL;
  281. const char *name = luaL_checkstring(l, 2);
  282. void *obj = lua_touserdata(l, 1);
  283. if (!obj) {
  284. lua_pushboolean(l, 0);
  285. return 1;
  286. }
  287. if (lua_isValidUserdata(l, 1)) {
  288. headers = *((BBS2chProxyHttpHeaders **)obj);
  289. }
  290. if (headers) {
  291. lua_pushboolean(l, headers->has(name));
  292. }
  293. else {
  294. lua_pushboolean(l, 0);
  295. }
  296. return 1;
  297. }
  298. static int lua_httpHeadersRemove(lua_State *l)
  299. {
  300. BBS2chProxyHttpHeaders *headers = NULL;
  301. const char *name = luaL_checkstring(l, 2);
  302. void *obj = lua_touserdata(l, 1);
  303. if (!obj) {
  304. return 0;
  305. }
  306. if (lua_isValidUserdata(l, 1)) {
  307. headers = *((BBS2chProxyHttpHeaders **)obj);
  308. }
  309. if (headers) {
  310. headers->remove(name);
  311. }
  312. return 0;
  313. }
  314. static int lua_httpHeadersClear(lua_State *l)
  315. {
  316. BBS2chProxyHttpHeaders *headers = NULL;
  317. void *obj = lua_touserdata(l, 1);
  318. if (!obj) {
  319. return 0;
  320. }
  321. if (lua_isValidUserdata(l, 1)) {
  322. headers = *((BBS2chProxyHttpHeaders **)obj);
  323. }
  324. if (headers) {
  325. headers->clear();
  326. }
  327. return 0;
  328. }
  329. static int lua_httpHeadersCount(lua_State *l)
  330. {
  331. BBS2chProxyHttpHeaders *headers = NULL;
  332. void *obj = lua_touserdata(l, 1);
  333. if (!obj) {
  334. lua_pushinteger(l, 0);
  335. return 1;
  336. }
  337. if (lua_isValidUserdata(l, 1)) {
  338. headers = *((BBS2chProxyHttpHeaders **)obj);
  339. }
  340. if (headers) {
  341. lua_pushinteger(l, headers->getMap().size());
  342. }
  343. else {
  344. lua_pushinteger(l, 0);
  345. }
  346. return 1;
  347. }
  348. static int lua_httpHeadersNext(lua_State *l)
  349. {
  350. BBS2chProxyHttpHeaders *headers = NULL;
  351. const char *index = NULL;
  352. if (!lua_isnoneornil(l, 2)) {
  353. index = luaL_checkstring(l, 2);
  354. }
  355. void *obj = lua_touserdata(l, 1);
  356. if (!obj) {
  357. goto fail;
  358. }
  359. if (lua_isValidUserdata(l, 1)) {
  360. headers = *((BBS2chProxyHttpHeaders **)obj);
  361. }
  362. if (headers) {
  363. if (headers->getMap().empty()) {
  364. goto fail;
  365. }
  366. std::map<std::string, PBBS2chProxyHttpHeaderEntry>::iterator it = headers->getMap().begin();
  367. if (!index) {
  368. lua_pushstring(l, it->second->getName().c_str());
  369. lua_pushstring(l, it->second->getValue().c_str());
  370. return 2;
  371. }
  372. for (; it != headers->getMap().end(); it++) {
  373. if (it->second->getName() == index) {
  374. break;
  375. }
  376. }
  377. if (++it != headers->getMap().end()) {
  378. lua_pushstring(l, it->second->getName().c_str());
  379. lua_pushstring(l, it->second->getValue().c_str());
  380. return 2;
  381. }
  382. }
  383. fail:
  384. lua_pushnil(l);
  385. return 1;
  386. }
  387. static int lua_httpHeadersPairs(lua_State *l)
  388. {
  389. void *obj = lua_touserdata(l, 1);
  390. if (!obj) {
  391. return 0;
  392. }
  393. if (lua_isValidUserdata(l, 1)) {
  394. lua_pushcfunction(l, lua_httpHeadersNext);
  395. lua_pushvalue(l, 1);
  396. lua_pushnil(l);
  397. return 3;
  398. }
  399. return 0;
  400. }
  401. static int lua_httpHeadersNew(lua_State *l)
  402. {
  403. void **obj = (void **)lua_newuserdata(l, sizeof(void *));
  404. *obj = new BBS2chProxyHttpHeaders();
  405. lua_pushvalue(l, lua_upvalueindex(1));
  406. lua_setmetatable(l, -2);
  407. return 1;
  408. }
  409. static int lua_httpHeadersDelete(lua_State *l)
  410. {
  411. void *obj = lua_touserdata(l, 1);
  412. if (!obj) {
  413. return 0;
  414. }
  415. if (lua_isValidUserdata(l, 1)) {
  416. delete *((BBS2chProxyHttpHeaders **)obj);
  417. }
  418. return 0;
  419. }
  420. static int lua_functionOrGetter(lua_State *l)
  421. {
  422. if (!lua_getmetatable(l, 1)) {
  423. lua_pushnil(l);
  424. return 1;
  425. }
  426. lua_pushvalue(l, 2);
  427. if (lua_rawget(l, -2) == LUA_TFUNCTION) {
  428. return 1;
  429. }
  430. lua_pop(l, 2);
  431. return lua_httpHeadersGet(l);
  432. }
  433. static int lua_enableLowLevelFuncs(lua_State *l)
  434. {
  435. if (!lua_isuserdata(l, 1) || !lua_isValidUserdata(l, 1)) {
  436. return 0;
  437. }
  438. if (!lua_getmetatable(l, 1)) {
  439. return 0;
  440. }
  441. lua_newtable(l);
  442. lua_pushnil(l);
  443. while (lua_next(l, -3)) {
  444. lua_pushvalue(l, -2);
  445. lua_insert(l, -2);
  446. lua_settable(l, -4);
  447. }
  448. lua_pushcfunction(l, lua_functionOrGetter);
  449. lua_setfield(l, -2, "__index");
  450. lua_setmetatable(l, 1);
  451. lua_pop(l, 1);
  452. return 0;
  453. }
  454. void BBS2chProxyHttpHeaders::getObjectMetatableForLua(lua_State *l)
  455. {
  456. lua_newtable(l);
  457. lua_pushcfunction(l, lua_httpHeadersGet);
  458. lua_setfield(l, -2, "__index");
  459. lua_pushcfunction(l, lua_httpHeadersSet);
  460. lua_setfield(l, -2, "__newindex");
  461. lua_pushcfunction(l, lua_httpHeadersPairs);
  462. lua_setfield(l, -2, "__pairs");
  463. lua_pushcfunction(l, lua_httpHeadersCount);
  464. lua_setfield(l, -2, "__len");
  465. lua_pushcfunction(l, lua_httpHeadersGet);
  466. lua_setfield(l, -2, "get");
  467. lua_pushcfunction(l, lua_httpHeadersSet);
  468. lua_setfield(l, -2, "set");
  469. lua_pushcfunction(l, lua_httpHeadersAdd);
  470. lua_setfield(l, -2, "add");
  471. lua_pushcfunction(l, lua_httpHeadersHas);
  472. lua_setfield(l, -2, "has");
  473. lua_pushcfunction(l, lua_httpHeadersRemove);
  474. lua_setfield(l, -2, "remove");
  475. lua_pushcfunction(l, lua_httpHeadersClear);
  476. lua_setfield(l, -2, "clear");
  477. lua_pushcfunction(l, lua_httpHeadersCount);
  478. lua_setfield(l, -2, "count");
  479. lua_pushliteral(l, "HttpHeaders");
  480. lua_setfield(l, -2, "_type");
  481. }
  482. void BBS2chProxyHttpHeaders::getClassDefinitionForLua(lua_State *l)
  483. {
  484. lua_newtable(l);
  485. getObjectMetatableForLua(l);
  486. lua_pushcfunction(l, lua_httpHeadersDelete);
  487. lua_setfield(l, -2, "__gc");
  488. lua_pushcclosure(l, lua_httpHeadersNew, 1);
  489. lua_setfield(l, -2, "new");
  490. lua_pushcfunction(l, lua_enableLowLevelFuncs);
  491. lua_setfield(l, -2, "enableLowLevelAccess");
  492. }
  493. void BBS2chProxyHttpHeaders::getUserdataForLua(lua_State *l)
  494. {
  495. void **obj = (void **)lua_newuserdata(l, sizeof(this));
  496. *obj = this;
  497. getObjectMetatableForLua(l);
  498. lua_setmetatable(l, -2);
  499. }
  500. #endif