X-Git-Url: http://git.pk910.de/?p=NeonServV5.git;a=blobdiff_plain;f=src%2Fmodules%2FNeonServ.mod%2Fcmd_neonserv_nicklist.c;h=5043f42fc653fe338c4bba74c5a38d85053762a4;hp=181923c45e611760fefbfc60c5bc28260e0824b3;hb=0c695128d9b6a81f2e8a11e35ef2c785e2bfea16;hpb=706e48b1e666054030c491d864f740071e390038 diff --git a/src/modules/NeonServ.mod/cmd_neonserv_nicklist.c b/src/modules/NeonServ.mod/cmd_neonserv_nicklist.c index 181923c..5043f42 100644 --- a/src/modules/NeonServ.mod/cmd_neonserv_nicklist.c +++ b/src/modules/NeonServ.mod/cmd_neonserv_nicklist.c @@ -1,4 +1,4 @@ -/* cmd_neonserv_nicklist.c - NeonServ v5.3 +/* cmd_neonserv_nicklist.c - NeonServ v5.6 * Copyright (C) 2011-2012 Philipp Kreil (pk910) * * This program is free software: you can redistribute it and/or modify @@ -22,37 +22,46 @@ * argv[1] (optional) nick mask */ static USERLIST_CALLBACK(neonserv_cmd_nicklist_userlist_lookup); -static void neonserv_cmd_nicklist_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *nickmask, int syncusers); +static void neonserv_cmd_nicklist_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *nickmask, int flags); static void neonserv_cmd_nicklist_synchronize_user(struct ChanNode *chan, struct UserNode *user, int access); +#define NEONSERV_CMD_NICKLIST_FLAG_SYNCUSERS 0x01 +#define NEONSERV_CMD_NICKLIST_FLAG_NOWHO 0x02 +#define NEONSERV_CMD_NICKLIST_FLAG_VISCOUNT 0x04 + struct neonserv_cmd_nicklist_cache { struct ClientSocket *client, *textclient; struct UserNode *user; struct Event *event; char *nickmask; - int syncusers; + int flags; }; CMD_BIND(neonserv_cmd_nicklist) { - int syncusers = 0; - if(argc && !stricmp(argv[0], "sync")) { - if(!checkChannelAccess(user, chan, "channel_canadd", 0)) { - if(isGodMode(user)) { - event->flags |= CMDFLAG_OPLOG; - } else { - reply(getTextBot(), user, "NS_ACCESS_DENIED"); - return; + int flags = 0; + while(argc) { + if(!stricmp(argv[0], "sync")) { + if(!checkChannelAccess(user, chan, "channel_canadd", 0)) { + if(isGodMode(user)) { + event->flags |= CMDFLAG_OPLOG; + } else { + reply(textclient, user, "NS_ACCESS_DENIED"); + return; + } } - } + flags |= NEONSERV_CMD_NICKLIST_FLAG_SYNCUSERS; + event->flags |= CMDFLAG_LOG; + } else if(argc && !stricmp(argv[0], "nowho") && isGodMode(user)) { + flags |= NEONSERV_CMD_NICKLIST_FLAG_NOWHO; + } else if(argc && !stricmp(argv[0], "viscount") && isGodMode(user)) { + flags |= NEONSERV_CMD_NICKLIST_FLAG_VISCOUNT; + } else + break; argv++; argc--; - syncusers = 1; - event->flags |= CMDFLAG_LOG; } - if(argc && !stricmp(argv[0], "nowho") && isGodMode(user)) { - argv++; - argc--; - neonserv_cmd_nicklist_async1(client, getTextBot(), user, chan, event, (argc ? argv[0] : NULL), syncusers); + if(flags & NEONSERV_CMD_NICKLIST_FLAG_NOWHO) { + neonserv_cmd_nicklist_async1(client, textclient, user, chan, event, (argc ? argv[0] : NULL), flags); return; } struct neonserv_cmd_nicklist_cache *cache = malloc(sizeof(*cache)); @@ -61,44 +70,88 @@ CMD_BIND(neonserv_cmd_nicklist) { return; } cache->client = client; - cache->textclient = getTextBot(); + cache->textclient = textclient; cache->user = user; cache->event = event; if(argc) { cache->nickmask = strdup(argv[0]); } else cache->nickmask = NULL; - cache->syncusers = syncusers; - get_userlist_with_invisible(chan, neonserv_cmd_nicklist_userlist_lookup, cache); + cache->flags = flags; + get_userlist_with_invisible(chan, module_id, neonserv_cmd_nicklist_userlist_lookup, cache); } static USERLIST_CALLBACK(neonserv_cmd_nicklist_userlist_lookup) { struct neonserv_cmd_nicklist_cache *cache = data; - neonserv_cmd_nicklist_async1(cache->client, cache->textclient, cache->user, chan, cache->event, cache->nickmask, cache->syncusers); + neonserv_cmd_nicklist_async1(cache->client, cache->textclient, cache->user, chan, cache->event, cache->nickmask, cache->flags); if(cache->nickmask) free(cache->nickmask); free(cache); } -static void neonserv_cmd_nicklist_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *nickmask, int syncusers) { +static int neonserv_cmd_nicklist_sort_flags[] = { + CHANUSERFLAG_OPPED | CHANUSERFLAG_HALFOPPED | CHANUSERFLAG_VOICED, + CHANUSERFLAG_OPPED | CHANUSERFLAG_HALFOPPED, + CHANUSERFLAG_OPPED | CHANUSERFLAG_VOICED, + CHANUSERFLAG_OPPED, + CHANUSERFLAG_HALFOPPED | CHANUSERFLAG_VOICED, + CHANUSERFLAG_HALFOPPED, + CHANUSERFLAG_VOICED, + CHANUSERFLAG_INVISIBLE, + 0 +}; + +static int neonserv_cmd_nicklist_sort(const void *a, const void *b) { + const struct ChanUser *chanuser_a = *((struct ChanUser * const *) a); + const struct ChanUser *chanuser_b = *((struct ChanUser * const *) b); + int i_a = 0, i_b = 0; + while((chanuser_a->flags & (CHANUSERFLAG_OPPED | CHANUSERFLAG_VOICED | CHANUSERFLAG_INVISIBLE)) != neonserv_cmd_nicklist_sort_flags[i_a] && neonserv_cmd_nicklist_sort_flags[i_a]) + i_a++; + while((chanuser_b->flags & (CHANUSERFLAG_OPPED | CHANUSERFLAG_VOICED | CHANUSERFLAG_INVISIBLE)) != neonserv_cmd_nicklist_sort_flags[i_b] && neonserv_cmd_nicklist_sort_flags[i_b]) + i_b++; + if(i_a == i_b) { + return stricmp(chanuser_a->user->nick, chanuser_b->user->nick); + } else + return i_a - i_b; +} + +static void neonserv_cmd_nicklist_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *nickmask, int flags) { MYSQL_RES *res; MYSQL_ROW row, defaults = NULL; struct Table *table; - table = table_init(3, chan->usercount + 1, 0); - char *content[3]; + char *content[4]; + int userlistlen, i, j; + int db_enfops, db_enfvoice; + int caccess, synced_user, accessbufpos; + struct ChanUser *chanusers[chan->usercount]; + struct ChanUser *chanuser; + struct ClientSocket *bot; + int chanuser_count; + char statebuf[5]; + char accessbuf[50]; + char viscountbuf[5]; + int uaccess; + + i = 3; + if(flags & NEONSERV_CMD_NICKLIST_FLAG_VISCOUNT) { + i++; + content[3] = "VisCount"; + } + table = table_init(i, chan->usercount + 1, 0); content[0] = get_language_string(user, "NS_NICKLIST_NICK"); content[1] = get_language_string(user, "NS_NICKLIST_STATE"); content[2] = get_language_string(user, "NS_NICKLIST_ACCESS"); table_add(table, content); + printf_mysql_query("SELECT `chanuser_access`, `user_user`, `chanuser_flags` FROM `chanusers` LEFT JOIN `users` ON `chanuser_uid` = `user_id` WHERE `chanuser_cid` = '%d'", chan->channel_id); res = mysql_use(); - int userlistlen = mysql_num_rows(res); - int i = 0; + userlistlen = mysql_num_rows(res); + i = 0; MYSQL_ROW userlist[userlistlen]; while ((row = mysql_fetch_row(res)) != NULL) { userlist[i++] = row; } - int db_enfops, db_enfvoice; + printf_mysql_query("SELECT `channel_getop`, `channel_getvoice` FROM `channels` WHERE `channel_id` = '%d'", chan->channel_id); row = mysql_fetch_row(mysql_use()); if(row[0] == NULL || row[1] == NULL) { @@ -107,106 +160,130 @@ static void neonserv_cmd_nicklist_async1(struct ClientSocket *client, struct Cli } db_enfops = atoi((row[0] ? row[0] : defaults[0])); db_enfvoice = atoi((row[1] ? row[1] : defaults[1])); - int caccess = getChannelAccess(user, chan); - int synced_user = 0; - struct ChanUser *chanuser; - int sort_nicklist[] = { - CHANUSERFLAG_OPPED | CHANUSERFLAG_HALFOPPED | CHANUSERFLAG_VOICED, - CHANUSERFLAG_OPPED | CHANUSERFLAG_HALFOPPED, - CHANUSERFLAG_OPPED | CHANUSERFLAG_VOICED, - CHANUSERFLAG_OPPED, - CHANUSERFLAG_HALFOPPED | CHANUSERFLAG_VOICED, - CHANUSERFLAG_HALFOPPED, - CHANUSERFLAG_VOICED, - CHANUSERFLAG_INVISIBLE, - 0 - }; - int *sort_pos = sort_nicklist; - int sort_flags; - do { - sort_flags = *(sort_pos++); - char statebuf[5]; - char accessbuf[9]; - int uaccess; - int stateset = 0; - for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) { - if((chanuser->flags & (CHANUSERFLAG_OPPED | CHANUSERFLAG_VOICED | CHANUSERFLAG_INVISIBLE)) != sort_flags) continue; - if(nickmask && match(nickmask, chanuser->user->nick)) continue; - if(!stateset) { - if((chanuser->flags & CHANUSERFLAG_INVISIBLE)) statebuf[stateset++] = '<'; - if((chanuser->flags & CHANUSERFLAG_OPPED)) statebuf[stateset++] = '@'; - if((chanuser->flags & CHANUSERFLAG_HALFOPPED)) statebuf[stateset++] = '%'; - if((chanuser->flags & CHANUSERFLAG_VOICED)) statebuf[stateset++] = '+'; - statebuf[stateset++] = '\0'; - } - content[0] = chanuser->user->nick; - content[1] = statebuf; - uaccess = 0; - if(chanuser->user->flags & USERFLAG_ISAUTHED) { - for(i = 0; i < userlistlen; i++) { - if(!stricmp(chanuser->user->auth, userlist[i][1])) { - uaccess = atoi(userlist[i][0]); - if((((chanuser->flags & CHANUSERFLAG_OPPED) && uaccess < db_enfops) || ((chanuser->flags & CHANUSERFLAG_VOICED) && uaccess < db_enfvoice)) && !isNetworkService(chanuser->user)) { - if(syncusers) { - if((chanuser->flags & CHANUSERFLAG_OPPED) && (db_enfops < caccess || isGodMode(user))) { - if(db_enfops >= caccess) - event->flags |= CMDFLAG_OPLOG; - uaccess = db_enfops; - } else if((chanuser->flags & CHANUSERFLAG_VOICED) && (caccess < db_enfvoice || isGodMode(user))) { - if(db_enfvoice >= caccess) - event->flags |= CMDFLAG_OPLOG; - uaccess = db_enfvoice; - } else { - //fail... - sprintf(accessbuf, "\00307%d\003", uaccess); - break; - } - neonserv_cmd_nicklist_synchronize_user(chan, chanuser->user, uaccess); - sprintf(accessbuf, "\00309%d\003", uaccess); - synced_user = 1; + + chanuser_count = 0; + for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) { + if(nickmask && match(nickmask, chanuser->user->nick)) continue; + chanusers[chanuser_count++] = chanuser; + } + qsort(chanusers, chanuser_count, sizeof(struct ChanUser *), neonserv_cmd_nicklist_sort); + + caccess = getChannelAccess(user, chan); + synced_user = 0; + for(i = 0; i < chanuser_count; i++) { + chanuser = chanusers[i]; + + content[0] = chanuser->user->nick; + + j = 0; + if((chanuser->flags & CHANUSERFLAG_INVISIBLE)) statebuf[j++] = '<'; + if((chanuser->flags & CHANUSERFLAG_OPPED)) statebuf[j++] = '@'; + if((chanuser->flags & CHANUSERFLAG_HALFOPPED)) statebuf[j++] = '%'; + if((chanuser->flags & CHANUSERFLAG_VOICED)) statebuf[j++] = '+'; + statebuf[j++] = '\0'; + content[1] = statebuf; + + uaccess = 0; + if(chanuser->user->flags & USERFLAG_ISAUTHED) { + for(j = 0; j < userlistlen; j++) { + if(!stricmp(chanuser->user->auth, userlist[j][1])) { + uaccess = atoi(userlist[j][0]); + if((((chanuser->flags & CHANUSERFLAG_OPPED) && uaccess < db_enfops) || ((chanuser->flags & CHANUSERFLAG_VOICED) && uaccess < db_enfvoice)) && !isNetworkService(chanuser->user)) { + if(flags & NEONSERV_CMD_NICKLIST_FLAG_SYNCUSERS) { + if((chanuser->flags & CHANUSERFLAG_OPPED) && (db_enfops < caccess || isGodMode(user))) { + if(db_enfops >= caccess) + event->flags |= CMDFLAG_OPLOG; + uaccess = db_enfops; + } else if((chanuser->flags & CHANUSERFLAG_VOICED) && (caccess < db_enfvoice || isGodMode(user))) { + if(db_enfvoice >= caccess) + event->flags |= CMDFLAG_OPLOG; + uaccess = db_enfvoice; } else { - synced_user = 1; - sprintf(accessbuf, "\00307%d\003", uaccess); + //fail... + accessbufpos = sprintf(accessbuf, "\00307%d\003", uaccess); + break; } - } else if((uaccess >= db_enfops && !(chanuser->flags & CHANUSERFLAG_OPPED)) || (uaccess >= db_enfvoice && !(chanuser->flags & CHANUSERFLAG_OPPED_OR_VOICED))) - sprintf(accessbuf, "\00303%d\003", uaccess); - else - sprintf(accessbuf, "%d", uaccess); - break; - } + neonserv_cmd_nicklist_synchronize_user(chan, chanuser->user, uaccess); + accessbufpos = sprintf(accessbuf, "\00309%d\003", uaccess); + synced_user = 1; + } else { + synced_user = 1; + accessbufpos = sprintf(accessbuf, "\00307%d\003", uaccess); + } + } else if((uaccess >= db_enfops && !(chanuser->flags & CHANUSERFLAG_OPPED)) || (uaccess >= db_enfvoice && !(chanuser->flags & CHANUSERFLAG_OPPED_OR_VOICED))) + accessbufpos = sprintf(accessbuf, "\00303%d\003", uaccess); + else + accessbufpos = sprintf(accessbuf, "%d", uaccess); + break; } } - if(!uaccess && (chanuser->flags & CHANUSERFLAG_OPPED_OR_VOICED) && !isNetworkService(chanuser->user)) { - if(syncusers) { - if((chanuser->flags & CHANUSERFLAG_OPPED) && (db_enfops < caccess || isGodMode(user))) { - if(db_enfops >= caccess) - event->flags |= CMDFLAG_OPLOG; - uaccess = db_enfops; - } else if((chanuser->flags & CHANUSERFLAG_VOICED) && (db_enfvoice < caccess || isGodMode(user))) { - if(db_enfvoice >= caccess) - event->flags |= CMDFLAG_OPLOG; - uaccess = db_enfvoice; - } else { - uaccess = 0; - sprintf(accessbuf, "\003040\003"); - } - if(uaccess && (chanuser->user->flags & USERFLAG_ISAUTHED)) { - neonserv_cmd_nicklist_synchronize_user(chan, chanuser->user, uaccess); - sprintf(accessbuf, "\00309%d\003", uaccess); - synced_user = 1; - } else if(uaccess) { - sprintf(accessbuf, "\003040\003"); - } + } + if(!uaccess && (chanuser->flags & CHANUSERFLAG_OPPED_OR_VOICED) && !isNetworkService(chanuser->user)) { + if(flags & NEONSERV_CMD_NICKLIST_FLAG_SYNCUSERS) { + if((chanuser->flags & CHANUSERFLAG_OPPED) && (db_enfops < caccess || isGodMode(user))) { + if(db_enfops >= caccess) + event->flags |= CMDFLAG_OPLOG; + uaccess = db_enfops; + } else if((chanuser->flags & CHANUSERFLAG_VOICED) && (db_enfvoice < caccess || isGodMode(user))) { + if(db_enfvoice >= caccess) + event->flags |= CMDFLAG_OPLOG; + uaccess = db_enfvoice; } else { + uaccess = 0; + accessbufpos = sprintf(accessbuf, "\003040\003"); + } + if(uaccess && (chanuser->user->flags & USERFLAG_ISAUTHED)) { + neonserv_cmd_nicklist_synchronize_user(chan, chanuser->user, uaccess); + accessbufpos = sprintf(accessbuf, "\00309%d\003", uaccess); synced_user = 1; - sprintf(accessbuf, "\003040\003"); + } else if(uaccess) { + accessbufpos = sprintf(accessbuf, "\003040\003"); } - } else if(!uaccess) - sprintf(accessbuf, "0"); - content[2] = accessbuf; - table_add(table, content); + } else { + synced_user = 1; + if(((chanuser->flags & CHANUSERFLAG_OPPED) && db_enfops > caccess) || ((chanuser->flags & CHANUSERFLAG_VOICED) && db_enfvoice > caccess)) + accessbufpos = sprintf(accessbuf, "\003040\003"); + else + accessbufpos = sprintf(accessbuf, "0"); + } + } else if(!uaccess) + accessbufpos = sprintf(accessbuf, "0"); + j = 0; + if(isBot(chanuser->user)) { + //check if bot is secret + for(bot = getBots(SOCKET_FLAG_READY, NULL); bot; bot = getBots(SOCKET_FLAG_READY, bot)) { + if(bot->user == chanuser->user) + break; + } + if(bot && !(bot->flags & SOCKET_FLAG_SECRET_BOT)) { + if(j) + accessbufpos += sprintf(accessbuf+accessbufpos, ", "); + else { + accessbufpos += sprintf(accessbuf+accessbufpos, " ("); + j = 1; + } + accessbufpos += sprintf(accessbuf+accessbufpos, "%s", get_language_string(user, "NS_NICKLIST_ACCESS_BOT")); + } } - } while(sort_flags != 0); + if(chanuser->user->flags & USERFLAG_ISIRCOP) { + if(j) + accessbufpos += sprintf(accessbuf+accessbufpos, ", "); + else { + accessbufpos += sprintf(accessbuf+accessbufpos, " ("); + j = 1; + } + accessbufpos += sprintf(accessbuf+accessbufpos, "%s", get_language_string(user, "NS_NICKLIST_ACCESS_OPER")); + } + if(j) + accessbufpos += sprintf(accessbuf+accessbufpos, ")"); + content[2] = accessbuf; + if(flags & NEONSERV_CMD_NICKLIST_FLAG_VISCOUNT) { + sprintf(viscountbuf, "%d", chanuser->visCount); + content[3] = viscountbuf; + } + table_add(table, content); + } + //send the table char **table_lines = table_end(table); for(i = 0; i < table->entrys; i++) { @@ -217,7 +294,7 @@ static void neonserv_cmd_nicklist_async1(struct ClientSocket *client, struct Cli reply(textclient, user, "NS_TABLE_COUNT", table->length - 1); table_free(table); if(synced_user) { - if(!syncusers) + if(!(flags & NEONSERV_CMD_NICKLIST_FLAG_SYNCUSERS)) reply(textclient, user, "NS_NICKLIST_SYNC", db_enfops, db_enfvoice); else logEvent(event);