summaryrefslogtreecommitdiff
path: root/protocols/WhatsAppWeb/src/server.cpp
diff options
context:
space:
mode:
authorGeorge Hazan <ghazan@miranda.im>2019-10-07 20:40:13 +0300
committerGeorge Hazan <ghazan@miranda.im>2019-10-07 20:40:20 +0300
commit8d0500df234fc5b59ea7687bd5f55f19d7b8e28c (patch)
treea090b606b6e5fa25574c4836121cebae667de5cb /protocols/WhatsAppWeb/src/server.cpp
parent5ffd6fe3ab6f29444c699720b9ea588b57313c27 (diff)
WhatsAppWeb: QR code viewer
Diffstat (limited to 'protocols/WhatsAppWeb/src/server.cpp')
-rw-r--r--protocols/WhatsAppWeb/src/server.cpp151
1 files changed, 151 insertions, 0 deletions
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