BBS2chProxyHttpHeaders.cpp 18 KB

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