BBS2chProxyHttpHeaders.cpp 11 KB

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