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.

359 lignes
7.4 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
  214. p = benc_next(p);
  215. }
  216. return NULL;
  217. }
  218. const char *
  219. benc_dget_lst(const char *p, const char *key)
  220. {
  221. const char *ret = benc_dget_any(p, key);
  222. return ret != NULL && benc_islst(ret) ? ret : NULL;
  223. }
  224. const char *
  225. benc_dget_dct(const char *p, const char *key)
  226. {
  227. const char *ret = benc_dget_any(p, key);
  228. return ret != NULL && benc_isdct(ret) ? ret : NULL;
  229. }
  230. const char *
  231. benc_dget_mem(const char *p, const char *key, size_t *len)
  232. {
  233. const char *str = benc_dget_any(p, key);
  234. return str != NULL && benc_isstr(str) ? benc_mem(str, len, NULL) : NULL;
  235. }
  236. char *
  237. benc_dget_mema(const char *p, const char *key, size_t *len)
  238. {
  239. const char *str = benc_dget_any(p, key);
  240. return str != NULL && benc_isstr(str) ? benc_mema(str, len, NULL) : NULL;
  241. }
  242. char *
  243. benc_dget_str(const char *p, const char *key, size_t *len)
  244. {
  245. const char *str = benc_dget_any(p, key);
  246. return str != NULL && benc_isstr(str) ? benc_str(str, len, NULL) : NULL;
  247. }
  248. long long
  249. benc_dget_int(const char *p, const char *key)
  250. {
  251. const char *intp = benc_dget_any(p, key);
  252. return intp != NULL && benc_isint(intp) ? benc_int(intp, NULL) : 0;
  253. }
  254. int
  255. benc_islst(const char *p)
  256. {
  257. return *p == 'l' || *p == 'd';
  258. }
  259. int
  260. benc_isdct(const char *p)
  261. {
  262. return *p == 'd';
  263. }
  264. int
  265. benc_isint(const char *p)
  266. {
  267. return *p == 'i';
  268. }
  269. int
  270. benc_isstr(const char *p)
  271. {
  272. return isdigit(*p);
  273. }
  274. int
  275. benc_istype(const char *p, enum be_type type)
  276. {
  277. switch (type) {
  278. case BE_ANY:
  279. return benc_isdct(p) || benc_isint(p) ||
  280. benc_islst(p) || benc_isstr(p);
  281. case BE_DCT:
  282. return benc_isdct(p);
  283. case BE_INT:
  284. return benc_isint(p);
  285. case BE_LST:
  286. return benc_islst(p);
  287. case BE_STR:
  288. return benc_isstr(p);
  289. default:
  290. abort();
  291. }
  292. }
  293. int
  294. benc_dct_chk(const char *p, int count, ...)
  295. {
  296. int i, ok = 1;
  297. va_list ap;
  298. if (!benc_isdct(p))
  299. ok = 0;
  300. va_start(ap, count);
  301. for (i = 0; ok && i < count; i++) {
  302. enum be_type type = va_arg(ap, enum be_type);
  303. int level = va_arg(ap, int);
  304. const char *dct = p;
  305. const char *key = va_arg(ap, const char *);
  306. while (ok && level > 1) {
  307. if ((dct = benc_dget_dct(dct, key)) != NULL) {
  308. level--;
  309. key = va_arg(ap, const char *);
  310. } else
  311. ok = 0;
  312. }
  313. if (ok) {
  314. const char *val = benc_dget_any(dct, key);
  315. if (val == NULL || !benc_istype(val, type))
  316. ok = 0;
  317. }
  318. }
  319. va_end(ap);
  320. return ok;
  321. }