2011-02-24 04:14:30 +01:00
/* 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
2012-12-23 11:36:54 -08:00
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
2011-02-24 04:14:30 +01:00
*/
#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>
2011-12-11 17:34:02 +01:00
#include <unistd.h>
2011-02-24 04:14:30 +01:00
#endif
#include <time.h>
#include <signal.h>
#include <sys/stat.h>
#include <fcntl.h>
2026-01-05 23:12:38 -07:00
#include "zoitechat.h"
2011-02-24 04:14:30 +01:00
#include "plugin.h"
#include "ignore.h"
#include "util.h"
#include "fe.h"
2026-01-05 23:12:38 -07:00
#include "cfgfiles.h" /* zoitechat_fopen_file() */
2011-02-24 04:14:30 +01:00
#include "network.h" /* net_ip() */
#include "modes.h"
#include "notify.h"
#include "inbound.h"
#include "text.h"
2026-01-05 23:12:38 -07:00
#include "zoitechatc.h"
2011-02-24 04:14:30 +01:00
#include "servlist.h"
#include "server.h"
#include "tree.h"
#include "outbound.h"
2012-07-21 14:26:19 +02:00
#include "chanopt.h"
2011-02-24 04:14:30 +01:00
#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 ;
2026-01-05 23:12:38 -07:00
fh = zoitechat_fopen_file ( file_name , "r" , 0 );
2011-02-24 04:14:30 +01:00
if ( ! fh )
{
nofile :
/* reason is not a file, an actual reason! */
2014-12-28 06:37:25 -05:00
return g_strdup ( file_name );
2011-02-24 04:14:30 +01:00
}
/* 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 );
2014-12-28 06:37:25 -05:00
return g_strdup ( buf );
2011-02-24 04:14:30 +01:00
}
void
server_sendpart ( server * serv , char * channel , char * reason )
{
if ( ! reason )
{
2012-10-22 14:50:36 +02:00
reason = random_line ( prefs . hex_irc_part_reason );
2011-02-24 04:14:30 +01:00
serv -> p_part ( serv , channel , reason );
2014-12-28 06:37:25 -05:00
g_free ( reason );
2011-02-24 04:14:30 +01:00
} else
{
/* reason set by /quit, /close argument */
serv -> p_part ( serv , channel , reason );
}
}
void
server_sendquit ( session * sess )
{
char * rea , * colrea ;
if ( ! sess -> quitreason )
{
2014-12-28 06:37:25 -05:00
colrea = g_strdup ( prefs . hex_irc_quit_reason );
2011-02-24 04:14:30 +01:00
check_special_chars ( colrea , FALSE );
rea = random_line ( colrea );
2014-12-28 06:37:25 -05:00
g_free ( colrea );
2011-02-24 04:14:30 +01:00
sess -> server -> p_quit ( sess -> server , rea );
2014-12-28 06:37:25 -05:00
g_free ( rea );
2011-02-24 04:14:30 +01:00
} 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 " ;
2016-05-28 16:35:45 +10:00
word [ 1 ] = buf ;
word_eol [ 1 ] = cmd ;
2011-02-24 04:14:30 +01:00
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 ;
}
2012-10-13 06:03:14 +02:00
/* ADDSERVER <networkname> <serveraddress>, add a new network and server to the network list */
static int
cmd_addserver ( struct session * sess , char * tbuf , char * word [], char * word_eol [])
{
ircnet * network ;
/* do we have enough arguments given? */
if ( * word [ 2 ] && * word_eol [ 3 ])
{
network = servlist_net_find ( word [ 2 ], NULL , strcmp );
/* if the given network doesn't exist yet, add it */
if ( ! network )
{
network = servlist_net_add ( word [ 2 ], "" , TRUE );
2014-12-28 06:37:25 -05:00
network -> encoding = g_strdup ( IRC_DEFAULT_CHARSET );
2012-10-13 06:03:14 +02:00
}
/* if we had the network already, check if the given server already exists */
else if ( servlist_server_find ( network , word_eol [ 3 ], NULL ))
{
PrintTextf ( sess , _ ( "Server %s already exists on network %s. \n " ), word_eol [ 3 ], word [ 2 ]);
return TRUE ; /* unsuccessful, but the syntax was correct so we don't want to show the help */
}
/* server added to new or existing network, doesn't make any difference */
servlist_server_add ( network , word_eol [ 3 ]);
PrintTextf ( sess , _ ( "Added server %s to network %s. \n " ), word_eol [ 3 ], word [ 2 ]);
return TRUE ; /* success */
}
else
{
return FALSE ; /* print help */
}
}
2011-02-24 04:14:30 +01:00
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 [])
{
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() */
2012-10-22 09:53:28 +02:00
reason = random_line ( prefs . hex_away_reason );
2011-02-24 04:14:30 +01:00
}
sess -> server -> p_set_away ( sess -> server , reason );
if ( sess -> server -> last_away_reason != reason )
{
2014-12-28 06:37:25 -05:00
g_free ( sess -> server -> last_away_reason );
2011-02-24 04:14:30 +01:00
if ( reason == word_eol [ 2 ])
2014-12-28 06:37:25 -05:00
sess -> server -> last_away_reason = g_strdup ( reason );
2011-02-24 04:14:30 +01:00
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 [])
{
if ( sess -> server -> is_away )
{
sess -> server -> p_set_back ( sess -> server );
}
else
{
PrintText ( sess , _ ( "Already marked back. \n " ));
}
2014-12-28 06:37:25 -05:00
g_free ( sess -> server -> last_away_reason );
2011-02-24 04:14:30 +01:00
sess -> server -> last_away_reason = NULL ;
return TRUE ;
}
2013-06-07 08:24:13 -04:00
static char *
create_mask ( session * sess , char * mask , char * mode , char * typestr , int deop )
2011-02-24 04:14:30 +01:00
{
2013-06-07 08:24:13 -04:00
int type ;
2011-02-24 04:14:30 +01:00
struct User * user ;
char * at , * dot , * lastdot ;
2013-06-08 03:01:36 +01:00
char username [ 64 ], fullhost [ 128 ], domain [ 128 ], buf [ 512 ], * p2 ;
2011-02-24 04:14:30 +01:00
user = userlist_find ( sess , mask );
if ( user && user -> hostname ) /* it's a nickname, let's find a proper ban mask */
{
if ( deop )
p2 = user -> nick ;
2013-06-07 08:24:13 -04:00
else
2011-02-24 04:14:30 +01:00
p2 = "" ;
mask = user -> hostname ;
at = strchr ( mask , '@' ); /* FIXME: utf8 */
if ( ! at )
2013-06-07 08:24:13 -04:00
return NULL ; /* can't happen? */
2011-02-24 04:14:30 +01:00
* 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 ));
}
2013-06-07 08:24:13 -04:00
if ( * typestr )
type = atoi ( typestr );
2011-02-24 04:14:30 +01:00
else
2013-06-07 08:24:13 -04:00
type = prefs . hex_irc_ban_type ;
2011-02-24 04:14:30 +01:00
2013-06-08 03:01:36 +01:00
buf [ 0 ] = 0 ;
2024-01-28 19:33:45 -08:00
if ( inet_addr ( fullhost ) != ( guint32 ) - 1 ) /* "fullhost" is really a IP number */
2011-02-24 04:14:30 +01:00
{
lastdot = strrchr ( fullhost , '.' );
if ( ! lastdot )
2013-06-07 08:24:13 -04:00
return NULL ; /* can't happen? */
2011-02-24 04:14:30 +01:00
* lastdot = 0 ;
strcpy ( domain , fullhost );
* lastdot = '.' ;
2013-06-07 08:24:13 -04:00
switch ( type )
2011-02-24 04:14:30 +01:00
{
case 0 :
2014-12-17 18:49:59 -05:00
g_snprintf ( buf , sizeof ( buf ), "%s %s *!*@%s.*" , mode , p2 , domain );
2011-02-24 04:14:30 +01:00
break ;
case 1 :
2014-12-17 18:49:59 -05:00
g_snprintf ( buf , sizeof ( buf ), "%s %s *!*@%s" , mode , p2 , fullhost );
2011-02-24 04:14:30 +01:00
break ;
case 2 :
2014-12-17 18:49:59 -05:00
g_snprintf ( buf , sizeof ( buf ), "%s %s *!%s@%s.*" , mode , p2 , username , domain );
2011-02-24 04:14:30 +01:00
break ;
case 3 :
2014-12-17 18:49:59 -05:00
g_snprintf ( buf , sizeof ( buf ), "%s %s *!%s@%s" , mode , p2 , username , fullhost );
2011-02-24 04:14:30 +01:00
break ;
}
} else
{
2013-06-07 08:24:13 -04:00
switch ( type )
2011-02-24 04:14:30 +01:00
{
case 0 :
2014-12-17 18:49:59 -05:00
g_snprintf ( buf , sizeof ( buf ), "%s %s *!*@*%s" , mode , p2 , domain );
2011-02-24 04:14:30 +01:00
break ;
case 1 :
2014-12-17 18:49:59 -05:00
g_snprintf ( buf , sizeof ( buf ), "%s %s *!*@%s" , mode , p2 , fullhost );
2011-02-24 04:14:30 +01:00
break ;
case 2 :
2014-12-17 18:49:59 -05:00
g_snprintf ( buf , sizeof ( buf ), "%s %s *!%s@*%s" , mode , p2 , username , domain );
2011-02-24 04:14:30 +01:00
break ;
case 3 :
2014-12-17 18:49:59 -05:00
g_snprintf ( buf , sizeof ( buf ), "%s %s *!%s@%s" , mode , p2 , username , fullhost );
2011-02-24 04:14:30 +01:00
break ;
}
}
} else
{
2014-12-17 18:49:59 -05:00
g_snprintf ( buf , sizeof ( buf ), "%s %s" , mode , mask );
2013-06-07 08:24:13 -04:00
}
2013-06-08 03:01:36 +01:00
return g_strdup ( buf );
2013-06-07 08:24:13 -04:00
}
static void
ban ( session * sess , char * tbuf , char * mask , char * bantypestr , int deop )
{
char * banmask = create_mask ( sess , mask , deop ? "-o+b" : "+b" , bantypestr , deop );
server * serv = sess -> server ;
if ( banmask )
{
serv -> p_mode ( serv , sess -> channel , banmask );
g_free ( banmask );
2011-02-24 04:14:30 +01:00
}
}
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 [])
{
2013-06-06 19:16:50 -04:00
int ret ;
2011-02-24 04:14:30 +01:00
/* chanopt.c */
2013-06-06 19:16:50 -04:00
ret = chanopt_command ( sess , tbuf , word , word_eol );
2016-03-29 19:38:34 +02:00
chanopt_save_all ( FALSE );
2013-06-06 19:16:50 -04:00
return ret ;
2011-02-24 04:14:30 +01:00
}
static int
cmd_charset ( struct session * sess , char * tbuf , char * word [], char * word_eol [])
{
server * serv = sess -> server ;
int offset = 0 ;
if ( strcmp ( word [ 2 ], "-quiet" ) == 0 )
offset ++ ;
if ( ! word [ 2 + offset ][ 0 ])
{
2015-01-18 02:55:32 -08:00
PrintTextf ( sess , "Current charset: %s \n " , serv -> encoding );
2011-02-24 04:14:30 +01:00
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 , " \003 4Unknown 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 ];
2012-06-16 13:01:47 +02:00
if ( g_ascii_strcasecmp ( reason , "HISTORY" ) == 0 )
2011-02-24 04:14:30 +01:00
{
history_free ( & sess -> history );
return TRUE ;
}
2012-06-16 13:01:47 +02:00
if ( g_ascii_strncasecmp ( reason , "all" , 3 ) == 0 )
2011-02-24 04:14:30 +01:00
{
while ( list )
{
sess = list -> data ;
2016-11-11 19:25:46 -05:00
if ( ! ( sess -> tab_state & TAB_STATE_NEW_HILIGHT ))
2011-02-24 04:14:30 +01:00
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 [])
{
2013-09-23 17:17:35 -04:00
char * key = NULL ;
2011-02-24 04:14:30 +01:00
char * chan = word [ 2 ];
2013-09-23 17:17:35 -04:00
session * chan_sess ;
2011-02-24 04:14:30 +01:00
if ( !* chan )
chan = sess -> channel ;
2013-09-23 17:17:35 -04:00
if ( chan )
2011-02-24 04:14:30 +01:00
{
2013-09-23 17:17:35 -04:00
chan_sess = find_channel ( sess -> server , chan );
if ( chan_sess && chan_sess -> type == SESS_CHANNEL )
{
key = chan_sess -> channelkey ;
sess -> server -> p_cycle ( sess -> server , chan , key );
return TRUE ;
}
2011-02-24 04:14:30 +01:00
}
2013-09-23 17:17:35 -04:00
2011-02-24 04:14:30 +01:00
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 )
{
2012-06-16 13:01:47 +02:00
if ( ! g_ascii_strcasecmp ( type , "HELP" ))
2011-02-24 04:14:30 +01:00
return FALSE ;
2012-06-16 13:01:47 +02:00
if ( ! g_ascii_strcasecmp ( type , "CLOSE" ))
2011-02-24 04:14:30 +01:00
{
if ( * word [ 3 ] && * word [ 4 ])
{
goodtype = 0 ;
2012-06-16 13:01:47 +02:00
if ( ! g_ascii_strcasecmp ( word [ 3 ], "SEND" ))
2011-02-24 04:14:30 +01:00
{
dcc = find_dcc ( word [ 4 ], word [ 5 ], TYPE_SEND );
dcc_abort ( sess , dcc );
goodtype = TRUE ;
}
2012-06-16 13:01:47 +02:00
if ( ! g_ascii_strcasecmp ( word [ 3 ], "GET" ))
2011-02-24 04:14:30 +01:00
{
dcc = find_dcc ( word [ 4 ], word [ 5 ], TYPE_RECV );
dcc_abort ( sess , dcc );
goodtype = TRUE ;
}
2012-06-16 13:01:47 +02:00
if ( ! g_ascii_strcasecmp ( word [ 3 ], "CHAT" ))
2011-02-24 04:14:30 +01:00
{
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 ;
}
2012-06-16 13:01:47 +02:00
if (( ! g_ascii_strcasecmp ( type , "CHAT" )) || ( ! g_ascii_strcasecmp ( type , "PCHAT" )))
2011-02-24 04:14:30 +01:00
{
char * nick = word [ 3 ];
2012-06-16 13:01:47 +02:00
int passive = ( ! g_ascii_strcasecmp ( type , "PCHAT" )) ? 1 : 0 ;
2011-02-24 04:14:30 +01:00
if ( * nick )
dcc_chat ( sess , nick , passive );
return TRUE ;
}
2012-06-16 13:01:47 +02:00
if ( ! g_ascii_strcasecmp ( type , "LIST" ))
2011-02-24 04:14:30 +01:00
{
dcc_show_list ( sess );
return TRUE ;
}
2012-06-16 13:01:47 +02:00
if ( ! g_ascii_strcasecmp ( type , "GET" ))
2011-02-24 04:14:30 +01:00
{
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 ;
}
2012-06-16 13:01:47 +02:00
if (( ! g_ascii_strcasecmp ( type , "SEND" )) || ( ! g_ascii_strcasecmp ( type , "PSEND" )))
2011-02-24 04:14:30 +01:00
{
int i = 3 , maxcps ;
char * nick , * file ;
2012-06-16 13:01:47 +02:00
int passive = ( ! g_ascii_strcasecmp ( type , "PSEND" )) ? 1 : 0 ;
2011-02-24 04:14:30 +01:00
nick = word [ i ];
if ( !* nick )
return FALSE ;
2012-10-22 12:10:55 +02:00
maxcps = prefs . hex_dcc_max_send_cps ;
2012-06-16 13:01:47 +02:00
if ( ! g_ascii_strncasecmp ( nick , "-maxcps=" , 8 ))
2011-02-24 04:14:30 +01:00
{
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 ,
" \n front_session: %p \n "
"current_tab: %p \n\n " ,
sess -> server -> front_session , current_tab );
PrintText ( sess , tbuf );
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 [])
{
2014-12-28 06:37:25 -05:00
char ** nicks = g_new0 ( char * , sess -> hops );
2011-02-24 04:14:30 +01:00
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 );
2014-12-28 06:37:25 -05:00
g_free ( nicks );
2011-02-24 04:14:30 +01:00
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 [])
{
2014-12-28 06:37:25 -05:00
char ** nicks = g_new0 ( char * , sess -> ops );
2011-02-24 04:14:30 +01:00
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 );
2014-12-28 06:37:25 -05:00
g_free ( nicks );
2011-02-24 04:14:30 +01:00
return TRUE ;
}
GSList * menu_list = NULL ;
static void
menu_free ( menu_entry * me )
{
2014-12-28 06:37:25 -05:00
g_free ( me -> path );
g_free ( me -> label );
g_free ( me -> cmd );
g_free ( me -> ucmd );
g_free ( me -> group );
g_free ( me -> icon );
g_free ( me );
2011-02-24 04:14:30 +01:00
}
/* 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 ])
2014-12-17 18:49:59 -05:00
g_snprintf ( buf , sizeof ( buf ), "%s/%s" , path , label );
2011-02-24 04:14:30 +01:00
else
2014-12-17 18:49:59 -05:00
g_snprintf ( buf , sizeof ( buf ), "%s" , label );
2011-02-24 04:14:30 +01:00
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 ]))
{
2014-12-11 13:49:37 -05:00
* offset = menus [ i ][ 0 ]; /* number of bytes to offset the root */
if ( path [ * offset ] != '\0' )
* offset += 1 ;
2011-02-24 04:14:30 +01:00
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 ;
}
2014-12-28 06:37:25 -05:00
me = g_new ( menu_entry , 1 );
2011-02-24 04:14:30 +01:00
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 ;
2014-12-28 06:37:25 -05:00
me -> path = g_strdup ( path );
2011-02-24 04:14:30 +01:00
me -> label = NULL ;
me -> cmd = NULL ;
me -> ucmd = NULL ;
me -> group = NULL ;
me -> icon = NULL ;
2014-12-28 06:37:25 -05:00
me -> label = g_strdup ( label );
me -> cmd = g_strdup ( cmd );
me -> ucmd = g_strdup ( ucmd );
me -> group = g_strdup ( group );
me -> icon = g_strdup ( icon );
2011-02-24 04:14:30 +01:00
menu_list = g_slist_append ( menu_list , me );
label = fe_menu_add ( me );
if ( label )
{
/* FE has given us a stripped label */
2014-12-28 06:37:25 -05:00
g_free ( me -> label );
me -> label = g_strdup ( label );
2011-02-24 04:14:30 +01:00
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 ;
2013-01-19 12:33:16 -08:00
int state = 0 ;
2011-02-24 04:14:30 +01:00
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 */
2014-12-31 11:12:43 -05:00
for ( p = label ; p && * p ; p ++ )
2011-02-24 04:14:30 +01:00
if ( * p == 3 )
* p = '/' ;
}
2012-06-16 13:01:47 +02:00
if ( ! g_ascii_strcasecmp ( word [ idx ], "ADD" ))
2011-02-24 04:14:30 +01:00
{
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 ;
}
2012-06-16 13:01:47 +02:00
if ( ! g_ascii_strcasecmp ( word [ idx ], "DEL" ))
2011-02-24 04:14:30 +01:00
{
menu_del ( tbuf , label );
return TRUE ;
}
return FALSE ;
}
2016-08-10 21:53:30 -07:00
static int
mhop_cb ( struct User * user , multidata * data )
{
if ( ! user -> hop )
{
data -> nicks [ data -> i ] = user -> nick ;
data -> i ++ ;
}
return TRUE ;
}
static int
cmd_mhop ( struct session * sess , char * tbuf , char * word [], char * word_eol [])
{
char ** nicks = g_new0 ( char * , sess -> total - sess -> hops );
multidata data ;
data . nicks = nicks ;
data . i = 0 ;
tree_foreach ( sess -> usertree , ( tree_traverse_func * ) mhop_cb , & data );
send_channel_modes ( sess , tbuf , nicks , 0 , data . i , '+' , 'h' , 0 );
g_free ( nicks );
return TRUE ;
}
2011-02-24 04:14:30 +01:00
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 [])
{
char * nick = word [ 2 ];
struct User * user ;
2014-01-08 01:32:28 -05:00
message_tags_data no_tags = MESSAGE_TAGS_DATA_INIT ;
2011-02-24 04:14:30 +01:00
if ( * nick )
{
2014-01-08 01:32:28 -05:00
user = userlist_find ( sess , nick );
if ( user )
2011-02-24 04:14:30 +01:00
{
2014-01-08 01:32:28 -05:00
if ( user -> hostname )
2011-02-24 04:14:30 +01:00
{
2013-06-23 19:53:41 +01:00
do_dns ( sess , user -> nick , user -> hostname , & no_tags );
2011-02-24 04:14:30 +01:00
} else
{
sess -> server -> p_get_ip ( sess -> server , nick );
sess -> server -> doing_dns = TRUE ;
}
} else
{
2014-01-08 01:32:28 -05:00
do_dns ( sess , NULL , nick , & no_tags );
2011-02-24 04:14:30 +01:00
}
return TRUE ;
}
return FALSE ;
}
2016-11-08 22:34:31 -05:00
static int
cmd_doat ( struct session * sess , char * tbuf , char * word [], char * word_eol [])
{
GStrv channels ;
guint i ;
if ( ! word [ 2 ] || !* word [ 2 ] || ! word [ 3 ] || !* word [ 3 ])
return FALSE ;
channels = g_strsplit ( word [ 2 ], "," , - 1 );
for ( i = 0 ; channels [ i ] && * channels [ i ]; ++ i )
{
char * chan = channels [ i ];
char * serv ;
session * ctx ;
/* Split channel and network, either may be empty */
2017-07-04 13:53:15 -04:00
if (( serv = strrchr ( chan , '/' )))
2016-11-08 22:34:31 -05:00
{
* serv = '\0' ;
serv ++ ;
if ( ! strlen ( serv ))
serv = NULL ;
}
if ( ! strlen ( chan ))
chan = NULL ;
if (( ctx = plugin_find_context ( serv , chan , sess -> server )))
handle_command ( ctx , word_eol [ 3 ], FALSE );
}
g_strfreev ( channels );
return TRUE ;
}
2011-02-24 04:14:30 +01:00
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 );
2014-12-28 06:37:25 -05:00
g_free ( sess -> running_exec );
2011-02-24 04:14:30 +01:00
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 ;
}
2022-01-24 18:38:21 +01:00
if ( strcmp ( word [ 2 ], "--" ) == 0 )
{
len = strlen ( word_eol [ 3 ]);
temp = g_strconcat ( word_eol [ 3 ], " \n " , NULL );
PrintText ( sess , temp );
}
else
{
if ( strcmp ( word [ 2 ], "-q" ) == 0 )
{
len = strlen ( word_eol [ 3 ]);
temp = g_strconcat ( word_eol [ 3 ], " \n " , NULL );
}
else
{
len = strlen ( word_eol [ 2 ]);
temp = g_strconcat ( word_eol [ 2 ], " \n " , NULL );
PrintText ( sess , temp );
}
}
2011-02-24 04:14:30 +01:00
write ( sess -> running_exec -> myfd , temp , len + 1 );
2014-12-28 06:37:25 -05:00
g_free ( temp );
2011-02-24 04:14:30 +01:00
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 ;
2014-12-28 06:37:25 -05:00
nbuf = g_malloc ( len + 1 );
2011-02-24 04:14:30 +01:00
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 );
2014-12-28 06:37:25 -05:00
g_free ( nbuf );
2011-02-24 04:14:30 +01:00
}
#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 ;
2014-12-31 11:31:17 -05:00
return NULL ;
2011-02-24 04:14:30 +01:00
}
#endif
2016-12-04 04:39:06 -05:00
static void
exec_print_line ( session * sess , char * data , gssize len , gboolean tochannel )
{
2016-12-04 04:44:10 -05:00
char * valid ;
2016-12-04 04:39:06 -05:00
exec_handle_colors ( data , len );
2016-12-04 04:44:10 -05:00
valid = text_fixup_invalid_utf8 ( data , len , NULL );
2016-12-04 04:39:06 -05:00
if ( tochannel )
{
/* must turn off auto-completion temporarily */
const unsigned int old = prefs . hex_completion_auto ;
prefs . hex_completion_auto = 0 ;
handle_multiline ( sess , valid , FALSE , TRUE );
prefs . hex_completion_auto = old ;
}
else
PrintText ( sess , valid );
g_free ( valid );
}
2011-02-24 04:14:30 +01:00
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 */
2014-12-28 06:37:25 -05:00
buf = g_malloc ( len + 2050 );
2011-02-24 04:14:30 +01:00
memcpy ( buf , s -> linebuf , len );
readpos = buf + len ;
2014-12-28 06:37:25 -05:00
g_free ( s -> linebuf );
2011-02-24 04:14:30 +01:00
s -> linebuf = NULL ;
}
else
2014-12-28 06:37:25 -05:00
readpos = buf = g_malloc ( 2050 );
2011-02-24 04:14:30 +01:00
rd = read ( sok , readpos , 2048 );
if ( rd < 1 )
{
/* The process has died */
kill ( s -> childpid , SIGKILL );
if ( len ) {
buf [ len ] = '\0' ;
2016-12-04 04:39:06 -05:00
exec_print_line ( s -> sess , buf , len , s -> tochannel );
2011-02-24 04:14:30 +01:00
}
2014-12-28 06:37:25 -05:00
g_free ( buf );
2011-02-24 04:14:30 +01:00
waitpid ( s -> childpid , NULL , 0 );
s -> sess -> running_exec = NULL ;
fe_input_remove ( s -> iotag );
close ( sok );
2014-12-28 06:37:25 -05:00
g_free ( s );
2011-02-24 04:14:30 +01:00
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) */
2014-12-28 06:37:25 -05:00
s -> linebuf = g_malloc ( s -> buffill + 1 );
2011-02-24 04:14:30 +01:00
memcpy ( s -> linebuf , rest , s -> buffill );
* rest = '\0' ;
len -= s -> buffill ; /* possibly 0 */
}
else
s -> buffill = 0 ;
if ( len ) {
2016-12-04 04:39:06 -05:00
exec_print_line ( s -> sess , buf , len , s -> tochannel );
2011-02-24 04:14:30 +01:00
}
2014-12-28 06:37:25 -05:00
g_free ( buf );
2011-02-24 04:14:30 +01:00
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
2014-12-28 06:37:25 -05:00
s = g_new0 ( struct nbexec , 1 );
2011-02-24 04:14:30 +01:00
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 ;
2014-04-25 13:41:38 -04:00
g_shell_parse_argv ( cmd , & argc , & argv , NULL );
2011-02-24 04:14:30 +01:00
execvp ( argv [ 0 ], argv );
2014-04-25 13:41:38 -04:00
g_strfreev ( argv );
2011-02-24 04:14:30 +01:00
}
/* not reached unless error */
/*printf("exec error\n");*/
fflush ( stdout );
_exit ( 0 );
}
if ( pid == - 1 )
{
/* Parent context, fork() failed */
PrintText ( sess , "Error in fork(2) \n " );
close ( fds [ 0 ]);
close ( fds [ 1 ]);
2014-12-28 06:37:25 -05:00
g_free ( s );
}
else
2011-02-24 04:14:30 +01:00
{
/* 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
2012-11-03 06:29:51 +01:00
#if 0
/* export config stub */
static int
cmd_exportconf (struct session *sess, char *tbuf, char *word[], char *word_eol[])
{
2026-01-05 23:12:38 -07:00
/* this is pretty much the same as in zoitechat_exit() */
2012-11-03 06:29:51 +01:00
save_config ();
if (prefs.save_pevents)
{
pevent_save (NULL);
}
sound_save ();
notify_save ();
ignore_save ();
free_sessions ();
chanopt_save_all ();
return TRUE; /* success */
return FALSE; /* fail */
}
#endif
2011-02-24 04:14:30 +01:00
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 ;
2013-12-31 17:06:58 -05:00
static void
get_bool_cb ( int val , getvalinfo * info )
{
char buf [ 512 ];
2014-12-17 18:49:59 -05:00
g_snprintf ( buf , sizeof ( buf ), "%s %d" , info -> cmd , val );
2013-12-31 17:06:58 -05:00
if ( is_session ( info -> sess ))
handle_command ( info -> sess , buf , FALSE );
2014-12-28 06:37:25 -05:00
g_free ( info -> cmd );
g_free ( info );
2013-12-31 17:06:58 -05:00
}
static int
cmd_getbool ( struct session * sess , char * tbuf , char * word [], char * word_eol [])
{
getvalinfo * info ;
if ( ! word [ 4 ][ 0 ])
return FALSE ;
2014-12-28 06:37:25 -05:00
info = g_new ( getvalinfo , 1 );
info -> cmd = g_strdup ( word [ 2 ]);
2013-12-31 17:06:58 -05:00
info -> sess = sess ;
fe_get_bool ( word [ 3 ], word_eol [ 4 ], get_bool_cb , info );
return TRUE ;
}
2011-02-24 04:14:30 +01:00
static void
get_int_cb ( int cancel , int val , getvalinfo * info )
{
char buf [ 512 ];
if ( ! cancel )
{
2014-12-17 18:49:59 -05:00
g_snprintf ( buf , sizeof ( buf ), "%s %d" , info -> cmd , val );
2011-02-24 04:14:30 +01:00
if ( is_session ( info -> sess ))
handle_command ( info -> sess , buf , FALSE );
}
2014-12-28 06:37:25 -05:00
g_free ( info -> cmd );
g_free ( info );
2011-02-24 04:14:30 +01:00
}
static int
cmd_getint ( struct session * sess , char * tbuf , char * word [], char * word_eol [])
{
getvalinfo * info ;
if ( ! word [ 4 ][ 0 ])
return FALSE ;
2014-12-28 06:37:25 -05:00
info = g_new ( getvalinfo , 1 );
info -> cmd = g_strdup ( word [ 3 ]);
2011-02-24 04:14:30 +01:00
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 )
{
2014-12-17 18:49:59 -05:00
g_snprintf ( buf , sizeof ( buf ), "%s %s" , cmd , file );
2011-02-24 04:14:30 +01:00
handle_command ( current_sess , buf , FALSE );
}
else
{
handle_command ( current_sess , cmd , FALSE );
2014-12-28 06:37:25 -05:00
g_free ( cmd );
2011-02-24 04:14:30 +01:00
}
}
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 ++ ;
}
2014-12-28 06:37:25 -05:00
fe_get_file ( word [ idx + 1 ], word [ idx + 2 ], ( void * ) get_file_cb , g_strdup ( word [ idx ]), flags );
2011-02-24 04:14:30 +01:00
return TRUE ;
}
static void
get_str_cb ( int cancel , char * val , getvalinfo * info )
{
char buf [ 512 ];
if ( ! cancel )
{
2014-12-17 18:49:59 -05:00
g_snprintf ( buf , sizeof ( buf ), "%s %s" , info -> cmd , val );
2011-02-24 04:14:30 +01:00
if ( is_session ( info -> sess ))
handle_command ( info -> sess , buf , FALSE );
}
2014-12-28 06:37:25 -05:00
g_free ( info -> cmd );
g_free ( info );
2011-02-24 04:14:30 +01:00
}
static int
cmd_getstr ( struct session * sess , char * tbuf , char * word [], char * word_eol [])
{
getvalinfo * info ;
if ( ! word [ 4 ][ 0 ])
return FALSE ;
2014-12-28 06:37:25 -05:00
info = g_new ( getvalinfo , 1 );
info -> cmd = g_strdup ( word [ 3 ]);
2011-02-24 04:14:30 +01:00
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 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 */
2012-06-16 13:01:47 +02:00
if ( ! g_ascii_strcasecmp ( word [ 3 ], "TOGGLE" ))
2011-02-24 04:14:30 +01:00
fe_ctrl_gui ( sess , 6 , 0 );
else
return FALSE ;
break ;
2021-10-14 07:44:11 -07:00
case 0x05a72f63 : /* COLOR */
if ( ! g_ascii_strcasecmp ( word [ 4 ], "-NOOVERRIDE" ))
fe_ctrl_gui ( sess , 4 , FE_COLOR_FLAG_NOOVERRIDE | atoi ( word [ 3 ]));
else
fe_ctrl_gui ( sess , 4 , atoi ( word [ 3 ]));
break ;
2011-02-24 04:14:30 +01:00
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 , " \003 4%s \003 : \n " , name );
else
PrintTextf ( sess , " \003 4%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 ;
2014-12-28 06:37:25 -05:00
char * buf = g_malloc ( 4096 );
2011-02-24 04:14:30 +01:00
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 );
2014-12-28 06:37:25 -05:00
g_free ( buf );
2011-02-24 04:14:30 +01:00
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 ])
2013-03-17 16:27:26 -03:00
word [ 3 ] = "ALL" ;
2011-02-24 04:14:30 +01:00
i = 3 ;
while ( 1 )
{
if ( !* word [ i ])
{
if ( type == 0 )
return FALSE ;
mask = word [ 2 ];
2018-03-09 21:33:42 -05:00
/* If not a full mask or using wildcards, assume nick */
if ( strchr ( mask , '!' ) == NULL &&
strchr ( mask , '@' ) == NULL &&
strchr ( mask , '?' ) == NULL &&
2012-07-13 20:18:53 +02:00
strchr ( mask , '*' ) == NULL )
2011-02-24 04:14:30 +01:00
{
mask = tbuf ;
2014-12-17 18:49:59 -05:00
g_snprintf ( tbuf , TBUFSIZE , "%s!*@*" , word [ 2 ]);
2011-02-24 04:14:30 +01:00
}
2013-10-14 17:25:21 -04:00
i = ignore_add ( mask , type , TRUE );
2011-02-24 04:14:30 +01:00
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 ;
}
2012-06-16 13:01:47 +02:00
if ( ! g_ascii_strcasecmp ( word [ i ], "UNIGNORE" ))
2011-02-24 04:14:30 +01:00
type |= IG_UNIG ;
2012-06-16 13:01:47 +02:00
else if ( ! g_ascii_strcasecmp ( word [ i ], "ALL" ))
2011-02-24 04:14:30 +01:00
type |= IG_PRIV | IG_NOTI | IG_CHAN | IG_CTCP | IG_INVI | IG_DCC ;
2012-06-16 13:01:47 +02:00
else if ( ! g_ascii_strcasecmp ( word [ i ], "PRIV" ))
2011-02-24 04:14:30 +01:00
type |= IG_PRIV ;
2012-06-16 13:01:47 +02:00
else if ( ! g_ascii_strcasecmp ( word [ i ], "NOTI" ))
2011-02-24 04:14:30 +01:00
type |= IG_NOTI ;
2012-06-16 13:01:47 +02:00
else if ( ! g_ascii_strcasecmp ( word [ i ], "CHAN" ))
2011-02-24 04:14:30 +01:00
type |= IG_CHAN ;
2012-06-16 13:01:47 +02:00
else if ( ! g_ascii_strcasecmp ( word [ i ], "CTCP" ))
2011-02-24 04:14:30 +01:00
type |= IG_CTCP ;
2012-06-16 13:01:47 +02:00
else if ( ! g_ascii_strcasecmp ( word [ i ], "INVI" ))
2011-02-24 04:14:30 +01:00
type |= IG_INVI ;
2012-06-16 13:01:47 +02:00
else if ( ! g_ascii_strcasecmp ( word [ i ], "QUIET" ))
2011-02-24 04:14:30 +01:00
quiet = 1 ;
2012-06-16 13:01:47 +02:00
else if ( ! g_ascii_strcasecmp ( word [ i ], "NOSAVE" ))
2011-02-24 04:14:30 +01:00
type |= IG_NOSAVE ;
2012-06-16 13:01:47 +02:00
else if ( ! g_ascii_strcasecmp ( word [ i ], "DCC" ))
2011-02-24 04:14:30 +01:00
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 ];
2013-02-24 23:04:48 +01:00
session * sess_find ;
2011-02-24 04:14:30 +01:00
if ( * chan )
{
char * po , * pass = word [ 3 ];
2013-02-24 23:04:48 +01:00
sess_find = find_channel ( sess -> server , chan );
if ( ! sess_find )
2011-02-24 04:14:30 +01:00
{
2013-02-24 23:04:48 +01:00
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 );
}
2011-02-24 04:14:30 +01:00
}
2013-02-24 23:04:48 +01:00
else
fe_ctrl_gui ( sess_find , 2 , 0 ); /* bring-to-front */
2011-02-24 04:14:30 +01:00
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 [])
{
2026-01-05 23:12:38 -07:00
zoitechat_exit ();
2011-02-24 04:14:30 +01:00
return 2 ;
}
static int
cmd_lagcheck ( struct session * sess , char * tbuf , char * word [], char * word_eol [])
{
lag_check ();
return TRUE ;
}
static void
2012-08-28 19:10:03 -07:00
lastlog ( session * sess , char * search , gtk_xtext_search_flags flags )
2011-02-24 04:14:30 +01:00
{
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 ;
2012-08-28 19:10:03 -07:00
lastlog_sess -> lastlog_flags = flags ;
2011-02-24 04:14:30 +01:00
fe_text_clear ( lastlog_sess , 0 );
2012-08-28 19:10:03 -07:00
fe_lastlog ( sess , lastlog_sess , search , flags );
2011-02-24 04:14:30 +01:00
}
static int
cmd_lastlog ( struct session * sess , char * tbuf , char * word [], char * word_eol [])
{
2012-08-28 19:10:03 -07:00
int j = 2 ;
gtk_xtext_search_flags flags = 0 ;
gboolean doublehyphen = FALSE ;
while ( word_eol [ j ] != NULL && word_eol [ j ][ 0 ] == '-' && ! doublehyphen )
2011-02-24 04:14:30 +01:00
{
2012-08-28 19:10:03 -07:00
switch ( word_eol [ j ][ 1 ])
2012-07-25 22:12:42 +02:00
{
2012-08-28 19:10:03 -07:00
case 'r' :
flags |= regexp ;
break ;
case 'm' :
flags |= case_match ;
break ;
case 'h' :
flags |= highlight ;
break ;
case '-' :
doublehyphen = TRUE ;
break ;
default :
break ;
/* O dear whatever shall we do here? */
2012-07-25 22:12:42 +02:00
}
2012-08-28 19:10:03 -07:00
j ++ ;
}
2014-04-26 18:12:46 +02:00
if ( word_eol [ j ] != NULL && * word_eol [ j ])
2012-08-28 19:10:03 -07:00
{
lastlog ( sess , word_eol [ j ], flags );
2011-02-24 04:14:30 +01:00
return TRUE ;
}
2012-08-28 19:10:03 -07:00
else
{
return FALSE ;
}
2011-02-24 04:14:30 +01:00
}
static int
cmd_list ( struct session * sess , char * tbuf , char * word [], char * word_eol [])
{
2013-10-13 22:39:17 +03:00
fe_open_chan_list ( sess -> server , word_eol [ 2 ], TRUE );
2011-02-24 04:14:30 +01:00
return TRUE ;
}
gboolean
load_perform_file ( session * sess , char * file )
{
char tbuf [ 1024 + 4 ];
char * nl ;
FILE * fp ;
2026-01-05 23:12:38 -07:00
fp = zoitechat_fopen_file ( file , "r" , 0 ); /* load files from config dir */
2011-02-24 04:14:30 +01:00
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 ;
2012-10-22 14:18:20 +02:00
if ( tbuf [ 0 ] == prefs . hex_input_command_char [ 0 ])
2011-02-24 04:14:30 +01:00
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 [])
{
2014-01-16 00:46:49 -05:00
char * file , * buf ;
#ifdef USE_PLUGIN
char * error , * arg ;
#endif
2011-02-24 04:14:30 +01:00
if ( ! word [ 2 ][ 0 ])
return FALSE ;
if ( strcmp ( word [ 2 ], "-e" ) == 0 )
{
file = expand_homedir ( word [ 3 ]);
if ( ! load_perform_file ( sess , file ))
{
2013-06-04 06:34:15 -03:00
buf = g_strdup_printf ( "%s%c%s" , get_xdir (), G_DIR_SEPARATOR , file );
PrintTextf ( sess , _ ( "Cannot access %s \n " ), buf );
2011-02-24 04:14:30 +01:00
PrintText ( sess , errorstring ( errno ));
2013-06-04 06:34:15 -03:00
g_free ( buf );
2011-02-24 04:14:30 +01:00
}
2014-12-08 21:24:59 -08:00
g_free ( file );
2011-02-24 04:14:30 +01:00
return TRUE ;
}
#ifdef USE_PLUGIN
2018-03-31 00:53:56 +02:00
if ( g_str_has_suffix ( word [ 2 ], "." PLUGIN_SUFFIX ))
2011-02-24 04:14:30 +01:00
{
arg = NULL ;
if ( word_eol [ 3 ][ 0 ])
arg = word_eol [ 3 ];
file = expand_homedir ( word [ 2 ]);
error = plugin_load ( sess , file , arg );
2014-12-08 21:24:59 -08:00
g_free ( file );
2011-02-24 04:14:30 +01:00
if ( error )
PrintText ( sess , error );
return TRUE ;
}
sprintf ( tbuf , "Unknown file type %s. Maybe you need to install the Perl or Python plugin? \n " , word [ 2 ]);
PrintText ( sess , tbuf );
2014-01-16 00:46:49 -05:00
#endif
2011-02-24 04:14:30 +01:00
return FALSE ;
}
2013-04-05 23:14:51 +02:00
char *
2013-04-06 00:11:45 +02:00
split_up_text ( struct session * sess , char * text , int cmd_length , char * split_text )
2013-04-05 23:14:51 +02:00
{
2013-09-24 19:57:37 -04:00
unsigned int max , space_offset ;
char * space ;
2013-04-05 23:14:51 +02:00
/* maximum allowed text */
/* :nickname!username@host.com cmd_length */
max = 512 ; /* rfc 2812 */
max -= 3 ; /* :, !, @ */
max -= cmd_length ;
max -= strlen ( sess -> server -> nick );
max -= strlen ( sess -> channel );
if ( sess -> me && sess -> me -> hostname )
max -= strlen ( sess -> me -> hostname );
else
{
max -= 9 ; /* username */
max -= 65 ; /* max possible hostname and '@' */
}
if ( strlen ( text ) > max )
{
unsigned int i = 0 ;
int size ;
/* traverse the utf8 string and find the nearest cut point that
doesn't split 1 char in half */
while ( 1 )
{
size = g_utf8_skip [(( unsigned char * ) text )[ i ]];
if (( i + size ) >= max )
break ;
i += size ;
}
max = i ;
2013-09-24 19:57:37 -04:00
/* Try splitting at last space */
space = g_utf8_strrchr ( text , max , ' ' );
if ( space )
{
space_offset = g_utf8_pointer_to_offset ( text , space );
/* Only split if last word is of sane length */
if ( max != space_offset && max - space_offset < 20 )
max = space_offset + 1 ;
}
2013-04-06 00:11:45 +02:00
split_text = g_strdup_printf ( "%.*s" , max , text );
2013-04-05 23:14:51 +02:00
2013-04-06 00:11:45 +02:00
return split_text ;
2013-04-05 23:14:51 +02:00
}
return NULL ;
}
2011-02-24 04:14:30 +01:00
static int
cmd_me ( struct session * sess , char * tbuf , char * word [], char * word_eol [])
{
char * act = word_eol [ 2 ];
2013-04-06 00:11:45 +02:00
char * split_text = NULL ;
2013-04-05 23:14:51 +02:00
int cmd_length = 22 ; /* " PRIVMSG ", " ", :, \001ACTION, " ", \001, \r, \n */
int offset = 0 ;
2013-06-23 19:53:41 +01:00
message_tags_data no_tags = MESSAGE_TAGS_DATA_INIT ;
2011-02-24 04:14:30 +01:00
if ( ! ( * act ))
return FALSE ;
if ( sess -> type == SESS_SERVER )
{
notj_msg ( sess );
return TRUE ;
}
2014-12-17 18:49:59 -05:00
g_snprintf ( tbuf , TBUFSIZE , " \001 ACTION %s \001\r " , act );
2011-02-24 04:14:30 +01:00
/* first try through DCC CHAT */
if ( dcc_write_chat ( sess -> channel , tbuf ))
{
/* print it to screen */
2013-06-23 19:53:41 +01:00
inbound_action ( sess , sess -> channel , sess -> server -> nick , "" , act , TRUE , FALSE ,
& no_tags );
2011-02-24 04:14:30 +01:00
} else
{
/* DCC CHAT failed, try through server */
if ( sess -> server -> connected )
{
2013-04-06 00:11:45 +02:00
while (( split_text = split_up_text ( sess , act + offset , cmd_length , split_text )))
2013-04-05 23:14:51 +02:00
{
2013-04-06 00:11:45 +02:00
sess -> server -> p_action ( sess -> server , sess -> channel , split_text );
2013-04-05 23:14:51 +02:00
/* print it to screen */
2013-06-23 19:53:41 +01:00
inbound_action ( sess , sess -> channel , sess -> server -> nick , "" ,
split_text , TRUE , FALSE ,
& no_tags );
2013-04-05 23:14:51 +02:00
2013-04-06 00:11:45 +02:00
if ( * split_text )
offset += strlen ( split_text );
2013-04-05 23:14:51 +02:00
2014-12-08 21:24:59 -08:00
g_free ( split_text );
2013-04-05 23:14:51 +02:00
}
sess -> server -> p_action ( sess -> server , sess -> channel , act + offset );
2011-02-24 04:14:30 +01:00
/* print it to screen */
2013-06-23 19:53:41 +01:00
inbound_action ( sess , sess -> channel , sess -> server -> nick , "" ,
act + offset , TRUE , FALSE , & no_tags );
2011-02-24 04:14:30 +01:00
} else
{
notc_msg ( sess );
}
}
return TRUE ;
}
static int
cmd_mode ( struct session * sess , char * tbuf , char * word [], char * word_eol [])
{
2015-09-03 02:28:25 -04:00
/* We allow omitting the target, so we have to figure it out:
* - Can only use info from channels or dialogs
* - Empty arg is always sess info
* - Assume + is mode not channel
* - We know valid channels and our nick
* - We cannot easily know if other nick or valid mode (Need to store 004)
*/
if (( sess -> type != SESS_CHANNEL && sess -> type != SESS_DIALOG )
|| ( ! ( * word [ 2 ] == '-' || * word [ 2 ] == '+' || * word [ 2 ] == '\0' )
&& ( is_channel ( sess -> server , word [ 2 ]) || ! rfc_casecmp ( sess -> server -> nick , word [ 2 ])))
)
{
sess -> server -> p_mode ( sess -> server , word [ 2 ], word_eol [ 3 ]);
}
else
2011-02-24 04:14:30 +01:00
{
if ( sess -> channel [ 0 ] == 0 )
return FALSE ;
sess -> server -> p_mode ( sess -> server , sess -> channel , word_eol [ 2 ]);
}
return TRUE ;
}
static int
mop_cb ( struct User * user , multidata * data )
{
if ( ! user -> op )
{
data -> nicks [ data -> i ] = user -> nick ;
data -> i ++ ;
}
return TRUE ;
}
static int
cmd_mop ( struct session * sess , char * tbuf , char * word [], char * word_eol [])
{
2014-12-28 06:37:25 -05:00
char ** nicks = g_new0 ( char * , sess -> total - sess -> ops );
2011-02-24 04:14:30 +01:00
multidata data ;
data . nicks = nicks ;
data . i = 0 ;
tree_foreach ( sess -> usertree , ( tree_traverse_func * ) mop_cb , & data );
send_channel_modes ( sess , tbuf , nicks , 0 , data . i , '+' , 'o' , 0 );
2014-12-28 06:37:25 -05:00
g_free ( nicks );
2011-02-24 04:14:30 +01:00
return TRUE ;
}
static int
cmd_msg ( struct session * sess , char * tbuf , char * word [], char * word_eol [])
{
char * nick = word [ 2 ];
char * msg = word_eol [ 3 ];
struct session * newsess ;
2013-04-06 01:11:28 +02:00
char * split_text = NULL ;
int cmd_length = 13 ; /* " PRIVMSG ", " ", :, \r, \n */
int offset = 0 ;
2011-02-24 04:14:30 +01:00
if ( * nick )
{
if ( * msg )
{
if ( strcmp ( nick , "." ) == 0 )
{ /* /msg the last nick /msg'ed */
if ( sess -> lastnick [ 0 ])
nick = sess -> lastnick ;
} else
{
safe_strcpy ( sess -> lastnick , nick , NICKLEN ); /* prime the last nick memory */
}
if ( * nick == '=' )
{
nick ++ ;
if ( ! dcc_write_chat ( nick , msg ))
{
EMIT_SIGNAL ( XP_TE_NODCC , sess , NULL , NULL , NULL , NULL , 0 );
return TRUE ;
}
} else
{
if ( ! sess -> server -> connected )
{
notc_msg ( sess );
return TRUE ;
}
2013-04-06 01:11:28 +02:00
while (( split_text = split_up_text ( sess , msg + offset , cmd_length , split_text )))
{
sess -> server -> p_message ( sess -> server , nick , split_text );
if ( * split_text )
offset += strlen ( split_text );
2014-12-08 21:24:59 -08:00
g_free ( split_text );
2013-04-06 01:11:28 +02:00
}
sess -> server -> p_message ( sess -> server , nick , msg + offset );
offset = 0 ;
2011-02-24 04:14:30 +01:00
}
newsess = find_dialog ( sess -> server , nick );
if ( ! newsess )
newsess = find_channel ( sess -> server , nick );
if ( newsess )
2013-04-06 01:11:28 +02:00
{
2013-06-23 21:31:09 +01:00
message_tags_data no_tags = MESSAGE_TAGS_DATA_INIT ;
2013-04-06 01:11:28 +02:00
while (( split_text = split_up_text ( sess , msg + offset , cmd_length , split_text )))
{
inbound_chanmsg ( newsess -> server , NULL , newsess -> channel ,
2013-06-23 21:31:09 +01:00
newsess -> server -> nick , split_text , TRUE , FALSE ,
& no_tags );
2013-04-06 01:11:28 +02:00
if ( * split_text )
offset += strlen ( split_text );
2014-12-08 21:24:59 -08:00
g_free ( split_text );
2013-04-06 01:11:28 +02:00
}
2011-02-24 04:14:30 +01:00
inbound_chanmsg ( newsess -> server , NULL , newsess -> channel ,
2013-06-23 21:31:09 +01:00
newsess -> server -> nick , msg + offset , TRUE , FALSE ,
& no_tags );
2013-04-06 01:11:28 +02:00
}
2011-02-24 04:14:30 +01:00
else
{
/* mask out passwords */
2016-06-17 15:07:15 +02:00
if ( g_ascii_strcasecmp ( nick , "nickserv" ) == 0 )
{
if ( g_ascii_strncasecmp ( msg , "identify " , 9 ) == 0 )
msg = "identify ****" ;
else if ( g_ascii_strncasecmp ( msg , "ghost " , 6 ) == 0 )
msg = "ghost ****" ;
}
2011-02-24 04:14:30 +01:00
EMIT_SIGNAL ( XP_TE_MSGSEND , sess , nick , msg , NULL , NULL , 0 );
}
return TRUE ;
}
}
return FALSE ;
}
static int
cmd_names ( struct session * sess , char * tbuf , char * word [], char * word_eol [])
{
if ( * word [ 2 ])
sess -> server -> p_names ( sess -> server , word [ 2 ]);
else
sess -> server -> p_names ( sess -> server , sess -> channel );
return TRUE ;
}
static int
cmd_nctcp ( struct session * sess , char * tbuf , char * word [], char * word_eol [])
{
if ( * word_eol [ 3 ])
{
sess -> server -> p_nctcp ( sess -> server , word [ 2 ], word_eol [ 3 ]);
return TRUE ;
}
return FALSE ;
}
static int
cmd_newserver ( struct session * sess , char * tbuf , char * word [],
char * word_eol [])
{
if ( strcmp ( word [ 2 ], "-noconnect" ) == 0 )
{
new_ircwindow ( NULL , word [ 3 ], SESS_SERVER , 0 );
return TRUE ;
}
2013-10-15 22:54:38 -04:00
sess = new_ircwindow ( NULL , NULL , SESS_SERVER , 1 );
2011-02-24 04:14:30 +01:00
cmd_server ( sess , tbuf , word , word_eol );
return TRUE ;
}
static int
cmd_nick ( struct session * sess , char * tbuf , char * word [], char * word_eol [])
{
char * nick = word [ 2 ];
if ( * nick )
{
if ( sess -> server -> connected )
sess -> server -> p_change_nick ( sess -> server , nick );
else
2013-06-22 15:32:50 +01:00
{
message_tags_data no_tags = MESSAGE_TAGS_DATA_INIT ;
inbound_newnick ( sess -> server , sess -> server -> nick , nick , TRUE ,
& no_tags );
}
2011-02-24 04:14:30 +01:00
return TRUE ;
}
return FALSE ;
}
static int
cmd_notice ( struct session * sess , char * tbuf , char * word [], char * word_eol [])
{
2013-04-05 23:14:51 +02:00
char * text = word_eol [ 3 ];
2013-04-06 00:11:45 +02:00
char * split_text = NULL ;
2013-04-05 23:14:51 +02:00
int cmd_length = 12 ; /* " NOTICE ", " ", :, \r, \n */
int offset = 0 ;
2011-02-24 04:14:30 +01:00
if ( * word [ 2 ] && * word_eol [ 3 ])
{
2013-04-06 00:11:45 +02:00
while (( split_text = split_up_text ( sess , text + offset , cmd_length , split_text )))
2013-04-05 23:14:51 +02:00
{
2013-04-06 00:11:45 +02:00
sess -> server -> p_notice ( sess -> server , word [ 2 ], split_text );
EMIT_SIGNAL ( XP_TE_NOTICESEND , sess , word [ 2 ], split_text , NULL , NULL , 0 );
2013-04-05 23:14:51 +02:00
2013-04-06 00:11:45 +02:00
if ( * split_text )
offset += strlen ( split_text );
2013-04-05 23:14:51 +02:00
2014-12-08 21:24:59 -08:00
g_free ( split_text );
2013-04-05 23:14:51 +02:00
}
sess -> server -> p_notice ( sess -> server , word [ 2 ], text + offset );
EMIT_SIGNAL ( XP_TE_NOTICESEND , sess , word [ 2 ], text + offset , NULL , NULL , 0 );
2011-02-24 04:14:30 +01:00
return TRUE ;
}
return FALSE ;
}
static int
cmd_notify ( struct session * sess , char * tbuf , char * word [], char * word_eol [])
{
int i = 1 ;
char * net = NULL ;
if ( * word [ 2 ])
{
if ( strcmp ( word [ 2 ], "-n" ) == 0 ) /* comma sep network list */
{
net = word [ 3 ];
i += 2 ;
}
while ( 1 )
{
i ++ ;
if ( !* word [ i ])
break ;
if ( notify_deluser ( word [ i ]))
{
EMIT_SIGNAL ( XP_TE_DELNOTIFY , sess , word [ i ], NULL , NULL , NULL , 0 );
return TRUE ;
}
if ( net && strcmp ( net , "ASK" ) == 0 )
fe_notify_ask ( word [ i ], NULL );
else
{
notify_adduser ( word [ i ], net );
EMIT_SIGNAL ( XP_TE_ADDNOTIFY , sess , word [ i ], NULL , NULL , NULL , 0 );
}
}
} else
2013-06-22 23:48:17 +01:00
{
message_tags_data no_tags = MESSAGE_TAGS_DATA_INIT ;
notify_showlist ( sess , & no_tags );
}
2011-02-24 04:14:30 +01:00
return TRUE ;
}
static int
cmd_op ( 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 ++ ;
}
}
static int
cmd_part ( struct session * sess , char * tbuf , char * word [], char * word_eol [])
{
char * chan = word [ 2 ];
char * reason = word_eol [ 3 ];
if ( !* chan )
chan = sess -> channel ;
if (( * chan ) && is_channel ( sess -> server , chan ))
{
if ( reason [ 0 ] == 0 )
reason = NULL ;
server_sendpart ( sess -> server , chan , reason );
return TRUE ;
}
return FALSE ;
}
static int
cmd_ping ( struct session * sess , char * tbuf , char * word [], char * word_eol [])
{
char timestring [ 64 ];
unsigned long tim ;
char * to = word [ 2 ];
tim = make_ping_time ();
2014-12-17 18:49:59 -05:00
g_snprintf ( timestring , sizeof ( timestring ), "%lu" , tim );
2011-02-24 04:14:30 +01:00
sess -> server -> p_ping ( sess -> server , to , timestring );
return TRUE ;
}
2013-10-10 19:51:33 +01:00
session *
2011-02-24 04:14:30 +01:00
open_query ( server * serv , char * nick , gboolean focus_existing )
{
session * sess ;
sess = find_dialog ( serv , nick );
if ( ! sess )
2013-10-10 19:51:33 +01:00
sess = new_ircwindow ( serv , nick , SESS_DIALOG , focus_existing );
2011-02-24 04:14:30 +01:00
else if ( focus_existing )
fe_ctrl_gui ( sess , 2 , 0 ); /* bring-to-front */
2013-10-10 19:51:33 +01:00
return sess ;
2011-02-24 04:14:30 +01:00
}
static int
cmd_query ( struct session * sess , char * tbuf , char * word [], char * word_eol [])
{
char * nick = word [ 2 ];
2013-09-17 18:19:02 -04:00
char * msg = word_eol [ 3 ];
char * split_text = NULL ;
2011-02-24 04:14:30 +01:00
gboolean focus = TRUE ;
2013-09-17 18:19:02 -04:00
int cmd_length = 13 ; /* " PRIVMSG ", " ", :, \r, \n */
int offset = 0 ;
2011-02-24 04:14:30 +01:00
if ( strcmp ( word [ 2 ], "-nofocus" ) == 0 )
{
nick = word [ 3 ];
2013-09-17 18:19:02 -04:00
msg = word_eol [ 4 ];
2011-02-24 04:14:30 +01:00
focus = FALSE ;
}
if ( * nick && ! is_channel ( sess -> server , nick ))
{
2013-10-10 19:51:33 +01:00
struct session * nick_sess ;
nick_sess = open_query ( sess -> server , nick , focus );
2013-09-17 18:19:02 -04:00
if ( * msg )
{
2013-10-10 19:51:33 +01:00
message_tags_data no_tags = MESSAGE_TAGS_DATA_INIT ;
2013-09-17 18:19:02 -04:00
if ( ! sess -> server -> connected )
{
notc_msg ( sess );
return TRUE ;
}
while (( split_text = split_up_text ( sess , msg + offset , cmd_length , split_text )))
{
sess -> server -> p_message ( sess -> server , nick , split_text );
2013-10-10 19:51:33 +01:00
inbound_chanmsg ( nick_sess -> server , nick_sess , nick_sess -> channel ,
nick_sess -> server -> nick , split_text , TRUE , FALSE ,
& no_tags );
2013-09-17 18:19:02 -04:00
if ( * split_text )
offset += strlen ( split_text );
2014-12-08 21:24:59 -08:00
g_free ( split_text );
2013-09-17 18:19:02 -04:00
}
sess -> server -> p_message ( sess -> server , nick , msg + offset );
2013-10-10 19:51:33 +01:00
inbound_chanmsg ( nick_sess -> server , nick_sess , nick_sess -> channel ,
nick_sess -> server -> nick , msg + offset , TRUE , FALSE ,
& no_tags );
2013-09-17 18:19:02 -04:00
}
2011-02-24 04:14:30 +01:00
return TRUE ;
}
return FALSE ;
}
2013-06-07 08:24:13 -04:00
static int
cmd_quiet ( struct session * sess , char * tbuf , char * word [], char * word_eol [])
{
char * quietmask ;
server * serv = sess -> server ;
if ( strchr ( serv -> chanmodes , 'q' ) == NULL )
{
PrintText ( sess , _ ( "Quiet is not supported by this server." ));
return TRUE ;
}
if ( * word [ 2 ])
{
quietmask = create_mask ( sess , word [ 2 ], "+q" , word [ 3 ], 0 );
if ( quietmask )
{
serv -> p_mode ( serv , sess -> channel , quietmask );
g_free ( quietmask );
}
}
else
{
serv -> p_mode ( serv , sess -> channel , "+q" ); /* quietlist */
}
return TRUE ;
}
static int
cmd_unquiet ( struct session * sess , char * tbuf , char * word [], char * word_eol [])
{
/* Allow more than one mask in /unban -- tvk */
int i = 2 ;
if ( strchr ( sess -> server -> chanmodes , 'q' ) == NULL )
{
PrintText ( sess , _ ( "Quiet is not supported by this server." ));
return TRUE ;
}
while ( 1 )
{
if ( !* word [ i ])
{
if ( i == 2 )
return FALSE ;
send_channel_modes ( sess , tbuf , word , 2 , i , '-' , 'q' , 0 );
return TRUE ;
}
i ++ ;
}
}
2011-02-24 04:14:30 +01:00
static int
cmd_quote ( struct session * sess , char * tbuf , char * word [], char * word_eol [])
{
char * raw = word_eol [ 2 ];
return sess -> server -> p_raw ( sess -> server , raw );
}
static int
cmd_reconnect ( struct session * sess , char * tbuf , char * word [], char * word_eol [])
{
2012-10-22 15:55:43 +02:00
int tmp = prefs . hex_net_reconnect_delay ;
2011-02-24 04:14:30 +01:00
GSList * list ;
server * serv = sess -> server ;
2012-10-22 15:55:43 +02:00
prefs . hex_net_reconnect_delay = 0 ;
2011-02-24 04:14:30 +01:00
2012-06-16 13:01:47 +02:00
if ( ! g_ascii_strcasecmp ( word [ 2 ], "ALL" ))
2011-02-24 04:14:30 +01:00
{
list = serv_list ;
while ( list )
{
serv = list -> data ;
if ( serv -> connected )
serv -> auto_reconnect ( serv , TRUE , - 1 );
list = list -> next ;
}
}
/* If it isn't "ALL" and there is something
there it *should* be a server they are trying to connect to*/
else if ( * word [ 2 ])
{
int offset = 0 ;
2021-05-30 06:25:09 +01:00
#ifdef USE_OPENSSL
2022-09-24 15:33:20 +01:00
int use_ssl = TRUE ;
2021-05-31 01:11:19 +01:00
int use_ssl_noverify = FALSE ;
2021-05-30 06:25:09 +01:00
if ( g_strcmp0 ( word [ 2 ], "-ssl" ) == 0 )
{
2021-05-31 01:11:19 +01:00
use_ssl = TRUE ;
use_ssl_noverify = FALSE ;
2021-05-30 06:25:09 +01:00
offset ++ ; /* args move up by 1 word */
} else if ( g_strcmp0 ( word [ 2 ], "-ssl-noverify" ) == 0 )
2011-02-24 04:14:30 +01:00
{
2021-05-31 01:11:19 +01:00
use_ssl = TRUE ;
use_ssl_noverify = TRUE ;
2011-02-24 04:14:30 +01:00
offset ++ ; /* args move up by 1 word */
2022-09-24 15:33:20 +01:00
} else if ( g_strcmp0 ( word [ 2 ], "-insecure" ) == 0 )
{
use_ssl = FALSE ;
use_ssl_noverify = FALSE ;
offset ++ ; /* args move up by 1 word */
2011-02-24 04:14:30 +01:00
}
2021-05-31 01:11:19 +01:00
serv -> use_ssl = use_ssl ;
serv -> accept_invalid_cert = use_ssl_noverify ;
2011-02-24 04:14:30 +01:00
#endif
if ( * word [ 4 + offset ])
safe_strcpy ( serv -> password , word [ 4 + offset ], sizeof ( serv -> password ));
if ( * word [ 3 + offset ])
serv -> port = atoi ( word [ 3 + offset ]);
safe_strcpy ( serv -> hostname , word [ 2 + offset ], sizeof ( serv -> hostname ));
serv -> auto_reconnect ( serv , TRUE , - 1 );
}
else
{
serv -> auto_reconnect ( serv , TRUE , - 1 );
}
2012-10-22 15:55:43 +02:00
prefs . hex_net_reconnect_delay = tmp ;
2011-02-24 04:14:30 +01:00
return TRUE ;
}
static int
cmd_recv ( struct session * sess , char * tbuf , char * word [], char * word_eol [])
{
if ( * word_eol [ 2 ])
{
sess -> server -> p_inline ( sess -> server , word_eol [ 2 ], strlen ( word_eol [ 2 ]));
return TRUE ;
}
return FALSE ;
}
static int
cmd_say ( struct session * sess , char * tbuf , char * word [], char * word_eol [])
{
char * speech = word_eol [ 2 ];
if ( * speech )
{
handle_say ( sess , speech , FALSE );
return TRUE ;
}
return FALSE ;
}
static int
cmd_send ( struct session * sess , char * tbuf , char * word [], char * word_eol [])
{
guint32 addr ;
socklen_t len ;
struct sockaddr_in SAddr ;
if ( ! word [ 2 ][ 0 ])
return FALSE ;
2019-05-21 16:02:30 +02:00
addr = dcc_get_my_address ( sess );
2011-02-24 04:14:30 +01:00
if ( addr == 0 )
{
/* use the one from our connected server socket */
memset ( & SAddr , 0 , sizeof ( struct sockaddr_in ));
len = sizeof ( SAddr );
getsockname ( sess -> server -> sok , ( struct sockaddr * ) & SAddr , & len );
addr = SAddr . sin_addr . s_addr ;
}
addr = ntohl ( addr );
if (( addr & 0xffff0000 ) == 0xc0a80000 || /* 192.168.x.x */
( addr & 0xff000000 ) == 0x0a000000 ) /* 10.x.x.x */
/* we got a private net address, let's PSEND or it'll fail */
2014-12-17 18:49:59 -05:00
g_snprintf ( tbuf , 512 , "DCC PSEND %s" , word_eol [ 2 ]);
2011-02-24 04:14:30 +01:00
else
2014-12-17 18:49:59 -05:00
g_snprintf ( tbuf , 512 , "DCC SEND %s" , word_eol [ 2 ]);
2011-02-24 04:14:30 +01:00
handle_command ( sess , tbuf , FALSE );
return TRUE ;
}
static int
cmd_setcursor ( struct session * sess , char * tbuf , char * word [], char * word_eol [])
{
int delta = FALSE ;
if ( * word [ 2 ])
{
if ( word [ 2 ][ 0 ] == '-' || word [ 2 ][ 0 ] == '+' )
delta = TRUE ;
fe_set_inputbox_cursor ( sess , delta , atoi ( word [ 2 ]));
return TRUE ;
}
return FALSE ;
}
static int
cmd_settab ( struct session * sess , char * tbuf , char * word [], char * word_eol [])
{
if ( * word_eol [ 2 ])
{
strcpy ( tbuf , sess -> channel );
safe_strcpy ( sess -> channel , word_eol [ 2 ], CHANLEN );
fe_set_channel ( sess );
strcpy ( sess -> channel , tbuf );
}
return TRUE ;
}
static int
cmd_settext ( struct session * sess , char * tbuf , char * word [], char * word_eol [])
{
fe_set_inputbox_contents ( sess , word_eol [ 2 ]);
return TRUE ;
}
static int
cmd_splay ( struct session * sess , char * tbuf , char * word [], char * word_eol [])
{
if ( * word [ 2 ])
{
2013-04-27 23:00:18 +02:00
sound_play ( word [ 2 ], FALSE );
2011-02-24 04:14:30 +01:00
return TRUE ;
}
return FALSE ;
}
static int
2013-03-04 15:46:04 -05:00
parse_irc_url ( char * url , char * server_name [], char * port [], char * channel [], char * key [], int * use_ssl )
2011-02-24 04:14:30 +01:00
{
char * co ;
#ifdef USE_OPENSSL
2012-06-16 13:01:47 +02:00
if ( g_ascii_strncasecmp ( "ircs://" , url , 7 ) == 0 )
2011-02-24 04:14:30 +01:00
{
* use_ssl = TRUE ;
* server_name = url + 7 ;
goto urlserv ;
}
#endif
2012-06-16 13:01:47 +02:00
if ( g_ascii_strncasecmp ( "irc://" , url , 6 ) == 0 )
2011-02-24 04:14:30 +01:00
{
* server_name = url + 6 ;
#ifdef USE_OPENSSL
urlserv :
#endif
/* check for port */
co = strchr ( * server_name , ':' );
if ( co )
{
* port = co + 1 ;
* co = 0 ;
} else
co = * server_name ;
/* check for channel - mirc style */
co = strchr ( co + 1 , '/' );
if ( co )
{
* co = 0 ;
co ++ ;
if ( * co == '#' )
* channel = co + 1 ;
2013-07-02 12:19:47 -04:00
else if ( * co != '\0' )
2011-02-24 04:14:30 +01:00
* channel = co ;
2013-03-27 02:23:51 -03:00
/* check for key - mirc style */
co = strchr ( co + 1 , '?' );
if ( co )
{
* co = 0 ;
co ++ ;
* key = co ;
}
2013-03-04 15:46:04 -05:00
}
2011-02-24 04:14:30 +01:00
return TRUE ;
}
return FALSE ;
}
static int
cmd_server ( struct session * sess , char * tbuf , char * word [], char * word_eol [])
{
int offset = 0 ;
char * server_name = NULL ;
char * port = NULL ;
char * pass = NULL ;
char * channel = NULL ;
2013-03-04 15:46:04 -05:00
char * key = NULL ;
2022-09-24 15:33:20 +01:00
#ifdef USE_OPENSSL
int use_ssl = TRUE ;
2021-05-30 06:25:09 +01:00
int use_ssl_noverify = FALSE ;
2023-11-01 17:47:34 +01:00
#else
int use_ssl = FALSE ;
2022-09-24 15:33:20 +01:00
#endif
2011-02-24 04:14:30 +01:00
int is_url = TRUE ;
server * serv = sess -> server ;
2014-01-11 16:08:50 -05:00
ircnet * net = NULL ;
2011-02-24 04:14:30 +01:00
#ifdef USE_OPENSSL
/* BitchX uses -ssl, mIRC uses -e, let's support both */
2021-05-30 06:25:09 +01:00
if ( g_strcmp0 ( word [ 2 ], "-ssl" ) == 0 || g_strcmp0 ( word [ 2 ], "-e" ) == 0 )
{
use_ssl = TRUE ;
offset ++ ; /* args move up by 1 word */
}
else if ( g_strcmp0 ( word [ 2 ], "-ssl-noverify" ) == 0 )
2011-02-24 04:14:30 +01:00
{
use_ssl = TRUE ;
2021-05-30 06:25:09 +01:00
use_ssl_noverify = TRUE ;
2011-02-24 04:14:30 +01:00
offset ++ ; /* args move up by 1 word */
}
2022-09-24 15:33:20 +01:00
else if ( g_strcmp0 ( word [ 2 ], "-insecure" ) == 0 )
{
use_ssl = FALSE ;
offset ++ ; /* args move up by 1 word */
}
2011-02-24 04:14:30 +01:00
#endif
2013-03-04 15:46:04 -05:00
if ( ! parse_irc_url ( word [ 2 + offset ], & server_name , & port , & channel , & key , & use_ssl ))
2011-02-24 04:14:30 +01:00
{
is_url = FALSE ;
server_name = word [ 2 + offset ];
}
if ( port )
pass = word [ 3 + offset ];
else
{
port = word [ 3 + offset ];
pass = word [ 4 + offset ];
}
if ( ! ( * server_name ))
return FALSE ;
sess -> server -> network = NULL ;
/* dont clear it for /servchan */
2012-06-16 13:01:47 +02:00
if ( g_ascii_strncasecmp ( word_eol [ 1 ], "SERVCHAN " , 9 ))
2011-02-24 04:14:30 +01:00
sess -> willjoinchannel [ 0 ] = 0 ;
if ( channel )
{
sess -> willjoinchannel [ 0 ] = '#' ;
safe_strcpy (( sess -> willjoinchannel + 1 ), channel , ( CHANLEN - 1 ));
2013-03-04 16:30:36 -05:00
if ( key )
safe_strcpy ( sess -> channelkey , key , 64 );
2011-02-24 04:14:30 +01:00
}
/* support +7000 style ports like mIRC */
if ( port [ 0 ] == '+' )
{
port ++ ;
#ifdef USE_OPENSSL
use_ssl = TRUE ;
#endif
}
2022-09-24 15:33:20 +01:00
else if ( port [ 0 ] == '-' )
{
port ++ ;
#ifdef USE_OPENSSL
use_ssl = FALSE ;
#endif
}
2011-02-24 04:14:30 +01:00
if ( * pass )
{
safe_strcpy ( serv -> password , pass , sizeof ( serv -> password ));
2013-05-23 13:22:34 +01:00
serv -> loginmethod = LOGIN_PASS ;
2011-02-24 04:14:30 +01:00
}
2013-05-25 20:47:16 -03:00
else
{
2014-01-11 16:08:50 -05:00
/* If part of a known network, login like normal */
net = servlist_net_find_from_server ( server_name );
2014-01-11 16:27:34 -05:00
if ( net && net -> pass && * net -> pass )
2014-01-11 16:08:50 -05:00
{
safe_strcpy ( serv -> password , net -> pass , sizeof ( serv -> password ));
serv -> loginmethod = net -> logintype ;
}
2015-09-14 09:33:06 -04:00
else /* Otherwise ensure no password is sent or SASL started */
2014-01-11 16:08:50 -05:00
{
2015-09-14 09:33:06 -04:00
serv -> loginmethod = LOGIN_DEFAULT ;
2014-01-11 16:08:50 -05:00
serv -> password [ 0 ] = 0 ;
}
2013-05-25 20:47:16 -03:00
}
2011-02-24 04:14:30 +01:00
#ifdef USE_OPENSSL
serv -> use_ssl = use_ssl ;
2021-05-30 06:25:09 +01:00
serv -> accept_invalid_cert = use_ssl_noverify ;
2011-02-24 04:14:30 +01:00
#endif
/* try to connect by Network name */
if ( servlist_connect_by_netname ( sess , server_name , ! is_url ))
return TRUE ;
if ( * port )
{
serv -> connect ( serv , server_name , atoi ( port ), FALSE );
} else
{
/* -1 for default port */
serv -> connect ( serv , server_name , - 1 , FALSE );
}
/* try to associate this connection with a listed network */
2016-03-11 02:15:42 -05:00
/* may return NULL, but that's OK */
if (( serv -> network = servlist_net_find_from_server ( server_name )))
server_set_encoding ( serv , (( ircnet * ) serv -> network ) -> encoding );
2011-02-24 04:14:30 +01:00
return TRUE ;
}
static int
cmd_servchan ( struct session * sess , char * tbuf , char * word [],
char * word_eol [])
{
int offset = 0 ;
#ifdef USE_OPENSSL
2022-09-24 15:33:20 +01:00
if ( g_strcmp0 ( word [ 2 ], "-ssl" ) == 0 || g_strcmp0 ( word [ 2 ], "-ssl-noverify" ) == 0 || g_strcmp0 ( word [ 2 ], "-insecure" ) == 0 )
2011-02-24 04:14:30 +01:00
offset ++ ;
#endif
if ( * word [ 4 + offset ])
{
safe_strcpy ( sess -> willjoinchannel , word [ 4 + offset ], CHANLEN );
return cmd_server ( sess , tbuf , word , word_eol );
}
return FALSE ;
}
static int
cmd_topic ( struct session * sess , char * tbuf , char * word [], char * word_eol [])
{
if ( word [ 2 ][ 0 ] && is_channel ( sess -> server , word [ 2 ]))
sess -> server -> p_topic ( sess -> server , word [ 2 ], word_eol [ 3 ]);
else
sess -> server -> p_topic ( sess -> server , sess -> channel , word_eol [ 2 ]);
return TRUE ;
}
static int
cmd_tray ( struct session * sess , char * tbuf , char * word [], char * word_eol [])
{
if ( strcmp ( word [ 2 ], "-t" ) == 0 )
{
fe_tray_set_tooltip ( word [ 3 ][ 0 ] ? word [ 3 ] : NULL );
return TRUE ;
}
if ( strcmp ( word [ 2 ], "-i" ) == 0 )
{
fe_tray_set_icon ( atoi ( word [ 3 ]));
return TRUE ;
}
if ( strcmp ( word [ 2 ], "-f" ) != 0 )
return FALSE ;
if ( ! word [ 3 ][ 0 ])
{
2026-01-05 23:12:38 -07:00
fe_tray_set_file ( NULL ); /* default ZoiteChat icon */
2011-02-24 04:14:30 +01:00
return TRUE ;
}
if ( ! word [ 4 ][ 0 ])
{
fe_tray_set_file ( word [ 3 ]); /* fixed custom icon */
return TRUE ;
}
/* flash between 2 icons */
fe_tray_set_flash ( word [ 4 ], word [ 5 ][ 0 ] ? word [ 5 ] : NULL , atoi ( word [ 3 ]));
return TRUE ;
}
static int
cmd_unignore ( struct session * sess , char * tbuf , char * word [],
char * word_eol [])
{
char * mask = word [ 2 ];
char * arg = word [ 3 ];
if ( * mask )
{
2013-03-17 16:20:38 -03:00
if ( strchr ( mask , '?' ) == NULL && strchr ( mask , '*' ) == NULL )
{
mask = tbuf ;
2014-12-17 18:49:59 -05:00
g_snprintf ( tbuf , TBUFSIZE , "%s!*@*" , word [ 2 ]);
2013-03-17 16:20:38 -03:00
}
2011-02-24 04:14:30 +01:00
if ( ignore_del ( mask , NULL ))
{
2012-06-16 13:01:47 +02:00
if ( g_ascii_strcasecmp ( arg , "QUIET" ))
2011-02-24 04:14:30 +01:00
EMIT_SIGNAL ( XP_TE_IGNOREREMOVE , sess , mask , NULL , NULL , NULL , 0 );
}
return TRUE ;
}
return FALSE ;
}
static int
cmd_unload ( struct session * sess , char * tbuf , char * word [], char * word_eol [])
{
#ifdef USE_PLUGIN
2014-06-04 11:15:35 -04:00
gboolean by_file = FALSE ;
2011-02-24 04:14:30 +01:00
2018-03-31 00:53:56 +02:00
if ( g_str_has_suffix ( word [ 2 ], "." PLUGIN_SUFFIX ))
2011-02-24 04:14:30 +01:00
by_file = TRUE ;
switch ( plugin_kill ( word [ 2 ], by_file ))
{
case 0 :
PrintText ( sess , _ ( "No such plugin found. \n " ));
break ;
case 1 :
return TRUE ;
case 2 :
PrintText ( sess , _ ( "That plugin is refusing to unload. \n " ));
break ;
}
#endif
return FALSE ;
}
2013-08-04 04:36:10 -04:00
static int
cmd_reload ( struct session * sess , char * tbuf , char * word [], char * word_eol [])
{
#ifdef USE_PLUGIN
2014-06-04 11:15:35 -04:00
gboolean by_file = FALSE ;
2013-08-04 04:36:10 -04:00
2018-03-31 00:53:56 +02:00
if ( g_str_has_suffix ( word [ 2 ], "." PLUGIN_SUFFIX ))
2013-08-04 04:36:10 -04:00
by_file = TRUE ;
switch ( plugin_reload ( sess , word [ 2 ], by_file ))
{
case 0 : /* error */
PrintText ( sess , _ ( "No such plugin found. \n " ));
break ;
case 1 : /* success */
return TRUE ;
case 2 : /* fake plugin, we know it exists but scripts should handle it. */
return TRUE ;
}
#endif
return FALSE ;
}
2011-02-24 04:14:30 +01:00
static server *
find_server_from_hostname ( char * hostname )
{
GSList * list = serv_list ;
server * serv ;
while ( list )
{
serv = list -> data ;
2012-06-16 13:01:47 +02:00
if ( ! g_ascii_strcasecmp ( hostname , serv -> hostname ) && serv -> connected )
2011-02-24 04:14:30 +01:00
return serv ;
list = list -> next ;
}
return NULL ;
}
static server *
find_server_from_net ( void * net )
{
GSList * list = serv_list ;
server * serv ;
while ( list )
{
serv = list -> data ;
if ( serv -> network == net && serv -> connected )
return serv ;
list = list -> next ;
}
return NULL ;
}
static void
2013-03-04 15:46:04 -05:00
url_join_only ( server * serv , char * tbuf , char * channel , char * key )
2011-02-24 04:14:30 +01:00
{
2013-03-04 15:46:04 -05:00
/* already connected, JOIN only. */
2013-01-10 00:13:25 -08:00
if ( channel == NULL )
return ;
2011-02-24 04:14:30 +01:00
tbuf [ 0 ] = '#' ;
/* tbuf is 4kb */
safe_strcpy (( tbuf + 1 ), channel , 256 );
2013-03-04 15:46:04 -05:00
if ( key )
serv -> p_join ( serv , tbuf , key );
else
serv -> p_join ( serv , tbuf , "" );
2011-02-24 04:14:30 +01:00
}
static int
cmd_url ( struct session * sess , char * tbuf , char * word [], char * word_eol [])
{
if ( word [ 2 ][ 0 ])
{
char * server_name = NULL ;
char * port = NULL ;
char * channel = NULL ;
2013-03-04 15:46:04 -05:00
char * key = NULL ;
2011-02-24 04:14:30 +01:00
char * url = g_strdup ( word [ 2 ]);
int use_ssl = FALSE ;
void * net ;
server * serv ;
2013-03-04 15:46:04 -05:00
if ( parse_irc_url ( url , & server_name , & port , & channel , & key , & use_ssl ))
2011-02-24 04:14:30 +01:00
{
/* maybe we're already connected to this net */
/* check for "FreeNode" */
2012-06-16 13:01:47 +02:00
net = servlist_net_find ( server_name , NULL , g_ascii_strcasecmp );
2011-02-24 04:14:30 +01:00
/* check for "irc.eu.freenode.net" */
if ( ! net )
net = servlist_net_find_from_server ( server_name );
if ( net )
{
/* found the network, but are we connected? */
serv = find_server_from_net ( net );
if ( serv )
{
2013-03-04 15:46:04 -05:00
url_join_only ( serv , tbuf , channel , key );
2011-02-24 04:14:30 +01:00
g_free ( url );
return TRUE ;
}
}
else
{
/* an un-listed connection */
serv = find_server_from_hostname ( server_name );
if ( serv )
{
2013-03-04 15:46:04 -05:00
url_join_only ( serv , tbuf , channel , key );
2011-02-24 04:14:30 +01:00
g_free ( url );
return TRUE ;
}
}
/* not connected to this net, open new window */
cmd_newserver ( sess , tbuf , word , word_eol );
} else
fe_open_url ( word [ 2 ]);
g_free ( url );
return TRUE ;
}
return FALSE ;
}
static int
userlist_cb ( struct User * user , session * sess )
{
time_t lt ;
if ( ! user -> lasttalk )
lt = 0 ;
else
lt = time ( 0 ) - user -> lasttalk ;
PrintTextf ( sess ,
2014-07-18 07:16:43 -04:00
" \003 06%s \t\003 14[ \003 10%-38s \003 14] \017 ov \003 3= \017 %d%d away=%u lt \003 3= \017 %ld \n " ,
user -> nick , user -> hostname , user -> op , user -> voice , user -> away , ( long ) lt );
2011-02-24 04:14:30 +01:00
return TRUE ;
}
static int
cmd_uselect ( struct session * sess , char * tbuf , char * word [], char * word_eol [])
{
int idx = 2 ;
int clear = TRUE ;
int scroll = FALSE ;
if ( strcmp ( word [ 2 ], "-a" ) == 0 ) /* ADD (don't clear selections) */
{
clear = FALSE ;
idx ++ ;
}
if ( strcmp ( word [ idx ], "-s" ) == 0 ) /* SCROLL TO */
{
scroll = TRUE ;
idx ++ ;
}
/* always valid, no args means clear the selection list */
fe_uselect ( sess , word + idx , clear , scroll );
return TRUE ;
}
static int
cmd_userlist ( struct session * sess , char * tbuf , char * word [],
char * word_eol [])
{
tree_foreach ( sess -> usertree , ( tree_traverse_func * ) userlist_cb , sess );
return TRUE ;
}
static int
wallchop_cb ( struct User * user , multidata * data )
{
if ( user -> op )
{
if ( data -> i )
strcat ( data -> tbuf , "," );
strcat ( data -> tbuf , user -> nick );
data -> i ++ ;
}
if ( data -> i == 5 )
{
data -> i = 0 ;
sprintf ( data -> tbuf + strlen ( data -> tbuf ),
" :[@%s] %s" , data -> sess -> channel , data -> reason );
data -> sess -> server -> p_raw ( data -> sess -> server , data -> tbuf );
strcpy ( data -> tbuf , "NOTICE " );
}
return TRUE ;
}
static int
cmd_wallchop ( struct session * sess , char * tbuf , char * word [],
char * word_eol [])
{
multidata data ;
if ( ! ( * word_eol [ 2 ]))
return FALSE ;
strcpy ( tbuf , "NOTICE " );
data . reason = word_eol [ 2 ];
data . tbuf = tbuf ;
data . i = 0 ;
data . sess = sess ;
tree_foreach ( sess -> usertree , ( tree_traverse_func * ) wallchop_cb , & data );
if ( data . i )
{
sprintf ( tbuf + strlen ( tbuf ),
" :[@%s] %s" , sess -> channel , word_eol [ 2 ]);
sess -> server -> p_raw ( sess -> server , tbuf );
}
return TRUE ;
}
static int
cmd_hop ( 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_voice ( 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 ++ ;
}
}
/* *MUST* be kept perfectly sorted for the bsearch to work */
const struct commands xc_cmds [] = {
{ "ADDBUTTON" , cmd_addbutton , 0 , 0 , 1 ,
N_ ( "ADDBUTTON <name> <action>, adds a button under the user-list" )},
2021-05-23 06:58:18 +01:00
{ "ADDSERVER" , cmd_addserver , 0 , 0 , 1 , N_ ( "ADDSERVER <NewNetwork> <hostname/port>, adds a new network with a new server to the network list" )},
2011-02-24 04:14:30 +01:00
{ "ALLCHAN" , cmd_allchannels , 0 , 0 , 1 ,
N_ ( "ALLCHAN <cmd>, sends a command to all channels you're in" )},
{ "ALLCHANL" , cmd_allchannelslocal , 0 , 0 , 1 ,
2012-05-13 14:33:30 +02:00
N_ ( "ALLCHANL <cmd>, sends a command to all channels on the current server" )},
2011-02-24 04:14:30 +01:00
{ "ALLSERV" , cmd_allservers , 0 , 0 , 1 ,
N_ ( "ALLSERV <cmd>, sends a command to all servers you're in" )},
2015-04-05 00:51:49 -04:00
{ "AWAY" , cmd_away , 1 , 0 , 1 , N_ ( "AWAY [<reason>], sets you away (use /BACK to unset)" )},
2011-02-24 04:14:30 +01:00
{ "BACK" , cmd_back , 1 , 0 , 1 , N_ ( "BACK, sets you back (not away)" )},
{ "BAN" , cmd_ban , 1 , 1 , 1 ,
N_ ( "BAN <mask> [<bantype>], bans everyone matching the mask from the current channel. If they are already on the channel this doesn't kick them (needs chanop)" )},
{ "CHANOPT" , cmd_chanopt , 0 , 0 , 1 , N_ ( "CHANOPT [-quiet] <variable> [<value>]" )},
2012-05-13 14:33:30 +02:00
{ "CHARSET" , cmd_charset , 0 , 0 , 1 , N_ ( "CHARSET [<encoding>], get or set the encoding used for the current connection" )},
2013-08-25 11:16:49 -04:00
{ "CLEAR" , cmd_clear , 0 , 0 , 1 , N_ ( "CLEAR [ALL|HISTORY|[-]<amount>], Clears the current text window or command history" )},
2016-03-30 08:58:25 -04:00
{ "CLOSE" , cmd_close , 0 , 0 , 1 , N_ ( "CLOSE [-m], Closes the current tab, closing the window if this is the only open tab, or with the \" -m \" flag, closes all queries." )},
2011-02-24 04:14:30 +01:00
{ "COUNTRY" , cmd_country , 0 , 0 , 1 ,
N_ ( "COUNTRY [-s] <code|wildcard>, finds a country code, eg: au = australia" )},
{ "CTCP" , cmd_ctcp , 1 , 0 , 1 ,
N_ ( "CTCP <nick> <message>, send the CTCP message to nick, common messages are VERSION and USERINFO" )},
{ "CYCLE" , cmd_cycle , 1 , 1 , 1 ,
N_ ( "CYCLE [<channel>], parts the current or given channel and immediately rejoins" )},
{ "DCC" , cmd_dcc , 0 , 0 , 1 ,
N_ ( " \n "
"DCC GET <nick> - accept an offered file \n "
"DCC SEND [-maxcps=#] <nick> [file] - send a file to someone \n "
"DCC PSEND [-maxcps=#] <nick> [file] - send a file using passive mode \n "
"DCC LIST - show DCC list \n "
"DCC CHAT <nick> - offer DCC CHAT to someone \n "
"DCC PCHAT <nick> - offer DCC CHAT using passive mode \n "
"DCC CLOSE <type> <nick> <file> example: \n "
" /dcc close send johnsmith file.tar.gz" )},
{ "DEBUG" , cmd_debug , 0 , 0 , 1 , 0 },
{ "DEHOP" , cmd_dehop , 1 , 1 , 1 ,
N_ ( "DEHOP <nick>, removes chanhalf-op status from the nick on the current channel (needs chanop)" )},
{ "DELBUTTON" , cmd_delbutton , 0 , 0 , 1 ,
N_ ( "DELBUTTON <name>, deletes a button from under the user-list" )},
{ "DEOP" , cmd_deop , 1 , 1 , 1 ,
N_ ( "DEOP <nick>, removes chanop status from the nick on the current channel (needs chanop)" )},
{ "DEVOICE" , cmd_devoice , 1 , 1 , 1 ,
N_ ( "DEVOICE <nick>, removes voice status from the nick on the current channel (needs chanop)" )},
{ "DISCON" , cmd_discon , 0 , 0 , 1 , N_ ( "DISCON, Disconnects from server" )},
2014-01-08 01:32:28 -05:00
{ "DNS" , cmd_dns , 0 , 0 , 1 , N_ ( "DNS <nick|host|ip>, Resolves an IP or hostname" )},
2016-11-08 22:34:31 -05:00
{ "DOAT" , cmd_doat , 0 , 0 , 1 , N_ ( "DOAT <channel,list,/network> <command>" )},
2011-02-24 04:14:30 +01:00
{ "ECHO" , cmd_echo , 0 , 0 , 1 , N_ ( "ECHO <text>, Prints text locally" )},
#ifndef WIN32
{ "EXEC" , cmd_exec , 0 , 0 , 1 ,
N_ ( "EXEC [-o] <command>, runs the command. If -o flag is used then output is sent to current channel, else is printed to current text box" )},
#ifndef __EMX__
{ "EXECCONT" , cmd_execc , 0 , 0 , 1 , N_ ( "EXECCONT, sends the process SIGCONT" )},
#endif
{ "EXECKILL" , cmd_execk , 0 , 0 , 1 ,
N_ ( "EXECKILL [-9], kills a running exec in the current session. If -9 is given the process is SIGKILL'ed" )},
#ifndef __EMX__
{ "EXECSTOP" , cmd_execs , 0 , 0 , 1 , N_ ( "EXECSTOP, sends the process SIGSTOP" )},
2022-01-24 18:38:21 +01:00
{ "EXECWRITE" , cmd_execw , 0 , 0 , 1 , N_ ( "EXECWRITE [-q|--], sends data to the processes stdin; use -q flag to quiet/suppress output at text box; use -- flag to stop interpreting arguments as flags, needed if -q itself would occur as data" )},
2011-02-24 04:14:30 +01:00
#endif
2012-11-03 06:29:51 +01:00
#endif
#if 0
2026-01-05 23:12:38 -07:00
{"EXPORTCONF", cmd_exportconf, 0, 0, 1, N_("EXPORTCONF, exports ZoiteChat settings")},
2011-02-24 04:14:30 +01:00
#endif
{ "FLUSHQ" , cmd_flushq , 0 , 0 , 1 ,
N_ ( "FLUSHQ, flushes the current server's send queue" )},
{ "GATE" , cmd_gate , 0 , 0 , 1 ,
N_ ( "GATE <host> [<port>], proxies through a host, port defaults to 23" )},
2013-12-31 17:06:58 -05:00
{ "GETBOOL" , cmd_getbool , 0 , 0 , 1 , "GETBOOL <command> <title> <text>" },
2011-02-24 04:14:30 +01:00
{ "GETFILE" , cmd_getfile , 0 , 0 , 1 , "GETFILE [-folder] [-multi] [-save] <command> <title> [<initial>]" },
{ "GETINT" , cmd_getint , 0 , 0 , 1 , "GETINT <default> <command> <prompt>" },
{ "GETSTR" , cmd_getstr , 0 , 0 , 1 , "GETSTR <default> <command> <prompt>" },
{ "GHOST" , cmd_ghost , 1 , 0 , 1 , N_ ( "GHOST <nick> [password], Kills a ghosted nickname" )},
2021-10-14 07:44:11 -07:00
{ "GUI" , cmd_gui , 0 , 0 , 1 , "GUI [APPLY|ATTACH|DETACH|SHOW|HIDE|FOCUS|FLASH|ICONIFY] \n "
" GUI [MSGBOX <text>|MENU TOGGLE] \n "
" GUI COLOR <n> [-NOOVERRIDE]" },
2011-02-24 04:14:30 +01:00
{ "HELP" , cmd_help , 0 , 0 , 1 , 0 },
{ "HOP" , cmd_hop , 1 , 1 , 1 ,
N_ ( "HOP <nick>, gives chanhalf-op status to the nick (needs chanop)" )},
{ "ID" , cmd_id , 1 , 0 , 1 , N_ ( "ID <password>, identifies yourself to nickserv" )},
{ "IGNORE" , cmd_ignore , 0 , 0 , 1 ,
N_ ( "IGNORE <mask> <types..> <options..> \n "
" mask - host mask to ignore, eg: *!*@*.aol.com \n "
" types - types of data to ignore, one or all of: \n "
" PRIV, CHAN, NOTI, CTCP, DCC, INVI, ALL \n "
" options - NOSAVE, QUIET" )},
{ "INVITE" , cmd_invite , 1 , 0 , 1 ,
N_ ( "INVITE <nick> [<channel>], invites someone to a channel, by default the current channel (needs chanop)" )},
{ "JOIN" , cmd_join , 1 , 0 , 0 , N_ ( "JOIN <channel>, joins the channel" )},
{ "KICK" , cmd_kick , 1 , 1 , 1 ,
2013-11-01 14:42:43 -04:00
N_ ( "KICK <nick> [reason], kicks the nick from the current channel (needs chanop)" )},
2011-02-24 04:14:30 +01:00
{ "KICKBAN" , cmd_kickban , 1 , 1 , 1 ,
2013-11-01 14:42:43 -04:00
N_ ( "KICKBAN <nick> [reason], bans then kicks the nick from the current channel (needs chanop)" )},
2011-02-24 04:14:30 +01:00
{ "KILLALL" , cmd_killall , 0 , 0 , 1 , "KILLALL, immediately exit" },
{ "LAGCHECK" , cmd_lagcheck , 0 , 0 , 1 ,
N_ ( "LAGCHECK, forces a new lag check" )},
{ "LASTLOG" , cmd_lastlog , 0 , 0 , 1 ,
2012-08-28 19:10:03 -07:00
N_ ( "LASTLOG [-h] [-m] [-r] [--] <string>, searches for a string in the buffer \n "
" Use -h to highlight the found string(s) \n "
" Use -m to match case \n "
" Use -r when string is a Regular Expression \n "
" Use -- (double hyphen) to end options when searching for, say, the string '-r'" )},
2011-02-24 04:14:30 +01:00
{ "LIST" , cmd_list , 1 , 0 , 1 , 0 },
{ "LOAD" , cmd_load , 0 , 0 , 1 , N_ ( "LOAD [-e] <file>, loads a plugin or script" )},
{ "MDEHOP" , cmd_mdehop , 1 , 1 , 1 ,
N_ ( "MDEHOP, Mass deop's all chanhalf-ops in the current channel (needs chanop)" )},
{ "MDEOP" , cmd_mdeop , 1 , 1 , 1 ,
N_ ( "MDEOP, Mass deop's all chanops in the current channel (needs chanop)" )},
{ "ME" , cmd_me , 0 , 0 , 1 ,
N_ ( "ME <action>, sends the action to the current channel (actions are written in the 3rd person, like /me jumps)" )},
{ "MENU" , cmd_menu , 0 , 0 , 1 , "MENU [-eX] [-i<ICONFILE>] [-k<mod>,<key>] [-m] [-pX] [-r<X,group>] [-tX] {ADD|DEL} <path> [command] [unselect command] \n "
2026-03-30 18:25:26 -06:00
" See https://docs.zoitechat.org/en/latest/en/latest/plugins.html#controlling-the-gui for more details." },
2016-08-10 21:53:30 -07:00
{ "MHOP" , cmd_mhop , 1 , 1 , 1 ,
N_ ( "MHOP, Mass hop's all users in the current channel (needs chanop)" )},
2011-02-24 04:14:30 +01:00
{ "MKICK" , cmd_mkick , 1 , 1 , 1 ,
N_ ( "MKICK, Mass kicks everyone except you in the current channel (needs chanop)" )},
{ "MODE" , cmd_mode , 1 , 0 , 1 , 0 },
{ "MOP" , cmd_mop , 1 , 1 , 1 ,
N_ ( "MOP, Mass op's all users in the current channel (needs chanop)" )},
2013-08-25 11:16:49 -04:00
{ "MSG" , cmd_msg , 0 , 0 , 1 , N_ ( "MSG <nick> <message>, sends a private message, message \" . \" to send to last nick or prefix with \" = \" for dcc chat" )},
2011-02-24 04:14:30 +01:00
2013-11-28 05:00:34 -05:00
{ "NAMES" , cmd_names , 1 , 0 , 1 ,
N_ ( "NAMES [channel], Lists the nicks on the channel" )},
2011-02-24 04:14:30 +01:00
{ "NCTCP" , cmd_nctcp , 1 , 0 , 1 ,
N_ ( "NCTCP <nick> <message>, Sends a CTCP notice" )},
{ "NEWSERVER" , cmd_newserver , 0 , 0 , 1 , N_ ( "NEWSERVER [-noconnect] <hostname> [<port>]" )},
{ "NICK" , cmd_nick , 0 , 0 , 1 , N_ ( "NICK <nickname>, sets your nick" )},
{ "NOTICE" , cmd_notice , 1 , 0 , 1 ,
2013-04-30 21:27:41 -03:00
N_ ( "NOTICE <nick/channel> <message>, sends a notice" )},
2011-02-24 04:14:30 +01:00
{ "NOTIFY" , cmd_notify , 0 , 0 , 1 ,
N_ ( "NOTIFY [-n network1[,network2,...]] [<nick>], displays your notify list or adds someone to it" )},
{ "OP" , cmd_op , 1 , 1 , 1 ,
N_ ( "OP <nick>, gives chanop status to the nick (needs chanop)" )},
{ "PART" , cmd_part , 1 , 1 , 0 ,
N_ ( "PART [<channel>] [<reason>], leaves the channel, by default the current one" )},
{ "PING" , cmd_ping , 1 , 0 , 1 ,
N_ ( "PING <nick | channel>, CTCP pings nick or channel" )},
{ "QUERY" , cmd_query , 0 , 0 , 1 ,
2013-09-17 18:19:02 -04:00
N_ ( "QUERY [-nofocus] <nick> [message], opens up a new privmsg window to someone and optionally sends a message" )},
2013-06-07 08:24:13 -04:00
{ "QUIET" , cmd_quiet , 1 , 1 , 1 ,
N_ ( "QUIET <mask> [<quiettype>], quiet everyone matching the mask in the current channel if supported by the server." )},
2011-02-24 04:14:30 +01:00
{ "QUIT" , cmd_quit , 0 , 0 , 1 ,
N_ ( "QUIT [<reason>], disconnects from the current server" )},
{ "QUOTE" , cmd_quote , 1 , 0 , 1 ,
N_ ( "QUOTE <text>, sends the text in raw form to the server" )},
#ifdef USE_OPENSSL
{ "RECONNECT" , cmd_reconnect , 0 , 0 , 1 ,
2021-05-30 06:25:09 +01:00
N_ ( "RECONNECT [-ssl|-ssl-noverify] [<host>] [<port>] [<password>], Can be called just as /RECONNECT to reconnect to the current server or with /RECONNECT ALL to reconnect to all the open servers" )},
2011-02-24 04:14:30 +01:00
#else
{ "RECONNECT" , cmd_reconnect , 0 , 0 , 1 ,
N_ ( "RECONNECT [<host>] [<port>] [<password>], Can be called just as /RECONNECT to reconnect to the current server or with /RECONNECT ALL to reconnect to all the open servers" )},
#endif
2026-01-05 23:12:38 -07:00
{ "RECV" , cmd_recv , 1 , 0 , 1 , N_ ( "RECV <text>, send raw data to ZoiteChat, as if it was received from the IRC server" )},
2013-08-04 04:36:10 -04:00
{ "RELOAD" , cmd_reload , 0 , 0 , 1 , N_ ( "RELOAD <name>, reloads a plugin or script" )},
2011-02-24 04:14:30 +01:00
{ "SAY" , cmd_say , 0 , 0 , 1 ,
N_ ( "SAY <text>, sends the text to the object in the current window" )},
{ "SEND" , cmd_send , 0 , 0 , 1 , N_ ( "SEND <nick> [<file>]" )},
#ifdef USE_OPENSSL
{ "SERVCHAN" , cmd_servchan , 0 , 0 , 1 ,
2022-10-16 11:18:44 +01:00
N_ ( "SERVCHAN [-insecure|-ssl|-ssl-noverify] <host> <port> <channel>, connects and joins a channel using ssl unless otherwise specified" )},
2011-02-24 04:14:30 +01:00
#else
{ "SERVCHAN" , cmd_servchan , 0 , 0 , 1 ,
N_ ( "SERVCHAN <host> <port> <channel>, connects and joins a channel" )},
#endif
#ifdef USE_OPENSSL
{ "SERVER" , cmd_server , 0 , 0 , 1 ,
2022-10-16 11:18:44 +01:00
N_ ( "SERVER [-insecure|-ssl|-ssl-noverify] <host> [<port>] [<password>], connects to a server using ssl unless otherwise specified, the default port is 6697 for ssl connections and 6667 for insecure connections" )},
2011-02-24 04:14:30 +01:00
#else
{ "SERVER" , cmd_server , 0 , 0 , 1 ,
N_ ( "SERVER <host> [<port>] [<password>], connects to a server, the default port is 6667" )},
#endif
{ "SET" , cmd_set , 0 , 0 , 1 , N_ ( "SET [-e] [-off|-on] [-quiet] <variable> [<value>]" )},
2012-05-13 14:33:30 +02:00
{ "SETCURSOR" , cmd_setcursor , 0 , 0 , 1 , N_ ( "SETCURSOR [-|+]<position>, reposition the cursor in the inputbox" )},
{ "SETTAB" , cmd_settab , 0 , 0 , 1 , N_ ( "SETTAB <new name>, change a tab's name, tab_trunc limit still applies" )},
{ "SETTEXT" , cmd_settext , 0 , 0 , 1 , N_ ( "SETTEXT <new text>, replace the text in the input box" )},
2011-02-24 04:14:30 +01:00
{ "SPLAY" , cmd_splay , 0 , 0 , 1 , "SPLAY <soundfile>" },
{ "TOPIC" , cmd_topic , 1 , 1 , 1 ,
N_ ( "TOPIC [<topic>], sets the topic if one is given, else shows the current topic" )},
{ "TRAY" , cmd_tray , 0 , 0 , 1 ,
N_ ( " \n TRAY -f <timeout> <file1> [<file2>] Blink tray between two icons. \n "
"TRAY -f <filename> Set tray to a fixed icon. \n "
"TRAY -i <number> Blink tray with an internal icon. \n "
"TRAY -t <text> Set the tray tooltip. \n "
"TRAY -b <title> <text> Set the tray balloon."
)},
{ "UNBAN" , cmd_unban , 1 , 1 , 1 ,
N_ ( "UNBAN <mask> [<mask>...], unbans the specified masks." )},
{ "UNIGNORE" , cmd_unignore , 0 , 0 , 1 , N_ ( "UNIGNORE <mask> [QUIET]" )},
{ "UNLOAD" , cmd_unload , 0 , 0 , 1 , N_ ( "UNLOAD <name>, unloads a plugin or script" )},
2013-06-07 08:24:13 -04:00
{ "UNQUIET" , cmd_unquiet , 1 , 1 , 1 ,
N_ ( "UNQUIET <mask> [<mask>...], unquiets the specified masks if supported by the server." )},
2011-02-24 04:14:30 +01:00
{ "URL" , cmd_url , 0 , 0 , 1 , N_ ( "URL <url>, opens a URL in your browser" )},
{ "USELECT" , cmd_uselect , 0 , 1 , 0 ,
N_ ( "USELECT [-a] [-s] <nick1> <nick2> etc, highlights nick(s) in channel userlist" )},
{ "USERLIST" , cmd_userlist , 1 , 1 , 1 , 0 },
{ "VOICE" , cmd_voice , 1 , 1 , 1 ,
N_ ( "VOICE <nick>, gives voice status to someone (needs chanop)" )},
{ "WALLCHOP" , cmd_wallchop , 1 , 1 , 1 ,
N_ ( "WALLCHOP <message>, sends the message to all chanops on the current channel" )},
{ 0 , 0 , 0 , 0 , 0 , 0 }
};
static int
command_compare ( const void * a , const void * b )
{
2026-05-11 01:35:57 -06:00
return g_ascii_strcasecmp ( a , (( const struct commands * ) b ) -> name );
2011-02-24 04:14:30 +01:00
}
2026-05-11 01:35:57 -06:00
static const struct commands *
2011-02-24 04:14:30 +01:00
find_internal_command ( char * name )
{
/* the "-1" is to skip the NULL terminator */
return bsearch ( name , xc_cmds , ( sizeof ( xc_cmds ) /
sizeof ( xc_cmds [ 0 ])) - 1 , sizeof ( xc_cmds [ 0 ]), command_compare );
}
2014-01-27 18:08:25 -05:00
static gboolean
usercommand_show_help ( session * sess , char * name )
{
struct popup * pop ;
gboolean found = FALSE ;
char buf [ 1024 ];
GSList * list ;
list = command_list ;
while ( list )
{
pop = ( struct popup * ) list -> data ;
if ( ! g_ascii_strcasecmp ( pop -> name , name ))
{
2014-12-17 18:49:59 -05:00
g_snprintf ( buf , sizeof ( buf ), _ ( "User Command for: %s \n " ), pop -> cmd );
2014-01-27 18:08:25 -05:00
PrintText ( sess , buf );
found = TRUE ;
}
list = list -> next ;
}
return found ;
}
2011-02-24 04:14:30 +01:00
static void
help ( session * sess , char * tbuf , char * helpcmd , int quiet )
{
2026-05-11 01:35:57 -06:00
const struct commands * cmd ;
2011-02-24 04:14:30 +01:00
if ( plugin_show_help ( sess , helpcmd ))
return ;
2014-01-27 18:08:25 -05:00
if ( usercommand_show_help ( sess , helpcmd ))
return ;
2011-02-24 04:14:30 +01:00
2014-01-27 18:08:25 -05:00
cmd = find_internal_command ( helpcmd );
2011-02-24 04:14:30 +01:00
if ( cmd )
{
if ( cmd -> help )
{
2014-12-17 18:49:59 -05:00
g_snprintf ( tbuf , TBUFSIZE , _ ( "Usage: %s \n " ), _ ( cmd -> help ));
2011-02-24 04:14:30 +01:00
PrintText ( sess , tbuf );
} else
{
if ( ! quiet )
PrintText ( sess , _ ( " \n No help available on that command. \n " ));
}
return ;
}
if ( ! quiet )
PrintText ( sess , _ ( "No such command. \n " ));
}
/* inserts %a, %c, %d etc into buffer. Also handles &x %x for word/word_eol. *
* returns 2 on buffer overflow
* returns 1 on success *
* returns 0 on bad-args-for-user-command *
* - word/word_eol args might be NULL *
* - this beast is used for UserCommands, UserlistButtons and CTCP replies */
int
2014-12-15 10:25:28 -08:00
auto_insert ( char * dest , gsize destlen , unsigned char * src , char * word [],
2011-02-24 04:14:30 +01:00
char * word_eol [], char * a , char * c , char * d , char * e , char * h ,
2013-04-03 18:10:14 -04:00
char * n , char * s , char * u )
2011-02-24 04:14:30 +01:00
{
int num ;
char buf [ 32 ];
time_t now ;
struct tm * tm_ptr ;
char * utf ;
gsize utf_len ;
char * orig = dest ;
destlen -- ;
while ( src [ 0 ])
{
if ( src [ 0 ] == '%' || src [ 0 ] == '&' )
{
if ( isdigit (( unsigned char ) src [ 1 ]))
{
if ( isdigit (( unsigned char ) src [ 2 ]) && isdigit (( unsigned char ) src [ 3 ]))
{
buf [ 0 ] = src [ 1 ];
buf [ 1 ] = src [ 2 ];
buf [ 2 ] = src [ 3 ];
buf [ 3 ] = 0 ;
dest [ 0 ] = atoi ( buf );
utf = g_locale_to_utf8 ( dest , 1 , 0 , & utf_len , 0 );
if ( utf )
{
if (( dest - orig ) + utf_len >= destlen )
{
g_free ( utf );
return 2 ;
}
memcpy ( dest , utf , utf_len );
g_free ( utf );
dest += utf_len ;
}
src += 3 ;
} else
{
if ( word )
{
src ++ ;
num = src [ 0 ] - '0' ; /* ascii to decimal */
if ( * word [ num ] == 0 )
return 0 ;
if ( src [ - 1 ] == '%' )
utf = word [ num ];
else
utf = word_eol [ num ];
/* avoid recusive usercommand overflow */
if (( dest - orig ) + strlen ( utf ) >= destlen )
return 2 ;
strcpy ( dest , utf );
dest += strlen ( dest );
}
}
} else
{
if ( src [ 0 ] == '&' )
goto lamecode ;
src ++ ;
utf = NULL ;
switch ( src [ 0 ])
{
case '%' :
2014-12-15 10:25:28 -08:00
if (( dest - orig ) + 2u >= destlen )
2011-02-24 04:14:30 +01:00
return 2 ;
dest [ 0 ] = '%' ;
dest [ 1 ] = 0 ;
dest ++ ;
break ;
case 'a' :
utf = a ; break ;
case 'c' :
utf = c ; break ;
case 'd' :
utf = d ; break ;
case 'e' :
utf = e ; break ;
case 'h' :
utf = h ; break ;
case 'm' :
2012-10-28 00:05:40 +02:00
utf = get_sys_str ( 1 ); break ;
2011-02-24 04:14:30 +01:00
case 'n' :
utf = n ; break ;
case 's' :
utf = s ; break ;
case 't' :
now = time ( 0 );
utf = ctime ( & now );
utf [ 19 ] = 0 ;
break ;
2013-04-03 18:10:14 -04:00
case 'u' :
utf = u ; break ;
2011-02-24 04:14:30 +01:00
case 'v' :
utf = PACKAGE_VERSION ; break ;
break ;
case 'y' :
now = time ( 0 );
tm_ptr = localtime ( & now );
2014-12-17 18:49:59 -05:00
g_snprintf ( buf , sizeof ( buf ), "%4d%02d%02d" , 1900 +
2011-02-24 04:14:30 +01:00
tm_ptr -> tm_year , 1 + tm_ptr -> tm_mon , tm_ptr -> tm_mday );
utf = buf ;
break ;
default :
src -- ;
goto lamecode ;
}
if ( utf )
{
if (( dest - orig ) + strlen ( utf ) >= destlen )
return 2 ;
strcpy ( dest , utf );
dest += strlen ( dest );
}
}
src ++ ;
} else
{
utf_len = g_utf8_skip [ src [ 0 ]];
if (( dest - orig ) + utf_len >= destlen )
return 2 ;
if ( utf_len == 1 )
{
lamecode :
dest [ 0 ] = src [ 0 ];
dest ++ ;
src ++ ;
} else
{
memcpy ( dest , src , utf_len );
dest += utf_len ;
src += utf_len ;
}
}
}
dest [ 0 ] = 0 ;
return 1 ;
}
void
check_special_chars ( char * cmd , int do_ascii ) /* check for %X */
{
int occur = 0 ;
2026-05-20 15:34:19 -06:00
size_t len = strlen ( cmd );
2011-02-24 04:14:30 +01:00
char * buf , * utf ;
char tbuf [ 4 ];
int i = 0 , j = 0 ;
gsize utf_len ;
if ( ! len )
return ;
2014-12-28 06:37:25 -05:00
buf = g_malloc ( len + 1 );
2011-02-24 04:14:30 +01:00
2014-12-28 06:37:25 -05:00
while ( cmd [ j ])
2011-02-24 04:14:30 +01:00
{
2014-12-28 06:37:25 -05:00
switch ( cmd [ j ])
2011-02-24 04:14:30 +01:00
{
2014-12-28 06:37:25 -05:00
case '%' :
occur ++ ;
if ( do_ascii &&
j + 3 < len &&
( isdigit (( unsigned char ) cmd [ j + 1 ]) && isdigit (( unsigned char ) cmd [ j + 2 ]) &&
isdigit (( unsigned char ) cmd [ j + 3 ])))
2011-02-24 04:14:30 +01:00
{
2014-12-28 06:37:25 -05:00
tbuf [ 0 ] = cmd [ j + 1 ];
tbuf [ 1 ] = cmd [ j + 2 ];
tbuf [ 2 ] = cmd [ j + 3 ];
tbuf [ 3 ] = 0 ;
buf [ i ] = atoi ( tbuf );
utf = g_locale_to_utf8 ( buf + i , 1 , 0 , & utf_len , 0 );
if ( utf )
2011-02-24 04:14:30 +01:00
{
2014-12-28 06:37:25 -05:00
memcpy ( buf + i , utf , utf_len );
g_free ( utf );
i += ( utf_len - 1 );
}
j += 3 ;
} else
{
switch ( cmd [ j + 1 ])
2011-02-24 04:14:30 +01:00
{
2014-12-28 06:37:25 -05:00
case 'R' :
buf [ i ] = '\026' ;
break ;
case 'U' :
buf [ i ] = '\037' ;
break ;
case 'B' :
buf [ i ] = '\002' ;
break ;
case 'I' :
buf [ i ] = '\035' ;
break ;
2021-06-01 13:31:38 +01:00
case 'S' :
buf [ i ] = '\036' ;
break ;
2014-12-28 06:37:25 -05:00
case 'C' :
buf [ i ] = '\003' ;
break ;
case 'O' :
buf [ i ] = '\017' ;
break ;
case 'H' : /* CL: invisible text code */
buf [ i ] = HIDDEN_CHAR ;
break ;
case '%' :
buf [ i ] = '%' ;
break ;
default :
buf [ i ] = '%' ;
j -- ;
2011-02-24 04:14:30 +01:00
break ;
}
2014-12-28 06:37:25 -05:00
j ++ ;
break ;
default :
buf [ i ] = cmd [ j ];
2011-02-24 04:14:30 +01:00
}
}
2014-12-28 06:37:25 -05:00
j ++ ;
i ++ ;
2011-02-24 04:14:30 +01:00
}
2014-12-28 06:37:25 -05:00
buf [ i ] = 0 ;
if ( occur )
strcpy ( cmd , buf );
g_free ( buf );
2011-02-24 04:14:30 +01:00
}
typedef struct
{
char * nick ;
int len ;
struct User * best ;
int bestlen ;
char * space ;
char * tbuf ;
} nickdata ;
static int
nick_comp_cb ( struct User * user , nickdata * data )
{
int lenu ;
if ( ! rfc_ncasecmp ( user -> nick , data -> nick , data -> len ))
{
lenu = strlen ( user -> nick );
if ( lenu == data -> len )
{
2014-12-17 18:49:59 -05:00
g_snprintf ( data -> tbuf , TBUFSIZE , "%s%s" , user -> nick , data -> space );
2011-02-24 04:14:30 +01:00
data -> len = - 1 ;
return FALSE ;
} else if ( lenu < data -> bestlen )
{
data -> bestlen = lenu ;
data -> best = user ;
}
}
return TRUE ;
}
static void
perform_nick_completion ( struct session * sess , char * cmd , char * tbuf )
{
int len ;
char * space = strchr ( cmd , ' ' );
if ( space && space != cmd )
{
2012-10-22 10:10:19 +02:00
if ( space [ - 1 ] == prefs . hex_completion_suffix [ 0 ] && space - 1 != cmd )
2011-02-24 04:14:30 +01:00
{
len = space - cmd - 1 ;
if ( len < NICKLEN )
{
char nick [ NICKLEN ];
nickdata data ;
memcpy ( nick , cmd , len );
nick [ len ] = 0 ;
data . nick = nick ;
data . len = len ;
data . bestlen = INT_MAX ;
data . best = NULL ;
data . tbuf = tbuf ;
data . space = space - 1 ;
tree_foreach ( sess -> usertree , ( tree_traverse_func * ) nick_comp_cb , & data );
if ( data . len == - 1 )
return ;
if ( data . best )
{
2014-12-17 18:49:59 -05:00
g_snprintf ( tbuf , TBUFSIZE , "%s%s" , data . best -> nick , space - 1 );
2011-02-24 04:14:30 +01:00
return ;
}
}
}
}
strcpy ( tbuf , cmd );
}
static void
user_command ( session * sess , char * tbuf , char * cmd , char * word [],
char * word_eol [])
{
if ( ! auto_insert ( tbuf , 2048 , cmd , word , word_eol , "" , sess -> channel , "" ,
server_get_network ( sess -> server , TRUE ), "" ,
2013-04-03 18:10:14 -04:00
sess -> server -> nick , "" , "" ))
2011-02-24 04:14:30 +01:00
{
PrintText ( sess , _ ( "Bad arguments for user command. \n " ));
return ;
}
handle_command ( sess , tbuf , TRUE );
}
2012-10-22 14:18:20 +02:00
/* handle text entered without a hex_input_command_char prefix */
2011-02-24 04:14:30 +01:00
static void
handle_say ( session * sess , char * text , int check_spch )
{
struct DCC * dcc ;
char * word [ PDIWORDS + 1 ];
char * word_eol [ PDIWORDS + 1 ];
2014-12-28 06:37:25 -05:00
char * pdibuf ;
char * newcmd ;
2011-02-24 04:14:30 +01:00
int len ;
2014-12-28 06:37:25 -05:00
int newcmdlen ;
2013-06-23 21:31:09 +01:00
message_tags_data no_tags = MESSAGE_TAGS_DATA_INIT ;
2011-02-24 04:14:30 +01:00
if ( strcmp ( sess -> channel , "(lastlog)" ) == 0 )
{
2012-08-28 19:10:03 -07:00
lastlog ( sess -> lastlog_sess , text , sess -> lastlog_flags );
2011-02-24 04:14:30 +01:00
return ;
}
len = strlen ( text );
2014-12-28 06:37:25 -05:00
pdibuf = g_malloc ( len + 1 );
newcmdlen = MAX ( len + NICKLEN + 1 , TBUFSIZE );
newcmd = g_malloc ( newcmdlen );
2011-02-24 04:14:30 +01:00
2012-10-22 14:18:20 +02:00
if ( check_spch && prefs . hex_input_perc_color )
check_special_chars ( text , prefs . hex_input_perc_ascii );
2011-02-24 04:14:30 +01:00
/* Python relies on this */
word [ PDIWORDS ] = NULL ;
word_eol [ PDIWORDS ] = NULL ;
/* split the text into words and word_eol */
process_data_init ( pdibuf , text , word , word_eol , TRUE , FALSE );
/* a command of "" can be hooked for non-commands */
if ( plugin_emit_command ( sess , "" , word , word_eol ))
goto xit ;
/* incase a plugin did /close */
if ( ! is_session ( sess ))
goto xit ;
if ( ! sess -> channel [ 0 ] || sess -> type == SESS_SERVER || sess -> type == SESS_NOTICES || sess -> type == SESS_SNOTICES )
{
notj_msg ( sess );
goto xit ;
}
2012-10-22 10:10:19 +02:00
if ( prefs . hex_completion_auto )
2011-02-24 04:14:30 +01:00
perform_nick_completion ( sess , text , newcmd );
else
safe_strcpy ( newcmd , text , newcmdlen );
text = newcmd ;
if ( sess -> type == SESS_DIALOG )
{
/* try it via dcc, if possible */
dcc = dcc_write_chat ( sess -> channel , text );
if ( dcc )
{
inbound_chanmsg ( sess -> server , NULL , sess -> channel ,
2013-06-23 21:31:09 +01:00
sess -> server -> nick , text , TRUE , FALSE , & no_tags );
2011-02-24 04:14:30 +01:00
set_topic ( sess , net_ip ( dcc -> addr ), net_ip ( dcc -> addr ));
goto xit ;
}
}
if ( sess -> server -> connected )
{
2013-04-06 00:11:45 +02:00
char * split_text = NULL ;
2013-04-05 23:14:51 +02:00
int cmd_length = 13 ; /* " PRIVMSG ", " ", :, \r, \n */
int offset = 0 ;
2011-02-24 04:14:30 +01:00
2013-04-06 00:11:45 +02:00
while (( split_text = split_up_text ( sess , text + offset , cmd_length , split_text )))
2011-02-24 04:14:30 +01:00
{
2013-04-05 23:14:51 +02:00
inbound_chanmsg ( sess -> server , sess , sess -> channel , sess -> server -> nick ,
2013-06-23 21:31:09 +01:00
split_text , TRUE , FALSE , & no_tags );
2013-04-06 00:11:45 +02:00
sess -> server -> p_message ( sess -> server , sess -> channel , split_text );
2013-04-05 23:14:51 +02:00
2013-04-06 00:11:45 +02:00
if ( * split_text )
offset += strlen ( split_text );
2013-04-05 23:14:51 +02:00
2014-12-08 21:24:59 -08:00
g_free ( split_text );
2011-02-24 04:14:30 +01:00
}
inbound_chanmsg ( sess -> server , sess , sess -> channel , sess -> server -> nick ,
2013-06-23 21:31:09 +01:00
text + offset , TRUE , FALSE , & no_tags );
2013-04-05 23:14:51 +02:00
sess -> server -> p_message ( sess -> server , sess -> channel , text + offset );
2011-02-24 04:14:30 +01:00
} else
{
notc_msg ( sess );
}
xit :
2014-12-28 06:37:25 -05:00
g_free ( pdibuf );
2011-02-24 04:14:30 +01:00
2014-12-28 06:37:25 -05:00
g_free ( newcmd );
2011-02-24 04:14:30 +01:00
}
2013-05-19 03:30:45 +02:00
char *
command_insert_vars ( session * sess , char * cmd )
{
int pos ;
GString * expanded ;
ircnet * mynet = ( ircnet * ) sess -> server -> network ;
if ( ! mynet ) /* shouldn't really happen */
{
return g_strdup ( cmd ); /* the return value will be freed so we must srtdup() it */
}
expanded = g_string_new ( NULL );
while ( strchr ( cmd , '%' ) != NULL )
{
pos = ( int ) ( strchr ( cmd , '%' ) - cmd ); /* offset to the first '%' */
g_string_append_len ( expanded , cmd , pos ); /* copy contents till the '%' */
cmd += pos + 1 ; /* jump to the char after the '%' */
switch ( cmd [ 0 ])
{
case 'n' :
if ( mynet -> nick )
{
g_string_append ( expanded , mynet -> nick );
}
else
{
g_string_append ( expanded , prefs . hex_irc_nick1 );
}
cmd ++ ;
break ;
case 'p' :
if ( mynet -> pass )
{
g_string_append ( expanded , mynet -> pass );
}
cmd ++ ;
break ;
case 'r' :
if ( mynet -> real )
{
g_string_append ( expanded , mynet -> real );
}
else
{
g_string_append ( expanded , prefs . hex_irc_real_name );
}
cmd ++ ;
break ;
case 'u' :
if ( mynet -> user )
{
g_string_append ( expanded , mynet -> user );
}
else
{
g_string_append ( expanded , prefs . hex_irc_user_name );
}
cmd ++ ;
break ;
default : /* unsupported character? copy it along with the '%'! */
cmd -- ;
g_string_append_len ( expanded , cmd , 2 );
cmd += 2 ;
break ;
}
}
g_string_append ( expanded , cmd ); /* copy any remaining string after the last '%' */
return g_string_free ( expanded , FALSE );
}
2011-02-24 04:14:30 +01:00
/* handle a command, without the '/' prefix */
int
handle_command ( session * sess , char * cmd , int check_spch )
{
struct popup * pop ;
int user_cmd = FALSE ;
GSList * list ;
char * word [ PDIWORDS + 1 ];
char * word_eol [ PDIWORDS + 1 ];
static int command_level = 0 ;
2026-05-11 01:35:57 -06:00
const struct commands * int_cmd ;
2011-02-24 04:14:30 +01:00
char * pdibuf ;
char * tbuf ;
int len ;
int ret = TRUE ;
if ( command_level > 99 )
{
fe_message ( _ ( "Too many recursive usercommands, aborting." ), FE_MSG_ERROR );
return TRUE ;
}
command_level ++ ;
/* anything below MUST DEC command_level before returning */
2013-08-10 16:51:56 -04:00
len = strlen ( cmd );
2014-12-28 06:37:25 -05:00
pdibuf = g_malloc ( len + 1 );
tbuf = g_malloc ( MAX ( TBUFSIZE , ( len * 2 ) + 1 ));
2011-02-24 04:14:30 +01:00
/* split the text into words and word_eol */
2013-08-10 16:51:56 -04:00
process_data_init ( pdibuf , cmd , word , word_eol , TRUE , TRUE );
2011-02-24 04:14:30 +01:00
/* ensure an empty string at index 32 for cmd_deop etc */
/* (internal use only, plugins can still only read 1-31). */
word [ PDIWORDS ] = " \000\000 " ;
word_eol [ PDIWORDS ] = " \000\000 " ;
int_cmd = find_internal_command ( word [ 1 ]);
/* redo it without quotes processing, for some commands like /JOIN */
if ( int_cmd && ! int_cmd -> handle_quotes )
2013-05-19 03:30:45 +02:00
{
2013-08-10 16:51:56 -04:00
process_data_init ( pdibuf , cmd , word , word_eol , FALSE , FALSE );
2013-05-19 03:30:45 +02:00
}
2011-02-24 04:14:30 +01:00
2012-10-22 14:18:20 +02:00
if ( check_spch && prefs . hex_input_perc_color )
2013-05-19 03:30:45 +02:00
{
2013-08-10 16:51:56 -04:00
check_special_chars ( cmd , prefs . hex_input_perc_ascii );
2013-05-19 03:30:45 +02:00
}
2011-02-24 04:14:30 +01:00
if ( plugin_emit_command ( sess , word [ 1 ], word , word_eol ))
2013-05-19 03:30:45 +02:00
{
2011-02-24 04:14:30 +01:00
goto xit ;
2013-05-19 03:30:45 +02:00
}
2011-02-24 04:14:30 +01:00
/* incase a plugin did /close */
if ( ! is_session ( sess ))
2013-05-19 03:30:45 +02:00
{
2011-02-24 04:14:30 +01:00
goto xit ;
2013-05-19 03:30:45 +02:00
}
2011-02-24 04:14:30 +01:00
/* first see if it's a userCommand */
list = command_list ;
while ( list )
{
pop = ( struct popup * ) list -> data ;
2012-06-16 13:01:47 +02:00
if ( ! g_ascii_strcasecmp ( pop -> name , word [ 1 ]))
2011-02-24 04:14:30 +01:00
{
user_command ( sess , tbuf , pop -> cmd , word , word_eol );
user_cmd = TRUE ;
}
list = list -> next ;
}
if ( user_cmd )
2013-05-19 03:30:45 +02:00
{
2011-02-24 04:14:30 +01:00
goto xit ;
2013-05-19 03:30:45 +02:00
}
2011-02-24 04:14:30 +01:00
/* now check internal commands */
int_cmd = find_internal_command ( word [ 1 ]);
if ( int_cmd )
{
if ( int_cmd -> needserver && ! sess -> server -> connected )
{
notc_msg ( sess );
2013-05-19 03:30:45 +02:00
}
else if ( int_cmd -> needchannel && ! sess -> channel [ 0 ])
2011-02-24 04:14:30 +01:00
{
notj_msg ( sess );
2013-05-19 03:30:45 +02:00
}
else
2011-02-24 04:14:30 +01:00
{
switch ( int_cmd -> callback ( sess , tbuf , word , word_eol ))
{
2013-05-19 03:30:45 +02:00
case FALSE :
help ( sess , tbuf , int_cmd -> name , TRUE );
break ;
case 2 :
ret = FALSE ;
goto xit ;
2011-02-24 04:14:30 +01:00
}
}
2013-05-19 03:30:45 +02:00
}
else
2011-02-24 04:14:30 +01:00
{
if ( ! sess -> server -> connected )
2013-05-19 03:30:45 +02:00
{
2015-01-07 13:42:42 -08:00
PrintTextf ( sess , _ ( "Unknown Command %s. Try /help \n " ), word [ 1 ]);
2013-05-19 03:30:45 +02:00
}
2011-02-24 04:14:30 +01:00
else
2013-05-19 03:30:45 +02:00
{
2015-01-07 13:42:42 -08:00
/* unknown command, just send it to the server and hope */
2013-08-10 16:51:56 -04:00
sess -> server -> p_raw ( sess -> server , cmd );
2013-05-19 03:30:45 +02:00
}
2011-02-24 04:14:30 +01:00
}
xit :
command_level -- ;
2014-12-28 06:37:25 -05:00
g_free ( pdibuf );
g_free ( tbuf );
2013-05-19 03:30:45 +02:00
2011-02-24 04:14:30 +01:00
return ret ;
}
/* handle one line entered into the input box */
static int
handle_user_input ( session * sess , char * text , int history , int nocommand )
{
2026-04-06 14:26:47 -06:00
char cmd_char = prefs . hex_input_command_char [ 0 ];
unsigned int i ;
2011-02-24 04:14:30 +01:00
if ( * text == '\0' )
return 1 ;
if ( history )
history_add ( & sess -> history , text );
/* is it NOT a command, just text? */
2026-04-06 14:26:47 -06:00
if ( nocommand || text [ 0 ] != cmd_char )
2011-02-24 04:14:30 +01:00
{
handle_say ( sess , text , TRUE );
return 1 ;
}
2026-04-06 14:26:47 -06:00
for ( i = 1 ; text [ i ]; i ++ )
2011-02-24 04:14:30 +01:00
{
2026-04-06 14:26:47 -06:00
if ( text [ i ] == cmd_char )
{
handle_say ( sess , text , TRUE );
return 1 ;
}
if ( text [ i ] == ' ' )
break ;
2011-02-24 04:14:30 +01:00
}
return handle_command ( sess , text + 1 , TRUE );
}
/* changed by Steve Green. Macs sometimes paste with imbedded \r */
void
handle_multiline ( session * sess , char * cmd , int history , int nocommand )
{
while ( * cmd )
{
char * cr = cmd + strcspn ( cmd , " \n\r " );
int end_of_string = * cr == 0 ;
* cr = 0 ;
if ( ! handle_user_input ( sess , cmd , history , nocommand ))
return ;
if ( end_of_string )
break ;
cmd = cr + 1 ;
}
}
/*void
handle_multiline (session *sess, char *cmd, int history, int nocommand)
{
char *cr;
cr = strchr (cmd, '\n');
if (cr)
{
while (1)
{
if (cr)
*cr = 0;
if (!handle_user_input (sess, cmd, history, nocommand))
return;
if (!cr)
break;
cmd = cr + 1;
if (*cmd == 0)
break;
cr = strchr (cmd, '\n');
}
} else
{
handle_user_input (sess, cmd, history, nocommand);
}
}*/