/* Returns memberfields if the nick is in the member list. */ memberlist *ismember(struct chanset_t *chan, const char *nick) { register memberlist *x = NULL; if (chan && nick && nick[0]) for (x = chan->channel.member; x && x->nick[0]; x = x->next) if (!rfc_casecmp(x->nick, nick)) return x; return NULL; }
/* Check for expired timed-invites. */ static void check_expired_invites(void) { maskrec *u, *u2; struct chanset_t *chan; masklist *b; if (!use_invites) return; for (u = global_invites; u; u = u2) { u2 = u->next; if (!(u->flags & MASKREC_PERM) && (now >= u->expire)) { putlog(LOG_MISC, "*", "%s %s (%s)", INVITES_NOLONGER, u->mask, MISC_EXPIRED); for (chan = chanset; chan; chan = chan->next) if (!(chan->channel.mode & CHANINV)) for (b = chan->channel.invite; b->mask[0]; b = b->next) if (!rfc_casecmp(b->mask, u->mask) && expired_mask(chan, b->who) && b->timer != now) { add_mode(chan, '-', 'I', u->mask); b->timer = now; } u_delinvite(NULL, u->mask, 1); } } /* Check for specific channel-domain invites expiring */ for (chan = chanset; chan; chan = chan->next) { for (u = chan->invites; u; u = u2) { u2 = u->next; if (!(u->flags & MASKREC_PERM) && (now >= u->expire)) { putlog(LOG_MISC, "*", "%s %s %s %s (%s)", INVITES_NOLONGER, u->mask, MISC_ONLOCALE, chan->dname, MISC_EXPIRED); if (!(chan->channel.mode & CHANINV)) for (b = chan->channel.invite; b->mask[0]; b = b->next) if (!rfc_casecmp(b->mask, u->mask) && expired_mask(chan, b->who) && b->timer != now) { add_mode(chan, '-', 'I', u->mask); b->timer = now; } u_delinvite(chan, u->mask, 1); } } } }
static int u_delinvite(struct chanset_t *c, char *who, int doit) { int j, i = 0; maskrec *t; maskrec **u = c ? &(c->invites) : &global_invites; char temp[256]; if (!strchr(who, '!') && str_isdigit(who)) { j = atoi(who); j--; for (; (*u) && j; u = &((*u)->next), j--); if (*u) { strncpyz(temp, (*u)->mask, sizeof temp); i = 1; } else return -j - 1; } else { /* Find matching host, if there is one */ for (; *u && !i; u = &((*u)->next)) if (!rfc_casecmp((*u)->mask, who)) { strncpyz(temp, who, sizeof temp); i = 1; break; } if (!*u) return 0; } if (i && doit) { if (!noshare) { char *mask = str_escape(temp, ':', '\\'); if (mask) { /* Distribute chan invites differently */ if (c) shareout(c, "-invc %s %s\n", c->dname, mask); else shareout(NULL, "-inv %s\n", mask); nfree(mask); } } if (lastdeletedmask) nfree(lastdeletedmask); lastdeletedmask = nmalloc(strlen((*u)->mask) + 1); strcpy(lastdeletedmask, (*u)->mask); nfree((*u)->mask); if ((*u)->desc) nfree((*u)->desc); if ((*u)->user) nfree((*u)->user); t = *u; *u = (*u)->next; nfree(t); } return i; }
/* Got nick change. */ static int gotnick(char *from, char *msg) { char *nick, *alt = get_altbotnick(); nick = splitnick(&from); fixcolon(msg); check_queues(nick, msg); if (match_my_nick(nick)) { /* Regained nick! */ strncpyz(botname, msg, NICKLEN); altnick_char = 0; if (!strcmp(msg, origbotname)) { putlog(LOG_SERV | LOG_MISC, "*", "Regained nickname '%s'.", msg); nick_juped = 0; } else if (alt[0] && !strcmp(msg, alt)) putlog(LOG_SERV | LOG_MISC, "*", "Regained alternate nickname '%s'.", msg); else if (keepnick && strcmp(nick, msg)) { putlog(LOG_SERV | LOG_MISC, "*", "Nickname changed to '%s'???", msg); if (!rfc_casecmp(nick, origbotname)) { putlog(LOG_MISC, "*", IRC_GETORIGNICK, origbotname); dprintf(DP_SERVER, "NICK %s\n", origbotname); } else if (alt[0] && !rfc_casecmp(nick, alt) && egg_strcasecmp(botname, origbotname)) { putlog(LOG_MISC, "*", IRC_GETALTNICK, alt); dprintf(DP_SERVER, "NICK %s\n", alt); } } else putlog(LOG_SERV | LOG_MISC, "*", "Nickname changed to '%s'???", msg); } else if ((keepnick) && (rfc_casecmp(nick, msg))) { /* Only do the below if there was actual nick change, case doesn't count */ if (!rfc_casecmp(nick, origbotname)) { putlog(LOG_MISC, "*", IRC_GETORIGNICK, origbotname); dprintf(DP_SERVER, "NICK %s\n", origbotname); } else if (alt[0] && !rfc_casecmp(nick, alt) && egg_strcasecmp(botname, origbotname)) { putlog(LOG_MISC, "*", IRC_GETALTNICK, altnick); dprintf(DP_SERVER, "NICK %s\n", altnick); } } return 0; }
/* Merge of u_equals_ban(), u_equals_exempt() and u_equals_invite(). * * Returns: * 0 not a ban * 1 temporary ban * 2 perm ban */ static int u_equals_mask(maskrec *u, char *mask) { for (; u; u = u->next) if (!rfc_casecmp(u->mask, mask)) { if (u->flags & MASKREC_PERM) return 2; else return 1; } return 0; }
static char * log_create_pathname (char *servname, char *channame, char *netname) { char fname[384]; char fnametime[384]; time_t now; if (!netname) { netname = g_strdup ("NETWORK"); } else { netname = log_create_filename (netname); } /* first, everything is in UTF-8 */ if (!rfc_casecmp (channame, servname)) { channame = g_strdup ("server"); } else { channame = log_create_filename (channame); } servname = log_create_filename (servname); log_insert_vars (fname, sizeof (fname), prefs.hex_irc_logmask, channame, netname, servname); g_free (channame); g_free (netname); g_free (servname); /* insert time/date */ now = time (NULL); strftime_utf8 (fnametime, sizeof (fnametime), fname, now); /* If one uses log mask variables, such as "%c/...", %c will be empty upon * connecting since there's no channel name yet, so we have to make sure * we won't try to write to the FS root. */ if (g_path_is_absolute (prefs.hex_irc_logmask)) { g_snprintf (fname, sizeof (fname), "%s", fnametime); } else /* relative path */ { g_snprintf (fname, sizeof (fname), "%s" G_DIR_SEPARATOR_S "logs" G_DIR_SEPARATOR_S "%s", get_xdir (), fnametime); } /* create all the subdirectories */ mkdir_p (fname); return g_strdup (fname); }
static char * log_create_pathname (char *servname, char *channame, char *netname) { char fname[384]; char fnametime[384]; char *fs; struct tm *tm; time_t now; if (!netname) { netname = "NETWORK"; } /* first, everything is in UTF-8 */ if (!rfc_casecmp (channame, servname)) { channame = strdup ("server"); } else { channame = log_create_filename (channame); } log_insert_vars (fname, sizeof (fname), prefs.logmask, channame, netname, servname); free (channame); /* insert time/date */ now = time (NULL); tm = localtime (&now); strftime (fnametime, sizeof (fnametime), fname, tm); /* create final path/filename */ if (logmask_is_fullpath ()) { snprintf (fname, sizeof (fname), "%s", fnametime); } else /* relative path */ { snprintf (fname, sizeof (fname), "%s/logs/%s", get_xdir_utf8 (), fnametime); } /* now we need it in FileSystem encoding */ fs = xchat_filename_from_utf8 (fname, -1, 0, 0, 0); /* create all the subdirectories */ if (fs) { mkdir_p (fs); } return fs; }
/* Clear the user pointer of a specific nick in the chanlists. * * Necessary when a hostmask is added/removed, a nick changes, etc. * Does not completely invalidate the channel cache like clear_chanlist(). */ void clear_chanlist_member(const char *nick) { register memberlist *m; register struct chanset_t *chan; for (chan = chanset; chan; chan = chan->next) for (m = chan->channel.member; m && m->nick[0]; m = m->next) if (!rfc_casecmp(m->nick, nick)) { m->user = NULL; m->tried_getuser = 0; break; } }
static char * log_create_pathname (char *servname, char *channame, char *netname) { char fname[384]; char fnametime[384]; struct tm *tm; time_t now; if (!netname) { netname = strdup ("NETWORK"); } else { netname = log_create_filename (netname); } /* first, everything is in UTF-8 */ if (!rfc_casecmp (channame, servname)) { channame = strdup ("server"); } else { channame = log_create_filename (channame); } log_insert_vars (fname, sizeof (fname), prefs.hex_irc_logmask, channame, netname, servname); free (channame); free (netname); /* insert time/date */ now = time (NULL); tm = localtime (&now); strftime_validated (fnametime, sizeof (fnametime), fname, tm); /* create final path/filename */ if (logmask_is_fullpath ()) { snprintf (fname, sizeof (fname), "%s", fnametime); } else /* relative path */ { snprintf (fname, sizeof (fname), "%s" G_DIR_SEPARATOR_S "logs" G_DIR_SEPARATOR_S "%s", get_xdir (), fnametime); } /* create all the subdirectories */ mkdir_p (fname); return g_strdup(fname); }
static int notify_netcmp (char *str, void *serv) { char *net = despacify_dup (server_get_network (serv, TRUE)); if (rfc_casecmp (str, net) == 0) { free (net); return 0; /* finish & return FALSE from token_foreach() */ } free (net); return 1; /* keep going... */ }
/* If this user@host is in a channel, set it (it was null) */ void set_chanlist(const char *host, struct userrec *rec) { char *nick, *uhost, buf[UHOSTLEN]; register memberlist *m; register struct chanset_t *chan; strncpyz(buf, host, sizeof buf); uhost = buf; nick = splitnick(&uhost); for (chan = chanset; chan; chan = chan->next) for (m = chan->channel.member; m && m->nick[0]; m = m->next) if (!rfc_casecmp(nick, m->nick) && !egg_strcasecmp(uhost, m->userhost)) m->user = rec; }
void set_user_flagrec(struct userrec *u, struct flag_record *fr, char *chname) { struct chanuserrec *cr = NULL; int oldflags = fr->match; char buffer[100]; struct chanset_t *ch; if (!u) return; if (oldflags & FR_GLOBAL) { u->flags = fr->global; u->flags_udef = fr->udef_global; if (!noshare && !(u->flags & USER_UNSHARED)) { fr->match = FR_GLOBAL; build_flags(buffer, fr, NULL); shareout(NULL, "a %s %s\n", u->handle, buffer); } } if ((oldflags & FR_BOT) && (u->flags & USER_BOT)) set_user(&USERENTRY_BOTFL, u, (void *) fr->bot); /* dont share bot attrs */ if ((oldflags & FR_CHAN) && chname) { for (cr = u->chanrec; cr; cr = cr->next) if (!rfc_casecmp(chname, cr->channel)) break; ch = findchan(chname); if (!cr && ch) { cr = user_malloc(sizeof(struct chanuserrec)); bzero(cr, sizeof(struct chanuserrec)); cr->next = u->chanrec; u->chanrec = cr; strncpy(cr->channel, chname, 80); cr->channel[80] = 0; } if (cr && ch) { cr->flags = fr->chan; cr->flags_udef = fr->udef_chan; if (!noshare && !(u->flags & USER_UNSHARED) && channel_shared(ch)) { fr->match = FR_CHAN; build_flags(buffer, fr, NULL); shareout(ch, "a %s %s %s\n", u->handle, buffer, chname); } } } fr->match = oldflags; }
/* Shortcut for get_user_by_host -- might have user record in one * of the channel caches. */ struct userrec *check_chanlist(const char *host) { char *nick = NULL, *uhost = NULL, buf[UHOSTLEN] = ""; register memberlist *m = NULL; register struct chanset_t *chan = NULL; strlcpy(buf, host, sizeof buf); uhost = buf; nick = splitnick(&uhost); for (chan = chanset; chan; chan = chan->next) for (m = chan->channel.member; m && m->nick[0]; m = m->next) if (!rfc_casecmp(nick, m->nick) && !strcasecmp(uhost, m->userhost)) return m->user; return NULL; }
static int gotkick(char *from, char *msg) { char *nick; nick = from; if (rfc_casecmp(nick, botname)) /* Not my kick, I don't need to bother about it. */ return 0; if (use_penalties) { last_time += 2; if (raw_log) putlog(LOG_SRVOUT, "*", "adding 2secs penalty (successful kick)"); } return 0; }
static void mns_chan(int idx, char *par, char *bot) { char *chname = NULL, buf2[1024] = ""; struct chanset_t *chan = NULL; int i; if (!bot) putlog(LOG_CMDS, "*", "#%s# -chan %s", dcc[idx].nick, par); if (!par[0]) { dprintf(idx, "Usage: -chan [%s]<channel>\n", CHANMETA); return; } chname = newsplit(&par); simple_snprintf(buf2, sizeof(buf2), "cpart %s %s", chname, bot ? bot : "*"); if (bot) /* bot will just set it +inactive */ putbot(bot, buf2); else putallbots(buf2); chan = findchan_by_dname(chname); if (!chan) { if ((chan = findchan(chname))) dprintf(idx, "That channel exists with a short name of %s, use that.\n", chan->dname); else dprintf(idx, "That channel doesn't exist!\n"); return; } if (!bot) { for (i = 0; i < dcc_total; i++) { if (dcc[i].type && (dcc[i].type->flags & DCT_CHAT) && !rfc_casecmp(dcc[i].u.chat->con_chan, chan->dname)) { dprintf(i, "%s is no longer a valid channel, changing your console to '*'\n", chname); strlcpy(dcc[i].u.chat->con_chan, "*", 2); console_dostore(i, 0); } } remove_channel(chan); if (conf.bot->hub) write_userfile(idx); dprintf(idx, "Channel %s removed from the botnet.\n", chname); dprintf(idx, "This includes any channel specific bans, invites, exemptions and user records that you set.\n"); } else dprintf(idx, "Channel %s removed from the bot: %s\n", chname, bot); }
void get_user_flagrec(struct userrec *u, struct flag_record *fr, char *chname) { struct chanuserrec *cr = NULL; if (!u) { fr->global = fr->udef_global = fr->chan = fr->udef_chan = fr->bot = 0; return; } if (fr->match & FR_GLOBAL) { fr->global = u->flags; fr->udef_global = u->flags_udef; } else { fr->global = 0; fr->udef_global = 0; } if (fr->match & FR_BOT) { fr->bot = (long) get_user(&USERENTRY_BOTFL, u); } else fr->bot = 0; if (fr->match & FR_CHAN) { if (fr->match & FR_ANYWH) { fr->chan = u->flags; fr->udef_chan = u->flags_udef; for (cr = u->chanrec; cr; cr = cr->next) if (findchan(cr->channel)) { fr->chan |= cr->flags; fr->udef_chan |= cr->flags_udef; } } else { if (chname) for (cr = u->chanrec; cr; cr = cr->next) if (!rfc_casecmp(chname, cr->channel)) break; if (chname && cr) { fr->chan = cr->flags; fr->udef_chan = cr->flags_udef; } else { fr->chan = 0; fr->udef_chan = 0; } } } }
static void got_unexempt(struct chanset_t *chan, char *nick, char *from, char *who, char *ch, struct userrec *u) { masklist *e = chan->channel.exempt, *old = NULL; masklist *b; int match = 0; while (e && e->mask[0] && rfc_casecmp(e->mask, who)) { old = e; e = e->next; } if (e && e->mask[0]) { if (old) old->next = e->next; else chan->channel.exempt = e->next; nfree(e->mask); nfree(e->who); nfree(e); } check_tcl_mode(nick, from, u, chan->dname, "-e", who); if (!(chan = modebind_refresh(ch, from, &user, NULL, NULL))) return; if (channel_pending(chan)) return; if (u_sticky_mask(chan->exempts, who) || u_sticky_mask(global_exempts, who)) add_mode(chan, '+', 'e', who); /* If exempt was removed by master then leave it else check for bans */ if (!nick[0] && glob_bot(user) && !glob_master(user) && !chan_master(user)) { b = chan->channel.ban; while (b->mask[0] && !match) { if (mask_match(b->mask, who)) { add_mode(chan, '+', 'e', who); match = 1; } else b = b->next; } } if ((u_equals_mask(global_exempts, who) || u_equals_mask(chan->exempts, who)) && me_op(chan) && !channel_dynamicexempts(chan) && (!glob_bot(user) || !(bot_flags(u) & BOT_SHARE))) add_mode(chan, '+', 'e', who); }
/* Adds a ban, exempt or invite mask to the list * m should be chan->channel.(exempt|invite|ban) */ static void newmask(masklist *m, char *s, char *who) { for (; m && m->mask[0] && rfc_casecmp(m->mask, s); m = m->next); if (m->mask[0]) return; /* Already existent mask */ m->next = (masklist *) channel_malloc(sizeof(masklist)); m->next->next = NULL; m->next->mask = (char *) channel_malloc(1); m->next->mask[0] = 0; nfree(m->mask); m->mask = (char *) channel_malloc(strlen(s) + 1); strcpy(m->mask, s); m->who = (char *) channel_malloc(strlen(who) + 1); strcpy(m->who, who); m->timer = now; }
/* We try to change to a preferred unique nick here. We always first try the * specified alternate nick. If that failes, we repeatedly modify the nick * until it gets accepted. * * sent nick: * "<altnick><c>" * ^--- additional count character: 1-9^-_\\[]`a-z * ^--------- given, alternate nick * * The last added character is always saved in altnick_char. At the very first * attempt (were altnick_char is 0), we try the alternate nick without any * additions. * * fixed by guppy (1999/02/24) and Fabian (1999/11/26) */ static int gotfake433(char *from) { int l = strlen(botname) - 1; /* First run? */ if (altnick_char == 0) { char *alt = get_altbotnick(); if (alt[0] && (rfc_casecmp(alt, botname))) /* Alternate nickname defined. Let's try that first. */ strcpy(botname, alt); else { /* Fall back to appending count char. */ altnick_char = '0'; if ((l + 1) == nick_len) { botname[l] = altnick_char; } else { botname[++l] = altnick_char; botname[l + 1] = 0; } } /* No, we already tried the default stuff. Now we'll go through variations * of the original alternate nick. */ } else { char *oknicks = "^-_\\[]`"; char *p = strchr(oknicks, altnick_char); if (p == NULL) { if (altnick_char == '9') altnick_char = oknicks[0]; else altnick_char = altnick_char + 1; } else { p++; if (!*p) altnick_char = 'a' + randint(26); else altnick_char = (*p); } botname[l] = altnick_char; } putlog(LOG_MISC, "*", IRC_BOTNICKINUSE, botname); dprintf(DP_MODE, "NICK %s\n", botname); return 0; }
/* ignore_exists (): * returns: struct ig, if this mask is in the ignore list already * NULL, otherwise */ struct ignore * ignore_exists (char *mask) { struct ignore *ig = NULL; GSList *list; list = ignore_list; while (list) { ig = (struct ignore *) list->data; if (!rfc_casecmp (ig->mask, mask)) return ig; list = list->next; } return NULL; }
/* handonanychan(): * checks if the given user is on any channel (no matter under which nick) */ static struct chanset_t *handonanychan(char *hand) { struct chanset_t *ch; memberlist *m; for (ch = chanset; ch; ch = ch->next) { if (ch->channel.members > 0) { for (m = ch->channel.member; m; m = m->next) { if (m->user) { if (m->user->handle && !rfc_casecmp(m->user->handle, hand)) return ch; } } } } return NULL; }
void set_user_flagrec(struct userrec *u, struct flag_record *fr, const char *chname) { if (!u) return; struct chanuserrec *cr = NULL; flag_t oldflags = fr->match; char buffer[100] = ""; struct chanset_t *ch; if (oldflags & FR_GLOBAL) { u->flags = fr->global; if (!noshare) { fr->match = FR_GLOBAL; build_flags(buffer, fr, NULL); shareout("a %s %s\n", u->handle, buffer); } } if ((oldflags & FR_CHAN) && chname) { for (cr = u->chanrec; cr; cr = cr->next) if (!rfc_casecmp(chname, cr->channel)) break; ch = findchan_by_dname(chname); if (!cr && ch) { cr = (struct chanuserrec *) my_calloc(1, sizeof(struct chanuserrec)); cr->next = u->chanrec; u->chanrec = cr; strlcpy(cr->channel, chname, sizeof cr->channel); } if (cr && ch) { cr->flags = fr->chan; if (!noshare) { fr->match = FR_CHAN; build_flags(buffer, fr, NULL); shareout("a %s %s %s\n", u->handle, buffer, chname); } } } fr->match = oldflags; }
/* handonchan(): * checks if the given user is on the channel and returns its nick */ static char *handonchan(char *hand, char *chan) { struct chanset_t *ch; memberlist *m; ch = findchan_by_dname(chan); if (!ch) return 0; if (ch->channel.members > 0) { for (m = ch->channel.member; m; m = m->next) { if (m->user) { if (m->user->handle && !rfc_casecmp(m->user->handle, hand)) return m->nick; } } } return NULL; }
static int msg_ident(char *nick, char *host, struct userrec *u, char *par) { char s[UHOSTLEN] = "", s1[UHOSTLEN] = "", *pass = NULL, who[HANDLEN + 1] = ""; struct userrec *u2 = NULL; if (match_my_nick(nick) || (u && u->bot)) return BIND_RET_BREAK; pass = newsplit(&par); if (!par[0]) strlcpy(who, nick, sizeof(who)); else { strlcpy(who, par, sizeof(who)); } bd::String msg; u2 = get_user_by_handle(userlist, who); if (u2 && rfc_casecmp(who, origbotname) && !u2->bot) { /* This could be used as detection... */ if (u_pass_match(u2, "-")) { putlog(LOG_CMDS, "*", "(%s!%s) !*! IDENT %s", nick, host, who); } else if (!u_pass_match(u2, pass)) { putlog(LOG_CMDS, "*", "(%s!%s) !*! failed IDENT %s", nick, host, who); return BIND_RET_BREAK; } else if (u == u2) { notice(nick, "I recognize you there.", DP_HELP); return BIND_RET_BREAK; } else if (u) { msg = bd::String::printf("You're not %s, you're %s.", who, u->handle); notice(nick, msg.c_str(), DP_HELP); return BIND_RET_BREAK; } else { putlog(LOG_CMDS, "*", "(%s!%s) !*! IDENT %s", nick, host, who); simple_snprintf(s, sizeof s, "%s!%s", nick, host); maskaddr(s, s1, 0); /* *!user@host */ msg = bd::String::printf("Added hostmask: %s", s1); notice(nick, msg.c_str(), DP_HELP); addhost_by_handle(who, s1); check_this_user(who, 0, NULL); return BIND_RET_BREAK; } } putlog(LOG_CMDS, "*", "(%s!%s) !*! failed IDENT %s", nick, host, who); return BIND_RET_BREAK; }
/* Expire mask originally set by `who' on `chan'? * * We might not want to expire masks in all cases, as other bots * often tend to immediately reset masks they've listed in their * internal ban list, making it quite senseless for us to remove * them in the first place. * * Returns 1 if a mask on `chan' by `who' may be expired and 0 if * not. */ static int expired_mask(struct chanset_t *chan, char *who) { memberlist *m, *m2; char buf[UHOSTLEN], *snick, *sfrom; struct userrec *u; /* Always expire masks, regardless of who set it? */ if (force_expire) return 1; strcpy(buf, who); sfrom = buf; snick = splitnick(&sfrom); if (!snick[0]) return 1; m = ismember(chan, snick); if (!m) for (m2 = chan->channel.member; m2 && m2->nick[0]; m2 = m2->next) if (!egg_strcasecmp(sfrom, m2->userhost)) { m = m2; break; } if (!m || !chan_hasop(m) || !rfc_casecmp(m->nick, botname)) return 1; /* At this point we know the person/bot who set the mask is currently * present in the channel and has op. */ if (m->user) u = m->user; else { simple_sprintf(buf, "%s!%s", m->nick, m->userhost); u = get_user_by_host(buf); } /* Do not expire masks set by bots. */ if (u && u->flags & USER_BOT) return 0; else return 1; }
static char* log_create_pathname(char *servname, char *channame, char *netname) { char fname[384]; char fnametime[384]; char *fs; tm *tm; time_t now; if (!netname) netname = "NETWORK"; // first, everything is in UTF-8 if (!rfc_casecmp(channame, servname)) channame = strdup("server"); else channame = log_create_filename(channame); log_insert_vars(fname, sizeof(fname), prefs.logmask, channame, netname, servname); free(channame); // insert time/date now = time(nullptr); tm = localtime(&now); strftime(fnametime, sizeof(fnametime), fname, tm); // create final path/filename #ifdef WIN32 if (fnametime[0] == '/' || (fnametime[0] >= 'A' && fnametime[1] == ':')) #else if (fnametime[0] == '/') // is it fullpath already? #endif snprintf(fname, sizeof(fname), "%s", fnametime); else snprintf(fname, sizeof(fname), "%s/xchatlogs/%s", get_xdir_utf8(), fnametime); // now we need it in FileSystem encoding fs = xchat_filename_from_utf8(fname, -1, 0, 0, 0); // create all the subdirectories if (fs) mkdir_p(fs); return fs; }
/* Always pass the dname (display name) to this function for chname <cybah> */ void get_user_flagrec(struct userrec *u, struct flag_record *fr, const char *chname, const struct chanset_t* chan) { fr->bot = 0; if (!u) { fr->global = fr->chan = 0; return; } if (u->bot) fr->bot = 1; fr->global = (fr->match & FR_GLOBAL) ? u->flags : 0; if (fr->match & FR_CHAN) { struct chanuserrec *cr = NULL; if ((fr->match & FR_ANYWH) || (fr->match & FR_ANYCH)) { if (fr->match & FR_ANYWH) fr->chan = u->flags; for (cr = u->chanrec; cr; cr = cr->next) { if (chan || findchan_by_dname(cr->channel)) { fr->chan |= cr->flags; } } } else { if (chname) { for (cr = u->chanrec; cr; cr = cr->next) { if (!rfc_casecmp(chname, cr->channel)) break; } } if (cr) { fr->chan = cr->flags; } else { fr->chan = 0; } } } }
static void del_chanrec(struct userrec *u, char *chname) { struct chanuserrec *ch = u->chanrec, *lst = NULL; while (ch) { if (!rfc_casecmp(chname, ch->channel)) { if (lst == NULL) u->chanrec = ch->next; else lst->next = ch->next; if (ch->info != NULL) nfree(ch->info); nfree(ch); if (!noshare && !(u->flags & USER_UNSHARED)) shareout(findchan_by_dname(chname), "-cr %s %s\n", u->handle, chname); return; } lst = ch; ch = ch->next; } }
/* Set sticky attribute for a mask. */ static int u_setsticky_mask(struct chanset_t *chan, maskrec *u, char *uhost, int sticky, char *botcmd) { int j; if (str_isdigit(uhost)) j = atoi(uhost); else j = -1; while (u) { if (j >= 0) j--; if (!j || ((j < 0) && !rfc_casecmp(u->mask, uhost))) { if (sticky > 0) u->flags |= MASKREC_STICKY; else if (!sticky) u->flags &= ~MASKREC_STICKY; else /* We don't actually want to change, just skip over */ return 0; if (!j) strcpy(uhost, u->mask); if (!noshare) shareout(chan, "%s %s %d %s\n", botcmd, uhost, sticky, (chan) ? chan->dname : ""); return 1; } u = u->next; } if (j >= 0) return -j; return 0; }
/* Removes a nick from the channel member list (returns 1 if successful) */ static int killmember(struct chanset_t *chan, char *nick) { memberlist *x, *old; old = NULL; for (x = chan->channel.member; x && x->nick[0]; old = x, x = x->next) if (!rfc_casecmp(x->nick, nick)) break; if (!x || !x->nick[0]) { if (!channel_pending(chan) && !channel_djoins(chan)) putlog(LOG_MISC, "*", "(!) killmember(%s) -> nonexistent", nick); return 0; } if (old) old->next = x->next; else chan->channel.member = x->next; nfree(x); chan->channel.members--; /* The following two errors should NEVER happen. We will try to correct * them though, to keep the bot from crashing. */ if (chan->channel.members < 0) { chan->channel.members = 0; for (x = chan->channel.member; x && x->nick[0]; x = x->next) chan->channel.members++; putlog(LOG_MISC, "*", "(!) actually I know of %d members.", chan->channel.members); } if (!chan->channel.member) { chan->channel.member = (memberlist *) channel_malloc(sizeof(memberlist)); chan->channel.member->nick[0] = 0; chan->channel.member->next = NULL; } return 1; }