From 8411617ad832612d074884ce7304516fe2459b48 Mon Sep 17 00:00:00 2001 From: "admin@progandy.co.cc" Date: Sun, 12 Sep 2010 13:33:13 +0000 Subject: - [ issue 2 ] implemented SMP - fixed some memory leaks - ugly workaround for SMP in ICQ git-svn-id: http://mirotr.googlecode.com/svn/trunk@8 eced67a3-f377-a0ae-92ae-d6de1850b05a --- MirOTR/DLG_smp.cpp | 96 ----------- MirOTR/MirOTR.vcproj | 28 ---- MirOTR/dialogs.cpp | 370 ++++++++++++++++++++++++++++++++++++++++--- MirOTR/dialogs.h | 4 +- MirOTR/language.h | 23 ++- MirOTR/options.cpp | 6 +- MirOTR/otr.cpp | 9 +- MirOTR/resources/resource.rc | 3 +- MirOTR/svcs_proto.cpp | 17 +- MirOTR/utils.cpp | 17 ++ MirOTR/utils.h | 2 + MirOTR/version.h | 2 +- 12 files changed, 406 insertions(+), 171 deletions(-) delete mode 100644 MirOTR/DLG_smp.cpp diff --git a/MirOTR/DLG_smp.cpp b/MirOTR/DLG_smp.cpp deleted file mode 100644 index b701b7f..0000000 --- a/MirOTR/DLG_smp.cpp +++ /dev/null @@ -1,96 +0,0 @@ -#include "stdafx.h" -#include -//TODO: Social Millionaire Protocol -typedef std::map SmpForContactMap; -SmpForContactMap smp_for_contact; - -HWND smp_find_for_contact(HANDLE hContact) { - SmpForContactMap::iterator iter = smp_for_contact.find(hContact); - if (iter == smp_for_contact.end()) return null; - return iter->second; -} - -/* Create the SMP dialog. responder is true if this is called in - * response to someone else's run of SMP. */ -static void dialog_socialist_millionaires(ConnContext *context, - TCHAR *question, bool responder) -{ - if (context == NULL) return; - TCHAR primary[1024]; - - if (responder && question) { - (HANDLE)context->app_data - mir_sntprintf(primary, 1024, TranslateT(LANG_SMP_AUTH_FROM), - contact_get_nameT((HANDLE)context->app_data)); - } else { - mir_sntprintf(primary, 1024, TranslateT(LANG_SMP_AUTH), - contact_get_nameT((HANDLE)context->app_data)); - } - - /* fprintf(stderr, "Question = ``%s''\n", question); */ - //TCHAR* proto_name = mir_a2t(context->protocol); - //if (!proto_name) proto_name = mir_tstrdup(TranslateT(LANG_UNKNOWN)); - - - dialog = create_smp_dialog(_("Authenticate Buddy"), - primary, context, responder, question); - - //mir_free(proto_name); -} - -/* Call this to update the status of an ongoing socialist millionaires - * protocol. Progress_level is a percentage, from 0.0 (aborted) to - * 1.0 (complete). Any other value represents an intermediate state. */ -static void otrg_gtk_dialog_update_smp(ConnContext *context, - double progress_level) -{ - PurpleConversation *conv = otrg_plugin_context_to_conv(context, 0); - GtkProgressBar *bar; - SMPData *smp_data = purple_conversation_get_data(conv, "otr-smpdata"); - - if (!smp_data) return; - - bar = GTK_PROGRESS_BAR(smp_data->smp_progress_bar); - gtk_progress_bar_set_fraction(bar, progress_level); - - /* If the counter is reset to absolute zero, the protocol has aborted */ - if (progress_level == 0.0) { - GtkDialog *dialog = GTK_DIALOG(smp_data->smp_progress_dialog); - - gtk_dialog_set_response_sensitive(dialog, GTK_RESPONSE_ACCEPT, 1); - gtk_dialog_set_response_sensitive(dialog, GTK_RESPONSE_REJECT, 0); - gtk_dialog_set_default_response(GTK_DIALOG(dialog), - GTK_RESPONSE_ACCEPT); - - gtk_label_set_text(GTK_LABEL(smp_data->smp_progress_label), - _("An error occurred during authentication.")); - return; - } else if (progress_level == 1.0) { - /* If the counter reaches 1.0, the protocol is complete */ - GtkDialog *dialog = GTK_DIALOG(smp_data->smp_progress_dialog); - - gtk_dialog_set_response_sensitive(dialog, GTK_RESPONSE_ACCEPT, 1); - gtk_dialog_set_response_sensitive(dialog, GTK_RESPONSE_REJECT, 0); - gtk_dialog_set_default_response(GTK_DIALOG(dialog), - GTK_RESPONSE_ACCEPT); - - if (context->smstate->sm_prog_state == OTRL_SMP_PROG_SUCCEEDED) { - if (context->active_fingerprint->trust && - context->active_fingerprint->trust[0]) { - gtk_label_set_text(GTK_LABEL(smp_data->smp_progress_label), - _("Authentication successful.")); - } else { - gtk_label_set_text(GTK_LABEL(smp_data->smp_progress_label), - _("Your buddy has successfully authenticated you. " - "You may want to authenticate your buddy as " - "well by asking your own question.")); - } - } else { - gtk_label_set_text(GTK_LABEL(smp_data->smp_progress_label), - _("Authentication failed.")); - } - } else { - /* Clear the progress label */ - gtk_label_set_text(GTK_LABEL(smp_data->smp_progress_label), ""); - } -} \ No newline at end of file diff --git a/MirOTR/MirOTR.vcproj b/MirOTR/MirOTR.vcproj index 905d4b3..11c59a0 100644 --- a/MirOTR/MirOTR.vcproj +++ b/MirOTR/MirOTR.vcproj @@ -280,34 +280,6 @@ RelativePath=".\dialogs.cpp" > - - - - - - - - - - - diff --git a/MirOTR/dialogs.cpp b/MirOTR/dialogs.cpp index a064a74..50c25aa 100644 --- a/MirOTR/dialogs.cpp +++ b/MirOTR/dialogs.cpp @@ -4,26 +4,304 @@ #include #include -static void VerifyFingerprint(ConnContext *context, bool verify) { - TCHAR msg[1024]; - if (verify) { - lib_cs_lock(); - otrl_context_set_trust(context->active_fingerprint, "verified"); - otrl_privkey_write_fingerprints(otr_user_state, g_fingerprint_store_filename); - lib_cs_unlock(); - mir_sntprintf(msg, 1024, TranslateT(LANG_FINGERPRINT_VERIFIED), contact_get_nameT((HANDLE)context->app_data)); - } else { - lib_cs_lock(); - otrl_context_set_trust(context->active_fingerprint, NULL); - otrl_privkey_write_fingerprints(otr_user_state, g_fingerprint_store_filename); - lib_cs_unlock(); - mir_sntprintf(msg, 1024, TranslateT(LANG_FINGERPRINT_NOT_VERIFIED), contact_get_nameT((HANDLE)context->app_data)); +struct SmpData { + HWND dialog; + TrustLevel oldlevel; + ConnContext *context; + bool responder; + TCHAR *question; +}; +typedef std::map SmpForContactMap; +SmpForContactMap smp_for_contact; + + +INT_PTR CALLBACK DlgSMPUpdateProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch ( msg ) { + case WM_INITDIALOG: + { + if (!lParam) { + EndDialog(hwndDlg, IDCANCEL); + return FALSE; + } + TranslateDialogDefault( hwndDlg ); + + SmpData *data = (SmpData*)lParam; + ConnContext *context = data->context; + data->dialog = hwndDlg; + //smp_for_contact.insert(SmpForContactMap::value_type(context->app_data, *data)); + if (smp_for_contact[context->app_data].dialog) SendMessage(smp_for_contact[context->app_data].dialog, WMU_REFRESHSMP, 0, 0); + smp_for_contact[context->app_data].context = data->context; + smp_for_contact[context->app_data].dialog = hwndDlg; + smp_for_contact[context->app_data].oldlevel = data->oldlevel; + smp_for_contact[context->app_data].responder = data->responder; + mir_free(data); + + TCHAR title[512], *proto = mir_a2t(contact_get_proto((HANDLE)context->app_data)); + const TCHAR *name =contact_get_nameT((HANDLE)context->app_data); + mir_sntprintf(title, 512, TranslateT(LANG_SMP_PROGRESS_TITLE), name, proto); + SendMessage(hwndDlg, WM_SETTEXT, 0, (LPARAM)title); + mir_sntprintf(title, 512, TranslateT(LANG_SMP_PROGRESS_DESC), name, proto); + mir_free(proto); + SetDlgItemText(hwndDlg, IDC_STC_SMP_HEADPRO, title); + SetWindowLongPtr(hwndDlg, GWL_USERDATA, (LONG_PTR)context); + + // Move window to screen center + // Get the owner window and dialog box rectangles. + HWND hwndOwner; RECT rcOwner, rcDlg, rc; + if ((hwndOwner = GetParent(hwndDlg)) == NULL) + { + hwndOwner = GetDesktopWindow(); + } + + GetWindowRect(hwndOwner, &rcOwner); + GetWindowRect(hwndDlg, &rcDlg); + CopyRect(&rc, &rcOwner); + + // Offset the owner and dialog box rectangles so that right and bottom + // values represent the width and height, and then offset the owner again + // to discard space taken up by the dialog box. + + OffsetRect(&rcDlg, -rcDlg.left, -rcDlg.top); + OffsetRect(&rc, -rc.left, -rc.top); + OffsetRect(&rc, -rcDlg.right, -rcDlg.bottom); + + // The new position is the sum of half the remaining space and the owner's + // original position. + + SetWindowPos(hwndDlg, + HWND_TOP, + rcOwner.left + (rc.right / 2), + rcOwner.top + (rc.bottom / 2), + 0, 0, // Ignores size arguments. + SWP_NOSIZE); + + // end center dialog + + SendDlgItemMessage(hwndDlg, IDC_PGB_SMP, PBM_SETRANGE, 0, MAKELONG(0, 100)); + SendDlgItemMessage(hwndDlg, IDC_PGB_SMP, PBM_SETPOS, 10, 0); + + EnableWindow(GetDlgItem(hwndDlg, IDCANCEL), true); + EnableWindow(GetDlgItem(hwndDlg, IDOK), false); + + return TRUE; + } + + case WMU_REFRESHSMP: + { + ConnContext *context = (ConnContext*)GetWindowLongPtr(hwndDlg, GWL_USERDATA); + SendDlgItemMessage(hwndDlg, IDC_PGB_SMP, PBM_SETPOS, wParam, 0); + switch (wParam) { + case 0: + EnableWindow(GetDlgItem(hwndDlg, IDCANCEL), false); + EnableWindow(GetDlgItem(hwndDlg, IDOK), true); + SetDlgItemText(hwndDlg, IDC_STC_SMP_PROGRESS, TranslateT(LANG_SMP_ERROR)); + smp_for_contact.erase(context->app_data); + break; + case 100: + { + EnableWindow(GetDlgItem(hwndDlg, IDCANCEL), false); + EnableWindow(GetDlgItem(hwndDlg, IDOK), true); + smp_for_contact.erase(context->app_data); + if (context->smstate->sm_prog_state == OTRL_SMP_PROG_SUCCEEDED) { + if (context->active_fingerprint->trust && + context->active_fingerprint->trust[0]) { + SetDlgItemText(hwndDlg, IDC_STC_SMP_PROGRESS, TranslateT(LANG_SMP_SUCCESS)); + } else { + SetDlgItemText(hwndDlg, IDC_STC_SMP_PROGRESS, TranslateT(LANG_SMP_SUCCESS_VERIFY)); + } + } else { + SetDlgItemText(hwndDlg, IDC_STC_SMP_PROGRESS, TranslateT(LANG_SMP_FAILED)); + } + } + break; + default: + SetDlgItemText(hwndDlg, IDC_STC_SMP_PROGRESS, _T("")); + } + } + + case WM_COMMAND: + switch ( HIWORD( wParam )) { + case BN_CLICKED: + { + ConnContext *context = (ConnContext*)GetWindowLongPtr(hwndDlg, GWL_USERDATA); + switch ( LOWORD( wParam )) { + case IDCANCEL: + otr_abort_smp(context); + //break; + case IDOK: + smp_for_contact.erase(context->app_data); + EndDialog(hwndDlg, LOWORD( wParam )); + break; + } + }break; + } + + } + + return FALSE; +} + +void SMPInitUpdateDialog(ConnContext *context, bool responder) { + if (!context) return; + SmpData *data = (SmpData*)mir_calloc(sizeof(SmpData)); + data->context = context; + data->oldlevel = otr_context_get_trust(context); + data->responder = responder; + CreateDialogParam(hInst, MAKEINTRESOURCE(IDD_SMP_PROGRESS), 0, DlgSMPUpdateProc, (LPARAM) data); +} + +INT_PTR CALLBACK DlgSMPResponseProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch ( msg ) { + case WM_INITDIALOG: + { + if (!lParam) { + EndDialog(hwndDlg, IDCANCEL); + return FALSE; + } + TranslateDialogDefault( hwndDlg ); + + SmpData *data = (SmpData*)lParam; + ConnContext *context = data->context; + data->dialog = hwndDlg; + //smp_for_contact.insert(SmpForContactMap::value_type(context->app_data, *data)); + if (smp_for_contact[context->app_data].dialog) SendMessage(smp_for_contact[context->app_data].dialog, WMU_REFRESHSMP, 0, 0); + smp_for_contact[context->app_data].context = data->context; + smp_for_contact[context->app_data].dialog = hwndDlg; + smp_for_contact[context->app_data].oldlevel = data->oldlevel; + smp_for_contact[context->app_data].responder = data->responder; + + TCHAR buff[512], *proto=mir_a2t(contact_get_proto(context->app_data)); + mir_sntprintf(buff, 512, TranslateT(LANG_SMP_VERIFY_TITLE), contact_get_nameT(context->app_data), proto); + mir_free(proto); + SendMessage(hwndDlg, WM_SETTEXT, 0, (LPARAM)buff); + SetDlgItemText(hwndDlg, IDC_STC_SMP_HEAD, buff); + SetWindowLongPtr(hwndDlg, GWL_USERDATA, (LONG_PTR)context); + + if (data->question) { + mir_sntprintf(buff, 512, TranslateT(LANG_OTR_SMPQUESTION_RESPOND_DESC), contact_get_nameT(context->app_data)); + + SetDlgItemText(hwndDlg, IDC_STC_SMP_INFO, buff); + + SetDlgItemText(hwndDlg, IDC_EDT_SMP_FIELD1, data->question); + SendDlgItemMessage(hwndDlg, IDC_EDT_SMP_FIELD1, EM_SETREADONLY, TRUE, 0); + SetDlgItemText(hwndDlg, IDC_STC_SMP_FIELD1, TranslateT(LANG_SMP_QUESTION)); + + SetDlgItemText(hwndDlg, IDC_EDT_SMP_FIELD2, _T("")); + SendDlgItemMessage(hwndDlg, IDC_EDT_SMP_FIELD2, EM_SETREADONLY, FALSE, 0); + SetDlgItemText(hwndDlg, IDC_STC_SMP_FIELD2, TranslateT(LANG_SMP_ANSWER)); + + + ShowWindow(GetDlgItem(hwndDlg, IDOK), SW_SHOWNA); + ShowWindow(GetDlgItem(hwndDlg, IDYES), SW_HIDE); + ShowWindow(GetDlgItem(hwndDlg, IDNO), SW_HIDE); + + mir_free(data->question); + } else { + mir_sntprintf(buff, 512, TranslateT(LANG_OTR_SMPPASSWORD_RESPOND_DESC), contact_get_nameT((HANDLE)context->app_data)); + + SetDlgItemText(hwndDlg, IDC_STC_SMP_INFO, buff); + + SetDlgItemText(hwndDlg, IDC_EDT_SMP_FIELD1, _T("")); + SendDlgItemMessage(hwndDlg, IDC_EDT_SMP_FIELD1, EM_SETREADONLY, TRUE, 0); + SetDlgItemText(hwndDlg, IDC_STC_SMP_FIELD1, _T("")); + + SetDlgItemText(hwndDlg, IDC_EDT_SMP_FIELD2, _T("")); + SendDlgItemMessage(hwndDlg, IDC_EDT_SMP_FIELD2, EM_SETREADONLY, FALSE, 0); + SetDlgItemText(hwndDlg, IDC_STC_SMP_FIELD2, TranslateT(LANG_SMP_PASSWORD)); + + + ShowWindow(GetDlgItem(hwndDlg, IDOK), SW_SHOWNA); + ShowWindow(GetDlgItem(hwndDlg, IDYES), SW_HIDE); + ShowWindow(GetDlgItem(hwndDlg, IDNO), SW_HIDE); + } + mir_free(data); + + // Move window to screen center + // Get the owner window and dialog box rectangles. + HWND hwndOwner; RECT rcOwner, rcDlg, rc; + if ((hwndOwner = GetParent(hwndDlg)) == NULL) + { + hwndOwner = GetDesktopWindow(); + } + + GetWindowRect(hwndOwner, &rcOwner); + GetWindowRect(hwndDlg, &rcDlg); + CopyRect(&rc, &rcOwner); + + // Offset the owner and dialog box rectangles so that right and bottom + // values represent the width and height, and then offset the owner again + // to discard space taken up by the dialog box. + + OffsetRect(&rcDlg, -rcDlg.left, -rcDlg.top); + OffsetRect(&rc, -rc.left, -rc.top); + OffsetRect(&rc, -rcDlg.right, -rcDlg.bottom); + + // The new position is the sum of half the remaining space and the owner's + // original position. + + SetWindowPos(hwndDlg, + HWND_TOP, + rcOwner.left + (rc.right / 2), + rcOwner.top + (rc.bottom / 2), + 0, 0, // Ignores size arguments. + SWP_NOSIZE); + + // end center dialog + + + + return TRUE; + } + + case WM_COMMAND: + switch ( HIWORD( wParam )) { + case BN_CLICKED: + { + ConnContext *context = (ConnContext *)GetWindowLongPtr(hwndDlg, GWL_USERDATA); + switch ( LOWORD( wParam )) { + case IDOK: + { + SMPInitUpdateDialog(context, true); + + int len = SendDlgItemMessage(hwndDlg, IDC_EDT_SMP_FIELD2, WM_GETTEXTLENGTH, 0, 0); + TCHAR *answer = new TCHAR[len+1]; + GetDlgItemText(hwndDlg, IDC_EDT_SMP_FIELD2, answer, len+1); + char *ans = mir_utf8encodeT(answer); + delete answer; + + otr_continue_smp(context, (const unsigned char *)ans, strlen(ans)); + mir_free(ans); + + EndDialog(hwndDlg, LOWORD( wParam )); + }break; + case IDCANCEL: + smp_for_contact.erase(context->app_data); + EndDialog(hwndDlg, LOWORD( wParam )); + break; + } + } + } + break; + } - msg[1023] = '\0'; - ShowMessage((HANDLE)context->app_data, msg); - SetEncryptionStatus(context->app_data, otr_context_get_trust(context)); + + return FALSE; } +/* +void SMPInitResponseDialog(ConnContext *context, const TCHAR *question) { + if (!context) return; + SmpData *data = (SmpData*)mir_calloc(sizeof(SmpData)); + data->context = context; + data->oldlevel = TRUST_NOT_PRIVATE; + data->responder = true; + data->question = (question) ? mir_tstrdup(question) : NULL; + CreateDialogParam(hInst, MAKEINTRESOURCE(IDD_SMP_INPUT), 0, DlgSMPResponseProc, (LPARAM) data); +} +*/ + INT_PTR CALLBACK DlgProcSMPInitProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) { switch ( msg ) { @@ -36,8 +314,14 @@ INT_PTR CALLBACK DlgProcSMPInitProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARA TranslateDialogDefault( hwndDlg ); ConnContext *context = (ConnContext*)lParam; - TCHAR title[512]; - mir_sntprintf(title, 512, TranslateT(LANG_SMP_VERIFY_TITLE), contact_get_nameT((HANDLE)context->app_data)); + if (smp_for_contact.find(context->app_data) != smp_for_contact.end()) { + EndDialog(hwndDlg, IDCANCEL); + return FALSE; + } + + TCHAR title[512], *proto = mir_a2t(contact_get_proto((HANDLE)context->app_data)); + mir_sntprintf(title, 512, TranslateT(LANG_SMP_VERIFY_TITLE), contact_get_nameT((HANDLE)context->app_data), proto); + mir_free(proto); SendMessage(hwndDlg, WM_SETTEXT, 0, (LPARAM)title); SetDlgItemText(hwndDlg, IDC_STC_SMP_HEAD, title); SetWindowLongPtr(hwndDlg, GWL_USERDATA, lParam); @@ -126,6 +410,11 @@ INT_PTR CALLBACK DlgProcSMPInitProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARA case IDOK: GetDlgItemText(hwndDlg, IDC_CBO_SMP_CHOOSE, msg, 255); if (_tcsncmp(msg, TranslateT(LANG_SMPTYPE_QUESTION), 255)==0) { + if (smp_for_contact.find(context->app_data) != smp_for_contact.end()) { + TCHAR msg[512]; + mir_sntprintf(msg, 512, TranslateT(LANG_SMP_IN_PROGRESS), contact_get_nameT((HANDLE)context->app_data)); + ShowError(msg); + }else { int len = SendDlgItemMessage(hwndDlg, IDC_EDT_SMP_FIELD1, WM_GETTEXTLENGTH, 0, 0); TCHAR *question = new TCHAR[len+1]; GetDlgItemText(hwndDlg, IDC_EDT_SMP_FIELD1, question, len+1); @@ -138,19 +427,28 @@ INT_PTR CALLBACK DlgProcSMPInitProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARA char *ans = mir_utf8encodeT(answer); delete answer; + SMPInitUpdateDialog(context, false); otr_start_smp(context, quest, (const unsigned char*)ans, strlen(ans)); mir_free(quest); mir_free(ans); + } }else if (_tcsncmp(msg, TranslateT(LANG_SMPTYPE_PASSWORD), 255)==0) { + if (smp_for_contact.find(context->app_data) != smp_for_contact.end()) { + TCHAR msg[512]; + mir_sntprintf(msg, 512, TranslateT(LANG_SMP_IN_PROGRESS), contact_get_nameT((HANDLE)context->app_data)); + ShowError(msg); + }else { int len = SendDlgItemMessage(hwndDlg, IDC_EDT_SMP_FIELD2, WM_GETTEXTLENGTH, 0, 0); TCHAR *answer = new TCHAR[len+1]; GetDlgItemText(hwndDlg, IDC_EDT_SMP_FIELD2, answer, len+1); char *ans = mir_utf8encodeT(answer); delete answer; + SMPInitUpdateDialog(context, false); otr_start_smp(context, NULL, (const unsigned char*)ans, strlen(ans)); mir_free(ans); + } }else break; EndDialog(hwndDlg, LOWORD( wParam )); @@ -183,9 +481,9 @@ INT_PTR CALLBACK DlgProcSMPInitProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARA GetDlgItemText(hwndDlg, IDC_CBO_SMP_CHOOSE, buff, 255); if (_tcsncmp(buff, TranslateT(LANG_SMPTYPE_QUESTION), 255)==0) { if (trusted) - mir_sntprintf(buff, 512, TranslateT(LANG_OTR_SMPQUESTION_VERIFY_DESC), contact_get_nameT((HANDLE)context->app_data)); - else mir_sntprintf(buff, 512, TranslateT(LANG_OTR_SMPQUESTION_VERIFIED_DESC), contact_get_nameT((HANDLE)context->app_data)); + else + mir_sntprintf(buff, 512, TranslateT(LANG_OTR_SMPQUESTION_VERIFY_DESC), contact_get_nameT((HANDLE)context->app_data)); SetDlgItemText(hwndDlg, IDC_STC_SMP_INFO, buff); @@ -203,9 +501,9 @@ INT_PTR CALLBACK DlgProcSMPInitProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARA ShowWindow(GetDlgItem(hwndDlg, IDNO), SW_HIDE); } else if (_tcsncmp(buff, TranslateT(LANG_SMPTYPE_PASSWORD), 255)==0) { if (trusted) - mir_sntprintf(buff, 512, TranslateT(LANG_OTR_SMPPASSWORD_VERIFY_DESC), contact_get_nameT((HANDLE)context->app_data)); - else mir_sntprintf(buff, 512, TranslateT(LANG_OTR_SMPPASSWORD_VERIFIED_DESC), contact_get_nameT((HANDLE)context->app_data)); + else + mir_sntprintf(buff, 512, TranslateT(LANG_OTR_SMPPASSWORD_VERIFY_DESC), contact_get_nameT((HANDLE)context->app_data)); SetDlgItemText(hwndDlg, IDC_STC_SMP_INFO, buff); @@ -223,9 +521,9 @@ INT_PTR CALLBACK DlgProcSMPInitProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARA ShowWindow(GetDlgItem(hwndDlg, IDNO), SW_HIDE); } else if (_tcsncmp(buff, TranslateT(LANG_SMPTYPE_FINGERPRINT), 255)==0) { if (trusted) - mir_sntprintf(buff, 512, TranslateT(LANG_OTR_FPVERIFY_DESC), contact_get_nameT((HANDLE)context->app_data)); - else mir_sntprintf(buff, 512, TranslateT(LANG_OTR_FPVERIFIED_DESC), contact_get_nameT((HANDLE)context->app_data)); + else + mir_sntprintf(buff, 512, TranslateT(LANG_OTR_FPVERIFY_DESC), contact_get_nameT((HANDLE)context->app_data)); SetDlgItemText(hwndDlg, IDC_STC_SMP_INFO, buff); @@ -267,6 +565,19 @@ void SMPInitDialog(ConnContext* context) { } void SMPDialogUpdate(ConnContext *context, int percent) { + if (!context) return; + SmpForContactMap::iterator it = smp_for_contact.find(context->app_data); + if (it == smp_for_contact.end()) return; + if (it->second.dialog) PostMessage(it->second.dialog, WMU_REFRESHSMP, percent, 0); + TrustLevel level = otr_context_get_trust(context); + if (!it->second.responder && it->second.oldlevel != level) { + if (level == TRUST_PRIVATE) + VerifyFingerprintMessage(context, true); + else if (level == TRUST_UNVERIFIED) + VerifyFingerprintMessage(context, false); + } + //if (percent == 100) + /* switch (percent){ case 0: VerifyFingerprint(context, false); @@ -279,10 +590,19 @@ void SMPDialogUpdate(ConnContext *context, int percent) { default: ShowWarning(_T("Received an SMP update")); } + */ } void SMPDialogReply(ConnContext *context, const char* question){ + SmpData *data = (SmpData*)mir_calloc(sizeof(SmpData)); + data->context = context; + data->oldlevel = TRUST_NOT_PRIVATE; + data->responder = true; + data->question = (question) ? mir_utf8decodeT(question) : NULL; + CreateDialogParam(hInst, MAKEINTRESOURCE(IDD_SMP_INPUT), 0, DlgSMPResponseProc, (LPARAM) data); + /* ShowError(_T("SMP requires user password (NOT IMPL YET)")); otr_abort_smp(context); + */ //otr_continue_smp(context, pass, strlen(pass)); } diff --git a/MirOTR/dialogs.h b/MirOTR/dialogs.h index 27593db..0422dc3 100644 --- a/MirOTR/dialogs.h +++ b/MirOTR/dialogs.h @@ -3,4 +3,6 @@ void VerifyContextDialog(ConnContext* context); void SMPInitDialog(ConnContext* context); INT_PTR CALLBACK DlgProcVerifyContext(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam); void SMPDialogUpdate(ConnContext *context, int percent); -void SMPDialogReply(ConnContext *context, const char* question); \ No newline at end of file +void SMPDialogReply(ConnContext *context, const char* question); + +#define WMU_REFRESHSMP (WM_USER + 245) \ No newline at end of file diff --git a/MirOTR/language.h b/MirOTR/language.h index 1e6b81a..952a41f 100644 --- a/MirOTR/language.h +++ b/MirOTR/language.h @@ -85,19 +85,32 @@ #define LANG_YOUR_PRIVKEY LPGEN("Your Fingerprint to tell your contact (use a trusted channel!)") #define LANG_CONTACT_FINGERPRINT LPGEN("VERIFY: Fingerprint from contact") -#define LANG_SMP_VERIFY_TITLE LPGEN("OTR Authenticate %s") -#define LANG_SMPTYPE_QUESTION LPGEN("Question / Answer") +#define LANG_SMP_VERIFY_TITLE LPGEN("OTR Authenticate: %s (%s)") +#define LANG_SMPTYPE_QUESTION LPGEN("Challenge Question") #define LANG_SMPTYPE_PASSWORD LPGEN("Known Password") #define LANG_SMPTYPE_FINGERPRINT LPGEN("Manual fingerprint comparison") -#define LANG_SMP_ANSWER LPGEN("Answer") +#define LANG_SMP_ANSWER LPGEN("Secret Answer") #define LANG_SMP_QUESTION LPGEN("Question") #define LANG_SMP_PASSWORD LPGEN("Password") +#define LANG_SMP_SUCCESS LPGEN("Authentication sucessful.") +#define LANG_SMP_SUCCESS_VERIFY LPGEN("You contact authenticated you sucessful. You can send your own request to authenticate him.") +#define LANG_SMP_ERROR LPGEN("Error during authentication.") +#define LANG_SMP_FAILED LPGEN("Authentication failed") +#define LANG_SMP_IN_PROGRESS LPGEN("Authentication for '%s' is already in progress.") + +#define LANG_SMP_PROGRESS_TITLE LPGEN("OTR Authenticating: %s (%s)") +#define LANG_SMP_PROGRESS_DESC LPGEN("Authenticating contact:\n%s (%s)") + #define LANG_OTR_SMPQUESTION_VERIFY_DESC LPGEN("OTR encrypted session with '%s' (UNVERIFIED).\nUse a question only your partner can answer.") #define LANG_OTR_SMPQUESTION_VERIFIED_DESC LPGEN("OTR encrypted session with '%s' (VERIFIED).\nVerify the session again using a question only your partner can answer.") #define LANG_OTR_SMPPASSWORD_VERIFY_DESC LPGEN("OTR encrypted session with '%s' (UNVERIFIED).\nUse a known password.") #define LANG_OTR_SMPPASSWORD_VERIFIED_DESC LPGEN("OTR encrypted session with '%s' (VERIFIED).\nVerify the session again using a known password.") -#define LANG_FINGERPRINT_STILL_IN_USE LPGEN("Fingerprint '%s' still in use in conversation with '%s'. You cannot delete it!") -#define LANG_FINGERPRINT_NOT_DELETED LPGEN("Fingerprint '%s' in use in conversation with '%s'. It could not be deleted!") \ No newline at end of file +#define LANG_OTR_SMPQUESTION_RESPOND_DESC LPGEN("Your contact '%s' wants to verify your identity with a question only you can answer.") + +#define LANG_OTR_SMPPASSWORD_RESPOND_DESC LPGEN("Your contact '%s' wants to verify your identity with a secret password you should know.") + +#define LANG_FINGERPRINT_STILL_IN_USE LPGEN("Fingerprint '%s' still in use in conversation with '%s' (%s). You cannot delete it!") +#define LANG_FINGERPRINT_NOT_DELETED LPGEN("Fingerprint '%s' in use in conversation with '%s' (%s). It could not be deleted!") \ No newline at end of file diff --git a/MirOTR/options.cpp b/MirOTR/options.cpp index 993f7fd..8672071 100644 --- a/MirOTR/options.cpp +++ b/MirOTR/options.cpp @@ -848,12 +848,14 @@ static INT_PTR CALLBACK DlgProcMirOTROptsFinger(HWND hwndDlg, UINT msg, WPARAM w case FPM_VERIFY: otrl_context_set_trust(it->first, "verified"); if (it->first == it->first->context->active_fingerprint) - SetEncryptionStatus((HANDLE)it->first->context->app_data, otr_context_get_trust(it->first->context)); + VerifyFingerprint(it->first->context, true); + //SetEncryptionStatus((HANDLE)it->first->context->app_data, otr_context_get_trust(it->first->context)); break; case FPM_NOTRUST: otrl_context_set_trust(it->first, NULL); if (it->first == it->first->context->active_fingerprint) - SetEncryptionStatus((HANDLE)it->first->context->app_data, otr_context_get_trust(it->first->context)); + VerifyFingerprint(it->first->context, false); + //SetEncryptionStatus((HANDLE)it->first->context->app_data, otr_context_get_trust(it->first->context)); break; } } diff --git a/MirOTR/otr.cpp b/MirOTR/otr.cpp index f409e03..eb6728c 100644 --- a/MirOTR/otr.cpp +++ b/MirOTR/otr.cpp @@ -108,7 +108,7 @@ extern "C" { //QueueUserAPC(newKeyAPC, Global::mainThread, (DWORD)nkd); if (opdata) protocol = contact_get_proto((HANDLE)opdata); if (!protocol) return; - DialogBoxParamW(hInst, MAKEINTRESOURCE(IDD_GENKEYNOTIFY), 0, GenKeyDlgFunc, (LPARAM)protocol ); + DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_GENKEYNOTIFY), 0, GenKeyDlgFunc, (LPARAM)protocol ); } @@ -314,8 +314,11 @@ extern "C" { } int max_message_size(void *opdata, ConnContext *context) { - int s = CallProtoService(context->protocol, PS_GETCAPS, PFLAG_MAXLENOFMESSAGE, 0); - return s; + // ugly wokaround for ICQ. ICQ protocol reports more than 7k, but in SMP this is too long. + // possibly ICQ doesn't allow single words without spaces to become longer than ~2340? + if (strcmp("ICQ", context->protocol)==0 || strncmp("ICQ_", context->protocol, 4)==0) + return 2340; + return CallProtoService(context->protocol, PS_GETCAPS, PFLAG_MAXLENOFMESSAGE, (LPARAM)context->app_data); } const char *account_name(void *opdata, const char *account, const char *protocol) { diff --git a/MirOTR/resources/resource.rc b/MirOTR/resources/resource.rc index 35564ac..eea7258 100644 --- a/MirOTR/resources/resource.rc +++ b/MirOTR/resources/resource.rc @@ -110,6 +110,7 @@ BEGIN CONTROL "",IDC_PGB_SMP,"msctls_progress32",WS_CHILDWINDOW|WS_VISIBLE|PBS_SMOOTH,3,36,194,18 CONTROL "",IDC_STC_SMP_PROGRESS,"Static",WS_CHILDWINDOW|WS_VISIBLE,3,57,194,20 CONTROL "&Cancel",IDCANCEL,"Button",WS_CHILDWINDOW|WS_VISIBLE|WS_TABSTOP,70,80,60,16 + CONTROL "&OK",IDOK,"Button",WS_CHILDWINDOW|WS_VISIBLE|WS_TABSTOP,135,80,60,16 END IDD_SMP_INPUT DIALOGEX 10,10,200,200 @@ -120,7 +121,7 @@ BEGIN CONTROL IDI_OTR,IDC_ICO_SMP,"Static",WS_CHILDWINDOW|WS_VISIBLE|SS_CENTERIMAGE|SS_ICON,3,3,32,32 CONTROL "Socialist Millionaires Protocol\r\nVerification",IDC_STC_SMP_HEAD,"Static",WS_CHILDWINDOW|WS_VISIBLE|SS_NOPREFIX,39,9,156,21 CONTROL "",IDC_CBO_SMP_CHOOSE,"ComboBox",WS_CHILDWINDOW|WS_VISIBLE|WS_TABSTOP|CBS_HASSTRINGS|CBS_DROPDOWNLIST,3,36,194,60 - CONTROL "",IDC_STC_SMP_INFO,"Static",WS_CHILDWINDOW|WS_VISIBLE,3,60,195,35 + CONTROL "",IDC_STC_SMP_INFO,"Static",WS_CHILDWINDOW|WS_VISIBLE,3,60,194,35 CONTROL "",IDC_STC_SMP_FIELD1,"Static",WS_CHILDWINDOW|WS_VISIBLE,3,105,194,10 CONTROL "",IDC_EDT_SMP_FIELD1,"Edit",WS_CHILDWINDOW|WS_VISIBLE|WS_TABSTOP,3,117,194,13,WS_EX_CLIENTEDGE CONTROL "",IDC_STC_SMP_FIELD2,"Static",WS_CHILDWINDOW|WS_VISIBLE,3,141,194,10 diff --git a/MirOTR/svcs_proto.cpp b/MirOTR/svcs_proto.cpp index 2d2bde6..6e78a23 100644 --- a/MirOTR/svcs_proto.cpp +++ b/MirOTR/svcs_proto.cpp @@ -14,9 +14,8 @@ int SVC_OTRSendMessage(WPARAM wParam,LPARAM lParam){ char *proto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)ccs->hContact, 0); if(proto && g_metaproto && strcmp(proto, g_metaproto) == 0) // bypass for metacontacts - return CallService(MS_PROTO_CHAINSEND, wParam, lParam); - char *username = contact_get_id(ccs->hContact); - if(!proto || !username) return 1; // error + return CallService(MS_PROTO_CHAINSEND, wParam, lParam); + if(!proto || !ccs->hContact) return 1; // error gcry_error_t err; char *newmessage = 0; @@ -43,7 +42,8 @@ int SVC_OTRSendMessage(WPARAM wParam,LPARAM lParam){ if (!(ccs->wParam & PREF_UTF)) mir_free(oldmessage_utf); return CallService(MS_PROTO_CHAINSEND, wParam, lParam); } - + + char *username = contact_get_id(ccs->hContact); err = otrl_message_sending(otr_user_state, &ops, (void*)ccs->hContact, proto, proto, username, oldmessage_utf, NULL, &newmessage, add_appdata, (void*)ccs->hContact); @@ -148,9 +148,8 @@ int SVC_OTRRecvMessage(WPARAM wParam,LPARAM lParam){ return 1; //error else if(proto && g_metaproto && strcmp(proto, g_metaproto) == 0) // bypass for metacontacts return CallService(MS_PROTO_CHAINRECV, wParam, lParam); - - char *uname = contact_get_id(ccs->hContact); - if(!uname) return 1; // error + + if (!ccs->hContact) return 1; //error char *oldmessage = pre->szMessage; char *oldmessage_utf = NULL; @@ -172,11 +171,13 @@ int SVC_OTRRecvMessage(WPARAM wParam,LPARAM lParam){ ConnContext *context; //NextExpectedSMP nextMsg; + char *uname = contact_get_id(ccs->hContact); lib_cs_lock(); ignore_msg = otrl_message_receiving(otr_user_state, &ops, (void*)ccs->hContact, proto, proto, uname, oldmessage_utf, &newmessage, &tlvs, add_appdata, (void*)ccs->hContact); lib_cs_unlock(); + mir_free(uname); if( !(pre->flags & PREF_UTF)) mir_free(oldmessage_utf); oldmessage_utf = NULL; @@ -282,8 +283,6 @@ int SVC_OTRRecvMessage(WPARAM wParam,LPARAM lParam){ } otrl_tlv_free(tlvs); - mir_free(uname); - /* If we're supposed to ignore this incoming message (because it's a * protocol message), set it to NULL, so that other plugins that * catch receiving-im-msg don't return 0, and cause it to be diff --git a/MirOTR/utils.cpp b/MirOTR/utils.cpp index 59dd5b2..6fe6dde 100644 --- a/MirOTR/utils.cpp +++ b/MirOTR/utils.cpp @@ -71,6 +71,23 @@ TrustLevel otr_context_get_trust(ConnContext *context) return level; } +/* Set verification of fingerprint */ +void VerifyFingerprint(ConnContext *context, bool verify) { + lib_cs_lock(); + otrl_context_set_trust(context->active_fingerprint, (verify)?"verified":NULL); + otrl_privkey_write_fingerprints(otr_user_state, g_fingerprint_store_filename); + lib_cs_unlock(); + VerifyFingerprintMessage(context, verify); +} + +void VerifyFingerprintMessage(ConnContext *context, bool verify) { + TCHAR msg[1024]; + mir_sntprintf(msg, 1024, (verify)?TranslateT(LANG_FINGERPRINT_VERIFIED):TranslateT(LANG_FINGERPRINT_NOT_VERIFIED), contact_get_nameT((HANDLE)context->app_data)); + msg[1023] = '\0'; + ShowMessage((HANDLE)context->app_data, msg); + SetEncryptionStatus(context->app_data, otr_context_get_trust(context)); +} + /* Convert a 20-byte hash value to a 45-byte human-readable value */ void otrl_privkey_hash_to_humanT(TCHAR human[45], const unsigned char hash[20]) { diff --git a/MirOTR/utils.h b/MirOTR/utils.h index ac1ad1b..5dc0526 100644 --- a/MirOTR/utils.h +++ b/MirOTR/utils.h @@ -17,6 +17,8 @@ typedef enum { TRUST_PRIVATE } TrustLevel; TrustLevel otr_context_get_trust(ConnContext *context); +void VerifyFingerprint(ConnContext *context, bool verify); +void VerifyFingerprintMessage(ConnContext *context, bool verify); void otrl_privkey_hash_to_humanT(TCHAR human[45], const unsigned char hash[20]); diff --git a/MirOTR/version.h b/MirOTR/version.h index 04ace48..9f34a9e 100644 --- a/MirOTR/version.h +++ b/MirOTR/version.h @@ -8,7 +8,7 @@ #define VER_BUILD 1 #define __STRINGIZE(x) #x -#define VER_STRING "0.9.1.1" +#define VER_STRING "0.9.4.1" #ifdef _UNICODE #define SHORT_NAME_STRING "Miranda OTR" -- cgit v1.2.3