00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifndef lint
00021 static const char rcsid[] = "$Id: partymember.c,v 1.31 2007-09-13 22:20:55 sven Exp $";
00022 #endif
00023
00024 #include <eggdrop/eggdrop.h>
00025
00026 static partymember_t *party_head = NULL;
00027 static partymember_t *local_party_head = NULL;
00028 static int npartymembers = 0;
00029
00030 static int partymember_cleanup(void *client_data);
00031 static int on_udelete(user_t *u);
00032
00033 static bind_list_t partymember_udelete_binds[] = {
00034 {NULL, NULL, on_udelete},
00035 {0}
00036 };
00037
00038 static bind_table_t *BT_nick = NULL, *BT_new = NULL, *BT_quit = NULL;
00039
00040 int partymember_init(void)
00041 {
00042 bind_add_list(BTN_USER_DELETE, partymember_udelete_binds);
00043 BT_nick = bind_table_add(BTN_PARTYLINE_NICK, 3, "Pss", MATCH_NONE, BIND_STACKABLE);
00044 BT_new = bind_table_add(BTN_PARTYLINE_NEW, 1, "P", MATCH_MASK, BIND_STACKABLE);
00045 BT_quit = bind_table_add(BTN_PARTYLINE_QUIT, 2, "Ps", MATCH_MASK, BIND_STACKABLE);
00046 return(0);
00047 }
00048
00049 int partymember_shutdown(void)
00050 {
00051 while (party_head) partymember_delete(party_head, NULL, _("Bot shutdown"));
00052 bind_rem_list(BTN_USER_DELETE, partymember_udelete_binds);
00053 bind_table_del(BT_nick);
00054 bind_table_del(BT_new);
00055 bind_table_del(BT_quit);
00056
00057
00058
00059
00060 garbage_run();
00061
00062 return (0);
00063 }
00064
00065 static void partymember_really_delete(partymember_t *p)
00066 {
00067
00068 if (p->prev) p->prev->next = p->next;
00069 else party_head = p->next;
00070 if (p->next) p->next->prev = p->prev;
00071
00072 if (p->prev_on_bot) p->prev_on_bot->next_on_bot = p->next_on_bot;
00073 else if (p->bot) p->bot->partys = p->next_on_bot;
00074 else if (local_party_head == p) local_party_head = p->next_on_bot;
00075 if (p->next_on_bot) p->next_on_bot->prev_on_bot = p->prev_on_bot;
00076
00077
00078 free(p->nick);
00079 if (p->ident) free(p->ident);
00080 if (p->host) free(p->host);
00081 free(p->net_name);
00082 free(p->full_id_name);
00083 if (p->channels) free(p->channels);
00084
00085
00086 memset(p, 0, sizeof(*p));
00087
00088 free(p);
00089 }
00090
00091 static int partymember_cleanup(void *client_data)
00092 {
00093 partymember_t *p, *next;
00094
00095 for (p = party_head; p; p = next) {
00096 next = p->next;
00097 if (p->flags & PARTY_DELETED) partymember_really_delete(p);
00098 }
00099 return(0);
00100 }
00101
00102 partymember_t *partymember_get_head()
00103 {
00104 return party_head;
00105 }
00106
00107 partymember_t *partymember_get_local_head()
00108 {
00109 return local_party_head;
00110 }
00111
00112 static int partymember_get_id(botnet_bot_t *bot)
00113 {
00114 int id;
00115
00116 for (id = 1; partymember_lookup(NULL, bot, id); id++) {
00117 ;
00118 }
00119 return(id);
00120 }
00121
00122 partymember_t *partymember_new(int id, user_t *user, botnet_bot_t *bot, const char *nick, const char *ident, const char *host, partyline_event_t *handler, void *client_data, event_owner_t *owner)
00123 {
00124 partymember_t *mem;
00125
00126 if (user && user->flags & USER_BOT) return NULL;
00127 mem = calloc(1, sizeof(*mem));
00128 if (id == -1) id = partymember_get_id(bot);
00129 mem->id = id;
00130 mem->user = user;
00131 mem->bot = bot;
00132 mem->nick = strdup(nick);
00133 mem->ident = strdup(ident);
00134 mem->host = strdup(host);
00135 mem->net_name = egg_mprintf("%s@%s", b64enc_int(id), bot ? bot->name : botnet_get_name());
00136 mem->full_id_name = egg_mprintf("%d:%s@%s", id, nick, bot ? bot->name : botnet_get_name());
00137 mem->full_name = strchr(mem->full_id_name, ':') + 1;
00138 mem->common_name = bot ? mem->full_name : mem->nick;
00139 mem->handler = handler;
00140 mem->client_data = client_data;
00141 mem->owner = owner;
00142
00143 mem->next = party_head;
00144 if (party_head) party_head->prev = mem;
00145 party_head = mem;
00146
00147 mem->prev_on_bot = NULL;
00148 if (bot) {
00149 mem->next_on_bot = bot->partys;
00150 if (bot->partys) bot->partys->prev_on_bot = mem;
00151 bot->partys = mem;
00152 } else {
00153 mem->next_on_bot = local_party_head;
00154 if (local_party_head) local_party_head->prev_on_bot = mem;
00155 local_party_head = mem;
00156 }
00157
00158 npartymembers++;
00159 botnet_announce_login(mem);
00160 bind_check(BT_new, NULL, nick, mem);
00161 return(mem);
00162 }
00163
00175 int partymember_delete_by_owner(struct egg_module *module, void *script)
00176 {
00177 int ret = 0;
00178 partymember_t *p;
00179
00180 for (p = party_head; p; p = p->next) {
00181 if (p->flags & PARTY_DELETED) continue;
00182 if (p->owner && p->owner->module == module && (!script || p->owner->client_data == script)) {
00183 partymember_delete(p, NULL, "Module unloaded");
00184 ++ret;
00185 }
00186 }
00187
00188 return ret;
00189 }
00190
00191 int partymember_delete(partymember_t *p, const botnet_bot_t *lost_bot, const char *text)
00192 {
00193 int i, len;
00194 partymember_common_t *common;
00195 partymember_t *mem;
00196
00197 if (p->flags & PARTY_DELETED) return(-1);
00198
00199 len = strlen(text);
00200
00201 if (!lost_bot && p->nchannels) botnet_member_quit(p, text, len);
00202
00203 bind_check(BT_quit, NULL, p->nick, p, text);
00204
00205
00206 p->flags |= PARTY_DELETED;
00207 garbage_add(partymember_cleanup, NULL, GARBAGE_ONCE);
00208 npartymembers--;
00209
00210 common = partychan_get_common(p);
00211 if (common) {
00212 for (i = 0; i < common->len; i++) {
00213 mem = common->members[i];
00214 if (mem->flags & PARTY_DELETED) continue;
00215 if (mem->handler->on_quit) (mem->handler->on_quit)(mem->client_data, p, lost_bot, text, len);
00216 }
00217 partychan_free_common(common);
00218 }
00219
00220
00221 for (i = 0; i < p->nchannels; i++) {
00222 partychan_part(p->channels[i], p, text);
00223 }
00224 p->nchannels = 0;
00225
00226 if (p->handler && p->handler->on_quit) {
00227 (p->handler->on_quit)(p->client_data, p, lost_bot, text, strlen(text));
00228 }
00229 if (p->owner && p->owner->on_delete) p->owner->on_delete(p->owner, p->client_data);
00230 p->bot = NULL;
00231 return(0);
00232 }
00233
00234 int partymember_set_nick(partymember_t *p, const char *nick)
00235 {
00236 partymember_common_t *common;
00237 partymember_t *mem;
00238 char *oldnick;
00239 int i;
00240
00241 oldnick = p->nick;
00242 p->nick = strdup(nick);
00243 if (p->handler && p->handler->on_nick)
00244 (p->handler->on_nick)(p->client_data, p, oldnick, nick);
00245 botnet_set_nick(p, oldnick);
00246 p->flags |= PARTY_SELECTED;
00247 common = partychan_get_common(p);
00248 if (common) {
00249 for (i = 0; i < common->len; i++) {
00250 mem = common->members[i];
00251 if (mem->flags & PARTY_DELETED) continue;
00252 if (mem->handler->on_nick) (mem->handler->on_nick)(mem->client_data, p, oldnick, nick);
00253 }
00254 partychan_free_common(common);
00255 }
00256 bind_check(BT_nick, NULL, NULL, p, oldnick, p->nick);
00257 if (oldnick) free(oldnick);
00258 p->flags &= ~PARTY_SELECTED;
00259 return(0);
00260 }
00261
00262 int partymember_update_info(partymember_t *p, const char *ident, const char *host)
00263 {
00264 if (!p) return(-1);
00265 if (ident) str_redup(&p->ident, ident);
00266 if (host) str_redup(&p->host, host);
00267 return(0);
00268 }
00269
00270 int partymember_who(int **ids, int *len)
00271 {
00272 int i;
00273 partymember_t *p;
00274
00275 *ids = malloc(sizeof(int) * (npartymembers+1));
00276 i = 0;
00277 for (p = local_party_head; p; p = p->next_on_bot) {
00278 if (p->flags & PARTY_DELETED) continue;
00279 (*ids)[i] = p->id;
00280 i++;
00281 }
00282 (*ids)[i] = 0;
00283 *len = i;
00284 return(0);
00285 }
00286
00287 partymember_t *partymember_lookup(const char *full_name, botnet_bot_t *bot, int id)
00288 {
00289 int i = id;
00290 char *name = NULL;
00291 const char *ptr, *nick = full_name;
00292 botnet_bot_t *b = bot;
00293 partymember_t *p;
00294
00295 if (!full_name && id == -1) return NULL;
00296
00297 if (full_name) {
00298 ptr = strchr(full_name, '@');
00299 if (ptr) {
00300 bot = botnet_lookup(ptr + 1);
00301 if (!bot && strcmp(ptr + 1, botnet_get_name())) return NULL;
00302 if (b && bot != b) return NULL;
00303 name = strdup(full_name);
00304 name[ptr - full_name] = 0;
00305 nick = name;
00306 }
00307
00308 ptr = strchr(nick, ':');
00309 if (ptr) {
00310 id = atoi(nick);
00311 if (i != -1 && i != id) {
00312 if (name) free(name);
00313 return NULL;
00314 }
00315 nick = ptr + 1;
00316 }
00317 }
00318
00319 for (p = bot ? bot->partys : local_party_head; p; p = p->next_on_bot) {
00320 if (p->flags & PARTY_DELETED) continue;
00321 if (id != -1) {
00322 if (p->id == id) break;
00323 } else {
00324 if (!strcmp(p->nick, nick)) break;
00325 }
00326 }
00327
00328 if (p && id != -1 && nick && strcmp(p->nick, nick)) p = NULL;
00329 if (name) free(name);
00330 return p;
00331 }
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341 int partymember_write(partymember_t *p, const char *text, int len)
00342 {
00343 return partymember_msg(p, NULL, text, len);
00344 }
00345
00346 int partymember_msg(partymember_t *p, botnet_entity_t *src, const char *text, int len)
00347 {
00348 if (!p || p->flags & PARTY_DELETED) return(-1);
00349
00350 if (len < 0) len = strlen(text);
00351 if (p->handler && p->handler->on_privmsg)
00352 p->handler->on_privmsg(p->client_data, p, src, text, len);
00353 else if (p->bot && p->bot->direction->handler && p->bot->direction->handler->on_privmsg)
00354 p->bot->direction->handler->on_privmsg(p->bot->direction->client_data, src, p, text, len);
00355 return 0;
00356 }
00357
00358 int partymember_local_broadcast(botnet_entity_t *src, const char *text, int len)
00359 {
00360 partymember_t *p;
00361
00362 if (len < 0) len = strlen(text);
00363 for (p = local_party_head; p; p = p->next_on_bot) {
00364 if (p->flags & PARTY_DELETED) continue;
00365 partymember_msg(p, src, text, len);
00366 }
00367 return 0;
00368 }
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386 int partymember_printf(partymember_t *p, const char *fmt, ...)
00387 {
00388 va_list args;
00389 char *ptr, buf[1024];
00390 int len;
00391
00392 va_start(args, fmt);
00393 ptr = egg_mvsprintf(buf, sizeof(buf), &len, fmt, args);
00394 va_end(args);
00395
00396 partymember_write(p, ptr, len);
00397
00398 if (ptr != buf) free(ptr);
00399 return(0);
00400 }
00401
00402 int partymember_msgf(partymember_t *p, botnet_entity_t *src, const char *fmt, ...)
00403 {
00404 va_list args;
00405 char *ptr, buf[1024];
00406 int len;
00407
00408 va_start(args, fmt);
00409 ptr = egg_mvsprintf(buf, sizeof(buf), &len, fmt, args);
00410 va_end(args);
00411
00412 partymember_msg(p, src, ptr, len);
00413
00414 if (ptr != buf) free(ptr);
00415 return(0);
00416 }
00417
00418 static int on_udelete(user_t *u)
00419 {
00420 partymember_t *p;
00421
00422 for (p = local_party_head; p; p = p->next_on_bot) {
00423 if (p->user == u) partymember_delete(p, NULL, "User deleted!");
00424 }
00425 return(0);
00426 }
00427
00438 int partymember_count_by_bot(const struct botnet_bot *bot)
00439 {
00440 int ret = 0;
00441 partymember_t *p;
00442
00443 for (p = bot ? bot->partys : local_party_head; p; p = p->next_on_bot) {
00444 if (p->flags & PARTY_DELETED) continue;
00445 ++ret;
00446 }
00447 return ret;
00448 }
00449
00462 int partymember_delete_by_bot(const botnet_bot_t *bot, const botnet_bot_t *lost_bot, const char *reason)
00463 {
00464 int ret = 0;
00465 partymember_t *p;
00466
00467 for (p = bot ? bot->partys : local_party_head; p; p = p->next_on_bot) {
00468 if (p->flags & PARTY_DELETED) continue;
00469 partymember_delete(p, lost_bot, reason);
00470 ++ret;
00471 }
00472 return ret;
00473 }