KviIrcServer * KviIrcNetwork::findServer(const KviIrcServer * pServer) { for (KviIrcServer *s = m_pServerList->first(); s; s = m_pServerList->next()) { // we better go with the unique id first if(!s->id().isEmpty()) { // at least one of the 2 id is not empty, so if they match we're done if(KviQString::equalCI(s->id(), pServer->id())) return s; } else { // failback on the "check everything" method if (KviQString::equalCI(s->hostName(), pServer->hostName()) && (s->port() == pServer->port()) && (s->useSSL() == pServer->useSSL()) && (s->isIPv6() == pServer->isIPv6())) return s; } } return 0; }
bool KviIrcServerDataBase::makeCurrentServer(KviIrcServerDefinition * pDef, QString & szError) { KviIrcServer * pServer = 0; KviPointerHashTableIterator<QString,KviIrcNetwork> it(*m_pRecords); KviIrcNetwork * pNet = 0; KviIrcServer * pServ; if(KviQString::equalCIN(pDef->szServer,"net:",4)) { // net:networkname form QString szNet = pDef->szServer; szNet.remove(0,4); KviIrcNetwork * pNet = m_pRecords->find(szNet); if(pNet) return makeCurrentBestServerInNetwork(szNet,pNet,szError); szError = __tr2qs("The server specification seems to be in the net:<string> but the network couldn't be found in the database"); return false; } if(KviQString::equalCIN(pDef->szServer,"id:",3)) { // id:serverid form QString szId = pDef->szServer; szId.remove(0,3); while((pNet = it.current())) { for(pServ = pNet->serverList()->first(); pServ && (!pServer); pServ = pNet->serverList()->next()) { if(KviQString::equalCI(pServ->id(),szId)) { pServer = pServ; goto search_finished; } } ++it; } szError = __tr2qs("The server specification seems to be in the id:<string> form but the identifier couldn't be found in the database"); return false; } it.toFirst(); while((pNet = it.current())) { for(pServ = pNet->serverList()->first(); pServ && (!pServer); pServ = pNet->serverList()->next()) { if(KviQString::equalCI(pServ->hostName(),pDef->szServer)) { if(pDef->szId.isEmpty() || KviQString::equalCI(pServ->id(),pDef->szId)) { if(pDef->bIPv6 == pServ->isIPv6()) { if(pDef->bSSL == pServ->useSSL()) { if(pDef->bPortIsValid) { // must match the port if(pDef->uPort == pServ->port()) { // port matches if(!pDef->szLinkFilter.isEmpty()) { // must match the link filter if(KviQString::equalCI(pDef->szLinkFilter,pServ->linkFilter())) { // link filter matches pServer = pServ; goto search_finished; } // else link filter doesn't match } else { // no need to match the link filter pServer = pServ; goto search_finished; } } // else port doesn't match } else { // no need to match the port if(!pDef->szLinkFilter.isEmpty()) { // must match the link filter if(KviQString::equalCI(pDef->szLinkFilter,pServ->linkFilter())) { // link filter matches pServer = pServ; goto search_finished; } // else link filter doesn't match } else { // no need to match the link filter pServer = pServ; goto search_finished; } } } } } } } ++it; } search_finished: if(pNet && pServer) { m_szCurrentNetwork = pNet->name(); pNet->setCurrentServer(pServer); return true; } // no such server: is it a valid ip address or hostname ? bool bIsValidIPv4 = KviNetUtils::isValidStringIp(pDef->szServer); #ifdef COMPILE_IPV6_SUPPORT bool bIsValidIPv6 = KviNetUtils::isValidStringIPv6(pDef->szServer); #else bool bIsValidIPv6 = false; #endif if(!(bIsValidIPv4 || bIsValidIPv6)) { // is it a valid hostname ? (must contain at least one dot) if(!pDef->szServer.contains('.')) { // assume it is a network name! KviIrcNetwork * pNet = m_pRecords->find(pDef->szServer); if(pNet) return makeCurrentBestServerInNetwork(pDef->szServer,pNet,szError); // else probably not a network name } } // a valid hostname or ip address, not found in list : add it and make it current pNet = m_pRecords->find(__tr2qs("Standalone Servers")); if(!pNet) { pNet = new KviIrcNetwork(__tr2qs("Standalone Servers")); m_pRecords->replace(pNet->name(),pNet); } KviIrcServer * pSrv = new KviIrcServer(); pSrv->setHostName(pDef->szServer); if(bIsValidIPv4) { pSrv->setIp(pDef->szServer); pSrv->setCacheIp(true); #ifdef COMPILE_IPV6_SUPPORT } else { if(bIsValidIPv6) { pSrv->setIp(pDef->szServer); pSrv->setCacheIp(true); pDef->bIPv6 = true; } } #else }
void KviIrcContext::connectToCurrentServer() { if(m_pReconnectTimer) { delete m_pReconnectTimer; m_pReconnectTimer = nullptr; } m_pConsole->outputNoFmt(KVI_OUT_SYSTEMMESSAGE, " "); // spacer // No connection target specified. // If we have a saved target, reuse it if(!m_pAsynchronousConnectionData && m_pSavedAsynchronousConnectionData) { m_pAsynchronousConnectionData = m_pSavedAsynchronousConnectionData; m_pSavedAsynchronousConnectionData = nullptr; } if(m_pAsynchronousConnectionData) { // we have a specified connection target (either from outside or saved) if(m_pAsynchronousConnectionData->szServer.isEmpty()) { // an empty server might mean "reuse the last server in context" if(m_pAsynchronousConnectionData->bUseLastServerInContext && m_pSavedAsynchronousConnectionData) { // reuse the saved connection data // the server for sure m_pAsynchronousConnectionData->szServer = m_pSavedAsynchronousConnectionData->szServer; m_pAsynchronousConnectionData->szServerId = m_pSavedAsynchronousConnectionData->szServerId; m_pAsynchronousConnectionData->uPort = m_pSavedAsynchronousConnectionData->uPort; m_pAsynchronousConnectionData->bPortIsOk = true; m_pAsynchronousConnectionData->bUseIPv6 = m_pSavedAsynchronousConnectionData->bUseIPv6; m_pAsynchronousConnectionData->bUseSSL = m_pSavedAsynchronousConnectionData->bUseSSL; m_pAsynchronousConnectionData->bSTARTTLS = m_pSavedAsynchronousConnectionData->bSTARTTLS; if(m_pSavedAsynchronousConnectionData->m_pReconnectInfo) m_pAsynchronousConnectionData->m_pReconnectInfo = new KviIrcServerReconnectInfo(*(m_pSavedAsynchronousConnectionData->m_pReconnectInfo)); else m_pAsynchronousConnectionData->m_pReconnectInfo = nullptr; // and the other info, only if not overridden by the user if(m_pAsynchronousConnectionData->szBindAddress.isEmpty()) m_pAsynchronousConnectionData->szBindAddress = m_pSavedAsynchronousConnectionData->szBindAddress; if(m_pAsynchronousConnectionData->szCommandToExecAfterConnect.isEmpty()) m_pAsynchronousConnectionData->szCommandToExecAfterConnect = m_pSavedAsynchronousConnectionData->szCommandToExecAfterConnect; if(m_pAsynchronousConnectionData->szLinkFilter.isEmpty()) m_pAsynchronousConnectionData->szLinkFilter = m_pSavedAsynchronousConnectionData->szLinkFilter; if(m_pAsynchronousConnectionData->szPass.isEmpty()) m_pAsynchronousConnectionData->szPass = m_pSavedAsynchronousConnectionData->szPass; if(m_pAsynchronousConnectionData->szNick.isEmpty()) m_pAsynchronousConnectionData->szNick = m_pSavedAsynchronousConnectionData->szNick; if(m_pAsynchronousConnectionData->szInitUMode.isEmpty()) m_pAsynchronousConnectionData->szInitUMode = m_pSavedAsynchronousConnectionData->szInitUMode; } else { m_pConsole->outputNoFmt(KVI_OUT_SYSTEMWARNING, __tr2qs("This is the first connection in this IRC context: using the global server setting")); } } if(!m_pAsynchronousConnectionData->szServer.isEmpty()) { // !m_pAsynchronousConnectionData->szServer.isEmpty() // ok, have a server to look for in the db // FIXME: this is a bit ugly... could it be managed in some completely different and nicer way ? KviIrcServerDefinition d; d.szServer = m_pAsynchronousConnectionData->szServer; d.bPortIsValid = m_pAsynchronousConnectionData->bPortIsOk; d.uPort = m_pAsynchronousConnectionData->uPort; d.bIPv6 = m_pAsynchronousConnectionData->bUseIPv6; d.bSSL = m_pAsynchronousConnectionData->bUseSSL; d.bSTARTTLS = m_pAsynchronousConnectionData->bSTARTTLS; d.szLinkFilter = m_pAsynchronousConnectionData->szLinkFilter; d.szPass = m_pAsynchronousConnectionData->szPass; d.szNick = m_pAsynchronousConnectionData->szNick; d.szInitUMode = m_pAsynchronousConnectionData->szInitUMode; d.szId = m_pAsynchronousConnectionData->szServerId; QString szError; if(!g_pServerDataBase->makeCurrentServer(&d, szError)) { m_pConsole->outputNoFmt(KVI_OUT_SYSTEMERROR, szError); destroyAsynchronousConnectionData(); return; } } // else we just connect to the globally selected IRC server in the options dialog } KviIrcNetwork * net = g_pServerDataBase->currentNetwork(); KviIrcServer * srv = net ? net->currentServer() : nullptr; if(!srv) { if(g_pServerDataBase->networkCount()) KviKvsScript::run("options.edit -n OptionsWidget_servers", m_pConsole); else m_pConsole->outputNoFmt(KVI_OUT_SYSTEMERROR, __tr2qs("No servers available. Check the options dialog or use the /SERVER command")); destroyAsynchronousConnectionData(); return; } KviProxy * prx = srv->proxyServer(g_pProxyDataBase); if(!prx && (srv->proxy() != -1) && KVI_OPTION_BOOL(KviOption_boolUseProxyHost)) { prx = g_pProxyDataBase->currentProxy(); if(!prx) { m_pConsole->outputNoFmt(KVI_OUT_SYSTEMWARNING, __tr2qs("No proxy hosts available, resuming direct connection")); } } QString szBindAddress; srv->clearReconnectInfo(); if(m_pAsynchronousConnectionData) { szBindAddress = m_pAsynchronousConnectionData->szBindAddress; if(m_pAsynchronousConnectionData->m_pReconnectInfo) srv->setReconnectInfo(new KviIrcServerReconnectInfo(*(m_pAsynchronousConnectionData->m_pReconnectInfo))); } // Find out the identity we'll be using in this connection // First check the server for one const KviUserIdentity * pIdentity = nullptr; QString szUserIdentityId = srv->userIdentityId(); if(!szUserIdentityId.isEmpty()) pIdentity = KviUserIdentityManager::instance()->findIdentity(szUserIdentityId); // If not found, look in the network instead if(!pIdentity) szUserIdentityId = net->userIdentityId(); if(!szUserIdentityId.isEmpty()) pIdentity = KviUserIdentityManager::instance()->findIdentity(szUserIdentityId); // If not found, get the default identity (this is GRANTED to be never null, eventually filled up with defaults) pIdentity = KviUserIdentityManager::instance()->defaultIdentity(); if(m_pConnection) delete m_pConnection; m_pConnection = new KviIrcConnection( this, new KviIrcConnectionTarget( net, srv, prx, szBindAddress), new KviUserIdentity(*pIdentity)); setState(Connecting); if(m_pAsynchronousConnectionData) { m_pConnection->stateData()->setCommandToExecAfterConnect(m_pAsynchronousConnectionData->szCommandToExecAfterConnect); destroyAsynchronousConnectionData(); } m_pConsole->connectionAttached(); // save stuff for later // FIXME: this management of "next" connection should be reviewed a bit anyway if(m_pSavedAsynchronousConnectionData) delete m_pSavedAsynchronousConnectionData; m_pSavedAsynchronousConnectionData = new KviAsynchronousConnectionData(); m_pSavedAsynchronousConnectionData->szServer = srv->hostName(); m_pSavedAsynchronousConnectionData->uPort = srv->port(); m_pSavedAsynchronousConnectionData->bPortIsOk = true; m_pSavedAsynchronousConnectionData->bUseIPv6 = srv->isIPv6(); m_pSavedAsynchronousConnectionData->bUseSSL = srv->useSSL(); m_pSavedAsynchronousConnectionData->bSTARTTLS = srv->enabledSTARTTLS(); m_pSavedAsynchronousConnectionData->szPass = srv->password(); m_pSavedAsynchronousConnectionData->szServerId = srv->id(); m_pSavedAsynchronousConnectionData->szInitUMode = srv->initUMode(); if(srv->reconnectInfo()) m_pSavedAsynchronousConnectionData->m_pReconnectInfo = new KviIrcServerReconnectInfo(*(srv->reconnectInfo())); else m_pSavedAsynchronousConnectionData->m_pReconnectInfo = nullptr; // this never fails! m_pConnection->start(); }
int KviIrcUrl::run(const QString & text, int contextSpec, KviConsoleWindow * pConsole) { // first, sanity check the url QString cmdBuffer; QString szJoinCommand; KviIrcUrlParts parts; bool bAlreadyConnected = false; KviIrcUrl::split(text, parts); if(parts.iError & KviIrcUrl::InvalidProtocol || parts.iError & KviIrcUrl::InvalidUrl) { // invalid proto return parts.iError; } g_pApp->addRecentUrl(text); makeJoinCmd(parts.chanList, szJoinCommand); // then, get a context if((contextSpec & CurrentContext) && !pConsole) contextSpec = FirstFreeContext; if(contextSpec & TryCurrentContext) { if(pConsole) { KviConsoleWindow * pTmpConsole = pConsole; pConsole = nullptr; if(pTmpConsole->connection()) { KviIrcServer * server = pTmpConsole->connection()->target()->server(); if( (server->hostName() == parts.szHost) && (server->port() == parts.iPort) && (server->useSSL() == parts.bSsl) && (server->isIPv6() == parts.bIPv6)) { pConsole = pTmpConsole; bAlreadyConnected = true; } } if(!pConsole) contextSpec = FirstFreeContext; } else { contextSpec = FirstFreeContext; } } if(contextSpec & TryEveryContext) { KviConsoleWindow * pTmpConsole = nullptr; pConsole = nullptr; for(auto & wnd : g_pGlobalWindowDict) { if(wnd.second->type() == KviWindow::Console) { pTmpConsole = (KviConsoleWindow *)wnd.second; if(pTmpConsole->connection()) { KviIrcServer * server = pTmpConsole->connection()->target()->server(); if( (server->hostName() == parts.szHost) && (server->port() == parts.iPort) && (server->useSSL() == parts.bSsl) && (server->isIPv6() == parts.bIPv6)) { pConsole = pTmpConsole; bAlreadyConnected = true; break; } } } } if(!pConsole) contextSpec = FirstFreeContext; } if(contextSpec & FirstFreeContext) { if(pConsole) { if(pConsole->connectionInProgress()) { pConsole = g_pMainWindow->firstNotConnectedConsole(); if(!pConsole) { pConsole = g_pMainWindow->createNewConsole(); } } } else { pConsole = g_pMainWindow->firstNotConnectedConsole(); if(!pConsole) { pConsole = g_pMainWindow->createNewConsole(); } } } if(bAlreadyConnected) { // we already have a connected context to the right server on pConsole // just check if thr user want us to join or part any channel QString tmp; QString toPart; for(auto & c : pConsole->connection()->channelList()) { tmp = c->target(); if(c->hasChannelMode('k')) { tmp.append("?"); tmp.append(c->channelModeParam('k')); } if(!parts.chanList.removeAll(tmp)) { toPart.append(c->target()); toPart.append(","); } } if(!(contextSpec & DoNotPartChans)) { makeJoinCmd(parts.chanList, szJoinCommand); if(!toPart.isEmpty()) { toPart.prepend("part "); KviKvsScript::run(toPart, pConsole); } } if(!szJoinCommand.isEmpty()) { pConsole->connection()->sendData(pConsole->connection()->encodeText(szJoinCommand).data()); } return parts.iError; } else { // we need to create a new connection on the context of pConsole QString szCommand("server "); if(parts.bSsl) szCommand.append("-s "); if(parts.bIPv6) szCommand.append("-i "); if(!szJoinCommand.isEmpty()) { szCommand.append("-c=\""); szCommand.append(szJoinCommand); szCommand.append("\" "); } szCommand.append(QString("%1 %2 ").arg(parts.szHost).arg(parts.iPort)); KviKvsScript::run(szCommand, (contextSpec & TryCurrentContext) ? g_pMainWindow->createNewConsole() : pConsole); return parts.iError; } }