BBS2chProxyFormData.cpp 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292
  1. #include "BBS2chProxyFormData.h"
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. std::string decodeURIComponent(const char *input, size_t inputLength, bool decodePlus)
  5. {
  6. std::string output;
  7. for (size_t i=0; i<inputLength; i++) {
  8. if (input[i] == '%') {
  9. if (i < inputLength - 2) {
  10. char from[3];
  11. char *end;
  12. from[0] = input[i+1];
  13. from[1] = input[i+2];
  14. from[2] = 0;
  15. unsigned long n = strtoul(from, &end, 16);
  16. if (n < 256 && end == from+2) {
  17. output.append(1, n);
  18. i += 2;
  19. continue;
  20. }
  21. }
  22. }
  23. else if (decodePlus && input[i] == '+') {
  24. output.append(" ");
  25. continue;
  26. }
  27. output.append(1, input[i]);
  28. }
  29. return output;
  30. }
  31. static std::string encodeURIComponent(const std::string &input, bool spaceAsPlus)
  32. {
  33. std::string output;
  34. for (size_t i=0; i<input.size(); i++) {
  35. unsigned char c = (unsigned char)input[i];
  36. if ((c >= '0' && c <= '9') ||
  37. (c >= 'A' && c <= 'Z') ||
  38. (c >= 'a' && c <= 'z') ||
  39. (c == '-') || (c == '.') || (c == '_')) {
  40. output.append(1, c);
  41. }
  42. else if (c == ' ' && spaceAsPlus) {
  43. output.append("+");
  44. }
  45. else {
  46. char percentEncoded[4];
  47. snprintf(percentEncoded, 4, "%%%02X", c);
  48. output.append(percentEncoded);
  49. }
  50. }
  51. return output;
  52. }
  53. std::string encodeURIComponent(const char *input, size_t inputLength, bool spaceAsPlus)
  54. {
  55. return encodeURIComponent(std::string(input, inputLength), spaceAsPlus);
  56. }
  57. BBS2chProxyURLEncodedValue::BBS2chProxyURLEncodedValue()
  58. : _hasValue(true), _hasEncodedValue(true)
  59. {
  60. }
  61. BBS2chProxyURLEncodedValue::BBS2chProxyURLEncodedValue(const std::string &value, bool encoded)
  62. {
  63. if (value.empty()) {
  64. _hasValue = true;
  65. _hasEncodedValue = true;
  66. return;
  67. }
  68. if (encoded) {
  69. _encodedValue = value;
  70. _hasValue = false;
  71. _hasEncodedValue = true;
  72. } else {
  73. _value = value;
  74. _hasValue = true;
  75. _hasEncodedValue = false;
  76. }
  77. }
  78. BBS2chProxyURLEncodedValue::BBS2chProxyURLEncodedValue(const char *value, size_t length, bool encoded)
  79. {
  80. if (length == 0) {
  81. _hasValue = true;
  82. _hasEncodedValue = true;
  83. return;
  84. }
  85. if (encoded) {
  86. _encodedValue = std::string(value, length);
  87. _hasValue = false;
  88. _hasEncodedValue = true;
  89. } else {
  90. _value = std::string(value, length);
  91. _hasValue = true;
  92. _hasEncodedValue = false;
  93. }
  94. }
  95. const std::string& BBS2chProxyURLEncodedValue::get()
  96. {
  97. if (!_hasValue) {
  98. _value = decodeURIComponent(_encodedValue.data(), _encodedValue.size(), true);
  99. _hasValue = true;
  100. }
  101. return _value;
  102. }
  103. const std::string& BBS2chProxyURLEncodedValue::getEncoded()
  104. {
  105. if (!_hasEncodedValue) {
  106. _encodedValue = encodeURIComponent(_value, true);
  107. _hasEncodedValue = true;
  108. }
  109. return _encodedValue;
  110. }
  111. void BBS2chProxyURLEncodedValue::set(const std::string &value, bool encoded)
  112. {
  113. if (value.empty()) {
  114. _value.clear();
  115. _encodedValue.clear();
  116. _hasValue = true;
  117. _hasEncodedValue = true;
  118. return;
  119. }
  120. if (encoded) {
  121. _encodedValue = value;
  122. _hasValue = false;
  123. _hasEncodedValue = true;
  124. } else {
  125. _value = value;
  126. _hasValue = true;
  127. _hasEncodedValue = false;
  128. }
  129. }
  130. bool BBS2chProxyURLEncodedValue::empty()
  131. {
  132. return !((_hasValue && !_value.empty()) || (_hasEncodedValue && !_encodedValue.empty()));
  133. }
  134. BBS2chProxyURLEncodedValue& BBS2chProxyURLEncodedValue::operator=(const std::string &value)
  135. {
  136. set(value);
  137. return *this;
  138. }
  139. BBS2chProxyFormData::BBS2chProxyFormData(const char *data, size_t length)
  140. : _dirty(true)
  141. {
  142. if (length == 0) return;
  143. const char *ptr = data;
  144. while (1) {
  145. const char *tmp = ptr;
  146. while (*tmp != '=' && tmp - data < length) tmp++;
  147. std::string key = decodeURIComponent(ptr, tmp-ptr, true);
  148. if (tmp - data >= length) {
  149. bool inserted = _fields.insert(std::make_pair(key, BBS2chProxyURLEncodedValue())).second;
  150. if (inserted) _order.push_back(key);
  151. break;
  152. }
  153. tmp++;
  154. ptr = tmp;
  155. while (*tmp != '&' && tmp - data < length) tmp++;
  156. BBS2chProxyURLEncodedValue value(ptr, tmp-ptr, true);
  157. bool inserted = _fields.insert(std::make_pair(key, value)).second;
  158. if (inserted) _order.push_back(key);
  159. if (tmp - data >= length) {
  160. break;
  161. }
  162. ptr = tmp + 1;
  163. }
  164. }
  165. std::string BBS2chProxyFormData::get(const std::string &key)
  166. {
  167. iterator it = _fields.find(key);
  168. if (it == _fields.end()) return "";
  169. return it->second.get();
  170. }
  171. std::string BBS2chProxyFormData::getEncoded(const std::string &key)
  172. {
  173. iterator it = _fields.find(key);
  174. if (it == _fields.end()) return "";
  175. return it->second.getEncoded();
  176. }
  177. void BBS2chProxyFormData::append(const std::string &key, const std::string &value, bool encoded)
  178. {
  179. const std::string &decodedKey = encoded ? decodeURIComponent(key.data(), key.size(), true) : key;
  180. BBS2chProxyURLEncodedValue encodedValue(value, encoded);
  181. bool inserted = _fields.insert(std::make_pair(decodedKey, encodedValue)).second;
  182. if (inserted) {
  183. _order.push_back(decodedKey);
  184. _dirty = true;
  185. }
  186. }
  187. void BBS2chProxyFormData::set(const std::string &key, const std::string &value, bool encoded)
  188. {
  189. const std::string &decodedKey = encoded ? decodeURIComponent(key.data(), key.size(), true) : key;
  190. iterator it = _fields.find(decodedKey);
  191. if (it == _fields.end()) return;
  192. it->second.set(value, encoded);
  193. _dirty = true;
  194. }
  195. bool BBS2chProxyFormData::has(const std::string &key)
  196. {
  197. return _fields.find(key) != _fields.end();
  198. }
  199. void BBS2chProxyFormData::remove(const std::string &key)
  200. {
  201. if (_fields.erase(key) > 0) {
  202. for (std::vector<std::string>::iterator it = _order.begin(); it != _order.end();) {
  203. if (*it == key) it = _order.erase(it);
  204. else it++;
  205. }
  206. _dirty = true;
  207. }
  208. }
  209. void BBS2chProxyFormData::reorder(const std::vector<std::string> &order)
  210. {
  211. std::map<std::string, BBS2chProxyURLEncodedValue> newFields;
  212. std::vector<std::string> newOrder;
  213. for (std::vector<std::string>::const_iterator it = order.begin(); it != order.end(); it++) {
  214. const std::string &key = *it;
  215. iterator it2 = _fields.find(key);
  216. if (it2 != _fields.end()) {
  217. newFields.insert(std::make_pair(key, it2->second));
  218. newOrder.push_back(key);
  219. _fields.erase(key);
  220. }
  221. }
  222. for (std::vector<std::string>::iterator it = _order.begin(); it != _order.end(); it++) {
  223. const std::string &key = *it;
  224. iterator it2 = _fields.find(key);
  225. if (it2 != _fields.end()) {
  226. newFields.insert(std::make_pair(key, it2->second));
  227. newOrder.push_back(key);
  228. _fields.erase(key);
  229. }
  230. }
  231. _dirty = true;
  232. _fields = newFields;
  233. _order = newOrder;
  234. }
  235. const std::string& BBS2chProxyFormData::toString()
  236. {
  237. if (!_dirty) return _body;
  238. _body.clear();
  239. for (std::vector<std::string>::iterator it = _order.begin(); it != _order.end(); it++) {
  240. const std::string &key = *it;
  241. const std::string &value = _fields.find(key)->second.getEncoded();
  242. if (!_body.empty()) _body += '&';
  243. _body += encodeURIComponent(key, true);
  244. _body += '=';
  245. _body += value;
  246. }
  247. _dirty = false;
  248. return _body;
  249. }
  250. size_t BBS2chProxyFormData::size()
  251. {
  252. return toString().size();
  253. }
  254. BBS2chProxyFormData::iterator BBS2chProxyFormData::begin()
  255. {
  256. _dirty = true;
  257. return _fields.begin();
  258. }
  259. BBS2chProxyFormData::iterator BBS2chProxyFormData::end()
  260. {
  261. _dirty = true;
  262. return _fields.end();
  263. }
  264. std::string BBS2chProxyFormData::operator[](const std::string &key)
  265. {
  266. return get(key);
  267. }