From 5f2e4efe46fefa7cd11f275896954c24be37b568 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Sch=C3=BCmann?= Date: Thu, 26 Mar 2015 20:38:55 +0000 Subject: MirOTR: compatibility update to support/use libotr 4 + added otrlextensions from Psi+ (thanks guys, better than our old modification to libotr) * basic instance tag support, though we don't offer user choice yet. + added ProtoGetNickname(), stolen from TabSRMM to get our own nickname of given protocol (utils.cpp) git-svn-id: http://svn.miranda-ng.org/main/trunk@12503 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- plugins/MirOTR/MirOTR_10.vcxproj | 2 + plugins/MirOTR/MirOTR_10.vcxproj.filters | 6 + plugins/MirOTR/MirOTR_12.vcxproj | 2 + plugins/MirOTR/MirOTR_12.vcxproj.filters | 6 + plugins/MirOTR/src/dbfilter.cpp | 702 ++++++------ plugins/MirOTR/src/options.cpp | 1745 +++++++++++++++--------------- plugins/MirOTR/src/options.h | 140 +-- plugins/MirOTR/src/otr.cpp | 781 +++++++------ plugins/MirOTR/src/otr.h | 101 +- plugins/MirOTR/src/otrlextensions.c | 127 +++ plugins/MirOTR/src/otrlextensions.h | 35 + plugins/MirOTR/src/stdafx.cpp | 13 +- plugins/MirOTR/src/stdafx.h | 8 +- plugins/MirOTR/src/svcs_menu.cpp | 378 +++---- plugins/MirOTR/src/svcs_proto.cpp | 586 ++++------ plugins/MirOTR/src/svcs_srmm.cpp | 314 +++--- plugins/MirOTR/src/utils.cpp | 783 +++++++------- plugins/MirOTR/src/utils.h | 98 +- 18 files changed, 2941 insertions(+), 2886 deletions(-) create mode 100644 plugins/MirOTR/src/otrlextensions.c create mode 100644 plugins/MirOTR/src/otrlextensions.h (limited to 'plugins/MirOTR') diff --git a/plugins/MirOTR/MirOTR_10.vcxproj b/plugins/MirOTR/MirOTR_10.vcxproj index dbaa43317d..2045c2dabf 100644 --- a/plugins/MirOTR/MirOTR_10.vcxproj +++ b/plugins/MirOTR/MirOTR_10.vcxproj @@ -187,6 +187,7 @@ + Create @@ -205,6 +206,7 @@ + diff --git a/plugins/MirOTR/MirOTR_10.vcxproj.filters b/plugins/MirOTR/MirOTR_10.vcxproj.filters index bf71a67267..db465389ad 100644 --- a/plugins/MirOTR/MirOTR_10.vcxproj.filters +++ b/plugins/MirOTR/MirOTR_10.vcxproj.filters @@ -39,6 +39,9 @@ Source Files + + Source Files + Source Files @@ -83,6 +86,9 @@ Header Files + + Header Files + Header Files diff --git a/plugins/MirOTR/MirOTR_12.vcxproj b/plugins/MirOTR/MirOTR_12.vcxproj index 3495612d8b..134210fe49 100644 --- a/plugins/MirOTR/MirOTR_12.vcxproj +++ b/plugins/MirOTR/MirOTR_12.vcxproj @@ -190,6 +190,7 @@ + Create @@ -208,6 +209,7 @@ + diff --git a/plugins/MirOTR/MirOTR_12.vcxproj.filters b/plugins/MirOTR/MirOTR_12.vcxproj.filters index bf71a67267..db465389ad 100644 --- a/plugins/MirOTR/MirOTR_12.vcxproj.filters +++ b/plugins/MirOTR/MirOTR_12.vcxproj.filters @@ -39,6 +39,9 @@ Source Files + + Source Files + Source Files @@ -83,6 +86,9 @@ Header Files + + Header Files + Header Files diff --git a/plugins/MirOTR/src/dbfilter.cpp b/plugins/MirOTR/src/dbfilter.cpp index 9f2223100d..339592c832 100644 --- a/plugins/MirOTR/src/dbfilter.cpp +++ b/plugins/MirOTR/src/dbfilter.cpp @@ -1,351 +1,351 @@ -#include "stdafx.h" - -static HANDLE hDBEventPreAdd, hDBEventAdded, hContactSettingChanged; -static CRITICAL_SECTION RemoveChainCS={0}, *lpRemoveChainCS = &RemoveChainCS; -static UINT_PTR timerId = 0; - -struct DeleteEventNode { - DeleteEventNode *next; - time_t timestamp; - MCONTACT hContact; - MEVENT hDbEvent; -}; -struct DeleteEventHead { - DeleteEventNode *first; - DeleteEventNode *last; -}; -static DeleteEventHead DeleteEvents = {0,0}; - -VOID CALLBACK DeleteTimerProc(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime) { - if (!DeleteEvents.first) return; - EnterCriticalSection(lpRemoveChainCS); - DeleteEventNode *prev =0, *current, *next; - DBEVENTINFO info = { sizeof(info) }; - next = DeleteEvents.first; - while (current = next) { - if (difftime(time(0), current->timestamp) < 1) break; - if (!db_event_get(current->hDbEvent, &info)) // && info.flags&DBEF_READ) - { - db_event_delete(current->hContact, current->hDbEvent); - next = current->next; - if (prev) prev->next = next; - else if (DeleteEvents.first == current) DeleteEvents.first = next; - delete current; - } - else { - prev = current; - next = current->next; - } - } - if (!DeleteEvents.first) DeleteEvents.last = 0; - LeaveCriticalSection(lpRemoveChainCS); -} - - -// add prefix to sent messages -int OnDatabaseEventPreAdd(WPARAM hContact, LPARAM lParam) -{ - if (!options.prefix_messages || !lParam) - return 0; - - DBEVENTINFO *dbei = (DBEVENTINFO *)lParam; - if ((dbei->eventType != EVENTTYPE_MESSAGE) || !(dbei->flags & DBEF_SENT) || (dbei->flags & DBEF_OTR_PREFIXED)) - return 0; - - if(dbei->cbBlob == 0 || dbei->pBlob == 0) - return 0; // just to be safe - - const char *proto = GetContactProto(hContact); - if (!proto) - return 0; - if (db_get_b(hContact, proto, "ChatRoom", 0) == 1) - return 0; - - if(strcmp(proto, META_PROTO) == 0) { - hContact = db_mc_getMostOnline(hContact); - if (!hContact) return 0; - proto = GetContactProto(hContact); - if (!proto ) return 0; - } - - - ConnContext *context = otrl_context_find_miranda(otr_user_state, hContact); - bool encrypted = otr_context_get_trust(context) != TRUST_NOT_PRIVATE; - if (!encrypted) return 0; - - DBEVENTINFO my_dbei = *dbei; // copy the other event - - char *msg = (char *)dbei->pBlob; - char *newmsg = 0; - DWORD alloclen = 0; - DWORD msglen = (DWORD)strlen(msg); - if (dbei->flags & DBEF_UTF) { - int prefixlen = (int)strnlen(options.prefix, 64); - if (strncmp(msg, options.prefix, prefixlen) == 0) return 0; - alloclen = (msglen+prefixlen+1)*sizeof(char); - - // get additional data - DWORD len2 = alloclen- prefixlen*sizeof(char); - int datalen = dbei->cbBlob - len2; - if (datalen < 0) datalen = 0; - - newmsg = (char*)mir_alloc(alloclen); - memset(newmsg, 0, alloclen+datalen); - strncpy(newmsg, options.prefix, prefixlen); - strncat(newmsg, msg, msglen); - // append additional data - if (datalen) { - memcpy(newmsg+alloclen, msg+len2, datalen); - alloclen += datalen; - } - } else { - bool dz = false; - if(msglen < dbei->cbBlob) { - for(unsigned int i = msglen; i < dbei->cbBlob; i++) { - if(msg[i] == 0 && msg[i - 1] == 0) { - dz = true; - break; - } - } - } - if(dz) { - // yes, unicode - wchar_t* msgw = (wchar_t *)&msg[msglen]; - wchar_t *prefixw = mir_utf8decodeW(options.prefix); - int prefixlenw = (int)wcslen(prefixw); - if (wcsncmp(msgw, prefixw, prefixlenw) == 0) { - mir_free(prefixw); - return 0; - } - int msglenw = (int)wcslen(msgw); - - char *prefix = mir_utf8decodeA(options.prefix); - int prefixlen = (int)strlen(prefix); - - alloclen = (msglen+prefixlen+1)* sizeof(char) + (msglenw + prefixlenw +1) * sizeof(wchar_t); - // get additional data - DWORD len2 = (msglen+1)* sizeof(char) + (msglenw+1) * sizeof(wchar_t); - int datalen = dbei->cbBlob - len2; - if (datalen < 0) datalen = 0; - - newmsg = (char*)mir_alloc(alloclen+datalen); - memset(newmsg, 0, alloclen+datalen); - strncpy(newmsg, prefix, prefixlen); - strncat(newmsg, msg, msglen); - wchar_t *p = (wchar_t*) newmsg + (msglen + prefixlen + 1); - wcsncpy(p, prefixw, prefixlenw); - wcsncat(p, msgw, msglenw); - mir_free(prefix); - mir_free(prefixw); - // append additional data - if (datalen) { - memcpy(newmsg+alloclen, msg+len2, datalen); - alloclen += datalen; - } - } - else { - char *prefix = mir_utf8decodeA(options.prefix); - int prefixlen = (int)strlen(prefix); - if (strncmp(msg, prefix, prefixlen) == 0) { - mir_free(prefix); - return 0; - } - alloclen = msglen+prefixlen+sizeof(char); - // get additional data - DWORD len2 = alloclen-prefixlen; - int datalen = dbei->cbBlob - len2; - if (datalen < 0) datalen = 0; - - newmsg = (char*)mir_alloc(alloclen+datalen); - memset(newmsg, 0, alloclen+datalen); - strncpy(newmsg, prefix, prefixlen); - strncat(newmsg, msg, msglen); - mir_free(prefix); - // append additional data - if (datalen) { - memcpy(newmsg+alloclen, msg+len2, datalen); - alloclen += datalen; - } - } - - } - - my_dbei.pBlob = (BYTE *)newmsg; - my_dbei.cbBlob = alloclen; - my_dbei.flags |= DBEF_OTR_PREFIXED; - - db_event_add(hContact, &my_dbei); - if (newmsg) mir_free(newmsg); - - // stop original event from being added - return 1; -} - - int OnDatabaseEventAdded(WPARAM hContact, LPARAM lParam) - { - if (!options.delete_history) return 0; - - static char* prefixutf = mir_utf8encodeT(TranslateT(LANG_INLINE_PREFIX)); - static char* prefix = Translate(LANG_INLINE_PREFIX); - static DWORD lenutf = (DWORD)strlen(prefixutf); - static DWORD len = (DWORD)strlen(prefix); - - DBEVENTINFO info = { sizeof(info) }; - info.cbBlob = lenutf*2; - info.pBlob = (PBYTE)mir_alloc(info.cbBlob); - if (!db_event_get(lParam, &info)) { - if(info.eventType == EVENTTYPE_MESSAGE) { - MCONTACT hSub; - if((hSub = db_mc_getMostOnline(hContact)) != 0) - hContact = hSub; - - ConnContext *context = otrl_context_find_miranda(otr_user_state, hContact); - if (context && otr_context_get_trust(context) != TRUST_NOT_PRIVATE ) { - // only delete encrypted messages that are no OTR system messages - if ( options.delete_systeminfo || - ((info.flags&DBEF_UTF && !(info.cbBlob >lenutf && 0==strncmp((char*)info.pBlob, prefixutf, lenutf))) - || (!(info.flags&DBEF_UTF) && !(info.cbBlob >len && 0==strncmp((char*)info.pBlob, prefix, len))))) - { - DeleteEventNode *node = new DeleteEventNode(); - node->hContact = hContact; - node->hDbEvent = lParam; - node->timestamp = time(0); - node->next = 0; - EnterCriticalSection(lpRemoveChainCS); - if (DeleteEvents.last) - DeleteEvents.last->next = node; - else - DeleteEvents.first = node; - DeleteEvents.last = node; - LeaveCriticalSection(lpRemoveChainCS); - } - } - } - } - mir_free(prefixutf); - mir_free(info.pBlob); - return 0; -} - -void FinishSession(MCONTACT hContact) { - if (!hContact) return; - ConnContext *context = otrl_context_find_miranda(otr_user_state, hContact); - TrustLevel level = otr_context_get_trust(context); - if (level == TRUST_UNVERIFIED || level == TRUST_PRIVATE) { - otrl_context_force_finished(context); - //SetEncryptionStatus(hContact, TRUST_FINISHED); - otr_gui_gone_insecure(context->app_data, context); - //otrl_message_disconnect(otr_user_state, &ops, hContact, context->accountname, context->protocol, context->username); - //SetEncryptionStatus(hContact, TRUST_NOT_PRIVATE); - } - return; -} - -int WindowEvent(WPARAM wParam, LPARAM lParam) { - MessageWindowEventData *mwd = (MessageWindowEventData *)lParam; - - if(mwd->uType == MSG_WINDOW_EVT_CLOSE && options.end_window_close) { - FinishSession(mwd->hContact); - return 0; - } - - if(mwd->uType != MSG_WINDOW_EVT_OPEN) return 0; - - MCONTACT hContact = mwd->hContact, hTemp; - if((hTemp = db_mc_getMostOnline(hContact)) != 0) - hContact = hTemp; - - if (!CallService(MS_PROTO_ISPROTOONCONTACT, hContact, (LPARAM)MODULENAME)) - return 0; - - lib_cs_lock(); - ConnContext *context = otrl_context_find_miranda(otr_user_state, hContact); - lib_cs_unlock(); - - SetEncryptionStatus(hContact, otr_context_get_trust(context)); - - return 0; -} - -// if it's a protocol going offline, attempt to send terminate session to all contacts of that protocol -// (this would be hooked as the ME_CLIST_STATUSMODECHANGE handler except that event is sent *after* the proto goes offline) -int StatusModeChange(WPARAM wParam, LPARAM lParam) { - int status = (int)wParam; - - if(status != ID_STATUS_OFFLINE ) return 0; - - const char *proto = (char *)lParam; - MCONTACT hContact; - - lib_cs_lock(); - - ConnContext *context = otr_user_state->context_root; - while(context) { - if(context->msgstate == OTRL_MSGSTATE_ENCRYPTED && (proto == 0 || strcmp(proto, context->protocol) == 0)) { - hContact = (MCONTACT)context->app_data; - - if(hContact) { - otrl_message_disconnect(otr_user_state, &ops, (void*)hContact, context->accountname, context->protocol, context->username); - SetEncryptionStatus(hContact, TRUST_NOT_PRIVATE); - } - - } - context = context->next; - } - lib_cs_unlock(); - - return 0; -} - -int OnContactSettingChanged(WPARAM hContact, LPARAM lParam) -{ - if (!options.end_offline) - return 0; - DBCONTACTWRITESETTING *cws = (DBCONTACTWRITESETTING *)lParam; - if (!lParam || strcmp(cws->szSetting, "Status") != 0) return 0; - int status=0; - switch (cws->value.type){ - case DBVT_WORD: - status = cws->value.wVal; - break; - case DBVT_BYTE: - status = cws->value.bVal; - break; - case DBVT_DWORD: - status = cws->value.dVal; - break; - } - if (status == ID_STATUS_OFFLINE) { - if (!hContact) { - // Protocol is going offline - // Terminate sessions with all contacts of that proto - StatusModeChange((WPARAM) ID_STATUS_OFFLINE, (LPARAM)cws->szModule); - return 0; - }else if(CallService(MS_PROTO_ISPROTOONCONTACT, hContact, (LPARAM)MODULENAME)) { - // only care about contacts to which this filter is attached - FinishSession(hContact); - } - } - - - return 0; -} - -void InitDBFilter() { - InitializeCriticalSectionAndSpinCount(lpRemoveChainCS, 500); - hDBEventPreAdd = HookEvent(ME_DB_EVENT_FILTER_ADD, OnDatabaseEventPreAdd); - hDBEventAdded = HookEvent(ME_DB_EVENT_ADDED, OnDatabaseEventAdded); - hContactSettingChanged = HookEvent(ME_DB_CONTACT_SETTINGCHANGED, OnContactSettingChanged); - timerId = SetTimer(0, 0, 1000, DeleteTimerProc); -} -void DeinitDBFilter() { - UnhookEvent(hDBEventPreAdd); - hDBEventPreAdd = 0; - UnhookEvent(hDBEventAdded); - hDBEventAdded = 0; - UnhookEvent(hContactSettingChanged); - hContactSettingChanged=0; - if (timerId) KillTimer(0, timerId); - DeleteTimerProc(0,0,0,0); - DeleteCriticalSection(lpRemoveChainCS); -} \ No newline at end of file +#include "stdafx.h" + +static HANDLE hDBEventPreAdd, hDBEventAdded, hContactSettingChanged; +static CRITICAL_SECTION RemoveChainCS={0}, *lpRemoveChainCS = &RemoveChainCS; +static UINT_PTR timerId = 0; + +struct DeleteEventNode { + DeleteEventNode *next; + time_t timestamp; + MCONTACT hContact; + MEVENT hDbEvent; +}; +struct DeleteEventHead { + DeleteEventNode *first; + DeleteEventNode *last; +}; +static DeleteEventHead DeleteEvents = {0,0}; + +VOID CALLBACK DeleteTimerProc(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime) { + if (!DeleteEvents.first) return; + EnterCriticalSection(lpRemoveChainCS); + DeleteEventNode *prev =0, *current, *next; + DBEVENTINFO info = { sizeof(info) }; + next = DeleteEvents.first; + while (current = next) { + if (difftime(time(0), current->timestamp) < 1) break; + if (!db_event_get(current->hDbEvent, &info)) // && info.flags&DBEF_READ) + { + db_event_delete(current->hContact, current->hDbEvent); + next = current->next; + if (prev) prev->next = next; + else if (DeleteEvents.first == current) DeleteEvents.first = next; + delete current; + } + else { + prev = current; + next = current->next; + } + } + if (!DeleteEvents.first) DeleteEvents.last = 0; + LeaveCriticalSection(lpRemoveChainCS); +} + + +// add prefix to sent messages +int OnDatabaseEventPreAdd(WPARAM hContact, LPARAM lParam) +{ + if (!options.prefix_messages || !lParam) + return 0; + + DBEVENTINFO *dbei = (DBEVENTINFO *)lParam; + if ((dbei->eventType != EVENTTYPE_MESSAGE) || !(dbei->flags & DBEF_SENT) || (dbei->flags & DBEF_OTR_PREFIXED)) + return 0; + + if(dbei->cbBlob == 0 || dbei->pBlob == 0) + return 0; // just to be safe + + const char *proto = GetContactProto(hContact); + if (!proto) + return 0; + if (db_get_b(hContact, proto, "ChatRoom", 0) == 1) + return 0; + + if(strcmp(proto, META_PROTO) == 0) { + hContact = db_mc_getMostOnline(hContact); + if (!hContact) return 0; + proto = GetContactProto(hContact); + if (!proto ) return 0; + } + + + ConnContext *context = otrl_context_find_miranda(otr_user_state, hContact); + bool encrypted = otr_context_get_trust(context) != TRUST_NOT_PRIVATE; + if (!encrypted) return 0; + + DBEVENTINFO my_dbei = *dbei; // copy the other event + + char *msg = (char *)dbei->pBlob; + char *newmsg = 0; + DWORD alloclen = 0; + DWORD msglen = (DWORD)strlen(msg); + if (dbei->flags & DBEF_UTF) { + int prefixlen = (int)strnlen(options.prefix, 64); + if (strncmp(msg, options.prefix, prefixlen) == 0) return 0; + alloclen = (msglen+prefixlen+1)*sizeof(char); + + // get additional data + DWORD len2 = alloclen- prefixlen*sizeof(char); + int datalen = dbei->cbBlob - len2; + if (datalen < 0) datalen = 0; + + newmsg = (char*)mir_alloc(alloclen); + memset(newmsg, 0, alloclen+datalen); + strncpy(newmsg, options.prefix, prefixlen); + strncat(newmsg, msg, msglen); + // append additional data + if (datalen) { + memcpy(newmsg+alloclen, msg+len2, datalen); + alloclen += datalen; + } + } else { + bool dz = false; + if(msglen < dbei->cbBlob) { + for(unsigned int i = msglen; i < dbei->cbBlob; i++) { + if(msg[i] == 0 && msg[i - 1] == 0) { + dz = true; + break; + } + } + } + if(dz) { + // yes, unicode + wchar_t* msgw = (wchar_t *)&msg[msglen]; + wchar_t *prefixw = mir_utf8decodeW(options.prefix); + int prefixlenw = (int)wcslen(prefixw); + if (wcsncmp(msgw, prefixw, prefixlenw) == 0) { + mir_free(prefixw); + return 0; + } + int msglenw = (int)wcslen(msgw); + + char *prefix = mir_utf8decodeA(options.prefix); + int prefixlen = (int)strlen(prefix); + + alloclen = (msglen+prefixlen+1)* sizeof(char) + (msglenw + prefixlenw +1) * sizeof(wchar_t); + // get additional data + DWORD len2 = (msglen+1)* sizeof(char) + (msglenw+1) * sizeof(wchar_t); + int datalen = dbei->cbBlob - len2; + if (datalen < 0) datalen = 0; + + newmsg = (char*)mir_alloc(alloclen+datalen); + memset(newmsg, 0, alloclen+datalen); + strncpy(newmsg, prefix, prefixlen); + strncat(newmsg, msg, msglen); + wchar_t *p = (wchar_t*) newmsg + (msglen + prefixlen + 1); + wcsncpy(p, prefixw, prefixlenw); + wcsncat(p, msgw, msglenw); + mir_free(prefix); + mir_free(prefixw); + // append additional data + if (datalen) { + memcpy(newmsg+alloclen, msg+len2, datalen); + alloclen += datalen; + } + } + else { + char *prefix = mir_utf8decodeA(options.prefix); + int prefixlen = (int)strlen(prefix); + if (strncmp(msg, prefix, prefixlen) == 0) { + mir_free(prefix); + return 0; + } + alloclen = msglen+prefixlen+sizeof(char); + // get additional data + DWORD len2 = alloclen-prefixlen; + int datalen = dbei->cbBlob - len2; + if (datalen < 0) datalen = 0; + + newmsg = (char*)mir_alloc(alloclen+datalen); + memset(newmsg, 0, alloclen+datalen); + strncpy(newmsg, prefix, prefixlen); + strncat(newmsg, msg, msglen); + mir_free(prefix); + // append additional data + if (datalen) { + memcpy(newmsg+alloclen, msg+len2, datalen); + alloclen += datalen; + } + } + + } + + my_dbei.pBlob = (BYTE *)newmsg; + my_dbei.cbBlob = alloclen; + my_dbei.flags |= DBEF_OTR_PREFIXED; + + db_event_add(hContact, &my_dbei); + if (newmsg) mir_free(newmsg); + + // stop original event from being added + return 1; +} + + int OnDatabaseEventAdded(WPARAM hContact, LPARAM lParam) + { + if (!options.delete_history) return 0; + + static char* prefixutf = mir_utf8encodeT(TranslateT(LANG_INLINE_PREFIX)); + static char* prefix = Translate(LANG_INLINE_PREFIX); + static DWORD lenutf = (DWORD)strlen(prefixutf); + static DWORD len = (DWORD)strlen(prefix); + + DBEVENTINFO info = { sizeof(info) }; + info.cbBlob = lenutf*2; + info.pBlob = (PBYTE)mir_alloc(info.cbBlob); + if (!db_event_get(lParam, &info)) { + if(info.eventType == EVENTTYPE_MESSAGE) { + MCONTACT hSub; + if((hSub = db_mc_getMostOnline(hContact)) != 0) + hContact = hSub; + + ConnContext *context = otrl_context_find_miranda(otr_user_state, hContact); + if (context && otr_context_get_trust(context) != TRUST_NOT_PRIVATE ) { + // only delete encrypted messages that are no OTR system messages + if ( options.delete_systeminfo || + ((info.flags&DBEF_UTF && !(info.cbBlob >lenutf && 0==strncmp((char*)info.pBlob, prefixutf, lenutf))) + || (!(info.flags&DBEF_UTF) && !(info.cbBlob >len && 0==strncmp((char*)info.pBlob, prefix, len))))) + { + DeleteEventNode *node = new DeleteEventNode(); + node->hContact = hContact; + node->hDbEvent = lParam; + node->timestamp = time(0); + node->next = 0; + EnterCriticalSection(lpRemoveChainCS); + if (DeleteEvents.last) + DeleteEvents.last->next = node; + else + DeleteEvents.first = node; + DeleteEvents.last = node; + LeaveCriticalSection(lpRemoveChainCS); + } + } + } + } + mir_free(prefixutf); + mir_free(info.pBlob); + return 0; +} + +void FinishSession(MCONTACT hContact) { + if (!hContact) return; + ConnContext *context = otrl_context_find_miranda(otr_user_state, hContact); + TrustLevel level = otr_context_get_trust(context); + if (level == TRUST_UNVERIFIED || level == TRUST_PRIVATE) { + otrl_context_force_finished(context); + //SetEncryptionStatus(hContact, TRUST_FINISHED); + otr_gui_gone_insecure(context->app_data, context); + //otrl_message_disconnect(otr_user_state, &ops, hContact, context->accountname, context->protocol, context->username); + //SetEncryptionStatus(hContact, TRUST_NOT_PRIVATE); + } + return; +} + +int WindowEvent(WPARAM wParam, LPARAM lParam) { + MessageWindowEventData *mwd = (MessageWindowEventData *)lParam; + + if(mwd->uType == MSG_WINDOW_EVT_CLOSE && options.end_window_close) { + FinishSession(mwd->hContact); + return 0; + } + + if(mwd->uType != MSG_WINDOW_EVT_OPEN) return 0; + + MCONTACT hContact = mwd->hContact, hTemp; + if((hTemp = db_mc_getMostOnline(hContact)) != 0) + hContact = hTemp; + + if (!CallService(MS_PROTO_ISPROTOONCONTACT, hContact, (LPARAM)MODULENAME)) + return 0; + + lib_cs_lock(); + ConnContext *context = otrl_context_find_miranda(otr_user_state, hContact); + lib_cs_unlock(); + + SetEncryptionStatus(hContact, otr_context_get_trust(context)); + + return 0; +} + +// if it's a protocol going offline, attempt to send terminate session to all contacts of that protocol +// (this would be hooked as the ME_CLIST_STATUSMODECHANGE handler except that event is sent *after* the proto goes offline) +int StatusModeChange(WPARAM wParam, LPARAM lParam) { + int status = (int)wParam; + + if(status != ID_STATUS_OFFLINE ) return 0; + + const char *proto = (char *)lParam; + MCONTACT hContact; + + lib_cs_lock(); + + ConnContext *context = otr_user_state->context_root; + while(context) { + if(context->msgstate == OTRL_MSGSTATE_ENCRYPTED && (proto == 0 || strcmp(proto, context->protocol) == 0)) { + hContact = (MCONTACT)context->app_data; + + if(hContact) { + otrl_message_disconnect(otr_user_state, &ops, (void*)hContact, context->accountname, context->protocol, context->username, OTRL_INSTAG_BEST); + SetEncryptionStatus(hContact, TRUST_NOT_PRIVATE); + } + + } + context = context->next; + } + lib_cs_unlock(); + + return 0; +} + +int OnContactSettingChanged(WPARAM hContact, LPARAM lParam) +{ + if (!options.end_offline) + return 0; + DBCONTACTWRITESETTING *cws = (DBCONTACTWRITESETTING *)lParam; + if (!lParam || strcmp(cws->szSetting, "Status") != 0) return 0; + int status=0; + switch (cws->value.type){ + case DBVT_WORD: + status = cws->value.wVal; + break; + case DBVT_BYTE: + status = cws->value.bVal; + break; + case DBVT_DWORD: + status = cws->value.dVal; + break; + } + if (status == ID_STATUS_OFFLINE) { + if (!hContact) { + // Protocol is going offline + // Terminate sessions with all contacts of that proto + StatusModeChange((WPARAM) ID_STATUS_OFFLINE, (LPARAM)cws->szModule); + return 0; + }else if(CallService(MS_PROTO_ISPROTOONCONTACT, hContact, (LPARAM)MODULENAME)) { + // only care about contacts to which this filter is attached + FinishSession(hContact); + } + } + + + return 0; +} + +void InitDBFilter() { + InitializeCriticalSectionAndSpinCount(lpRemoveChainCS, 500); + hDBEventPreAdd = HookEvent(ME_DB_EVENT_FILTER_ADD, OnDatabaseEventPreAdd); + hDBEventAdded = HookEvent(ME_DB_EVENT_ADDED, OnDatabaseEventAdded); + hContactSettingChanged = HookEvent(ME_DB_CONTACT_SETTINGCHANGED, OnContactSettingChanged); + timerId = SetTimer(0, 0, 1000, DeleteTimerProc); +} +void DeinitDBFilter() { + UnhookEvent(hDBEventPreAdd); + hDBEventPreAdd = 0; + UnhookEvent(hDBEventAdded); + hDBEventAdded = 0; + UnhookEvent(hContactSettingChanged); + hContactSettingChanged=0; + if (timerId) KillTimer(0, timerId); + DeleteTimerProc(0,0,0,0); + DeleteCriticalSection(lpRemoveChainCS); +} diff --git a/plugins/MirOTR/src/options.cpp b/plugins/MirOTR/src/options.cpp index 7a4bce4afc..89f2b49b46 100644 --- a/plugins/MirOTR/src/options.cpp +++ b/plugins/MirOTR/src/options.cpp @@ -1,868 +1,877 @@ -#include "stdafx.h" - -char g_fingerprint_store_filename[MAX_PATH]; -char g_private_key_filename[MAX_PATH]; -HANDLE hPATH_MIROTR; -Options options; -#define DATA_DIRECTORY MIRANDA_USERDATA "\\" MODULENAME -HANDLE hHookOptions; -struct PROTOREGENKEYOPTIONS { - HWND refresh; - TCHAR proto[129]; -}; - -void SetFilenames(const char *path) -{ - if (!path || !path[0]) - return; - - CreateDirectoryTree(path); - strcpy(g_fingerprint_store_filename, path); - strcpy(g_private_key_filename, path); - strcat(g_fingerprint_store_filename, ("\\")); - strcat(g_private_key_filename, ("\\")); - - strcat(g_fingerprint_store_filename, FINGERPRINT_STORE_FILENAME); - strcat(g_private_key_filename, PRIVATE_KEY_FILENAME); -} - -int FoldersChanged(WPARAM wParam, LPARAM lParam) -{ - char path[MAX_PATH]; - if ( FoldersGetCustomPath(hPATH_MIROTR, path, SIZEOF(path), "")) - SetFilenames( VARS(DATA_DIRECTORY)); - else - SetFilenames(path); - - ReadPrivkeyFiles(); - return 0; -} - -void LoadFilenames() -{ - if (hPATH_MIROTR = FoldersRegisterCustomPath("OTR", LPGEN("Private Data"), DATA_DIRECTORY)) { - HookEvent(ME_FOLDERS_PATH_CHANGED, FoldersChanged); - - // get the path - above are only defaults - there may be a different value in the db - FoldersChanged(0, 0); - } - else { - SetFilenames( VARS(DATA_DIRECTORY)); - ReadPrivkeyFiles(); - } -} - -void LoadOptions() { - options.default_policy = db_get_w(0, MODULENAME, "DefaultPolicy", OTRL_POLICY_OPPORTUNISTIC); - // deal with changed flags in proto.h and new interpretation of 'manual' mode (see common.h) - switch(options.default_policy) { - case OTRL_POLICY_MANUAL: - options.default_policy = OTRL_POLICY_MANUAL_MOD; - break; - case OTRL_POLICY_OPPORTUNISTIC: - case OTRL_POLICY_MANUAL_MOD: - case OTRL_POLICY_ALWAYS: - case OTRL_POLICY_NEVER: - break; - default: - options.default_policy = OTRL_POLICY_OPPORTUNISTIC; - break; - } - options.err_method = (ErrorDisplay)db_get_w(0, MODULENAME, "ErrorDisplay", ED_POP); - options.prefix_messages = (db_get_b(0, MODULENAME, "PrefixMessages", 0) == 1); - options.msg_inline = (db_get_b(0, MODULENAME, "MsgInline", 0) == 1); - options.msg_popup = (db_get_b(0, MODULENAME, "MsgPopup", 1) == 1); - options.delete_history = (db_get_b(0, MODULENAME, "NoHistory", 0) == 1); - options.delete_systeminfo = (db_get_b(0, MODULENAME, "NoSystemHistory", 0) == 1); - options.autoshow_verify = (db_get_b(0, MODULENAME, "AutoShowVerify", 1) == 1); - - DBVARIANT dbv; - if (!db_get_utf(0, MODULENAME, "Prefix", &dbv)) { - strncpy(options.prefix, dbv.pszVal, OPTIONS_PREFIXLEN-1); - options.prefix[OPTIONS_PREFIXLEN-1] = 0; - db_free(&dbv); - } else - strncpy(options.prefix, ("OTR: "), OPTIONS_PREFIXLEN-1); - - options.end_offline = (db_get_b(0, MODULENAME, "EndOffline", 1) == 1); - options.end_window_close = (db_get_b(0, MODULENAME, "EndWindowClose", 0) == 1); - - options.bHavePopups = 0 != ServiceExists(MS_POPUP_ADDPOPUPT) && ServiceExists(MS_POPUP_SHOWMESSAGE); - options.bHaveSecureIM = 0 != ServiceExists("SecureIM/IsContactSecured"); - options.bHaveButtonsBar = 0 != ServiceExists(MS_BB_ADDBUTTON); - - LoadFilenames(); -} - -extern "C" int OpenOptions(WPARAM wParam, LPARAM lParam) -{ - OPTIONSDIALOGPAGE odp = { sizeof(odp) }; - odp.position = 100; - odp.hInstance = hInst; - odp.ptszGroup = LPGENT("Services"); - odp.ptszTitle = _T("OTR"); - odp.flags = ODPF_BOLDGROUPS|ODPF_TCHAR; - - odp.ptszTab = _T(LANG_OPT_GENERAL); - odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_GENERAL); - odp.pfnDlgProc = DlgProcMirOTROpts; - Options_AddPage(wParam, &odp); - - odp.ptszTab = _T(LANG_OPT_PROTO); - odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_PROTO); - odp.pfnDlgProc = DlgProcMirOTROptsProto; - Options_AddPage(wParam, &odp); - - odp.ptszTab = _T(LANG_OPT_CONTACTS); - odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_CONTACTS); - odp.pfnDlgProc = DlgProcMirOTROptsContacts; - Options_AddPage(wParam, &odp); - - odp.ptszTab = _T(LANG_OPT_FINGER); - odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_FINGER); - odp.pfnDlgProc = DlgProcMirOTROptsFinger; - Options_AddPage(wParam, &odp); - return 0; -} - -void InitOptions() { - LoadOptions(); - hHookOptions = HookEvent(ME_OPT_INITIALISE, OpenOptions); -} - -void DeinitOptions() { - UnhookEvent(hHookOptions); -} - -void SaveOptions() { - db_set_w(0, MODULENAME, "DefaultPolicy", options.default_policy); - db_set_w(0, MODULENAME, "ErrorDisplay", (int)options.err_method); - db_set_b(0, MODULENAME, "PrefixMessages", options.prefix_messages ? 1 : 0); - db_set_b(0, MODULENAME, "MsgInline", options.msg_inline ? 1 : 0); - db_set_b(0, MODULENAME, "MsgPopup", options.msg_popup ? 1 : 0); - - db_set_b(0, MODULENAME, "NoHistory", options.delete_history ? 1 : 0); - db_set_b(0, MODULENAME, "NoSystemHistory", options.delete_systeminfo ? 1 : 0); - db_set_b(0, MODULENAME, "AutoShowVerify", options.autoshow_verify ? 1 : 0); - - db_set_utf(0, MODULENAME, "Prefix", options.prefix); - - db_set_b(0, MODULENAME, "EndOffline", options.end_offline ? 1 : 0); - db_set_b(0, MODULENAME, "EndWindowClose", options.end_window_close ? 1 : 0); -} - -extern "C" void set_context_contact(void *data, ConnContext *context) -{ - MCONTACT hContact = find_contact(context->username, context->protocol); - context->app_data = (void*)hContact; -} - -void ReadPrivkeyFiles() { - DEBUGOUT_T("READ privkey"); - lib_cs_lock(); - otrl_privkey_read(otr_user_state, g_private_key_filename); - otrl_privkey_read_fingerprints(otr_user_state, g_fingerprint_store_filename, set_context_contact, 0); - lib_cs_unlock(); -} - -static INT_PTR CALLBACK DlgProcMirOTROpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) -{ - TCHAR *prefix; char* prefix_utf; - switch ( msg ) { - case WM_INITDIALOG: - TranslateDialogDefault( hwndDlg ); - - // set default policy radio - switch(options.default_policy) { - case OTRL_POLICY_OPPORTUNISTIC: - CheckDlgButton(hwndDlg, IDC_RAD_OPP, BST_CHECKED); - break; - case OTRL_POLICY_MANUAL_MOD: - CheckDlgButton(hwndDlg, IDC_RAD_MANUAL, BST_CHECKED); - break; - case OTRL_POLICY_ALWAYS: - CheckDlgButton(hwndDlg, IDC_RAD_ALWAYS, BST_CHECKED); - break; - case OTRL_POLICY_NEVER: - CheckDlgButton(hwndDlg, IDC_RAD_NEVER, BST_CHECKED); - break; - } - - CheckDlgButton(hwndDlg, IDC_CHK_PREFIX, options.prefix_messages ? BST_CHECKED : BST_UNCHECKED); - CheckDlgButton(hwndDlg, IDC_CHK_MSGINLINE, options.msg_inline ? BST_CHECKED : BST_UNCHECKED); - CheckDlgButton(hwndDlg, IDC_CHK_MSGPOPUP, options.msg_popup ? BST_CHECKED : BST_UNCHECKED); - CheckDlgButton(hwndDlg, IDC_CHK_PREVENTSAVE, options.delete_history ? BST_CHECKED : BST_UNCHECKED); - CheckDlgButton(hwndDlg, IDC_CHK_PREVENTSYSSAVE, options.delete_systeminfo ? BST_CHECKED : BST_UNCHECKED); - CheckDlgButton(hwndDlg, IDC_CHK_AUTOSHOW_VERIFY, options.autoshow_verify ? BST_CHECKED : BST_UNCHECKED); - CheckDlgButton(hwndDlg, IDC_CHK_ENDOFFLINE, options.end_offline ? BST_CHECKED : BST_UNCHECKED); - CheckDlgButton(hwndDlg, IDC_CHK_ENDCLOSE, options.end_window_close ? BST_CHECKED : BST_UNCHECKED); - - prefix = mir_utf8decodeT(options.prefix); - SetDlgItemText(hwndDlg, IDC_ED_PREFIX, prefix); - mir_free(prefix); - - return TRUE; - break; - - case WM_COMMAND: - switch ( HIWORD( wParam )) { - case BN_CLICKED: - switch ( LOWORD( wParam )) { - case IDC_RAD_OPP: - case IDC_RAD_MANUAL: - case IDC_RAD_ALWAYS: - case IDC_RAD_NEVER: - case IDC_CHK_PREFIX: - case IDC_CHK_MSGINLINE: - case IDC_CHK_MSGPOPUP: - case IDC_CHK_PREVENTSAVE: - case IDC_CHK_AUTOSHOW_VERIFY: - case IDC_CHK_ENDOFFLINE: - case IDC_CHK_ENDCLOSE: - SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); - } - break; - case EN_CHANGE: - if (LOWORD( wParam ) == IDC_ED_PREFIX && ( HWND )lParam == GetFocus()) - SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); - break; - } - break; - - case WM_NOTIFY: - - if (((LPNMHDR)lParam)->code == (UINT) PSN_APPLY ) { - // handle apply - - if (IsDlgButtonChecked(hwndDlg, IDC_RAD_OPP)) - options.default_policy = OTRL_POLICY_OPPORTUNISTIC; - else if (IsDlgButtonChecked(hwndDlg, IDC_RAD_MANUAL)) - options.default_policy = OTRL_POLICY_MANUAL_MOD; - else if (IsDlgButtonChecked(hwndDlg, IDC_RAD_ALWAYS)) - options.default_policy = OTRL_POLICY_ALWAYS; - else - options.default_policy = OTRL_POLICY_NEVER; - - options.prefix_messages = (TRUE==IsDlgButtonChecked(hwndDlg, IDC_CHK_PREFIX)); - options.msg_inline = (TRUE==IsDlgButtonChecked(hwndDlg, IDC_CHK_MSGINLINE)); - options.msg_popup = (TRUE==IsDlgButtonChecked(hwndDlg, IDC_CHK_MSGPOPUP)); - options.delete_history = (TRUE==IsDlgButtonChecked(hwndDlg, IDC_CHK_PREVENTSAVE)); - options.delete_systeminfo = (TRUE==IsDlgButtonChecked(hwndDlg, IDC_CHK_PREVENTSYSSAVE)); - options.autoshow_verify = (TRUE==IsDlgButtonChecked(hwndDlg, IDC_CHK_AUTOSHOW_VERIFY)); - options.end_offline = (TRUE==IsDlgButtonChecked(hwndDlg, IDC_CHK_ENDOFFLINE)); - options.end_window_close = (TRUE==IsDlgButtonChecked(hwndDlg, IDC_CHK_ENDCLOSE)); - - prefix = (TCHAR*)mir_alloc(sizeof(TCHAR)*OPTIONS_PREFIXLEN); - GetDlgItemText(hwndDlg, IDC_ED_PREFIX, prefix, OPTIONS_PREFIXLEN); - prefix_utf = mir_utf8encodeT(prefix); - mir_free(prefix); - strncpy(options.prefix, prefix_utf, OPTIONS_PREFIXLEN-1); - mir_free(prefix_utf); - - SaveOptions(); - - return TRUE; - } - - break; - } - return FALSE; -} - -static unsigned int CALLBACK regen_key_thread(void* param) -{ - Thread_Push(0); - PROTOREGENKEYOPTIONS *opts = (PROTOREGENKEYOPTIONS *)param; - TCHAR buff[512]; - - mir_sntprintf(buff, SIZEOF(buff), TranslateT(LANG_OTR_ASK_NEWKEY), opts->proto); - EnableWindow(opts->refresh, FALSE); - if (IDYES == MessageBox(opts->refresh, buff, TranslateT(LANG_OTR_INFO), MB_ICONQUESTION|MB_YESNO)) - { - char* proto = mir_t2a(opts->proto); - otr_gui_create_privkey(0, proto, proto); - SendMessage(opts->refresh, WMU_REFRESHPROTOLIST, 0, 0); - /* - char *fp = (char*)mir_alloc(20); - otrl_privkey_fingerprint(otr_user_state, fp, proto, proto); - TCHAR *fpt = mir_a2t(fp); - mir_free(fp); - ListView_SetItemText(GetDlgItem(hwndDlg, IDC_LV_PROTO_PROTOS), sel, 2, fpt); - mir_free(fpt); - mir_free(proto); - */ - } - EnableWindow(opts->refresh, TRUE); - delete opts; - Thread_Pop(); - return 0; -} - -static INT_PTR CALLBACK DlgProcMirOTROptsProto(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) -{ - HWND lv; - switch ( msg ) { - case WM_INITDIALOG: - TranslateDialogDefault( hwndDlg ); - lv = GetDlgItem(hwndDlg, IDC_LV_PROTO_PROTOS); - - { - HWND cmb = GetDlgItem(hwndDlg, IDC_CMB_PROTO_POLICY); - SendMessage(cmb, CB_ADDSTRING, 0, (WPARAM)TranslateT(LANG_POLICY_DEFAULT)); - SendMessage(cmb, CB_ADDSTRING, 0, (WPARAM)TranslateT(LANG_POLICY_ALWAYS)); - SendMessage(cmb, CB_ADDSTRING, 0, (WPARAM)TranslateT(LANG_POLICY_OPP)); - SendMessage(cmb, CB_ADDSTRING, 0, (WPARAM)TranslateT(LANG_POLICY_MANUAL)); - SendMessage(cmb, CB_ADDSTRING, 0, (WPARAM)TranslateT(LANG_POLICY_NEVER)); - SendDlgItemMessage(hwndDlg, IDC_CMB_PROTO_POLICY, CB_SETCURSEL, (LPARAM)-1, 0); - EnableWindow(GetDlgItem(hwndDlg, IDC_CMB_PROTO_POLICY), FALSE); - EnableWindow(GetDlgItem(hwndDlg, IDC_BTN_PROTO_NEWKEY), FALSE); - EnableWindow(GetDlgItem(hwndDlg, IDC_BTN_PROTO_FORGET), FALSE); - } - - SendMessage(lv,LVM_SETEXTENDEDLISTVIEWSTYLE, 0,LVS_EX_FULLROWSELECT);// | LVS_EX_CHECKBOXES); - { - // add list columns - LVCOLUMN lvc; - // Initialize the LVCOLUMN structure. - // The mask specifies that the format, width, text, and - // subitem members of the structure are valid. - lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM; - lvc.fmt = LVCFMT_LEFT; - - lvc.iSubItem = 0; - lvc.pszText = TranslateT(LANG_PROTO); - lvc.cx = 85; // width of column in pixels - ListView_InsertColumn(lv, 0, &lvc); - - lvc.iSubItem = 1; - lvc.pszText = TranslateT(LANG_POLICY); - lvc.cx = 80; // width of column in pixels - ListView_InsertColumn(lv, 1, &lvc); - - lvc.iSubItem = 2; - lvc.pszText = TranslateT(LANG_FINGERPRINT); - lvc.cx = 275; // width of column in pixels - ListView_InsertColumn(lv, 2, &lvc); - } - PostMessage(hwndDlg, WMU_REFRESHPROTOLIST, 0, 0); - - return TRUE; - case WMU_REFRESHPROTOLIST: - { - lv = GetDlgItem(hwndDlg, IDC_LV_PROTO_PROTOS); - ListView_DeleteAllItems(lv); - int num_protocols; - PROTOACCOUNT **pppDesc; - int ilvItem; - LV_ITEM item = {0}; - char fprint[45]; - TCHAR* temp; - //BOOL unicode = ListView_GetUnicodeFormat(lv); - - ProtoEnumAccounts(&num_protocols, &pppDesc); - for(int i = 0; i < num_protocols; i++) { - if((strcmp(pppDesc[i]->szModuleName, META_PROTO) != 0) - && (CallProtoService(pppDesc[i]->szModuleName, PS_GETCAPS, PFLAGNUM_1, 0) & PF1_IM) == PF1_IM) - { - //if (unicode) { - item.mask = LVIF_TEXT; - temp = mir_a2t(pppDesc[i]->szModuleName); - item.pszText = temp; - ilvItem = ListView_InsertItem(lv, &item); - mir_free(temp); - - - ListView_SetItemText(lv, ilvItem, 1, (TCHAR*)policy_to_string(db_get_dw(0,MODULENAME"_ProtoPol", pppDesc[i]->szModuleName, CONTACT_DEFAULT_POLICY)) ); - if(otrl_privkey_fingerprint(otr_user_state, fprint, pppDesc[i]->szModuleName, pppDesc[i]->szModuleName)) { - temp = mir_a2t(fprint); - ListView_SetItemText(lv, ilvItem, 2, temp); - mir_free(temp); - } - } - } - } - return TRUE; - case WM_COMMAND: - switch ( HIWORD( wParam )) { - case BN_CLICKED: - switch ( LOWORD( wParam )) { - case IDC_BTN_PROTO_NEWKEY: - { - int sel = ListView_GetSelectionMark(GetDlgItem(hwndDlg, IDC_LV_PROTO_PROTOS)); - if (sel != -1) { - PROTOREGENKEYOPTIONS *opts = new PROTOREGENKEYOPTIONS(); - opts->refresh = hwndDlg; - ListView_GetItemText(GetDlgItem(hwndDlg, IDC_LV_PROTO_PROTOS), sel, 0, opts->proto, SIZEOF(opts->proto)); - CloseHandle((HANDLE)_beginthreadex(0, 0, regen_key_thread, opts, 0, 0)); - } - }break; - case IDC_BTN_PROTO_FORGET: - { - int sel = ListView_GetSelectionMark(GetDlgItem(hwndDlg, IDC_LV_PROTO_PROTOS)); - if (sel != -1) { - TCHAR buff_proto[128]; - ListView_GetItemText(GetDlgItem(hwndDlg, IDC_LV_PROTO_PROTOS), sel, 0, buff_proto, SIZEOF(buff_proto)); - TCHAR buff[512]; - mir_sntprintf(buff, SIZEOF(buff), TranslateT(LANG_OTR_ASK_REMOVEKEY), buff_proto); - if (IDYES == MessageBox(hwndDlg, buff, TranslateT(LANG_OTR_INFO), MB_ICONQUESTION|MB_YESNO)) - { - char* proto = mir_t2a(buff_proto); - OtrlPrivKey *key = otrl_privkey_find(otr_user_state, proto, proto); - mir_free(proto); - if (key) { - otrl_privkey_forget(key); - otrl_privkey_write(otr_user_state, g_private_key_filename); - ListView_SetItemText(GetDlgItem(hwndDlg, IDC_LV_PROTO_PROTOS), sel, 2, _T("")); - } - } - } - }break; - } - break; - case CBN_SELCHANGE: - switch ( LOWORD( wParam )) { - case IDC_CMB_PROTO_POLICY: - { - int proto = ListView_GetSelectionMark(GetDlgItem(hwndDlg, IDC_LV_PROTO_PROTOS)); - if (proto == -1) break; - int sel = SendDlgItemMessage(hwndDlg, IDC_CMB_PROTO_POLICY, CB_GETCURSEL, 0, 0); - if (sel==CB_ERR) break; - int len = SendDlgItemMessage(hwndDlg, IDC_CMB_PROTO_POLICY, CB_GETLBTEXTLEN, sel, 0); - if (len < 0) break; - TCHAR *text = new TCHAR[len+1]; - SendDlgItemMessage(hwndDlg, IDC_CMB_PROTO_POLICY, CB_GETLBTEXT, sel, (LPARAM)text); - ListView_SetItemText(GetDlgItem(hwndDlg, IDC_LV_PROTO_PROTOS), proto, 1, text); - delete[] text; - SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); - }break; - } - break; - } - break; - - case WM_NOTIFY: - if (((LPNMHDR) lParam)->code == (UINT) LVN_ITEMCHANGED && ((LPNMHDR) lParam)->hwndFrom == GetDlgItem(hwndDlg, IDC_LV_PROTO_PROTOS) - && (((LPNMLISTVIEW)lParam)->uNewState & LVIS_SELECTED )) { - int sel = ListView_GetSelectionMark(((LPNMHDR) lParam)->hwndFrom); - if (sel == -1) { - SendDlgItemMessage(hwndDlg, IDC_CMB_PROTO_POLICY, CB_SETCURSEL, (LPARAM)-1, 0); - EnableWindow(GetDlgItem(hwndDlg, IDC_CMB_PROTO_POLICY), FALSE); - EnableWindow(GetDlgItem(hwndDlg, IDC_BTN_PROTO_NEWKEY), FALSE); - EnableWindow(GetDlgItem(hwndDlg, IDC_BTN_PROTO_FORGET), FALSE); - } else { - EnableWindow(GetDlgItem(hwndDlg, IDC_CMB_PROTO_POLICY), TRUE); - EnableWindow(GetDlgItem(hwndDlg, IDC_BTN_PROTO_NEWKEY), TRUE); - EnableWindow(GetDlgItem(hwndDlg, IDC_BTN_PROTO_FORGET), TRUE); - TCHAR buff[50]; - ListView_GetItemText(((LPNMHDR)lParam)->hwndFrom, sel, 1, buff, SIZEOF(buff)); - SendDlgItemMessage(hwndDlg, IDC_CMB_PROTO_POLICY, CB_SELECTSTRING, (LPARAM)-1, (WPARAM)buff); - } - - } else if (((LPNMHDR)lParam)->code == (UINT) PSN_APPLY ) { - lv = GetDlgItem(hwndDlg, IDC_LV_PROTO_PROTOS); - int cnt = ListView_GetItemCount(lv); - TCHAR proto_t[128], policy[64]; - char* proto; - for (int i = 0; i < cnt; ++i) { - ListView_GetItemText(lv, i, 0, proto_t, SIZEOF(proto_t)); - ListView_GetItemText(lv, i, 1, policy, SIZEOF(policy)); - proto = mir_t2a(proto_t); - db_set_dw(0, MODULENAME"_ProtoPol", proto, policy_from_string(policy)); - mir_free(proto); - } - // handle apply - return TRUE; - } - break; - } - return FALSE; -} - -static INT_PTR CALLBACK DlgProcMirOTROptsContacts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) -{ - switch ( msg ) { - case WM_INITDIALOG: - { - TranslateDialogDefault( hwndDlg ); - - SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR) new ContactPolicyMap()); - - HWND cmb = GetDlgItem(hwndDlg, IDC_CMB_CONT_POLICY); - SendMessage(cmb, CB_ADDSTRING, 0, (WPARAM)TranslateT(LANG_POLICY_DEFAULT)); - SendMessage(cmb, CB_ADDSTRING, 0, (WPARAM)TranslateT(LANG_POLICY_ALWAYS)); - SendMessage(cmb, CB_ADDSTRING, 0, (WPARAM)TranslateT(LANG_POLICY_OPP)); - SendMessage(cmb, CB_ADDSTRING, 0, (WPARAM)TranslateT(LANG_POLICY_MANUAL)); - SendMessage(cmb, CB_ADDSTRING, 0, (WPARAM)TranslateT(LANG_POLICY_NEVER)); - EnableWindow(GetDlgItem(hwndDlg, IDC_CMB_CONT_POLICY), FALSE); - - SendDlgItemMessage(hwndDlg, IDC_LV_CONT_CONTACTS ,LVM_SETEXTENDEDLISTVIEWSTYLE, 0,LVS_EX_FULLROWSELECT);// | LVS_EX_CHECKBOXES); - - - HWND lv = GetDlgItem(hwndDlg, IDC_LV_CONT_CONTACTS); - - - // add list columns - LVCOLUMN lvc; - // Initialize the LVCOLUMN structure. - // The mask specifies that the format, width, text, and - // subitem members of the structure are valid. - lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM; - lvc.fmt = LVCFMT_LEFT; - - lvc.iSubItem = 0; - lvc.pszText = TranslateT(LANG_CONTACT); - lvc.cx = 150; // width of column in pixels - ListView_InsertColumn(lv, 0, &lvc); - - lvc.iSubItem = 1; - lvc.pszText = TranslateT(LANG_PROTO); - lvc.cx = 100; // width of column in pixels - ListView_InsertColumn(lv, 1, &lvc); - - lvc.iSubItem = 2; - lvc.pszText = TranslateT(LANG_POLICY); - lvc.cx = 90; // width of column in pixels - ListView_InsertColumn(lv, 2, &lvc); - - lvc.iSubItem = 3; - lvc.pszText = TranslateT(LANG_HTMLCONV); - lvc.cx = 80; // width of column in pixels - ListView_InsertColumn(lv, 3, &lvc); - } - SendMessage(hwndDlg, WMU_REFRESHLIST, 0, 0); - - return TRUE; - case WMU_REFRESHLIST: - { - HWND lv = GetDlgItem(hwndDlg, IDC_LV_CONT_CONTACTS); - - ListView_DeleteAllItems(lv); - - LVITEM lvI = {0}; - - // Some code to create the list-view control. - // Initialize LVITEM members that are common to all - // items. - lvI.mask = LVIF_TEXT | LVIF_PARAM;// | LVIF_NORECOMPUTE;// | LVIF_IMAGE; - - const char *proto; - TCHAR *proto_t; - for (MCONTACT hContact = db_find_first(); hContact; hContact = db_find_next(hContact)) { - proto = GetContactProto(hContact); - if(proto && db_get_b(hContact, proto, "ChatRoom", 0) == 0 && CallService(MS_PROTO_ISPROTOONCONTACT, hContact, (LPARAM)MODULENAME) // ignore chatrooms - && strcmp(proto, META_PROTO) != 0) // and MetaContacts - { - lvI.iItem = 0; - lvI.iSubItem = 0; - lvI.lParam = hContact; - lvI.pszText = (TCHAR*)contact_get_nameT(hContact); - lvI.iItem = ListView_InsertItem(lv , &lvI); - - proto_t = mir_a2t(proto); - ListView_SetItemText(lv, lvI.iItem, 1, proto_t); - mir_free(proto_t); - - ListView_SetItemText(lv, lvI.iItem, 2, (TCHAR*)policy_to_string((OtrlPolicy)db_get_dw(hContact, MODULENAME, "Policy", CONTACT_DEFAULT_POLICY)) ); - ListView_SetItemText(lv, lvI.iItem, 3, (db_get_b(hContact, MODULENAME, "HTMLConv", 0))?TranslateT(LANG_YES):TranslateT(LANG_NO) ); - } - } - } - return TRUE; - break; - - case WM_COMMAND: - switch ( HIWORD( wParam )) { - case CBN_SELCHANGE: - switch ( LOWORD( wParam )) { - case IDC_CMB_CONT_POLICY: - { - MCONTACT hContact = 0; - int iUser = ListView_GetSelectionMark(GetDlgItem(hwndDlg, IDC_LV_CONT_CONTACTS)); - if (iUser == -1) break; - int sel = SendDlgItemMessage(hwndDlg, IDC_CMB_CONT_POLICY, CB_GETCURSEL, 0, 0); - if (sel==CB_ERR) break; - int len = SendDlgItemMessage(hwndDlg, IDC_CMB_CONT_POLICY, CB_GETLBTEXTLEN, sel, 0); - if (len < 0) break; - TCHAR *text = new TCHAR[len+1]; - SendDlgItemMessage(hwndDlg, IDC_CMB_CONT_POLICY, CB_GETLBTEXT, sel, (LPARAM)text); - ListView_SetItemText(GetDlgItem(hwndDlg, IDC_LV_CONT_CONTACTS), iUser, 2, text); - OtrlPolicy policy = policy_from_string(text); - delete[] text; - LVITEM lvi = {0}; - lvi.mask = LVIF_PARAM; - lvi.iItem = iUser; - lvi.iSubItem = 0; - ListView_GetItem(GetDlgItem(hwndDlg, IDC_LV_CONT_CONTACTS), &lvi); - ContactPolicyMap* cpm = (ContactPolicyMap*) GetWindowLongPtr(hwndDlg, GWLP_USERDATA); - hContact = (MCONTACT)lvi.lParam; - (*cpm)[hContact].policy = policy; - SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); - }break; - } - break; - } - break; - - case WM_NOTIFY: - { - UINT code = ((LPNMHDR) lParam)->code; - if (code == (UINT) PSN_APPLY ) { - // handle apply - - ContactPolicyMap *cpm = (ContactPolicyMap*) GetWindowLongPtr(hwndDlg, GWLP_USERDATA); - // Iterate over the map and print out all key/value pairs. - // Using a const_iterator since we are not going to change the values. - for(ContactPolicyMap::const_iterator it = cpm->begin(); it != cpm->end(); ++it) - { - if (!it->first) continue; - if (it->second.policy) db_set_dw(it->first, MODULENAME, "Policy", (DWORD)it->second.policy); - if (it->second.htmlconv) db_set_b(it->first, MODULENAME, "HTMLConv", it->second.htmlconv-1); - } - return TRUE; - } else if (((LPNMHDR) lParam)->hwndFrom == GetDlgItem(hwndDlg, IDC_LV_CONT_CONTACTS)) { - if (code == (UINT) LVN_ITEMCHANGED && (((LPNMLISTVIEW)lParam)->uNewState & LVIS_SELECTED )) { - int sel = ListView_GetSelectionMark(((LPNMHDR) lParam)->hwndFrom); - if (sel == -1) { - SendDlgItemMessage(hwndDlg, IDC_CMB_CONT_POLICY, CB_SETCURSEL, (LPARAM)-1, 0); - EnableWindow(GetDlgItem(hwndDlg, IDC_CMB_CONT_POLICY), FALSE); - } else { - EnableWindow(GetDlgItem(hwndDlg, IDC_CMB_CONT_POLICY), TRUE); - TCHAR buff[50]; - ListView_GetItemText(((LPNMHDR)lParam)->hwndFrom, sel, 2, buff, SIZEOF(buff)); - SendDlgItemMessage(hwndDlg, IDC_CMB_CONT_POLICY, CB_SELECTSTRING, (LPARAM)-1, (WPARAM)buff); - } - } else if (code == (UINT) NM_CLICK) { - if (((LPNMLISTVIEW)lParam)->iSubItem == 3) { - LVITEM lvi; - lvi.mask = LVIF_PARAM; - lvi.iItem = ((LPNMLISTVIEW)lParam)->iItem; - if (lvi.iItem < 0) return FALSE; - lvi.iSubItem = 0; - SendDlgItemMessage(hwndDlg, IDC_LV_CONT_CONTACTS, LVM_GETITEM, 0, (LPARAM)&lvi); - - MCONTACT hContact = (MCONTACT)lvi.lParam; - ContactPolicyMap *cp = (ContactPolicyMap *)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); - TCHAR buff[50]; - ListView_GetItemText(((LPNMHDR)lParam)->hwndFrom, lvi.iItem, 3, buff, SIZEOF(buff)); - if (_tcsncmp(buff, TranslateT(LANG_YES), 50)==0){ - (*cp)[hContact].htmlconv = HTMLCONV_DISABLE; - ListView_SetItemText(((LPNMHDR)lParam)->hwndFrom, lvi.iItem, 3, TranslateT(LANG_NO)); - }else { - (*cp)[hContact].htmlconv = HTMLCONV_ENABLE; - ListView_SetItemText(((LPNMHDR)lParam)->hwndFrom, lvi.iItem, 3, TranslateT(LANG_YES)); - } - (*cp)[hContact].htmlconv += 1; - SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); - } - - - } - } - }break; - case WM_DESTROY: - ContactPolicyMap *cpm = (ContactPolicyMap*) GetWindowLongPtr(hwndDlg, GWLP_USERDATA); - cpm->clear(); - delete cpm; - break; - } - return FALSE; -} - -static INT_PTR CALLBACK DlgProcMirOTROptsFinger(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) -{ - switch ( msg ) { - case WM_INITDIALOG: - TranslateDialogDefault( hwndDlg ); - SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR) new FPModifyMap()); - - SendDlgItemMessage(hwndDlg, IDC_LV_FINGER_LIST ,LVM_SETEXTENDEDLISTVIEWSTYLE, 0,LVS_EX_FULLROWSELECT);// | LVS_EX_CHECKBOXES); - - { - HWND lv = GetDlgItem(hwndDlg, IDC_LV_FINGER_LIST); - // add list columns - LVCOLUMN lvc; - // Initialize the LVCOLUMN structure. - // The mask specifies that the format, width, text, and - // subitem members of the structure are valid. - lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM; - lvc.fmt = LVCFMT_LEFT; - - lvc.iSubItem = 0; - lvc.pszText = TranslateT(LANG_CONTACT); - lvc.cx = 100; // width of column in pixels - ListView_InsertColumn(lv, 0, &lvc); - - lvc.iSubItem = 1; - lvc.pszText = TranslateT(LANG_PROTO); - lvc.cx = 90; // width of column in pixels - ListView_InsertColumn(lv, 1, &lvc); - - lvc.iSubItem = 2; - lvc.pszText = TranslateT(LANG_ACTIVE); - lvc.cx = 50; // width of column in pixels - ListView_InsertColumn(lv, 2, &lvc); - - lvc.iSubItem = 3; - lvc.pszText = TranslateT(LANG_VERIFIED); - lvc.cx = 50; // width of column in pixels - ListView_InsertColumn(lv, 3, &lvc); - - lvc.iSubItem = 4; - lvc.pszText = TranslateT(LANG_FINGERPRINT); - lvc.cx = 300; // width of column in pixels - ListView_InsertColumn(lv, 4, &lvc); - } - SendMessage(hwndDlg, WMU_REFRESHLIST, 0, 0); - - return TRUE; - - case WMU_REFRESHLIST: - //enumerate contacts, fill in list - { - HWND lv = GetDlgItem(hwndDlg, IDC_LV_FINGER_LIST); - ListView_DeleteAllItems(lv); - - LVITEM lvI = {0}; - - // Some code to create the list-view control. - // Initialize LVITEM members that are common to all - // items. - lvI.mask = LVIF_TEXT | LVIF_PARAM;// | LVIF_NORECOMPUTE;// | LVIF_IMAGE; - - TCHAR *proto, *user, hash[45] = {0}; - for (ConnContext *context = otr_user_state->context_root;context;context = context->next) { - if (context->app_data) { - user = (TCHAR*)contact_get_nameT((MCONTACT)context->app_data); - if (user) { - proto = mir_a2t(context->protocol); - - for(Fingerprint *fp = context->fingerprint_root.next;fp;fp = fp->next) { - otrl_privkey_hash_to_humanT(hash, fp->fingerprint); - lvI.iSubItem = 0; - lvI.lParam = (LPARAM)fp; - lvI.pszText = user; - int d = ListView_InsertItem(lv, &lvI); - - ListView_SetItemText(lv,d, 1, proto); - ListView_SetItemText(lv,d, 2, (context->active_fingerprint == fp)? TranslateT(LANG_YES) : TranslateT(LANG_NO)); - ListView_SetItemText(lv,d, 3, (fp->trust && fp->trust[0] != '\0')? TranslateT(LANG_YES) : TranslateT(LANG_NO)); - ListView_SetItemText(lv,d, 4, hash ); - } - mir_free(proto); - } - } - } - } - - return TRUE; - case WM_COMMAND: - switch ( HIWORD( wParam )) { - case BN_CLICKED: - switch ( LOWORD( wParam )) { - case IDC_BTN_FINGER_DONTTRUST: - { - int sel = ListView_GetSelectionMark(GetDlgItem(hwndDlg, IDC_LV_FINGER_LIST)); - if (sel != -1) { - LVITEM lvi = {0}; - lvi.mask = LVIF_PARAM; - lvi.iItem = sel; - ListView_GetItem(GetDlgItem(hwndDlg, IDC_LV_FINGER_LIST), &lvi); - Fingerprint *fp = (Fingerprint*) lvi.lParam; - FPModifyMap* fpm = (FPModifyMap*) GetWindowLongPtr(hwndDlg, GWLP_USERDATA); - (*fpm)[fp] = FPM_NOTRUST; - ListView_SetItemText(GetDlgItem(hwndDlg, IDC_LV_FINGER_LIST), sel, 3, TranslateT(LANG_NO)); - SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); - } - }break; - case IDC_BTN_FINGER_TRUST: - { - int sel = ListView_GetSelectionMark(GetDlgItem(hwndDlg, IDC_LV_FINGER_LIST)); - if (sel != -1) { - LVITEM lvi = {0}; - lvi.mask = LVIF_PARAM; - lvi.iItem = sel; - ListView_GetItem(GetDlgItem(hwndDlg, IDC_LV_FINGER_LIST), &lvi); - Fingerprint *fp = (Fingerprint*) lvi.lParam; - FPModifyMap* fpm = (FPModifyMap*) GetWindowLongPtr(hwndDlg, GWLP_USERDATA); - (*fpm)[fp] = FPM_VERIFY; - ListView_SetItemText(GetDlgItem(hwndDlg, IDC_LV_FINGER_LIST), sel, 3, TranslateT(LANG_YES)); - SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); - } - }break; - case IDC_BTN_FINGER_FORGET: - { - int sel = ListView_GetSelectionMark(GetDlgItem(hwndDlg, IDC_LV_FINGER_LIST)); - if (sel != -1) { - LVITEM lvi = {0}; - lvi.mask = LVIF_PARAM; - lvi.iItem = sel; - ListView_GetItem(GetDlgItem(hwndDlg, IDC_LV_FINGER_LIST), &lvi); - Fingerprint *fp = (Fingerprint*) lvi.lParam; - if (fp->context->active_fingerprint == fp) { - TCHAR buff[1024], hash[45]; - otrl_privkey_hash_to_humanT(hash, fp->fingerprint); - mir_sntprintf(buff, SIZEOF(buff), TranslateT(LANG_FINGERPRINT_STILL_IN_USE), hash, contact_get_nameT((MCONTACT)fp->context->app_data)); - ShowError(buff); - } else { - FPModifyMap* fpm = (FPModifyMap*) GetWindowLongPtr(hwndDlg, GWLP_USERDATA); - (*fpm)[fp] = FPM_DELETE; - ListView_DeleteItem(GetDlgItem(hwndDlg, IDC_LV_FINGER_LIST), sel); - SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); - } - } - }break; - } - } - break; - - case WM_NOTIFY: - if (((LPNMHDR)lParam)->code == (UINT) PSN_APPLY ) { - // handle apply - - FPModifyMap *fpm = (FPModifyMap*) GetWindowLongPtr(hwndDlg, GWLP_USERDATA); - // Iterate over the map and print out all key/value pairs. - // Using a const_iterator since we are not going to change the values. - for(FPModifyMap::const_iterator it = fpm->begin(); it != fpm->end(); ++it) - { - if (!it->first) continue; - switch (it->second) { - case FPM_DELETE: - if (it->first->context->active_fingerprint == it->first) { - TCHAR buff[1024], hash[45]; - otrl_privkey_hash_to_humanT(hash, it->first->fingerprint); - mir_sntprintf(buff, SIZEOF(buff), TranslateT(LANG_FINGERPRINT_NOT_DELETED), hash, contact_get_nameT((MCONTACT)it->first->context->app_data)); - ShowError(buff); - } else { - otrl_context_forget_fingerprint(it->first, 1); - } - break; - case FPM_VERIFY: - otrl_context_set_trust(it->first, "verified"); - if (it->first == it->first->context->active_fingerprint) - 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) - VerifyFingerprint(it->first->context, false); - //SetEncryptionStatus((HANDLE)it->first->context->app_data, otr_context_get_trust(it->first->context)); - break; - } - } - if (!fpm->empty()) otr_gui_write_fingerprints(0); - fpm->clear(); - SendMessage(hwndDlg, WMU_REFRESHLIST, 0, 0); - - return TRUE; - } - break; - case WM_DESTROY: - FPModifyMap *fpm = (FPModifyMap*) GetWindowLongPtr(hwndDlg, GWLP_USERDATA); - fpm->clear(); - delete fpm; - break; - } - - return FALSE; -} \ No newline at end of file +#include "stdafx.h" +extern "C"{ + #include "otrlextensions.h" +} + +char g_private_key_filename[MAX_PATH]; +char g_fingerprint_store_filename[MAX_PATH]; +char g_instag_filename[MAX_PATH]; +HANDLE hPATH_MIROTR; +Options options; +#define DATA_DIRECTORY MIRANDA_USERDATA "\\" MODULENAME +HANDLE hHookOptions; +struct PROTOREGENKEYOPTIONS { + HWND refresh; + TCHAR proto[129]; +}; + +void SetFilenames(const char *path) +{ + if (!path || !path[0]) + return; + CreateDirectoryTree(path); + + strcpy(g_private_key_filename, path); + strcat(g_private_key_filename, ("\\")); + strcat(g_private_key_filename, PRIVATE_KEY_FILENAME); + + strcpy(g_fingerprint_store_filename, path); + strcat(g_fingerprint_store_filename, ("\\")); + strcat(g_fingerprint_store_filename, FINGERPRINT_STORE_FILENAME); + + strcpy(g_instag_filename, path); + strcat(g_instag_filename, ("\\")); + strcat(g_instag_filename, INSTAG_FILENAME); +} + +int FoldersChanged(WPARAM wParam, LPARAM lParam) +{ + char path[MAX_PATH]; + if ( FoldersGetCustomPath(hPATH_MIROTR, path, SIZEOF(path), "")) + SetFilenames( VARS(DATA_DIRECTORY)); + else + SetFilenames(path); + + ReadPrivkeyFiles(); + return 0; +} + +void LoadFilenames() +{ + if (hPATH_MIROTR = FoldersRegisterCustomPath("OTR", LPGEN("Private Data"), DATA_DIRECTORY)) { + HookEvent(ME_FOLDERS_PATH_CHANGED, FoldersChanged); + + // get the path - above are only defaults - there may be a different value in the db + FoldersChanged(0, 0); + } + else { + SetFilenames( VARS(DATA_DIRECTORY)); + ReadPrivkeyFiles(); + } +} + +void LoadOptions() { + options.default_policy = db_get_w(0, MODULENAME, "DefaultPolicy", OTRL_POLICY_OPPORTUNISTIC); + // deal with changed flags in proto.h and new interpretation of 'manual' mode (see common.h) + switch(options.default_policy) { + case OTRL_POLICY_MANUAL: + options.default_policy = OTRL_POLICY_MANUAL_MOD; + break; + case OTRL_POLICY_OPPORTUNISTIC: + case OTRL_POLICY_MANUAL_MOD: + case OTRL_POLICY_ALWAYS: + case OTRL_POLICY_NEVER: + break; + default: + options.default_policy = OTRL_POLICY_OPPORTUNISTIC; + break; + } + options.err_method = (ErrorDisplay)db_get_w(0, MODULENAME, "ErrorDisplay", ED_POP); + options.prefix_messages = (db_get_b(0, MODULENAME, "PrefixMessages", 0) == 1); + options.msg_inline = (db_get_b(0, MODULENAME, "MsgInline", 0) == 1); + options.msg_popup = (db_get_b(0, MODULENAME, "MsgPopup", 1) == 1); + options.delete_history = (db_get_b(0, MODULENAME, "NoHistory", 0) == 1); + options.delete_systeminfo = (db_get_b(0, MODULENAME, "NoSystemHistory", 0) == 1); + options.autoshow_verify = (db_get_b(0, MODULENAME, "AutoShowVerify", 1) == 1); + + DBVARIANT dbv; + if (!db_get_utf(0, MODULENAME, "Prefix", &dbv)) { + strncpy(options.prefix, dbv.pszVal, OPTIONS_PREFIXLEN-1); + options.prefix[OPTIONS_PREFIXLEN-1] = 0; + db_free(&dbv); + } else + strncpy(options.prefix, ("OTR: "), OPTIONS_PREFIXLEN-1); + + options.end_offline = (db_get_b(0, MODULENAME, "EndOffline", 1) == 1); + options.end_window_close = (db_get_b(0, MODULENAME, "EndWindowClose", 0) == 1); + + options.bHavePopups = 0 != ServiceExists(MS_POPUP_ADDPOPUPT) && ServiceExists(MS_POPUP_SHOWMESSAGE); + options.bHaveSecureIM = 0 != ServiceExists("SecureIM/IsContactSecured"); + options.bHaveButtonsBar = 0 != ServiceExists(MS_BB_ADDBUTTON); + + LoadFilenames(); +} + +extern "C" int OpenOptions(WPARAM wParam, LPARAM lParam) +{ + OPTIONSDIALOGPAGE odp = { sizeof(odp) }; + odp.position = 100; + odp.hInstance = hInst; + odp.ptszGroup = LPGENT("Services"); + odp.ptszTitle = _T("OTR"); + odp.flags = ODPF_BOLDGROUPS|ODPF_TCHAR; + + odp.ptszTab = _T(LANG_OPT_GENERAL); + odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_GENERAL); + odp.pfnDlgProc = DlgProcMirOTROpts; + Options_AddPage(wParam, &odp); + + odp.ptszTab = _T(LANG_OPT_PROTO); + odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_PROTO); + odp.pfnDlgProc = DlgProcMirOTROptsProto; + Options_AddPage(wParam, &odp); + + odp.ptszTab = _T(LANG_OPT_CONTACTS); + odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_CONTACTS); + odp.pfnDlgProc = DlgProcMirOTROptsContacts; + Options_AddPage(wParam, &odp); + + odp.ptszTab = _T(LANG_OPT_FINGER); + odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_FINGER); + odp.pfnDlgProc = DlgProcMirOTROptsFinger; + Options_AddPage(wParam, &odp); + return 0; +} + +void InitOptions() { + LoadOptions(); + hHookOptions = HookEvent(ME_OPT_INITIALISE, OpenOptions); +} + +void DeinitOptions() { + UnhookEvent(hHookOptions); +} + +void SaveOptions() { + db_set_w(0, MODULENAME, "DefaultPolicy", options.default_policy); + db_set_w(0, MODULENAME, "ErrorDisplay", (int)options.err_method); + db_set_b(0, MODULENAME, "PrefixMessages", options.prefix_messages ? 1 : 0); + db_set_b(0, MODULENAME, "MsgInline", options.msg_inline ? 1 : 0); + db_set_b(0, MODULENAME, "MsgPopup", options.msg_popup ? 1 : 0); + + db_set_b(0, MODULENAME, "NoHistory", options.delete_history ? 1 : 0); + db_set_b(0, MODULENAME, "NoSystemHistory", options.delete_systeminfo ? 1 : 0); + db_set_b(0, MODULENAME, "AutoShowVerify", options.autoshow_verify ? 1 : 0); + + db_set_utf(0, MODULENAME, "Prefix", options.prefix); + + db_set_b(0, MODULENAME, "EndOffline", options.end_offline ? 1 : 0); + db_set_b(0, MODULENAME, "EndWindowClose", options.end_window_close ? 1 : 0); +} + +extern "C" void set_context_contact(void *data, ConnContext *context) +{ + MCONTACT hContact = find_contact(context->username, context->protocol); + context->app_data = (void*)hContact; +} + +void ReadPrivkeyFiles() { + DEBUGOUT_T("READ privkey"); + lib_cs_lock(); + otrl_privkey_read(otr_user_state, g_private_key_filename); + otrl_privkey_read_fingerprints(otr_user_state, g_fingerprint_store_filename, set_context_contact, 0); + otrl_instag_read(otr_user_state, g_instag_filename); + lib_cs_unlock(); +} + +static INT_PTR CALLBACK DlgProcMirOTROpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + TCHAR *prefix; char* prefix_utf; + switch ( msg ) { + case WM_INITDIALOG: + TranslateDialogDefault( hwndDlg ); + + // set default policy radio + switch(options.default_policy) { + case OTRL_POLICY_OPPORTUNISTIC: + CheckDlgButton(hwndDlg, IDC_RAD_OPP, BST_CHECKED); + break; + case OTRL_POLICY_MANUAL_MOD: + CheckDlgButton(hwndDlg, IDC_RAD_MANUAL, BST_CHECKED); + break; + case OTRL_POLICY_ALWAYS: + CheckDlgButton(hwndDlg, IDC_RAD_ALWAYS, BST_CHECKED); + break; + case OTRL_POLICY_NEVER: + CheckDlgButton(hwndDlg, IDC_RAD_NEVER, BST_CHECKED); + break; + } + + CheckDlgButton(hwndDlg, IDC_CHK_PREFIX, options.prefix_messages ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_CHK_MSGINLINE, options.msg_inline ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_CHK_MSGPOPUP, options.msg_popup ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_CHK_PREVENTSAVE, options.delete_history ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_CHK_PREVENTSYSSAVE, options.delete_systeminfo ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_CHK_AUTOSHOW_VERIFY, options.autoshow_verify ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_CHK_ENDOFFLINE, options.end_offline ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_CHK_ENDCLOSE, options.end_window_close ? BST_CHECKED : BST_UNCHECKED); + + prefix = mir_utf8decodeT(options.prefix); + SetDlgItemText(hwndDlg, IDC_ED_PREFIX, prefix); + mir_free(prefix); + + return TRUE; + break; + + case WM_COMMAND: + switch ( HIWORD( wParam )) { + case BN_CLICKED: + switch ( LOWORD( wParam )) { + case IDC_RAD_OPP: + case IDC_RAD_MANUAL: + case IDC_RAD_ALWAYS: + case IDC_RAD_NEVER: + case IDC_CHK_PREFIX: + case IDC_CHK_MSGINLINE: + case IDC_CHK_MSGPOPUP: + case IDC_CHK_PREVENTSAVE: + case IDC_CHK_AUTOSHOW_VERIFY: + case IDC_CHK_ENDOFFLINE: + case IDC_CHK_ENDCLOSE: + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + } + break; + case EN_CHANGE: + if (LOWORD( wParam ) == IDC_ED_PREFIX && ( HWND )lParam == GetFocus()) + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + break; + } + break; + + case WM_NOTIFY: + + if (((LPNMHDR)lParam)->code == (UINT) PSN_APPLY ) { + // handle apply + + if (IsDlgButtonChecked(hwndDlg, IDC_RAD_OPP)) + options.default_policy = OTRL_POLICY_OPPORTUNISTIC; + else if (IsDlgButtonChecked(hwndDlg, IDC_RAD_MANUAL)) + options.default_policy = OTRL_POLICY_MANUAL_MOD; + else if (IsDlgButtonChecked(hwndDlg, IDC_RAD_ALWAYS)) + options.default_policy = OTRL_POLICY_ALWAYS; + else + options.default_policy = OTRL_POLICY_NEVER; + + options.prefix_messages = (TRUE==IsDlgButtonChecked(hwndDlg, IDC_CHK_PREFIX)); + options.msg_inline = (TRUE==IsDlgButtonChecked(hwndDlg, IDC_CHK_MSGINLINE)); + options.msg_popup = (TRUE==IsDlgButtonChecked(hwndDlg, IDC_CHK_MSGPOPUP)); + options.delete_history = (TRUE==IsDlgButtonChecked(hwndDlg, IDC_CHK_PREVENTSAVE)); + options.delete_systeminfo = (TRUE==IsDlgButtonChecked(hwndDlg, IDC_CHK_PREVENTSYSSAVE)); + options.autoshow_verify = (TRUE==IsDlgButtonChecked(hwndDlg, IDC_CHK_AUTOSHOW_VERIFY)); + options.end_offline = (TRUE==IsDlgButtonChecked(hwndDlg, IDC_CHK_ENDOFFLINE)); + options.end_window_close = (TRUE==IsDlgButtonChecked(hwndDlg, IDC_CHK_ENDCLOSE)); + + prefix = (TCHAR*)mir_alloc(sizeof(TCHAR)*OPTIONS_PREFIXLEN); + GetDlgItemText(hwndDlg, IDC_ED_PREFIX, prefix, OPTIONS_PREFIXLEN); + prefix_utf = mir_utf8encodeT(prefix); + mir_free(prefix); + strncpy(options.prefix, prefix_utf, OPTIONS_PREFIXLEN-1); + mir_free(prefix_utf); + + SaveOptions(); + + return TRUE; + } + + break; + } + return FALSE; +} + +static unsigned int CALLBACK regen_key_thread(void* param) +{ + Thread_Push(0); + PROTOREGENKEYOPTIONS *opts = (PROTOREGENKEYOPTIONS *)param; + TCHAR buff[512]; + + mir_sntprintf(buff, SIZEOF(buff), TranslateT(LANG_OTR_ASK_NEWKEY), opts->proto); + EnableWindow(opts->refresh, FALSE); + if (IDYES == MessageBox(opts->refresh, buff, TranslateT(LANG_OTR_INFO), MB_ICONQUESTION|MB_YESNO)) + { + char* proto = mir_t2a(opts->proto); + otr_gui_create_privkey(0, proto, proto); + SendMessage(opts->refresh, WMU_REFRESHPROTOLIST, 0, 0); + /* + char *fp = (char*)mir_alloc(20); + otrl_privkey_fingerprint(otr_user_state, fp, proto, proto); + TCHAR *fpt = mir_a2t(fp); + mir_free(fp); + ListView_SetItemText(GetDlgItem(hwndDlg, IDC_LV_PROTO_PROTOS), sel, 2, fpt); + mir_free(fpt); + mir_free(proto); + */ + } + EnableWindow(opts->refresh, TRUE); + delete opts; + Thread_Pop(); + return 0; +} + +static INT_PTR CALLBACK DlgProcMirOTROptsProto(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + HWND lv; + switch ( msg ) { + case WM_INITDIALOG: + TranslateDialogDefault( hwndDlg ); + lv = GetDlgItem(hwndDlg, IDC_LV_PROTO_PROTOS); + + { + HWND cmb = GetDlgItem(hwndDlg, IDC_CMB_PROTO_POLICY); + SendMessage(cmb, CB_ADDSTRING, 0, (WPARAM)TranslateT(LANG_POLICY_DEFAULT)); + SendMessage(cmb, CB_ADDSTRING, 0, (WPARAM)TranslateT(LANG_POLICY_ALWAYS)); + SendMessage(cmb, CB_ADDSTRING, 0, (WPARAM)TranslateT(LANG_POLICY_OPP)); + SendMessage(cmb, CB_ADDSTRING, 0, (WPARAM)TranslateT(LANG_POLICY_MANUAL)); + SendMessage(cmb, CB_ADDSTRING, 0, (WPARAM)TranslateT(LANG_POLICY_NEVER)); + SendDlgItemMessage(hwndDlg, IDC_CMB_PROTO_POLICY, CB_SETCURSEL, (LPARAM)-1, 0); + EnableWindow(GetDlgItem(hwndDlg, IDC_CMB_PROTO_POLICY), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_BTN_PROTO_NEWKEY), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_BTN_PROTO_FORGET), FALSE); + } + + SendMessage(lv,LVM_SETEXTENDEDLISTVIEWSTYLE, 0,LVS_EX_FULLROWSELECT);// | LVS_EX_CHECKBOXES); + { + // add list columns + LVCOLUMN lvc; + // Initialize the LVCOLUMN structure. + // The mask specifies that the format, width, text, and + // subitem members of the structure are valid. + lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM; + lvc.fmt = LVCFMT_LEFT; + + lvc.iSubItem = 0; + lvc.pszText = TranslateT(LANG_PROTO); + lvc.cx = 85; // width of column in pixels + ListView_InsertColumn(lv, 0, &lvc); + + lvc.iSubItem = 1; + lvc.pszText = TranslateT(LANG_POLICY); + lvc.cx = 80; // width of column in pixels + ListView_InsertColumn(lv, 1, &lvc); + + lvc.iSubItem = 2; + lvc.pszText = TranslateT(LANG_FINGERPRINT); + lvc.cx = 275; // width of column in pixels + ListView_InsertColumn(lv, 2, &lvc); + } + PostMessage(hwndDlg, WMU_REFRESHPROTOLIST, 0, 0); + + return TRUE; + case WMU_REFRESHPROTOLIST: + { + lv = GetDlgItem(hwndDlg, IDC_LV_PROTO_PROTOS); + ListView_DeleteAllItems(lv); + int num_protocols; + PROTOACCOUNT **pppDesc; + int ilvItem; + LV_ITEM item = {0}; + char fprint[45]; + TCHAR* temp; + //BOOL unicode = ListView_GetUnicodeFormat(lv); + + ProtoEnumAccounts(&num_protocols, &pppDesc); + for(int i = 0; i < num_protocols; i++) { + if((strcmp(pppDesc[i]->szModuleName, META_PROTO) != 0) + && (CallProtoService(pppDesc[i]->szModuleName, PS_GETCAPS, PFLAGNUM_1, 0) & PF1_IM) == PF1_IM) + { + //if (unicode) { + item.mask = LVIF_TEXT; + temp = mir_a2t(pppDesc[i]->szModuleName); + item.pszText = temp; + ilvItem = ListView_InsertItem(lv, &item); + mir_free(temp); + + + ListView_SetItemText(lv, ilvItem, 1, (TCHAR*)policy_to_string(db_get_dw(0,MODULENAME"_ProtoPol", pppDesc[i]->szModuleName, CONTACT_DEFAULT_POLICY)) ); + if(otrl_privkey_fingerprint(otr_user_state, fprint, pppDesc[i]->szModuleName, pppDesc[i]->szModuleName)) { + temp = mir_a2t(fprint); + ListView_SetItemText(lv, ilvItem, 2, temp); + mir_free(temp); + } + } + } + } + return TRUE; + case WM_COMMAND: + switch ( HIWORD( wParam )) { + case BN_CLICKED: + switch ( LOWORD( wParam )) { + case IDC_BTN_PROTO_NEWKEY: + { + int sel = ListView_GetSelectionMark(GetDlgItem(hwndDlg, IDC_LV_PROTO_PROTOS)); + if (sel != -1) { + PROTOREGENKEYOPTIONS *opts = new PROTOREGENKEYOPTIONS(); + opts->refresh = hwndDlg; + ListView_GetItemText(GetDlgItem(hwndDlg, IDC_LV_PROTO_PROTOS), sel, 0, opts->proto, SIZEOF(opts->proto)); + CloseHandle((HANDLE)_beginthreadex(0, 0, regen_key_thread, opts, 0, 0)); + } + }break; + case IDC_BTN_PROTO_FORGET: + { + int sel = ListView_GetSelectionMark(GetDlgItem(hwndDlg, IDC_LV_PROTO_PROTOS)); + if (sel != -1) { + TCHAR buff_proto[128]; + ListView_GetItemText(GetDlgItem(hwndDlg, IDC_LV_PROTO_PROTOS), sel, 0, buff_proto, SIZEOF(buff_proto)); + TCHAR buff[512]; + mir_sntprintf(buff, SIZEOF(buff), TranslateT(LANG_OTR_ASK_REMOVEKEY), buff_proto); + if (IDYES == MessageBox(hwndDlg, buff, TranslateT(LANG_OTR_INFO), MB_ICONQUESTION|MB_YESNO)) + { + char* proto = mir_t2a(buff_proto); + OtrlPrivKey *key = otrl_privkey_find(otr_user_state, proto, proto); + mir_free(proto); + if (key) { + otrl_privkey_forget(key); + otrl_privkey_write(otr_user_state, g_private_key_filename); + ListView_SetItemText(GetDlgItem(hwndDlg, IDC_LV_PROTO_PROTOS), sel, 2, _T("")); + } + } + } + }break; + } + break; + case CBN_SELCHANGE: + switch ( LOWORD( wParam )) { + case IDC_CMB_PROTO_POLICY: + { + int proto = ListView_GetSelectionMark(GetDlgItem(hwndDlg, IDC_LV_PROTO_PROTOS)); + if (proto == -1) break; + int sel = SendDlgItemMessage(hwndDlg, IDC_CMB_PROTO_POLICY, CB_GETCURSEL, 0, 0); + if (sel==CB_ERR) break; + int len = SendDlgItemMessage(hwndDlg, IDC_CMB_PROTO_POLICY, CB_GETLBTEXTLEN, sel, 0); + if (len < 0) break; + TCHAR *text = new TCHAR[len+1]; + SendDlgItemMessage(hwndDlg, IDC_CMB_PROTO_POLICY, CB_GETLBTEXT, sel, (LPARAM)text); + ListView_SetItemText(GetDlgItem(hwndDlg, IDC_LV_PROTO_PROTOS), proto, 1, text); + delete[] text; + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + }break; + } + break; + } + break; + + case WM_NOTIFY: + if (((LPNMHDR) lParam)->code == (UINT) LVN_ITEMCHANGED && ((LPNMHDR) lParam)->hwndFrom == GetDlgItem(hwndDlg, IDC_LV_PROTO_PROTOS) + && (((LPNMLISTVIEW)lParam)->uNewState & LVIS_SELECTED )) { + int sel = ListView_GetSelectionMark(((LPNMHDR) lParam)->hwndFrom); + if (sel == -1) { + SendDlgItemMessage(hwndDlg, IDC_CMB_PROTO_POLICY, CB_SETCURSEL, (LPARAM)-1, 0); + EnableWindow(GetDlgItem(hwndDlg, IDC_CMB_PROTO_POLICY), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_BTN_PROTO_NEWKEY), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_BTN_PROTO_FORGET), FALSE); + } else { + EnableWindow(GetDlgItem(hwndDlg, IDC_CMB_PROTO_POLICY), TRUE); + EnableWindow(GetDlgItem(hwndDlg, IDC_BTN_PROTO_NEWKEY), TRUE); + EnableWindow(GetDlgItem(hwndDlg, IDC_BTN_PROTO_FORGET), TRUE); + TCHAR buff[50]; + ListView_GetItemText(((LPNMHDR)lParam)->hwndFrom, sel, 1, buff, SIZEOF(buff)); + SendDlgItemMessage(hwndDlg, IDC_CMB_PROTO_POLICY, CB_SELECTSTRING, (LPARAM)-1, (WPARAM)buff); + } + + } else if (((LPNMHDR)lParam)->code == (UINT) PSN_APPLY ) { + lv = GetDlgItem(hwndDlg, IDC_LV_PROTO_PROTOS); + int cnt = ListView_GetItemCount(lv); + TCHAR proto_t[128], policy[64]; + char* proto; + for (int i = 0; i < cnt; ++i) { + ListView_GetItemText(lv, i, 0, proto_t, SIZEOF(proto_t)); + ListView_GetItemText(lv, i, 1, policy, SIZEOF(policy)); + proto = mir_t2a(proto_t); + db_set_dw(0, MODULENAME"_ProtoPol", proto, policy_from_string(policy)); + mir_free(proto); + } + // handle apply + return TRUE; + } + break; + } + return FALSE; +} + +static INT_PTR CALLBACK DlgProcMirOTROptsContacts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch ( msg ) { + case WM_INITDIALOG: + { + TranslateDialogDefault( hwndDlg ); + + SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR) new ContactPolicyMap()); + + HWND cmb = GetDlgItem(hwndDlg, IDC_CMB_CONT_POLICY); + SendMessage(cmb, CB_ADDSTRING, 0, (WPARAM)TranslateT(LANG_POLICY_DEFAULT)); + SendMessage(cmb, CB_ADDSTRING, 0, (WPARAM)TranslateT(LANG_POLICY_ALWAYS)); + SendMessage(cmb, CB_ADDSTRING, 0, (WPARAM)TranslateT(LANG_POLICY_OPP)); + SendMessage(cmb, CB_ADDSTRING, 0, (WPARAM)TranslateT(LANG_POLICY_MANUAL)); + SendMessage(cmb, CB_ADDSTRING, 0, (WPARAM)TranslateT(LANG_POLICY_NEVER)); + EnableWindow(GetDlgItem(hwndDlg, IDC_CMB_CONT_POLICY), FALSE); + + SendDlgItemMessage(hwndDlg, IDC_LV_CONT_CONTACTS ,LVM_SETEXTENDEDLISTVIEWSTYLE, 0,LVS_EX_FULLROWSELECT);// | LVS_EX_CHECKBOXES); + + + HWND lv = GetDlgItem(hwndDlg, IDC_LV_CONT_CONTACTS); + + + // add list columns + LVCOLUMN lvc; + // Initialize the LVCOLUMN structure. + // The mask specifies that the format, width, text, and + // subitem members of the structure are valid. + lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM; + lvc.fmt = LVCFMT_LEFT; + + lvc.iSubItem = 0; + lvc.pszText = TranslateT(LANG_CONTACT); + lvc.cx = 150; // width of column in pixels + ListView_InsertColumn(lv, 0, &lvc); + + lvc.iSubItem = 1; + lvc.pszText = TranslateT(LANG_PROTO); + lvc.cx = 100; // width of column in pixels + ListView_InsertColumn(lv, 1, &lvc); + + lvc.iSubItem = 2; + lvc.pszText = TranslateT(LANG_POLICY); + lvc.cx = 90; // width of column in pixels + ListView_InsertColumn(lv, 2, &lvc); + + lvc.iSubItem = 3; + lvc.pszText = TranslateT(LANG_HTMLCONV); + lvc.cx = 80; // width of column in pixels + ListView_InsertColumn(lv, 3, &lvc); + } + SendMessage(hwndDlg, WMU_REFRESHLIST, 0, 0); + + return TRUE; + case WMU_REFRESHLIST: + { + HWND lv = GetDlgItem(hwndDlg, IDC_LV_CONT_CONTACTS); + + ListView_DeleteAllItems(lv); + + LVITEM lvI = {0}; + + // Some code to create the list-view control. + // Initialize LVITEM members that are common to all + // items. + lvI.mask = LVIF_TEXT | LVIF_PARAM;// | LVIF_NORECOMPUTE;// | LVIF_IMAGE; + + const char *proto; + TCHAR *proto_t; + for (MCONTACT hContact = db_find_first(); hContact; hContact = db_find_next(hContact)) { + proto = GetContactProto(hContact); + if(proto && db_get_b(hContact, proto, "ChatRoom", 0) == 0 && CallService(MS_PROTO_ISPROTOONCONTACT, hContact, (LPARAM)MODULENAME) // ignore chatrooms + && strcmp(proto, META_PROTO) != 0) // and MetaContacts + { + lvI.iItem = 0; + lvI.iSubItem = 0; + lvI.lParam = hContact; + lvI.pszText = (TCHAR*)contact_get_nameT(hContact); + lvI.iItem = ListView_InsertItem(lv , &lvI); + + proto_t = mir_a2t(proto); + ListView_SetItemText(lv, lvI.iItem, 1, proto_t); + mir_free(proto_t); + + ListView_SetItemText(lv, lvI.iItem, 2, (TCHAR*)policy_to_string((OtrlPolicy)db_get_dw(hContact, MODULENAME, "Policy", CONTACT_DEFAULT_POLICY)) ); + ListView_SetItemText(lv, lvI.iItem, 3, (db_get_b(hContact, MODULENAME, "HTMLConv", 0))?TranslateT(LANG_YES):TranslateT(LANG_NO) ); + } + } + } + return TRUE; + break; + + case WM_COMMAND: + switch ( HIWORD( wParam )) { + case CBN_SELCHANGE: + switch ( LOWORD( wParam )) { + case IDC_CMB_CONT_POLICY: + { + MCONTACT hContact = 0; + int iUser = ListView_GetSelectionMark(GetDlgItem(hwndDlg, IDC_LV_CONT_CONTACTS)); + if (iUser == -1) break; + int sel = SendDlgItemMessage(hwndDlg, IDC_CMB_CONT_POLICY, CB_GETCURSEL, 0, 0); + if (sel==CB_ERR) break; + int len = SendDlgItemMessage(hwndDlg, IDC_CMB_CONT_POLICY, CB_GETLBTEXTLEN, sel, 0); + if (len < 0) break; + TCHAR *text = new TCHAR[len+1]; + SendDlgItemMessage(hwndDlg, IDC_CMB_CONT_POLICY, CB_GETLBTEXT, sel, (LPARAM)text); + ListView_SetItemText(GetDlgItem(hwndDlg, IDC_LV_CONT_CONTACTS), iUser, 2, text); + OtrlPolicy policy = policy_from_string(text); + delete[] text; + LVITEM lvi = {0}; + lvi.mask = LVIF_PARAM; + lvi.iItem = iUser; + lvi.iSubItem = 0; + ListView_GetItem(GetDlgItem(hwndDlg, IDC_LV_CONT_CONTACTS), &lvi); + ContactPolicyMap* cpm = (ContactPolicyMap*) GetWindowLongPtr(hwndDlg, GWLP_USERDATA); + hContact = (MCONTACT)lvi.lParam; + (*cpm)[hContact].policy = policy; + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + }break; + } + break; + } + break; + + case WM_NOTIFY: + { + UINT code = ((LPNMHDR) lParam)->code; + if (code == (UINT) PSN_APPLY ) { + // handle apply + + ContactPolicyMap *cpm = (ContactPolicyMap*) GetWindowLongPtr(hwndDlg, GWLP_USERDATA); + // Iterate over the map and print out all key/value pairs. + // Using a const_iterator since we are not going to change the values. + for(ContactPolicyMap::const_iterator it = cpm->begin(); it != cpm->end(); ++it) + { + if (!it->first) continue; + if (it->second.policy) db_set_dw(it->first, MODULENAME, "Policy", (DWORD)it->second.policy); + if (it->second.htmlconv) db_set_b(it->first, MODULENAME, "HTMLConv", it->second.htmlconv-1); + } + return TRUE; + } else if (((LPNMHDR) lParam)->hwndFrom == GetDlgItem(hwndDlg, IDC_LV_CONT_CONTACTS)) { + if (code == (UINT) LVN_ITEMCHANGED && (((LPNMLISTVIEW)lParam)->uNewState & LVIS_SELECTED )) { + int sel = ListView_GetSelectionMark(((LPNMHDR) lParam)->hwndFrom); + if (sel == -1) { + SendDlgItemMessage(hwndDlg, IDC_CMB_CONT_POLICY, CB_SETCURSEL, (LPARAM)-1, 0); + EnableWindow(GetDlgItem(hwndDlg, IDC_CMB_CONT_POLICY), FALSE); + } else { + EnableWindow(GetDlgItem(hwndDlg, IDC_CMB_CONT_POLICY), TRUE); + TCHAR buff[50]; + ListView_GetItemText(((LPNMHDR)lParam)->hwndFrom, sel, 2, buff, SIZEOF(buff)); + SendDlgItemMessage(hwndDlg, IDC_CMB_CONT_POLICY, CB_SELECTSTRING, (LPARAM)-1, (WPARAM)buff); + } + } else if (code == (UINT) NM_CLICK) { + if (((LPNMLISTVIEW)lParam)->iSubItem == 3) { + LVITEM lvi; + lvi.mask = LVIF_PARAM; + lvi.iItem = ((LPNMLISTVIEW)lParam)->iItem; + if (lvi.iItem < 0) return FALSE; + lvi.iSubItem = 0; + SendDlgItemMessage(hwndDlg, IDC_LV_CONT_CONTACTS, LVM_GETITEM, 0, (LPARAM)&lvi); + + MCONTACT hContact = (MCONTACT)lvi.lParam; + ContactPolicyMap *cp = (ContactPolicyMap *)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); + TCHAR buff[50]; + ListView_GetItemText(((LPNMHDR)lParam)->hwndFrom, lvi.iItem, 3, buff, SIZEOF(buff)); + if (_tcsncmp(buff, TranslateT(LANG_YES), 50)==0){ + (*cp)[hContact].htmlconv = HTMLCONV_DISABLE; + ListView_SetItemText(((LPNMHDR)lParam)->hwndFrom, lvi.iItem, 3, TranslateT(LANG_NO)); + }else { + (*cp)[hContact].htmlconv = HTMLCONV_ENABLE; + ListView_SetItemText(((LPNMHDR)lParam)->hwndFrom, lvi.iItem, 3, TranslateT(LANG_YES)); + } + (*cp)[hContact].htmlconv += 1; + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + } + + + } + } + }break; + case WM_DESTROY: + ContactPolicyMap *cpm = (ContactPolicyMap*) GetWindowLongPtr(hwndDlg, GWLP_USERDATA); + cpm->clear(); + delete cpm; + break; + } + return FALSE; +} + +static INT_PTR CALLBACK DlgProcMirOTROptsFinger(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch ( msg ) { + case WM_INITDIALOG: + TranslateDialogDefault( hwndDlg ); + SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR) new FPModifyMap()); + + SendDlgItemMessage(hwndDlg, IDC_LV_FINGER_LIST ,LVM_SETEXTENDEDLISTVIEWSTYLE, 0,LVS_EX_FULLROWSELECT);// | LVS_EX_CHECKBOXES); + + { + HWND lv = GetDlgItem(hwndDlg, IDC_LV_FINGER_LIST); + // add list columns + LVCOLUMN lvc; + // Initialize the LVCOLUMN structure. + // The mask specifies that the format, width, text, and + // subitem members of the structure are valid. + lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM; + lvc.fmt = LVCFMT_LEFT; + + lvc.iSubItem = 0; + lvc.pszText = TranslateT(LANG_CONTACT); + lvc.cx = 100; // width of column in pixels + ListView_InsertColumn(lv, 0, &lvc); + + lvc.iSubItem = 1; + lvc.pszText = TranslateT(LANG_PROTO); + lvc.cx = 90; // width of column in pixels + ListView_InsertColumn(lv, 1, &lvc); + + lvc.iSubItem = 2; + lvc.pszText = TranslateT(LANG_ACTIVE); + lvc.cx = 50; // width of column in pixels + ListView_InsertColumn(lv, 2, &lvc); + + lvc.iSubItem = 3; + lvc.pszText = TranslateT(LANG_VERIFIED); + lvc.cx = 50; // width of column in pixels + ListView_InsertColumn(lv, 3, &lvc); + + lvc.iSubItem = 4; + lvc.pszText = TranslateT(LANG_FINGERPRINT); + lvc.cx = 300; // width of column in pixels + ListView_InsertColumn(lv, 4, &lvc); + } + SendMessage(hwndDlg, WMU_REFRESHLIST, 0, 0); + + return TRUE; + + case WMU_REFRESHLIST: + //enumerate contacts, fill in list + { + HWND lv = GetDlgItem(hwndDlg, IDC_LV_FINGER_LIST); + ListView_DeleteAllItems(lv); + + LVITEM lvI = {0}; + + // Some code to create the list-view control. + // Initialize LVITEM members that are common to all + // items. + lvI.mask = LVIF_TEXT | LVIF_PARAM;// | LVIF_NORECOMPUTE;// | LVIF_IMAGE; + + TCHAR *proto, *user, hash[45] = {0}; + for (ConnContext *context = otr_user_state->context_root;context;context = context->next) { + if (context->app_data) { + user = (TCHAR*)contact_get_nameT((MCONTACT)context->app_data); + if (user) { + proto = mir_a2t(context->protocol); + + for(Fingerprint *fp = context->fingerprint_root.next;fp;fp = fp->next) { + otrl_privkey_hash_to_humanT(hash, fp->fingerprint); + lvI.iSubItem = 0; + lvI.lParam = (LPARAM)fp; + lvI.pszText = user; + int d = ListView_InsertItem(lv, &lvI); + + ListView_SetItemText(lv,d, 1, proto); + ListView_SetItemText(lv,d, 2, (context->active_fingerprint == fp)? TranslateT(LANG_YES) : TranslateT(LANG_NO)); + ListView_SetItemText(lv,d, 3, (fp->trust && fp->trust[0] != '\0')? TranslateT(LANG_YES) : TranslateT(LANG_NO)); + ListView_SetItemText(lv,d, 4, hash ); + } + mir_free(proto); + } + } + } + } + + return TRUE; + case WM_COMMAND: + switch ( HIWORD( wParam )) { + case BN_CLICKED: + switch ( LOWORD( wParam )) { + case IDC_BTN_FINGER_DONTTRUST: + { + int sel = ListView_GetSelectionMark(GetDlgItem(hwndDlg, IDC_LV_FINGER_LIST)); + if (sel != -1) { + LVITEM lvi = {0}; + lvi.mask = LVIF_PARAM; + lvi.iItem = sel; + ListView_GetItem(GetDlgItem(hwndDlg, IDC_LV_FINGER_LIST), &lvi); + Fingerprint *fp = (Fingerprint*) lvi.lParam; + FPModifyMap* fpm = (FPModifyMap*) GetWindowLongPtr(hwndDlg, GWLP_USERDATA); + (*fpm)[fp] = FPM_NOTRUST; + ListView_SetItemText(GetDlgItem(hwndDlg, IDC_LV_FINGER_LIST), sel, 3, TranslateT(LANG_NO)); + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + } + }break; + case IDC_BTN_FINGER_TRUST: + { + int sel = ListView_GetSelectionMark(GetDlgItem(hwndDlg, IDC_LV_FINGER_LIST)); + if (sel != -1) { + LVITEM lvi = {0}; + lvi.mask = LVIF_PARAM; + lvi.iItem = sel; + ListView_GetItem(GetDlgItem(hwndDlg, IDC_LV_FINGER_LIST), &lvi); + Fingerprint *fp = (Fingerprint*) lvi.lParam; + FPModifyMap* fpm = (FPModifyMap*) GetWindowLongPtr(hwndDlg, GWLP_USERDATA); + (*fpm)[fp] = FPM_VERIFY; + ListView_SetItemText(GetDlgItem(hwndDlg, IDC_LV_FINGER_LIST), sel, 3, TranslateT(LANG_YES)); + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + } + }break; + case IDC_BTN_FINGER_FORGET: + { + int sel = ListView_GetSelectionMark(GetDlgItem(hwndDlg, IDC_LV_FINGER_LIST)); + if (sel != -1) { + LVITEM lvi = {0}; + lvi.mask = LVIF_PARAM; + lvi.iItem = sel; + ListView_GetItem(GetDlgItem(hwndDlg, IDC_LV_FINGER_LIST), &lvi); + Fingerprint *fp = (Fingerprint*) lvi.lParam; + if (fp->context->active_fingerprint == fp) { + TCHAR buff[1024], hash[45]; + otrl_privkey_hash_to_humanT(hash, fp->fingerprint); + mir_sntprintf(buff, SIZEOF(buff), TranslateT(LANG_FINGERPRINT_STILL_IN_USE), hash, contact_get_nameT((MCONTACT)fp->context->app_data)); + ShowError(buff); + } else { + FPModifyMap* fpm = (FPModifyMap*) GetWindowLongPtr(hwndDlg, GWLP_USERDATA); + (*fpm)[fp] = FPM_DELETE; + ListView_DeleteItem(GetDlgItem(hwndDlg, IDC_LV_FINGER_LIST), sel); + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + } + } + }break; + } + } + break; + + case WM_NOTIFY: + if (((LPNMHDR)lParam)->code == (UINT) PSN_APPLY ) { + // handle apply + + FPModifyMap *fpm = (FPModifyMap*) GetWindowLongPtr(hwndDlg, GWLP_USERDATA); + // Iterate over the map and print out all key/value pairs. + // Using a const_iterator since we are not going to change the values. + for(FPModifyMap::const_iterator it = fpm->begin(); it != fpm->end(); ++it) + { + if (!it->first) continue; + switch (it->second) { + case FPM_DELETE: + if (it->first->context->active_fingerprint == it->first) { + TCHAR buff[1024], hash[45]; + otrl_privkey_hash_to_humanT(hash, it->first->fingerprint); + mir_sntprintf(buff, SIZEOF(buff), TranslateT(LANG_FINGERPRINT_NOT_DELETED), hash, contact_get_nameT((MCONTACT)it->first->context->app_data)); + ShowError(buff); + } else { + otrl_context_forget_fingerprint(it->first, 1); + } + break; + case FPM_VERIFY: + otrl_context_set_trust(it->first, "verified"); + if (it->first == it->first->context->active_fingerprint) + 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) + VerifyFingerprint(it->first->context, false); + //SetEncryptionStatus((HANDLE)it->first->context->app_data, otr_context_get_trust(it->first->context)); + break; + } + } + if (!fpm->empty()) otr_gui_write_fingerprints(0); + fpm->clear(); + SendMessage(hwndDlg, WMU_REFRESHLIST, 0, 0); + + return TRUE; + } + break; + case WM_DESTROY: + FPModifyMap *fpm = (FPModifyMap*) GetWindowLongPtr(hwndDlg, GWLP_USERDATA); + fpm->clear(); + delete fpm; + break; + } + + return FALSE; +} diff --git a/plugins/MirOTR/src/options.h b/plugins/MirOTR/src/options.h index 772d0c5d45..da2e59ba3c 100644 --- a/plugins/MirOTR/src/options.h +++ b/plugins/MirOTR/src/options.h @@ -1,69 +1,71 @@ -#ifndef _OPTIONS_INC -#define _OPTIONS_INC - -#define PRIVATE_KEY_FILENAME "otr.private_key" -#define FINGERPRINT_STORE_FILENAME "otr.fingerprints" - -extern char g_fingerprint_store_filename[MAX_PATH]; -extern char g_private_key_filename[MAX_PATH]; - -#define CONTACT_DEFAULT_POLICY 0xFFFF - -typedef enum {ED_POP, ED_BAL, ED_MB} ErrorDisplay; - -#define OPTIONS_PREFIXLEN 64 - -typedef struct { - OtrlPolicy default_policy; - ErrorDisplay err_method; - bool prefix_messages; - bool msg_inline; - bool msg_popup; - char prefix[OPTIONS_PREFIXLEN]; - - bool delete_history; - bool delete_systeminfo; - bool autoshow_verify; - - bool end_offline, end_window_close; - - // temporary options - bool bHavePopups, bHaveSecureIM, bHaveButtonsBar; - -} Options; - -extern Options options; - -#define WMU_REFRESHLIST (WM_USER + 241) -#define WMU_REFRESHPROTOLIST (WM_USER + 242) -#define CONTACT_DEFAULT_POLICY 0xFFFF - -#include -enum HTMLConvSetting { - HTMLCONV_DISABLE, - HTMLCONV_ENABLE -}; -struct CONTACT_DATA { - OtrlPolicy policy; - int htmlconv; -}; -typedef std::map ContactPolicyMap; -typedef enum {FPM_VERIFY, FPM_NOTRUST, FPM_DELETE } FPModify; -typedef std::map FPModifyMap; - -int OptInit(WPARAM wParam, LPARAM lParam); - -void LoadOptions(); -void SaveOptions(); -extern "C" int OpenOptions(WPARAM wParam, LPARAM lParam); -void InitOptions(); -void DeinitOptions(); - -void ReadPrivkeyFiles(); - -static INT_PTR CALLBACK DlgProcMirOTROpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam); -static INT_PTR CALLBACK DlgProcMirOTROptsProto(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam); -static INT_PTR CALLBACK DlgProcMirOTROptsContacts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam); -static INT_PTR CALLBACK DlgProcMirOTROptsFinger(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam); - -#endif +#ifndef _OPTIONS_INC +#define _OPTIONS_INC + +#define PRIVATE_KEY_FILENAME "otr.private_key" +#define FINGERPRINT_STORE_FILENAME "otr.fingerprints" +#define INSTAG_FILENAME "otr.instag" + +extern char g_fingerprint_store_filename[MAX_PATH]; +extern char g_private_key_filename[MAX_PATH]; +extern char g_instag_filename[MAX_PATH]; + +#define CONTACT_DEFAULT_POLICY 0xFFFF + +typedef enum {ED_POP, ED_BAL, ED_MB} ErrorDisplay; + +#define OPTIONS_PREFIXLEN 64 + +typedef struct { + OtrlPolicy default_policy; + ErrorDisplay err_method; + bool prefix_messages; + bool msg_inline; + bool msg_popup; + char prefix[OPTIONS_PREFIXLEN]; + + bool delete_history; + bool delete_systeminfo; + bool autoshow_verify; + + bool end_offline, end_window_close; + + // temporary options + bool bHavePopups, bHaveSecureIM, bHaveButtonsBar; + +} Options; + +extern Options options; + +#define WMU_REFRESHLIST (WM_USER + 241) +#define WMU_REFRESHPROTOLIST (WM_USER + 242) +#define CONTACT_DEFAULT_POLICY 0xFFFF + +#include +enum HTMLConvSetting { + HTMLCONV_DISABLE, + HTMLCONV_ENABLE +}; +struct CONTACT_DATA { + OtrlPolicy policy; + int htmlconv; +}; +typedef std::map ContactPolicyMap; +typedef enum {FPM_VERIFY, FPM_NOTRUST, FPM_DELETE } FPModify; +typedef std::map FPModifyMap; + +int OptInit(WPARAM wParam, LPARAM lParam); + +void LoadOptions(); +void SaveOptions(); +extern "C" int OpenOptions(WPARAM wParam, LPARAM lParam); +void InitOptions(); +void DeinitOptions(); + +void ReadPrivkeyFiles(); + +static INT_PTR CALLBACK DlgProcMirOTROpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam); +static INT_PTR CALLBACK DlgProcMirOTROptsProto(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam); +static INT_PTR CALLBACK DlgProcMirOTROptsContacts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam); +static INT_PTR CALLBACK DlgProcMirOTROptsFinger(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam); + +#endif 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); + } +} diff --git a/plugins/MirOTR/src/otr.h b/plugins/MirOTR/src/otr.h index 795991ffdb..9691cbbfc7 100644 --- a/plugins/MirOTR/src/otr.h +++ b/plugins/MirOTR/src/otr.h @@ -1,51 +1,50 @@ -#pragma once - -extern OtrlUserState otr_user_state; -extern OtrlMessageAppOps ops; - -extern "C" { - - /* Return the OTR policy for the given context. */ - OtrlPolicy otr_gui_policy(void *opdata, ConnContext *context); - - /* 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); - - int otr_gui_is_logged_in(void *opdata, const char *accountname, const char *protocol, const char *recipient); - - void otr_gui_inject_message(void *opdata, const char *accountname, const char *protocol, const char *recipient, const char *message); - - 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); - - int otr_gui_display_otr_message(void *opdata, const char *accountname, const char *protocol, const char *username, const char *msg); - - void otr_gui_update_context_list(void *opdata); - - const char *otr_gui_protocol_name(void *opdata, const char *protocol); - - void otr_gui_protocol_name_free(void *opdata, const char *protocol_name); - - void otr_gui_new_fingerprint(void *opdata, OtrlUserState us, const char *accountname, const char *protocol, const char *username, unsigned char fingerprint[20]); - - void otr_gui_write_fingerprints(void *opdata); - - void otr_gui_gone_secure(void *opdata, ConnContext *context); - - void otr_gui_gone_insecure(void *opdata, ConnContext *context); - - void otr_gui_still_secure(void *opdata, ConnContext *context, int is_reply); - - void otr_gui_log_message(void *opdata, const char *message); - - int max_message_size(void *opdata, ConnContext *context); - - const char *account_name(void *opdata, const char *account, const char *protocol); - - void account_name_free(void *opdata, const char *account_name); - - void add_appdata(void *data, ConnContext *context); - -} - -gcry_error_t otrl_privkey_write(OtrlUserState us, const char *filename); \ No newline at end of file +#pragma once + +extern OtrlUserState otr_user_state; +extern OtrlMessageAppOps ops; + +/// @todo : add OTR version 3 instance tag choice (currently we use the most secure/active one) +#define MIROTR_PROTO_HELLO "?OTRv23?" + +extern "C" { + + /* Return the OTR policy for the given context. */ + OtrlPolicy otr_gui_policy(void *opdata, ConnContext *context); + + /* 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); + + int otr_gui_is_logged_in(void *opdata, const char *accountname, const char *protocol, const char *recipient); + + void otr_gui_inject_message(void *opdata, const char *accountname, const char *protocol, const char *recipient, const char *message); + + void otr_gui_update_context_list(void *opdata); + + void otr_gui_new_fingerprint(void *opdata, OtrlUserState us, const char *accountname, const char *protocol, const char *username, unsigned char fingerprint[20]); + + void otr_gui_write_fingerprints(void *opdata); + + void otr_gui_gone_secure(void *opdata, ConnContext *context); + + void otr_gui_gone_insecure(void *opdata, ConnContext *context); + + void otr_gui_still_secure(void *opdata, ConnContext *context, int is_reply); + + int max_message_size(void *opdata, ConnContext *context); + + const char *account_name(void *opdata, const char *account, const char *protocol); + + void account_name_free(void *opdata, const char *account_name); + + void add_appdata(void *data, ConnContext *context); + + const char* resent_msg_prefix(void *opdata, ConnContext *context); + void resent_msg_prefix_free(void *opdata, const char *prefix); + + void handle_smp_event(void *opdata, OtrlSMPEvent smp_event, ConnContext *context, unsigned short progress_percent, char *question); + + void handle_msg_event(void *opdata, OtrlMessageEvent msg_event, ConnContext *context, const char *message, gcry_error_t err); + + void otr_create_instag(void *opdata, const char *accountname, const char *protocol); +} diff --git a/plugins/MirOTR/src/otrlextensions.c b/plugins/MirOTR/src/otrlextensions.c new file mode 100644 index 0000000000..da68e73354 --- /dev/null +++ b/plugins/MirOTR/src/otrlextensions.c @@ -0,0 +1,127 @@ +/* + * otrlextensions.c - Off-the-Record Messaging library extensions + * + * Strongly based on parts of the Off-the-Record Messaging library, + * Copyright (C) 2004-2008 Ian Goldberg, Chris Alexander, Nikita Borisov + * + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of version 2.1 of the GNU Lesser General + * Public License as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this library. If not, see . + * + */ + +/* system headers */ +#include +#include +#include +#include + +/* libgcrypt headers */ +#include + +/* libotr headers */ +#include + +#include "otrlextensions.h" + +static gcry_error_t sexp_write(FILE* privf, gcry_sexp_t sexp) +{ + size_t buflen; + char* buf; + + buflen = gcry_sexp_sprint(sexp, GCRYSEXP_FMT_ADVANCED, NULL, 0); + buf = malloc(buflen); + if (buf == NULL && buflen > 0) { + return gcry_error(GPG_ERR_ENOMEM); + } + gcry_sexp_sprint(sexp, GCRYSEXP_FMT_ADVANCED, buf, buflen); + + fprintf(privf, "%s", buf); + free(buf); + + return gcry_error(GPG_ERR_NO_ERROR); +} + +static gcry_error_t account_write(FILE* privf, const char* accountname, + const char* protocol, gcry_sexp_t privkey) +{ + gcry_error_t err; + gcry_sexp_t names, protos; + + fprintf(privf, " (account\n"); + + err = gcry_sexp_build(&names, NULL, "(name %s)", accountname); + if (!err) { + err = sexp_write(privf, names); + gcry_sexp_release(names); + } + if (!err) err = gcry_sexp_build(&protos, NULL, "(protocol %s)", protocol); + if (!err) { + err = sexp_write(privf, protos); + gcry_sexp_release(protos); + } + if (!err) err = sexp_write(privf, privkey); + + fprintf(privf, " )\n"); + + return err; +} + +/* Store all 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; + + /* Output the other keys we know */ + fprintf(privf, "(privkeys\n"); + + for (p=us->privkey_root; p; p=p->next) { + account_write(privf, p->accountname, p->protocol, p->privkey); + } + + fprintf(privf, ")\n"); + + fseek(privf, 0, SEEK_SET); + + return otrl_privkey_read_FILEp(us, privf); +} + +/* Store all keys of an OtrlUserState. */ +gcry_error_t otrl_privkey_write(OtrlUserState us, const char* filename) +{ + gcry_error_t err; + FILE* privf; +#ifndef WIN32 + mode_t oldmask; +#endif + +#ifndef WIN32 + 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; +} diff --git a/plugins/MirOTR/src/otrlextensions.h b/plugins/MirOTR/src/otrlextensions.h new file mode 100644 index 0000000000..c0fa75c673 --- /dev/null +++ b/plugins/MirOTR/src/otrlextensions.h @@ -0,0 +1,35 @@ +/* + * otrlextensions.h - Off-the-Record Messaging library extensions + * + * Strongly based on parts of the Off-the-Record Messaging library, + * Copyright (C) 2004-2008 Ian Goldberg, Chris Alexander, Nikita Borisov + * + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of version 2.1 of the GNU Lesser General + * Public License as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this library. If not, see . + * + */ + +#ifndef __OTRLEXT_H__ +#define __OTRLEXT_H__ + +#include +#include + +/* Store all keys of an OtrlUserState. */ +gcry_error_t otrl_privkey_write(OtrlUserState us, const char* filename); + +/* Store all keys of an OtrlUserState. + * The FILE* must be open for reading and writing. */ +gcry_error_t otrl_privkey_write_FILEp(OtrlUserState us, FILE* privf); + +#endif diff --git a/plugins/MirOTR/src/stdafx.cpp b/plugins/MirOTR/src/stdafx.cpp index 98540cbccf..ade275910d 100644 --- a/plugins/MirOTR/src/stdafx.cpp +++ b/plugins/MirOTR/src/stdafx.cpp @@ -1,8 +1,5 @@ -// stdafx.cpp : Quelldatei, die nur die Standard-Includes einbindet. -// MirOTR.pch ist der vorkompilierte Header. -// stdafx.obj enthält die vorkompilierten Typinformationen. - -#include "stdafx.h" - -// TODO: Auf zusätzliche Header verweisen, die in STDAFX.H -// und nicht in dieser Datei erforderlich sind. +// stdafx.cpp : Quelldatei, die nur die Standard-Includes einbindet. +// MirOTR.pch ist der vorkompilierte Header. +// stdafx.obj enthält die vorkompilierten Typinformationen. + +#include "stdafx.h" diff --git a/plugins/MirOTR/src/stdafx.h b/plugins/MirOTR/src/stdafx.h index 29c63f73e4..a67c5a40f4 100644 --- a/plugins/MirOTR/src/stdafx.h +++ b/plugins/MirOTR/src/stdafx.h @@ -74,9 +74,9 @@ using namespace std; #include "svcs_proto.h" #ifdef _DEBUG - #define DEBUGOUTA(x) OutputDebugStringA(x); - #define DEBUGOUT(x) OutputDebugString(x); - #define DEBUGOUT_T(x) OutputDebugString(__T(x)); + #define DEBUGOUTA(x) OutputDebugStringA(x) + #define DEBUGOUT(x) OutputDebugString(x) + #define DEBUGOUT_T(x) OutputDebugString(__T(x)) #else #define DEBUGOUTA(x); #define DEBUGOUT(x) @@ -92,5 +92,3 @@ using namespace std; #define PREF_NO_HISTORY 0x10000 extern HINSTANCE hInst; - -// TODO: Hier auf zusätzliche Header, die das Programm erfordert, verweisen. diff --git a/plugins/MirOTR/src/svcs_menu.cpp b/plugins/MirOTR/src/svcs_menu.cpp index 6699c00adc..4ed3f7a0d9 100644 --- a/plugins/MirOTR/src/svcs_menu.cpp +++ b/plugins/MirOTR/src/svcs_menu.cpp @@ -1,189 +1,189 @@ -#include "stdafx.h" - -static HGENMENU hStopItem, hStartItem; - -//////////////////////////////// -///////// Menu Services //////// -/////////////////////////////// -int StartOTR(MCONTACT hContact) { - const char *proto = GetContactProto(hContact); - if (!proto) return 1; // error - char *uname = contact_get_id(hContact); - if (!uname) return 1; // error - DWORD pol = db_get_dw(hContact, MODULENAME, "Policy", CONTACT_DEFAULT_POLICY); - if(pol == CONTACT_DEFAULT_POLICY) pol = options.default_policy; - - lib_cs_lock(); - char *msg = otrl_proto_default_query_msg(MODULENAME, pol); - otr_gui_inject_message((void*)hContact, proto, proto, uname, msg ? msg : "?OTRv2?"); - lib_cs_unlock(); - otrl_message_free(msg); - mir_free(uname); - return 0; -} - -INT_PTR SVC_StartOTR(WPARAM hContact, LPARAM lParam) -{ - TCHAR buff[512]; - - MCONTACT hSub = db_mc_getMostOnline(hContact); - if(hSub != 0) - hContact = hSub; - - if ( options.bHaveSecureIM && CallService("SecureIM/IsContactSecured", hContact, 0) != 0 ) { - mir_sntprintf(buff, SIZEOF(buff), TranslateT(LANG_OTR_SECUREIM_STARTED), contact_get_nameT(hContact)); - ShowError(buff); - return 0; - } - - mir_sntprintf(buff, SIZEOF(buff), TranslateT(LANG_SESSION_REQUEST_OTR), contact_get_nameT(hContact)); - ShowMessage(hContact, buff); - - return StartOTR(hContact); -} - -INT_PTR SVC_RefreshOTR(WPARAM hContact, LPARAM lParam) -{ - TCHAR buff[512]; - - MCONTACT hSub = db_mc_getMostOnline(hContact); - if(hSub != 0) - hContact = hSub; - - if ( options.bHaveSecureIM && CallService("SecureIM/IsContactSecured", hContact, 0) != 0 ) { - mir_sntprintf(buff, 512, TranslateT(LANG_OTR_SECUREIM_STARTED), contact_get_nameT(hContact)); - ShowError(buff); - return 0; - } - - mir_sntprintf(buff, SIZEOF(buff), TranslateT(LANG_SESSION_TRY_CONTINUE_OTR), contact_get_nameT(hContact)); - ShowMessage(hContact, buff); - - int res = StartOTR(hContact); - if (res) return res; - - return 0; -} - -int otr_disconnect_contact(MCONTACT hContact) -{ - MCONTACT hSub = db_mc_getMostOnline(hContact); - if (hSub != 0) - hContact = hSub; - - const char *proto = GetContactProto(hContact); - if (!proto) return 1; // error - char *uname = contact_get_id(hContact); - if (!uname) return 1; // error - - lib_cs_lock(); - otrl_message_disconnect(otr_user_state, &ops, (void*)hContact, proto, proto, uname); - lib_cs_unlock(); - mir_free(uname); - return 0; -} - -INT_PTR SVC_StopOTR(WPARAM hContact, LPARAM lParam) -{ - // prevent this filter from acting on injeceted messages for metas, when they are passed though the subcontact's proto send chain - if (otr_disconnect_contact(hContact)) return 0; - - SetEncryptionStatus(hContact, TRUST_NOT_PRIVATE); - - TCHAR buff[512]; - mir_sntprintf(buff, SIZEOF(buff), TranslateT(LANG_SESSION_TERMINATED_OTR), contact_get_nameT(hContact)); - ShowMessage(hContact, buff); - return 0; -} - -INT_PTR SVC_VerifyOTR(WPARAM hContact, LPARAM lParam) -{ - MCONTACT hSub = db_mc_getMostOnline(hContact); - if(hSub != 0) - hContact = hSub; - - ConnContext *context = otrl_context_find_miranda(otr_user_state, hContact); - if (!context) - return 1; - - //VerifyContextDialog(context); - SMPInitDialog(context); - return 0; -} - -INT_PTR SVC_ToggleHTMLOTR(WPARAM hContact, LPARAM lParam) -{ - MCONTACT hSub = db_mc_getMostOnline(hContact); - if (hSub != 0) - hContact = hSub; - - if (db_get_b(hContact, MODULENAME, "HTMLConv", 0)) - db_set_b(hContact, MODULENAME, "HTMLConv", 0); - else - db_set_b(hContact, MODULENAME, "HTMLConv", 1); - - return 0; -} - -void InitMenu() -{ - CreateServiceFunction(MS_OTR_MENUSTART, SVC_StartOTR); - CreateServiceFunction(MS_OTR_MENUSTOP, SVC_StopOTR); - CreateServiceFunction(MS_OTR_MENUREFRESH, SVC_RefreshOTR); - CreateServiceFunction(MS_OTR_MENUVERIFY, SVC_VerifyOTR); - CreateServiceFunction(MS_OTR_MENUTOGGLEHTML, SVC_ToggleHTMLOTR); - - CLISTMENUITEM mi = { sizeof(mi) }; - mi.flags = CMIF_NOTOFFLINE | CMIF_TCHAR; - mi.position = -400000; - - mi.ptszName = _T(LANG_STOP_OTR); - mi.pszService = MS_OTR_MENUSTOP; - mi.icolibItem = GetIconHandle(ICON_PRIVATE); - - hStopItem = Menu_AddContactMenuItem(&mi); - - mi.ptszName = _T(LANG_START_OTR); - mi.pszService = MS_OTR_MENUSTART; - mi.icolibItem = GetIconHandle(ICON_NOT_PRIVATE); - - hStartItem = Menu_AddContactMenuItem(&mi); - - HookEvent(ME_CLIST_PREBUILDCONTACTMENU, SVC_PrebuildContactMenu); -} - -int SVC_PrebuildContactMenu(WPARAM hContact, LPARAM lParam) -{ - CLISTMENUITEM mi = { sizeof(mi) }; - mi.flags = CMIM_FLAGS | CMIF_NOTOFFLINE | CMIF_TCHAR; - - const char *proto = GetContactProto(hContact); - DWORD pol = CONTACT_DEFAULT_POLICY; - - if (!proto || db_get_b(hContact, proto, "ChatRoom", 0) == 1) { -hide_all: - Menu_ShowItem(hStartItem, false); - Menu_ShowItem(hStopItem, false); - return 0; - } - - if(proto && strcmp(proto, META_PROTO) == 0) { - // make menu act as per most online subcontact - hContact = db_mc_getMostOnline(hContact); - if (!hContact) - goto hide_all; - proto = GetContactProto(hContact); - } - - pol = db_get_dw(hContact, MODULENAME, "Policy", CONTACT_DEFAULT_POLICY); - if(pol == CONTACT_DEFAULT_POLICY) pol = options.default_policy; - - if(pol == OTRL_POLICY_NEVER || pol == OTRL_POLICY_ALWAYS) - goto hide_all; - - ConnContext *context = otrl_context_find_miranda(otr_user_state, hContact); - TrustLevel encrypted = otr_context_get_trust(context); - Menu_ShowItem(hStartItem, encrypted == TRUST_NOT_PRIVATE); - Menu_ShowItem(hStopItem, encrypted != TRUST_NOT_PRIVATE); - return 0; -} \ No newline at end of file +#include "stdafx.h" + +static HGENMENU hStopItem, hStartItem; + +//////////////////////////////// +///////// Menu Services //////// +/////////////////////////////// +int StartOTR(MCONTACT hContact) { + const char *proto = GetContactProto(hContact); + if (!proto) return 1; // error + char *uname = contact_get_id(hContact); + if (!uname) return 1; // error + DWORD pol = db_get_dw(hContact, MODULENAME, "Policy", CONTACT_DEFAULT_POLICY); + if(pol == CONTACT_DEFAULT_POLICY) pol = options.default_policy; + + lib_cs_lock(); + char *msg = otrl_proto_default_query_msg(MODULENAME, pol); + otr_gui_inject_message((void*)hContact, proto, proto, uname, msg ? msg : MIROTR_PROTO_HELLO); + free(msg); + lib_cs_unlock(); + mir_free(uname); + return 0; +} + +INT_PTR SVC_StartOTR(WPARAM hContact, LPARAM lParam) +{ + TCHAR buff[512]; + + MCONTACT hSub = db_mc_getMostOnline(hContact); + if(hSub != 0) + hContact = hSub; + + if ( options.bHaveSecureIM && CallService("SecureIM/IsContactSecured", hContact, 0) != 0 ) { + mir_sntprintf(buff, SIZEOF(buff), TranslateT(LANG_OTR_SECUREIM_STARTED), contact_get_nameT(hContact)); + ShowError(buff); + return 0; + } + + mir_sntprintf(buff, SIZEOF(buff), TranslateT(LANG_SESSION_REQUEST_OTR), contact_get_nameT(hContact)); + ShowMessage(hContact, buff); + + return StartOTR(hContact); +} + +INT_PTR SVC_RefreshOTR(WPARAM hContact, LPARAM lParam) +{ + TCHAR buff[512]; + + MCONTACT hSub = db_mc_getMostOnline(hContact); + if(hSub != 0) + hContact = hSub; + + if ( options.bHaveSecureIM && CallService("SecureIM/IsContactSecured", hContact, 0) != 0 ) { + mir_sntprintf(buff, 512, TranslateT(LANG_OTR_SECUREIM_STARTED), contact_get_nameT(hContact)); + ShowError(buff); + return 0; + } + + mir_sntprintf(buff, SIZEOF(buff), TranslateT(LANG_SESSION_TRY_CONTINUE_OTR), contact_get_nameT(hContact)); + ShowMessage(hContact, buff); + + int res = StartOTR(hContact); + if (res) return res; + + return 0; +} + +int otr_disconnect_contact(MCONTACT hContact) +{ + MCONTACT hSub = db_mc_getMostOnline(hContact); + if (hSub != 0) + hContact = hSub; + + const char *proto = GetContactProto(hContact); + if (!proto) return 1; // error + char *uname = contact_get_id(hContact); + if (!uname) return 1; // error + + lib_cs_lock(); + otrl_message_disconnect_all_instances(otr_user_state, &ops, (void*)hContact, proto, proto, uname); + lib_cs_unlock(); + mir_free(uname); + return 0; +} + +INT_PTR SVC_StopOTR(WPARAM hContact, LPARAM lParam) +{ + // prevent this filter from acting on injeceted messages for metas, when they are passed though the subcontact's proto send chain + if (otr_disconnect_contact(hContact)) return 0; + + SetEncryptionStatus(hContact, TRUST_NOT_PRIVATE); + + TCHAR buff[512]; + mir_sntprintf(buff, SIZEOF(buff), TranslateT(LANG_SESSION_TERMINATED_OTR), contact_get_nameT(hContact)); + ShowMessage(hContact, buff); + return 0; +} + +INT_PTR SVC_VerifyOTR(WPARAM hContact, LPARAM lParam) +{ + MCONTACT hSub = db_mc_getMostOnline(hContact); + if(hSub != 0) + hContact = hSub; + + ConnContext *context = otrl_context_find_miranda(otr_user_state, hContact); + if (!context) + return 1; + + //VerifyContextDialog(context); + SMPInitDialog(context); + return 0; +} + +INT_PTR SVC_ToggleHTMLOTR(WPARAM hContact, LPARAM lParam) +{ + MCONTACT hSub = db_mc_getMostOnline(hContact); + if (hSub != 0) + hContact = hSub; + + if (db_get_b(hContact, MODULENAME, "HTMLConv", 0)) + db_set_b(hContact, MODULENAME, "HTMLConv", 0); + else + db_set_b(hContact, MODULENAME, "HTMLConv", 1); + + return 0; +} + +void InitMenu() +{ + CreateServiceFunction(MS_OTR_MENUSTART, SVC_StartOTR); + CreateServiceFunction(MS_OTR_MENUSTOP, SVC_StopOTR); + CreateServiceFunction(MS_OTR_MENUREFRESH, SVC_RefreshOTR); + CreateServiceFunction(MS_OTR_MENUVERIFY, SVC_VerifyOTR); + CreateServiceFunction(MS_OTR_MENUTOGGLEHTML, SVC_ToggleHTMLOTR); + + CLISTMENUITEM mi = { sizeof(mi) }; + mi.flags = CMIF_NOTOFFLINE | CMIF_TCHAR; + mi.position = -400000; + + mi.ptszName = _T(LANG_STOP_OTR); + mi.pszService = MS_OTR_MENUSTOP; + mi.icolibItem = GetIconHandle(ICON_PRIVATE); + + hStopItem = Menu_AddContactMenuItem(&mi); + + mi.ptszName = _T(LANG_START_OTR); + mi.pszService = MS_OTR_MENUSTART; + mi.icolibItem = GetIconHandle(ICON_NOT_PRIVATE); + + hStartItem = Menu_AddContactMenuItem(&mi); + + HookEvent(ME_CLIST_PREBUILDCONTACTMENU, SVC_PrebuildContactMenu); +} + +int SVC_PrebuildContactMenu(WPARAM hContact, LPARAM lParam) +{ + CLISTMENUITEM mi = { sizeof(mi) }; + mi.flags = CMIM_FLAGS | CMIF_NOTOFFLINE | CMIF_TCHAR; + + const char *proto = GetContactProto(hContact); + DWORD pol = CONTACT_DEFAULT_POLICY; + + if (!proto || db_get_b(hContact, proto, "ChatRoom", 0) == 1) { +hide_all: + Menu_ShowItem(hStartItem, false); + Menu_ShowItem(hStopItem, false); + return 0; + } + + if(proto && strcmp(proto, META_PROTO) == 0) { + // make menu act as per most online subcontact + hContact = db_mc_getMostOnline(hContact); + if (!hContact) + goto hide_all; + proto = GetContactProto(hContact); + } + + pol = db_get_dw(hContact, MODULENAME, "Policy", CONTACT_DEFAULT_POLICY); + if(pol == CONTACT_DEFAULT_POLICY) pol = options.default_policy; + + if(pol == OTRL_POLICY_NEVER || pol == OTRL_POLICY_ALWAYS) + goto hide_all; + + ConnContext *context = otrl_context_find_miranda(otr_user_state, hContact); + TrustLevel encrypted = otr_context_get_trust(context); + Menu_ShowItem(hStartItem, encrypted == TRUST_NOT_PRIVATE); + Menu_ShowItem(hStopItem, encrypted != TRUST_NOT_PRIVATE); + return 0; +} diff --git a/plugins/MirOTR/src/svcs_proto.cpp b/plugins/MirOTR/src/svcs_proto.cpp index 545f5574b7..90f4373128 100644 --- a/plugins/MirOTR/src/svcs_proto.cpp +++ b/plugins/MirOTR/src/svcs_proto.cpp @@ -1,368 +1,218 @@ -#include "stdafx.h" - -//TODO: Social-Millionaire-Dialoge -INT_PTR SVC_OTRSendMessage(WPARAM wParam,LPARAM lParam){ - if (!lParam) return 0; - - CCSDATA *ccs = (CCSDATA *) lParam; - - DEBUGOUT_T("SENDING") - - if (ccs->wParam & PREF_BYPASS_OTR) // bypass for OTR-messages - return CallService(MS_PROTO_CHAINSEND, wParam, lParam); - - char *proto = GetContactProto(ccs->hContact); - if(proto && strcmp(proto, META_PROTO) == 0) // bypass for metacontacts - return CallService(MS_PROTO_CHAINSEND, wParam, lParam); - - if (!proto || !ccs->hContact) - return 1; // error - - char *oldmessage = (char *)ccs->lParam; - char *oldmessage_utf = 0; - - //MessageBox(0, "Send message - converting to UTF-8", "msg", MB_OK); - - if(ccs->wParam & PREF_UTF) { - oldmessage_utf = oldmessage; - } - else if(ccs->wParam & PREF_UNICODE) { - //TODO: check if this is correct or oldmessage[strlen(oldmessage)+1] is needed - //oldmessage_utf = mir_utf8encodeW((wchar_t*)oldmessage); - //should be the thing with strlen - oldmessage_utf = mir_utf8encodeW((wchar_t*)&oldmessage[strlen(oldmessage)+1]); - } - else { - oldmessage_utf = mir_utf8encode(oldmessage); - } - if (!oldmessage_utf) return 1; - - // don't filter OTR messages being sent (OTR messages should only happen *after* the otrl_message_sending call below) - if(strncmp(oldmessage_utf, "?OTR", 4) == 0) { - DEBUGOUT_T("OTR message without PREF_BYPASS_OTR") - if (!(ccs->wParam & PREF_UTF)) - mir_free(oldmessage_utf); - return CallService(MS_PROTO_CHAINSEND, wParam, lParam); - } - - char *tmpencode = NULL; - ConnContext *context = otrl_context_find_miranda(otr_user_state, ccs->hContact); - if (db_get_b(ccs->hContact, MODULENAME, "HTMLConv", 0) && otr_context_get_trust(context) >= TRUST_UNVERIFIED) { - tmpencode = encode_html_entities_utf8(oldmessage_utf); - if (tmpencode != NULL) { - if (!(ccs->wParam & PREF_UTF)) mir_free(oldmessage_utf); - oldmessage_utf = tmpencode; - } - } - - char *newmessage = 0; - char *username = contact_get_id(ccs->hContact); - gcry_error_t err = otrl_message_sending(otr_user_state, &ops, (void*)ccs->hContact, - proto, proto, username, oldmessage_utf, NULL, &newmessage, - add_appdata, (void*)ccs->hContact); - if (tmpencode!= NULL || !(ccs->wParam & PREF_UTF)) - mir_free(oldmessage_utf); - oldmessage_utf = NULL; - mir_free(username); - - if (err && newmessage == NULL) { - /* Be *sure* not to send out plaintext */ - ShowError(TranslateT(LANG_ENCRYPTION_ERROR)); - return 1; - } - else if (newmessage) { - /* Fragment the message if necessary, and send all but the last - * fragment over the network. We will send the last segment later */ - - // oldmessage_utf is not used anymore, so use it as buffer - err = otrl_message_fragment_and_send(&ops, (void*)ccs->hContact, context, - newmessage, OTRL_FRAGMENT_SEND_ALL_BUT_LAST, &oldmessage_utf); - // newmessage is not needed anymore - otrl_message_free(newmessage); - // move the last fragment to newmessage, oldmessage_utf will be buffer later - newmessage = oldmessage_utf; - - WPARAM oldflags = ccs->wParam; - if(ccs->wParam & PREF_UTF) { - ccs->lParam = (LPARAM)newmessage; - } - else if(ccs->wParam & PREF_UNICODE) { - // just send UTF, hope that proto supports it. - // don't want to create the Unicode-Format - // oldmessage_utf = (char*)mir_utf8decodeW(newmessage); - ccs->lParam = (LPARAM)newmessage; - ccs->wParam &= ~PREF_UNICODE; - ccs->wParam |= PREF_UTF; - } - else { - mir_utf8decode(newmessage, NULL); - ccs->lParam = (LPARAM)newmessage; - } - INT_PTR ret = CallService(MS_PROTO_CHAINSEND, wParam, lParam); - - DEBUGOUTA("OTR - sending raw message: "); - DEBUGOUTA((char *)ccs->lParam); - - // reset to original values - ccs->lParam = (LPARAM)oldmessage; - ccs->wParam = oldflags; - otrl_message_free(newmessage); - return ret; - } - return CallService(MS_PROTO_CHAINSEND, wParam, lParam); -} - -/* -#define MESSAGE_PREFIX "(OTR) " -#define MESSAGE_PREFIXW L"(OTR) " -#define MESSAGE_PREFIX_LEN 6 -*/ - -INT_PTR SVC_OTRRecvMessage(WPARAM wParam,LPARAM lParam) -{ - CCSDATA *ccs = (CCSDATA *) lParam; - PROTORECVEVENT *pre = (PROTORECVEVENT *) ccs->lParam; - - DEBUGOUTA("OTR - receiving message: "); - DEBUGOUTA((char *)ccs->lParam); - - if (pre->flags & PREF_BYPASS_OTR) { // bypass for our inline messages - return CallService(MS_PROTO_CHAINRECV, wParam, lParam); - } - - char *proto = GetContactProto(ccs->hContact); - if (!proto) - return 1; //error - else if(proto && strcmp(proto, META_PROTO) == 0) // bypass for metacontacts - return CallService(MS_PROTO_CHAINRECV, wParam, lParam); - - if (!ccs->hContact) - return 1; //error - - char *oldmessage = pre->szMessage; - char *oldmessage_utf = NULL; - // convert oldmessage to utf-8 - if(pre->flags & PREF_UTF) { - oldmessage_utf = oldmessage; - } else if(pre->flags & PREF_UNICODE) { //UNSURE!! - oldmessage_utf = mir_utf8encodeW((wchar_t*)(&oldmessage[strlen(oldmessage)+1])); - } else { - oldmessage_utf = mir_utf8encode(oldmessage); - } - if (!oldmessage_utf) return 1; - - - char *newmessage = NULL; - OtrlTLV *tlvs = NULL; - - char *uname = contact_get_id(ccs->hContact); - lib_cs_lock(); - BOOL 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; - - - OtrlTLV *tlv = otrl_tlv_find(tlvs, OTRL_TLV_DISCONNECTED); - if (tlv && !Miranda_Terminated()) { - /* Notify the user that the other side disconnected. */ - TCHAR buff[256]; - mir_sntprintf(buff, SIZEOF(buff), TranslateT(LANG_SESSION_TERMINATED_BY_OTR), contact_get_nameT(ccs->hContact)); - //MessageBox(0, buff, Translate("OTR Information"), MB_OK); - ShowMessage(ccs->hContact, buff); - } - - lib_cs_lock(); - ConnContext *context = otrl_context_find_miranda(otr_user_state, ccs->hContact); - lib_cs_unlock(); - /* Keep track of our current progress in the Socialist Millionaires' - * Protocol. */ - - /* - if (context && ( (context->smstate->sm_prog_state == OTRL_SMP_PROG_CHEATED) || - otrl_tlv_find(tlvs, OTRL_TLV_SMP1Q) || - otrl_tlv_find(tlvs, OTRL_TLV_SMP1) || - otrl_tlv_find(tlvs, OTRL_TLV_SMP2) || - otrl_tlv_find(tlvs, OTRL_TLV_SMP3) || - otrl_tlv_find(tlvs, OTRL_TLV_SMP4) ) - ) - { - otr_abort_smp(context); // we do not support it (yet), notify partner to shorten wait time - } - */ - - - if (context) { - NextExpectedSMP nextMsg = context->smstate->nextExpected; - - if (context->smstate->sm_prog_state == OTRL_SMP_PROG_CHEATED) { - otr_abort_smp(context); - //otrg_dialog_update_smp(context, 0.0); - SMPDialogUpdate(context, 0); - context->smstate->nextExpected = OTRL_SMP_EXPECT1; - context->smstate->sm_prog_state = OTRL_SMP_PROG_OK; - } - else { - tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP1Q); - if (tlv) { - if (nextMsg != OTRL_SMP_EXPECT1) - otr_abort_smp(context); - else { - char *question = (char *)tlv->data; - char *eoq = (char*)memchr(question, '\0', tlv->len); - if (eoq) { - SMPDialogReply(context, question); - } - } - } - tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP1); - if (tlv) { - if (nextMsg != OTRL_SMP_EXPECT1) - otr_abort_smp(context); - else { - SMPDialogReply(context, NULL); - } - } - tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP2); - if (tlv) { - if (nextMsg != OTRL_SMP_EXPECT2) - otr_abort_smp(context); - else { - context->smstate->nextExpected = OTRL_SMP_EXPECT4; - SMPDialogUpdate(context, 60); - } - } - tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP3); - if (tlv) { - if (nextMsg != OTRL_SMP_EXPECT3) - otr_abort_smp(context); - else { - context->smstate->nextExpected = OTRL_SMP_EXPECT1; - SMPDialogUpdate(context, 100); - //otrg_dialog_update_smp(context, 1.0); - } - } - tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP4); - if (tlv) { - if (nextMsg != OTRL_SMP_EXPECT4) - otr_abort_smp(context); - else { - SMPDialogUpdate(context, 100); - //otrg_dialog_update_smp(context, 1.0); - context->smstate->nextExpected = OTRL_SMP_EXPECT1; - } - } - tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP_ABORT); - if (tlv) { - SMPDialogUpdate(context, 0); - context->smstate->nextExpected = OTRL_SMP_EXPECT1; - } - } - } - otrl_tlv_free(tlvs); - - /* 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 - * displayed anyway. */ - if (ignore_msg) { - /* should not be required ;) - char t[3] = {0, 0, 0}; - char t[3] = {0, 0, 0}; - if(pre->flags & PREF_UNICODE) { //TODO!! mir_tstrlen(pre->szMessage)+1 ?? - if (pre->szMessage && strlen(pre->szMessage)) memcpy(pre->szMessage, t,3 ); - } else { - if (pre->szMessage && strlen(pre->szMessage)) memcpy(pre->szMessage, t, 1); - } - */ - if (newmessage) - otrl_message_free(newmessage); - return 1; - } - else if (newmessage) { - //bool free=false; - DWORD flags = pre->flags; - /* if(pre->flags & PREF_UTF) { - oldmessage_utf = newmessage; - } else if(pre->flags & PREF_UNICODE) { //TODO!! mir_tstrlen(pre->szMessage)+1 ?? - oldmessage_utf = (char*)mir_utf8decodeW(newmessage); - free = true; - } else { - mir_utf8decode(newmessage, NULL); - oldmessage_utf = newmessage; - } */ - - //pre->szMessage = oldmessage_utf; - pre->flags &= ~PREF_UNICODE; - pre->flags |= PREF_UTF; // just use UTF, so we do not have to recode the message - - bool is_miralloc = false; - if (context) { - TrustLevel level = otr_context_get_trust(context); - if (level >= TRUST_UNVERIFIED) { - char *premsg; - if (db_get_b(ccs->hContact, MODULENAME, "HTMLConv", 0)) { - premsg = striphtml(newmessage); - otrl_message_free(newmessage); - newmessage = premsg; - is_miralloc = true; - } - - if (options.prefix_messages) { - size_t len = (strlen(options.prefix)+strlen(newmessage)+1)*sizeof(char); - premsg = (char*)mir_alloc( len ); - memset(premsg, 0, len); - strcpy(premsg, options.prefix); - strcat(premsg, newmessage); - (is_miralloc) ? mir_free(newmessage) : otrl_message_free(newmessage); - newmessage = premsg; - is_miralloc = true; - } - } - } - pre->szMessage = newmessage; - BOOL ret = CallService(MS_PROTO_CHAINRECV, wParam, lParam); - pre->flags = flags; - pre->szMessage = oldmessage; - if (is_miralloc) - mir_free(newmessage); - else - otrl_message_free(newmessage); - - // if (free) mir_free(oldmessage_utf); - return ret; - } - return CallService(MS_PROTO_CHAINRECV, wParam, lParam); - -} - -/* Abort the SMP protocol. Used when malformed or unexpected messages - * are received. */ -void otr_abort_smp(ConnContext *context) -{ - otrl_message_abort_smp(otr_user_state, &ops, context->app_data, context); -} - -/* Start the Socialist Millionaires' Protocol over the current connection, - * using the given initial secret, and optionally a question to pass to - * the buddy. */ -void otr_start_smp(ConnContext *context, const char *question, - const unsigned char *secret, size_t secretlen) -{ - otrl_message_initiate_smp_q(otr_user_state, &ops, context->app_data, - context, question, secret, secretlen); -} - -/* Continue the Socialist Millionaires' Protocol over the current connection, - * using the given initial secret (ie finish step 2). */ -void otr_continue_smp(ConnContext *context, - const unsigned char *secret, size_t secretlen) -{ - otrl_message_respond_smp(otr_user_state, &ops, context->app_data, - context, secret, secretlen); -} \ No newline at end of file +#include "stdafx.h" + +INT_PTR SVC_OTRSendMessage(WPARAM wParam,LPARAM lParam){ + if (!lParam) return 0; + + CCSDATA *ccs = (CCSDATA *) lParam; + + DEBUGOUT_T("SENDING\n"); + DEBUGOUTA("'"); + DEBUGOUTA((const char*)ccs->lParam); + DEBUGOUTA("'\n"); + + if (ccs->wParam & PREF_BYPASS_OTR) // bypass for OTR-messages + return CallService(MS_PROTO_CHAINSEND, wParam, lParam); + + char *proto = GetContactProto(ccs->hContact); + if(proto && strcmp(proto, META_PROTO) == 0) // bypass for metacontacts + return CallService(MS_PROTO_CHAINSEND, wParam, lParam); + + if (!proto || !ccs->hContact) + return 1; // error + + const char *oldmessage = (const char *)ccs->lParam; + char *oldmessage_utf = NULL; + + //MessageBox(0, "Send message - converting to UTF-8", "msg", MB_OK); + + if(ccs->wParam & PREF_UTF) { + oldmessage_utf = (char*)oldmessage; + } + else if(ccs->wParam & PREF_UNICODE) { + oldmessage_utf = mir_utf8encodeW((wchar_t*)&oldmessage[strlen(oldmessage)+1]); + } + else { + oldmessage_utf = mir_utf8encode(oldmessage); + } + if (!oldmessage_utf) return 1; + + // don't filter OTR messages being sent (OTR messages should only happen *after* the otrl_message_sending call below) + if(strncmp(oldmessage_utf, "?OTR", 4) == 0) { + DEBUGOUT_T("OTR message without PREF_BYPASS_OTR\n"); + if (!(ccs->wParam & PREF_UTF)) + mir_free(oldmessage_utf); + return CallService(MS_PROTO_CHAINSEND, wParam, lParam); + } + + char *tmpencode = NULL; + ConnContext *context = otrl_context_find_miranda(otr_user_state, ccs->hContact); + if (db_get_b(ccs->hContact, MODULENAME, "HTMLConv", 0) && otr_context_get_trust(context) >= TRUST_UNVERIFIED) { + tmpencode = encode_html_entities_utf8(oldmessage_utf); + if (tmpencode != NULL) { + if (!(ccs->wParam & PREF_UTF)) mir_free(oldmessage_utf); + oldmessage_utf = tmpencode; + } + } + + char *newmessage = NULL; + char *username = contact_get_id(ccs->hContact); + gcry_error_t err = otrl_message_sending(otr_user_state, &ops, (void*)ccs->hContact, proto, proto, username, OTRL_INSTAG_BEST, oldmessage_utf, NULL, &newmessage, OTRL_FRAGMENT_SEND_ALL_BUT_LAST, NULL, add_appdata, (void*)ccs->hContact); + if (tmpencode!= NULL || !(ccs->wParam & PREF_UTF)) + mir_free(oldmessage_utf); + mir_free(username); + + if (err) { /* Be *sure* not to send out plaintext */ + DEBUGOUTA("otrl_message_sending err"); + ShowError(TranslateT(LANG_ENCRYPTION_ERROR)); + otrl_message_free(newmessage); + return 1; + } else if (newmessage) { + if(!newmessage[0]){ + otrl_message_free(newmessage); + return 1; // skip empty messages (OTR might prevent us sending unencrypted messages by replacing them with empty ones) + } + WPARAM oldflags = ccs->wParam; + if(ccs->wParam & (PREF_UTF|PREF_UNICODE)) { + ccs->lParam = (LPARAM)newmessage; + ccs->wParam &= ~PREF_UNICODE; + ccs->wParam |= PREF_UTF; + } else { + mir_utf8decode(newmessage, NULL); + ccs->lParam = (LPARAM)newmessage; + } + INT_PTR ret = CallService(MS_PROTO_CHAINSEND, wParam, lParam); + + DEBUGOUTA("OTR - sending raw message: '"); + DEBUGOUTA((const char*)ccs->lParam); + DEBUGOUTA("'\n"); + otrl_message_free(newmessage); + + // reset to original values + ccs->lParam = (LPARAM)oldmessage; + ccs->wParam = oldflags; + return ret; + } + return CallService(MS_PROTO_CHAINSEND, wParam, lParam); +} + + +INT_PTR SVC_OTRRecvMessage(WPARAM wParam,LPARAM lParam) +{ + CCSDATA *ccs = (CCSDATA *) lParam; + PROTORECVEVENT *pre = (PROTORECVEVENT *) ccs->lParam; + + DEBUGOUTA("OTR - receiving message: '"); + DEBUGOUTA(pre->szMessage); + DEBUGOUTA("'\n"); + + if (pre->flags & PREF_BYPASS_OTR) { // bypass for our inline messages + return CallService(MS_PROTO_CHAINRECV, wParam, lParam); + } + + char *proto = GetContactProto(ccs->hContact); + if (!proto || !ccs->hContact) + return 1; //error + else if(proto && strcmp(proto, META_PROTO) == 0) // bypass for metacontacts + return CallService(MS_PROTO_CHAINRECV, wParam, lParam); + + char *oldmessage = pre->szMessage; + char *oldmessage_utf = NULL; + // convert oldmessage to utf-8 + if(pre->flags & PREF_UTF) { + oldmessage_utf = oldmessage; + } else if(pre->flags & PREF_UNICODE) { + oldmessage_utf = mir_utf8encodeW((wchar_t*)(&oldmessage[strlen(oldmessage)+1])); + } else { + oldmessage_utf = mir_utf8encode(oldmessage); + } + if (!oldmessage_utf) return 1; + + + ConnContext* context=NULL; + char *uname = contact_get_id(ccs->hContact); + char *newmessage = NULL; + OtrlTLV *tlvs = NULL; + + lib_cs_lock(); + int ignore_msg = otrl_message_receiving(otr_user_state, &ops, (void*)ccs->hContact, + proto, proto, uname, oldmessage_utf, + &newmessage, &tlvs, &context, add_appdata, (void*)ccs->hContact); + lib_cs_unlock(); + mir_free(uname); + + if ( !(pre->flags & PREF_UTF)) + mir_free(oldmessage_utf); + + OtrlTLV *tlv = otrl_tlv_find(tlvs, OTRL_TLV_DISCONNECTED); + if (tlv && !Miranda_Terminated()) { + /* Notify the user that the other side disconnected. */ + TCHAR buff[256]; + mir_sntprintf(buff, SIZEOF(buff), TranslateT(LANG_SESSION_TERMINATED_BY_OTR), contact_get_nameT(ccs->hContact)); + SetEncryptionStatus(ccs->hContact, otr_context_get_trust(context)); // required since libotr 4!? + ShowMessage(ccs->hContact, buff); + } + otrl_tlv_free(tlvs); + + if (ignore_msg) { + if (newmessage) + otrl_message_free(newmessage); + return 1; // discard internal protocol messages + } else if (newmessage) { + DWORD oldflags = pre->flags; + pre->flags &= ~PREF_UNICODE; + pre->flags |= PREF_UTF; // just use UTF, so we do not have to recode the message + + typedef void (*msg_free_t)(void*); + msg_free_t msg_free = (msg_free_t)otrl_message_free; + if (db_get_b(ccs->hContact, MODULENAME, "HTMLConv", 0)) { + char* tmp = striphtml(newmessage); + msg_free(newmessage); + newmessage = tmp; + msg_free = mir_free; + } + if (options.prefix_messages) { + size_t len = (strlen(options.prefix)+strlen(newmessage)+1)*sizeof(char); + char* tmp = (char*)mir_alloc( len ); + strcpy(tmp, options.prefix); + strcat(tmp, newmessage); + msg_free(newmessage); + newmessage = tmp; + msg_free = mir_free; + } + pre->szMessage = newmessage; + BOOL ret = CallService(MS_PROTO_CHAINRECV, wParam, lParam); +/// @todo (White-Tiger#1#03/23/15): why are we doing this? + pre->flags = oldflags; + pre->szMessage = oldmessage; + msg_free(newmessage); + return ret; + } + return CallService(MS_PROTO_CHAINRECV, wParam, lParam); + +} + +/* Abort the SMP protocol. Used when malformed or unexpected messages + * are received. */ +void otr_abort_smp(ConnContext *context) +{ + otrl_message_abort_smp(otr_user_state, &ops, context->app_data, context); +} + +/* Start the Socialist Millionaires' Protocol over the current connection, + * using the given initial secret, and optionally a question to pass to + * the buddy. */ +void otr_start_smp(ConnContext *context, const char *question, + const unsigned char *secret, size_t secretlen) +{ + otrl_message_initiate_smp_q(otr_user_state, &ops, context->app_data, + context, question, secret, secretlen); +} + +/* Continue the Socialist Millionaires' Protocol over the current connection, + * using the given initial secret (ie finish step 2). */ +void otr_continue_smp(ConnContext *context, + const unsigned char *secret, size_t secretlen) +{ + otrl_message_respond_smp(otr_user_state, &ops, context->app_data, + context, secret, secretlen); +} diff --git a/plugins/MirOTR/src/svcs_srmm.cpp b/plugins/MirOTR/src/svcs_srmm.cpp index 56e3f44d9b..27eb741700 100644 --- a/plugins/MirOTR/src/svcs_srmm.cpp +++ b/plugins/MirOTR/src/svcs_srmm.cpp @@ -1,156 +1,158 @@ -#include "stdafx.h" - -HICON hIconNotSecure, hIconFinished, hIconPrivate, hIconUnverified; -BBButton OTRButton; - -int SVC_IconPressed(WPARAM hContact, LPARAM lParam) -{ - StatusIconClickData *sicd = (StatusIconClickData *)lParam; - if(sicd->cbSize < sizeof(StatusIconClickData)) - return 0; - - if(strcmp(sicd->szModule, MODULENAME) == 0) { - char *proto = GetContactProto(hContact); - if(proto && db_get_b(hContact, proto, "ChatRoom", 0)) - return 0; - ShowOTRMenu(hContact, sicd->clickLocation); - } - - return 0; -} - -// set SRMM icon status, if applicable -void SetEncryptionStatus(MCONTACT hContact, TrustLevel level) -{ - char *proto = GetContactProto(hContact); - bool chat_room = (proto && db_get_b(hContact, proto, "ChatRoom", 0)); - - BBButton button = OTRButton; - - StatusIconData sid = { sizeof(sid) }, sid2 = { sizeof(sid) }; - sid.szModule = MODULENAME; - sid.dwId = 0; - sid.flags = MBF_HIDDEN; - - sid2.szModule = MODULENAME; - sid2.dwId = 1; - sid2.flags = MBF_HIDDEN; - - if (!chat_room) { - switch (level) { - case TRUST_FINISHED: - sid.flags = 0; - button.ptszTooltip = TranslateT(LANG_STATUS_FINISHED); - button.hIcon = GetIconHandle(ICON_FINISHED); - break; - case TRUST_UNVERIFIED: - sid2.flags = MBF_DISABLED; - button.ptszTooltip = TranslateT(LANG_STATUS_UNVERIFIED); - button.hIcon = GetIconHandle(ICON_UNVERIFIED); - break; - case TRUST_PRIVATE: - sid2.flags = 0; - button.ptszTooltip = TranslateT(LANG_STATUS_PRIVATE); - button.hIcon = GetIconHandle(ICON_PRIVATE); - break; - default: - sid.flags = MBF_DISABLED; - button.ptszTooltip = TranslateT(LANG_STATUS_DISABLED); - button.hIcon = GetIconHandle(ICON_NOT_PRIVATE); - break; - } - button.bbbFlags = 0; - } - else button.bbbFlags = BBSF_HIDDEN; - - Srmm_ModifyIcon(hContact, &sid); - Srmm_ModifyIcon(hContact, &sid2); - - if (options.bHaveButtonsBar) CallService(MS_BB_SETBUTTONSTATE, hContact, (LPARAM)&button); - db_set_dw(hContact, MODULENAME, "TrustLevel", level); - - if (!chat_room) { - MCONTACT hMeta = db_mc_getMeta(hContact); - MCONTACT hMostOnline = db_mc_getMostOnline(hMeta); - if(hMeta && hContact == hMostOnline) - SetEncryptionStatus(hMeta, level); - else if(hMeta) { - /* in case the new most online contact has changed - (e.g. when the otr subcontact goes offline) */ - ConnContext *context = otrl_context_find_miranda(otr_user_state, hMostOnline); - TrustLevel encrypted = otr_context_get_trust(context); - SetEncryptionStatus(hMeta, encrypted); - } - } -} - -int SVC_ButtonsBarLoaded(WPARAM, LPARAM) -{ - CallService(MS_BB_ADDBUTTON, 0, (LPARAM)&OTRButton); - return 0; -} - -int SVC_ButtonsBarPressed(WPARAM w, LPARAM l) -{ - CustomButtonClickData* cbcd = (CustomButtonClickData *)l; - if (cbcd->cbSize == sizeof(CustomButtonClickData) && cbcd->dwButtonId == 0 && strcmp(cbcd->pszModule, MODULENAME)==0) { - MCONTACT hContact = (MCONTACT)w; - - char *proto = GetContactProto(hContact); - if(proto && db_get_b(hContact, proto, "ChatRoom", 0)) - return 0; - ShowOTRMenu(hContact, cbcd->pt); - - } - return 0; -} - -void InitSRMM() -{ - // add icon to srmm status icons - InitMirOTRMenu(); - - hIconNotSecure = LoadIcon(ICON_NOT_PRIVATE, 0); - hIconFinished = LoadIcon(ICON_FINISHED, 0); - hIconPrivate = LoadIcon(ICON_PRIVATE, 0); - hIconUnverified = LoadIcon(ICON_UNVERIFIED, 0); - - StatusIconData sid = { sizeof(sid) }; - sid.szModule = MODULENAME; - sid.hIcon = hIconFinished; - sid.hIconDisabled = hIconNotSecure; - sid.flags = MBF_DISABLED | MBF_HIDDEN; - sid.szTooltip = LANG_OTR_TOOLTIP; - Srmm_AddIcon(&sid); - - sid.dwId = 1; - sid.hIcon = hIconPrivate; - sid.hIconDisabled = hIconUnverified; - Srmm_AddIcon(&sid); - - // hook the window events so that we can can change the status of the icon - HookEvent(ME_MSG_ICONPRESSED, SVC_IconPressed); - - if (options.bHaveButtonsBar) { - memset(&OTRButton, 0, sizeof(OTRButton)); - OTRButton.cbSize = sizeof(OTRButton); - OTRButton.dwButtonID = 0; - OTRButton.pszModuleName = MODULENAME; - OTRButton.dwDefPos = 200; - OTRButton.bbbFlags = BBBF_ISRSIDEBUTTON|BBBF_CANBEHIDDEN|BBBF_ISIMBUTTON; - OTRButton.ptszTooltip = TranslateT(LANG_OTR_TOOLTIP); - OTRButton.hIcon = GetIconHandle(ICON_NOT_PRIVATE); - HookEvent(ME_MSG_TOOLBARLOADED, SVC_ButtonsBarLoaded); - HookEvent(ME_MSG_BUTTONPRESSED, SVC_ButtonsBarPressed); - } -} -void DeinitSRMM() -{ - ReleaseIcon(ICON_NOT_PRIVATE, 0); - ReleaseIcon(ICON_FINISHED, 0); - ReleaseIcon(ICON_PRIVATE, 0); - ReleaseIcon(ICON_UNVERIFIED, 0); - hIconNotSecure = hIconFinished = hIconPrivate = hIconUnverified =0; - - UninitMirOTRMenu(); -} \ No newline at end of file +#include "stdafx.h" + +HICON hIconNotSecure, hIconFinished, hIconPrivate, hIconUnverified; +BBButton OTRButton; + +int SVC_IconPressed(WPARAM hContact, LPARAM lParam) +{ + StatusIconClickData *sicd = (StatusIconClickData *)lParam; + if(sicd->cbSize < sizeof(StatusIconClickData)) + return 0; + + if(strcmp(sicd->szModule, MODULENAME) == 0) { + char *proto = GetContactProto(hContact); + if(proto && db_get_b(hContact, proto, "ChatRoom", 0)) + return 0; + ShowOTRMenu(hContact, sicd->clickLocation); + } + + return 0; +} + +// set SRMM icon status, if applicable +void SetEncryptionStatus(MCONTACT hContact, TrustLevel level) +{ + char *proto = GetContactProto(hContact); + bool chat_room = (proto && db_get_b(hContact, proto, "ChatRoom", 0)); + + BBButton button = OTRButton; + + StatusIconData sid = { sizeof(sid) }, sid2 = { sizeof(sid) }; + sid.szModule = MODULENAME; + sid.dwId = 0; + sid.flags = MBF_HIDDEN; + + sid2.szModule = MODULENAME; + sid2.dwId = 1; + sid2.flags = MBF_HIDDEN; + + if (!chat_room) { + switch (level) { + case TRUST_FINISHED: + sid.flags = 0; + button.ptszTooltip = TranslateT(LANG_STATUS_FINISHED); + button.hIcon = GetIconHandle(ICON_FINISHED); + break; + case TRUST_UNVERIFIED: + sid2.flags = MBF_DISABLED; + button.ptszTooltip = TranslateT(LANG_STATUS_UNVERIFIED); + button.hIcon = GetIconHandle(ICON_UNVERIFIED); + break; + case TRUST_PRIVATE: + sid2.flags = 0; + button.ptszTooltip = TranslateT(LANG_STATUS_PRIVATE); + button.hIcon = GetIconHandle(ICON_PRIVATE); + break; + default: + sid.flags = MBF_DISABLED; + button.ptszTooltip = TranslateT(LANG_STATUS_DISABLED); + button.hIcon = GetIconHandle(ICON_NOT_PRIVATE); + break; + } + button.bbbFlags = 0; + } + else button.bbbFlags = BBSF_HIDDEN; + + Srmm_ModifyIcon(hContact, &sid); + Srmm_ModifyIcon(hContact, &sid2); + + if (options.bHaveButtonsBar) CallService(MS_BB_SETBUTTONSTATE, hContact, (LPARAM)&button); + db_set_dw(hContact, MODULENAME, "TrustLevel", level); + + if (!chat_room) { + MCONTACT hMeta = db_mc_getMeta(hContact); + if(hMeta){ + MCONTACT hMostOnline = db_mc_getMostOnline(hMeta); + if(hContact == hMostOnline) { + SetEncryptionStatus(hMeta, level); + } else { + /* in case the new most online contact has changed + (e.g. when the otr subcontact goes offline) */ + ConnContext *context = otrl_context_find_miranda(otr_user_state, hMostOnline); + TrustLevel encrypted = otr_context_get_trust(context); + SetEncryptionStatus(hMeta, encrypted); + } + } + } +} + +int SVC_ButtonsBarLoaded(WPARAM, LPARAM) +{ + CallService(MS_BB_ADDBUTTON, 0, (LPARAM)&OTRButton); + return 0; +} + +int SVC_ButtonsBarPressed(WPARAM w, LPARAM l) +{ + CustomButtonClickData* cbcd = (CustomButtonClickData *)l; + if (cbcd->cbSize == sizeof(CustomButtonClickData) && cbcd->dwButtonId == 0 && strcmp(cbcd->pszModule, MODULENAME)==0) { + MCONTACT hContact = (MCONTACT)w; + + char *proto = GetContactProto(hContact); + if(proto && db_get_b(hContact, proto, "ChatRoom", 0)) + return 0; + ShowOTRMenu(hContact, cbcd->pt); + + } + return 0; +} + +void InitSRMM() +{ + // add icon to srmm status icons + InitMirOTRMenu(); + + hIconNotSecure = LoadIcon(ICON_NOT_PRIVATE, 0); + hIconFinished = LoadIcon(ICON_FINISHED, 0); + hIconPrivate = LoadIcon(ICON_PRIVATE, 0); + hIconUnverified = LoadIcon(ICON_UNVERIFIED, 0); + + StatusIconData sid = { sizeof(sid) }; + sid.szModule = MODULENAME; + sid.hIcon = hIconFinished; + sid.hIconDisabled = hIconNotSecure; + sid.flags = MBF_DISABLED | MBF_HIDDEN; + sid.szTooltip = LANG_OTR_TOOLTIP; + Srmm_AddIcon(&sid); + + sid.dwId = 1; + sid.hIcon = hIconPrivate; + sid.hIconDisabled = hIconUnverified; + Srmm_AddIcon(&sid); + + // hook the window events so that we can can change the status of the icon + HookEvent(ME_MSG_ICONPRESSED, SVC_IconPressed); + + if (options.bHaveButtonsBar) { + memset(&OTRButton, 0, sizeof(OTRButton)); + OTRButton.cbSize = sizeof(OTRButton); + OTRButton.dwButtonID = 0; + OTRButton.pszModuleName = MODULENAME; + OTRButton.dwDefPos = 200; + OTRButton.bbbFlags = BBBF_ISRSIDEBUTTON|BBBF_CANBEHIDDEN|BBBF_ISIMBUTTON; + OTRButton.ptszTooltip = TranslateT(LANG_OTR_TOOLTIP); + OTRButton.hIcon = GetIconHandle(ICON_NOT_PRIVATE); + HookEvent(ME_MSG_TOOLBARLOADED, SVC_ButtonsBarLoaded); + HookEvent(ME_MSG_BUTTONPRESSED, SVC_ButtonsBarPressed); + } +} +void DeinitSRMM() +{ + ReleaseIcon(ICON_NOT_PRIVATE, 0); + ReleaseIcon(ICON_FINISHED, 0); + ReleaseIcon(ICON_PRIVATE, 0); + ReleaseIcon(ICON_UNVERIFIED, 0); + hIconNotSecure = hIconFinished = hIconPrivate = hIconUnverified =0; + + UninitMirOTRMenu(); +} diff --git a/plugins/MirOTR/src/utils.cpp b/plugins/MirOTR/src/utils.cpp index d834fb84a1..91ad993928 100644 --- a/plugins/MirOTR/src/utils.cpp +++ b/plugins/MirOTR/src/utils.cpp @@ -1,382 +1,401 @@ -#include "stdafx.h" - -CRITICAL_SECTION lib_cs; - -void InitUtils() -{ - InitializeCriticalSection(&lib_cs); -} - -void DeinitUtils() -{ - DeleteCriticalSection(&lib_cs); -} - -void lib_cs_lock() -{ - EnterCriticalSection(&lib_cs); -} - -void lib_cs_unlock() -{ - LeaveCriticalSection(&lib_cs); -} - -MCONTACT find_contact(const char* userid, const char* protocol) -{ - for (MCONTACT hContact = db_find_first(); hContact; hContact = db_find_next(hContact)) { - const char *proto = GetContactProto(hContact); - if(proto && strcmp(proto, protocol) == 0) { - char *name = contact_get_id(hContact); - if(name && strcmp(name, userid) == 0) { - mir_free(name); - return hContact; - } - mir_free(name); - } - } - - return 0; -} - -/* Look up a connection context by hContact from the given -* OtrlUserState. If add_if_missing is true, allocate and return a new -* context if one does not currently exist. In that event, call -* add_app_data(data, context) so that app_data and app_data_free can be -* filled in by the application, and set *addedp to 1. */ -ConnContext * otrl_context_find_miranda(OtrlUserState us, MCONTACT hContact) -{ - ConnContext ** curp; - if (!hContact) return NULL; - for (curp = &(us->context_root); *curp; curp = &((*curp)->next)) { - if ((*curp)->app_data == (void*)hContact) - return *curp; - } - return NULL; -} - -/* What level of trust do we have in the privacy of this ConnContext? */ -TrustLevel otr_context_get_trust(ConnContext *context) -{ - TrustLevel level = TRUST_NOT_PRIVATE; - - if (context && context->msgstate == OTRL_MSGSTATE_ENCRYPTED) { - if (context->active_fingerprint->trust && - context->active_fingerprint->trust[0] != '\0') { - level = TRUST_PRIVATE; - } else { - level = TRUST_UNVERIFIED; - } - } else if (context && context->msgstate == OTRL_MSGSTATE_FINISHED) { - level = TRUST_FINISHED; - } - - 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) { - MCONTACT hContact = (MCONTACT)context->app_data; - TCHAR msg[1024]; - - mir_sntprintf(msg, SIZEOF(msg), (verify)?TranslateT(LANG_FINGERPRINT_VERIFIED):TranslateT(LANG_FINGERPRINT_NOT_VERIFIED), contact_get_nameT(hContact)); - ShowMessage(hContact, msg); - SetEncryptionStatus(hContact, 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]) -{ - int word, byte; - TCHAR *p = human; - - for(word=0; word<5; ++word) { - for(byte=0; byte<4; ++byte) { - _stprintf(p, _T("%02X"), hash[word*4+byte]); //!!!!!!!!!!!!!! - p += 2; - } - *(p++) = ' '; - } - /* Change that last ' ' to a '\0' */ - --p; - *p = '\0'; -} - -char* contact_get_id(MCONTACT hContact, bool bNameOnError) { - char* pszUniqueID = NULL; - CONTACTINFO ci; - memset(&ci, 0, sizeof(ci)); - ci.cbSize = sizeof(ci); - ci.hContact = hContact; - ci.dwFlag = CNF_UNIQUEID; - - if (CallService(MS_CONTACT_GETCONTACTINFO, 0, (LPARAM)&ci) == 0) - { - if (ci.type == CNFT_ASCIIZ) { - pszUniqueID = (char*)ci.pszVal; // MS_CONTACT_GETCONTACTINFO uses mir_alloc - } else if (ci.type == CNFT_DWORD) { - pszUniqueID = (char*)mir_alloc(15); - if (pszUniqueID) - mir_snprintf(pszUniqueID, 15, ("%u"), ci.dVal); - } else if (ci.type == CNFT_WORD) { - pszUniqueID = (char*)mir_alloc(15); - if (pszUniqueID) - mir_snprintf(pszUniqueID, 15, ("%u"), ci.wVal); - } else if (ci.type == CNFT_BYTE) { - pszUniqueID = (char*)mir_alloc(15); - if (pszUniqueID) - mir_snprintf(pszUniqueID, 15, ("%u"), ci.bVal); - } - } - if (!pszUniqueID && bNameOnError) { - char *name = (char *)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, hContact, 0); - if (name) pszUniqueID = mir_strdup(name); - } - return pszUniqueID; -} - -__inline const TCHAR* contact_get_nameT(MCONTACT hContact) { - return (TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, hContact, GCDNF_TCHAR); -} - - -__inline const char* contact_get_account(MCONTACT hContact) { - char *uacc = (char *)CallService(MS_PROTO_GETCONTACTBASEACCOUNT, hContact, 0); - return uacc; -} - -void ShowPopup(const TCHAR* line1, const TCHAR* line2, int timeout, const MCONTACT hContact) { - if(CallService(MS_SYSTEM_TERMINATED, 0, 0)) return; - - if ( !options.bHavePopups) { - TCHAR title[256]; - mir_sntprintf(title, SIZEOF(title), _T("%s Message"), _T(MODULENAME)); - - if(line1 && line2) { - int size = int(_tcslen(line1) + _tcslen(line2) + 3); - TCHAR *message = new TCHAR[size]; // newline and null terminator - mir_sntprintf(message, size, _T("%s\r\n%s"), line1, line2); - MessageBox( NULL, message, title, MB_OK | MB_ICONINFORMATION ); - delete[] message; - } else if(line1) { - MessageBox( NULL, line1, title, MB_OK | MB_ICONINFORMATION ); - } else if(line2) { - MessageBox( NULL, line2, title, MB_OK | MB_ICONINFORMATION ); - } - return; - } - - POPUPDATAT ppd = {0}; - //memset((void *)&ppd, 0, sizeof(POPUPDATAT)); - - ppd.lchContact = hContact; - ppd.lchIcon = NULL; - - if(line1 && line2) { - _tcsncpy( ppd.lptzContactName, line1, MAX_CONTACTNAME-1 ); - _tcsncpy( ppd.lptzText, line2, MAX_SECONDLINE-1 ); - } else if(line1) - _tcsncpy( ppd.lptzText, line1, MAX_SECONDLINE-1 ); - else if(line2) - _tcsncpy( ppd.lptzText, line2, MAX_SECONDLINE-1 ); - - ppd.iSeconds = timeout; - - ppd.PluginWindowProc = NULL; - ppd.PluginData = NULL; - - PUAddPopupT(&ppd); - -} - -void ShowWarning(TCHAR *msg) { - TCHAR buffer[512]; - ErrorDisplay disp = options.err_method; - // funny logic :) ... try to avoid message boxes - // if want baloons but no balloons, try popups - // if want popups but no popups, try baloons - // if, after that, you want balloons but no balloons, revert to message boxes - if(disp == ED_BAL && !ServiceExists(MS_CLIST_SYSTRAY_NOTIFY)) disp = ED_POP; - if(disp == ED_POP && !options.bHavePopups) disp = ED_BAL; - if(disp == ED_BAL && !ServiceExists(MS_CLIST_SYSTRAY_NOTIFY)) disp = ED_MB; - - mir_sntprintf(buffer, SIZEOF(buffer), _T("%s Warning"), _T(MODULENAME)); - - TCHAR *message; - switch(disp) { - case ED_POP: - { - int size = int(_tcslen(msg) + 515); - message = new TCHAR[size]; // newline and null terminator - mir_sntprintf(message, size, _T("%s\r\n%s"), buffer, msg); - PUShowMessageT(message, SM_WARNING); - delete message; - } - break; - case ED_MB: - MessageBox(0, msg, buffer, MB_OK | MB_ICONWARNING); - break; - case ED_BAL: - { - MIRANDASYSTRAYNOTIFY sn = {0}; - sn.cbSize = sizeof(sn); - sn.szProto= MODULENAME; - sn.tszInfoTitle = buffer; - sn.tszInfo = msg; - - sn.dwInfoFlags = NIIF_WARNING | NIIF_INTERN_UNICODE; - - sn.uTimeout = 10; - - CallService(MS_CLIST_SYSTRAY_NOTIFY, 0, (LPARAM)&sn); - } - - break; - } -} - -void ShowError(TCHAR *msg) { - TCHAR buffer[512]; - ErrorDisplay disp = options.err_method; - // funny logic :) ... try to avoid message boxes - // if want baloons but no balloons, try popups - // if want popups but no popups, try baloons - // if, after that, you want balloons but no balloons, revert to message boxes - if(disp == ED_BAL && !ServiceExists(MS_CLIST_SYSTRAY_NOTIFY)) disp = ED_POP; - if(disp == ED_POP && !options.bHavePopups) disp = ED_BAL; - if(disp == ED_BAL && !ServiceExists(MS_CLIST_SYSTRAY_NOTIFY)) disp = ED_MB; - - mir_sntprintf(buffer, SIZEOF(buffer), _T("%s Error"), _T(MODULENAME)); - - - TCHAR *message; - switch(disp) { - case ED_POP: - { - int size = int(_tcslen(msg) + 515); - message = new TCHAR[size]; // newline and null terminator - mir_sntprintf(message, size, _T("%s\r\n%s"), buffer, msg); - PUShowMessageT(message, SM_WARNING); - delete message; - } - break; - case ED_MB: - MessageBox(0, msg, buffer, MB_OK | MB_ICONERROR); - break; - case ED_BAL: - { - MIRANDASYSTRAYNOTIFY sn = {0}; - sn.cbSize = sizeof(sn); - sn.szProto = MODULENAME; - sn.tszInfoTitle = buffer; - sn.tszInfo = msg; - - sn.dwInfoFlags = NIIF_ERROR | NIIF_INTERN_UNICODE; - - sn.uTimeout = 10; - - CallService(MS_CLIST_SYSTRAY_NOTIFY, 0, (LPARAM)&sn); - } - - break; - } -} - - -void ShowPopupUtf(const char* line1, const char* line2, int timeout, const MCONTACT hContact) { - TCHAR* l1 = (line1) ? mir_utf8decodeT(line1) : NULL; - TCHAR* l2 = (line2) ? mir_utf8decodeT(line2) : NULL; - ShowPopup(l1, l2, timeout, hContact); - if (l1) mir_free(l1); - if (l2) mir_free(l2); -} - -void ShowWarningUtf(char* msg) { - TCHAR* m = (msg) ? mir_utf8decodeT(msg) : NULL; - ShowWarning(m); - if (m) mir_free(m); -} -void ShowErrorUtf(char* msg) { - TCHAR* m = (msg) ? mir_utf8decodeT(msg) : NULL; - ShowError(m); - if (m) mir_free(m); -} - -void ShowMessageInline(const MCONTACT hContact, const TCHAR *msg) { - TCHAR buff[1024]; - mir_sntprintf(buff, SIZEOF(buff), _T("%s%s"), TranslateT(LANG_INLINE_PREFIX), msg); - - PROTORECVEVENT pre = {0}; - pre.timestamp = time(0); - char *utf = mir_utf8encodeT(buff); - pre.szMessage = utf; - pre.flags = PREF_UTF|PREF_BYPASS_OTR; - ProtoChainRecvMsg(hContact, &pre); - - mir_free(utf); -} - -void ShowMessageInlineUtf(const MCONTACT hContact, const char *msg) { - char buff[1024]; - mir_snprintf(buff, SIZEOF(buff), "%s%s", Translate(LANG_INLINE_PREFIX), msg); - - PROTORECVEVENT pre = {0}; - pre.timestamp = time(0); - pre.szMessage = buff; - pre.flags = PREF_UTF|PREF_BYPASS_OTR; - ProtoChainRecvMsg(hContact, &pre); -} - -void ShowMessageUtf(const MCONTACT hContact, const char *msg) { - if(options.msg_inline) - ShowMessageInlineUtf(hContact, msg); - if(options.msg_popup) - ShowPopupUtf(Translate(LANG_OTR_INFO), msg, 0, hContact); -} - -void ShowMessage(const MCONTACT hContact, const TCHAR *msg) { - if(options.msg_inline) - ShowMessageInline(hContact, msg); - if(options.msg_popup) - ShowPopup(TranslateT(LANG_OTR_INFO), msg, 0, hContact); -} - -const TCHAR *policy_to_string(OtrlPolicy policy) { - switch (policy) { - case OTRL_POLICY_NEVER: - return TranslateT(LANG_POLICY_NEVER); - break; - case OTRL_POLICY_OPPORTUNISTIC: - return TranslateT(LANG_POLICY_OPP); - break; - case OTRL_POLICY_MANUAL: - case OTRL_POLICY_MANUAL_MOD: - return TranslateT(LANG_POLICY_MANUAL); - break; - case OTRL_POLICY_ALWAYS: - return TranslateT(LANG_POLICY_ALWAYS); - break; - } - return TranslateT(LANG_POLICY_DEFAULT); -} - -OtrlPolicy policy_from_string(const TCHAR *polstring) { - if (_tcscmp(polstring, TranslateT(LANG_POLICY_NEVER)) == 0) - return OTRL_POLICY_NEVER; - else if (_tcscmp(polstring, TranslateT(LANG_POLICY_OPP)) == 0) - return OTRL_POLICY_OPPORTUNISTIC; - else if (_tcscmp(polstring, TranslateT(LANG_POLICY_MANUAL)) == 0) - return OTRL_POLICY_MANUAL_MOD; - else if (_tcscmp(polstring, TranslateT(LANG_POLICY_ALWAYS)) == 0) - return OTRL_POLICY_ALWAYS; - else - return CONTACT_DEFAULT_POLICY; -} \ No newline at end of file +#include "stdafx.h" + +CRITICAL_SECTION lib_cs; + +void InitUtils() +{ + InitializeCriticalSection(&lib_cs); +} + +void DeinitUtils() +{ + DeleteCriticalSection(&lib_cs); +} + +void lib_cs_lock() +{ + EnterCriticalSection(&lib_cs); +} + +void lib_cs_unlock() +{ + LeaveCriticalSection(&lib_cs); +} + +MCONTACT find_contact(const char* userid, const char* protocol) +{ + for (MCONTACT hContact = db_find_first(); hContact; hContact = db_find_next(hContact)) { + const char *proto = GetContactProto(hContact); + if(proto && strcmp(proto, protocol) == 0) { + char *name = contact_get_id(hContact); + if(name && strcmp(name, userid) == 0) { + mir_free(name); + return hContact; + } + mir_free(name); + } + } + + return 0; +} + +/* Look up a connection context by hContact from the given +* OtrlUserState. If add_if_missing is true, allocate and return a new +* context if one does not currently exist. In that event, call +* add_app_data(data, context) so that app_data and app_data_free can be +* filled in by the application, and set *addedp to 1. */ +ConnContext * otrl_context_find_miranda(OtrlUserState us, MCONTACT hContact) +{ + const char *proto = GetContactProto(hContact); + char *username = contact_get_id(hContact); + ConnContext* ret = otrl_context_find(us, username, proto, proto, OTRL_INSTAG_BEST, 0, NULL, NULL, NULL); + mir_free(username); + return ret; +} + +/* What level of trust do we have in the privacy of this ConnContext? */ +TrustLevel otr_context_get_trust(ConnContext *context) +{ + TrustLevel level = TRUST_NOT_PRIVATE; + + if (context && context->msgstate == OTRL_MSGSTATE_ENCRYPTED) { + if (context->active_fingerprint->trust && context->active_fingerprint->trust[0]) { + level = TRUST_PRIVATE; + } else { + level = TRUST_UNVERIFIED; + } + } else if (context && context->msgstate == OTRL_MSGSTATE_FINISHED) { + level = TRUST_FINISHED; + } + + 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) { + MCONTACT hContact = (MCONTACT)context->app_data; + TCHAR msg[1024]; + + mir_sntprintf(msg, SIZEOF(msg), (verify)?TranslateT(LANG_FINGERPRINT_VERIFIED):TranslateT(LANG_FINGERPRINT_NOT_VERIFIED), contact_get_nameT(hContact)); + ShowMessage(hContact, msg); + SetEncryptionStatus(hContact, 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]) +{ + int word, byte; + TCHAR *p = human; + + for(word=0; word<5; ++word) { + for(byte=0; byte<4; ++byte) { + _stprintf(p, _T("%02X"), hash[word*4+byte]); //!!!!!!!!!!!!!! + p += 2; + } + *(p++) = ' '; + } + /* Change that last ' ' to a '\0' */ + --p; + *p = '\0'; +} + +char* contact_get_id(MCONTACT hContact, bool bNameOnError) { + char* pszUniqueID = NULL; + CONTACTINFO ci; + memset(&ci, 0, sizeof(ci)); + ci.cbSize = sizeof(ci); + ci.hContact = hContact; + ci.dwFlag = CNF_UNIQUEID; + + if (CallService(MS_CONTACT_GETCONTACTINFO, 0, (LPARAM)&ci) == 0) + { + if (ci.type == CNFT_ASCIIZ) { + pszUniqueID = (char*)ci.pszVal; // MS_CONTACT_GETCONTACTINFO uses mir_alloc + } else if (ci.type == CNFT_DWORD) { + pszUniqueID = (char*)mir_alloc(15); + if (pszUniqueID) + mir_snprintf(pszUniqueID, 15, ("%u"), ci.dVal); + } else if (ci.type == CNFT_WORD) { + pszUniqueID = (char*)mir_alloc(15); + if (pszUniqueID) + mir_snprintf(pszUniqueID, 15, ("%u"), ci.wVal); + } else if (ci.type == CNFT_BYTE) { + pszUniqueID = (char*)mir_alloc(15); + if (pszUniqueID) + mir_snprintf(pszUniqueID, 15, ("%u"), ci.bVal); + } + } + if (!pszUniqueID && bNameOnError) { + char *name = (char *)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, hContact, 0); + if (name) pszUniqueID = mir_strdup(name); + } + return pszUniqueID; +} + +__inline const TCHAR* contact_get_nameT(MCONTACT hContact) { + return (TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, hContact, GCDNF_TCHAR); +} + + +__inline const char* contact_get_account(MCONTACT hContact) { + char *uacc = (char *)CallService(MS_PROTO_GETCONTACTBASEACCOUNT, hContact, 0); + return uacc; +} + +TCHAR* ProtoGetNickname(const char* proto) +{ + CONTACTINFO ci = {sizeof(ci)}; + ci.dwFlag = CNF_TCHAR | CNF_NICK; + ci.szProto = (char*)proto; + if (!CallService(MS_CONTACT_GETCONTACTINFO, 0, (LPARAM)&ci)) { + switch (ci.type) { + case CNFT_ASCIIZ: + return ci.pszVal; + case CNFT_DWORD: + mir_free(ci.pszVal); + ci.pszVal=(TCHAR*)mir_alloc(12*sizeof(TCHAR)); // long can only have up to 11 characters (unsigned = 10) + if(ci.pszVal) + _ltot(ci.dVal, ci.pszVal, 10); + return ci.pszVal; + default: + mir_free(ci.pszVal); + } + } + return mir_tstrdup(TranslateT("'(Unknown contact)'")); +} + +void ShowPopup(const TCHAR* line1, const TCHAR* line2, int timeout, const MCONTACT hContact) { + if(CallService(MS_SYSTEM_TERMINATED, 0, 0)) return; + + if ( !options.bHavePopups) { + TCHAR title[256]; + mir_sntprintf(title, SIZEOF(title), _T("%s Message"), _T(MODULENAME)); + + if(line1 && line2) { + int size = int(_tcslen(line1) + _tcslen(line2) + 3); + TCHAR *message = new TCHAR[size]; // newline and null terminator + mir_sntprintf(message, size, _T("%s\r\n%s"), line1, line2); + MessageBox( NULL, message, title, MB_OK | MB_ICONINFORMATION ); + delete[] message; + } else if(line1) { + MessageBox( NULL, line1, title, MB_OK | MB_ICONINFORMATION ); + } else if(line2) { + MessageBox( NULL, line2, title, MB_OK | MB_ICONINFORMATION ); + } + return; + } + + POPUPDATAT ppd = {0}; + //memset((void *)&ppd, 0, sizeof(POPUPDATAT)); + + ppd.lchContact = hContact; + ppd.lchIcon = NULL; + + if(line1 && line2) { + _tcsncpy( ppd.lptzContactName, line1, MAX_CONTACTNAME-1 ); + _tcsncpy( ppd.lptzText, line2, MAX_SECONDLINE-1 ); + } else if(line1) + _tcsncpy( ppd.lptzText, line1, MAX_SECONDLINE-1 ); + else if(line2) + _tcsncpy( ppd.lptzText, line2, MAX_SECONDLINE-1 ); + + ppd.iSeconds = timeout; + + ppd.PluginWindowProc = NULL; + ppd.PluginData = NULL; + + PUAddPopupT(&ppd); + +} + +void ShowWarning(TCHAR *msg) { + TCHAR buffer[512]; + ErrorDisplay disp = options.err_method; + // funny logic :) ... try to avoid message boxes + // if want baloons but no balloons, try popups + // if want popups but no popups, try baloons + // if, after that, you want balloons but no balloons, revert to message boxes + if(disp == ED_BAL && !ServiceExists(MS_CLIST_SYSTRAY_NOTIFY)) disp = ED_POP; + if(disp == ED_POP && !options.bHavePopups) disp = ED_BAL; + if(disp == ED_BAL && !ServiceExists(MS_CLIST_SYSTRAY_NOTIFY)) disp = ED_MB; + + mir_sntprintf(buffer, SIZEOF(buffer), _T("%s Warning"), _T(MODULENAME)); + + TCHAR *message; + switch(disp) { + case ED_POP: + { + int size = int(_tcslen(msg) + 515); + message = new TCHAR[size]; // newline and null terminator + mir_sntprintf(message, size, _T("%s\r\n%s"), buffer, msg); + PUShowMessageT(message, SM_WARNING); + delete message; + } + break; + case ED_MB: + MessageBox(0, msg, buffer, MB_OK | MB_ICONWARNING); + break; + case ED_BAL: + { + MIRANDASYSTRAYNOTIFY sn = {0}; + sn.cbSize = sizeof(sn); + sn.szProto= MODULENAME; + sn.tszInfoTitle = buffer; + sn.tszInfo = msg; + + sn.dwInfoFlags = NIIF_WARNING | NIIF_INTERN_UNICODE; + + sn.uTimeout = 10; + + CallService(MS_CLIST_SYSTRAY_NOTIFY, 0, (LPARAM)&sn); + } + + break; + } +} + +void ShowError(TCHAR *msg) { + TCHAR buffer[512]; + ErrorDisplay disp = options.err_method; + // funny logic :) ... try to avoid message boxes + // if want baloons but no balloons, try popups + // if want popups but no popups, try baloons + // if, after that, you want balloons but no balloons, revert to message boxes + if(disp == ED_BAL && !ServiceExists(MS_CLIST_SYSTRAY_NOTIFY)) disp = ED_POP; + if(disp == ED_POP && !options.bHavePopups) disp = ED_BAL; + if(disp == ED_BAL && !ServiceExists(MS_CLIST_SYSTRAY_NOTIFY)) disp = ED_MB; + + mir_sntprintf(buffer, SIZEOF(buffer), _T("%s Error"), _T(MODULENAME)); + + + TCHAR *message; + switch(disp) { + case ED_POP: + { + int size = int(_tcslen(msg) + 515); + message = new TCHAR[size]; // newline and null terminator + mir_sntprintf(message, size, _T("%s\r\n%s"), buffer, msg); + PUShowMessageT(message, SM_WARNING); + delete message; + } + break; + case ED_MB: + MessageBox(0, msg, buffer, MB_OK | MB_ICONERROR); + break; + case ED_BAL: + { + MIRANDASYSTRAYNOTIFY sn = {0}; + sn.cbSize = sizeof(sn); + sn.szProto = MODULENAME; + sn.tszInfoTitle = buffer; + sn.tszInfo = msg; + + sn.dwInfoFlags = NIIF_ERROR | NIIF_INTERN_UNICODE; + + sn.uTimeout = 10; + + CallService(MS_CLIST_SYSTRAY_NOTIFY, 0, (LPARAM)&sn); + } + + break; + } +} + + +void ShowPopupUtf(const char* line1, const char* line2, int timeout, const MCONTACT hContact) { + TCHAR* l1 = (line1) ? mir_utf8decodeT(line1) : NULL; + TCHAR* l2 = (line2) ? mir_utf8decodeT(line2) : NULL; + ShowPopup(l1, l2, timeout, hContact); + if (l1) mir_free(l1); + if (l2) mir_free(l2); +} + +void ShowWarningUtf(char* msg) { + TCHAR* m = (msg) ? mir_utf8decodeT(msg) : NULL; + ShowWarning(m); + if (m) mir_free(m); +} +void ShowErrorUtf(char* msg) { + TCHAR* m = (msg) ? mir_utf8decodeT(msg) : NULL; + ShowError(m); + if (m) mir_free(m); +} + +void ShowMessageInline(const MCONTACT hContact, const TCHAR *msg) { + TCHAR buff[1024]; + mir_sntprintf(buff, SIZEOF(buff), _T("%s%s"), TranslateT(LANG_INLINE_PREFIX), msg); + + PROTORECVEVENT pre = {0}; + pre.timestamp = time(0); + char *utf = mir_utf8encodeT(buff); + pre.szMessage = utf; + pre.flags = PREF_UTF|PREF_BYPASS_OTR; + ProtoChainRecvMsg(hContact, &pre); + + mir_free(utf); +} + +void ShowMessageInlineUtf(const MCONTACT hContact, const char *msg) { + char buff[1024]; + mir_snprintf(buff, SIZEOF(buff), "%s%s", Translate(LANG_INLINE_PREFIX), msg); + + PROTORECVEVENT pre = {0}; + pre.timestamp = time(0); + pre.szMessage = buff; + pre.flags = PREF_UTF|PREF_BYPASS_OTR; + ProtoChainRecvMsg(hContact, &pre); +} + +void ShowMessageUtf(const MCONTACT hContact, const char *msg) { + if(options.msg_inline) + ShowMessageInlineUtf(hContact, msg); + if(options.msg_popup) + ShowPopupUtf(Translate(LANG_OTR_INFO), msg, 0, hContact); +} + +void ShowMessage(const MCONTACT hContact, const TCHAR *msg) { + if(options.msg_inline) + ShowMessageInline(hContact, msg); + if(options.msg_popup) + ShowPopup(TranslateT(LANG_OTR_INFO), msg, 0, hContact); +} + +const TCHAR *policy_to_string(OtrlPolicy policy) { + switch (policy) { + case OTRL_POLICY_NEVER: + return TranslateT(LANG_POLICY_NEVER); + break; + case OTRL_POLICY_OPPORTUNISTIC: + return TranslateT(LANG_POLICY_OPP); + break; + case OTRL_POLICY_MANUAL: + case OTRL_POLICY_MANUAL_MOD: + return TranslateT(LANG_POLICY_MANUAL); + break; + case OTRL_POLICY_ALWAYS: + return TranslateT(LANG_POLICY_ALWAYS); + break; + } + return TranslateT(LANG_POLICY_DEFAULT); +} + +OtrlPolicy policy_from_string(const TCHAR *polstring) { + if (_tcscmp(polstring, TranslateT(LANG_POLICY_NEVER)) == 0) + return OTRL_POLICY_NEVER; + else if (_tcscmp(polstring, TranslateT(LANG_POLICY_OPP)) == 0) + return OTRL_POLICY_OPPORTUNISTIC; + else if (_tcscmp(polstring, TranslateT(LANG_POLICY_MANUAL)) == 0) + return OTRL_POLICY_MANUAL_MOD; + else if (_tcscmp(polstring, TranslateT(LANG_POLICY_ALWAYS)) == 0) + return OTRL_POLICY_ALWAYS; + else + return CONTACT_DEFAULT_POLICY; +} diff --git a/plugins/MirOTR/src/utils.h b/plugins/MirOTR/src/utils.h index 71890a77eb..1b34c34eb5 100644 --- a/plugins/MirOTR/src/utils.h +++ b/plugins/MirOTR/src/utils.h @@ -1,48 +1,50 @@ -#pragma once -#ifndef __HEADER_UTILS_H -#define __HEADER_UTILS_H -#include "stdafx.h" - - -void lib_cs_lock(); -void lib_cs_unlock(); - -MCONTACT find_contact(const char* userid, const char* protocol); -ConnContext * otrl_context_find_miranda(OtrlUserState us, MCONTACT hContact); - -typedef enum { - TRUST_NOT_PRIVATE, - TRUST_FINISHED, - TRUST_UNVERIFIED, - 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]); - -char* contact_get_id(MCONTACT hContact, bool bNameOnError=true); -__inline const char* contact_get_account(MCONTACT hContact); -extern __inline const TCHAR* contact_get_nameT(MCONTACT hContact); - -void ShowPopup(const TCHAR* line1, const TCHAR* line2, int timeout, const MCONTACT hContact = NULL); -void ShowWarning(TCHAR* msg); -void ShowError(TCHAR* msg); -void ShowPopupUtf(const char* line1, const char* line2, int timeout, const MCONTACT hContact = NULL); -void ShowWarningUtf(char* msg); -void ShowErrorUtf(char* msg); - -void ShowMessageInline(const MCONTACT hContact, const TCHAR *msg); -void ShowMessageInlineUtf(const MCONTACT hContact, const char *msg); - -void ShowMessage(const MCONTACT hContact, const TCHAR *msg); -void ShowMessageUtf(const MCONTACT hContact, const char *msg); - -void InitUtils(); -void DeinitUtils(); - -const TCHAR *policy_to_string(OtrlPolicy policy); -OtrlPolicy policy_from_string(const TCHAR *polstring); - -#endif \ No newline at end of file +#pragma once +#ifndef __HEADER_UTILS_H +#define __HEADER_UTILS_H +#include "stdafx.h" + + +void lib_cs_lock(); +void lib_cs_unlock(); + +MCONTACT find_contact(const char* userid, const char* protocol); +ConnContext * otrl_context_find_miranda(OtrlUserState us, MCONTACT hContact); + +typedef enum { + TRUST_NOT_PRIVATE, + TRUST_FINISHED, + TRUST_UNVERIFIED, + 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]); + +char* contact_get_id(MCONTACT hContact, bool bNameOnError=true); +__inline const char* contact_get_account(MCONTACT hContact); +extern __inline const TCHAR* contact_get_nameT(MCONTACT hContact); + +TCHAR* ProtoGetNickname(const char* proto); + +void ShowPopup(const TCHAR* line1, const TCHAR* line2, int timeout, const MCONTACT hContact = NULL); +void ShowWarning(TCHAR* msg); +void ShowError(TCHAR* msg); +void ShowPopupUtf(const char* line1, const char* line2, int timeout, const MCONTACT hContact = NULL); +void ShowWarningUtf(char* msg); +void ShowErrorUtf(char* msg); + +void ShowMessageInline(const MCONTACT hContact, const TCHAR *msg); +void ShowMessageInlineUtf(const MCONTACT hContact, const char *msg); + +void ShowMessage(const MCONTACT hContact, const TCHAR *msg); +void ShowMessageUtf(const MCONTACT hContact, const char *msg); + +void InitUtils(); +void DeinitUtils(); + +const TCHAR *policy_to_string(OtrlPolicy policy); +OtrlPolicy policy_from_string(const TCHAR *polstring); + +#endif -- cgit v1.2.3