/src/common/outbound.c
C | 4403 lines | 3707 code | 532 blank | 164 comment | 767 complexity | 6d7ca8990a04d46f3a2d711c8fec74d9 MD5 | raw file
Possible License(s): GPL-2.0
Large files files are truncated, but you can click here to view the full file
- /* X-Chat
- * Copyright (C) 1998 Peter Zelezny.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
- #define _GNU_SOURCE /* for memrchr */
- #include <string.h>
- #include <stdlib.h>
- #include <stdio.h>
- #include <ctype.h>
- #include <limits.h>
- #include <errno.h>
- #define WANTSOCKET
- #define WANTARPA
- #include "inet.h"
- #ifndef WIN32
- #include <sys/wait.h>
- #endif
- #include <unistd.h>
- #include <time.h>
- #include <signal.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- #include "xchat.h"
- #include "plugin.h"
- #include "ignore.h"
- #include "util.h"
- #include "fe.h"
- #include "cfgfiles.h" /* xchat_fopen_file() */
- #include "network.h" /* net_ip() */
- #include "modes.h"
- #include "notify.h"
- #include "inbound.h"
- #include "text.h"
- #include "xchatc.h"
- #include "servlist.h"
- #include "server.h"
- #include "tree.h"
- #include "outbound.h"
- #ifdef USE_DEBUG
- extern int current_mem_usage;
- #endif
- #define TBUFSIZE 4096
- static void help (session *sess, char *tbuf, char *helpcmd, int quiet);
- static int cmd_server (session *sess, char *tbuf, char *word[], char *word_eol[]);
- static void handle_say (session *sess, char *text, int check_spch);
- static void
- notj_msg (struct session *sess)
- {
- PrintText (sess, _("No channel joined. Try /join #<channel>\n"));
- }
- void
- notc_msg (struct session *sess)
- {
- PrintText (sess, _("Not connected. Try /server <host> [<port>]\n"));
- }
- static char *
- random_line (char *file_name)
- {
- FILE *fh;
- char buf[512];
- int lines, ran;
- if (!file_name[0])
- goto nofile;
- fh = xchat_fopen_file (file_name, "r", 0);
- if (!fh)
- {
- nofile:
- /* reason is not a file, an actual reason! */
- return strdup (file_name);
- }
- /* count number of lines in file */
- lines = 0;
- while (fgets (buf, sizeof (buf), fh))
- lines++;
- if (lines < 1)
- goto nofile;
- /* go down a random number */
- rewind (fh);
- ran = RAND_INT (lines);
- do
- {
- fgets (buf, sizeof (buf), fh);
- lines--;
- }
- while (lines > ran);
- fclose (fh);
- buf[strlen (buf) - 1] = 0; /* remove the trailing '\n' */
- return strdup (buf);
- }
- void
- server_sendpart (server * serv, char *channel, char *reason)
- {
- if (!reason)
- {
- reason = random_line (prefs.partreason);
- serv->p_part (serv, channel, reason);
- free (reason);
- } else
- {
- /* reason set by /quit, /close argument */
- serv->p_part (serv, channel, reason);
- }
- }
- void
- server_sendquit (session * sess)
- {
- char *rea, *colrea;
- if (!sess->quitreason)
- {
- colrea = strdup (prefs.quitreason);
- check_special_chars (colrea, FALSE);
- rea = random_line (colrea);
- free (colrea);
- sess->server->p_quit (sess->server, rea);
- free (rea);
- } else
- {
- /* reason set by /quit, /close argument */
- sess->server->p_quit (sess->server, sess->quitreason);
- }
- }
- void
- process_data_init (char *buf, char *cmd, char *word[],
- char *word_eol[], gboolean handle_quotes,
- gboolean allow_escape_quotes)
- {
- int wordcount = 2;
- int space = FALSE;
- int quote = FALSE;
- int j = 0;
- int len;
- word[0] = "\000\000";
- word_eol[0] = "\000\000";
- word[1] = (char *)buf;
- word_eol[1] = (char *)cmd;
- while (1)
- {
- switch (*cmd)
- {
- case 0:
- buf[j] = 0;
- for (j = wordcount; j < PDIWORDS; j++)
- {
- word[j] = "\000\000";
- word_eol[j] = "\000\000";
- }
- return;
- case '\042':
- if (!handle_quotes)
- goto def;
- /* two quotes turn into 1 */
- if (allow_escape_quotes && cmd[1] == '\042')
- {
- cmd++;
- goto def;
- }
- if (quote)
- {
- quote = FALSE;
- space = FALSE;
- } else
- quote = TRUE;
- cmd++;
- break;
- case ' ':
- if (!quote)
- {
- if (!space)
- {
- buf[j] = 0;
- j++;
- if (wordcount < PDIWORDS)
- {
- word[wordcount] = &buf[j];
- word_eol[wordcount] = cmd + 1;
- wordcount++;
- }
- space = TRUE;
- }
- cmd++;
- break;
- }
- default:
- def:
- space = FALSE;
- len = g_utf8_skip[((unsigned char *)cmd)[0]];
- if (len == 1)
- {
- buf[j] = *cmd;
- j++;
- cmd++;
- } else
- {
- /* skip past a multi-byte utf8 char */
- memcpy (buf + j, cmd, len);
- j += len;
- cmd += len;
- }
- }
- }
- }
- static int
- cmd_addbutton (struct session *sess, char *tbuf, char *word[],
- char *word_eol[])
- {
- if (*word[2] && *word_eol[3])
- {
- if (sess->type == SESS_DIALOG)
- {
- list_addentry (&dlgbutton_list, word_eol[3], word[2]);
- fe_dlgbuttons_update (sess);
- } else
- {
- list_addentry (&button_list, word_eol[3], word[2]);
- fe_buttons_update (sess);
- }
- return TRUE;
- }
- return FALSE;
- }
- static int
- cmd_allchannels (session *sess, char *tbuf, char *word[], char *word_eol[])
- {
- GSList *list = sess_list;
- if (!*word_eol[2])
- return FALSE;
- while (list)
- {
- sess = list->data;
- if (sess->type == SESS_CHANNEL && sess->channel[0] && sess->server->connected)
- {
- handle_command (sess, word_eol[2], FALSE);
- }
- list = list->next;
- }
- return TRUE;
- }
- static int
- cmd_allchannelslocal (session *sess, char *tbuf, char *word[], char *word_eol[])
- {
- GSList *list = sess_list;
- server *serv = sess->server;
- if (!*word_eol[2])
- return FALSE;
- while (list)
- {
- sess = list->data;
- if (sess->type == SESS_CHANNEL && sess->channel[0] &&
- sess->server->connected && sess->server == serv)
- {
- handle_command (sess, word_eol[2], FALSE);
- }
- list = list->next;
- }
- return TRUE;
- }
- static int
- cmd_allservers (struct session *sess, char *tbuf, char *word[],
- char *word_eol[])
- {
- GSList *list;
- server *serv;
- if (!*word_eol[2])
- return FALSE;
- list = serv_list;
- while (list)
- {
- serv = list->data;
- if (serv->connected)
- handle_command (serv->front_session, word_eol[2], FALSE);
- list = list->next;
- }
- return TRUE;
- }
- static int
- cmd_away (struct session *sess, char *tbuf, char *word[], char *word_eol[])
- {
- GSList *list;
- char *reason = word_eol[2];
- if (!(*reason))
- {
- if (sess->server->is_away)
- {
- if (sess->server->last_away_reason)
- PrintTextf (sess, _("Already marked away: %s\n"), sess->server->last_away_reason);
- return FALSE;
- }
- if (sess->server->reconnect_away)
- reason = sess->server->last_away_reason;
- else
- /* must manage memory pointed to by random_line() */
- reason = random_line (prefs.awayreason);
- }
- sess->server->p_set_away (sess->server, reason);
- if (prefs.show_away_message)
- {
- snprintf (tbuf, TBUFSIZE, "me is away: %s", reason);
- for (list = sess_list; list; list = list->next)
- {
- /* am I the right server and not a dialog box */
- if (((struct session *) list->data)->server == sess->server
- && ((struct session *) list->data)->type == SESS_CHANNEL
- && ((struct session *) list->data)->channel[0])
- {
- handle_command ((session *) list->data, tbuf, TRUE);
- }
- }
- }
- if (sess->server->last_away_reason != reason)
- {
- if (sess->server->last_away_reason)
- free (sess->server->last_away_reason);
- if (reason == word_eol[2])
- sess->server->last_away_reason = strdup (reason);
- else
- sess->server->last_away_reason = reason;
- }
- if (!sess->server->connected)
- sess->server->reconnect_away = 1;
- return TRUE;
- }
- static int
- cmd_back (struct session *sess, char *tbuf, char *word[], char *word_eol[])
- {
- GSList *list;
- unsigned int gone;
- if (sess->server->is_away)
- {
- sess->server->p_set_back (sess->server);
- if (prefs.show_away_message)
- {
- gone = time (NULL) - sess->server->away_time;
- sprintf (tbuf, "me is back (gone %.2d:%.2d:%.2d)", gone / 3600,
- (gone / 60) % 60, gone % 60);
- for (list = sess_list; list; list = list->next)
- {
- /* am I the right server and not a dialog box */
- if (((struct session *) list->data)->server == sess->server
- && ((struct session *) list->data)->type == SESS_CHANNEL
- && ((struct session *) list->data)->channel[0])
- {
- handle_command ((session *) list->data, tbuf, TRUE);
- }
- }
- }
- }
- else
- {
- PrintText (sess, _("Already marked back.\n"));
- }
- if (sess->server->last_away_reason)
- free (sess->server->last_away_reason);
- sess->server->last_away_reason = NULL;
- return TRUE;
- }
- static void
- ban (session * sess, char *tbuf, char *mask, char *bantypestr, int deop)
- {
- int bantype;
- struct User *user;
- char *at, *dot, *lastdot;
- char username[64], fullhost[128], domain[128], *mode, *p2;
- server *serv = sess->server;
- user = userlist_find (sess, mask);
- if (user && user->hostname) /* it's a nickname, let's find a proper ban mask */
- {
- if (deop)
- {
- mode = "-o+b ";
- p2 = user->nick;
- } else
- {
- mode = "+b";
- p2 = "";
- }
- mask = user->hostname;
- at = strchr (mask, '@'); /* FIXME: utf8 */
- if (!at)
- return; /* can't happen? */
- *at = 0;
- if (mask[0] == '~' || mask[0] == '+' ||
- mask[0] == '=' || mask[0] == '^' || mask[0] == '-')
- {
- /* the ident is prefixed with something, we replace that sign with an * */
- safe_strcpy (username+1, mask+1, sizeof (username)-1);
- username[0] = '*';
- } else if (at - mask < USERNAMELEN)
- {
- /* we just add an * in the begining of the ident */
- safe_strcpy (username+1, mask, sizeof (username)-1);
- username[0] = '*';
- } else
- {
- /* ident might be too long, we just ban what it gives and add an * in the end */
- safe_strcpy (username, mask, sizeof (username));
- }
- *at = '@';
- safe_strcpy (fullhost, at + 1, sizeof (fullhost));
- dot = strchr (fullhost, '.');
- if (dot)
- {
- safe_strcpy (domain, dot, sizeof (domain));
- } else
- {
- safe_strcpy (domain, fullhost, sizeof (domain));
- }
- if (*bantypestr)
- bantype = atoi (bantypestr);
- else
- bantype = prefs.bantype;
- tbuf[0] = 0;
- if (inet_addr (fullhost) != -1) /* "fullhost" is really a IP number */
- {
- lastdot = strrchr (fullhost, '.');
- if (!lastdot)
- return; /* can't happen? */
- *lastdot = 0;
- strcpy (domain, fullhost);
- *lastdot = '.';
- switch (bantype)
- {
- case 0:
- snprintf (tbuf, TBUFSIZE, "%s%s *!*@%s.*", mode, p2, domain);
- break;
- case 1:
- snprintf (tbuf, TBUFSIZE, "%s%s *!*@%s", mode, p2, fullhost);
- break;
- case 2:
- snprintf (tbuf, TBUFSIZE, "%s%s *!%s@%s.*", mode, p2, username, domain);
- break;
- case 3:
- snprintf (tbuf, TBUFSIZE, "%s%s *!%s@%s", mode, p2, username, fullhost);
- break;
- }
- } else
- {
- switch (bantype)
- {
- case 0:
- snprintf (tbuf, TBUFSIZE, "%s%s *!*@*%s", mode, p2, domain);
- break;
- case 1:
- snprintf (tbuf, TBUFSIZE, "%s%s *!*@%s", mode, p2, fullhost);
- break;
- case 2:
- snprintf (tbuf, TBUFSIZE, "%s%s *!%s@*%s", mode, p2, username, domain);
- break;
- case 3:
- snprintf (tbuf, TBUFSIZE, "%s%s *!%s@%s", mode, p2, username, fullhost);
- break;
- }
- }
- } else
- {
- snprintf (tbuf, TBUFSIZE, "+b %s", mask);
- }
- serv->p_mode (serv, sess->channel, tbuf);
- }
- static int
- cmd_ban (struct session *sess, char *tbuf, char *word[], char *word_eol[])
- {
- char *mask = word[2];
- if (*mask)
- {
- ban (sess, tbuf, mask, word[3], 0);
- } else
- {
- sess->server->p_mode (sess->server, sess->channel, "+b"); /* banlist */
- }
- return TRUE;
- }
- static int
- cmd_unban (struct session *sess, char *tbuf, char *word[], char *word_eol[])
- {
- /* Allow more than one mask in /unban -- tvk */
- int i = 2;
- while (1)
- {
- if (!*word[i])
- {
- if (i == 2)
- return FALSE;
- send_channel_modes (sess, tbuf, word, 2, i, '-', 'b', 0);
- return TRUE;
- }
- i++;
- }
- }
- static int
- cmd_chanopt (struct session *sess, char *tbuf, char *word[], char *word_eol[])
- {
- /* chanopt.c */
- return chanopt_command (sess, tbuf, word, word_eol);
- }
- static int
- cmd_charset (struct session *sess, char *tbuf, char *word[], char *word_eol[])
- {
- server *serv = sess->server;
- const char *locale = NULL;
- int offset = 0;
- if (strcmp (word[2], "-quiet") == 0)
- offset++;
- if (!word[2 + offset][0])
- {
- g_get_charset (&locale);
- PrintTextf (sess, "Current charset: %s\n",
- serv->encoding ? serv->encoding : locale);
- return TRUE;
- }
- if (servlist_check_encoding (word[2 + offset]))
- {
- server_set_encoding (serv, word[2 + offset]);
- if (offset < 1)
- PrintTextf (sess, "Charset changed to: %s\n", word[2 + offset]);
- } else
- {
- PrintTextf (sess, "\0034Unknown charset:\017 %s\n", word[2 + offset]);
- }
- return TRUE;
- }
- static int
- cmd_clear (struct session *sess, char *tbuf, char *word[], char *word_eol[])
- {
- GSList *list = sess_list;
- char *reason = word_eol[2];
- if (strcasecmp (reason, "HISTORY") == 0)
- {
- history_free (&sess->history);
- return TRUE;
- }
- if (strncasecmp (reason, "all", 3) == 0)
- {
- while (list)
- {
- sess = list->data;
- if (!sess->nick_said)
- fe_text_clear (list->data, 0);
- list = list->next;
- }
- return TRUE;
- }
- if (reason[0] != '-' && !isdigit (reason[0]) && reason[0] != 0)
- return FALSE;
- fe_text_clear (sess, atoi (reason));
- return TRUE;
- }
- static int
- cmd_close (struct session *sess, char *tbuf, char *word[], char *word_eol[])
- {
- GSList *list;
- if (strcmp (word[2], "-m") == 0)
- {
- list = sess_list;
- while (list)
- {
- sess = list->data;
- list = list->next;
- if (sess->type == SESS_DIALOG)
- fe_close_window (sess);
- }
- } else
- {
- if (*word_eol[2])
- sess->quitreason = word_eol[2];
- fe_close_window (sess);
- }
- return TRUE;
- }
- static int
- cmd_ctcp (struct session *sess, char *tbuf, char *word[], char *word_eol[])
- {
- int mbl;
- char *to = word[2];
- if (*to)
- {
- char *msg = word_eol[3];
- if (*msg)
- {
- unsigned char *cmd = (unsigned char *)msg;
- /* make the first word upper case (as per RFC) */
- while (1)
- {
- if (*cmd == ' ' || *cmd == 0)
- break;
- mbl = g_utf8_skip[*cmd];
- if (mbl == 1)
- *cmd = toupper (*cmd);
- cmd += mbl;
- }
- sess->server->p_ctcp (sess->server, to, msg);
- EMIT_SIGNAL (XP_TE_CTCPSEND, sess, to, msg, NULL, NULL, 0);
- return TRUE;
- }
- }
- return FALSE;
- }
- static int
- cmd_country (struct session *sess, char *tbuf, char *word[], char *word_eol[])
- {
- char *code = word[2];
- if (*code)
- {
- /* search? */
- if (strcmp (code, "-s") == 0)
- {
- country_search (word[3], sess, (void *)PrintTextf);
- return TRUE;
- }
- /* search, but forgot the -s */
- if (strchr (code, '*'))
- {
- country_search (code, sess, (void *)PrintTextf);
- return TRUE;
- }
- sprintf (tbuf, "%s = %s\n", code, country (code));
- PrintText (sess, tbuf);
- return TRUE;
- }
- return FALSE;
- }
- static int
- cmd_cycle (struct session *sess, char *tbuf, char *word[], char *word_eol[])
- {
- char *key = sess->channelkey;
- char *chan = word[2];
- if (!*chan)
- chan = sess->channel;
- if (*chan && sess->type == SESS_CHANNEL)
- {
- sess->server->p_cycle (sess->server, chan, key);
- return TRUE;
- }
- return FALSE;
- }
- static int
- cmd_dcc (struct session *sess, char *tbuf, char *word[], char *word_eol[])
- {
- int goodtype;
- struct DCC *dcc = 0;
- char *type = word[2];
- if (*type)
- {
- if (!strcasecmp (type, "HELP"))
- return FALSE;
- if (!strcasecmp (type, "CLOSE"))
- {
- if (*word[3] && *word[4])
- {
- goodtype = 0;
- if (!strcasecmp (word[3], "SEND"))
- {
- dcc = find_dcc (word[4], word[5], TYPE_SEND);
- dcc_abort (sess, dcc);
- goodtype = TRUE;
- }
- if (!strcasecmp (word[3], "GET"))
- {
- dcc = find_dcc (word[4], word[5], TYPE_RECV);
- dcc_abort (sess, dcc);
- goodtype = TRUE;
- }
- if (!strcasecmp (word[3], "CHAT"))
- {
- dcc = find_dcc (word[4], "", TYPE_CHATRECV);
- if (!dcc)
- dcc = find_dcc (word[4], "", TYPE_CHATSEND);
- dcc_abort (sess, dcc);
- goodtype = TRUE;
- }
- if (!goodtype)
- return FALSE;
- if (!dcc)
- EMIT_SIGNAL (XP_TE_NODCC, sess, NULL, NULL, NULL, NULL, 0);
- return TRUE;
- }
- return FALSE;
- }
- if ((!strcasecmp (type, "CHAT")) || (!strcasecmp (type, "PCHAT")))
- {
- char *nick = word[3];
- int passive = (!strcasecmp(type, "PCHAT")) ? 1 : 0;
- if (*nick)
- dcc_chat (sess, nick, passive);
- return TRUE;
- }
- if (!strcasecmp (type, "LIST"))
- {
- dcc_show_list (sess);
- return TRUE;
- }
- if (!strcasecmp (type, "GET"))
- {
- char *nick = word[3];
- char *file = word[4];
- if (!*file)
- {
- if (*nick)
- dcc_get_nick (sess, nick);
- } else
- {
- dcc = find_dcc (nick, file, TYPE_RECV);
- if (dcc)
- dcc_get (dcc);
- else
- EMIT_SIGNAL (XP_TE_NODCC, sess, NULL, NULL, NULL, NULL, 0);
- }
- return TRUE;
- }
- if ((!strcasecmp (type, "SEND")) || (!strcasecmp (type, "PSEND")))
- {
- int i = 3, maxcps;
- char *nick, *file;
- int passive = (!strcasecmp(type, "PSEND")) ? 1 : 0;
- nick = word[i];
- if (!*nick)
- return FALSE;
- maxcps = prefs.dcc_max_send_cps;
- if (!strncasecmp(nick, "-maxcps=", 8))
- {
- maxcps = atoi(nick + 8);
- i++;
- nick = word[i];
- if (!*nick)
- return FALSE;
- }
- i++;
- file = word[i];
- if (!*file)
- {
- fe_dcc_send_filereq (sess, nick, maxcps, passive);
- return TRUE;
- }
- do
- {
- dcc_send (sess, nick, file, maxcps, passive);
- i++;
- file = word[i];
- }
- while (*file);
- return TRUE;
- }
- return FALSE;
- }
- dcc_show_list (sess);
- return TRUE;
- }
- static int
- cmd_debug (struct session *sess, char *tbuf, char *word[], char *word_eol[])
- {
- struct session *s;
- struct server *v;
- GSList *list = sess_list;
- PrintText (sess, "Session T Channel WaitChan WillChan Server\n");
- while (list)
- {
- s = (struct session *) list->data;
- sprintf (tbuf, "%p %1x %-10.10s %-10.10s %-10.10s %p\n",
- s, s->type, s->channel, s->waitchannel,
- s->willjoinchannel, s->server);
- PrintText (sess, tbuf);
- list = list->next;
- }
- list = serv_list;
- PrintText (sess, "Server Sock Name\n");
- while (list)
- {
- v = (struct server *) list->data;
- sprintf (tbuf, "%p %-5d %s\n",
- v, v->sok, v->servername);
- PrintText (sess, tbuf);
- list = list->next;
- }
- sprintf (tbuf,
- "\nfront_session: %p\n"
- "current_tab: %p\n\n",
- sess->server->front_session, current_tab);
- PrintText (sess, tbuf);
- #ifdef USE_DEBUG
- sprintf (tbuf, "current mem: %d\n\n", current_mem_usage);
- PrintText (sess, tbuf);
- #endif /* !MEMORY_DEBUG */
- return TRUE;
- }
- static int
- cmd_delbutton (struct session *sess, char *tbuf, char *word[],
- char *word_eol[])
- {
- if (*word[2])
- {
- if (sess->type == SESS_DIALOG)
- {
- if (list_delentry (&dlgbutton_list, word[2]))
- fe_dlgbuttons_update (sess);
- } else
- {
- if (list_delentry (&button_list, word[2]))
- fe_buttons_update (sess);
- }
- return TRUE;
- }
- return FALSE;
- }
- static int
- cmd_dehop (struct session *sess, char *tbuf, char *word[], char *word_eol[])
- {
- int i = 2;
- while (1)
- {
- if (!*word[i])
- {
- if (i == 2)
- return FALSE;
- send_channel_modes (sess, tbuf, word, 2, i, '-', 'h', 0);
- return TRUE;
- }
- i++;
- }
- }
- static int
- cmd_deop (struct session *sess, char *tbuf, char *word[], char *word_eol[])
- {
- int i = 2;
- while (1)
- {
- if (!*word[i])
- {
- if (i == 2)
- return FALSE;
- send_channel_modes (sess, tbuf, word, 2, i, '-', 'o', 0);
- return TRUE;
- }
- i++;
- }
- }
- typedef struct
- {
- char **nicks;
- int i;
- session *sess;
- char *reason;
- char *tbuf;
- } multidata;
- static int
- mdehop_cb (struct User *user, multidata *data)
- {
- if (user->hop && !user->me)
- {
- data->nicks[data->i] = user->nick;
- data->i++;
- }
- return TRUE;
- }
- static int
- cmd_mdehop (struct session *sess, char *tbuf, char *word[], char *word_eol[])
- {
- char **nicks = malloc (sizeof (char *) * sess->hops);
- multidata data;
- data.nicks = nicks;
- data.i = 0;
- tree_foreach (sess->usertree, (tree_traverse_func *)mdehop_cb, &data);
- send_channel_modes (sess, tbuf, nicks, 0, data.i, '-', 'h', 0);
- free (nicks);
- return TRUE;
- }
- static int
- mdeop_cb (struct User *user, multidata *data)
- {
- if (user->op && !user->me)
- {
- data->nicks[data->i] = user->nick;
- data->i++;
- }
- return TRUE;
- }
- static int
- cmd_mdeop (struct session *sess, char *tbuf, char *word[], char *word_eol[])
- {
- char **nicks = malloc (sizeof (char *) * sess->ops);
- multidata data;
- data.nicks = nicks;
- data.i = 0;
- tree_foreach (sess->usertree, (tree_traverse_func *)mdeop_cb, &data);
- send_channel_modes (sess, tbuf, nicks, 0, data.i, '-', 'o', 0);
- free (nicks);
- return TRUE;
- }
- GSList *menu_list = NULL;
- static void
- menu_free (menu_entry *me)
- {
- free (me->path);
- if (me->label)
- free (me->label);
- if (me->cmd)
- free (me->cmd);
- if (me->ucmd)
- free (me->ucmd);
- if (me->group)
- free (me->group);
- if (me->icon)
- free (me->icon);
- free (me);
- }
- /* strings equal? but ignore underscores */
- int
- menu_streq (const char *s1, const char *s2, int def)
- {
- /* for separators */
- if (s1 == NULL && s2 == NULL)
- return 0;
- if (s1 == NULL || s2 == NULL)
- return 1;
- while (*s1)
- {
- if (*s1 == '_')
- s1++;
- if (*s2 == '_')
- s2++;
- if (*s1 != *s2)
- return 1;
- s1++;
- s2++;
- }
- if (!*s2)
- return 0;
- return def;
- }
- static menu_entry *
- menu_entry_find (char *path, char *label)
- {
- GSList *list;
- menu_entry *me;
- list = menu_list;
- while (list)
- {
- me = list->data;
- if (!strcmp (path, me->path))
- {
- if (me->label && label && !strcmp (label, me->label))
- return me;
- }
- list = list->next;
- }
- return NULL;
- }
- static void
- menu_del_children (char *path, char *label)
- {
- GSList *list, *next;
- menu_entry *me;
- char buf[512];
- if (!label)
- label = "";
- if (path[0])
- snprintf (buf, sizeof (buf), "%s/%s", path, label);
- else
- snprintf (buf, sizeof (buf), "%s", label);
- list = menu_list;
- while (list)
- {
- me = list->data;
- next = list->next;
- if (!menu_streq (buf, me->path, 0))
- {
- menu_list = g_slist_remove (menu_list, me);
- menu_free (me);
- }
- list = next;
- }
- }
- static int
- menu_del (char *path, char *label)
- {
- GSList *list;
- menu_entry *me;
- list = menu_list;
- while (list)
- {
- me = list->data;
- if (!menu_streq (me->label, label, 1) && !menu_streq (me->path, path, 1))
- {
- menu_list = g_slist_remove (menu_list, me);
- fe_menu_del (me);
- menu_free (me);
- /* delete this item's children, if any */
- menu_del_children (path, label);
- return 1;
- }
- list = list->next;
- }
- return 0;
- }
- static char
- menu_is_mainmenu_root (char *path, gint16 *offset)
- {
- static const char *menus[] = {"\x4$TAB","\x5$TRAY","\x4$URL","\x5$NICK","\x5$CHAN"};
- int i;
- for (i = 0; i < 5; i++)
- {
- if (!strncmp (path, menus[i] + 1, menus[i][0]))
- {
- *offset = menus[i][0] + 1; /* number of bytes to offset the root */
- return 0; /* is not main menu */
- }
- }
- *offset = 0;
- return 1; /* is main menu */
- }
- static void
- menu_add (char *path, char *label, char *cmd, char *ucmd, int pos, int state, int markup, int enable, int mod, int key, char *group, char *icon)
- {
- menu_entry *me;
- /* already exists? */
- me = menu_entry_find (path, label);
- if (me)
- {
- /* update only */
- me->state = state;
- me->enable = enable;
- fe_menu_update (me);
- return;
- }
- me = malloc (sizeof (menu_entry));
- me->pos = pos;
- me->modifier = mod;
- me->is_main = menu_is_mainmenu_root (path, &me->root_offset);
- me->state = state;
- me->markup = markup;
- me->enable = enable;
- me->key = key;
- me->path = strdup (path);
- me->label = NULL;
- me->cmd = NULL;
- me->ucmd = NULL;
- me->group = NULL;
- me->icon = NULL;
- if (label)
- me->label = strdup (label);
- if (cmd)
- me->cmd = strdup (cmd);
- if (ucmd)
- me->ucmd = strdup (ucmd);
- if (group)
- me->group = strdup (group);
- if (icon)
- me->icon = strdup (icon);
- menu_list = g_slist_append (menu_list, me);
- label = fe_menu_add (me);
- if (label)
- {
- /* FE has given us a stripped label */
- free (me->label);
- me->label = strdup (label);
- g_free (label); /* this is from pango */
- }
- }
- static int
- cmd_menu (struct session *sess, char *tbuf, char *word[], char *word_eol[])
- {
- int idx = 2;
- int len;
- int pos = 0xffff;
- int state;
- int toggle = FALSE;
- int enable = TRUE;
- int markup = FALSE;
- int key = 0;
- int mod = 0;
- char *label;
- char *group = NULL;
- char *icon = NULL;
- if (!word[2][0] || !word[3][0])
- return FALSE;
- /* -eX enabled or not? */
- if (word[idx][0] == '-' && word[idx][1] == 'e')
- {
- enable = atoi (word[idx] + 2);
- idx++;
- }
- /* -i<ICONFILE> */
- if (word[idx][0] == '-' && word[idx][1] == 'i')
- {
- icon = word[idx] + 2;
- idx++;
- }
- /* -k<mod>,<key> key binding */
- if (word[idx][0] == '-' && word[idx][1] == 'k')
- {
- char *comma = strchr (word[idx], ',');
- if (!comma)
- return FALSE;
- mod = atoi (word[idx] + 2);
- key = atoi (comma + 1);
- idx++;
- }
- /* -m to specify PangoMarkup language */
- if (word[idx][0] == '-' && word[idx][1] == 'm')
- {
- markup = TRUE;
- idx++;
- }
- /* -pX to specify menu position */
- if (word[idx][0] == '-' && word[idx][1] == 'p')
- {
- pos = atoi (word[idx] + 2);
- idx++;
- }
- /* -rSTATE,GROUP to specify a radio item */
- if (word[idx][0] == '-' && word[idx][1] == 'r')
- {
- state = atoi (word[idx] + 2);
- group = word[idx] + 4;
- idx++;
- }
- /* -tX to specify toggle item with default state */
- if (word[idx][0] == '-' && word[idx][1] == 't')
- {
- state = atoi (word[idx] + 2);
- idx++;
- toggle = TRUE;
- }
- if (word[idx+1][0] == 0)
- return FALSE;
- /* the path */
- path_part (word[idx+1], tbuf, 512);
- len = strlen (tbuf);
- if (len)
- tbuf[len - 1] = 0;
- /* the name of the item */
- label = file_part (word[idx + 1]);
- if (label[0] == '-' && label[1] == 0)
- label = NULL; /* separator */
- if (markup)
- {
- char *p; /* to force pango closing tags through */
- for (p = label; *p; p++)
- if (*p == 3)
- *p = '/';
- }
- if (!strcasecmp (word[idx], "ADD"))
- {
- if (toggle)
- {
- menu_add (tbuf, label, word[idx + 2], word[idx + 3], pos, state, markup, enable, mod, key, NULL, NULL);
- } else
- {
- if (word[idx + 2][0])
- menu_add (tbuf, label, word[idx + 2], NULL, pos, state, markup, enable, mod, key, group, icon);
- else
- menu_add (tbuf, label, NULL, NULL, pos, state, markup, enable, mod, key, group, icon);
- }
- return TRUE;
- }
- if (!strcasecmp (word[idx], "DEL"))
- {
- menu_del (tbuf, label);
- return TRUE;
- }
- return FALSE;
- }
- static int
- mkick_cb (struct User *user, multidata *data)
- {
- if (!user->op && !user->me)
- data->sess->server->p_kick (data->sess->server, data->sess->channel, user->nick, data->reason);
- return TRUE;
- }
- static int
- mkickops_cb (struct User *user, multidata *data)
- {
- if (user->op && !user->me)
- data->sess->server->p_kick (data->sess->server, data->sess->channel, user->nick, data->reason);
- return TRUE;
- }
- static int
- cmd_mkick (struct session *sess, char *tbuf, char *word[], char *word_eol[])
- {
- multidata data;
- data.sess = sess;
- data.reason = word_eol[2];
- tree_foreach (sess->usertree, (tree_traverse_func *)mkickops_cb, &data);
- tree_foreach (sess->usertree, (tree_traverse_func *)mkick_cb, &data);
- return TRUE;
- }
- static int
- cmd_devoice (struct session *sess, char *tbuf, char *word[], char *word_eol[])
- {
- int i = 2;
- while (1)
- {
- if (!*word[i])
- {
- if (i == 2)
- return FALSE;
- send_channel_modes (sess, tbuf, word, 2, i, '-', 'v', 0);
- return TRUE;
- }
- i++;
- }
- }
- static int
- cmd_discon (struct session *sess, char *tbuf, char *word[], char *word_eol[])
- {
- sess->server->disconnect (sess, TRUE, -1);
- return TRUE;
- }
- static int
- cmd_dns (struct session *sess, char *tbuf, char *word[], char *word_eol[])
- {
- #ifdef WIN32
- PrintText (sess, "DNS is not implemented in Windows.\n");
- return TRUE;
- #else
- char *nick = word[2];
- struct User *user;
- if (*nick)
- {
- if (strchr (nick, '.') == NULL)
- {
- user = userlist_find (sess, nick);
- if (user && user->hostname)
- {
- do_dns (sess, user->nick, user->hostname);
- } else
- {
- sess->server->p_get_ip (sess->server, nick);
- sess->server->doing_dns = TRUE;
- }
- } else
- {
- snprintf (tbuf, TBUFSIZE, "exec -d %s %s", prefs.dnsprogram, nick);
- handle_command (sess, tbuf, FALSE);
- }
- return TRUE;
- }
- return FALSE;
- #endif
- }
- static int
- cmd_echo (struct session *sess, char *tbuf, char *word[], char *word_eol[])
- {
- PrintText (sess, word_eol[2]);
- return TRUE;
- }
- #ifndef WIN32
- static void
- exec_check_process (struct session *sess)
- {
- int val;
- if (sess->running_exec == NULL)
- return;
- val = waitpid (sess->running_exec->childpid, NULL, WNOHANG);
- if (val == -1 || val > 0)
- {
- close (sess->running_exec->myfd);
- fe_input_remove (sess->running_exec->iotag);
- free (sess->running_exec);
- sess->running_exec = NULL;
- }
- }
- #ifndef __EMX__
- static int
- cmd_execs (struct session *sess, char *tbuf, char *word[], char *word_eol[])
- {
- int r;
- exec_check_process (sess);
- if (sess->running_exec == NULL)
- {
- EMIT_SIGNAL (XP_TE_NOCHILD, sess, NULL, NULL, NULL, NULL, 0);
- return FALSE;
- }
- r = kill (sess->running_exec->childpid, SIGSTOP);
- if (r == -1)
- PrintText (sess, "Error in kill(2)\n");
- return TRUE;
- }
- static int
- cmd_execc (struct session *sess, char *tbuf, char *word[], char *word_eol[])
- {
- int r;
- exec_check_process (sess);
- if (sess->running_exec == NULL)
- {
- EMIT_SIGNAL (XP_TE_NOCHILD, sess, NULL, NULL, NULL, NULL, 0);
- return FALSE;
- }
- r = kill (sess->running_exec->childpid, SIGCONT);
- if (r == -1)
- PrintText (sess, "Error in kill(2)\n");
- return TRUE;
- }
- static int
- cmd_execk (struct session *sess, char *tbuf, char *word[], char *word_eol[])
- {
- int r;
- exec_check_process (sess);
- if (sess->running_exec == NULL)
- {
- EMIT_SIGNAL (XP_TE_NOCHILD, sess, NULL, NULL, NULL, NULL, 0);
- return FALSE;
- }
- if (strcmp (word[2], "-9") == 0)
- r = kill (sess->running_exec->childpid, SIGKILL);
- else
- r = kill (sess->running_exec->childpid, SIGTERM);
- if (r == -1)
- PrintText (sess, "Error in kill(2)\n");
- return TRUE;
- }
- /* OS/2 Can't have the /EXECW command because it uses pipe(2) not socketpair
- and thus it is simplex --AGL */
- static int
- cmd_execw (struct session *sess, char *tbuf, char *word[], char *word_eol[])
- {
- int len;
- char *temp;
- exec_check_process (sess);
- if (sess->running_exec == NULL)
- {
- EMIT_SIGNAL (XP_TE_NOCHILD, sess, NULL, NULL, NULL, NULL, 0);
- return FALSE;
- }
- len = strlen(word_eol[2]);
- temp = malloc(len + 2);
- sprintf(temp, "%s\n", word_eol[2]);
- PrintText(sess, temp);
- write(sess->running_exec->myfd, temp, len + 1);
- free(temp);
- return TRUE;
- }
- #endif /* !__EMX__ */
- /* convert ANSI escape color codes to mIRC codes */
- static short escconv[] =
- /* 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 */
- { 1,4,3,5,2,10,6,1, 1,7,9,8,12,11,13,1 };
- static void
- exec_handle_colors (char *buf, int len)
- {
- char numb[16];
- char *nbuf;
- int i = 0, j = 0, k = 0, firstn = 0, col, colf = 0, colb = 0;
- int esc = FALSE, backc = FALSE, bold = FALSE;
- /* any escape codes in this text? */
- if (strchr (buf, 27) == 0)
- return;
- nbuf = malloc (len + 1);
- while (i < len)
- {
- switch (buf[i])
- {
- case '\r':
- break;
- case 27:
- esc = TRUE;
- break;
- case ';':
- if (!esc)
- goto norm;
- backc = TRUE;
- numb[k] = 0;
- firstn = atoi (numb);
- k = 0;
- break;
- case '[':
- if (!esc)
- goto norm;
- break;
- default:
- if (esc)
- {
- if (buf[i] >= 'A' && buf[i] <= 'z')
- {
- if (buf[i] == 'm')
- {
- /* ^[[0m */
- if (k == 0 || (numb[0] == '0' && k == 1))
- {
- nbuf[j] = '\017';
- j++;
- bold = FALSE;
- goto cont;
- }
- numb[k] = 0;
- col = atoi (numb);
- backc = FALSE;
- if (firstn == 1)
- bold = TRUE;
- if (firstn >= 30 && firstn <= 37)
- colf = firstn - 30;
- if (col >= 40)
- {
- colb = col - 40;
- backc = TRUE;
- }
- if (col >= 30 && col <= 37)
- colf = col - 30;
- if (bold)
- colf += 8;
- if (backc)
- {
- colb = escconv[colb % 14];
- colf = escconv[colf % 14];
- j += sprintf (&nbuf[j], "\003%d,%02d", colf, colb);
- } else
- {
- colf = escconv[colf % 14];
- j += sprintf (&nbuf[j], "\003%02d", colf);
- }
- }
- cont: esc = FALSE;
- backc = FALSE;
- k = 0;
- } else
- {
- if (isdigit ((unsigned char) buf[i]) && k < (sizeof (numb) - 1))
- {
- numb[k] = buf[i];
- k++;
- }
- }
- } else
- {
- norm: nbuf[j] = buf[i];
- j++;
- }
- }
- i++;
- }
- nbuf[j] = 0;
- memcpy (buf, nbuf, j + 1);
- free (nbuf);
- }
- #ifndef HAVE_MEMRCHR
- static void *
- memrchr (const void *block, int c, size_t size)
- {
- unsigned char *p;
- for (p = (unsigned char *)block + size; p != block; p--)
- if (*p == c)
- return p;
- return 0;
- }
- #endif
- static gboolean
- exec_data (GIOChannel *source, GIOCondition condition, struct nbexec *s)
- {
- char *buf, *readpos, *rest;
- int rd, len;
- int sok = s->myfd;
- len = s->buffill;
- if (len) {
- /* append new data to buffered incomplete line */
- buf = malloc(len + 2050);
- memcpy(buf, s->linebuf, len);
- readpos = buf + len;
- free(s->linebuf);
- s->linebuf = NULL;
- }
- else
- readpos = buf = malloc(2050);
- rd = read (sok, readpos, 2048);
- if (rd < 1)
- {
- /* The process has died */
- kill(s->childpid, SIGKILL);
- if (len) {
- buf[len] = '\0';
- exec_handle_colors(buf, len);
- if (s->tochannel)
- {
- /* must turn off auto-completion temporarily */
- unsigned int old = prefs.nickcompletion;
- prefs.nickcompletion = 0;
- handle_multiline (s->sess, buf, FALSE, TRUE);
- prefs.nickcompletion = old;
- }
- else
- PrintText (s->sess, buf);
- }
- free(buf);
- waitpid (s->childpid, NULL, 0);
- s->sess->running_exec = NULL;
- fe_input_remove (s->iotag);
- close (sok);
- free (s);
- return TRUE;
- }
- len += rd;
- buf[len] = '\0';
- rest = memrchr(buf, '\n', len);
- if (rest)
- rest++;
- else
- rest = buf;
- if (*rest) {
- s->buffill = len - (rest - buf); /* = strlen(rest) */
- s->linebuf = malloc(s->buffill);
- memcpy(s->linebuf, rest, s->buffill);
- *rest = '\0';
- len -= s->buffill; /* possibly 0 */
- }
- else
- s->buffill = 0;
- if (len) {
- exec_handle_colors (buf, len);
- if (s->tochannel)
- handle_multiline (s->sess, buf, FALSE, TRUE);
- else
- PrintText (s->sess, buf);
- }
- free(buf);
- return TRUE;
- }
- static int
- cmd_exec (struct session *sess, char *tbuf, char *word[], char *word_eol[])
- {
- int tochannel = FALSE;
- char *cmd = word_eol[2];
- int fds[2], pid = 0;
- struct nbexec *s;
- int shell = TRUE;
- int fd;
- if (*cmd)
- {
- exec_check_process (sess);
- if (sess->running_exec != NULL)
- {
- EMIT_SIGNAL (XP_TE_ALREADYPROCESS, sess, NULL, NULL, NULL, NULL, 0);
- return TRUE;
- }
- if (!strcmp (word[2], "-d"))
- {
- if (!*word[3])
- return FALSE;
- cmd = word_eol[3];
- shell = FALSE;
- }
- else if (!strcmp (word[2], "-o"))
- {
- if (!*word[3])
- return FALSE;
- cmd = word_eol[3];
- tochannel = TRUE;
- }
- if (shell)
- {
- if (access ("/bin/sh", X_OK) != 0)
- {
- fe_message (_("I need /bin/sh to run!\n"), FE_MSG_ERROR);
- return TRUE;
- }
- }
- #ifdef __EMX__ /* if os/2 */
- if (pipe (fds) < 0)
- {
- PrintText (sess, "Pipe create error\n");
- return FALSE;
- }
- setmode (fds[0], O_BINARY);
- setmode (fds[1], O_BINARY);
- #else
- if (socketpair (PF_UNIX, SOCK_STREAM, 0, fds) == -1)
- {
- PrintText (sess, "socketpair(2) failed\n");
- return FALSE;
- }
- #endif
- s = (struct nbexec *) malloc (sizeof (struct nbexec));
- memset(s, 0, sizeof(*s));
- s->myfd = fds[0];
- s->tochannel = tochannel;
- s->sess = sess;
- pid = fork ();
- if (pid == 0)
- {
- /* This is the child's context */
- close (0);
- close (1);
- close (2);
- /* Close parent's end of pipe */
- close(s->myfd);
- /* Copy the child end of the pipe to stdout and stderr */
- dup2 (fds[1], 1);
- dup2 (fds[1], 2);
- /* Also copy it to stdin so we can write to it */
- dup2 (fds[1], 0);
- /* Now close all open file descriptors except stdin, stdout and stderr */
- for (fd = 3; fd < 1024; fd++) close(fd);
- /* Now we call /bin/sh to run our cmd ; made it more friendly -DC1 */
- if (shell)
- {
- execl ("/bin/sh", "sh", "-c", cmd, NULL);
- } else
- {
- char **argv;
- int argc;
- my_poptParseArgvString (cmd, &argc, &argv);
- execvp (argv[0], argv);
- }
- /* not reached unless error */
- /*printf("exec error\n");*/
- fflush (stdout);
- fflush (stdin);
- _exit (0);
- }
- if (pid == -1)
- {
- /* Parent context, fork() failed */
- PrintText (sess, "Error in fork(2)\n");
- close(fds[0]);
- close(fds[1]);
- } else
- {
- /* Parent path */
- close(fds[1]);
- s->childpid = pid;
- s->iotag = fe_input_add (s->myfd, FIA_READ|FIA_EX, exec_data, s);
- sess->running_exec = s;
- return TRUE;
- }
- }
- return FALSE;
- }
- #endif
- static int
- cmd_flushq (struct session *sess, char *tbuf, char *word[], char *word_eol[])
- {
- sprintf (tbuf, "Flushing server send queue, %d bytes.\n", sess->server->sendq_len);
- PrintText (sess, tbuf);
- sess->server->flush_queue (sess->server);
- return TRUE;
- }
- static int
- cmd_quit (struct session *sess, char *tbuf, char *word[], char *word_eol[])
- {
- if (*word_eol[2])
- sess->quitreason = word_eol[2];
- sess->server->disconnect (sess, TRUE, -1);
- sess->quitreason = NULL;
- return 2;
- }
- static int
- cmd_gate (struct session *sess, char *tbuf, char *word[], char *word_eol[])
- {
- char *server_name = word[2];
- server *serv = sess->server;
- if (*server_name)
- {
- char *port = word[3];
- #ifdef USE_OPENSSL
- serv->use_ssl = FALSE;
- #endif
- server_fill_her_up (serv);
- if (*port)
- serv->connect (serv, server_name, atoi (port), TRUE);
- else
- serv->connect (serv, server_name, 23, TRUE);
- return TRUE;
- }
- return FALSE;
- }
- typedef struct
- {
- char *cmd;
- session *sess;
- } getvalinfo;
- static void
- get_int_cb (int cancel, int val, getvalinfo *info)
- {
- char buf[512];
- if (!cancel)
- {
- snprintf (buf, sizeof (buf), "%s %d", info->cmd, val);
- if (is_session (info->sess))
- handle_command (info->sess, buf, FALSE);
- }
- free (info->cmd);
- free (info);
- }
- static int
- cmd_getint (struct session *sess, char *tbuf, char *word[], char *word_eol[])
- {
- getvalinfo *info;
- if (!word[4][0])
- return FALSE;
- info = malloc (sizeof (*info));
- info->cmd = strdup (word[3]);
- info->sess = sess;
- fe_get_int (word[4], atoi (word[2]), get_int_cb, info);
- return TRUE;
- }
- static void
- get_file_cb (char *cmd, char *file)
- {
- char buf[1024 + 128];
- /* execute the command once per file, then once more with
- no args */
- if (file)
- {
- snprintf (buf, sizeof (buf), "%s %s", cmd, file);
- handle_command (current_sess, buf, FALSE);
- }
- else
- {
- handle_command (current_sess, cmd, FALSE);
- free (cmd);
- }
- }
- static int
- cmd_getfile (struct session *sess, char *tbuf, char *word[], char *word_eol[])
- {
- int idx = 2;
- int flags = 0;
- if (!word[3][0])
- return FALSE;
- if (!strcmp (word[2], "-folder"))
- {
- flags |= FRF_CHOOSEFOLDER;
- idx++;
- }
- if (!strcmp (word[idx], "-multi"))
- {
- flags |= FRF_MULTIPLE;
- idx++;
- }
- if (!strcmp (word[idx], "-save"))
- {
- flags |= FRF_WRITE;
- idx++;
- }
- fe_get_file (word[idx+1], word[idx+2], (void *)get_file_cb, strdup (word[idx]), flags);
- return TRUE;
- }
- static void
- get_str_cb (int cancel, char *val, getvalinfo *info)
- {
- char buf[512];
- if (!cancel)
- {
- snprintf (buf, sizeof (buf), "%s %s", info->cmd, val);
- if (is_session (info->sess))
- handle_command (info->sess, buf, FALSE);
- }
- free (info->cmd);
- free (info);
- }
- static int
- cmd_getstr (struct session *sess, char *tbuf, char *word[], char *word_eol[])
- {
- getvalinfo *info;
- if (!word[4][0])
- return FALSE;
- info = malloc (sizeof (*info));
- info->cmd = strdup (word[3]);
- info->sess = sess;
- fe_get_str (word[4], word[2], get_str_cb, info);
- return TRUE;
- }
- static int
- cmd_ghost (struct session *sess, char *tbuf, char *word[], char *word_eol[])
- {
- if (!word[2][0])
- return FALSE;
- sess->server->p_ns_ghost (sess->server, word[2], word[3]);
- return TRUE;
- }
- static int
- cmd_gui (struct session *sess, char *tbuf, char *word[], char *word_eol[])
- {
- switch (str_ihash (word[2]))
- {
- case 0x058b836e: fe_ctrl_gui (sess, 8, 0); break; /* APPLY */
- case 0xac1eee45: fe_ctrl_gui (sess, 7, 2); break; /* ATTACH */
- case 0x05a72f63: fe_ctrl_gui (sess, 4, atoi (word[3])); break; /* COLOR */
- case 0xb06a1793: fe_ctrl_gui (sess, 7, 1); break; /* DETACH */
- case 0x05cfeff0: fe_ctrl_gui (sess, 3, 0); break; /* FLASH */
- case 0x05d154d8: fe_ctrl_gui (sess, 2, 0); break; /* FOCUS */
- case 0x0030dd42: fe_ctrl_gui (sess, 0, 0); break; /* HIDE */
- case 0x61addbe3: fe_ctrl_gui (sess, 5, 0); break; /* ICONIFY */
- case 0xc0851aaa: fe_message (word[3], FE_MSG_INFO|FE_MSG_MARKUP); break; /* MSGBOX */
- case 0x0035dafd: fe_ctrl_gui (sess, 1, 0); break; /* SHOW */
- case 0x0033155f: /* MENU */
- if (!strcasecmp (word[3], "TOGGLE"))
- fe_ctrl_gui (sess, 6, 0);
- else
- return FALSE;
- break;
- default:
- return FALSE;
- }
- return TRUE;
- }
- typedef struct
- {
- int longfmt;
- int i, t;
- char *buf;
- } help_list;
- static void
- show_help_line (session *sess, help_list *hl, char *name, char *usage)
- {
- int j, len, max;
- char *p;
- if (name[0] == '.') /* hidden command? */
- return;
- if (hl->longfmt) /* long format for /HELP -l */
- {
- if (!usage || usage[0] == 0)
- PrintTextf (sess, " \0034%s\003 :\n", name);
- else
- PrintTextf (sess, " \0034%s\003 : %s\n", name, _(usage));
- return;
- }
- /* append the name into buffer, but convert to uppercase */
- len = strlen (hl->buf);
- p = name;
- while (*p)
- {
- hl->buf[len] = toupper ((unsigned char) *p);
- len++;
- p++;
- }
- hl->buf[len] = 0;
- hl->t++;
- if (hl->t == 5)
- {
- hl->t = 0;
- strcat (hl->buf, "\n");
- PrintText (sess, hl->buf);
- hl->buf[0] = ' ';
- hl->buf[1] = ' ';
- hl->buf[2] = 0;
- } else
- {
- /* append some spaces after the command name */
- max = strlen (name);
- if (max < 10)
- {
- max = 10 - max;
- for (j = 0; j < max; j++)
- {
- hl->buf[len] = ' ';
- len++;
- hl->buf[len] = 0;
- }
- }
- }
- }
- static int
- cmd_help (struct session *sess, char *tbuf, char *word[], char *word_eol[])
- {
- int i = 0, longfmt = 0;
- char *helpcmd = "";
- GSList *list;
- if (tbuf)
- helpcmd = word[2];
- if (*helpcmd && strcmp (helpcmd, "-l") == 0)
- longfmt = 1;
- if (*helpcmd && !longfmt)
- {
- help (sess, tbuf, helpcmd, FALSE);
- } else
- {
- struct popup *pop;
- char *buf = malloc (4096);
- help_list hl;
- hl.longfmt = longfmt;
- hl.buf = buf;
- PrintTextf (sess, "\n%s\n\n", _("Commands Available:"));
- buf[0] = ' ';
- buf[1] = ' ';
- buf[2] = 0;
- hl.t = 0;
- hl.i = 0;
- while (xc_cmds[i].name)
- {
- show_help_line (sess, &hl, xc_cmds[i].name, xc_cmds[i].help);
- i++;
- }
- strcat (buf, "\n");
- PrintText (sess, buf);
- PrintTextf (sess, "\n%s\n\n", _("User defined commands:"));
- buf[0] = ' ';
- buf[1] = ' ';
- buf[2] = 0;
- hl.t = 0;
- hl.i = 0;
- list = command_list;
- while (list)
- {
- pop = list->data;
- show_help_line (sess, &hl, pop->name, pop->cmd);
- list = list->next;
- }
- strcat (buf, "\n");
- PrintText (sess, buf);
- PrintTextf (sess, "\n%s\n\n", _("Plugin defined commands:"));
- buf[0] = ' ';
- buf[1] = ' ';
- buf[2] = 0;
- hl.t = 0;
- hl.i = 0;
- plugin_command_foreach (sess, &hl, (void *)show_help_line);
- strcat (buf, "\n");
- PrintText (sess, buf);
- free (buf);
- PrintTextf (sess, "\n%s\n\n", _("Type /HELP <command> for more information, or /HELP -l"));
- }
- return TRUE;
- }
- static int
- cmd_id (struct session *sess, char *tbuf, char *word[], char *word_eol[])
- {
- if (word[2][0])
- {
- sess->server->p_ns_identify (sess->server, word[2]);
- return TRUE;
- }
- return FALSE;
- }
- static int
- cmd_ignore (struct session *sess, char *tbuf, char *word[], char *word_eol[])
- {
- int i;
- int type = 0;
- int quiet = 0;
- char *mask;
- if (!*word[2])
- {
- ignore_showlist (sess);
- return TRUE;
- }
- if (!*word[3])
- return FALSE;
- i = 3;
- while (1)
- {
- if (!*word[i])
- {
- if (type == 0)
- return FALSE;
- mask = word[2];
- if (strchr (mask, '?') == NULL &&
- strchr (mask, '*') == NULL &&
- userlist_find (sess, mask))
- {
- mask = tbuf;
- snprintf (tbuf, TBUFSIZE, "%s!*@*", word[2]);
- }
- i = ignore_add (mask, type);
- if (quiet)
- return TRUE;
- switch (i)
- {
- case 1:
- EMIT_SIGNAL (XP_TE_IGNOREADD, sess, mask, NULL, NULL, NULL, 0);
- break;
- case 2: /* old ignore changed */
- EMIT_SIGNAL (XP_TE_IGNORECHANGE, sess, mask, NULL, NULL, NULL, 0);
- }
- return TRUE;
- }
- if (!strcasecmp (word[i], "UNIGNORE"))
- type |= IG_UNIG;
- else if (!strcasecmp (word[i], "ALL"))
- type |= IG_PRIV | IG_NOTI | IG_CHAN | IG_CTCP | IG_INVI | IG_DCC;
- else if (!strcasecmp (word[i], "PRIV"))
- type |= IG_PRIV;
- else if (!strcasecmp (word[i], "NOTI"))
- type |= IG_NOTI;
- else if (!strcasecmp (word[i], "CHAN"))
- type |= IG_CHAN;
- else if (!strcasecmp (word[i], "CTCP"))
- type |= IG_CTCP;
- else if (!strcasecmp (word[i], "INVI"))
- type |= IG_INVI;
- else if (!strcasecmp (word[i], "QUIET"))
- quiet = 1;
- else if (!strcasecmp (word[i], "NOSAVE"))
- type |= IG_NOSAVE;
- else if (!strcasecmp (word[i], "DCC"))
- type |= IG_DCC;
- else
- {
- sprintf (tbuf, _("Unknown arg '%s' ignored."), word[i]);
- PrintText (sess, tbuf);
- }
- i++;
- }
- }
- static int
- cmd_invite (struct session *sess, char *tbuf, char *word[], char *word_eol[])
- {
- if (!*word[2])
- return FALSE;
- if (*word[3])
- sess->server->p_invite (sess->server, word[3], word[2]);
- else
- sess->server->p_invite (sess->server, sess->channel, word[2]);
- return TRUE;
- }
- static int
- cmd_join (struct session *sess, char *tbuf, char *word[], char *word_eol[])
- {
- char *chan = word[2];
- if (*chan)
- {
- char *po, *pass = word[3];
- sess->server->p_join (sess->server, chan, pass);
- if (sess->channel[0] == 0 && sess->waitchannel[0])
- {
- po = strchr (chan, ',');
- if (po)
- *po = 0;
- safe_strcpy (sess->waitchannel, chan, CHANLEN);
- }
- return TRUE;
- }
- return FALSE;
- }
- static int
- cmd_kick (struct session *sess, char *tbuf, char *word[], char *word_eol[])
- {
- char *nick = word[2];
- char *reason = word_eol[3];
- if (*nick)
- {
- sess->server->p_kick (sess->server, sess->channel, nick, reason);
- return TRUE;
- }
- return FALSE;
- }
- static int
- cmd_kickban (struct session *sess, char *tbuf, char *word[], char *word_eol[])
- {
- char *nick = word[2];
- char *reason = word_eol[3];
- struct User *user;
- if (*nick)
- {
- /* if the reason is a 1 digit number, treat it as a bantype */
- user = userlist_find (sess, nick);
- if (isdigit ((unsigned char) reason[0]) && reason[1] == 0)
- {
- ban (sess, tbuf, nick, reason, (user && user->op));
- reason[0] = 0;
- } else
- ban (sess, tbuf, nick, "", (user && user->op));
- sess->server->p_kick (sess->server, sess->channel, nick, reason);
- return TRUE;
- }
- return FALSE;
- }
- static int
- cmd_killall (struct session *sess, char *tbuf, char *word[], char *word_eol[])
- {
- xchat_exit();
- return 2;
- }
- static int
- cmd_lagcheck (struct session *sess, char *tbuf, char *word[], char *word_eol[])
- {
- lag_check ();
- return TRUE;
- }
- static void
- lastlog (session *sess, char *search, gboolean regexp)
- {
- session *lastlog_sess;
- if (!is_session (sess))
- return;
- lastlog_sess = find_dialog (sess->server, "(lastlog)");
- if (!lastlog_sess)
- lastlog_sess = new_ircwindow (sess->server, "(lastlog)", SESS_DIALOG, 0);
- lastlog_sess->lastlog_sess = sess;
- lastlog_sess->lastlog_regexp = regexp; /* remember the search type */
- fe_text_clear (lastlog_sess, 0);
- fe_lastlog (sess, lastlog_sess, search, regexp);
- }
- static int
- cmd_lastlog (struct session *sess, char *tbuf, char *word[], char *word_eol[])
- {
- if (*word_eol[2])
- {
- if (!strcmp (word[2], "-r"))
- lastlog (sess, word_eol[3], TRUE);
- else
- lastlog (sess, word_eol[2], FALSE);
- return TRUE;
- }
- return FALSE;
- }
- static int
- cmd_list (struct session *sess, char *tbuf, char *word[], char *word_eol[])
- {
- sess->server->p_list_channels (sess->server, word_eol[2], 1);
- return TRUE;
- }
- gboolean
- load_perform_file (session *sess, char *file)
- {
- char tbuf[1024 + 4];
- char *nl;
- FILE *fp;
- fp = xchat_fopen_file (file, "r", XOF_FULLPATH);
- if (!fp)
- return FALSE;
- tbuf[1024] = 0;
- while (fgets (tbuf, 1024, fp))
- {
- nl = strchr (tbuf, '\n');
- if (nl == tbuf) /* skip empty commands */
- continue;
- if (nl)
- *nl = 0;
- if (tbuf[0] == prefs.cmdchar[0])
- handle_command (sess, tbuf + 1, TRUE);
- else
- handle_command (sess, tbuf, TRUE);
- }
- fclose (fp);
- return TRUE;
- }
- static int
- cmd_load (struct session *sess, char *tbuf, char *word[], char *word_eol[])
- {
- char *error, *arg, *file;
- int len;
- if (!word[2][0])
- return FALSE;
- if (strcmp (word[2], "-e") == 0)
- {
- file = expand_homedir (word[3]);
- if (!load_perform_file (sess, file))
- {
- PrintTextf (sess, _("Cannot access %s\n"), file);
- PrintText (sess, errorstring (errno));
- }
- free (file);
- return TRUE;
- }
- #ifdef USE_PLUGIN
- len = strlen (word[2]);
- #ifdef WIN32
- if (len > 4 && strcasecmp (".dll", word[2] + len - 4) == 0)
- #else
- #if defined(__hpux)
- if (len > 3 && strcasecmp (".sl", word[2] + len - 3) == 0)
- #else
- if (len > 3 && strcasecmp (".so", word[2] + len - 3) == 0)
- #endif
- #endif
- {
- arg = NULL;
- if (word_eol[3][0])
- arg = word_eol[3];
- file = expand_homedir (word[2]);
- error = plugin_load (sess, file, arg);
- free (file);
- if (error)
- PrintText (sess, error);
- return TRUE;
- }
- #endif
- sprintf (tbuf, "Unknown file type %s. Maybe you need to install the Perl or Python plugin?\n", word[2]);
- PrintText (sess, tbuf);
- return FALSE;
- }
- static int
- cmd_me (struct session *sess, char *tbuf, char *word[], char *word_eol[])
- {
- char *act = word_eol[2];
- if (!(*act))
- return FALSE;
- if (sess->type == SESS_SERVER)
- {
- notj_msg (sess);
- return TRUE;
- }
- snprintf (tbuf, TBUFSIZE, "\001ACTION %s\001\r", act);
- /* first try through DCC CHAT */
- if (dcc_write_chat (sess->channel, tbuf))
- {
- /* print it to screen */
- inbound_action (sess, sess->channel, sess->server->nick, "", act, TRUE, FALSE);
- } else
- {
- /* DCC CHAT failed, try through server */
- if (sess->server->connected)
- {
- sess->server->p_action (sess->server, sess->channel, act);
- /* print it to screen */
- inbound_action (sess, sess->channel, sess->server->nick, "", act, TRUE, FALSE);
- } else
- {
- notc_msg (sess);
- }
- }
- return TRUE;
- }
- static int
- cmd_mode (struct session *sess, char *tbuf, char *word[], char *word_eol[])
- {
- …
Large files files are truncated, but you can click here to view the full file