summaryrefslogtreecommitdiff
path: root/protocols/Icq10
diff options
context:
space:
mode:
authorGeorge Hazan <ghazan@miranda.im>2019-01-02 23:18:11 +0300
committerGeorge Hazan <ghazan@miranda.im>2019-01-02 23:18:19 +0300
commitbd007cf5a03ba398546b343a8b7be8aab081dbaa (patch)
treee6e884f427cbd1beeb49c99fd56d23f9f5687a5e /protocols/Icq10
parent14bc22db14c5c9f2fc7f3797ce968dc0a32805ff (diff)
fixes #1669 (ICQ10: phone number auth support)
Diffstat (limited to 'protocols/Icq10')
-rw-r--r--protocols/Icq10/res/resources.rc124
-rw-r--r--protocols/Icq10/src/http.cpp7
-rw-r--r--protocols/Icq10/src/options.cpp127
-rw-r--r--protocols/Icq10/src/proto.cpp20
-rw-r--r--protocols/Icq10/src/proto.h5
-rw-r--r--protocols/Icq10/src/resource.h9
-rw-r--r--protocols/Icq10/src/server.cpp1
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;