void CAimProto::aim_connection_authorization(void) { if (m_iDesiredStatus != ID_STATUS_OFFLINE) { char *password = getStringA(AIM_KEY_PW); if (password != NULL) { mir_free(m_username); m_username = getStringA(AIM_KEY_SN); if (m_username != NULL) { HANDLE hServerPacketRecver = (HANDLE)CallService(MS_NETLIB_CREATEPACKETRECVER, (WPARAM)m_hServerConn, 2048 * 4); NETLIBPACKETRECVER packetRecv = { 0 }; packetRecv.cbSize = sizeof(packetRecv); packetRecv.dwTimeout = 5000; for (;;) { int recvResult = CallService(MS_NETLIB_GETMOREPACKETS, (WPARAM)hServerPacketRecver, (LPARAM)& packetRecv); if (recvResult == 0) { debugLogA("Connection Closed: No Error? during Connection Authorization"); break; } else if (recvResult < 0) { debugLogA("Connection Closed: Socket Error during Connection Authorization %d", WSAGetLastError()); break; } else { unsigned short flap_length = 0; for (; packetRecv.bytesUsed < packetRecv.bytesAvailable; packetRecv.bytesUsed = flap_length) { if (!packetRecv.buffer) break; FLAP flap((char*)&packetRecv.buffer[packetRecv.bytesUsed], (unsigned short)(packetRecv.bytesAvailable - packetRecv.bytesUsed)); if (!flap.len()) break; flap_length += FLAP_SIZE + flap.len(); if (flap.cmp(0x01)) { if (aim_send_connection_packet(m_hServerConn, m_seqno, flap.val()) == 0) // cookie challenge aim_authkey_request(m_hServerConn, m_seqno); // md5 authkey request } else if (flap.cmp(0x02)) { SNAC snac(flap.val(), flap.snaclen()); if (snac.cmp(0x0017)) { snac_md5_authkey(snac, m_hServerConn, m_seqno, m_username, password); int authres = snac_authorization_reply(snac); switch (authres) { case 1: mir_free(password); Netlib_CloseHandle(hServerPacketRecver); debugLogA("Connection Authorization Thread Ending: Negotiation Beginning"); return; case 2: ProtoBroadcastAck(NULL, ACKTYPE_LOGIN, ACKRESULT_FAILED, NULL, LOGINERR_WRONGPASSWORD); goto exit; case 3: ProtoBroadcastAck(NULL, ACKTYPE_LOGIN, ACKRESULT_FAILED, NULL, LOGINERR_NOSERVER); goto exit; } } } else if (flap.cmp(0x04)) { debugLogA("Connection Authorization Thread Ending: Flap 0x04"); goto exit; } } } } exit: if (hServerPacketRecver) Netlib_CloseHandle(hServerPacketRecver); } } mir_free(password); } if (m_iStatus != ID_STATUS_OFFLINE) broadcast_status(ID_STATUS_OFFLINE); Netlib_CloseHandle(m_hServerConn); m_hServerConn = NULL; debugLogA("Connection Authorization Thread Ending: End of Thread"); }
void CSkypeProto::OnEndpointCreated(const NETLIBHTTPREQUEST *response) { if (!IsStatusConnecting(m_iStatus)) return; m_iStatus++; if (response == NULL) { debugLogA(__FUNCTION__ ": failed to get create endpoint"); ProtoBroadcastAck(NULL, ACKTYPE_LOGIN, ACKRESULT_FAILED, NULL, LOGIN_ERROR_UNKNOWN); SetStatus(ID_STATUS_OFFLINE); return; } for (int i = 0; i < response->headersCount; i++) { if (!mir_strcmpi(response->headers[i].szName, "Set-RegistrationToken")) { CMStringA szValue = response->headers[i].szValue, szCookieName, szCookieVal; int iStart = 0; while (true) { CMStringA szToken = szValue.Tokenize(";", iStart).Trim(); if (iStart == -1) break; int iStart2 = 0; szCookieName = szToken.Tokenize("=", iStart2); szCookieVal = szToken.Mid(iStart2); setString(szCookieName, szCookieVal); } } else if (!mir_strcmpi(response->headers[i].szName, "Location")) { CMStringA szValue = response->headers[i].szValue; li.endpoint.szServer = GetServerFromUrl(szValue).Detach(); setString("Server", li.endpoint.szServer); } } if (m_iStatus++ > SKYPE_MAX_CONNECT_RETRIES) { debugLogA(__FUNCTION__ ": failed to create endpoint (too many connect retries)"); ProtoBroadcastAck(NULL, ACKTYPE_LOGIN, ACKRESULT_FAILED, NULL, LOGIN_ERROR_UNKNOWN); SetStatus(ID_STATUS_OFFLINE); return; } if (response->resultCode != 201) { if (response->resultCode == 401) { delSetting("TokenExpiresIn"); SendRequest(new LoginOAuthRequest(li.szSkypename, ptrA(getStringA(SKYPE_SETTINGS_PASSWORD))), &CSkypeProto::OnLoginOAuth); return; } else //it should be rewritten { SendRequest(new CreateEndpointRequest(li), &CSkypeProto::OnEndpointCreated); return; } } li.endpoint.szToken = getStringA("registrationToken"); li.endpoint.szId = getStringA("endpointId"); SendRequest(new CreateSubscriptionsRequest(li), &CSkypeProto::OnSubscriptionsCreated); }
void CSteamProto::OnGotRsaKey(const HttpResponse *response) { if (!CheckResponse(response)) return; // load rsa key parts JSONNode root = JSONNode::parse(response->pData); if (!root) return; if (!root["success"].as_bool()) return; std::string modulus = root["publickey_mod"].as_string(); // exponent "010001" is used as constant in CSteamProto::RsaEncrypt //std::string exponent = root["publickey_exp"].as_string(); std::string timestamp = root["timestamp"].as_string(); // encrcrypt password ptrA base64RsaEncryptedPassword; ptrA szPassword(getStringA("Password")); DWORD error = 0; DWORD encryptedSize = 0; if ((error = RsaEncrypt(modulus.c_str(), szPassword, NULL, encryptedSize)) != 0) { debugLogA("CSteamProto::OnGotRsaKey: encryption error (%lu)", error); return; } BYTE *encryptedPassword = (BYTE*)mir_calloc(encryptedSize); if ((error = RsaEncrypt(modulus.c_str(), szPassword, encryptedPassword, encryptedSize)) != 0) { debugLogA("CSteamProto::OnGotRsaKey: encryption error (%lu)", error); return; } base64RsaEncryptedPassword = mir_base64_encode(encryptedPassword, encryptedSize); mir_free(encryptedPassword); // run authorization request T2Utf username(getTStringA("Username")); ptrA twoFactorCode(getStringA("TwoFactorCode")); if (!twoFactorCode) twoFactorCode = mir_strdup(""); ptrA guardId(getStringA("GuardId")); if (!guardId) guardId = mir_strdup(""); ptrA guardCode(getStringA("GuardCode")); if (!guardCode) guardCode = mir_strdup(""); ptrA captchaId(getStringA("CaptchaId")); if (!captchaId) captchaId = mir_strdup("-1"); ptrA captchaText(getStringA("CaptchaText")); if (!captchaText) captchaText = mir_strdup(""); PushRequest( new AuthorizationRequest(username, base64RsaEncryptedPassword, timestamp.c_str(), twoFactorCode, guardCode, guardId, captchaId, captchaText), &CSteamProto::OnAuthorization); }
void CAimProto::aim_connection_clientlogin(void) { pass_ptrA password(getStringA(AIM_KEY_PW)); replaceStr(m_username, ptrA(getStringA(AIM_KEY_SN))); CMStringA buf; buf.Format("devId=%s&f=xml&pwd=%s&s=%s", AIM_DEFAULT_CLIENT_KEY, ptrA(mir_urlEncode(password)), ptrA(mir_urlEncode(m_username))); NETLIBHTTPHEADER headers[] = { { "Content-Type", "application/x-www-form-urlencoded; charset=UTF-8" } }; NETLIBHTTPREQUEST req = { 0 }; req.cbSize = sizeof(req); req.flags = NLHRF_SSL; req.requestType = REQUEST_POST; req.szUrl = AIM_LOGIN_URL; req.headers = headers; req.headersCount = _countof(headers); req.pData = buf.GetBuffer(); req.dataLength = buf.GetLength(); NLHR_PTR resp(CallService(MS_NETLIB_HTTPTRANSACTION, (WPARAM)m_hNetlibUser, (LPARAM)&req)); if (!resp || !resp->dataLength) { broadcast_status(ID_STATUS_OFFLINE); return; } time_t hosttime; CMStringA token, secret; if (!parse_clientlogin_response(resp, headers, token, secret, hosttime)) { //TODO: handle error broadcast_status(ID_STATUS_OFFLINE); mir_free(headers[0].szValue); return; } bool encryption = !getByte(AIM_KEY_DSSL, 0); CMStringA url; fill_session_url(url, token, secret, hosttime, password, encryption); // reuse NETLIBHTTPREQUEST req.requestType = REQUEST_GET; req.pData = NULL; req.flags |= NLHRF_MANUALHOST; req.dataLength = 0; req.headersCount = 1; req.szUrl = url.GetBuffer(); { NETLIBHTTPHEADER headers2[] = { { "Host", "api.oscar.aol.com" }, }; req.headers = headers2; resp = CallService(MS_NETLIB_HTTPTRANSACTION, (WPARAM)m_hNetlibUser, (LPARAM)&req); } if (!resp || !resp->dataLength) { // TODO: handle error broadcast_status(ID_STATUS_OFFLINE); return; } CMStringA bos_host, cookie, tls_cert_name; //TODO: find efficient buf size unsigned short bos_port = 0; if (!parse_start_socar_session_response(resp->pData, bos_host, bos_port, cookie, tls_cert_name, encryption)) { // TODO: handle error broadcast_status(ID_STATUS_OFFLINE); return; } m_hServerConn = aim_connect(bos_host, bos_port, (tls_cert_name[0] && encryption) ? true : false, bos_host); if (!m_hServerConn) { // TODO: handle error broadcast_status(ID_STATUS_OFFLINE); return; } replaceStr(COOKIE, cookie); COOKIE_LENGTH = (int)mir_strlen(cookie); ForkThread(&CAimProto::aim_protocol_negotiation, 0); }
std::string FacebookProto::ThreadIDToContactID(const std::string &thread_id) { if (thread_id.empty()) { debugLogA("!!! Calling ThreadIDToContactID() with empty thread_id"); return ""; } // First check cache std::map<std::string, std::string>::iterator it = facy.thread_id_to_user_id.find(thread_id); if (it != facy.thread_id_to_user_id.end()) { return it->second; } // Go through all local contacts for (MCONTACT hContact = db_find_first(m_szModuleName); hContact; hContact = db_find_next(hContact, m_szModuleName)) { if (!IsMyContact(hContact)) continue; ptrA tid(getStringA(hContact, FACEBOOK_KEY_TID)); if (tid && !mir_strcmp(tid, thread_id.c_str())) { ptrA id(getStringA(hContact, FACEBOOK_KEY_ID)); std::string user_id = (id ? id : ""); if (!user_id.empty()) { facy.thread_id_to_user_id.insert(std::make_pair(thread_id, user_id)); return user_id; } break; // this shouldn't happen unless user manually deletes ID from FB contact in DB } } // We don't have any contact with this thread_id cached, we must ask server if (isOffline()) return ""; std::string data = "client=mercury"; data += "&__user="******"&__dyn=" + facy.__dyn(); data += "&__req=" + facy.__req(); data += "&fb_dtsg=" + facy.dtsg_; data += "&ttstamp=" + facy.ttstamp_; data += "&__rev=" + facy.__rev(); data += "&threads[thread_ids][0]=" + utils::url::encode(thread_id); std::string user_id; http::response resp = facy.flap(REQUEST_THREAD_INFO, &data); // NOTE: Request revised 1.9.2015 if (resp.code == HTTP_CODE_OK) { CODE_BLOCK_TRY facebook_json_parser* p = new facebook_json_parser(this); p->parse_thread_info(&resp.data, &user_id); delete p; if (!user_id.empty()) facy.thread_id_to_user_id.insert(std::make_pair(thread_id, user_id)); debugLogA("*** Thread info processed"); CODE_BLOCK_CATCH debugLogA("*** Error processing thread info: %s", e.what()); CODE_BLOCK_END }
void CSteamProto::OnAuthorizationError(const JSONNode &node) { std::string message = node["message"].as_string(); ptrT messageT(mir_utf8decodeT(message.c_str())); debugLogA("CSteamProto::OnAuthorizationError: %s", message.c_str()); if (!mir_tstrcmpi(messageT, _T("Incorrect login."))) { // We can't continue with incorrect login/password DeleteAuthSettings(); SetStatus(ID_STATUS_OFFLINE); return; } T2Utf username(getTStringA("Username")); if (node["requires_twofactor"].as_bool()) { debugLogA("CSteamProto::OnAuthorizationError: requires twofactor"); CSteamTwoFactorDialog twoFactorDialog(this); if (twoFactorDialog.DoModal() != DIALOG_RESULT_OK) { DeleteAuthSettings(); SetStatus(ID_STATUS_OFFLINE); return; } setString("TwoFactorCode", twoFactorDialog.GetTwoFactorCode()); PushRequest( new GetRsaKeyRequest(username), &CSteamProto::OnGotRsaKey); return; } if (node["clear_password_field"].as_bool()) { debugLogA("CSteamProto::OnAuthorizationError: clear password field"); return; } if (node["emailauth_needed"].as_bool()) { debugLogA("CSteamProto::OnAuthorizationError: emailauth needed"); std::string guardId = node["emailsteamid"].as_string(); ptrA oldGuardId(getStringA("GuardId")); if (mir_strcmp(guardId.c_str(), oldGuardId) == 0) { delSetting("GuardId"); delSetting("GuardCode"); PushRequest( new GetRsaKeyRequest(username), &CSteamProto::OnGotRsaKey); return; } std::string domain = node["emaildomain"].as_string(); // Make absolute link if (domain.find("://") == std::string::npos) domain = "http://" + domain; CSteamGuardDialog guardDialog(this, domain.c_str()); if (guardDialog.DoModal() != DIALOG_RESULT_OK) { DeleteAuthSettings(); SetStatus(ID_STATUS_OFFLINE); return; } setString("GuardId", guardId.c_str()); setString("GuardCode", guardDialog.GetGuardCode()); PushRequest( new GetRsaKeyRequest(username), &CSteamProto::OnGotRsaKey); return; } if (node["captcha_needed"].as_bool()) { debugLogA("CSteamProto::OnAuthorizationError: captcha needed"); std::string captchaId = node["captcha_gid"].as_string(); GetCaptchaRequest *request = new GetCaptchaRequest(captchaId.c_str()); HttpResponse *response = request->Send(m_hNetlibUser); delete request; CSteamCaptchaDialog captchaDialog(this, (BYTE*)response->pData, response->dataLength); delete response; if (captchaDialog.DoModal() != DIALOG_RESULT_OK) { DeleteAuthSettings(); SetStatus(ID_STATUS_OFFLINE); return; } setString("CaptchaId", captchaId.c_str()); setString("CaptchaText", captchaDialog.GetCaptchaText()); PushRequest( new GetRsaKeyRequest(username), &CSteamProto::OnGotRsaKey); return; } DeleteAuthSettings(); SetStatus(ID_STATUS_OFFLINE); }
HANDLE WhatsAppProto::SendFile(MCONTACT hContact, const TCHAR* desc, TCHAR **ppszFiles) { if (!isOnline()) return 0; ptrA jid(getStringA(hContact, "ID")); if (jid == NULL) return 0; // input validation char *name = mir_utf8encodeW(ppszFiles[0]); string mime = MediaUploader::getMimeFromExtension(split(name, '.')[1]); if (mime.empty()) return 0; // get file size FILE *hFile = _tfopen(ppszFiles[0], _T("rb")); if (hFile == NULL) { debugLogA(__FUNCTION__": cannot open file %s", ppszFiles[0]); return 0; } _fseeki64(hFile, 0, SEEK_END); uint64_t fileSize = _ftelli64(hFile); fclose(hFile); // get filetype from mimeType int fileType = FMessage::getMessage_WA_Type(split(mime, '/')[0]); // check max file sizes switch (fileType) { case FMessage::WA_TYPE_IMAGE: if (fileSize >= 5 * 1024 * 1024) return 0; break; case FMessage::WA_TYPE_AUDIO: if (fileSize >= 10 * 1024 * 1024) return 0; break; case FMessage::WA_TYPE_VIDEO: if (fileSize >= 20 * 1024 * 1024) return 0; break; default: return 0; } int msgId = GetSerial(); time_t now = time(NULL); std::string msgid = Utilities::intToStr(now) + "-" + Utilities::intToStr(msgId); FMessage * fmsg = new FMessage(std::string(jid), true, msgid); fmsg->media_url = name; fmsg->media_size = fileSize; fmsg->media_wa_type = fileType; fmsg->data = mir_utf8encodeW(desc); // calculate file hash unsigned char hash[MIR_SHA256_HASH_SIZE]; SHA256_CONTEXT sha256; mir_sha256_init(&sha256); FILE *fd = _tfopen(ppszFiles[0], _T("rb")); int read = 0; do { char buf[1024]; read = (int)fread(buf, 1, 1024, fd); mir_sha256_write(&sha256, buf, read); } while (read > 0); fclose(fd); mir_sha256_final(&sha256, hash); fmsg->media_name = mir_base64_encode((BYTE*)hash,sizeof(hash)); // request media upload url m_pConnection->sendMessage(fmsg); return (HANDLE)fmsg; // TODO what to return here to make the upload shown complete when done and how to handle errors? }
int CSteamProto::SetStatus(int new_status) { mir_cslock lock(set_status_lock); // Routing statuses not supported by Steam switch (new_status) { case ID_STATUS_OFFLINE: case ID_STATUS_AWAY: case ID_STATUS_NA: break; case ID_STATUS_DND: case ID_STATUS_OCCUPIED: case ID_STATUS_ONTHEPHONE: case ID_STATUS_OUTTOLUNCH: new_status = ID_STATUS_NA; break; default: new_status = ID_STATUS_ONLINE; break; } if (new_status == m_iDesiredStatus) return 0; debugLog(_T("CSteamProto::SetStatus: changing status from %i to %i"), m_iStatus, new_status); int old_status = m_iStatus; m_iDesiredStatus = new_status; if (new_status == ID_STATUS_OFFLINE) { m_iStatus = m_iDesiredStatus = ID_STATUS_OFFLINE; ProtoBroadcastAck(NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)old_status, m_iStatus); ptrA token(getStringA("TokenSecret")); ptrA umqid(getStringA("UMQID")); SendRequest(new LogoffRequest(token, umqid)); requestQueue->Stop(); if (!Miranda_Terminated()) SetAllContactsStatus(ID_STATUS_OFFLINE); } else if (old_status == ID_STATUS_OFFLINE) { m_iStatus = ID_STATUS_CONNECTING; ProtoBroadcastAck(NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)old_status, m_iStatus); requestQueue->Start(); ptrA token(getStringA("TokenSecret")); if (mir_strlen(token) > 0) { PushRequest( new LogonRequest(token), &CSteamProto::OnLoggedOn); } else { ptrA username(mir_urlEncode(ptrA(mir_utf8encodeT(getTStringA("Username"))))); if (username == NULL || username[0] == '\0') { m_iStatus = m_iDesiredStatus = ID_STATUS_OFFLINE; ProtoBroadcastAck(NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)ID_STATUS_CONNECTING, m_iStatus); return 0; } PushRequest( new GetRsaKeyRequest(username), &CSteamProto::OnGotRsaKey); } } else { m_iStatus = new_status; ProtoBroadcastAck(NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)old_status, m_iStatus); } return 0; }
FacebookProto::FacebookProto(const char* proto_name, const TCHAR* username) : PROTO<FacebookProto>(proto_name, username), m_tszDefaultGroup(getTStringA(FACEBOOK_KEY_DEF_GROUP)) { facy.parent = this; signon_lock_ = CreateMutex(NULL, FALSE, NULL); avatar_lock_ = CreateMutex(NULL, FALSE, NULL); log_lock_ = CreateMutex(NULL, FALSE, NULL); update_loop_lock_ = CreateEvent(NULL, FALSE, FALSE, NULL); facy.buddies_lock_ = CreateMutex(NULL, FALSE, NULL); facy.send_message_lock_ = CreateMutex(NULL, FALSE, NULL); facy.fcb_conn_lock_ = CreateMutex(NULL, FALSE, NULL); facy.notifications_lock_ = CreateMutex(NULL, FALSE, NULL); facy.cookies_lock_ = CreateMutex(NULL, FALSE, NULL); // Initialize random seed for this client facy.random_ = ::time(NULL) + PtrToUint(&facy); m_enableChat = DEFAULT_ENABLE_CHATS; // Load custom locale, if set ptrA locale(getStringA(FACEBOOK_KEY_LOCALE)); if (locale != NULL) m_locale = locale; if (m_tszDefaultGroup == NULL) m_tszDefaultGroup = mir_tstrdup(_T("Facebook")); CreateProtoService(PS_CREATEACCMGRUI, &FacebookProto::SvcCreateAccMgrUI); CreateProtoService(PS_GETMYAWAYMSG, &FacebookProto::GetMyAwayMsg); CreateProtoService(PS_GETMYAVATAR, &FacebookProto::GetMyAvatar); CreateProtoService(PS_GETAVATARINFO, &FacebookProto::GetAvatarInfo); CreateProtoService(PS_GETAVATARCAPS, &FacebookProto::GetAvatarCaps); CreateProtoService(PS_GETUNREADEMAILCOUNT, &FacebookProto::GetNotificationsCount); CreateProtoService(PS_JOINCHAT, &FacebookProto::OnJoinChat); CreateProtoService(PS_LEAVECHAT, &FacebookProto::OnLeaveChat); HookProtoEvent(ME_CLIST_PREBUILDSTATUSMENU, &FacebookProto::OnBuildStatusMenu); HookProtoEvent(ME_OPT_INITIALISE, &FacebookProto::OnOptionsInit); HookProtoEvent(ME_IDLE_CHANGED, &FacebookProto::OnIdleChanged); HookProtoEvent(ME_TTB_MODULELOADED, &FacebookProto::OnToolbarInit); HookProtoEvent(ME_GC_EVENT, &FacebookProto::OnGCEvent); HookProtoEvent(ME_GC_BUILDMENU, &FacebookProto::OnGCMenuHook); HookProtoEvent(ME_DB_EVENT_MARKED_READ, &FacebookProto::OnDbEventRead); db_set_resident(m_szModuleName, "IdleTS"); db_set_resident(m_szModuleName, FACEBOOK_KEY_MESSAGE_READ); db_set_resident(m_szModuleName, FACEBOOK_KEY_MESSAGE_READERS); InitHotkeys(); InitPopups(); InitSounds(); // Create standard network connection TCHAR descr[512]; NETLIBUSER nlu = { sizeof(nlu) }; nlu.flags = NUF_INCOMING | NUF_OUTGOING | NUF_HTTPCONNS | NUF_TCHAR; nlu.szSettingsModule = m_szModuleName; mir_sntprintf(descr, TranslateT("%s server connection"), m_tszUserName); nlu.ptszDescriptiveName = descr; m_hNetlibUser = (HANDLE)CallService(MS_NETLIB_REGISTERUSER, 0, (LPARAM)&nlu); if (m_hNetlibUser == NULL) { TCHAR error[200]; mir_sntprintf(error, TranslateT("Unable to initialize Netlib for %s."), m_tszUserName); MessageBox(NULL, error, _T("Miranda NG"), MB_OK | MB_ICONERROR); } facy.set_handle(m_hNetlibUser); // Set all contacts offline -- in case we crashed SetAllContactStatuses(ID_STATUS_OFFLINE); // register special type of event // there's no need to declare the special service for getting text // because a blob contains only text DBEVENTTYPEDESCR evtype = { sizeof(evtype) }; evtype.module = m_szModuleName; evtype.eventType = FACEBOOK_EVENTTYPE_CALL; evtype.descr = LPGEN("Video call"); evtype.eventIcon = GetIconHandle("facebook"); evtype.flags = DETF_HISTORY | DETF_MSGWINDOW; CallService(MS_DB_EVENT_REGISTERTYPE, 0, (LPARAM)&evtype); }
int __cdecl CAimProto::SendMsg(MCONTACT hContact, int flags, const char* pszSrc) { if (pszSrc == NULL) return 0; if (state != 1) { msg_ack_param *msg_ack = (msg_ack_param*)mir_calloc(sizeof(msg_ack_param)); msg_ack->hContact = hContact; msg_ack->msg = "Message cannot be sent, when protocol offline"; ForkThread(&CAimProto::msg_ack_success, msg_ack); } char *sn = getStringA(hContact, AIM_KEY_SN); if (sn == NULL) { msg_ack_param *msg_ack = (msg_ack_param*)mir_calloc(sizeof(msg_ack_param)); msg_ack->hContact = hContact; msg_ack->msg = "Screen Name for the contact not available"; ForkThread(&CAimProto::msg_ack_success, msg_ack); } char* msg; if (flags & PREF_UNICODE) { const char* p = strchr(pszSrc, '\0'); if (p != pszSrc) { while (*(++p) == '\0'); } msg = mir_utf8encodeW((wchar_t*)p); } else if (flags & PREF_UTF) msg = mir_strdup(pszSrc); else msg = mir_utf8encode(pszSrc); char* smsg = html_encode(msg); mir_free(msg); if (getByte(AIM_KEY_FO, 1)) { msg = bbcodes_to_html(smsg); mir_free(smsg); } else msg = smsg; bool blast = getBool(hContact, AIM_KEY_BLS, false); int res = aim_send_message(hServerConn, seqno, sn, msg, false, blast); mir_free(msg); mir_free(sn); if (!res || blast || 0 == getByte(AIM_KEY_DC, 1)) { msg_ack_param *msg_ack = (msg_ack_param*)mir_alloc(sizeof(msg_ack_param)); msg_ack->hContact = hContact; msg_ack->msg = NULL; msg_ack->id = res; msg_ack->success = res != 0; ForkThread(&CAimProto::msg_ack_success, msg_ack); } return res; }
void __cdecl CJabberProto::FileServerThread(filetransfer *ft) { debugLogA("Thread started: type=file_send"); ThreadData info(this, NULL); ft->type = FT_OOB; NETLIBBIND nlb = { 0 }; nlb.cbSize = sizeof(NETLIBBIND); nlb.pfnNewConnectionV2 = JabberFileServerConnection; nlb.pExtra = this; nlb.wPort = 0; // Use user-specified incoming port ranges, if available info.s = (HANDLE)CallService(MS_NETLIB_BINDPORT, (WPARAM)m_hNetlibUser, (LPARAM)&nlb); if (info.s == NULL) { debugLogA("Cannot allocate port to bind for file server thread, thread ended."); ProtoBroadcastAck(ft->std.hContact, ACKTYPE_FILE, ACKRESULT_FAILED, ft, 0); delete ft; return; } ft->s = info.s; debugLogA("ft->s = %d", info.s); HANDLE hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); ft->hFileEvent = hEvent; TCHAR szPort[20]; mir_sntprintf(szPort, _T("%d"), nlb.wPort); JABBER_LIST_ITEM *item = ListAdd(LIST_FILE, szPort); item->ft = ft; TCHAR *ptszResource = ListGetBestClientResourceNamePtr(ft->jid); if (ptszResource != NULL) { ft->state = FT_CONNECTING; for (int i = 0; i < ft->std.totalFiles && ft->state != FT_ERROR && ft->state != FT_DENIED; i++) { ft->std.currentFileNumber = i; ft->state = FT_CONNECTING; if (ft->httpPath) mir_free(ft->httpPath); ft->httpPath = NULL; TCHAR *p; if ((p = _tcschr(ft->std.ptszFiles[i], '\\')) != NULL) p++; else p = ft->std.ptszFiles[i]; ptrA pFileName(mir_urlEncode(T2Utf(p))); if (pFileName != NULL) { ft->szId = JabberId2string(SerialNext()); ptrA myAddr; if (m_options.BsDirect && m_options.BsDirectManual) myAddr = getStringA("BsDirectAddr"); if (myAddr == NULL) myAddr = (char*)CallService(MS_NETLIB_ADDRESSTOSTRING, 1, nlb.dwExternalIP); char szAddr[256]; mir_snprintf(szAddr, "http://%s:%d/%s", myAddr, nlb.wPort, pFileName); size_t len = mir_tstrlen(ptszResource) + mir_tstrlen(ft->jid) + 2; TCHAR *fulljid = (TCHAR *)alloca(sizeof(TCHAR) * len); mir_sntprintf(fulljid, len, _T("%s/%s"), ft->jid, ptszResource); XmlNodeIq iq(_T("set"), ft->szId, fulljid); HXML query = iq << XQUERY(JABBER_FEAT_OOB); query << XCHILD(_T("url"), _A2T(szAddr)); query << XCHILD(_T("desc"), ft->szDescription); m_ThreadInfo->send(iq); debugLogA("Waiting for the file to be sent..."); WaitForSingleObject(hEvent, INFINITE); } debugLogA("File sent, advancing to the next file..."); ProtoBroadcastAck(ft->std.hContact, ACKTYPE_FILE, ACKRESULT_NEXTFILE, ft, 0); } CloseHandle(hEvent); ft->hFileEvent = NULL; debugLogA("Finish all files"); } ft->s = NULL; debugLogA("ft->s is NULL"); ListRemove(LIST_FILE, szPort); switch (ft->state) { case FT_DONE: debugLogA("Finish successfully"); ProtoBroadcastAck(ft->std.hContact, ACKTYPE_FILE, ACKRESULT_SUCCESS, ft, 0); break; case FT_DENIED: ProtoBroadcastAck(ft->std.hContact, ACKTYPE_FILE, ACKRESULT_DENIED, ft, 0); break; default: // FT_ERROR: debugLogA("Finish with errors"); ProtoBroadcastAck(ft->std.hContact, ACKTYPE_FILE, ACKRESULT_FAILED, ft, 0); break; } debugLogA("Thread ended: type=file_send"); delete ft; }