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.

360 lignes
7.5 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. #include "subr.h"
  10. #define benc_safeset(out, val) if ((out) != NULL) *(out) = (val)
  11. static const char *benc_validate_aux(const char *p, const char *end);
  12. int
  13. benc_validate(const char *p, size_t len)
  14. {
  15. const char *end = p + len - 1;
  16. if (len <= 0)
  17. return EINVAL;
  18. return benc_validate_aux(p, end) == end ? 0 : EINVAL;
  19. }
  20. static const char *
  21. benc_validate_aux(const char *p, const char *end)
  22. {
  23. size_t d = 0;
  24. switch (*p) {
  25. case 'd':
  26. d = 1;
  27. case 'l':
  28. for (p++; p <= end && *p != 'e'; p++) {
  29. if (d != 0) {
  30. if (d % 2 == 1 && !isdigit(*p))
  31. return NULL;
  32. else
  33. d++;
  34. }
  35. if ((p = benc_validate_aux(p, end)) == NULL)
  36. return NULL;
  37. }
  38. if (p > end || (d != 0 && d % 2 != 1))
  39. return NULL;
  40. break;
  41. case 'i':
  42. p++;
  43. if (p > end)
  44. return NULL;
  45. if (*p == '-')
  46. p++;
  47. if (p > end || !isdigit(*p))
  48. return NULL;
  49. p++;
  50. while (p <= end && isdigit(*p))
  51. p++;
  52. if (p > end || *p != 'e')
  53. return NULL;
  54. break;
  55. default:
  56. if (isdigit(*p)) {
  57. size_t len = 0;
  58. while (p <= end && isdigit(*p)) {
  59. len *= 10;
  60. len += *p - '0';
  61. p++;
  62. }
  63. if (p <= end && *p == ':' && p + len <= end)
  64. p += len;
  65. else
  66. return NULL;
  67. }
  68. else
  69. return NULL;
  70. break;
  71. }
  72. return p;
  73. }
  74. int
  75. benc_strcmp(const char *str1, const char *str2)
  76. {
  77. size_t len1, len2;
  78. const char *cs1 = benc_mem(str1, &len1, NULL);
  79. const char *cs2 = benc_mem(str2, &len2, NULL);
  80. int test = strncmp(cs1, cs2, min(len1, len2));
  81. if (test == 0) {
  82. if (len1 == len2)
  83. return 0;
  84. else if (len1 < len2)
  85. return -1;
  86. else
  87. return 1;
  88. } else
  89. return test;
  90. }
  91. size_t
  92. benc_strlen(const char *p)
  93. {
  94. char *endptr;
  95. return strtoul(p, &endptr, 10);
  96. }
  97. size_t
  98. benc_length(const char *p)
  99. {
  100. size_t blen;
  101. const char *next;
  102. switch (*p) {
  103. case 'd':
  104. case 'l':
  105. blen = 2; // [l|d]...e
  106. next = benc_first(p);
  107. while (*next != 'e') {
  108. size_t len = benc_length(next);
  109. blen += len;
  110. next += len;
  111. }
  112. return blen;
  113. case 'i':
  114. for (next = p + 1; *next != 'e'; next++)
  115. ;
  116. return next - p + 1;
  117. default:
  118. assert((next = benc_mem(p, &blen, NULL)) != NULL);
  119. return next - p + blen;
  120. }
  121. }
  122. size_t
  123. benc_nelems(const char *p)
  124. {
  125. size_t nelems = 0;
  126. for (p = benc_first(p); p != NULL; p = benc_next(p))
  127. nelems++;
  128. return nelems;
  129. }
  130. const char *
  131. benc_first(const char *p)
  132. {
  133. assert(benc_islst(p));
  134. return *(p + 1) == 'e' ? NULL : p + 1;
  135. }
  136. const char *
  137. benc_next(const char *p)
  138. {
  139. size_t blen = benc_length(p);
  140. return *(p + blen) == 'e' ? NULL : p + blen;
  141. }
  142. const char *
  143. benc_mem(const char *p, size_t *len, const char**next)
  144. {
  145. if (!benc_isstr(p))
  146. return NULL;
  147. char *endptr;
  148. size_t blen = strtoul(p, &endptr, 10);
  149. assert(*endptr == ':');
  150. benc_safeset(len, blen);
  151. benc_safeset(next, *(endptr + blen + 1) == 'e' ? NULL : endptr + blen + 1);
  152. return endptr + 1;
  153. }
  154. char *
  155. benc_str(const char *p, size_t *len, const char **next)
  156. {
  157. size_t blen;
  158. const char *bstr;
  159. char *ret;
  160. if ((bstr = benc_mem(p, &blen, next)) == NULL)
  161. return NULL;
  162. if ((ret = malloc(blen + 1)) == NULL)
  163. return NULL;
  164. bcopy(bstr, ret, blen);
  165. ret[blen] = '\0';
  166. benc_safeset(len, blen);
  167. return ret;
  168. }
  169. char *
  170. benc_mema(const char *p, size_t *len, const char **next)
  171. {
  172. size_t blen;
  173. const char *bstr;
  174. char *ret;
  175. if ((bstr = benc_mem(p, &blen, next)) == NULL)
  176. return NULL;
  177. if ((ret = malloc(blen)) == NULL)
  178. return NULL;
  179. bcopy(bstr, ret, blen);
  180. benc_safeset(len, blen);
  181. return ret;
  182. }
  183. long long
  184. benc_int(const char *p, const char **next)
  185. {
  186. long long res;
  187. char *endptr;
  188. if (!benc_isint(p))
  189. return 0;
  190. res = strtoll(p + 1, &endptr, 10);
  191. assert(*endptr == 'e');
  192. benc_safeset(next, *(endptr + 1) == 'e' ? NULL : endptr + 1);
  193. return res;
  194. }
  195. const char *
  196. benc_dget_any(const char *p, const char *key)
  197. {
  198. int cmp;
  199. size_t len, blen;
  200. const char *bstr;
  201. if (!benc_isdct(p))
  202. return NULL;
  203. len = strlen(key);
  204. p = benc_first(p);
  205. while (p != NULL) {
  206. if (!benc_isstr(p))
  207. return NULL;
  208. bstr = benc_mem(p, &blen, &p);
  209. cmp = strncmp(bstr, key, blen);
  210. if (cmp == 0 && len == blen)
  211. return p;
  212. else if (cmp <= 0)
  213. p = benc_next(p);
  214. else
  215. return NULL;
  216. }
  217. return NULL;
  218. }
  219. const char *
  220. benc_dget_lst(const char *p, const char *key)
  221. {
  222. const char *ret = benc_dget_any(p, key);
  223. return ret != NULL && benc_islst(ret) ? ret : NULL;
  224. }
  225. const char *
  226. benc_dget_dct(const char *p, const char *key)
  227. {
  228. const char *ret = benc_dget_any(p, key);
  229. return ret != NULL && benc_isdct(ret) ? ret : NULL;
  230. }
  231. const char *
  232. benc_dget_mem(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_mem(str, len, NULL) : NULL;
  236. }
  237. char *
  238. benc_dget_mema(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_mema(str, len, NULL) : NULL;
  242. }
  243. char *
  244. benc_dget_str(const char *p, const char *key, size_t *len)
  245. {
  246. const char *str = benc_dget_any(p, key);
  247. return str != NULL && benc_isstr(str) ? benc_str(str, len, NULL) : NULL;
  248. }
  249. long long
  250. benc_dget_int(const char *p, const char *key)
  251. {
  252. const char *intp = benc_dget_any(p, key);
  253. return intp != NULL && benc_isint(intp) ? benc_int(intp, NULL) : 0;
  254. }
  255. int
  256. benc_islst(const char *p)
  257. {
  258. return *p == 'l' || *p == 'd';
  259. }
  260. int
  261. benc_isdct(const char *p)
  262. {
  263. return *p == 'd';
  264. }
  265. int
  266. benc_isint(const char *p)
  267. {
  268. return *p == 'i';
  269. }
  270. int
  271. benc_isstr(const char *p)
  272. {
  273. return isdigit(*p);
  274. }
  275. int
  276. benc_istype(const char *p, enum be_type type)
  277. {
  278. switch (type) {
  279. case BE_ANY:
  280. return benc_isdct(p) || benc_isint(p) ||
  281. benc_islst(p) || benc_isstr(p);
  282. case BE_DCT:
  283. return benc_isdct(p);
  284. case BE_INT:
  285. return benc_isint(p);
  286. case BE_LST:
  287. return benc_islst(p);
  288. case BE_STR:
  289. return benc_isstr(p);
  290. default:
  291. abort();
  292. }
  293. }
  294. int
  295. benc_dct_chk(const char *p, int count, ...)
  296. {
  297. int i, ok = 1;
  298. va_list ap;
  299. if (!benc_isdct(p))
  300. ok = 0;
  301. va_start(ap, count);
  302. for (i = 0; ok && i < count; i++) {
  303. enum be_type type = va_arg(ap, enum be_type);
  304. int level = va_arg(ap, int);
  305. const char *dct = p;
  306. const char *key = va_arg(ap, const char *);
  307. while (ok && level > 1) {
  308. if ((dct = benc_dget_dct(dct, key)) != NULL) {
  309. level--;
  310. key = va_arg(ap, const char *);
  311. } else
  312. ok = 0;
  313. }
  314. if (ok) {
  315. const char *val = benc_dget_any(dct, key);
  316. if (val == NULL || !benc_istype(val, type))
  317. ok = 0;
  318. }
  319. }
  320. va_end(ap);
  321. return ok;
  322. }