int server_unref(SERVER_REC *server) { g_return_val_if_fail(IS_SERVER(server), FALSE); if (--server->refcount > 0) return TRUE; if (g_slist_find(servers, server) != NULL) { g_warning("Non-referenced server wasn't disconnected"); server_disconnect(server); return TRUE; } MODULE_DATA_DEINIT(server); server_connect_unref(server->connrec); if (server->rawlog != NULL) rawlog_destroy(server->rawlog); g_free(server->version); g_free(server->away_reason); g_free(server->nick); g_free(server->tag); server->type = 0; g_free(server); return FALSE; }
static void server_connect_callback_init_ssl(SERVER_REC *server, GIOChannel *handle) { int error; g_return_if_fail(IS_SERVER(server)); error = irssi_ssl_handshake(handle); if (error == -1) { server->connection_lost = TRUE; server_connect_failed(server, NULL); return; } if (error & 1) { if (server->connect_tag != -1) g_source_remove(server->connect_tag); server->connect_tag = g_input_add(handle, error == 1 ? G_INPUT_READ : G_INPUT_WRITE, (GInputFunction) server_connect_callback_init_ssl, server); return; } lookup_servers = g_slist_remove(lookup_servers, server); if (server->connect_tag != -1) { g_source_remove(server->connect_tag); server->connect_tag = -1; } server_connect_finished(server); }
/* connection to server failed */ void server_connect_failed(SERVER_REC *server, const char *msg) { g_return_if_fail(IS_SERVER(server)); lookup_servers = g_slist_remove(lookup_servers, server); signal_emit("server connect failed", 2, server, msg); if (server->connect_tag != -1) { g_source_remove(server->connect_tag); server->connect_tag = -1; } if (server->handle != NULL) { net_sendbuffer_destroy(server->handle, TRUE); server->handle = NULL; } if (server->connect_pipe[0] != NULL) { g_io_channel_shutdown(server->connect_pipe[0], TRUE, NULL); g_io_channel_unref(server->connect_pipe[0]); g_io_channel_shutdown(server->connect_pipe[1], TRUE, NULL); g_io_channel_unref(server->connect_pipe[1]); server->connect_pipe[0] = NULL; server->connect_pipe[1] = NULL; } server_unref(server); }
/* SYNTAX: WAIT [-<server tag>] <milliseconds> */ static void cmd_wait(const char *data, IRC_SERVER_REC *server) { GHashTable *optlist; char *msecs; void *free_arg; int n; g_return_if_fail(data != NULL); if (!IS_SERVER(server) || !server->connected) cmd_return_error(CMDERR_NOT_CONNECTED); if (!cmd_get_params(data, &free_arg, 1 | PARAM_FLAG_OPTIONS | PARAM_FLAG_UNKNOWN_OPTIONS | PARAM_FLAG_GETREST, NULL, &optlist, &msecs)) return; if (*msecs == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); /* -<server tag> */ server = IRC_SERVER(cmd_options_get_server(NULL, optlist, SERVER(server))); n = atoi(msecs); if (server != NULL && n > 0) { g_get_current_time(&server->wait_cmd); server->wait_cmd.tv_sec += n/1000; server->wait_cmd.tv_usec += n%1000; if (server->wait_cmd.tv_usec >= 1000) { server->wait_cmd.tv_sec++; server->wait_cmd.tv_usec -= 1000; } } cmd_params_free(free_arg); }
/* SYNTAX: CYCLE [<channel>] [<message>] */ static void cmd_cycle(const char *data, SERVER_REC *server, WI_ITEM_REC *item) { CHANNEL_REC *chanrec; char *channame, *msg, *joindata; void *free_arg; g_return_if_fail(data != NULL); if (!IS_SERVER(server) || !server->connected) cmd_return_error(CMDERR_NOT_CONNECTED); if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_OPTCHAN, item, &channame, &msg)) return; if (*channame == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); chanrec = channel_find(server, channame); if (chanrec == NULL) cmd_param_error(CMDERR_CHAN_NOT_FOUND); joindata = chanrec->get_join_data(chanrec); window_bind_add(window_item_window(chanrec), chanrec->server->tag, chanrec->name); /* FIXME: kludgy kludgy... */ signal_emit("command part", 3, data, server, item); if (g_slist_find(channels, chanrec) != NULL) { chanrec->left = TRUE; channel_destroy(chanrec); } server->channels_join(server, joindata, FALSE); g_free(joindata); cmd_params_free(free_arg); }
CmdResult Handle (const std::vector<std::string>& parameters, User *user) { User* dest = ServerInstance->FindNick(parameters[0]); if ((dest) && (!IS_SERVER(dest))) { if (ServerInstance->ULine(dest->server)) { user->WriteNumeric(ERR_NOPRIVILEGES, "%s :Cannot use an SA command on a u-lined client",user->nick.c_str()); return CMD_FAILURE; } // Pass the command on, so the client's server can quit it properly. if (!IS_LOCAL(dest)) return CMD_SUCCESS; ServerInstance->SNO->WriteGlobalSno('a', user->nick+" used SAQUIT to make "+dest->nick+" quit with a reason of "+parameters[1]); ServerInstance->Users->QuitUser(dest, parameters[1]); return CMD_SUCCESS; } else { user->WriteNotice("*** Invalid nickname '" + parameters[0] + "'"); return CMD_FAILURE; } }
void unserialize(SerializeFormat format, Extensible* container, const std::string& value) { if (format == FORMAT_NETWORK) return; callerid_data* dat = new callerid_data; irc::commasepstream s(value); std::string tok; if (s.GetToken(tok)) dat->lastnotify = ConvToInt(tok); while (s.GetToken(tok)) { User *u = ServerInstance->FindNick(tok); if ((u) && (u->registered == REG_ALL) && (!u->quitting) && (!IS_SERVER(u))) { if (dat->accepting.insert(u).second) { callerid_data* other = this->get(u, true); other->wholistsme.push_back(dat); } } } void* old = set_raw(container, dat); if (old) this->free(old); }
bool TreeSocket::Away(const std::string &prefix, parameterlist ¶ms) { User* u = ServerInstance->FindNick(prefix); if ((!u) || (IS_SERVER(u))) return true; if (params.size()) { FOREACH_MOD(I_OnSetAway, OnSetAway(u, params[params.size() - 1])); if (params.size() > 1) u->awaytime = atoi(params[0].c_str()); else u->awaytime = ServerInstance->Time(); u->awaymsg = params[params.size() - 1]; params[params.size() - 1] = ":" + params[params.size() - 1]; } else { FOREACH_MOD(I_OnSetAway, OnSetAway(u, "")); u->awaymsg.clear(); } Utils->DoOneToAllButSender(prefix,"AWAY",params,u->server); return true; }
static void sig_not_in_roster(XMPP_SERVER_REC *server, const char *jid) { g_return_if_fail(IS_SERVER(server)); g_return_if_fail(jid != NULL); printformat_module(MODULE_NAME, server, NULL, MSGLEVEL_CLIENTERROR, XMPPTXT_NOT_IN_ROSTER, jid); }
static void sig_connected(SERVER_REC *server) { g_return_if_fail(IS_SERVER(server)); if (!server->connrec->reconnection) return; if (server->connrec->channels != NULL) server->channels_join(server, server->connrec->channels, TRUE); }
static void show_group(XMPP_SERVER_REC *server, XMPP_ROSTER_GROUP_REC *group) { g_return_if_fail(IS_SERVER(server)); g_return_if_fail(group != NULL); printformat_module(MODULE_NAME, server, NULL, MSGLEVEL_CRAP, XMPPTXT_ROSTER_GROUP, (group->name != NULL) ? group->name : settings_get_str("xmpp_roster_default_group")); }
GVariant * server_get_variant (Server * server) { /* Okay, this doesn't do anything useful, but it will generate an error which could be a good thing */ g_return_val_if_fail(IS_SERVER(server), NULL); ServerClass * klass = SERVER_GET_CLASS(server); if (klass->get_properties != NULL) { GVariantBuilder tuple; g_variant_builder_init(&tuple, G_VARIANT_TYPE_TUPLE); if (IS_CITRIX_SERVER(server)) { g_variant_builder_add_value(&tuple, g_variant_new_string("ica")); } else if (IS_RDP_SERVER(server)) { g_variant_builder_add_value(&tuple, g_variant_new_string("freerdp")); } else if (IS_UCCS_SERVER(server)) { g_variant_builder_add_value(&tuple, g_variant_new_string("uccs")); } else if (IS_X2GO_SERVER(server)) { g_variant_builder_add_value(&tuple, g_variant_new_string("x2go")); } else { g_assert_not_reached(); } if (server->name != NULL) { g_variant_builder_add_value(&tuple, g_variant_new_string(server->name)); } else { g_warning("Server has no name"); g_variant_builder_add_value(&tuple, g_variant_new_string("")); } if (server->uri != NULL) { g_variant_builder_add_value(&tuple, g_variant_new_string(server->uri)); } else { g_warning("Server has no URI"); g_variant_builder_add_value(&tuple, g_variant_new_string("")); } g_variant_builder_add_value(&tuple, g_variant_new_boolean(server->last_used)); GVariant * props = klass->get_properties(server); g_variant_builder_add_value(&tuple, props); if (klass->get_applications != NULL) { GVariant * array = klass->get_applications(server); g_variant_builder_add_value(&tuple, array); } else { /* NULL array of applications */ g_variant_builder_add_value(&tuple, g_variant_new_array(G_VARIANT_TYPE("(si)"), NULL, 0)); } return g_variant_builder_end(&tuple); } return NULL; }
ModeAction OnModeChange(User* source, User* dest, Channel* channel, std::string ¶meter, bool adding) { if (IS_SERVER(source) || ServerInstance->ULine(source->server)) return MODEACTION_ALLOW; else { if (source && channel) source->WriteNumeric(ERR_CHANOPRIVSNEEDED, "%s %s :Only servers are permitted to change channel mode '%c'", source->nick.c_str(), channel->name.c_str(), 'y'); return MODEACTION_DENY; } }
/** * server_cached_domains: * @server: Where should we find those domains? * * Gets a list of cached domains for a particular server, if this function * isn't overriden, then a null array is returned. */ GVariant * server_cached_domains (Server * server) { g_return_val_if_fail(IS_SERVER(server), NULL); ServerClass * klass = SERVER_GET_CLASS(server); if (klass->get_domains != NULL) { return klass->get_domains(server); } return g_variant_new_array(G_VARIANT_TYPE_STRING, NULL, 0); }
ACCEPTAction GetTargetAndAction(std::string& tok) { bool remove = (tok[0] == '-'); if ((remove) || (tok[0] == '+')) tok.erase(tok.begin()); User* target = ServerInstance->FindNick(tok); if ((!target) || (target->registered != REG_ALL) || (target->quitting) || (IS_SERVER(target))) target = NULL; return std::make_pair(target, !remove); }
void UserManager::QuitUser(User* user, const std::string& quitreason, const std::string* operreason) { if (user->quitting) { ServerInstance->Logs->Log("USERS", LOG_DEFAULT, "ERROR: Tried to quit quitting user: "******"USERS", LOG_DEFAULT, "ERROR: Tried to quit server user: "******"USERS", LOG_DEBUG, "QuitUser: %s=%s '%s'", user->uuid.c_str(), user->nick.c_str(), quitreason.c_str()); user->Write("ERROR :Closing link: (%s@%s) [%s]", user->ident.c_str(), user->host.c_str(), operreason ? operreason->c_str() : quitreason.c_str()); std::string reason; reason.assign(quitreason, 0, ServerInstance->Config->Limits.MaxQuit); if (!operreason) operreason = &reason; ServerInstance->GlobalCulls.AddItem(user); if (user->registered == REG_ALL) { FOREACH_MOD(OnUserQuit, (user, reason, *operreason)); user->WriteCommonQuit(reason, *operreason); } else unregistered_count--; if (IS_LOCAL(user)) { LocalUser* lu = IS_LOCAL(user); FOREACH_MOD(OnUserDisconnect, (lu)); lu->eh.Close(); if (lu->registered == REG_ALL) ServerInstance->SNO->WriteToSnoMask('q',"Client exiting: %s (%s) [%s]", user->GetFullRealHost().c_str(), user->GetIPString().c_str(), operreason->c_str()); } user_hash::iterator iter = this->clientlist->find(user->nick); if (iter != this->clientlist->end()) this->clientlist->erase(iter); else ServerInstance->Logs->Log("USERS", LOG_DEFAULT, "ERROR: Nick not found in clientlist, cannot remove: " + user->nick); uuidlist->erase(user->uuid); }
/** * SAVE command - force nick change to UID on timestamp match */ CmdResult CommandSave::Handle(User* user, std::vector<std::string>& params) { User* u = ServerInstance->FindUUID(params[0]); if ((!u) || (IS_SERVER(u))) return CMD_FAILURE; time_t ts = atol(params[1].c_str()); if (u->age == ts) u->ChangeNick(u->uuid, SavedTimestamp); return CMD_SUCCESS; }
static void sig_connected(SERVER_REC *server) { CHATNET_REC *rec; g_return_if_fail(IS_SERVER(server)); if (server->connrec->chatnet == NULL || server->session_reconnect) return; rec = chatnet_find(server->connrec->chatnet); if (!server->connrec->no_autosendcmd && rec != NULL && rec->autosendcmd) eval_special_string(rec->autosendcmd, "", server, NULL); }
CHANNEL_REC *channel_find(SERVER_REC *server, const char *name) { g_return_val_if_fail(server == NULL || IS_SERVER(server), NULL); g_return_val_if_fail(name != NULL, NULL); if (server != NULL) return channel_find_server(server, name); /* find from any server */ return gslist_foreach_find(servers, (FOREACH_FIND_FUNC) channel_find_server, (void *) name); }
/* Create a new channel */ CHANNEL_REC *channel_create(int chat_type, SERVER_REC *server, const char *name, int automatic) { CHANNEL_REC *channel; g_return_val_if_fail(server == NULL || IS_SERVER(server), NULL); g_return_val_if_fail(name != NULL, NULL); channel = NULL; signal_emit("channel create", 5, &channel, GINT_TO_POINTER(chat_type), server, name, GINT_TO_POINTER(automatic)); return channel; }
CmdResult CommandMetadata::Handle(const std::vector<std::string>& params, User *srcuser) { if (params[0] == "*") { std::string value = params.size() < 3 ? "" : params[2]; FOREACH_MOD(I_OnDecodeMetaData,OnDecodeMetaData(NULL,params[1],value)); return CMD_SUCCESS; } if (params[0][0] == '#') { // Channel METADATA has an additional parameter: the channel TS // :22D METADATA #channel 12345 extname :extdata if (params.size() < 3) return CMD_INVALID; Channel* c = ServerInstance->FindChan(params[0]); if (!c) return CMD_FAILURE; time_t ChanTS = ConvToInt(params[1]); if (!ChanTS) return CMD_INVALID; if (c->age < ChanTS) // Their TS is newer than ours, discard this command and do not propagate return CMD_FAILURE; std::string value = params.size() < 4 ? "" : params[3]; ExtensionItem* item = ServerInstance->Extensions.GetItem(params[2]); if (item) item->unserialize(FORMAT_NETWORK, c, value); FOREACH_MOD(I_OnDecodeMetaData,OnDecodeMetaData(c,params[2],value)); } else { User* u = ServerInstance->FindUUID(params[0]); if ((u) && (!IS_SERVER(u))) { ExtensionItem* item = ServerInstance->Extensions.GetItem(params[1]); std::string value = params.size() < 3 ? "" : params[2]; if (item) item->unserialize(FORMAT_NETWORK, u, value); FOREACH_MOD(I_OnDecodeMetaData,OnDecodeMetaData(u,params[1],value)); } } return CMD_SUCCESS; }
static void sig_disconnected(SERVER_REC *server) { WINDOW_REC *window; GSList *tmp; g_return_if_fail(IS_SERVER(server)); for (tmp = server->channels; tmp != NULL; tmp = tmp->next) { CHANNEL_REC *channel = tmp->data; window = window_item_window((WI_ITEM_REC *) channel); window_bind_add(window, server->tag, channel->name); } }
/** * server_set_last_used: * @server: Server to look in * @uri: URI to set as last used * * Checks the URI of this server to see if it matches, and then look * to see if subclasses have a way to match it another way. */ void server_set_last_used_server (Server * server, const gchar * uri) { g_return_if_fail(IS_SERVER(server)); if (g_strcmp0(server->uri, uri) == 0) { server->last_used = TRUE; } else { ServerClass * klass = SERVER_GET_CLASS(server); if (klass->set_last_used_server != NULL) { klass->set_last_used_server(server, uri); } } }
static void sig_disconnected(SERVER_REC *server) { WINDOW_REC *window; GSList *tmp; g_return_if_fail(IS_SERVER(server)); for (tmp = server->channels; tmp != NULL; tmp = tmp->next) { CHANNEL_REC *channel = tmp->data; window = window_item_window((WI_ITEM_REC *) channel); window->waiting_channels = g_slist_append(window->waiting_channels, g_strdup_printf("%s %s", server->tag, channel->name)); } }
GSList *nicklist_get_same(SERVER_REC *server, const char *nick) { NICKLIST_GET_SAME_REC rec; GSList *tmp; g_return_val_if_fail(IS_SERVER(server), NULL); rec.nick = nick; rec.list = NULL; for (tmp = server->channels; tmp != NULL; tmp = tmp->next) { rec.channel = tmp->data; g_hash_table_foreach(rec.channel->nicks, (GHFunc) get_nicks_same_hash, &rec); } return rec.list; }
/** * server_find_uri: * @server: Server to look in * @uri: URI to search for * * Checks the URI of this server to see if it matches, and then look * to see if subclasses have a way to match it another way. */ Server * server_find_uri (Server * server, const gchar * uri) { g_return_val_if_fail(IS_SERVER(server), NULL); if (g_strcmp0(server->uri, uri) == 0) { return server; } ServerClass * klass = SERVER_GET_CLASS(server); if (klass->find_uri != NULL) { return klass->find_uri(server, uri); } return NULL; }
/* Return query where to put the private message. */ QUERY_REC *privmsg_get_query(SERVER_REC *server, const char *nick, int own, int level) { QUERY_REC *query; g_return_val_if_fail(IS_SERVER(server), NULL); g_return_val_if_fail(nick != NULL, NULL); query = query_find(server, nick); if (query == NULL && (querycreate_level & level) != 0 && (!own || settings_get_bool("autocreate_own_query"))) { query = CHAT_PROTOCOL(server)-> query_create(server->tag, nick, TRUE); } return query; }
int mask_match_address(SERVER_REC *server, const char *mask, const char *nick, const char *address) { char *str; int ret, wildcards; g_return_val_if_fail(server == NULL || IS_SERVER(server), FALSE); g_return_val_if_fail(mask != NULL && nick != NULL, FALSE); if (address == NULL) address = ""; str = !check_address(mask, &wildcards) ? (char *) nick : g_strdup_printf("%s!%s", nick, address); ret = check_mask(server, mask, str, wildcards); if (str != nick) g_free(str); return ret; }
void server_disconnect(SERVER_REC *server) { int chans; g_return_if_fail(IS_SERVER(server)); if (server->disconnected) return; if (server->connect_tag != -1) { /* still connecting to server.. */ if (server->connect_pid != -1) net_disconnect_nonblock(server->connect_pid); server_connect_failed(server, NULL); return; } servers = g_slist_remove(servers, server); server->disconnected = TRUE; signal_emit("server disconnected", 1, server); /* close all channels */ chans = server_remove_channels(server); if (server->handle != NULL) { if (!chans || server->connection_lost) net_sendbuffer_destroy(server->handle, TRUE); else { /* we were on some channels, try to let the server disconnect so that our quit message is guaranteed to get displayed */ net_disconnect_later(net_sendbuffer_handle(server->handle)); net_sendbuffer_destroy(server->handle, FALSE); } server->handle = NULL; } if (server->readtag > 0) { g_source_remove(server->readtag); server->readtag = -1; } server_unref(server); }
ModeAction OnModeChange(User* source, User* dest, Channel* chan, std::string& parameter, bool adding) { if (dest->IsModeSet(GetModeChar()) == adding) return MODEACTION_DENY; dest->SetMode(GetModeChar(), adding); LocalUser* const localuser = IS_LOCAL(dest); // Send snotices char snodest = localuser ? 'v' : 'V'; if (snoonset && adding) ServerInstance->SNO->WriteToSnoMask(snodest, "Oper %s has turned on override", dest->nick.c_str()); else if (!adding) { // IS_OPER check is needed to make sure we don't send snotices when the server unsets // the mode due to deopering if ((snoonunset) && (IS_OPER(dest)) && (!IS_SERVER(source))) ServerInstance->SNO->WriteToSnoMask(snodest, "Oper %s has turned off override", dest->nick.c_str()); } // Ignore remote users, their own server handles them if (localuser) { if (adding) { if (activetime > 0) activeopers.push_back(ActiveOper(localuser)); } else { // Remove this oper from the list for (ActiveOperList::iterator i = activeopers.begin(); i != activeopers.end(); ++i) { ActiveOper& item = *i; if (item.uuid == dest->uuid) { activeopers.erase(i); break; } } } } return MODEACTION_ALLOW; }