Merge branch 'development'
[NeonServV5.git] / src / modules.c
1 /* modules.c - NeonServ v5.6
2  * Copyright (C) 2011-2012  Philipp Kreil (pk910)
3  * 
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  * 
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  * 
14  * You should have received a copy of the GNU General Public License 
15  * along with this program. If not, see <http://www.gnu.org/licenses/>. 
16  */
17 #include "modules.h"
18 #ifndef WIN32
19 #include <dlfcn.h>
20 #endif
21
22 /* 000-001 */ #include "main.h"
23 /* 002-004 */ #include "tools.h"
24 #ifdef ENABLE_MUTEX_DEBUG
25 /* 005-006 */ #include "mutexDebug.h"
26 #endif
27 /* 007-009 */ /* main.h */
28 /* 010     */ #include "log.h"
29 /* 011     */ /* main.h */
30 /* 012     */ #include "BanNode.h"
31 /* 013-019 */ #include "bots.h"
32 /* 020-025 */ #include "ChanNode.h"
33 /* 026-029 */ #include "ChanUser.h"
34 /* 030-036 */ #include "ClientSocket.h"
35 /* 037-038 */ #include "ConfigParser.h"
36 /* 039-048 */ #include "DBHelper.h"
37 /* 049     */ #include "EventLogger.h"
38 /* 050     */ #include "HandleInfoHandler.h"
39 /* 051-088 */ #include "IRCEvents.h"
40 /* 089-091 */ #include "IRCParser.h"
41 /* 092-098 */ #include "lang.h"
42 #ifdef ENABLE_MEMORY_DEBUG
43 /* 099-102 */ #include "memoryDebug.h"
44 #endif
45 /* 103-106 */ #include "memoryInfo.h"
46 /* 107-122 */ #include "modcmd.h"
47 /* 123     */ /* deprecated */
48 /* 124-125 */ /* modcmd.h */
49 /* 126-136 */ #include "ModeNode.h"
50 /* 137-142 */ #include "mysqlConn.h"
51 /* 143-149 */ #include "timeq.h"
52 /* 150-169 */ /* tools.h */
53 /* 170-180 */ #include "UserNode.h"
54 /* 181-183 */ #include "WHOHandler.h"
55 /* 184-188 */ #include "version.h"
56 /* 189     */ /* modules.h */
57 /* 190     */ /* UserNode.h */
58 /* 191-193 */ #include "ModuleFunctions.h"
59 /* 194     */ /* bots.h */
60 /* 195-196 */ /* version.h */
61 /* 197-198 */ /* IRCEvents.h */
62
63 #define Function void *
64
65 void *global_functions[] = {
66 /* 000 */ (Function) getStartTime,
67 /* 001 */ (Function) getRunningThreads,
68 /* 002 */ (Function) getCurrentSecondsOfDay,
69 /* 003 */ (Function) stricmp,
70 /* 004 */ (Function) stricmplen,
71 #ifdef ENABLE_MUTEX_DEBUG
72 /* 005 */ (Function) xmutex,
73 /* 006 */ (Function) mutex_debug,
74 #else
75 /* 005 */ (Function) NULL,
76 /* 006 */ (Function) NULL,
77 #endif
78 /* 007 */ (Function) restart_bot,
79 /* 008 */ (Function) stop_bot,
80 /* 009 */ (Function) reload_config,
81 /* 010 */ (Function) printf_log,
82 #ifdef HAVE_THREADS
83 /* 011 */ (Function) getCurrentThreadID,
84 #else
85 /* 011 */ (Function) NULL,
86 #endif
87 /* 012 */ (Function) getMatchingChannelBan,
88 /* 013 */ (Function) getChannelBot,
89 /* 014 */ (Function) requestOp,
90 /* 015 */ (Function) channel_ban_timeout,
91 /* 016 */ (Function) general_event_privctcp,
92 /* 017 */ (Function) set_bot_alias,
93 /* 018 */ (Function) resolve_botid,
94 /* 019 */ (Function) resolve_botalias,
95 /* 020 */ (Function) is_valid_chan,
96 /* 021 */ (Function) getAllChans,
97 /* 022 */ (Function) getChanByName,
98 /* 023 */ (Function) getChannelCount,
99 /* 024 */ (Function) getChanUserCount,
100 /* 025 */ (Function) getChanBanCount,
101 /* 026 */ (Function) isUserOnChan,
102 /* 027 */ (Function) getChanUser,
103 /* 028 */ (Function) getChannelUsers,
104 /* 029 */ (Function) getUserChannels,
105 /* 030 */ (Function) create_socket,
106 /* 031 */ (Function) connect_socket,
107 /* 032 */ (Function) close_socket,
108 /* 033 */ (Function) destroy_socket,
109 /* 034 */ (Function) write_socket,
110 /* 035 */ (Function) putsock,
111 /* 036 */ (Function) getBots,
112 /* 037 */ (Function) get_int_field,
113 /* 038 */ (Function) get_string_field,
114 /* 039 */ (Function) _loadUserSettings,
115 /* 040 */ (Function) isGodMode,
116 /* 041 */ (Function) getChanDefault,
117 /* 042 */ (Function) getChannelAccess,
118 /* 043 */ (Function) checkChannelAccess,
119 /* 044 */ (Function) _loadChannelSettings,
120 /* 045 */ (Function) isUserProtected,
121 /* 046 */ (Function) getBanAffectingMask,
122 /* 047 */ (Function) renameAccount,
123 /* 048 */ (Function) deleteUser,
124 /* 049 */ (Function) logEvent,
125 /* 050 */ (Function) lookup_authname,
126 /* 051 */ (Function) bind_join,
127 /* 052 */ (Function) unbind_join,
128 /* 053 */ (Function) bind_nick,
129 /* 054 */ (Function) unbind_nick,
130 /* 055 */ (Function) bind_part,
131 /* 056 */ (Function) unbind_part,
132 /* 057 */ (Function) bind_reload,
133 /* 058 */ (Function) unbind_reload,
134 /* 059 */ (Function) bind_kick,
135 /* 060 */ (Function) unbind_kick,
136 /* 061 */ (Function) bind_topic,
137 /* 062 */ (Function) unbind_topic,
138 /* 063 */ (Function) bind_mode,
139 /* 064 */ (Function) unbind_mode,
140 /* 065 */ (Function) bind_chanmsg,
141 /* 066 */ (Function) unbind_chanmsg,
142 /* 067 */ (Function) bind_privmsg,
143 /* 068 */ (Function) unbind_privmsg,
144 /* 069 */ (Function) bind_channotice,
145 /* 070 */ (Function) unbind_channotice,
146 /* 071 */ (Function) bind_privnotice,
147 /* 072 */ (Function) unbind_privnotice,
148 /* 073 */ (Function) bind_chanctcp,
149 /* 074 */ (Function) unbind_chanctcp,
150 /* 075 */ (Function) bind_privctcp,
151 /* 076 */ (Function) unbind_privctcp,
152 /* 077 */ (Function) bind_invite,
153 /* 078 */ (Function) unbind_invite,
154 /* 079 */ (Function) bind_raw,
155 /* 080 */ (Function) unbind_raw,
156 /* 081 */ (Function) bind_bot_ready,
157 /* 082 */ (Function) unbind_bot_ready,
158 /* 083 */ (Function) bind_registered,
159 /* 084 */ (Function) unbind_registered,
160 /* 085 */ (Function) bind_freeuser,
161 /* 086 */ (Function) unbind_freeuser,
162 /* 087 */ (Function) bind_freechan,
163 /* 088 */ (Function) unbind_freechan,
164 /* 089 */ (Function) reply,
165 /* 090 */ (Function) merge_argv,
166 /* 091 */ (Function) merge_argv_char,
167 /* 092 */ (Function) get_language_by_tag,
168 /* 093 */ (Function) get_language_by_name,
169 /* 094 */ (Function) get_default_language,
170 /* 095 */ (Function) load_language,
171 /* 096 */ (Function) register_default_language_table,
172 /* 097 */ (Function) get_language_string,
173 /* 098 */ (Function) build_language_string,
174 #ifdef ENABLE_MEMORY_DEBUG
175 /* 099 */ (Function) xmalloc,
176 /* 100 */ (Function) xcalloc,
177 /* 101 */ (Function) xstrdup,
178 /* 102 */ (Function) xfree,
179 #else
180 /* 099 */ (Function) NULL,
181 /* 100 */ (Function) NULL,
182 /* 101 */ (Function) NULL,
183 /* 102 */ (Function) NULL,
184 #endif
185 /* 103 */ (Function) getMemoryInfoFiles,
186 /* 104 */ (Function) freeMemoryInfoFiles,
187 /* 105 */ (Function) getMemoryInfoLines,
188 /* 106 */ (Function) freeMemoryInfoLines,
189 /* 107 */ (Function) get_botwise_prefered_bot,
190 /* 108 */ (Function) register_command,
191 /* 109 */ (Function) set_trigger_callback,
192 /* 110 */ (Function) flush_trigger_cache,
193 /* 111 */ (Function) changeBotwiseChannelTrigger,
194 /* 112 */ (Function) bind_botwise_cmd_to_function,
195 /* 113 */ (Function) bind_botwise_cmd_to_command,
196 /* 114 */ (Function) unbind_botwise_cmd,
197 /* 115 */ (Function) unbind_botwise_allcmd,
198 /* 116 */ (Function) bind_botwise_set_parameters,
199 /* 117 */ (Function) bind_botwise_set_global_access,
200 /* 118 */ (Function) bind_botwise_set_channel_access,
201 /* 119 */ (Function) bind_botwise_set_bind_flags,
202 /* 120 */ (Function) find_botwise_cmd_binding,
203 /* 121 */ (Function) bind_botwise_unbound_required_functions,
204 /* 122 */ (Function) find_cmd_function,
205 /* 123 */ (Function) NULL, /* deprecated */
206 /* 124 */ (Function) register_command_alias,
207 /* 125 */ (Function) getAllBinds,
208 /* 126 */ (Function) createModeNode,
209 /* 127 */ (Function) freeModeNode,
210 /* 128 */ (Function) isModeSet,
211 /* 129 */ (Function) isModeAffected,
212 /* 130 */ (Function) getModeValue,
213 /* 131 */ (Function) getModeType,
214 /* 132 */ (Function) parseModes,
215 /* 133 */ (Function) parseModeString,
216 /* 134 */ (Function) parseMode,
217 /* 135 */ (Function) getModeString,
218 /* 136 */ (Function) getFullModeString,
219 /* 137 */ (Function) mysql_use,
220 /* 138 */ (Function) mysql_free,
221 /* 139 */ (Function) printf_mysql_query,
222 /* 140 */ (Function) printf_long_mysql_query,
223 /* 141 */ (Function) escape_string,
224 /* 142 */ (Function) get_mysql_conn,
225 /* 143 */ (Function) timeq_add,
226 /* 144 */ (Function) timeq_uadd,
227 /* 145 */ (Function) timeq_add_name,
228 /* 146 */ (Function) timeq_uadd_name,
229 /* 147 */ (Function) timeq_del,
230 /* 148 */ (Function) timeq_del_name,
231 /* 149 */ (Function) timeq_name_exists,
232 /* 150 */ (Function) match,
233 /* 151 */ (Function) table_init,
234 /* 152 */ (Function) table_add,
235 /* 153 */ (Function) table_change,
236 /* 154 */ (Function) table_change_field,
237 /* 155 */ (Function) table_set_bold,
238 /* 156 */ (Function) table_end,
239 /* 157 */ (Function) table_free,
240 /* 158 */ (Function) timeToStr,
241 /* 159 */ (Function) strToTime,
242 /* 160 */ (Function) initModeBuffer,
243 /* 161 */ (Function) modeBufferSet,
244 /* 162 */ (Function) flushModeBuffer,
245 /* 163 */ (Function) freeModeBuffer,
246 /* 164 */ (Function) is_ircmask,
247 /* 165 */ (Function) generate_banmask,
248 /* 166 */ (Function) make_banmask,
249 /* 167 */ (Function) isFakeHost,
250 /* 168 */ (Function) mask_match,
251 /* 169 */ (Function) crc32,
252 /* 170 */ (Function) is_valid_nick,
253 /* 171 */ (Function) getUserByNick,
254 /* 172 */ (Function) getUserByMask,
255 /* 173 */ (Function) countUsersWithHost,
256 /* 174 */ (Function) getAuthFakehost,
257 /* 175 */ (Function) searchUserByNick,
258 /* 176 */ (Function) getAllUsers,
259 /* 177 */ (Function) getUsersWithAuth,
260 /* 178 */ (Function) getUserCount,
261 /* 179 */ (Function) createTempUser,
262 /* 180 */ (Function) createTempUserMask,
263 /* 181 */ (Function) get_userlist,
264 /* 182 */ (Function) _get_userlist_with_invisible,
265 /* 183 */ (Function) get_userauth,
266 /* 184 */ (Function) get_compilation,
267 /* 185 */ (Function) get_creation,
268 /* 186 */ (Function) get_revision,
269 /* 187 */ (Function) get_codelines,
270 /* 188 */ (Function) get_patchlevel,
271 /* 189 */ (Function) get_module_name,
272 /* 190 */ (Function) isUserModeSet,
273 /* 191 */ (Function) module_global_cmd_register_neonbackup,
274 /* 192 */ (Function) module_global_cmd_unregister_neonbackup,
275 /* 193 */ (Function) module_neonbackup_recover_chan,
276 /* 194 */ (Function) requestInvite,
277 /* 195 */ (Function) is_stable_revision,
278 /* 196 */ (Function) get_dev_revision,
279 /* 197 */ (Function) bind_freeclient,
280 /* 198 */ (Function) unbind_freeclient
281 };
282
283 static int module_id_counter = 1;
284 static struct ModuleInfo *modules = NULL;
285
286 static void unregister_module_hooks(int module_id);
287
288 void loadModules() {
289     char **modulelist = get_all_fieldnames("modules");
290     if(!modulelist) return;
291     int i = 0;
292     char tmp[MAXLEN];
293     struct ModuleInfo *modinfo;
294     while(modulelist[i]) {
295         sprintf(tmp, "modules.%s.enabled", modulelist[i]);
296         if(get_int_field(tmp)) {
297             modinfo = loadModule(modulelist[i]);
298             sprintf(tmp, "modules.%s.protected", modulelist[i]);
299             if(get_int_field(tmp))
300                 modinfo->state |= MODINFO_STATE_PROTECTED;
301         }
302         i++;
303     }
304     free(modulelist);
305     start_modules();
306 }
307
308 struct ModuleInfo *loadModule(char *name) {
309     struct ModuleInfo *modinfo;
310     for(modinfo = modules; modinfo; modinfo = modinfo->next) {
311         if(!stricmp(modinfo->name, name)) return NULL;
312     }
313     char fname[256];
314     #ifndef WIN32
315     sprintf(fname, "%s.so", name);
316     void* module = dlopen(fname, RTLD_LAZY);
317     if(!module) {
318         sprintf(fname, "./%s.so", name);
319         module = dlopen(fname, RTLD_LAZY);
320     }
321     if(!module) {
322         sprintf(fname, ".libs/%s.so", name);
323         module = dlopen(fname, RTLD_LAZY);
324     }
325     if(!module) {
326         printf_log("main", LOG_ERROR, "Error loading module '%s': %s not found.\n", name, fname);
327         return NULL;
328     }
329     void* initfunc = dlsym(module, "init_module");
330     void* startfunc = dlsym(module, "start_module");
331     void* stopfunc = dlsym(module, "stop_module");
332     void* modversion = dlsym(module, "modversion");
333     #else
334     sprintf(fname, "%s.dll", name);
335     HMODULE module = LoadLibrary(fname);
336     if(!module) {
337         printf_log("main", LOG_ERROR, "Error loading module '%s': %s not found.\n", name, fname);
338         return NULL;
339     }
340     FARPROC initfunc = GetProcAddress(module, "init_module");
341     FARPROC startfunc = GetProcAddress(module, "start_module");
342     FARPROC stopfunc = GetProcAddress(module, "stop_module");
343     FARPROC modversion = GetProcAddress(module, "modversion");
344     #endif
345     if(!startfunc || !stopfunc || !modversion) {
346         printf_log("main", LOG_ERROR, "Error loading module '%s': required symbols not found.\n", name);
347         return NULL;
348     }
349     int version = ((int (*)(void)) modversion)();
350     if(version != MODULE_VERSION) {
351         printf_log("main", LOG_ERROR, "Error loading module '%s': version mismatch ('%d' main code, '%d' module)\n", name, MODULE_VERSION, version);
352         return NULL;
353     }
354     //start module
355     int errid;
356     int module_id = module_id_counter++;
357     if((errid = ((int (*)(void **, int)) initfunc)(global_functions, module_id))) {
358         printf_log("main", LOG_ERROR, "Error loading module '%s': module reported error (errid: %d)\n", name, errid);
359         return NULL;
360     }
361     modinfo = malloc(sizeof(*modinfo));
362     if(!modinfo) {
363         unregister_module_hooks(module_id);
364         return NULL;
365     }
366     modinfo->name = strdup(name);
367     modinfo->module_id = module_id;
368     modinfo->module = module;
369     modinfo->startfunc = startfunc;
370     modinfo->stopfunc = stopfunc;
371     modinfo->state = 0;
372     modinfo->next = modules;
373     modules = modinfo;
374     scan_module(modinfo);
375     return modinfo;
376 }
377
378 #ifndef WIN32
379 static void closemodule(void *module) {
380     dlclose(module);
381 }
382 #else
383 static void closemodule(HMODULE module) {
384     FreeLibrary(module);
385 }
386 #endif
387
388 int ext_load_module(char *name) {
389     if(!loadModule(name)) return 0;
390     struct ModuleInfo *modinfo;
391     for(modinfo = modules; modinfo; modinfo = modinfo->next) {
392         if(!(modinfo->state & MODINFO_STATE_STARTED)) {
393             modinfo->state |= MODINFO_STATE_STARTED;
394             ((void (*)(int)) modinfo->startfunc)(MODSTATE_STARTSTOP);
395         } else
396             ((void (*)(int)) modinfo->startfunc)(MODSTATE_REBIND);
397     }
398     return 1;
399 }
400
401 int ext_unload_module(char *name) {
402     struct ModuleInfo *old_modinfo, *old_prev = NULL;
403     for(old_modinfo = modules; old_modinfo; old_modinfo = old_modinfo->next) {
404         if(!stricmp(old_modinfo->name, name)) {
405             if(old_modinfo->state & MODINFO_STATE_PROTECTED) {
406                 return 0;
407             }
408             if(old_prev)
409                 old_prev->next = old_modinfo->next;
410             else
411                 modules = old_modinfo->next;
412             unregister_module_hooks(old_modinfo->module_id);
413             ((void (*)(int)) old_modinfo->stopfunc)(MODSTATE_STARTSTOP);
414             closemodule(old_modinfo->module);
415             free_module_functions(old_modinfo);
416             free(old_modinfo->name);
417             free(old_modinfo);
418             return 1;
419         } else
420             old_prev = old_modinfo;
421     }
422     return 0;
423 }
424
425 int ext_reload_module(char *name) {
426     char libname[256];
427     struct ModuleInfo *old_modinfo, *old_prev = NULL;
428     for(old_modinfo = modules; old_modinfo; old_modinfo = old_modinfo->next) {
429         if(!stricmp(old_modinfo->name, name)) {
430             strcpy(libname, old_modinfo->name);
431             if(old_prev)
432                 old_prev->next = old_modinfo->next;
433             else
434                 modules = old_modinfo->next;
435             unregister_module_hooks(old_modinfo->module_id);
436             ((void (*)(int)) old_modinfo->stopfunc)(MODSTATE_RELOAD);
437             closemodule(old_modinfo->module);
438             free_module_functions(old_modinfo);
439             free(old_modinfo->name);
440             free(old_modinfo);
441             break;
442         } else
443             old_prev = old_modinfo;
444     }
445     if(!loadModule(libname)) return 0;
446     struct ModuleInfo *modinfo;
447     for(modinfo = modules; modinfo; modinfo = modinfo->next) {
448         if(!(modinfo->state & MODINFO_STATE_STARTED)) {
449             modinfo->state |= MODINFO_STATE_STARTED;
450             ((void (*)(int)) modinfo->startfunc)(MODSTATE_RELOAD);
451         } else
452             ((void (*)(int)) modinfo->startfunc)(MODSTATE_REBIND);
453     }
454     return 1;
455 }
456
457 struct ModuleInfo *ext_get_modules(struct ModuleInfo *last) {
458     return (last ? last->next : modules);
459 }
460
461 void start_modules() {
462     struct ModuleInfo *modinfo;
463     for(modinfo = modules; modinfo; modinfo = modinfo->next) {
464         if(!(modinfo->state & MODINFO_STATE_STARTED)) {
465             modinfo->state |= MODINFO_STATE_STARTED;
466             ((void (*)(int)) modinfo->startfunc)(MODSTATE_STARTSTOP);
467         }
468     }
469 }
470
471 void stop_modules() {
472     struct ModuleInfo *modinfo, *next;
473     for(modinfo = modules; modinfo; modinfo = next) {
474         next = modinfo->next;
475         unregister_module_hooks(modinfo->module_id);
476         ((void (*)(int)) modinfo->stopfunc)(MODSTATE_STARTSTOP);
477         closemodule(modinfo->module);
478         free_module_functions(modinfo);
479         free(modinfo->name);
480         free(modinfo);
481     }
482     modules = NULL;
483 }
484
485 static void unregister_module_hooks(int module_id) {
486     unregister_module_commands(module_id);
487     unregister_module_events(module_id);
488     unregister_module_timers(module_id);
489     
490 }
491
492 int module_loaded(int module_id) {
493     if(!module_id) return 1;
494     struct ModuleInfo *modinfo;
495     for(modinfo = modules; modinfo; modinfo = modinfo->next) {
496         if(modinfo->module_id == module_id)
497             return 1;
498     }
499     return 0;
500 }
501
502 char *get_module_name(int module_id) {
503     if(!module_id) return NULL;
504     struct ModuleInfo *modinfo;
505     for(modinfo = modules; modinfo; modinfo = modinfo->next) {
506         if(modinfo->module_id == module_id)
507             return modinfo->name;
508     }
509     return NULL;
510 }
511
512