diff options
author | George Hazan <ghazan@miranda.im> | 2019-01-02 23:18:11 +0300 |
---|---|---|
committer | George Hazan <ghazan@miranda.im> | 2019-01-02 23:18:19 +0300 |
commit | bd007cf5a03ba398546b343a8b7be8aab081dbaa (patch) | |
tree | e6e884f427cbd1beeb49c99fd56d23f9f5687a5e /protocols/Icq10 | |
parent | 14bc22db14c5c9f2fc7f3797ce968dc0a32805ff (diff) |
fixes #1669 (ICQ10: phone number auth support)
Diffstat (limited to 'protocols/Icq10')
-rw-r--r-- | protocols/Icq10/res/resources.rc | 124 | ||||
-rw-r--r-- | protocols/Icq10/src/http.cpp | 7 | ||||
-rw-r--r-- | protocols/Icq10/src/options.cpp | 127 | ||||
-rw-r--r-- | protocols/Icq10/src/proto.cpp | 20 | ||||
-rw-r--r-- | protocols/Icq10/src/proto.h | 5 | ||||
-rw-r--r-- | protocols/Icq10/src/resource.h | 9 | ||||
-rw-r--r-- | protocols/Icq10/src/server.cpp | 1 |
7 files changed, 255 insertions, 38 deletions
diff --git a/protocols/Icq10/res/resources.rc b/protocols/Icq10/res/resources.rc index 03ee5ca11f..04c82cfab4 100644 --- a/protocols/Icq10/res/resources.rc +++ b/protocols/Icq10/res/resources.rc @@ -12,6 +12,67 @@ #undef APSTUDIO_READONLY_SYMBOLS ///////////////////////////////////////////////////////////////////////////// +// Russian (Russia) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_RUS) +LANGUAGE LANG_RUSSIAN, SUBLANG_DEFAULT +#pragma code_page(1251) + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_REGISTER DIALOGEX 0, 0, 316, 111 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU +EXSTYLE WS_EX_APPWINDOW +CAPTION "Account registration" +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + DEFPUSHBUTTON "OK",IDOK,205,90,50,14 + PUSHBUTTON "Cancel",IDCANCEL,259,90,50,14 + LTEXT "Enter full phone number",IDC_STATIC,7,7,302,14 + EDITTEXT IDC_PHONE,7,18,302,14,ES_AUTOHSCROLL + PUSHBUTTON "Send me registration code via SMS",IDC_SENDSMS,49,37,221,14,BS_CENTER | WS_DISABLED + LTEXT "Enter registration code",IDC_STATIC,7,58,302,8 + EDITTEXT IDC_CODE,7,70,302,14,ES_AUTOHSCROLL | WS_DISABLED +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO +BEGIN + IDD_REGISTER, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 309 + TOPMARGIN, 7 + BOTTOMMARGIN, 104 + END +END +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// AFX_DIALOG_LAYOUT +// + +IDD_REGISTER AFX_DIALOG_LAYOUT +BEGIN + 0 +END + +#endif // Russian (Russia) resources +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// // English (United States) resources #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) @@ -32,9 +93,10 @@ BEGIN EDITTEXT IDC_UIN,54,0,131,12,ES_AUTOHSCROLL LTEXT "Password:",IDC_STATIC,0,16,53,12 EDITTEXT IDC_PASSWORD,54,16,131,12,ES_PASSWORD | ES_AUTOHSCROLL + PUSHBUTTON "Create a new ICQ account",IDC_REGISTER,62,34,122,14 END -IDD_OPTIONS_FULL DIALOGEX 0, 0, 310, 62 +IDD_OPTIONS_FULL DIALOGEX 0, 0, 310, 80 STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD EXSTYLE WS_EX_CONTROLPARENT FONT 8, "MS Shell Dlg", 0, 0, 0x1 @@ -46,34 +108,10 @@ BEGIN EDITTEXT IDC_PASSWORD,68,26,106,12,ES_PASSWORD | ES_AUTOHSCROLL CONTROL "Send messages slower, but with full acknowledgment",IDC_SLOWSEND, "Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,43,285,10 + PUSHBUTTON "Create a new ICQ account",IDC_REGISTER,183,61,122,14 END -#ifdef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// TEXTINCLUDE -// - -1 TEXTINCLUDE -BEGIN - "..\\src\\resource.h\0" -END - -2 TEXTINCLUDE -BEGIN - "#include ""winres.h""\0" -END - -3 TEXTINCLUDE -BEGIN - "\r\n" - "\0" -END - -#endif // APSTUDIO_INVOKED - - ///////////////////////////////////////////////////////////////////////////// // // DESIGNINFO @@ -82,6 +120,10 @@ END #ifdef APSTUDIO_INVOKED GUIDELINES DESIGNINFO BEGIN + IDD_OPTIONS_ACCMGR, DIALOG + BEGIN + END + IDD_OPTIONS_FULL, DIALOG BEGIN END @@ -99,6 +141,36 @@ BEGIN 0 END +IDD_OPTIONS_ACCMGR AFX_DIALOG_LAYOUT +BEGIN + 0 +END + + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "..\\src\\resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""winres.h""\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + #endif // English (United States) resources ///////////////////////////////////////////////////////////////////////////// diff --git a/protocols/Icq10/src/http.cpp b/protocols/Icq10/src/http.cpp index 5590ddc596..92154cd13e 100644 --- a/protocols/Icq10/src/http.cpp +++ b/protocols/Icq10/src/http.cpp @@ -27,14 +27,7 @@ void __cdecl CIcqProto::ServerThread(void*) memset(&m_ConnPool, 0, sizeof(m_ConnPool)); m_bTerminated = false; - if (m_dwUin == 0 || mir_wstrlen(m_szPassword) == 0) { - debugLogA("Thread ended, UIN/password are not configured"); - ConnectionFailed(LOGINERR_BADUSERID); - return; - } - debugLogA("CIcqProto::WorkerThread: %s", "entering"); - CheckPassword(); while (true) { WaitForSingleObject(m_evRequestsQueue, 1000); diff --git a/protocols/Icq10/src/options.cpp b/protocols/Icq10/src/options.cpp index 2d0445f1a8..357e8617bf 100644 --- a/protocols/Icq10/src/options.cpp +++ b/protocols/Icq10/src/options.cpp @@ -20,19 +20,135 @@ #include "stdafx.h" +struct CIcqRegistrationDlg : public CProtoDlgBase<CIcqProto> +{ + CMStringA szTrans; + int iErrorCode; + + CCtrlEdit edtPhone, edtCode; + CCtrlButton btnSendSms; + + CIcqRegistrationDlg(CIcqProto *ppro) : + CProtoDlgBase<CIcqProto>(ppro, IDD_REGISTER), + edtPhone(this, IDC_PHONE), + edtCode(this, IDC_CODE), + btnSendSms(this, IDC_SENDSMS) + { + btnSendSms.OnClick = Callback(this, &CIcqRegistrationDlg::onClick_SendSms); + edtPhone.OnChange = Callback(this, &CIcqRegistrationDlg::onChange_Phone); + } + + bool OnApply() override + { + auto *pReq = new AsyncHttpRequest(CONN_MAIN, REQUEST_GET, "https://www.icq.com/smsreg/loginWithPhoneNumber.php", &CIcqProto::OnLoginViaPhone); + pReq << CHAR_PARAM("locale", "en") << WCHAR_PARAM("msisdn", ptrW(edtPhone.GetText())) << CHAR_PARAM("trans_id", szTrans) << CHAR_PARAM("k", ICQ_APP_ID) + << CHAR_PARAM("r", pReq->m_reqId) << CHAR_PARAM("f", "json") << WCHAR_PARAM("sms_code", ptrW(edtCode.GetText())) << INT_PARAM("create_account", 1); + pReq->pUserInfo = this; + + SetCursor(LoadCursor(0, IDC_WAIT)); + m_proto->ExecuteRequest(pReq); + SetCursor(LoadCursor(0, IDC_ARROW)); + + if (iErrorCode != 200) + return false; + + EndDialog(m_hwnd, 1); + return true; + } + + void onChange_Phone(CCtrlEdit*) + { + auto *pReq = new AsyncHttpRequest(CONN_MAIN, REQUEST_GET, "https://clientapi.icq.net/fcgi-bin/smsphoneinfo", &CIcqProto::OnCheckPhone); + pReq << CHAR_PARAM("service", "icq_registration") << CHAR_PARAM("info", "typing_check,score,iso_country_code") + << WCHAR_PARAM("phone", ptrW(edtPhone.GetText())) << CHAR_PARAM("id", pReq->m_reqId); + pReq->pUserInfo = this; + m_proto->Push(pReq); + } + + void onClick_SendSms(CCtrlButton*) + { + auto *pReq = new AsyncHttpRequest(CONN_MAIN, REQUEST_GET, "https://www.icq.com/smsreg/requestPhoneValidation.php", &CIcqProto::OnValidateSms); + pReq << CHAR_PARAM("locale", "en") << WCHAR_PARAM("msisdn", ptrW(edtPhone.GetText())) << CHAR_PARAM("r", pReq->m_reqId) + << CHAR_PARAM("smsFormatType", "human") << CHAR_PARAM("k", ICQ_APP_ID); + pReq->pUserInfo = this; + m_proto->Push(pReq); + } +}; + +void CIcqProto::OnCheckPhone(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest *pReq) +{ + if (pReply == nullptr || pReply->resultCode != 200) + return; + + CIcqRegistrationDlg *pDlg = (CIcqRegistrationDlg*)pReq->pUserInfo; + pDlg->btnSendSms.Disable(); + pDlg->edtCode.Disable(); + + JSONROOT root(pReply->pData); + CMStringW wszStatus((*root)["status"].as_mstring()); + if (wszStatus != L"OK") { + pDlg->edtCode.SetText((*root)["printable"].as_mstring()); + return; + } + + pDlg->btnSendSms.Enable(); +} + +void CIcqProto::OnValidateSms(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest *pReq) +{ + JsonReply root(pReply); + if (root.error() != 200) + return; + + CIcqRegistrationDlg *pDlg = (CIcqRegistrationDlg*)pReq->pUserInfo; + const JSONNode &data = root.data(); + pDlg->szTrans = data["trans_id"].as_mstring(); + + pDlg->edtCode.Enable(); + pDlg->edtCode.SetText(L""); +} + +void CIcqProto::OnLoginViaPhone(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest *pReq) +{ + CIcqRegistrationDlg *pDlg = (CIcqRegistrationDlg*)pReq->pUserInfo; + + JsonReply root(pReply); + pDlg->iErrorCode = root.error(); + if (root.error() != 200) + return; + + const JSONNode &data = root.data(); + m_szAToken = data["token"]["a"].as_mstring(); + m_szAToken = ptrA(mir_urlDecode(m_szAToken)); + setString(DB_KEY_ATOKEN, m_szAToken); + + m_szSessionKey = data["sessionKey"].as_mstring(); + m_szSessionKey = ptrA(mir_urlDecode(m_szSessionKey)); + setString(DB_KEY_SESSIONKEY, m_szSessionKey); + + m_dwUin = _wtoi(data["loginId"].as_mstring()); + setByte("PhoneReg", 1); +} + +///////////////////////////////////////////////////////////////////////////////////////// + class CIcqOptionsDlg : public CProtoDlgBase<CIcqProto> { CCtrlEdit edtUin, edtPassword; CCtrlCheck chkSlowSend; + CCtrlButton btnCreate; CMStringW wszOldPass; public: CIcqOptionsDlg(CIcqProto *ppro, int iDlgID, bool bFullDlg) : CProtoDlgBase<CIcqProto>(ppro, iDlgID), edtUin(this, IDC_UIN), + btnCreate(this, IDC_REGISTER), edtPassword(this, IDC_PASSWORD), chkSlowSend(this, IDC_SLOWSEND) { + btnCreate.OnClick = Callback(this, &CIcqOptionsDlg::onClick_Register); + CreateLink(edtUin, ppro->m_dwUin); CreateLink(edtPassword, ppro->m_szPassword); @@ -47,9 +163,20 @@ public: if (wszOldPass != ptrW(edtPassword.GetText())) { m_proto->delSetting(DB_KEY_ATOKEN); m_proto->delSetting(DB_KEY_SESSIONKEY); + m_proto->delSetting("PhoneReg"); } return true; } + + void onClick_Register(CCtrlButton*) + { + CIcqRegistrationDlg dlg(m_proto); + dlg.SetParent(m_hwnd); + if (dlg.DoModal()) { + m_proto->m_dwUin = m_proto->getDword(DB_KEY_UIN); + m_proto->m_szPassword = L""; + } + } }; INT_PTR CIcqProto::CreateAccMgrUI(WPARAM, LPARAM hwndParent) diff --git a/protocols/Icq10/src/proto.cpp b/protocols/Icq10/src/proto.cpp index 3f3e5484dd..e4877204c7 100644 --- a/protocols/Icq10/src/proto.cpp +++ b/protocols/Icq10/src/proto.cpp @@ -62,6 +62,8 @@ CIcqProto::CIcqProto(const char* aProtoName, const wchar_t* aUserName) : nlu.szDescriptiveName.w = descr.GetBuffer(); m_hNetlibUser = Netlib_RegisterUser(&nlu); + m_hWorkerThread = ForkThreadEx(&CIcqProto::ServerThread, nullptr, nullptr); + InitContactCache(); } @@ -79,6 +81,7 @@ void CIcqProto::OnModulesLoaded() void CIcqProto::OnShutdown() { + m_bTerminated = true; } void CIcqProto::OnContactDeleted(MCONTACT hContact) @@ -337,10 +340,23 @@ int CIcqProto::SetStatus(int iNewStatus) ProtoBroadcastAck(0, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)iOldStatus, m_iStatus); } // not logged in? come on - else if (m_hWorkerThread == nullptr && !IsStatusConnecting(m_iStatus)) { + else if (!IsStatusConnecting(m_iStatus)) { m_iStatus = ID_STATUS_CONNECTING; ProtoBroadcastAck(0, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)iOldStatus, m_iStatus); - m_hWorkerThread = ForkThreadEx(&CIcqProto::ServerThread, nullptr, nullptr); + + if (m_dwUin == 0) { + debugLogA("Thread ended, UIN/password are not configured"); + ConnectionFailed(LOGINERR_BADUSERID); + return 0; + } + + if (!getByte("PhoneReg") && mir_wstrlen(m_szPassword) == 0) { + debugLogA("Thread ended, password is not configured"); + ConnectionFailed(LOGINERR_BADUSERID); + return 0; + } + + CheckPassword(); } else if (m_bOnline) { debugLogA("setting server online status to %d", iNewStatus); diff --git a/protocols/Icq10/src/proto.h b/protocols/Icq10/src/proto.h index 8b2861b5a5..ec693efaea 100644 --- a/protocols/Icq10/src/proto.h +++ b/protocols/Icq10/src/proto.h @@ -64,6 +64,8 @@ struct IcqOwnMessage class CIcqProto : public PROTO<CIcqProto> { + friend struct CIcqRegistrationDlg; + bool m_bOnline = false, m_bTerminated = false; void CheckAvatarChange(MCONTACT hContact, const JSONNode&); void CheckNickChange(MCONTACT hContact, const JSONNode&); @@ -80,12 +82,15 @@ class CIcqProto : public PROTO<CIcqProto> void OnAddBuddy(NETLIBHTTPREQUEST*, AsyncHttpRequest*); void OnAddClient(NETLIBHTTPREQUEST*, AsyncHttpRequest*); void OnCheckPassword(NETLIBHTTPREQUEST*, AsyncHttpRequest*); + void OnCheckPhone(NETLIBHTTPREQUEST*, AsyncHttpRequest*); void OnFetchEvents(NETLIBHTTPREQUEST*, AsyncHttpRequest*); void OnGetUserInfo(NETLIBHTTPREQUEST*, AsyncHttpRequest*); + void OnLoginViaPhone(NETLIBHTTPREQUEST*, AsyncHttpRequest*); void OnReceiveAvatar(NETLIBHTTPREQUEST*, AsyncHttpRequest*); void OnSearchResults(NETLIBHTTPREQUEST*, AsyncHttpRequest*); void OnSendMessage(NETLIBHTTPREQUEST*, AsyncHttpRequest*); void OnStartSession(NETLIBHTTPREQUEST*, AsyncHttpRequest*); + void OnValidateSms(NETLIBHTTPREQUEST*, AsyncHttpRequest*); void ProcessBuddyList(const JSONNode&); void ProcessEvent(const JSONNode&); diff --git a/protocols/Icq10/src/resource.h b/protocols/Icq10/src/resource.h index cdd4695b7e..77e27cc815 100644 --- a/protocols/Icq10/src/resource.h +++ b/protocols/Icq10/src/resource.h @@ -4,17 +4,22 @@ // #define IDD_OPTIONS_FULL 101 #define IDD_OPTIONS_ACCMGR 102 +#define IDD_REGISTER 105 #define IDC_PASSWORD 1001 #define IDC_UIN 1002 #define IDC_SLOWSEND 1003 +#define IDC_REGISTER 1005 +#define IDC_PHONE 1006 +#define IDC_SENDSMS 1008 +#define IDC_CODE 1009 // Next default values for new objects // #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 104 +#define _APS_NEXT_RESOURCE_VALUE 107 #define _APS_NEXT_COMMAND_VALUE 40001 -#define _APS_NEXT_CONTROL_VALUE 1004 +#define _APS_NEXT_CONTROL_VALUE 1010 #define _APS_NEXT_SYMED_VALUE 101 #endif #endif diff --git a/protocols/Icq10/src/server.cpp b/protocols/Icq10/src/server.cpp index 006b2d6959..5aee47ddf9 100644 --- a/protocols/Icq10/src/server.cpp +++ b/protocols/Icq10/src/server.cpp @@ -85,7 +85,6 @@ void CIcqProto::OnLoggedOut() { debugLogA("CIcqProto::OnLoggedOut"); m_bOnline = false; - m_bTerminated = true; ProtoBroadcastAck(0, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)m_iStatus, ID_STATUS_OFFLINE); m_iStatus = m_iDesiredStatus = ID_STATUS_OFFLINE; |