unrealircd- supernets unrealircd source & configuration |
git clone git://git.acid.vegas/unrealircd.git |
Log | Files | Refs | Archive | README | LICENSE |
api-messagetag.c (5548B)
1 /************************************************************************ 2 * UnrealIRCd - Unreal Internet Relay Chat Daemon - src/api-mtag.c 3 * (c) 2019- Bram Matthys and The UnrealIRCd team 4 * 5 * See file AUTHORS in IRC package for additional names of 6 * the programmers. 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by 10 * the Free Software Foundation; either version 1, or (at your option) 11 * any later version. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, write to the Free Software 20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 21 */ 22 23 /** @file 24 * @brief Message tag API 25 */ 26 #include "unrealircd.h" 27 28 /** This is the message tags API (message-tags). 29 * For an overview of message tags in general (not the API) 30 * see https://www.unrealircd.org/docs/Message_tags 31 * @defgroup MessagetagAPI Message tag API 32 * @{ 33 */ 34 35 /** List of message tag handlers */ 36 MODVAR MessageTagHandler *mtaghandlers = NULL; 37 38 /* Forward declarations */ 39 static void unload_mtag_handler_commit(MessageTagHandler *m); 40 41 /** Adds a new message tag handler. 42 * @param module The module which owns this message-tag handler. 43 * @param mreq The details of the request such as which message tag, the handler, etc. 44 * @return Returns the handle to the new token if successful, otherwise NULL. 45 * The module's error code contains specific information about the 46 * error. 47 */ 48 MessageTagHandler *MessageTagHandlerAdd(Module *module, MessageTagHandlerInfo *mreq) 49 { 50 MessageTagHandler *m; 51 52 /* Some consistency checks to avoid a headache for module devs later on: */ 53 if ((mreq->flags & MTAG_HANDLER_FLAGS_NO_CAP_NEEDED) && mreq->clicap_handler) 54 { 55 unreal_log(ULOG_ERROR, "module", "MESSAGETAGHANDLERADD_API_ERROR", NULL, 56 "MessageTagHandlerAdd() from module $module_name: " 57 ".flags is set to MTAG_HANDLER_FLAGS_NO_CAP_NEEDED " 58 "but a .clicap_handler is passed as well. These options are mutually " 59 "exclusive, choose one or the other.", 60 log_data_string("module_name", module->header->name)); 61 abort(); 62 } else if (!(mreq->flags & MTAG_HANDLER_FLAGS_NO_CAP_NEEDED) && !mreq->clicap_handler) 63 { 64 unreal_log(ULOG_ERROR, "module", "MESSAGETAGHANDLERADD_API_ERROR", NULL, 65 "MessageTagHandlerAdd() from module $module_name: " 66 "no .clicap_handler is passed. If the " 67 "message tag really does not require a cap then you must " 68 "set .flags to MTAG_HANDLER_FLAGS_NO_CAP_NEEDED", 69 log_data_string("module_name", module->header->name)); 70 abort(); 71 } 72 73 m = MessageTagHandlerFind(mreq->name); 74 if (m) 75 { 76 if (m->unloaded) 77 { 78 m->unloaded = 0; 79 } else { 80 if (module) 81 module->errorcode = MODERR_EXISTS; 82 return NULL; 83 } 84 } else { 85 /* New message tag handler */ 86 m = safe_alloc(sizeof(MessageTagHandler)); 87 safe_strdup(m->name, mreq->name); 88 AddListItem(m, mtaghandlers); 89 } 90 /* Add or update the following fields: */ 91 m->owner = module; 92 m->flags = mreq->flags; 93 m->is_ok = mreq->is_ok; 94 m->should_send_to_client = mreq->should_send_to_client; 95 m->clicap_handler = mreq->clicap_handler; 96 97 /* Update reverse dependency (if any) */ 98 if (m->clicap_handler) 99 m->clicap_handler->mtag_handler = m; 100 101 if (module) 102 { 103 ModuleObject *mobj = safe_alloc(sizeof(ModuleObject)); 104 mobj->type = MOBJ_MTAG; 105 mobj->object.mtag = m; 106 AddListItem(mobj, module->objects); 107 module->errorcode = MODERR_NOERROR; 108 } 109 110 return m; 111 } 112 113 /** Returns the message tag handler for the given name. 114 * @param name The message-tag name to search for. 115 * @return Returns the handle to the message tag handler, 116 * or NULL if not found. 117 */ 118 MessageTagHandler *MessageTagHandlerFind(const char *name) 119 { 120 MessageTagHandler *m; 121 122 for (m = mtaghandlers; m; m = m->next) 123 { 124 if (!strcasecmp(name, m->name)) 125 return m; 126 } 127 return NULL; 128 } 129 130 /** Remove the specified message tag handler - modules should not call this. 131 * This is done automatically for modules on unload, so is only called internally. 132 * @param m The message tag handler to remove. 133 */ 134 void MessageTagHandlerDel(MessageTagHandler *m) 135 { 136 if (m->owner) 137 { 138 ModuleObject *mobj; 139 for (mobj = m->owner->objects; mobj; mobj = mobj->next) { 140 if (mobj->type == MOBJ_MTAG && mobj->object.mtag == m) 141 { 142 DelListItem(mobj, m->owner->objects); 143 safe_free(mobj); 144 break; 145 } 146 } 147 m->owner = NULL; 148 } 149 150 if (loop.rehashing) 151 m->unloaded = 1; 152 else 153 unload_mtag_handler_commit(m); 154 } 155 156 /** @} */ 157 158 static void unload_mtag_handler_commit(MessageTagHandler *m) 159 { 160 /* This is an unusual operation, I think we should log it. */ 161 unreal_log(ULOG_INFO, "module", "UNLOAD_MESSAGE_TAG", NULL, 162 "Unloading message-tag handler for '$token'", 163 log_data_string("token", m->name)); 164 165 /* Remove reverse dependency, if any */ 166 if (m->clicap_handler) 167 m->clicap_handler->mtag_handler = NULL; 168 169 /* Destroy the object */ 170 DelListItem(m, mtaghandlers); 171 safe_free(m->name); 172 safe_free(m); 173 } 174 175 void unload_all_unused_mtag_handlers(void) 176 { 177 MessageTagHandler *m, *m_next; 178 179 for (m = mtaghandlers; m; m = m_next) 180 { 181 m_next = m->next; 182 if (m->unloaded) 183 unload_mtag_handler_commit(m); 184 } 185 }