diff options
Diffstat (limited to 'MirOTR/svcs_proto.cpp')
-rw-r--r-- | MirOTR/svcs_proto.cpp | 370 |
1 files changed, 370 insertions, 0 deletions
diff --git a/MirOTR/svcs_proto.cpp b/MirOTR/svcs_proto.cpp new file mode 100644 index 0000000..b46b33f --- /dev/null +++ b/MirOTR/svcs_proto.cpp @@ -0,0 +1,370 @@ +#include "stdafx.h"
+#include "svcs_proto.h"
+
+//TODO: Social-Millionaire-Dialoge
+int 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 = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)ccs->hContact, 0);
+ if(proto && g_metaproto && strcmp(proto, g_metaproto) == 0) // bypass for metacontacts
+ return CallService(MS_PROTO_CHAINSEND, wParam, lParam);
+ char *username = contact_get_id(ccs->hContact); + if(!proto || !username) return 1; // error
+
+ gcry_error_t err;
+ char *newmessage = 0;
+ 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);
+ } 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);
+ }
+ + err = otrl_message_sending(otr_user_state, &ops, (void*)ccs->hContact, + proto, proto, username, oldmessage_utf, NULL, &newmessage, + add_appdata, (void*)ccs->hContact); + if (!(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)); + /* should not be needed + char t[3] = {0, 0, 0}; + if(ccs->wParam & PREF_UNICODE) { //TODO!! lstrlen(pre->szMessage)+1 ??
+ if (strlen(oldmessage)) memcpy(oldmessage, t,3 );
+ } else {
+ if (strlen(oldmessage)) memcpy(oldmessage, t, 1);
+ } + */ + 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 */ + ConnContext *context = otrl_context_find_miranda(otr_user_state, + (void*)ccs->hContact); + + // 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;
+ } + if (otr_context_get_trust(context) >= TRUST_UNVERIFIED) ccs->wParam; + int ret = CallService(MS_PROTO_CHAINSEND, wParam, lParam); +
+/*#ifdef _DEBUG
+ if(ccs->wParam & PREF_UNICODE)
+ MessageBox(0, (wchar_t *)ccs->lParam, _T("OTR - sending raw message"), MB_OK);
+ else
+ MessageBoxA(0, (char *)ccs->lParam, ("OTR - sending raw message"), MB_OK); +#endif*/ + + // reset to original values + ccs->lParam = (LPARAM)oldmessage; + ccs->wParam = oldflags; + otrl_message_free(newmessage); + return ret; + + }
+
+ return CallService(MS_PROTO_CHAINSEND, wParam, lParam);
+}
+
+int SVC_OTRSendMessageW(WPARAM wParam, LPARAM lParam){
+ if(!lParam) return 0;
+
+ CCSDATA *ccs = (CCSDATA *) lParam;
+ if (!(ccs->wParam & PREF_UTF)) ccs->wParam |= PREF_UNICODE;
+
+ return SVC_OTRSendMessage(wParam, lParam);
+}
+
+/*
+#define MESSAGE_PREFIX "(OTR) "
+#define MESSAGE_PREFIXW L"(OTR) "
+#define MESSAGE_PREFIX_LEN 6
+*/
+
+int SVC_OTRRecvMessage(WPARAM wParam,LPARAM lParam){
+ //PUShowMessage("OTR Recv Message", SM_NOTIFY);
+ CCSDATA *ccs = (CCSDATA *) lParam;
+ PROTORECVEVENT *pre = (PROTORECVEVENT *) ccs->lParam;
+
+#ifdef _DEBUG
+ if(pre->flags & PREF_UNICODE)
+ MessageBox(0, (wchar_t *)pre->szMessage, _T("OTR - receiving message"), MB_OK);
+ else
+ MessageBoxA(0, (char *)pre->szMessage, ("OTR - receiving message"), MB_OK);
+#endif
+
+ if (pre->flags & PREF_BYPASS_OTR) { // bypass for our inline messages
+ //TODO: check, whether this can be removed (then OTR status info should be still saved)
+ return CallService(MS_PROTO_CHAINRECV, wParam, lParam);
+ }
+
+ char *proto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)ccs->hContact, 0);
+ if(!proto)
+ return 1; //error
+ else if(proto && g_metaproto && strcmp(proto, g_metaproto) == 0) // bypass for metacontacts
+ return CallService(MS_PROTO_CHAINRECV, wParam, lParam);
+
+ char *uname = contact_get_id(ccs->hContact);
+ if(!uname) return 1; // error
+
+ 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; + OtrlTLV *tlv = NULL; + BOOL ignore_msg; + ConnContext *context; + //NextExpectedSMP nextMsg; + + lib_cs_lock(); + ignore_msg = otrl_message_receiving(otr_user_state, &ops, (void*)ccs->hContact, + proto, proto, uname, oldmessage_utf, + &newmessage, &tlvs, add_appdata, (void*)ccs->hContact); + lib_cs_unlock(); + + if( !(pre->flags & PREF_UTF)) mir_free(oldmessage_utf); + oldmessage_utf = NULL; + + + tlv = otrl_tlv_find(tlvs, OTRL_TLV_DISCONNECTED); + if (tlv) { + /* Notify the user that the other side disconnected. */ + TCHAR buff[256];
+ mir_sntprintf(buff, 256, TranslateT(LANG_SESSION_TERMINATED_BY_OTR), contact_get_nameT(ccs->hContact));
+ //MessageBox(0, buff, Translate("OTR Information"), MB_OK);
+ ShowMessage((HANDLE)ccs->hContact, buff);
+
+ //if(options.timeout_finished) ResetFinishedTimer(); + } + + lib_cs_lock(); + 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) { + 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); + 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) { + otrg_dialog_socialist_millionaires_q(context, + question); + } + } + } + tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP1); + if (tlv) { + if (nextMsg != OTRL_SMP_EXPECT1) + otr_abort_smp(context); + else { + otrg_dialog_socialist_millionaires(context); + } + } + tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP2); + if (tlv) { + if (nextMsg != OTRL_SMP_EXPECT2) + otr_abort_smp(context); + else { + otrg_dialog_update_smp(context, 0.6); + context->smstate->nextExpected = OTRL_SMP_EXPECT4; + } + } + tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP3); + if (tlv) { + if (nextMsg != OTRL_SMP_EXPECT3) + otr_abort_smp(context); + else { + otrg_dialog_update_smp(context, 1.0); + context->smstate->nextExpected = OTRL_SMP_EXPECT1; + } + } + tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP4); + if (tlv) { + if (nextMsg != OTRL_SMP_EXPECT4) + otr_abort_smp(context); + else { + otrg_dialog_update_smp(context, 1.0); + context->smstate->nextExpected = OTRL_SMP_EXPECT1; + } + } + tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP_ABORT); + if (tlv) { + otrg_dialog_update_smp(context, 0.0); + context->smstate->nextExpected = OTRL_SMP_EXPECT1; + } + } + } + */ + + otrl_tlv_free(tlvs); + + mir_free(uname); + + /* If we're supposed to ignore this incoming message (because it's a + * protocol message), set it to NULL, so that other plugins that + * catch receiving-im-msg don't return 0, and cause it to be + * displayed anyway. */ + if (ignore_msg) { + /* should not be required ;) + char t[3] = {0, 0, 0}; + if(pre->flags & PREF_UNICODE) { //TODO!! lstrlen(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!! lstrlen(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 (options.prefix_messages && (level == TRUST_PRIVATE || level == TRUST_UNVERIFIED)) { + DWORD len = (strlen(options.prefix)+strlen(newmessage)+1)*sizeof(char); + char* premsg = (char*)mir_alloc( len ); + memset(premsg, 0, len); + strcpy(premsg, options.prefix); + strcat(premsg, 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 |