From 4c78e956c61c76a3e93e289b112c1cd31eab0d18 Mon Sep 17 00:00:00 2001 From: Jay Threeth Date: Sat, 2 Apr 2011 10:18:40 -0700 Subject: checkpoint, non functional --- linden/indra/cmake/00-Common.cmake | 13 + linden/indra/cmake/Variables.cmake | 1 + linden/indra/newview/llappviewer.cpp | 12 + linden/indra/newview/llfirstuse.cpp | 28 +- linden/indra/newview/llfloaterpreference.cpp | 21 + linden/indra/newview/llimpanel.cpp | 972 ++++++++++++++++++++++++++- linden/indra/newview/llviewermessage.cpp | 125 ++++ linden/indra/newview/viewer_manifest.py | 17 + 8 files changed, 1186 insertions(+), 3 deletions(-) (limited to 'linden/indra') diff --git a/linden/indra/cmake/00-Common.cmake b/linden/indra/cmake/00-Common.cmake index 3120534..583e15e 100644 --- a/linden/indra/cmake/00-Common.cmake +++ b/linden/indra/cmake/00-Common.cmake @@ -66,6 +66,10 @@ if (WINDOWS) /MP ) + add_definitions( + /DUSE_OTR=1 + ) + if(MSVC80 OR MSVC90) set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -D_SECURE_STL=0 -D_HAS_ITERATOR_DEBUGGING=0" @@ -146,6 +150,10 @@ if (LINUX) -pthread ) + add_definitions( + -DUSE_OTR=1 + ) + if (SERVER) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ftemplate-depth-60") if (EXISTS /etc/debian_version) @@ -193,6 +201,11 @@ endif (LINUX) if (DARWIN) add_definitions(-DLL_DARWIN=1) + + add_definitions( + -DUSE_OTR=1 + ) + set(CMAKE_CXX_LINK_FLAGS "-Wl,-headerpad_max_install_names,-search_paths_first") set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_CXX_LINK_FLAGS}") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mlong-branch -msse3 -mssse3 -w") diff --git a/linden/indra/cmake/Variables.cmake b/linden/indra/cmake/Variables.cmake index 18f3cdd..65fe841 100644 --- a/linden/indra/cmake/Variables.cmake +++ b/linden/indra/cmake/Variables.cmake @@ -42,6 +42,7 @@ endif (EXISTS ${CMAKE_SOURCE_DIR}/Server.cmake) if (${CMAKE_SYSTEM_NAME} MATCHES "Windows") set(WINDOWS ON BOOL FORCE) + set(USE_OTR 0) set(ARCH i686) set(LL_ARCH ${ARCH}_win32) set(LL_ARCH_DIR ${ARCH}-win32) diff --git a/linden/indra/newview/llappviewer.cpp b/linden/indra/newview/llappviewer.cpp index 18b65cc..16ff418 100644 --- a/linden/indra/newview/llappviewer.cpp +++ b/linden/indra/newview/llappviewer.cpp @@ -206,6 +206,11 @@ //---------------------------------------------------------------------------- // viewer.cpp - these are only used in viewer, should be easily moved. + +#if USE_OTR // [$PLOTR$] +#include "otr_wrapper.h" +#endif // COMPILE_OTR // [/$PLOTR$] + extern void disable_win_error_reporting(); #if LL_DARWIN @@ -3779,6 +3784,10 @@ void LLAppViewer::idle() void LLAppViewer::idleShutdown() { +#if USE_OTR // [$PLOTR$] + OTR_Wrapper::logout(); +#endif // USE_OTR // [/$PLOTR$] + // Wait for all modal alerts to get resolved if (LLModalDialog::activeCount() > 0) { @@ -4354,4 +4363,7 @@ void LLAppViewer::handleLoginComplete() gRlvHandler.processRetainedCommands(); } // [/RLVa:KB] +#if USE_OTR // [$PLOTR$] + OTR_Wrapper::init(); +#endif // USE_OTR // [/$PLOTR$] } diff --git a/linden/indra/newview/llfirstuse.cpp b/linden/indra/newview/llfirstuse.cpp index bae1ff4..a377959 100644 --- a/linden/indra/newview/llfirstuse.cpp +++ b/linden/indra/newview/llfirstuse.cpp @@ -363,6 +363,32 @@ void LLFirstUse::ClientTags() } } +#if USE_OTR // [$PLOTR$] +void LLFirstUse::callbackEmeraldOTR(const LLSD ¬ification, const LLSD &response) +{ + gSavedSettings.setWarning("EmeraldOTR", FALSE); + + S32 option = LLNotification::getSelectedOption(notification, response); + + if ( option == 0 ) + { + gSavedSettings.setU32("EmeraldUseOTR",(U32)1); + } + else if ( option == 1 ) + { + gSavedSettings.setU32("EmeraldUseOTR",(U32)2); + } +} + +void LLFirstUse::EmeraldOTR() +{ + if(gSavedSettings.getWarning("EmeraldOTR")) + { + LLNotifications::instance().add("QueryEmeraldOTR", LLSD(),LLSD(), callbackEmeraldOTR); + } +} +#endif // USE_OTR // [/$PLOTR$] + // static void LLFirstUse::useLoginScreen() { @@ -417,4 +443,4 @@ void LLFirstUse::Privacy() { LLStartUp::setStartupState(STATE_PRIVACY_LECTURED); } -} \ No newline at end of file +} diff --git a/linden/indra/newview/llfloaterpreference.cpp b/linden/indra/newview/llfloaterpreference.cpp index 0f81be6..46e6104 100644 --- a/linden/indra/newview/llfloaterpreference.cpp +++ b/linden/indra/newview/llfloaterpreference.cpp @@ -79,6 +79,10 @@ #include "llscrollcontainer.h" #include "llfloaterhardwaresettings.h" +#if USE_OTR // [$PLOTR$] +#include "otr_wrapper.h" +#endif // USE_OTR // [/$PLOTR$] + const S32 PREF_BORDER = 4; const S32 PREF_PAD = 5; const S32 PREF_BUTTON_WIDTH = 70; @@ -422,6 +426,11 @@ LLFloaterPreference::~LLFloaterPreference() void LLFloaterPreference::apply() { this->mPreferenceCore->apply(); +#if USE_OTR // [$PLOTR$] + U32 otrpref = gSavedSettings.getU32("EmeraldUseOTR"); + // otrpref: 0 == Require OTR, 1 == Request OTR, 2 == Accept OTR, 3 == Decline OTR + if (3 == otrpref) OTR_Wrapper::stopAll(); +#endif // USE_OTR // [/$PLOTR$] } @@ -473,6 +482,13 @@ void LLFloaterPreference::onBtnOK( void* userdata ) if (fp->canClose()) { fp->apply(); + +#if USE_OTR // [$PLOTR$] + U32 otrpref = gSavedSettings.getU32("EmeraldUseOTR"); + // otrpref: 0 == Require OTR, 1 == Request OTR, 2 == Accept OTR, 3 == Decline OTR + if (3 == otrpref) OTR_Wrapper::stopAll(); +#endif // USE_OTR // [/$PLOTR$] + fp->close(false); gSavedSettings.saveToFile( gSavedSettings.getString("ClientSettingsFile"), TRUE ); @@ -504,6 +520,11 @@ void LLFloaterPreference::onBtnApply( void* userdata ) } } fp->apply(); +#if USE_OTR // [$PLOTR$] + U32 otrpref = gSavedSettings.getU32("EmeraldUseOTR"); + // otrpref: 0 == Require OTR, 1 == Request OTR, 2 == Accept OTR, 3 == Decline OTR + if (3 == otrpref) OTR_Wrapper::stopAll(); +#endif // USE_OTR // [/$PLOTR$] LLPanelLogin::refreshLocation( false ); } diff --git a/linden/indra/newview/llimpanel.cpp b/linden/indra/newview/llimpanel.cpp index cfe3996..3f531aa 100644 --- a/linden/indra/newview/llimpanel.cpp +++ b/linden/indra/newview/llimpanel.cpp @@ -83,6 +83,15 @@ #include "rlvhandler.h" // [/RLVa:KB] +#if USE_OTR // [$PLOTR$] +#include "context.h" +#include "llcombobox.h" +#include "otr_wrapper.h" +#include "otr_floater_smp_dialog.h" +#include "otr_floater_smp_progress.h" +#include "mfdKeywordFloater.h" +#endif // USE_OTR // [/$PLOTR$] + // // Constants // @@ -1107,6 +1116,10 @@ LLFloaterIMPanel::LLFloaterIMPanel( mCallBackEnabled(TRUE), mSpeakers(NULL), mSpeakerPanel(NULL), +#if USE_OTR // [$PLOTR$] + mOtrSmpDialog(NULL), + mOtrSmpProgress(NULL), +#endif // USE_OTR // [/$PLOTR$] mFirstKeystrokeTimer(), mLastKeystrokeTimer() { @@ -1140,6 +1153,10 @@ LLFloaterIMPanel::LLFloaterIMPanel( mCallBackEnabled(TRUE), mSpeakers(NULL), mSpeakerPanel(NULL), +#if USE_OTR // [$PLOTR$] + mOtrSmpDialog(NULL), + mOtrSmpProgress(NULL), +#endif // USE_OTR // [/$PLOTR$] mFirstKeystrokeTimer(), mLastKeystrokeTimer(), mIMPanelType(IM_PANEL_PLAIN) @@ -1319,6 +1336,11 @@ LLFloaterIMPanel::~LLFloaterIMPanel() { mInputEditor->setFocusLostCallback( NULL ); } + +#if USE_OTR // [$PLOTR$] + if (mOtrSmpDialog) delete mOtrSmpDialog; + if (mOtrSmpProgress) delete mOtrSmpProgress; +#endif // USE_OTR // [/$PLOTR$] } BOOL LLFloaterIMPanel::postBuild() @@ -1388,6 +1410,26 @@ BOOL LLFloaterIMPanel::postBuild() childSetCommitCallback("speaker_volume", onVolumeChange, this); } +#if USE_OTR // [$PLOTR$] + if (!gOTR) OTR_Wrapper::init(); + if (gOTR && (IM_NOTHING_SPECIAL == mDialog)) + { + LLComboBox *combo = getChild("otr_combo"); + if (!combo) + { + llwarns << "$PLOTR$ Can't find OTR control/status" << llendl; + } + else + { + llinfos << "$PLOTR$ found OTR control/status" << llendl; + combo->setCommitCallback(onClickOtr); + combo->setCallbackUserData(this); + combo->setAllowTextEntry(FALSE, 0, FALSE); + showOtrStatus(); + } + } +#endif // USE_OTR // [/$PLOTR$] + setDefaultBtn("send_btn"); return TRUE; } @@ -2112,6 +2154,786 @@ void deliver_message(const std::string& utf8_text, } } +#if USE_OTR // [$PLOTR$] +static bool g_otr_force_typing_stop = false; // ugly hack... +// sometimes we must send messages, but don't know if they are offline + +void otr_deliver_message(const std::string& utf8_text, + const LLUUID& im_session_id, + const LLUUID& other_participant_id, + EInstantMessage dialog) +{ +// llinfos +// << "$PLOTR$ message length:" << utf8_text.length() +// << " [" << utf8_text.substr(0, 24) +// << "]...[" << utf8_text.substr(utf8_text.length()-10, utf8_text.length()-1) +// << "]" << llendl; + std::string name; + gAgent.buildFullname(name); + + const LLRelationship* info = NULL; + info = LLAvatarTracker::instance().getBuddyInfo(other_participant_id); + + U8 offline = (!info || info->isOnline()) ? IM_ONLINE : IM_OFFLINE; + + // default to IM_SESSION_SEND unless it's nothing special - in + // which case it's probably an IM to everyone. + U8 new_dialog = dialog; + + if ( dialog != IM_NOTHING_SPECIAL ) + { + new_dialog = IM_SESSION_SEND; + } + if ((new_dialog == IM_NOTHING_SPECIAL) && + (g_otr_force_typing_stop || + (gSavedSettings.getBOOL("EmeraldOTRInTypingStop")))) + { + OtrlMessageType mtype = otrl_proto_message_type(utf8_text.c_str()); + switch (mtype) + { + case OTRL_MSGTYPE_UNKNOWN: + llwarns << "Sending unknown type of OTR message" << llendl; + // fall through + case OTRL_MSGTYPE_QUERY: + case OTRL_MSGTYPE_DH_COMMIT: + case OTRL_MSGTYPE_DH_KEY: + case OTRL_MSGTYPE_REVEALSIG: + case OTRL_MSGTYPE_SIGNATURE: + case OTRL_MSGTYPE_V1_KEYEXCH: + case OTRL_MSGTYPE_DATA: + case OTRL_MSGTYPE_TAGGEDPLAINTEXT: + new_dialog = IM_TYPING_STOP; + break; + case OTRL_MSGTYPE_NOTOTR: + case OTRL_MSGTYPE_ERROR: + default: + /* new_dialog = IM_NOTHING_SPECIAL */ ; + } + } + pack_instant_message( + gMessageSystem, + gAgent.getID(), + FALSE, + gAgent.getSessionID(), + other_participant_id, + name.c_str(), + utf8_text.c_str(), + offline, + (EInstantMessage)new_dialog, + im_session_id); + gAgent.sendReliableMessage(); + + // If there is a mute list and this is not a group chat... + if ( LLMuteList::getInstance() ) + { + // ... the target should not be in our mute list for some message types. + // Auto-remove them if present. + switch( dialog ) + { + case IM_NOTHING_SPECIAL: + case IM_GROUP_INVITATION: + case IM_INVENTORY_OFFERED: + case IM_SESSION_INVITE: + case IM_SESSION_P2P_INVITE: + case IM_SESSION_CONFERENCE_START: + case IM_SESSION_SEND: // This one is marginal - erring on the side of hearing. + case IM_LURE_USER: + case IM_GODLIKE_LURE_USER: + case IM_FRIENDSHIP_OFFERED: + LLMuteList::getInstance()->autoRemove(other_participant_id, LLMuteList::AR_IM); + break; + default: ; // do nothing + } + } +} + +// static +void LLFloaterIMPanel::onClickOtr(LLUICtrl* source, void* userdata) +{ + LLFloaterIMPanel* self = (LLFloaterIMPanel*) userdata; + if (self) + { + self->doOtrMenu(); + self->showOtrStatus(); + } + else + { + llwarns << "$PLOTR$ onClickOtr() can't find floater." << llendl; + } +} + +void LLFloaterIMPanel::doOtrStart() +{ + U32 otrpref = gSavedSettings.getU32("EmeraldUseOTR"); + // otrpref: 0 == Require use of OTR in IMs, 1 == Request OTR if available, 2 == Accept OTR requests, 3 == Decline use of OTR + if (3 == otrpref) + { + //otrLogMessageGetstring("otr_err_deacivated"); + showOtrStatus(); + return; + } + if (gOTR && (IM_NOTHING_SPECIAL == mDialog)) + { + llinfos << "$PLOTR$ otr menu start/restart/refresh" << llendl; + gcry_error_t err = 0; + char *newmessage = NULL; + char my_uuid[UUID_STR_SIZE]; + char their_uuid[UUID_STR_SIZE]; + gAgent.getID().toString(&(my_uuid[0])); + mOtherParticipantUUID.toString(&(their_uuid[0])); + + const LLRelationship* info = NULL; + info = LLAvatarTracker::instance().getBuddyInfo(mOtherParticipantUUID); + if (info && (!info->isOnline())) + { + otrLogMessageGetstringName("otr_err_offline_start"); + return; + } + + if (gOTR && (IM_NOTHING_SPECIAL == mDialog)) + { + // only try OTR for 1 on 1 IM's + err = otrl_message_sending( + gOTR->get_userstate(), + gOTR->get_uistate(), + &mSessionUUID, + my_uuid, + gOTR->get_protocolid(), + their_uuid, + "?OTRv2?", NULL, &newmessage, + NULL, NULL); + } + if (err) + { + llwarns << "$PLOTR$ OTR failed to encrypt start message" << llendl; + otrLogMessageGetstring("otr_err_failed_starting"); + return; + } + else if (newmessage) + { + // OTR encrypted the message. Handle fragmentation of the message + int context_added = 0; + ConnContext *context = getOtrContext(1, &context_added); + if (context_added) + { + llwarns << "$PLOTR$ context added *after* send start but before fragmentation." << llendl; + } + if (! context) + { + otrLogMessageGetstring("otr_err_failed_starting"); + llwarns << "$PLOTR$ can't find context, not sending start message." << llendl; + return; + } + else + { + char *extrafragment = NULL; + err = otrl_message_fragment_and_send( + gOTR->get_uistate(), + &mSessionUUID, + context, + newmessage, + OTRL_FRAGMENT_SEND_ALL, + &extrafragment); + } + if (newmessage) otrl_message_free(newmessage); + //otrLogMessageGetstringName("otr_prog_I_start"); + } + else + { + llwarns << "$PLOTR$ can't start OTR for some reason." << llendl; + otrLogMessageGetstring("otr_err_failed_starting"); + return; + } + } +} + +void LLFloaterIMPanel::doOtrStop(bool pretend_they_did) +{ + llinfos << "$PLOTR$ otr menu stop 1" << llendl; + // do not disable this bassed on gSavedSettings.getU32("EmeraldUseOTR"); + // when the user disables OTR we may still need to stop currently encrypted conversations + if (gOTR && (IM_NOTHING_SPECIAL == mDialog)) + { + char my_uuid[UUID_STR_SIZE]; + char their_uuid[UUID_STR_SIZE]; + gAgent.getID().toString(&(my_uuid[0])); + mOtherParticipantUUID.toString(&(their_uuid[0])); + llinfos << "$PLOTR$ otr menu stop 2 their_uuid:" << mOtherParticipantUUID << llendl; + g_otr_force_typing_stop = true; // ugly hack + otrl_message_disconnect( + gOTR->get_userstate(), + gOTR->get_uistate(), + &mSessionUUID, + my_uuid, + gOTR->get_protocolid(), + their_uuid); + g_otr_force_typing_stop = false; + if (pretend_they_did) + { + otrLogMessageGetstringName("otr_prog_they_stop"); + } + else + { + //otrLogMessageGetstringName("otr_prog_I_stop"); + } + showOtrStatus(); + } +} + +void LLFloaterIMPanel::doOtrAuth() +{ + if (mOtrSmpDialog) + { + llinfos << "$PLOTR$ mOtrSmpDialog SMP already in progress, ignoring request to start it" << llendl; + return; + } + if (mOtrSmpDialog || mOtrSmpProgress) + { + llinfos << "$PLOTR$ SMP already in progress, ignoring request to start it" << llendl; + // $TODO$ Tell the user nicely to cancel the one in progress. + // $TODO$ better yet, cancel it/them for the user + return; + } + if (gOTR && (IM_NOTHING_SPECIAL == mDialog)) + { + llinfos << "$PLOTR$ otr menu auth" << llendl; + + ConnContext *context = getOtrContext(); + if (!context) + { + llwarns << "$PLOTR$ doOtrAuth can't find context." << llendl; + return; + } + char my_uuid[UUID_STR_SIZE]; + gAgent.getID().toString(&(my_uuid[0])); + char my_fingerprint[45]; + otrl_privkey_fingerprint(gOTR->get_userstate(), + my_fingerprint, + my_uuid, + gOTR->get_protocolid()); + char other_fingerprint[45]; + otrl_privkey_hash_to_human(other_fingerprint, context->active_fingerprint->fingerprint); + startSmpDialog(mSessionUUID, mOtherParticipantUUID, + &(my_fingerprint[0]), &(other_fingerprint[0])); + } +} + +void LLFloaterIMPanel::doOtrMenu() +{ + if (gOTR && (IM_NOTHING_SPECIAL == mDialog)) + { + LLComboBox *combo = getChild("otr_combo"); + if (!combo) + { + llwarns << "$PLOTR$ Can't find OTR control/status" << llendl; + } + else + { + std::string choice = combo->getSimple(); + if ((getString("otr_start") == choice) || + (getString("otr_restart") == choice) || + (getString("otr_refresh") == choice)) + { + doOtrStart(); + } + else if (getString("otr_stop") == choice) + { + doOtrStop(); + } + else if (getString("otr_auth") == choice) + { + doOtrAuth(); + } + else if (getString("otr_help") == choice) + { + llinfos << "$PLOTR$ otr help" << llendl; + LLWeb::loadURL("http://www.cypherpunks.ca/otr/"); + } + else if (getString("otr_levels") == choice) + { + llinfos << "$PLOTR$ otr levels help" << llendl; + LLWeb::loadURL("http://www.cypherpunks.ca/otr/help/3.2.0/levels.php"); + } + else + { + llwarns << "$PLOTR$ unknown menu item" << llendl; + } + } + } +} + +ConnContext *LLFloaterIMPanel::getOtrContext(int create_if_not_found, int *context_added) +{ + ConnContext *context = NULL; + if (gOTR && (IM_NOTHING_SPECIAL == mDialog)) + { + char my_uuid[UUID_STR_SIZE]; + char their_uuid[UUID_STR_SIZE]; + gAgent.getID().toString(&(my_uuid[0])); + mOtherParticipantUUID.toString(&(their_uuid[0])); + context = otrl_context_find( + gOTR->get_userstate(), + their_uuid, + my_uuid, + gOTR->get_protocolid(), + create_if_not_found, context_added, NULL, NULL); + } + return context; +} + +bool LLFloaterIMPanel::otherIsOtrAuthenticated() +{ + if (gOTR && (IM_NOTHING_SPECIAL == mDialog)) + { + ConnContext *context = getOtrContext(); + if (context && context->active_fingerprint && + context->active_fingerprint->trust && + *(context->active_fingerprint->trust)) + { + llinfos << "$PLOTR$ they are authenticated -- trust level is " + << (context->active_fingerprint->trust) << llendl; + return true; + } + } + llinfos << "$PLOTR$ they are NOT authenticated" << llendl; + return false; +} + +void LLFloaterIMPanel::showOtrStatus() +{ + if (gOTR && (IM_NOTHING_SPECIAL == mDialog)) + { + LLComboBox *combo = getChild("otr_combo"); + if (!combo) + { + llwarns << "$PLOTR$ Can't find OTR control/status" << llendl; + } + else + { + ConnContext *context = getOtrContext(); + U32 otrpref = gSavedSettings.getU32("EmeraldUseOTR"); + // otrpref: 0 == Require OTR, 1 == Request OTR, 2 == Accept OTR, 3 == Decline OTR + if (3 == otrpref) + { + if (context && (OTRL_MSGSTATE_ENCRYPTED == context->msgstate)) + { + doOtrStop(); + } + combo->removeall(); + combo->add(getString("otr_start"), ADD_BOTTOM, TRUE); // to tell them where to turn it back on + combo->add(getString("otr_stop"), ADD_BOTTOM, FALSE); + combo->add(getString("otr_auth"), ADD_BOTTOM, FALSE); + combo->add(getString("otr_help"), ADD_BOTTOM, TRUE); + combo->add(getString("otr_levels"), ADD_BOTTOM, TRUE); + combo->setLabel(getString("otr_not_private")); + } + else if (context && (OTRL_MSGSTATE_ENCRYPTED == context->msgstate)) + { + combo->removeall(); + combo->add(getString("otr_refresh"), ADD_BOTTOM, TRUE); + combo->add(getString("otr_stop"), ADD_BOTTOM, TRUE); + combo->add(getString("otr_auth"), ADD_BOTTOM, TRUE); + combo->add(getString("otr_help"), ADD_BOTTOM, TRUE); + combo->add(getString("otr_levels"), ADD_BOTTOM, TRUE); + if (otherIsOtrAuthenticated()) + combo->setLabel(getString("otr_private")); + else + combo->setLabel(getString("otr_unverified")); + } + else if (context && (OTRL_MSGSTATE_FINISHED == context->msgstate)) + { + if (OTRL_MSGSTATE_ENCRYPTED == mOtrLastStatus) + { + if (otherIsOtrAuthenticated()) + otrLogMessageGetstringName("otr_prog_they_stop_private"); + else + otrLogMessageGetstringName("otr_prog_they_stop_unverified"); + } + combo->removeall(); + combo->add(getString("otr_restart"), ADD_BOTTOM, TRUE); + combo->add(getString("otr_stop"), ADD_BOTTOM, TRUE); + combo->add(getString("otr_auth"), ADD_BOTTOM, FALSE); + combo->add(getString("otr_help"), ADD_BOTTOM, TRUE); + combo->add(getString("otr_levels"), ADD_BOTTOM, TRUE); + combo->setLabel(getString("otr_finished")); + } + else // OTRL_MSGSTATE_PLAINTEXT, or no context yet + { + combo->removeall(); + combo->add(getString("otr_start"), ADD_BOTTOM, TRUE); + combo->add(getString("otr_stop"), ADD_BOTTOM, FALSE); + combo->add(getString("otr_auth"), ADD_BOTTOM, FALSE); + combo->add(getString("otr_help"), ADD_BOTTOM, TRUE); + combo->add(getString("otr_levels"), ADD_BOTTOM, TRUE); + combo->setLabel(getString("otr_not_private")); + } + if (context) + { + mOtrLastStatus = context->msgstate; + } + } + } +} + +void LLFloaterIMPanel::otrLogMessage(std::string message) +{ + addHistoryLine(message, gSavedSettings.getColor("SystemChatColor"), true, mOtherParticipantUUID); +} + +void LLFloaterIMPanel::otrLogMessageGetstring(const char *message_name) +{ + LLUIString msg = getString(message_name); + otrLogMessage(msg); +} + +void LLFloaterIMPanel::otrLogMessageGetstringName(const char *message_name) +{ + LLUIString msg = getString(message_name); + std::string them; + if (!gCacheName->getFullName(mOtherParticipantUUID, them)) them = getString("otr_generic_name"); + msg.setArg("[NAME]", them); + otrLogMessage(msg); +} + +void otr_log_message(LLUUID session_id, const char *message) +{ + LLFloaterIMPanel* floater = gIMMgr->findFloaterBySession(session_id); + if (floater) floater->otrLogMessage(message); + else + { + llinfos << "$PLOTR$ otr_log_message(" << message << ") failed to find floater." << llendl; + } +} + +void otr_log_message_getstring(LLUUID session_id, const char *message_name) +{ + LLFloaterIMPanel* floater = gIMMgr->findFloaterBySession(session_id); + if (floater) floater->otrLogMessageGetstring(message_name); + else + { + llinfos << "$PLOTR$ otr_log_message_getstring(" << message_name << ") failed to find floater." << llendl; + } +} + +void otr_log_message_getstring_name(LLUUID session_id, const char *message_name) +{ + LLFloaterIMPanel* floater = gIMMgr->findFloaterBySession(session_id); + if (floater) floater->otrLogMessageGetstringName(message_name); + else + { + llinfos << "$PLOTR$ otr_log_message_getstring_name(" << message_name << ") failed to find floater." << llendl; + } +} + +void LLFloaterIMPanel::otrAuthenticateKey(const char *trust) +{ + int context_added = 0; + ConnContext *context = getOtrContext(0, &context_added); + if (gOTR && context) + { + otrl_context_set_trust(context->active_fingerprint, trust); + otrLogMessageGetstringName("otr_log_authenticated"); + otrLogMessageGetstringName("otr_log_start_private"); + std::string pubpath = + gDirUtilp->getExpandedFilename( + LL_PATH_PER_SL_ACCOUNT, OTR_PUBLIC_KEYS_FILE); + otrl_privkey_write_fingerprints(gOTR->get_userstate(), pubpath.c_str()); + showOtrStatus(); + } +} + +void otr_authenticate_key(LLUUID session_id, const char *trust) +{ + LLFloaterIMPanel* floater = gIMMgr->findFloaterBySession(session_id); + if (floater) floater->otrAuthenticateKey(trust); + else + { + llinfos << "$PLOTR$ otr_authenticate_key(" << session_id << ", " << trust << ") failed to find floater." << llendl; + } +} + +void otr_show_status(LLUUID session_id) +{ + LLFloaterIMPanel* floater = gIMMgr->findFloaterBySession(session_id); + if (floater) floater->showOtrStatus(); + else + { + llinfos << "$PLOTR$ can't find floater." << llendl; + } +} + +void LLFloaterIMPanel::pretendTheyOtrStop() +{ + llinfos << "$PLOTR$ pretending they did doOtrStop()" << llendl; + // we really stop our end, but... + doOtrStop(true); // ... pretend that they did it + ConnContext *context = getOtrContext(); + if (context) context->msgstate = OTRL_MSGSTATE_FINISHED; + else + { + llwarns << "$PLOTR$ can't find context." << llendl; + } + showOtrStatus(); +} + +void LLFloaterIMPanel::startSmpDialog( + LLUUID session_id, LLUUID other_id, + std::string my_fingerprint, std::string other_fingerprint) +{ + if (mOtrSmpDialog) + { + mOtrSmpDialog->close(); + delete mOtrSmpDialog; + } + mOtrSmpDialog = new OtrFloaterSmpDialog( + this, mSessionUUID, mOtherParticipantUUID, + my_fingerprint, other_fingerprint); + if (mOtrSmpDialog) mOtrSmpDialog->show(); + else + { + llwarns << "$PLOTR$ couldn't new OtrFloaterSmpDialog" << llendl; + } +} + +void LLFloaterIMPanel::startSmpDialogQA( + LLUUID session_id, LLUUID other_id, std::string question, OtrlTLV *tlv) +{ + if (mOtrSmpDialog) + { + mOtrSmpDialog->close(); + delete mOtrSmpDialog; + } + mOtrSmpDialog = new OtrFloaterSmpDialog( + this, mSessionUUID, mOtherParticipantUUID, question, tlv); + if (mOtrSmpDialog) mOtrSmpDialog->show(); + else + { + llwarns << "$PLOTR$ couldn't new OtrFloaterSmpDialog" << llendl; + } +} + +void LLFloaterIMPanel::startSmpDialogSS( + LLUUID session_id, LLUUID other_id, OtrlTLV *tlv) +{ + if (mOtrSmpDialog) + { + mOtrSmpDialog->close(); + delete mOtrSmpDialog; + } + mOtrSmpDialog = new OtrFloaterSmpDialog( + this, mSessionUUID, mOtherParticipantUUID, tlv); + if (mOtrSmpProgress) mOtrSmpDialog->show(); + else + { + llwarns << "$PLOTR$ couldn't new OtrFloaterSmpDialog" << llendl; + } +} + +void LLFloaterIMPanel::endSmpDialog() +{ + if (!mOtrSmpDialog) + { + llwarns << "$PLOTR$ couldn't find OtrFloaterSmpDialog" << llendl; + } + else + { + delete mOtrSmpDialog; + mOtrSmpDialog = NULL; + } +} + +void LLFloaterIMPanel::startSmpProgress( + LLUUID session_id, LLUUID other_id, + std::string a_question, std::string a_secret_answer, bool is_reply) +{ + if (mOtrSmpProgress) + { + mOtrSmpProgress->close(); + delete mOtrSmpProgress; + } + mOtrSmpProgress = + new OtrFloaterSmpProgress(this, mSessionUUID, mOtherParticipantUUID, + a_question, a_secret_answer, is_reply); + if (mOtrSmpProgress) mOtrSmpProgress->show(); + else + { + llwarns << "$PLOTR$ couldn't new OtrFloaterSmpProgress" << llendl; + } +} + +void LLFloaterIMPanel::startSmpProgress( + LLUUID session_id, LLUUID other_id, + std::string a_secret, bool is_reply) +{ + if (mOtrSmpProgress) + { + mOtrSmpProgress->close(); + delete mOtrSmpProgress; + } + mOtrSmpProgress = + new OtrFloaterSmpProgress(this, mSessionUUID, mOtherParticipantUUID, + a_secret, is_reply); + if (mOtrSmpProgress) mOtrSmpProgress->show(); + else + { + llwarns << "$PLOTR$ couldn't new OtrFloaterSmpProgress" << llendl; + } +} + +void LLFloaterIMPanel::endSmpProgress() +{ + if (!mOtrSmpProgress) + { + llwarns << "$PLOTR$ couldn't find OtrFloaterSmpProgress" << llendl; + } + else + { + delete mOtrSmpProgress; + mOtrSmpProgress = NULL; + } +} + +void LLFloaterIMPanel::handleOtrTlvs(OtrlTLV *tlvs) +{ + ConnContext *context = getOtrContext(); + if (! context) + { + llwarns << "$PLOTR$ Can't find otr context" << llendl; + return; + } + if (! context->smstate) + { + llwarns << "$PLOTR$ OTR context doesn't have smstate" << llendl; + return; + } + if (context->smstate->sm_prog_state == OTRL_SMP_PROG_CHEATED) + { + if (mOtrSmpProgress) mOtrSmpProgress->setFinalStatus("otr_smp_prog_auth_errored"); + context->smstate->nextExpected = OTRL_SMP_EXPECT1; + context->smstate->sm_prog_state = OTRL_SMP_PROG_OK; + return; + } + NextExpectedSMP nextMsg = context->smstate->nextExpected; + OtrlTLV *tlv = NULL; + tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP1Q); + if (tlv) + { + if (nextMsg != OTRL_SMP_EXPECT1) + { + if (mOtrSmpProgress) mOtrSmpProgress->setFinalStatus("otr_smp_prog_auth_errored"); + return; + } + // Start a challenge SMP dialog + char *question = (char *)tlv->data; + char *eoq = (char *)memchr(question, '\0', tlv->len); + if (!eoq) + { + llwarns << "$PLOTR$ bad format in OTRL_TLV_SMP1Q, no end to question." << llendl; + if (mOtrSmpProgress) mOtrSmpProgress->setFinalStatus("otr_smp_prog_auth_errored"); + return; + } + startSmpDialogQA(mSessionUUID, mOtherParticipantUUID, question, tlv); + if (mOtrSmpProgress) mOtrSmpProgress->setPercent(25); + return; + } + tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP1); + if (tlv) + { + if (nextMsg != OTRL_SMP_EXPECT1) + { + if (mOtrSmpProgress) mOtrSmpProgress->setFinalStatus("otr_smp_prog_auth_errored"); + return; + } + // Start a challenge SMP dialog + startSmpDialogSS(mSessionUUID, mOtherParticipantUUID, tlv); + if (mOtrSmpProgress) mOtrSmpProgress->setPercent(25); + return; + } + tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP2); + if (tlv) + { + if (nextMsg != OTRL_SMP_EXPECT2) + { + if (mOtrSmpProgress) mOtrSmpProgress->setFinalStatus("otr_smp_prog_auth_errored"); + return; + } + else + { + // If we received TLV2, we will send TLV3 and expect TLV4 + context->smstate->nextExpected = OTRL_SMP_EXPECT4; + if (mOtrSmpProgress) mOtrSmpProgress->setPercent(75); + } + } + tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP3); + if (tlv) + { + if (nextMsg != OTRL_SMP_EXPECT3) + { + if (mOtrSmpProgress) mOtrSmpProgress->setFinalStatus("otr_smp_prog_auth_errored"); + return; + } + else + { + // If we received TLV3, we will send TLV4 + // We will not expect more messages, so prepare for next SMP + context->smstate->nextExpected = OTRL_SMP_EXPECT1; + // Report result to user + if (context->smstate->sm_prog_state == OTRL_SMP_PROG_SUCCEEDED) + { + if (context->active_fingerprint && + context->active_fingerprint->trust && + *(context->active_fingerprint->trust)) + { + // they authed me OK, and I already authed them in the past + if (mOtrSmpProgress) mOtrSmpProgress->setFinalStatus("otr_smp_prog_auth_ok"); + } + else + { + // they authed me OK, but I haven't authed them yet + if (mOtrSmpProgress) mOtrSmpProgress->setFinalStatus("otr_smp_prog_auth_ok_name_next"); + } + } + else + { + if (mOtrSmpProgress) mOtrSmpProgress->setFinalStatus("otr_smp_prog_auth_failed"); + } + } + } + tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP4); + if (tlv) + { + if (nextMsg != OTRL_SMP_EXPECT4) + { + if (mOtrSmpProgress) mOtrSmpProgress->setFinalStatus("otr_smp_prog_auth_errored"); + return; + } + else { + // We will not expect more messages, so prepare for next SMP + context->smstate->nextExpected = OTRL_SMP_EXPECT1; + // Report result to user + if (context->active_fingerprint && + context->active_fingerprint->trust && + *(context->active_fingerprint->trust)) + { + if (mOtrSmpProgress) mOtrSmpProgress->setFinalStatus("otr_smp_prog_auth_ok"); + } + else + { + if (mOtrSmpProgress) mOtrSmpProgress->setFinalStatus("otr_smp_prog_auth_failed"); + } + } + } + tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP_ABORT); + if (tlv) + { + // The message we are waiting for will not arrive, so reset + // and prepare for the next SMP + context->smstate->nextExpected = OTRL_SMP_EXPECT1; + if (mOtrSmpProgress) mOtrSmpProgress->setFinalStatus("otr_smp_prog_auth_aborted"); + } +} +#endif // USE_OTR // [/$PLOTR$] + void LLFloaterIMPanel::sendMsg() { if (!gAgent.isGodlike() @@ -2204,11 +3026,137 @@ void LLFloaterIMPanel::sendMsg() if ( mSessionInitialized ) { +#if USE_OTR // [$PLOTR$] + const LLRelationship* info = NULL; + info = LLAvatarTracker::instance().getBuddyInfo(mOtherParticipantUUID); + ConnContext *context = getOtrContext(1); + if (info && (!info->isOnline()) && context && + ( (OTRL_MSGSTATE_ENCRYPTED == context->msgstate) + || (OTRL_MSGSTATE_FINISHED == context->msgstate))) + { + // we can't continue this encrypted session but we + // can't let the user accidentally send unencrypted + if (OTRL_MSGSTATE_ENCRYPTED == context->msgstate) + pretendTheyOtrStop(); + otrLogMessageGetstringName("otr_err_offline_send"); + return; // leave the unsent message in the edit box + } + + gcry_error_t err = 0; + char *newmessage = NULL; + char my_uuid[UUID_STR_SIZE]; + char their_uuid[UUID_STR_SIZE]; + gAgent.getID().toString(&(my_uuid[0])); + mOtherParticipantUUID.toString(&(their_uuid[0])); + + bool was_finished = false; + if (gOTR && context && (context->msgstate == OTRL_MSGSTATE_FINISHED)) + { + was_finished = true; + } + else if (gOTR && (IM_NOTHING_SPECIAL == mDialog)) + { + // only try OTR for 1 on 1 IM's + err = otrl_message_sending( + gOTR->get_userstate(), + gOTR->get_uistate(), + &mSessionUUID, + my_uuid, + gOTR->get_protocolid(), + their_uuid, + &(utf8_text[0]), NULL, &newmessage, + NULL, NULL); + } + context = getOtrContext(); + if (err) + { + otrLogMessageGetstring("otr_err_failed_sending"); + return; // leave the unsent message in the edit box + } + if (was_finished) + { + llinfos << "$PLOTR$ OTR tried to send into finished conv, not sending message!" << llendl; + //otrLogMessageGetstringName("otr_err_send_in_finished"); //Don't error and tell the user to restart, just restart instead! + doOtrStart(); + return; // leave the unsent message in the edit box + } + OtrlMessageType msgtype = OTRL_MSGTYPE_NOTOTR; + if (newmessage) msgtype = otrl_proto_message_type(newmessage); + if (newmessage && (OTRL_MSGTYPE_TAGGEDPLAINTEXT == msgtype)) + { + // OTR just added the whitespace tag. + otrl_message_free(newmessage); // don't send the message with whitespace tag + err = otrl_message_sending( + gOTR->get_userstate(), + gOTR->get_uistate(), + &mSessionUUID, + my_uuid, + gOTR->get_protocolid(), + their_uuid, + "typing", NULL, &newmessage, + NULL, NULL); + if (!newmessage) + { + llwarns << "$PLOTR$ shouldn't happen, OTR should keep adding whitespace tags till we get a reply from them." << llendl; + } + else + { + // deliver a whitespace tagged "typing" in a IM_TYPING_STOP packet + std::string my_name; + gAgent.buildFullname(my_name); + const LLRelationship* info = NULL; + info = LLAvatarTracker::instance().getBuddyInfo(mOtherParticipantUUID); + U8 offline = (!info || info->isOnline()) ? IM_ONLINE : IM_OFFLINE; + pack_instant_message( + gMessageSystem, + gAgent.getID(), + FALSE, + gAgent.getSessionID(), + mOtherParticipantUUID, + my_name, + newmessage, + offline, + IM_TYPING_STOP, + mSessionUUID); + gAgent.sendReliableMessage(); + otrl_message_free(newmessage); + newmessage = NULL; + } + } + if (newmessage) + { + // OTR encrypted the message + if (! context) + { + llwarns << "$PLOTR$ can't find context, not sending message." << llendl; + otrLogMessageGetstring("otr_err_failed_sending"); + return; // leave the unsent message in the edit box + } + + { + // Handle fragmentation of the message + char *extrafragment = NULL; + err = otrl_message_fragment_and_send( + gOTR->get_uistate(), + &mSessionUUID, + context, + newmessage, + OTRL_FRAGMENT_SEND_ALL, + &extrafragment); + } + if (newmessage) otrl_message_free(newmessage); + showOtrStatus(); + } + else + { // OTR didn't encrypt, or we didn't try cause it's not 1:1 IM +#endif // USE_OTR // [/$PLOTR$] deliver_message(utf8_text, mSessionUUID, mOtherParticipantUUID, mDialog); - +#if USE_OTR // [$PLOTR$] + } +#endif // USE_OTR // [/$PLOTR$] // local echo if((mDialog == IM_NOTHING_SPECIAL) && (mOtherParticipantUUID.notNull())) @@ -2475,7 +3423,27 @@ void LLFloaterIMPanel::chatFromLogFile(LLLogChat::ELogLineType type, std::string //self->addHistoryLine(line, LLColor4::grey, FALSE); self->mHistoryEditor->appendColoredText(message, false, true, LLColor4::grey); } - +/* +// user is known to be offline when we receive this +void LLFloaterIMPanel::setOffline() +{ + if(!gAgent.isGodlike()) + { + childSetEnabled("profile_tele_btn", false); + } +#if USE_OTR // [$PLOTR$] + llinfos << "$PLOTR$ friend went offline" << llendl; + if (gOTR) + { + ConnContext *context = getOtrContext(); + if (context && (context->msgstate == OTRL_MSGSTATE_ENCRYPTED)) + { + pretendTheyOtrStop(); + } + } +#endif // USE_OTR // [/$PLOTR$] +} +*/ void LLFloaterIMPanel::showSessionStartError( const std::string& error_string) { diff --git a/linden/indra/newview/llviewermessage.cpp b/linden/indra/newview/llviewermessage.cpp index 504c193..84e2b7e 100755 --- a/linden/indra/newview/llviewermessage.cpp +++ b/linden/indra/newview/llviewermessage.cpp @@ -158,6 +158,10 @@ #include "llwindebug.h" // For the invalid message handler #endif +#if USE_OTR // [$PLOTR$] +#include "otr_wrapper.h" +#endif // USE_OTR // [/$PLOTR$] + //silly spam define D: bool dialogSpamOn; static LLFrameTimer d_spam; @@ -1582,14 +1586,135 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) is_owned_by_me = source->permYouOwner(); } +#if USE_OTR // [$PLOTR$] + std::string decrypted_msg; + bool encrypted = false; +// if ((CHAT_SOURCE_SYSTEM == chat.mSourceType) && +// ((std::string::npos != message.find("not online")) || +// (std::string::npos != message.find("stored and delivered later")))) +// { +// llinfos << "$PLOTR$ Looks like " << from_id << " went offline." << llendl; +// } + U32 otrpref = gSavedSettings.getU32("EmeraldUseOTR"); + // otrpref: 0 == Require use of OTR in IMs, 1 == Request OTR if available, 2 == Accept OTR requests, 3 == Decline use of OTR + if ((otrpref != 3) && !is_muted && (chat.mSourceType == CHAT_SOURCE_AGENT)) + { + int ignore_message = 0; + char *newmessage = NULL; + OtrlTLV *tlvs = NULL; + char my_uuid[UUID_STR_SIZE]; + char their_uuid[UUID_STR_SIZE]; + + if (gOTR && + ((IM_NOTHING_SPECIAL == dialog) || + ((IM_TYPING_STOP == dialog) && + (! ((message == "typing") || (message == "cryo::ping")))))) + { + // only try OTR for 1 on 1 IM's or special tagged typing_stop packets + gAgent.getID().toString(&(my_uuid[0])); + from_id.toString(&(their_uuid[0])); + ignore_message = otrl_message_receiving( + gOTR->get_userstate(), + gOTR->get_uistate(), + &session_id, + my_uuid, + gOTR->get_protocolid(), + their_uuid, + &(message[0]), &newmessage, + &tlvs, + NULL, NULL); + } + if (tlvs) + { + llinfos << "$PLOTR$ recieved TLVs" << llendl; + LLUUID session = LLIMMgr::computeSessionID(dialog,from_id); + + if(!otrl_tlv_find(tlvs, OTRL_TLV_DISCONNECTED)) + { + // currently the only TLVs we deal with are SMP, and they require an IM panel + if(!gIMMgr->hasSession(session)) + { + gIMMgr->addSession(name,IM_NOTHING_SPECIAL,from_id); + } + + } + LLFloaterIMPanel* pan = gIMMgr->findFloaterBySession(session); + if (pan) pan->handleOtrTlvs(tlvs); + otrl_tlv_free(tlvs); + } + if (1 == ignore_message) + { + OtrlMessageType msgtype = otrl_proto_message_type(&(message[0])); + if (OTRL_MSGTYPE_NOTOTR == msgtype) + { + llinfos << "$PLOTR$ [not otr, but to be ignored (" << message << ")]" << llendl; + if ((0 == otrpref) && (IM_NOTHING_SPECIAL == dialog) && !is_muted) + { + LLUUID session = LLIMMgr::computeSessionID(dialog,from_id); + if(!gIMMgr->hasSession(session)) + { + gIMMgr->addSession(name,IM_NOTHING_SPECIAL,from_id); + } + // NOT deliver_otr_message since those might go via typing_stop + deliver_message( // $TODO$ move the following message to some .xml file + "/me's settings require OTR encrypted instant messages. Your message was not displayed.", + session, from_id, IM_NOTHING_SPECIAL); + LLFloaterIMPanel* pan = gIMMgr->findFloaterBySession(session); + if(pan)pan->doOtrStart(); + } + } + else + { + // an internal OTR protocol message was recieved, don't show anything to the user + llinfos << "$PLOTR$ [OTR PROTOCOL MESSAGE (" << message << ")]" << llendl; + } + otr_show_status(session_id); + return; + } + if (newmessage) + { + // message was processed by OTR. Maybe decrypted, maybe just stripping off the + // white-space "I have OTR" tag + decrypted_msg = newmessage; // use processed message + message = newmessage; // use processed message + otrl_message_free(newmessage); + ConnContext *context = otrl_context_find( + gOTR->get_userstate(), + their_uuid, + my_uuid, + gOTR->get_protocolid(), + 0, NULL, NULL, NULL); + encrypted = (context && (OTRL_MSGSTATE_ENCRYPTED == context->msgstate)); + if (IM_TYPING_STOP == dialog) + { + if ("typing" == message) return; // don't display whitespace tagged "typing" stop messages + dialog = IM_NOTHING_SPECIAL; // display messages received in typing_stop packets + } + } + } + +#endif // USE_OTR // [/$PLOTR$] + std::string separator_string(": "); int message_offset = 0; +#if USE_OTR // [$PLOTR$] + if(encrypted) + { + separator_string = "\xe2\x80\xa7: "; + message = decrypted_msg; + } +#endif // USE_OTR // [/$PLOTR$] + //Handle IRC styled /me messages. std::string prefix = message.substr(0, 4); if (prefix == "/me " || prefix == "/me'") { +#if USE_OTR // [$PLOTR$] + separator_string = encrypted ? "\xe2\x80\xa7" : ""; +#else separator_string = ""; +#endif // USE_OTR // [/$PLOTR$] message_offset = 3; } diff --git a/linden/indra/newview/viewer_manifest.py b/linden/indra/newview/viewer_manifest.py index 3a7039b..0008e45 100755 --- a/linden/indra/newview/viewer_manifest.py +++ b/linden/indra/newview/viewer_manifest.py @@ -596,6 +596,19 @@ class DarwinManifest(ViewerManifest): self.path("libopenal.1.dylib") self.path("libalut.0.dylib") + # otr lib and deps + self.path("libotr.dylib"); + self.path("libintl.8.dylib"); + self.path("libgcrypt.11.dylib"); + self.path("libgpg-error.0.dylib"); + self.path("libiconv.2.dylib"); + # self.path("../../libraries/universal-darwin/lib_release/libotr.dylib", "MacOS/libotr.dylib"); + # self.path("../../libraries/universal-darwin/lib_release/libintl.8.dylib", "MacOS/libintl.8.dylib"); + # self.path("../../libraries/universal-darwin/lib_release/libgcrypt.11.dylib", "MacOS/libgcrypt.11.dylib"); + # self.path("../../libraries/universal-darwin/lib_release/libgpg-error.0.dylib", "MacOS/libgpg-error.0.dylib"); + # self.path("../../libraries/universal-darwin/lib_release/libiconv.2.dylib", "MacOS/libiconv.2.dylib"); + + # self.path("libglib-2.0.dylib") # self.path("libgmodule-2.0.dylib") # self.path("libgobject-2.0.dylib") @@ -1105,6 +1118,8 @@ class Linux_i686Manifest(LinuxManifest): #self.end_prefix("gstreamer-plugins") + self.path("libotr.so.2.2.0") + self.path("libotr.so.2") self.end_prefix("lib") # Vivox runtimes and libs @@ -1237,6 +1252,8 @@ class Linux_x86_64Manifest(LinuxManifest): #self.path("libgstwavparse.so") #self.end_prefix("gstreamer-plugins") + self.path("libotr.so.2.2.0") + self.path("libotr.so.2") self.end_prefix("lib64") -- cgit v1.1