A clone of btpd with my configuration changes.
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

429 lignes
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