A clone of btpd with my configuration changes.
Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

360 lines
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 = p + 1;
  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. }