00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #ifndef USE_PCH
00017 #include "sys.h"
00018 #include "debug.h"
00019 #endif
00020
00021 #include <boost/tokenizer.hpp>
00022 #include "PrivateTarget.h"
00023 #include "MessageIn.h"
00024 #include "keys.h"
00025 #include "ClientSession.h"
00026 #include "Identity.h"
00027 #include "is_channel.h"
00028 #include "Application.h"
00029
00030
00031
00032
00033
00034 void PrivateTarget::new_client_message_received(ClientMessageIn const& msg)
00035 {
00036 DoutEntering(dc::debug, "PrivateTarget::new_client_message_received(" << msg << ") for target \"" << in_name(client_session()) << "\".");
00037 ASSERT(&client_session() == &msg.client_session());
00038 switch(msg.key())
00039 {
00040 using namespace keys;
00041 case MODE:
00042 if (is_channel(in_name(client_session())))
00043 client_session() << ':' << client_session().identity().server_source() << " 324 " <<
00044 client_session().client_out_nick() << ' ' << out_name(client_session()) << " +" << channel_modes() << "\r\n";
00045 break;
00046 case NAMES:
00047 do_names_output();
00048 break;
00049 case PART:
00050 client_session().del_private_target(msg.param(0));
00051 client_session() << ':' << client_session().client_out_nick() <<
00052 " PART " << msg.param(0) << "\r\n";
00053 break;
00054 case PRIVMSG:
00055 handle_command(msg);
00056 break;
00057 }
00058 }
00059
00060
00061 void PrivateTarget::handle_command(ClientMessageIn const& msg)
00062 {
00063
00064 ClientSession& client_session(this->client_session());
00065 Identity& identity(client_session.identity());
00066 ServerConnection& server_connection(identity.server_connection());
00067
00068 std::string prefix(msg.param(0));
00069 if (!is_channel(prefix))
00070 prefix = client_session.client_out_nick();
00071 prefix = ":Leandro PRIVMSG " + prefix + " :";
00072
00073 typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
00074 boost::char_separator<char> sep(" ");
00075 tokenizer tokens(msg.param(1), sep);
00076 tokenizer::iterator tok_iter = tokens.begin();
00077 if (tok_iter == tokens.end())
00078 return;
00079 std::string command = *tok_iter;
00080 ++tok_iter;
00081 if (command == "!help")
00082 {
00083 client_session << prefix << "!help : This help text." << "\r\n";
00084 client_session << prefix << "!server <host> [<port>]: Connect to server <host> at port <port> (default 6667)." << "\r\n";
00085 #ifdef CWDEBUG
00086 client_session << prefix << "!quit : Send 'QUIT :Received command !quit' to the server socket (debugging)." << "\r\n";
00087 #endif
00088 }
00089 else if (command == "!server")
00090 {
00091 if (tok_iter == tokens.end())
00092 {
00093 client_session << prefix << "Usage: !server <host> [<port>] [<vhost>]\r\n";
00094 return;
00095 }
00096 std::string hostname(*tok_iter);
00097 std::string::size_type pos = hostname.rfind('.');
00098 std::string domain;
00099 if (pos != std::string::npos)
00100 domain = hostname.substr(hostname.rfind('.', pos - 1) + 1);
00101 ++tok_iter;
00102 unsigned short port = 0;
00103 bool no_vhost_argument_given = true;
00104 struct in_addr vhost = { INADDR_ANY };
00105 if (tok_iter != tokens.end())
00106 {
00107 std::string argument(*tok_iter);
00108 ++tok_iter;
00109 if (tok_iter != tokens.end() || argument.find_first_not_of("0123456789") == std::string::npos)
00110 port = atoi(argument.c_str());
00111 else
00112 {
00113 inet_aton(argument.c_str(), &vhost);
00114 no_vhost_argument_given = false;
00115 }
00116 if (tok_iter != tokens.end())
00117 {
00118 inet_aton(tok_iter->c_str(), &vhost);
00119 no_vhost_argument_given = false;
00120 }
00121 }
00122
00123 bool found = false;
00124 networks_type::iterator network_iter;
00125 Network::servers_type::iterator server_found;
00126 for (network_iter = Application::instance().networks().begin(); network_iter != Application::instance().networks().end(); ++network_iter)
00127 {
00128 for (Network::servers_type::iterator server_iter = network_iter->servers().begin(); server_iter != network_iter->servers().end(); ++server_iter)
00129 if (strcasecmp((*server_iter)->hostname().c_str(), hostname.c_str()) == 0)
00130 {
00131 Dout(dc::notice, "Found existing server " << *server_iter);
00132 found = true;
00133 server_found = server_iter;
00134 break;
00135 }
00136 if (found)
00137 break;
00138 }
00139 bool trying_to_switch_network = false;
00140 if (found)
00141 {
00142
00143 if (server_connection.has_server() && server_connection.state() >= real_nick_accepted)
00144 {
00145
00146 if (server_connection.server() == *server_found)
00147 {
00148
00149 if (!port || port == server_connection.server()->port())
00150 {
00151
00152 if (no_vhost_argument_given || std::memcmp(&server_connection.server()->vhost(), &vhost, sizeof(vhost)) == 0)
00153 {
00154
00155 static struct in_addr const any = { INADDR_ANY };
00156 bool print_vhost = !no_vhost_argument_given || std::memcmp(&server_connection.server()->vhost(), &any, sizeof(vhost)) != 0;
00157 client_session << prefix << "You are already connected to " << server_connection.server()->get_irc_name();
00158 if (port)
00159 client_session << ' ';
00160 else
00161 client_session << " (";
00162 client_session << "port " << server_connection.server()->port();
00163 if (print_vhost)
00164 {
00165 if (port && no_vhost_argument_given)
00166 client_session << " (";
00167 else if (!port && !no_vhost_argument_given)
00168 client_session << ") ";
00169 else
00170 client_session << ' ';
00171 client_session << "using vhost " << server_connection.server()->vhost();
00172 }
00173 if ((print_vhost && no_vhost_argument_given) || (!print_vhost && !port))
00174 client_session << ')';
00175 client_session << "\r\n";
00176 return;
00177 }
00178 }
00179 if (no_vhost_argument_given)
00180 std::memcpy(&vhost, &server_connection.server()->vhost(), sizeof(vhost));
00181 }
00182 else if (network_iter->name() != identity.network().name())
00183 trying_to_switch_network = true;
00184 }
00185 }
00186 else
00187 trying_to_switch_network = identity.network().has_domain() && strcasecmp(identity.network().domain().c_str(), domain.c_str()) != 0;
00188 if (trying_to_switch_network)
00189 {
00190 client_session << prefix << "The identity \"" << identity.key() <<
00191 "\" belongs to network \"" << identity.network_name() << "\". You can not switch IRC network.\r\n";
00192 return;
00193 }
00194 if (!port)
00195 port = 6667;
00196 boost::shared_ptr<Server> new_server;
00197 if (!found)
00198 new_server.reset(NEW(Server(identity.network(), hostname, port, vhost)));
00199 else
00200 {
00201 ASSERT(&(*server_found)->network() == NULL || &identity.network() == &(*server_found)->network());
00202 ASSERT(!strcasecmp((*server_found)->hostname().c_str(), hostname.c_str()));
00203 new_server = *server_found;
00204 std::memcpy(&new_server->vhost(), &vhost, sizeof(vhost));
00205 new_server->set_next_port(port);
00206 }
00207 identity.start_secondary_server_connection(new_server);
00208 }
00209 #ifdef CWDEBUG
00210 else if (command == "!quit")
00211 {
00212 client_session << "QUIT :Received command !quit\r\n";
00213 }
00214 #endif
00215 }
00216
00217
00218 void PrivateTarget::do_names_output(void)
00219 {
00220 client_session() << ':' << client_session().identity().server_source() << " 353 " <<
00221 client_session().client_out_nick() << " @ " << out_name(client_session()) <<
00222 " :@Leandro " << client_session().client_out_nick() << "\r\n";
00223 client_session() << ':' << client_session().identity().server_source() << " 366 " <<
00224 client_session().client_out_nick() << ' ' << out_name(client_session()) << " :End of /NAMES list.\r\n";
00225 }
00226
00227 void PrivateTarget::handle_who(WhoRequest const& who_request)
00228 {
00229 DoutEntering(dc::debug, "PrivateTarget::handle_who(" << who_request << ")");
00230
00231 Prefix prefix(client_session().identity().server_source());
00232 MessageOut msgout(default_priority(352));
00233 ClientSession& cs(client_session());
00234 Identity& identity(cs.identity());
00235 cs.queue_msg(msgout << prefix << 352 << identity.mynick() << out_name(client_session()) <<
00236 "leandro 127.0.0.1" << identity.server_source() << "Leandro H@ :3 Cyborg");
00237 cs.queue_msg(msgout << prefix << 352 << identity.mynick() << out_name(client_session()) <<
00238 identity.ident() << identity.hostname() << identity.server_source() <<
00239 identity.mynick() << "H :0 " << JustInTimeCatenate(identity.real_name()));
00240 cs.queue_msg(msgout << prefix << 315 << identity.mynick() << out_name(client_session()) << ":End of /WHO list.");
00241 }