diff options
author | George Hazan <ghazan@miranda.im> | 2019-10-07 20:40:13 +0300 |
---|---|---|
committer | George Hazan <ghazan@miranda.im> | 2019-10-07 20:40:20 +0300 |
commit | 8d0500df234fc5b59ea7687bd5f55f19d7b8e28c (patch) | |
tree | a090b606b6e5fa25574c4836121cebae667de5cb | |
parent | 5ffd6fe3ab6f29444c699720b9ea588b57313c27 (diff) |
WhatsAppWeb: QR code viewer
-rw-r--r-- | protocols/WhatsAppWeb/WhatsAppWeb.vcxproj | 11 | ||||
-rw-r--r-- | protocols/WhatsAppWeb/WhatsAppWeb.vcxproj.filters | 53 | ||||
-rw-r--r-- | protocols/WhatsAppWeb/res/version.rc | 48 | ||||
-rw-r--r-- | protocols/WhatsAppWeb/res/whatsapp.rc | 118 | ||||
-rw-r--r-- | protocols/WhatsAppWeb/src/avatars.cpp | 13 | ||||
-rw-r--r-- | protocols/WhatsAppWeb/src/db.h | 61 | ||||
-rw-r--r-- | protocols/WhatsAppWeb/src/main.cpp | 14 | ||||
-rw-r--r-- | protocols/WhatsAppWeb/src/options.cpp | 8 | ||||
-rw-r--r-- | protocols/WhatsAppWeb/src/proto.cpp | 68 | ||||
-rw-r--r-- | protocols/WhatsAppWeb/src/proto.h | 31 | ||||
-rw-r--r-- | protocols/WhatsAppWeb/src/resource.h | 8 | ||||
-rw-r--r-- | protocols/WhatsAppWeb/src/server.cpp | 151 | ||||
-rw-r--r-- | protocols/WhatsAppWeb/src/stdafx.cxx | 12 | ||||
-rw-r--r-- | protocols/WhatsAppWeb/src/stdafx.h | 21 | ||||
-rw-r--r-- | protocols/WhatsAppWeb/src/version.h | 2 |
15 files changed, 446 insertions, 173 deletions
diff --git a/protocols/WhatsAppWeb/WhatsAppWeb.vcxproj b/protocols/WhatsAppWeb/WhatsAppWeb.vcxproj index ac48c7237b..276ea52570 100644 --- a/protocols/WhatsAppWeb/WhatsAppWeb.vcxproj +++ b/protocols/WhatsAppWeb/WhatsAppWeb.vcxproj @@ -18,6 +18,17 @@ <Platform>x64</Platform> </ProjectConfiguration> </ItemGroup> + <ItemGroup> + <ProjectReference Include="..\..\libs\libqrencode\libqrencode.vcxproj"> + <Project>{4d3554de-6e14-4f94-a909-a4b19151a47e}</Project> + </ProjectReference> + <ProjectReference Include="..\..\libs\libsignal\libsignal.vcxproj"> + <Project>{620e0be7-3763-4f35-9dbd-4770104e269c}</Project> + </ProjectReference> + </ItemGroup> + <ItemGroup> + <Image Include="res\whatsapp.ico" /> + </ItemGroup> <PropertyGroup Label="Globals"> <ProjectGuid>{13E796AD-BEA4-4213-A1B8-E18E2397E544}</ProjectGuid> <ProjectName>WhatsAppWeb</ProjectName> diff --git a/protocols/WhatsAppWeb/WhatsAppWeb.vcxproj.filters b/protocols/WhatsAppWeb/WhatsAppWeb.vcxproj.filters index fcae13a9d8..e9b9de29a9 100644 --- a/protocols/WhatsAppWeb/WhatsAppWeb.vcxproj.filters +++ b/protocols/WhatsAppWeb/WhatsAppWeb.vcxproj.filters @@ -1,4 +1,57 @@ <?xml version="1.0" encoding="utf-8"?> <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Import Project="$(ProjectDir)..\..\build\vc.common\common.filters" /> + <ItemGroup> + <ClCompile Include="src\stdafx.cxx"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="src\*.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="src\*.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="src\*.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="src\*.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="src\*.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + </ItemGroup> + <ItemGroup> + <ClInclude Include="src\*.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="src\*.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="src\*.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="src\*.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="src\*.h"> + <Filter>Header Files</Filter> + </ClInclude> + </ItemGroup> + <ItemGroup> + <ResourceCompile Include="res\*.rc"> + <Filter>Resource Files</Filter> + </ResourceCompile> + <ResourceCompile Include="res\whatsapp.rc"> + <Filter>Resource Files</Filter> + </ResourceCompile> + <ResourceCompile Include="res\*.rc"> + <Filter>Resource Files</Filter> + </ResourceCompile> + </ItemGroup> + <ItemGroup> + <Image Include="res\whatsapp.ico"> + <Filter>Resource Files</Filter> + </Image> + </ItemGroup> </Project>
\ No newline at end of file diff --git a/protocols/WhatsAppWeb/res/version.rc b/protocols/WhatsAppWeb/res/version.rc index 37934706a0..5a5ddd63ed 100644 --- a/protocols/WhatsAppWeb/res/version.rc +++ b/protocols/WhatsAppWeb/res/version.rc @@ -6,50 +6,4 @@ #include "..\src\version.h" -#define APSTUDIO_READONLY_SYMBOLS -#include "afxres.h" -#undef APSTUDIO_READONLY_SYMBOLS - -///////////////////////////////////////////////////////////////////////////// -// English (U.S.) resources - -#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) -#ifdef _WIN32 -LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US -#pragma code_page(1252) -#endif //_WIN32 - -VS_VERSION_INFO VERSIONINFO - FILEVERSION __FILEVERSION_STRING - PRODUCTVERSION __FILEVERSION_STRING - FILEFLAGSMASK 0x17L -#ifdef _DEBUG - FILEFLAGS 0x1L -#else - FILEFLAGS 0x0L -#endif - FILEOS 0x4L - FILETYPE 0x2L - FILESUBTYPE 0x0L -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "000004b0" - BEGIN - VALUE "Author", __AUTHOR - VALUE "FileDescription", __DESCRIPTION - VALUE "FileVersion", __VERSION_STRING - VALUE "InternalName", __PLUGIN_NAME - VALUE "LegalCopyright", __COPYRIGHT - VALUE "OriginalFilename", __FILENAME - VALUE "ProductName", __PLUGIN_NAME - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x0, 1200 - END -END - -#endif // English (U.S.) resources -///////////////////////////////////////////////////////////////////////////// +#include "..\..\build\Version.rc" diff --git a/protocols/WhatsAppWeb/res/whatsapp.rc b/protocols/WhatsAppWeb/res/whatsapp.rc index e3d3cba800..b8718da79e 100644 --- a/protocols/WhatsAppWeb/res/whatsapp.rc +++ b/protocols/WhatsAppWeb/res/whatsapp.rc @@ -1,5 +1,7 @@ // Microsoft Visual C++ generated resource script. // +#pragma code_page(65001) + #include "..\src\resource.h" #define APSTUDIO_READONLY_SYMBOLS @@ -13,60 +15,25 @@ #undef APSTUDIO_READONLY_SYMBOLS ///////////////////////////////////////////////////////////////////////////// -// German (Germany) resources - -#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_DEU) -LANGUAGE LANG_GERMAN, SUBLANG_GERMAN -#pragma code_page(1252) - -#ifdef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// TEXTINCLUDE -// - -1 TEXTINCLUDE -BEGIN - "..\\src\\resource.h\0" -END - -2 TEXTINCLUDE -BEGIN - "#include ""afxres.h""\r\n" - "\0" -END - -3 TEXTINCLUDE -BEGIN - "\r\n" - "\0" -END - -#endif // APSTUDIO_INVOKED +// English (United States) resources +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US ///////////////////////////////////////////////////////////////////////////// // -// DESIGNINFO +// Dialog // -#ifdef APSTUDIO_INVOKED -GUIDELINES DESIGNINFO +IDD_SHOWQR DIALOGEX 0, 0, 318, 335 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Dialog" +FONT 8, "MS Shell Dlg", 400, 0, 0x1 BEGIN - IDD_WHATSAPOPTIONS, DIALOG - BEGIN - VERTGUIDE, 60 - VERTGUIDE, 178 - BOTTOMMARGIN, 126 - END + CONTROL "",IDC_QRPIC,"Static",SS_BITMAP | SS_NOTIFY | SS_CENTERIMAGE | SS_REALSIZEIMAGE | SS_SUNKEN,7,7,304,304 + DEFPUSHBUTTON "OK",IDOK,205,316,50,14 + PUSHBUTTON "Cancel",IDCANCEL,261,316,50,14 END -#endif // APSTUDIO_INVOKED - - -///////////////////////////////////////////////////////////////////////////// -// -// Dialog -// IDD_ACCMGRUI DIALOGEX 0, 0, 188, 144 STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD @@ -81,7 +48,7 @@ BEGIN LTEXT "Default group:",IDC_STATIC,4,37,55,10 EDITTEXT IDC_DEFGROUP,60,36,124,12,ES_AUTOHSCROLL CONTROL "Use SSL connection (port 443)",IDC_SSL,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,4,52,180,10 - CONTROL "Use remote message timestamps", IDC_REMOTE_TIME, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 4, 64, 180, 10 + CONTROL "Use remote message timestamps",IDC_REMOTE_TIME,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,4,64,180,10 CONTROL "Automatically open group chats",IDC_AUTORUN,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,4,76,180,10 GROUPBOX "Registration",IDC_STATIC,4,92,184,48 LTEXT "Enter code",IDC_STATIC,8,123,47,10 @@ -107,7 +74,7 @@ BEGIN LTEXT "Default group:",IDC_STATIC,4,57,55,10 EDITTEXT IDC_DEFGROUP,60,56,124,12,ES_AUTOHSCROLL CONTROL "Use SSL connection (port 443)",IDC_SSL,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,4,72,180,10 - CONTROL "Use remote message timestamps", IDC_REMOTE_TIME, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 4, 84, 180, 10 + CONTROL "Use remote message timestamps",IDC_REMOTE_TIME,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,4,84,180,10 CONTROL "Automatically open group chats",IDC_AUTORUN,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,4,96,180,10 GROUPBOX "Registration",IDC_STATIC,4,112,184,48 LTEXT "Enter code",IDC_STATIC,8,143,47,10 @@ -142,7 +109,60 @@ END // remains consistent on all systems. IDI_WHATSAPP ICON "whatsapp.ico" -#endif // German (Germany) resources + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "..\\src\\resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO +BEGIN + IDD_SHOWQR, DIALOG + BEGIN + BOTTOMMARGIN, 330 + END +END +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// AFX_DIALOG_LAYOUT +// + +IDD_SHOWQR AFX_DIALOG_LAYOUT +BEGIN + 0 +END + +#endif // English (United States) resources ///////////////////////////////////////////////////////////////////////////// diff --git a/protocols/WhatsAppWeb/src/avatars.cpp b/protocols/WhatsAppWeb/src/avatars.cpp index cacd251639..5c85c437d8 100644 --- a/protocols/WhatsAppWeb/src/avatars.cpp +++ b/protocols/WhatsAppWeb/src/avatars.cpp @@ -1,10 +1,17 @@ +/* + +WhatsAppWeb plugin for Miranda NG +Copyright © 2019 George Hazan + +*/ + #include "stdafx.h" INT_PTR WhatsAppProto::GetAvatarInfo(WPARAM wParam, LPARAM lParam) { PROTO_AVATAR_INFORMATION *pai = (PROTO_AVATAR_INFORMATION*)lParam; - ptrA id(getStringA(pai->hContact, isChatRoom(pai->hContact) ? "ChatRoomID" : WHATSAPP_KEY_ID)); + ptrA id(getStringA(pai->hContact, isChatRoom(pai->hContact) ? "ChatRoomID" : DBKEY_ID)); if (id == NULL) return GAIR_NOAVATAR; @@ -12,7 +19,7 @@ INT_PTR WhatsAppProto::GetAvatarInfo(WPARAM wParam, LPARAM lParam) wcsncpy_s(pai->filename, tszFileName.c_str(), _TRUNCATE); pai->format = PA_FORMAT_JPEG; - ptrA szAvatarId(getStringA(pai->hContact, WHATSAPP_KEY_AVATAR_ID)); + ptrA szAvatarId(getStringA(pai->hContact, DBKEY_AVATAR_ID)); if (szAvatarId == NULL || (wParam & GAIF_FORCE) != 0) if (pai->hContact != NULL && isOnline()) { // m_pConnection->sendGetPicture(id, "image"); @@ -50,7 +57,7 @@ CMStringW WhatsAppProto::GetAvatarFileName(MCONTACT hContact) CMStringA jid; if (hContact != NULL) { - ptrA szId(getStringA(hContact, isChatRoom(hContact) ? "ChatRoomID" : WHATSAPP_KEY_ID)); + ptrA szId(getStringA(hContact, isChatRoom(hContact) ? "ChatRoomID" : DBKEY_ID)); if (szId == NULL) return L""; diff --git a/protocols/WhatsAppWeb/src/db.h b/protocols/WhatsAppWeb/src/db.h index 3c73fb18e7..97dc165324 100644 --- a/protocols/WhatsAppWeb/src/db.h +++ b/protocols/WhatsAppWeb/src/db.h @@ -1,35 +1,34 @@ +/* + +WhatsAppWeb plugin for Miranda NG +Copyright © 2019 George Hazan + +*/ + #define MODULENAME "WhatsApp" // DB keys -#define WHATSAPP_KEY_ID "ID" -#define WHATSAPP_KEY_LOGIN "Login" -#define WHATSAPP_KEY_CC "CountryCode" -#define WHATSAPP_KEY_NICK "Nick" -#define WHATSAPP_KEY_PASS "Password" -#define WHATSAPP_KEY_IDX "DeviceID" -#define WHATSAPP_KEY_MAP_STATUSES "MapStatuses" -#define WHATSAPP_KEY_LOGGING_ENABLE "LoggingEnable" -#define WHATSAPP_KEY_NAME "RealName" -#define WHATSAPP_KEY_LAST_SEEN "LastSeen" -#define WHATSAPP_KEY_LAST_SEEN_DENIED "LastSeenDenied" -#define WHATSAPP_KEY_AVATAR_ID "AvatarId" -#define WHATSAPP_KEY_SYSTRAY_NOTIFY "UseSystrayNotify" -#define WHATSAPP_KEY_DEF_GROUP "DefaultGroup" -#define WHATSAPP_KEY_REG_CODE "RegistrationCode" -#define WHATSAPP_KEY_SSL "UseSSL" -#define WHATSAPP_KEY_AUTORUNCHATS "AutoRunChats" -#define WHATSAPP_KEY_USE_REMOTE_TIME "UseRemoteTime" - -#define WHATSAPP_KEY_EVENT_CLIENT_ENABLE "EventClientEnable" -#define WHATSAPP_KEY_EVENT_OTHER_ENABLE "EventOtherEnable" - -#define WHATSAPP_KEY_EVENT_CLIENT_COLBACK "PopupClientColorBack" -#define WHATSAPP_KEY_EVENT_CLIENT_COLTEXT "PopupClientColorText" -#define WHATSAPP_KEY_EVENT_CLIENT_TIMEOUT "PopupClientTimeout" -#define WHATSAPP_KEY_EVENT_CLIENT_DEFAULT "PopupClientColorDefault" - -#define WHATSAPP_KEY_EVENT_OTHER_COLBACK "PopupOtherColorBack" -#define WHATSAPP_KEY_EVENT_OTHER_COLTEXT "PopupOtherColorText" -#define WHATSAPP_KEY_EVENT_OTHER_TIMEOUT "PopupOtherTimeout" -#define WHATSAPP_KEY_EVENT_OTHER_DEFAULT "PopupOtherColorDefault" +#define DBKEY_ID "ID" +#define DBKEY_LOGIN "Login" +#define DBKEY_CC "CountryCode" + +#define DBKEY_CLIENT_ID "ClientId" +#define DBKEY_CLIENT_SECRET "ClientSecret" +#define DBKEY_PUBKEY "PublicKey" +#define DBKEY_PRIVATEKEY "PrivateKey" + +#define DBKEY_NAME "RealName" +#define DBKEY_DEF_GROUP "DefaultGroup" +#define DBKEY_AUTORUNCHATS "AutoRunChats" +#define DBKEY_AVATAR_ID "AvatarId" + +#define DBKEY_EVENT_CLIENT_COLBACK "PopupClientColorBack" +#define DBKEY_EVENT_CLIENT_COLTEXT "PopupClientColorText" +#define DBKEY_EVENT_CLIENT_TIMEOUT "PopupClientTimeout" +#define DBKEY_EVENT_CLIENT_DEFAULT "PopupClientColorDefault" + +#define DBKEY_EVENT_OTHER_COLBACK "PopupOtherColorBack" +#define DBKEY_EVENT_OTHER_COLTEXT "PopupOtherColorText" +#define DBKEY_EVENT_OTHER_TIMEOUT "PopupOtherTimeout" +#define DBKEY_EVENT_OTHER_DEFAULT "PopupOtherColorDefault" diff --git a/protocols/WhatsAppWeb/src/main.cpp b/protocols/WhatsAppWeb/src/main.cpp index f414c61c19..0f63d3ba80 100644 --- a/protocols/WhatsAppWeb/src/main.cpp +++ b/protocols/WhatsAppWeb/src/main.cpp @@ -1,3 +1,10 @@ +/* + +WhatsAppWeb plugin for Miranda NG +Copyright © 2019 George Hazan + +*/ + #include "stdafx.h" #include "version.h" @@ -12,9 +19,8 @@ PLUGININFOEX pluginInfo = { __AUTHOREMAIL, __COPYRIGHT, UNICODE_AWARE, //not transient - // {4f1ff7fa-4d75-44b9-93b0-2ced2e4f9e3e} - { 0x4f1ff7fa, 0x4d75, 0x44b9, { 0x93, 0xb0, 0x2c, 0xed, 0x2e, 0x4f, 0x9e, 0x3e } } - + // {008B9CE1-154B-44E4-9823-97C1AAB00C3C} + { 0x8b9ce1, 0x154b, 0x44e4, { 0x98, 0x23, 0x97, 0xc1, 0xaa, 0xb0, 0xc, 0x3c }} }; ///////////////////////////////////////////////////////////////////////////////////////// @@ -27,7 +33,7 @@ extern "C" __declspec(dllexport) const MUUID MirandaInterfaces[] = { MIID_PROTOC CMPlugin::CMPlugin() : ACCPROTOPLUGIN<WhatsAppProto>(MODULENAME, pluginInfo) { - SetUniqueId(WHATSAPP_KEY_ID); + SetUniqueId(DBKEY_ID); } ///////////////////////////////////////////////////////////////////////////////////////// diff --git a/protocols/WhatsAppWeb/src/options.cpp b/protocols/WhatsAppWeb/src/options.cpp new file mode 100644 index 0000000000..07cbd9967a --- /dev/null +++ b/protocols/WhatsAppWeb/src/options.cpp @@ -0,0 +1,8 @@ +/* + +WhatsAppWeb plugin for Miranda NG +Copyright © 2019 George Hazan + +*/ + +#include "stdafx.h" diff --git a/protocols/WhatsAppWeb/src/proto.cpp b/protocols/WhatsAppWeb/src/proto.cpp index ac7a5b2bff..a29e50d06f 100644 --- a/protocols/WhatsAppWeb/src/proto.cpp +++ b/protocols/WhatsAppWeb/src/proto.cpp @@ -1,3 +1,10 @@ +/* + +WhatsAppWeb plugin for Miranda NG +Copyright © 2019 George Hazan + +*/ + #include "stdafx.h" struct SearchParam @@ -12,7 +19,7 @@ struct SearchParam WhatsAppProto::WhatsAppProto(const char *proto_name, const wchar_t *username) : PROTO<WhatsAppProto>(proto_name, username), - m_tszDefaultGroup(getWStringA(WHATSAPP_KEY_DEF_GROUP)) + m_tszDefaultGroup(getWStringA(DBKEY_DEF_GROUP)) { db_set_resident(m_szModuleName, "StatusMsg"); @@ -26,6 +33,16 @@ WhatsAppProto::WhatsAppProto(const char *proto_name, const wchar_t *username) // HookProtoEvent(ME_OPT_INITIALISE, &WhatsAppProto::OnOptionsInit); // HookProtoEvent(ME_CLIST_PREBUILDSTATUSMENU, &WhatsAppProto::OnBuildStatusMenu); + // Client id generation + m_szClientId = getMStringA(DBKEY_CLIENT_ID); + if (m_szClientId.IsEmpty()) { + int8_t randBytes[16]; + Utils_GetRandom(randBytes, sizeof(randBytes)); + + m_szClientId = ptrA(mir_base64_encode(randBytes, sizeof(randBytes))); + setString(DBKEY_CLIENT_ID, m_szClientId); + } + // Create standard network connection wchar_t descr[512]; mir_snwprintf(descr, TranslateT("%s server connection"), m_tszUserName); @@ -55,6 +72,21 @@ WhatsAppProto::~WhatsAppProto() { } +MCONTACT WhatsAppProto::AddToList(int flags, PROTOSEARCHRESULT *psr) +{ + if (psr->id.w == nullptr) + return NULL; + + std::string phone(T2Utf(psr->id.w)); + std::string jid(phone + "@s.whatsapp.net"); + + /* MCONTACT hContact = AddToContactList(jid, phone.c_str()); + if (!(flags & PALF_TEMPORARY)) + db_unset(hContact, "CList", "NotOnList"); + + return hContact;*/ +} + INT_PTR WhatsAppProto::GetCaps(int type, MCONTACT) { switch (type) { @@ -103,30 +135,30 @@ int WhatsAppProto::SetStatus(int new_status) m_iStatus = m_iDesiredStatus = ID_STATUS_OFFLINE; ProtoBroadcastAck(NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)oldStatus, m_iStatus); } - else if (!IsStatusConnecting(m_iStatus)) { + else if (m_pConn == nullptr && !IsStatusConnecting(m_iStatus)) { m_iStatus = ID_STATUS_CONNECTING; ProtoBroadcastAck(NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)oldStatus, m_iStatus); + + ForkThread(&WhatsAppProto::ServerThread); + } + else if (m_pConn != nullptr) { + if (m_iDesiredStatus == ID_STATUS_ONLINE) { + // m_pConn->sendAvailableForChat(); + m_iStatus = ID_STATUS_ONLINE; + ProtoBroadcastAck(0, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)oldStatus, m_iStatus); + } + else if (m_iStatus == ID_STATUS_ONLINE && m_iDesiredStatus == ID_STATUS_INVISIBLE) { + // m_pConn->sendClose(); + m_iStatus = ID_STATUS_INVISIBLE; + setAllContactStatuses(ID_STATUS_OFFLINE); + ProtoBroadcastAck(0, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)oldStatus, m_iStatus); + } } else ProtoBroadcastAck(NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)oldStatus, m_iStatus); return 0; } -MCONTACT WhatsAppProto::AddToList(int flags, PROTOSEARCHRESULT *psr) -{ - if (psr->id.w == nullptr) - return NULL; - - std::string phone(T2Utf(psr->id.w)); - std::string jid(phone + "@s.whatsapp.net"); - -/* MCONTACT hContact = AddToContactList(jid, phone.c_str()); - if (!(flags & PALF_TEMPORARY)) - db_unset(hContact, "CList", "NotOnList"); - - return hContact;*/ -} - int WhatsAppProto::SendMsg(MCONTACT hContact, int, const char *msg) { ptrA jid(getStringA(hContact, "ID")); @@ -144,7 +176,7 @@ int WhatsAppProto::SendMsg(MCONTACT hContact, int, const char *msg) int WhatsAppProto::UserIsTyping(MCONTACT hContact, int type) { if (hContact && isOnline()) { - ptrA jid(getStringA(hContact, WHATSAPP_KEY_ID)); + ptrA jid(getStringA(hContact, DBKEY_ID)); if (jid && isOnline()) { } } diff --git a/protocols/WhatsAppWeb/src/proto.h b/protocols/WhatsAppWeb/src/proto.h index 564a31eb2e..610313ab0e 100644 --- a/protocols/WhatsAppWeb/src/proto.h +++ b/protocols/WhatsAppWeb/src/proto.h @@ -1,3 +1,10 @@ +/* + +WhatsAppWeb plugin for Miranda NG +Copyright © 2019 George Hazan + +*/ + #if !defined(PROTO_H) #define PROTO_H @@ -15,13 +22,22 @@ struct WAChatInfo MCONTACT hContact; }; +struct WAConnection : public MZeroedObject +{ + EVP_PKEY *m_pKeys; // private & public keys +}; + class WhatsAppProto : public PROTO<WhatsAppProto> { ptrW m_tszDefaultGroup; - CMStringA m_szJid; + CMStringA m_szJid, m_szClientId; CMStringW m_tszAvatarFolder; + WAConnection *m_pConn; + + bool ShowQrCode(void); + /// Avatars ////////////////////////////////////////////////////////////////////////// CMStringW GetAvatarFileName(MCONTACT hContact); @@ -48,12 +64,12 @@ public: // PROTO_INTERFACE /////////////////////////////////////////////////////////////////// - MCONTACT __cdecl AddToList(int flags, PROTOSEARCHRESULT *psr) override; - INT_PTR __cdecl GetCaps(int type, MCONTACT hContact = NULL) override; - HANDLE __cdecl SearchBasic(const wchar_t* id) override; - int __cdecl SendMsg(MCONTACT hContact, int flags, const char* msg) override; - int __cdecl SetStatus(int iNewStatus) override; - int __cdecl UserIsTyping(MCONTACT hContact, int type) override; + MCONTACT AddToList(int flags, PROTOSEARCHRESULT *psr) override; + INT_PTR GetCaps(int type, MCONTACT hContact = NULL) override; + HANDLE SearchBasic(const wchar_t* id) override; + int SendMsg(MCONTACT hContact, int flags, const char* msg) override; + int SetStatus(int iNewStatus) override; + int UserIsTyping(MCONTACT hContact, int type) override; // Services ////////////////////////////////////////////////////////////////////////// @@ -74,6 +90,7 @@ public: void __cdecl ProcessBuddyList(void*); void __cdecl SearchAckThread(void*); + void __cdecl ServerThread(void*); // Contacts handling ///////////////////////////////////////////////////////////////// diff --git a/protocols/WhatsAppWeb/src/resource.h b/protocols/WhatsAppWeb/src/resource.h index 67e976f3ca..42d8bf91fd 100644 --- a/protocols/WhatsAppWeb/src/resource.h +++ b/protocols/WhatsAppWeb/src/resource.h @@ -1,12 +1,13 @@ //{{NO_DEPENDENCIES}} // Microsoft Visual C++ generated include file. -// Used by ..\res\whatsapp.rc +// Used by w:\miranda-ng\protocols\WhatsAppWeb\res\whatsapp.rc // #define IDD_INPUTBOX 102 #define IDR_REGISTERUTILITY 103 #define IDD_ACCMGRUI 104 #define IDD_GROUPCHAT_INVITE 105 #define IDD_OPTIONS 106 +#define IDD_SHOWQR 107 #define IDI_WHATSAPP 203 #define IDI_ADD_GROUP 206 #define IDI_RENAME_GROUP 208 @@ -30,14 +31,15 @@ #define IDC_DEFGROUP 1017 #define IDC_REMOTE_TIME 1018 #define IDC_BUTTON_REQUEST_VOICE_CODE 1019 +#define IDC_QRPIC 1020 // Next default values for new objects // #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 107 +#define _APS_NEXT_RESOURCE_VALUE 109 #define _APS_NEXT_COMMAND_VALUE 40001 -#define _APS_NEXT_CONTROL_VALUE 1020 +#define _APS_NEXT_CONTROL_VALUE 1021 #define _APS_NEXT_SYMED_VALUE 101 #endif #endif diff --git a/protocols/WhatsAppWeb/src/server.cpp b/protocols/WhatsAppWeb/src/server.cpp new file mode 100644 index 0000000000..8b94cb675c --- /dev/null +++ b/protocols/WhatsAppWeb/src/server.cpp @@ -0,0 +1,151 @@ +/* + +WhatsAppWeb plugin for Miranda NG +Copyright © 2019 George Hazan + +*/ + +#include "stdafx.h" + +class CWhatsAppQRDlg : public CProtoDlgBase<WhatsAppProto> +{ + QRcode *m_qr; + +public: + CWhatsAppQRDlg(WhatsAppProto *ppro, const CMStringA &szData) : + CProtoDlgBase<WhatsAppProto>(ppro, IDD_SHOWQR) + { + m_qr = QRcode_encodeString(szData, 0, QR_ECLEVEL_L, QR_MODE_8, 1); + } + + ~CWhatsAppQRDlg() + { + QRcode_free(m_qr); + } + + bool OnInitDialog() override + { + HWND hwndRc = GetDlgItem(m_hwnd, IDC_QRPIC); + RECT rc; + GetClientRect(hwndRc, &rc); + + ::SetForegroundWindow(m_hwnd); + + int scale = 8; // (rc.bottom - rc.top) / m_qr->width; + int rowLen = m_qr->width * scale * 3; + if (rowLen % 4) + rowLen = (rowLen / 4 + 1) * 4; + int dataLen = rowLen * m_qr->width * scale; + + mir_ptr<BYTE> pData((BYTE *)mir_alloc(dataLen)); + if (pData == nullptr) + return false; + + memset(pData, 0xFF, dataLen); // white background by default + + const BYTE *s = m_qr->data; + for (int y = 0; y < m_qr->width; y++) { + BYTE *d = pData.get() + rowLen * y * scale; + for (int x = 0; x < m_qr->width; x++) { + if (*s & 1) + for (int i = 0; i < scale; i++) + for (int j = 0; j < scale; j++) { + d[j * 3 + i * rowLen] = 0; + d[1 + j * 3 + i * rowLen] = 0; + d[2 + j * 3 + i * rowLen] = 0; + } + + d += scale * 3; + s++; + } + } + + BITMAPFILEHEADER fih = {}; + fih.bfType = 0x4d42; // "BM" + fih.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + dataLen; + fih.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER); + + BITMAPINFOHEADER bih = {}; + bih.biSize = sizeof(BITMAPINFOHEADER); + bih.biWidth = m_qr->width * scale; + bih.biHeight = -bih.biWidth; + bih.biPlanes = 1; + bih.biBitCount = 24; + bih.biCompression = BI_RGB; + + wchar_t wszTempPath[MAX_PATH], wszTempFile[MAX_PATH]; + GetTempPathW(_countof(wszTempPath), wszTempPath); + GetTempFileNameW(wszTempPath, L"wa_", TRUE, wszTempFile); + FILE *f = _wfopen(wszTempFile, L"wb"); + fwrite(&fih, sizeof(BITMAPFILEHEADER), 1, f); + fwrite(&bih, sizeof(BITMAPINFOHEADER), 1, f); + fwrite(pData, sizeof(unsigned char), dataLen, f); + fclose(f); + + SendMessage(hwndRc, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)Image_Load(wszTempFile)); + + DeleteFileW(wszTempFile); + return true; + } +}; + +///////////////////////////////////////////////////////////////////////////////////////// + +static int random_func(uint8_t *pData, size_t size, void *) +{ + Utils_GetRandom(pData, size); + return 0; +} + +bool WhatsAppProto::ShowQrCode() +{ + CMStringA szPubKey(getMStringA(DBKEY_PUBKEY)); + if (szPubKey.IsEmpty()) { + // generate new pair of private & public keys for this account + signal_context *pTmpCtx; + signal_context_create(&pTmpCtx, nullptr); + + signal_crypto_provider prov; + memset(&prov, 0xFF, sizeof(prov)); + prov.random_func = random_func; + signal_context_set_crypto_provider(pTmpCtx, &prov); + + ec_key_pair *pKeys; + if (curve_generate_key_pair(pTmpCtx, &pKeys)) { + signal_context_destroy(pTmpCtx); + return false; + } + + auto *pPubKey = ec_key_pair_get_public(pKeys); + signal_buffer *pBuf; + ec_public_key_serialize(&pBuf, pPubKey); + szPubKey = ptrA(mir_base64_encode(&pBuf->data, pBuf->len)); + signal_buffer_free(pBuf); + setString(DBKEY_PUBKEY, szPubKey); + + auto *pPrivKey = ec_key_pair_get_private(pKeys); + ec_private_key_serialize(&pBuf, pPrivKey); + CMStringA szPrivKey(ptrA(mir_base64_encode(&pBuf->data, pBuf->len))); + signal_buffer_free(pBuf); + setString(DBKEY_PRIVATEKEY, szPrivKey); + } + + CMStringA szQrData(FORMAT, "%s,%s,%s", m_szJid.c_str(), szPubKey.c_str(), m_szClientId.c_str()); + CWhatsAppQRDlg(this, szQrData).DoModal(); + return true; +} + +///////////////////////////////////////////////////////////////////////////////////////// + +void WhatsAppProto::ServerThread(void *) +{ + m_pConn = new WAConnection(); + + ptrA szClientToken(getStringA(DBKEY_CLIENT_SECRET)); + if (szClientToken == nullptr) { + if (!ShowQrCode()) { + delete m_pConn; + return; + } + } +}
\ No newline at end of file diff --git a/protocols/WhatsAppWeb/src/stdafx.cxx b/protocols/WhatsAppWeb/src/stdafx.cxx index 115d277c7a..46e6a71904 100644 --- a/protocols/WhatsAppWeb/src/stdafx.cxx +++ b/protocols/WhatsAppWeb/src/stdafx.cxx @@ -1,8 +1,8 @@ -// stdafx.cpp : Quelldatei, die nur die Standard-Includes einbindet. -// WhatsAPI++.pch ist der vorkompilierte Header. -// stdafx.obj enthдlt die vorkompilierten Typinformationen. +/* -#include "stdafx.h" +WhatsAppWeb plugin for Miranda NG +Copyright © 2019 George Hazan + +*/ -// TODO: Auf zusдtzliche Header verweisen, die in STDAFX.H -// und nicht in dieser Datei erforderlich sind. +#include "stdafx.h" diff --git a/protocols/WhatsAppWeb/src/stdafx.h b/protocols/WhatsAppWeb/src/stdafx.h index 1f3834b9bc..ee6c6a1156 100644 --- a/protocols/WhatsAppWeb/src/stdafx.h +++ b/protocols/WhatsAppWeb/src/stdafx.h @@ -1,14 +1,12 @@ /* -WhatsApp plugin for Miranda NG -Copyright © 2013-14 Uli Hecht +WhatsAppWeb plugin for Miranda NG +Copyright © 2019 George Hazan */ #pragma once -//#pragma warning(push) -//#pragma warning(disable:4312) #pragma warning(disable:4996) #pragma warning(disable:4290) @@ -43,5 +41,20 @@ Copyright © 2013-14 Uli Hecht #include <m_json.h> #include <m_gui.h> +#include <openssl/evp.h> + +#include "../../libs/libqrencode/src/qrencode.h" +#include "../../libs/libsignal/src/curve.h" +#include "../../libs/libsignal/src/signal_protocol.h" + +struct signal_buffer +{ + size_t len; + uint8_t data[]; +}; + #include "db.h" #include "proto.h" +#include "resource.h" + +#pragma comment(lib, "libeay32.lib")
\ No newline at end of file diff --git a/protocols/WhatsAppWeb/src/version.h b/protocols/WhatsAppWeb/src/version.h index 2aa4528fd5..4f09c6c183 100644 --- a/protocols/WhatsAppWeb/src/version.h +++ b/protocols/WhatsAppWeb/src/version.h @@ -6,7 +6,7 @@ #include <stdver.h> #define __PLUGIN_NAME "WhatsAppWeb protocol" -#define __FILENAME "WhatsApp.dll" +#define __FILENAME "WhatsAppWeb.dll" #define __DESCRIPTION "WhatsApp Web protocol support for Miranda NG." #define __AUTHOR "George Hazan" #define __AUTHOREMAIL "" |