A clone of btpd with my configuration changes.
Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

334 рядки
6.9 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. #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. }