diff options
Diffstat (limited to 'plugins/MirOTR/src/otr.cpp')
-rw-r--r-- | plugins/MirOTR/src/otr.cpp | 781 |
1 files changed, 390 insertions, 391 deletions
diff --git a/plugins/MirOTR/src/otr.cpp b/plugins/MirOTR/src/otr.cpp index 92608222b5..ba91ff8594 100644 --- a/plugins/MirOTR/src/otr.cpp +++ b/plugins/MirOTR/src/otr.cpp @@ -1,391 +1,390 @@ -#include "stdafx.h"
-
-OtrlUserState otr_user_state;
-#define WMU_ENDDIALOG (WM_USER+244)
-
-OtrlMessageAppOps ops = {
- otr_gui_policy,
- otr_gui_create_privkey,
- otr_gui_is_logged_in,
- otr_gui_inject_message,
- otr_gui_notify,
- otr_gui_display_otr_message,
- otr_gui_update_context_list,
- otr_gui_protocol_name,
- otr_gui_protocol_name_free,
- otr_gui_new_fingerprint,
- otr_gui_write_fingerprints,
- otr_gui_gone_secure,
- otr_gui_gone_insecure,
- otr_gui_still_secure,
- otr_gui_log_message,
- max_message_size,
- account_name,
- account_name_free
-};
-
-struct GenKeyData{
- HWND dialog;
- const char *proto;
-};
-
-static unsigned int CALLBACK generate_key_thread(void* param)
-{
- Thread_Push(0);
- GenKeyData *data = (GenKeyData *)param;
- //lib_cs_lock();
- otrl_privkey_generate(otr_user_state, g_private_key_filename, data->proto, data->proto);
- //lib_cs_unlock();
- PostMessage(data->dialog, WMU_ENDDIALOG, 0, 0);
- mir_free(data);
- Thread_Pop();
- return 0;
-}
-
-INT_PTR CALLBACK GenKeyDlgFunc(HWND hWndDlg, UINT msg, WPARAM wParam, LPARAM lParam) {
- switch(msg) {
- case WM_INITDIALOG:
- {
- if (!lParam) {
- EndDialog(hWndDlg, 0);
- return 0;
- }
- TranslateDialogDefault(hWndDlg);
- SetClassLongPtr(hWndDlg, GCLP_HICON, (LONG_PTR)LoadIcon(ICON_OTR,1) );
- TCHAR buff[256];
- TCHAR *proto = mir_a2t((char*)lParam);
- mir_sntprintf(buff, SIZEOF(buff), TranslateT(LANG_GENERATE_KEY), proto);
- mir_free(proto);
- SetDlgItemText(hWndDlg, IDC_GENERATE, buff);
- GenKeyData *data = (GenKeyData *)mir_calloc(sizeof(GenKeyData));
- data->dialog = hWndDlg;
- data->proto = (char*)lParam;
- CloseHandle((HANDLE)_beginthreadex(0, 0, generate_key_thread, (void*)data, 0, 0));
- }break;
- case WMU_ENDDIALOG:
- EndDialog(hWndDlg, 0);
- return TRUE;
- case WM_DESTROY:
- SetClassLongPtr(hWndDlg, GCLP_HICON, 0);
- ReleaseIcon(ICON_OTR,1);
- }
- return FALSE;
-}
-
-extern "C" {
- /* Return the OTR policy for the given context. */
- OtrlPolicy otr_gui_policy(void *opdata, ConnContext *context) {
- DEBUGOUT_T("OTR_GUI_POLICY")
- MCONTACT hContact = (MCONTACT)opdata;
- DWORD pol;
- if(hContact) {
- pol = db_get_dw(hContact, MODULENAME, "Policy", CONTACT_DEFAULT_POLICY);
- if (options.bHaveSecureIM && pol != OTRL_POLICY_MANUAL_MOD && pol != OTRL_POLICY_NEVER && db_get_b(hContact, "SecureIM" , "StatusID", 0)) {
- // if SecureIM is not disabled for this contact, MirOTR will be set to manual
- db_set_dw(hContact, MODULENAME, "Policy", OTRL_POLICY_MANUAL_MOD);
- return OTRL_POLICY_MANUAL_MOD;
- }
- if(pol != CONTACT_DEFAULT_POLICY) return pol ;
- }
- if(context->protocol) {
- pol = db_get_dw(0,MODULENAME"_ProtoPol", context->protocol, CONTACT_DEFAULT_POLICY);
- if(pol != CONTACT_DEFAULT_POLICY) return pol ;
- }
-
- return options.default_policy ;
- }
-
- /* Create a private key for the given accountname/protocol if
- * desired. */
- void otr_gui_create_privkey(void *opdata, const char *account_name, const char *protocol) {
- DEBUGOUT_T("OTR_GUI_CREATE_PRIVKEY")
- //if(MessageBox(0, Translate("Would you like to generate a new private key for this protocol?"), Translate("OTR"), MB_YESNO) == IDYES)
- //if(options.err_method == ED_POP)
- //ShowPopup(Translate("Generating new private key."), 0 /*Translate("Please wait.")*/, 5);
-
- //NewKeyData *nkd = (NewKeyData *)malloc(sizeof(NewKeyData));
- //nkd->account_name = strdup(account_name);
- //nkd->protocol = strdup(protocol);
-
- //DWORD tid;
- //CloseHandle(CreateThread(0, 0, newKeyThread, (VOID *)nkd, 0, &tid));
- //QueueUserAPC(newKeyAPC, Global::mainThread, (DWORD)nkd);
- if (opdata) protocol = GetContactProto((MCONTACT)opdata);
- if (!protocol) return;
- DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_GENKEYNOTIFY), 0, GenKeyDlgFunc, (LPARAM)protocol );
-
- }
-
- /* Report whether you think the given user is online. Return 1 if
- * you think he is, 0 if you think he isn't, -1 if you're not sure.
- *
- * If you return 1, messages such as heartbeats or other
- * notifications may be sent to the user, which could result in "not
- * logged in" errors if you're wrong. */
- int otr_gui_is_logged_in(void *opdata, const char *accountname, const char *protocol, const char *recipient) {
- DEBUGOUT_T("OTR_GUI_IS_LOGGED_IN")
- MCONTACT hContact = (MCONTACT)opdata;
- if(hContact) {
- WORD status = db_get_w(hContact, GetContactProto(hContact), "Status", ID_STATUS_OFFLINE);
- if(status == ID_STATUS_OFFLINE) return 0;
- else return 1;
- }
-
- return -1;
- }
-
- /* Send the given IM to the given recipient from the given
- * accountname/protocol. */
- void otr_gui_inject_message(void *opdata, const char *accountname, const char *protocol, const char *recipient, const char *message) {
- DEBUGOUT_T("OTR_GUI_INJECT_MESSAGE")
- //MessageBox(0, message, "OTR Inject", MB_OK);
- MCONTACT hContact = (MCONTACT)opdata;
-
- if(protocol && db_get_w(hContact, protocol, "Status", ID_STATUS_OFFLINE) != ID_STATUS_OFFLINE)
- CallContactService(hContact, PSS_MESSAGE, PREF_UTF|PREF_BYPASS_OTR, (LPARAM)message);
- }
-
- /* Display a notification message for a particular accountname /
- * protocol / username conversation. */
- void otr_gui_notify(void *opdata, OtrlNotifyLevel level, const char *accountname, const char *protocol, const char *username, const char *title, const char *primary, const char *secondary) {
- DEBUGOUT_T("OTR_GUI_NOTIFY")
- MCONTACT hContact = (MCONTACT) opdata;
- const TCHAR* uname = contact_get_nameT(hContact);
- TCHAR* title_t = mir_utf8decodeT(title);
- TCHAR *notify = TranslateT(LANG_OTR_NOTIFY);
-
- size_t len = _tcslen(uname) + _tcslen(title_t) + _tcslen(notify);
- TCHAR *buff1 = new TCHAR[len];
- mir_sntprintf(buff1, len, notify, TranslateTS(title_t), uname);
- mir_free(title_t);
-
- len = strlen(primary) + strlen(secondary) + 5;
- char *buff2 = new char[len];
- mir_snprintf(buff2, len, "%s\n%s", Translate(primary), Translate(secondary));
- TCHAR* buff2_t = mir_utf8decodeT(buff2);
- delete[] buff2;
-
- DEBUGOUT_T("OTR_GUI_NOTIFY")
-
- ShowPopup(buff1, buff2_t, 0);
- mir_free(buff2_t);
- delete buff1;
- }
-
- /* Display an OTR control message for a particular accountname /
- * protocol / username conversation. Return 0 if you are able to
- * successfully display it. If you return non-0 (or if this
- * function is NULL), the control message will be displayed inline,
- * as a received message, or else by using the above notify()
- * callback. */
- int otr_gui_display_otr_message(void *opdata, const char *accountname, const char *protocol, const char *username, const char *msg) {
- MCONTACT hContact = (MCONTACT) opdata;
- DEBUGOUT_T("OTR_GUI_DISPLAY_OTR_MESSAGE")
- if(options.msg_inline)
- ShowMessageInlineUtf(hContact, Translate(msg));
- if(options.msg_popup) {
- TCHAR buff[512];
- TCHAR* proto = mir_a2t(protocol);
- mir_sntprintf(buff, SIZEOF(buff), TranslateT(LANG_OTR_USERMESSAGE), contact_get_nameT(hContact), proto);
- mir_free(proto);
- TCHAR *msg_t = mir_utf8decodeT(msg);
- ShowPopup(buff, TranslateTS(msg_t), 0);
- mir_free(msg_t);
- }
- return 0;
- }
-
- /* When the list of ConnContexts changes (including a change in
- * state), this is called so the UI can be updated. */
- void otr_gui_update_context_list(void *opdata) {
- //MessageBox(0, "Update Context List", "OTR Callback", MB_OK);
- DEBUGOUT_T("OTR: Update Context List");
- }
-
- /* Return a newly-allocated string containing a human-friendly name
- * for the given protocol id */
- const char *otr_gui_protocol_name(void *opdata, const char *protocol) {
- //return strdup(protocol);
- DEBUGOUT_T("OTR_GUI_PROTOCOL_NAME")
- return protocol;
- }
-
- /* Deallocate a string allocated by protocol_name */
- void otr_gui_protocol_name_free(void *opdata, const char *protocol_name) {
- //free((void *)protocol_name);
- }
-
- /* A new fingerprint for the given user has been received. */
- void otr_gui_new_fingerprint(void *opdata, OtrlUserState us, const char *accountname, const char *protocol, const char *username, unsigned char fingerprint[20]) {
- DEBUGOUT_T("OTR_GUI_NEW_FUNGERPRINT")
- ConnContext *context = otrl_context_find(us, username, accountname, protocol, TRUE, 0, add_appdata, opdata);
- Fingerprint *fp = otrl_context_find_fingerprint(context, fingerprint, TRUE, 0);
-
- //CloseHandle((HANDLE)_beginthreadex(0, 0, trust_fp_thread, (void *)fp, 0, 0));
-
- otrl_context_set_trust(fp, NULL);
- otrl_privkey_write_fingerprints(otr_user_state, g_fingerprint_store_filename);
- }
-
- /* The list of known fingerprints has changed. Write them to disk. */
- void otr_gui_write_fingerprints(void *opdata) {
- DEBUGOUT_T("OTR_GUI_WRITE_FINGERPRINTS")
- //if(MessageBox(0, Translate("Would you like to save the current fingerprint list?"), Translate(MODULE), MB_YESNO) == IDYES)
- otrl_privkey_write_fingerprints(otr_user_state, g_fingerprint_store_filename);
- }
-
- /* A ConnContext has entered a secure state. */
- void otr_gui_gone_secure(void *opdata, ConnContext *context) {
- DEBUGOUT_T("OTR_GUI_GONE_SECURE")
- MCONTACT hContact = (MCONTACT) opdata;
- TrustLevel trusted = otr_context_get_trust(context);
- // opdata is hContact
- SetEncryptionStatus(hContact, trusted);
- TCHAR buff[1024];
- if(trusted == TRUST_PRIVATE) {
- mir_sntprintf(buff, SIZEOF(buff), TranslateT(LANG_SESSION_START_OTR), contact_get_nameT(hContact));
- } else if (trusted == TRUST_UNVERIFIED) {
- if (options.autoshow_verify) SMPInitDialog(context); //VerifyContextDialog(context);
- mir_sntprintf(buff, SIZEOF(buff), TranslateT(LANG_SESSION_START_OTR_VERIFY), contact_get_nameT(hContact));
- } else { // should never happen
- mir_sntprintf(buff, SIZEOF(buff), TranslateT(LANG_SESSION_NOT_STARTED_OTR), contact_get_nameT(hContact));
- }
- // opdata is hContact
- ShowMessage(hContact, buff);
-
- }
-
- /* A ConnContext has left a secure state. */
- void otr_gui_gone_insecure(void *opdata, ConnContext *context) {
- MCONTACT hContact = (MCONTACT) opdata;
- DEBUGOUT_T("OTR_GUI_GONE_INSECURE")
- TCHAR buff[512];
- mir_sntprintf(buff, SIZEOF(buff), TranslateT(LANG_SESSION_TERMINATED_BY_OTR), contact_get_nameT(hContact));
- //MessageBox(0, buff, Translate("OTR Information"), MB_OK);
- if (!Miranda_Terminated()) {
- ShowMessage(hContact, buff);
- }
-
- // opdata is hContact
- SetEncryptionStatus(hContact, otr_context_get_trust(context));
- }
-
- /* We have completed an authentication, using the D-H keys we
- * already knew. is_reply indicates whether we initiated the AKE. */
- void otr_gui_still_secure(void *opdata, ConnContext *context, int is_reply) {
- MCONTACT hContact = (MCONTACT) opdata;
- DEBUGOUT_T("OTR_GUI_STILL_SECURE")
- TrustLevel trusted = otr_context_get_trust(context);
- SetEncryptionStatus(hContact, trusted);
- TCHAR buff[1024];
- if (!is_reply) {
- if(trusted == TRUST_PRIVATE) {
- mir_sntprintf(buff, SIZEOF(buff), TranslateT(LANG_SESSION_CONTINUE_OTR), contact_get_nameT(hContact));
- } else if (trusted == TRUST_UNVERIFIED) {
- if (options.autoshow_verify) SMPInitDialog(context); //VerifyContextDialog(context);
- mir_sntprintf(buff, SIZEOF(buff), TranslateT(LANG_SESSION_CONTINUE_OTR_VERIFY), contact_get_nameT(hContact));
- } else { // should never happen
- mir_sntprintf(buff, SIZEOF(buff), TranslateT(LANG_SESSION_NOT_STARTED_OTR), contact_get_nameT(hContact));
- }
- // opdata is hContact
- ShowMessage(hContact, buff);
- } else {
- if(trusted == TRUST_PRIVATE) {
- mir_sntprintf(buff, SIZEOF(buff), TranslateT(LANG_SESSION_HAS_CONTINUE_OTR), contact_get_nameT(hContact));
- } else if (trusted == TRUST_UNVERIFIED) {
- mir_sntprintf(buff, SIZEOF(buff), TranslateT(LANG_SESSION_HAS_CONTINUE_OTR_VERIFY), contact_get_nameT(hContact));
- } else { // should never happen
- mir_sntprintf(buff, SIZEOF(buff), TranslateT(LANG_SESSION_NOT_STARTED_OTR), contact_get_nameT(hContact));
- }
-
- }
- SetEncryptionStatus(hContact, trusted);
- }
-
- /* Log a message. The passed message will end in "\n". */
- void otr_gui_log_message(void *opdata, const char *message) {
- //MessageBox(0, message, Translate("OTR Log Message"), MB_OK);
- //ShowMessageInline((MCONTACT)opdata, message);
-#ifdef _DEBUG
- char* msg = strcpy((char*)mir_alloc(strlen(message)+15), "OTR message: ");
- strcat(msg, message);
- DEBUGOUTA(msg)
- mir_free(msg);
-#endif
- }
-
- int max_message_size(void *opdata, ConnContext *context) {
- const char *proto;
- if (context && context->protocol)
- proto = context->protocol;
- else
- proto = GetContactProto((MCONTACT)opdata);
- // 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", proto)==0 || strncmp("ICQ_", proto, 4)==0)
- return 2340;
- return CallProtoService(proto, PS_GETCAPS, PFLAG_MAXLENOFMESSAGE, (LPARAM)opdata);
- }
-
- const char *account_name(void *opdata, const char *account, const char *protocol) {
- return account;
- }
-
- void account_name_free(void *opdata, const char *account_name) {
- }
-
- void add_appdata(void *data, ConnContext *context) {
- if(context) context->app_data = data;
- }
-}
-
-// Forward decl
-gcry_error_t otrl_privkey_write_FILEp(OtrlUserState us, FILE *privf);
-/* Generate a private DSA key for a given account, storing it into a
-* file on disk, and loading it into the given OtrlUserState. Overwrite any
-* previously generated keys for that account in that OtrlUserState. */
-gcry_error_t otrl_privkey_write(OtrlUserState us, const char *filename)
-{
- gcry_error_t err;
- FILE *privf;
-#ifndef WIN32
- mode_t oldmask = umask(077);
-#endif
- privf = fopen(filename, "w+b");
- if (!privf) {
-#ifndef WIN32
- umask(oldmask);
-#endif
- err = gcry_error_from_errno(errno);
- return err;
- }
-
- err = otrl_privkey_write_FILEp(us, privf);
-
- fclose(privf);
-#ifndef WIN32
- umask(oldmask);
-#endif
- return err;
-}
-
- /* Just store the private keys of an OtrlUserState.
- * The FILE* must be open for reading and writing. */
- gcry_error_t otrl_privkey_write_FILEp(OtrlUserState us, FILE *privf)
- {
- OtrlPrivKey *p;
-
- if (!privf) return gcry_error(GPG_ERR_NO_ERROR);
-
-
-
- /* Output the other keys we know */
- fprintf(privf, "(privkeys\n");
- for (p = us->privkey_root; p; p = p->next) {
- otrl_account_write(privf, p->accountname, p->protocol, p->privkey);
- }
- if (fprintf(privf, ")\n") < 0)
- return gcry_error_from_errno(errno);
- return gcry_error(GPG_ERR_NO_ERROR);
-
- }
\ No newline at end of file +#include "stdafx.h" + +OtrlUserState otr_user_state; +#define WMU_ENDDIALOG (WM_USER+244) + +OtrlMessageAppOps ops = { + otr_gui_policy,//policy + otr_gui_create_privkey,//create_privkey + otr_gui_is_logged_in,//is_logged_in + otr_gui_inject_message,//inject_message + otr_gui_update_context_list,//update_context_list + otr_gui_new_fingerprint,//new_fingerprint + otr_gui_write_fingerprints,//write_fingerprints + otr_gui_gone_secure,//gone_secure + otr_gui_gone_insecure,//gone_insecure + otr_gui_still_secure,//still_secure + max_message_size,//max_message_size + account_name,//account_name + account_name_free,//account_name_free + NULL,//received_symkey (optional) + NULL,//otr_error_message (optional, send to remote party so we could send them errors in a language they know) + NULL,//otr_error_message_free (optional) + resent_msg_prefix,//resent_msg_prefix (optional) + resent_msg_prefix_free,//resent_msg_prefix_free (optional) + handle_smp_event,//handle_smp_event (optional) + handle_msg_event,//handle_msg_event (optional) + otr_create_instag,//create_instag (optional) + NULL,//convert_msg (optional) + NULL,//convert_free (optional) + NULL,//timer_control (optional) // @todo : implement security timers +}; + +struct GenKeyData{ + HWND dialog; + const char *proto; +}; + +static unsigned int CALLBACK generate_key_thread(void* param) +{ + Thread_Push(0); + GenKeyData *data = (GenKeyData *)param; + //lib_cs_lock(); + otrl_privkey_generate(otr_user_state, g_private_key_filename, data->proto, data->proto); + //lib_cs_unlock(); + PostMessage(data->dialog, WMU_ENDDIALOG, 0, 0); + mir_free(data); + Thread_Pop(); + return 0; +} + +INT_PTR CALLBACK GenKeyDlgFunc(HWND hWndDlg, UINT msg, WPARAM wParam, LPARAM lParam) { + switch(msg) { + case WM_INITDIALOG: + { + if (!lParam) { + EndDialog(hWndDlg, 0); + return 0; + } + TranslateDialogDefault(hWndDlg); + SetClassLongPtr(hWndDlg, GCLP_HICON, (LONG_PTR)LoadIcon(ICON_OTR,1) ); + TCHAR buff[256]; + TCHAR *proto = mir_a2t((char*)lParam); + mir_sntprintf(buff, SIZEOF(buff), TranslateT(LANG_GENERATE_KEY), proto); + mir_free(proto); + SetDlgItemText(hWndDlg, IDC_GENERATE, buff); + GenKeyData *data = (GenKeyData *)mir_calloc(sizeof(GenKeyData)); + data->dialog = hWndDlg; + data->proto = (char*)lParam; + CloseHandle((HANDLE)_beginthreadex(0, 0, generate_key_thread, (void*)data, 0, 0)); + }break; + case WMU_ENDDIALOG: + EndDialog(hWndDlg, 0); + return TRUE; + case WM_DESTROY: + SetClassLongPtr(hWndDlg, GCLP_HICON, 0); + ReleaseIcon(ICON_OTR,1); + } + return FALSE; +} + +extern "C" { + /* Return the OTR policy for the given context. */ + OtrlPolicy otr_gui_policy(void *opdata, ConnContext *context) { + DEBUGOUT_T("OTR_GUI_POLICY\n"); + MCONTACT hContact = (MCONTACT)opdata; + DWORD pol; + if(hContact) { + pol = db_get_dw(hContact, MODULENAME, "Policy", CONTACT_DEFAULT_POLICY); + if (options.bHaveSecureIM && pol != OTRL_POLICY_MANUAL_MOD && pol != OTRL_POLICY_NEVER && db_get_b(hContact, "SecureIM" , "StatusID", 0)) { + // if SecureIM is not disabled for this contact, MirOTR will be set to manual + db_set_dw(hContact, MODULENAME, "Policy", OTRL_POLICY_MANUAL_MOD); + return OTRL_POLICY_MANUAL_MOD; + } + if(pol != CONTACT_DEFAULT_POLICY) return pol ; + } + if(context->protocol) { + pol = db_get_dw(0,MODULENAME"_ProtoPol", context->protocol, CONTACT_DEFAULT_POLICY); + if(pol != CONTACT_DEFAULT_POLICY) return pol ; + } + + return options.default_policy ; + } + + /* Create a private key for the given accountname/protocol if + * desired. */ + void otr_gui_create_privkey(void *opdata, const char *account_name, const char *protocol) { + DEBUGOUT_T("OTR_GUI_CREATE_PRIVKEY\n"); + //if(MessageBox(0, Translate("Would you like to generate a new private key for this protocol?"), Translate("OTR"), MB_YESNO) == IDYES) + //if(options.err_method == ED_POP) + //ShowPopup(Translate("Generating new private key."), 0 /*Translate("Please wait.")*/, 5); + + //NewKeyData *nkd = (NewKeyData *)malloc(sizeof(NewKeyData)); + //nkd->account_name = strdup(account_name); + //nkd->protocol = strdup(protocol); + + //DWORD tid; + //CloseHandle(CreateThread(0, 0, newKeyThread, (VOID *)nkd, 0, &tid)); + //QueueUserAPC(newKeyAPC, Global::mainThread, (DWORD)nkd); + if (opdata) protocol = GetContactProto((MCONTACT)opdata); + if (!protocol) return; + DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_GENKEYNOTIFY), 0, GenKeyDlgBoxProc, (LPARAM)protocol ); + + } + + /* Report whether you think the given user is online. Return 1 if + * you think he is, 0 if you think he isn't, -1 if you're not sure. + * + * If you return 1, messages such as heartbeats or other + * notifications may be sent to the user, which could result in "not + * logged in" errors if you're wrong. */ + int otr_gui_is_logged_in(void *opdata, const char *accountname, const char *protocol, const char *recipient) { + DEBUGOUT_T("OTR_GUI_IS_LOGGED_IN\n"); + MCONTACT hContact = (MCONTACT)opdata; + if(hContact) { + WORD status = db_get_w(hContact, GetContactProto(hContact), "Status", ID_STATUS_OFFLINE); + if(status == ID_STATUS_OFFLINE) return 0; + else return 1; + } + + return -1; + } + + /* Send the given IM to the given recipient from the given + * accountname/protocol. */ + void otr_gui_inject_message(void *opdata, const char *accountname, const char *protocol, const char *recipient, const char *message) { + DEBUGOUT_T("OTR_GUI_INJECT_MESSAGE\n"); + MCONTACT hContact = (MCONTACT)opdata; + if(db_get_w(hContact, protocol, "Status", ID_STATUS_OFFLINE) != ID_STATUS_OFFLINE) + CallContactService(hContact, PSS_MESSAGE, PREF_UTF|PREF_BYPASS_OTR, (LPARAM)message); + } + + /* When the list of ConnContexts changes (including a change in + * state), this is called so the UI can be updated. */ + void otr_gui_update_context_list(void *opdata) { + //MessageBox(0, "Update Context List", "OTR Callback", MB_OK); + DEBUGOUT_T("OTR: Update Context List\n"); + } + + /* A new fingerprint for the given user has been received. */ + void otr_gui_new_fingerprint(void *opdata, OtrlUserState us, const char *accountname, const char *protocol, const char *username, unsigned char fingerprint[20]) { + DEBUGOUT_T("OTR_GUI_NEW_FINGERPRINT\n"); + ConnContext *context = otrl_context_find(us, username, accountname, protocol, OTRL_INSTAG_BEST, TRUE, 0, add_appdata, opdata); + Fingerprint *fp = otrl_context_find_fingerprint(context, fingerprint, TRUE, 0); + + //CloseHandle((HANDLE)_beginthreadex(0, 0, trust_fp_thread, (void *)fp, 0, 0)); + + otrl_context_set_trust(fp, NULL); + otrl_privkey_write_fingerprints(otr_user_state, g_fingerprint_store_filename); + } + + /* The list of known fingerprints has changed. Write them to disk. */ + void otr_gui_write_fingerprints(void *opdata) { + DEBUGOUT_T("OTR_GUI_WRITE_FINGERPRINTS\n"); + //if(MessageBox(0, Translate("Would you like to save the current fingerprint list?"), Translate(MODULE), MB_YESNO) == IDYES) + otrl_privkey_write_fingerprints(otr_user_state, g_fingerprint_store_filename); + } + + /* A ConnContext has entered a secure state. */ + void otr_gui_gone_secure(void *opdata, ConnContext *context) { + DEBUGOUT_T("OTR_GUI_GONE_SECURE\n"); + MCONTACT hContact = (MCONTACT) opdata; + TrustLevel trusted = otr_context_get_trust(context); + SetEncryptionStatus(hContact, trusted); + TCHAR buff[512]; + if(trusted == TRUST_PRIVATE) { + mir_sntprintf(buff, SIZEOF(buff), TranslateT(LANG_SESSION_START_OTR), contact_get_nameT(hContact)); + } else if (trusted == TRUST_UNVERIFIED) { + if (options.autoshow_verify) SMPInitDialog(context); //VerifyContextDialog(context); + mir_sntprintf(buff, SIZEOF(buff), TranslateT(LANG_SESSION_START_OTR_VERIFY), contact_get_nameT(hContact)); + } else { // should never happen + mir_sntprintf(buff, SIZEOF(buff), TranslateT(LANG_SESSION_NOT_STARTED_OTR), contact_get_nameT(hContact)); + } + ShowMessage(hContact, buff); + + } + + /* A ConnContext has left a secure state. */ + void otr_gui_gone_insecure(void *opdata, ConnContext *context) { + MCONTACT hContact = (MCONTACT) opdata; + DEBUGOUT_T("OTR_GUI_GONE_INSECURE\n"); + TCHAR buff[512]; + mir_sntprintf(buff, SIZEOF(buff), TranslateT(LANG_SESSION_TERMINATED_BY_OTR), contact_get_nameT(hContact)); + //MessageBox(0, buff, Translate("OTR Information"), MB_OK); + if (!Miranda_Terminated()) { + ShowMessage(hContact, buff); + } + + // opdata is hContact + SetEncryptionStatus(hContact, otr_context_get_trust(context)); + } + + /* We have completed an authentication, using the D-H keys we + * already knew. is_reply indicates whether we initiated the AKE. */ + void otr_gui_still_secure(void *opdata, ConnContext *context, int is_reply) { + MCONTACT hContact = (MCONTACT) opdata; + DEBUGOUT_T("OTR_GUI_STILL_SECURE\n"); + TrustLevel trusted = otr_context_get_trust(context); + SetEncryptionStatus(hContact, trusted); + TCHAR buff[1024]; + if (!is_reply) { + if(trusted == TRUST_PRIVATE) { + mir_sntprintf(buff, SIZEOF(buff), TranslateT(LANG_SESSION_CONTINUE_OTR), contact_get_nameT(hContact)); + } else if (trusted == TRUST_UNVERIFIED) { + if (options.autoshow_verify) SMPInitDialog(context); //VerifyContextDialog(context); + mir_sntprintf(buff, SIZEOF(buff), TranslateT(LANG_SESSION_CONTINUE_OTR_VERIFY), contact_get_nameT(hContact)); + } else { // should never happen + mir_sntprintf(buff, SIZEOF(buff), TranslateT(LANG_SESSION_NOT_STARTED_OTR), contact_get_nameT(hContact)); + } + // opdata is hContact + ShowMessage(hContact, buff); + } else { + if(trusted == TRUST_PRIVATE) { + mir_sntprintf(buff, SIZEOF(buff), TranslateT(LANG_SESSION_HAS_CONTINUE_OTR), contact_get_nameT(hContact)); + } else if (trusted == TRUST_UNVERIFIED) { + mir_sntprintf(buff, SIZEOF(buff), TranslateT(LANG_SESSION_HAS_CONTINUE_OTR_VERIFY), contact_get_nameT(hContact)); + } else { // should never happen + mir_sntprintf(buff, SIZEOF(buff), TranslateT(LANG_SESSION_NOT_STARTED_OTR), contact_get_nameT(hContact)); + } + + } + SetEncryptionStatus(hContact, trusted); + } + + int max_message_size(void *opdata, ConnContext *context) { + const char *proto; + if (context && context->protocol) + proto = context->protocol; + else + proto = GetContactProto((MCONTACT)opdata); + // 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", proto)==0 || strncmp("ICQ_", proto, 4)==0) + return 2340; + return CallProtoService(proto, PS_GETCAPS, PFLAG_MAXLENOFMESSAGE, (LPARAM)opdata); + } + + const char *account_name(void *opdata, const char *account, const char *protocol) { + return account; + } + + void account_name_free(void *opdata, const char *account_name) { + } + + void add_appdata(void *data, ConnContext *context) { + if(context) context->app_data = data; + } + + const char* resent_msg_prefix(void *opdata, ConnContext *context){ + return "[resent]"; + } + void resent_msg_prefix_free(void *opdata, const char *prefix){ + return; + } + + void handle_smp_event(void *opdata, OtrlSMPEvent smp_event, ConnContext *context, unsigned short progress_percent, char *question) { + DEBUGOUT_T("HANDLE_SMP_EVENT\n"); + if(!context) return; + switch(smp_event){ + case OTRL_SMPEVENT_NONE: + break; + case OTRL_SMPEVENT_ASK_FOR_SECRET: + case OTRL_SMPEVENT_ASK_FOR_ANSWER: + SMPDialogReply(context,question); + break; + case OTRL_SMPEVENT_CHEATED: + otrl_message_abort_smp(otr_user_state, &ops, opdata, context); + case OTRL_SMPEVENT_IN_PROGRESS: + case OTRL_SMPEVENT_SUCCESS: + case OTRL_SMPEVENT_FAILURE: + case OTRL_SMPEVENT_ABORT: + SMPDialogUpdate(context, progress_percent); + break; + case OTRL_SMPEVENT_ERROR: + otrl_message_abort_smp(otr_user_state, &ops, opdata, context); + break; + } + } + + void handle_msg_event(void *opdata, OtrlMessageEvent msg_event, ConnContext *context, const char *message, gcry_error_t err) { + DEBUGOUTA("HANDLE_MSG_EVENT\n"); + MCONTACT hContact = (MCONTACT)opdata; + const TCHAR* contact = contact_get_nameT(hContact); + +// TCHAR* title = NULL; + TCHAR msg[512]; + msg[0] = '\0'; + switch(msg_event){ + case OTRL_MSGEVENT_NONE: + case OTRL_MSGEVENT_LOG_HEARTBEAT_RCVD: + case OTRL_MSGEVENT_LOG_HEARTBEAT_SENT: + case OTRL_MSGEVENT_RCVDMSG_UNRECOGNIZED: + break; + case OTRL_MSGEVENT_ENCRYPTION_REQUIRED: +// title = TranslateT("OTR Policy Violation"); + mir_snwprintf(msg,SIZEOF(msg),TranslateT("You attempted to send an unencrypted message to %s"),contact); + break; + case OTRL_MSGEVENT_ENCRYPTION_ERROR: +// title = TranslateT("Error encrypting message"); + mir_tstrncpy(msg,TranslateT("An error occurred when encrypting your message.\nThe message was not sent."),SIZEOF(msg)); + break; + case OTRL_MSGEVENT_CONNECTION_ENDED: +// title = TranslateT("Your message was not sent."); + mir_snwprintf(msg,SIZEOF(msg),TranslateT("%s has already closed his/her private connection to you; you should do the same."),contact); + break; + case OTRL_MSGEVENT_SETUP_ERROR: +// title = TranslateT("OTR Error"); + if(!err) err = GPG_ERR_INV_VALUE; + switch(gcry_err_code(err)){ + case GPG_ERR_INV_VALUE: + mir_snwprintf(msg,SIZEOF(msg),TranslateT("Error setting up private conversation: %s"),TranslateT("Malformed message received")); + break; + default:{ + TCHAR* tmp = mir_utf8decodeT(gcry_strerror(err)); + mir_snwprintf(msg,SIZEOF(msg),TranslateT("Error setting up private conversation: %s"),tmp); + mir_free(tmp);} + } + break; + case OTRL_MSGEVENT_MSG_REFLECTED: +// title = TranslateT("OTR Error"); + mir_tstrncpy(msg,TranslateT("We are receiving our own OTR messages.\nYou are either trying to talk to yourself, or someone is reflecting your messages back at you."),SIZEOF(msg)); + break; + case OTRL_MSGEVENT_MSG_RESENT: +// title = TranslateT("Message resent"); + mir_snwprintf(msg,SIZEOF(msg),TranslateT("The last message to %s was resent."),contact); + break; + case OTRL_MSGEVENT_RCVDMSG_NOT_IN_PRIVATE: +// title = TranslateT("Unreadable message"); + mir_snwprintf(msg,SIZEOF(msg),TranslateT("The encrypted message received from %s is unreadable, as you are not currently communicating privately."),contact); + break; + case OTRL_MSGEVENT_RCVDMSG_UNREADABLE: +// title = TranslateT("OTR Error"); + mir_snwprintf(msg,SIZEOF(msg),TranslateT("We received an unreadable encrypted message from %s."),contact); + break; + case OTRL_MSGEVENT_RCVDMSG_MALFORMED: +// title = TranslateT("OTR Error"); + mir_snwprintf(msg,SIZEOF(msg),TranslateT("We received a malformed data message from %s."),contact); + break; + case OTRL_MSGEVENT_RCVDMSG_GENERAL_ERR:{ +// title = TranslateT("OTR Error"); + TCHAR* tmp = mir_utf8decodeT(message); + mir_tstrncpy(msg,tmp,SIZEOF(msg)); + mir_free(tmp); + break;} + case OTRL_MSGEVENT_RCVDMSG_UNENCRYPTED:{ +// title = TranslateT("Received unencrypted message"); + TCHAR* tmp = mir_utf8decodeT(message); + mir_snwprintf(msg,SIZEOF(msg),TranslateT("The following message received from '%s' was NOT encrypted: [%s]"),contact,tmp); + mir_free(tmp); + break;} + case OTRL_MSGEVENT_RCVDMSG_FOR_OTHER_INSTANCE: +// title = TranslateT("Received message for a different session"); + mir_snwprintf(msg,SIZEOF(msg),TranslateT("%s has sent a message intended for a different session. If you are logged in multiple times, another session may have received the message."),contact); + break; + default: +// title = TranslateT("OTR Error"); + mir_tstrncpy(msg,TranslateT("unknown OTR message received, please report that to Miranda NG"),SIZEOF(msg)); + } + if(msg[0]) + ShowMessage(hContact,msg); + } + + void otr_create_instag(void *opdata, const char *accountname, const char *protocol){ + DEBUGOUT_T("OTR_CREATE_INSTAG\n"); + FILE* instagf = fopen(g_instag_filename, "w+b"); + if(!instagf) + return; + otrl_instag_generate_FILEp(otr_user_state, instagf, accountname, protocol); + fclose(instagf); + } +} |