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.

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