BBS2chProxyHttpHeaders.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704
  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. std::string delimiter = ", ";
  18. if (getLowercasedName() == "cookie") delimiter = "; ";
  19. for (std::vector<std::string>::iterator it = _values.begin(); it != _values.end(); it++) {
  20. if (!ret.empty()) ret += delimiter;
  21. ret += *it;
  22. }
  23. return ret;
  24. }
  25. std::string BBS2chProxyHttpHeaderEntry::getFull(bool shouldIncludeLineBreak)
  26. {
  27. if (shouldIncludeLineBreak) {
  28. std::string header;
  29. for (std::vector<std::string>::iterator it = _values.begin(); it != _values.end(); it++) {
  30. header += _name;
  31. header += ": ";
  32. header += *it;
  33. header += "\r\n";
  34. }
  35. return header;
  36. }
  37. std::string ret = _name;
  38. ret += ": ";
  39. ret += getValue();
  40. return ret;
  41. }
  42. std::vector<std::string>& BBS2chProxyHttpHeaderEntry::getValueList(void)
  43. {
  44. return _values;
  45. }
  46. void BBS2chProxyHttpHeaderEntry::add(const std::string &value)
  47. {
  48. _values.push_back(value);
  49. }
  50. void BBS2chProxyHttpHeaderEntry::set(const std::string &value)
  51. {
  52. _values.clear();
  53. _values.push_back(value);
  54. }
  55. bool BBS2chProxyHttpHeaderEntry::has(const std::string &value)
  56. {
  57. for (std::vector<std::string>::iterator it = _values.begin(); it != _values.end(); it++) {
  58. if (*it == value) return true;
  59. }
  60. return false;
  61. }
  62. bool BBS2chProxyHttpHeaderEntry::contains(const std::string &value)
  63. {
  64. for (std::vector<std::string>::iterator it = _values.begin(); it != _values.end(); it++) {
  65. if (it->find(value) != std::string::npos) return true;
  66. }
  67. return false;
  68. }
  69. void BBS2chProxyHttpHeaderEntry::replaceValue(const std::string &from, const std::string &to)
  70. {
  71. for (std::vector<std::string>::iterator it = _values.begin(); it != _values.end(); it++) {
  72. size_t pos = it->find(from);
  73. while (pos != std::string::npos) {
  74. it->replace(pos, from.size(), to);
  75. pos = it->find(from, pos+to.size());
  76. }
  77. }
  78. }
  79. std::string BBS2chProxyHttpHeaders::get(const std::string &name)
  80. {
  81. if (!has(name)) return "";
  82. std::string lowerName = name;
  83. std::transform(name.begin(), name.end(), lowerName.begin(), tolower);
  84. return _headers[lowerName]->getValue();
  85. }
  86. std::string BBS2chProxyHttpHeaders::getFull(const std::string &name, bool shouldIncludeLineBreak)
  87. {
  88. if (!has(name)) return "";
  89. std::string lowerName = name;
  90. std::transform(name.begin(), name.end(), lowerName.begin(), tolower);
  91. return _headers[lowerName]->getFull(shouldIncludeLineBreak);
  92. }
  93. PBBS2chProxyHttpHeaderEntry BBS2chProxyHttpHeaders::getEntry(const std::string &name)
  94. {
  95. if (!has(name)) return PBBS2chProxyHttpHeaderEntry();
  96. std::string lowerName = name;
  97. std::transform(name.begin(), name.end(), lowerName.begin(), tolower);
  98. return _headers[lowerName];
  99. }
  100. bool BBS2chProxyHttpHeaders::has(const std::string &name)
  101. {
  102. if (_headers.empty()) return false;
  103. std::string lowerName = name;
  104. std::transform(name.begin(), name.end(), lowerName.begin(), tolower);
  105. return _headers.count(lowerName) != 0;
  106. }
  107. bool BBS2chProxyHttpHeaders::hasNameAndValue(const std::string &name, const std::string &value)
  108. {
  109. if (_headers.empty()) return false;
  110. std::string lowerName = name;
  111. std::transform(name.begin(), name.end(), lowerName.begin(), tolower);
  112. std::map<std::string, PBBS2chProxyHttpHeaderEntry>::iterator it = _headers.find(lowerName);
  113. if (it == _headers.end()) return false;
  114. return it->second->has(value);
  115. }
  116. void BBS2chProxyHttpHeaders::add(const std::string &name, const std::string &value)
  117. {
  118. if (name.empty()) return;
  119. if (!has(name)) return set(name, value);
  120. std::string lowerName = name;
  121. std::transform(name.begin(), name.end(), lowerName.begin(), tolower);
  122. PBBS2chProxyHttpHeaderEntry entry = _headers[lowerName];
  123. entry->add(value);
  124. }
  125. void BBS2chProxyHttpHeaders::add(const char *field)
  126. {
  127. const char *ptr = field;
  128. while (*ptr == ' ' || *ptr == '\t') ptr++;
  129. const char *start = ptr;
  130. while (*ptr != ':' && *ptr != 0) ptr++;
  131. if (*ptr != ':' || ptr == start) return;
  132. const char *next = ptr + 1;
  133. ptr--;
  134. while (*ptr == ' ' && ptr > start) ptr--;
  135. std::string name(start, ptr-start+1);
  136. ptr = next;
  137. while (*ptr == ' ' || *ptr == '\t') ptr++;
  138. start = ptr;
  139. while (*ptr != '\r' && *ptr != '\n' && *ptr != 0) ptr++;
  140. std::string value(start, ptr-start);
  141. add(name, value);
  142. }
  143. void BBS2chProxyHttpHeaders::add(const char *field, size_t length)
  144. {
  145. const char *ptr = field;
  146. const char *end = field + length;
  147. while (ptr < end && (*ptr == ' ' || *ptr == '\t')) ptr++;
  148. if (ptr == end) return;
  149. const char *start = ptr;
  150. while (*ptr != ':' && ptr < end) ptr++;
  151. if (ptr == end || ptr == start) return;
  152. const char *next = ptr + 1;
  153. ptr--;
  154. while (*ptr == ' ' && ptr > start) ptr--;
  155. std::string name(start, ptr-start+1);
  156. ptr = next;
  157. while (ptr < end && (*ptr == ' ' || *ptr == '\t')) ptr++;
  158. start = ptr;
  159. while (ptr < end && *ptr != '\r' && *ptr != '\n') ptr++;
  160. std::string value(start, ptr-start);
  161. add(name, value);
  162. }
  163. void BBS2chProxyHttpHeaders::set(const std::string &name, const std::string &value)
  164. {
  165. if (name.empty()) return;
  166. std::string lowerName = name;
  167. std::transform(name.begin(), name.end(), lowerName.begin(), tolower);
  168. _headers.erase(lowerName);
  169. PBBS2chProxyHttpHeaderEntry entry(new BBS2chProxyHttpHeaderEntry(name, value));
  170. _headers.insert(std::make_pair(lowerName, entry));
  171. }
  172. void BBS2chProxyHttpHeaders::set(PBBS2chProxyHttpHeaderEntry entry)
  173. {
  174. const std::string &lowerName = entry->getLowercasedName();
  175. _headers.erase(lowerName);
  176. _headers.insert(std::make_pair(lowerName, entry));
  177. }
  178. void BBS2chProxyHttpHeaders::remove(const std::string &name)
  179. {
  180. if (name.empty()) return;
  181. std::string lowerName = name;
  182. std::transform(name.begin(), name.end(), lowerName.begin(), tolower);
  183. _headers.erase(lowerName);
  184. }
  185. void BBS2chProxyHttpHeaders::clear(void)
  186. {
  187. _headers.clear();
  188. }
  189. const std::string& BBS2chProxyHttpHeaders::getStatusLine()
  190. {
  191. return _statusLine;
  192. }
  193. void BBS2chProxyHttpHeaders::setStatusLine(const char *field, size_t length)
  194. {
  195. if (length < 5 || strncasecmp(field, "HTTP/", 5)) return;
  196. const char *ptr = field + 5;
  197. const char *end = field + length;
  198. while (ptr < end && *ptr != ' ') ptr++;
  199. while (ptr < end && *ptr == ' ') ptr++;
  200. if (ptr < end) {
  201. unsigned long code = strtoul(ptr, (char **)&ptr, 10);
  202. if (code == 0) return;
  203. while (ptr < end && *ptr != '\r' && *ptr != '\n') ptr++;
  204. _statusLine = std::string(field, ptr-field);
  205. }
  206. }
  207. curl_slist* BBS2chProxyHttpHeaders::appendToCurlSlist(curl_slist *list, const std::set<std::string> &excludes)
  208. {
  209. for (std::map<std::string, PBBS2chProxyHttpHeaderEntry>::iterator it = _headers.begin(); it != _headers.end(); it++) {
  210. if (excludes.find(it->first) != excludes.end()) continue;
  211. std::vector<std::string>& values = it->second->getValueList();
  212. for (std::vector<std::string>::iterator it2 = values.begin(); it2 != values.end(); it2++) {
  213. std::string header = it->second->getName();
  214. header += ": ";
  215. header += *it2;
  216. list = curl_slist_append(list, header.c_str());
  217. }
  218. }
  219. return list;
  220. }
  221. curl_slist* BBS2chProxyHttpHeaders::appendToCurlSlist(curl_slist *list, const std::string &name)
  222. {
  223. if (name.empty()) return list;
  224. std::string lowerName = name;
  225. std::transform(name.begin(), name.end(), lowerName.begin(), tolower);
  226. std::map<std::string, PBBS2chProxyHttpHeaderEntry>::iterator it = _headers.find(lowerName);
  227. if (it != _headers.end()) {
  228. PBBS2chProxyHttpHeaderEntry& entry = it->second;
  229. std::vector<std::string>& values = entry->getValueList();
  230. for (std::vector<std::string>::iterator it = values.begin(); it != values.end(); it++) {
  231. std::string header = entry->getName();
  232. header += ": ";
  233. header += *it;
  234. list = curl_slist_append(list, header.c_str());
  235. }
  236. }
  237. return list;
  238. }
  239. std::map<std::string, PBBS2chProxyHttpHeaderEntry>& BBS2chProxyHttpHeaders::getMap(void)
  240. {
  241. return _headers;
  242. }
  243. bool BBS2chProxyHttpHeaders::empty()
  244. {
  245. return _headers.empty();
  246. }
  247. BBS2chProxyHttpHeaders::iterator BBS2chProxyHttpHeaders::begin()
  248. {
  249. return BBS2chProxyHttpHeadersIterator(this, false);
  250. }
  251. BBS2chProxyHttpHeaders::iterator BBS2chProxyHttpHeaders::end()
  252. {
  253. return BBS2chProxyHttpHeadersIterator(this, true);
  254. }
  255. PBBS2chProxyHttpHeaderEntry BBS2chProxyHttpHeaders::parse(const char *field, size_t length)
  256. {
  257. PBBS2chProxyHttpHeaderEntry entry;
  258. const char *ptr = field;
  259. const char *end = field + length;
  260. while (ptr < end && (*ptr == ' ' || *ptr == '\t')) ptr++;
  261. if (ptr == end) return entry;
  262. const char *start = ptr;
  263. while (*ptr != ':' && ptr < end) ptr++;
  264. if (ptr == end || ptr == start) return entry;
  265. const char *next = ptr + 1;
  266. ptr--;
  267. while (*ptr == ' ' && ptr > start) ptr--;
  268. std::string name(start, ptr-start+1);
  269. ptr = next;
  270. while (ptr < end && (*ptr == ' ' || *ptr == '\t')) ptr++;
  271. start = ptr;
  272. while (ptr < end && *ptr != '\r' && *ptr != '\n') ptr++;
  273. std::string value(start, ptr-start);
  274. entry.reset(new BBS2chProxyHttpHeaderEntry(name, value));
  275. return entry;
  276. }
  277. BBS2chProxyHttpHeadersIterator::BBS2chProxyHttpHeadersIterator(BBS2chProxyHttpHeaders* headers, bool firstOrLast)
  278. {
  279. _mapIteratorEnd = headers->_headers.end();
  280. if (!firstOrLast && !headers->_headers.empty()) {
  281. _mapIterator = headers->_headers.begin();
  282. _vectorIterator = _mapIterator->second->_values.begin();
  283. std::string tmp = _mapIterator->second->_name + ": ";
  284. _value = std::make_pair(_mapIterator->second, tmp + *_vectorIterator);
  285. } else {
  286. _mapIterator = _mapIteratorEnd;
  287. _vectorIterator = headers->_headers.rbegin()->second->_values.end();
  288. }
  289. }
  290. BBS2chProxyHttpHeadersIterator& BBS2chProxyHttpHeadersIterator::operator++()
  291. {
  292. if (_mapIterator != _mapIteratorEnd) {
  293. _vectorIterator++;
  294. if (_vectorIterator == _mapIterator->second->_values.end()) {
  295. _mapIterator++;
  296. if (_mapIterator != _mapIteratorEnd) {
  297. _vectorIterator = _mapIterator->second->_values.begin();
  298. }
  299. }
  300. if (_mapIterator != _mapIteratorEnd) {
  301. std::string tmp = _mapIterator->second->_name + ": ";
  302. _value = std::make_pair(_mapIterator->second, tmp + *_vectorIterator);
  303. }
  304. }
  305. return *this;
  306. }
  307. BBS2chProxyHttpHeadersIterator BBS2chProxyHttpHeadersIterator::operator++(int)
  308. {
  309. BBS2chProxyHttpHeadersIterator ret = *this;
  310. if (_mapIterator != _mapIteratorEnd) {
  311. _vectorIterator++;
  312. if (_vectorIterator == _mapIterator->second->_values.end()) {
  313. _mapIterator++;
  314. if (_mapIterator != _mapIteratorEnd) {
  315. _vectorIterator = _mapIterator->second->_values.begin();
  316. }
  317. }
  318. if (_mapIterator != _mapIteratorEnd) {
  319. std::string tmp = _mapIterator->second->_name + ": ";
  320. _value = std::make_pair(_mapIterator->second, tmp + *_vectorIterator);
  321. }
  322. }
  323. return ret;
  324. }
  325. BBS2chProxyHttpHeadersIterator::reference BBS2chProxyHttpHeadersIterator::operator*()
  326. {
  327. return _value;
  328. }
  329. BBS2chProxyHttpHeadersIterator::pointer BBS2chProxyHttpHeadersIterator::operator->()
  330. {
  331. return &_value;
  332. }
  333. bool BBS2chProxyHttpHeadersIterator::operator==(const BBS2chProxyHttpHeadersIterator& iterator)
  334. {
  335. return !(*this != iterator);
  336. }
  337. bool BBS2chProxyHttpHeadersIterator::operator!=(const BBS2chProxyHttpHeadersIterator& iterator)
  338. {
  339. return iterator._mapIterator != _mapIterator || iterator._vectorIterator != _vectorIterator;
  340. }
  341. #ifdef USE_LUA
  342. static bool lua_isValidUserdata(lua_State *l, int idx)
  343. {
  344. if (!lua_getmetatable(l, idx)) {
  345. return false;
  346. }
  347. #if LUA_VERSION_NUM > 502
  348. if (lua_getfield(l, -1, "_type") != LUA_TSTRING)
  349. #else
  350. if (lua_getfield(l, -1, "_type"), lua_type(l, -1) != LUA_TSTRING)
  351. #endif
  352. {
  353. lua_pop(l, 2);
  354. return false;
  355. }
  356. bool isValid = !strcmp(lua_tostring(l, -1), "HttpHeaders");
  357. lua_pop(l, 2);
  358. return isValid;
  359. }
  360. static int lua_httpHeadersGet(lua_State *l)
  361. {
  362. BBS2chProxyHttpHeaders *headers = NULL;
  363. const char *name = luaL_checkstring(l, 2);
  364. void *obj = lua_touserdata(l, 1);
  365. if (!obj) {
  366. lua_pushnil(l);
  367. return 1;
  368. }
  369. if (lua_isValidUserdata(l, 1)) {
  370. headers = *((BBS2chProxyHttpHeaders **)obj);
  371. }
  372. if (headers && headers->has(name)) {
  373. lua_pushstring(l, headers->get(name).c_str());
  374. }
  375. else {
  376. lua_pushnil(l);
  377. }
  378. return 1;
  379. }
  380. static int lua_httpHeadersSet(lua_State *l)
  381. {
  382. BBS2chProxyHttpHeaders *headers = NULL;
  383. const char *name = luaL_checkstring(l, 2);
  384. const char *value = NULL;
  385. if (!lua_isnoneornil(l, 3)) {
  386. value = luaL_checkstring(l, 3);
  387. }
  388. void *obj = lua_touserdata(l, 1);
  389. if (!obj) {
  390. return 0;
  391. }
  392. if (lua_isValidUserdata(l, 1)) {
  393. headers = *((BBS2chProxyHttpHeaders **)obj);
  394. }
  395. if (headers) {
  396. if (value) headers->set(name, value);
  397. else headers->remove(name);
  398. }
  399. return 0;
  400. }
  401. static int lua_httpHeadersAdd(lua_State *l)
  402. {
  403. BBS2chProxyHttpHeaders *headers = NULL;
  404. const char *name = luaL_checkstring(l, 2);
  405. const char *value = NULL;
  406. if (!lua_isnoneornil(l, 3)) {
  407. value = luaL_checkstring(l, 3);
  408. }
  409. void *obj = lua_touserdata(l, 1);
  410. if (!obj) {
  411. return 0;
  412. }
  413. if (lua_isValidUserdata(l, 1)) {
  414. headers = *((BBS2chProxyHttpHeaders **)obj);
  415. }
  416. if (headers && value) {
  417. headers->add(name, value);
  418. }
  419. return 0;
  420. }
  421. static int lua_httpHeadersHas(lua_State *l)
  422. {
  423. BBS2chProxyHttpHeaders *headers = NULL;
  424. const char *name = luaL_checkstring(l, 2);
  425. void *obj = lua_touserdata(l, 1);
  426. if (!obj) {
  427. lua_pushboolean(l, 0);
  428. return 1;
  429. }
  430. if (lua_isValidUserdata(l, 1)) {
  431. headers = *((BBS2chProxyHttpHeaders **)obj);
  432. }
  433. if (headers) {
  434. lua_pushboolean(l, headers->has(name));
  435. }
  436. else {
  437. lua_pushboolean(l, 0);
  438. }
  439. return 1;
  440. }
  441. static int lua_httpHeadersRemove(lua_State *l)
  442. {
  443. BBS2chProxyHttpHeaders *headers = NULL;
  444. const char *name = luaL_checkstring(l, 2);
  445. void *obj = lua_touserdata(l, 1);
  446. if (!obj) {
  447. return 0;
  448. }
  449. if (lua_isValidUserdata(l, 1)) {
  450. headers = *((BBS2chProxyHttpHeaders **)obj);
  451. }
  452. if (headers) {
  453. headers->remove(name);
  454. }
  455. return 0;
  456. }
  457. static int lua_httpHeadersClear(lua_State *l)
  458. {
  459. BBS2chProxyHttpHeaders *headers = NULL;
  460. void *obj = lua_touserdata(l, 1);
  461. if (!obj) {
  462. return 0;
  463. }
  464. if (lua_isValidUserdata(l, 1)) {
  465. headers = *((BBS2chProxyHttpHeaders **)obj);
  466. }
  467. if (headers) {
  468. headers->clear();
  469. }
  470. return 0;
  471. }
  472. static int lua_httpHeadersCount(lua_State *l)
  473. {
  474. BBS2chProxyHttpHeaders *headers = NULL;
  475. void *obj = lua_touserdata(l, 1);
  476. if (!obj) {
  477. lua_pushinteger(l, 0);
  478. return 1;
  479. }
  480. if (lua_isValidUserdata(l, 1)) {
  481. headers = *((BBS2chProxyHttpHeaders **)obj);
  482. }
  483. if (headers) {
  484. lua_pushinteger(l, headers->getMap().size());
  485. }
  486. else {
  487. lua_pushinteger(l, 0);
  488. }
  489. return 1;
  490. }
  491. static int lua_httpHeadersNext(lua_State *l)
  492. {
  493. BBS2chProxyHttpHeaders *headers = NULL;
  494. const char *index = NULL;
  495. if (!lua_isnoneornil(l, 2)) {
  496. index = luaL_checkstring(l, 2);
  497. }
  498. void *obj = lua_touserdata(l, 1);
  499. if (!obj) {
  500. goto fail;
  501. }
  502. if (lua_isValidUserdata(l, 1)) {
  503. headers = *((BBS2chProxyHttpHeaders **)obj);
  504. }
  505. if (headers) {
  506. if (headers->getMap().empty()) {
  507. goto fail;
  508. }
  509. std::map<std::string, PBBS2chProxyHttpHeaderEntry>::iterator it = headers->getMap().begin();
  510. if (!index) {
  511. lua_pushstring(l, it->second->getName().c_str());
  512. lua_pushstring(l, it->second->getValue().c_str());
  513. return 2;
  514. }
  515. for (; it != headers->getMap().end(); it++) {
  516. if (it->second->getName() == index) {
  517. break;
  518. }
  519. }
  520. if (++it != headers->getMap().end()) {
  521. lua_pushstring(l, it->second->getName().c_str());
  522. lua_pushstring(l, it->second->getValue().c_str());
  523. return 2;
  524. }
  525. }
  526. fail:
  527. lua_pushnil(l);
  528. return 1;
  529. }
  530. static int lua_httpHeadersPairs(lua_State *l)
  531. {
  532. void *obj = lua_touserdata(l, 1);
  533. if (!obj) {
  534. return 0;
  535. }
  536. if (lua_isValidUserdata(l, 1)) {
  537. lua_pushcfunction(l, lua_httpHeadersNext);
  538. lua_pushvalue(l, 1);
  539. lua_pushnil(l);
  540. return 3;
  541. }
  542. return 0;
  543. }
  544. static int lua_httpHeadersNew(lua_State *l)
  545. {
  546. void **obj = (void **)lua_newuserdata(l, sizeof(void *));
  547. *obj = new BBS2chProxyHttpHeaders();
  548. lua_pushvalue(l, lua_upvalueindex(1));
  549. lua_setmetatable(l, -2);
  550. return 1;
  551. }
  552. static int lua_httpHeadersDelete(lua_State *l)
  553. {
  554. void *obj = lua_touserdata(l, 1);
  555. if (!obj) {
  556. return 0;
  557. }
  558. if (lua_isValidUserdata(l, 1)) {
  559. delete *((BBS2chProxyHttpHeaders **)obj);
  560. }
  561. return 0;
  562. }
  563. static int lua_functionOrGetter(lua_State *l)
  564. {
  565. if (!lua_getmetatable(l, 1)) {
  566. lua_pushnil(l);
  567. return 1;
  568. }
  569. lua_pushvalue(l, 2);
  570. #if LUA_VERSION_NUM > 502
  571. if (lua_rawget(l, -2) == LUA_TFUNCTION)
  572. #else
  573. if (lua_rawget(l, -2), lua_type(l, -1) == LUA_TFUNCTION)
  574. #endif
  575. {
  576. return 1;
  577. }
  578. lua_pop(l, 2);
  579. return lua_httpHeadersGet(l);
  580. }
  581. static int lua_enableLowLevelFuncs(lua_State *l)
  582. {
  583. if (!lua_isuserdata(l, 1) || !lua_isValidUserdata(l, 1)) {
  584. return 0;
  585. }
  586. if (!lua_getmetatable(l, 1)) {
  587. return 0;
  588. }
  589. lua_newtable(l);
  590. lua_pushnil(l);
  591. while (lua_next(l, -3)) {
  592. lua_pushvalue(l, -2);
  593. lua_insert(l, -2);
  594. lua_settable(l, -4);
  595. }
  596. lua_pushcfunction(l, lua_functionOrGetter);
  597. lua_setfield(l, -2, "__index");
  598. lua_setmetatable(l, 1);
  599. lua_pop(l, 1);
  600. return 0;
  601. }
  602. void BBS2chProxyHttpHeaders::getObjectMetatableForLua(lua_State *l)
  603. {
  604. lua_newtable(l);
  605. lua_pushcfunction(l, lua_httpHeadersGet);
  606. lua_setfield(l, -2, "__index");
  607. lua_pushcfunction(l, lua_httpHeadersSet);
  608. lua_setfield(l, -2, "__newindex");
  609. lua_pushcfunction(l, lua_httpHeadersPairs);
  610. lua_setfield(l, -2, "__pairs");
  611. lua_pushcfunction(l, lua_httpHeadersCount);
  612. lua_setfield(l, -2, "__len");
  613. lua_pushcfunction(l, lua_httpHeadersGet);
  614. lua_setfield(l, -2, "get");
  615. lua_pushcfunction(l, lua_httpHeadersSet);
  616. lua_setfield(l, -2, "set");
  617. lua_pushcfunction(l, lua_httpHeadersAdd);
  618. lua_setfield(l, -2, "add");
  619. lua_pushcfunction(l, lua_httpHeadersHas);
  620. lua_setfield(l, -2, "has");
  621. lua_pushcfunction(l, lua_httpHeadersRemove);
  622. lua_setfield(l, -2, "remove");
  623. lua_pushcfunction(l, lua_httpHeadersClear);
  624. lua_setfield(l, -2, "clear");
  625. lua_pushcfunction(l, lua_httpHeadersCount);
  626. lua_setfield(l, -2, "count");
  627. lua_pushliteral(l, "HttpHeaders");
  628. lua_setfield(l, -2, "_type");
  629. }
  630. void BBS2chProxyHttpHeaders::getClassDefinitionForLua(lua_State *l)
  631. {
  632. lua_newtable(l);
  633. getObjectMetatableForLua(l);
  634. lua_pushcfunction(l, lua_httpHeadersDelete);
  635. lua_setfield(l, -2, "__gc");
  636. lua_pushcclosure(l, lua_httpHeadersNew, 1);
  637. lua_setfield(l, -2, "new");
  638. lua_pushcfunction(l, lua_enableLowLevelFuncs);
  639. lua_setfield(l, -2, "enableLowLevelAccess");
  640. }
  641. void BBS2chProxyHttpHeaders::getUserdataForLua(lua_State *l)
  642. {
  643. void **obj = (void **)lua_newuserdata(l, sizeof(this));
  644. *obj = this;
  645. getObjectMetatableForLua(l);
  646. lua_setmetatable(l, -2);
  647. }
  648. #endif