void KviIsOnNotifyListManager::newUserhostSession() { buildUserhostList(); if(m_pUserhostList->isEmpty()) { // this is unexpected! m_pConsole->output(KVI_OUT_SYSTEMWARNING,__tr2qs("Notify list: Unexpected inconsistency, userhost list is empty!")); if(m_pOnlineList->isEmpty()) { if(m_pNotifyList->isEmpty())delayedNotifySession(); else delayedIsOnSession(); } else delayedUserhostSession(); return; } sendUserhost(); }
bool KviIsOnNotifyListManager::handleUserhost(KviIrcMessage * msg) { if(!m_bExpectingUserhost) return false; // first check for consistency: all the replies must be on the USERHOST list KviPointerList<KviIrcMask> tmplist; tmplist.setAutoDelete(true); KviCString nk; const char * aux = msg->trailing(); while(*aux) { nk = ""; aux = kvi_extractToken(nk, aux, ' '); if(nk.hasData()) { // split it in a mask KviCString nick; KviCString user; KviCString host; int idx = nk.findFirstIdx('='); if(idx != -1) { nick = nk.left(idx); if(nick.lastCharIs('*')) nick.cutRight(1); nk.cutLeft(idx + 1); if(nk.firstCharIs('+') || nk.firstCharIs('-')) nk.cutLeft(1); idx = nk.findFirstIdx('@'); if(idx != -1) { user = nk.left(idx); nk.cutLeft(idx + 1); host = nk; } else { user = "******"; host = nk; } bool bGotIt = false; QString szNick = m_pConnection->decodeText(nick.ptr()); QString szUser = m_pConnection->decodeText(user.ptr()); QString szHost = m_pConnection->decodeText(host.ptr()); for(QString * s = m_pUserhostList->first(); s && (!bGotIt); s = m_pUserhostList->next()) { if(KviQString::equalCI(*s, szNick)) { KviIrcMask * mk = new KviIrcMask(szNick, szUser, szHost); tmplist.append(mk); bGotIt = true; m_pUserhostList->removeRef(s); } } if(!bGotIt) { // ops...not my userhost! if(_OUTPUT_VERBOSE) m_pConsole->output(KVI_OUT_SYSTEMWARNING, __tr2qs("Notify list: Hey! You've used USERHOST behind my back? (I might be confused now...)")); return false; } } else { if(_OUTPUT_VERBOSE) m_pConsole->output(KVI_OUT_SYSTEMWARNING, __tr2qs("Notify list: Broken USERHOST reply from the server? (%s)"), nk.ptr()); } } } // Ok...looks to be my usershot (still not sure at 100%, but can't do better) if(m_pConnection->lagMeter()) m_pConnection->lagMeter()->lagCheckComplete("@notify_userhost"); m_bExpectingUserhost = false; for(KviIrcMask * mk = tmplist.first(); mk; mk = tmplist.next()) { if(!doMatchUser(mk->nick(), *mk)) return true; // have to restart!!! } if(!(m_pUserhostList->isEmpty())) { // ops...someone is no longer online ? while(QString * s = m_pUserhostList->first()) { if(_OUTPUT_VERBOSE) m_pConsole->output(KVI_OUT_SYSTEMMESSAGE, __tr2qs("Notify list: \r!n\r%Q\r appears to have gone offline before USERHOST reply was received, will recheck in the next loop"), s); m_pUserhostList->removeFirst(); } } if(m_pOnlineList->isEmpty()) { if(m_pNotifyList->isEmpty()) delayedNotifySession(); else delayedIsOnSession(); } else delayedUserhostSession(); return true; }
bool KviIsOnNotifyListManager::handleIsOn(KviIrcMessage * msg) { if(!m_bExpectingIsOn) return false; // Check if it is our ISON // all the nicks must be on the IsOnList KviPointerList<QString> tmplist; tmplist.setAutoDelete(false); KviCString nk; const char * aux = msg->trailing(); while(*aux) { nk = ""; aux = kvi_extractToken(nk, aux, ' '); if(nk.hasData()) { bool bGotIt = false; QString dnk = m_pConnection->decodeText(nk.ptr()); for(QString * s = m_pIsOnList->first(); s && (!bGotIt); s = m_pIsOnList->next()) { if(KviQString::equalCI(*s, dnk)) { tmplist.append(s); bGotIt = true; } } if(!bGotIt) { // ops...not my userhost! if(_OUTPUT_VERBOSE) m_pConsole->output(KVI_OUT_SYSTEMMESSAGE, __tr2qs("Notify list: Hey! You've used ISON behind my back? (I might be confused now...)")); return false; } } } // Ok...looks to be my ison (still not sure at 100%, but can't do better) if(m_pConnection->lagMeter()) m_pConnection->lagMeter()->lagCheckComplete("@notify_ison"); m_bExpectingIsOn = false; m_pOnlineList->clear(); m_pIsOnList->setAutoDelete(false); // Ok...we have an IsOn reply here // The nicks in the IsOnList that are also in the reply are online, and go to the OnlineList // the remaining in the IsOnList are offline QString * s; for(s = tmplist.first(); s; s = tmplist.next()) { m_pIsOnList->removeRef(s); m_pOnlineList->append(s); } m_pIsOnList->setAutoDelete(true); // Ok...all the users that are online, are on the OnlineList // the remaining users are in the m_pIsOnList, and are no longer online // first the easy step: remove the users that have just left irc or have never been online // we're clearling the m_pIsOnList while((s = m_pIsOnList->first())) { if(m_pConsole->notifyListView()->findEntry(*s)) { // has just left IRC... make him part notifyOffLine(*s); } // else has never been here m_pIsOnList->removeFirst(); // autodelete is true } // ok... complex step now: the remaining users in the userhost list are online // if they have been online before, just remove them from the list // otherwise they must be matched for masks // and eventually inserted in the notify view later KviIrcUserDataBase * db = console()->connection()->userDataBase(); KviPointerList<QString> l; l.setAutoDelete(false); for(s = m_pOnlineList->first(); s; s = m_pOnlineList->next()) { if(KviUserListEntry * ent = m_pConsole->notifyListView()->findEntry(*s)) { // the user was online from a previous notify session // might the mask have been changed ? (heh...this is tricky, maybe too much even) if(KVI_OPTION_BOOL(KviOption_boolNotifyListSendUserhostForOnlineUsers)) { // user wants to be sure about online users.... // check if he is on some channels if(ent->globalData()->nRefs() > 1) { // mmmh...we have more than one ref, so the user is at least in one query or channel // look him up on channels, if we find his entry, we can be sure that he is // still the right user KviPointerList<KviChannelWindow> * chlist = m_pConsole->connection()->channelList(); for(KviChannelWindow * ch = chlist->first(); ch; ch = chlist->next()) { if(KviUserListEntry * le = ch->findEntry(*s)) { l.append(s); // ok...found on a channel...we don't need a userhost to match him KviIrcMask mk(*s, le->globalData()->user(), le->globalData()->host()); if(!doMatchUser(*s, mk)) return true; // critical problems = have to restart!!! break; } } } // else Only one ref...we need a userhost to be sure (don't remove from the list) } else { // user wants no userhost for online users...we "hope" that everything will go ok. l.append(s); } //l.append(s); // we will remove him from the list } else { // the user was not online! // check if we have a cached mask if(db) { if(KviIrcUserEntry * ue = db->find(*s)) { // already in the db... do we have a mask ? if(ue->hasUser() && ue->hasHost()) { // yup! we have a complete mask to match on KviIrcMask mk(*s, ue->user(), ue->host()); // lookup the user's name in the m_pRegUserDict if(!doMatchUser(*s, mk)) return true; // critical problems = have to restart!!! l.append(s); // remove anyway } } } } } for(s = l.first(); s; s = l.next()) { m_pOnlineList->removeRef(s); // autodelete is true } if(m_pOnlineList->isEmpty()) { if(m_pNotifyList->isEmpty()) delayedNotifySession(); else delayedIsOnSession(); } else delayedUserhostSession(); return true; }
bool KviIsOnNotifyListManager::handleUserhost(KviIrcMessage * msg) { if(!m_bExpectingUserhost) return false; // first check for consistency: all the replies must be on the USERHOST list std::map<std::size_t, std::unique_ptr<KviIrcMask>> tmplist; KviCString nk; const char * aux = msg->trailing(); while(*aux) { nk = ""; aux = kvi_extractToken(nk, aux, ' '); if(nk.hasData()) { // split it in a mask KviCString nick; KviCString user; KviCString host; int idx = nk.findFirstIdx('='); if(idx != -1) { nick = nk.left(idx); if(nick.lastCharIs('*')) nick.cutRight(1); nk.cutLeft(idx + 1); if(nk.firstCharIs('+') || nk.firstCharIs('-')) nk.cutLeft(1); idx = nk.findFirstIdx('@'); if(idx != -1) { user = nk.left(idx); nk.cutLeft(idx + 1); host = nk; } else { user = "******"; host = nk; } bool bGotIt = false; QString szNick = m_pConnection->decodeText(nick.ptr()); QString szUser = m_pConnection->decodeText(user.ptr()); QString szHost = m_pConnection->decodeText(host.ptr()); std::size_t i = 0; for(const auto & s : m_UserhostList) { if(KviQString::equalCI(s, szNick)) { tmplist.emplace(i, std::make_unique<KviIrcMask>(szNick, szUser, szHost)); bGotIt = true; break; } } if(!bGotIt) { // oops... not my userhost! if(_OUTPUT_VERBOSE) m_pConsole->output(KVI_OUT_SYSTEMWARNING, __tr2qs("Notify list: Hey! You've used USERHOST behind my back? (I might be confused now...)")); return false; } } else { if(_OUTPUT_VERBOSE) m_pConsole->output(KVI_OUT_SYSTEMWARNING, __tr2qs("Notify list: Broken USERHOST reply from the server? (%s)"), nk.ptr()); } } } // Ok... looks to be my usershot (still not sure at 100%, but can't do better) if(m_pConnection->lagMeter()) m_pConnection->lagMeter()->lagCheckComplete("@notify_userhost"); m_bExpectingUserhost = false; for(auto & pair : tmplist) { KviIrcMask * mk = pair.second.get(); if(!doMatchUser(mk->nick(), *mk)) return true; // have to restart!!! } for(auto i = tmplist.rbegin(); i != tmplist.rend(); ++i) m_UserhostList.erase(m_UserhostList.begin() + i->first); for(const auto & s : m_UserhostList) { // oops... someone is no longer online ? if(_OUTPUT_VERBOSE) m_pConsole->output(KVI_OUT_SYSTEMMESSAGE, __tr2qs("Notify list: \r!n\r%Q\r appears to have gone offline before USERHOST reply was received, will recheck in the next loop"), &s); } m_UserhostList.clear(); if(m_OnlineList.empty()) { if(m_NotifyList.empty()) delayedNotifySession(); else delayedIsOnSession(); } else { delayedUserhostSession(); } return true; }