void RegisteredUserEntryDialog::notifyCheckClicked(bool bChecked) { m_pNotifyNick->setEnabled(bChecked); m_pNotifyLabel->setEnabled(bChecked); if(bChecked && m_pNotifyNick->text().isEmpty()) { QString szMask; if(m_pUser) { for(KviIrcMask * m = m_pUser->maskList()->first();m;m = m_pUser->maskList()->next()) { QString tmp = m->nick(); if((tmp.indexOf('*') == -1) && (tmp.indexOf('?') == -1) && (!tmp.isEmpty())) { if(!szMask.isEmpty())szMask.append(' '); szMask.append(tmp); } } // if the nickname list is still empty, build a dummy nick to notify if(szMask.isEmpty()) { szMask = m_pUser->name(); szMask.replace(" ",""); szMask.replace("'",""); szMask.replace("&",""); szMask.replace(",",""); } m_pNotifyNick->setText(szMask); } } }
bool KviRegisteredUser::matchesFixed(const QString & nick,const QString & user,const QString & host) { for(KviIrcMask * m = m_pMaskList->first();m;m = m_pMaskList->next()) { if(m->matchesFixed(nick,user,host))return true; } return false; }
bool KviRegisteredUser::matchesFixed(const KviIrcMask &mask) { for(KviIrcMask * m = m_pMaskList->first();m;m = m_pMaskList->next()) { if(m->matchesFixed(mask))return true; } return false; }
void RegisteredUsersDialog::itemPressed(QTreeWidgetItem * it, int c) { if(!it) return; RegisteredUsersDialogItemBase * b = (RegisteredUsersDialogItemBase *)it; if(b->type() == RegisteredUsersDialogItemBase::User) { RegisteredUsersDialogItem * i = (RegisteredUsersDialogItem *)it; QRect r = m_pListView->visualItemRect(i); int daw = m_pListView->columnWidth(0); QPoint ppp = m_pListView->mapFromGlobal(QCursor::pos()); if((c == 1) && (ppp.x() < (r.height() + 5 + daw))) { // notify list toggle if(i->user()->getProperty("notify").isEmpty()) { // try to find the nicknames to be notified QString szMask; for(KviIrcMask * m = i->user()->maskList()->first(); m; m = i->user()->maskList()->next()) { QString tmp = m->nick(); if((tmp.indexOf('*') == -1) && (tmp.indexOf('?') == -1) && (!tmp.isEmpty())) { if(!szMask.isEmpty()) szMask.append(' '); szMask.append(tmp); } } // if the nickname list is still empty, build a dummy nick to notify if(szMask.isEmpty()) { szMask = i->user()->name(); szMask.replace(" ", ""); szMask.replace("'", ""); szMask.replace("&", ""); szMask.replace(",", ""); } i->user()->setProperty("notify", szMask); } else { i->user()->setProperty("notify", QString("")); // kill that } m_pListView->repaint(r); } } }
void RegisteredUserEntryDialog::addMaskClicked() { KviIrcMask mk; RegisteredUserMaskDialog * dlg = new RegisteredUserMaskDialog(this,&mk); if(dlg->exec() == QDialog::Accepted) { QString m = mk.nick(); m += QChar('!'); m += mk.user(); m += QChar('@'); m += mk.host(); m_pMaskListBox->addItem(m); } delete dlg; }
void KviRegisteredUserDataBase::save(const QString & szFilename) { KviConfigurationFile cfg(szFilename, KviConfigurationFile::Write); cfg.clear(); cfg.preserveEmptyGroups(true); KviPointerHashTableIterator<QString, KviRegisteredUser> it(*m_pUserDict); while(it.current()) { cfg.setGroup(it.current()->name()); // Write properties cfg.writeEntry("IgnoreEnabled", it.current()->ignoreEnabled()); cfg.writeEntry("IgnoreFlags", it.current()->ignoreFlags()); if(it.current()->propertyDict()) { KviPointerHashTableIterator<QString, QString> pit(*(it.current()->propertyDict())); while(pit.current()) { QString tmp = "prop_"; tmp.append(pit.currentKey()); cfg.writeEntry(tmp, *(pit.current())); ++pit; } } // Write masks int i = 0; for(KviIrcMask * pMask = it.current()->maskList()->first(); pMask; pMask = it.current()->maskList()->next()) { QString szTmp = QString("mask_%1").arg(i); QString szMask; pMask->mask(szMask, KviIrcMask::NickUserHost); cfg.writeEntry(szTmp, szMask); ++i; } cfg.writeEntry("Group", it.current()->group()); ++it; } KviPointerHashTableIterator<QString, KviRegisteredUserGroup> git(*m_pGroupDict); QString szTmp; while(git.current()) { szTmp = QString("#Group %1").arg(git.current()->name()); cfg.setGroup(szTmp); ++git; } }
void KviAvatarCache::remove(const KviIrcMask &mask,const QString &szNetwork) { QString szKey; mask.mask(szKey,KviIrcMask::NickCleanUserSmartNet); szKey.append(QChar('+')); szKey.append(szNetwork); m_pAvatarDict->remove(szKey); }
bool KviIsOnNotifyListManager::doMatchUser(const QString & notifyString, const KviIrcMask & mask) { const auto i = m_pRegUserDict.find(notifyString); if(i != m_pRegUserDict.end()) { const QString & nam = i->second; // ok... find the user if(KviRegisteredUser * u = g_pRegisteredUserDataBase->findUserByName(nam)) { // ok... match the user if(u->matchesFixed(mask)) { // new user online if(!(m_pConsole->notifyListView()->findEntry(mask.nick()))) { notifyOnLine(mask.nick(), mask.user(), mask.host()); } // else already online, and matching... all ok } else { // not matched.... has he been online before ? if(m_pConsole->notifyListView()->findEntry(mask.nick())) { // has been online just a sec ago, but now the mask does not match // either reguserdb has changed, or the user went offline and another one got his nick // in the meantime... (ugly situation anyway) notifyOffLine(mask.nick(), mask.user(), mask.host(), __tr2qs("registration mask changed, or nickname is being used by someone else")); } else { // has never been online if(_OUTPUT_VERBOSE) m_pConsole->output(KVI_OUT_SYSTEMMESSAGE, __tr2qs("Notify list: \r!n\r%Q\r appears to be online, but the mask [%Q@\r!h\r%Q\r] does not match (registration mask does not match, or nickname is being used by someone else)"), &(mask.nick()), &(mask.user()), &(mask.host())); } } } else { // oops... unexpected inconsistency.... reguser db modified ? m_pConsole->output(KVI_OUT_SYSTEMWARNING, __tr2qs("Notify list: Unexpected inconsistency, registered user DB modified? (restarting)")); stop(); start(); return false; // critical... exit from the call stack } } else { // oops... unexpected inconsistency m_pConsole->output(KVI_OUT_SYSTEMWARNING, __tr2qs("Notify list: Unexpected inconsistency, expected \r!n\r%Q\r in the registered user DB"), ¬ifyString); } return true; }
void KviAvatarCache::replace(const QString &szIdString,const KviIrcMask &mask,const QString &szNetwork) { QString szKey; mask.mask(szKey,KviIrcMask::NickCleanUserSmartNet); szKey.append(QChar('+')); szKey.append(szNetwork); KviAvatarCacheEntry * e = new KviAvatarCacheEntry; e->szIdString = szIdString; e->tLastAccess = kvi_unixTime(); m_pAvatarDict->replace(szKey,e); if(m_pAvatarDict->count() > MAX_AVATARS_IN_CACHE) { cleanup(); } }
RegisteredUserEntryDialog::RegisteredUserEntryDialog(QWidget *p,KviRegisteredUser * r,bool bModal) : KviTalTabDialog(p,"reguser_entry_editor",bModal) { m_pUser = r; m_pCustomColor = new QColor(); if(r) { QString col=r->getProperty("customColor"); KviStringConversion::fromString(col,(*m_pCustomColor)); } m_pPropertyDict = new KviPointerHashTable<QString,QString>(17,false); m_pPropertyDict->setAutoDelete(true); //setMinimumSize(400,450); setWindowIcon(*(g_pIconManager->getSmallIcon(KviIconManager::Linux))); setWindowTitle(__tr2qs_ctx("Registered User Entry","register")); QWidget * p1 = new QWidget(this); QGridLayout * g = new QGridLayout(p1); QLabel * l = new QLabel(__tr2qs_ctx("Name:","register"),p1); g->addWidget(l,0,0); m_pNameEdit = new QLineEdit(p1); g->addWidget(m_pNameEdit,0,1); l = new QLabel(__tr2qs_ctx("Comment:","register"),p1); g->addWidget(l,1,0); m_pCommentEdit = new QLineEdit(p1); g->addWidget(m_pCommentEdit,1,1); QFrame * f = new QFrame(p1); g->addWidget(f,2,0,1,2); f->setFrameStyle(QFrame::HLine | QFrame::Sunken); l = new QLabel(__tr2qs_ctx("Masks:","register"),p1); g->addWidget(l,3,0,1,2); m_pMaskListBox = new QListWidget(p1); connect(m_pMaskListBox,SIGNAL(itemSelectionChanged()),this,SLOT(maskCurrentChanged())); m_pMaskListBox->setMinimumSize(300,200); g->addWidget(m_pMaskListBox,4,0,1,2); KviTalHBox * b = new KviTalHBox(p1); g->addWidget(b,5,0,1,2); b->setSpacing(4); m_pAddMaskButton = new QPushButton(__tr2qs_ctx("&Add...","register"),b); connect(m_pAddMaskButton,SIGNAL(clicked()),this,SLOT(addMaskClicked())); m_pAddMaskButton->setIcon(*(g_pIconManager->getSmallIcon(KviIconManager::NewItem))); m_pDelMaskButton = new QPushButton(__tr2qs_ctx("Re&move","register"),b); m_pDelMaskButton->setEnabled(false); connect(m_pDelMaskButton,SIGNAL(clicked()),this,SLOT(delMaskClicked())); m_pDelMaskButton->setIcon(*(g_pIconManager->getSmallIcon(KviIconManager::DeleteItem))); m_pEditMaskButton = new QPushButton(__tr2qs_ctx("&Edit","register"),b); m_pEditMaskButton->setEnabled(false); connect(m_pEditMaskButton,SIGNAL(clicked()),this,SLOT(editMaskClicked())); m_pEditMaskButton->setIcon(*(g_pIconManager->getSmallIcon(KviIconManager::EditItem))); g->setRowStretch(4,1); g->setColumnStretch(1,1); addTab(p1,__tr2qs_ctx("Identity","register")); QWidget * p2 = new QWidget(this); g = new QGridLayout(p2); m_pNotifyCheck = new QCheckBox(__tr2qs_ctx("Notify when user is online","register"),p2); g->addWidget(m_pNotifyCheck,0,0,1,3); m_pNotifyLabel = new QLabel(__tr2qs_ctx("Notify nicknames:","register"),p2); m_pNotifyLabel->setEnabled(m_pNotifyCheck->isChecked()); g->addWidget(m_pNotifyLabel,1,0); m_pNotifyCheck->setToolTip(__tr2qs_ctx("<center>You can enter a space separated list of nicknames.</center>","register")); m_pNotifyNick = new QLineEdit(p2); m_pNotifyNick->setEnabled(false); g->addWidget(m_pNotifyNick,1,1,1,2); connect(m_pNotifyCheck,SIGNAL(toggled(bool)),this,SLOT(notifyCheckClicked(bool))); f = new QFrame(p2); f->setFrameStyle(QFrame::HLine | QFrame::Sunken); g->addWidget(f,2,0,1,3); m_pAvatar = 0; if(r) { const QString av = r->getProperty("avatar"); if(!av.isEmpty()) { m_pAvatar = new KviPixmap(av.toUtf8().data()); } } if(!m_pAvatar)m_pAvatar = new KviPixmap(); m_pAvatarSelector = new KviPixmapSelector(p2,__tr2qs_ctx("Avatar","register"),m_pAvatar,true); g->addWidget(m_pAvatarSelector,3,0,1,3); f = new QFrame(p2); f->setFrameStyle(QFrame::HLine | QFrame::Sunken); g->addWidget(f,4,0,1,3); m_pCustomColorCheck = new QCheckBox(__tr2qs_ctx("Use custom color in userlist","register"),p2); if(r) m_pCustomColorCheck->setChecked(r->getBoolProperty("useCustomColor")); g->addWidget(m_pCustomColorCheck,5,0,1,2); m_pCustomColorSelector = new KviColorSelector(p2,QString(),m_pCustomColor,1); g->addWidget(m_pCustomColorSelector,5,2); QPushButton * pb = new QPushButton(__tr2qs_ctx("All Properties...","register"),p2); connect(pb,SIGNAL(clicked()),this,SLOT(editAllPropertiesClicked())); g->addWidget(pb,6,2); g->setColumnStretch(1,1); g->setRowStretch(3,1); addTab(p2,__tr2qs_ctx("Properties","register")); // Ignore TAB KviTalVBox * vb = new KviTalVBox(this); vb->setMargin(10); m_pIgnoreEnabled = new QCheckBox(__tr2qs_ctx("Enable ignore for this user","register"),vb); QGroupBox * gb = new QGroupBox(__tr2qs_ctx("Ignore features","register"),vb); connect(m_pIgnoreEnabled,SIGNAL(toggled(bool)),gb,SLOT(setEnabled(bool))); QVBoxLayout * layout = new QVBoxLayout(gb); layout->setMargin(20); layout->setSpacing(3); m_pIgnoreQuery = new QCheckBox(__tr2qs_ctx("Ignore query messages","register"),gb); layout->addWidget(m_pIgnoreQuery); m_pIgnoreChannel = new QCheckBox(__tr2qs_ctx("Ignore channel messages","register"),gb); layout->addWidget(m_pIgnoreChannel); m_pIgnoreNotice = new QCheckBox(__tr2qs_ctx("Ignore notice messages","register"),gb); layout->addWidget(m_pIgnoreNotice); m_pIgnoreCtcp = new QCheckBox(__tr2qs_ctx("Ignore CTCP messages","register"),gb); layout->addWidget(m_pIgnoreCtcp); m_pIgnoreInvite = new QCheckBox(__tr2qs_ctx("Ignore invites","register"),gb); layout->addWidget(m_pIgnoreInvite); m_pIgnoreDcc = new QCheckBox(__tr2qs_ctx("Ignore DCCs","register"),gb); layout->addWidget(m_pIgnoreDcc); QWidget *w = new QWidget(vb); w->setSizePolicy(QSizePolicy::Ignored,QSizePolicy::Ignored); addTab(vb,__tr2qs_ctx("Ignore","register")); setCancelButton(__tr2qs_ctx("Cancel","register")); setOkButton(__tr2qs_ctx("&OK","register")); connect(this,SIGNAL(applyButtonPressed()),this,SLOT(okClicked())); connect(this,SIGNAL(cancelButtonPressed()),this,SLOT(reject())); if(r) { m_pNameEdit->setText(r->name()); m_pCommentEdit->setText(r->getProperty("comment")); for(KviIrcMask * m = r->maskList()->first();m;m = r->maskList()->next()) { QString mk = m->nick(); mk += QChar('!'); mk += m->user(); mk += QChar('@'); mk += m->host(); m_pMaskListBox->addItem(mk); } QString szNotifyNicks = r->getProperty("notify"); if(!szNotifyNicks.isEmpty()) { m_pNotifyCheck->setChecked(true); m_pNotifyNick->setText(szNotifyNicks); m_pNotifyNick->setEnabled(true); } if(r->propertyDict()) { KviPointerHashTableIterator<QString,QString> it(*(r->propertyDict())); while(QString *s = it.current()) { m_pPropertyDict->insert(it.currentKey(),new QString(*s)); ++it; } } m_pIgnoreEnabled->setChecked(r->ignoreEnagled()); gb->setEnabled(r->ignoreEnagled()); m_pIgnoreQuery->setChecked(r->ignoreFlags() & KviRegisteredUser::Query); m_pIgnoreChannel->setChecked(r->ignoreFlags() & KviRegisteredUser::Channel); m_pIgnoreNotice->setChecked(r->ignoreFlags() & KviRegisteredUser::Notice); m_pIgnoreCtcp->setChecked(r->ignoreFlags() & KviRegisteredUser::Ctcp); m_pIgnoreInvite->setChecked(r->ignoreFlags() & KviRegisteredUser::Invite); m_pIgnoreDcc->setChecked(r->ignoreFlags() & KviRegisteredUser::Dcc); } else { // default values if(!m_pIgnoreEnabled->isChecked()) { gb->setEnabled(false); } } }
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 KviWatchNotifyListManager::doMatchUser(KviIrcMessage * msg, const QString & notifyString, const KviIrcMask & mask) { QString * nam = m_pRegUserDict->find(notifyString); if(nam) { // ok...find the user if(KviRegisteredUser * u = g_pRegisteredUserDataBase->findUserByName(*nam)) { // ok ... match the user if(u->matchesFixed(mask)) { // new user online if(!(m_pConsole->notifyListView()->findEntry(mask.nick()))) { notifyOnLine(mask.nick(), mask.user(), mask.host(), "watch"); } else { // else already online, and matching...all ok if(msg->numeric() == RPL_NOWON) { // This is a reply to a /watch +something (should not happen, unless the user is messing) or to /watch l (user requested) notifyOnLine(mask.nick(), mask.user(), mask.host(), __tr2qs("watch entry listing requested by user"), false); } else { // This is a RPL_LOGON....we're desynched ? notifyOnLine(mask.nick(), mask.user(), mask.host(), __tr2qs("possible watch list desync"), false); } } } else { // not matched.... has he been online before ? if(m_pConsole->notifyListView()->findEntry(mask.nick())) { // has been online just a sec ago, but now the mask does not match // prolly the reguserdb has been changed notifyOffLine(mask.nick(), mask.user(), mask.host(), __tr2qs("registration mask changed or desync with the watch service")); } else { // has never been online if(_OUTPUT_VERBOSE) m_pConsole->output(KVI_OUT_SYSTEMMESSAGE, __tr("Notify list: \r!n\r%Q\r appears to be online, but the mask [%Q@\r!h\r%Q\r] does not match (watch: registration mask does not match, or nickname is being used by someone else)"), &(mask.nick()), &(mask.user()), &(mask.host())); } } } else { // ops... unexpected inconsistency .... reguser db modified ? m_pConsole->output(KVI_OUT_SYSTEMWARNING, __tr2qs("Notify list: Unexpected inconsistency, registered user DB modified? (watch: restarting)")); stop(); start(); return false; // critical ... exit from the call stack } } else { // not in our dictionary // prolly someone used /WATCH behind our back... bad boy! if(!(m_pConsole->notifyListView()->findEntry(mask.nick()))) { notifyOnLine(mask.nick(), mask.user(), mask.host(), __tr2qs("watch entry added by user")); } } 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; }