HANDLE GGPROTO::SearchBasic(const TCHAR *id) { if (!isonline()) return 0; gg_pubdir50_t req = gg_pubdir50_new(GG_PUBDIR50_SEARCH); if (!req) { #ifdef DEBUGMODE debugLogA("SearchBasic(): ForkThread 10 GGPROTO::searchthread"); #endif ForkThread(&GGPROTO::searchthread, NULL); return (HANDLE)1; } // Add uin and search it gg_pubdir50_add(req, GG_PUBDIR50_UIN, T2Utf(id)); gg_pubdir50_seq_set(req, GG_SEQ_SEARCH); gg_EnterCriticalSection(&sess_mutex, "SearchBasic", 50, "sess_mutex", 1); if (!gg_pubdir50(sess, req)) { gg_LeaveCriticalSection(&sess_mutex, "SearchBasic", 50, 1, "sess_mutex", 1); #ifdef DEBUGMODE debugLogA("SearchBasic(): ForkThread 11 GGPROTO::searchthread"); #endif ForkThread(&GGPROTO::searchthread, NULL); return (HANDLE)1; } gg_LeaveCriticalSection(&sess_mutex, "SearchBasic", 50, 2, "sess_mutex", 1); debugLogA("SearchBasic(): Seq %d.", req->seq); gg_pubdir50_free(req); return (HANDLE)1; }
int GGPROTO::SetAwayMsg(int iStatus, const PROTOCHAR *newMsg) { int status = gg_normalizestatus(iStatus); TCHAR **msgPtr; debugLog(_T("SetAwayMsg(): PS_SETAWAYMSG(%d, \"%s\")."), iStatus, newMsg); gg_EnterCriticalSection(&modemsg_mutex, "SetAwayMsg", 55, "modemsg_mutex", 1); // Select proper our msg ptr switch(status) { case ID_STATUS_ONLINE: msgPtr = &modemsg.online; break; case ID_STATUS_AWAY: msgPtr = &modemsg.away; break; case ID_STATUS_DND: msgPtr = &modemsg.dnd; break; case ID_STATUS_FREECHAT: msgPtr = &modemsg.freechat; break; case ID_STATUS_INVISIBLE: msgPtr = &modemsg.invisible; break; default: gg_LeaveCriticalSection(&modemsg_mutex, "SetAwayMsg", 55, 1, "modemsg_mutex", 1); return 1; } // Check if we change status here somehow if (*msgPtr && newMsg && !_tcscmp(*msgPtr, newMsg) || !*msgPtr && (!newMsg || !*newMsg)) { if (status == m_iDesiredStatus && m_iDesiredStatus == m_iStatus) { debugLogA("SetAwayMsg(): Message hasn't been changed, return."); gg_LeaveCriticalSection(&modemsg_mutex, "SetAwayMsg", 55, 2, "modemsg_mutex", 1); return 0; } } else { if (*msgPtr) mir_free(*msgPtr); *msgPtr = newMsg && *newMsg ? mir_tstrdup(newMsg) : NULL; #ifdef DEBUGMODE debugLogA("SetAwayMsg(): Message changed."); #endif } gg_LeaveCriticalSection(&modemsg_mutex, "SetAwayMsg", 55, 3, "modemsg_mutex", 1); // Change the status if it was desired by PS_SETSTATUS if (status == m_iDesiredStatus) refreshstatus(status); return 0; }
HANDLE GGPROTO::dcc7fileallow(HANDLE hTransfer, const PROTOCHAR* szPath) { struct gg_dcc7 *dcc7 = (struct gg_dcc7 *) hTransfer; char fileName[MAX_PATH], *path = mir_t2a(szPath); int iFtRemoveRes; strncpy(fileName, path, sizeof(fileName)); strncat(fileName, (char*)dcc7->filename, sizeof(fileName) - strlen(fileName)); dcc7->folder = _strdup((char *) path); dcc7->tick = 0; mir_free(path); // Remove transfer from waiting list gg_EnterCriticalSection(&ft_mutex, "dcc7fileallow", 40, "ft_mutex", 1); iFtRemoveRes = list_remove(&transfers, dcc7, 0); gg_LeaveCriticalSection(&ft_mutex, "dcc7fileallow", 40, 1, "ft_mutex", 1); if (iFtRemoveRes == -1) { debugLogA("dcc7fileallow(): File transfer denied."); ProtoBroadcastAck(dcc7->contact, ACKTYPE_FILE, ACKRESULT_DENIED, dcc7, 0); // Free transfer gg_dcc7_free(dcc7); return 0; } // Open file for appending and check if ok if ((dcc7->file_fd = _open(fileName, _O_WRONLY | _O_APPEND | _O_BINARY | _O_CREAT, _S_IREAD | _S_IWRITE)) == -1) { debugLogA("dcc7fileallow(): Failed to create file \"%s\". errno=%d: %s", fileName, errno, strerror(errno)); TCHAR error[512]; mir_sntprintf(error, SIZEOF(error), TranslateT("Cannot create transfer file. ERROR: %d: %s (dcc7)\n%s"), errno, _tcserror(errno), szPath); showpopup(m_tszUserName, error, GG_POPUP_ERROR); gg_dcc7_reject(dcc7, GG_DCC7_REJECT_USER); ProtoBroadcastAck(dcc7->contact, ACKTYPE_FILE, ACKRESULT_FAILED, dcc7, 0); // Free transfer gg_dcc7_free(dcc7); return 0; } // Put an offset to the file dcc7->offset = _lseek(dcc7->file_fd, 0, SEEK_END); gg_dcc7_accept(dcc7, dcc7->offset); // Add to watches and start transfer gg_EnterCriticalSection(&ft_mutex, "dcc7fileallow", 41, "ft_mutex", 1); list_add(&watches, dcc7, 0); gg_LeaveCriticalSection(&ft_mutex, "dcc7fileallow", 41, 1, "ft_mutex", 1); debugLogA("dcc7fileallow(): Receiving file \"%s\" from %d.", dcc7->filename, dcc7->peer_uin); return hTransfer; }
int GGPROTO::refreshstatus(int status) { if (status == ID_STATUS_OFFLINE) { disconnect(); return TRUE; } if (!isonline()) { DWORD exitCode = 0; GetExitCodeThread(pth_sess.hThread, &exitCode); if (exitCode == STILL_ACTIVE) return TRUE; #ifdef DEBUGMODE debugLogA("refreshstatus(): Waiting pth_sess thread. Going to connect..."); #endif threadwait(&pth_sess); #ifdef DEBUGMODE debugLogA("refreshstatus(): Waiting pth_sess thread - OK"); debugLogA("refreshstatus(): ForkThreadEx 21 GGPROTO::mainthread"); #endif pth_sess.hThread = ForkThreadEx(&GGPROTO::mainthread, NULL, &pth_sess.dwThreadId); } else { TCHAR *szMsg = NULL; // Select proper msg gg_EnterCriticalSection(&modemsg_mutex, "refreshstatus", 69, "modemsg_mutex", 1); szMsg = getstatusmsg(status); gg_LeaveCriticalSection(&modemsg_mutex, "refreshstatus", 69, 1, "modemsg_mutex", 1); T2Utf szMsg_utf8(szMsg); if (szMsg_utf8) { debugLogA("refreshstatus(): Setting status and away message."); gg_EnterCriticalSection(&sess_mutex, "refreshstatus", 70, "sess_mutex", 1); gg_change_status_descr(sess, status_m2gg(status, szMsg_utf8 != NULL), szMsg_utf8); gg_LeaveCriticalSection(&sess_mutex, "refreshstatus", 70, 1, "sess_mutex", 1); } else { debugLogA("refreshstatus(): Setting just status."); gg_EnterCriticalSection(&sess_mutex, "refreshstatus", 71, "sess_mutex", 1); gg_change_status(sess, status_m2gg(status, 0)); gg_LeaveCriticalSection(&sess_mutex, "refreshstatus", 71, 1, "sess_mutex", 1); } // Change status of the contact with our own UIN (if got yourself added to the contact list) changecontactstatus( getDword(GG_KEY_UIN, 0), status_m2gg(status, szMsg != NULL), szMsg, 0, 0, 0, 0); broadcastnewstatus(status); } return TRUE; }
void GGPROTO::dccconnect(uin_t uin) { struct gg_dcc *local_dcc; MCONTACT hContact = getcontact(uin, 0, 0, NULL); DWORD ip, myuin; WORD port; debugLogA("dccconnect(): Connecting to uin %d.", uin); // If unknown user or not on list ignore if (!hContact) return; // Read user IP and port ip = swap32(getDword(hContact, GG_KEY_CLIENTIP, 0)); port = getWord(hContact, GG_KEY_CLIENTPORT, 0); myuin = getDword(GG_KEY_UIN, 0); // If not port nor ip nor my uin (?) specified if (!ip || !port || !uin) return; if (!(local_dcc = gg_dcc_get_file(ip, port, myuin, uin))) return; // Add client dcc to watches gg_EnterCriticalSection(&ft_mutex, "dccconnect", 36, "ft_mutex", 1); list_add(&watches, local_dcc, 0); gg_LeaveCriticalSection(&ft_mutex, "dccconnect", 36, 1, "ft_mutex", 1); }
int GGPROTO::dccfilecancel(HANDLE hTransfer) { struct gg_dcc *dcc = (struct gg_dcc *) hTransfer; // Remove transfer from any list gg_EnterCriticalSection(&ft_mutex, "dccfilecancel", 44, "ft_mutex", 1); if (watches) list_remove(&watches, dcc, 0); if (requests) list_remove(&requests, dcc, 0); if (transfers) list_remove(&transfers, dcc, 0); gg_LeaveCriticalSection(&ft_mutex, "dccfilecancel", 44, 1, "ft_mutex", 1); // Send failed info ProtoBroadcastAck((UINT_PTR)dcc->contact, ACKTYPE_FILE, ACKRESULT_FAILED, dcc, 0); // Close file if (dcc->file_fd != -1) { _close(dcc->file_fd); dcc->file_fd = -1; } debugLogA("dccfilecancel(): Canceled file \"%s\" from/to %d.", dcc->file_info.filename, dcc->peer_uin); // Free transfer gg_free_dcc(dcc); return 0; }
int GGPROTO::dcc7filecancel(HANDLE hTransfer) { struct gg_dcc7 *dcc7 = (struct gg_dcc7 *) hTransfer; if (dcc7->type == GG_SESSION_DCC7_SEND && dcc7->state == GG_STATE_WAITING_FOR_ACCEPT) gg_dcc7_abort(dcc7); // Remove transfer from any list gg_EnterCriticalSection(&ft_mutex, "dcc7filecancel", 45, "ft_mutex", 1); if (watches) list_remove(&watches, dcc7, 0); if (transfers) list_remove(&transfers, dcc7, 0); gg_LeaveCriticalSection(&ft_mutex, "dcc7filecancel", 45, 1, "ft_mutex", 1); // Send failed info ProtoBroadcastAck((UINT_PTR)dcc7->contact, ACKTYPE_FILE, ACKRESULT_FAILED, dcc7, 0); // Close file if (dcc7->file_fd != -1) { _close(dcc7->file_fd); dcc7->file_fd = -1; } debugLogA("dcc7filecancel(): Canceled file \"%s\" from/to %d.", dcc7->filename, dcc7->peer_uin); // Free transfer gg_dcc7_free(dcc7); return 0; }
int GGPROTO::SendMsg(MCONTACT hContact, int, const char *msg) { uin_t uin = (uin_t)getDword(hContact, GG_KEY_UIN, 0); if (!isonline() || !uin) return 0; if (!msg) return 0; gg_EnterCriticalSection(&sess_mutex, "SendMsg", 53, "sess_mutex", 1); int seq = gg_send_message(sess, GG_CLASS_CHAT, uin, (BYTE*)msg); gg_LeaveCriticalSection(&sess_mutex, "SendMsg", 53, 1, "sess_mutex", 1); if (!getByte(GG_KEY_MSGACK, GG_KEYDEF_MSGACK)) { // Auto-ack message without waiting for server ack GG_SEQ_ACK *ack = (GG_SEQ_ACK*)mir_alloc(sizeof(GG_SEQ_ACK)); if (ack) { ack->seq = seq; ack->hContact = hContact; #ifdef DEBUGMODE debugLogA("SendMsg(): ForkThread 16 GGPROTO::sendackthread"); #endif ForkThread(&GGPROTO::sendackthread, ack); } } return seq; }
INT_PTR GGPROTO::getmyawaymsg(WPARAM wParam, LPARAM lParam) { INT_PTR res = 0; gg_EnterCriticalSection(&modemsg_mutex, "refreshstatus", 72, "modemsg_mutex", 1); TCHAR *szMsg = getstatusmsg(wParam ? gg_normalizestatus(wParam) : m_iStatus); if (isonline() && szMsg) res = (lParam & SGMA_UNICODE) ? (INT_PTR)mir_t2u(szMsg) : (INT_PTR)mir_t2a(szMsg); gg_LeaveCriticalSection(&modemsg_mutex, "refreshstatus", 72, 1, "modemsg_mutex", 1); return res; }
HANDLE GGPROTO::dccfileallow(HANDLE hTransfer, const TCHAR* szPath) { struct gg_dcc *dcc = (struct gg_dcc *) hTransfer; char fileName[MAX_PATH], *path = mir_t2a(szPath); mir_snprintf(fileName, "%s%s", path, dcc->file_info.filename); dcc->folder = _strdup((char*)path); dcc->tick = 0; mir_free(path); // Remove transfer from waiting list gg_EnterCriticalSection(&ft_mutex, "dccfileallow", 38, "ft_mutex", 1); list_remove(&transfers, dcc, 0); gg_LeaveCriticalSection(&ft_mutex, "dccfileallow", 38, 1, "ft_mutex", 1); // Open file for appending and check if ok if ((dcc->file_fd = _open(fileName, _O_WRONLY | _O_APPEND | _O_BINARY | _O_CREAT, _S_IREAD | _S_IWRITE)) == -1) { debugLogA("dccfileallow(): Failed to create file \"%s\". errno=%d: %s", fileName, errno, strerror(errno)); TCHAR error[512]; mir_sntprintf(error, TranslateT("Cannot create transfer file. ERROR: %d: %s (dcc)\n%s"), errno, _tcserror(errno), szPath); showpopup(m_tszUserName, error, GG_POPUP_ERROR); ProtoBroadcastAck((UINT_PTR)dcc->contact, ACKTYPE_FILE, ACKRESULT_FAILED, dcc, 0); // Free transfer gg_free_dcc(dcc); return 0; } // Put an offset to the file dcc->offset = _lseek(dcc->file_fd, 0, SEEK_END); // Add to watches and start transfer gg_EnterCriticalSection(&ft_mutex, "dccfileallow", 39, "ft_mutex", 1); list_add(&watches, dcc, 0); gg_LeaveCriticalSection(&ft_mutex, "dccfileallow", 39, 1, "ft_mutex", 1); debugLogA("dccfileallow(): Receiving file \"%s\" from %d.", dcc->file_info.filename, dcc->peer_uin); return hTransfer; }
int GGPROTO::UserIsTyping(HANDLE hContact, int type) { uin_t uin = getDword(hContact, GG_KEY_UIN, 0); if (!uin || !isonline()) return 0; if (type == PROTOTYPE_SELFTYPING_ON || type == PROTOTYPE_SELFTYPING_OFF) { gg_EnterCriticalSection(&sess_mutex, "UserIsTyping", 56, "sess_mutex", 1); gg_typing_notification(sess, uin, (type == PROTOTYPE_SELFTYPING_ON)); gg_LeaveCriticalSection(&sess_mutex, "UserIsTyping", 56, 1, "sess_mutex", 1); } return 0; }
int GGPROTO::SetStatus(int iNewStatus) { int nNewStatus = gg_normalizestatus(iNewStatus); gg_EnterCriticalSection(&modemsg_mutex, "SetStatus", 54, "modemsg_mutex", 1); m_iDesiredStatus = nNewStatus; gg_LeaveCriticalSection(&modemsg_mutex, "SetStatus", 54, 1, "modemsg_mutex", 1); // If waiting for connection retry attempt then signal to stop that if (hConnStopEvent) SetEvent(hConnStopEvent); if (m_iStatus == nNewStatus) return 0; debugLogA("SetStatus(): PS_SETSTATUS(%d) normalized to %d.", iNewStatus, nNewStatus); refreshstatus(nNewStatus); return 0; }
int GGPROTO::dccfiledeny(HANDLE hTransfer) { struct gg_dcc *dcc = (struct gg_dcc *) hTransfer; // Remove transfer from any list gg_EnterCriticalSection(&ft_mutex, "dccfiledeny", 42, "ft_mutex", 1); if (watches) list_remove(&watches, dcc, 0); if (requests) list_remove(&requests, dcc, 0); if (transfers) list_remove(&transfers, dcc, 0); gg_LeaveCriticalSection(&ft_mutex, "dccfiledeny", 42, 1, "ft_mutex", 1); debugLogA("dccfiledeny(): Rejected file \"%s\" from/to %d.", dcc->file_info.filename, dcc->peer_uin); // Free transfer gg_free_dcc(dcc); return 0; }
int GGPROTO::dcc7filedeny(HANDLE hTransfer) { struct gg_dcc7 *dcc7 = (struct gg_dcc7 *) hTransfer; gg_dcc7_reject(dcc7, GG_DCC7_REJECT_USER); // Remove transfer from any list gg_EnterCriticalSection(&ft_mutex, "dcc7filedeny", 43, "ft_mutex", 1); if (watches) list_remove(&watches, dcc7, 0); if (transfers) list_remove(&transfers, dcc7, 0); gg_LeaveCriticalSection(&ft_mutex, "dcc7filedeny", 43, 1, "ft_mutex", 1); debugLogA("dcc7filedeny(): Rejected file \"%s\" from/to %d.", dcc7->filename, dcc7->peer_uin); // Free transfer gg_dcc7_free(dcc7); return 0; }
int GGPROTO::SendMsg(HANDLE hContact, int flags, const char *msg) { uin_t uin = (uin_t)getDword(hContact, GG_KEY_UIN, 0); if (!isonline() || !uin) return 0; char* msg_utf8; if (flags & PREF_UNICODE) msg_utf8 = mir_utf8encodeW((wchar_t*)&msg[ strlen( msg )+1 ] ); else if (flags & PREF_UTF) msg_utf8 = mir_strdup(msg); else msg_utf8 = mir_utf8encode(msg); if (!msg_utf8) return 0; gg_EnterCriticalSection(&sess_mutex, "SendMsg", 53, "sess_mutex", 1); int seq = gg_send_message(sess, GG_CLASS_CHAT, uin, (BYTE*)msg_utf8); gg_LeaveCriticalSection(&sess_mutex, "SendMsg", 53, 1, "sess_mutex", 1); if (!getByte(GG_KEY_MSGACK, GG_KEYDEF_MSGACK)) { // Auto-ack message without waiting for server ack GG_SEQ_ACK *ack = (GG_SEQ_ACK*)mir_alloc(sizeof(GG_SEQ_ACK)); if (ack) { ack->seq = seq; ack->hContact = hContact; #ifdef DEBUGMODE debugLogA("SendMsg(): ForkThread 16 GGPROTO::sendackthread"); #endif ForkThread(&GGPROTO::sendackthread, ack); } } mir_free(msg_utf8); return seq; }
HANDLE GGPROTO::SendFile(MCONTACT hContact, const TCHAR* szDescription, TCHAR** ppszFiles) { char *bslash, *filename; DWORD ip, ver; WORD port; uin_t myuin, uin; // Check if main dcc thread is on if (!isonline()) return ftfail(this, hContact); filename = mir_t2a(ppszFiles[0]); // Read user IP and port ip = swap32(getDword(hContact, GG_KEY_CLIENTIP, 0)); port = getWord(hContact, GG_KEY_CLIENTPORT, 0); myuin = getDword(GG_KEY_UIN, 0); uin = getDword(hContact, GG_KEY_UIN, 0); ver = getDword(hContact, GG_KEY_CLIENTVERSION, 0); // Use DCC7 if a contact is using at least version 7.6 or unknown version if ((ver & 0x00ffffff) >= 0x29 || !ver) { gg_EnterCriticalSection(&sess_mutex, "SendFile", 46, "sess_mutex", 1); struct gg_dcc7 *dcc7 = gg_dcc7_send_file(sess, uin, filename, NULL, NULL); if (!dcc7) { gg_LeaveCriticalSection(&sess_mutex, "SendFile", 46, 1, "sess_mutex", 1); debugLogA("SendFile(): Failed to send file \"%s\".", filename); mir_free(filename); return ftfail(this, hContact); } gg_LeaveCriticalSection(&sess_mutex, "SendFile", 46, 2, "sess_mutex", 1); debugLogA("SendFile(): Sending file \"%s\" to %d.", filename, uin); // Add dcc to watches list_add(&watches, dcc7, 0); // Store handle dcc7->contact = (void*)hContact; dcc7->folder = _strdup(filename); dcc7->tick = 0; // Make folder name bslash = strrchr(dcc7->folder, '\\'); if (bslash) *(bslash + 1) = 0; else *(dcc7->folder) = 0; mir_free(filename); return dcc7; } // Return if bad connection info if (!port || !uin || !myuin) { debugLogA("SendFile(): Bad contact uin or my uin. Exit."); mir_free(filename); return ftfail(this, hContact); } // Try to connect if not ask user to connect me struct gg_dcc *dcc = NULL; if ((ip && port >= 10 && !(dcc = gg_dcc_send_file(ip, port, myuin, uin))) || (port < 10 && port > 0)) { // Make fake dcc structure dcc = (gg_dcc*)malloc(sizeof(struct gg_dcc)); memset(dcc, 0, sizeof(struct gg_dcc)); // Fill up structures dcc->uin = myuin; dcc->peer_uin = uin; dcc->fd = -1; dcc->type = GG_SESSION_DCC_SEND; debugLogA("SendFile(): Requesting user to connect us and scheduling gg_dcc struct for a later use."); gg_EnterCriticalSection(&sess_mutex, "SendFile", 47, "sess_mutex", 1); gg_dcc_request(sess, uin); gg_LeaveCriticalSection(&sess_mutex, "SendFile", 47, 1, "sess_mutex", 1); list_add(&requests, dcc, 0); } // Write filename if (gg_dcc_fill_file_info(dcc, filename) == -1) { debugLogA("SendFile(): Cannot open and file fileinfo \"%s\".", filename); gg_free_dcc(dcc); mir_free(filename); return ftfail(this, hContact); } debugLogA("SendFile(): Sending file \"%s\" to %d in %s mode.", filename, uin, (dcc->fd != -1) ? "active" : "passive"); // Add dcc to watches if not passive if (dcc->fd != -1) list_add(&watches, dcc, 0); // Store handle dcc->contact = (void*)hContact; dcc->folder = _strdup(filename); dcc->tick = 0; // Make folder name bslash = strrchr(dcc->folder, '\\'); if (bslash) *(bslash + 1) = 0; else *(dcc->folder) = 0; mir_free(filename); return dcc; }
int GGPROTO::GetInfo(HANDLE hContact, int infoType) { gg_pubdir50_t req; // Custom contact info if (hContact) { if (!(req = gg_pubdir50_new(GG_PUBDIR50_SEARCH))) { #ifdef DEBUGMODE debugLogA("GetInfo(): ForkThread 6 GGPROTO::cmdgetinfothread"); #endif ForkThread(&GGPROTO::cmdgetinfothread, hContact); return 1; } // Add uin and search it gg_pubdir50_add(req, GG_PUBDIR50_UIN, ditoa((uin_t)getDword(hContact, GG_KEY_UIN, 0))); gg_pubdir50_seq_set(req, GG_SEQ_INFO); debugLogA("GetInfo(): Requesting user info.", req->seq); if (isonline()) { gg_EnterCriticalSection(&sess_mutex, "GetInfo", 48, "sess_mutex", 1); if (!gg_pubdir50(sess, req)) { gg_LeaveCriticalSection(&sess_mutex, "GetInfo", 48, 1, "sess_mutex", 1); #ifdef DEBUGMODE debugLogA("GetInfo(): ForkThread 7 GGPROTO::cmdgetinfothread"); #endif ForkThread(&GGPROTO::cmdgetinfothread, hContact); return 1; } gg_LeaveCriticalSection(&sess_mutex, "GetInfo", 48, 2, "sess_mutex", 1); } } // Own contact info else { if (!(req = gg_pubdir50_new(GG_PUBDIR50_READ))) { #ifdef DEBUGMODE debugLogA("GetInfo(): ForkThread 8 GGPROTO::cmdgetinfothread"); #endif ForkThread(&GGPROTO::cmdgetinfothread, hContact); return 1; } // Add seq gg_pubdir50_seq_set(req, GG_SEQ_CHINFO); debugLogA("GetInfo(): Requesting owner info.", req->seq); if (isonline()) { gg_EnterCriticalSection(&sess_mutex, "GetInfo", 49, "sess_mutex", 1); if (!gg_pubdir50(sess, req)) { gg_LeaveCriticalSection(&sess_mutex, "GetInfo", 49, 1, "sess_mutex", 1); #ifdef DEBUGMODE debugLogA("GetInfo(): ForkThread 9 GGPROTO::cmdgetinfothread"); #endif ForkThread(&GGPROTO::cmdgetinfothread, hContact); return 1; } gg_LeaveCriticalSection(&sess_mutex, "GetInfo", 49, 2, "sess_mutex", 1); } } debugLogA("GetInfo(): Seq %d.", req->seq); gg_pubdir50_free(req); return 1; }
HANDLE GGPROTO::SearchByName(const PROTOCHAR *nick, const PROTOCHAR *firstName, const PROTOCHAR *lastName) { gg_pubdir50_t req; unsigned long crc; char data[512] = "\0"; // Check if connected and if there's a search data if (!isonline()) return 0; if (!nick && !firstName && !lastName) return 0; if (!(req = gg_pubdir50_new(GG_PUBDIR50_SEARCH))) { #ifdef DEBUGMODE debugLogA("SearchByName(): ForkThread 12 GGPROTO::searchthread"); #endif ForkThread(&GGPROTO::searchthread, NULL); return (HANDLE)1; } // Add nick,firstName,lastName and search it if (nick) { char *nick_utf8 = mir_utf8encodeT(nick); gg_pubdir50_add(req, GG_PUBDIR50_NICKNAME, nick_utf8); strncat(data, nick_utf8, sizeof(data) - strlen(data)); mir_free(nick_utf8); } strncat(data, ".", sizeof(data) - strlen(data)); if (firstName) { char *firstName_utf8 = mir_utf8encodeT(firstName); gg_pubdir50_add(req, GG_PUBDIR50_FIRSTNAME, firstName_utf8); strncat(data, firstName_utf8, sizeof(data) - strlen(data)); mir_free(firstName_utf8); } strncat(data, ".", sizeof(data) - strlen(data)); if (lastName) { char *lastName_utf8 = mir_utf8encodeT(lastName); gg_pubdir50_add(req, GG_PUBDIR50_LASTNAME, lastName_utf8); strncat(data, lastName_utf8, sizeof(data) - strlen(data)); mir_free(lastName_utf8); } strncat(data, ".", sizeof(data) - strlen(data)); // Count crc & check if the data was equal if yes do same search with shift crc = crc_get(data); if (crc == last_crc && next_uin) gg_pubdir50_add(req, GG_PUBDIR50_START, ditoa(next_uin)); else last_crc = crc; gg_pubdir50_seq_set(req, GG_SEQ_SEARCH); gg_EnterCriticalSection(&sess_mutex, "SearchByName", 51, "sess_mutex", 1); if (!gg_pubdir50(sess, req)) { gg_LeaveCriticalSection(&sess_mutex, "SearchByName", 51, 1, "sess_mutex", 1); #ifdef DEBUGMODE debugLogA("SearchByName(): ForkThread 13 GGPROTO::searchthread"); #endif ForkThread(&GGPROTO::searchthread, NULL); return (HANDLE)1; } gg_LeaveCriticalSection(&sess_mutex, "SearchByName", 51, 2, "sess_mutex", 1); debugLogA("SearchByName(): Seq %d.", req->seq); gg_pubdir50_free(req); return (HANDLE)1; }
HWND GGPROTO::SearchAdvanced(HWND hwndDlg) { gg_pubdir50_t req; TCHAR text[64]; char data[800] = "\0"; unsigned long crc; // Check if connected if (!isonline()) return (HWND)0; if (!(req = gg_pubdir50_new(GG_PUBDIR50_SEARCH))) { #ifdef DEBUGMODE debugLogA("SearchAdvanced(): ForkThread 14 GGPROTO::searchthread"); #endif ForkThread(&GGPROTO::searchthread, NULL); return (HWND)1; } // Fetch search data GetDlgItemText(hwndDlg, IDC_FIRSTNAME, text, sizeof(text)); if (_tcslen(text)) { char *firstName_utf8 = mir_utf8encodeT(text); gg_pubdir50_add(req, GG_PUBDIR50_FIRSTNAME, firstName_utf8); strncat(data, firstName_utf8, sizeof(data) - strlen(data)); mir_free(firstName_utf8); } /* 1 */ strncat(data, ".", sizeof(data) - strlen(data)); GetDlgItemText(hwndDlg, IDC_LASTNAME, text, sizeof(text)); if (_tcslen(text)) { char *lastName_utf8 = mir_utf8encodeT(text); gg_pubdir50_add(req, GG_PUBDIR50_LASTNAME, lastName_utf8); strncat(data, lastName_utf8, sizeof(data) - strlen(data)); mir_free(lastName_utf8); } /* 2 */ strncat(data, ".", sizeof(data) - strlen(data)); GetDlgItemText(hwndDlg, IDC_NICKNAME, text, sizeof(text)); if (_tcslen(text)) { char *nickName_utf8 = mir_utf8encodeT(text); gg_pubdir50_add(req, GG_PUBDIR50_NICKNAME, nickName_utf8); strncat(data, nickName_utf8, sizeof(data) - strlen(data)); mir_free(nickName_utf8); } /* 3 */ strncat(data, ".", sizeof(data) - strlen(data)); GetDlgItemText(hwndDlg, IDC_CITY, text, sizeof(text)); if (_tcslen(text)) { char *city_utf8 = mir_utf8encodeT(text); gg_pubdir50_add(req, GG_PUBDIR50_CITY, city_utf8); strncat(data, city_utf8, sizeof(data) - strlen(data)); mir_free(city_utf8); } /* 4 */ strncat(data, ".", sizeof(data) - strlen(data)); GetDlgItemText(hwndDlg, IDC_AGEFROM, text, sizeof(text)); if (_tcslen(text)) { int yearTo = _tstoi(text); int yearFrom; time_t t = time(NULL); struct tm *lt = localtime(&t); int ay = lt->tm_year + 1900; char age[16]; GetDlgItemTextA(hwndDlg, IDC_AGETO, age, sizeof(age)); yearFrom = atoi(age); // Count & fix ranges if (!yearTo) yearTo = ay; else yearTo = ay - yearTo; if (!yearFrom) yearFrom = 0; else yearFrom = ay - yearFrom; mir_sntprintf(text, sizeof(text), _T("%d %d"), yearFrom, yearTo); char *age_utf8 = mir_utf8encodeT(text); gg_pubdir50_add(req, GG_PUBDIR50_BIRTHYEAR, age_utf8); strncat(data, age_utf8, sizeof(data) - strlen(data)); mir_free(age_utf8); } /* 5 */ strncat(data, ".", sizeof(data) - strlen(data)); switch(SendDlgItemMessage(hwndDlg, IDC_GENDER, CB_GETCURSEL, 0, 0)) { case 1: gg_pubdir50_add(req, GG_PUBDIR50_GENDER, GG_PUBDIR50_GENDER_FEMALE); strncat(data, GG_PUBDIR50_GENDER_MALE, sizeof(data) - strlen(data)); break; case 2: gg_pubdir50_add(req, GG_PUBDIR50_GENDER, GG_PUBDIR50_GENDER_MALE); strncat(data, GG_PUBDIR50_GENDER_FEMALE, sizeof(data) - strlen(data)); break; } /* 6 */ strncat(data, ".", sizeof(data) - strlen(data)); if (IsDlgButtonChecked(hwndDlg, IDC_ONLYCONNECTED)) { gg_pubdir50_add(req, GG_PUBDIR50_ACTIVE, GG_PUBDIR50_ACTIVE_TRUE); strncat(data, GG_PUBDIR50_ACTIVE_TRUE, sizeof(data) - strlen(data)); } /* 7 */ strncat(data, ".", sizeof(data) - strlen(data)); // No data entered if (strlen(data) <= 7 || (strlen(data) == 8 && IsDlgButtonChecked(hwndDlg, IDC_ONLYCONNECTED))) return (HWND)0; // Count crc & check if the data was equal if yes do same search with shift crc = crc_get(data); if (crc == last_crc && next_uin) gg_pubdir50_add(req, GG_PUBDIR50_START, ditoa(next_uin)); else last_crc = crc; gg_pubdir50_seq_set(req, GG_SEQ_SEARCH); if (isonline()) { gg_EnterCriticalSection(&sess_mutex, "SearchAdvanced", 52, "sess_mutex", 1); if (!gg_pubdir50(sess, req)) { gg_LeaveCriticalSection(&sess_mutex, "SearchAdvanced", 52, 1, "sess_mutex", 1); #ifdef DEBUGMODE debugLogA("SearchAdvanced(): ForkThread 15 GGPROTO::searchthread"); #endif ForkThread(&GGPROTO::searchthread, NULL); return (HWND)1; } gg_LeaveCriticalSection(&sess_mutex, "SearchAdvanced", 52, 2, "sess_mutex", 1); } debugLogA("SearchAdvanced(): Seq %d.", req->seq); gg_pubdir50_free(req); return (HWND)1; }
void __cdecl GGPROTO::dccmainthread(void*) { uin_t uin; gg_event *e; struct timeval tv; fd_set rd, wd; int ret; SOCKET maxfd; DWORD tick; list_t l; char szFilename[MAX_PATH]; // Zero up lists watches = transfers = requests = l = NULL; debugLogA("dccmainthread(): started. DCC Server Thread Starting"); // Readup number if (!(uin = getDword(GG_KEY_UIN, 0))) { debugLogA("dccmainthread(): No Gadu-Gadu number specified. Exiting."); if (hEvent) SetEvent(hEvent); #ifdef DEBUGMODE debugLogA("dccmainthread(): end 1."); #endif return; } // Create listen socket on config direct port if (!(dcc = gg_dcc_socket_create(uin, (uint16_t)getWord(GG_KEY_DIRECTPORT, GG_KEYDEF_DIRECTPORT)))) { debugLogA("dccmainthread(): Cannot create DCC listen socket. Exiting."); // Signalize mainthread we haven't start if (hEvent) SetEvent(hEvent); #ifdef DEBUGMODE debugLogA("dccmainthread(): end 2."); #endif return; } gg_dcc_port = dcc->port; gg_dcc_ip = inet_addr("255.255.255.255"); debugLogA("dccmainthread(): Listening on port %d.", gg_dcc_port); // Signalize mainthread we started if (hEvent) SetEvent(hEvent); // Add main dcc handler to watches list_add(&watches, dcc, 0); // Do while we are in the main server thread while(pth_dcc.dwThreadId && dcc) { // Timeouts tv.tv_sec = 1; tv.tv_usec = 0; // Prepare descriptiors for select FD_ZERO(&rd); FD_ZERO(&wd); for (maxfd = 0, l = watches; l; l = l->next) { gg_common *w = (gg_common*)l->data; if (!w || w->state == GG_STATE_ERROR || w->state == GG_STATE_IDLE || w->state == GG_STATE_DONE) continue; // Check if it's proper descriptor if (w->fd == -1) continue; if (w->fd > maxfd) maxfd = w->fd; if ((w->check & GG_CHECK_READ)) FD_SET(w->fd, &rd); if ((w->check & GG_CHECK_WRITE)) FD_SET(w->fd, &wd); } // Wait for data on selects ret = select(maxfd + 1, &rd, &wd, NULL, &tv); // Check for select error if (ret == -1) { if (errno == EBADF) debugLogA("dccmainthread(): Bad descriptor on select()."); else if (errno != EINTR) debugLogA("dccmainthread(): Unknown error on select()."); continue; } // Process watches (carefull with l) l = watches; gg_EnterCriticalSection(&ft_mutex, "dccmainthread", 37, "ft_mutex", 1); while (l) { struct gg_common *local_c = (gg_common*)l->data; struct gg_dcc *local_dcc = (gg_dcc*)l->data; struct gg_dcc7 *local_dcc7 = (gg_dcc7*)l->data; l = l->next; switch (local_c->type) { default: if (!local_dcc || (!FD_ISSET(local_dcc->fd, &rd) && !FD_ISSET(local_dcc->fd, &wd))) continue; ///////////////////////////////////////////////////////////////// // Process DCC events // Connection broken/closed gg_LeaveCriticalSection(&ft_mutex, "dccmainthread", 37, 2, "ft_mutex", 1); if (!(e = gg_dcc_socket_watch_fd(local_dcc))) { debugLogA("dccmainthread(): Socket closed."); // Remove socket and _close gg_EnterCriticalSection(&ft_mutex, "dccmainthread", 37, "ft_mutex", 1); list_remove(&watches, local_dcc, 0); gg_dcc_socket_free(local_dcc); // Check if it's main socket if (local_dcc == dcc) dcc = NULL; continue; } else { gg_EnterCriticalSection(&ft_mutex, "dccmainthread", 37, "ft_mutex", 1); debugLogA("dccmainthread(): Event: %s", ggdebug_eventtype(e)); } switch(e->type) { // Client connected case GG_EVENT_DCC_NEW: list_add(&watches, e->event.dcc_new, 0); e->event.dcc_new = NULL; break; // case GG_EVENT_NONE: // If transfer in progress do status if (local_dcc->file_fd != -1 && local_dcc->offset > 0 && (((tick = GetTickCount()) - local_dcc->tick) > GGSTATREFRESHEVERY)) { PROTOFILETRANSFERSTATUS pfts; local_dcc->tick = tick; mir_snprintf(szFilename, "%s%s", local_dcc->folder, local_dcc->file_info.filename); memset(&pfts, 0, sizeof(PROTOFILETRANSFERSTATUS)); pfts.cbSize = sizeof(PROTOFILETRANSFERSTATUS); pfts.hContact = (UINT_PTR)local_dcc->contact; pfts.flags = (local_dcc->type == GG_SESSION_DCC_SEND); pfts.pszFiles = NULL; pfts.totalFiles = 1; pfts.currentFileNumber = 0; pfts.totalBytes = local_dcc->file_info.size; pfts.totalProgress = local_dcc->offset; pfts.szWorkingDir = local_dcc->folder; pfts.szCurrentFile = szFilename; pfts.currentFileSize = local_dcc->file_info.size; pfts.currentFileProgress = local_dcc->offset; pfts.currentFileTime = 0; gg_LeaveCriticalSection(&ft_mutex, "dccmainthread", 37, 3, "ft_mutex", 1); ProtoBroadcastAck((UINT_PTR)local_dcc->contact, ACKTYPE_FILE, ACKRESULT_DATA, local_dcc, (LPARAM)&pfts); gg_EnterCriticalSection(&ft_mutex, "dccmainthread", 37, "ft_mutex", 1); } break; // Connection was successfuly ended case GG_EVENT_DCC_DONE: debugLogA("dccmainthread(): Client: %d, Transfer done ! Closing connection.", dcc->peer_uin); // Remove from watches list_remove(&watches, local_dcc, 0); // Close file & success if (local_dcc->file_fd != -1) { PROTOFILETRANSFERSTATUS pfts; mir_snprintf(szFilename, "%s%s", local_dcc->folder, local_dcc->file_info.filename); memset(&pfts, 0, sizeof(PROTOFILETRANSFERSTATUS)); pfts.cbSize = sizeof(PROTOFILETRANSFERSTATUS); pfts.hContact = (UINT_PTR)local_dcc->contact; pfts.flags = (local_dcc->type == GG_SESSION_DCC_SEND); pfts.pszFiles = NULL; pfts.totalFiles = 1; pfts.currentFileNumber = 0; pfts.totalBytes = local_dcc->file_info.size; pfts.totalProgress = local_dcc->file_info.size; pfts.szWorkingDir = local_dcc->folder; pfts.szCurrentFile = szFilename; pfts.currentFileSize = local_dcc->file_info.size; pfts.currentFileProgress = local_dcc->file_info.size; pfts.currentFileTime = 0; gg_LeaveCriticalSection(&ft_mutex, "dccmainthread", 37, 4, "ft_mutex", 1); ProtoBroadcastAck((UINT_PTR)local_dcc->contact, ACKTYPE_FILE, ACKRESULT_DATA, local_dcc, (LPARAM)&pfts); gg_EnterCriticalSection(&ft_mutex, "dccmainthread", 37, "ft_mutex", 1); _close(local_dcc->file_fd); local_dcc->file_fd = -1; gg_LeaveCriticalSection(&ft_mutex, "dccmainthread", 37, 5, "ft_mutex", 1); ProtoBroadcastAck((UINT_PTR)local_dcc->contact, ACKTYPE_FILE, ACKRESULT_SUCCESS, local_dcc, 0); gg_EnterCriticalSection(&ft_mutex, "dccmainthread", 37, "ft_mutex", 1); } // Free dcc gg_free_dcc(local_dcc); if (local_dcc == dcc) dcc = NULL; break; // Client error case GG_EVENT_DCC_ERROR: switch (e->event.dcc_error) { case GG_ERROR_DCC_HANDSHAKE: debugLogA("dccmainthread(): Client: %d, Handshake error.", local_dcc->peer_uin); break; case GG_ERROR_DCC_NET: debugLogA("dccmainthread(): Client: %d, Network error.", local_dcc->peer_uin); break; case GG_ERROR_DCC_FILE: debugLogA("dccmainthread(): Client: %d, File read/write error.", local_dcc->peer_uin); break; case GG_ERROR_DCC_EOF: debugLogA("dccmainthread(): Client: %d, End of file/connection error.", local_dcc->peer_uin); break; case GG_ERROR_DCC_REFUSED: debugLogA("dccmainthread(): Client: %d, Connection refused error.", local_dcc->peer_uin); break; default: debugLogA("dccmainthread(): Client: %d, Unknown error.", local_dcc->peer_uin); } // Don't do anything if it's main socket if (local_dcc == dcc) break; // Remove from watches list_remove(&watches, local_dcc, 0); // Close file & fail if (local_dcc->contact) { _close(local_dcc->file_fd); local_dcc->file_fd = -1; gg_LeaveCriticalSection(&ft_mutex, "dccmainthread", 37, 6, "ft_mutex", 1); ProtoBroadcastAck((UINT_PTR)local_dcc->contact, ACKTYPE_FILE, ACKRESULT_FAILED, local_dcc, 0); gg_EnterCriticalSection(&ft_mutex, "dccmainthread", 37, "ft_mutex", 1); } // Free dcc gg_free_dcc(local_dcc); if (local_dcc == dcc) dcc = NULL; break; // Need file acknowledgement case GG_EVENT_DCC_NEED_FILE_ACK: debugLogA("dccmainthread(): Client: %d, File ack filename \"%s\" size %d.", local_dcc->peer_uin, local_dcc->file_info.filename, local_dcc->file_info.size); // Do not watch for transfer until user accept it list_remove(&watches, local_dcc, 0); // Add to waiting transfers list_add(&transfers, local_dcc, 0); ////////////////////////////////////////////////// // Add file recv request { // Make new ggtransfer struct local_dcc->contact = (void*)getcontact(local_dcc->peer_uin, 0, 0, NULL); TCHAR* filenameT = mir_utf8decodeT((char*)dcc->file_info.filename); PROTORECVFILET pre = {0}; pre.dwFlags = PRFF_TCHAR; pre.fileCount = 1; pre.timestamp = time(NULL); pre.descr.t = filenameT; pre.files.t = &filenameT; pre.lParam = (LPARAM)local_dcc; gg_LeaveCriticalSection(&ft_mutex, "dccmainthread", 37, 7, "ft_mutex", 1); ProtoChainRecvFile((UINT_PTR)local_dcc->contact, &pre); gg_EnterCriticalSection(&ft_mutex, "dccmainthread", 37, "ft_mutex", 1); mir_free(filenameT); } break; // Need client accept case GG_EVENT_DCC_CLIENT_ACCEPT: debugLogA("dccmainthread(): Client: %d, Client accept.", local_dcc->peer_uin); // Check if user is on the list and if it is my uin if (getcontact(local_dcc->peer_uin, 0, 0, NULL) && getDword(GG_KEY_UIN, -1) == local_dcc->uin) break; // Kill unauthorized dcc list_remove(&watches, dcc, 0); gg_free_dcc(local_dcc); if (local_dcc == dcc) dcc = NULL; break; // Client connected as we wished to (callback) case GG_EVENT_DCC_CALLBACK: { int found = 0; debugLogA("dccmainthread(): Callback from client %d.", local_dcc->peer_uin); // Seek for stored callback request for (l = requests; l; l = l->next) { struct gg_dcc *req = (gg_dcc*)l->data; if (req && req->peer_uin == local_dcc->peer_uin) { gg_dcc_set_type(local_dcc, GG_SESSION_DCC_SEND); found = 1; // Copy data req ===> dcc local_dcc->folder = req->folder; local_dcc->contact = req->contact; local_dcc->file_fd = req->file_fd; memcpy(&local_dcc->file_info, &req->file_info, sizeof(struct gg_file_info)); // Copy data back to dcc ===> req memcpy(req, local_dcc, sizeof(struct gg_dcc)); // Remove request list_remove(&requests, req, 0); // Remove dcc from watches list_remove(&watches, local_dcc, 0); // Add request to watches list_add(&watches, req, 0); // Free old dat gg_free_dcc(local_dcc); debugLogA("dccmainthread(): Found stored request to client %d, filename \"%s\" size %d, folder \"%s\".", req->peer_uin, req->file_info.filename, req->file_info.size, req->folder); break; } } if (!found) { debugLogA("dccmainthread(): Unknown request to client %d.", local_dcc->peer_uin); // Kill unauthorized dcc list_remove(&watches, local_dcc, 0); gg_free_dcc(local_dcc); if (local_dcc == dcc) dcc = NULL; } break; } } // Free event gg_free_event(e); break; case GG_SESSION_DCC7_SOCKET: case GG_SESSION_DCC7_GET: case GG_SESSION_DCC7_SEND: case GG_SESSION_DCC7_VOICE: if (!local_dcc7 || (!FD_ISSET(local_dcc7->fd, &rd) && !FD_ISSET(local_dcc7->fd, &wd))) continue; ///////////////////////////////////////////////////////////////// // Process DCC7 events // Connection broken/closed gg_LeaveCriticalSection(&ft_mutex, "dccmainthread", 37, 8, "ft_mutex", 1); if (!(e = gg_dcc7_watch_fd(local_dcc7))) { debugLogA("dccmainthread(): Socket closed."); // Remove socket and _close gg_EnterCriticalSection(&ft_mutex, "dccmainthread", 37, "ft_mutex", 1); list_remove(&watches, local_dcc7, 0); gg_dcc7_free(local_dcc7); continue; } else { gg_EnterCriticalSection(&ft_mutex, "dccmainthread", 37, "ft_mutex", 1); debugLogA("dccmainthread(): Event: %s", ggdebug_eventtype(e)); } switch(e->type) { // case GG_EVENT_NONE: // If transfer in progress do status if (local_dcc7->file_fd != -1 && local_dcc7->offset > 0 && (((tick = GetTickCount()) - local_dcc7->tick) > GGSTATREFRESHEVERY)) { PROTOFILETRANSFERSTATUS pfts; local_dcc7->tick = tick; mir_snprintf(szFilename, "%s%s", local_dcc->folder, local_dcc7->filename); memset(&pfts, 0, sizeof(PROTOFILETRANSFERSTATUS)); pfts.cbSize = sizeof(PROTOFILETRANSFERSTATUS); pfts.hContact = (UINT_PTR)local_dcc7->contact; pfts.flags = (local_dcc7->type == GG_SESSION_DCC7_SEND); pfts.pszFiles = NULL; pfts.totalFiles = 1; pfts.currentFileNumber = 0; pfts.totalBytes = local_dcc7->size; pfts.totalProgress = local_dcc7->offset; pfts.szWorkingDir = local_dcc7->folder; pfts.szCurrentFile = szFilename; pfts.currentFileSize = local_dcc7->size; pfts.currentFileProgress = local_dcc7->offset; pfts.currentFileTime = 0; gg_LeaveCriticalSection(&ft_mutex, "dccmainthread", 37, 9, "ft_mutex", 1); ProtoBroadcastAck((UINT_PTR)local_dcc7->contact, ACKTYPE_FILE, ACKRESULT_DATA, local_dcc7, (LPARAM)&pfts); gg_EnterCriticalSection(&ft_mutex, "dccmainthread", 37, "ft_mutex", 1); } break; // Connection was successfuly ended case GG_EVENT_DCC7_DONE: debugLogA("dccmainthread(): Client: %d, Transfer done ! Closing connection.", dcc->peer_uin); // Remove from watches list_remove(&watches, local_dcc7, 0); // Close file & success if (local_dcc7->file_fd != -1) { PROTOFILETRANSFERSTATUS pfts; mir_snprintf(szFilename, "%s%s", local_dcc->folder, local_dcc7->filename); memset(&pfts, 0, sizeof(PROTOFILETRANSFERSTATUS)); pfts.cbSize = sizeof(PROTOFILETRANSFERSTATUS); pfts.hContact = (UINT_PTR)local_dcc7->contact; pfts.flags = (local_dcc7->type == GG_SESSION_DCC7_SEND); pfts.pszFiles = NULL; pfts.totalFiles = 1; pfts.currentFileNumber = 0; pfts.totalBytes = local_dcc7->size; pfts.totalProgress = local_dcc7->size; pfts.szWorkingDir = local_dcc7->folder; pfts.szCurrentFile = szFilename; pfts.currentFileSize = local_dcc7->size; pfts.currentFileProgress = local_dcc7->size; pfts.currentFileTime = 0; gg_LeaveCriticalSection(&ft_mutex, "dccmainthread", 37, 10, "ft_mutex", 1); ProtoBroadcastAck((UINT_PTR)local_dcc7->contact, ACKTYPE_FILE, ACKRESULT_DATA, local_dcc7, (LPARAM)&pfts); gg_EnterCriticalSection(&ft_mutex, "dccmainthread", 37, "ft_mutex", 1); _close(local_dcc7->file_fd); local_dcc7->file_fd = -1; gg_LeaveCriticalSection(&ft_mutex, "dccmainthread", 37, 11, "ft_mutex", 1); ProtoBroadcastAck((UINT_PTR)local_dcc7->contact, ACKTYPE_FILE, ACKRESULT_SUCCESS, local_dcc7, 0); gg_EnterCriticalSection(&ft_mutex, "dccmainthread", 37, "ft_mutex", 1); } // Free dcc gg_dcc7_free(local_dcc7); break; // Client error case GG_EVENT_DCC7_ERROR: switch (e->event.dcc7_error) { case GG_ERROR_DCC7_HANDSHAKE: debugLogA("dccmainthread(): Client: %d, Handshake error.", local_dcc7->peer_uin); break; case GG_ERROR_DCC7_NET: debugLogA("dccmainthread(): Client: %d, Network error.", local_dcc7->peer_uin); break; case GG_ERROR_DCC7_FILE: debugLogA("dccmainthread(): Client: %d, File read/write error.", local_dcc7->peer_uin); break; case GG_ERROR_DCC7_EOF: debugLogA("dccmainthread(): Client: %d, End of file/connection error.", local_dcc7->peer_uin); break; case GG_ERROR_DCC7_REFUSED: debugLogA("dccmainthread(): Client: %d, Connection refused error.", local_dcc7->peer_uin); break; case GG_ERROR_DCC7_RELAY: debugLogA("dccmainthread(): Client: %d, Relay connection error.", local_dcc7->peer_uin); break; default: debugLogA("dccmainthread(): Client: %d, Unknown error.", local_dcc7->peer_uin); } // Remove from watches list_remove(&watches, local_dcc7, 0); // Close file & fail if (local_dcc7->file_fd != -1) { _close(local_dcc7->file_fd); local_dcc7->file_fd = -1; } if (local_dcc7->contact) { gg_LeaveCriticalSection(&ft_mutex, "dccmainthread", 37, 12, "ft_mutex", 1); ProtoBroadcastAck((UINT_PTR)local_dcc7->contact, ACKTYPE_FILE, ACKRESULT_FAILED, local_dcc7, 0); gg_EnterCriticalSection(&ft_mutex, "dccmainthread", 37, "ft_mutex", 1); } // Free dcc gg_dcc7_free(local_dcc7); break; } // Free event gg_free_event(e); break; } } gg_LeaveCriticalSection(&ft_mutex, "dccmainthread", 37, 1, "ft_mutex", 1); } // Close all dcc client sockets for (l = watches; l; l = l->next) { struct gg_common *c = (gg_common*)l->data; if (!c) continue; if (c->type == GG_SESSION_DCC7_SOCKET || c->type == GG_SESSION_DCC7_SEND || c->type == GG_SESSION_DCC7_GET) { struct gg_dcc7 *local_dcc7 = (gg_dcc7*)l->data; gg_dcc7_free(local_dcc7); } else { struct gg_dcc *local_dcc = (gg_dcc*)l->data; gg_dcc_socket_free(local_dcc); // Check if it's main socket if (local_dcc == dcc) dcc = NULL; } } // Close all waiting for aknowledgle transfers for (l = transfers; l; l = l->next) { struct gg_common *c = (gg_common*)l->data; if (!c) continue; if (c->type == GG_SESSION_DCC7_SOCKET || c->type == GG_SESSION_DCC7_SEND || c->type == GG_SESSION_DCC7_GET) { struct gg_dcc7 *local_dcc7 = (gg_dcc7*)l->data; gg_dcc7_free(local_dcc7); } else { struct gg_dcc *local_dcc = (gg_dcc*)l->data; gg_dcc_socket_free(local_dcc); } } // Close all waiting dcc requests for (l = requests; l; l = l->next) { struct gg_dcc *local_dcc = (gg_dcc*)l->data; if (local_dcc) gg_free_dcc(local_dcc); } list_destroy(watches, 0); list_destroy(transfers, 0); list_destroy(requests, 0); gg_dcc_port = 0; gg_dcc_ip = 0; debugLogA("dccmainthread(): end. DCC Server Thread Ending"); }
int GGPROTO::gc_event(WPARAM, LPARAM lParam) { GCHOOK *gch = (GCHOOK *)lParam; GGGC *chat = NULL; uin_t uin; // Check if we got our protocol, and fields are set if (!gch || !gch->pDest || !gch->pDest->ptszID || !gch->pDest->pszModule || mir_strcmpi(gch->pDest->pszModule, m_szModuleName) || !(uin = getDword(GG_KEY_UIN, 0)) || !(chat = gc_lookup(gch->pDest->ptszID))) return 0; // Window terminated (Miranda exit) if (gch->pDest->iType == SESSION_TERMINATE) { debugLog(_T("gc_event(): Terminating chat %x, id %s from chat window..."), chat, gch->pDest->ptszID); // Destroy chat entry free(chat->recipients); list_remove(&chats, chat, 1); // Remove contact from contact list (duh!) should be done by chat.dll !! for (MCONTACT hContact = db_find_first(); hContact; ) { MCONTACT hNext = db_find_next(hContact); DBVARIANT dbv; if (!getTString(hContact, "ChatRoomID", &dbv)) { if (dbv.ptszVal && !mir_tstrcmp(gch->pDest->ptszID, dbv.ptszVal)) CallService(MS_DB_CONTACT_DELETE, hContact, 0); db_free(&dbv); } hContact = hNext; } return 1; } // Message typed / send only if online if (isonline() && (gch->pDest->iType == GC_USER_MESSAGE) && gch->ptszText) { TCHAR id[32]; UIN2IDT(uin, id); DBVARIANT dbv; GCDEST gcd = { m_szModuleName, gch->pDest->ptszID, GC_EVENT_MESSAGE }; GCEVENT gce = { sizeof(gce), &gcd }; gce.ptszUID = id; gce.ptszText = gch->ptszText; TCHAR* nickT; if (!getTString(GG_KEY_NICK, &dbv)){ nickT = mir_tstrdup(dbv.ptszVal); db_free(&dbv); } else nickT = mir_tstrdup(TranslateT("Me")); gce.ptszNick = nickT; // Get rid of CRLF at back int lc = (int)mir_tstrlen(gch->ptszText) - 1; while(lc >= 0 && (gch->ptszText[lc] == '\n' || gch->ptszText[lc] == '\r')) gch->ptszText[lc --] = 0; gce.time = time(NULL); gce.bIsMe = 1; gce.dwFlags = GCEF_ADDTOLOG; debugLog(_T("gc_event(): Sending conference message to room %s, \"%s\"."), gch->pDest->ptszID, gch->ptszText); CallServiceSync(MS_GC_EVENT, 0, (LPARAM)&gce); mir_free(nickT); T2Utf pszText_utf8(gch->ptszText); gg_EnterCriticalSection(&sess_mutex, "gc_event", 57, "sess_mutex", 1); gg_send_message_confer(sess, GG_CLASS_CHAT, chat->recipients_count, chat->recipients, pszText_utf8); gg_LeaveCriticalSection(&sess_mutex, "gc_event", 57, 1, "sess_mutex", 1); return 1; } // Privmessage selected if (gch->pDest->iType == GC_USER_PRIVMESS) { MCONTACT hContact = NULL; if ((uin = _ttoi(gch->ptszUID)) && (hContact = getcontact(uin, 1, 0, NULL))) CallService(MS_MSG_SENDMESSAGE, hContact, 0); } debugLog(_T("gc_event(): Unhandled event %d, chat %x, uin %d, text \"%s\"."), gch->pDest->iType, chat, uin, gch->ptszText); return 0; }
HANDLE GGPROTO::SearchByName(const TCHAR *nick, const TCHAR *firstName, const TCHAR *lastName) { // Check if connected and if there's a search data if (!isonline()) return 0; if (!nick && !firstName && !lastName) return 0; gg_pubdir50_t req = gg_pubdir50_new(GG_PUBDIR50_SEARCH); if (req == NULL) { #ifdef DEBUGMODE debugLogA("SearchByName(): ForkThread 12 GGPROTO::searchthread"); #endif ForkThread(&GGPROTO::searchthread, NULL); return (HANDLE)1; } // Add nick,firstName,lastName and search it CMStringA szQuery; if (nick) { T2Utf nick_utf8(nick); gg_pubdir50_add(req, GG_PUBDIR50_NICKNAME, nick_utf8); szQuery.Append(nick_utf8); } szQuery.AppendChar('.'); if (firstName) { T2Utf firstName_utf8(firstName); gg_pubdir50_add(req, GG_PUBDIR50_FIRSTNAME, firstName_utf8); szQuery.Append(firstName_utf8); } szQuery.AppendChar('.'); if (lastName) { T2Utf lastName_utf8(lastName); gg_pubdir50_add(req, GG_PUBDIR50_LASTNAME, lastName_utf8); szQuery.Append(lastName_utf8); } szQuery.AppendChar('.'); // Count crc & check if the data was equal if yes do same search with shift unsigned long crc = crc_get(szQuery.GetBuffer()); if (crc == last_crc && next_uin) gg_pubdir50_add(req, GG_PUBDIR50_START, ditoa(next_uin)); else last_crc = crc; gg_pubdir50_seq_set(req, GG_SEQ_SEARCH); gg_EnterCriticalSection(&sess_mutex, "SearchByName", 51, "sess_mutex", 1); if (!gg_pubdir50(sess, req)) { gg_LeaveCriticalSection(&sess_mutex, "SearchByName", 51, 1, "sess_mutex", 1); #ifdef DEBUGMODE debugLogA("SearchByName(): ForkThread 13 GGPROTO::searchthread"); #endif ForkThread(&GGPROTO::searchthread, NULL); return (HANDLE)1; } gg_LeaveCriticalSection(&sess_mutex, "SearchByName", 51, 2, "sess_mutex", 1); debugLogA("SearchByName(): Seq %d.", req->seq); gg_pubdir50_free(req); return (HANDLE)1; }