summaryrefslogtreecommitdiff
path: root/protocols/Icq10/src
diff options
context:
space:
mode:
Diffstat (limited to 'protocols/Icq10/src')
-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
6 files changed, 157 insertions, 12 deletions
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;