From f1000598cfdd80dc4dc0eb9bb1a0e3e142137856 Mon Sep 17 00:00:00 2001 From: Alexander Lantsev Date: Fri, 28 Dec 2012 14:27:17 +0000 Subject: - code refactoring - added account registration - temporary disabled chatrooms git-svn-id: http://svn.miranda-ng.org/main/trunk@2869 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- protocols/Skype/Skype_10.vcxproj | 3 + protocols/Skype/Skype_10.vcxproj.filters | 15 +- protocols/Skype/res/Resource.rc | 34 +- protocols/Skype/src/base64/base64.cpp | 101 ++++++ protocols/Skype/src/base64/base64.h | 12 + protocols/Skype/src/resource.h | 8 +- protocols/Skype/src/skype.cpp | 329 +------------------ protocols/Skype/src/skype.h | 6 +- protocols/Skype/src/skype_account.cpp | 23 +- protocols/Skype/src/skype_chat.cpp | 88 ++++-- protocols/Skype/src/skype_contacts.cpp | 510 ++++-------------------------- protocols/Skype/src/skype_dialogs.cpp | 225 ++++++------- protocols/Skype/src/skype_events.cpp | 66 +++- protocols/Skype/src/skype_instances.cpp | 9 +- protocols/Skype/src/skype_menus.cpp | 6 +- protocols/Skype/src/skype_netlib.cpp | 78 ++++- protocols/Skype/src/skype_profile.cpp | 381 +++++++++------------- protocols/Skype/src/skype_proto.cpp | 119 ++----- protocols/Skype/src/skype_proto.h | 94 +++--- protocols/Skype/src/skype_runtime.cpp | 18 ++ protocols/Skype/src/skype_services.cpp | 2 +- protocols/Skype/src/skype_subclassing.cpp | 258 +++++++++++++++ protocols/Skype/src/skype_subclassing.h | 12 +- protocols/Skype/src/skype_utils.cpp | 143 +++++---- 24 files changed, 1137 insertions(+), 1403 deletions(-) create mode 100644 protocols/Skype/src/base64/base64.cpp create mode 100644 protocols/Skype/src/base64/base64.h create mode 100644 protocols/Skype/src/skype_runtime.cpp diff --git a/protocols/Skype/Skype_10.vcxproj b/protocols/Skype/Skype_10.vcxproj index aedc6bde93..02e29c13c8 100644 --- a/protocols/Skype/Skype_10.vcxproj +++ b/protocols/Skype/Skype_10.vcxproj @@ -180,6 +180,7 @@ + @@ -188,6 +189,7 @@ + @@ -201,6 +203,7 @@ + diff --git a/protocols/Skype/Skype_10.vcxproj.filters b/protocols/Skype/Skype_10.vcxproj.filters index 4d031f4ed2..72884a0675 100644 --- a/protocols/Skype/Skype_10.vcxproj.filters +++ b/protocols/Skype/Skype_10.vcxproj.filters @@ -57,15 +57,21 @@ Source Files - - Source Files - Source Files Source Files + + Source Files + + + Source Files + + + Source Files + @@ -83,6 +89,9 @@ Header Files + + Header Files + diff --git a/protocols/Skype/res/Resource.rc b/protocols/Skype/res/Resource.rc index 485f51fe0f..1021f7335a 100644 --- a/protocols/Skype/res/Resource.rc +++ b/protocols/Skype/res/Resource.rc @@ -168,31 +168,32 @@ LANGUAGE LANG_RUSSIAN, SUBLANG_DEFAULT // Dialog // -IDD_SKYPEACCOUNT DIALOGEX 0, 0, 199, 92 +IDD_ACCMGR DIALOGEX 0, 0, 199, 92 STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_SYSMENU EXSTYLE WS_EX_CONTROLPARENT FONT 8, "MS Shell Dlg", 400, 0, 0x1 BEGIN - LTEXT "Skype login:",IDC_STATIC,7,7,53,12 - EDITTEXT IDC_SL,61,7,124,12,ES_AUTOHSCROLL - LTEXT "Password:",IDC_STATIC,7,23,53,12 - EDITTEXT IDC_PW,61,23,124,12,ES_PASSWORD | ES_AUTOHSCROLL + LTEXT "Skype name:",IDC_STATIC,14,8,46,12 + EDITTEXT IDC_SL,66,7,119,12,ES_AUTOHSCROLL + LTEXT "Password:",IDC_STATIC,14,24,46,12 + EDITTEXT IDC_PW,66,23,119,12,ES_PASSWORD | ES_AUTOHSCROLL + PUSHBUTTON "Register new account",IDC_REGISTER,66,39,119,14,WS_DISABLED END -IDD_OPTIONS DIALOGEX 0, 0, 305, 238 +IDD_OPT_MAIN DIALOGEX 0, 0, 305, 238 STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD EXSTYLE WS_EX_CONTROLPARENT FONT 8, "MS Shell Dlg", 400, 0, 0x1 BEGIN GROUPBOX "User Details",IDC_STATIC,7,7,291,60 LTEXT "Skype login:",IDC_STATIC,17,19,61,8 - EDITTEXT IDC_SL,84,17,123,13,ES_AUTOHSCROLL + EDITTEXT IDC_SL,78,17,121,13,ES_AUTOHSCROLL LTEXT "Password:",IDC_STATIC,17,35,61,8 - EDITTEXT IDC_PW,84,33,123,13,ES_PASSWORD | ES_AUTOHSCROLL + EDITTEXT IDC_PW,78,33,121,13,ES_PASSWORD | ES_AUTOHSCROLL GROUPBOX "Connection",IDC_STATIC,7,69,291,47 LTEXT "Use port",IDC_STATIC,17,81,44,8 - EDITTEXT IDC_PORT,84,79,40,14,ES_AUTOHSCROLL - LTEXT "for incoming connections",IDC_STATIC,130,81,158,8 + EDITTEXT IDC_PORT,78,79,30,14,ES_AUTOHSCROLL | ES_NUMBER + LTEXT "for incoming connections",IDC_STATIC,115,81,173,8 CONTROL "Use ports 80 and 443 as alternative incoming",IDC_USE_ALT_PORTS, "Button",BS_AUTOCHECKBOX | WS_TABSTOP,17,97,271,10 END @@ -206,21 +207,26 @@ END #ifdef APSTUDIO_INVOKED GUIDELINES DESIGNINFO BEGIN - IDD_SKYPEACCOUNT, DIALOG + IDD_ACCMGR, DIALOG BEGIN LEFTMARGIN, 7 RIGHTMARGIN, 192 + VERTGUIDE, 14 + VERTGUIDE, 60 + VERTGUIDE, 66 + VERTGUIDE, 185 TOPMARGIN, 7 BOTTOMMARGIN, 85 END - IDD_OPTIONS, DIALOG + IDD_OPT_MAIN, DIALOG BEGIN LEFTMARGIN, 7 VERTGUIDE, 17 VERTGUIDE, 78 - VERTGUIDE, 84 - VERTGUIDE, 207 + VERTGUIDE, 108 + VERTGUIDE, 115 + VERTGUIDE, 199 VERTGUIDE, 288 VERTGUIDE, 298 TOPMARGIN, 7 diff --git a/protocols/Skype/src/base64/base64.cpp b/protocols/Skype/src/base64/base64.cpp new file mode 100644 index 0000000000..d5d1558e50 --- /dev/null +++ b/protocols/Skype/src/base64/base64.cpp @@ -0,0 +1,101 @@ +#include "base64.h" + +char Base64::CharBase64[] = +{ + 'A','B','C','D','E','F','G','H','I','J','K','L','M ','N','O','P', + 'Q','R','S','T','U','V','W','X','Y','Z','a','b','c ','d','e','f', + 'g','h','i','j','k','l','m','n','o','p','q','r','s ','t','u','v', + 'w','x','y','z','0','1','2','3','4','5','6','7','8 ','9','+','/' +}; + +ULONG Base64::Encode(const char *inputString, char *outputBuffer, SIZE_T nMaxLength) +{ + int outpos = 0; + char chr[3], enc[4]; + + for (unsigned int i = 0; i < ::strlen(inputString); i += 3) + { + if (outpos + 4 >= nMaxLength)break; + + chr[0] = inputString[i]; + chr[1] = inputString[i+1]; + chr[2] = inputString[i+2]; + + enc[0] = chr[0] >> 2; + enc[1] = ((chr[0] & 0x03) << 4) | (chr[1] >> 4); + enc[2] = ((chr[1] & 0x0F) << 2) | (chr[2] >> 6); + enc[3] = chr[2] & 0x3F; + + outputBuffer[outpos++] = Base64::CharBase64[enc[0]]; + outputBuffer[outpos++] = Base64::CharBase64[enc[1]]; + + if (i + 1 >= ::strlen(inputString)) + { + outputBuffer[outpos++] = '='; + outputBuffer[outpos++] = '='; + } + else if (i + 2 >= ::strlen(inputString)) + { + outputBuffer[outpos++] = Base64::CharBase64[enc[2]]; + outputBuffer[outpos++] = '='; + } + else + { + outputBuffer[outpos++] = Base64::CharBase64[enc[2]]; + outputBuffer[outpos++] = Base64::CharBase64[enc[3]]; + } + } + + outputBuffer[outpos] = 0; + return outpos; +} + +int Base64::IndexBase64[] = +{ + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,62, -1,-1,-1,63, + 52,53,54,55, 56,57,58,59, 60,61,-1,-1, -1,-1,-1,-1, + -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10, 11,12,13,14, + 15,16,17,18, 19,20,21,22, 23,24,25,-1, -1,-1,-1,-1, + -1,26,27,28, 29,30,31,32, 33,34,35,36, 37,38,39,40, + 41,42,43,44, 45,46,47,48, 49,50,51,-1, -1,-1,-1,-1, + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1 +}; + +ULONG Base64::Decode(const char *inputString, char *outputBuffer, SIZE_T nMaxLength) +{ + int outpos = 0; + char chr[3], enc[4]; + + for (int i = 0; i < ::strlen(inputString); i += 4) + { + if (outpos+3 >= nMaxLength) break; + + enc[0] = Base64::IndexBase64[inputString[i]]; + enc[1] = Base64::IndexBase64[inputString[i+1]]; + enc[2] = Base64::IndexBase64[inputString[i+2]]; + enc[3] = Base64::IndexBase64[inputString[i+3]]; + + if (enc[0] == -1 || enc[1] == -1) break; + + chr[0] = (enc[0] << 2) | (enc[1] >> 4); + chr[1] = ((enc[1] & 15) << 4) | (enc[2] >> 2); + chr[2] = ((enc[2] & 3) << 6) | enc[3]; + + outputBuffer[outpos++] = chr[0]; + + if (enc[2] != -1) outputBuffer[outpos++] = chr[1]; + if (enc[3] != -1) outputBuffer[outpos++] = chr[2]; + } + + outputBuffer[outpos] = 0; + return outpos; +} \ No newline at end of file diff --git a/protocols/Skype/src/base64/base64.h b/protocols/Skype/src/base64/base64.h new file mode 100644 index 0000000000..9406df7a8f --- /dev/null +++ b/protocols/Skype/src/base64/base64.h @@ -0,0 +1,12 @@ +#include + +class Base64 +{ +private: + static char CharBase64[]; + static int IndexBase64[]; + +public: + static ULONG Encode(const char *inputString, char *outputBuffer, SIZE_T nMaxLength); + static ULONG Decode(const char *inputString, char *outputBuffer, SIZE_T nMaxLength); +}; \ No newline at end of file diff --git a/protocols/Skype/src/resource.h b/protocols/Skype/src/resource.h index 12cd98774d..85a839cbc9 100644 --- a/protocols/Skype/src/resource.h +++ b/protocols/Skype/src/resource.h @@ -1,9 +1,11 @@ //{{NO_DEPENDENCIES}} // Microsoft Visual C++ generated include file. -// Used by D:\Projects\CPlusPlus\MirandaNG\protocols\Skype\res\Resource.rc +// Used by e:\Projects\C++\MirandaNG\protocols\Skype\res\Resource.rc // #define IDD_SKYPEACCOUNT 9 +#define IDD_ACCMGR 9 #define IDD_OPTIONS 10 +#define IDD_OPT_MAIN 10 #define IDD_INFO_SKYPE 11 #define IDD_OWNINFO_SKYPE 12 #define IDD_CHATROOM_INVITE 40 @@ -35,6 +37,8 @@ #define IDC_PORT 1016 #define IDC_CHECK1 1017 #define IDC_USE_ALT_PORTS 1017 +#define IDC_BUTTON1 1018 +#define IDC_REGISTER 1018 // Next default values for new objects // @@ -42,7 +46,7 @@ #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NEXT_RESOURCE_VALUE 108 #define _APS_NEXT_COMMAND_VALUE 40001 -#define _APS_NEXT_CONTROL_VALUE 1018 +#define _APS_NEXT_CONTROL_VALUE 1019 #define _APS_NEXT_SYMED_VALUE 101 #endif #endif diff --git a/protocols/Skype/src/skype.cpp b/protocols/Skype/src/skype.cpp index 67354a37b3..06376b70c9 100644 --- a/protocols/Skype/src/skype.cpp +++ b/protocols/Skype/src/skype.cpp @@ -6,8 +6,6 @@ HINSTANCE g_hInstance; XML_API xi = {0}; TIME_API tmi = {0}; -CSkype* g_skype; - PLUGININFOEX pluginInfo = { sizeof(PLUGININFOEX), @@ -37,334 +35,18 @@ extern "C" __declspec(dllexport) PLUGININFOEX* MirandaPluginInfoEx(DWORD miranda extern "C" __declspec(dllexport) const MUUID MirandaInterfaces[] = {MIID_PROTOCOL, MIID_LAST}; -int port = 8963; - -void *buf; - -static const char base64Fillchar = '='; // used to mark partial words at the end - -const unsigned char base64DecodeTable[] = { - 99, 98, 98, 98, 98, 98, 98, 98, 98, 97, 97, 98, 98, 97, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, //00 -29 - 98, 98, 97, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 62, 98, 98, 98, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 98, 98, //30 -59 - 98, 96, 98, 98, 98, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, //60 -89 - 25, 98, 98, 98, 98, 98, 98, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, //90 -119 - 49, 50, 51, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, //120 -149 - 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, //150 -179 - 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, //180 -209 - 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, //210 -239 - 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98 //240 -255 -}; - -unsigned int decodeSize(char * data) -{ - if ( !data) return 0; - int size = 0; - unsigned char c; - //skip any extra characters (e.g. newlines or spaces) - while (*data) - { - if (*data>255) { return 0; } - c = base64DecodeTable[(unsigned char)(*data)]; - if (c<97) size++; - else if (c == 98) { return 0; } - data++; - } - if (size == 0) return 0; - do { data--; size--; } while (*data == base64Fillchar); size++; - return (unsigned int)((size*3)/4); -} - -unsigned char decode(char * data, unsigned char *buf, int len) -{ - if ( !data) return 0; - int i=0, p = 0; - unsigned char d, c; - for (;;) - { - - #define BASE64DECODE_READ_NEXT_CHAR(c) \ - do { \ - if (data[i]>255) { c = 98; break; } \ - c = base64DecodeTable[(unsigned char)data[i++]]; \ - }while (c == 97); \ - if(c == 98) { return 0; } - - BASE64DECODE_READ_NEXT_CHAR(c) - if (c == 99) { return 2; } - if (c == 96) - { - if (p == (int)len) return 2; - return 1; - } - - BASE64DECODE_READ_NEXT_CHAR(d) - if ((d == 99) || (d == 96)) { return 1; } - if (p == (int)len) { return 0; } - buf[p++] = (unsigned char)((c<<2)|((d>>4)&0x3)); - - BASE64DECODE_READ_NEXT_CHAR(c) - if (c == 99) { return 1; } - if (p == (int)len) - { - if (c == 96) return 2; - return 0; - } - if (c == 96) { return 1; } - buf[p++] = (unsigned char)(((d<<4)&0xf0)|((c>>2)&0xf)); - - BASE64DECODE_READ_NEXT_CHAR(d) - if (d == 99) { return 1; } - if (p == (int)len) - { - if (d == 96) return 2; - return 0; - } - if (d == 96) { return 1; } - buf[p++] = (unsigned char)(((c<<6)&0xc0)|d); - } -} -#undef BASE64DECODE_READ_NEXT_CHAR - -unsigned char *decode(char * data, int *outlen) -{ - if ( !data) { *outlen = 0; return (unsigned char*)""; } - unsigned int len = decodeSize(data); - if (outlen) *outlen = len; - if ( !len) return NULL; - malloc(len+1); - if( !decode(data, (unsigned char*)buf, len)) { return NULL; } - return (unsigned char*)buf; -} - -char* LoadKeyPair() -{ - HRSRC hRes = FindResource(g_hInstance, MAKEINTRESOURCE(IDR_KEY), _T("BIN")); - if (hRes) { - HGLOBAL hResource = LoadResource(g_hInstance, hRes); - if (hResource) { - aes_context ctx; - - int basedecodedkey = decodeSize((char*)MY_KEY); - unsigned char *tmpK = (unsigned char*)malloc(basedecodedkey + 1); - decode((char*)MY_KEY, tmpK, basedecodedkey); - tmpK[basedecodedkey] = 0; - - - aes_set_key( &ctx, tmpK, 128); - int dwResSize = SizeofResource(g_hInstance, hRes); - char *pData = (char*)GlobalLock(hResource); - char *pCopy = (char*)_alloca(dwResSize+1); - memcpy(pCopy, pData, dwResSize); - pCopy[dwResSize] = 0; - int basedecoded = decodeSize(pCopy); - GlobalUnlock(hResource); - unsigned char *bufD = (unsigned char*)mir_alloc(basedecoded + 1); - unsigned char *tmpD = (unsigned char*)mir_alloc(basedecoded + 1); - decode(pData, tmpD, basedecoded); - for (int i = 0; i < basedecoded; i += 16) { - aes_decrypt(&ctx, tmpD+i, bufD+i); - } - mir_free(tmpD); - bufD[basedecoded] = 0; //cert should be null terminated - return (char*)bufD; - } - return NULL; - } - return NULL; -} - -// -// FUNCTION: IsRunAsAdmin() -// -// PURPOSE: The function checks whether the current process is run as -// administrator. In other words, it dictates whether the primary access -// token of the process belongs to user account that is a member of the -// local Administrators group and it is elevated. -// -// RETURN VALUE: Returns TRUE if the primary access token of the process -// belongs to user account that is a member of the local Administrators -// group and it is elevated. Returns FALSE if the token does not. -// -// EXCEPTION: If this function fails, it throws a C++ DWORD exception which -// contains the Win32 error code of the failure. -// -// EXAMPLE CALL: -// try -// { -// if (IsRunAsAdmin()) -// wprintf (L"Process is run as administrator\n"); -// else -// wprintf (L"Process is not run as administrator\n"); -// } -// catch (DWORD dwError) -// { -// wprintf(L"IsRunAsAdmin failed w/err %lu\n", dwError); -// } -// -BOOL 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; -} - -int StartSkypeRuntime() -{ - // loading skype runtime - // shitcode - STARTUPINFO cif; - PROCESS_INFORMATION pi; - TCHAR param[128]; - - ZeroMemory(&cif, sizeof(STARTUPINFO)); - cif.cb = sizeof(STARTUPINFO); - cif.dwFlags = STARTF_USESHOWWINDOW; - cif.wShowWindow = SW_HIDE; - - HRSRC hRes; - HGLOBAL hResource; - TCHAR szFilename[MAX_PATH]; - - hRes = FindResource(g_hInstance, MAKEINTRESOURCE(IDR_RUNTIME), _T("BIN")); - - if (hRes) { - hResource = LoadResource(g_hInstance, hRes); - if (hResource) { - HANDLE hFile; - char *pData = (char *)LockResource(hResource); - DWORD dwSize = SizeofResource(g_hInstance, hRes), written = 0; - GetModuleFileName(g_hInstance, szFilename, MAX_PATH); - TCHAR *SkypeKitPath = _tcsrchr(szFilename, '\\'); - if (SkypeKitPath != NULL) - *SkypeKitPath = '\0'; - mir_sntprintf(szFilename, SIZEOF(szFilename), _T("%s\\%s"), szFilename, _T("SkypeKit.exe")); - if (!PathFileExists(szFilename)) - { - if ((hFile = CreateFile(szFilename, 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 (!IsRunAsAdmin()) - { - wchar_t szPath[MAX_PATH], cmdLine[100]; - GetModuleFileName(NULL, szPath, ARRAYSIZE(szPath)); - TCHAR *profilename = Utils_ReplaceVarsT(_T("%miranda_profilename%")); - mir_sntprintf(cmdLine, SIZEOF(cmdLine), _T(" /restart:%d /profile=%s"), GetCurrentProcessId(), profilename); - // Launch itself as administrator. - SHELLEXECUTEINFO sei = { sizeof(sei) }; - sei.lpVerb = L"runas"; - sei.lpFile = szPath; - 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 (_tcsicmp(entry.szExeFile, _T("SkypeKit.exe")) == 0) { - HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, entry.th32ProcessID); - port += rand() % 100; - CloseHandle(hProcess); - break; - } - } - } - CloseHandle(snapshot); - - wchar_t* tszUserFolder = Utils_ReplaceVarsT(_T("%miranda_userdata%\\SkypeKit")); - mir_sntprintf(param, SIZEOF(param), L"-p -P %d -f %s", port, tszUserFolder); - int startingrt = CreateProcess(szFilename, param, NULL, NULL, FALSE, CREATE_NEW_CONSOLE, NULL, NULL, &cif, &pi); - mir_free(tszUserFolder); - - return startingrt; -} extern "C" int __declspec(dllexport) Load(void) { - if (!StartSkypeRuntime()) - return 1; - mir_getXI(&xi); mir_getTMI(&tmi); mir_getLP(&pluginInfo); - g_skype = new CSkype(); - char *keyBuf = LoadKeyPair(); - g_skype->init(keyBuf, "127.0.0.1", port); - mir_free(keyBuf); - g_skype->start(); - PROTOCOLDESCRIPTOR pd = { sizeof(pd) }; - pd.szName = "SKYPE"; - pd.type = PROTOTYPE_PROTOCOL; - pd.fnInit = (pfnInitProto)CSkypeProto::InitSkypeProto; - pd.fnUninit = (pfnUninitProto)CSkypeProto::UninitSkypeProto; + pd.szName = "SKYPE"; + pd.type = PROTOTYPE_PROTOCOL; + pd.fnInit = (pfnInitProto) CSkypeProto::InitSkypeProto; + pd.fnUninit = (pfnUninitProto)CSkypeProto::UninitSkypeProto; CallService(MS_PROTO_REGISTERMODULE, 0, reinterpret_cast(&pd)); CSkypeProto::InitIcons(); @@ -379,8 +61,5 @@ extern "C" int __declspec(dllexport) Unload(void) CSkypeProto::UninitMenus(); CSkypeProto::UninitIcons(); - g_skype->stop(); - delete g_skype; - return 0; } \ No newline at end of file diff --git a/protocols/Skype/src/skype.h b/protocols/Skype/src/skype.h index 8e357b1efd..ba1a8266b7 100644 --- a/protocols/Skype/src/skype.h +++ b/protocols/Skype/src/skype.h @@ -54,10 +54,7 @@ #include "resource.h" #include "version.h" #include "skype_subclassing.h" -extern "C" -{ -#include "aes\aes.h" -} + #include "..\..\..\skypekit\key.h" #define MODULE "Skype" @@ -80,5 +77,4 @@ extern "C" #define CMITEMS_COUNT 3 -extern CSkype* g_skype; extern HINSTANCE g_hInstance; \ No newline at end of file diff --git a/protocols/Skype/src/skype_account.cpp b/protocols/Skype/src/skype_account.cpp index 18505d9af4..34cac051a5 100644 --- a/protocols/Skype/src/skype_account.cpp +++ b/protocols/Skype/src/skype_account.cpp @@ -12,9 +12,14 @@ void CSkypeProto::OnAccountChanged(int prop) { this->ForkThread(&CSkypeProto::SignInAsync, 0); //this->SignInAsync(this); + + CContact::AVAILABILITY status; + this->account->GetPropAvailability(status); + if (status != CContact::CONNECTING && status >= CContact::ONLINE) + this->SetStatus(this->SkypeToMirandaStatus(status)); } - if ((loginStatus == CAccount::LOGGED_OUT || loginStatus == CAccount::LOGGED_OUT_AND_PWD_SAVED)) + if (loginStatus == CAccount::LOGGED_OUT) { CAccount::LOGOUTREASON whyLogout; this->account->GetPropLogoutreason(whyLogout); @@ -27,13 +32,23 @@ void CSkypeProto::OnAccountChanged(int prop) NULL, this->SkypeToMirandaLoginError(whyLogout)); - this->ShowNotification(NULL, CSkypeProto::LogoutReasons[whyLogout - 1]); + this->ShowNotification(CSkypeProto::LogoutReasons[whyLogout - 1]); } } break; - default : - OnProfileChanged(prop); + //case CAccount::P_AVATAR_IMAGE: + case CAccount::P_AVATAR_TIMESTAMP: + this->UpdateProfileAvatar(this->account.fetch()); + break; + + //case CAccount::P_MOOD_TEXT: + case CAccount::P_MOOD_TIMESTAMP: + this->UpdateProfileStatusMessage(this->account.fetch()); + break; + + case CAccount::P_PROFILE_TIMESTAMP: + this->UpdateProfile(this->account.fetch()); } } diff --git a/protocols/Skype/src/skype_chat.cpp b/protocols/Skype/src/skype_chat.cpp index 66fea56334..8ca1abfa99 100644 --- a/protocols/Skype/src/skype_chat.cpp +++ b/protocols/Skype/src/skype_chat.cpp @@ -3,6 +3,23 @@ #include #include +char *CSkypeProto::Groups[] = +{ + "Creator", + "Admin", + "Speaker", + "Writer", + "Retried", + "Outlaw" +}; + +#define SKYPE_CHAT_GROUP_OWNER 0 +#define SKYPE_CHAT_GROUP_ADMIN 1 +#define SKYPE_CHAT_GROUP_SPEAKER 2 +#define SKYPE_CHAT_GROUP_WIRTER 3 +#define SKYPE_CHAT_GROUP_RETRIED 4 +#define SKYPE_CHAT_GROUP_OUTLAW 5 + bool CSkypeProto::IsChatRoom(HANDLE hContact) { return ::DBGetContactSettingByte(hContact, this->m_szModuleName, "ChatRoom", 0) > 0; @@ -145,16 +162,16 @@ char *CSkypeProto::StartChat(const char *cid, const SEStringList &invitedContact if (cid) { - g_skype->GetConversationByIdentity(cid, conversation); + this->skype->GetConversationByIdentity(cid, conversation); conversation->GetJoinBlob(data); - g_skype->GetConversationByBlob(data, conversation, false); + this->skype->GetConversationByBlob(data, conversation, false); conversation->Join(); chatID = ::mir_strdup(cid); } else { - g_skype->CreateConference(conversation); + this->skype->CreateConference(conversation); conversation->SetOption(CConversation::P_OPT_JOINING_ENABLED, true); conversation->SetOption(CConversation::P_OPT_ENTRY_LEVEL_RANK, CParticipant::WRITER); conversation->SetOption(CConversation::P_OPT_DISCLOSE_HISTORY, 1); @@ -186,12 +203,11 @@ char *CSkypeProto::StartChat(const char *cid, const SEStringList &invitedContact GCEVENT gce = {0}; gce.cbSize = sizeof(GCEVENT); gce.pDest = &gcd; - gce.pszStatus = ::Translate("Me"); - ::CallServiceSync(MS_GC_EVENT, 0, (LPARAM)&gce); - - gcd.iType = GC_EVENT_ADDGROUP; - gce.pszStatus = ::Translate("Others"); - ::CallServiceSync(MS_GC_EVENT, 0, (LPARAM)&gce); + for (int i = 0; i < SIZEOF(CSkypeProto::Groups); i++) + { + gce.pszStatus = Translate(CSkypeProto::Groups[i]); + CallServiceSync(MS_GC_EVENT, NULL, (LPARAM)&gce); + } gcd.iType = GC_EVENT_CONTROL; ::CallServiceSync(MS_GC_EVENT, SESSION_INITDONE, (LPARAM)&gce); @@ -210,9 +226,9 @@ void CSkypeProto::JoinToChat(const char *cid, bool showWindow) SEString data; CConversation::Ref conversation; - g_skype->GetConversationByIdentity(cid, conversation); + this->skype->GetConversationByIdentity(cid, conversation); conversation->GetJoinBlob(data); - g_skype->GetConversationByBlob(data, conversation, false); + this->skype->GetConversationByBlob(data, conversation, false); conversation->Join(); conversation->GetPropDisplayname(data); @@ -232,12 +248,13 @@ void CSkypeProto::JoinToChat(const char *cid, bool showWindow) GCEVENT gce = {0}; gce.cbSize = sizeof(GCEVENT); gce.pDest = &gcd; - gce.pszStatus = ::Translate("Me"); - ::CallServiceSync(MS_GC_EVENT, 0, (LPARAM)&gce); gcd.iType = GC_EVENT_ADDGROUP; - gce.pszStatus = ::Translate("Others"); - ::CallServiceSync(MS_GC_EVENT, 0, (LPARAM)&gce); + for (int i = 0; i < SIZEOF(CSkypeProto::Groups); i++) + { + gce.pszStatus = Translate(CSkypeProto::Groups[i]); + CallServiceSync(MS_GC_EVENT, NULL, (LPARAM)&gce); + } gcd.iType = GC_EVENT_CONTROL; ::CallServiceSync(MS_GC_EVENT, showWindow ? SESSION_INITDONE : WINDOW_HIDDEN, (LPARAM)&gce); @@ -249,7 +266,20 @@ void CSkypeProto::JoinToChat(const char *cid, bool showWindow) for (uint i = 0; i < participants.size(); i++) { participants[i]->GetPropIdentity(data); - this->AddChatContact(cid, ::mir_strdup(data)); + + CParticipant::RANK rank; + participants[i]->GetPropRank(rank); + + CContact::Ref contact; + CContact::AVAILABILITY status; + this->skype->GetContact(data, contact); + contact->GetPropAvailability(status); + + this->AddChatContact( + cid, + ::mir_strdup(data), + CParticipant::GetRankName(rank), + this->SkypeToMirandaStatus(status)); } ::mir_free(chatName); @@ -272,7 +302,7 @@ void CSkypeProto::LeaveChat(const char *cid) ::mir_free(chatID); } -void CSkypeProto::RaiseChatEvent(const char *cid, const char *sid, int evt, const char *message) +void CSkypeProto::RaiseChatEvent(const char *cid, const char *sid, int evt, const DWORD itemData, const char *status, const char *message) { char *idt = ::mir_strdup(cid); char *snt = ::mir_strdup(sid); @@ -290,7 +320,8 @@ void CSkypeProto::RaiseChatEvent(const char *cid, const char *sid, int evt, cons gce.pszNick = nick; gce.pszUID = snt; gce.bIsMe = ::stricmp(sid, this->login) == 0; - gce.pszStatus = gce.bIsMe ? ::Translate("Me") : ::Translate("Others"); + gce.dwItemData = itemData; + gce.pszStatus = status; gce.pszText = message; gce.time = time(NULL); ::CallServiceSync(MS_GC_EVENT, 0, (LPARAM)&gce); @@ -301,12 +332,14 @@ void CSkypeProto::RaiseChatEvent(const char *cid, const char *sid, int evt, cons void CSkypeProto::SendChatMessage(const char *cid, const char *sid, const char *message) { - this->RaiseChatEvent(cid, sid, GC_EVENT_MESSAGE, message); + this->RaiseChatEvent(cid, sid, GC_EVENT_MESSAGE, 0, NULL, message); } -void CSkypeProto::AddChatContact(const char *cid, const char *sid) +void CSkypeProto::AddChatContact(const char *cid, const char *sid, const char *group, const WORD status) { this->RaiseChatEvent(cid, sid, GC_EVENT_JOIN); + this->RaiseChatEvent(cid, sid, GC_EVENT_ADDSTATUS, 0, CSkypeProto::Groups[SKYPE_CHAT_GROUP_WIRTER]); + this->RaiseChatEvent(cid, sid, GC_EVENT_SETCONTACTSTATUS, status); } void CSkypeProto::KickChatContact(const char *cid, const char *sid) @@ -360,7 +393,7 @@ int __cdecl CSkypeProto::OnGCEventHook(WPARAM, LPARAM lParam) case GC_SESSION_TERMINATE: { CConversation::Ref conversation; - if (g_skype->GetConversationByIdentity(chatID, conversation, false)) + if (this->skype->GetConversationByIdentity(chatID, conversation, false)) { Participant::Refs participants; conversation->GetParticipants(participants, CConversation::MYSELF); @@ -373,22 +406,11 @@ int __cdecl CSkypeProto::OnGCEventHook(WPARAM, LPARAM lParam) if (gch->pszText && gch->pszText[0]) { CConversation::Ref conversation; - if (g_skype->GetConversationByIdentity(chatID, conversation, false)) + if (this->skype->GetConversationByIdentity(chatID, conversation, false)) { CMessage::Ref message; char *text = ::mir_utf8encode(gch->pszText); conversation->PostText(text, message); - - char *nick = (char *)::DBGetString(NULL, this->m_szModuleName, "Nick"); - if (::stricmp(nick, "") == 0) - { - nick = this->login; - } - - this->SendChatMessage( - chatID, - nick, - gch->pszText); } } break; diff --git a/protocols/Skype/src/skype_contacts.cpp b/protocols/Skype/src/skype_contacts.cpp index 26e26326a4..9512deca75 100644 --- a/protocols/Skype/src/skype_contacts.cpp +++ b/protocols/Skype/src/skype_contacts.cpp @@ -1,17 +1,5 @@ #include "skype_proto.h" -void CSkypeProto::UpdateContactAboutText(HANDLE hContact, CContact::Ref contact) -{ - SEString data; - contact->GetPropAbout(data); - wchar_t* aboutText = ::mir_utf8decodeW((const char*)data); - if (wcscmp(aboutText, L"") == 0) - this->DeleteSetting(hContact, "About"); - else - this->SetSettingString(hContact, "About", aboutText); - ::mir_free(aboutText); -} - void CSkypeProto::UpdateContactAuthState(HANDLE hContact, CContact::Ref contact) { uint newTS = 0; @@ -37,221 +25,6 @@ void CSkypeProto::UpdateContactAuthState(HANDLE hContact, CContact::Ref contact) } } -void CSkypeProto::UpdateContactAvatar(HANDLE hContact, CContact::Ref contact) -{ - uint newTS = 0; - contact->GetPropAvatarTimestamp(newTS); - DWORD oldTS = this->GetSettingDword(hContact, "AvatarTS"); - SEBinary data; - contact->GetPropAvatarImage(data); - wchar_t *path = this->GetContactAvatarFilePath(hContact); - int ttt = _waccess(path, 0); - if ((newTS > oldTS) || (!newTS && data.size() > 0 && _waccess(path, 0) == -1) || (newTS && _waccess(path, 0) == -1)) //hack for avatars without timestamp - { - FILE* fp = _wfopen(path, L"wb"); - if (fp) - { - fwrite(data.data(), sizeof(char), data.size(), fp); - fclose(fp); - - this->SetSettingDword(hContact, "AvatarTS", newTS); - - PROTO_AVATAR_INFORMATIONW pai = {0}; - pai.cbSize = sizeof(pai); - pai.format = PA_FORMAT_JPEG; - pai.hContact = hContact; - wcscpy(pai.filename, path); - - this->SendBroadcast(hContact, ACKTYPE_AVATAR, ACKRESULT_SUCCESS, (HANDLE)&pai, 0); - } - } - delete path; -} - -void CSkypeProto::UpdateContactBirthday(HANDLE hContact, CContact::Ref contact) -{ - uint data; - contact->GetPropBirthday(data); - TCHAR date[9]; - if (data > 0) - { - _itot_s(data, date, 10); - INT day, month, year; - _stscanf(date, _T("%04d%02d%02d"), &year, &month, &day); - this->SetSettingByte(hContact, "BirthDay", day); - this->SetSettingByte(hContact, "BirthMonth", month); - this->SetSettingWord(hContact, "BirthYear", year); - - SYSTEMTIME sToday = {0}; - GetLocalTime(&sToday); - int nAge = sToday.wYear - year; - if (sToday.wMonth < month || (sToday.wMonth == month && sToday.wDay < day)) - nAge--; - if (nAge) - this->SetSettingWord( hContact, "Age", ( WORD )nAge ); - } - else - { - this->DeleteSetting(hContact, "BirthDay"); - this->DeleteSetting(hContact, "BirthMonth"); - this->DeleteSetting(hContact, "BirthYear"); - this->DeleteSetting(hContact, "Age"); - } -} - -void CSkypeProto::UpdateContactCity(HANDLE hContact, CContact::Ref contact) -{ - SEString data; - contact->GetPropCity(data); - wchar_t* city = ::mir_utf8decodeW((const char*)data); - if (wcscmp(city, L"") == 0) - this->DeleteSetting(hContact, "City"); - else - this->SetSettingString(hContact, "City", city); - ::mir_free(city); -} - -void CSkypeProto::UpdateContactCountry(HANDLE hContact, CContact::Ref contact) -{ - // country (en, ru, etc) - SEString data; - char* country; - contact->GetPropCountry(data); - char* isocode = ::mir_utf8decodeA((const char*)data); - if (strcmp(isocode, "") == 0) - { - country = (char*)CallService(MS_UTILS_GETCOUNTRYBYNUMBER, 0xFFFF, 0); - this->SetSettingString(hContact, "Country", _A2T(country)); - } - else - { - country = (char*)CallService(MS_UTILS_GETCOUNTRYBYISOCODE, (WPARAM)isocode, 0); - this->SetSettingString(hContact, "Country", _A2T(country)); - } - ::mir_free(isocode); -} - -void CSkypeProto::UpdateContactEmails(HANDLE hContact, CContact::Ref contact) -{ - SEString data; - contact->GetPropEmails(data); - wchar_t* emails = ::mir_utf8decodeW((const char*)data); - if (wcscmp(emails, L"") == 0) - { - this->DeleteSetting(hContact, "e-mail0"); - this->DeleteSetting(hContact, "e-mail1"); - this->DeleteSetting(hContact, "e-mail2"); - } - else - { - wchar_t* p = wcstok(emails, L" "); - if (p == NULL) - { - this->SetSettingString(hContact, "e-mail0", emails); - } - else - { - this->SetSettingString(hContact, "e-mail0", p); - p = wcstok(NULL, L" "); - if (p) this->SetSettingString(hContact, "e-mail1", p); - p = wcstok(NULL, L" "); - if (p) this->SetSettingString(hContact, "e-mail2", p); - } - } - ::mir_free(emails); -} - -void CSkypeProto::UpdateContactGender(HANDLE hContact, CContact::Ref contact) -{ - uint data; - contact->GetPropGender(data); - if (data) - this->SetSettingByte(hContact, "Gender", (BYTE)(data == 1 ? 'M' : 'F')); - else - this->DeleteSetting(hContact, "Gender"); -} - -void CSkypeProto::UpdateContactHomepage(HANDLE hContact, CContact::Ref contact) -{ - SEString data; - contact->GetPropHomepage(data); - wchar_t* homepage = ::mir_utf8decodeW((const char*)data); - if (wcscmp(homepage, L"") == 0) - this->DeleteSetting(hContact, "Homepage"); - else - this->SetSettingString(hContact, "Homepage", homepage); - ::mir_free(homepage); -} - -void CSkypeProto::UpdateContactLanguages(HANDLE hContact, CContact::Ref contact) -{ - // languages (en, ru, etc), space searated - SEString data; - contact->GetPropLanguages(data); - char* isocode = ::mir_utf8decodeA((const char*)data); - if (strcmp(isocode, "") == 0) - { - this->DeleteSetting(hContact, "Language1"); } - else - { - for (int i = 0; i < SIZEOF(CSkypeProto::languages); i++) - if ( lstrcmpiA((char*)isocode, CSkypeProto::languages[i].ISOcode) == 0) - { - this->SetSettingString(hContact, "Language1", ::mir_a2u(CSkypeProto::languages[i].szName)); - break; - } - } - ::mir_free(isocode); -} - -void CSkypeProto::UpdateContactMobilePhone(HANDLE hContact, CContact::Ref contact) -{ - SEString data; - contact->GetPropPhoneMobile(data); - wchar_t* phone = ::mir_utf8decodeW((const char*)data); - if (wcscmp(phone, L"") == 0) - this->DeleteSetting(hContact, "Cellular"); - else - this->SetSettingString(hContact, "Cellular", phone); - ::mir_free(phone); -} - -void CSkypeProto::UpdateContactPhone(HANDLE hContact, CContact::Ref contact) -{ - SEString data; - contact->GetPropPhoneHome(data); - wchar_t* phone = ::mir_utf8decodeW((const char*)data); - if (wcscmp(phone, L"") == 0) - this->DeleteSetting(hContact, "Phone"); - else - this->SetSettingString(hContact, "Phone", phone); - ::mir_free(phone); -} - -void CSkypeProto::UpdateContactOfficePhone(HANDLE hContact, CContact::Ref contact) -{ - SEString data; - contact->GetPropPhoneOffice(data); - wchar_t* phone = ::mir_utf8decodeW((const char*)data); - if (wcscmp(phone, L"") == 0) - this->DeleteSetting(hContact, "CompanyPhone"); - else - this->SetSettingString(hContact, "CompanyPhone", phone); - ::mir_free(phone); -} - -void CSkypeProto::UpdateContactState(HANDLE hContact, CContact::Ref contact) -{ - SEString data; - contact->GetPropProvince(data); - wchar_t* state = ::mir_utf8decodeW((const char*)data); - if (wcscmp(state, L"") == 0) - this->DeleteSetting(hContact, "State"); - else - this->SetSettingString(hContact, "State", state); - ::mir_free(state); -} - void CSkypeProto::UpdateContactStatus(HANDLE hContact, CContact::Ref contact) { CContact::AVAILABILITY availability; @@ -271,105 +44,22 @@ void CSkypeProto::UpdateContactStatus(HANDLE hContact, CContact::Ref contact) } } -void CSkypeProto::UpdateContactStatusMessage(HANDLE hContact, CContact::Ref contact) -{ - SEString data; - contact->GetPropMoodText(data); - wchar_t* status = ::mir_utf8decodeW((const char*)data); - if (wcscmp(status, L"") == 0) - this->DeleteSetting(hContact, "XStatusMsg"); - else - this->SetSettingString(hContact, "XStatusMsg", status); - ::mir_free(status); -} - -void CSkypeProto::UpdateContactTimezone(HANDLE hContact, CContact::Ref contact) -{ - uint data; - contact->GetPropTimezone(data); - if (data > 0) - { - uint diffmin = (data - 24*3600) / 60; - wchar_t sign[2]; - if (diffmin < 0) - ::wcscpy(sign, L"-"); - else - ::wcscpy(sign, L"+"); - uint hours = ::abs((int)(diffmin / 60)); - uint mins = ::abs((int)(diffmin % 60)); - wchar_t timeshift[7]; - ::mir_sntprintf(timeshift, SIZEOF(timeshift), _T("%s%d:%02d"), sign, hours, mins); - - wchar_t *szMin = wcschr(timeshift, ':'); - int nTz = ::_wtoi(timeshift) * -2; - nTz += (nTz < 0 ? -1 : 1) * (szMin ? _ttoi( szMin + 1 ) / 30 : 0); - - TIME_ZONE_INFORMATION tzinfo; - if (::GetTimeZoneInformation(&tzinfo) == TIME_ZONE_ID_DAYLIGHT) - nTz -= tzinfo.DaylightBias / 30; - - this->SetSettingByte(hContact, "Timezone", (signed char)nTz); - } - else - this->DeleteSetting(hContact, "TimeZone"); -} - -void CSkypeProto::UpdateContactOnlineSinceTime(HANDLE hContact, CContact::Ref contact) +void CSkypeProto::UpdateContactOnlineSinceTime(SEObject *obj, HANDLE hContact) { - uint newTS = 0; - contact->GetPropLastonlineTimestamp(newTS); + uint newTS = obj->GetUintProp(/* CContact::P_LASTONLINE_TIMESTAMP */35); DWORD oldTS = this->GetSettingDword(hContact, "OnlineSinceTS"); if (newTS > oldTS) this->SetSettingDword(hContact, "OnlineSinceTS", newTS); } -void CSkypeProto::UpdateContactLastEventDate(HANDLE hContact, CContact::Ref contact) -{ - uint newTS = 0; - contact->GetPropLastusedTimestamp(newTS); - DWORD oldTS = this->GetSettingDword(hContact, "LastEventDateTS"); - if (newTS > oldTS) - this->SetSettingDword(hContact, "LastEventDateTS", newTS); -} - -void CSkypeProto::UpdateFullName(HANDLE hContact, CContact::Ref contact) -{ - SEString data; - contact->GetPropFullname(data); - wchar_t* fullname = ::mir_utf8decodeW((const char*)data); - if (wcscmp(fullname, L"") == 0) - this->DeleteSetting(hContact, "LastName"); - else - this->SetSettingString(hContact, "LastName", fullname); - ::mir_free(fullname); -} - -void CSkypeProto::UpdateContactProfile(HANDLE hContact, CContact::Ref contact) +void CSkypeProto::UpdateContactLastEventDate(SEObject *obj, HANDLE hContact) { - uint newTS = 0; - contact->GetPropProfileTimestamp(newTS); - DWORD oldTS = this->GetSettingDword(hContact, "ProfileTS"); - if (newTS > oldTS) + if (hContact) { - this->UpdateContactAboutText(hContact, contact); - this->UpdateContactBirthday(hContact, contact); - this->UpdateContactCity(hContact, contact); - this->UpdateContactCountry(hContact, contact); - this->UpdateContactEmails(hContact, contact); - this->UpdateContactGender(hContact, contact); - this->UpdateContactHomepage(hContact, contact); - this->UpdateContactLanguages(hContact, contact); - this->UpdateContactMobilePhone(hContact, contact); - this->UpdateContactPhone(hContact, contact); - this->UpdateContactOfficePhone(hContact, contact); - this->UpdateContactState(hContact, contact); - this->UpdateContactTimezone(hContact, contact); - this->UpdateContactOnlineSinceTime(hContact, contact); - this->UpdateContactLastEventDate(hContact, contact); - this->UpdateFullName(hContact, contact); - - this->SetSettingString(hContact, "MirVer", _T("Skype")); - this->SetSettingDword(hContact, "ProfileTS", newTS); + uint newTS = obj->GetUintProp(/* CContact::P_LASTUSED_TIMESTAMP */39); + DWORD oldTS = this->GetSettingDword(hContact, "LastEventDateTS"); + if (newTS > oldTS) + this->SetSettingDword(hContact, "LastEventDateTS", newTS); } } @@ -380,13 +70,12 @@ void CSkypeProto::OnContactChanged(CContact::Ref contact, int prop) const char *sid = (const char*)data; HANDLE hContact = this->GetContactBySid(sid); + SEObject *contactObj = contact.fetch(); + if (hContact) { switch(prop) { - case CContact::P_ABOUT: - this->UpdateContactAboutText(hContact, contact); - break; case CContact::P_AUTHREQ_TIMESTAMP: { uint newTS = 0; @@ -418,58 +107,22 @@ void CSkypeProto::OnContactChanged(CContact::Ref contact, int prop) // todo: all authrequests after first should be catch here this->UpdateContactAuthState(hContact, contact); break; + case CContact::P_AVAILABILITY: this->UpdateContactStatus(hContact, contact); break; - case CContact::P_AVATAR_IMAGE: + + //case CContact::P_AVATAR_IMAGE: case CContact::P_AVATAR_TIMESTAMP: - this->UpdateContactAvatar(hContact, contact); - break; - case CContact::P_BIRTHDAY: - this->UpdateContactBirthday(hContact, contact); - break; - case CContact::P_CITY: - this->UpdateContactCity(hContact, contact); - break; - case CContact::P_COUNTRY: - this->UpdateContactCountry(hContact, contact); - break; - case CContact::P_EMAILS: - this->UpdateContactEmails(hContact, contact); + this->UpdateProfileAvatar(contactObj, hContact); break; - case CContact::P_GENDER: - this->UpdateContactGender(hContact, contact); - break; - case CContact::P_HOMEPAGE: - this->UpdateContactHomepage(hContact, contact); - break; - case CContact::P_LANGUAGES: - this->UpdateContactLanguages(hContact, contact); - break; - case CContact::P_MOOD_TEXT: + //case CContact::P_MOOD_TEXT: case CContact::P_MOOD_TIMESTAMP: - this->UpdateContactStatusMessage(hContact, contact); - break; - case CContact::P_PHONE_HOME: - this->UpdateContactPhone(hContact, contact); - break; - case CContact::P_PHONE_MOBILE: - this->UpdateContactMobilePhone(hContact, contact); - break; - case CContact::P_PHONE_OFFICE: - this->UpdateContactOfficePhone(hContact, contact); + this->UpdateProfileStatusMessage(contactObj, hContact); break; + case CContact::P_PROFILE_TIMESTAMP: - this->UpdateContactProfile(hContact, contact); - break; - case CContact::P_PROVINCE: - this->UpdateContactState(hContact, contact); - break; - case CContact::P_TIMEZONE: - this->UpdateContactTimezone(hContact, contact); - break; - case CContact::P_FULLNAME: - this->UpdateFullName(hContact, contact); + this->UpdateProfile(contactObj, hContact); break; } } @@ -578,14 +231,14 @@ HANDLE CSkypeProto::AddContactBySid(const char* sid, const char* nick, DWORD fla ::DBWriteContactSettingString(hContact, this->m_szModuleName, "Nick", nick); CContact::Ref contact; - if (g_skype->GetContact(sid, contact)) + if (this->skype->GetContact(sid, contact)) { contact.fetch(); bool result; if (contact->IsMemberOfHardwiredGroup(CContactGroup::ALL_BUDDIES, result)) { CContactGroup::Ref group; - if (g_skype->GetHardwiredContactGroup(CContactGroup::ALL_BUDDIES, group)) + if (this->skype->GetHardwiredContactGroup(CContactGroup::ALL_BUDDIES, group)) { group.fetch(); group->AddContact(contact); @@ -602,7 +255,7 @@ HANDLE CSkypeProto::AddContactBySid(const char* sid, const char* nick, DWORD fla this->SetSettingByte(hContact, "Auth", 1); ::DBDeleteContactSetting(hContact, this->m_szModuleName, "IsSkypeOut"); - this->UpdateContactProfile(hContact, contact); + this->UpdateProfile(contact.fetch(), hContact); if (flags & PALF_TEMPORARY) { @@ -620,60 +273,9 @@ HANDLE CSkypeProto::AddContactBySid(const char* sid, const char* nick, DWORD fla return hContact; } -int CSkypeProto::SkypeToMirandaStatus(CContact::AVAILABILITY availability) -{ - int status = ID_STATUS_OFFLINE; - - switch (availability) - { - case CContact::ONLINE: - case CContact::ONLINE_FROM_MOBILE: - status = ID_STATUS_ONLINE; - break; - - case CContact::AWAY: - case CContact::AWAY_FROM_MOBILE: - status = ID_STATUS_AWAY; - break; - - case CContact::DO_NOT_DISTURB: - case CContact::DO_NOT_DISTURB_FROM_MOBILE: - status = ID_STATUS_DND; - break; - } - - return status; -} - -CContact::AVAILABILITY CSkypeProto::MirandaToSkypeStatus(int status) -{ - CContact::AVAILABILITY availability = CContact::UNKNOWN; - - switch(status) - { - case ID_STATUS_ONLINE: - availability = CContact::ONLINE; - break; - - case ID_STATUS_AWAY: - availability = CContact::AWAY; - break; - - case ID_STATUS_DND: - availability = CContact::DO_NOT_DISTURB; - break; - - case ID_STATUS_INVISIBLE: - availability = CContact::INVISIBLE; - break; - } - - return availability; -} - void __cdecl CSkypeProto::LoadContactList(void*) { - g_skype->GetHardwiredContactGroup(CContactGroup::ALL_BUDDIES, this->commonList); + this->skype->GetHardwiredContactGroup(CContactGroup::ALL_BUDDIES, this->commonList); this->commonList.fetch(); this->commonList->SetOnContactListChangedCallback( (CContactGroup::OnContactListChanged)&CSkypeProto::OnContactListChanged, @@ -715,47 +317,49 @@ void __cdecl CSkypeProto::LoadContactList(void*) HANDLE hContact = this->AddContactBySid(sid, nick, flags); + SEObject *obj = contact.fetch(); this->UpdateContactAuthState(hContact, contact); - this->UpdateContactAvatar(hContact, contact); - this->UpdateContactProfile(hContact, contact); this->UpdateContactStatus(hContact, contact); - this->UpdateContactStatusMessage(hContact, contact); + + this->UpdateProfile(obj, hContact); + this->UpdateProfileAvatar(obj, hContact); + this->UpdateProfileStatusMessage(obj, hContact); } - CConversation::Refs conversations; - g_skype->GetConversationList(conversations); - for (uint i = 0; i < conversations.size(); i++) - { - CConversation::TYPE type; - conversations[i]->GetPropType(type); + //CConversation::Refs conversations; + //this->skype->GetConversationList(conversations); + //for (uint i = 0; i < conversations.size(); i++) + //{ + // CConversation::TYPE type; + // conversations[i]->GetPropType(type); - CConversation::MY_STATUS status; - conversations[i]->GetPropMyStatus(status); - if (type == CConversation::CONFERENCE) - { - SEString data; + // CConversation::MY_STATUS status; + // conversations[i]->GetPropMyStatus(status); + // if (type == CConversation::CONFERENCE) + // { + // SEString data; - conversations[i]->GetPropIdentity(data); - char *cid = ::mir_strdup(data); + // conversations[i]->GetPropIdentity(data); + // char *cid = ::mir_strdup(data); - conversations[i]->GetPropDisplayname(data); - char *name = ::mir_utf8decodeA(data); + // conversations[i]->GetPropDisplayname(data); + // char *name = ::mir_utf8decodeA(data); - HANDLE hContact = this->AddChatRoomByID(cid, name); - //::DBWriteContactSettingString(hContact, this->m_szModuleName, "Nick", name); + // HANDLE hContact = this->AddChatRoomByID(cid, name); + // //::DBWriteContactSettingString(hContact, this->m_szModuleName, "Nick", name); - CConversation::LOCAL_LIVESTATUS live; - conversations[i]->GetPropLocalLivestatus(live); + // CConversation::LOCAL_LIVESTATUS live; + // conversations[i]->GetPropLocalLivestatus(live); - if (status == CConversation::CONSUMER)// && live != CConversation::NONE) - { - this->JoinToChat(cid, false); - } - } - } + // if (status == CConversation::CONSUMER)// && live != CConversation::NONE) + // { + // this->JoinToChat(cid, false); + // } + // } + //} /*CConversation::Refs conversations; - g_skype->GetConversationList(conversations); + this->skype->GetConversationList(conversations); for (uint i = 0; i < conversations.size(); i++) { conversations[i]->Delete(); @@ -763,7 +367,7 @@ void __cdecl CSkypeProto::LoadContactList(void*) // raise auth event for all non auth contacts CContact::Refs authContacts; - g_skype->GetHardwiredContactGroup(CContactGroup::CONTACTS_WAITING_MY_AUTHORIZATION, this->authWaitList); + this->skype->GetHardwiredContactGroup(CContactGroup::CONTACTS_WAITING_MY_AUTHORIZATION, this->authWaitList); this->authWaitList.fetch(); this->authWaitList->SetOnContactListChangedCallback( (CContactGroup::OnContactListChanged)&CSkypeProto::OnContactListChanged, @@ -869,13 +473,13 @@ void __cdecl CSkypeProto::SearchBySidAsync(void* arg) HANDLE hContact = this->GetContactBySid(sid); if (hContact) { - this->ShowNotification(sid, TranslateT("Contact already in your contact list"), 0); + this->ShowNotification(TranslateT("Contact already in your contact list"), 0, sid); this->SendBroadcast(ACKTYPE_SEARCH, ACKRESULT_SUCCESS, (HANDLE)SKYPE_SEARCH_BYSID, 0); return; } CContactSearch::Ref search; - g_skype->CreateIdentitySearch(sid, search); + this->skype->CreateIdentitySearch(sid, search); search.fetch(); search->SetProtoInfo(this, (HANDLE)SKYPE_SEARCH_BYSID); search->SetOnContactFindedCallback( @@ -897,7 +501,7 @@ void __cdecl CSkypeProto::SearchByEmailAsync(void* arg) const wchar_t *email = (wchar_t *)arg; CContactSearch::Ref search; - g_skype->CreateContactSearch(search); + this->skype->CreateContactSearch(search); search.fetch(); search->SetProtoInfo(this, (HANDLE)SKYPE_SEARCH_BYEMAIL); search->SetOnContactFindedCallback( diff --git a/protocols/Skype/src/skype_dialogs.cpp b/protocols/Skype/src/skype_dialogs.cpp index f91416c599..07895a63c8 100644 --- a/protocols/Skype/src/skype_dialogs.cpp +++ b/protocols/Skype/src/skype_dialogs.cpp @@ -1,73 +1,6 @@ #include "skype_proto.h" -INT_PTR CALLBACK CSkypeProto::SkypeAccountProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) -{ - CSkypeProto *proto; - - switch (message) - { - case WM_INITDIALOG: - { - TranslateDialogDefault(hwnd); - - proto = reinterpret_cast(lparam); - SetWindowLongPtr(hwnd, GWLP_USERDATA, lparam); - - wchar_t* sid = proto->GetSettingString(SKYPE_SETTINGS_LOGIN); - SetDlgItemText(hwnd, IDC_SL, sid); - ::mir_free(sid); - - char* pwd = proto->GetDecodeSettingString(NULL, SKYPE_SETTINGS_PASSWORD); - SetDlgItemTextA(hwnd, IDC_PW, pwd); - ::mir_free(pwd); - - if ( proto->m_iStatus != ID_STATUS_OFFLINE) { - SendMessage(GetDlgItem(hwnd, IDC_SL), EM_SETREADONLY, 1, 0); - SendMessage(GetDlgItem(hwnd, IDC_PW), EM_SETREADONLY, 1, 0); - } - } - return TRUE; - - case WM_COMMAND: - { - if (HIWORD(wparam) == EN_CHANGE && reinterpret_cast(lparam) == GetFocus()) - { - switch(LOWORD(wparam)) { - case IDC_SL: - case IDC_PW: - SendMessage(GetParent(hwnd), PSM_CHANGED, 0, 0); - } - } - } - break; - - case WM_NOTIFY: - { - if (reinterpret_cast(lparam)->code == PSN_APPLY) { - proto = reinterpret_cast(GetWindowLongPtr(hwnd, GWLP_USERDATA)); - - char data[128]; - ::mir_free(proto->login); - GetDlgItemTextA(hwnd, IDC_SL, data, SIZEOF(data)); - ::DBWriteContactSettingString(NULL, proto->m_szModuleName, "sid", data); - proto->login = ::mir_strdup(data); - - GetDlgItemTextA(hwnd, IDC_PW, data, sizeof(data)); - proto->SetDecodeSettingString(NULL, SKYPE_SETTINGS_PASSWORD, data); - - proto->SetSettingByte("RememberPassword", true); - - return TRUE; - } - } - break; - - } - - return FALSE; -} - -INT_PTR CALLBACK CSkypeProto::SkypeOptionsProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) +INT_PTR CALLBACK CSkypeProto::SkypeMainOptionsProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { CSkypeProto *proto; @@ -77,8 +10,8 @@ INT_PTR CALLBACK CSkypeProto::SkypeOptionsProc(HWND hwnd, UINT message, WPARAM w { TranslateDialogDefault(hwnd); - proto = reinterpret_cast(lparam); - SetWindowLongPtr(hwnd, GWLP_USERDATA, lparam); + proto = reinterpret_cast(lParam); + SetWindowLongPtr(hwnd, GWLP_USERDATA, lParam); { wchar_t* data = proto->GetSettingString(SKYPE_SETTINGS_LOGIN, L""); SetDlgItemText(hwnd, IDC_SL, data); @@ -91,40 +24,89 @@ INT_PTR CALLBACK CSkypeProto::SkypeOptionsProc(HWND hwnd, UINT message, WPARAM w } { int port; - g_skype->GetInt(SETUPKEY_PORT, port); + proto->skype->GetInt(SETUPKEY_PORT, port); SetDlgItemInt(hwnd, IDC_PORT, proto->GetSettingWord("Port", port), FALSE); + SendMessage(GetDlgItem(hwnd, IDC_PORT), EM_SETLIMITTEXT, 5, 0); } { CheckDlgButton(hwnd, IDC_USE_ALT_PORTS, proto->GetSettingByte("UseAlternativePorts", 1)); } - - if (proto->m_iStatus != ID_STATUS_OFFLINE) { + if (proto->IsOnline()) + { SendMessage(GetDlgItem(hwnd, IDC_SL), EM_SETREADONLY, 1, 0); SendMessage(GetDlgItem(hwnd, IDC_PW), EM_SETREADONLY, 1, 0); SendMessage(GetDlgItem(hwnd, IDC_PORT), EM_SETREADONLY, 1, 0); SendMessage(GetDlgItem(hwnd, IDC_USE_ALT_PORTS), EM_SETREADONLY, 1, 0); + EnableWindow(GetDlgItem(hwnd, IDC_REGISTER), FALSE); + } + else if (proto->GetSettingWord("Status") > 0) + { + EnableWindow(GetDlgItem(hwnd, IDC_REGISTER), FALSE); } } return TRUE; case WM_COMMAND: { - if (HIWORD(wparam) == EN_CHANGE && reinterpret_cast(lparam) == GetFocus()) + proto = reinterpret_cast(GetWindowLongPtr(hwnd, GWLP_USERDATA)); + + switch(LOWORD(wParam)) { - switch(LOWORD(wparam)) + case IDC_SL: { - case IDC_SL: - case IDC_PW: - case IDC_PORT: - case IDC_USE_ALT_PORTS: + if ((HIWORD(wParam) != EN_CHANGE || (HWND)lParam != GetFocus())) return 0; + + if ( !proto->IsOnline() && proto->GetSettingWord("Status") == 0) + { + char data[128]; + GetDlgItemTextA(hwnd, IDC_SL, data, SIZEOF(data)); + EnableWindow(GetDlgItem(hwnd, IDC_REGISTER), ::strlen(data)); + } SendMessage(GetParent(hwnd), PSM_CHANGED, 0, 0); } + break; + + case IDC_PW: + { + if ((HIWORD(wParam) != EN_CHANGE || (HWND)lParam != GetFocus())) return 0; + SendMessage(GetParent(hwnd), PSM_CHANGED, 0, 0); + } + break; + + case IDC_PORT: + case IDC_USE_ALT_PORTS: + SendMessage(GetParent(hwnd), PSM_CHANGED, 0, 0); + break; + + case IDC_REGISTER: + { + char sid[128], pwd[128]; + GetDlgItemTextA(hwnd, IDC_SL, sid, SIZEOF(sid)); + GetDlgItemTextA(hwnd, IDC_PW, pwd, SIZEOF(pwd)); + + CSkype::VALIDATERESULT reason; + proto->skype->ValidatePassword(sid, pwd, reason); + + if (reason == CSkype::VALIDATED_OK) + { + CAccount::Ref account; + proto->skype->GetAccount(sid, proto->account); + proto->account->SetStrProperty(CAccount::P_FULLNAME, sid); + proto->account->SetOnAccountChangedCallback( + (CAccount::OnAccountChanged)&CSkypeProto::OnAccountChanged, proto); + proto->account->Register(pwd, false, false); + } + else + { + proto->ShowNotification(CSkypeProto::ValidationReasons[reason]); + } + } } } break; case WM_NOTIFY: - if (reinterpret_cast(lparam)->code == PSN_APPLY) + if (reinterpret_cast(lParam)->code == PSN_APPLY) { proto = reinterpret_cast(GetWindowLongPtr(hwnd, GWLP_USERDATA)); @@ -150,6 +132,35 @@ INT_PTR CALLBACK CSkypeProto::SkypeOptionsProc(HWND hwnd, UINT message, WPARAM w return FALSE; } +INT_PTR __cdecl CSkypeProto::OnAccountManagerInit(WPARAM wParam, LPARAM lParam) +{ + return (int)::CreateDialogParam( + g_hInstance, + MAKEINTRESOURCE(IDD_SKYPEACCOUNT), + (HWND)lParam, + &CSkypeProto::SkypeMainOptionsProc, + (LPARAM)this); +} + +int __cdecl CSkypeProto::OnOptionsInit(WPARAM wParam, LPARAM lParam) +{ + OPTIONSDIALOGPAGE odp = {0}; + odp.cbSize = sizeof(odp); + odp.hInstance = g_hInstance; + odp.ptszTitle = m_tszUserName; + odp.dwInitParam = LPARAM(this); + odp.flags = ODPF_BOLDGROUPS | ODPF_TCHAR | ODPF_DONTTRANSLATE; + + odp.position = 271828; + odp.ptszGroup = LPGENT("Network"); + odp.ptszTab = LPGENT("Account"); + odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPTIONS); + odp.pfnDlgProc = SkypeMainOptionsProc; + ::Options_AddPage(wParam, &odp); + + return 0; +} + INT_PTR CALLBACK CSkypeProto::SkypePasswordProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) { CSkypeProto* ppro = (CSkypeProto*)::GetWindowLongPtr(hwndDlg, GWLP_USERDATA); @@ -216,34 +227,6 @@ INT_PTR CALLBACK CSkypeProto::SkypePasswordProc(HWND hwndDlg, UINT msg, WPARAM w return FALSE; } -INT_PTR __cdecl CSkypeProto::OnAccountManagerInit(WPARAM wParam, LPARAM lParam) -{ - return (int)CreateDialogParam( - g_hInstance, - MAKEINTRESOURCE(IDD_SKYPEACCOUNT), - (HWND)lParam, - &CSkypeProto::SkypeAccountProc, (LPARAM)this); -} - -int __cdecl CSkypeProto::OnOptionsInit(WPARAM wParam, LPARAM lParam) -{ - OPTIONSDIALOGPAGE odp = {0}; - odp.cbSize = sizeof(odp); - odp.hInstance = g_hInstance; - odp.ptszTitle = m_tszUserName; - odp.dwInitParam = LPARAM(this); - odp.flags = ODPF_BOLDGROUPS | ODPF_TCHAR | ODPF_DONTTRANSLATE; - - odp.position = 271828; - odp.ptszGroup = LPGENT("Network"); - odp.ptszTab = LPGENT("Account"); - odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPTIONS); - odp.pfnDlgProc = SkypeOptionsProc; - Options_AddPage(wParam, &odp); - - return 0; -} - INT_PTR CALLBACK CSkypeProto::SkypeDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) { switch (msg) { @@ -562,11 +545,21 @@ INT_PTR CALLBACK CSkypeProto::InviteToChatProc(HWND hwndDlg, UINT msg, WPARAM wP { for (uint i = 0; i < invitedContacts.size(); i++) { - param->ppro->AddChatContact(chatID, invitedContacts[i]); + CContact::Ref contact; + CContact::AVAILABILITY status; + param->ppro->skype->GetContact(invitedContacts[i], contact); + contact->GetPropAvailability(status); + + //todo: fix rank + param->ppro->AddChatContact( + chatID, + invitedContacts[i], + CParticipant::GetRankName(CParticipant::SPEAKER), + status); } CConversation::Ref conversation; - g_skype->GetConversationByIdentity(chatID, conversation); + param->ppro->skype->GetConversationByIdentity(chatID, conversation); conversation->AddConsumers(invitedContacts); } else @@ -575,7 +568,17 @@ INT_PTR CALLBACK CSkypeProto::InviteToChatProc(HWND hwndDlg, UINT msg, WPARAM wP for (uint i = 0; i < invitedContacts.size(); i++) { - param->ppro->AddChatContact(chatID, invitedContacts[i]); + CContact::Ref contact; + CContact::AVAILABILITY status; + param->ppro->skype->GetContact(invitedContacts[i], contact); + contact->GetPropAvailability(status); + + //todo: fix rank + param->ppro->AddChatContact( + chatID, + invitedContacts[i], + CParticipant::GetRankName(CParticipant::SPEAKER), + status); } } } diff --git a/protocols/Skype/src/skype_events.cpp b/protocols/Skype/src/skype_events.cpp index 7ae3583906..348b8ef463 100644 --- a/protocols/Skype/src/skype_events.cpp +++ b/protocols/Skype/src/skype_events.cpp @@ -2,9 +2,13 @@ int CSkypeProto::OnModulesLoaded(WPARAM, LPARAM) { - this->InitChat(); + this->InitSkype(); - this->HookEvent(ME_OPT_INITIALISE, &CSkypeProto::OnOptionsInit); + //this->InitChat(); + this->InitNetLib(); + this->InitCustomFolders(); + + this->HookEvent(ME_OPT_INITIALISE, &CSkypeProto::OnOptionsInit); this->HookEvent(ME_USERINFO_INITIALISE, &CSkypeProto::OnUserInfoInit); this->login = ::DBGetString(NULL, this->m_szModuleName, "sid"); @@ -17,6 +21,10 @@ int CSkypeProto::OnPreShutdown(WPARAM, LPARAM) { this->SetStatus(ID_STATUS_OFFLINE); + this->UninitNetLib(); + + this->UninitSkype(); + return 0; } @@ -31,7 +39,7 @@ int CSkypeProto::OnContactDeleted(WPARAM wParam, LPARAM lParam) this->LeaveChat(chatID); CConversation::Ref conversation; - g_skype->GetConversationByIdentity(chatID, conversation); + this->skype->GetConversationByIdentity(chatID, conversation); conversation->RetireFrom(); conversation->Delete(); } @@ -62,16 +70,16 @@ void CSkypeProto::OnMessageSended(CConversation::Ref conversation, CMessage::Ref CParticipant::Refs participants; conversation->GetParticipants(participants, CConversation::OTHER_CONSUMERS); - for (uint i = 0; i < participants.size(); i ++) + //for (uint i = 0; i < participants.size(); i ++) { - participants[i]->GetPropIdentity(data); + participants[0]->GetPropIdentity(data); char *contactSid = ::mir_strdup(data); //todo: get nickname this->RaiseMessageSendedEvent( timestamp, contactSid, contactSid, - text); + CSkypeProto::RemoveHtml(text)); } } else @@ -79,7 +87,18 @@ void CSkypeProto::OnMessageSended(CConversation::Ref conversation, CMessage::Ref conversation->GetPropIdentity(data); char *cid = ::mir_strdup(data); - this->SendChatMessage(cid, sid, ::mir_utf8decodeA(text)); + //this->SendChatMessage(cid, sid, ::mir_utf8decodeA(text)); + + char *nick = (char *)::DBGetString(NULL, this->m_szModuleName, "Nick"); + if (::stricmp(nick, "") == 0) + { + nick = sid; + } + + this->SendChatMessage( + cid, + nick, + CSkypeProto::RemoveHtml(::mir_utf8decodeA(text))); ::mir_free(cid); } @@ -116,7 +135,7 @@ void CSkypeProto::OnMessageReceived(CConversation::Ref conversation, CMessage::R conversation->GetPropIdentity(data); char *cid = ::mir_strdup(data); - this->SendChatMessage(cid, sid, ::mir_utf8decodeA(text)); + this->SendChatMessage(cid, sid, CSkypeProto::RemoveHtml(::mir_utf8decodeA(text))); ::mir_free(cid); } @@ -141,7 +160,7 @@ void CSkypeProto::OnMessage(CConversation::Ref conversation, CMessage::Ref messa message->GetPropConsumptionStatus(status); // it's old message (hystory sync) - if (status == CMessage::CONSUMED) return; + if (status == CMessage::CONSUMED && sendingStatus != CMessage::SENT) return; switch (messageType) { @@ -178,7 +197,20 @@ void CSkypeProto::OnMessage(CConversation::Ref conversation, CMessage::Ref messa for (uint i = 0; i < participants.size(); i++) { participants[i]->GetPropIdentity(data); - this->AddChatContact(cid, data); + + CContact::Ref contact; + CContact::AVAILABILITY status; + this->skype->GetContact(data, contact); + contact->GetPropAvailability(status); + + CParticipant::RANK rank; + participants[i]->GetPropRank(rank); + + this->AddChatContact( + cid, + data, + CParticipant::GetRankName(rank), + status); } } @@ -192,7 +224,19 @@ void CSkypeProto::OnMessage(CConversation::Ref conversation, CMessage::Ref messa { char *sid = needToAdd[i]; if (::stricmp(sid, this->login) != 0 && !alreadyInChat.contains(sid)) - this->AddChatContact(cid, sid); + { + CContact::Ref contact; + CContact::AVAILABILITY status; + this->skype->GetContact(sid, contact); + contact->GetPropAvailability(status); + + //todo: fix rank + this->AddChatContact( + cid, + sid, + CParticipant::GetRankName(CParticipant::WRITER), + status); + } } } } diff --git a/protocols/Skype/src/skype_instances.cpp b/protocols/Skype/src/skype_instances.cpp index 67b34e3f95..a34d99a192 100644 --- a/protocols/Skype/src/skype_instances.cpp +++ b/protocols/Skype/src/skype_instances.cpp @@ -9,8 +9,13 @@ LIST CSkypeProto::instanceList(1, CSkypeProto::CompareProtos); CSkypeProto* CSkypeProto::InitSkypeProto(const char* protoName, const wchar_t* userName) { - if (CSkypeProto::instanceList.getCount() > 0) { - MessageBox(NULL, TranslateT("SkypeKit will only permit you to login to one account at a time. Adding multiple instances of SkypeKit is prohibited in the licence agreement and standard distribution terms."), _T(MODULE), MB_OK | MB_ICONWARNING); + if (CSkypeProto::instanceList.getCount() > 0) + { + CSkypeProto::ShowNotification( + ::TranslateT("SkypeKit will only permit you to login to one account at a time. \ + Adding multiple instances of SkypeKit is prohibited in the licence \ + agreement and standard distribution terms."), + MB_ICONWARNING); return NULL; } CSkypeProto *ppro = new CSkypeProto(protoName, userName); diff --git a/protocols/Skype/src/skype_menus.cpp b/protocols/Skype/src/skype_menus.cpp index 9f529c993a..5ab78ef5e2 100644 --- a/protocols/Skype/src/skype_menus.cpp +++ b/protocols/Skype/src/skype_menus.cpp @@ -77,7 +77,7 @@ int CSkypeProto::GrantAuth(WPARAM wParam, LPARAM lParam) CContact::Ref contact; HANDLE hContact = (HANDLE)wParam; SEString sid(::mir_u2a(this->GetSettingString(hContact, "sid"))); - if (g_skype->GetContact(sid, contact)) + if (this->skype->GetContact(sid, contact)) { if (contact->SetBuddyStatus(true)) { @@ -94,7 +94,7 @@ int CSkypeProto::RevokeAuth(WPARAM wParam, LPARAM lParam) CContact::Ref contact; HANDLE hContact = (HANDLE)wParam; SEString sid(::mir_u2a(this->GetSettingString(hContact, "sid"))); - if (g_skype->GetContact(sid, contact)) + if (this->skype->GetContact(sid, contact)) { if (contact->SetBuddyStatus(false)) { @@ -192,7 +192,7 @@ void CSkypeProto::OnInitStatusMenu() mi.position = -1999901006; mi.hParentMenu = HGENMENU_ROOT; mi.flags = CMIF_ICONFROMICOLIB | CMIF_ROOTPOPUP | CMIF_TCHAR | CMIF_KEEPUNTRANSLATED; - mi.icolibItem = CSkypeProto::GetIconHandle("main"); + mi.icolibItem = CSkypeProto::GetIconHandle("Skype_main"); hJabberRoot = m_hMenuRoot = ::Menu_AddProtoMenuItem(&mi); } else { diff --git a/protocols/Skype/src/skype_netlib.cpp b/protocols/Skype/src/skype_netlib.cpp index ece518f351..d86845fc45 100644 --- a/protocols/Skype/src/skype_netlib.cpp +++ b/protocols/Skype/src/skype_netlib.cpp @@ -1,34 +1,94 @@ #include "skype_proto.h" +#include "base64/base64.h" void CSkypeProto::InitNetLib() { wchar_t name[128]; - mir_sntprintf(name, SIZEOF(name), TranslateT("%s connection"), this->m_tszUserName); + ::mir_sntprintf(name, SIZEOF(name), ::TranslateT("%s connection"), this->m_tszUserName); NETLIBUSER nlu = {0}; nlu.cbSize = sizeof(nlu); nlu.flags = NUF_OUTGOING | NUF_INCOMING | NUF_HTTPCONNS | NUF_UNICODE; nlu.ptszDescriptiveName = name; nlu.szSettingsModule = this->m_szModuleName; - this->hNetlibUser = (HANDLE)CallService(MS_NETLIB_REGISTERUSER, 0, (LPARAM)&nlu); + this->hNetLibUser = (HANDLE)::CallService(MS_NETLIB_REGISTERUSER, 0, (LPARAM)&nlu); - this->Log("Setting protocol/module name to '%s/%s'", m_szProtoName, m_szModuleName); + this->Log( + L"Setting protocol/module name to '%s/%s'", + ::mir_a2u(this->m_szProtoName), + ::mir_a2u(this->m_szModuleName)); } void CSkypeProto::UninitNetLib() { - Netlib_CloseHandle(this->hNetlibUser); - this->hNetlibUser = NULL; + ::Netlib_CloseHandle(this->hNetLibUser); + this->hNetLibUser = NULL; } -void CSkypeProto::Log(const char* fmt, ...) +void CSkypeProto::InitProxy() +{ + if (this->hNetLibUser) + { + NETLIBUSERSETTINGS nlus = { sizeof(NETLIBUSERSETTINGS) }; + ::CallService(MS_NETLIB_GETUSERSETTINGS, (WPARAM)this->hNetLibUser, (LPARAM)&nlus); + + if (nlus.useProxy) + { + char address[MAX_PATH]; + ::mir_snprintf(address, MAX_PATH, "%s:%d", nlus.szProxyServer, nlus.wProxyPort); + + switch (nlus.proxyType) + { + case PROXYTYPE_HTTP: + case PROXYTYPE_HTTPS: + this->skype->SetInt(SETUPKEY_HTTPS_PROXY_ENABLE, 1); + this->skype->SetInt(SETUPKEY_SOCKS_PROXY_ENABLE, 0); + this->skype->SetStr(SETUPKEY_HTTPS_PROXY_ADDR, address); + if (nlus.useProxyAuth) + { + char encodedPass[MAX_PATH]; + Base64::Encode(nlus.szProxyAuthPassword, encodedPass, MAX_PATH); + + this->skype->SetStr(SETUPKEY_HTTPS_PROXY_USER, nlus.szProxyAuthUser); + this->skype->SetStr(SETUPKEY_HTTPS_PROXY_PWD, encodedPass); + } + break; + + case PROXYTYPE_SOCKS4: + case PROXYTYPE_SOCKS5: + this->skype->SetInt(SETUPKEY_HTTPS_PROXY_ENABLE, 0); + this->skype->SetInt(SETUPKEY_SOCKS_PROXY_ENABLE, 1); + this->skype->SetStr(SETUPKEY_SOCKS_PROXY_ADDR, address); + if (nlus.useProxyAuth) + { + this->skype->SetStr(SETUPKEY_SOCKS_PROXY_USER, nlus.szProxyAuthUser); + this->skype->SetStr(SETUPKEY_SOCKS_PROXY_PWD, nlus.szProxyAuthPassword); + } + break; + + default: + this->skype->Delete(SETUPKEY_HTTPS_PROXY_ENABLE); + this->skype->Delete(SETUPKEY_HTTPS_PROXY_ADDR); + this->skype->Delete(SETUPKEY_HTTPS_PROXY_USER); + this->skype->Delete(SETUPKEY_HTTPS_PROXY_PWD); + this->skype->Delete(SETUPKEY_SOCKS_PROXY_ENABLE); + this->skype->Delete(SETUPKEY_SOCKS_PROXY_ADDR); + this->skype->Delete(SETUPKEY_SOCKS_PROXY_USER); + this->skype->Delete(SETUPKEY_SOCKS_PROXY_PWD); + break; + } + } + } +} + +void CSkypeProto::Log(const wchar_t* fmt, ...) { va_list va; - char msg[1024]; + wchar_t msg[1024]; va_start(va, fmt); - mir_vsnprintf(msg, sizeof(msg), fmt, va); + ::mir_vsntprintf(msg, sizeof(msg), fmt, va); va_end(va); - CallService(MS_NETLIB_LOG, (WPARAM)this->hNetlibUser, (LPARAM)msg); + ::CallService(MS_NETLIB_LOGW, (WPARAM)this->hNetLibUser, (LPARAM)msg); } \ No newline at end of file diff --git a/protocols/Skype/src/skype_profile.cpp b/protocols/Skype/src/skype_profile.cpp index d9df4724c4..081f8b22dc 100644 --- a/protocols/Skype/src/skype_profile.cpp +++ b/protocols/Skype/src/skype_profile.cpp @@ -1,13 +1,13 @@ #include "skype_proto.h" -void CSkypeProto::UpdateOwnAvatar() +void CSkypeProto::UpdateProfileAvatar(SEObject *obj, HANDLE hContact) { - uint newTS = 0; - this->account->GetPropAvatarTimestamp(newTS); - DWORD oldTS = this->GetSettingDword("AvatarTS"); - wchar_t *path = this->GetContactAvatarFilePath(NULL); - SEBinary data; - this->account->GetPropAvatarImage(data); + uint newTS = obj->GetUintProp(/* *::P_AVATAR_TIMESTAMP */ 182); + DWORD oldTS = this->GetSettingDword(hContact, "AvatarTS"); + + wchar_t *path = this->GetContactAvatarFilePath(hContact); + SEBinary data = obj->GetBinProp(/* *::P_AVATAR_IMAGE */ 37); + if ((newTS > oldTS) || (!newTS && data.size() > 0 && _waccess(path, 0) == -1) || (newTS && _waccess(path, 0) == -1)) //hack for avatars without timestamp { FILE* fp = _wfopen(path, L"wb"); @@ -21,28 +21,40 @@ void CSkypeProto::UpdateOwnAvatar() PROTO_AVATAR_INFORMATIONW pai = {0}; pai.cbSize = sizeof(pai); pai.format = PA_FORMAT_JPEG; - pai.hContact = NULL; + pai.hContact = hContact; wcscpy(pai.filename, path); - this->SendBroadcast(ACKTYPE_AVATAR, ACKRESULT_SUCCESS, (HANDLE)&pai, 0); + this->SendBroadcast(hContact, ACKTYPE_AVATAR, ACKRESULT_SUCCESS, (HANDLE)&pai, 0); } } + delete path; } -void CSkypeProto::UpdateOwnBirthday() +void CSkypeProto::UpdateProfileAboutText(SEObject *obj, HANDLE hContact) +{ + wchar_t* aboutText = ::mir_utf8decodeW(obj->GetStrProp(/* *::P_ABOUT */ 18)); + if ( !::wcslen(aboutText)) + this->DeleteSetting(hContact, "About"); + else + this->SetSettingString(hContact, "About", aboutText); + ::mir_free(aboutText); +} + +void CSkypeProto::UpdateProfileBirthday(SEObject *obj, HANDLE hContact) { - uint data; - this->account->GetPropBirthday(data); - TCHAR date[9]; + uint data = obj->GetUintProp(/* *::P_BIRTHDAY */ 7); if (data > 0) { + TCHAR date[9]; _itot_s(data, date, 10); + INT day, month, year; _stscanf(date, _T("%04d%02d%02d"), &year, &month, &day); - this->SetSettingByte("BirthDay", day); - this->SetSettingByte("BirthMonth", month); - this->SetSettingWord("BirthYear", year); + + this->SetSettingByte(hContact, "BirthDay", day); + this->SetSettingByte(hContact, "BirthMonth", month); + this->SetSettingWord(hContact, "BirthYear", year); SYSTEMTIME sToday = {0}; GetLocalTime(&sToday); @@ -50,203 +62,191 @@ void CSkypeProto::UpdateOwnBirthday() if (sToday.wMonth < month || (sToday.wMonth == month && sToday.wDay < day)) nAge--; if (nAge) - this->SetSettingWord("Age", ( WORD )nAge ); + this->SetSettingWord( hContact, "Age", ( WORD )nAge ); } else { - this->DeleteSetting("BirthDay"); - this->DeleteSetting("BirthMonth"); - this->DeleteSetting("BirthYear"); - this->DeleteSetting("Age"); + this->DeleteSetting(hContact, "BirthDay"); + this->DeleteSetting(hContact, "BirthMonth"); + this->DeleteSetting(hContact, "BirthYear"); + this->DeleteSetting(hContact, "Age"); } } -void CSkypeProto::UpdateOwnCity() +void CSkypeProto::UpdateProfileCity(SEObject *obj, HANDLE hContact) { - SEString data; - this->account->GetPropCity(data); - wchar_t* city = ::mir_utf8decodeW((const char*)data); - if (wcscmp(city, L"") == 0) - this->DeleteSetting("City"); + wchar_t* city = ::mir_utf8decodeW(obj->GetStrProp(/* *::P_CITY */ 12)); + if ( !::wcslen(city)) + this->DeleteSetting(hContact, "City"); else - this->SetSettingString("City", city); + this->SetSettingString(hContact, "City", city); ::mir_free(city); } -void CSkypeProto::UpdateOwnCountry() +void CSkypeProto::UpdateProfileCountry(SEObject *obj, HANDLE hContact) { - // country (en, ru, etc) - SEString data; char* country; - this->account->GetPropCountry(data); - char* isocode = ::mir_utf8decodeA((const char*)data); - if (strcmp(isocode, "") == 0) + char* isocode = ::mir_strdup(obj->GetStrProp(/* *::P_COUNTRY */ 10)); + if ( !::strlen(isocode)) { country = (char*)CallService(MS_UTILS_GETCOUNTRYBYNUMBER, 0xFFFF, 0); - this->SetSettingString("Country", _A2T(country)); + this->SetSettingString(hContact, "Country", ::mir_a2t(country)); } else { country = (char*)CallService(MS_UTILS_GETCOUNTRYBYISOCODE, (WPARAM)isocode, 0); - this->SetSettingString("Country", _A2T(country)); + this->SetSettingString(hContact, "Country", ::mir_a2t(country)); } ::mir_free(isocode); } -void CSkypeProto::UpdateOwnEmails() +void CSkypeProto::UpdateProfileEmails(SEObject *obj, HANDLE hContact) { - SEString data; - this->account->GetPropEmails(data); - wchar_t* emails = ::mir_utf8decodeW((const char*)data); + wchar_t* emails = ::mir_a2u(obj->GetStrProp(/* *::P_EMAILS */ 16)); if (wcscmp(emails, L"") == 0) { - this->DeleteSetting("e-mail0"); - this->DeleteSetting("e-mail1"); - this->DeleteSetting("e-mail2"); + this->DeleteSetting(hContact, "e-mail0"); + this->DeleteSetting(hContact, "e-mail1"); + this->DeleteSetting(hContact, "e-mail2"); } else { wchar_t* p = wcstok(emails, L" "); if (p == NULL) { - this->SetSettingString("e-mail0", emails); + this->SetSettingString(hContact, "e-mail0", emails); } else { - this->SetSettingString("e-mail0", p); + this->SetSettingString(hContact, "e-mail0", p); p = wcstok(NULL, L" "); - if (p) this->SetSettingString("e-mail1", p); + if (p) this->SetSettingString(hContact, "e-mail1", p); p = wcstok(NULL, L" "); - if (p) this->SetSettingString("e-mail2", p); + if (p) this->SetSettingString(hContact, "e-mail2", p); } + ::mir_free(p); } ::mir_free(emails); } -void CSkypeProto::UpdateOwnGender() +void CSkypeProto::UpdateProfileFullName(SEObject *obj, HANDLE hContact) { - uint data; - this->account->GetPropGender(data); + wchar_t* fullname = ::mir_utf8decodeW(obj->GetStrProp(/* *::P_FULLNAME */ 5)); + if ( !::wcslen(fullname)) + this->DeleteSetting(hContact, "LastName"); + else + this->SetSettingString(hContact, "LastName", fullname); + ::mir_free(fullname); +} + +void CSkypeProto::UpdateProfileGender(SEObject *obj, HANDLE hContact) +{ + uint data = obj->GetUintProp(/* *::P_GENDER */ 8); if (data) - this->SetSettingByte("Gender", (BYTE)(data == 1 ? 'M' : 'F')); + this->SetSettingByte(hContact, "Gender", (BYTE)(data == 1 ? 'M' : 'F')); else - this->DeleteSetting("Gender"); + this->DeleteSetting(hContact, "Gender"); } -void CSkypeProto::UpdateOwnHomepage() +void CSkypeProto::UpdateProfileHomepage(SEObject *obj, HANDLE hContact) { - SEString data; - this->account->GetPropHomepage(data); - wchar_t* homepage = ::mir_utf8decodeW((const char*)data); - if (wcscmp(homepage, L"") == 0) - this->DeleteSetting("Homepage"); + wchar_t* homepage = ::mir_a2u(obj->GetStrProp(/* *::P_HOMEPAGE */ 17)); + if (::wcscmp(homepage, L"") == 0) + this->DeleteSetting(hContact, "Homepage"); else - this->SetSettingString("Homepage", homepage); - ::mir_free(homepage); + this->SetSettingString(hContact, "Homepage", homepage); + ::mir_free(homepage); } -void CSkypeProto::UpdateOwnLanguages() +void CSkypeProto::UpdateProfileLanguages(SEObject *obj, HANDLE hContact) { - // languages (en, ru, etc), space searated - SEString data; - this->account->GetPropLanguages(data); - char* isocode = ::mir_utf8decodeA((const char*)data); - if (strcmp(isocode, "") == 0) + wchar_t *isocodes = ::mir_utf8decodeW(obj->GetStrProp(/* *::P_LANGUAGES */ 9)); + if ( !::wcslen(isocodes)) { - this->DeleteSetting("Language1"); + this->DeleteSetting(hContact, "Language1"); + this->DeleteSetting(hContact, "Language2"); + this->DeleteSetting(hContact, "Language3"); } else { - for (int i = 0; i < SIZEOF(CSkypeProto::languages); i++) - if ( lstrcmpiA((char*)isocode, CSkypeProto::languages[i].ISOcode) == 0) + wchar_t* p = wcstok(isocodes, L" "); + if (p == NULL) + { + this->SetSettingString(hContact, "e-Language1", isocodes); + } + else + { + this->SetSettingString(hContact, "e-Language1", p); + p = wcstok(NULL, L" "); + if (p) this->SetSettingString(hContact, "e-Language2", p); + p = wcstok(NULL, L" "); + if (p) this->SetSettingString(hContact, "e-Language3", p); + } + + // todo: fix + /*for (int i = 0; i < SIZEOF(CSkypeProto::languages); i++) + if ( ::stricmp((char*)isocode, CSkypeProto::languages[i].ISOcode) == 0) { - this->SetSettingString("Language1", ::mir_a2u(CSkypeProto::languages[i].szName)); + this->SetSettingString(hContact, "Language1", ::mir_a2u(CSkypeProto::languages[i].szName)); break; - } + }*/ } - ::mir_free(isocode); + ::mir_free(isocodes); } -void CSkypeProto::UpdateOwnMobilePhone() +void CSkypeProto::UpdateProfileMobilePhone(SEObject *obj, HANDLE hContact) { - SEString data; - this->account->GetPropPhoneMobile(data); - wchar_t* phone = ::mir_utf8decodeW((const char*)data); - if (wcscmp(phone, L"") == 0) - this->DeleteSetting("Cellular"); + wchar_t* phone = ::mir_a2u(obj->GetStrProp(/* *::P_PHONE_MOBILE */ 15)); + if ( !::wcslen(phone)) + this->DeleteSetting(hContact, "Cellular"); else - this->SetSettingString("Cellular", phone); + this->SetSettingString(hContact, "Cellular", phone); ::mir_free(phone); } -void CSkypeProto::UpdateOwnNickName() -{ - SEString data; - this->account->GetPropFullname(data); - wchar_t* nick = ::mir_utf8decodeW((const char*)data); - this->SetSettingString("Nick", nick); - ::mir_free(nick); -} - -void CSkypeProto::UpdateOwnPhone() +void CSkypeProto::UpdateProfilePhone(SEObject *obj, HANDLE hContact) { - SEString data; - this->account->GetPropPhoneHome(data); - wchar_t* phone = ::mir_utf8decodeW((const char*)data); - if (wcscmp(phone, L"") == 0) - this->DeleteSetting("Phone"); + wchar_t* phone = ::mir_a2u(obj->GetStrProp(/* *::P_PHONE_HOME */ 13)); + if ( !::wcslen(phone)) + this->DeleteSetting(hContact, "Phone"); else - this->SetSettingString("Phone", phone); + this->SetSettingString(hContact, "Phone", phone); ::mir_free(phone); } -void CSkypeProto::UpdateOwnOfficePhone() +void CSkypeProto::UpdateProfileOfficePhone(SEObject *obj, HANDLE hContact) { - SEString data; - this->account->GetPropPhoneOffice(data); - wchar_t* phone = ::mir_utf8decodeW((const char*)data); - if (wcscmp(phone, L"") == 0) - this->DeleteSetting("CompanyPhone"); + wchar_t* phone = ::mir_a2u(obj->GetStrProp(/* *::P_PHONE_OFFICE */ 14)); + if ( !::wcslen(phone)) + this->DeleteSetting(hContact, "CompanyPhone"); else - this->SetSettingString("CompanyPhone", phone); + this->SetSettingString(hContact, "CompanyPhone", phone); ::mir_free(phone); } -void CSkypeProto::UpdateOwnState() +void CSkypeProto::UpdateProfileState(SEObject *obj, HANDLE hContact) { - SEString data; - this->account->GetPropProvince(data); - wchar_t* state = ::mir_utf8decodeW((const char*)data); - if (wcscmp(state, L"") == 0) - this->DeleteSetting("State"); + wchar_t* state = ::mir_utf8decodeW(obj->GetStrProp(/* *::P_PROVINCE */ 11)); + if ( !::wcslen(state)) + this->DeleteSetting(hContact, "State"); else - this->SetSettingString("State", state); + this->SetSettingString(hContact, "State", state); ::mir_free(state); } -void CSkypeProto::UpdateOwnStatusMessage() +void CSkypeProto::UpdateProfileStatusMessage(SEObject *obj, HANDLE hContact) { - uint newTS = 0; - this->account->GetPropMoodTimestamp(newTS); - DWORD oldTS = this->GetSettingDword("XStatusTS"); - if (newTS > oldTS) - { - SEString data; - this->account->GetPropMoodText(data); - wchar_t* status = ::mir_utf8decodeW((const char*)data); - if (wcscmp(status, L"") == 0) - this->DeleteSetting("XStatusMsg"); - else - this->SetSettingString("XStatusMsg", status); - ::mir_free(status); - this->SetSettingDword("XStatusTS", newTS); - } + wchar_t* statusMessage = ::mir_utf8decodeW(obj->GetStrProp(/* *::P_MOOD_TEXT */ 26)); + if ( !::wcslen(statusMessage)) + this->DeleteSetting(hContact, "XStatusMsg"); + else + this->SetSettingString(hContact, "XStatusMsg", statusMessage); + ::mir_free(statusMessage); } -void CSkypeProto::UpdateOwnTimezone() +void CSkypeProto::UpdateProfileTimezone(SEObject *obj, HANDLE hContact) { - uint data; - this->account->GetPropTimezone(data); + uint data = obj->GetUintProp(/* *::P_TIMEZONE */ 27); if (data > 0) { uint diffmin = (data - 24*3600) / 60; @@ -259,7 +259,7 @@ void CSkypeProto::UpdateOwnTimezone() uint mins = ::abs((int)(diffmin % 60)); wchar_t timeshift[7]; ::mir_sntprintf(timeshift, SIZEOF(timeshift), _T("%s%d:%02d"), sign, hours, mins); - + wchar_t *szMin = wcschr(timeshift, ':'); int nTz = ::_wtoi(timeshift) * -2; nTz += (nTz < 0 ? -1 : 1) * (szMin ? _ttoi( szMin + 1 ) / 30 : 0); @@ -268,112 +268,45 @@ void CSkypeProto::UpdateOwnTimezone() if (::GetTimeZoneInformation(&tzinfo) == TIME_ZONE_ID_DAYLIGHT) nTz -= tzinfo.DaylightBias / 30; - this->SetSettingByte("Timezone", (signed char)nTz); + this->SetSettingByte(hContact, "Timezone", (signed char)nTz); } else - this->DeleteSetting("TimeZone"); + this->DeleteSetting(hContact, "TimeZone"); } -void CSkypeProto::UpdateOwnAbout() +void CSkypeProto::UpdateProfile(SEObject *obj, HANDLE hContact) { - SEString data; - this->account->GetPropAbout(data); - wchar_t* about = ::mir_utf8decodeW((const char*)data); - if (wcscmp(about, L"") == 0) - this->DeleteSetting("About"); - else - this->SetSettingString("About", about); - ::mir_free(about); -} -void CSkypeProto::UpdateOwnProfile() -{ - uint newTS = 0; - this->account->GetPropProfileTimestamp(newTS); - DWORD oldTS = this->GetSettingDword("ProfileTS"); - if (newTS > oldTS) + uint newTS = obj->GetUintProp(/* *::P_PROFILE_TIMESTAMP */ 19); + if (newTS > this->GetSettingDword("ProfileTS")) { - this->UpdateOwnAvatar(); - this->UpdateOwnBirthday(); - this->UpdateOwnCity(); - this->UpdateOwnCountry(); - this->UpdateOwnEmails(); - this->UpdateOwnGender(); - this->UpdateOwnHomepage(); - this->UpdateOwnLanguages(); - this->UpdateOwnMobilePhone(); - this->UpdateOwnNickName(); - this->UpdateOwnPhone(); - this->UpdateOwnOfficePhone(); - this->UpdateOwnState(); - this->UpdateOwnStatusMessage(); - this->UpdateOwnTimezone(); - this->UpdateOwnAbout(); + this->UpdateProfileAboutText(obj, hContact); + this->UpdateProfileBirthday(obj, hContact); + this->UpdateProfileCity(obj, hContact); + this->UpdateProfileCountry(obj, hContact); + this->UpdateProfileEmails(obj, hContact); + this->UpdateProfileFullName(obj, hContact); + this->UpdateProfileGender(obj, hContact); + this->UpdateProfileHomepage(obj, hContact); + this->UpdateProfileLanguages(obj, hContact); + this->UpdateProfileMobilePhone(obj, hContact); + this->UpdateProfilePhone(obj, hContact); + this->UpdateProfileOfficePhone(obj, hContact); + this->UpdateProfileState(obj, hContact); + this->UpdateProfileTimezone(obj, hContact); - this->SetSettingDword("ProfileTS", newTS); - } -} + if (hContact) + { + this->UpdateContactOnlineSinceTime(obj, hContact); + this->UpdateContactLastEventDate(obj, hContact); -void CSkypeProto::OnProfileChanged(int prop) -{ - switch(prop) - { - case CAccount::P_AVATAR_IMAGE: - case CAccount::P_AVATAR_TIMESTAMP: - this->UpdateOwnAvatar(); - break; - case CAccount::P_BIRTHDAY: - this->UpdateOwnBirthday(); - break; - case CAccount::P_CITY: - this->UpdateOwnCity(); - break; - case CAccount::P_COUNTRY: - this->UpdateOwnCountry(); - break; - case CAccount::P_EMAILS: - this->UpdateOwnEmails(); - break; - case CAccount::P_GENDER: - this->UpdateOwnGender(); - break; - case CAccount::P_HOMEPAGE: - this->UpdateOwnHomepage(); - break; - case CAccount::P_LANGUAGES: - this->UpdateOwnLanguages(); - break; - case CAccount::P_MOOD_TEXT: - case CAccount::P_MOOD_TIMESTAMP: - this->UpdateOwnStatusMessage(); - break; - case CAccount::P_PHONE_HOME: - this->UpdateOwnPhone(); - break; - case CAccount::P_PHONE_MOBILE: - this->UpdateOwnMobilePhone(); - break; - case CAccount::P_PHONE_OFFICE: - this->UpdateOwnOfficePhone(); - break; - case CAccount::P_PROFILE_TIMESTAMP: - this->UpdateOwnProfile(); - break; - case CAccount::P_PROVINCE: - this->UpdateOwnState(); - break; - case CAccount::P_TIMEZONE: - this->UpdateOwnTimezone(); - break; - case CAccount::P_FULLNAME: - this->UpdateOwnNickName(); - break; - case CAccount::P_ABOUT: - this->UpdateOwnAbout(); - break; + this->SetSettingString(hContact, "MirVer", L"Skype"); + } + + this->SetSettingDword("ProfileTS", newTS); } } void __cdecl CSkypeProto::LoadOwnInfo(void*) { - this->UpdateOwnProfile(); + this->UpdateProfile(this->account.fetch()); } \ No newline at end of file diff --git a/protocols/Skype/src/skype_proto.cpp b/protocols/Skype/src/skype_proto.cpp index ac249a8d8b..48a32e32db 100644 --- a/protocols/Skype/src/skype_proto.cpp +++ b/protocols/Skype/src/skype_proto.cpp @@ -4,11 +4,12 @@ CSkypeProto::CSkypeProto(const char* protoName, const TCHAR* userName) { this->m_iVersion = 2; this->m_iStatus = ID_STATUS_OFFLINE; - this->m_tszUserName = mir_tstrdup(userName); - this->m_szModuleName = mir_strdup(protoName); - this->m_szProtoName = mir_strdup(protoName); + + this->m_tszUserName = ::mir_tstrdup(userName); + this->m_szModuleName = ::mir_strdup(protoName); + this->m_szProtoName = ::mir_strdup(protoName); ::strlwr(m_szProtoName); - this->m_szProtoName[0] = ::toupper(m_szProtoName[0]); + this->m_szProtoName[0] = ::toupper(this->m_szProtoName[0]); //this->login = NULL; this->password = NULL; @@ -18,7 +19,7 @@ CSkypeProto::CSkypeProto(const char* protoName, const TCHAR* userName) this->SetAllContactStatus(ID_STATUS_OFFLINE); this->CreateService(PS_CREATEACCMGRUI, &CSkypeProto::OnAccountManagerInit); - // Chat + // Chat API this->CreateService(PS_JOINCHAT, &CSkypeProto::OnJoinChat); this->CreateService(PS_LEAVECHAT, &CSkypeProto::OnLeaveChat); // Avatar API @@ -26,21 +27,11 @@ CSkypeProto::CSkypeProto(const char* protoName, const TCHAR* userName) this->CreateService(PS_GETAVATARCAPS, &CSkypeProto::GetAvatarCaps); this->CreateService(PS_GETMYAVATART, &CSkypeProto::GetMyAvatar); this->CreateService(PS_SETMYAVATART, &CSkypeProto::SetMyAvatar); - - this->InitNetLib(); - this->InitCustomFolders(); - - // - g_skype->SetOnMessageCallback( - (CSkype::OnMessaged)&CSkypeProto::OnMessage, - this); } CSkypeProto::~CSkypeProto() { - this->UninitNetLib(); - - CloseHandle(this->signin_lock); + ::CloseHandle(this->signin_lock); ::mir_free(this->login); ::mir_free(this->password); @@ -133,7 +124,8 @@ int __cdecl CSkypeProto::AuthRequest(HANDLE hContact, const TCHAR* szMessage) { CContact::Ref contact; SEString sid(::mir_u2a(this->GetSettingString(hContact, "sid"))); - if (g_skype->GetContact(sid, contact)) { + if (this->skype->GetContact(sid, contact)) + { contact->SetBuddyStatus(Contact::AUTHORIZED_BY_ME); contact->SendAuthRequest(::mir_utf8encodeW(szMessage)); } @@ -243,7 +235,7 @@ int __cdecl CSkypeProto::SendMsg(HANDLE hContact, int flags, const char* msg) int result = ::InterlockedIncrement((LONG volatile*)&dwCMDNum); CConversation::Ref conversation = CConversation::FindBySid( - g_skype, + this->skype, ::DBGetString(hContact, this->m_szModuleName, "sid")); if (conversation) { @@ -255,8 +247,7 @@ int __cdecl CSkypeProto::SendMsg(HANDLE hContact, int flags, const char* msg) hContact, ACKTYPE_MESSAGE, ACKRESULT_SUCCESS, - (HANDLE)result, - 0); + (HANDLE)result, 0); return result; } @@ -273,9 +264,11 @@ int CSkypeProto::SetStatus(int new_status) int old_status = this->m_iStatus; this->m_iDesiredStatus = new_status; - switch (new_status) { + switch (new_status) + { case ID_STATUS_OFFLINE: - if (this->IsOnline()) { + if (this->IsOnline()) + { this->account->SetAvailability(CContact::OFFLINE); this->account->Logout(true); @@ -289,7 +282,6 @@ int CSkypeProto::SetStatus(int new_status) { this->m_iStatus = ID_STATUS_CONNECTING; if ( !this->SignIn()) return 0; - } else { @@ -320,7 +312,7 @@ int __cdecl CSkypeProto::UserIsTyping( HANDLE hContact, int type ) if (::strcmp(::DBGetString(hContact, this->m_szModuleName, "sid"), this->login) != 0) { CConversation::Ref conversation = CConversation::FindBySid( - g_skype, + this->skype, ::DBGetString(hContact, this->m_szModuleName, "sid")); if (conversation) { @@ -331,7 +323,7 @@ int __cdecl CSkypeProto::UserIsTyping( HANDLE hContact, int type ) return 0; case PROTOTYPE_SELFTYPING_OFF: - conversation->SetMyTextStatusTo(Participant::READING); // mb TEXT_UNKNOWN? + conversation->SetMyTextStatusTo(Participant::READING); //todo: mb TEXT_UNKNOWN? return 0; } } @@ -363,29 +355,25 @@ int __cdecl CSkypeProto::OnEvent(PROTOEVENTTYPE eventType, WPARAM wParam, LPA void __cdecl CSkypeProto::SignInAsync(void*) { - this->SetStatus(this->m_iDesiredStatus); - this->LoadOwnInfo(this); this->LoadContactList(this); } bool CSkypeProto::SignIn(bool isReadPassword) { - if (!this->login || !::lstrcmpA(this->login, "")) + if ( !this->login || !::strlen(this->login)) { this->m_iStatus = ID_STATUS_OFFLINE; this->SendBroadcast(ACKTYPE_LOGIN, ACKRESULT_FAILED, NULL, LOGINERR_BADUSERID); - ::MessageBox( - NULL, - TranslateT("You have not entered a Skype name.\nConfigure this in Options->Network->Skype and try again."), - _T(MODULE), - MB_OK); + this->ShowNotification( + TranslateT("You have not entered a Skype name.\n\ + Configure this in Options->Network->Skype and try again.")); } - else if (g_skype->GetAccount(this->login, this->account)) + else if (this->skype->GetAccount(this->login, this->account)) { if (isReadPassword) this->password = this->GetDecodeSettingString(NULL, SKYPE_SETTINGS_PASSWORD); - if ( !::lstrcmpA(this->password, "")) + if ( !this->password || !::strlen(this->password)) this->RequestPassword(); else { @@ -395,64 +383,11 @@ bool CSkypeProto::SignIn(bool isReadPassword) this); // int port; - g_skype->GetInt(SETUPKEY_PORT, port); - g_skype->SetInt(SETUPKEY_PORT, this->GetSettingWord("Port", port)); - g_skype->SetInt(SETUPKEY_DISABLE_PORT80, (int)!this->GetSettingByte("UseAlternativePorts", 1)); + this->skype->GetInt(SETUPKEY_PORT, port); + this->skype->SetInt(SETUPKEY_PORT, this->GetSettingWord("Port", port)); + this->skype->SetInt(SETUPKEY_DISABLE_PORT80, (int)!this->GetSettingByte("UseAlternativePorts", 1)); // - if (this->hNetlibUser) - { - NETLIBUSERSETTINGS nlus = { sizeof(NETLIBUSERSETTINGS) }; - ::CallService(MS_NETLIB_GETUSERSETTINGS, (WPARAM)this->hNetlibUser, (LPARAM)&nlus); - - if (nlus.useProxy) - { - char address[MAX_PATH]; - ::mir_snprintf(address, MAX_PATH, "%s:%d", nlus.szProxyServer, nlus.wProxyPort); - - switch (nlus.proxyType) - { - case PROXYTYPE_HTTP: - case PROXYTYPE_HTTPS: - g_skype->SetInt(SETUPKEY_HTTPS_PROXY_ENABLE, 1); - g_skype->SetInt(SETUPKEY_SOCKS_PROXY_ENABLE, 0); - g_skype->SetStr(SETUPKEY_HTTPS_PROXY_ADDR, address); - if (nlus.useProxyAuth) - { - g_skype->SetStr(SETUPKEY_HTTPS_PROXY_USER, nlus.szProxyAuthUser); - - char *encodedPass = new char[MAX_PATH]; - - CSkypeProto::Base64Encode(nlus.szProxyAuthPassword, encodedPass, MAX_PATH); - - g_skype->SetStr(SETUPKEY_HTTPS_PROXY_PWD, encodedPass); - } - break; - - case PROXYTYPE_SOCKS4: - case PROXYTYPE_SOCKS5: - g_skype->SetInt(SETUPKEY_HTTPS_PROXY_ENABLE, 0); - g_skype->SetInt(SETUPKEY_SOCKS_PROXY_ENABLE, 1); - g_skype->SetStr(SETUPKEY_SOCKS_PROXY_ADDR, address); - if (nlus.useProxyAuth) - { - g_skype->SetStr(SETUPKEY_SOCKS_PROXY_USER, nlus.szProxyAuthUser); - g_skype->SetStr(SETUPKEY_SOCKS_PROXY_PWD, nlus.szProxyAuthPassword); - } - break; - - default: - g_skype->Delete(SETUPKEY_HTTPS_PROXY_ENABLE); - g_skype->Delete(SETUPKEY_HTTPS_PROXY_ADDR); - g_skype->Delete(SETUPKEY_HTTPS_PROXY_USER); - g_skype->Delete(SETUPKEY_HTTPS_PROXY_PWD); - g_skype->Delete(SETUPKEY_SOCKS_PROXY_ENABLE); - g_skype->Delete(SETUPKEY_SOCKS_PROXY_ADDR); - g_skype->Delete(SETUPKEY_SOCKS_PROXY_USER); - g_skype->Delete(SETUPKEY_SOCKS_PROXY_PWD); - break; - } - } - } + this->InitProxy(); // this->account->LoginWithPassword(this->password, false, false); return true; diff --git a/protocols/Skype/src/skype_proto.h b/protocols/Skype/src/skype_proto.h index cce9a776f2..be81d8fd60 100644 --- a/protocols/Skype/src/skype_proto.h +++ b/protocols/Skype/src/skype_proto.h @@ -2,7 +2,7 @@ #include "skype.h" #include -#include + struct CSkypeProto; @@ -148,7 +148,7 @@ struct InviteChatParam struct CSkypeProto : public PROTO_INTERFACE, public MZeroedObject { public: - CSkypeProto(const char*, const TCHAR*); + CSkypeProto(const char *, const wchar_t *); ~CSkypeProto(); // PROTO_INTERFACE @@ -237,13 +237,13 @@ public: protected: DWORD dwCMDNum; + CSkype *skype; CAccount::Ref account; CContact::Refs contactList; CContactGroup::Ref commonList; CContactGroup::Ref authWaitList; // account - void OnAccountChanged(int prop); char *login; @@ -256,6 +256,7 @@ protected: void __cdecl SignInAsync(void*); static wchar_t* LogoutReasons[]; + static wchar_t* ValidationReasons[]; static LanguagesListEntry languages[223]; // messages @@ -264,6 +265,8 @@ protected: void OnMessageReceived(CConversation::Ref conversation, CMessage::Ref message); // chat + static char* Groups[]; + bool IsChatRoom(HANDLE hContact); HANDLE GetChatRoomByID(const char *cid); HANDLE AddChatRoomByID(const char* cid, const char* name, DWORD flags = 0); @@ -280,9 +283,9 @@ protected: void JoinToChat(const char *cid, bool showWindow = true); void LeaveChat(const char *cid); - void RaiseChatEvent(const char *cid, const char *sid, int evt, const char *message = NULL); + void RaiseChatEvent(const char *cid, const char *sid, int evt, const DWORD itemData = 0, const char *status = NULL, const char *message = NULL); void SendChatMessage(const char *cid, const char *sid, const char *message); - void AddChatContact(const char *cid, const char *sid); + void AddChatContact(const char *cid, const char *sid, const char *group, const WORD status = ID_STATUS_ONLINE); void KickChatContact(const char *cid, const char *sid); void RemoveChatContact(const char *cid, const char *sid); @@ -293,27 +296,11 @@ protected: int __cdecl OnGCEventHook(WPARAM, LPARAM lParam); // contacts - void UpdateContactAboutText(HANDLE hContact, CContact::Ref contact); void UpdateContactAuthState(HANDLE hContact, CContact::Ref contact); void UpdateContactAvatar(HANDLE hContact, CContact::Ref contact); - void UpdateContactBirthday(HANDLE hContact, CContact::Ref contact); - void UpdateContactCity(HANDLE hContact, CContact::Ref contact); - void UpdateContactCountry(HANDLE hContact, CContact::Ref contact); - void UpdateContactEmails(HANDLE hContact, CContact::Ref contact); - void UpdateContactGender(HANDLE hContact, CContact::Ref contact); - void UpdateContactHomepage(HANDLE hContact, CContact::Ref contact); - void UpdateContactLanguages(HANDLE hContact, CContact::Ref contact); - void UpdateContactMobilePhone(HANDLE hContact, CContact::Ref contact); - void UpdateContactPhone(HANDLE hContact, CContact::Ref contact); - void UpdateContactOfficePhone(HANDLE hContact, CContact::Ref contact); - void UpdateContactState(HANDLE hContact, CContact::Ref contact); void UpdateContactStatus(HANDLE hContact, CContact::Ref contact); - void UpdateContactStatusMessage(HANDLE hContact, CContact::Ref contact); - void UpdateContactTimezone(HANDLE hContact, CContact::Ref contact); - void UpdateContactProfile(HANDLE hContact, CContact::Ref contact); - void UpdateContactOnlineSinceTime(HANDLE hContact, CContact::Ref contact); - void UpdateContactLastEventDate(HANDLE hContact, CContact::Ref contact); - void UpdateFullName(HANDLE hContact, CContact::Ref contact); + void UpdateContactOnlineSinceTime(SEObject *obj, HANDLE hContact); + void UpdateContactLastEventDate(SEObject *obj, HANDLE hContact); void OnSearchCompleted(HANDLE hSearch); void OnContactFinded(HANDLE hSearch, CContact::Ref contact); @@ -326,8 +313,6 @@ protected: HANDLE GetContactFromAuthEvent(HANDLE hEvent); HANDLE AddContactBySid(const char* sid, const char* nick, DWORD flags = 0); - int SkypeToMirandaStatus(CContact::AVAILABILITY availability); - CContact::AVAILABILITY MirandaToSkypeStatus(int status); void SetAllContactStatus(int status); void __cdecl LoadContactList(void*); @@ -336,25 +321,24 @@ protected: void __cdecl SearchByEmailAsync(void*); // profile - void UpdateOwnAvatar(); - void UpdateOwnBirthday(); - void UpdateOwnCity(); - void UpdateOwnCountry(); - void UpdateOwnEmails(); - void UpdateOwnGender(); - void UpdateOwnHomepage(); - void UpdateOwnLanguages(); - void UpdateOwnMobilePhone(); - void UpdateOwnNickName(); - void UpdateOwnPhone(); - void UpdateOwnOfficePhone(); - void UpdateOwnState(); - void UpdateOwnStatusMessage(); - void UpdateOwnTimezone(); - void UpdateOwnProfile(); - void UpdateOwnAbout(); - - void OnProfileChanged(int prop); + void UpdateProfileAvatar(SEObject *obj, HANDLE hContact = NULL); + void UpdateProfileAboutText(SEObject *obj, HANDLE hContact = NULL); + void UpdateProfileBirthday(SEObject *obj, HANDLE hContact = NULL); + void UpdateProfileCity(SEObject *obj, HANDLE hContact = NULL); + void UpdateProfileCountry(SEObject *obj, HANDLE hContact = NULL); + void UpdateProfileEmails(SEObject *obj, HANDLE hContact = NULL); + void UpdateProfileFullName(SEObject *obj, HANDLE hContact = NULL); + void UpdateProfileGender(SEObject *obj, HANDLE hContact = NULL); + void UpdateProfileHomepage(SEObject *obj, HANDLE hContact = NULL); + void UpdateProfileLanguages(SEObject *obj, HANDLE hContact = NULL); + void UpdateProfileMobilePhone(SEObject *obj, HANDLE hContact = NULL); + void UpdateProfilePhone(SEObject *obj, HANDLE hContact = NULL); + void UpdateProfileOfficePhone(SEObject *obj, HANDLE hContact = NULL); + void UpdateProfileState(SEObject *obj, HANDLE hContact = NULL); + void UpdateProfileStatusMessage(SEObject *obj, HANDLE hContact = NULL); + void UpdateProfileTimezone(SEObject *obj, HANDLE hContact = NULL); + + void UpdateProfile(SEObject *obj, HANDLE hContact = NULL); void __cdecl LoadOwnInfo(void*); @@ -369,14 +353,18 @@ protected: int SkypeToMirandaLoginError(CAccount::LOGOUTREASON logoutReason); - void ShowNotification(const char *nick, const wchar_t *message, int flags = 0); - - // - static char CharBase64[]; - static ULONG Base64Encode(char *inputString, char *outputBuffer, SIZE_T nMaxLength); + static void ShowNotification(const wchar_t *message, int flags = 0, const char *nick = NULL); static char *RemoveHtml(char *data); + int SkypeToMirandaStatus(CContact::AVAILABILITY availability); + CContact::AVAILABILITY MirandaToSkypeStatus(int status); + + + // runtime + void InitSkype(); + void UninitSkype(); + // instances static LIST instanceList; static int CompareProtos(const CSkypeProto *p1, const CSkypeProto *p2); @@ -395,10 +383,11 @@ protected: HANDLE ForkThreadEx(SkypeThreadFunc, void*, UINT* threadID = NULL); // netlib - HANDLE hNetlibUser; + HANDLE hNetLibUser; void InitNetLib(); void UninitNetLib(); - void Log(const char* fmt, ...); + void InitProxy(); + void Log(const wchar_t *fmt, ...); // services static LIST serviceList; @@ -466,8 +455,7 @@ protected: void DeleteSetting(HANDLE hContact, const char *setting); // dialog procs - static INT_PTR CALLBACK SkypeAccountProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam); - static INT_PTR CALLBACK SkypeOptionsProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam); + static INT_PTR CALLBACK SkypeMainOptionsProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam); static INT_PTR CALLBACK SkypePasswordProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam); static INT_PTR CALLBACK SkypeDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam); static INT_PTR CALLBACK OwnSkypeDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam); diff --git a/protocols/Skype/src/skype_runtime.cpp b/protocols/Skype/src/skype_runtime.cpp new file mode 100644 index 0000000000..ea2f11b835 --- /dev/null +++ b/protocols/Skype/src/skype_runtime.cpp @@ -0,0 +1,18 @@ +#include "skype_proto.h" + +void CSkypeProto::InitSkype() +{ + int port = 8963; + + wchar_t *profileName = ::Utils_ReplaceVarsT(L"%miranda_profilename%"); + wchar_t *dbPath = ::Utils_ReplaceVarsT(L"%miranda_userdata%\\SkypeKit\\"); + + this->skype = CSkype::GetInstance(g_hInstance, profileName, dbPath); + this->skype->SetOnMessageCallback((CSkype::OnMessaged)&CSkypeProto::OnMessage, this); +} + +void CSkypeProto::UninitSkype() +{ + this->skype->stop(); + delete this->skype; +} \ No newline at end of file diff --git a/protocols/Skype/src/skype_services.cpp b/protocols/Skype/src/skype_services.cpp index d5d1eefc52..9fae8d0ee0 100644 --- a/protocols/Skype/src/skype_services.cpp +++ b/protocols/Skype/src/skype_services.cpp @@ -110,7 +110,7 @@ INT_PTR __cdecl CSkypeProto::SetMyAvatar(WPARAM, LPARAM lParam) wchar_t *avatarPath = this->GetContactAvatarFilePath(NULL); if (::wcscmp(path, avatarPath) && !::CopyFile(path, avatarPath, FALSE)) { - this->Log("Failed to copy our avatar to local storage."); + this->Log(L"Failed to copy our avatar to local storage."); return iRet; } // need to validate avatar Skype::ValidateAvatar diff --git a/protocols/Skype/src/skype_subclassing.cpp b/protocols/Skype/src/skype_subclassing.cpp index 6289bc1f98..32a8c95b2c 100644 --- a/protocols/Skype/src/skype_subclassing.cpp +++ b/protocols/Skype/src/skype_subclassing.cpp @@ -1,5 +1,16 @@ #include "skype_subclassing.h" +#include +#include +#include +#include +#include "base64/base64.h" +#include "..\..\..\skypekit\key.h" +extern "C" +{ +#include "aes\aes.h" +} + // CSkype CSkype::CSkype(int num_threads) : Skype(num_threads) @@ -63,6 +74,217 @@ void CSkype::SetOnMessageCallback(OnMessaged callback, CSkypeProto* 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*/107), 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); + + int dwResSize = ::SizeofResource(hInstance, hRes); + char *pData = (char *)::GlobalLock(hResource); + basedecoded = dwResSize; + ::GlobalUnlock(hResource); + + 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() % 1000; + ::CloseHandle(hProcess); + break; + } + } + } + ::CloseHandle(snapshot); + + ::swprintf(param, SIZEOF(param), L"-p -P %d -f %s", port, dbPath); + int startingrt = ::CreateProcess( + fileName, param, + NULL, NULL, FALSE, + CREATE_NEW_CONSOLE, + NULL, NULL, &cif, &pi); + + 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); + + CSkype *skype = new CSkype(); + skype->init(keyPair, "127.0.0.1", port); + 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) @@ -161,6 +383,36 @@ void CContactSearch::SetOnContactFindedCallback(OnContactFinded callback) 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) @@ -175,6 +427,12 @@ void CContact::SetOnContactChangedCallback(OnContactChanged callback, CSkypeProt 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) diff --git a/protocols/Skype/src/skype_subclassing.h b/protocols/Skype/src/skype_subclassing.h index 0993cde7d9..694fce2c56 100644 --- a/protocols/Skype/src/skype_subclassing.h +++ b/protocols/Skype/src/skype_subclassing.h @@ -26,6 +26,8 @@ public: typedef DRefs Refs; CParticipant(unsigned int oid, SERootObject* root); + + static SEString GetRankName(CParticipant::RANK rank); }; class CConversation : public Conversation @@ -58,7 +60,9 @@ public: typedef DRefs Refs; CContact(unsigned int oid, SERootObject* root); - + + /*bool SentAuthRequest(SEString message);*/ + void SetOnContactChangedCallback(OnContactChanged callback, CSkypeProto* proto); private: @@ -152,6 +156,8 @@ public: void SetOnMessageCallback(OnMessaged callback, CSkypeProto* proto); + static CSkype *GetInstance(HINSTANCE hInstance, const wchar_t *profileName, const wchar_t *dbPath); + private: CSkypeProto* proto; OnMessaged onMessagedCallback; @@ -161,4 +167,8 @@ private: const bool & changesInboxTimestamp, const MessageRef & supersedesHistoryMessage, const ConversationRef & conversation); + + static BOOL IsRunAsAdmin(); + static char *LoadKeyPair(HINSTANCE hInstance); + static int StartSkypeRuntime(HINSTANCE hInstance, const wchar_t *profileName, int &port, const wchar_t *dbPath); }; \ No newline at end of file diff --git a/protocols/Skype/src/skype_utils.cpp b/protocols/Skype/src/skype_utils.cpp index 008f295cae..fb27c18c23 100644 --- a/protocols/Skype/src/skype_utils.cpp +++ b/protocols/Skype/src/skype_utils.cpp @@ -31,6 +31,21 @@ wchar_t* CSkypeProto::LogoutReasons[] = LPGENW("") /* ACCESS_TOKEN_RENEWAL_FAILED */ }; +wchar_t* CSkypeProto::ValidationReasons[] = +{ + LPGENW("NOT_VALIDATED") /* NOT_VALIDATED */, + LPGENW("Validation succeeded") /* VALIDATED_OK */, + LPGENW("Password is too short") /* TOO_SHORT */, + LPGENW("The value exceeds max size limit for the given property") /* TOO_LONG */, + LPGENW("Value contains illegal characters") /* CONTAINS_INVALID_CHAR */, + LPGENW("Value contains whitespace") /* CONTAINS_SPACE */, + LPGENW("Password cannot be the same as skypename") /* SAME_AS_USERNAME */, + LPGENW("Value has invalid format") /* INVALID_FORMAT */, + LPGENW("Value contains invalid word") /* CONTAINS_INVALID_WORD */, + LPGENW("Password is too simple") /* TOO_SIMPLE */, + LPGENW("Value starts with an invalid character") /* STARTS_WITH_INVALID_CHAR */, +}; + LanguagesListEntry CSkypeProto::languages[] = { {"Abkhazian", "ab"}, @@ -304,10 +319,11 @@ void CSkypeProto::InitCustomFolders() return; bInitDone = true; - if (ServiceExists(MS_FOLDERS_REGISTER_PATH)) { + if (::ServiceExists(MS_FOLDERS_REGISTER_PATH)) + { TCHAR AvatarsFolder[MAX_PATH]; mir_sntprintf(AvatarsFolder, SIZEOF(AvatarsFolder), _T("%%miranda_avatarcache%%\\") _T(TCHAR_STR_PARAM), this->m_szModuleName); - hAvatarsFolder = FoldersRegisterCustomPathT(this->m_szModuleName, "Avatars", AvatarsFolder); + hAvatarsFolder = ::FoldersRegisterCustomPathT(this->m_szModuleName, "Avatars", AvatarsFolder); } } @@ -452,12 +468,12 @@ int CSkypeProto::SkypeToMirandaLoginError(CAccount::LOGOUTREASON logoutReason) return loginError; } -void CSkypeProto::ShowNotification(const char *nick, const wchar_t *message, int flags) +void CSkypeProto::ShowNotification(const wchar_t *message, int flags, const char *nick) { if (::Miranda_Terminated()) return; - if ( !ServiceExists(MS_POPUP_ADDPOPUPT) || !DBGetContactSettingByte(NULL, "PopUp", "ModuleIsEnabled", 1)) - MessageBoxW(NULL, message, TranslateT("Skype Protocol"), MB_OK); + if ( !::ServiceExists(MS_POPUP_ADDPOPUPT) || !::DBGetContactSettingByte(NULL, "PopUp", "ModuleIsEnabled", 1)) + ::MessageBoxW(NULL, message, TranslateT("Skype Protocol"), MB_OK | flags); else { if ( !nick) nick = ""; @@ -467,7 +483,7 @@ void CSkypeProto::ShowNotification(const char *nick, const wchar_t *message, int ppd.lchContact = NULL; lstrcpyn(ppd.lpwzContactName, ::mir_a2u(nick), MAX_CONTACTNAME); lstrcpyn(ppd.lpwzText, message, MAX_SECONDLINE); - ppd.lchIcon = Skin_GetIcon("Skype_main"); + ppd.lchIcon = ::Skin_GetIcon("Skype_main"); ppd.colorBack = ppd.colorText = 0; ppd.iSeconds = 0; @@ -475,57 +491,6 @@ void CSkypeProto::ShowNotification(const char *nick, const wchar_t *message, int } } -char CSkypeProto::CharBase64[] = -{ - 'A','B','C','D','E','F','G','H','I','J','K','L','M ','N','O','P', - 'Q','R','S','T','U','V','W','X','Y','Z','a','b','c ','d','e','f', - 'g','h','i','j','k','l','m','n','o','p','q','r','s ','t','u','v', - 'w','x','y','z','0','1','2','3','4','5','6','7','8 ','9','+','/' -}; - -ULONG CSkypeProto::Base64Encode(char *inputString, char *outputBuffer, SIZE_T nMaxLength) -{ - int outpos = 0; - char chr[3], enc[4]; - - for (uint i = 0; i < ::strlen(inputString); i += 3) - { - if (outpos + 4 >= nMaxLength) - break; - - chr[0] = inputString[i]; - chr[1] = inputString[i+1]; - chr[2] = inputString[i+2]; - - enc[0] = chr[0] >> 2; - enc[1] = ((chr[0] & 0x03) << 4) | (chr[1] >> 4); - enc[2] = ((chr[1] & 0x0F) << 2) | (chr[2] >> 6); - enc[3] = chr[2] & 0x3F; - - outputBuffer[outpos++] = CSkypeProto::CharBase64[enc[0]]; - outputBuffer[outpos++] = CSkypeProto::CharBase64[enc[1]]; - - if (i + 1 >= ::strlen(inputString)) - { - outputBuffer[outpos++] = '='; - outputBuffer[outpos++] = '='; - } - else if (i + 2 >= ::strlen(inputString)) - { - outputBuffer[outpos++] = CSkypeProto::CharBase64[enc[2]]; - outputBuffer[outpos++] = '='; - } - else - { - outputBuffer[outpos++] = CSkypeProto::CharBase64[enc[2]]; - outputBuffer[outpos++] = CSkypeProto::CharBase64[enc[3]]; - } - } - - outputBuffer[outpos] = 0; - return outpos; -} - char *CSkypeProto::RemoveHtml(char *text) { std::string new_string = ""; @@ -572,4 +537,68 @@ char *CSkypeProto::RemoveHtml(char *text) ::mir_free(text); return ::mir_strdup(new_string.c_str()); +} + +int CSkypeProto::SkypeToMirandaStatus(CContact::AVAILABILITY availability) +{ + int status = ID_STATUS_OFFLINE; + + switch (availability) + { + case CContact::ONLINE: + case CContact::SKYPE_ME: + status = ID_STATUS_ONLINE; + break; + + case CContact::ONLINE_FROM_MOBILE: + case CContact::SKYPE_ME_FROM_MOBILE: + status = ID_STATUS_ONTHEPHONE; + break; + + case CContact::AWAY: + case CContact::AWAY_FROM_MOBILE: + status = ID_STATUS_AWAY; + break; + + case CContact::DO_NOT_DISTURB: + case CContact::DO_NOT_DISTURB_FROM_MOBILE: + status = ID_STATUS_DND; + break; + + case CContact::SKYPEOUT: + status = ID_STATUS_OUTTOLUNCH; + break; + + case CContact::CONNECTING: + status = ID_STATUS_CONNECTING; + break; + } + + return status; +} + +CContact::AVAILABILITY CSkypeProto::MirandaToSkypeStatus(int status) +{ + CContact::AVAILABILITY availability = CContact::UNKNOWN; + + switch(status) + { + case ID_STATUS_ONLINE: + availability = CContact::ONLINE; + break; + + case ID_STATUS_AWAY: + availability = CContact::AWAY; + break; + + case ID_STATUS_DND: + availability = CContact::DO_NOT_DISTURB; + break; + + case ID_STATUS_INVISIBLE: + availability = CContact::INVISIBLE; + break; + } + + return availability; } \ No newline at end of file -- cgit v1.2.3