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.

benc.c 6.9 KiB

il y a 19 ans
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333
  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. char *endptr;
  124. size_t blen = strtoul(p, &endptr, 10);
  125. assert(*endptr == ':');
  126. benc_safeset(len, blen);
  127. benc_safeset(next, *(endptr + blen + 1) == 'e' ? NULL : endptr + blen + 1);
  128. return endptr + 1;
  129. }
  130. char *
  131. benc_str(const char *p, size_t *len, const char **next)
  132. {
  133. size_t blen;
  134. const char *bstr;
  135. char *ret;
  136. if ((bstr = benc_mem(p, &blen, next)) == NULL)
  137. return NULL;
  138. if ((ret = malloc(blen + 1)) == NULL)
  139. return NULL;
  140. bcopy(bstr, ret, blen);
  141. ret[blen] = '\0';
  142. benc_safeset(len, blen);
  143. return ret;
  144. }
  145. char *
  146. benc_mema(const char *p, size_t *len, const char **next)
  147. {
  148. size_t blen;
  149. const char *bstr;
  150. char *ret;
  151. if ((bstr = benc_mem(p, &blen, next)) == NULL)
  152. return NULL;
  153. if ((ret = malloc(blen)) == NULL)
  154. return NULL;
  155. bcopy(bstr, ret, blen);
  156. benc_safeset(len, blen);
  157. return ret;
  158. }
  159. long long
  160. benc_int(const char *p, const char **next)
  161. {
  162. long long res;
  163. char *endptr;
  164. if (!benc_isint(p))
  165. return 0;
  166. res = strtoll(p + 1, &endptr, 10);
  167. assert(*endptr == 'e');
  168. benc_safeset(next, *(endptr + 1) == 'e' ? NULL : endptr + 1);
  169. return res;
  170. }
  171. const char *
  172. benc_dget_any(const char *p, const char *key)
  173. {
  174. int cmp;
  175. size_t len, blen;
  176. const char *bstr;
  177. if (!benc_isdct(p))
  178. return NULL;
  179. len = strlen(key);
  180. p = benc_first(p);
  181. while (p != NULL) {
  182. if (!benc_isstr(p))
  183. return NULL;
  184. bstr = benc_mem(p, &blen, &p);
  185. cmp = strncmp(bstr, key, blen);
  186. if (cmp == 0 && len == blen)
  187. return p;
  188. else if (cmp <= 0)
  189. p = benc_next(p);
  190. else
  191. return NULL;
  192. }
  193. return NULL;
  194. }
  195. const char *
  196. benc_dget_lst(const char *p, const char *key)
  197. {
  198. const char *ret = benc_dget_any(p, key);
  199. return ret != NULL && benc_islst(ret) ? ret : NULL;
  200. }
  201. const char *
  202. benc_dget_dct(const char *p, const char *key)
  203. {
  204. const char *ret = benc_dget_any(p, key);
  205. return ret != NULL && benc_isdct(ret) ? ret : NULL;
  206. }
  207. const char *
  208. benc_dget_mem(const char *p, const char *key, size_t *len)
  209. {
  210. const char *str = benc_dget_any(p, key);
  211. return str != NULL && benc_isstr(str) ? benc_mem(str, len, NULL) : NULL;
  212. }
  213. char *
  214. benc_dget_mema(const char *p, const char *key, size_t *len)
  215. {
  216. const char *str = benc_dget_any(p, key);
  217. return str != NULL && benc_isstr(str) ? benc_mema(str, len, NULL) : NULL;
  218. }
  219. char *
  220. benc_dget_str(const char *p, const char *key, size_t *len)
  221. {
  222. const char *str = benc_dget_any(p, key);
  223. return str != NULL && benc_isstr(str) ? benc_str(str, len, NULL) : NULL;
  224. }
  225. long long
  226. benc_dget_int(const char *p, const char *key)
  227. {
  228. const char *intp = benc_dget_any(p, key);
  229. return intp != NULL && benc_isint(intp) ? benc_int(intp, NULL) : 0;
  230. }
  231. int
  232. benc_islst(const char *p)
  233. {
  234. return *p == 'l' || *p == 'd';
  235. }
  236. int
  237. benc_isdct(const char *p)
  238. {
  239. return *p == 'd';
  240. }
  241. int
  242. benc_isint(const char *p)
  243. {
  244. return *p == 'i';
  245. }
  246. int
  247. benc_isstr(const char *p)
  248. {
  249. return isdigit(*p);
  250. }
  251. int
  252. benc_istype(const char *p, enum be_type type)
  253. {
  254. switch (type) {
  255. case BE_ANY:
  256. return benc_isdct(p) || benc_isint(p) ||
  257. benc_islst(p) || benc_isstr(p);
  258. case BE_DCT:
  259. return benc_isdct(p);
  260. case BE_INT:
  261. return benc_isint(p);
  262. case BE_LST:
  263. return benc_islst(p);
  264. case BE_STR:
  265. return benc_isstr(p);
  266. default:
  267. abort();
  268. }
  269. }
  270. int
  271. benc_dct_chk(const char *p, int count, ...)
  272. {
  273. int i, ok = 1;
  274. va_list ap;
  275. if (!benc_isdct(p))
  276. ok = 0;
  277. va_start(ap, count);
  278. for (i = 0; ok && i < count; i++) {
  279. enum be_type type = va_arg(ap, enum be_type);
  280. int level = va_arg(ap, int);
  281. const char *dct = p;
  282. const char *key = va_arg(ap, const char *);
  283. while (ok && level > 1) {
  284. if ((dct = benc_dget_dct(dct, key)) != NULL) {
  285. level--;
  286. key = va_arg(ap, const char *);
  287. } else
  288. ok = 0;
  289. }
  290. if (ok) {
  291. const char *val = benc_dget_any(dct, key);
  292. if (val == NULL || !benc_istype(val, type))
  293. ok = 0;
  294. }
  295. }
  296. va_end(ap);
  297. return ok;
  298. }