A clone of btpd with my configuration changes.
25'ten fazla konu seçemezsiniz Konular bir harf veya rakamla başlamalı, kısa çizgiler ('-') içerebilir ve en fazla 35 karakter uzunluğunda olabilir.

341 satır
7.0 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_strlen(const char *p)
  75. {
  76. char *endptr;
  77. return strtoul(p, &endptr, 10);
  78. }
  79. size_t
  80. benc_length(const char *p)
  81. {
  82. size_t blen;
  83. const char *next;
  84. switch (*p) {
  85. case 'd':
  86. case 'l':
  87. blen = 2; // [l|d]...e
  88. next = benc_first(p);
  89. while (*next != 'e') {
  90. size_t len = benc_length(next);
  91. blen += len;
  92. next += len;
  93. }
  94. return blen;
  95. case 'i':
  96. for (next = p + 1; *next != 'e'; next++)
  97. ;
  98. return next - p + 1;
  99. default:
  100. assert((next = benc_mem(p, &blen, NULL)) != NULL);
  101. return next - p + blen;
  102. }
  103. }
  104. size_t
  105. benc_nelems(const char *p)
  106. {
  107. size_t nelems = 0;
  108. for (p = benc_first(p); p != NULL; p = benc_next(p))
  109. nelems++;
  110. return nelems;
  111. }
  112. const char *
  113. benc_first(const char *p)
  114. {
  115. assert(benc_islst(p));
  116. return *(p + 1) == 'e' ? NULL : p + 1;
  117. }
  118. const char *
  119. benc_next(const char *p)
  120. {
  121. size_t blen = benc_length(p);
  122. return *(p + blen) == 'e' ? NULL : p + blen;
  123. }
  124. const char *
  125. benc_mem(const char *p, size_t *len, const char**next)
  126. {
  127. if (!benc_isstr(p))
  128. return NULL;
  129. char *endptr;
  130. size_t blen = strtoul(p, &endptr, 10);
  131. assert(*endptr == ':');
  132. benc_safeset(len, blen);
  133. benc_safeset(next, *(endptr + blen + 1) == 'e' ? NULL : endptr + blen + 1);
  134. return endptr + 1;
  135. }
  136. char *
  137. benc_str(const char *p, size_t *len, const char **next)
  138. {
  139. size_t blen;
  140. const char *bstr;
  141. char *ret;
  142. if ((bstr = benc_mem(p, &blen, next)) == NULL)
  143. return NULL;
  144. if ((ret = malloc(blen + 1)) == NULL)
  145. return NULL;
  146. bcopy(bstr, ret, blen);
  147. ret[blen] = '\0';
  148. benc_safeset(len, blen);
  149. return ret;
  150. }
  151. char *
  152. benc_mema(const char *p, size_t *len, const char **next)
  153. {
  154. size_t blen;
  155. const char *bstr;
  156. char *ret;
  157. if ((bstr = benc_mem(p, &blen, next)) == NULL)
  158. return NULL;
  159. if ((ret = malloc(blen)) == NULL)
  160. return NULL;
  161. bcopy(bstr, ret, blen);
  162. benc_safeset(len, blen);
  163. return ret;
  164. }
  165. long long
  166. benc_int(const char *p, const char **next)
  167. {
  168. long long res;
  169. char *endptr;
  170. if (!benc_isint(p))
  171. return 0;
  172. res = strtoll(p + 1, &endptr, 10);
  173. assert(*endptr == 'e');
  174. benc_safeset(next, *(endptr + 1) == 'e' ? NULL : endptr + 1);
  175. return res;
  176. }
  177. const char *
  178. benc_dget_any(const char *p, const char *key)
  179. {
  180. int cmp;
  181. size_t len, blen;
  182. const char *bstr;
  183. if (!benc_isdct(p))
  184. return NULL;
  185. len = strlen(key);
  186. p = benc_first(p);
  187. while (p != NULL) {
  188. if (!benc_isstr(p))
  189. return NULL;
  190. bstr = benc_mem(p, &blen, &p);
  191. cmp = strncmp(bstr, key, blen);
  192. if (cmp == 0 && len == blen)
  193. return p;
  194. else if (cmp <= 0)
  195. p = benc_next(p);
  196. else
  197. return NULL;
  198. }
  199. return NULL;
  200. }
  201. const char *
  202. benc_dget_lst(const char *p, const char *key)
  203. {
  204. const char *ret = benc_dget_any(p, key);
  205. return ret != NULL && benc_islst(ret) ? ret : NULL;
  206. }
  207. const char *
  208. benc_dget_dct(const char *p, const char *key)
  209. {
  210. const char *ret = benc_dget_any(p, key);
  211. return ret != NULL && benc_isdct(ret) ? ret : NULL;
  212. }
  213. const char *
  214. benc_dget_mem(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_mem(str, len, NULL) : NULL;
  218. }
  219. char *
  220. benc_dget_mema(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_mema(str, len, NULL) : NULL;
  224. }
  225. char *
  226. benc_dget_str(const char *p, const char *key, size_t *len)
  227. {
  228. const char *str = benc_dget_any(p, key);
  229. return str != NULL && benc_isstr(str) ? benc_str(str, len, NULL) : NULL;
  230. }
  231. long long
  232. benc_dget_int(const char *p, const char *key)
  233. {
  234. const char *intp = benc_dget_any(p, key);
  235. return intp != NULL && benc_isint(intp) ? benc_int(intp, NULL) : 0;
  236. }
  237. int
  238. benc_islst(const char *p)
  239. {
  240. return *p == 'l' || *p == 'd';
  241. }
  242. int
  243. benc_isdct(const char *p)
  244. {
  245. return *p == 'd';
  246. }
  247. int
  248. benc_isint(const char *p)
  249. {
  250. return *p == 'i';
  251. }
  252. int
  253. benc_isstr(const char *p)
  254. {
  255. return isdigit(*p);
  256. }
  257. int
  258. benc_istype(const char *p, enum be_type type)
  259. {
  260. switch (type) {
  261. case BE_ANY:
  262. return benc_isdct(p) || benc_isint(p) ||
  263. benc_islst(p) || benc_isstr(p);
  264. case BE_DCT:
  265. return benc_isdct(p);
  266. case BE_INT:
  267. return benc_isint(p);
  268. case BE_LST:
  269. return benc_islst(p);
  270. case BE_STR:
  271. return benc_isstr(p);
  272. default:
  273. abort();
  274. }
  275. }
  276. int
  277. benc_dct_chk(const char *p, int count, ...)
  278. {
  279. int i, ok = 1;
  280. va_list ap;
  281. if (!benc_isdct(p))
  282. ok = 0;
  283. va_start(ap, count);
  284. for (i = 0; ok && i < count; i++) {
  285. enum be_type type = va_arg(ap, enum be_type);
  286. int level = va_arg(ap, int);
  287. const char *dct = p;
  288. const char *key = va_arg(ap, const char *);
  289. while (ok && level > 1) {
  290. if ((dct = benc_dget_dct(dct, key)) != NULL) {
  291. level--;
  292. key = va_arg(ap, const char *);
  293. } else
  294. ok = 0;
  295. }
  296. if (ok) {
  297. const char *val = benc_dget_any(dct, key);
  298. if (val == NULL || !benc_istype(val, type))
  299. ok = 0;
  300. }
  301. }
  302. va_end(ap);
  303. return ok;
  304. }