irc.h File Reference


Detailed Description

Handles core communication with IRC server.

Definition in file irc.h.

#include <time.h>
#include <string>
#include <map>

Include dependency graph for irc.h:

This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Classes

struct  s_005
 Stores parsed data of ISUPPORT 005 numeric reply. More...
struct  s_msg_to_server
 Stores messages for server (for bot's flood protection mechanism). More...

Defines

#define CRITICAL_PRIORITY   1
 Command is sent immediatelly.
#define HIGH_PRIORITY   2
 Command is put to high-priority queue.
#define LOW_PRIORITY   3
 Command is put to low-priority queue.

Functions

int cmp_strings_case_insensitive (string s1, string s2)
 Compares two strings, case in-sensitive.
void irc_await_dcc_chat (string nick, string user_name_as_in_logic, int dcc_group)
 Called to await DCC connection from user.
bool irc_ban (const char *channel, const char *mask)
 Bans (MODE #channel +b mask) host mask on channel.
bool irc_chan_mode (const char *channel, const char *mode, int priority)
 Sets mode of channel.
int irc_connect (const char *bind_ip, const char *host_, unsigned short port)
 Connects to server.
bool irc_deop (const char *channel, const char *nick, int priority)
 Sets -o (chan op) status to nick on channel.
bool irc_devoice (const char *channel, const char *nick, int priority)
 Sets -v (voice) status to nick on channel.
int irc_disconnect ()
 Disconnects from server.
void irc_get_005 (map< string, string > &raw, map< char, char > &prefix, string &chm_a, string &chm_b, string &chm_c, string &chm_d)
 Gets information from parsed RPL_ISUPPORT message (005 numeric).
string irc_get_chan_mode (string channel, string &topic)
 Returns channel mode.
string irc_get_fullname (string nick)
 Looks-up user from nick name and checks its full name.
string irc_get_host (string nick)
 Looks-up host of online user.
string irc_get_ident (string nick)
 Looks-up ident of online user.
string irc_get_mode (string channel, string nick)
 Looks-up user from nick name and checks its mode on channel.
string irc_get_modes_for_log (string channel, string nick)
 Looks-up user from nick name and returns their mode(s) for logging purposes to channel log.
string irc_get_nick (string user)
 Looks-up user from name in logic.txt to nick name (if online).
bool irc_got_op (string channel)
 Checks if bot has op (+o) on channel.
bool irc_is_ircop (string nick)
 Looks-up user from name in logic.txt and checks if it is an irc operator (if online).
string irc_is_online (string user)
 Looks-up user from name in logic.txt to nick name (if online).
bool irc_join (const char *channel, const char *key)
 JOINs channel.
bool irc_kick (const char *channel, const char *nick, const char *reason)
 Kicks nick on channel.
int irc_loop_process_input ()
 This is called in loop to process messages from server.
bool irc_loop_putserv ()
 This function should be called in a loop to process send and receive to/from server.
bool irc_notice (const char *target, const char *msg, int priority)
 Sends NOTICE to user/channel.
bool irc_op (const char *channel, const char *nick, int priority)
 Sets +o (chan op) status to nick on channel.
void irc_parse_modes (string modes, map< char, string > &with_param, string &plain)
 Parses a channel mode.
bool irc_part (const char *channel, const char *reason)
 PARTs channel.
bool irc_privmsg (const char *target, const char *msg, int priority)
 Sends PRIVMSG to user/channel.
void irc_put (string data, int priority)
 Raw-ly puts message to queue to send to server.
bool irc_putserv (const char *msg, bool wait_for_response, int priority)
 Puts message for server to queue to send.
void irc_quit (const char *reason)
 Quits the IRC.
void irc_rehashed ()
 Called from logic.cpp after rehashing. Deletes all online users and so applies new configuration.
void irc_set_redir (bool follow_redirs)
 Sets value of irc_follow_redirs flag.
bool irc_unban (const char *channel, const char *mask)
 Unbans (MODE #channel -b mask) host mask on channel.
bool irc_voice (const char *channel, const char *nick, int priority)
 Sets +v (voice) status to nick on channel.


Define Documentation

#define CRITICAL_PRIORITY   1
 

Command is sent immediatelly.

Definition at line 51 of file irc.h.

Referenced by irc_putserv(), logic_get_priority(), logic_process_script_output(), and logic_set_priority().

#define HIGH_PRIORITY   2
 

Command is put to high-priority queue.

Definition at line 56 of file irc.h.

Referenced by dcc_send_file(), irc_access_to_partyline(), irc_ban(), irc_check_bans(), irc_check_invites(), irc_join(), irc_kick(), irc_loop_process_input(), irc_loop_putserv(), irc_part(), irc_putserv(), irc_quoted_callback(), irc_RPL_NAMREPLY(), irc_unban(), logic_exec(), logic_get_priority(), logic_process_script_output(), and logic_set_priority().

#define LOW_PRIORITY   3
 

Command is put to low-priority queue.

Definition at line 61 of file irc.h.

Referenced by dcc_notify(), dcc_send_file(), irc_loop_process_input(), irc_put_multiple_lines(), irc_putserv(), irc_quoted_callback(), irc_RPL_ENDOFWHOIS(), logic_ctcp(), logic_get_priority(), logic_process_script_output(), and logic_set_priority().


Function Documentation

int cmp_strings_case_insensitive string  s1,
string  s2
 

Compares two strings, case in-sensitive.

Author:
VooDooMan
Version:
1
Date:
2004
Parameters:
s1 String 1
s2 String 2
Returns:
Zero if strings are the same (case in-sensitive)
Return values:
0 Strings are the same (case in-sensitive)

Definition at line 289 of file irc.cpp.

References irc_to_upper().

Referenced by dcc_loop(), dcc_loop_edit_dynbans(), dcc_loop_edit_user1(), dcc_loop_filesystem(), dcc_loop_msg(), filesys_dcc_check_for_notifies(), irc_access_to_partyline(), irc_banned(), irc_check_bans(), irc_check_flood(), irc_check_for_not_invited(), irc_check_for_not_reopped(), irc_check_invites(), irc_check_nick_on_channel(), irc_excepted(), irc_find_user(), irc_get_chan_mode(), irc_get_fullname(), irc_get_host(), irc_get_ident(), irc_get_mode(), irc_get_modes_for_log(), irc_get_nick(), irc_get_online_channel(), irc_in_reop(), irc_internal_set_mode(), irc_invited(), irc_is_ircop(), irc_is_online(), irc_loop_process_input(), irc_loop_putserv(), irc_mode_change_ban(), irc_mode_change_ban_exception(), irc_mode_change_chan_key(), irc_mode_change_chan_limit(), irc_mode_change_chan_status(), irc_mode_change_creator(), irc_mode_change_invitation(), irc_mode_change_op(), irc_mode_change_other(), irc_mode_change_reop(), irc_mode_change_voice(), irc_on_broadcast(), irc_on_notice(), irc_on_privmsg(), irc_remove_redundant_mode(), irc_remove_redundant_mode2(), irc_RPL_324(), irc_RPL_ENDOFWHOIS(), irc_RPL_MODE(), irc_RPL_NAMREPLY(), irc_RPL_WHOISCHANNELS(), irc_RPL_WHOISOPERATOR(), irc_RPL_WHOISUSER(), irc_unban(), irc_user_mode_change(), logic_cmp_strings_case_insensitive(), logic_ctcp(), logic_exec(), logic_exec_script(), logic_on_banned(), logic_on_flood(), logic_on_ircop(), logic_on_join(), logic_on_nick_change(), logic_on_nick_validate(), logic_on_not_in_reop(), logic_on_not_invited(), logic_on_notice(), logic_on_part(), logic_on_privmsg(), logic_on_server_msg(), logic_partyline_access(), logic_partyline_get_channel_def(), logic_validate(), logic_validate_by_mask(), logic_validate_chan_key(), logic_validate_chan_limit(), logic_validate_chan_mode(), logic_validate_kick(), and logic_validate_topic().

00290 {
00291     s1=irc_to_upper(s1);
00292     s2=irc_to_upper(s2);
00293     if((s1.empty() && !s2.empty()) || (!s1.empty() && s2.empty()))
00294         return -1;
00295     return s1.compare(s2);
00296 }

Here is the call graph for this function:

void irc_await_dcc_chat string  nick,
string  user_name_as_in_logic,
int  dcc_group
 

Called to await DCC connection from user.

Author:
VooDooMan
Version:
1
Date:
2004
Parameters:
nick Nick of user
dcc_group DCC-group ID
user_name_as_in_logic User name from "logic.txt"

Definition at line 6875 of file irc.cpp.

References s_dcc_awaiting_user::addr4, s_dcc_awaiting_user::addr6, dcc_awaiting_users, s_dcc_awaiting_user::fullname, s_dcc_awaiting_user::host, s_dcc_awaiting_user::ident, inet_pton(), irc_get_fullname(), irc_get_host(), irc_get_ident(), logic_get_dcc_host(), s_dcc_awaiting_user::nick, sock_resolve(), s_dcc_awaiting_user::start_time, s_dcc_awaiting_user::user_name_as_in_logic, and s_dcc_awaiting_user::using_ipv6.

Referenced by dcc_notify().

06876 {
06877     string dcc_host=logic_get_dcc_host(dcc_group,user_name_as_in_logic);
06878 
06879     s_dcc_awaiting_user user;
06880 
06881     user.nick=nick;
06882     user.ident=irc_get_ident(nick);
06883     user.host=irc_get_host(nick);
06884     user.fullname=irc_get_fullname(nick);
06885 
06886     size_t n=user_name_as_in_logic.length();
06887     if(n>128-1)
06888         n=128-1;
06889     strncpy(user.user_name_as_in_logic,user_name_as_in_logic.c_str(),n);
06890     user.user_name_as_in_logic[n]=0;
06891 
06892     in_addr6_ ip6;
06893     if(inet_pton(AF_INET6,dcc_host.c_str(),&ip6)!=1) {
06894         user.addr4=sock_resolve(dcc_host.c_str(),NULL);
06895         user.using_ipv6=false;
06896     } else {
06897         memcpy(&user.addr6,&ip6,sizeof(user.addr6));
06898 #ifdef _WIN32
06899         user.addr4.S_un.S_addr=(unsigned long)-1;
06900 #else
06901         user.addr4.s_addr=(unsigned long)-1;
06902 #endif
06903         user.using_ipv6=true;
06904     }
06905     time(&user.start_time);
06906     dcc_awaiting_users.push_back(user);
06907 }

Here is the call graph for this function:

bool irc_ban const char *  channel,
const char *  mask
 

Bans (MODE #channel +b mask) host mask on channel.

Author:
VooDooMan
Version:
1
Date:
2004
Parameters:
channel Channel name
mask Ban mask
Returns:
Returns false if socket I/O error occured, or channel is longer than 128 chars, or mask is longer than 511 bytes

Definition at line 6721 of file irc.cpp.

References s_005::chanmodes_a, HIGH_PRIORITY, and irc_putserv().

Referenced by logic_exec().

06722 {
06723     if(strlen(channel)>128)
06724         return false;
06725     if(strlen(mask)>512-1)
06726         return false;
06727 
06728      if(irc_isupport.chanmodes_a.find("b")==string::npos)
06729          return true;
06730 
06731     char tmp[4096];
06732     strcpy(tmp,"MODE ");
06733     strcat(tmp,channel);
06734     strcat(tmp," +b ");
06735     strcat(tmp,mask);
06736 
06737     return irc_putserv(tmp,false,HIGH_PRIORITY);
06738 }

Here is the call graph for this function:

bool irc_chan_mode const char *  channel,
const char *  mode,
int  priority
 

Sets mode of channel.

Author:
VooDooMan
Version:
1
Date:
2004
Parameters:
channel Channel name
mode Mode to set
priority Priority class (LOW_PRIORITY, HIGH_PRIORITY, or CRITICAL_PRIORITY)
Returns:
Returns irc_putserv() result

Definition at line 6839 of file irc.cpp.

References irc_putserv().

Referenced by logic_exec().

06840 {
06841     string msg="MODE ";
06842     msg+=channel;
06843     msg+=" ";
06844     msg+=mode;
06845     return !irc_putserv(msg.c_str(),false,priority);
06846 }

Here is the call graph for this function:

int irc_connect const char *  bind_ip,
const char *  host_,
unsigned short  port
 

Connects to server.

Author:
VooDooMan
Version:
1
Date:
2004
Parameters:
bind_ip IPv4 address to bind to (client address)
host_ DNS host of server
port Port of server
Returns:
Returns zero for no error, or OS's socket I/O error code

Definition at line 1223 of file irc.cpp.

References s_005::clear(), s_socket::clear(), conf_getvar(), dcc_request_whois, filesys_last_notify, filesys_notify_interval, flood_history, flood_history_other, gone_users, irc_bot_flood_bytes, irc_bot_flood_lines, irc_bot_flood_other_seconds, irc_bot_flood_seconds, irc_cannot_join_channels, irc_channels, irc_fullname, irc_keepalive_sent, irc_key_chans, irc_last_join_try, irc_last_keepalive_detection, irc_nick, irc_nicks, irc_recommended_port, irc_recommended_server, irc_socket_error, irc_unique_id, log_irc(), log_socket(), ltoa(), mode_queue, modes_from_server, s_msg_to_server::msg, msgs_from_server, msgs_to_server, msgs_to_server2, s_msg_to_server::response, sock_connect(), sock_error(), stats_irc_new_connection(), tmp_users, unknown_users_on_channels, s_msg_to_server::wait_for_response, and waiting_for_response.

Referenced by logic_exec().

01224 {
01225     char host[1024];
01226     if(strlen(host_)>sizeof(host)-1)
01227         return -1;
01228     strcpy(host,host_);
01229 
01230     irc_socket_error=false;
01231 
01232     irc_bot_flood_bytes=atol(conf_getvar("irc_bot_flood_bytes").c_str());
01233     irc_bot_flood_seconds=atol(conf_getvar("irc_bot_flood_seconds").c_str());
01234     irc_bot_flood_lines=atol(conf_getvar("irc_bot_flood_lines").c_str());
01235     irc_bot_flood_other_seconds=atol(conf_getvar("irc_bot_flood_other_seconds").c_str());
01236 
01237     if(!irc_bot_flood_bytes)
01238         irc_bot_flood_bytes=64;
01239     if(!irc_bot_flood_seconds)
01240         irc_bot_flood_seconds=5;
01241     if(!irc_bot_flood_lines)
01242         irc_bot_flood_lines=2;
01243     if(!irc_bot_flood_other_seconds)
01244         irc_bot_flood_other_seconds=5;
01245 
01246     // do NOT re-set this anymore! - Fixed bug in 1.0.12
01247     //irc_follow_redirs=false;
01248 
01249     irc_recommended_server="";
01250     irc_recommended_port=0;
01251 
01252     irc_socket.clear();
01253     irc_last_keepalive_detection=0;
01254     irc_keepalive_sent=false;
01255 
01256     irc_nick[0]=0;
01257     irc_fullname[0]=0;
01258     irc_unique_id[0]=0;
01259 
01260     irc_nicks.clear();
01261     filesys_notify_interval=0;
01262     filesys_last_notify=0;
01263 
01264     irc_key_chans.clear();
01265     irc_channels.clear();
01266 
01267     tmp_users.clear();
01268 
01269     gone_users.clear();
01270 
01271     unknown_users_on_channels.clear();
01272 
01273     last_msg.wait_for_response=false;
01274     waiting_for_response.clear();
01275 
01276     msgs_to_server.clear();
01277     msgs_to_server2.clear();
01278     msgs_from_server.clear();
01279 
01280     mode_queue.clear();
01281 
01282     flood_history.clear();
01283     flood_history_other.clear();
01284 
01285     irc_cannot_join_channels.clear();
01286     irc_last_join_try=0;
01287 
01288     last_msg.msg=NULL;
01289     last_msg.wait_for_response=false;
01290     last_msg.response[0]=0;
01291 
01292     irc_channels.clear();
01293 
01294     dcc_request_whois.clear();
01295     modes_from_server.clear();
01296 
01297     irc_isupport.clear();
01298 
01299     {
01300         string msg="Connecting to ";
01301         if(strstr(host,":"))
01302             msg+="[";
01303         msg+=host;
01304         if(strstr(host,":"))
01305             msg+="]";
01306         msg+=":";
01307         char tmp[64];
01308         ltoa(port,tmp,10);
01309         msg+=tmp;
01310         msg+="...";
01311         log_irc(false,msg.c_str());
01312     }
01313 
01314     int ec=0;
01315     /*char ip[128];
01316     ip[0]=0;
01317     unsigned long ip_=sock_resolve(host,ip).S_un.S_addr;
01318     if(ip_!=0) {*/
01319         irc_socket=sock_connect((char*)bind_ip,(char*)host,port,ec,true);
01320         irc_last_keepalive_detection=time(NULL);
01321         if(ec) {
01322             irc_socket.clear();
01323             log_socket(ec,sock_error(ec),"while calling sock_connect in file " __FILE__ " in function " __FUNC__);
01324             return ec;
01325         }
01326     /*} else {
01327         irc_socket.clear();
01328         string str="Cannot resolve host \"";
01329         str+=host;
01330         str+="\" to IP address in file " __FILE__ " in function " __FUNC__;
01331         log_socket(-1,"DNS",str.c_str());
01332         return -1;
01333     }*/
01334 
01335     stats_irc_new_connection(host,port);
01336 
01337     return 0;
01338 }

Here is the call graph for this function:

bool irc_deop const char *  channel,
const char *  nick,
int  priority
 

Sets -o (chan op) status to nick on channel.

Author:
VooDooMan
Version:
1
Date:
2004
Parameters:
channel Channel name
nick Nick name
Returns:
Returns false if socket I/O error occured
Parameters:
priority Priority class (LOW_PRIORITY, HIGH_PRIORITY, or CRITICAL_PRIORITY)

Definition at line 6293 of file irc.cpp.

References irc_internal_set_mode(), and irc_putserv().

Referenced by logic_exec().

06294 {
06295     if(strlen(channel)>128)
06296         return false;
06297     if(strlen(nick)>128)
06298         return false;
06299 
06300     irc_internal_set_mode(channel,nick,'-','@');
06301 
06302     char msg[4096];
06303     strcpy(msg,"MODE ");
06304     strcat(msg,channel);
06305     strcat(msg," -o ");
06306     strcat(msg,nick);
06307 
06308     return irc_putserv(msg,true,priority);
06309 }

Here is the call graph for this function:

bool irc_devoice const char *  channel,
const char *  nick,
int  priority
 

Sets -v (voice) status to nick on channel.

Author:
VooDooMan
Version:
1
Date:
2004
Parameters:
channel Channel name
nick Nick name
priority Priority class (LOW_PRIORITY, HIGH_PRIORITY, or CRITICAL_PRIORITY)
Returns:
Returns false if socket I/O error occured

Definition at line 6349 of file irc.cpp.

References irc_internal_set_mode(), and irc_putserv().

Referenced by logic_exec().

06350 {
06351     if(strlen(channel)>128)
06352         return false;
06353     if(strlen(nick)>128)
06354         return false;
06355 
06356     irc_internal_set_mode(channel,nick,'-','+');
06357 
06358     char msg[4096];
06359     strcpy(msg,"MODE ");
06360     strcat(msg,channel);
06361     strcat(msg," -v ");
06362     strcat(msg,nick);
06363 
06364     return irc_putserv(msg,true,priority);
06365 }

Here is the call graph for this function:

int irc_disconnect  ) 
 

Disconnects from server.

Author:
VooDooMan
Version:
1
Date:
2004
Returns:
Returns zero for no error

Definition at line 1188 of file irc.cpp.

References s_socket::clear(), irc_channels, irc_ident, irc_keepalive_sent, log_irc(), mode_queue, msgs_to_server, msgs_to_server2, sock_close(), sock_flush_later(), sock_send_cache(), s_msg_to_server::wait_for_response, and waiting_for_response.

Referenced by irc_loop_process_input(), irc_loop_putserv(), logic_exec(), and main().

01189 {
01190     {
01191         string msg="Disconnecting";
01192         log_irc(false,msg.c_str());
01193     }
01194 
01195     while(irc_channels.begin()!=irc_channels.end())
01196         irc_channels.erase(irc_channels.begin());
01197 
01198     irc_keepalive_sent=false;
01199 
01200     sock_send_cache();
01201     sock_flush_later(irc_socket);
01202     sock_close(irc_socket);
01203     irc_socket.clear();
01204     msgs_to_server.clear();
01205     msgs_to_server2.clear();
01206     mode_queue.clear();
01207     last_msg.wait_for_response=false;
01208     waiting_for_response.clear();
01209     irc_ident="*";
01210     return 0;
01211 }

Here is the call graph for this function:

void irc_get_005 map< string, string > &  raw,
map< char, char > &  prefix,
string &  chm_a,
string &  chm_b,
string &  chm_c,
string &  chm_d
 

Gets information from parsed RPL_ISUPPORT message (005 numeric).

Author:
VooDooMan
Version:
1
Date:
2004
Parameters:
raw Assiciative array with all features
prefix Associative array with prefixes (user modes: 'o'=='@', 'v'=='+', etc.)
chm_a Channel modes class A - +b, +e, ...
chm_b Channel modes class B - +k
chm_c Channel modes class C - +l
chm_d Channel modes class D - +n, +t, ...

Definition at line 6984 of file irc.cpp.

References s_005::chanmodes_a, s_005::chanmodes_b, s_005::chanmodes_c, s_005::chanmodes_d, s_005::prefix, and s_005::raw.

Referenced by logic_exec_script().

06985 {
06986     raw=irc_isupport.raw;
06987     prefix=irc_isupport.prefix;
06988     chm_a=irc_isupport.chanmodes_a;
06989     chm_b=irc_isupport.chanmodes_b;
06990     chm_c=irc_isupport.chanmodes_c;
06991     chm_d=irc_isupport.chanmodes_d;
06992 }

string irc_get_chan_mode string  channel,
string &  topic
 

Returns channel mode.

Author:
VooDooMan
Version:
1
Date:
2004
Parameters:
channel Channel name
topic Returns topic of channel
Returns:
Returns mode (i.e. "", "nt", "nts", "ntp", "n",..)

Definition at line 6958 of file irc.cpp.

References cmp_strings_case_insensitive(), and irc_channels.

Referenced by logic_exec().

06959 {
06960     topic="";
06961     vector<s_online_channel>::iterator i;
06962     for(i=irc_channels.begin(); i!=irc_channels.end(); i++) {
06963         if(!cmp_strings_case_insensitive((*i).name,channel)) {
06964             topic=(*i).topic;
06965             return (*i).modes;
06966         }
06967     }
06968 
06969     return "";
06970 }

Here is the call graph for this function:

string irc_get_fullname string  nick  ) 
 

Looks-up user from nick name and checks its full name.

Author:
VooDooMan
Version:
1
Date:
2004
Parameters:
nick Nick name
Returns:
Returns full name if online, if not, empty string

Definition at line 6657 of file irc.cpp.

References cmp_strings_case_insensitive(), and irc_channels.

Referenced by dcc_file_has_been_read(), dcc_loop(), dcc_send_file(), irc_await_dcc_chat(), irc_loop_process_input(), irc_quoted_callback(), irc_RPL_ENDOFWHOIS(), irc_RPL_NAMREPLY(), irc_user_mode_change(), logic_exec(), logic_on_ircop(), logic_on_part(), and logic_validate().

06658 {
06659     vector<s_online_channel>::iterator i;
06660     for(i=irc_channels.begin(); i!=irc_channels.end(); i++) {
06661         vector<s_online_user>::iterator ii;
06662         for(ii=(*i).users.begin(); ii!=(*i).users.end(); ii++) {
06663             if(!cmp_strings_case_insensitive((*ii).nick,nick)) {
06664                 if(!(*ii).got_whois)
06665                     return "";
06666                 return (*ii).fullname;
06667             }
06668         }
06669     }
06670 
06671     return "";
06672 }

Here is the call graph for this function:

string irc_get_host string  nick  ) 
 

Looks-up host of online user.

Author:
VooDooMan
Version:
1
Date:
2004
Parameters:
nick Nick name of user
Returns:
Returns host of user, or empty string if there's no such nick online

Definition at line 6792 of file irc.cpp.

References cmp_strings_case_insensitive(), gone_users, and irc_channels.

Referenced by dcc_file_has_been_read(), dcc_loop(), dcc_send_file(), irc_await_dcc_chat(), irc_loop_process_input(), irc_quoted_callback(), irc_RPL_ENDOFWHOIS(), irc_RPL_NAMREPLY(), irc_user_mode_change(), logic_exec(), logic_on_ircop(), logic_on_part(), and logic_validate().

06793 {
06794     vector<s_online_channel>::iterator i1;
06795     for(i1=irc_channels.begin(); i1!=irc_channels.end(); i1++) {
06796         vector<s_online_user>::iterator i2;
06797         for(i2=(*i1).users.begin(); i2!=(*i1).users.end(); i2++) {
06798             if(!cmp_strings_case_insensitive((*i2).nick,nick)) {
06799                 if(!(*i2).got_whois)
06800                     break;
06801                 return (*i2).host;
06802             }
06803         }
06804     }
06805     vector<s_online_user>::iterator i2;
06806     for(i2=gone_users.begin(); i2!=gone_users.end(); i2++) {
06807         if(!cmp_strings_case_insensitive((*i2).nick,nick)) {
06808             if(!(*i2).got_whois)
06809                 break;
06810             return (*i2).host;
06811         }
06812     }
06813     return "";
06814 }

Here is the call graph for this function:

string irc_get_ident string  nick  ) 
 

Looks-up ident of online user.

Author:
VooDooMan
Version:
1
Date:
2004
Parameters:
nick Nick name of user
Returns:
Returns ident of user, or empty string if there's no such nick online

Definition at line 6760 of file irc.cpp.

References cmp_strings_case_insensitive(), gone_users, and irc_channels.

Referenced by dcc_file_has_been_read(), dcc_loop(), dcc_send_file(), irc_await_dcc_chat(), irc_loop_process_input(), irc_quoted_callback(), irc_RPL_ENDOFWHOIS(), irc_RPL_NAMREPLY(), irc_user_mode_change(), logic_exec(), logic_on_ircop(), logic_on_part(), and logic_validate().

06761 {
06762     vector<s_online_channel>::iterator i1;
06763     for(i1=irc_channels.begin(); i1!=irc_channels.end(); i1++) {
06764         vector<s_online_user>::iterator i2;
06765         for(i2=(*i1).users.begin(); i2!=(*i1).users.end(); i2++) {
06766             if(!cmp_strings_case_insensitive((*i2).nick,nick)) {
06767                 if(!(*i2).got_whois)
06768                     break;
06769                 return (*i2).ident;
06770             }
06771         }
06772     }
06773     vector<s_online_user>::iterator i2;
06774     for(i2=gone_users.begin(); i2!=gone_users.end(); i2++) {
06775         if(!cmp_strings_case_insensitive((*i2).nick,nick)) {
06776             if(!(*i2).got_whois)
06777                 break;
06778             return (*i2).ident;
06779         }
06780     }
06781     return "";
06782 }

Here is the call graph for this function:

string irc_get_mode string  channel,
string  nick
 

Looks-up user from nick name and checks its mode on channel.

Author:
VooDooMan
Version:
1
Date:
2004
Parameters:
channel Channel name
nick Nick name
Returns:
Returns mode (i.e. "+", "@", "~", "@+", "+@", or "0")
Return values:
+ User has voice
@ User is channel operator
0 Normal user
@+ both +o and +v

Definition at line 6595 of file irc.cpp.

References cmp_strings_case_insensitive(), and irc_channels.

Referenced by dcc_loop(), irc_got_op(), irc_loop_process_input(), logic_exec(), logic_on_nick_change(), and logic_on_nick_validate().

06596 {
06597     vector<s_online_channel>::iterator i;
06598     for(i=irc_channels.begin(); i!=irc_channels.end(); i++) {
06599         if(!cmp_strings_case_insensitive((*i).name,channel)) {
06600             vector<s_online_user>::iterator ii;
06601             for(ii=(*i).users.begin(); ii!=(*i).users.end(); ii++) {
06602                 if(!cmp_strings_case_insensitive((*ii).nick,nick)) {
06603                     if(!(*ii).got_mode)
06604                         return "0";
06605                     return (*ii).mode;
06606                 }
06607             }
06608         }
06609     }
06610 
06611     return "0";
06612 }

Here is the call graph for this function:

string irc_get_modes_for_log string  channel,
string  nick
 

Looks-up user from nick name and returns their mode(s) for logging purposes to channel log.

Author:
VooDooMan
Version:
1
Date:
2005
Parameters:
channel Channel name
nick Nick name
Returns:
Returns mode(s) (i.e. "o", "v", "a", "ov", or "" - an empty string for none, or "?" for not-got-WHOIS-yet/unknown nick)
Return values:
'?' if we don't have WHOIS yet, or nick is unknown

Definition at line 6624 of file irc.cpp.

References cmp_strings_case_insensitive(), s_005::get_prefix2(), and irc_channels.

Referenced by irc_loop_process_input(), and irc_RPL_WHOISOPERATOR().

06625 {
06626     vector<s_online_channel>::iterator i;
06627     for(i=irc_channels.begin(); i!=irc_channels.end(); i++) {
06628         if(!cmp_strings_case_insensitive((*i).name,channel)) {
06629             vector<s_online_user>::iterator ii;
06630             for(ii=(*i).users.begin(); ii!=(*i).users.end(); ii++) {
06631                 if(!cmp_strings_case_insensitive((*ii).nick,nick)) {
06632                     if(!(*ii).got_mode)
06633                         return "?";
06634                     string res;
06635                     if((*ii).irc_op)
06636                         res+="!";
06637                     for(unsigned int i1=0; i1<(*ii).mode.length(); i1++)
06638                         if((*ii).mode[i1]!='0')
06639                             res+=(string)""+irc_isupport.get_prefix2((*ii).mode[i1]);
06640                     return res;
06641                 }
06642             }
06643         }
06644     }
06645 
06646     return "?";
06647 }

Here is the call graph for this function:

string irc_get_nick string  user  ) 
 

Looks-up user from name in logic.txt to nick name (if online).

Author:
VooDooMan
Version:
1
Date:
2004
Parameters:
user User name as in logic.txt
Returns:
If user is online, returns its nick name, if not, returns user parameter

Definition at line 6521 of file irc.cpp.

References cmp_strings_case_insensitive(), and irc_channels.

Referenced by dcc_loop(), dcc_loop_filesystem(), dcc_notify(), logic_exec_script(), and logic_validate_by_mask().

06522 {
06523     vector<s_online_channel>::iterator i;
06524     for(i=irc_channels.begin(); i!=irc_channels.end(); i++) {
06525         vector<s_online_user>::iterator ii;
06526         for(ii=(*i).users.begin(); ii!=(*i).users.end(); ii++) {
06527             if(!cmp_strings_case_insensitive((*ii).in_logic_as,user)) {
06528                 return (*ii).nick;
06529             }
06530         }
06531     }
06532 
06533     return user;
06534 }

Here is the call graph for this function:

bool irc_got_op string  channel  ) 
 

Checks if bot has op (+o) on channel.

Author:
VooDooMan
Version:
1
Date:
2004
Parameters:
channel Channel to check
Return values:
true If bot got +o
false If bot got -o

Definition at line 6943 of file irc.cpp.

References s_005::get_prefix1(), irc_get_mode(), and irc_nick.

Referenced by logic_exec().

06944 {
06945     string m=irc_get_mode(channel,irc_nick);
06946     return m.find(irc_isupport.get_prefix1('o'),0)!=string::npos;
06947 }

Here is the call graph for this function:

bool irc_is_ircop string  nick  ) 
 

Looks-up user from name in logic.txt and checks if it is an irc operator (if online).

Author:
VooDooMan
Version:
1
Date:
2004
Parameters:
nick Nick name
Returns:
If user is online, returns true for irc operator, if it is not online, returns false

Definition at line 6567 of file irc.cpp.

References cmp_strings_case_insensitive(), and irc_channels.

Referenced by dcc_file_has_been_read(), dcc_loop(), dcc_send_file(), irc_quoted_callback(), irc_RPL_NAMREPLY(), irc_user_mode_change(), logic_exec(), logic_on_ircop(), and logic_on_part().

06568 {
06569     vector<s_online_channel>::iterator i;
06570     for(i=irc_channels.begin(); i!=irc_channels.end(); i++) {
06571         vector<s_online_user>::iterator ii;
06572         for(ii=(*i).users.begin(); ii!=(*i).users.end(); ii++) {
06573             if(!cmp_strings_case_insensitive((*ii).nick,nick)) {
06574                 return (*ii).irc_op;
06575             }
06576         }
06577     }
06578 
06579     return false;
06580 }

Here is the call graph for this function:

string irc_is_online string  user  ) 
 

Looks-up user from name in logic.txt to nick name (if online).

Author:
VooDooMan
Version:
1
Date:
2004
Parameters:
user User name as in logic.txt
Returns:
If user is online, returns its nick name, if not, returns empty string

Definition at line 6544 of file irc.cpp.

References cmp_strings_case_insensitive(), and irc_channels.

06545 {
06546     vector<s_online_channel>::iterator i;
06547     for(i=irc_channels.begin(); i!=irc_channels.end(); i++) {
06548         vector<s_online_user>::iterator ii;
06549         for(ii=(*i).users.begin(); ii!=(*i).users.end(); ii++) {
06550             if(!cmp_strings_case_insensitive((*ii).in_logic_as,user)) {
06551                 return (*ii).nick;
06552             }
06553         }
06554     }
06555 
06556     return "";
06557 }

Here is the call graph for this function:

bool irc_join const char *  channel,
const char *  key
 

JOINs channel.

Author:
VooDooMan
Version:
1
Date:
2004
Parameters:
channel Channel name
key Key to channel (can be empty)
Returns:
Returns false if socket I/O error occured

Definition at line 6408 of file irc.cpp.

References HIGH_PRIORITY, irc_nick, and irc_putserv().

Referenced by dcc_loop(), and logic_exec().

06409 {
06410     if(strlen(channel)>128)
06411         return false;
06412 
06413     char msg[4096];
06414     strcpy(msg,"JOIN ");
06415     strcat(msg,channel);
06416     if(key[0]!=0) {
06417         strcat(msg," ");
06418         strcat(msg,key);
06419     }
06420     bool ok=irc_putserv(msg,false,HIGH_PRIORITY);
06421     strcpy(msg,"MODE ");
06422     strcat(msg,channel);
06423     ok&=irc_putserv(msg,true,HIGH_PRIORITY);
06424     strcpy(msg,"TOPIC ");
06425     strcat(msg,channel);
06426     ok&=irc_putserv(msg,true,HIGH_PRIORITY);
06427     strcpy(msg,"WHOIS ");
06428     strcat(msg,irc_nick);
06429     ok&=irc_putserv(msg,true,HIGH_PRIORITY);
06430 
06431     return ok;
06432 }

Here is the call graph for this function:

bool irc_kick const char *  channel,
const char *  nick,
const char *  reason
 

Kicks nick on channel.

Author:
VooDooMan
Version:
1
Date:
2004
Parameters:
channel Channel name
nick Nick name
reason Kick message (reason of kick)
Returns:
Returns false if socket I/O error occured

Definition at line 6377 of file irc.cpp.

References HIGH_PRIORITY, and irc_putserv().

Referenced by logic_exec().

06378 {
06379     if(strlen(channel)>128)
06380         return false;
06381     if(strlen(nick)>128)
06382         return false;
06383     if(strlen(reason)>128)
06384         return false;
06385 
06386     char msg[4096];
06387     strcpy(msg,"KICK ");
06388     strcat(msg,channel);
06389     strcat(msg," ");
06390     strcat(msg,nick);
06391     if(reason!=NULL && strlen(reason)>0) {
06392         strcat(msg," :");
06393         strcat(msg,reason);
06394     }
06395 
06396     return irc_putserv(msg,false,HIGH_PRIORITY);
06397 }

Here is the call graph for this function:

int irc_loop_process_input  ) 
 

This is called in loop to process messages from server.

Author:
VooDooMan
Version:
1
Date:
2004
Return values:
0 Okay
1 Error occured and bot should reconnect to server
2 Throttled - should be sleep for a couple of seconds

Definition at line 4630 of file irc.cpp.

References s_dcc_awaiting_user::addr4, s_dcc_awaiting_user::addr6, s_online_channel::b_bans_sent, s_online_channel::b_excepts_sent, s_online_channel::b_invites_sent, s_online_channel::bans, in_addr6_::bytes, s_005::chanmodes_a, s_key_chan::channel_name, cmp_strings_case_insensitive(), DCC_ACCESS_DENIED, dcc_awaiting_users, dcc_file_has_been_read(), dcc_get_string(), DCC_IO_ERROR, dcc_loop(), DCC_NO_SUCH_FILE, dcc_send_file(), s_online_channel::excepts, s_online_user::fullname, s_dcc_awaiting_user::fullname, gone_users, s_online_channel::got_excepts, s_online_channel::got_invites, s_online_user::got_mode, s_online_user::got_whois, HIGH_PRIORITY, s_online_user::host, s_dcc_awaiting_user::host, s_online_user::ident, s_dcc_awaiting_user::ident, s_online_user::in_logic_as, inet_pton(), s_online_channel::invites, irc_access_to_partyline(), irc_banned(), irc_cannot_join_channels, irc_channels, irc_check_bans(), irc_check_flood(), irc_check_for_not_invited(), irc_check_for_not_reopped(), irc_check_last_msg(), irc_check_nick_on_channel(), irc_disconnect(), irc_end_of_excepted(), irc_excepted(), irc_follow_redirs, irc_get_fullname(), irc_get_host(), irc_get_ident(), irc_get_mode(), irc_get_modes_for_log(), irc_get_online_channel(), irc_in_reop(), irc_invited(), irc_key_chans, irc_kicked(), irc_kill_command_wait(), irc_kill_last_msg_wait(), irc_last_keepalive_detection, irc_nick, irc_on_broadcast(), irc_on_notice(), irc_on_privmsg(), s_online_user::irc_op, irc_privmsg(), irc_putserv(), irc_putserv_immediately(), irc_quoted_callback(), irc_recommended_port, irc_recommended_server, irc_RPL_324(), irc_RPL_ENDOFWHOIS(), irc_RPL_ISUPPORT(), irc_RPL_MODE(), irc_RPL_NAMREPLY(), irc_RPL_TOPIC(), irc_RPL_WHOISCHANNELS(), irc_RPL_WHOISOPERATOR(), irc_RPL_WHOISUSER(), irc_RPL_YOURID(), irc_server_host, irc_server_port, irc_unique_id, s_online_user::just_joined, s_online_user::just_joined_channel, s_key_chan::keys, lang_get_string(), log_bot(), log_broadcast(), log_channel(), log_debug(), log_irc(), logic_fnc(), logic_get_dcc_host(), logic_on_ircop(), logic_on_join(), logic_on_nick_change(), logic_on_part(), logic_on_server_msg(), LOW_PRIORITY, s_online_user::mode, s_online_channel::modes, msgs_from_server, s_online_channel::name, s_online_user::nick, s_dcc_awaiting_user::nick, s_online_user::old_mode, s_online_user::old_nick, s_online_user::on_join_called, r_channel_defs, s_005::raw, s_msg_to_server::response, sleep(), sock_resolve(), sock_resolve6(), s_dcc_awaiting_user::start_time, s_msg_to_server::timestamp, tmp_users, s_online_channel::topic, TYPE_CTCP, TYPE_IRCOP_JOIN, TYPE_IRCOP_LEFT, TYPE_JOIN, TYPE_KICK, TYPE_MODE, TYPE_NICK, TYPE_NOTICE, TYPE_PART, TYPE_PRIVMSG, TYPE_QUIT, TYPE_QUIT_PART_KICK, TYPE_TOPIC, s_dcc_awaiting_user::user_name_as_in_logic, s_online_channel::users, s_dcc_awaiting_user::using_ipv6, s_msg_to_server::wait_for_response, and s_online_user::whois_sent.

Referenced by logic_exec(), and main().

04631 {
04632     time_t now;
04633     time(&now);
04634     vector<s_online_user>::iterator ii;
04635 _label_1:
04636     for(ii=tmp_users.begin(); ii!=tmp_users.end(); ii++) {
04637         if((*ii).last_whois+10<=now) {
04638             tmp_users.erase(ii);
04639             goto _label_1;
04640         }
04641     }
04642 
04643     list<char*>::iterator i;
04644 
04645 l1:
04646     i=msgs_from_server.begin();
04647     if(i!=msgs_from_server.end()) {
04648         irc_last_keepalive_detection=time(NULL);
04649 
04650         log_irc(true,*i);
04651 
04652         {
04653             string resp=*i;
04654             //bool b=false;
04655             if(resp.length()>=4) {
04656                 if(resp[0]=='P' && resp[1]=='I' && resp[2]=='N' && resp[3]=='G') {
04657                     string pong="PONG :";
04658                     for(unsigned int i1=6; i1<resp.length(); i1++)
04659                         pong+=resp[i1];
04660                     pong+="\r\n";
04661 
04662                     delete[] (*i);
04663                     msgs_from_server.pop_front();
04664 
04665                     irc_putserv_immediately(irc_socket,pong.c_str());
04666 
04667                     goto l1;
04668                 }
04669 
04670                 if(resp[0]=='E' && resp[1]=='R' && resp[2]=='R' && resp[3]=='O' && resp[4]=='R') {
04671                     if(strstr(resp.c_str(),"Throttled") ||
04672                         strstr(resp.c_str(),"throttled") ||
04673                         strstr(resp.c_str(),"too fast") ||
04674                         strstr(resp.c_str(),"Overridden") ||
04675                         strstr(resp.c_str(),"overridden")
04676                         ) {
04677                             irc_disconnect();
04678                             return 2;
04679                         }
04680                     irc_disconnect();
04681                     sleep(60);
04682 
04683                     return 1;
04684                 }
04685 
04686                 unsigned int i1;
04687                 for(i1=0; i1<resp.length(); i1++)
04688                     if(resp[i1]==0x20)
04689                         break;
04690                 i1++;
04691 
04692                 size_t len=resp.length()-i1;
04693                 if(len>4*1024-1) {
04694                     log_debug("one line from IRC server exceeded about 4 KB, in file " __FILE__ " in function ");
04695                     goto l2;
04696                 }
04697 
04698                 char tmp[4*1024];
04699                 strcpy(tmp,(char*)&((resp.c_str())[i1]));
04700                 if(tmp[strlen(tmp)-1]=='\r' || tmp[strlen(tmp)-1]=='\n')
04701                     tmp[strlen(tmp)-1]=0;
04702                 if(tmp[strlen(tmp)-1]=='\r' || tmp[strlen(tmp)-1]=='\n')
04703                     tmp[strlen(tmp)-1]=0;
04704 
04705                 string str=tmp;
04706                 len=str.length();
04707 
04708                 string hm;
04709                 string nick, ident, host;
04710                 string channel;
04711                 string whom; // only for KICK
04712                 string topic; // only for topic
04713                 string notice; // only for NOTICE from server
04714                 if(resp.length()>0 && resp[0]==':') {
04715                     unsigned int i1;
04716                     for(i1=1; i1<resp.length(); i1++) {
04717                         if(resp[i1]==0x20)
04718                             break;
04719                         hm+=resp[i1];
04720                     }
04721                     if(hm.find("!")!=string::npos && hm.find("@")!=string::npos) {
04722                         i1++;
04723                         int pos=0;
04724                         for(i1=1; i1<resp.length(); i1++) {
04725                             if(pos==0 && resp[i1]=='!') {
04726                                 pos++;
04727                                 continue;
04728                             }
04729                             if(pos==1 && resp[i1]=='@') {
04730                                 pos++;
04731                                 continue;
04732                             }
04733                             if(pos==2 && resp[i1]==0x20) {
04734                                 pos++;
04735                                 continue;
04736                             }
04737                             if(pos==3 && resp[i1]==0x20) {
04738                                 pos++;
04739                                 continue;
04740                             }
04741                             if(pos==4 && resp[i1]==0x20) {
04742                                 pos++;
04743                                 continue;
04744                             }
04745                             if(pos==5 && resp[i1]==':') {
04746                                 pos++;
04747                                 continue;
04748                             }
04749                             if(pos==0)
04750                                 nick+=resp[i1];
04751                             if(pos==1)
04752                                 ident+=resp[i1];
04753                             if(pos==2)
04754                                 host+=resp[i1];
04755                             if(pos==3) {
04756                                 // command
04757                             }
04758                             if(pos==4)
04759                                 channel+=resp[i1];
04760                             if(pos==5)
04761                                 whom+=resp[i1];
04762                             if(pos==6)
04763                                 topic+=resp[i1];
04764                         }
04765                     } else {
04766                         // message from server
04767                         nick="";
04768                         ident="";
04769                         host="";
04770                         whom="";
04771                         channel="";
04772                         topic="";
04773                         notice="";
04774                         if(resp.length()>=i1+6 && resp[i1+1]=='M' && resp[i1+2]=='O' && resp[i1+3]=='D' &&
04775                             resp[i1+4]=='E' && resp[i1+5]==0x20) {
04776                                 channel=resp;
04777                                 channel.erase(0,i1+1+strlen("MODE "));
04778                                 whom=channel;
04779                                 if(channel.find("\x20",0)!=string::npos)
04780                                     channel.erase(channel.find(0x20,0),channel.length()-channel.find(0x20,0));
04781                                 if(whom.find(0x20,0)!=string::npos)
04782                                     whom.erase(0,whom.find(0x20,0)+1);
04783                             }
04784                         if(resp.length()>=i1+7 && resp[i1+1]=='T' && resp[i1+2]=='O' && resp[i1+3]=='P' &&
04785                             resp[i1+4]=='I' && resp[i1+5]=='C' && resp[i1+6]==0x20) {
04786                                 channel=resp;
04787                                 channel.erase(0,i1+1+strlen("TOPIC "));
04788                                 whom=channel;
04789                                 if(channel.find("\x20",0)!=string::npos)
04790                                     channel.erase(channel.find(0x20,0),channel.length()-channel.find(0x20,0));
04791                                 if(whom.find(0x20,0)!=string::npos)
04792                                     whom.erase(0,whom.find(0x20,0)+1);
04793                                 whom.erase(0,1);
04794                                 topic=whom;
04795                                 whom="";
04796                             }
04797                         if(resp.length()>=i1+8 && resp[i1+1]=='N' && resp[i1+2]=='O' && resp[i1+3]=='T' &&
04798                             resp[i1+4]=='I' && resp[i1+5]=='C' && resp[i1+6]=='E' && resp[i1+7]==0x20) {
04799                                 channel=resp;
04800                                 channel.erase(0,i1+1+strlen("NOTICE "));
04801                                 whom=channel;
04802                                 if(channel.find("\x20",0)!=string::npos)
04803                                     channel.erase(channel.find(0x20,0),channel.length()-channel.find(0x20,0));
04804                                 if(whom.find(0x20,0)!=string::npos)
04805                                     whom.erase(0,whom.find(0x20,0)+1);
04806                                 whom.erase(0,1);
04807                                 notice=whom;
04808                                 whom="";
04809                             }
04810                     }
04811                     while(whom.length()>0 && whom[whom.length()-1]==0x20)
04812                         whom.erase(whom.length()-1,1);
04813                 }
04814                 string quoted;
04815                 string msg;
04816                 bool sometihng=false;
04817                 bool after_colon=false;
04818                 for(i1=0; i1<len; i1++) {
04819                     if(after_colon)
04820                         msg+=str[i1];
04821                     if(str[i1]==':')
04822                         after_colon=true;
04823                     if(sometihng && str[i1]==0x01)
04824                         break;
04825                     if(!sometihng && str[i1]==0x01) {
04826                         sometihng=true;
04827                         continue;
04828                     }
04829                     if(sometihng)
04830                         quoted+=str[i1];
04831                 }
04832                 if(channel.length()>0 && channel[0]==':')
04833                     channel.erase(0,1);
04834 
04835                 if(len>=4 && str[0]=='P' && str[1]=='O' && str[2]=='N' && str[3]=='G') {
04836                     irc_kill_command_wait("PING");
04837                 }
04838 
04839                 if(len>=7 && str[0]=='P' && str[1]=='R' && str[2]=='I' && str[3]=='V' && str[4]=='M' && str[5]=='S' && str[6]=='G' && str[7]==' ') {
04840                     string tmp=nick;
04841                     tmp+="!";
04842                     tmp+=ident;
04843                     tmp+="@";
04844                     tmp+=host;
04845                     if(channel.find("$")!=-1 || channel.find("%")!=-1) {
04846                         // we got broadcast PRIVMSG message
04847                         log_broadcast(channel.c_str(),TYPE_PRIVMSG,tmp.c_str(),msg.c_str(),irc_server_host,irc_server_port);
04848                         irc_on_broadcast(channel,TYPE_PRIVMSG,tmp,msg,irc_server_host,irc_server_port);
04849                     } else if(!nick.empty()) {
04850                         if(cmp_strings_case_insensitive(channel,irc_nick)) {
04851                             log_channel(channel.c_str(),TYPE_PRIVMSG,tmp.c_str(),"",msg.c_str(),irc_get_modes_for_log(channel,nick).c_str());
04852                             if(msg.find('\x01',0)!=-1 && msg.find("\x01" "ACTION ",0)==-1)
04853                                 irc_check_flood(TYPE_CTCP,channel,tmp,msg);
04854                             else
04855                                 irc_check_flood(TYPE_PRIVMSG,channel,tmp,msg);
04856                             irc_on_privmsg(channel,tmp,msg);
04857                         } else {
04858                             log_channel("private",TYPE_PRIVMSG,tmp.c_str(),"",msg.c_str(),"");
04859                             irc_on_privmsg("",tmp,msg);
04860                         }
04861                     } else {
04862                         // PRIVMSG from server
04863                         if(cmp_strings_case_insensitive(channel,irc_nick)) {
04864                             // it is for channel
04865                             log_channel(channel.c_str(),TYPE_PRIVMSG,hm.c_str(),channel.c_str(),msg.c_str(),"");
04866                             // we really don't want to check for flood now, since it is not likely
04867                             //   when server begins to flood channel, and there is a fact that we
04868                             //   cannot ban server ;-)
04869                             //   -- quote of VooDooMan on 2005-04-22 @ 14:30 GMT +01:00 (zopiclonum 7.5 mg per oral)
04870 
04871                             logic_on_server_msg(channel,hm,TYPE_PRIVMSG,msg,irc_server_host,irc_server_port);
04872                         } else {
04873                             // it is privately for bot
04874                             log_channel("private",TYPE_PRIVMSG,hm.c_str(),channel.c_str(),msg.c_str(),"");
04875 
04876                             logic_on_server_msg("",hm,TYPE_PRIVMSG,msg,irc_server_host,irc_server_port);
04877                         }
04878                     }
04879 
04880                     if(!cmp_strings_case_insensitive(channel,irc_nick) && msg.length()>=3 && msg[0]=='d' && msg[1]=='c' && msg[2]=='c') {
04881                         string user_name_as_in_logic;
04882                         if(irc_access_to_partyline(hm.c_str(),user_name_as_in_logic,msg)) {
04883                             int dcc_group=0;
04884                             string dcc=dcc_get_string(msg,dcc_group);
04885                             string dcc_host=logic_get_dcc_host(dcc_group,user_name_as_in_logic);
04886                             if(!dcc.empty()) {
04887                                 string str="\x01";
04888                                 str+=dcc;
04889                                 str+="\x01";
04890                                 irc_privmsg(nick.c_str(),str.c_str(),LOW_PRIORITY);
04891                                 s_dcc_awaiting_user user;
04892 
04893                                 user.nick=nick;
04894                                 user.ident=irc_get_ident(nick);
04895                                 user.host=irc_get_host(nick);
04896                                 user.fullname=irc_get_fullname(nick);
04897 
04898                                 size_t n=user_name_as_in_logic.length();
04899                                 if(n>128-1)
04900                                     n=128-1;
04901                                 strncpy(user.user_name_as_in_logic,user_name_as_in_logic.c_str(),n);
04902                                 user.user_name_as_in_logic[n]=0;
04903 
04904                                 in_addr6_ ip6;
04905                                 if(inet_pton(AF_INET6,host.c_str(),&ip6)!=1) {
04906                                     user.using_ipv6=false;
04907 #ifdef _WIN32
04908                                     user.addr4.S_un.S_addr=0;
04909 #else
04910                                     user.addr4.s_addr=0;
04911 #endif
04912                                     user.addr4=sock_resolve(host.c_str(),NULL);
04913 #ifdef _WIN32
04914                                     if(!user.addr4.S_un.S_addr) {
04915                                         user.addr4.S_un.S_addr=(unsigned long)-1;
04916 #else
04917                                     if(!user.addr4.s_addr) {
04918                                         user.addr4.s_addr=(unsigned long)-1;
04919 #endif
04920                                         user.addr6=sock_resolve6((char*)host.c_str());
04921                                         user.using_ipv6=true;
04922                                     }
04923                                 } else {
04924                                     memcpy(&user.addr6,&ip6,sizeof(user.addr6));
04925 #ifdef _WIN32
04926                                     user.addr4.S_un.S_addr=(unsigned long)-1;
04927 #else
04928                                     user.addr4.s_addr=(unsigned long)-1;
04929 #endif
04930                                     user.using_ipv6=true;
04931                                 }
04932 
04933                                 time(&user.start_time);
04934 
04935                                 // security issue (two users from the same IP (proxy) connecting at the same time)
04936                                 vector<s_dcc_awaiting_user>::iterator i;
04937 again_:
04938                                 bool ignore=false;
04939                                 for(i=dcc_awaiting_users.begin(); i!=dcc_awaiting_users.end(); i++) {
04940                                     if((*i).start_time+20<time(NULL)) {
04941                                         dcc_awaiting_users.erase(i);
04942                                         goto again_;
04943                                     }
04944                                     if(!(*i).using_ipv6 && !user.using_ipv6) {
04945 #ifdef _WIN32
04946                                         if((*i).addr4.S_un.S_addr==user.addr4.S_un.S_addr)
04947 #else
04948                                         if((*i).addr4.s_addr==user.addr4.s_addr)
04949 #endif
04950                                             ignore=true;
04951                                     }
04952                                     if((*i).using_ipv6 && user.using_ipv6) {
04953                                         if((*i).addr6.bytes[0]==user.addr6.bytes[0] &&
04954                                            (*i).addr6.bytes[1]==user.addr6.bytes[1] &&
04955                                            (*i).addr6.bytes[2]==user.addr6.bytes[2] &&
04956                                            (*i).addr6.bytes[3]==user.addr6.bytes[3] &&
04957                                            (*i).addr6.bytes[4]==user.addr6.bytes[4] &&
04958                                            (*i).addr6.bytes[5]==user.addr6.bytes[5] &&
04959                                            (*i).addr6.bytes[6]==user.addr6.bytes[6] &&
04960                                            (*i).addr6.bytes[7]==user.addr6.bytes[7] &&
04961                                            (*i).addr6.bytes[8]==user.addr6.bytes[8] &&
04962                                            (*i).addr6.bytes[9]==user.addr6.bytes[9] &&
04963                                            (*i).addr6.bytes[10]==user.addr6.bytes[10] &&
04964                                            (*i).addr6.bytes[11]==user.addr6.bytes[11] &&
04965                                            (*i).addr6.bytes[12]==user.addr6.bytes[12] &&
04966                                            (*i).addr6.bytes[13]==user.addr6.bytes[13] &&
04967                                            (*i).addr6.bytes[14]==user.addr6.bytes[14] &&
04968                                            (*i).addr6.bytes[15]==user.addr6.bytes[15])
04969                                            ignore=true;
04970                                     }
04971                                 }
04972 
04973                                 if(!ignore)
04974                                     dcc_awaiting_users.push_back(user);
04975                             }
04976                         }
04977                     }
04978 
04979                     if((msg.length()>=7 && msg[0]=='g' && msg[1]=='e' && msg[2]=='t' && msg[3]=='f' && msg[4]=='i' && msg[5]=='l' && msg[6]=='e' && msg[7]==' ')
04980                         ||
04981                         (msg.length()>=8 && msg[0]=='.' && msg[1]=='g' && msg[2]=='e' && msg[3]=='t' && msg[4]=='f' && msg[5]=='i' && msg[6]=='l' && msg[7]=='e' && msg[8]==' ')
04982                         ) {
04983                         string cmd=msg;
04984                         while(cmd[0]!=' ')
04985                             cmd.erase(0,1);
04986                         string fn;
04987                         string dcc_gr="0";
04988                         int pos=0;
04989                         while(cmd.length()>0) {
04990                             if(cmd[0]==' ') {
04991                                 cmd.erase(0,1);
04992                                 pos++;
04993                                 continue;
04994                             }
04995                             if(pos==1) {
04996                                 fn+=cmd[0];
04997                                 cmd.erase(0,1);
04998                                 continue;
04999                             }
05000                             if(pos==2) {
05001                                 dcc_gr+=cmd[0];
05002                                 cmd.erase(0,1);
05003                                 continue;
05004                             }
05005                         }
05006                         int dcc_group=atol(dcc_gr.c_str());
05007                         int res=dcc_send_file(false,fn,nick,dcc_group);
05008                         string disp;
05009                         switch(res) {
05010                             case DCC_NO_SUCH_FILE:
05011                                 disp=lang_get_string(1,"en",334);
05012                                 break;
05013                             case DCC_ACCESS_DENIED:
05014                                 disp=lang_get_string(1,"en",335);
05015                                 break;
05016                             case DCC_IO_ERROR:
05017                                 disp=lang_get_string(1,"en",336);
05018                                 break;
05019                         }
05020 
05021                         if(!disp.empty()) {
05022                             string m="PRIVMSG ";
05023                             m+=nick;
05024                             m+=" :";
05025                             m+=disp;
05026                             irc_putserv(m.c_str(),false,LOW_PRIORITY);
05027                         } else {
05028                             dcc_file_has_been_read(fn,nick);
05029                         }
05030                     }
05031 
05032                     if(!quoted.empty()) {
05033                         irc_quoted_callback(quoted.c_str(), nick.c_str(), hm.c_str());
05034                     }
05035 
05036                     delete[] (*i);
05037                     msgs_from_server.pop_front();
05038 
05039                     goto l1;
05040                 }
05041 
05042                 if(len>=6 && str[0]=='N' && str[1]=='O' && str[2]=='T' && str[3]=='I' && str[4]=='C' && str[5]=='E' && str[6]==' ') {
05043                     string tmp=nick;
05044                     tmp+="!";
05045                     tmp+=ident;
05046                     tmp+="@";
05047                     tmp+=host;
05048                     if(channel.find("$")!=-1 || channel.find("%")!=-1) {
05049                         // we got broadcast NOTICE message
05050                         log_broadcast(channel,TYPE_NOTICE,tmp,msg,irc_server_host,irc_server_port);
05051                         irc_on_broadcast(channel,TYPE_NOTICE,tmp,msg,irc_server_host,irc_server_port);
05052                     } else if(!nick.empty()) {
05053                         if(cmp_strings_case_insensitive(channel,irc_nick)) {
05054                             log_channel(channel.c_str(),TYPE_NOTICE,hm.c_str(),channel.c_str(),msg.c_str(),irc_get_modes_for_log(channel,nick).c_str());
05055                             if(msg.find('\x01',0)!=-1 && msg.find("\x01" "ACTION ",0)==-1)
05056                                 irc_check_flood(TYPE_CTCP,channel,tmp,msg);
05057                             else
05058                                 irc_check_flood(TYPE_NOTICE,channel,tmp,msg);
05059                             irc_on_notice(channel,tmp,msg);
05060                         } else {
05061                             log_channel("private",TYPE_NOTICE,hm.c_str(),channel.c_str(),msg.c_str(),"");
05062                             irc_on_notice("",tmp,msg);
05063                         }
05064                     } else {
05065                         // NOTICE from server
05066                         if(cmp_strings_case_insensitive(channel,irc_nick)) {
05067                             // it is for channel
05068                             log_channel(channel.c_str(),TYPE_NOTICE,hm.c_str(),channel.c_str(),msg.c_str(),"");
05069                             // we really don't want to check for flood now, since it is not likely
05070                             //   when server begins to flood channel, and there is a fact that we
05071                             //   cannot ban server ;-)
05072                             //   -- quote of VooDooMan on 2005-04-22 @ 14:30 GMT +01:00 (zopiclonum 7.5 mg per oral)
05073 
05074                             logic_on_server_msg(channel,hm,TYPE_NOTICE,msg,irc_server_host,irc_server_port);
05075                         } else {
05076                             // it is privately for bot
05077                             log_channel("private",TYPE_NOTICE,hm.c_str(),channel.c_str(),msg.c_str(),"");
05078 
05079                             logic_on_server_msg("",hm,TYPE_NOTICE,msg,irc_server_host,irc_server_port);
05080                         }
05081                     }
05082                 }
05083 
05084                 if(len>4 && str[0]=='J' && str[1]=='O' && str[2]=='I' && str[3]=='N') {
05085                     if(!nick.empty()) {
05086                         string tmp=nick;
05087                         tmp+="!";
05088                         tmp+=ident;
05089                         tmp+="@";
05090                         tmp+=host;
05091                         log_channel(channel.c_str(),TYPE_JOIN,tmp.c_str(),"","",irc_get_modes_for_log(channel,nick).c_str());
05092 
05093                         irc_check_flood(TYPE_JOIN,channel,tmp,""); // !!! we (maybe) don't know who "tmp" is here!
05094                     }
05095 
05096                     if(!nick.compare(irc_nick)) {
05097                         irc_kill_command_wait("JOIN");
05098 
05099                         vector<s_key_chan>::iterator i2;
05100                     label_b:
05101                         for(i2=irc_key_chans.begin(); i2!=irc_key_chans.end(); i2++) {
05102                             if(!cmp_strings_case_insensitive((*i2).channel_name,channel)) {
05103                                 irc_key_chans.erase(i2);
05104                                 goto label_b;
05105                             }
05106                         }
05107 
05108                         vector<string>::iterator i1;
05109                     erase_again:
05110                         for(i1=irc_cannot_join_channels.begin(); i1!=irc_cannot_join_channels.end(); i1++) {
05111                             if(!cmp_strings_case_insensitive(*i1,channel)) {
05112                                 irc_cannot_join_channels.erase(i1);
05113                                 goto erase_again;
05114                             }
05115                         }
05116                     }
05117 
05118                     str.erase(0,5);
05119                     unsigned int i1;
05120                     for(i1=0; i1<str.length(); i1++)
05121                         if(str[i1]==0x20)
05122                             break;
05123                     if(str.length()-i1>0)
05124                         str.erase(i1,str.length()-i1);
05125 
05126                     for(i1=0; i1<str.length(); i1++)
05127                         if(str[i1]==':')
05128                             break;
05129                     if(str[i1]==':')
05130                         str.erase(0,i1+1); // erase everything before ':'
05131 
05132                     bool got_user=false;
05133                     bool got_channel=false;
05134                 l5:
05135                     vector<s_online_channel>::iterator i2;
05136                     vector<s_online_user>::iterator ii;
05137                     for(i2=irc_channels.begin(); i2!=irc_channels.end(); i2++) {
05138                         if(!cmp_strings_case_insensitive((*i2).name,str)) {
05139                             got_channel=true;
05140                             for(ii=(*i2).users.begin(); ii!=(*i2).users.end(); ii++) {
05141                                 if(!cmp_strings_case_insensitive((*ii).nick,nick)) {
05142                                     (*i2).users.erase(ii);
05143                                     got_user=false;
05144                                     goto l5;
05145                                 }
05146                             }
05147                             if(got_user)
05148                                 break;
05149                         }
05150                     }
05151 
05152                 l10:
05153                     vector<s_online_channel>::iterator i;
05154                     got_channel=false;
05155                     for(i=irc_channels.begin(); i!=irc_channels.end(); i++) {
05156                         if(!cmp_strings_case_insensitive((*i).name,str)) {
05157                             got_channel=true;
05158                             break;
05159                         }
05160                     }
05161                     if(!got_channel) {
05162                         s_online_channel chan;
05163                         chan.b_excepts_sent=chan.b_invites_sent=chan.b_bans_sent=false;
05164                         chan.name=str;
05165                         chan.modes="";
05166                         chan.topic="";
05167                         chan.users.clear();
05168                         chan.bans.clear();
05169                         chan.got_excepts=false;
05170                         chan.got_invites=false;
05171                         chan.excepts.clear();
05172                         chan.invites.clear();
05173                         irc_channels.push_back(chan);
05174 
05175                         goto l10;
05176                     }
05177 
05178                     if(!nick.compare(irc_nick)) {
05179                         // we are new on channel, right after JOIN
05180                     }
05181 
05182                     if(got_channel && !irc_check_nick_on_channel(nick,channel)) {
05183                         for(i2=irc_channels.begin(); i2!=irc_channels.end(); i2++)
05184                             if(!cmp_strings_case_insensitive((*i2).name,str))
05185                                 break;
05186 
05187                         s_online_user u;
05188                         u.nick=nick;
05189                         u.got_whois=false;
05190                         u.on_join_called=false;
05191                         u.old_mode="INVALID";
05192 
05193                         bool got_nick=false;
05194                         vector<s_online_channel>::iterator ii1;
05195                         vector<s_online_user>::iterator ii2;
05196                         for(ii1=irc_channels.begin(); ii1!=irc_channels.end(); ii1++) {
05197                             for(ii2=(*ii1).users.begin(); ii2!=(*ii1).users.end(); ii2++) {
05198                                 if(!(*ii2).nick.compare(nick)) {
05199                                     got_nick=true;
05200                                     break;
05201                                 }
05202                             }
05203                             if(got_nick)
05204                                 break;
05205                         }
05206 
05207                         if(!got_nick) {
05208 hard_whois:
05209                             string str="WHOIS ";
05210                             str+=nick;
05211                             irc_putserv(str.c_str(),true,HIGH_PRIORITY);
05212 
05213                             u.whois_sent=true;
05214 
05215                             u.ident=ident;
05216                             u.host=host;
05217                             u.fullname="";
05218                             u.got_mode=false;
05219                             u.mode="0";
05220                             u.irc_op=false;
05221                             u.in_logic_as="";
05222 
05223                             u.just_joined=true;
05224                             u.just_joined_channel=channel;
05225                         } else {
05226                             if(!(*ii2).got_whois)
05227                                 goto hard_whois;
05228                             u.fullname=(*ii2).fullname;
05229                             u.got_mode=true;
05230                             u.got_whois=true;
05231                             u.host=(*ii2).host;
05232                             u.ident=(*ii2).ident;
05233                             u.in_logic_as=(*ii2).in_logic_as;
05234                             u.irc_op=(*ii2).irc_op;
05235                             u.mode="0";
05236                             u.nick=(*ii2).nick;
05237                             u.old_nick=u.nick;
05238                             u.old_mode=u.mode;
05239                             u.on_join_called=true;
05240                             u.whois_sent=true;
05241                             u.just_joined_channel=channel;
05242 
05243                             u.just_joined=true;
05244                             if(nick.compare(irc_nick)) // only call if it is not me myself!
05245                                 logic_on_join(u.nick,u.ident,u.host,u.fullname,u.just_joined_channel,u.irc_op);
05246                             if(u.irc_op) {
05247                                 logic_on_ircop(channel,u.nick,true);
05248                                 string host_mask=u.nick;
05249                                 host_mask+="!";
05250                                 host_mask+=u.ident;
05251                                 host_mask+="@";
05252                                 host_mask+=u.host;
05253                                 log_channel(channel.c_str(),TYPE_IRCOP_JOIN,host_mask.c_str(),"","",irc_get_modes_for_log(channel,nick).c_str());
05254                             }
05255                         }
05256                         (*i2).users.push_back(u);
05257                     }
05258 
05259                     if(irc_check_last_msg("JOIN"))
05260                         irc_kill_last_msg_wait(resp);
05261 
05262                     irc_kill_command_wait("JOIN");
05263                 }
05264                 str=tmp;
05265 
05266                 if(len>4 && str[0]=='Q' && str[1]=='U' && str[2]=='I' && str[3]=='T') {
05267                     string host_mask;
05268                     if(!nick.empty()) {
05269                         string tmp=nick;
05270                         tmp+="!";
05271                         tmp+=ident;
05272                         tmp+="@";
05273                         tmp+=host;
05274                         host_mask=tmp;
05275                         vector<s_online_channel>::iterator i1;
05276                         for(i1=irc_channels.begin(); i1!=irc_channels.end(); i1++) {
05277                             vector<s_online_user>::iterator i2;
05278                             for(i2=(*i1).users.begin(); i2!=(*i1).users.end(); i2++)
05279                                 if(!cmp_strings_case_insensitive((*i2).nick,nick)) {
05280                                     log_channel((*i1).name.c_str(),TYPE_QUIT,tmp.c_str(),"",msg.c_str(),irc_get_modes_for_log(channel,nick).c_str());
05281                                     if((*i2).irc_op) {
05282                                         logic_on_ircop((*i1).name,nick,false);
05283                                         log_channel((*i1).name.c_str(),TYPE_IRCOP_LEFT,host_mask.c_str(),"","",irc_get_modes_for_log((*i1).name,nick).c_str());
05284                                     }
05285                                     irc_check_flood(TYPE_QUIT_PART_KICK,(*i1).name,tmp,msg);
05286 
05287                                     logic_on_part((*i1).name,nick,msg,TYPE_QUIT);
05288                                 }
05289                         }
05290                     }
05291 
05292                     vector<s_online_channel>::iterator i;
05293                 l6:
05294                     for(i=irc_channels.begin(); i!=irc_channels.end(); i++) {
05295                         vector<s_online_user>::iterator ii;
05296                         for(ii=(*i).users.begin(); ii!=(*i).users.end(); ii++) {
05297                             if(!cmp_strings_case_insensitive((*ii).nick,nick)) {
05298                                 time(&(*ii).quit_time);
05299                                 gone_users.push_back(*ii);
05300                                 (*i).users.erase(ii);
05301                                 goto l6;
05302                             }
05303                         }
05304                     }
05305                 cycle1:
05306                     for(i=irc_channels.begin(); i!=irc_channels.end(); i++) {
05307                         string my_modes=irc_get_mode((*i).name,irc_nick);
05308                         if(my_modes.find('@',0)==-1 && cmp_strings_case_insensitive(nick,irc_nick)) {
05309                             int users=0;
05310                             vector<s_online_user>::iterator ii;
05311                             for(ii=(*i).users.begin(); ii!=(*i).users.end(); ii++, users++)
05312                                 ;
05313                             if(users==1) {
05314                                 // try to get op
05315                                 string m=(*i).name;
05316                                 irc_kill_last_msg_wait(resp);
05317                                 string msg="PART ";
05318                                 msg+=m;
05319                                 irc_putserv(msg.c_str(),false,HIGH_PRIORITY);
05320                                 msg="JOIN ";
05321                                 msg+=m;
05322                                 irc_putserv(msg.c_str(),true,HIGH_PRIORITY);
05323                                 msg="MODE ";
05324                                 msg+=m;
05325                                 irc_putserv(msg.c_str(),true,HIGH_PRIORITY);
05326                                 msg="TOPIC ";
05327                                 msg+=m;
05328                                 irc_putserv(msg.c_str(),true,HIGH_PRIORITY);
05329                                 msg="WHOIS ";
05330                                 msg+=irc_nick;
05331                                 irc_putserv(msg.c_str(),true,HIGH_PRIORITY);
05332 
05333                                 irc_channels.erase(i);
05334                                 goto cycle1;
05335                             }
05336                         }
05337                     }
05338                 }
05339                 str=tmp;
05340 
05341                 if(len>4 && str[0]=='P' && str[1]=='A' && str[2]=='R' && str[3]=='T') {
05342                     string host_mask;
05343                     if(!nick.empty()) {
05344                         string tmp=nick;
05345                         tmp+="!";
05346                         tmp+=ident;
05347                         tmp+="@";
05348                         tmp+=host;
05349                         host_mask=tmp;
05350                         log_channel(channel.c_str(),TYPE_PART,tmp.c_str(),"",msg.c_str(),irc_get_modes_for_log(channel,nick).c_str());
05351 
05352                         irc_check_flood(TYPE_QUIT_PART_KICK,channel,tmp,msg);
05353                     }
05354 
05355                     str.erase(0,5);
05356                     unsigned int i1;
05357                     for(i1=0; i1<str.length(); i1++)
05358                         if(str[i1]==0x20)
05359                             break;
05360                     if(str.length()-i1>0)
05361                         str.erase(i1,str.length()-i1);
05362 
05363                 l8:
05364                     vector<s_online_channel>::iterator i;
05365                     bool got_channel=false;
05366                     for(i=irc_channels.begin(); i!=irc_channels.end(); i++) {
05367                         if(!cmp_strings_case_insensitive((*i).name,str)) {
05368                             got_channel=true;
05369                             break;
05370                         }
05371                     }
05372                     if(!got_channel /*&& nick.compare(irc_nick)*/) {
05373                         // we are new on channel, right after JOIN
05374                         // assume that irc server will send names reply
05375                         s_online_channel chan;
05376                         chan.b_excepts_sent=chan.b_invites_sent=chan.b_bans_sent=false;
05377                         chan.name=str;
05378                         chan.modes="";
05379                         chan.topic="";
05380                         chan.users.clear();
05381                         chan.bans.clear();
05382                         chan.got_excepts=false;
05383                         chan.excepts.clear();
05384                         chan.got_invites=false;
05385                         chan.invites.clear();
05386                         irc_channels.push_back(chan);
05387 
05388                         goto l8;
05389                     }
05390 
05391                 l7:
05392                     vector<s_online_user>::iterator ii;
05393                     for(ii=(*i).users.begin(); ii!=(*i).users.end(); ii++) {
05394                         if(!cmp_strings_case_insensitive((*ii).nick,nick) && !cmp_strings_case_insensitive((*i).name,str)) {
05395                             logic_on_part(channel,nick,msg,TYPE_PART);
05396                             if((*ii).irc_op) {
05397                                 logic_on_ircop(channel,nick,false);
05398                                 log_channel(channel.c_str(),TYPE_IRCOP_LEFT,host_mask.c_str(),"","",irc_get_modes_for_log((*i).name,nick).c_str());
05399                             }
05400 
05401                             if(cmp_strings_case_insensitive((*ii).ident,ident) || cmp_strings_case_insensitive((*ii).host,host)) {
05402                                 time(&(*ii).quit_time);
05403                                 gone_users.push_back(*ii);
05404                                 (*i).users.erase(ii);
05405 
05406                                 goto l7;
05407                             }
05408                             (*i).users.erase(ii);
05409                             goto l7;
05410                         }
05411                     }
05412                 cycle2:
05413                     for(i=irc_channels.begin(); i!=irc_channels.end(); i++) {
05414                         string my_modes=irc_get_mode((*i).name,irc_nick);
05415                         if(my_modes.find('@',0)==-1 && cmp_strings_case_insensitive(nick,irc_nick)) {
05416                             int users=0;
05417                             vector<s_online_user>::iterator ii;
05418                             for(ii=(*i).users.begin(); ii!=(*i).users.end(); ii++, users++)
05419                                 ;
05420                             // if someone else has PART-ed, try to get op
05421                             if(users==1 && cmp_strings_case_insensitive(nick,irc_nick)) {
05422                                 // try to get op
05423                                 string m=(*i).name;
05424                                 irc_kill_last_msg_wait(resp);
05425                                 string msg="PART ";
05426                                 msg+=m;
05427                                 irc_putserv(msg.c_str(),false,HIGH_PRIORITY);
05428                                 msg="JOIN ";
05429                                 msg+=m;
05430                                 irc_putserv(msg.c_str(),true,HIGH_PRIORITY);
05431                                 msg="MODE ";
05432                                 msg+=m;
05433                                 irc_putserv(msg.c_str(),true,HIGH_PRIORITY);
05434                                 msg="TOPIC ";
05435                                 msg+=m;
05436                                 irc_putserv(msg.c_str(),true,HIGH_PRIORITY);
05437                                 msg="WHOIS ";
05438                                 msg+=irc_nick;
05439                                 irc_putserv(msg.c_str(),true,HIGH_PRIORITY);
05440 
05441                                 irc_channels.erase(i);
05442                                 goto cycle2;
05443                             }
05444                         }
05445                     }
05446                     if(!cmp_strings_case_insensitive(nick,irc_nick)) {
05447                         // if I PART-ed
05448                         irc_kill_last_msg_wait(resp);
05449 
05450                         irc_kill_command_wait("PART");
05451 
05452                 again_e_chan2:
05453                         vector<s_online_channel>::iterator i;
05454                         for(i=irc_channels.begin(); i!=irc_channels.end(); i++) {
05455                             if(!cmp_strings_case_insensitive((*i).name,channel)) {
05456                                 irc_channels.erase(i);
05457                                 goto again_e_chan2;
05458                             }
05459                         }
05460                     }
05461                 }
05462                 str=tmp;
05463 
05464                 if(len>4 && str[0]=='K' && str[1]=='I' && str[2]=='C' && str[3]=='K') {
05465                     irc_kill_command_wait("KICK");
05466 
05467                     string host_mask;
05468                     if(!nick.empty()) {
05469                         string tmp=nick;
05470                         tmp+="!";
05471                         tmp+=ident;
05472                         tmp+="@";
05473                         tmp+=host;
05474                         host_mask=tmp;
05475                         log_channel(channel.c_str(),TYPE_KICK,tmp.c_str(),whom.c_str(),msg.c_str(),irc_get_modes_for_log(channel,nick).c_str());
05476 
05477                         irc_check_flood(TYPE_QUIT_PART_KICK,channel,tmp,msg);
05478 
05479                         irc_kicked(resp);
05480                     }
05481 
05482                     vector<s_online_channel>::iterator i;
05483                     for(i=irc_channels.begin(); i!=irc_channels.end(); i++) {
05484                         if(!cmp_strings_case_insensitive((*i).name,channel)) {
05485                             vector<s_online_user>::iterator ii;
05486                             for(ii=(*i).users.begin(); ii!=(*i).users.end(); ii++) {
05487                                 if(!cmp_strings_case_insensitive((*ii).nick,whom)) {
05488                                     logic_on_part(channel,whom,msg,TYPE_KICK);
05489                                     if((*ii).irc_op) {
05490                                         logic_on_ircop(channel,whom,false);
05491                                         log_channel(channel.c_str(),TYPE_IRCOP_LEFT,host_mask.c_str(),"","",irc_get_modes_for_log((*i).name,nick).c_str());
05492                                     }
05493 
05494                                     time(&(*ii).quit_time);
05495                                     gone_users.push_back(*ii);
05496                                     (*i).users.erase(ii);
05497                                     break;
05498                                 }
05499                             }
05500                         }
05501                     }
05502                 cycle3:
05503                     for(i=irc_channels.begin(); i!=irc_channels.end(); i++) {
05504                         string my_modes=irc_get_mode((*i).name,irc_nick);
05505                         if(my_modes.find('@',0)==-1 && cmp_strings_case_insensitive(nick,irc_nick)) {
05506                             int users=0;
05507                             vector<s_online_user>::iterator ii;
05508                             for(ii=(*i).users.begin(); ii!=(*i).users.end(); ii++, users++)
05509                                 ;
05510                             // if not KICK-ed me, but someone else, try to get op
05511                             if(users==1 && cmp_strings_case_insensitive(whom,irc_nick)) {
05512                                 // try to get op
05513                                 string m=(*i).name;
05514                                 irc_kill_last_msg_wait(resp);
05515 
05516                                 irc_kill_command_wait("KICK");
05517 
05518                                 string msg="PART ";
05519                                 msg+=m;
05520                                 irc_putserv(msg.c_str(),false,HIGH_PRIORITY);
05521                                 msg="JOIN ";
05522                                 msg+=m;
05523                                 irc_putserv(msg.c_str(),true,HIGH_PRIORITY);
05524                                 msg="MODE ";
05525                                 msg+=m;
05526                                 irc_putserv(msg.c_str(),true,HIGH_PRIORITY);
05527                                 msg="TOPIC ";
05528                                 msg+=m;
05529                                 irc_putserv(msg.c_str(),true,HIGH_PRIORITY);
05530                                 msg="WHOIS ";
05531                                 msg+=irc_nick;
05532                                 irc_putserv(msg.c_str(),true,HIGH_PRIORITY);
05533 
05534                                 irc_channels.erase(i);
05535                                 goto cycle3;
05536                             }
05537                         }
05538                     }
05539                     if(!cmp_strings_case_insensitive(whom,irc_nick)) {
05540                 again_e_chan1:
05541                         vector<s_online_channel>::iterator i;
05542                         for(i=irc_channels.begin(); i!=irc_channels.end(); i++) {
05543                             if(!cmp_strings_case_insensitive((*i).name,channel)) {
05544                                 irc_channels.erase(i);
05545                                 goto again_e_chan1;
05546                             }
05547                         }
05548                     }
05549                     irc_kill_last_msg_wait(resp);
05550                 }
05551                 str=tmp;
05552 
05553                 if(len>4 && str[0]=='N' && str[1]=='I' && str[2]=='C' && str[3]=='K') {
05554                     irc_kill_command_wait("NICK");
05555 
05556             forced_nick_change:
05557                     if(!nick.empty()) {
05558                         string tmp=nick;
05559                         tmp+="!";
05560                         tmp+=ident;
05561                         tmp+="@";
05562                         tmp+=host;
05563                         vector<s_online_channel>::iterator i1;
05564                         for(i1=irc_channels.begin(); i1!=irc_channels.end(); i1++) {
05565                             vector<s_online_user>::iterator ii;
05566                             for(ii=(*i1).users.begin(); ii!=(*i1).users.end(); ii++) {
05567                                 if(!cmp_strings_case_insensitive((*ii).nick,nick)) {
05568                                     // msg contains new nick
05569                                     log_channel((*i1).name.c_str(),TYPE_NICK,tmp.c_str(),"",msg.c_str(),irc_get_modes_for_log((*i1).name,nick).c_str());
05570                                     if(nick.compare(irc_nick)) {
05571                                         irc_check_flood(TYPE_NICK,(*i1).name,tmp,msg);
05572                                         // do NOT perform next line! we got it later
05573                                         //(*ii).nick=msg;
05574                                         char tmp[1024];
05575                                         strcpy(tmp,"WHOIS ");
05576                                         strcat(tmp,msg.c_str());
05577                                         irc_putserv(tmp,true,HIGH_PRIORITY);
05578                                     } else {
05579                                         if(msg.length()<sizeof(irc_nick)) {
05580                                             strcpy(irc_nick,msg.c_str());
05581                                             char tmp[1024];
05582                                             strcpy(tmp,"WHOIS ");
05583                                             strcat(tmp,irc_nick);
05584                                             irc_putserv(tmp,true,HIGH_PRIORITY);
05585                                         }
05586                                     }
05587                                 }
05588                             }
05589                         }
05590                         if(!cmp_strings_case_insensitive(nick,irc_nick)) {
05591                             if(msg.length()<sizeof(irc_nick))
05592                                 strcpy(irc_nick,msg.c_str());
05593                         }
05594                     }
05595 
05596                     vector<s_online_channel>::iterator i;
05597                     for(i=irc_channels.begin(); i!=irc_channels.end(); i++) {
05598                         vector<s_online_user>::iterator ii;
05599                         for(ii=(*i).users.begin(); ii!=(*i).users.end(); ii++) {
05600                             if(!cmp_strings_case_insensitive((*ii).nick,nick)) {
05601                                 string old_nick=(*ii).nick;
05602                                 (*ii).nick=msg;
05603 
05604                                 // validate new nick
05605                                 logic_on_nick_change((*ii).nick,(*ii).ident,(*ii).host,(*ii).fullname,(*ii).just_joined_channel,(*ii).irc_op,old_nick);
05606                             }
05607                         }
05608                     }
05609                 }
05610                 str=tmp;
05611 
05612                 // 433: nickname already in use
05613                 if(len>4 && str[0]=='4' && str[1]=='3' && str[2]=='3' && str[3]==' ') {
05614                     if(irc_check_last_msg("NICK"))
05615                         irc_kill_last_msg_wait(resp);
05616 
05617                     irc_kill_command_wait("NICK");
05618                 }
05619 
05620                 if(len>4 && str[0]=='0' && str[1]=='0' && str[2]=='1' && str[3]==' ') {
05621                     if(irc_check_last_msg("USER"))
05622                         irc_kill_last_msg_wait(resp);
05623 
05624                     irc_kill_command_wait("USER");
05625                 }
05626                 if(len>4 && str[0]=='0' && str[1]=='0' && str[2]=='2' && str[3]==' ') {
05627                     if(irc_check_last_msg("USER"))
05628                         irc_kill_last_msg_wait(resp);
05629 
05630                     irc_kill_command_wait("USER");
05631                 }
05632                 if(len>4 && str[0]=='0' && str[1]=='0' && str[2]=='3' && str[3]==' ') {
05633                     if(irc_check_last_msg("USER"))
05634                         irc_kill_last_msg_wait(resp);
05635 
05636                     irc_kill_command_wait("USER");
05637                 }
05638                 if(len>4 && str[0]=='0' && str[1]=='0' && str[2]=='4' && str[3]==' ') {
05639                     if(irc_check_last_msg("USER"))
05640                         irc_kill_last_msg_wait(resp);
05641 
05642                     irc_kill_command_wait("USER");
05643                 }
05644                 if(len>4 && str[0]=='0' && str[1]=='0' && str[2]=='5' && str[3]==' ') {
05645                     if(irc_check_last_msg("USER"))
05646                         irc_kill_last_msg_wait(resp);
05647 
05648                     irc_kill_command_wait("USER");
05649 
05650                     // check for string "Try server <server name>, port <port number>"
05651                     str.erase(0,4);
05652                     size_t len=str.length();
05653                     if(len>11 && str[1]=='r' && str[2]=='y' && str[3]==0x20 &&  str[4]=='s' && str[5]=='e' &&
05654                         str[6]=='r' &&  str[7]=='v' &&  str[8]=='e' &&  str[9]=='r' &&  str[10]==0x20) {
05655                             str.erase(0,11);
05656                             string p;
05657                             p=str;
05658 
05659                             while(p.length()>0 && p[0]!=',')
05660                                 p.erase(0,1);
05661                             while(p.length()>0 && (p[0]<'0' || p[0]>'9'))
05662                                 p.erase(0,1);
05663 
05664                             unsigned int i1;
05665                             for(i1=0; i1<str.length(); i1++)
05666                                 if(str[i1]==',' || str[i1]==0x20)
05667                                     break;
05668                             str.erase(0,i1+1);
05669 
05670                             unsigned short port=(unsigned short)atol(p.c_str());
05671                             if(irc_follow_redirs) {
05672                                 irc_recommended_server=str;
05673                                 irc_recommended_port=port;
05674                             }
05675                         } else {
05676                             irc_RPL_ISUPPORT(str);
05677                         }
05678                 }
05679 
05680                 // NAMES reply
05681                 if(len>4 && str[0]=='3' && str[1]=='5' && str[2]=='3' && str[3]==' ') {
05682                     irc_RPL_NAMREPLY(str);
05683                 }
05684 
05685                 // RPL_ENDOFNAMES
05686                 if(len>4 && str[0]=='3' && str[1]=='6' && str[2]=='6' && str[3]==' ') {
05687                     if(irc_check_last_msg("NAMES"))
05688                         irc_kill_last_msg_wait(resp);
05689 
05690                     irc_kill_command_wait("NAMES");
05691                 }
05692 
05693                 // RPL_WHOISUSER
05694                 // WHOIS reply
05695                 if(len>4 && str[0]=='3' && str[1]=='1' && str[2]=='1' && str[3]==' ') {
05696                     irc_RPL_WHOISUSER(str);
05697                 }
05698 
05699                 // RPL_WHOISOPERATOR
05700                 // user is an IRC operator
05701                 if(len>4 && str[0]=='3' && str[1]=='1' && str[2]=='3' && str[3]==' ') {
05702                     irc_RPL_WHOISOPERATOR(str);
05703                 }
05704 
05705                 // RPL_ENDOFWHOIS
05706                 if(len>4 && str[0]=='3' && str[1]=='1' && str[2]=='8' && str[3]==' ') {
05707                     irc_RPL_ENDOFWHOIS(str);
05708                     if(irc_check_last_msg("WHOIS"))
05709                         irc_kill_last_msg_wait(resp);
05710 
05711                     irc_kill_command_wait("WHOIS");
05712                 }
05713 
05714                 // RPL_WHOISCHANNELS
05715                 if(len>4 && str[0]=='3' && str[1]=='1' && str[2]=='9' && str[3]==' ') {
05716                     irc_RPL_WHOISCHANNELS(str);
05717                 }
05718 
05719                 // 471: Cannot join channel (+l) - limit
05720                 // 473: Cannot join channel (+i) - invite only
05721                 // 474: Cannot join channel (+b) - banned
05722                 // 437: Channel/nick is temporarily unavailable (!!! also can be not channel, but nick!!!)
05723                 if(len>4 && (
05724                     (str[0]=='4' && str[1]=='7' && str[2]=='1' && str[3]==' ') ||
05725                     (str[0]=='4' && str[1]=='7' && str[2]=='3' && str[3]==' ') ||
05726                     (str[0]=='4' && str[1]=='7' && str[2]=='4' && str[3]==' ') ||
05727                     (str[0]=='4' && str[1]=='3' && str[2]=='7' && str[3]==' ')))
05728                 {
05729                     irc_kill_command_wait("JOIN");
05730                     irc_kill_command_wait("MODE");
05731                     irc_kill_command_wait("TOPIC");
05732 
05733                     string s=str;
05734                     int i1=0;
05735                     while(i1<2 && s.length()>0) {
05736                         if(s[0]==0x20)
05737                             i1++;
05738                         s.erase(0,1);
05739                     }
05740                     string chan;
05741                     while(s.length()>0 && s[0]!=0x20) {
05742                         chan+=s[0];
05743                         s.erase(0,1);
05744                     }
05745 
05746                     bool got=false;
05747                     vector<string>::iterator i2;
05748                     for(i2=irc_cannot_join_channels.begin(); i2!=irc_cannot_join_channels.end(); i2++)
05749                         if(!cmp_strings_case_insensitive(*i2,chan)) {
05750                             got=true;
05751                             break;
05752                         }
05753 
05754                     /*if(!got && chan.length()>0 && chan[0]!='#' && chan[0]!='&' && chan[0]!='+' && chan[0]!='!')
05755                         got=true; // it is just a "437 nick teporarily unavailable" (not channel)
05756                         */
05757                     string chantypes;
05758                     map<string,string>::iterator iii;
05759                     for(iii=irc_isupport.raw.begin(); iii!=irc_isupport.raw.end(); iii++)
05760                         if(!(*iii).first.compare("CHANTYPES")) {
05761                             chantypes=(*iii).second;
05762                             break;
05763                         }
05764                     if(!got && chan.length()>0 && chantypes.find(chan[0])==-1)
05765                         got=true; // it is just a "437 nick teporarily unavailable" (not channel)
05766 
05767                     if(!got)
05768                         irc_cannot_join_channels.push_back(chan);
05769 
05770                     vector<s_online_channel>::iterator i;
05771                     for(i=irc_channels.begin(); i!=irc_channels.end(); i++)
05772                         if(!cmp_strings_case_insensitive((*i).name,chan)) {
05773                             irc_channels.erase(i);
05774                             break;
05775                         }
05776 
05777                     irc_kill_last_msg_wait(resp);
05778                 }
05779 
05780                 //IRC IN  :irc.server.com 442 BOT #channel :You're not on that channel
05781                 if(len>4 && str[0]=='4' && str[1]=='4' && str[2]=='2' && str[3]==' ') {
05782                     irc_kill_command_wait("MODE");
05783                     irc_kill_command_wait("TOPIC");
05784 
05785                     irc_kill_last_msg_wait(resp);
05786                 }
05787 
05788                 // IRC IN  :irc.server.com 324 BOT #channel +nt
05789                 // channel mode after JOIN
05790                 if(len>4 && str[0]=='3' && str[1]=='2' && str[2]=='4' && str[3]==' ') {
05791                     irc_RPL_324(str);
05792 
05793                     if(str.find(" ",0)!=string::npos)
05794                         str.erase(0,str.find(" ")+1); // erase everything before and inclusive trailing SPACE - numeric reply
05795                     if(str.find(" ",0)!=string::npos)
05796                         str.erase(0,str.find(" ")+1); // erase everything before SPACE inclusive - my nick
05797                     string chan;
05798                     if(str.find(" ",0)!=string::npos)
05799                         while(str.length() && str[0]!=0x20) {
05800                             chan+=str[0];
05801                             str.erase(0,1);
05802                         }
05803                     str.erase(0,1); // erase space
05804                     if(str.length() && str[0]=='+')
05805                         str.erase(0,1); // erase leading '+'
05806                     if(str.find(" ",0)!=string::npos)
05807                         str.erase(str.find(" ",0),str.length()-str.find(" ",0)); // erase everything after SAPCE inclusive (possibly the topic)
05808                     // in "str" we have channel modes now
05809                     vector<s_online_channel>::iterator i;
05810                     for(i=irc_channels.begin(); i!=irc_channels.end(); i++) {
05811                         if(cmp_strings_case_insensitive((*i).name,chan))
05812                             continue;
05813                         (*i).modes=str;
05814                         break;
05815                     }
05816                     irc_kill_last_msg_wait(resp);
05817 
05818                     irc_kill_command_wait("MODE");
05819                 }
05820                 str=tmp;
05821 
05822                 // IRC IN  :irc.server.com 332 BOT #channel :topic
05823                 // topic after join
05824                 if(len>4 && str[0]=='3' && str[1]=='3' && str[2]=='2' && str[3]==' ') {
05825                     irc_kill_command_wait("TOPIC");
05826 
05827                     if(str.find(" ",0)!=string::npos)
05828                         str.erase(0,str.find(" ")+1); // erase everything before and inclusive trailing SPACE - numeric reply
05829                     if(str.find(" ",0)!=string::npos)
05830                         str.erase(0,str.find(" ")+1); // erase everything before SPACE inclusive - my nick
05831                     string chan;
05832                     if(str.find(" ",0)!=string::npos)
05833                         while(str.length() && str[0]!=0x20) {
05834                             chan+=str[0];
05835                             str.erase(0,1);
05836                         }
05837                     str.erase(0,1); // erase space
05838 
05839                     if(str.find(":",0)!=string::npos)
05840                         str.erase(0,str.find(":")+1); // erase everything before ':' inclusive
05841 
05842                     // in str we have topic
05843                     vector<s_online_channel>::iterator i;
05844                     for(i=irc_channels.begin(); i!=irc_channels.end(); i++) {
05845                         if(cmp_strings_case_insensitive((*i).name,chan))
05846                             continue;
05847                         (*i).topic=str;
05848                         break;
05849                     }
05850                     irc_kill_last_msg_wait(resp);
05851 
05852                     irc_kill_command_wait("TOPIC");
05853                 }
05854                 str=tmp;
05855 
05856                 // IRC IN  :irc.server.com 331 BOT #channel :No topic is set.
05857                 // NO topic after join
05858                 if(len>4 && str[0]=='3' && str[1]=='3' && str[2]=='1' && str[3]==' ') {
05859                     irc_kill_command_wait("TOPIC");
05860 
05861                     if(str.find(" ",0)!=string::npos)
05862                         str.erase(0,str.find(" ")+1); // erase everything before and inclusive trailing SPACE - numeric reply
05863                     if(str.find(" ",0)!=string::npos)
05864                         str.erase(0,str.find(" ")+1); // erase everything before SPACE inclusive - my nick
05865                     string chan;
05866                     if(str.find(" ",0)!=string::npos)
05867                         while(str.length() && str[0]!=0x20) {
05868                             chan+=str[0];
05869                             str.erase(0,1);
05870                         }
05871                     str.erase(0,1); // erase space
05872 
05873                     if(str.find(":",0)!=string::npos)
05874                         str.erase(0,str.find(":")+1); // erase everything before ':' inclusive
05875 
05876                     vector<s_online_channel>::iterator i;
05877                     for(i=irc_channels.begin(); i!=irc_channels.end(); i++) {
05878                         if(cmp_strings_case_insensitive((*i).name,chan))
05879                             continue;
05880                         (*i).topic="";
05881                         break;
05882                     }
05883                     irc_kill_last_msg_wait(resp);
05884 
05885                     irc_kill_command_wait("TOPIC");
05886                 }
05887                 str=tmp;
05888 
05889                 if(len>4 && str[0]=='M' && str[1]=='O' && str[2]=='D' && str[3]=='E') {
05890                     if(!nick.empty()) {
05891                         string tmp=nick;
05892                         tmp+="!";
05893                         tmp+=ident;
05894                         tmp+="@";
05895                         tmp+=host;
05896                         irc_check_flood(TYPE_MODE,channel,tmp,whom);
05897                     }
05898 
05899                     if(!channel.length()) {
05900                         whom=str;
05901                         if(whom.find(":",0)!=string::npos)
05902                             whom.erase(0,whom.find(":",0)+1);
05903                     }
05904                     log_channel(channel.c_str(),TYPE_MODE,hm.c_str(),"",whom.c_str(),irc_get_modes_for_log(channel,nick).c_str());
05905 
05906                     if(irc_check_last_msg("MODE"))
05907                         irc_kill_last_msg_wait(resp);
05908 
05909                     irc_kill_command_wait("MODE");
05910 
05911                     irc_RPL_MODE(resp);
05912                 }
05913 
05914                 if(len>4 && str[0]=='T' && str[1]=='O' && str[2]=='P' && str[3]=='I' && str[4]=='C') {
05915                     if(!nick.empty()) {
05916                         string tmp=nick;
05917                         tmp+="!";
05918                         tmp+=ident;
05919                         tmp+="@";
05920                         tmp+=host;
05921                         irc_check_flood(TYPE_MODE,channel,tmp,topic);
05922                     }
05923 
05924                     vector<s_online_channel>::iterator i;
05925                     for(i=irc_channels.begin(); i!=irc_channels.end(); i++) {
05926                         if(cmp_strings_case_insensitive((*i).name,channel))
05927                             continue;
05928                         (*i).topic=topic;
05929                         break;
05930                     }
05931 
05932                     log_channel(channel.c_str(),TYPE_TOPIC,hm.c_str(),"TOPIC",topic.c_str(),irc_get_modes_for_log(channel,nick).c_str());
05933 
05934                     if(irc_check_last_msg("TOPIC"))
05935                         irc_kill_last_msg_wait(resp);
05936 
05937                     irc_kill_command_wait("TOPIC");
05938 
05939                     irc_RPL_TOPIC(resp);
05940                 }
05941 
05942                 // 472: unknown mode
05943                 if(len>4 && str[0]=='4' && str[1]=='7' && str[2]=='2' && str[3]==' ') {
05944                     if(irc_check_last_msg("MODE"))
05945                         irc_kill_last_msg_wait(resp);
05946 
05947                     irc_kill_command_wait("MODE");
05948 
05949                     // assume that error is on MODE #chan +e (some irc networks doesn't support +e exceptions to bans)
05950                     vector<s_online_channel>::iterator i;
05951                     for(i=irc_channels.begin(); i!=irc_channels.end(); i++) {
05952                         (*i).got_excepts=true;
05953                         irc_check_bans((*i).name);
05954                     }
05955 
05956                     // assume that error is on MODE #chan +I (some irc networks doesn't support +I invitations)
05957                     //vector<s_online_channel>::iterator i;
05958                     for(i=irc_channels.begin(); i!=irc_channels.end(); i++) {
05959                         (*i).got_invites=true;
05960                         //irc_check_invites((*i).name);
05961                     }
05962 
05963                     //vector<s_online_channel>::iterator i;
05964                     for(i=irc_channels.begin(); i!=irc_channels.end(); i++) {
05965                         (*i).got_reops=true;
05966                     }
05967 
05968                     s_online_channel* chan;
05969                     if(irc_get_online_channel(channel,chan)) {
05970                         if(!chan->b_excepts_sent && irc_isupport.chanmodes_a.find("e")!=string::npos) {
05971                             chan->b_excepts_sent=true;
05972                             string excepts="MODE ";
05973                             excepts+=channel;
05974                             excepts+=" +e";
05975                             irc_putserv(excepts.c_str(),true,HIGH_PRIORITY);
05976                         }
05977     
05978                         if(!chan->b_bans_sent && irc_isupport.chanmodes_a.find("b")!=string::npos) {
05979                             chan->b_bans_sent=true;
05980                             string bans="MODE ";
05981                             bans+=channel;
05982                             bans+=" +b";
05983                             irc_putserv(bans.c_str(),true,HIGH_PRIORITY);
05984                         }
05985                     }
05986 
05987                     irc_end_of_excepted(resp);
05988                 }
05989 
05990                 // 475: cannot join channel (+k)
05991                 if(len>4 && str[0]=='4' && str[1]=='7' && str[2]=='5' && str[3]==' ') {
05992                     irc_kill_command_wait("JOIN");
05993                     irc_kill_command_wait("MODE");
05994                     irc_kill_command_wait("TOPIC");
05995 
05996                     string s=str;
05997                     int i1=0;
05998                     while(i1<2 && s.length()>0) {
05999                         if(s[0]==0x20)
06000                             i1++;
06001                         s.erase(0,1);
06002                     }
06003                     string chan;
06004                     while(s.length()>0 && s[0]!=0x20) {
06005                         chan+=s[0];
06006                         s.erase(0,1);
06007                     }
06008 
06009                     bool got=false;
06010 label_a:
06011                     vector<s_key_chan>::iterator i2;
06012                     for(i2=irc_key_chans.begin(); i2!=irc_key_chans.end(); i2++) {
06013                         if(!cmp_strings_case_insensitive((*i2).channel_name,chan)) {
06014                             if((*i2).keys.begin()==(*i2).keys.end()) {
06015                                 // :-(
06016                                 string log="Cannot join channel ";
06017                                 log+=chan;
06018                                 log+=" because it is +k, and I have tried all keys that I have in the history. Next retry is scheduled.";
06019                                 log_bot(log.c_str());
06020                                 irc_key_chans.erase(i2);
06021 
06022                                 {
06023                                     bool got=false;
06024                                     vector<string>::iterator ii;
06025                                     for(ii=irc_cannot_join_channels.begin(); ii!=irc_cannot_join_channels.end(); ii++)
06026                                         if(!chan.compare(*ii)) {
06027                                             got=true;
06028                                         }
06029                                     if(!got)
06030                                         irc_cannot_join_channels.push_back(chan);
06031                                 }
06032 
06033                                 got=true;
06034                                 break;
06035                             }
06036                             string key=*((*i2).keys.begin());
06037                             (*i2).keys.erase((*i2).keys.begin());
06038 
06039                             string msg="JOIN ";
06040                             msg+=chan;
06041                             msg+=" ";
06042                             msg+=key;
06043                             irc_putserv(msg.c_str(),true,HIGH_PRIORITY);
06044                             msg="MODE ";
06045                             msg+=chan;
06046                             irc_putserv(msg.c_str(),true,HIGH_PRIORITY);
06047                             msg="TOPIC ";
06048                             msg+=chan;
06049                             irc_putserv(msg.c_str(),true,HIGH_PRIORITY);
06050                             msg="WHOIS ";
06051                             msg+=irc_nick;
06052                             irc_putserv(msg.c_str(),true,HIGH_PRIORITY);
06053 
06054                             irc_kill_last_msg_wait(resp);
06055 
06056                             got=true;
06057                         }
06058                     }
06059                     if(!got) {
06060                         s_key_chan kch;
06061                         kch.channel_name=chan;
06062                         kch.keys.clear();
06063                         vector<s_channel_def>::iterator i2;
06064                         for(i2=r_channel_defs.begin(); i2!=r_channel_defs.end(); i2++)
06065                             if(!cmp_strings_case_insensitive((*i2).channel_name,chan)) {
06066                                 vector<string>::iterator i3;
06067                                 for(i3=(*i2).keys.begin(); i3!=(*i2).keys.end(); i3++)
06068                                     kch.keys.push_back(*i3);
06069                                 irc_key_chans.push_back(kch);
06070                             }
06071                         got=true; // for case that we don't have a channel definition
06072                         goto label_a;
06073                     }
06074                 }
06075 
06076                 // 348: exceptions
06077                 if(len>4 && str[0]=='3' && str[1]=='4' && str[2]=='8' && str[3]==' ') {
06078                     if(irc_check_last_msg("MODE"))
06079                         irc_kill_last_msg_wait(resp);
06080                     irc_excepted(resp);
06081                 }
06082 
06083                 // 349: end of exceptions
06084                 if(len>4 && str[0]=='3' && str[1]=='4' && str[2]=='9' && str[3]==' ') {
06085                     if(irc_check_last_msg("MODE"))
06086                         irc_kill_last_msg_wait(resp);
06087                     irc_kill_command_wait("MODE");
06088                     irc_end_of_excepted(resp);
06089                 }
06090 
06091                 // 367: ban list
06092                 if(len>4 && str[0]=='3' && str[1]=='6' && str[2]=='7' && str[3]==' ') {
06093                     irc_banned(resp);
06094                 }
06095 
06096                 // 368: end of +b list
06097                 if(len>4 && str[0]=='3' && str[1]=='6' && str[2]=='8' && str[3]==' ') {
06098                     if(irc_check_last_msg("MODE"))
06099                         irc_kill_last_msg_wait(resp);
06100                     irc_kill_command_wait("MODE");
06101                 }
06102 
06103                 // 346: invited
06104                 if(len>4 && str[0]=='3' && str[1]=='4' && str[2]=='6' && str[3]==' ') {
06105                     irc_invited(resp);
06106                 }
06107 
06108                 // 347: end of +I list
06109                 if(len>4 && str[0]=='3' && str[1]=='4' && str[2]=='7' && str[3]==' ') {
06110                     if(irc_check_last_msg("MODE"))
06111                         irc_kill_last_msg_wait(resp);
06112                     irc_kill_command_wait("MODE");
06113 
06114                     string s=str;
06115                     string channel;
06116                     int pos=0;
06117                     for(unsigned int i1=0; i1<len; i1++) {
06118                         if(str[i1]==0x20) {
06119                             pos++;
06120                             continue;
06121                         }
06122                         if(pos==2)
06123                             channel+=str[i1];
06124                         if(pos>2)
06125                             break;
06126                     }
06127                     irc_check_for_not_invited(channel);
06128 
06129                     s_online_channel* chan;
06130                     if(irc_get_online_channel(channel,chan)) {
06131                         if(!chan->b_excepts_sent && irc_isupport.chanmodes_a.find("e")!=string::npos) {
06132                             chan->b_excepts_sent=true;
06133                             string excepts="MODE ";
06134                             excepts+=channel;
06135                             excepts+=" +e";
06136                             irc_putserv(excepts.c_str(),true,HIGH_PRIORITY);
06137                         }
06138                     }
06139                 }
06140 
06141                 // 344: in reop list +R
06142                 if(len>4 && str[0]=='3' && str[1]=='4' && str[2]=='4' && str[3]==' ') {
06143                     irc_in_reop(resp);
06144                 }
06145 
06146                 // 345: end of +R list
06147                 if(len>4 && str[0]=='3' && str[1]=='4' && str[2]=='5' && str[3]==' ') {
06148                     if(irc_check_last_msg("MODE"))
06149                         irc_kill_last_msg_wait(resp);
06150                     irc_kill_command_wait("MODE");
06151 
06152                     string s=str;
06153                     string channel;
06154                     int pos=0;
06155                     for(unsigned int i1=0; i1<len; i1++) {
06156                         if(str[i1]==0x20) {
06157                             pos++;
06158                             continue;
06159                         }
06160                         if(pos==2)
06161                             channel+=str[i1];
06162                         if(pos>2)
06163                             break;
06164                     }
06165                     irc_check_for_not_reopped(channel);
06166                 }
06167 
06168                 // :%s 042 %s %s :your unique ID
06169                 if(len>4 && str[0]=='0' && str[1]=='4' && str[2]=='2' && str[3]==' ') {
06170                     irc_RPL_YOURID(resp);
06171                 }
06172 
06173                 // :%s 043 %s %s :nickname collision, forcing nick change to your unique ID.
06174                 if(len>4 && str[0]=='0' && str[1]=='4' && str[2]=='3' && str[3]==' ') {
06175                     static bool got=false;
06176                     if(!got) {
06177                         got=true;
06178                         
06179                         nick=irc_nick;
06180                         ident=irc_get_ident(nick);
06181                         host=irc_get_host(nick);
06182                         msg=irc_unique_id;
06183                         logic_fnc(nick,irc_unique_id);
06184                         goto forced_nick_change;
06185                     } else
06186                         got=false;
06187                 }
06188 
06189                 // 482: you are not a channel operator
06190                 if(len>4 && str[0]=='4' && str[1]=='8' && str[2]=='2' && str[3]==' ') {
06191                     if(irc_check_last_msg("MODE"))
06192                         irc_kill_last_msg_wait(resp);
06193                     irc_kill_command_wait("MODE");
06194 
06195                     if(irc_check_last_msg("KICK"))
06196                         irc_kill_last_msg_wait(resp);
06197                     irc_kill_command_wait("KICK");
06198                 }
06199 
06200                 if(last_msg.wait_for_response && last_msg.timestamp+20<time(NULL))
06201                     irc_kill_last_msg_wait(resp);
06202             }
06203         }
06204 
06205         l2:
06206 
06207         memset(last_msg.response,0,sizeof(last_msg.response));
06208         strncpy(last_msg.response,*i,sizeof(last_msg.response)-1);
06209 
06210         delete[] (*i);
06211 
06212         msgs_from_server.pop_front();
06213 
06214         //goto l1;
06215     }
06216 
06217     dcc_loop();
06218 
06219     return 0;
06220 }

Here is the call graph for this function:

bool irc_loop_putserv  ) 
 

This function should be called in a loop to process send and receive to/from server.

Author:
VooDooMan
Version:
1
Date:
2004
Returns:
Returns true if socket I/O error occured

Definition at line 633 of file irc.cpp.

References s_flood_history::bytes, s_socket::clear(), s_socket::cmp(), cmp_strings_case_insensitive(), conf_getvar(), filesys_last_notify, filesys_notify_interval, flood_history, flood_history_other, s_msg_to_server::flood_protection, HIGH_PRIORITY, irc_bot_flood_bytes, irc_bot_flood_lines, irc_bot_flood_other_seconds, irc_bot_flood_seconds, irc_cannot_join_channels, irc_channels, irc_check_for_filesystem(), irc_disconnect(), irc_keepalive_sent, irc_last_join_try, irc_last_keepalive_detection, IRC_MSG_TOO_LONG, irc_nick, irc_putserv(), irc_putserv_immediately(), irc_remove_redundant_mode2(), log_debug(), log_socket(), logic_exec_from_work(), ltoa(), s_005::max_modes, mode_queue, s_flood_history::msg, s_msg_to_server::msg, msgs_from_server, msgs_to_server, msgs_to_server2, s_msg_to_server::response, sock_close(), sock_error(), sock_read(), SOCK_SEND_ERROR, stats_irc_bytes_received(), s_flood_history::time, s_msg_to_server::timestamp, s_msg_to_server::wait_for_response, and waiting_for_response.

Referenced by logic_exec(), and main().

00634 {
00635     if(!irc_socket.cmp())
00636         return true;
00637 
00638     if(irc_last_keepalive_detection+60*3<time(NULL) && irc_keepalive_sent) {
00639         irc_last_keepalive_detection=time(NULL);
00640         irc_keepalive_sent=false;
00641         irc_disconnect();
00642         logic_exec_from_work();
00643         return false;
00644     }
00645     if(irc_last_join_try+15<time(NULL)) {
00646         time(&irc_last_join_try);
00647         vector<string>::iterator i1;
00648     erase_again:
00649         for(i1=irc_cannot_join_channels.begin(); i1!=irc_cannot_join_channels.end(); i1++) {
00650             vector<s_online_channel>::iterator i;
00651             for(i=irc_channels.begin(); i!=irc_channels.end(); i++)
00652                 if(!cmp_strings_case_insensitive((*i).name,*i1)) {
00653                     irc_cannot_join_channels.erase(i1);
00654                     goto erase_again;
00655                 }
00656 
00657             string msg="JOIN ";
00658             msg+=*i1;
00659             irc_putserv(msg.c_str(),true,HIGH_PRIORITY);
00660             msg="MODE ";
00661             msg+=*i1;
00662             irc_putserv(msg.c_str(),true,HIGH_PRIORITY);
00663             msg="TOPIC ";
00664             msg+=*i1;
00665             irc_putserv(msg.c_str(),true,HIGH_PRIORITY);
00666             msg="WHOIS ";
00667             msg+=irc_nick;
00668             irc_putserv(msg.c_str(),true,HIGH_PRIORITY);
00669         }
00670     }
00671 
00672     int compress_mode_wait=atol(conf_getvar("compress_mode_wait").c_str());
00673     if(compress_mode_wait>0) {
00674         time_t now=time(NULL);
00675         list<s_mode_queue_entry> wait_elapsed;
00676         wait_elapsed.clear();
00677     again:
00678         list<s_mode_queue_entry>::iterator i1;
00679         for(i1=mode_queue.begin(); i1!=mode_queue.end(); i1++) {
00680             if((*i1).submit+compress_mode_wait<now) {
00681                 wait_elapsed.push_back(*i1);
00682                 mode_queue.erase(i1);
00683                 goto again;
00684             }
00685         }
00686         string chan="";
00687         list<s_mode_queue_entry> single_channel;
00688         single_channel.clear();
00689     again2:
00690         for(i1=wait_elapsed.begin(); i1!=wait_elapsed.end(); i1++) {
00691             if(chan.empty()) {
00692                 chan=(*i1).channel;
00693                 single_channel.clear();
00694                 single_channel.push_back(*i1);
00695                 wait_elapsed.erase(i1);
00696                 goto again2;
00697             }
00698             if(!cmp_strings_case_insensitive((*i1).channel,chan)) {
00699                 single_channel.push_back(*i1);
00700                 wait_elapsed.erase(i1);
00701                 goto again2;
00702             }
00703         }
00704         {
00705             list<s_mode_queue_entry>::iterator i2;
00706             string cumulative1="MODE "; // chars
00707             cumulative1+=chan;
00708             cumulative1+=" ";
00709             string cumulative2=""; // params
00710             int cum_num=0;
00711         again3:
00712             if(cum_num==irc_isupport.max_modes) {
00713             jump_1:
00714                 if(cumulative2.length() && cumulative2[cumulative2.length()-1]==0x20)
00715                     cumulative2.erase(cumulative2.length()-1,1);
00716                 if(!cumulative2.empty()) {
00717                     cumulative1+=" ";
00718                     cumulative1+=cumulative2;
00719                 }
00720 
00721                 s_msg_to_server m;
00722 
00723                 size_t end;
00724                 m.msg=new char[end=(cumulative1.length()+2+1)]; // +2 == CR/LF
00725                 strcpy(m.msg,cumulative1.c_str());
00726                 m.msg[end-2-1+0]=0x0D;
00727                 m.msg[end-2-1+1]=0x0A;
00728                 m.msg[end-2-1+2]=0;
00729 
00730                 m.flood_protection=false;
00731 
00732                 m.wait_for_response=false;
00733                 if(m.wait_for_response)
00734                     m.response[0]=0;
00735 
00736                 msgs_to_server.push_back(m);
00737 
00738                 cumulative1="MODE "; // chars
00739                 cumulative1+=chan;
00740                 cumulative1+=" ";
00741                 cumulative2="";
00742 
00743                 cum_num=0;
00744             }
00745             for(i2=single_channel.begin(); i2!=single_channel.end(); i2++) {
00746                 if(cum_num<irc_isupport.max_modes) {
00747                     cum_num++;
00748                     cumulative1+=(*i2).mode;
00749                     if(!(*i2).param.empty()) {
00750                         cumulative2+=(*i2).param;
00751                         cumulative2+=" ";
00752                     }
00753                     single_channel.erase(i2);
00754                     goto again3;
00755                 } else
00756                     break;
00757             }
00758             if(cum_num>0)
00759                 goto jump_1;
00760         }
00761         if(!wait_elapsed.empty()) {
00762             chan="";
00763             single_channel.clear();
00764             goto again2;
00765         }
00766     }
00767 
00768     irc_remove_redundant_mode2();
00769 
00770     char* buff2=new char[10240];
00771     int buff2_pos=0;
00772     for(;;) {
00773         char buff[1024];
00774         int ec=0;
00775         bool closed;
00776         size_t size=sock_read(irc_socket,buff,sizeof(buff),ec,closed);
00777         if(closed) {
00778             if(msgs_from_server.empty())
00779                 return true;
00780         }
00781 
00782         if(ec) {
00783             log_socket(ec,sock_error(ec),"while reading from the socket, in file " __FILE__ " in function " __FUNC__);
00784             if(msgs_from_server.empty())
00785                 return true;
00786         }
00787 
00788         if(!size)
00789             break;
00790 
00791         stats_irc_bytes_received(size);
00792 
00793         irc_last_keepalive_detection=time(NULL);
00794         irc_keepalive_sent=false;
00795 
00796         for(size_t i1=0; i1<size; i1++) {
00797             if(buff[i1]==0 || buff[i1]=='\r' || buff[i1]=='\n') {
00798 l2:
00799                 if((buff2_pos==1 && (buff2[0]==0 || buff2[0]=='\r' || buff2[0]=='\n')) || buff2_pos==0)
00800                     buff2_pos=0;
00801                     else {
00802                         buff2[buff2_pos++]=0;
00803                         char* tmp=new char[buff2_pos+16];
00804                         strcpy(tmp,buff2);
00805                         msgs_from_server.push_back(tmp);
00806                         buff2_pos=0;
00807                     }
00808             } else {
00809                 if(buff2_pos>=10240-16) {
00810                     log_debug("one line from IRC server exceeded about 10 KB, in file " __FILE__ " in function " __FUNC__);
00811                     goto l2;
00812                 }
00813                 buff2[buff2_pos++]=buff[i1];
00814             }
00815         }
00816     }
00817     delete[] buff2;
00818     buff2=NULL;
00819 
00820     if(irc_last_keepalive_detection+30<time(NULL) && !irc_keepalive_sent) {
00821         irc_keepalive_sent=true;
00822         string ping="PING :";
00823         char tmp[64];
00824         ltoa((long)time(NULL),tmp,10);
00825         ping+=tmp;
00826         irc_putserv(ping.c_str(),true,HIGH_PRIORITY);
00827     }
00828 
00829     //---
00830     if(last_msg.timestamp+20<time(NULL))
00831         last_msg.wait_for_response=false;
00832 
00833     if(last_msg.wait_for_response && last_msg.response[0]==0)
00834         return false; // still waiting
00835 
00836     if(last_msg.msg) {
00837         delete[] last_msg.msg;
00838         last_msg.msg=NULL;
00839     }
00840     //---
00841 
00842     {
00843         vector<s_awaiting_response>::iterator i1;
00844 _again:
00845         for(i1=waiting_for_response.begin(); i1!=waiting_for_response.end(); i1++) {
00846             if((*i1).time+20<time(NULL)) {
00847                 string msg="Timeout while waiting for response to command: ";
00848                 msg+=(*i1).message;
00849 
00850                 while(msg.length() && msg[msg.length()-1]=='\r')
00851                     msg.erase(msg.length()-1,1);
00852                 while(msg.length() && msg[msg.length()-1]=='\n')
00853                     msg.erase(msg.length()-1,1);
00854                 while(msg.length() && msg[msg.length()-1]=='\r')
00855                     msg.erase(msg.length()-1,1);
00856                 while(msg.length() && msg[msg.length()-1]=='\n')
00857                     msg.erase(msg.length()-1,1);
00858 
00859                 log_debug(msg.c_str());
00860 
00861                 waiting_for_response.erase(i1);
00862                 goto _again;
00863             }
00864         }
00865 
00866         if(waiting_for_response.begin()!=waiting_for_response.end())
00867             return false; // still waiting
00868     }
00869 
00870     //---
00871 
00872     /*time_t now=time(NULL);
00873 
00874     list<s_flood_history>::iterator i;
00875 l1:
00876     for(i=flood_history.begin(); i!=flood_history.end(); i++) {
00877         bool del=false;
00878         if((*i).time>now) // for case of changing system time
00879             del=true;
00880             else
00881             if(((unsigned)now-(*i).time)>irc_bot_flood_seconds)
00882                 del=true;
00883 
00884         if(del) {
00885             flood_history.erase(i);
00886             goto l1;
00887         }
00888     }*/
00889 
00890     size_t bytes=0;
00891     list<s_flood_history>::iterator i;
00892     for(i=flood_history.begin(); i!=flood_history.end(); i++)
00893         bytes+=(*i).bytes;
00894 
00895     size_t all_1=0, all_2=0;
00896     size_t cnt=0;
00897     size_t cnt2=0;
00898     {
00899         list<s_flood_history>::iterator i2;
00900 fl_again1:
00901         for(i2=flood_history.begin(); i2!=flood_history.end(); i2++) {
00902             if((*i2).time+irc_bot_flood_seconds<time(NULL)) {
00903                 flood_history.erase(i2);
00904                 goto fl_again1;
00905             }
00906             all_1+=(*i2).msg.length();
00907             cnt++;
00908         }
00909     }
00910     {
00911         list<s_flood_history>::iterator i2;
00912 fl_again2:
00913         for(i2=flood_history_other.begin(); i2!=flood_history_other.end(); i2++) {
00914             if((*i2).time+irc_bot_flood_other_seconds<time(NULL)) {
00915                 flood_history_other.erase(i2);
00916                 goto fl_again2;
00917             }
00918             all_2+=(*i2).msg.length();
00919             cnt2++;
00920         }
00921     }
00922 
00923     for(;;) {
00924         list<s_msg_to_server>::iterator ii;
00925 
00926         int queue_num=1;
00927 
00928         ii=msgs_to_server.begin();
00929         if(ii==msgs_to_server.end()) {
00930             ii=msgs_to_server2.begin();
00931             if(ii==msgs_to_server2.end())
00932                 break;
00933             queue_num=2;
00934         }
00935 
00936         if(((queue_num==1?all_1:all_1+all_2)<irc_bot_flood_bytes && ((queue_num==1)?cnt<irc_bot_flood_lines:cnt2<1)) && (*ii).flood_protection) {
00937             bytes+=strlen((*ii).msg);
00938 
00939             bool wait_for_response=(*ii).wait_for_response;
00940             if(wait_for_response) {
00941                 last_msg=*ii;
00942                 last_msg.timestamp=time(NULL);
00943             }
00944             // no flood should occur
00945             char* msg=(*ii).msg;
00946             int error=irc_putserv_immediately(irc_socket,msg,wait_for_response);
00947 
00948             if(error==IRC_MSG_TOO_LONG) {
00949                 log_debug("IRC_MSG_TOO_LONG error #1, in file " __FILE__ " in function " __FUNC__);
00950             }
00951 
00952             if(error==SOCK_SEND_ERROR) {
00953                 msgs_to_server.clear();
00954                 flood_history.clear();
00955 
00956                 sock_close(irc_socket);
00957                 irc_socket.clear();
00958 
00959                 log_socket(0,"(socket closed)","in file " __FILE__ " in function " __FUNC__);
00960 
00961                 return true;
00962             }
00963 
00964             bytes+=strlen(msg);
00965 
00966             if((*ii).flood_protection) {
00967                 s_flood_history entry;
00968                 entry.bytes=strlen(msg);
00969                 entry.msg=msg;
00970                 time(&entry.time);
00971                 flood_history.push_back(entry);
00972             } else {
00973                 s_flood_history entry;
00974                 entry.bytes=strlen(msg);
00975                 entry.msg=msg;
00976                 time(&entry.time);
00977                 flood_history_other.push_back(entry);
00978             }
00979             if(queue_num==1)
00980                 msgs_to_server.pop_front();
00981             if(queue_num==2)
00982                 msgs_to_server2.pop_front();
00983 
00984             if(wait_for_response)
00985                 break;
00986         } else {
00987             if(((queue_num==1?all_1:all_1+all_2)<irc_bot_flood_bytes && ((queue_num==1)?cnt<irc_bot_flood_lines:cnt2<1)) && !(*ii).flood_protection) {
00988 
00989                 bytes+=strlen((*ii).msg);
00990 
00991                 bool wait_for_response=(*ii).wait_for_response;
00992                 if(wait_for_response) {
00993                     last_msg=*ii;
00994                     last_msg.timestamp=time(NULL);
00995                 }
00996                 // no flood should occur
00997                 char* msg=(*ii).msg;
00998                 int error=irc_putserv_immediately(irc_socket,msg,wait_for_response);
00999 
01000                 if(error==IRC_MSG_TOO_LONG) {
01001                     log_debug("IRC_MSG_TOO_LONG error #1, in file " __FILE__ " in function " __FUNC__);
01002                 }
01003 
01004                 if(error==SOCK_SEND_ERROR) {
01005                     msgs_to_server.clear();
01006                     flood_history.clear();
01007 
01008                     sock_close(irc_socket);
01009                     irc_socket.clear();
01010 
01011                     log_socket(0,"(socket closed)","in file " __FILE__ " in function " __FUNC__);
01012     
01013                     return true;
01014                 }
01015     
01016                 bytes+=strlen(msg);
01017     
01018                 if((*ii).flood_protection) {
01019                     s_flood_history entry;
01020                     entry.bytes=strlen(msg);
01021                     entry.msg=msg;
01022                     time(&entry.time);
01023                     flood_history.push_back(entry);
01024                 } else {
01025                     s_flood_history entry;
01026                     entry.bytes=strlen(msg);
01027                     entry.msg=msg;
01028                     time(&entry.time);
01029                     flood_history_other.push_back(entry);
01030                 }
01031 
01032                 if(queue_num==1)
01033                     msgs_to_server.pop_front();
01034                 if(queue_num==2)
01035                     msgs_to_server2.pop_front();
01036 
01037                 if(wait_for_response)
01038                     break;
01039             }
01040         }
01041         break;
01042     }
01043 
01044     // notify for files on the filesystem
01045     if(filesys_notify_interval==0) {
01046         filesys_notify_interval=atol(conf_getvar("notify_interval").c_str())*60;
01047         if(filesys_notify_interval==0)
01048             filesys_notify_interval=5*60;
01049     }
01050     if(filesys_last_notify+filesys_notify_interval<=time(NULL)) {
01051         if(filesys_last_notify==0) {
01052             time(&filesys_last_notify);
01053             filesys_last_notify-=filesys_notify_interval;
01054             filesys_last_notify+=20;
01055         } else {
01056             time(&filesys_last_notify);
01057             vector<s_online_channel>::iterator i1;
01058             for(i1=irc_channels.begin(); i1!=irc_channels.end(); i1++) {
01059                 vector<s_online_user>::iterator i2;
01060                 for(i2=(*i1).users.begin(); i2!=(*i1).users.end(); i2++)
01061                     irc_check_for_filesystem((*i2).in_logic_as,(*i1).name,(*i2).nick);
01062             }
01063         }
01064     }
01065 
01066     return false;
01067 }

Here is the call graph for this function:

bool irc_notice const char *  target,
const char *  msg,
int  priority
 

Sends NOTICE to user/channel.

Author:
VooDooMan
Version:
1
Date:
2004
Parameters:
target Nick name / channel name of target
msg Whole message
priority Priority class (LOW_PRIORITY, HIGH_PRIORITY, or CRITICAL_PRIORITY)
Returns:
Returns false if socket I/O error occured

Definition at line 6497 of file irc.cpp.

References irc_putserv().

Referenced by logic_exec().

06498 {
06499     if(strlen(target)>128)
06500         return false;
06501     if(strlen(msg)>512-1)
06502         return false;
06503 
06504     char tmp[4096];
06505     strcpy(tmp,"NOTICE ");
06506     strcat(tmp,target);
06507     strcat(tmp," :");
06508     strcat(tmp,msg);
06509 
06510     return irc_putserv(tmp,false,priority);
06511 }

Here is the call graph for this function:

bool irc_op const char *  channel,
const char *  nick,
int  priority
 

Sets +o (chan op) status to nick on channel.

Author:
VooDooMan
Version:
1
Date:
2004
Parameters:
channel Channel name
nick Nick name
priority Priority class (LOW_PRIORITY, HIGH_PRIORITY, or CRITICAL_PRIORITY)
Returns:
Returns false if socket I/O error occured

Definition at line 6265 of file irc.cpp.

References irc_internal_set_mode(), and irc_putserv().

Referenced by irc_RPL_WHOISUSER(), and logic_exec().

06266 {
06267     if(strlen(channel)>128)
06268         return false;
06269     if(strlen(nick)>128)
06270         return false;
06271 
06272     irc_internal_set_mode(channel,nick,'+','@');
06273 
06274     char msg[4096];
06275     strcpy(msg,"MODE ");
06276     strcat(msg,channel);
06277     strcat(msg," +o ");
06278     strcat(msg,nick);
06279 
06280     return irc_putserv(msg,true,priority);
06281 }

Here is the call graph for this function:

void irc_parse_modes string  modes,
map< char, string > &  with_param,
string &  plain
 

Parses a channel mode.

Author:
VooDooMan
Version:
1
Date:
2005
Parameters:
modes String with modes
with_param Returns map of modes with parameter (e.g. "k" -> "channel key")
plain Returns string of modes without parameter (e.g. "nt")

Definition at line 438 of file irc.cpp.

References s_005::chanmodes_a, s_005::chanmodes_b, s_005::chanmodes_c, and s_005::chanmodes_d.

00439 {
00440     with_param.clear();
00441     plain="";
00442 
00443     unsigned int i1=0;
00444     unsigned int i2=0;
00445     for(i2=0; i2<modes.length(); i2++) {
00446         if(modes[i2]==0x20) {
00447             i2++;
00448             break;
00449         }
00450     }
00451 
00452     for(;;) {
00453         if(i1>=modes.length())
00454             break;
00455         if(modes[i1]==0x20)
00456             break;
00457         if(modes[i1]=='+') {
00458             i1++;
00459             continue;
00460         }
00461         // however, CLASS A should never occur!
00462         if(irc_isupport.chanmodes_a.find(modes[i1],0)!=string::npos ||
00463            irc_isupport.chanmodes_b.find(modes[i1],0)!=string::npos ||
00464            irc_isupport.chanmodes_c.find(modes[i1],0)!=string::npos) {
00465             if(i2>=modes.length()) {
00466                 i1++;
00467                 continue;
00468             }
00469             pair<char,string> p;
00470             p.first=modes[i1];
00471             p.second="";
00472             for(; i2<modes.length(); i2++) {
00473                 if(modes[i2]==0x20) {
00474                     i2++;
00475                     break;
00476                 }
00477                 p.second+=(string)""+modes[i2];
00478             }
00479             with_param.insert(p);
00480             i1++;
00481             continue;
00482         }
00483         if(irc_isupport.chanmodes_d.find(modes[i1],0)!=string::npos) {
00484             plain+=(string)""+modes[i1];
00485             i1++;
00486             continue;
00487         }
00488         // there it shouldn't go
00489         i1++;
00490     }
00491 }

bool irc_part const char *  channel,
const char *  reason
 

PARTs channel.

Author:
VooDooMan
Version:
1
Date:
2004
Parameters:
channel Channel name
reason PART message (reason of PART)
Returns:
Returns false if socket I/O error occured

Definition at line 6443 of file irc.cpp.

References HIGH_PRIORITY, and irc_putserv().

Referenced by dcc_loop(), and logic_exec().

06444 {
06445     if(strlen(channel)>128)
06446         return false;
06447     if(strlen(reason)>128)
06448         return false;
06449 
06450     char msg[4096];
06451     strcpy(msg,"PART ");
06452     strcat(msg,channel);
06453     if(reason[0]) {
06454         strcat(msg," :");
06455         strcat(msg,reason);
06456     }
06457 
06458     return irc_putserv(msg,false,HIGH_PRIORITY);
06459 }

Here is the call graph for this function:

bool irc_privmsg const char *  target,
const char *  msg,
int  priority
 

Sends PRIVMSG to user/channel.

Author:
VooDooMan
Version:
1
Date:
2004
Parameters:
target Nick name / channel name of target
msg Whole message
priority Priority class (LOW_PRIORITY, HIGH_PRIORITY, or CRITICAL_PRIORITY)
Returns:
Returns false if socket I/O error occured

Definition at line 6471 of file irc.cpp.

References irc_putserv().

Referenced by irc_loop_process_input(), irc_RPL_ENDOFWHOIS(), and logic_exec().

06472 {
06473     if(strlen(target)>128)
06474         return false;
06475     if(strlen(msg)>512-1)
06476         return false;
06477 
06478     char tmp[4096];
06479     strcpy(tmp,"PRIVMSG ");
06480     strcat(tmp,target);
06481     strcat(tmp," :");
06482     strcat(tmp,msg);
06483 
06484     return irc_putserv(tmp,false,priority);
06485 }

Here is the call graph for this function:

void irc_put string  data,
int  priority
 

Raw-ly puts message to queue to send to server.

Author:
VooDooMan
Version:
1
Date:
2004
Parameters:
data Raw message (i.e. "PRIVMSG nick hello!")
priority Priority class (LOW_PRIORITY, HIGH_PRIORITY, or CRITICAL_PRIORITY)

Definition at line 6824 of file irc.cpp.

References irc_putserv().

Referenced by dcc_notify(), logic_exec(), and logic_process_script_output().

06825 {
06826     irc_putserv(data.c_str(),false,priority);
06827 }

Here is the call graph for this function:

bool irc_putserv const char *  msg,
bool  wait_for_response,
int  priority
 

Puts message for server to queue to send.

Author:
VooDooMan
Version:
1
Date:
2004
Parameters:
msg Message
wait_for_response Set this to true if message has to be marked as wait for response and then send next message
priority CRITICAL_PRIORITY, HIGH_PRIORITY, or LOW_PRIORITY
Returns:
Returns false if socket I/O error occured

Definition at line 503 of file irc.cpp.

References s_005::chanmodes_a, s_005::chanmodes_b, s_005::chanmodes_c, s_005::chanmodes_d, s_mode_queue_entry::channel, conf_getvar(), CRITICAL_PRIORITY, s_msg_to_server::flood_protection, s_005::get_prefix1(), HIGH_PRIORITY, irc_putserv_immediately(), LOW_PRIORITY, s_mode_queue_entry::mode, mode_queue, s_msg_to_server::msg, msgs_to_server, msgs_to_server2, s_mode_queue_entry::param, s_msg_to_server::response, s_mode_queue_entry::submit, and s_msg_to_server::wait_for_response.

Referenced by dcc_send_file(), irc_access_to_partyline(), irc_ban(), irc_chan_mode(), irc_check_bans(), irc_check_invites(), irc_deop(), irc_devoice(), irc_join(), irc_kick(), irc_loop_process_input(), irc_loop_putserv(), irc_notice(), irc_op(), irc_part(), irc_privmsg(), irc_put(), irc_put_multiple_lines(), irc_quoted_callback(), irc_RPL_NAMREPLY(), irc_unban(), irc_voice(), logic_ctcp(), and logic_exec().

00504 {
00505     if(strlen(msg)+2>512) { /* +2 == CR/LF */
00506         return false;
00507     }
00508 
00509     s_msg_to_server m;
00510 
00511     size_t end;
00512     m.msg=new char[end=(strlen(msg)+2+1)]; // +2 == CR/LF
00513     strcpy(m.msg,msg);
00514     m.msg[end-2-1+0]=0x0D;
00515     m.msg[end-2-1+1]=0x0A;
00516     m.msg[end-2-1+2]=0;
00517 
00518     int compress_mode_wait=atol(conf_getvar("compress_mode_wait").c_str());
00519     if(compress_mode_wait>0 && strstr(msg,"MODE")==msg && priority==LOW_PRIORITY) {
00520         string chan;
00521         string mode;
00522         string param;
00523         unsigned int i1;
00524         int context=0;
00525         for(i1=0; i1<strlen(msg); i1++) {
00526             if(msg[i1]==0x20) {
00527                 context++;
00528                 continue;
00529             }
00530             if(msg[i1]==0x0D || msg[i1]==0x0A)
00531                 break;
00532             if(context==1)
00533                 chan+=msg[i1];
00534             if(context==2)
00535                 mode+=msg[i1];
00536             if(context==3)
00537                 param+=msg[i1];
00538         }
00539         if(context<=3 && mode.length()==2 && (mode[0]=='+' || mode[0]=='-')) {
00540             // process only single mode
00541             int process=0;
00542             /*switch(mode[1]) {
00543                 case 'o':
00544                 case 'O':
00545                 //case 'b':
00546                     // do not precess bans, they should be put immediatelly
00547                 case 'e':
00548                 case 'I':
00549                 case 'v':
00550                     process=1;
00551                     break;
00552                 case 'k':
00553                 case 'l':
00554                     process=2;
00555                     break;
00556                 case 'n':
00557                 case 't':
00558                     process=3;
00559                     break;
00560                 default:
00561                     process=0;
00562                     break;
00563             }*/
00564             if(irc_isupport.get_prefix1(mode[1])!='0') {
00565                 process=1;
00566             }
00567             if(irc_isupport.chanmodes_a.find(mode[1])!=string::npos) {
00568                 if(mode[1]=='b') {
00569                     // do not precess bans, they should be put immediatelly
00570                     process=0;
00571                 } else {
00572                     process=1;
00573                 }
00574             }
00575             if(irc_isupport.chanmodes_b.find(mode[1])!=string::npos || irc_isupport.chanmodes_c.find(mode[1])!=string::npos) {
00576                 process=2;
00577             }
00578             if(irc_isupport.chanmodes_d.find(mode[1])!=string::npos) {
00579                 process=3;
00580             }
00581             if(process==0) {
00582                 // do nothing!
00583             }
00584             if((process==1 || process==2) && !param.empty()) {
00585                 // with parameter
00586                 s_mode_queue_entry e;
00587                 e.channel=chan;
00588                 e.mode=mode;
00589                 e.param=param;
00590                 time(&e.submit);
00591                 mode_queue.push_back(e);
00592                 return true;
00593             }
00594             if(process==3 && param.empty()) {
00595                 // without parameter
00596                 s_mode_queue_entry e;
00597                 e.channel=chan;
00598                 e.mode=mode;
00599                 e.param="";
00600                 time(&e.submit);
00601                 mode_queue.push_back(e);
00602                 return true;
00603             }
00604         }
00605     }
00606 
00607     m.flood_protection=strstr(msg,"PRIVMSG")==msg || strstr(msg,"NOTICE")==msg;
00608 
00609     m.wait_for_response=wait_for_response;
00610     if(wait_for_response)
00611         m.response[0]=0;
00612 
00613     if(priority==HIGH_PRIORITY)
00614         msgs_to_server.push_back(m);
00615     else if(priority==LOW_PRIORITY)
00616         msgs_to_server2.push_back(m);
00617     else if(priority==CRITICAL_PRIORITY)
00618         irc_putserv_immediately(irc_socket,m.msg,wait_for_response);
00619 
00620     return true;
00621 }

Here is the call graph for this function:

void irc_quit const char *  reason  ) 
 

Quits the IRC.

Author:
VooDooMan
Version:
1
Date:
2004
Parameters:
reason Quit message

Definition at line 6855 of file irc.cpp.

References irc_putserv_immediately(), sock_flush_later(), and sock_send_cache().

Referenced by write_kill_log().

06856 {
06857     string tmp="QUIT :";
06858     tmp+=reason;
06859     tmp+=(string)"\r\n";
06860     irc_putserv_immediately(irc_socket,tmp.c_str(),true);
06861     sock_send_cache();
06862     sock_flush_later(irc_socket);
06863     //sleep(1000);
06864 }

Here is the call graph for this function:

void irc_rehashed  ) 
 

Called from logic.cpp after rehashing. Deletes all online users and so applies new configuration.

Author:
VooDooMan
Version:
1
Date:
2004

Definition at line 6915 of file irc.cpp.

References conf_getvar(), irc_bot_flood_bytes, irc_bot_flood_lines, irc_bot_flood_seconds, irc_channels, logic_find_user(), and logic_on_nick_validate().

Referenced by dcc_loop(), and logic_rehash().

06916 {
06917     irc_bot_flood_bytes=atol(conf_getvar("irc_bot_flood_bytes").c_str());
06918     irc_bot_flood_seconds=atol(conf_getvar("irc_bot_flood_seconds").c_str());
06919     irc_bot_flood_lines=atol(conf_getvar("irc_bot_flood_lines").c_str());
06920 
06921     {
06922         vector<s_online_channel>::iterator i1;
06923         for(i1=irc_channels.begin(); i1!=irc_channels.end(); i1++) {
06924             vector<s_online_user>::iterator i2;
06925             for(i2=(*i1).users.begin(); i2!=(*i1).users.end(); i2++) {
06926                 if((*i2).got_whois)
06927                     (*i2).in_logic_as=logic_find_user((*i2).nick,(*i2).ident,(*i2).host,(*i2).fullname,(*i2).irc_op);
06928                 logic_on_nick_validate((*i2).nick,(*i2).ident,(*i2).host,(*i2).fullname,(*i1).name,(*i2).irc_op,true);
06929             }
06930         }
06931     }
06932 }

Here is the call graph for this function:

void irc_set_redir bool  follow_redirs  ) 
 

Sets value of irc_follow_redirs flag.

Author:
VooDooMan
Version:
1
Date:
2004
Parameters:
follow_redirs flag to set

Definition at line 6747 of file irc.cpp.

References irc_follow_redirs.

Referenced by logic_exec().

06748 {
06749     irc_follow_redirs=follow_redirs;
06750 }

bool irc_unban const char *  channel,
const char *  mask
 

Unbans (MODE #channel -b mask) host mask on channel.

Author:
VooDooMan
Version:
1
Date:
2004
Parameters:
channel Channel name
mask Ban mask
Returns:
Returns false if socket I/O error occured, or channel is longer than 128 chars, or mask is longer than 511 bytes

Definition at line 6683 of file irc.cpp.

References cmp_strings_case_insensitive(), HIGH_PRIORITY, irc_channels, and irc_putserv().

Referenced by logic_exec().

06684 {
06685     if(strlen(channel)>128)
06686         return false;
06687     if(strlen(mask)>512-1)
06688         return false;
06689 
06690     vector<s_online_channel>::iterator i;
06691     for(i=irc_channels.begin(); i!=irc_channels.end(); i++) {
06692         if(!cmp_strings_case_insensitive((*i).name,(string)channel)) {
06693             vector<string>::iterator i2;
06694             for(i2=(*i).bans.begin(); i2!=(*i).bans.end(); i2++) {
06695                 if(!cmp_strings_case_insensitive((*i2),(string)mask)) {
06696                     (*i).bans.erase(i2);
06697                     break;
06698                 }
06699             }
06700         }
06701     }
06702 
06703     char tmp[4096];
06704     strcpy(tmp,"MODE ");
06705     strcat(tmp,channel);
06706     strcat(tmp," -b ");
06707     strcat(tmp,mask);
06708 
06709     return irc_putserv(tmp,true,HIGH_PRIORITY);
06710 }

Here is the call graph for this function:

bool irc_voice const char *  channel,
const char *  nick,
int  priority
 

Sets +v (voice) status to nick on channel.

Author:
VooDooMan
Version:
1
Date:
2004
Parameters:
channel Channel name
nick Nick name
Returns:
Returns false if socket I/O error occured
Parameters:
priority Priority class (LOW_PRIORITY, HIGH_PRIORITY, or CRITICAL_PRIORITY)

Definition at line 6321 of file irc.cpp.

References irc_internal_set_mode(), and irc_putserv().

Referenced by logic_exec().

06322 {
06323     if(strlen(channel)>128)
06324         return false;
06325     if(strlen(nick)>128)
06326         return false;
06327 
06328     irc_internal_set_mode(channel,nick,'+','+');
06329 
06330     char msg[4096];
06331     strcpy(msg,"MODE ");
06332     strcat(msg,channel);
06333     strcat(msg," +v ");
06334     strcat(msg,nick);
06335 
06336     return irc_putserv(msg,true,priority);
06337 }

Here is the call graph for this function:


Generated on Sun Jul 10 04:41:10 2005 for VooDoo cIRCle by doxygen 1.4.3

Hosted by SourceForge.net Logo