#include "skype.h" #include "base64/base64.h" extern "C" { #include "aes\aes.h" } // CSkype CSkype::CSkype(int num_threads) : Skype(num_threads) { this->proto = NULL; this->onMessagedCallback = NULL; } CAccount* CSkype::newAccount(int oid) { return new CAccount(oid, this); } CContactGroup* CSkype::newContactGroup(int oid) { return new CContactGroup(oid, this); } CContact* CSkype::newContact(int oid) { return new CContact(oid, this); } CConversation* CSkype::newConversation(int oid) { return new CConversation(oid, this); } CParticipant* CSkype::newParticipant(int oid) { return new CParticipant(oid, this); } CMessage* CSkype::newMessage(int oid) { return new CMessage(oid, this); } CTransfer* CSkype::newTransfer(int oid) { return new CTransfer(oid, this); } CContactSearch* CSkype::newContactSearch(int oid) { return new CContactSearch(oid, this); } void CSkype::OnMessage ( const MessageRef & message, const bool & changesInboxTimestamp, const MessageRef & supersedesHistoryMessage, const ConversationRef & conversation) { /*uint now; skype->GetUnixTimestamp(now); conversation->SetConsumedHorizon(now);*/ if (this->proto) (proto->*onMessagedCallback)(conversation->ref(), message->ref()); } void CSkype::SetOnMessageCallback(OnMessaged callback, CSkypeProto* proto) { this->proto = proto; this->onMessagedCallback = callback; } BOOL CSkype::IsRunAsAdmin() { BOOL fIsRunAsAdmin = FALSE; DWORD dwError = ERROR_SUCCESS; PSID pAdministratorsGroup = NULL; // Allocate and initialize a SID of the administrators group. SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY; if ( !AllocateAndInitializeSid( &NtAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &pAdministratorsGroup)) { dwError = GetLastError(); goto Cleanup; } // Determine whether the SID of administrators group is enabled in // the primary access token of the process. if ( !CheckTokenMembership(NULL, pAdministratorsGroup, &fIsRunAsAdmin)) { dwError = GetLastError(); goto Cleanup; } Cleanup: // Centralized cleanup for all allocated resources. if (pAdministratorsGroup) { FreeSid(pAdministratorsGroup); pAdministratorsGroup = NULL; } // Throw the error if something failed in the function. if (ERROR_SUCCESS != dwError) { throw dwError; } return fIsRunAsAdmin; } char *CSkype::LoadKeyPair(HINSTANCE hInstance) { HRSRC hRes = FindResource(hInstance, MAKEINTRESOURCE(IDR_KEY), L"BIN"); if (hRes) { HGLOBAL hResource = LoadResource(hInstance, hRes); if (hResource) { aes_context ctx; unsigned char key[128]; int basedecoded = Base64::Decode(MY_KEY, (char *)key, MAX_PATH); ::aes_set_key(&ctx, key, 128); memset(key, 0, sizeof(key)); basedecoded = ::SizeofResource(hInstance, hRes); char *pData = (char *)hResource; if (!pData) return NULL; unsigned char *bufD = (unsigned char*)::malloc(basedecoded + 1); unsigned char *tmpD = (unsigned char*)::malloc(basedecoded + 1); basedecoded = Base64::Decode(pData, (char *)tmpD, basedecoded); for (int i = 0; i < basedecoded; i += 16) aes_decrypt(&ctx, tmpD+i, bufD+i); ::free(tmpD); bufD[basedecoded] = 0; //cert should be null terminated return (char *)bufD; } return NULL; } return NULL; } int CSkype::StartSkypeRuntime(HINSTANCE hInstance, const wchar_t *profileName, int &port, const wchar_t *dbPath) { STARTUPINFO cif; PROCESS_INFORMATION pi; wchar_t param[128]; ::ZeroMemory(&cif, sizeof(STARTUPINFO)); cif.cb = sizeof(STARTUPINFO); cif.dwFlags = STARTF_USESHOWWINDOW; cif.wShowWindow = SW_HIDE; //HRSRC hRes; //HGLOBAL hResource; wchar_t fileName[MAX_PATH]; HRSRC hRes = ::FindResource(hInstance, MAKEINTRESOURCE(/*IDR_RUNTIME*/102), L"BIN"); if (hRes) { HGLOBAL hResource = ::LoadResource(hInstance, hRes); if (hResource) { HANDLE hFile; char *pData = (char *)LockResource(hResource); DWORD dwSize = SizeofResource(hInstance, hRes), written = 0; ::GetModuleFileName(hInstance, fileName, MAX_PATH); wchar_t *skypeKitPath = ::wcsrchr(fileName, '\\'); if (skypeKitPath != NULL) *skypeKitPath = 0; ::swprintf(fileName, SIZEOF(fileName), L"%s\\%s", fileName, L"SkypeKit.exe"); if ( !::PathFileExists(fileName)) { if ((hFile = ::CreateFile( fileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0)) != INVALID_HANDLE_VALUE) { ::WriteFile(hFile, (void *)pData, dwSize, &written, NULL); ::CloseHandle(hFile); } else { // Check the current process's "run as administrator" status. // Elevate the process if it is not run as administrator. if (!CSkype::IsRunAsAdmin()) { wchar_t path[MAX_PATH], cmdLine[100]; ::GetModuleFileName(NULL, path, ARRAYSIZE(path)); ::swprintf( cmdLine, SIZEOF(cmdLine), L" /restart:%d /profile=%s", ::GetCurrentProcessId(), profileName); // Launch itself as administrator. SHELLEXECUTEINFO sei = { sizeof(sei) }; sei.lpVerb = L"runas"; sei.lpFile = path; sei.lpParameters = cmdLine; //sei.hwnd = hDlg; sei.nShow = SW_NORMAL; if ( !::ShellExecuteEx(&sei)) { DWORD dwError = ::GetLastError(); if (dwError == ERROR_CANCELLED) { // The user refused to allow privileges elevation. // Do nothing ... } } //else //{ // //DestroyWindow(hDlg); // Quit itself // ::CallService("CloseAction", 0, 0); //} } return 0; } } } } PROCESSENTRY32 entry; entry.dwSize = sizeof(PROCESSENTRY32); HANDLE snapshot = ::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL); if (::Process32First(snapshot, &entry) == TRUE) { while (::Process32Next(snapshot, &entry) == TRUE) { if (::wcsicmp(entry.szExeFile, L"SkypeKit.exe") == 0) { HANDLE hProcess = ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, entry.th32ProcessID); port += rand() % 8963 + 1000; ::CloseHandle(hProcess); break; } } } ::CloseHandle(snapshot); //::swprintf(param, SIZEOF(param), L"-p -P %d -f %s", port, dbPath); ::swprintf(param, SIZEOF(param), L"-p -P %d", port); int startingrt = ::CreateProcess( fileName, param, NULL, NULL, FALSE, CREATE_NEW_CONSOLE, NULL, NULL, &cif, &pi); DWORD rterr = GetLastError(); //if (startingrt && rterr == ERROR_SUCCESS) //return 1; //else //return 0; return startingrt; } CSkype *CSkype::GetInstance(HINSTANCE hInstance, const wchar_t *profileName, const wchar_t *dbPath) { int port = 8963; if (!CSkype::StartSkypeRuntime(hInstance, profileName, port, dbPath)) return NULL; char *keyPair = CSkype::LoadKeyPair(hInstance); if (!keyPair) return NULL; CSkype *skype = new CSkype(); TransportInterface::Status status = skype->init(keyPair, "127.0.0.1", port); if (status != TransportInterface::OK) return NULL; skype->start(); free(keyPair); //this->skype->SetOnMessageCallback((CSkype::OnMessaged)&CSkypeProto::OnMessage, this); return skype; } // CAccount CAccount::CAccount(unsigned int oid, SERootObject* root) : Account(oid, root) { this->proto = NULL; this->callback == NULL; } void CAccount::SetOnAccountChangedCallback(OnAccountChanged callback, CSkypeProto* proto) { this->skype = (CSkype *)root; this->proto = proto; this->callback = callback; } bool CAccount::SetAvatar(SEBinary avatar, Skype::VALIDATERESULT &result) { int fbl; if (!this->skype->ValidateAvatar(avatar, result, fbl) || result != Skype::VALIDATED_OK) return false; if (!this->SetBinProperty(Account::P_AVATAR_IMAGE, avatar)) return false; return true; } void CAccount::OnChange(int prop) { if (this->proto) (proto->*callback)(prop); } // CContactGroup CContactGroup::CContactGroup(unsigned int oid, SERootObject* root) : ContactGroup(oid, root) { this->proto = NULL; this->callback == NULL; } void CContactGroup::SetOnContactListChangedCallback(OnContactListChanged callback, CSkypeProto* proto) { this->proto = proto; this->callback = callback; } void CContactGroup::OnChange(const ContactRef& contact) { if (this->proto) (proto->*callback)(contact); } // CContactSearch CContactSearch::CContactSearch(unsigned int oid, SERootObject* root) : ContactSearch(oid, root) { this->proto = NULL; this->SearchCompletedCallback == NULL; this->ContactFindedCallback == NULL; } void CContactSearch::OnChange(int prop) { if (prop == P_CONTACT_SEARCH_STATUS) { CContactSearch::STATUS status; this->GetPropContactSearchStatus(status); if (status == FINISHED || status == FAILED) { this->isSeachFinished = true; if (this->proto) (proto->*SearchCompletedCallback)(this->hSearch); } } } void CContactSearch::OnNewResult(const ContactRef& contact, const uint& rankValue) { if (this->proto) (proto->*ContactFindedCallback)(this->hSearch, contact->ref()); } void CContactSearch::BlockWhileSearch() { this->isSeachFinished = false; this->isSeachFailed = false; while (!this->isSeachFinished && !this->isSeachFailed) Sleep(1); } void CContactSearch::SetProtoInfo(CSkypeProto* proto, HANDLE hSearch) { this->proto = proto; this->hSearch = hSearch; } void CContactSearch::SetOnSearchCompleatedCallback(OnSearchCompleted callback) { this->SearchCompletedCallback = callback; } void CContactSearch::SetOnContactFindedCallback(OnContactFinded callback) { this->ContactFindedCallback = callback; } // CParticipant CParticipant::CParticipant(unsigned int oid, SERootObject* root) : Participant(oid, root) { } SEString CParticipant::GetRankName(CParticipant::RANK rank) { char *result = NULL; switch (rank) { case CParticipant::CREATOR: result = "Creator"; break; case CParticipant::ADMIN: result = "Admin"; break; case CParticipant::SPEAKER: result = "Speaker"; break; case CParticipant::WRITER: result = "Writer"; break; case CParticipant::SPECTATOR: result = "Spectator"; break; case CParticipant::RETIRED: result = "Retried"; break; case CParticipant::OUTLAW: result = "Outlaw"; break; } return result; } // CContact CContact::CContact(unsigned int oid, SERootObject* root) : Contact(oid, root) { this->proto = NULL; this->callback == NULL; } SEString CContact::GetSid() { SEString result; CContact::AVAILABILITY availability; this->GetPropAvailability(availability); if (availability == CContact::SKYPEOUT) this->GetPropPstnnumber(result); else this->GetPropSkypename(result); return result; } SEString CContact::GetNick() { SEString result; CContact::AVAILABILITY availability; this->GetPropAvailability(availability); if (availability == CContact::SKYPEOUT) result = this->GetSid(); else this->GetPropDisplayname(result); return result; } bool CContact::GetFullname(SEString &firstName, SEString &lastName) { SEString fullname; this->GetPropFullname(fullname); int pos = fullname.find(" "); if (pos && pos < fullname.length()) { firstName = fullname.substr(0, pos); lastName = fullname.right(pos); } firstName = fullname; return true; } void CContact::SetOnContactChangedCallback(OnContactChanged callback, CSkypeProto* proto) { this->proto = proto; this->callback = callback; } //bool CContact::SentAuthRequest(SEString message) //{ // this->SetBuddyStatus(Contact::AUTHORIZED_BY_ME); // this->SendAuthRequest(message); //} void CContact::OnChange(int prop) { if (this->proto) (proto->*callback)(this->ref(), prop); } // Conversation CConversation::CConversation(unsigned int oid, SERootObject* root) : Conversation(oid, root) { this->proto = NULL; this->messageReceivedCallback = NULL; } void CConversation::OnMessage(const MessageRef & message) { if (this->proto) (proto->*messageReceivedCallback)(message->ref()); } void CConversation::OnChange(int prop) { if (prop == Conversation::P_LOCAL_LIVESTATUS) { Conversation::LOCAL_LIVESTATUS liveStatus; this->GetPropLocalLivestatus(liveStatus); if (liveStatus == Conversation::RINGING_FOR_ME) { } } } CConversation::Ref CConversation::FindBySid(CSkype *skype, const wchar_t *sid) { SEString identity = ::mir_u2a(sid); SEStringList participants; participants.append(identity); CConversation::Ref conversation; skype->GetConversationByParticipants(participants, conversation); return conversation; } void CConversation::SetOnMessageReceivedCallback(OnMessageReceived callback, CSkypeProto* proto) { this->proto = proto; this->messageReceivedCallback = callback; } // CMessage CMessage::CMessage(unsigned int oid, SERootObject* root) : Message(oid, root) { } // CTransfer CTransfer::CTransfer(unsigned int oid, SERootObject* root) : Transfer(oid, root) { this->proto = NULL; this->transferCallback = NULL; } void CTransfer::SetOnTransferCallback(OnTransfer callback, CSkypeProto* proto) { this->proto = proto; this->transferCallback = callback; } void CTransfer::OnChange(int prop) { if (this->proto) (proto->*transferCallback)(prop, this->ref()); }