A clone of btpd with my configuration changes.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

429 line
9.0 KiB

  1. #include <assert.h>
  2. #include <ctype.h>
  3. #include <errno.h>
  4. #include <inttypes.h>
  5. #include <stdarg.h>
  6. #include <stdlib.h>
  7. #include <string.h>
  8. #include "benc.h"
  9. #define benc_safeset(out, val) if ((out) != NULL) *(out) = (val)
  10. static const char *benc_validate_aux(const char *p, const char *end);
  11. int
  12. benc_validate(const char *p, size_t len)
  13. {
  14. const char *end = p + len - 1;
  15. if (len <= 0)
  16. return EINVAL;
  17. return benc_validate_aux(p, end) == end ? 0 : EINVAL;
  18. }
  19. static const char *
  20. benc_validate_aux(const char *p, const char *end)
  21. {
  22. size_t d = 0;
  23. switch (*p) {
  24. case 'd':
  25. d = 1;
  26. case 'l':
  27. for (p++; p <= end && *p != 'e'; p++) {
  28. if (d != 0) {
  29. if (d % 2 == 1 && !isdigit(*p))
  30. return NULL;
  31. else
  32. d++;
  33. }
  34. if ((p = benc_validate_aux(p, end)) == NULL)
  35. return NULL;
  36. }
  37. if (p > end || (d != 0 && d % 2 != 1))
  38. return NULL;
  39. break;
  40. case 'i':
  41. p++;
  42. if (p > end)
  43. return NULL;
  44. if (*p == '-')
  45. p++;
  46. if (p > end || !isdigit(*p))
  47. return NULL;
  48. p++;
  49. while (p <= end && isdigit(*p))
  50. p++;
  51. if (p > end || *p != 'e')
  52. return NULL;
  53. break;
  54. default:
  55. if (isdigit(*p)) {
  56. size_t len = 0;
  57. while (p <= end && isdigit(*p)) {
  58. len *= 10;
  59. len += *p - '0';
  60. p++;
  61. }
  62. if (p <= end && *p == ':' && p + len <= end)
  63. p += len;
  64. else
  65. return NULL;
  66. }
  67. else
  68. return NULL;
  69. break;
  70. }
  71. return p;
  72. }
  73. size_t
  74. benc_length(const char *p)
  75. {
  76. size_t blen;
  77. const char *next;
  78. switch (*p) {
  79. case 'd':
  80. case 'l':
  81. blen = 2; // [l|d]...e
  82. next = benc_first(p);
  83. while (*next != 'e') {
  84. size_t len = benc_length(next);
  85. blen += len;
  86. next += len;
  87. }
  88. return blen;
  89. case 'i':
  90. for (next = p + 1; *next != 'e'; next++)
  91. ;
  92. return next - p + 1;
  93. default:
  94. assert((next = benc_mem(p, &blen, NULL)) != NULL);
  95. return next - p + blen;
  96. }
  97. }
  98. size_t
  99. benc_nelems(const char *p)
  100. {
  101. size_t nelems = 0;
  102. for (p = benc_first(p); p != NULL; p = benc_next(p))
  103. nelems++;
  104. return nelems;
  105. }
  106. const char *
  107. benc_first(const char *p)
  108. {
  109. assert(benc_islst(p));
  110. return *(p + 1) == 'e' ? NULL : p + 1;
  111. }
  112. const char *
  113. benc_next(const char *p)
  114. {
  115. size_t blen = benc_length(p);
  116. return *(p + blen) == 'e' ? NULL : p + blen;
  117. }
  118. const char *
  119. benc_mem(const char *p, size_t *len, const char**next)
  120. {
  121. if (!benc_isstr(p))
  122. return NULL;
  123. size_t blen = 0;
  124. blen = *p - '0';
  125. p++;
  126. while (isdigit(*p)) {
  127. blen *= 10;
  128. blen += *p - '0';
  129. p++;
  130. }
  131. assert(*p == ':');
  132. benc_safeset(len, blen);
  133. benc_safeset(next, *(p + blen + 1) == 'e' ? NULL : p + blen + 1);
  134. return p + 1;
  135. }
  136. char *
  137. benc_str(const char *p, size_t *len, const char **next)
  138. {
  139. size_t blen;
  140. const char *bstr;
  141. char *ret;
  142. if ((bstr = benc_mem(p, &blen, next)) == NULL)
  143. return NULL;
  144. if ((ret = malloc(blen + 1)) == NULL)
  145. return NULL;
  146. bcopy(bstr, ret, blen);
  147. ret[blen] = '\0';
  148. benc_safeset(len, blen);
  149. return ret;
  150. }
  151. char *
  152. benc_mema(const char *p, size_t *len, const char **next)
  153. {
  154. size_t blen;
  155. const char *bstr;
  156. char *ret;
  157. if ((bstr = benc_mem(p, &blen, next)) == NULL)
  158. return NULL;
  159. if ((ret = malloc(blen)) == NULL)
  160. return NULL;
  161. bcopy(bstr, ret, blen);
  162. benc_safeset(len, blen);
  163. return ret;
  164. }
  165. long long
  166. benc_int(const char *p, const char **next)
  167. {
  168. int sign = 1;
  169. long long res = 0;
  170. if (!benc_isint(p))
  171. return 0;
  172. p++;
  173. if (*p == '-') {
  174. sign = -1;
  175. p++;
  176. }
  177. assert(isdigit(*p));
  178. res += sign * (*p - '0');
  179. p++;
  180. while (isdigit(*p)) {
  181. res *= sign * 10;
  182. res += sign * (*p - '0');
  183. p++;
  184. }
  185. assert(*p == 'e');
  186. benc_safeset(next, *(p + 1) == 'e' ? NULL : p + 1);
  187. return res;
  188. }
  189. const char *
  190. benc_dget_any(const char *p, const char *key)
  191. {
  192. int cmp;
  193. size_t len, blen;
  194. const char *bstr;
  195. if (!benc_isdct(p))
  196. return NULL;
  197. len = strlen(key);
  198. p = benc_first(p);
  199. while (p != NULL) {
  200. if (!benc_isstr(p))
  201. return NULL;
  202. bstr = benc_mem(p, &blen, &p);
  203. cmp = strncmp(bstr, key, blen);
  204. if (cmp == 0 && len == blen)
  205. return p;
  206. else if (cmp <= 0)
  207. p = benc_next(p);
  208. else
  209. return NULL;
  210. }
  211. return NULL;
  212. }
  213. const char *
  214. benc_dget_lst(const char *p, const char *key)
  215. {
  216. const char *ret = benc_dget_any(p, key);
  217. return ret != NULL && benc_islst(ret) ? ret : NULL;
  218. }
  219. const char *
  220. benc_dget_dct(const char *p, const char *key)
  221. {
  222. const char *ret = benc_dget_any(p, key);
  223. return ret != NULL && benc_isdct(ret) ? ret : NULL;
  224. }
  225. const char *
  226. benc_dget_mem(const char *p, const char *key, size_t *len)
  227. {
  228. const char *str = benc_dget_any(p, key);
  229. return str != NULL && benc_isstr(str) ? benc_mem(str, len, NULL) : NULL;
  230. }
  231. char *
  232. benc_dget_mema(const char *p, const char *key, size_t *len)
  233. {
  234. const char *str = benc_dget_any(p, key);
  235. return str != NULL && benc_isstr(str) ? benc_mema(str, len, NULL) : NULL;
  236. }
  237. char *
  238. benc_dget_str(const char *p, const char *key, size_t *len)
  239. {
  240. const char *str = benc_dget_any(p, key);
  241. return str != NULL && benc_isstr(str) ? benc_str(str, len, NULL) : NULL;
  242. }
  243. long long
  244. benc_dget_int(const char *p, const char *key)
  245. {
  246. const char *intp = benc_dget_any(p, key);
  247. return intp != NULL && benc_isint(intp) ? benc_int(intp, NULL) : 0;
  248. }
  249. int
  250. benc_islst(const char *p)
  251. {
  252. return *p == 'l' || *p == 'd';
  253. }
  254. int
  255. benc_isdct(const char *p)
  256. {
  257. return *p == 'd';
  258. }
  259. int
  260. benc_isint(const char *p)
  261. {
  262. return *p == 'i';
  263. }
  264. int
  265. benc_isstr(const char *p)
  266. {
  267. return isdigit(*p);
  268. }
  269. int
  270. benc_istype(const char *p, enum be_type type)
  271. {
  272. switch (type) {
  273. case BE_ANY:
  274. return benc_isdct(p) || benc_isint(p) ||
  275. benc_islst(p) || benc_isstr(p);
  276. case BE_DCT:
  277. return benc_isdct(p);
  278. case BE_INT:
  279. return benc_isint(p);
  280. case BE_LST:
  281. return benc_islst(p);
  282. case BE_STR:
  283. return benc_isstr(p);
  284. default:
  285. abort();
  286. }
  287. }
  288. int
  289. benc_dct_chk(const char *p, int count, ...)
  290. {
  291. int i, ok = 1;
  292. va_list ap;
  293. if (!benc_isdct(p))
  294. ok = 0;
  295. va_start(ap, count);
  296. for (i = 0; ok && i < count; i++) {
  297. enum be_type type = va_arg(ap, enum be_type);
  298. int level = va_arg(ap, int);
  299. const char *dct = p;
  300. const char *key = va_arg(ap, const char *);
  301. while (ok && level > 1) {
  302. if ((dct = benc_dget_dct(dct, key)) != NULL) {
  303. level--;
  304. key = va_arg(ap, const char *);
  305. } else
  306. ok = 0;
  307. }
  308. if (ok) {
  309. const char *val = benc_dget_any(dct, key);
  310. if (val == NULL || !benc_istype(val, type))
  311. ok = 0;
  312. }
  313. }
  314. va_end(ap);
  315. return ok;
  316. }
  317. #if 0
  318. int
  319. benc_dct_type_check(const char *p, int count, ...)
  320. {
  321. int i;
  322. va_list ap;
  323. benc_validate_dct(p, 2, BE_INT, "code", BE_STR, "hash",
  324. if (!benc_isdct(p))
  325. return EINVAL;
  326. va_start(ap, count);
  327. for (i = 0; i < count; i++) {
  328. }
  329. }
  330. int
  331. benc_dget_many(const char *p, int count, ...)
  332. {
  333. int i;
  334. va_list ap;
  335. if (!benc_isdct(p))
  336. return 0;
  337. va_start(ap, count);
  338. for (i = 0; i < count; i++) {
  339. const char *name = va_arg(ap, const char *);
  340. enum be_type type = va_arg(ap, enum be_type);
  341. int64_t *iret;
  342. size_t *lret;
  343. const char **mret;
  344. char **aret;
  345. switch (type) {
  346. case BE_INT:
  347. iret = va_arg(ap, int64_t *);
  348. if (benc_dget_int64(p, name, iret) != 0)
  349. goto out;
  350. break;
  351. case BE_LST:
  352. mret = va_arg(ap, const char **);
  353. lret = va_arg(ap, size_t *);
  354. if (benc_dget_lst(p, name, mret) != 0)
  355. goto out;
  356. if (lret != NULL)
  357. *lret = benc_nelems(*mret);
  358. break;
  359. case BE_DCT:
  360. mret = va_arg(ap, const char **);
  361. if (benc_dget_dct(p, name, mret) != 0)
  362. goto out;
  363. break;
  364. case BE_MEM:
  365. mret = va_arg(ap, const char **);
  366. lret = va_arg(ap, size_t *);
  367. if (benc_dget_str(p, name, mret, lret) != 0)
  368. goto out;
  369. break;
  370. case BE_STRZ:
  371. aret = va_arg(ap, char **);
  372. lret = va_arg(ap, size_t *);
  373. if (benc_dget_strz(p, name, aret, lret) != 0)
  374. goto out;
  375. break;
  376. default:
  377. abort();
  378. }
  379. }
  380. out:
  381. va_end(ap);
  382. return i;
  383. }
  384. #endif