uf_features.c 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  1. /*
  2. * uf_features.c -- part of share.mod
  3. *
  4. */
  5. /*
  6. * Userfile feature protocol description:
  7. *
  8. *
  9. * LEAF HUB
  10. *
  11. * uf_features_dump():
  12. * Finds out which features
  13. * it supports / wants to use
  14. * and then dumps those. The
  15. * list is appended to the
  16. * user file send ack.
  17. *
  18. * "s uy <features>" --+
  19. * |
  20. * +--> uf_features_parse():
  21. * Parses the given list of features,
  22. * given in a string, seperated with
  23. * spaces. Decides which features to
  24. * accept/use. Those features are then
  25. * locally set:
  26. *
  27. * dcc[idx].u.bot->uff_flags |= <feature_flag>
  28. *
  29. * and sent back to the LEAF:
  30. *
  31. * +--- "s feats <accepted_features>"
  32. * |
  33. * uf_features_check(): <--+
  34. * Checks wether the responded
  35. * features are still accepted
  36. * by us. If they are, we set
  37. * the flags locally:
  38. *
  39. * dcc[idx].u.bot->uff_flags |= <feature_flag>
  40. */
  41. typedef struct uff_list_struct {
  42. struct uff_list_struct *next; /* Pointer to next entry */
  43. struct uff_list_struct *prev; /* Pointer to previous entry */
  44. uff_table_t *entry; /* Pointer to entry in table. This is
  45. not copied or anything, we just refer
  46. to the original table entry. */
  47. } uff_list_t;
  48. typedef struct {
  49. uff_list_t *start;
  50. uff_list_t *end;
  51. } uff_head_t;
  52. static uff_head_t uff_list;
  53. static char uff_sbuf[512] = "";
  54. /*
  55. * Userfile features management functions
  56. */
  57. static void uff_init(void)
  58. {
  59. egg_bzero(&uff_list, sizeof(uff_head_t));
  60. }
  61. /* Search for a feature in the uff feature list that matches a supplied
  62. * feature flag. Returns a pointer to the entry in the list or NULL if
  63. * no feature uses the flag.
  64. */
  65. static uff_list_t *uff_findentry_byflag(int flag)
  66. {
  67. uff_list_t *ul = NULL;
  68. for (ul = uff_list.start; ul; ul = ul->next)
  69. if (ul->entry->flag & flag)
  70. return ul;
  71. return NULL;
  72. }
  73. /* Search for a feature in the uff feature list. Returns a pointer to the
  74. * entry in the list or NULL if no such feature exists.
  75. */
  76. static uff_list_t *uff_findentry_byname(char *feature)
  77. {
  78. uff_list_t *ul = NULL;
  79. for (ul = uff_list.start; ul; ul = ul->next)
  80. if (!strcmp(ul->entry->feature, feature))
  81. return ul;
  82. return NULL;
  83. }
  84. /* Insert entry into sorted list.
  85. */
  86. static void uff_insert_entry(uff_list_t *nul)
  87. {
  88. uff_list_t *ul = NULL, *lul = NULL;
  89. ul = uff_list.start;
  90. while (ul && ul->entry->priority < nul->entry->priority) {
  91. lul = ul;
  92. ul = ul->next;
  93. }
  94. nul->prev = NULL;
  95. nul->next = NULL;
  96. if (lul) {
  97. if (lul->next)
  98. lul->next->prev = nul;
  99. nul->next = lul->next;
  100. nul->prev = lul;
  101. lul->next = nul;
  102. } else if (ul) {
  103. uff_list.start->prev = nul;
  104. nul->next = uff_list.start;
  105. uff_list.start = nul;
  106. } else
  107. uff_list.start = nul;
  108. if (!nul->next)
  109. uff_list.end = nul;
  110. }
  111. /* Add a single feature to the list.
  112. */
  113. static void uff_addfeature(uff_table_t *ut)
  114. {
  115. uff_list_t *ul = NULL;
  116. if (uff_findentry_byname(ut->feature)) {
  117. putlog(LOG_MISC, "*", "(!) share: same feature name used twice: %s", ut->feature);
  118. return;
  119. }
  120. ul = uff_findentry_byflag(ut->flag);
  121. if (ul) {
  122. putlog(LOG_MISC, "*", "(!) share: feature flag %d used twice by %s and %s", ut->flag, ut->feature, ul->entry->feature);
  123. return;
  124. }
  125. ul = calloc(1, sizeof(uff_list_t));
  126. ul->entry = ut;
  127. uff_insert_entry(ul);
  128. }
  129. /* Add a complete table to the list.
  130. */
  131. void uff_addtable(uff_table_t *ut)
  132. {
  133. if (!ut)
  134. return;
  135. for (; ut->feature; ++ut)
  136. uff_addfeature(ut);
  137. }
  138. /*
  139. * Userfile feature parsing functions
  140. */
  141. #ifdef HUB
  142. /* Parse the given features string, set internal flags apropriately and
  143. * eventually respond with all features we will use.
  144. */
  145. static void uf_features_parse(int idx, char *par)
  146. {
  147. char *buf = NULL, *s = NULL, *p = NULL;
  148. uff_list_t *ul = NULL;
  149. uff_sbuf[0] = 0; /* Reset static buffer */
  150. p = s = buf = strdup(par);
  151. /* Clear all currently set features. */
  152. dcc[idx].u.bot->uff_flags = 0;
  153. /* Parse string */
  154. while ((s = strchr(s, ' ')) != NULL) {
  155. *s = '\0';
  156. /* Is the feature available and active? */
  157. ul = uff_findentry_byname(p);
  158. if (ul && (ul->entry->ask_func == NULL || ul->entry->ask_func(idx))) {
  159. dcc[idx].u.bot->uff_flags |= ul->entry->flag; /* Set flag */
  160. strcat(uff_sbuf, ul->entry->feature); /* Add feature to list */
  161. strcat(uff_sbuf, " ");
  162. }
  163. p = ++s;
  164. }
  165. free(buf);
  166. /* Send response string */
  167. if (uff_sbuf[0])
  168. dprintf(idx, "s feats %s\n", uff_sbuf);
  169. }
  170. #endif /* HUB */
  171. /* Return a list of features we are supporting.
  172. */
  173. static char *uf_features_dump(int idx)
  174. {
  175. uff_list_t *ul = NULL;
  176. uff_sbuf[0] = 0;
  177. for (ul = uff_list.start; ul; ul = ul->next)
  178. if (ul->entry->ask_func == NULL || ul->entry->ask_func(idx)) {
  179. strcat(uff_sbuf, ul->entry->feature); /* Add feature to list */
  180. strcat(uff_sbuf, " ");
  181. }
  182. return uff_sbuf;
  183. }
  184. static int uf_features_check(int idx, char *par)
  185. {
  186. char *buf = NULL, *s = NULL, *p = NULL;
  187. uff_list_t *ul = NULL;
  188. uff_sbuf[0] = 0; /* Reset static buffer */
  189. p = s = buf = strdup(par);
  190. /* Clear all currently set features. */
  191. dcc[idx].u.bot->uff_flags = 0;
  192. /* Parse string */
  193. while ((s = strchr(s, ' ')) != NULL) {
  194. *s = '\0';
  195. /* Is the feature available and active? */
  196. ul = uff_findentry_byname(p);
  197. if (ul && (ul->entry->ask_func == NULL || ul->entry->ask_func(idx)))
  198. dcc[idx].u.bot->uff_flags |= ul->entry->flag; /* Set flag */
  199. else {
  200. /* It isn't, and our hub wants to use it! This either happens
  201. * because the hub doesn't look at the features we suggested to
  202. * use or because our admin changed the flags, so that formerly
  203. * active features are now deactivated.
  204. *
  205. * In any case, we abort user file sharing.
  206. */
  207. putlog(LOG_BOTS, "*", "Bot %s tried unsupported feature!", dcc[idx].nick);
  208. dprintf(idx, "s e Attempt to use an unsupported feature\n");
  209. zapfbot(idx);
  210. free(buf);
  211. return 0;
  212. }
  213. p = ++s;
  214. }
  215. free(buf);
  216. return 1;
  217. }
  218. #ifdef HUB
  219. /* Call all active feature functions, sorted by their priority. This
  220. * should be called when we're about to send a user file.
  221. */
  222. static int uff_call_sending(int idx, char *user_file)
  223. {
  224. uff_list_t *ul = NULL;
  225. for (ul = uff_list.start; ul; ul = ul->next)
  226. if (ul->entry && ul->entry->snd &&
  227. (dcc[idx].u.bot->uff_flags & ul->entry->flag))
  228. if (!(ul->entry->snd(idx, user_file)))
  229. return 0; /* Failed! */
  230. return 1;
  231. }
  232. #endif /* HUB */
  233. /* Call all active feature functions, sorted by their priority. This
  234. * should be called when we've received a user file and are about to
  235. * parse it.
  236. */
  237. static int uff_call_receiving(int idx, char *user_file)
  238. {
  239. uff_list_t *ul = NULL;
  240. for (ul = uff_list.end; ul; ul = ul->prev)
  241. if (ul->entry && ul->entry->rcv &&
  242. (dcc[idx].u.bot->uff_flags & ul->entry->flag))
  243. if (!(ul->entry->rcv(idx, user_file)))
  244. return 0; /* Failed! */
  245. return 1;
  246. }
  247. /*
  248. * Userfile feature handlers
  249. */
  250. /*
  251. * Internal user file feature table
  252. */
  253. int
  254. blah() {
  255. return 1;
  256. }
  257. static uff_table_t internal_uff_table[] = {
  258. {"overbots", UFF_OVERRIDE, blah, 0, NULL, NULL},
  259. {"invites", UFF_INVITE, NULL, 0, NULL, NULL},
  260. {"exempts", UFF_EXEMPT, NULL, 0, NULL, NULL},
  261. {NULL, 0, NULL, 0, NULL, NULL}
  262. };