BBS2chProxyHttpHeaders.cpp 11 KB

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