Bez tytułu

z Gracious Treeshrew, 5 miesiące temu, napisane w C, wyświetlone 60 razy. [paste_expire] 5 miesiące.
URL https://pastebin.k4be.pl/view/b9409098 Udostępnij
Pobierz wklejkę lub Pokaż surowy tekst
  1.  
  2. #include "unrealircd.h"
  3.  
  4. /* this should go into include/numeric.h (was there at one point of time) */
  5.  
  6. #define RPL_WHOISKEYVALUE    760
  7. #define RPL_KEYVALUE         761
  8. #define RPL_KEYNOTSET    766
  9. #define RPL_METADATASUBOK    770
  10. #define RPL_METADATAUNSUBOK  771
  11. #define RPL_METADATASUBS     772
  12. #define RPL_METADATASYNCLATER 774
  13.  
  14. #define STR_RPL_WHOISKEYVALUE           /* 760 */       "%s %s %s :%s"
  15. #define STR_RPL_KEYVALUE                        /* 761 */       "%s %s %s :%s"
  16. #define STR_RPL_KEYNOTSET                       /* 766 */       "%s %s :key not set" /* FIXME sending FAIL instead */
  17. #define STR_RPL_METADATASUBOK           /* 770 */       ":%s"
  18. #define STR_RPL_METADATAUNSUBOK         /* 771 */       ":%s"
  19. #define STR_RPL_METADATASUBS            /* 772 */       ":%s"
  20. #define STR_RPL_METADATASYNCLATER       /* 774 */       "%s %s"
  21.  
  22. /* sendnumeric() which allows message tags (BATCH in our case) */
  23.  
  24. #define sendnumeric_mtags(to, mtags, numeric, ...) sendnumericfmt_tags(to, mtags, numeric, STR_ ## numeric, ##__VA_ARGS__)
  25.  
  26. void vsendto_one(Client *to, MessageTag *mtags, const char *pattern, va_list vl); /* no prototype from send.c */
  27.  
  28. void sendnumericfmt_tags (Client *to, MessageTag *mtags, int numeric, FORMAT_STRING(const char *pattern), ...) {
  29.         va_list vl;
  30.         char realpattern[512];
  31.  
  32.         snprintf(realpattern, sizeof(realpattern), ":%s %.3d %s %s", me.name, numeric, to->name[0] ? to->name : "*", pattern);
  33.  
  34.         va_start(vl, pattern);
  35.         vsendto_one(to, mtags, realpattern, vl);
  36.         va_end(vl);
  37. }
  38.  
  39. /* actual METADATA code */
  40.  
  41. #define STR_HELPER(x) #x
  42. #define STR(x) STR_HELPER(x)
  43.  
  44. /* get or set for perms */
  45. #define MODE_SET 0
  46. #define MODE_GET 1
  47.  
  48. #define WATCH_EVENT_METADATA    3000 /* core uses 0..8, we hope no other module will try 3000 */
  49.  
  50. #define MYCONF "metadata"
  51.  
  52. #define CHECKPARAMSCNT_OR_DIE(count, return) \
  53. { \
  54.         if (parc < count+1 || BadPtr(parv[count])) \
  55.         { \
  56.                 sendnumeric(client, ERR_NEEDMOREPARAMS, "METADATA"); \
  57.                 return; \
  58.         } \
  59. }
  60.  
  61. /* target "*" is always the user issuing the command */
  62.  
  63. #define PROCESS_TARGET_OR_DIE(target, user, channel, return) \
  64. { \
  65.         char *channame; \
  66.         channame = strchr(target, '#'); \
  67.         if (channame) \
  68.         { \
  69.                 channel = find_channel(channame); \
  70.                 if (!channel) \
  71.                 { \
  72.                         sendnumeric(client, ERR_NOSUCHNICK, channame); \
  73.                         return; \
  74.                 } \
  75.         } else \
  76.         { \
  77.                 if (strcmp(target, "*")) \
  78.                 { \
  79.                         user = hash_find_nickatserver(target, NULL); \
  80.                         if (!user) \
  81.                         { \
  82.                                 sendnumeric(client, ERR_NOSUCHNICK, target); \
  83.                                 return; \
  84.                         } \
  85.                 } else \
  86.                 { \
  87.                         user = client; \
  88.                 } \
  89.         } \
  90. }
  91.  
  92. #define FOR_EACH_KEY(keyindex, parc, parv) while(keyindex++, key = parv[keyindex], (!BadPtr(key) && keyindex < parc))
  93. #define IsSendable(x)           (DBufLength(&x->local->sendQ) < 2048)
  94. #define CHECKREGISTERED_OR_DIE(client, return) \
  95. { \
  96.         if (!IsUser(client)) \
  97.         { \
  98.                 sendnumeric(client, ERR_NOTREGISTERED); \
  99.                 return; \
  100.         } \
  101. }
  102. #define USER_METADATA(client) moddata_client(client, metadataUser).ptr
  103. #define CHANNEL_METADATA(channel) moddata_channel(channel, metadataChannel).ptr
  104.  
  105. struct metadata {
  106.         char *name;
  107.         char *value;
  108.         struct metadata *next;
  109. };
  110.  
  111. struct metadata_subscriptions {
  112.         char *name;
  113.         struct metadata_subscriptions *next;
  114. };
  115.  
  116. struct metadata_moddata_user {
  117.         struct metadata *metadata;
  118.         struct metadata_subscriptions *subs;
  119.         struct metadata_unsynced *us;
  120. };
  121.  
  122. struct metadata_unsynced { /* we're listing users (UIDs) or channels that should be synced but were not */
  123.         char *id;
  124.         char *key;
  125.         struct metadata_unsynced *next;
  126. };
  127.  
  128. CMD_FUNC(cmd_metadata);
  129. CMD_FUNC(cmd_metadata_remote);
  130. CMD_FUNC(cmd_metadata_local);
  131. EVENT(metadata_queue_evt);
  132. const char *metadata_cap_param(Client *client);
  133. char *metadata_isupport_param(void);
  134. int metadata_configtest(ConfigFile *cf, ConfigEntry *ce, int type, int *errs);
  135. int metadata_configposttest(int *errs);
  136. int metadata_configrun(ConfigFile *cf, ConfigEntry *ce, int type);
  137. int metadata_server_sync(Client *client);
  138. int metadata_join(Client *client, Channel *channel, MessageTag *mtags);
  139. int metadata_user_registered(Client *client);
  140. void metadata_user_free(ModData *md);
  141. void metadata_channel_free(ModData *md);
  142. void metadata_free(struct metadata *metadata);
  143. void metadata_free_subs(struct metadata_subscriptions *subs);
  144. int metadata_is_subscribed(Client *user, const char *key);
  145. const char *metadata_get_user_key_value(Client *user, const char *key);
  146. const char *metadata_get_channel_key_value(Channel *channel, const char *key);
  147. void user_metadata_changed(Client *user, const char *key, const char *value, Client *changer);
  148. void channel_metadata_changed(Channel *channel, const char *key, const char *value, Client *changer);
  149. void metadata_free_list(struct metadata *metadata, const char *whose, Client *client);
  150. struct metadata_moddata_user *metadata_prepare_user_moddata(Client *user);
  151. void metadata_set_channel(Channel *channel, const char *key, const char *value, Client *client);
  152. void metadata_set_user(Client *user, const char *key, const char *value, Client *client);
  153. void metadata_send_channel(Channel *channel, const char *key, Client *client);
  154. void metadata_send_user(Client *user, const char *key, Client *client);
  155. int metadata_subscribe(const char *key, Client *client, int remove);
  156. void metadata_clear_channel(Channel *channel, Client *client);
  157. void metadata_clear_user(Client *user, Client *client);
  158. void metadata_send_subscribtions(Client *client);
  159. void metadata_send_all_for_channel(Channel *channel, Client *client);
  160. void metadata_send_all_for_user(Client *user, Client *client);
  161. void metadata_send_pending(Client *client);
  162. void metadata_sync_user(Client *client, Client *target, MessageTag *mtags, int create_batch);
  163. void metadata_sync_channel(Client *client, Channel *channel);
  164. int metadata_key_valid(const char *key);
  165. int metadata_check_perms(Client *user, Channel *channel, Client *client, const char *key, int mode);
  166. void metadata_send_change(Client *client, MessageTag *mtags, const char *who, const char *key, const char *value, Client *changer);
  167. int metadata_notify_or_queue(Client *client, MessageTag *mtags, const char *who, const char *key, const char *value, Client *changer);
  168. int metadata_monitor_connect(Client *client);
  169. int metadata_monitor_notification(Client *client, Watch *watch, Link *lp, int event);
  170.  
  171. ModDataInfo *metadataUser;
  172. ModDataInfo *metadataChannel;
  173. long CAP_METADATA = 0L;
  174. long CAP_METADATA_NOTIFY = 0L;
  175.  
  176. struct metadata_settings_s {
  177.         int max_user_metadata;
  178.         int max_channel_metadata;
  179.         int max_subscriptions;
  180.         int max_value_bytes;
  181. } metadata_settings;
  182.  
  183. ModuleHeader MOD_HEADER = {
  184.         "third/metadata-2",
  185.         "6.0",
  186.         "draft/metadata-2 and draft/metadata-notify-2 cap",
  187.         "k4be",
  188.         "unrealircd-6"
  189. };
  190.  
  191. /*
  192. metadata {
  193.         max-user-metadata 10;
  194.         max-channel-metadata 10;
  195.         max-subscriptions 10;
  196.         max-value-bytes 300;
  197. };
  198. */
  199.  
  200. int metadata_configtest(ConfigFile *cf, ConfigEntry *ce, int type, int *errs) {
  201.         ConfigEntry *cep;
  202.         int errors = 0;
  203.         int i;
  204.        
  205.         if (type != CONFIG_MAIN)
  206.                 return 0;
  207.  
  208.         if (!ce || !ce->name)
  209.                 return 0;
  210.  
  211.         if (strcmp(ce->name, MYCONF))
  212.                 return 0;
  213.  
  214.         for (cep = ce->items; cep; cep = cep->next)
  215.         {
  216.                 if (!cep->name)
  217.                 {
  218.                         config_error("%s:%i: blank %s item", cep->file->filename, cep->line_number, MYCONF);
  219.                         errors++;
  220.                         continue;
  221.                 }
  222.  
  223.                 if (!cep->value || !strlen(cep->value))
  224.                 {
  225.                         config_error("%s:%i: %s::%s must be non-empty", cep->file->filename, cep->line_number, MYCONF, cep->name);
  226.                         errors++;
  227.                         continue;
  228.                 }
  229.        
  230.                 if (!strcmp(cep->name, "max-user-metadata"))
  231.                 {
  232.                         for (i = 0; cep->value[i]; i++)
  233.                         {
  234.                                 if (!isdigit(cep->value[i]))
  235.                                 {
  236.                                         config_error("%s:%i: %s::%s must be an integer between 1 and 100", cep->file->filename, cep->line_number, MYCONF, cep->name);
  237.                                         errors++;
  238.                                         break;
  239.                                 }
  240.                         }
  241.                         if (!errors && (atoi(cep->value) < 1 || atoi(cep->value) > 100))
  242.                         {
  243.                                 config_error("%s:%i: %s::%s must be an integer between 1 and 100", cep->file->filename, cep->line_number, MYCONF, cep->name);
  244.                                 errors++;
  245.                         }
  246.                         continue;
  247.                 }
  248.  
  249.                 if (!strcmp(cep->name, "max-channel-metadata"))
  250.                 {
  251.                         for (i = 0; cep->value[i]; i++)
  252.                         {
  253.                                 if (!isdigit(cep->value[i]))
  254.                                 {
  255.                                         config_error("%s:%i: %s::%s must be an integer between 0 and 100", cep->file->filename, cep->line_number, MYCONF, cep->name);
  256.                                         errors++;
  257.                                         break;
  258.                                 }
  259.                         }
  260.                         if (!errors && (atoi(cep->value) < 0 || atoi(cep->value) > 100))
  261.                         {
  262.                                 config_error("%s:%i: %s::%s must be an integer between 0 and 100", cep->file->filename, cep->line_number, MYCONF, cep->name);
  263.                                 errors++;
  264.                         }
  265.                         continue;
  266.                 }
  267.  
  268.                 if (!strcmp(cep->name, "max-subscriptions"))
  269.                 {
  270.                         for (i = 0; cep->value[i]; i++)
  271.                         {
  272.                                 if (!isdigit(cep->value[i]))
  273.                                 {
  274.                                         config_error("%s:%i: %s::%s must be an integer between 1 and 100", cep->file->filename, cep->line_number, MYCONF, cep->name);
  275.                                         errors++;
  276.                                         break;
  277.                                 }
  278.                         }
  279.                         if (!errors && (atoi(cep->value) < 0 || atoi(cep->value) > 100))
  280.                         {
  281.                                 config_error("%s:%i: %s::%s must be an integer between 1 and 100", cep->file->filename, cep->line_number, MYCONF, cep->name);
  282.                                 errors++;
  283.                         }
  284.                         continue;
  285.                 }
  286.  
  287.  
  288.                 if (!strcmp(cep->name, "max-value-bytes"))
  289.                 {
  290.                         for (i = 0; cep->value[i]; i++)
  291.                         {
  292.                                 if (!isdigit(cep->value[i]))
  293.                                 {
  294.                                         config_error("%s:%i: %s::%s must be an integer between 1 and 400", cep->file->filename, cep->line_number, MYCONF, cep->name);
  295.                                         errors++;
  296.                                         break;
  297.                                 }
  298.                         }
  299.                         if (!errors && (atoi(cep->value) < 0 || atoi(cep->value) > 400))
  300.                         {
  301.                                 config_error("%s:%i: %s::%s must be an integer between 1 and 400", cep->file->filename, cep->line_number, MYCONF, cep->name);
  302.                                 errors++;
  303.                         }
  304.                         continue;
  305.                 }
  306.  
  307.                 config_warn("%s:%i: unknown item %s::%s", cep->file->filename, cep->line_number, MYCONF, cep->name);
  308.         }
  309.        
  310.         *errs = errors;
  311.         return errors ? -1 : 1;
  312. }
  313.  
  314. int metadata_configposttest(int *errs) {
  315.         /* null the settings to avoid keeping old value if none is set in config */
  316.         metadata_settings.max_user_metadata = 0;
  317.         metadata_settings.max_channel_metadata = 0;
  318.         metadata_settings.max_subscriptions = 0;
  319.         metadata_settings.max_value_bytes = 0;
  320.         return 1;
  321. }
  322.  
  323. int metadata_configrun(ConfigFile *cf, ConfigEntry *ce, int type) {
  324.         ConfigEntry *cep;
  325.  
  326.         if (type != CONFIG_MAIN)
  327.                 return 0;
  328.  
  329.         if (!ce || !ce->name)
  330.                 return 0;
  331.  
  332.         if (strcmp(ce->name, MYCONF))
  333.                 return 0;
  334.  
  335.         for (cep = ce->items; cep; cep = cep->next)
  336.         {
  337.                 if (!cep->name)
  338.                         continue;
  339.  
  340.                 if (!strcmp(cep->name, "max-user-metadata"))
  341.                 {
  342.                         metadata_settings.max_user_metadata = atoi(cep->value);
  343.                         continue;
  344.                 }
  345.  
  346.                 if (!strcmp(cep->name, "max-channel-metadata"))
  347.                 {
  348.                         metadata_settings.max_channel_metadata = atoi(cep->value);
  349.                         continue;
  350.                 }
  351.  
  352.                 if (!strcmp(cep->name, "max-subscriptions"))
  353.                 {
  354.                         metadata_settings.max_subscriptions = atoi(cep->value);
  355.                         continue;
  356.                 }
  357.  
  358.                 if (!strcmp(cep->name, "max-value-bytes"))
  359.                 {
  360.                         metadata_settings.max_value_bytes = atoi(cep->value);
  361.                         continue;
  362.                 }
  363.         }
  364.         return 1;
  365. }
  366.  
  367. MOD_TEST(){
  368.         MARK_AS_OFFICIAL_MODULE(modinfo);
  369.         HookAdd(modinfo->handle, HOOKTYPE_CONFIGTEST, 0, metadata_configtest);
  370.         HookAdd(modinfo->handle, HOOKTYPE_CONFIGPOSTTEST, 0, metadata_configposttest);
  371.         return MOD_SUCCESS;
  372. }
  373.  
  374. MOD_INIT() {
  375.         ClientCapabilityInfo cap;
  376.         ClientCapability *c;
  377.         ModDataInfo mreq;
  378.        
  379.         MARK_AS_OFFICIAL_MODULE(modinfo);
  380.         MARK_AS_GLOBAL_MODULE(modinfo);
  381.  
  382.         memset(&cap, 0, sizeof(cap));
  383.         cap.name = "draft/metadata-2";
  384.         cap.parameter = metadata_cap_param;
  385.         c = ClientCapabilityAdd(modinfo->handle, &cap, &CAP_METADATA);
  386.        
  387.         memset(&cap, 0, sizeof(cap));
  388.         cap.name = "draft/metadata-notify-2"; /* for old client compatibility */
  389.         c = ClientCapabilityAdd(modinfo->handle, &cap, &CAP_METADATA_NOTIFY);
  390.        
  391.         CommandAdd(modinfo->handle, "METADATA", cmd_metadata, MAXPARA, CMD_USER|CMD_SERVER|CMD_UNREGISTERED);
  392.        
  393.         memset(&mreq, 0 , sizeof(mreq));
  394.         mreq.type = MODDATATYPE_CLIENT;
  395.         mreq.name = "metadata_user",
  396.         mreq.free = metadata_user_free;
  397.         metadataUser = ModDataAdd(modinfo->handle, mreq);
  398.         if (!metadataUser)
  399.         {
  400.                 config_error("[%s] Failed to request metadata_user moddata: %s", MOD_HEADER.name, ModuleGetErrorStr(modinfo->handle));
  401.                 return MOD_FAILED;
  402.         }
  403.        
  404.         memset(&mreq, 0 , sizeof(mreq));
  405.         mreq.type = MODDATATYPE_CHANNEL;
  406.         mreq.name = "metadata_channel",
  407.         mreq.free = metadata_channel_free;
  408.         metadataChannel = ModDataAdd(modinfo->handle, mreq);
  409.         if (!metadataChannel)
  410.         {
  411.                 config_error("[%s] Failed to request metadata_channel moddata: %s", MOD_HEADER.name, ModuleGetErrorStr(modinfo->handle));
  412.                 return MOD_FAILED;
  413.         }
  414.        
  415.         HookAdd(modinfo->handle, HOOKTYPE_SERVER_SYNC, 0, metadata_server_sync);
  416.         HookAdd(modinfo->handle, HOOKTYPE_LOCAL_JOIN, -2, metadata_join);
  417.         HookAdd(modinfo->handle, HOOKTYPE_REMOTE_JOIN, -2, metadata_join);
  418.         HookAdd(modinfo->handle, HOOKTYPE_LOCAL_CONNECT, 0, metadata_user_registered);
  419.         HookAdd(modinfo->handle, HOOKTYPE_LOCAL_CONNECT, 0, metadata_monitor_connect);
  420.         HookAdd(modinfo->handle, HOOKTYPE_REMOTE_CONNECT, 0, metadata_monitor_connect);
  421.  
  422.         HookAdd(modinfo->handle, HOOKTYPE_CONFIGRUN, 0, metadata_configrun);
  423.        
  424.         return MOD_SUCCESS;
  425. }
  426.  
  427. MOD_LOAD() {
  428.         /* setting default values if not configured */
  429.         if (metadata_settings.max_user_metadata == 0)
  430.                 metadata_settings.max_user_metadata = 10;
  431.         if (metadata_settings.max_channel_metadata == 0)
  432.                 metadata_settings.max_channel_metadata = 10;
  433.         if (metadata_settings.max_subscriptions == 0)
  434.                 metadata_settings.max_subscriptions = 10;
  435.         if (metadata_settings.max_value_bytes == 0)
  436.                 metadata_settings.max_value_bytes = 300;
  437.  
  438.         EventAdd(modinfo->handle, "metadata_queue", metadata_queue_evt, NULL, 1500, 0);
  439.         ISupportAdd(modinfo->handle, "METADATA", metadata_isupport_param());
  440.         return MOD_SUCCESS;
  441. }
  442.  
  443. MOD_UNLOAD() {
  444.         return MOD_SUCCESS;
  445. }
  446.  
  447. const char *metadata_cap_param(Client *client)
  448. {
  449.         static char buf[80];
  450.         ircsnprintf(buf, sizeof(buf), "before-connect,max-subs=%d,max-keys=%d,max-value-bytes=%d",
  451.                 metadata_settings.max_subscriptions, metadata_settings.max_user_metadata, metadata_settings.max_value_bytes);
  452.         return buf;
  453. }
  454.  
  455. char *metadata_isupport_param(void)
  456. {
  457.         static char buf[20];
  458.         ircsnprintf(buf, sizeof(buf), "%d", metadata_settings.max_user_metadata);
  459.         return buf;
  460. }
  461.  
  462. void metadata_free(struct metadata *metadata)
  463. {
  464.         safe_free(metadata->name);
  465.         safe_free(metadata->value);
  466.         safe_free(metadata);
  467. }
  468.  
  469. void metadata_free_subs(struct metadata_subscriptions *subs)
  470. {
  471.         safe_free(subs->name);
  472.         safe_free(subs);
  473. }
  474.  
  475. int metadata_is_subscribed(Client *user, const char *key)
  476. {
  477.         struct metadata_moddata_user *moddata = USER_METADATA(user);
  478.         if (!moddata)
  479.                 return 0;
  480.         struct metadata_subscriptions *subs;
  481.         for (subs = moddata->subs; subs; subs = subs->next)
  482.         {
  483.                 if (!strcasecmp(subs->name, key))
  484.                         return 1;
  485.         }
  486.         return 0;
  487. }
  488.  
  489. const char *metadata_get_user_key_value(Client *user, const char *key)
  490. {
  491.         struct metadata_moddata_user *moddata = USER_METADATA(user);
  492.         struct metadata *metadata = NULL;
  493.         if (!moddata)
  494.                 return NULL;
  495.         for (metadata = moddata->metadata; metadata; metadata = metadata->next)
  496.         {
  497.                 if (!strcasecmp(key, metadata->name))
  498.                         return metadata->value;
  499.         }
  500.         return NULL;
  501. }
  502.  
  503. const char *metadata_get_channel_key_value(Channel *channel, const char *key)
  504. {
  505.         struct metadata *metadata;
  506.         for (metadata = CHANNEL_METADATA(channel); metadata; metadata = metadata->next)
  507.         {
  508.                 if (!strcasecmp(key, metadata->name))
  509.                         return metadata->value;
  510.         }
  511.         return NULL;
  512. }
  513.  
  514. /* returns 1 if something remains to sync */
  515. int metadata_notify_or_queue(Client *client, MessageTag *mtags, const char *who, const char *key, const char *value, Client *changer)
  516. {
  517.         int trylater = 0;
  518.         if (!who)
  519.         {
  520.                 unreal_log(ULOG_DEBUG, "metadata", "METADATA_DEBUG", changer, "metadata_notify_or_queue called with null who!");
  521.                 return 0;
  522.         }
  523.         if (!key)
  524.         {
  525.                 unreal_log(ULOG_DEBUG, "metadata", "METADATA_DEBUG", changer, "metadata_notify_or_queue called with null key!");
  526.                 return 0;
  527.         }
  528.         if (!client)
  529.         {
  530.                 unreal_log(ULOG_DEBUG, "metadata", "METADATA_DEBUG", changer, "metadata_notify_or_queue called with null client!");
  531.                 return 0;
  532.         }
  533.  
  534.         struct metadata_moddata_user *moddata = USER_METADATA(client);
  535.         if (!moddata)
  536.                 moddata = metadata_prepare_user_moddata(client);
  537.         struct metadata_unsynced **us = &moddata->us;
  538.  
  539.         if (IsSendable(client))
  540.         {
  541.                 metadata_send_change(client, mtags, who, key, value, changer);
  542.         } else
  543.         { /* store for the SYNC */
  544.                 Client *who_client;
  545.                 const char *uid_or_channel;
  546.                 if (*who == '#') {
  547.                         uid_or_channel = who;
  548.                 } else {
  549.                         who_client = find_client(who, NULL); /* FIXME the caller should already have this figured out */
  550.                         if (!who_client) {
  551.                                 unreal_log(ULOG_DEBUG, "metadata", "METADATA_DEBUG", changer, "metadata_notify_or_queue called with nonexistent client!");
  552.                                 return 0; /* shouldn't happen */
  553.                         }
  554.                         uid_or_channel = who_client->id;
  555.                 }
  556.                        
  557.                 trylater = 1;
  558.                 while (*us)
  559.                         us = &(*us)->next; /* find last list element */
  560.                 *us = safe_alloc(sizeof(struct metadata_unsynced));
  561.                 (*us)->id = strdup(uid_or_channel);
  562.                 (*us)->key = strdup(key);
  563.                 (*us)->next = NULL;
  564.         }
  565.         return trylater;
  566. }
  567.  
  568. void metadata_send_change(Client *client, MessageTag *mtags, const char *who, const char *key, const char *value, Client *changer)
  569. {
  570.         char *sender = NULL;
  571.         if (!key)
  572.         {
  573.                 unreal_log(ULOG_DEBUG, "metadata", "METADATA_DEBUG", changer, "metadata_send_change called with null key!");
  574.                 return;
  575.         }
  576.         if (!who)
  577.         {
  578.                 unreal_log(ULOG_DEBUG, "metadata", "METADATA_DEBUG", changer, "metadata_send_change called with null who!");
  579.                 return;
  580.         }
  581.         if (!client)
  582.         {
  583.                 unreal_log(ULOG_DEBUG, "metadata", "METADATA_DEBUG", changer, "metadata_send_change called with null client!");
  584.                 return;
  585.         }
  586.         if (changer)
  587.         {
  588.                 if (IsServer(client))
  589.                         sender = changer->id;
  590.                 else
  591.                         sender = changer->name;
  592.         }
  593.         if (!sender)
  594.                 sender = me.name;
  595.         if (changer && IsUser(changer) && MyUser(client))
  596.         {
  597.                 if (!value)
  598.                         sendto_one(client, mtags, ":%s!%s@%s METADATA %s %s %s", sender, changer->user->username, GetHost(changer), who, key, "*");
  599.                 else
  600.                         sendto_one(client, mtags, ":%s!%s@%s METADATA %s %s %s :%s", sender, changer->user->username, GetHost(changer), who, key, "*", value);
  601.         } else
  602.         { /* sending S2S (sender is id) or receiving S2S (sender is servername) */
  603.                 if (!value)
  604.                         sendto_one(client, mtags, ":%s METADATA %s %s %s", sender, who, key, "*");
  605.                 else
  606.                         sendto_one(client, mtags, ":%s METADATA %s %s %s :%s", sender, who, key, "*", value);
  607.         }
  608. }
  609.  
  610. /* used for broadcasting changes to subscribed users and linked servers */
  611. void user_metadata_changed(Client *user, const char *key, const char *value, Client *changer){
  612.         Client *acptr;
  613.         if (!user || !key)
  614.                 return; /* sanity check */
  615.         list_for_each_entry(acptr, &lclient_list, lclient_node)
  616.         { /* notifications for local subscribers */
  617.                 if(IsUser(acptr) && IsUser(user) && metadata_is_subscribed(acptr, key) && has_common_channels(user, acptr))
  618.                         metadata_notify_or_queue(acptr, NULL, user->name, key, value, changer);
  619.         }
  620.  
  621.         list_for_each_entry(acptr, &server_list, special_node)
  622.         { /* notifications for linked servers, TODO change to sendto_server */
  623.                 if (acptr == &me)
  624.                         continue;
  625.                 metadata_send_change(acptr, NULL, user->name, key, value, changer);
  626.         }
  627.         /* notifications for MONITOR */
  628.         watch_check(user, WATCH_EVENT_METADATA, metadata_monitor_notification); /* for now sending info for all entries even if only one has changed */
  629. }
  630.  
  631. void channel_metadata_changed(Channel *channel, const char *key, const char *value, Client *changer)
  632. {
  633.         Client *acptr;
  634.         if (!channel || !key)
  635.                 return; /* sanity check */
  636.         list_for_each_entry(acptr, &lclient_list, lclient_node)
  637.         { /* notifications for local subscribers */
  638.                 if (metadata_is_subscribed(acptr, key) && IsMember(acptr, channel))
  639.                         metadata_send_change(acptr, NULL, channel->name, key, value, changer);
  640.         }
  641.        
  642.         list_for_each_entry(acptr, &server_list, special_node)
  643.         { /* notifications for linked servers, TODO change to sendto_server */
  644.                 if(acptr == &me)
  645.                         continue;
  646.                 metadata_send_change(acptr, NULL, channel->name, key, value, changer);
  647.         }
  648. }
  649.  
  650. void metadata_free_list(struct metadata *metadata, const char *whose, Client *client)
  651. {
  652.         struct metadata *prev_metadata = metadata;
  653.         char *name;
  654.         while(metadata)
  655.         {
  656.                 name = metadata->name;
  657.                 safe_free(metadata->value);
  658.                 metadata = metadata->next;
  659.                 safe_free(prev_metadata);
  660.                 prev_metadata = metadata;
  661.                 if(client && whose && *whose)
  662.                 { /* send out the data being removed, unless we're unloading the module */
  663.                         sendnumeric(client, RPL_KEYVALUE, whose, name, "*", "");
  664.                         if(*whose == '#')
  665.                                 channel_metadata_changed(find_channel(whose), name, NULL, client);
  666.                         else
  667.                                 user_metadata_changed(hash_find_nickatserver(whose, NULL), name, NULL, client);
  668.                 }
  669.                 safe_free(name);
  670.         }
  671. }
  672.  
  673. void metadata_channel_free(ModData *md)
  674. {
  675.         if (!md->ptr)
  676.                 return; /* was not set */
  677.         struct metadata *metadata = md->ptr;
  678.         metadata_free_list(metadata, NULL, NULL);
  679. }
  680.  
  681. void metadata_user_free(ModData *md)
  682. {
  683.         struct metadata_moddata_user *moddata = md->ptr;
  684.         if (!moddata)
  685.                 return; /* was not set */
  686.         struct metadata_subscriptions *sub = moddata->subs;
  687.         struct metadata_subscriptions *prev_sub = sub;
  688.         struct metadata_unsynced *us = moddata->us;
  689.         struct metadata_unsynced *prev_us;
  690.         while (sub)
  691.         {
  692.                 safe_free(sub->name);
  693.                 sub = sub->next;
  694.                 safe_free(prev_sub);
  695.                 prev_sub = sub;
  696.         }
  697.         struct metadata *metadata = moddata->metadata;
  698.         metadata_free_list(metadata, NULL, NULL);
  699.         while (us)
  700.         {
  701.                 safe_free(us->id);
  702.                 safe_free(us->key);
  703.                 prev_us = us;
  704.                 us = us->next;
  705.                 safe_free(prev_us);
  706.         }
  707.         safe_free(moddata);
  708. }
  709.  
  710. struct metadata_moddata_user *metadata_prepare_user_moddata(Client *user)
  711. {
  712.         USER_METADATA(user) = safe_alloc(sizeof(struct metadata_moddata_user));
  713.         struct metadata_moddata_user *ptr = USER_METADATA(user);
  714.         ptr->metadata = NULL;
  715.         ptr->subs = NULL;
  716.         return ptr;
  717. }
  718.  
  719. void metadata_set_user(Client *user, const char *key, const char *value, Client *client)
  720. {
  721.         int changed = 0;
  722.         Client *target;
  723.         char *target_name;
  724.         int removed = 0;
  725.         int set = 0;
  726.         int count = 0;
  727.  
  728.         if (user)
  729.         {
  730.                 target = user;
  731.                 target_name = user->name;
  732.         } else
  733.         {
  734.                 target = client;
  735.                 target_name = "*";
  736.         }
  737.                
  738.         struct metadata_moddata_user *moddata = USER_METADATA(target);
  739.         if (!moddata) /* first call for this user */
  740.                 moddata = metadata_prepare_user_moddata(target);
  741.         struct metadata **metadata = &moddata->metadata;
  742.         struct metadata *prev;
  743.        
  744.         if (value && strlen(value) > metadata_settings.max_value_bytes)
  745.         {
  746.                 if (client)
  747.                         sendto_one(client, NULL, ":%s FAIL METADATA VALUE_INVALID %s :metadata value too long", me.name, target_name);
  748.                 return;
  749.         }
  750.         if (BadPtr(value) || strlen(value) == 0)
  751.         { /* unset */
  752.                 value = NULL; /* just to make sure */
  753.                 removed = 0;
  754.                 while (*metadata)
  755.                 {
  756.                         if (!strcasecmp(key, (*metadata)->name))
  757.                                 break;
  758.                         metadata = &(*metadata)->next;
  759.                 }
  760.                 if (*metadata)
  761.                 {
  762.                         prev = *metadata;
  763.                         *metadata = prev->next;
  764.                         metadata_free(prev);
  765.                         removed = 1;
  766.                         changed = 1;
  767.                 }
  768.                 if (!removed)
  769.                 {
  770.                         if (client)
  771.                                 sendto_one(client, NULL, ":%s FAIL METADATA KEY_NOT_SET %s %s :key not set", me.name, target_name, key); /* not set so can't remove */
  772.                         return;
  773.                 }
  774.         } else
  775.         { /* set */
  776.                 while (*metadata)
  777.                 {
  778.                         if (!strcasecmp(key, (*metadata)->name))
  779.                         {
  780.                                 set = 1;
  781.                                 if (strcmp(value, (*metadata)->value))
  782.                                 {
  783.                                         safe_free((*metadata)->value);
  784.                                         (*metadata)->value = strdup(value);
  785.                                         changed = 1;
  786.                                 }
  787.                         }
  788.                         metadata = &(*metadata)->next;
  789.                         count++;
  790.                 }
  791.                 if (!set)
  792.                 {
  793.                         if (!client || count < metadata_settings.max_user_metadata)
  794.                         { /* add new entry for user */
  795.                                 *metadata = safe_alloc(sizeof(struct metadata));
  796.                                 (*metadata)->next = NULL;
  797.                                 (*metadata)->name = strdup(key);
  798.                                 (*metadata)->value = strdup(value);
  799.                                 changed = 1;
  800.                         } else
  801.                         { /* no more allowed */
  802.                                 if (client)
  803.                                         sendto_one(client, NULL, ":%s FAIL METADATA LIMIT_REACHED %s :metadata limit reached", me.name, target_name);
  804.                                 return;
  805.                         }
  806.                 }
  807.         }
  808.         if (!IsServer(client) && MyConnect(client))
  809.                 sendnumeric(client, RPL_KEYVALUE, target_name, key, "*", value?value:""); /* all OK */
  810.         if (changed && (client == &me || IsUser(client) || IsServer(client)))
  811.                 user_metadata_changed(target, key, value, client);
  812. }
  813.  
  814. void metadata_set_channel(Channel *channel, const char *key, const char *value, Client *client)
  815. {
  816.         int changed = 0;
  817.         int set = 0;
  818.         int count = 0;
  819.         struct metadata **metadata = (struct metadata **)&CHANNEL_METADATA(channel);
  820.         struct metadata *prev;
  821.  
  822.         if (value && strlen(value) > metadata_settings.max_value_bytes)
  823.         {
  824.                 if (client)
  825.                         sendto_one(client, NULL, ":%s FAIL METADATA VALUE_INVALID %s :metadata value too long", me.name, channel->name);
  826.                 return;
  827.         }
  828.  
  829.         if(BadPtr(value) || strlen(value) == 0)
  830.         { /* unset */
  831.                 value = NULL; /* just to make sure */
  832.                 int removed = 0;
  833.                 while (*metadata)
  834.                 {
  835.                         if (!strcasecmp(key, (*metadata)->name))
  836.                                 break;
  837.                         metadata = &(*metadata)->next;
  838.                 }
  839.                 if (*metadata)
  840.                 {
  841.                         prev = *metadata;
  842.                         *metadata = prev->next;
  843.                         metadata_free(prev);
  844.                         removed = 1;
  845.                         changed = 1;
  846.                 }
  847.                 if (!removed)
  848.                 {
  849.                         if (client)
  850.                                 sendto_one(client, NULL, ":%s FAIL METADATA KEY_NOT_SET %s %s :key not set", me.name, channel->name, key); /* not set so can't remove */
  851.                         return;
  852.                 }
  853.         } else { /* set */
  854.                 while (*metadata)
  855.                 {
  856.                         if (!strcasecmp(key, (*metadata)->name))
  857.                         {
  858.                                 set = 1;
  859.                                 if (strcmp(value, (*metadata)->value))
  860.                                 {
  861.                                         safe_free((*metadata)->value);
  862.                                         (*metadata)->value = strdup(value);
  863.                                         changed = 1;
  864.                                 }
  865.                         }
  866.                         metadata = &(*metadata)->next;
  867.                         count++;
  868.                 }
  869.                 if (!set)
  870.                 {
  871.                         if (!client || count < metadata_settings.max_channel_metadata)
  872.                         { /* add new entry for user */
  873.                                 *metadata = safe_alloc(sizeof(struct metadata));
  874.                                 (*metadata)->next = NULL;
  875.                                 (*metadata)->name = strdup(key);
  876.                                 (*metadata)->value = strdup(value);
  877.                                 changed = 1;
  878.                         } else
  879.                         { /* no more allowed */
  880.                                 if (client)
  881.                                         sendto_one(client, NULL, ":%s FAIL METADATA LIMIT_REACHED %s :metadata limit reached", me.name, channel->name);
  882.                                 return;
  883.                         }
  884.                 }
  885.         }
  886.         if (IsUser(client) && MyUser(client))
  887.                 sendnumeric(client, RPL_KEYVALUE, channel->name, key, "*", value?value:""); /* all OK */
  888.         if (changed && (IsUser(client) || IsServer(client)))
  889.                 channel_metadata_changed(channel, key, value, client);
  890. }
  891.  
  892. int metadata_subscribe(const char *key, Client *client, int remove)
  893. {
  894.         struct metadata_moddata_user *moddata = USER_METADATA(client);
  895.         struct metadata_subscriptions **subs;
  896.         struct metadata_subscriptions *prev_subs;
  897.         int found = 0;
  898.         int count = 0;
  899.         int trylater = 0;
  900.         const char *value;
  901.         unsigned int hashnum;
  902.         Channel *channel;
  903.         Client *acptr;
  904.         char batch[BATCHLEN+1] = "";
  905.         MessageTag *mtags = NULL;
  906.  
  907.         if (!client)
  908.                 return 0;
  909.        
  910.         if (!moddata) /* first call for this user */
  911.                 moddata = metadata_prepare_user_moddata(client);
  912.         subs = &moddata->subs;
  913.         while (*subs)
  914.         {
  915.                 count++;
  916.                 if (!strcasecmp(key, (*subs)->name))
  917.                 {
  918.                         found = 1;
  919.                         if (remove)
  920.                         {
  921.                                 prev_subs = *subs;
  922.                                 *subs = prev_subs->next;
  923.                                 metadata_free_subs(prev_subs);
  924.                         }
  925.                         break;
  926.                 }
  927.                 subs = &(*subs)->next;
  928.         }
  929.         if (!remove && !found)
  930.         {
  931.                 if (count < metadata_settings.max_subscriptions)
  932.                 {
  933.                         *subs = safe_alloc(sizeof(struct metadata_subscriptions));
  934.                         (*subs)->next = NULL;
  935.                         (*subs)->name = strdup(key);
  936.                 } else
  937.                 { /* no more allowed */
  938.                         sendto_one(client, NULL, ":%s FAIL METADATA TOO_MANY_SUBS %s :too many subscriptions", me.name, key);
  939.                         return 0;
  940.                 }
  941.         }
  942.         if (!remove)
  943.         {
  944.                 if (HasCapability(client, "batch")) {
  945.                         generate_batch_id(batch);
  946.                         sendto_one(client, NULL, ":%s BATCH +%s metadata", me.name, batch);
  947.                         mtags = safe_alloc(sizeof(MessageTag));
  948.                         mtags->name = strdup("batch");
  949.                         mtags->value = strdup(batch);
  950.                 }
  951.                 sendnumeric_mtags(client, mtags, RPL_METADATASUBOK, key);
  952.                 if(!IsUser(client))
  953.                         return 0; /* unregistered user is not getting any keys yet */
  954.                 /* we have to send out all subscribed data now */
  955.                 trylater = 0;
  956.                 list_for_each_entry(acptr, &client_list, client_node)
  957.                 {
  958.                         value = NULL;
  959.                         if (IsUser(client) && IsUser(acptr) && has_common_channels(acptr, client))
  960.                                 value = metadata_get_user_key_value(acptr, key);
  961.                         if (value)
  962.                                 trylater |= metadata_notify_or_queue(client, mtags, acptr->name, key, value, NULL);
  963.                 }
  964.                 for (hashnum = 0; hashnum < CHAN_HASH_TABLE_SIZE; hashnum++)
  965.                 {
  966.                         for (channel = hash_get_chan_bucket(hashnum); channel; channel = channel->hnextch)
  967.                         {
  968.                                 if (IsMember(client, channel))
  969.                                 {
  970.                                         value = metadata_get_channel_key_value(channel, key);
  971.                                         if (value)
  972.                                                 trylater |= metadata_notify_or_queue(client, mtags, channel->name, key, value, NULL);
  973.                                 }
  974.                         }
  975.                 }
  976.                 if (*batch)
  977.                         sendto_one(client, NULL, ":%s BATCH -%s", me.name, batch);
  978.                 if (mtags)
  979.                         free_message_tags(mtags);
  980.                 if (trylater)
  981.                         return 1;
  982.         } else
  983.         {
  984.                 sendnumeric(client, RPL_METADATAUNSUBOK, key); 
  985.         }
  986.         return 0;
  987. }
  988.  
  989. void metadata_send_channel(Channel *channel, const char *key, Client *client)
  990. {
  991.         struct metadata *metadata;
  992.         int found = 0;
  993.         char batch[BATCHLEN+1] = "";
  994.         MessageTag *mtags = NULL;
  995.         if (HasCapability(client, "batch")) {
  996.                 generate_batch_id(batch);
  997.                 sendto_one(client, NULL, ":%s BATCH +%s metadata", me.name, batch);
  998.                 mtags = safe_alloc(sizeof(MessageTag));
  999.                 mtags->name = strdup("batch");
  1000.                 mtags->value = strdup(batch);
  1001.         }
  1002.         for (metadata = CHANNEL_METADATA(channel); metadata; metadata = metadata->next)
  1003.         {
  1004.                 if (!strcasecmp(key, metadata->name))
  1005.                 {
  1006.                         found = 1;
  1007.                         sendnumeric_mtags(client, mtags, RPL_KEYVALUE, channel->name, key, "*", metadata->value);
  1008.                         break;
  1009.                 }
  1010.         }
  1011.         if (!found)
  1012.                 sendto_one(client, mtags, ":%s FAIL METADATA KEY_NOT_SET %s %s :key not set", me.name, channel->name, key);
  1013.         if (*batch)
  1014.                 sendto_one(client, NULL, ":%s BATCH -%s", me.name, batch);
  1015.         if (mtags)
  1016.                 free_message_tags(mtags);
  1017. }
  1018.  
  1019. void metadata_send_user(Client *user, const char *key, Client *client)
  1020. {
  1021.         if (!user)
  1022.                 user = client;
  1023.         struct metadata_moddata_user *moddata = USER_METADATA(user);
  1024.         struct metadata *metadata = NULL;
  1025.         char batch[BATCHLEN+1] = "";
  1026.         MessageTag *mtags = NULL;
  1027.         if (HasCapability(client, "batch")) {
  1028.                 generate_batch_id(batch);
  1029.                 sendto_one(client, NULL, ":%s BATCH +%s metadata", me.name, batch);
  1030.                 mtags = safe_alloc(sizeof(MessageTag));
  1031.                 mtags->name = strdup("batch");
  1032.                 mtags->value = strdup(batch);
  1033.         }
  1034.         if (moddata)
  1035.                 metadata = moddata->metadata;
  1036.         int found = 0;
  1037.         for ( ; metadata; metadata = metadata->next)
  1038.         {
  1039.                 if (!strcasecmp(key, metadata->name))
  1040.                 {
  1041.                         found = 1;
  1042.                         sendnumeric_mtags(client, mtags, RPL_KEYVALUE, user->name, key, "*", metadata->value);
  1043.                         break;
  1044.                 }
  1045.         }
  1046.         if (!found)
  1047.                 sendto_one(client, mtags, ":%s FAIL METADATA KEY_NOT_SET %s %s :key not set", me.name, user->name, key);
  1048.         if (*batch)
  1049.                 sendto_one(client, NULL, ":%s BATCH -%s", me.name, batch);
  1050.         if (mtags)
  1051.                 free_message_tags(mtags);
  1052. }
  1053.  
  1054. void metadata_clear_channel(Channel *channel, Client *client)
  1055. {
  1056.         struct metadata *metadata = CHANNEL_METADATA(channel);
  1057.         metadata_free_list(metadata, channel->name, client);
  1058.         CHANNEL_METADATA(channel) = NULL;
  1059. }
  1060.  
  1061. void metadata_clear_user(Client *user, Client *client)
  1062. {
  1063.         if (!user)
  1064.                 user = client;
  1065.         struct metadata_moddata_user *moddata = USER_METADATA(user);
  1066.         struct metadata *metadata = NULL;
  1067.         if (!moddata)
  1068.                 return; /* nothing to delete */
  1069.         metadata = moddata->metadata;
  1070.         metadata_free_list(metadata, user->name, client);
  1071.         moddata->metadata = NULL;
  1072. }
  1073.  
  1074. void metadata_send_subscribtions(Client *client)
  1075. {
  1076.         struct metadata_subscriptions *subs;
  1077.         struct metadata_moddata_user *moddata = USER_METADATA(client);
  1078.         char batch[BATCHLEN+1] = "";
  1079.         MessageTag *mtags = NULL;
  1080.         if (HasCapability(client, "batch")) {
  1081.                 generate_batch_id(batch);
  1082.                 sendto_one(client, NULL, ":%s BATCH +%s metadata", me.name, batch);
  1083.                 mtags = safe_alloc(sizeof(MessageTag));
  1084.                 mtags->name = strdup("batch");
  1085.                 mtags->value = strdup(batch);
  1086.         }
  1087.         if (moddata) {
  1088.                 for (subs = moddata->subs; subs; subs = subs->next)
  1089.                         sendnumeric_mtags(client, mtags, RPL_METADATASUBS, subs->name);
  1090.         }
  1091.         if (*batch)
  1092.                 sendto_one(client, NULL, ":%s BATCH -%s", me.name, batch);
  1093.         if (mtags)
  1094.                 free_message_tags(mtags);
  1095. }
  1096.  
  1097. void metadata_send_all_for_channel(Channel *channel, Client *client)
  1098. {
  1099.         struct metadata *metadata;
  1100.         char batch[BATCHLEN+1] = "";
  1101.         MessageTag *mtags = NULL;
  1102.         if (HasCapability(client, "batch")) {
  1103.                 generate_batch_id(batch);
  1104.                 sendto_one(client, NULL, ":%s BATCH +%s metadata", me.name, batch);
  1105.                 mtags = safe_alloc(sizeof(MessageTag));
  1106.                 mtags->name = strdup("batch");
  1107.                 mtags->value = strdup(batch);
  1108.         }
  1109.         for (metadata = CHANNEL_METADATA(channel); metadata; metadata = metadata->next)
  1110.                 sendnumeric_mtags(client, mtags, RPL_KEYVALUE, channel->name, metadata->name, "*", metadata->value);
  1111.         if (*batch)
  1112.                 sendto_one(client, NULL, ":%s BATCH -%s", me.name, batch);
  1113.         if (mtags)
  1114.                 free_message_tags(mtags);
  1115. }
  1116.  
  1117. void metadata_send_all_for_user(Client *user, Client *client)
  1118. {
  1119.         struct metadata *metadata;
  1120.         char batch[BATCHLEN+1] = "";
  1121.         MessageTag *mtags = NULL;
  1122.         if (!user)
  1123.                 user = client;
  1124.         struct metadata_moddata_user *moddata = USER_METADATA(user);
  1125.         if (HasCapability(client, "batch")) {
  1126.                 generate_batch_id(batch);
  1127.                 sendto_one(client, NULL, ":%s BATCH +%s metadata", me.name, batch);
  1128.                 mtags = safe_alloc(sizeof(MessageTag));
  1129.                 mtags->name = strdup("batch");
  1130.                 mtags->value = strdup(batch);
  1131.         }
  1132.         if (moddata) {
  1133.                 for (metadata = moddata->metadata; metadata; metadata = metadata->next)
  1134.                         sendnumeric_mtags(client, mtags, RPL_KEYVALUE, user->name, metadata->name, "*", metadata->value);
  1135.         }
  1136.         if (*batch)
  1137.                 sendto_one(client, NULL, ":%s BATCH -%s", me.name, batch);
  1138.         if (mtags)
  1139.                 free_message_tags(mtags);
  1140. }
  1141.  
  1142. int metadata_key_valid(const char *key)
  1143. {
  1144.         for( ; *key; key++)
  1145.         {
  1146.                 if(*key >= 'a' && *key <= 'z')
  1147.                         continue;
  1148.                 if(*key >= 'A' && *key <= 'Z')
  1149.                         continue;
  1150.                 if(*key >= '0' && *key <= '9')
  1151.                         continue;
  1152.                 if(*key == '_' || *key == '.' || *key == ':' || *key == '-')
  1153.                         continue;
  1154.                 return 0;
  1155.         }
  1156.         return 1;
  1157. }
  1158.  
  1159. int metadata_check_perms(Client *user, Channel *channel, Client *client, const char *key, int mode)
  1160. { /* either user or channel should be NULL */
  1161.         if (!IsUser(client) && channel) /* ignore channel metadata requests for unregistered users */
  1162.                 return 0;
  1163.         if ((user == client) || (!user && !channel)) /* specified target is "*" or own nick */
  1164.                 return 1;
  1165.         if (IsOper(client) && mode == MODE_GET)
  1166.                 return 1; /* allow ircops to view everything */
  1167.         if (channel)
  1168.         {
  1169.                 /* The only requirement for GET is to be in the channel */
  1170.                 if ((mode == MODE_GET) && IsMember(client, channel))
  1171.                         return 1;
  1172.                 /* Otherwise, +hoaq */
  1173.                 if (check_channel_access(client, channel, "hoaq"))
  1174.                         return 1;
  1175.         } else if (user)
  1176.         {
  1177.                 if (mode == MODE_SET)
  1178.                 {
  1179.                         if (user == client)
  1180.                                 return 1;
  1181.                 } else if (mode == MODE_GET)
  1182.                 {
  1183.                         if(has_common_channels(user, client))
  1184.                                 return 1;
  1185.                 }
  1186.                
  1187.         }
  1188.         if (key)
  1189.                 sendto_one(client, NULL, ":%s FAIL METADATA KEY_NO_PERMISSION %s %s :permission denied", me.name, user?user->name:channel->name, key);
  1190.         return 0;
  1191. }
  1192.  
  1193. /* METADATA <Target> <Subcommand> [<Param 1> ... [<Param n>]] */
  1194. CMD_FUNC(cmd_metadata_local)
  1195. {
  1196.         Channel *channel = NULL;
  1197.         Client *user = NULL;
  1198.         const char *target;
  1199.         const char *cmd;
  1200.         const char *key;
  1201.         const char *value = NULL;
  1202.         int keyindex = 3-1;
  1203.         char *channame;
  1204.  
  1205.         CHECKPARAMSCNT_OR_DIE(2, return);
  1206.  
  1207.         target = parv[1];
  1208.         cmd = parv[2];
  1209.  
  1210.         if (!strcasecmp(cmd, "GET"))
  1211.         {
  1212.                 CHECKREGISTERED_OR_DIE(client, return);
  1213.                 CHECKPARAMSCNT_OR_DIE(3, return);
  1214.                 PROCESS_TARGET_OR_DIE(target, user, channel, return);
  1215.                 FOR_EACH_KEY(keyindex, parc, parv)
  1216.                 {
  1217.                         if (metadata_check_perms(user, channel, client, key, MODE_GET))
  1218.                         {
  1219.                                 if (!metadata_key_valid(key))
  1220.                                 {
  1221.                                         sendto_one(client, NULL, ":%s FAIL METADATA KEY_INVALID %s :invalid key", me.name,  key);
  1222.                                         continue;
  1223.                                 }
  1224.                                 if (channel)
  1225.                                         metadata_send_channel(channel, key, client);
  1226.                                 else
  1227.                                         metadata_send_user(user, key, client);
  1228.                         }
  1229.                 }
  1230.         } else if (!strcasecmp(cmd, "LIST"))
  1231.         { /* we're just not sending anything if there are no permissions */
  1232.                 CHECKREGISTERED_OR_DIE(client, return);
  1233.                 PROCESS_TARGET_OR_DIE(target, user, channel, return);
  1234.                 if (metadata_check_perms(user, channel, client, NULL, MODE_GET))
  1235.                 {
  1236.                         if (channel)
  1237.                                 metadata_send_all_for_channel(channel, client);
  1238.                         else
  1239.                                 metadata_send_all_for_user(user, client);
  1240.                 }
  1241.         } else if (!strcasecmp(cmd, "SET"))
  1242.         {
  1243.                 CHECKPARAMSCNT_OR_DIE(3, return);
  1244.                 PROCESS_TARGET_OR_DIE(target, user, channel, return);
  1245.                 key = parv[3];
  1246.                 if (!metadata_check_perms(user, channel, client, key, MODE_SET))
  1247.                         return;
  1248.                 if (parc > 3 && !BadPtr(parv[4]))
  1249.                         value = parv[4];
  1250.  
  1251.                 if (!metadata_key_valid(key))
  1252.                 {
  1253.                         sendto_one(client, NULL, ":%s FAIL METADATA KEY_INVALID %s :invalid key", me.name,  key);
  1254.                         return;
  1255.                 }
  1256.  
  1257.                 if (channel)
  1258.                         metadata_set_channel(channel, key, value, client);
  1259.                 else
  1260.                         metadata_set_user(user, key, value, client);
  1261.         } else if (!strcasecmp(cmd, "CLEAR"))
  1262.         {
  1263.                 CHECKREGISTERED_OR_DIE(client, return);
  1264.                 PROCESS_TARGET_OR_DIE(target, user, channel, return);
  1265.                 if (metadata_check_perms(user, channel, client, "*", MODE_SET))
  1266.                 {
  1267.                         if (channel)
  1268.                                 metadata_clear_channel(channel, client);
  1269.                         else
  1270.                                 metadata_clear_user(user, client);
  1271.                 }
  1272.         } else if (!strcasecmp(cmd, "SUB"))
  1273.         {
  1274.                 PROCESS_TARGET_OR_DIE(target, user, channel, return);
  1275.                 CHECKPARAMSCNT_OR_DIE(3, return);
  1276.                 FOR_EACH_KEY(keyindex, parc, parv)
  1277.                 {
  1278.                         if(metadata_key_valid(key))
  1279.                         {
  1280.                                 metadata_subscribe(key, client, 0);
  1281.                         } else
  1282.                         {
  1283.                                 sendto_one(client, NULL, ":%s FAIL METADATA KEY_INVALID %s :invalid key", me.name,  key);
  1284.                                 continue;
  1285.                         }
  1286.                 }
  1287.         } else if (!strcasecmp(cmd, "UNSUB"))
  1288.         {
  1289.                 CHECKREGISTERED_OR_DIE(client, return);
  1290.                 CHECKPARAMSCNT_OR_DIE(3, return);
  1291.                 int subok = 0;
  1292.                 FOR_EACH_KEY(keyindex, parc, parv)
  1293.                 {
  1294.                         if(metadata_key_valid(key))
  1295.                         {
  1296.                                 metadata_subscribe(key, client, 1);
  1297.                         } else
  1298.                         {
  1299.                                 sendto_one(client, NULL, ":%s FAIL METADATA KEY_INVALID %s :invalid key", me.name,  key);
  1300.                                 continue;
  1301.                         }
  1302.                 }
  1303.         } else if (!strcasecmp(cmd, "SUBS"))
  1304.         {
  1305.                 CHECKREGISTERED_OR_DIE(client, return);
  1306.                 metadata_send_subscribtions(client);
  1307.         } else if (!strcasecmp(cmd, "SYNC"))
  1308.         { /* the client requested re-sending of all subbed metadata */
  1309.                 CHECKREGISTERED_OR_DIE(client, return);
  1310.                 PROCESS_TARGET_OR_DIE(target, user, channel, return);
  1311.                 if (channel)
  1312.                         metadata_sync_channel(client, channel);
  1313.                 else
  1314.                         metadata_sync_user(client, user, NULL, 1);
  1315.         } else
  1316.         {
  1317.                 sendto_one(client, NULL, ":%s FAIL METADATA SUBCOMMAND_INVALID %s :invalid subcommand", me.name,  cmd);
  1318.         }
  1319. }
  1320.  
  1321. /* format of S2S is same as the event: ":origin METADATA <client/channel> <key name> *[ :<key value>]" */
  1322. CMD_FUNC(cmd_metadata_remote)
  1323. { /* handling data from linked server */
  1324.         Channel *channel = NULL;
  1325.         Client *user = NULL;
  1326.         const char *target;
  1327.         const char *key;
  1328.         const char *value;
  1329.         const char *channame;
  1330.  
  1331.         if (parc < 5 || BadPtr(parv[4]))
  1332.         {
  1333.                 if (parc == 4 && !BadPtr(parv[3]))
  1334.                 {
  1335.                         value = NULL;
  1336.                 } else
  1337.                 {
  1338.                         unreal_log(ULOG_DEBUG, "metadata", "METADATA_DEBUG", client, "METADATA S2S: not enough args from $sender",
  1339.                                 log_data_string("sender", client->name));
  1340.                         return;
  1341.                 }
  1342.         } else
  1343.         {
  1344.                 value = parv[4];
  1345.         }
  1346.  
  1347.         target = parv[1];
  1348.         key = parv[2];
  1349.         channame = strchr(target, '#');
  1350.  
  1351.         if (!*target || !strcmp(target, "*") || !metadata_key_valid(key))
  1352.         {
  1353.                 unreal_log(ULOG_DEBUG, "metadata", "METADATA_DEBUG", client, "METADATA S2S: bad metadata target $target or key $key from $sender",
  1354.                         log_data_string("target", target),
  1355.                         log_data_string("key", key),
  1356.                         log_data_string("sender", client->name));
  1357.                 return;
  1358.         }
  1359.         PROCESS_TARGET_OR_DIE(target, user, channel, return);
  1360.  
  1361.         if(channel)
  1362.         {
  1363.                 metadata_set_channel(channel, key, value, client);
  1364.         } else
  1365.         {
  1366.                 metadata_set_user(user, key, value, client);
  1367.         }
  1368. }
  1369.  
  1370. CMD_FUNC(cmd_metadata)
  1371. {
  1372.         if (client != &me && MyConnect(client) && !IsServer(client))
  1373.                 cmd_metadata_local(client, recv_mtags, parc, parv);
  1374.         else
  1375.                 cmd_metadata_remote(client, recv_mtags, parc, parv);
  1376. }
  1377.  
  1378. int metadata_server_sync(Client *client)
  1379. { /* we send all our data to the server that was just linked */
  1380.         Client *acptr;
  1381.         struct metadata_moddata_user *moddata;
  1382.         struct metadata *metadata;
  1383.         unsigned int  hashnum;
  1384.         Channel *channel;
  1385.        
  1386.         list_for_each_entry(acptr, &client_list, client_node)
  1387.         { /* send out users (all on our side of the link) */
  1388.                 moddata = USER_METADATA(acptr);
  1389.                 if(!moddata)
  1390.                         continue;
  1391.                 for (metadata = moddata->metadata; metadata; metadata = metadata->next)
  1392.                         metadata_send_change(client, NULL, acptr->name, metadata->name, metadata->value, &me);
  1393.         }
  1394.  
  1395.         for (hashnum = 0; hashnum < CHAN_HASH_TABLE_SIZE; hashnum++)
  1396.         { /* send out channels */
  1397.                 for(channel = hash_get_chan_bucket(hashnum); channel; channel = channel->hnextch)
  1398.                 {
  1399.                         for(metadata = CHANNEL_METADATA(channel); metadata; metadata = metadata->next)
  1400.                                 metadata_send_change(client, NULL, channel->name, metadata->name, metadata->value, &me);
  1401.                 }
  1402.         }
  1403.         return 0;
  1404. }
  1405.  
  1406. int metadata_join(Client *client, Channel *channel, MessageTag *join_mtags)
  1407. {
  1408.         Client *acptr;
  1409.         Member *cm;
  1410.         const char *value;
  1411.         struct metadata_unsynced *prev_us;
  1412.         struct metadata_unsynced *us;
  1413.         Membership *lp;
  1414.         struct metadata_subscriptions *subs;
  1415.         struct metadata *metadata;
  1416.         char batch[BATCHLEN+1] = "";
  1417.         MessageTag *batch_mtags = NULL;
  1418.  
  1419.         struct metadata_moddata_user *moddata = USER_METADATA(client);
  1420.         if(!moddata)
  1421.                 return 0; /* the user is both not subscribed to anything and has no own data */
  1422.         for (metadata = moddata->metadata; metadata; metadata = metadata->next)
  1423.         { /* if joining user has metadata, let's notify all subscribers */
  1424.                 list_for_each_entry(acptr, &lclient_list, lclient_node)
  1425.                 {
  1426.                         if(IsMember(acptr, channel) && metadata_is_subscribed(acptr, metadata->name))
  1427.                                 metadata_notify_or_queue(acptr, NULL, client->name, metadata->name, metadata->value, NULL);
  1428.                 }
  1429.         }
  1430.         if (HasCapability(client, "batch")) {
  1431.                 generate_batch_id(batch);
  1432.                 sendto_one(client, NULL, ":%s BATCH +%s metadata", me.name, batch);
  1433.                 batch_mtags = safe_alloc(sizeof(MessageTag));
  1434.                 batch_mtags->name = strdup("batch");
  1435.                 batch_mtags->value = strdup(batch);
  1436.         }
  1437.         for (subs = moddata->subs; subs; subs = subs->next)
  1438.         {
  1439.                 value = metadata_get_channel_key_value(channel, subs->name); /* notify joining user about channel metadata */
  1440.                 if(value)
  1441.                         metadata_notify_or_queue(client, batch_mtags, channel->name, subs->name, value, NULL);
  1442.                 for (cm = channel->members; cm; cm = cm->next)
  1443.                 { /* notify joining user about other channel members' metadata */
  1444.                         acptr = cm->client;
  1445.                         if (acptr == client)
  1446.                                 continue; /* ignore own data */
  1447.                         if (has_common_channels(acptr, client))
  1448.                                 continue; /* already seen elsewhere */
  1449.                         value = metadata_get_user_key_value(acptr, subs->name);
  1450.                         if (value)
  1451.                                 metadata_notify_or_queue(client, batch_mtags, acptr->name, subs->name, value, NULL);
  1452.                 }
  1453.         }
  1454.         if (*batch)
  1455.                 sendto_one(client, NULL, ":%s BATCH -%s", me.name, batch);
  1456.         if (batch_mtags)
  1457.                 free_message_tags(batch_mtags);
  1458.         return 0;
  1459. }
  1460.  
  1461. void metadata_send_pending(Client *client)
  1462. {
  1463.         Client *acptr = NULL;
  1464.         Channel *channel = NULL;
  1465.         int do_send = 0;
  1466.         char *who;
  1467.         char batch[BATCHLEN+1] = "";
  1468.         MessageTag *mtags = NULL;
  1469.  
  1470.         struct metadata_moddata_user *my_moddata = USER_METADATA(client);
  1471.         if (!my_moddata)
  1472.                 return; /* nothing queued */
  1473.         struct metadata_unsynced *us = my_moddata->us;
  1474.         struct metadata_unsynced *prev_us;
  1475.  
  1476.         if (us && HasCapability(client, "batch")) {
  1477.                 generate_batch_id(batch);
  1478.                 sendto_one(client, NULL, ":%s BATCH +%s metadata", me.name, batch);
  1479.                 mtags = safe_alloc(sizeof(MessageTag));
  1480.                 mtags->name = strdup("batch");
  1481.                 mtags->value = strdup(batch);
  1482.         }
  1483.  
  1484.         while (us)
  1485.         {
  1486.                 if (!IsSendable(client))
  1487.                         break;
  1488.                 if (*us->id == '#') {
  1489.                         channel = find_channel(us->id);
  1490.                         if (channel && IsMember(client, channel)) {
  1491.                                 do_send = 1;
  1492.                                 who = us->id;
  1493.                         }
  1494.                 } else {
  1495.                         acptr = find_client(us->id, NULL);
  1496.                         if (acptr && has_common_channels(acptr, client)) { /* if not, the user has vanished since or one of us parted the channel */
  1497.                                 do_send = 1;
  1498.                                 who = acptr->name;
  1499.                         }
  1500.                 }
  1501.  
  1502.                 if (do_send) {
  1503.                         struct metadata_moddata_user *moddata;
  1504.                         if (acptr)
  1505.                                 moddata = USER_METADATA(acptr);
  1506.                         else
  1507.                                 moddata = CHANNEL_METADATA(channel);
  1508.                         if (moddata)
  1509.                         {
  1510.                                 struct metadata *metadata = moddata->metadata;
  1511.                                 while (metadata)
  1512.                                 {
  1513.                                         if (!strcasecmp(us->key, metadata->name))
  1514.                                         { /* has it */
  1515.                                                 const char *value = metadata_get_user_key_value(acptr, us->key);
  1516.                                                 if(value)
  1517.                                                         metadata_send_change(client, mtags, who, us->key, value, NULL);
  1518.                                         }
  1519.                                         metadata = metadata->next;
  1520.                                 }
  1521.                         }
  1522.                 }
  1523.                 /* now remove the processed entry */
  1524.                 prev_us = us;
  1525.                 us = us->next;
  1526.                 safe_free(prev_us->id);
  1527.                 safe_free(prev_us);
  1528.                 my_moddata->us = us; /* we're always removing the first list item */
  1529.         }
  1530.  
  1531.         if (*batch)
  1532.                 sendto_one(client, NULL, ":%s BATCH -%s", me.name, batch);
  1533.         if (mtags)
  1534.                 free_message_tags(mtags);
  1535. }
  1536.  
  1537. int metadata_user_registered(Client *client)
  1538. {       /*      if we have any metadata set at this point, let's broadcast it to other servers and users */
  1539.         struct metadata *metadata;
  1540.         struct metadata_moddata_user *moddata = USER_METADATA(client);
  1541.         if(!moddata)
  1542.                 return HOOK_CONTINUE;
  1543.         for (metadata = moddata->metadata; metadata; metadata = metadata->next)
  1544.                 user_metadata_changed(client, metadata->name, metadata->value, client);
  1545.         return HOOK_CONTINUE;
  1546. }
  1547.  
  1548. void metadata_sync_user(Client *client, Client *target, MessageTag *mtags, int create_batch) {
  1549.         char batch[BATCHLEN+1] = "";
  1550.         struct metadata_subscriptions *subs;
  1551.         struct metadata *metadata;
  1552.         int parent_mtags = 0;
  1553.         Client *acptr;
  1554.        
  1555.         if (mtags)
  1556.                 parent_mtags = 1;
  1557.  
  1558.         struct metadata_moddata_user *moddata = USER_METADATA(target);
  1559.  
  1560.         if (!parent_mtags && create_batch && HasCapability(client, "batch"))
  1561.         {
  1562.                         generate_batch_id(batch);
  1563.                         sendto_one(client, NULL, ":%s BATCH +%s metadata", me.name, batch);
  1564.                         mtags = safe_alloc(sizeof(MessageTag));
  1565.                         mtags->name = strdup("batch");
  1566.                         mtags->value = strdup(batch);
  1567.         }
  1568.  
  1569.         if (moddata) { /* the user is either subscribed to something (this is not interesting to us) or has some own data */
  1570.                 for (metadata = moddata->metadata; metadata; metadata = metadata->next)
  1571.                 {              
  1572.                         if(metadata_is_subscribed(client, metadata->name))
  1573.                                 metadata_notify_or_queue(client, mtags, target->name, metadata->name, metadata->value, NULL);
  1574.                 }
  1575.         }
  1576.  
  1577.         if (!parent_mtags)
  1578.         {
  1579.                 if (*batch)
  1580.                         sendto_one(client, NULL, ":%s BATCH -%s", me.name, batch);
  1581.                 if (mtags)
  1582.                         free_message_tags(mtags);
  1583.         }
  1584. }
  1585.  
  1586. void metadata_sync_channel(Client *client, Channel *channel) {
  1587.         MessageTag *mtags = NULL;
  1588.         char batch[BATCHLEN+1] = "";
  1589.         Member *cm;
  1590.         struct metadata_subscriptions *subs;
  1591.         const char *value;
  1592.         struct metadata_moddata_user *moddata = USER_METADATA(client);
  1593.  
  1594.         if (HasCapability(client, "batch"))
  1595.         {
  1596.                         generate_batch_id(batch);
  1597.                         sendto_one(client, NULL, ":%s BATCH +%s metadata", me.name, batch);
  1598.                         mtags = safe_alloc(sizeof(MessageTag));
  1599.                         mtags->name = strdup("batch");
  1600.                         mtags->value = strdup(batch);
  1601.         }
  1602.  
  1603.         if (moddata)
  1604.         {
  1605.                 for (subs = moddata->subs; subs; subs = subs->next)
  1606.                 {
  1607.                         value = metadata_get_channel_key_value(channel, subs->name); /* channel metadata notification */
  1608.                         if(value)
  1609.                                 metadata_notify_or_queue(client, mtags, channel->name, subs->name, value, NULL);
  1610.                 }
  1611.                 for (cm = channel->members; cm; cm = cm->next) /* notify about all channel members' metadata (including the query source) */
  1612.                         metadata_sync_user(client, cm->client, mtags, 0);
  1613.         }
  1614.  
  1615.         if (*batch)
  1616.                 sendto_one(client, NULL, ":%s BATCH -%s", me.name, batch);
  1617.         if (mtags)
  1618.                 free_message_tags(mtags);
  1619. }
  1620.  
  1621. EVENT(metadata_queue_evt)
  1622. { /* let's check every 1.5 seconds whether we have something to send */
  1623.         Client *acptr;
  1624.         list_for_each_entry(acptr, &lclient_list, lclient_node)
  1625.         { /* notifications for local subscribers */
  1626.                 if (!IsUser(acptr))
  1627.                         continue;
  1628.                 metadata_send_pending(acptr);
  1629.         }
  1630. }
  1631.  
  1632. int metadata_monitor_connect(Client *client) {
  1633.         watch_check(client, WATCH_EVENT_ONLINE, metadata_monitor_notification);
  1634.         return 0;
  1635. }
  1636.  
  1637. int metadata_monitor_notification(Client *client, Watch *watch, Link *lp, int event)
  1638. {
  1639.         if (!(lp->flags & WATCH_FLAG_TYPE_MONITOR))
  1640.                 return 0;
  1641.         if (!HasCapabilityFast(lp->value.client, CAP_METADATA_NOTIFY))
  1642.                 return 0;
  1643.  
  1644.         switch (event)
  1645.         {
  1646.                 case WATCH_EVENT_ONLINE:
  1647.                 case WATCH_EVENT_METADATA:
  1648.                         metadata_sync_user(lp->value.client, client, NULL, 0);
  1649.                         break;
  1650.                 default:
  1651.                         break; /* may be handled by other modules */
  1652.         }
  1653.        
  1654.         return 0;
  1655. }
  1656.  

odpowiedź "Bez tytułu"

Tutaj możesz odpowiedzieć na wklejkę z góry

captcha