123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692 |
- #include <algorithm>
- #include <string.h>
- #include "BBS2chProxyHttpHeaders.h"
- const std::string& BBS2chProxyHttpHeaderEntry::getName(void)
- {
- return _name;
- }
- std::string BBS2chProxyHttpHeaderEntry::getLowercasedName(void)
- {
- std::string lowerName = _name;
- std::transform(_name.begin(), _name.end(), lowerName.begin(), tolower);
- return lowerName;
- }
- std::string BBS2chProxyHttpHeaderEntry::getValue(void)
- {
- std::string ret;
- for (std::vector<std::string>::iterator it = _values.begin(); it != _values.end(); it++) {
- if (!ret.empty()) ret += ", ";
- ret += *it;
- }
- return ret;
- }
- std::string BBS2chProxyHttpHeaderEntry::getFull(bool shouldIncludeLineBreak)
- {
- if (shouldIncludeLineBreak) {
- std::string header;
- for (std::vector<std::string>::iterator it = _values.begin(); it != _values.end(); it++) {
- header += _name;
- header += ": ";
- header += *it;
- header += "\r\n";
- }
- return header;
- }
- std::string ret = _name;
- ret += ": ";
- ret += getValue();
- return ret;
- }
- std::vector<std::string>& BBS2chProxyHttpHeaderEntry::getValueList(void)
- {
- return _values;
- }
- void BBS2chProxyHttpHeaderEntry::add(const std::string &value)
- {
- _values.push_back(value);
- }
- void BBS2chProxyHttpHeaderEntry::set(const std::string &value)
- {
- _values.clear();
- _values.push_back(value);
- }
- bool BBS2chProxyHttpHeaderEntry::has(const std::string &value)
- {
- for (std::vector<std::string>::iterator it = _values.begin(); it != _values.end(); it++) {
- if (*it == value) return true;
- }
- return false;
- }
- bool BBS2chProxyHttpHeaderEntry::contains(const std::string &value)
- {
- for (std::vector<std::string>::iterator it = _values.begin(); it != _values.end(); it++) {
- if (it->find(value) != std::string::npos) return true;
- }
- return false;
- }
- void BBS2chProxyHttpHeaderEntry::replaceValue(const std::string &from, const std::string &to)
- {
- for (std::vector<std::string>::iterator it = _values.begin(); it != _values.end(); it++) {
- size_t pos = it->find(from);
- while (pos != std::string::npos) {
- it->replace(pos, from.size(), to);
- pos = it->find(from, pos+to.size());
- }
- }
- }
- std::string BBS2chProxyHttpHeaders::get(const std::string &name)
- {
- if (!has(name)) return "";
- std::string lowerName = name;
- std::transform(name.begin(), name.end(), lowerName.begin(), tolower);
- return _headers[lowerName]->getValue();
- }
- std::string BBS2chProxyHttpHeaders::getFull(const std::string &name, bool shouldIncludeLineBreak)
- {
- if (!has(name)) return "";
- std::string lowerName = name;
- std::transform(name.begin(), name.end(), lowerName.begin(), tolower);
- return _headers[lowerName]->getFull(shouldIncludeLineBreak);
- }
- PBBS2chProxyHttpHeaderEntry BBS2chProxyHttpHeaders::getEntry(const std::string &name)
- {
- if (!has(name)) return PBBS2chProxyHttpHeaderEntry();
- std::string lowerName = name;
- std::transform(name.begin(), name.end(), lowerName.begin(), tolower);
- return _headers[lowerName];
- }
- bool BBS2chProxyHttpHeaders::has(const std::string &name)
- {
- if (_headers.empty()) return false;
- std::string lowerName = name;
- std::transform(name.begin(), name.end(), lowerName.begin(), tolower);
- return _headers.count(lowerName) != 0;
- }
- bool BBS2chProxyHttpHeaders::hasNameAndValue(const std::string &name, const std::string &value)
- {
- if (_headers.empty()) return false;
- std::string lowerName = name;
- std::transform(name.begin(), name.end(), lowerName.begin(), tolower);
- std::map<std::string, PBBS2chProxyHttpHeaderEntry>::iterator it = _headers.find(lowerName);
- if (it == _headers.end()) return false;
- return it->second->has(value);
- }
- void BBS2chProxyHttpHeaders::add(const std::string &name, const std::string &value)
- {
- if (name.empty()) return;
- if (!has(name)) return set(name, value);
- std::string lowerName = name;
- std::transform(name.begin(), name.end(), lowerName.begin(), tolower);
- PBBS2chProxyHttpHeaderEntry entry = _headers[lowerName];
- entry->add(value);
- }
- void BBS2chProxyHttpHeaders::add(const char *field)
- {
- const char *ptr = field;
- while (*ptr == ' ' || *ptr == '\t') ptr++;
- const char *start = ptr;
- while (*ptr != ':' && *ptr != 0) ptr++;
- if (*ptr != ':' || ptr == start) return;
- const char *next = ptr + 1;
- ptr--;
- while (*ptr == ' ' && ptr > start) ptr--;
- std::string name(start, ptr-start+1);
- ptr = next;
- while (*ptr == ' ' || *ptr == '\t') ptr++;
- start = ptr;
- while (*ptr != '\r' && *ptr != '\n' && *ptr != 0) ptr++;
- std::string value(start, ptr-start);
- add(name, value);
- }
- void BBS2chProxyHttpHeaders::add(const char *field, size_t length)
- {
- const char *ptr = field;
- const char *end = field + length;
- while (ptr < end && (*ptr == ' ' || *ptr == '\t')) ptr++;
- if (ptr == end) return;
- const char *start = ptr;
- while (*ptr != ':' && ptr < end) ptr++;
- if (ptr == end || ptr == start) return;
- const char *next = ptr + 1;
- ptr--;
- while (*ptr == ' ' && ptr > start) ptr--;
- std::string name(start, ptr-start+1);
- ptr = next;
- while (ptr < end && (*ptr == ' ' || *ptr == '\t')) ptr++;
- start = ptr;
- while (ptr < end && *ptr != '\r' && *ptr != '\n') ptr++;
- std::string value(start, ptr-start);
- add(name, value);
- }
- void BBS2chProxyHttpHeaders::set(const std::string &name, const std::string &value)
- {
- if (name.empty()) return;
- std::string lowerName = name;
- std::transform(name.begin(), name.end(), lowerName.begin(), tolower);
- _headers.erase(lowerName);
- PBBS2chProxyHttpHeaderEntry entry(new BBS2chProxyHttpHeaderEntry(name, value));
- _headers.insert(std::make_pair(lowerName, entry));
- }
- void BBS2chProxyHttpHeaders::set(PBBS2chProxyHttpHeaderEntry entry)
- {
- const std::string &lowerName = entry->getLowercasedName();
- _headers.erase(lowerName);
- _headers.insert(std::make_pair(lowerName, entry));
- }
- void BBS2chProxyHttpHeaders::remove(const std::string &name)
- {
- if (name.empty()) return;
- std::string lowerName = name;
- std::transform(name.begin(), name.end(), lowerName.begin(), tolower);
- _headers.erase(lowerName);
- }
- void BBS2chProxyHttpHeaders::clear(void)
- {
- _headers.clear();
- }
- const std::string& BBS2chProxyHttpHeaders::getStatusLine()
- {
- return _statusLine;
- }
- void BBS2chProxyHttpHeaders::setStatusLine(const char *field, size_t length)
- {
- if (length < 5 || strncasecmp(field, "HTTP/", 5)) return;
- const char *ptr = field + 5;
- const char *end = field + length;
- while (ptr < end && *ptr != ' ') ptr++;
- while (ptr < end && *ptr == ' ') ptr++;
- if (ptr < end) {
- unsigned long code = strtoul(ptr, (char **)&ptr, 10);
- if (code == 0) return;
- while (ptr < end && *ptr != '\r' && *ptr != '\n') ptr++;
- _statusLine = std::string(field, ptr-field);
- }
- }
- curl_slist* BBS2chProxyHttpHeaders::appendToCurlSlist(curl_slist *list, const std::set<std::string> &excludes)
- {
- for (std::map<std::string, PBBS2chProxyHttpHeaderEntry>::iterator it = _headers.begin(); it != _headers.end(); it++) {
- if (excludes.find(it->first) != excludes.end()) continue;
- std::vector<std::string>& values = it->second->getValueList();
- for (std::vector<std::string>::iterator it2 = values.begin(); it2 != values.end(); it2++) {
- std::string header = it->second->getName();
- header += ": ";
- header += *it2;
- list = curl_slist_append(list, header.c_str());
- }
- }
- return list;
- }
- curl_slist* BBS2chProxyHttpHeaders::appendToCurlSlist(curl_slist *list, const std::string &name)
- {
- if (name.empty()) return list;
- std::string lowerName = name;
- std::transform(name.begin(), name.end(), lowerName.begin(), tolower);
- std::map<std::string, PBBS2chProxyHttpHeaderEntry>::iterator it = _headers.find(lowerName);
- if (it != _headers.end()) {
- PBBS2chProxyHttpHeaderEntry& entry = it->second;
- std::vector<std::string>& values = entry->getValueList();
- for (std::vector<std::string>::iterator it = values.begin(); it != values.end(); it++) {
- std::string header = entry->getName();
- header += ": ";
- header += *it;
- list = curl_slist_append(list, header.c_str());
- }
- }
- return list;
- }
- std::map<std::string, PBBS2chProxyHttpHeaderEntry>& BBS2chProxyHttpHeaders::getMap(void)
- {
- return _headers;
- }
- bool BBS2chProxyHttpHeaders::empty()
- {
- return _headers.empty();
- }
- BBS2chProxyHttpHeaders::iterator BBS2chProxyHttpHeaders::begin()
- {
- return BBS2chProxyHttpHeadersIterator(this, false);
- }
- BBS2chProxyHttpHeaders::iterator BBS2chProxyHttpHeaders::end()
- {
- return BBS2chProxyHttpHeadersIterator(this, true);
- }
- PBBS2chProxyHttpHeaderEntry BBS2chProxyHttpHeaders::parse(const char *field, size_t length)
- {
- PBBS2chProxyHttpHeaderEntry entry;
- const char *ptr = field;
- const char *end = field + length;
- while (ptr < end && (*ptr == ' ' || *ptr == '\t')) ptr++;
- if (ptr == end) return entry;
- const char *start = ptr;
- while (*ptr != ':' && ptr < end) ptr++;
- if (ptr == end || ptr == start) return entry;
- const char *next = ptr + 1;
- ptr--;
- while (*ptr == ' ' && ptr > start) ptr--;
- std::string name(start, ptr-start+1);
- ptr = next;
- while (ptr < end && (*ptr == ' ' || *ptr == '\t')) ptr++;
- start = ptr;
- while (ptr < end && *ptr != '\r' && *ptr != '\n') ptr++;
- std::string value(start, ptr-start);
- entry.reset(new BBS2chProxyHttpHeaderEntry(name, value));
- return entry;
- }
- BBS2chProxyHttpHeadersIterator::BBS2chProxyHttpHeadersIterator(BBS2chProxyHttpHeaders* headers, bool firstOrLast)
- {
- _mapIteratorEnd = headers->_headers.end();
- if (!firstOrLast && !headers->_headers.empty()) {
- _mapIterator = headers->_headers.begin();
- _vectorIterator = _mapIterator->second->_values.begin();
- std::string tmp = _mapIterator->second->_name + ": ";
- _value = std::make_pair(_mapIterator->second, tmp + *_vectorIterator);
- } else {
- _mapIterator = _mapIteratorEnd;
- _vectorIterator = headers->_headers.rbegin()->second->_values.end();
- }
- }
- BBS2chProxyHttpHeadersIterator& BBS2chProxyHttpHeadersIterator::operator++()
- {
- if (_mapIterator != _mapIteratorEnd) {
- _vectorIterator++;
- if (_vectorIterator == _mapIterator->second->_values.end()) {
- _mapIterator++;
- if (_mapIterator != _mapIteratorEnd) {
- _vectorIterator = _mapIterator->second->_values.begin();
- }
- }
- if (_mapIterator != _mapIteratorEnd) {
- std::string tmp = _mapIterator->second->_name + ": ";
- _value = std::make_pair(_mapIterator->second, tmp + *_vectorIterator);
- }
- }
- return *this;
- }
- BBS2chProxyHttpHeadersIterator BBS2chProxyHttpHeadersIterator::operator++(int)
- {
- BBS2chProxyHttpHeadersIterator ret = *this;
- if (_mapIterator != _mapIteratorEnd) {
- _vectorIterator++;
- if (_vectorIterator == _mapIterator->second->_values.end()) {
- _mapIterator++;
- if (_mapIterator != _mapIteratorEnd) {
- _vectorIterator = _mapIterator->second->_values.begin();
- }
- }
- if (_mapIterator != _mapIteratorEnd) {
- std::string tmp = _mapIterator->second->_name + ": ";
- _value = std::make_pair(_mapIterator->second, tmp + *_vectorIterator);
- }
- }
- return ret;
- }
- BBS2chProxyHttpHeadersIterator::reference BBS2chProxyHttpHeadersIterator::operator*()
- {
- return _value;
- }
- BBS2chProxyHttpHeadersIterator::pointer BBS2chProxyHttpHeadersIterator::operator->()
- {
- return &_value;
- }
- bool BBS2chProxyHttpHeadersIterator::operator==(const BBS2chProxyHttpHeadersIterator& iterator)
- {
- return !(*this != iterator);
- }
- bool BBS2chProxyHttpHeadersIterator::operator!=(const BBS2chProxyHttpHeadersIterator& iterator)
- {
- return iterator._mapIterator != _mapIterator || iterator._vectorIterator != _vectorIterator;
- }
- #ifdef USE_LUA
- static bool lua_isValidUserdata(lua_State *l, int idx)
- {
- if (!lua_getmetatable(l, idx)) {
- return false;
- }
- if (lua_getfield(l, -1, "_type") != LUA_TSTRING) {
- lua_pop(l, 2);
- return false;
- }
- bool isValid = !strcmp(lua_tostring(l, -1), "HttpHeaders");
- lua_pop(l, 2);
- return isValid;
- }
- static int lua_httpHeadersGet(lua_State *l)
- {
- BBS2chProxyHttpHeaders *headers = NULL;
- const char *name = luaL_checkstring(l, 2);
- void *obj = lua_touserdata(l, 1);
- if (!obj) {
- lua_pushnil(l);
- return 1;
- }
- if (lua_isValidUserdata(l, 1)) {
- headers = *((BBS2chProxyHttpHeaders **)obj);
- }
- if (headers && headers->has(name)) {
- lua_pushstring(l, headers->get(name).c_str());
- }
- else {
- lua_pushnil(l);
- }
- return 1;
- }
- static int lua_httpHeadersSet(lua_State *l)
- {
- BBS2chProxyHttpHeaders *headers = NULL;
- const char *name = luaL_checkstring(l, 2);
- const char *value = NULL;
- if (!lua_isnoneornil(l, 3)) {
- value = luaL_checkstring(l, 3);
- }
- void *obj = lua_touserdata(l, 1);
- if (!obj) {
- return 0;
- }
- if (lua_isValidUserdata(l, 1)) {
- headers = *((BBS2chProxyHttpHeaders **)obj);
- }
- if (headers) {
- if (value) headers->set(name, value);
- else headers->remove(name);
- }
- return 0;
- }
- static int lua_httpHeadersAdd(lua_State *l)
- {
- BBS2chProxyHttpHeaders *headers = NULL;
- const char *name = luaL_checkstring(l, 2);
- const char *value = NULL;
- if (!lua_isnoneornil(l, 3)) {
- value = luaL_checkstring(l, 3);
- }
- void *obj = lua_touserdata(l, 1);
- if (!obj) {
- return 0;
- }
- if (lua_isValidUserdata(l, 1)) {
- headers = *((BBS2chProxyHttpHeaders **)obj);
- }
- if (headers && value) {
- headers->add(name, value);
- }
- return 0;
- }
- static int lua_httpHeadersHas(lua_State *l)
- {
- BBS2chProxyHttpHeaders *headers = NULL;
- const char *name = luaL_checkstring(l, 2);
- void *obj = lua_touserdata(l, 1);
- if (!obj) {
- lua_pushboolean(l, 0);
- return 1;
- }
- if (lua_isValidUserdata(l, 1)) {
- headers = *((BBS2chProxyHttpHeaders **)obj);
- }
- if (headers) {
- lua_pushboolean(l, headers->has(name));
- }
- else {
- lua_pushboolean(l, 0);
- }
- return 1;
- }
- static int lua_httpHeadersRemove(lua_State *l)
- {
- BBS2chProxyHttpHeaders *headers = NULL;
- const char *name = luaL_checkstring(l, 2);
- void *obj = lua_touserdata(l, 1);
- if (!obj) {
- return 0;
- }
- if (lua_isValidUserdata(l, 1)) {
- headers = *((BBS2chProxyHttpHeaders **)obj);
- }
- if (headers) {
- headers->remove(name);
- }
- return 0;
- }
- static int lua_httpHeadersClear(lua_State *l)
- {
- BBS2chProxyHttpHeaders *headers = NULL;
- void *obj = lua_touserdata(l, 1);
- if (!obj) {
- return 0;
- }
- if (lua_isValidUserdata(l, 1)) {
- headers = *((BBS2chProxyHttpHeaders **)obj);
- }
- if (headers) {
- headers->clear();
- }
- return 0;
- }
- static int lua_httpHeadersCount(lua_State *l)
- {
- BBS2chProxyHttpHeaders *headers = NULL;
- void *obj = lua_touserdata(l, 1);
- if (!obj) {
- lua_pushinteger(l, 0);
- return 1;
- }
- if (lua_isValidUserdata(l, 1)) {
- headers = *((BBS2chProxyHttpHeaders **)obj);
- }
- if (headers) {
- lua_pushinteger(l, headers->getMap().size());
- }
- else {
- lua_pushinteger(l, 0);
- }
- return 1;
- }
- static int lua_httpHeadersNext(lua_State *l)
- {
- BBS2chProxyHttpHeaders *headers = NULL;
- const char *index = NULL;
- if (!lua_isnoneornil(l, 2)) {
- index = luaL_checkstring(l, 2);
- }
- void *obj = lua_touserdata(l, 1);
- if (!obj) {
- goto fail;
- }
- if (lua_isValidUserdata(l, 1)) {
- headers = *((BBS2chProxyHttpHeaders **)obj);
- }
- if (headers) {
- if (headers->getMap().empty()) {
- goto fail;
- }
- std::map<std::string, PBBS2chProxyHttpHeaderEntry>::iterator it = headers->getMap().begin();
- if (!index) {
- lua_pushstring(l, it->second->getName().c_str());
- lua_pushstring(l, it->second->getValue().c_str());
- return 2;
- }
- for (; it != headers->getMap().end(); it++) {
- if (it->second->getName() == index) {
- break;
- }
- }
- if (++it != headers->getMap().end()) {
- lua_pushstring(l, it->second->getName().c_str());
- lua_pushstring(l, it->second->getValue().c_str());
- return 2;
- }
- }
- fail:
- lua_pushnil(l);
- return 1;
- }
- static int lua_httpHeadersPairs(lua_State *l)
- {
- void *obj = lua_touserdata(l, 1);
- if (!obj) {
- return 0;
- }
- if (lua_isValidUserdata(l, 1)) {
- lua_pushcfunction(l, lua_httpHeadersNext);
- lua_pushvalue(l, 1);
- lua_pushnil(l);
- return 3;
- }
- return 0;
- }
- static int lua_httpHeadersNew(lua_State *l)
- {
- void **obj = (void **)lua_newuserdata(l, sizeof(void *));
- *obj = new BBS2chProxyHttpHeaders();
- lua_pushvalue(l, lua_upvalueindex(1));
- lua_setmetatable(l, -2);
- return 1;
- }
- static int lua_httpHeadersDelete(lua_State *l)
- {
- void *obj = lua_touserdata(l, 1);
- if (!obj) {
- return 0;
- }
- if (lua_isValidUserdata(l, 1)) {
- delete *((BBS2chProxyHttpHeaders **)obj);
- }
- return 0;
- }
- static int lua_functionOrGetter(lua_State *l)
- {
- if (!lua_getmetatable(l, 1)) {
- lua_pushnil(l);
- return 1;
- }
- lua_pushvalue(l, 2);
- if (lua_rawget(l, -2) == LUA_TFUNCTION) {
- return 1;
- }
- lua_pop(l, 2);
- return lua_httpHeadersGet(l);
- }
- static int lua_enableLowLevelFuncs(lua_State *l)
- {
- if (!lua_isuserdata(l, 1) || !lua_isValidUserdata(l, 1)) {
- return 0;
- }
- if (!lua_getmetatable(l, 1)) {
- return 0;
- }
- lua_newtable(l);
- lua_pushnil(l);
- while (lua_next(l, -3)) {
- lua_pushvalue(l, -2);
- lua_insert(l, -2);
- lua_settable(l, -4);
- }
- lua_pushcfunction(l, lua_functionOrGetter);
- lua_setfield(l, -2, "__index");
- lua_setmetatable(l, 1);
- lua_pop(l, 1);
- return 0;
- }
- void BBS2chProxyHttpHeaders::getObjectMetatableForLua(lua_State *l)
- {
- lua_newtable(l);
- lua_pushcfunction(l, lua_httpHeadersGet);
- lua_setfield(l, -2, "__index");
- lua_pushcfunction(l, lua_httpHeadersSet);
- lua_setfield(l, -2, "__newindex");
- lua_pushcfunction(l, lua_httpHeadersPairs);
- lua_setfield(l, -2, "__pairs");
- lua_pushcfunction(l, lua_httpHeadersCount);
- lua_setfield(l, -2, "__len");
- lua_pushcfunction(l, lua_httpHeadersGet);
- lua_setfield(l, -2, "get");
- lua_pushcfunction(l, lua_httpHeadersSet);
- lua_setfield(l, -2, "set");
- lua_pushcfunction(l, lua_httpHeadersAdd);
- lua_setfield(l, -2, "add");
- lua_pushcfunction(l, lua_httpHeadersHas);
- lua_setfield(l, -2, "has");
- lua_pushcfunction(l, lua_httpHeadersRemove);
- lua_setfield(l, -2, "remove");
- lua_pushcfunction(l, lua_httpHeadersClear);
- lua_setfield(l, -2, "clear");
- lua_pushcfunction(l, lua_httpHeadersCount);
- lua_setfield(l, -2, "count");
- lua_pushliteral(l, "HttpHeaders");
- lua_setfield(l, -2, "_type");
- }
- void BBS2chProxyHttpHeaders::getClassDefinitionForLua(lua_State *l)
- {
- lua_newtable(l);
- getObjectMetatableForLua(l);
- lua_pushcfunction(l, lua_httpHeadersDelete);
- lua_setfield(l, -2, "__gc");
- lua_pushcclosure(l, lua_httpHeadersNew, 1);
- lua_setfield(l, -2, "new");
- lua_pushcfunction(l, lua_enableLowLevelFuncs);
- lua_setfield(l, -2, "enableLowLevelAccess");
- }
- void BBS2chProxyHttpHeaders::getUserdataForLua(lua_State *l)
- {
- void **obj = (void **)lua_newuserdata(l, sizeof(this));
- *obj = this;
- getObjectMetatableForLua(l);
- lua_setmetatable(l, -2);
- }
- #endif
|