bool ICQClient::load(istream &s, string &nextPart) { ICQUser::load(s, nextPart); for (;;){ if (!strcmp(nextPart.c_str(), "[ContactList]")){ contacts.load(s, nextPart); continue; } if (!strcmp(nextPart.c_str(), "[Group]")){ ICQGroup *grp = new ICQGroup; if (grp->load(s, nextPart)){ contacts.groups.push_back(grp); }else{ delete grp; } continue; } if (!strcmp(nextPart.c_str(), "[User]")){ ICQUser *u = new ICQUser; if (u->load(s, nextPart) && u->Uin() && (u->Uin() != Uin())){ contacts.users.push_back(u); }else{ delete u; } continue; } break; } if (*EncryptedPassword.c_str() == 0) storePassword(DecryptedPassword.c_str()); setupProxy(); ICQEvent e(EVENT_INFO_CHANGED); process_event(&e); return true; }
ShowAwayMsgDlg::ShowAwayMsgDlg(CICQDaemon *_server, CSignalManager* _sigman, const char *szId, unsigned long nPPID, QWidget *parent) : LicqDialog(parent, "ShowAwayMessageDialog") { m_szId = szId ? strdup(szId) : 0; m_nPPID = nPPID; sigman = _sigman; server = _server; QBoxLayout* top_lay = new QVBoxLayout(this, 10); mleAwayMsg = new MLEditWrap(true, this); // ICQ99b allows 37 chars per line, so we do the same //mleAwayMsg->setWordWrap(QMultiLineEditNew::FixedColumnWidth); //mleAwayMsg->setWrapColumnOrWidth(37); mleAwayMsg->setReadOnly(true); mleAwayMsg->setMinimumSize(230, 110); connect(mleAwayMsg, SIGNAL(signal_CtrlEnterPressed()), SLOT(accept())); top_lay->addWidget(mleAwayMsg); QBoxLayout* lay = new QHBoxLayout(top_lay, 10); chkShowAgain = new QCheckBox(tr("&Show Again"), this); lay->addWidget(chkShowAgain); lay->addStretch(1); lay->addSpacing(30); ICQUser *u = gUserManager.FetchUser(m_szId, m_nPPID, LOCK_R); QTextCodec * codec = UserCodec::codecForICQUser(u); // chkShowAgain->setChecked(u->ShowAwayMsg()); setCaption(QString(tr("%1 Response for %2")).arg(u->StatusStr()).arg(QString::fromUtf8(u->GetAlias()))); btnOk = new QPushButton(tr("&Ok"), this); btnOk->setMinimumWidth(75); btnOk->setDefault(true); btnOk->setFocus(); connect(btnOk, SIGNAL(clicked()), SLOT(accept())); lay->addWidget(btnOk); // Check if this is an active request or not if (sigman == NULL || server == NULL) { mleAwayMsg->setText(codec->toUnicode(u->AutoResponse())); gUserManager.DropUser(u); icqEventTag = 0; } else { bool bSendServer = (u->SocketDesc(ICQ_CHNxNONE) <= 0 && u->Version() > 6); gUserManager.DropUser(u); mleAwayMsg->setEnabled(false); mleAwayMsg->setBackgroundMode(PaletteBackground); connect (sigman, SIGNAL(signal_doneUserFcn(ICQEvent *)), this, SLOT(doneEvent(ICQEvent *))); icqEventTag = server->icqFetchAutoResponse(szId, nPPID, bSendServer); } show(); }
void UserInfo::saveInfo() { ICQUser *u = pClient->getUser(m_nUin, m_nUin == 0); if (u == NULL) return; if (m_nUin == 0) m_nUin = u->Uin(); inSave = true; emit saveInfo(u); inSave = false; ICQEvent e(EVENT_INFO_CHANGED, m_nUin); processEvent(&e); }
void ShowAwayMsgDlg::accept() { ICQUser *u = gUserManager.FetchUser(m_szId, m_nPPID, LOCK_W); u->SetShowAwayMsg(chkShowAgain->isChecked()); gUserManager.DropUser(u); if (server != NULL && icqEventTag != 0) { server->CancelEvent(icqEventTag); icqEventTag = 0; } QDialog::accept(); }
CRefuseDlg::CRefuseDlg(unsigned long _nUin, QString t, QWidget* parent) : LicqDialog(parent, "RefuseDialog", true) { ICQUser *u = gUserManager.FetchUser(_nUin, LOCK_R); QLabel *lbl = new QLabel(tr("Refusal message for %1 with ").arg(t) + QString::fromUtf8(u->GetAlias()) + ":", this); gUserManager.DropUser(u); mleRefuseMsg = new MLEditWrap(true, this); QPushButton *btnRefuse = new QPushButton(tr("Refuse"), this ); connect( btnRefuse, SIGNAL(clicked()), SLOT(accept()) ); QPushButton *btnCancel = new QPushButton(tr("Cancel"), this ); connect( btnCancel, SIGNAL(clicked()), SLOT(reject()) ); int bw = 75; bw = QMAX(bw, btnRefuse->sizeHint().width()); bw = QMAX(bw, btnCancel->sizeHint().width()); btnRefuse->setFixedWidth(bw); btnCancel->setFixedWidth(bw); QGridLayout *lay = new QGridLayout(this, 3, 5, 15, 10); lay->addMultiCellWidget(lbl, 0, 0, 0, 4); lay->addMultiCellWidget(mleRefuseMsg, 1, 1, 0, 4); lay->addWidget(btnRefuse, 2, 1); lay->addWidget(btnCancel, 2, 3); lay->setColStretch(0, 2); lay->setColStretch(4, 2); lay->addColSpacing(2, 10); setCaption(tr("Licq %1 Refusal").arg(t)); }
void CForwardDlg::dropEvent(QDropEvent * de) { QString text; // extract the text from the event if (!QTextDrag::decode(de, text)) return; if (text.length() == 0) return; m_szId = strdup(text.latin1()); m_nPPID = LICQ_PPID; //TODO dropevent needs the ppid ICQUser *u = gUserManager.FetchUser(m_szId, m_nPPID, LOCK_R); edtUser->setText(QString::fromUtf8(u->GetAlias()) + " (" + text + ")"); gUserManager.DropUser(u); }
//-----CFileTransferManager::ConnectToFileServer----------------------------- bool CFileTransferManager::ConnectToFileServer(unsigned short nPort) { ICQUser *u = gUserManager.FetchUser(m_nUin, LOCK_R); if (u == NULL) return false; bool bTryDirect = u->Version() <= 6 || u->Mode() == MODE_DIRECT; bool bSendIntIp = u->SendIntIp(); gUserManager.DropUser(u); bool bSuccess = false; if (bTryDirect) { gLog.Info("%sFile Transfer: Connecting to server.\n", L_TCPxSTR); bSuccess = licqDaemon->OpenConnectionToUser(m_nUin, &ftSock, nPort); } bool bResult = false; if (!bSuccess) { ICQOwner *o = gUserManager.FetchOwner(LOCK_R); unsigned long nIp = bSendIntIp ? o->IntIp() : o->Ip(); gUserManager.DropOwner(); // try reverse connect int nId = licqDaemon->RequestReverseConnection(m_nUin, 0, nIp, LocalPort(), nPort); if (nId != -1) { struct SFileReverseConnectInfo *r = new struct SFileReverseConnectInfo; r->nId = nId; r->m = this; r->bTryDirect = !bTryDirect; pthread_mutex_lock(&thread_cancel_mutex); pthread_create(&m_tThread, NULL, FileWaitForSignal_tep, r); m_bThreadRunning = true; pthread_mutex_unlock(&thread_cancel_mutex); bResult = true; } } else bResult = SendFileHandshake(); return bResult; }
bool MoveUserEvent::process(ICQClient *icq, unsigned short result) { if (result == 0x0E){ log(L_DEBUG, "Need auth"); ICQUser *u = icq->getUser(m_nUin); ICQGroup *g = icq->getGroup(grp_id); if ((u == NULL) || (g == NULL)) return false; if (u->WaitAuth()){ log(L_WARN, "Move user failed (permission)"); return false; } u->WaitAuth = true; icq->moveUser(u, g); ICQEvent e(EVENT_AUTH_REQUIRED, m_nUin); icq->process_event(&e); return false; } if (result != 0){ log(L_WARN, "Move user failed %04X", result); return false; } ICQUser *u = icq->getUser(m_nUin); if (u == NULL) return false; ICQGroup *g = icq->getGroup(grp_id); if (g == NULL) return false; if (u->Uin() < UIN_SPECIAL){ icq->sendRosterGrp(g->Name, g->Id, u->Id); icq->snac(ICQ_SNACxFAM_LISTS, ICQ_SNACxLISTS_SAVE); icq->sendPacket(); if (u->GrpId){ ICQGroup *g = icq->getGroup(u->GrpId); if (g){ icq->snac(ICQ_SNACxFAM_LISTS, ICQ_SNACxLISTS_EDIT); icq->sendPacket(); MoveUserDummyEvent *e = new MoveUserDummyEvent; icq->sendRoster(e, ICQ_SNACxLISTS_DELETE, u->Uin, g->Id(), u->Id(), 0, u->Alias.c_str(), u->WaitAuth()); icq->sendRosterGrp(g->Name.c_str(), g->Id(), 0); icq->snac(ICQ_SNACxFAM_LISTS, ICQ_SNACxLISTS_SAVE); icq->sendPacket(); } } } u->GrpId = grp_id; return true; }
void ICQClient::processListQueue() { for (;;){ if (listQueue.size() == 0) return; list_req lr = *listQueue.begin(); ICQUser *u = getUser(lr.uin); if (u == NULL){ listQueue.remove(lr); continue; } unsigned short userId = contacts.getUserId(u); ICQSetListEvent *e = new ICQSetListEvent(u->Uin(), lr.list_type, lr.bSet); sendRoster(e, lr.bSet ? ICQ_SNACxLISTS_CREATE : ICQ_SNACxLISTS_DELETE, u->Uin, 0, userId, lr.list_type); return; } }
bool CFileTransferManager::SendFileHandshake() { gLog.Info(tr("%sFile Transfer: Shaking hands.\n"), L_TCPxSTR); // Send handshake packet: ICQUser *u = gUserManager.FetchUser(m_nUin, LOCK_R); unsigned short nVersion = u->ConnectionVersion(); gUserManager.DropUser(u); if (!CICQDaemon::Handshake_Send(&ftSock, m_nUin, LocalPort(), nVersion, false)) return false; // Send init packet: CPFile_InitClient p(m_szLocalName, m_nBatchFiles, m_nBatchSize); if (!SendPacket(&p)) return false; gLog.Info(tr("%sFile Transfer: Waiting for server to respond.\n"), L_TCPxSTR); m_nState = FT_STATE_WAITxFORxSERVERxINIT; sockman.AddSocket(&ftSock); sockman.DropSocket(&ftSock); return true; }
bool FullInfoEvent::processAnswer(ICQClient *client, Buffer &b, unsigned short nSubtype) { ICQUser *u; log(L_DEBUG, "Info about %lu %04X", Uin(), nSubtype); if (Uin() == client->Uin){ u = client; }else{ u = client->getUser(Uin(), false); if (u == NULL){ log(L_WARN, "User %lu for info not found", Uin()); return true; } } switch (nSubtype){ case ICQ_SRVxGENERAL_INFO:{ unsigned short n; char hideEmail; b >> u->Nick >> u->FirstName >> u->LastName >> u->EMail >> u->City >> u->State >> u->HomePhone >> u->HomeFax >> u->Address >> u->PrivateCellular >> u->Zip; b.unpack(n); u->Country = n; b >> u->TimeZone >> hideEmail; u->HiddenEMail = (hideEmail != 0); client->fromServer(u->Nick); client->fromServer(u->FirstName); client->fromServer(u->LastName); client->fromServer(u->City); client->fromServer(u->State); client->fromServer(u->Address); client->fromServer(u->Zip); client->fromServer(u->HomePhone); client->fromServer(u->HomeFax); client->fromServer(u->PrivateCellular); u->adjustEMails(u->EMails); break; } case ICQ_SRVxMORE_INFO:{ char c; b >> u->Age >> c >> u->Gender >> u->Homepage >> u->BirthYear >> u->BirthMonth >> u->BirthDay >> u->Language1 >> u->Language2 >> u->Language3; u->BirthYear = htons(u->BirthYear()); client->fromServer(u->Homepage); break; } case ICQ_SRVxEMAIL_INFO:{ EMailPtrList mails; char c; b >> c; for (;c > 0;c--){ char d; b >> d; string s; b >> s; client->fromServer(s); if (s.length() == 0) continue; EMailInfo *email = new EMailInfo; email->Email = s; email->Hide = (d != 0); mails.push_back(email); } u->adjustEMails(mails); break; } case ICQ_SRVxWORK_INFO:{ unsigned short n; b >> u->WorkCity >> u->WorkState >> u->WorkPhone >> u->WorkFax >> u->WorkAddress >> u->WorkZip; b.unpack(n); u->WorkCountry = n; b >> u->WorkName >> u->WorkDepartment >> u->WorkPosition; b.unpack(n); u->Occupation = n; b >> u->WorkHomepage; client->fromServer(u->WorkCity); client->fromServer(u->WorkState); client->fromServer(u->WorkPhone); client->fromServer(u->WorkFax); client->fromServer(u->WorkZip); client->fromServer(u->WorkAddress); client->fromServer(u->WorkName); client->fromServer(u->WorkDepartment); client->fromServer(u->WorkPosition); client->fromServer(u->WorkHomepage); break; } case ICQ_SRVxABOUT_INFO: b >> u->About; client->fromServer(u->About); break; case ICQ_SRVxINTERESTS_INFO:{ char n; b >> n; u->Interests.clear(); for (; n > 0; n--){ unsigned short c; b.unpack(c); string s; b >> s; client->fromServer(s); if (c == 0) continue; ExtInfo *interest = new ExtInfo; interest->Category = c; interest->Specific = s; u->Interests.push_back(interest); } break; } case ICQ_SRVxBACKGROUND_INFO:{ char n; u->Backgrounds.clear(); u->Affilations.clear(); b >> n; for (; n > 0; n--){ unsigned short c; b.unpack(c); string s; b >> s; client->fromServer(s); if (c == 0) continue; ExtInfo *info = new ExtInfo; info->Category = c; info->Specific = s; u->Backgrounds.push_back(info); } b >> n; for (; n > 0; n--){ unsigned short c; b.unpack(c); string s; b >> s; client->fromServer(s); if (c == 0) continue; ExtInfo *info = new ExtInfo; info->Category = c; info->Specific = s; u->Affilations.push_back(info); } break; } case ICQ_SRVxUNKNOWN_INFO: break; default: log(L_WARN, "Unknwon info type %04X for %lu", nSubtype, Uin()); } m_nParts++; if (m_nParts >= 8){ u->adjustPhones(); client->process_event(this); return true; } return false; }
void ShowAwayMsgDlg::doneEvent(ICQEvent *e) { if ( !e->Equals(icqEventTag) ) return; bool isOk = (e->Result() == EVENT_ACKED || e->Result() == EVENT_SUCCESS); QString title, result; if (e->ExtendedAck() && !e->ExtendedAck()->Accepted()) result = tr("refused"); else { switch (e->Result()) { case EVENT_FAILED: result = tr("failed"); break; case EVENT_TIMEDOUT: result = tr("timed out"); break; case EVENT_ERROR: result = tr("error"); break; default: break; } } if(!result.isEmpty()) { title = " [" + result + "]"; setCaption(caption() + title); } icqEventTag = 0; if (isOk && (e->Command() == ICQ_CMDxTCP_START || e->SNAC() == MAKESNAC(ICQ_SNACxFAM_MESSAGE, ICQ_SNACxMSG_SENDxSERVER) || e->SNAC() == MAKESNAC(ICQ_SNACxFAM_LOCATION, ICQ_SNACxLOC_INFOxREQ))) { ICQUser *u = gUserManager.FetchUser(m_szId, m_nPPID, LOCK_R); QTextCodec * codec = UserCodec::codecForICQUser(u); const char *szAutoResp = (e->ExtendedAck() && !e->ExtendedAck()->Accepted())? e->ExtendedAck()->Response() : u->AutoResponse(); if (m_nPPID == LICQ_PPID && isalpha(m_szId[0])) { // Strip HTML QString strResponse(codec->toUnicode(szAutoResp)); QRegExp regExp("<.*>"); regExp.setMinimal(true); strResponse.remove(regExp); mleAwayMsg->setText(strResponse); } else mleAwayMsg->setText(codec->toUnicode(szAutoResp)); gUserManager.DropUser(u); mleAwayMsg->setEnabled(true); mleAwayMsg->setBackgroundMode(PaletteBase); } }
/*------------------------------------------------------------------------------ * MonitorSockets_tep * * The server thread lives here. The main guy who waits on socket activity * and processes incoming packets. *----------------------------------------------------------------------------*/ void *MonitorSockets_tep(void *p) { //pthread_detach(pthread_self()); CICQDaemon *d = (CICQDaemon *)p; fd_set f; int nSocketsAvailable, nCurrentSocket, l; char buf[1024]; while (true) { /*pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); pthread_testcancel();*/ f = gSocketManager.SocketSet(); l = gSocketManager.LargestSocket() + 1; // Add the new socket pipe descriptor FD_SET(d->pipe_newsocket[PIPE_READ], &f); if (d->pipe_newsocket[PIPE_READ] >= l) l = d->pipe_newsocket[PIPE_READ] + 1; // Add the fifo descriptor if (d->fifo_fd != -1) { FD_SET(d->fifo_fd, &f); if (d->fifo_fd >= l) l = d->fifo_fd + 1; } nSocketsAvailable = select(l, &f, NULL, NULL, NULL); /*pthread_testcancel(); pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);*/ nCurrentSocket = 0; while (nSocketsAvailable > 0 && nCurrentSocket < l) { if (FD_ISSET(nCurrentSocket, &f)) { // New socket event ---------------------------------------------------- if (nCurrentSocket == d->pipe_newsocket[PIPE_READ]) { read(d->pipe_newsocket[PIPE_READ], buf, 1); if (buf[0] == 'S') { DEBUG_THREADS("[MonitorSockets_tep] Reloading socket info.\n"); } else if (buf[0] == 'X') { DEBUG_THREADS("[MonitorSockets_tep] Exiting.\n"); pthread_exit(NULL); } } // Fifo event ---------------------------------------------------------- if (nCurrentSocket == d->fifo_fd) { DEBUG_THREADS("[MonitorSockets_tep] Data on FIFO.\n"); fgets(buf, 1024, d->fifo_fs); d->ProcessFifo(buf); } else { INetSocket *s = gSocketManager.FetchSocket(nCurrentSocket); if (s != NULL && s->Owner() == gUserManager.OwnerUin() && d->m_nTCPSrvSocketDesc == -1) { /* This is the server socket and it is about to be destoryed so ignore this message (it's probably a disconnection anyway) */ gSocketManager.DropSocket(s); } // Message from the server ------------------------------------------- else if (nCurrentSocket == d->m_nTCPSrvSocketDesc) { DEBUG_THREADS("[MonitorSockets_tep] Data on TCP server socket.\n"); SrvSocket *srvTCP = static_cast<SrvSocket*>(s); if (srvTCP == NULL) { gLog.Warn(tr("%sInvalid server socket in set.\n"), L_WARNxSTR); close(nCurrentSocket); } // DAW FIXME error handling when socket is closed.. else if (srvTCP->Recv()) { CBuffer packet(srvTCP->RecvBuffer()); srvTCP->ClearRecvBuffer(); gSocketManager.DropSocket(srvTCP); if (!d->ProcessSrvPacket(packet));// d->icqRelogon(); } else { // probably server closed socket, try to relogon after a while // if ping-thread is running already int nSD = d->m_nTCPSrvSocketDesc; d->m_nTCPSrvSocketDesc = -1; gLog.Info("%sDropping server connection.\n", L_SRVxSTR); gSocketManager.DropSocket(srvTCP); gSocketManager.CloseSocket(nSD); // we need to initialize the logon time for the next retry d->m_tLogonTime = time(NULL); d->m_eStatus = STATUS_OFFLINE_FORCED; d->m_bLoggingOn = false; d->postLogoff(nSD, NULL); } } // Connection on the server port ------------------------------------- else if (nCurrentSocket == d->m_nTCPSocketDesc) { DEBUG_THREADS("[MonitorSockets_tep] Data on listening TCP socket." "\n"); TCPSocket *tcp = static_cast<TCPSocket *>(s); if (tcp == NULL) { gLog.Warn(tr("%sInvalid server TCP socket in set.\n"), L_WARNxSTR); close(nCurrentSocket); } else { TCPSocket *newSocket = new TCPSocket(0); tcp->RecvConnection(*newSocket); gSocketManager.DropSocket(tcp); gSocketManager.AddSocket(newSocket); gSocketManager.DropSocket(newSocket); } } // Message from connected socket-------------------------------------- else { DEBUG_THREADS("[MonitorSockets_tep] Data on TCP user socket.\n"); ssl_recv: TCPSocket *tcp = static_cast<TCPSocket *>(s); // If tcp is NULL then the socket is no longer in the set, hence it // must have been closed by us and we can ignore it. if (tcp == NULL) goto socket_done; if (!tcp->RecvPacket()) { int err = tcp->Error(); if (err == 0) gLog.Info(tr("%sConnection to %lu was closed.\n"), L_TCPxSTR , tcp->Owner()); else { char buf[128]; gLog.Info(tr("%sConnection to %lu lost:\n%s%s.\n"), L_TCPxSTR, tcp->Owner(), L_BLANKxSTR, tcp->ErrorStr(buf, 128)); } ICQUser *u = gUserManager.FetchUser(tcp->OwnerId(), tcp->OwnerPPID(), LOCK_W); if (u && u->Secure()) { u->ClearSocketDesc(ICQ_CHNxNONE); u->SetSecure(false); d->PushPluginSignal(new CICQSignal(SIGNAL_UPDATExUSER, USER_SECURITY, u->IdString(), u->PPID(), 0)); } gUserManager.DropUser(u); gSocketManager.DropSocket(tcp); gSocketManager.CloseSocket(nCurrentSocket); d->FailEvents(nCurrentSocket, err); break; } // Save the bytes pending status of the socket bool bPending = tcp->SSL_Pending(); bool r = true; // Process the packet if the buffer is full if (tcp->RecvBufferFull()) { if (tcp->Owner() == 0) r = d->ProcessTcpHandshake(tcp); else r = d->ProcessTcpPacket(tcp); tcp->ClearRecvBuffer(); } // Kill the socket if there was a problem if (!r) { gLog.Info(tr("%sClosing connection to %lu.\n"), L_TCPxSTR, tcp->Owner()); gSocketManager.DropSocket(tcp); gSocketManager.CloseSocket(nCurrentSocket); d->FailEvents(nCurrentSocket, 0); bPending = false; } else { gSocketManager.DropSocket(tcp); } // If there is more data pending then go again if (bPending) goto ssl_recv; } } socket_done: nSocketsAvailable--; } nCurrentSocket++; } } return NULL; }
void *ProcessRunningEvent_Client_tep(void *p) { pthread_detach(pthread_self()); pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); /* want to be cancelled immediately so we don't try to derefence the event after it has been deleted */ pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); DEBUG_THREADS("[ProcessRunningEvent_Client_tep] Caught event.\n"); ICQEvent *e = (ICQEvent *)p; pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); pthread_testcancel(); CICQDaemon *d = e->m_pDaemon; // Check if the socket is connected if (e->m_nSocketDesc == -1) { unsigned long nDestinationUin = e->m_nDestinationUin; unsigned char nChannel = e->Channel(); pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); ICQUser *u = gUserManager.FetchUser(nDestinationUin, LOCK_R); if (u == NULL) { if (d->DoneEvent(e, EVENT_ERROR) != NULL) d->ProcessDoneEvent(e); else { pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); pthread_testcancel(); delete e; } pthread_exit(NULL); } unsigned long nVersion = u->Version(); unsigned char nMode = u->Mode(); unsigned short nRemotePort = u->Port(); bool bSendIntIp = u->SendIntIp(); gUserManager.DropUser(u); ICQOwner *o = gUserManager.FetchOwner(LOCK_R); unsigned long nIP = bSendIntIp ? o->IntIp() : o->Ip(); unsigned short nLocalPort = o->Port(); gUserManager.DropOwner(); int socket = -1; if (!bSendIntIp && nVersion > 6 && nMode != MODE_DIRECT) { int nId = d->RequestReverseConnection(nDestinationUin, nChannel, nIP, nLocalPort, nRemotePort); if (nId != -1) { d->WaitForReverseConnection(nId, nDestinationUin); u = gUserManager.FetchUser(nDestinationUin, LOCK_R); if (u == NULL) { if (d->DoneEvent(e, EVENT_ERROR) != NULL) d->ProcessDoneEvent(e); else { pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); pthread_testcancel(); delete e; } pthread_exit(NULL); } socket = u->SocketDesc(nChannel); gUserManager.DropUser(u); } // if we failed, try direct anyway if (socket == -1) { pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); pthread_testcancel(); pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); socket = d->ConnectToUser(nDestinationUin, nChannel); } } else { socket = d->ConnectToUser(nDestinationUin, nChannel); // if we failed, try through server if (socket == -1) { pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); pthread_testcancel(); pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); int nId = d->RequestReverseConnection(nDestinationUin, nChannel, nIP, nLocalPort, nRemotePort); if (nId != -1) { d->WaitForReverseConnection(nId, nDestinationUin); u = gUserManager.FetchUser(nDestinationUin, LOCK_R); if (u == NULL) { if (d->DoneEvent(e, EVENT_ERROR) != NULL) d->ProcessDoneEvent(e); else { pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); pthread_testcancel(); delete e; } pthread_exit(NULL); } socket = u->SocketDesc(nChannel); gUserManager.DropUser(u); } } } pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); pthread_testcancel(); e->m_nSocketDesc = socket; // Check again, if still -1, fail the event if (e->m_nSocketDesc == -1) { pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); if (d->DoneEvent(e, EVENT_ERROR) != NULL) d->ProcessDoneEvent(e); else { pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); pthread_testcancel(); delete e; } pthread_exit(NULL); } } int socket = e->m_nSocketDesc; pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); INetSocket *s = gSocketManager.FetchSocket(socket); if (s == NULL) { pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); pthread_testcancel(); unsigned short nSequence = e->m_nSequence; pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); gLog.Warn(tr("%sSocket %d does not exist (#%hu).\n"), L_WARNxSTR, socket, nSequence); if (d->DoneEvent(e, EVENT_ERROR) != NULL) d->ProcessDoneEvent(e); else { pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); pthread_testcancel(); delete e; } pthread_exit(NULL); } CBuffer *buf; bool sent; char szErrorBuf[128]; pthread_cleanup_push(cleanup_socket, s); pthread_mutex_lock(&d->mutex_cancelthread); // check to make sure we were not cancelled already pthread_cleanup_push(cleanup_mutex, &d->mutex_cancelthread); pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); pthread_testcancel(); pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); //if we get here then we haven't been cancelled and we won't be //as long as we hold mutex_cancelthread buf = e->m_pPacket->Finalize(s); pthread_mutex_unlock(&d->mutex_cancelthread); pthread_cleanup_pop(0); sent = s->Send(buf); if (!sent) s->ErrorStr(szErrorBuf, 128); gSocketManager.DropSocket(s); pthread_cleanup_pop(0); if (!sent) { // Close the socket, alert the socket thread gSocketManager.CloseSocket(socket); pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); pthread_testcancel(); unsigned short nSequence = e->m_nSequence; pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); gLog.Warn(tr("%sError sending event (#%hu):\n%s%s.\n"), L_WARNxSTR, -nSequence, L_BLANKxSTR, szErrorBuf); write(d->pipe_newsocket[PIPE_WRITE], "S", 1); // Kill the event, do after the above as ProcessDoneEvent erase the event if (d->DoneEvent(e, EVENT_ERROR) != NULL) d->ProcessDoneEvent(e); else { pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); pthread_testcancel(); delete e; } pthread_exit(NULL); } pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); pthread_testcancel(); e->thread_running = false; // pthread_exit is not async cancel safe??? pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); pthread_exit(NULL); // Avoid compiler warnings return NULL; }
void ICQClientPrivate::snac_buddy(unsigned short type, unsigned short) { switch (type){ case ICQ_SNACxBDY_RIGHTSxGRANTED: log(L_DEBUG, "Buddy rights granted"); break; case ICQ_SNACxBDY_USEROFFLINE:{ unsigned long uin = sock->readBuffer.unpackUin(); ICQUser *user = client->getUser(uin); if (user && (user->uStatus != ICQ_STATUS_OFFLINE)){ log(L_DEBUG, "User %lu [%s] offline", uin, user->Alias.c_str()); user->setOffline(); ICQEvent e(EVENT_STATUS_CHANGED, uin); client->process_event(&e); } break; } case ICQ_SNACxBDY_USERONLINE:{ unsigned long uin = sock->readBuffer.unpackUin(); if (uin == client->owner->Uin) break; ICQUser *user = client->getUser(uin); if (user){ time_t now; time(&now); bool changed = false; if (user->uStatus == ICQ_STATUS_OFFLINE) user->Caps = 0; unsigned long cookie1, cookie2, cookie3; cookie1 = cookie2 = cookie3 = 0; unsigned short level, len; sock->readBuffer >> level >> len; TlvList tlv(sock->readBuffer); // Status TLV Tlv *tlvStatus = tlv(0x0006); if (tlvStatus){ unsigned long status = *tlvStatus; log(L_DEBUG, "User %lu [%s] online [%08lX]", uin, user->Alias.c_str(), status); if (status != user->uStatus){ user->prevStatus = user->uStatus; user->uStatus = status; if (status & 0xFF){ client->addResponseRequest(uin); }else{ user->AutoReply = ""; } user->StatusTime = (unsigned long)now; changed = true; } }else if (user->uStatus == ICQ_STATUS_OFFLINE){ user->uStatus = ICQ_STATUS_ONLINE; } // Online time TLV Tlv *tlvOnlineTime = tlv(0x0003); if (tlvOnlineTime){ user->OnlineTime = (unsigned long)(*tlvOnlineTime); changed = true; } Tlv *tlvNATime = tlv(0x0004); if (tlvNATime){ user->StatusTime = (unsigned long)now - (unsigned short)(*tlvNATime) * 60L; changed = true; } // IP TLV Tlv *tlvIP = tlv(0x000A); if (tlvIP){ unsigned long ip = htonl((unsigned long)(*tlvIP)); if (user->IP != ip) user->HostName = ""; user->IP = ip; log(L_DEBUG, "IP %s %lu", user->Alias.c_str(), user->IP); changed = true; } // Direct connection info Tlv *tlvDirect = tlv(0x000C); if (tlvDirect){ Buffer info(*tlvDirect); unsigned long realIP; unsigned short port; char mode, version, junk; info >> realIP; info.incReadPos(2); info >> port; realIP = htonl(realIP); if (user->RealIP != realIP) user->RealHostName =""; user->RealIP = realIP; user->Port = port; info >> mode >> junk >> version >> user->DCcookie; info.incReadPos(8); info >> cookie1 >> cookie2 >> cookie3; if (cookie3 != user->PhoneBookTime){ user->bPhoneChanged = true; user->PhoneBookTime = cookie3; } user->PhoneStatusTime = cookie2; user->InfoUpdateTime = cookie1; if (mode == MODE_DENIED) mode = MODE_INDIRECT; if ((mode != MODE_DIRECT) && (mode != MODE_INDIRECT)) mode = MODE_INDIRECT; user->Mode = (unsigned short)mode; user->Version = (unsigned short)version; changed = true; } Tlv *tlvCapability = tlv(0x000D); if (tlvCapability){ Buffer info(*tlvCapability); for (; info.readPos() < info.size(); ){ capability cap; info.unpack((char*)cap, sizeof(capability)); for (unsigned i = 0;; i++){ if (*capabilities[i] == 0) break; unsigned size = sizeof(capability); if (i == CAP_SIM) size--; if (i == CAP_MICQ) size -= 4; if (!memcmp(cap, capabilities[i], size)){ if (i == CAP_SIM){ unsigned char build = cap[sizeof(capability)-1]; log(L_DEBUG, "Build: %X %u", build, build); if (build && ((build == 0x92) || (build < (1 << 6)))) continue; user->Build = build; } if (i == CAP_MICQ){ unsigned char *p = (unsigned char*)cap; p += 12; user->Build = (p[0] << 24) + (p[1] << 16) + (p[2] << 8) + p[3]; } user->Caps |= (1 << i); } } } if (user->hasCap(CAP_RTF) && !user->CanPlugin){ user->CanPlugin = true; if (user->bPhoneChanged) client->addPhoneRequest(uin); } } Tlv *tlvPlugin = tlv(0x0011); if (tlvPlugin){ Buffer info(*tlvPlugin); char reqType; info >> reqType; info.incReadPos(10); capability cap; info.unpack((char*)cap, sizeof(capability)); if (user->CanPlugin && !memcmp(cap, PHONEBOOK_SIGN, sizeof(capability))){ if (reqType == 3){ info.incReadPos(3); info >> user->PhoneState; if (user->bPhoneChanged) client->addPhoneRequest(uin); }else if (reqType == 2) if (user->bPhoneChanged) client->addPhoneRequest(uin); } client->addInfoRequest(uin); changed = true; } if (changed){ ICQEvent e(EVENT_STATUS_CHANGED, uin); client->process_event(&e); user->prevStatus = user->uStatus; } } break; }
void MsgEdit::setMessage(ICQMessage *_msg, bool bMark, bool bInTop, bool bSaveEdit) { msgTail = ""; setUpdatesEnabled(false); if (msg != _msg){ if (msg && (msg->Id < MSG_PROCESS_ID)) delete msg; msg = _msg; } if (bMultiply) toggleMultiply(); if (msg == NULL){ edit->setText(""); edit->resetColors(false); urlEdit->setText(""); users->clear(); url->hide(); edit->hide(); file->hide(); lblUsers->hide(); btnBgColor->hide(); btnFgColor->hide(); btnBold->hide(); btnItalic->hide(); btnUnder->hide(); btnFont->hide(); #ifdef USE_SPELL btnSpell->hide(); #endif btnSend->hide(); chkClose->hide(); btnAccept->hide(); btnDecline->hide(); btnNext->show(); btnReply->hide(); btnQuote->hide(); btnGrant->hide(); btnRefuse->hide(); btnMultiply->hide(); btnForward->hide(); users->hide(); view->hide(); setupNext(); setUpdatesEnabled(true); repaint(); return; } emit showMessage(Uin, msg->Id); if (msg->Received()){ if (bMark) pClient->markAsRead(msg); phone->hide(); url->hide(); edit->hide(); file->hide(); lblUsers->hide(); btnBgColor->hide(); btnFgColor->hide(); btnBold->hide(); btnItalic->hide(); btnUnder->hide(); btnFont->hide(); #ifdef USE_SPELL btnSpell->hide(); #endif btnSend->hide(); chkClose->hide(); btnAccept->hide(); btnDecline->hide(); btnNext->show(); btnMultiply->hide(); setupNext(); if (msg->Type() == ICQ_MSGxCONTACTxLIST){ btnReply->hide(); btnQuote->hide(); btnGrant->hide(); btnRefuse->hide(); users->show(); view->hide(); btnForward->show(); ICQContacts *m = static_cast<ICQContacts*>(msg); for (ContactList::iterator it = m->Contacts.begin(); it != m->Contacts.end(); it++){ Contact *contact = static_cast<Contact*>(*it); users->addUser(contact->Uin, contact->Alias); } users->sender = false; }else{ switch (msg->Type()){ case ICQ_MSGxFILE:{ ICQFile *f = static_cast<ICQFile*>(msg); btnReply->hide(); btnQuote->hide(); btnGrant->hide(); btnRefuse->hide(); if (f->Id >= MSG_PROCESS_ID){ btnAccept->show(); btnDecline->show(); file->show(); ICQUser *u = pClient->getUser(f->getUin()); if ((u == NULL) || !u->AcceptFileOverride()) u = pClient; string path = u->AcceptFilePath.c_str(); if (*path.c_str() == 0) pMain->buildFileName(path, "IncommingFiles/"); QString name = QString::fromLocal8Bit(path.c_str()); #ifdef WIN32 name.replace(QRegExp("/"), "\\"); if ((name.length() == 0) || (name[(int)(name.length() - 1)] != '\\')) name += "\\"; #else if ((name.length() == 0) || (name[(int)(name.length() - 1)] != '/')) name += "/"; #endif name += QString::fromLocal8Bit(f->Name.c_str()); fileEdit->setText(name); fileEdit->setSaveMode(true); ftChanged(); }else{ btnAccept->hide(); btnDecline->hide(); } break; } case ICQ_MSGxAUTHxREQUEST: btnReply->hide(); btnQuote->hide(); btnGrant->show(); btnRefuse->show(); btnAccept->hide(); btnDecline->hide(); btnForward->hide(); break; case ICQ_MSGxMSG: case ICQ_MSGxURL: if (bInTop && !pMain->SimpleMode()){ btnReply->hide(); btnQuote->show(); btnForward->show(); btnGrant->hide(); btnRefuse->hide(); btnAccept->hide(); btnDecline->hide(); users->hide(); view->hide(); edit->setTextFormat(RichText); edit->setText(""); edit->show(); edit->resetColors(true); textChanged(); setUpdatesEnabled(true); edit->setFocus(); repaint(); return; } btnReply->show(); btnQuote->show(); btnGrant->hide(); btnRefuse->hide(); btnAccept->hide(); btnDecline->hide(); btnForward->show(); break; case ICQ_MSGxCHAT: btnReply->hide(); btnQuote->hide(); btnGrant->hide(); btnRefuse->hide(); btnAccept->hide(); btnDecline->hide(); btnForward->hide(); if (msg->Id >= MSG_PROCESS_ID){ btnAccept->show(); btnDecline->show(); chatChanged(); } break; default: btnReply->hide(); btnQuote->hide(); btnGrant->hide(); btnRefuse->hide(); btnAccept->hide(); btnDecline->hide(); btnForward->hide(); } users->hide(); view->show(); view->setText(view->makeMessageText(msg, false)); if (msg->Type() == ICQ_MSGxMSG){ ICQMsg *m = static_cast<ICQMsg*>(msg); if (m->BackColor() != m->ForeColor()){ view->setForeground(QColor(m->ForeColor)); view->setBackground(QColor(m->BackColor)); }else{ view->resetColors(); } }else{ view->resetColors(); } } }else{ btnReply->hide(); btnForward->hide(); btnQuote->hide(); btnGrant->hide(); btnRefuse->hide(); btnNext->hide(); btnAccept->hide(); btnDecline->hide(); chkClose->show(); btnSend->show(); switch (msg->Type()){ case ICQ_MSGxMSG:{ phone->hide(); url->hide(); edit->show(); users->hide(); view->hide(); file->hide(); lblUsers->hide(); btnBgColor->show(); btnFgColor->show(); btnBold->show(); btnItalic->show(); btnUnder->show(); btnFont->show(); btnMultiply->show(); #ifdef USE_SPELL btnSpell->show(); #endif if (!bSaveEdit){ edit->setTextFormat(RichText); ICQMsg *m = static_cast<ICQMsg*>(msg); edit->setText(QString::fromLocal8Bit(m->Message.c_str())); if (m->BackColor() != m->ForeColor()){ edit->setBackground(QColor(m->BackColor)); edit->setForeground(QColor(m->ForeColor)); }else{ edit->resetColors(true); } edit->setFocus(); } break; } case ICQ_MSGxURL:{ phone->hide(); url->show(); edit->show(); edit->setTextFormat(PlainText); users->hide(); view->hide(); file->hide(); lblUsers->hide(); btnBgColor->hide(); btnFgColor->hide(); btnBold->hide(); btnItalic->hide(); btnUnder->hide(); btnFont->hide(); btnMultiply->show(); #ifdef USE_SPELL btnSpell->show(); #endif ICQUrl *m = static_cast<ICQUrl*>(msg); edit->resetColors(false); edit->setText(QString::fromLocal8Bit(m->Message.c_str())); urlEdit->setText(QString::fromLocal8Bit(m->URL.c_str())); urlEdit->setFocus(); break; } case ICQ_MSGxFILE:{ phone->hide(); url->hide(); edit->show(); edit->setTextFormat(PlainText); users->hide(); view->hide(); file->show(); lblUsers->hide(); btnBgColor->hide(); btnFgColor->hide(); btnBold->hide(); btnItalic->hide(); btnUnder->hide(); btnFont->hide(); btnMultiply->hide(); #ifdef USE_SPELL btnSpell->show(); #endif ICQFile *m = static_cast<ICQFile*>(msg); edit->resetColors(false); edit->setText(QString::fromLocal8Bit(m->Description.c_str())); fileEdit->setSaveMode(false); fileEdit->setText(QString::fromLocal8Bit(m->Name.c_str())); fileEdit->setFocus(); break; } case ICQ_MSGxCHAT:{ phone->hide(); url->hide(); edit->show(); edit->setTextFormat(PlainText); users->hide(); view->hide(); file->hide(); lblUsers->hide(); btnBgColor->hide(); btnFgColor->hide(); btnBold->hide(); btnItalic->hide(); btnUnder->hide(); btnFont->hide(); btnMultiply->hide(); #ifdef USE_SPELL btnSpell->show(); #endif ICQChat *m = static_cast<ICQChat*>(msg); edit->resetColors(false); edit->setText(QString::fromLocal8Bit(m->Reason.c_str())); break; } case ICQ_MSGxSMS:{ phone->show(); url->hide(); edit->show(); edit->setTextFormat(RichText); users->hide(); view->hide(); file->hide(); lblUsers->hide(); btnBgColor->hide(); btnFgColor->hide(); btnBold->hide(); btnItalic->hide(); btnUnder->hide(); btnFont->hide(); btnMultiply->hide(); #ifdef USE_SPELL btnSpell->show(); #endif ICQSMS *m = static_cast<ICQSMS*>(msg); edit->resetColors(false); edit->setText(QString::fromLocal8Bit(pClient->clearHTML(m->Message.c_str()).c_str())); if (*m->Phone.c_str()) phoneEdit->lineEdit()->setText(QString::fromLocal8Bit(m->Phone.c_str())); phoneEdit->setFocus(); break; } case ICQ_MSGxCONTACTxLIST:{ phone->hide(); url->hide(); edit->hide(); users->show(); view->hide(); file->hide(); lblUsers->show(); btnBgColor->hide(); btnFgColor->hide(); btnBold->hide(); btnItalic->hide(); btnUnder->hide(); btnFont->hide(); btnMultiply->show(); #ifdef USE_SPELL btnSpell->hide(); #endif ICQContacts *m = static_cast<ICQContacts*>(msg); for (ContactList::iterator it = m->Contacts.begin(); it != m->Contacts.end(); it++){ Contact *contact = static_cast<Contact*>(*it); users->addUser(contact->Uin, contact->Alias); } users->sender = true; break; } case ICQ_MSGxAUTHxREQUEST:{ phone->hide(); url->hide(); edit->show(); edit->setTextFormat(RichText); users->hide(); view->hide(); file->hide(); lblUsers->hide(); btnBgColor->hide(); btnFgColor->hide(); btnBold->hide(); btnItalic->hide(); btnUnder->hide(); btnFont->hide(); btnMultiply->hide(); #ifdef USE_SPELL btnSpell->hide(); #endif ICQAuthRequest *m = static_cast<ICQAuthRequest*>(msg); edit->resetColors(false); edit->setText(QString::fromLocal8Bit(m->Message.c_str())); edit->setFocus(); break; } case ICQ_MSGxAUTHxREFUSED:{ phone->hide(); url->hide(); edit->show(); edit->setTextFormat(RichText); users->hide(); view->hide(); file->hide(); lblUsers->hide(); btnBgColor->hide(); btnFgColor->hide(); btnBold->hide(); btnItalic->hide(); btnUnder->hide(); btnFont->hide(); btnMultiply->hide(); #ifdef USE_SPELL btnSpell->hide(); #endif ICQAuthRefused *m = static_cast<ICQAuthRefused*>(msg); edit->resetColors(false); edit->setText(QString::fromLocal8Bit(m->Message.c_str())); edit->setFocus(); break; } case ICQ_MSGxAUTHxGRANTED:{ phone->hide(); url->hide(); edit->hide(); users->hide(); view->show(); file->hide(); lblUsers->hide(); btnBgColor->hide(); btnFgColor->hide(); btnBold->hide(); btnItalic->hide(); btnUnder->hide(); btnFont->hide(); btnMultiply->hide(); #ifdef USE_SPELL btnSpell->hide(); #endif break; } default: log(L_WARN, "Unknown message type %u", msg->Type()); } } textChanged(); setUpdatesEnabled(true); repaint(); }
void ICQClientPrivate::snac_lists(unsigned short type, unsigned short seq) { switch (type){ case ICQ_SNACxLISTS_RIGHTS: log(L_DEBUG, "List rights"); break; case ICQ_SNACxLISTS_ROSTER:{ char c; unsigned short list_len; log(L_DEBUG,"Rosters"); sock->readBuffer >> c; if (c){ log(L_WARN, "Bad first roster byte %02X", c); break; } bool bIgnoreTime = false; vector<ICQGroup*>::iterator it_grp; list<ICQUser*>::iterator it_usr; if (!m_bRosters){ m_bRosters = true; client->contacts.Invisible = 0; for (it_grp = client->contacts.groups.begin(); it_grp != client->contacts.groups.end(); it_grp++) (*it_grp)->bChecked = false; for (it_usr = client->contacts.users.begin(); it_usr != client->contacts.users.end(); it_usr++){ if ((*it_usr)->Type != USER_TYPE_ICQ) continue; (*it_usr)->Id = 0; (*it_usr)->GrpId = 0; (*it_usr)->IgnoreId = 0; (*it_usr)->VisibleId = 0; (*it_usr)->InvisibleId = 0; } } sock->readBuffer >> list_len; for (unsigned i = 0; i < list_len; i++){ string str; unsigned short id, grp_id, type, len; sock->readBuffer.unpackStr(str); sock->readBuffer >> grp_id >> id >> type >> len; TlvList *inf = NULL; if (len){ Buffer b(len); b.pack(sock->readBuffer.Data(sock->readBuffer.readPos()), len); sock->readBuffer.incReadPos(len); inf = new TlvList(b); } switch (type){ case 0x0000: /* User */{ unsigned long uin = atol(str.c_str()); if (uin){ Tlv *tlv_name = NULL; if (inf) tlv_name = (*inf)(0x0131); string alias = tlv_name ? (char*)(*tlv_name) : ""; client->fromUTF(alias, client->owner->Encoding.c_str()); bool needAuth = false; if (inf && (*inf)(0x0066)) needAuth = true; ICQUser *user = client->getUser(uin, true); user->Id = id; user->GrpId = grp_id; user->Alias = alias; user->WaitAuth = needAuth; Tlv *tlv_phone = NULL; if (inf) tlv_phone = (*inf)(0x13A); if (tlv_phone){ user->Phones.add(*tlv_phone, "Private cellular", SMS, true, false); user->adjustPhones(); } }else{ bIgnoreTime = true; } break; } case ICQ_GROUPS:{ if (str.size() == 0) break; client->fromUTF(str, client->owner->Encoding.c_str()); ICQGroup *grp = client->getGroup(grp_id, true); if (grp == NULL){ grp = client->createGroup(); client->contacts.groups.push_back(grp); } grp->Id = grp_id; grp->Name = str; grp->bChecked = true; break; } case ICQ_VISIBLE_LIST:{ unsigned long uin = atol(str.c_str()); if (uin) client->getUser(atol(str.c_str()), true)->VisibleId = id; break; } case ICQ_INVISIBLE_LIST:{ unsigned long uin = atol(str.c_str()); if (uin) client->getUser(atol(str.c_str()), true)->InvisibleId = id; break; } case ICQ_IGNORE_LIST:{ unsigned long uin = atol(str.c_str()); if (uin) client->getUser(atol(str.c_str()), true)->IgnoreId = id; break; } case ICQ_INVISIBLE_STATE: client->contacts.Invisible = id; break; case 0x0009: case 0x0011: case 0x0013: break; default: log(L_WARN,"Unknown roster type %04X", type); } if (inf) delete inf; } unsigned long time; sock->readBuffer >> time; if ((time == 0) && list_len && !bIgnoreTime) break; client->contacts.Time = time; for (;;){ bool ok = true; for (it_grp = client->contacts.groups.begin(); it_grp != client->contacts.groups.end(); it_grp++){ if (!(*it_grp)->bChecked){ client->contacts.groups.erase(it_grp); ok = false; break; } } if (ok) break; } for (it_usr = client->contacts.users.begin(); it_usr != client->contacts.users.end(); it_usr++){ unsigned short grpId = (*it_usr)->GrpId; bool ok = false; for (it_grp = client->contacts.groups.begin(); it_grp != client->contacts.groups.end(); it_grp++){ if ((*it_grp)->Id == grpId){ ok = true; break; } } if (!ok) (*it_usr)->GrpId = 0; } ICQEvent e(EVENT_GROUP_CHANGED); client->process_event(&e); m_state = Logged; } case ICQ_SNACxLISTS_ROSTERxOK: // FALLTHROUGH { log(L_DEBUG, "Rosters OK"); snac(ICQ_SNACxFAM_LISTS, ICQ_SNACxLISTS_UNKNOWN); sendPacket(); sendCapability(); sendICMB(); sendLogonStatus(); sendClientReady(); sendMessageRequest(); sendPhoneStatus(); if (client->owner->Nick.size() == 0){ client->addInfoRequest(client->owner->Uin); client->searchByUin(client->owner->Uin); } list<ICQUser*>::iterator it; for (it = client->contacts.users.begin(); it != client->contacts.users.end(); it++){ ICQUser *u = *it; if (u->IgnoreId) continue; if (u->Nick.size() || u->Alias.size()) continue; client->addInfoRequest(u->Uin); } if (client->contacts.groups.size() == 0){ m_state = Logged; client->createGroup("General"); } if (client->contacts.Invisible == 0){ snac(ICQ_SNACxFAM_LISTS, ICQ_SNACxLISTS_EDIT); sendPacket(); snac(ICQ_SNACxFAM_LISTS, ICQ_SNACxLISTS_CREATE, true); sock->writeBuffer << 0x00000000L << 0x00000001L << 0x000400C8L << (unsigned short)0; sendPacket(); snac(ICQ_SNACxFAM_LISTS, ICQ_SNACxLISTS_SAVE); sendPacket(); } break; } case ICQ_SNACxLISTS_ADDED:{ sock->readBuffer.incReadPos(8); unsigned long uin = sock->readBuffer.unpackUin(); ICQAddedToList *m = new ICQAddedToList; m->Uin.push_back(uin); messageReceived(m); break; } case ICQ_SNACxLISTS_AUTHxREQUEST:{ sock->readBuffer.incReadPos(8); unsigned long uin = sock->readBuffer.unpackUin(); ICQUser *u = client->getUser(uin); string message; string charset; unsigned short have_charset; sock->readBuffer.unpackStr(message); sock->readBuffer >> have_charset; if (have_charset){ sock->readBuffer.incReadPos(2); sock->readBuffer.unpackStr(charset); } if (charset.size()){ client->translate(client->localCharset(u), charset.c_str(), message); }else{ client->fromServer(message, u); } log(L_DEBUG, "Auth request %lu", uin); ICQAuthRequest *m = new ICQAuthRequest; m->Uin.push_back(uin); m->Message = message; messageReceived(m); break; } case ICQ_SNACxLISTS_AUTH:{ sock->readBuffer.incReadPos(8); unsigned long uin = sock->readBuffer.unpackUin(); char auth_ok; sock->readBuffer >> auth_ok; string message; string charset; unsigned short have_charset; sock->readBuffer.unpackStr(message); sock->readBuffer >> have_charset; if (have_charset){ sock->readBuffer.incReadPos(2); sock->readBuffer.unpackStr(charset); } ICQUser *u = client->getUser(uin); if (charset.size()){ client->translate(client->localCharset(u), charset.c_str(), message); }else{ client->fromServer(message, u); } log(L_DEBUG, "Auth %u %lu", auth_ok, uin); if (auth_ok){ ICQUser *user = client->getUser(uin); if (user){ user->WaitAuth = false; ICQEvent e(EVENT_INFO_CHANGED, uin); client->process_event(&e); } ICQAuthGranted *m = new ICQAuthGranted(); m->Uin.push_back(uin); messageReceived(m); }else{ ICQAuthRefused *m = new ICQAuthRefused(); m->Uin.push_back(uin); m->Message = message; messageReceived(m); } break; } case ICQ_SNACxLISTS_DONE:{ ICQEvent *e = findListEvent(seq); if (e == NULL) break; sock->readBuffer.incReadPos(8); unsigned short res; sock->readBuffer >> res; e->processAnswer(this, sock->readBuffer, res); delete e; break; } default: log(L_WARN, "Unknown lists family type %04X", type); } }
void ICQClient::snac_message(unsigned short type, unsigned short) { switch (type){ case ICQ_SNACxMSG_RIGHTSxGRANTED: log(L_DEBUG, "Message rights granted"); break; case ICQ_SNACxMSG_ACK: log(L_DEBUG, "Ack message"); break; case ICQ_SNACxMSG_AUTOREPLY:{ unsigned long timestamp1, timestamp2; readBuffer >> timestamp1 >> timestamp2; readBuffer.incReadPos(2); unsigned long uin = readBuffer.unpackUin(); readBuffer.incReadPos(6); unsigned long t1, t2; readBuffer >> t1 >> t2; unsigned short seq; readBuffer.incReadPos(0x0F); readBuffer >> seq; if ((t1 == 0) && (t2 == 0)){ readBuffer.incReadPos(0x16); string answer; readBuffer >> answer; fromServer(answer); if (timestamp1 || timestamp2){ log(L_DEBUG, "Message declined %s", answer.c_str()); list<ICQEvent*>::iterator it; for (it = processQueue.begin(); it != processQueue.end(); ++it){ ICQEvent *e = *it; if (e->type() != EVENT_MESSAGE_SEND) continue; ICQMessage *msg = e->message(); if (msg == NULL) continue; if ((msg->Uin == uin) && (msg->timestamp1 == timestamp1) && (msg->timestamp2 == timestamp2)){ msg->DeclineReason = answer; cancelMessage(msg, false); break; } } if (it == processQueue.end()) log(L_WARN, "Decline file answer: message not found"); }else{ log(L_DEBUG, "[%X] Autoreply from %u %s", seq, uin, answer.c_str()); ICQUser *u = getUser(uin); if (u) u->AutoReply = answer; ICQEvent e(EVENT_STATUS_CHANGED, uin); process_event(&e); processResponseRequestQueue(seq); } } if ((t1 == 0xA0E93F37L) && (t2 == 0x4FE9D311L)){ ICQUser *u = getUser(uin); if (u == NULL){ log(L_WARN, "Request info no my user %lu", uin); return; } if (u->inIgnore()){ log(L_WARN, "Request info ignore user %lu", uin); return; } readBuffer.incReadPos(0x1D); unsigned long cookie; readBuffer >> cookie; readBuffer.incReadPos(4); readBuffer.unpack(t1); if (t1 == 3){ u->PhoneBookTime = (unsigned long)htonl(cookie); u->bPhoneChanged = false; log(L_DEBUG, "[%X] Phone book info %u", seq, uin); PhoneBook::iterator it; PhonePtrList myNumbers; for (it = u->Phones.begin(); it != u->Phones.end(); ++it){ PhoneInfo *phone = static_cast<PhoneInfo*>(*it); if (!phone->MyInfo()) continue; PhoneInfo *myPhone = new PhoneInfo; *myPhone = *phone; myNumbers.push_back(myPhone); } u->Phones.clear(); unsigned long nPhones; readBuffer.unpack(nPhones); for (unsigned i = 0; i < nPhones; i++){ PhoneInfo *phone = new PhoneInfo; u->Phones.push_back(phone); readBuffer.unpackStr32(phone->Name); readBuffer.unpackStr32(phone->AreaCode); readBuffer.unpackStr32(phone->Number); readBuffer.unpackStr32(phone->Extension); readBuffer.unpackStr32(phone->Country); unsigned long type; readBuffer.unpack(type); if (type) phone->Active = true; if (readBuffer.readPos() >= readBuffer.size()) break; } for (it = u->Phones.begin(); it != u->Phones.end(); it++){ PhoneInfo *phone = static_cast<PhoneInfo*>(*it); string prop; readBuffer.unpackStr32(prop); Buffer b; b.pack(prop.c_str(), prop.length()); b.unpack(phone->Type); b.unpackStr32(phone->Provider); if (readBuffer.readPos() >= readBuffer.size()) break; } for (;;){ for (it = u->Phones.begin(); it != u->Phones.end(); it++){ PhoneInfo *phone = static_cast<PhoneInfo*>(*it); bool bOK = (phone->getNumber().length() > 0); if (bOK && !*phone->Number.c_str()) bOK = false; if (bOK) for (const char *p = phone->Number.c_str(); *p; p++){ if ((*p >= '0') && (*p <= '9')) continue; if ((*p == ' ') || (*p == '-')) continue; bOK = false; break; } if (bOK) continue; u->Phones.remove(phone); break; } if (it == u->Phones.end()) break; } u->adjustPhones(); u->Phones.add(myNumbers); ICQEvent e(EVENT_INFO_CHANGED, uin); process_event(&e); processPhoneRequestQueue(seq); } } break; }
char *CGPGHelper::Encrypt(const char *szPlain, const char *szId, unsigned long nPPID) { #ifdef HAVE_LIBGPGME if (!mCtx) return 0; if (!szPlain) return 0; char szUser[MAX_LINE_LEN], buf[MAX_LINE_LEN]; buf[0] = '\0'; sprintf(szUser, "%s.%lu", szId, nPPID); mKeysIni.SetSection("keys"); ICQUser *u = gUserManager.FetchUser( szId, nPPID, LOCK_R ); if ( u ) { const char *tmp = u->GPGKey(); if ( tmp && tmp[0]!='\0' ) strncpy( buf, tmp, MAX_LINE_LEN-1 ); gUserManager.DropUser( u ); } if ( !buf[0] && !mKeysIni.ReadStr(szUser, buf) ) return 0; gLog.Info("[GPG] Encrypting message to %s.\n", szId); CGPGMEMutex mutex; if (!mutex.Lock()) return 0; gpgme_key_t rcps[2]; gpgme_data_t plain = 0, cipher = 0; gpgme_error_t err; char *szCipher = 0; size_t nRead = 0; rcps[1] = 0; // Still use the old method, gpgme_get_key requires the fingerprint, which // actually isn't very helpful. if (gpgme_op_keylist_start (mCtx, buf, 0) != GPG_ERR_NO_ERROR) gLog.Error("%s[GPG] Couldn't use gpgme recipient: %s\n", L_ERRORxSTR, buf); else { if (gpgme_op_keylist_next(mCtx, rcps) != GPG_ERR_NO_ERROR) gLog.Error("%s[GPG] Couldn't get key: %s\n", L_ERRORxSTR, buf); else { if (gpgme_data_new_from_mem(&plain, szPlain, strlen(szPlain), 0) == GPG_ERR_NO_ERROR && gpgme_data_new(&cipher) == GPG_ERR_NO_ERROR) { if ((err = gpgme_op_encrypt(mCtx, rcps, GPGME_ENCRYPT_ALWAYS_TRUST, plain, cipher)) == GPG_ERR_NO_ERROR) { szCipher = gpgme_data_release_and_get_mem(cipher, &nRead); cipher = 0; szCipher = (char *)realloc(szCipher, nRead + 1); szCipher[nRead] = 0; } else gLog.Error("%s[GPG] Encryption failed: %s\n", L_ERRORxSTR, gpgme_strerror(err)); } } if (cipher) gpgme_data_release(cipher); if (plain) gpgme_data_release(plain); } gpgme_key_unref(rcps[0]); return szCipher; #else return 0; #endif }
void ICQClient::snac_buddy(unsigned short type, unsigned short) { switch (type){ case ICQ_SNACxBDY_RIGHTSxGRANTED: log(L_DEBUG, "Buddy rights granted"); break; case ICQ_SNACxBDY_USEROFFLINE:{ unsigned long uin = readBuffer.unpackUin(); ICQUser *user = getUser(uin); if (user && (user->uStatus != ICQ_STATUS_OFFLINE)){ log(L_DEBUG, "User %lu [%s] offline", uin, user->Alias.c_str()); user->setOffline(); ICQEvent e(EVENT_STATUS_CHANGED, uin); process_event(&e); } break; } case ICQ_SNACxBDY_USERONLINE:{ unsigned long uin = readBuffer.unpackUin(); if (uin == Uin()) break; ICQUser *user = getUser(uin); if (user){ time_t now; time(&now); bool changed = false; unsigned long cookie1, cookie2, cookie3; cookie1 = cookie2 = cookie3 = 0; unsigned short level, len; readBuffer >> level >> len; TlvList tlv(readBuffer); // Status TLV Tlv *tlvStatus = tlv(0x0006); if (tlvStatus){ unsigned long status = *tlvStatus; log(L_DEBUG, "User %lu [%s] online [%08lX]", uin, user->Alias.c_str(), status); if (status != user->uStatus){ user->prevStatus = user->uStatus; user->uStatus = status; if (status & 0xFF){ addResponseRequest(uin); }else{ user->AutoReply = ""; } user->StatusTime = (unsigned long)now; changed = true; } } // Online time TLV Tlv *tlvOnlineTime = tlv(0x0003); if (tlvOnlineTime){ user->OnlineTime = (unsigned long)(*tlvOnlineTime); changed = true; } Tlv *tlvNATime = tlv(0x0004); if (tlvNATime){ user->StatusTime = (unsigned long)now - (unsigned short)(*tlvNATime) * 60L; changed = true; } // IP TLV Tlv *tlvIP = tlv(0x000A); if (tlvIP){ unsigned long ip = htonl((unsigned long)(*tlvIP)); if (user->IP() != ip) user->HostName = ""; user->IP = ip; changed = true; } // Direct connection info Tlv *tlvDirect = tlv(0x000C); if (tlvDirect){ user->ClientType = 0; Buffer info(*tlvDirect); unsigned long realIP; unsigned short port; char mode, version, junk; info >> realIP; info.incReadPos(2); info >> port; realIP = htonl(realIP); if (user->RealIP != realIP) user->RealHostName =""; user->RealIP = realIP; user->Port = port; info >> mode >> junk >> version >> user->DCcookie; info.incReadPos(8); info >> cookie1 >> cookie2 >> cookie3; if (cookie3 != user->PhoneBookTime()){ user->bPhoneChanged = true; user->PhoneBookTime = cookie3; } user->PhoneStatusTime = cookie2; user->TimeStamp = cookie1; if (mode == MODE_DENIED) mode = MODE_INDIRECT; if ((mode != MODE_DIRECT) && (mode != MODE_INDIRECT)) mode = MODE_INDIRECT; user->Mode = (unsigned short)mode; user->Version = (unsigned short)version; changed = true; if (user->DCcookie == 0) user->ClientType = 4; if ((user->DCcookie == cookie1) && (cookie1 == cookie2)) user->ClientType = 5; if (cookie1 == 0x279c6996) user->ClientType = 3; } Tlv *tlvCapability = tlv(0x000D); if (tlvCapability){ user->GetRTF = false; Buffer info(*tlvCapability); for (; info.readPos() < info.size(); ){ capability cap; info.unpack((char*)cap, sizeof(capability)); if (!memcmp(cap, capabilities[1], sizeof(capability))){ user->GetRTF = true; if (!user->CanPlugin){ if (user->bPhoneChanged) addPhoneRequest(uin); user->CanPlugin = true; } } if (!memcmp(cap, capabilities[3], sizeof(capability))) user->CanResponse = true; if (!memcmp(cap, capabilities[5], sizeof(capability))) user->ClientType = 2; if (!memcmp(cap, capabilities[4], sizeof(capability))) user->ClientType = 1; if (!memcmp(cap, capabilities[4], sizeof(capability)-1) && (cap[sizeof(capability)-1] > (1 << 6)) && (cap[sizeof(capability)-1] != 0x92)) user->ClientType = (char)(cap[sizeof(capability)-1]); } } Tlv *tlvPlugin = tlv(0x0011); if (tlvPlugin){ Buffer info(*tlvPlugin); char reqType; info >> reqType; info.incReadPos(10); capability cap; info.unpack((char*)cap, sizeof(capability)); if (user->CanPlugin && !memcmp(cap, PHONEBOOK_SIGN, sizeof(capability))){ if (reqType == 3){ info.incReadPos(3); info >> user->PhoneState; if (user->bPhoneChanged) addPhoneRequest(uin); }else if (reqType == 2) if (user->bPhoneChanged) addPhoneRequest(uin); } addInfoRequest(uin); changed = true; } if (changed){ ICQEvent e(EVENT_STATUS_CHANGED, uin); process_event(&e); user->prevStatus = user->uStatus; } } break; }
void SecureDlg::sendRequest() { ICQUser *u = pClient->getUser(Uin); if (u) u->requestSecureChannel(pClient); }
void CMSN::ProcessSBPacket(char *szUser, CMSNBuffer *packet, int nSock) { char szCommand[4]; CMSNPacket *pReply; bool bSkipPacket; while (!packet->End()) { pReply = 0; bSkipPacket = true; packet->UnpackRaw(szCommand, 3); string strCmd(szCommand); if (strCmd == "IRO") { packet->SkipParameter(); // Seq packet->SkipParameter(); // current user to add packet->SkipParameter(); // total users in conversation string strUser = packet->GetParameter(); ICQUser *u = gUserManager.FetchUser(strUser.c_str(), MSN_PPID, LOCK_R); if (!u) { m_pDaemon->AddUserToList(strUser.c_str(), MSN_PPID, false, true); // MSN uses UTF-8 so we need to set this for all new users automatically ICQUser *u = gUserManager.FetchUser(strUser.c_str(), MSN_PPID, LOCK_W); if (u) // To be safe { u->SetEnableSave(false); u->SetUserEncoding("UTF-8"); u->SetEnableSave(true); u->SaveLicqInfo(); } } if (u) gUserManager.DropUser(u); // Add the user to the conversation if (!m_pDaemon->FindConversation(nSock)) m_pDaemon->AddConversation(nSock, MSN_PPID); m_pDaemon->AddUserConversation(nSock, strUser.c_str()); // Notify the plugins of the new CID m_pDaemon->PushPluginSignal(new CICQSignal(SIGNAL_SOCKET, 0, strdup(strUser.c_str()), MSN_PPID, 0, SocketToCID(nSock))); m_pDaemon->PushPluginSignal(new CICQSignal(SIGNAL_CONVOxJOIN, 0, strdup(strUser.c_str()), MSN_PPID, 0, SocketToCID(nSock))); gLog.Info("%s%s joined the conversation.\n", L_MSNxSTR, strUser.c_str()); } else if (strCmd == "ANS") { // just OK, ready to talk // we can ignore this } else if (strCmd == "MSG") { string strUser = packet->GetParameter(); packet->SkipParameter(); // Nick string strSize = packet->GetParameter(); // Size int nSize = atoi(strSize.c_str()) + 1; // Make up for the \n unsigned long nBeforeParse = packet->getDataPosRead() - packet->getDataStart(); packet->SkipPacket(); // Skip \r\n packet->ParseHeaders(); unsigned long nAfterParse = packet->getDataPosRead() - packet->getDataStart(); int nRead = nAfterParse - nBeforeParse; nSize -= nRead; string strType = packet->GetValue("Content-Type"); if (strType == "text/x-msmsgscontrol") { packet->SkipRN(); packet->SkipRN(); packet->SkipRN(); ICQUser *u = gUserManager.FetchUser(strUser.c_str(), MSN_PPID, LOCK_W); if (u) { u->SetTyping(ICQ_TYPING_ACTIVE); gUserManager.DropUser(u); m_pDaemon->PushPluginSignal(new CICQSignal(SIGNAL_UPDATExUSER, USER_TYPING, strUser.c_str(), MSN_PPID, SocketToCID(nSock))); } } else if (strncmp(strType.c_str(), "text/plain", 10) == 0) { gLog.Info("%sMessage from %s.\n", L_MSNxSTR, strUser.c_str()); bSkipPacket = false; char szMsg[nSize + 1]; int i; for (i = 0; i < nSize; i++) (*packet) >> szMsg[i]; szMsg[i] = '\0'; CEventMsg *e = CEventMsg::Parse(szMsg, ICQ_CMDxRCV_SYSxMSGxOFFLINE, time(0), 0, SocketToCID(nSock)); ICQUser *u = gUserManager.FetchUser(strUser.c_str(), MSN_PPID, LOCK_W); if (u) u->SetTyping(0); if (m_pDaemon->AddUserEvent(u, e)) m_pDaemon->m_xOnEventManager.Do(ON_EVENT_MSG, u); gUserManager.DropUser(u); } else if (strncmp(strType.c_str(), "text/x-msmsgsinvite", 19) == 0)
void MsgEdit::processEvent(ICQEvent *e) { ICQUser *u; switch (e->type()){ case EVENT_ACKED: if (e->message() && (e->message() == message())){ sendEvent = NULL; setMessage(); if (bCloseSend){ close(); }else{ action(mnuAction); switch (e->message()->Type()){ case ICQ_MSGxFILE: emit setStatus(i18n("Transfer started"), 2000); break; case ICQ_MSGxCHAT: emit setStatus(i18n("Chat started"), 2000); break; } } } break; case EVENT_INFO_CHANGED: fillPhones(); u = pClient->getUser(Uin); if (u && u->inIgnore()) QTimer::singleShot(10, this, SLOT(close())); break; case EVENT_USER_DELETED: if (e->Uin() == Uin) close(); break; } if (e->message() && (e->message() == message())){ if (e->type() == EVENT_MESSAGE_SEND){ if (e->state == ICQEvent::Success){ history()->addMessage(message()); if (!msgTail.isEmpty()){ emit addMessage(message(), false, true); emit showMessage(Uin(), message()->Id); if (e->message()->Type() == ICQ_MSGxSMS){ ICQSMS *m = new ICQSMS; m->Uin.push_back(Uin); m->Message = smsChunk(); m->Phone = phoneEdit->lineEdit()->text().local8Bit(); msg = m; sendEvent = pClient->sendMessage(msg); return; } log(L_WARN, "Bad type for chunked message"); } if (bCloseSend){ close(); }else{ emit addMessage(message(), false, true); emit showMessage(Uin(), message()->Id); setMessage(); action(mnuAction); emit setStatus(i18n("Message sent"), 2000); } }else{ e->message()->bDelete = false; emit setStatus(i18n("Send failed"), 2000); if (e->message() && *(e->message()->DeclineReason.c_str())) BalloonMsg::message(QString::fromLocal8Bit(msg->DeclineReason.c_str()), btnNext); } bCloseSend = false; sendEvent = NULL; setState(); }else if ((e->type() == EVENT_MESSAGE_RECEIVED) && (e->state == ICQEvent::Fail)){ msg = NULL; setMessage(); action(mnuAction); } } }