aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra
diff options
context:
space:
mode:
Diffstat (limited to 'linden/indra')
-rw-r--r--linden/indra/cmake/00-Common.cmake13
-rw-r--r--linden/indra/cmake/Variables.cmake1
-rw-r--r--linden/indra/newview/llappviewer.cpp12
-rw-r--r--linden/indra/newview/llfirstuse.cpp28
-rw-r--r--linden/indra/newview/llfloaterpreference.cpp21
-rw-r--r--linden/indra/newview/llimpanel.cpp972
-rwxr-xr-xlinden/indra/newview/llviewermessage.cpp125
-rwxr-xr-xlinden/indra/newview/viewer_manifest.py17
8 files changed, 1186 insertions, 3 deletions
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)
66 /MP 66 /MP
67 ) 67 )
68 68
69 add_definitions(
70 /DUSE_OTR=1
71 )
72
69 if(MSVC80 OR MSVC90) 73 if(MSVC80 OR MSVC90)
70 set(CMAKE_CXX_FLAGS_RELEASE 74 set(CMAKE_CXX_FLAGS_RELEASE
71 "${CMAKE_CXX_FLAGS_RELEASE} -D_SECURE_STL=0 -D_HAS_ITERATOR_DEBUGGING=0" 75 "${CMAKE_CXX_FLAGS_RELEASE} -D_SECURE_STL=0 -D_HAS_ITERATOR_DEBUGGING=0"
@@ -146,6 +150,10 @@ if (LINUX)
146 -pthread 150 -pthread
147 ) 151 )
148 152
153 add_definitions(
154 -DUSE_OTR=1
155 )
156
149 if (SERVER) 157 if (SERVER)
150 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ftemplate-depth-60") 158 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ftemplate-depth-60")
151 if (EXISTS /etc/debian_version) 159 if (EXISTS /etc/debian_version)
@@ -193,6 +201,11 @@ endif (LINUX)
193 201
194if (DARWIN) 202if (DARWIN)
195 add_definitions(-DLL_DARWIN=1) 203 add_definitions(-DLL_DARWIN=1)
204
205 add_definitions(
206 -DUSE_OTR=1
207 )
208
196 set(CMAKE_CXX_LINK_FLAGS "-Wl,-headerpad_max_install_names,-search_paths_first") 209 set(CMAKE_CXX_LINK_FLAGS "-Wl,-headerpad_max_install_names,-search_paths_first")
197 set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_CXX_LINK_FLAGS}") 210 set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_CXX_LINK_FLAGS}")
198 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mlong-branch -msse3 -mssse3 -w") 211 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)
42 42
43if (${CMAKE_SYSTEM_NAME} MATCHES "Windows") 43if (${CMAKE_SYSTEM_NAME} MATCHES "Windows")
44 set(WINDOWS ON BOOL FORCE) 44 set(WINDOWS ON BOOL FORCE)
45 set(USE_OTR 0)
45 set(ARCH i686) 46 set(ARCH i686)
46 set(LL_ARCH ${ARCH}_win32) 47 set(LL_ARCH ${ARCH}_win32)
47 set(LL_ARCH_DIR ${ARCH}-win32) 48 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 @@
206 206
207//---------------------------------------------------------------------------- 207//----------------------------------------------------------------------------
208// viewer.cpp - these are only used in viewer, should be easily moved. 208// viewer.cpp - these are only used in viewer, should be easily moved.
209
210#if USE_OTR // [$PLOTR$]
211#include "otr_wrapper.h"
212#endif // COMPILE_OTR // [/$PLOTR$]
213
209extern void disable_win_error_reporting(); 214extern void disable_win_error_reporting();
210 215
211#if LL_DARWIN 216#if LL_DARWIN
@@ -3779,6 +3784,10 @@ void LLAppViewer::idle()
3779 3784
3780void LLAppViewer::idleShutdown() 3785void LLAppViewer::idleShutdown()
3781{ 3786{
3787#if USE_OTR // [$PLOTR$]
3788 OTR_Wrapper::logout();
3789#endif // USE_OTR // [/$PLOTR$]
3790
3782 // Wait for all modal alerts to get resolved 3791 // Wait for all modal alerts to get resolved
3783 if (LLModalDialog::activeCount() > 0) 3792 if (LLModalDialog::activeCount() > 0)
3784 { 3793 {
@@ -4354,4 +4363,7 @@ void LLAppViewer::handleLoginComplete()
4354 gRlvHandler.processRetainedCommands(); 4363 gRlvHandler.processRetainedCommands();
4355 } 4364 }
4356// [/RLVa:KB] 4365// [/RLVa:KB]
4366#if USE_OTR // [$PLOTR$]
4367 OTR_Wrapper::init();
4368#endif // USE_OTR // [/$PLOTR$]
4357} 4369}
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()
363 } 363 }
364} 364}
365 365
366#if USE_OTR // [$PLOTR$]
367void LLFirstUse::callbackEmeraldOTR(const LLSD &notification, const LLSD &response)
368{
369 gSavedSettings.setWarning("EmeraldOTR", FALSE);
370
371 S32 option = LLNotification::getSelectedOption(notification, response);
372
373 if ( option == 0 )
374 {
375 gSavedSettings.setU32("EmeraldUseOTR",(U32)1);
376 }
377 else if ( option == 1 )
378 {
379 gSavedSettings.setU32("EmeraldUseOTR",(U32)2);
380 }
381}
382
383void LLFirstUse::EmeraldOTR()
384{
385 if(gSavedSettings.getWarning("EmeraldOTR"))
386 {
387 LLNotifications::instance().add("QueryEmeraldOTR", LLSD(),LLSD(), callbackEmeraldOTR);
388 }
389}
390#endif // USE_OTR // [/$PLOTR$]
391
366// static 392// static
367void LLFirstUse::useLoginScreen() 393void LLFirstUse::useLoginScreen()
368{ 394{
@@ -417,4 +443,4 @@ void LLFirstUse::Privacy()
417 { 443 {
418 LLStartUp::setStartupState(STATE_PRIVACY_LECTURED); 444 LLStartUp::setStartupState(STATE_PRIVACY_LECTURED);
419 } 445 }
420} \ No newline at end of file 446}
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 @@
79#include "llscrollcontainer.h" 79#include "llscrollcontainer.h"
80#include "llfloaterhardwaresettings.h" 80#include "llfloaterhardwaresettings.h"
81 81
82#if USE_OTR // [$PLOTR$]
83#include "otr_wrapper.h"
84#endif // USE_OTR // [/$PLOTR$]
85
82const S32 PREF_BORDER = 4; 86const S32 PREF_BORDER = 4;
83const S32 PREF_PAD = 5; 87const S32 PREF_PAD = 5;
84const S32 PREF_BUTTON_WIDTH = 70; 88const S32 PREF_BUTTON_WIDTH = 70;
@@ -422,6 +426,11 @@ LLFloaterPreference::~LLFloaterPreference()
422void LLFloaterPreference::apply() 426void LLFloaterPreference::apply()
423{ 427{
424 this->mPreferenceCore->apply(); 428 this->mPreferenceCore->apply();
429#if USE_OTR // [$PLOTR$]
430 U32 otrpref = gSavedSettings.getU32("EmeraldUseOTR");
431 // otrpref: 0 == Require OTR, 1 == Request OTR, 2 == Accept OTR, 3 == Decline OTR
432 if (3 == otrpref) OTR_Wrapper::stopAll();
433#endif // USE_OTR // [/$PLOTR$]
425} 434}
426 435
427 436
@@ -473,6 +482,13 @@ void LLFloaterPreference::onBtnOK( void* userdata )
473 if (fp->canClose()) 482 if (fp->canClose())
474 { 483 {
475 fp->apply(); 484 fp->apply();
485
486#if USE_OTR // [$PLOTR$]
487 U32 otrpref = gSavedSettings.getU32("EmeraldUseOTR");
488 // otrpref: 0 == Require OTR, 1 == Request OTR, 2 == Accept OTR, 3 == Decline OTR
489 if (3 == otrpref) OTR_Wrapper::stopAll();
490#endif // USE_OTR // [/$PLOTR$]
491
476 fp->close(false); 492 fp->close(false);
477 493
478 gSavedSettings.saveToFile( gSavedSettings.getString("ClientSettingsFile"), TRUE ); 494 gSavedSettings.saveToFile( gSavedSettings.getString("ClientSettingsFile"), TRUE );
@@ -504,6 +520,11 @@ void LLFloaterPreference::onBtnApply( void* userdata )
504 } 520 }
505 } 521 }
506 fp->apply(); 522 fp->apply();
523#if USE_OTR // [$PLOTR$]
524 U32 otrpref = gSavedSettings.getU32("EmeraldUseOTR");
525 // otrpref: 0 == Require OTR, 1 == Request OTR, 2 == Accept OTR, 3 == Decline OTR
526 if (3 == otrpref) OTR_Wrapper::stopAll();
527#endif // USE_OTR // [/$PLOTR$]
507 528
508 LLPanelLogin::refreshLocation( false ); 529 LLPanelLogin::refreshLocation( false );
509} 530}
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 @@
83#include "rlvhandler.h" 83#include "rlvhandler.h"
84// [/RLVa:KB] 84// [/RLVa:KB]
85 85
86#if USE_OTR // [$PLOTR$]
87#include "context.h"
88#include "llcombobox.h"
89#include "otr_wrapper.h"
90#include "otr_floater_smp_dialog.h"
91#include "otr_floater_smp_progress.h"
92#include "mfdKeywordFloater.h"
93#endif // USE_OTR // [/$PLOTR$]
94
86// 95//
87// Constants 96// Constants
88// 97//
@@ -1107,6 +1116,10 @@ LLFloaterIMPanel::LLFloaterIMPanel(
1107 mCallBackEnabled(TRUE), 1116 mCallBackEnabled(TRUE),
1108 mSpeakers(NULL), 1117 mSpeakers(NULL),
1109 mSpeakerPanel(NULL), 1118 mSpeakerPanel(NULL),
1119#if USE_OTR // [$PLOTR$]
1120 mOtrSmpDialog(NULL),
1121 mOtrSmpProgress(NULL),
1122#endif // USE_OTR // [/$PLOTR$]
1110 mFirstKeystrokeTimer(), 1123 mFirstKeystrokeTimer(),
1111 mLastKeystrokeTimer() 1124 mLastKeystrokeTimer()
1112{ 1125{
@@ -1140,6 +1153,10 @@ LLFloaterIMPanel::LLFloaterIMPanel(
1140 mCallBackEnabled(TRUE), 1153 mCallBackEnabled(TRUE),
1141 mSpeakers(NULL), 1154 mSpeakers(NULL),
1142 mSpeakerPanel(NULL), 1155 mSpeakerPanel(NULL),
1156#if USE_OTR // [$PLOTR$]
1157 mOtrSmpDialog(NULL),
1158 mOtrSmpProgress(NULL),
1159#endif // USE_OTR // [/$PLOTR$]
1143 mFirstKeystrokeTimer(), 1160 mFirstKeystrokeTimer(),
1144 mLastKeystrokeTimer(), 1161 mLastKeystrokeTimer(),
1145 mIMPanelType(IM_PANEL_PLAIN) 1162 mIMPanelType(IM_PANEL_PLAIN)
@@ -1319,6 +1336,11 @@ LLFloaterIMPanel::~LLFloaterIMPanel()
1319 { 1336 {
1320 mInputEditor->setFocusLostCallback( NULL ); 1337 mInputEditor->setFocusLostCallback( NULL );
1321 } 1338 }
1339
1340#if USE_OTR // [$PLOTR$]
1341 if (mOtrSmpDialog) delete mOtrSmpDialog;
1342 if (mOtrSmpProgress) delete mOtrSmpProgress;
1343#endif // USE_OTR // [/$PLOTR$]
1322} 1344}
1323 1345
1324BOOL LLFloaterIMPanel::postBuild() 1346BOOL LLFloaterIMPanel::postBuild()
@@ -1388,6 +1410,26 @@ BOOL LLFloaterIMPanel::postBuild()
1388 childSetCommitCallback("speaker_volume", onVolumeChange, this); 1410 childSetCommitCallback("speaker_volume", onVolumeChange, this);
1389 } 1411 }
1390 1412
1413#if USE_OTR // [$PLOTR$]
1414 if (!gOTR) OTR_Wrapper::init();
1415 if (gOTR && (IM_NOTHING_SPECIAL == mDialog))
1416 {
1417 LLComboBox *combo = getChild<LLComboBox>("otr_combo");
1418 if (!combo)
1419 {
1420 llwarns << "$PLOTR$ Can't find OTR control/status" << llendl;
1421 }
1422 else
1423 {
1424 llinfos << "$PLOTR$ found OTR control/status" << llendl;
1425 combo->setCommitCallback(onClickOtr);
1426 combo->setCallbackUserData(this);
1427 combo->setAllowTextEntry(FALSE, 0, FALSE);
1428 showOtrStatus();
1429 }
1430 }
1431#endif // USE_OTR // [/$PLOTR$]
1432
1391 setDefaultBtn("send_btn"); 1433 setDefaultBtn("send_btn");
1392 return TRUE; 1434 return TRUE;
1393 } 1435 }
@@ -2112,6 +2154,786 @@ void deliver_message(const std::string& utf8_text,
2112 } 2154 }
2113} 2155}
2114 2156
2157#if USE_OTR // [$PLOTR$]
2158static bool g_otr_force_typing_stop = false; // ugly hack...
2159// sometimes we must send messages, but don't know if they are offline
2160
2161void otr_deliver_message(const std::string& utf8_text,
2162 const LLUUID& im_session_id,
2163 const LLUUID& other_participant_id,
2164 EInstantMessage dialog)
2165{
2166// llinfos
2167// << "$PLOTR$ message length:" << utf8_text.length()
2168// << " [" << utf8_text.substr(0, 24)
2169// << "]...[" << utf8_text.substr(utf8_text.length()-10, utf8_text.length()-1)
2170// << "]" << llendl;
2171 std::string name;
2172 gAgent.buildFullname(name);
2173
2174 const LLRelationship* info = NULL;
2175 info = LLAvatarTracker::instance().getBuddyInfo(other_participant_id);
2176
2177 U8 offline = (!info || info->isOnline()) ? IM_ONLINE : IM_OFFLINE;
2178
2179 // default to IM_SESSION_SEND unless it's nothing special - in
2180 // which case it's probably an IM to everyone.
2181 U8 new_dialog = dialog;
2182
2183 if ( dialog != IM_NOTHING_SPECIAL )
2184 {
2185 new_dialog = IM_SESSION_SEND;
2186 }
2187 if ((new_dialog == IM_NOTHING_SPECIAL) &&
2188 (g_otr_force_typing_stop ||
2189 (gSavedSettings.getBOOL("EmeraldOTRInTypingStop"))))
2190 {
2191 OtrlMessageType mtype = otrl_proto_message_type(utf8_text.c_str());
2192 switch (mtype)
2193 {
2194 case OTRL_MSGTYPE_UNKNOWN:
2195 llwarns << "Sending unknown type of OTR message" << llendl;
2196 // fall through
2197 case OTRL_MSGTYPE_QUERY:
2198 case OTRL_MSGTYPE_DH_COMMIT:
2199 case OTRL_MSGTYPE_DH_KEY:
2200 case OTRL_MSGTYPE_REVEALSIG:
2201 case OTRL_MSGTYPE_SIGNATURE:
2202 case OTRL_MSGTYPE_V1_KEYEXCH:
2203 case OTRL_MSGTYPE_DATA:
2204 case OTRL_MSGTYPE_TAGGEDPLAINTEXT:
2205 new_dialog = IM_TYPING_STOP;
2206 break;
2207 case OTRL_MSGTYPE_NOTOTR:
2208 case OTRL_MSGTYPE_ERROR:
2209 default:
2210 /* new_dialog = IM_NOTHING_SPECIAL */ ;
2211 }
2212 }
2213 pack_instant_message(
2214 gMessageSystem,
2215 gAgent.getID(),
2216 FALSE,
2217 gAgent.getSessionID(),
2218 other_participant_id,
2219 name.c_str(),
2220 utf8_text.c_str(),
2221 offline,
2222 (EInstantMessage)new_dialog,
2223 im_session_id);
2224 gAgent.sendReliableMessage();
2225
2226 // If there is a mute list and this is not a group chat...
2227 if ( LLMuteList::getInstance() )
2228 {
2229 // ... the target should not be in our mute list for some message types.
2230 // Auto-remove them if present.
2231 switch( dialog )
2232 {
2233 case IM_NOTHING_SPECIAL:
2234 case IM_GROUP_INVITATION:
2235 case IM_INVENTORY_OFFERED:
2236 case IM_SESSION_INVITE:
2237 case IM_SESSION_P2P_INVITE:
2238 case IM_SESSION_CONFERENCE_START:
2239 case IM_SESSION_SEND: // This one is marginal - erring on the side of hearing.
2240 case IM_LURE_USER:
2241 case IM_GODLIKE_LURE_USER:
2242 case IM_FRIENDSHIP_OFFERED:
2243 LLMuteList::getInstance()->autoRemove(other_participant_id, LLMuteList::AR_IM);
2244 break;
2245 default: ; // do nothing
2246 }
2247 }
2248}
2249
2250// static
2251void LLFloaterIMPanel::onClickOtr(LLUICtrl* source, void* userdata)
2252{
2253 LLFloaterIMPanel* self = (LLFloaterIMPanel*) userdata;
2254 if (self)
2255 {
2256 self->doOtrMenu();
2257 self->showOtrStatus();
2258 }
2259 else
2260 {
2261 llwarns << "$PLOTR$ onClickOtr() can't find floater." << llendl;
2262 }
2263}
2264
2265void LLFloaterIMPanel::doOtrStart()
2266{
2267 U32 otrpref = gSavedSettings.getU32("EmeraldUseOTR");
2268 // otrpref: 0 == Require use of OTR in IMs, 1 == Request OTR if available, 2 == Accept OTR requests, 3 == Decline use of OTR
2269 if (3 == otrpref)
2270 {
2271 //otrLogMessageGetstring("otr_err_deacivated");
2272 showOtrStatus();
2273 return;
2274 }
2275 if (gOTR && (IM_NOTHING_SPECIAL == mDialog))
2276 {
2277 llinfos << "$PLOTR$ otr menu start/restart/refresh" << llendl;
2278 gcry_error_t err = 0;
2279 char *newmessage = NULL;
2280 char my_uuid[UUID_STR_SIZE];
2281 char their_uuid[UUID_STR_SIZE];
2282 gAgent.getID().toString(&(my_uuid[0]));
2283 mOtherParticipantUUID.toString(&(their_uuid[0]));
2284
2285 const LLRelationship* info = NULL;
2286 info = LLAvatarTracker::instance().getBuddyInfo(mOtherParticipantUUID);
2287 if (info && (!info->isOnline()))
2288 {
2289 otrLogMessageGetstringName("otr_err_offline_start");
2290 return;
2291 }
2292
2293 if (gOTR && (IM_NOTHING_SPECIAL == mDialog))
2294 {
2295 // only try OTR for 1 on 1 IM's
2296 err = otrl_message_sending(
2297 gOTR->get_userstate(),
2298 gOTR->get_uistate(),
2299 &mSessionUUID,
2300 my_uuid,
2301 gOTR->get_protocolid(),
2302 their_uuid,
2303 "?OTRv2?", NULL, &newmessage,
2304 NULL, NULL);
2305 }
2306 if (err)
2307 {
2308 llwarns << "$PLOTR$ OTR failed to encrypt start message" << llendl;
2309 otrLogMessageGetstring("otr_err_failed_starting");
2310 return;
2311 }
2312 else if (newmessage)
2313 {
2314 // OTR encrypted the message. Handle fragmentation of the message
2315 int context_added = 0;
2316 ConnContext *context = getOtrContext(1, &context_added);
2317 if (context_added)
2318 {
2319 llwarns << "$PLOTR$ context added *after* send start but before fragmentation." << llendl;
2320 }
2321 if (! context)
2322 {
2323 otrLogMessageGetstring("otr_err_failed_starting");
2324 llwarns << "$PLOTR$ can't find context, not sending start message." << llendl;
2325 return;
2326 }
2327 else
2328 {
2329 char *extrafragment = NULL;
2330 err = otrl_message_fragment_and_send(
2331 gOTR->get_uistate(),
2332 &mSessionUUID,
2333 context,
2334 newmessage,
2335 OTRL_FRAGMENT_SEND_ALL,
2336 &extrafragment);
2337 }
2338 if (newmessage) otrl_message_free(newmessage);
2339 //otrLogMessageGetstringName("otr_prog_I_start");
2340 }
2341 else
2342 {
2343 llwarns << "$PLOTR$ can't start OTR for some reason." << llendl;
2344 otrLogMessageGetstring("otr_err_failed_starting");
2345 return;
2346 }
2347 }
2348}
2349
2350void LLFloaterIMPanel::doOtrStop(bool pretend_they_did)
2351{
2352 llinfos << "$PLOTR$ otr menu stop 1" << llendl;
2353 // do not disable this bassed on gSavedSettings.getU32("EmeraldUseOTR");
2354 // when the user disables OTR we may still need to stop currently encrypted conversations
2355 if (gOTR && (IM_NOTHING_SPECIAL == mDialog))
2356 {
2357 char my_uuid[UUID_STR_SIZE];
2358 char their_uuid[UUID_STR_SIZE];
2359 gAgent.getID().toString(&(my_uuid[0]));
2360 mOtherParticipantUUID.toString(&(their_uuid[0]));
2361 llinfos << "$PLOTR$ otr menu stop 2 their_uuid:" << mOtherParticipantUUID << llendl;
2362 g_otr_force_typing_stop = true; // ugly hack
2363 otrl_message_disconnect(
2364 gOTR->get_userstate(),
2365 gOTR->get_uistate(),
2366 &mSessionUUID,
2367 my_uuid,
2368 gOTR->get_protocolid(),
2369 their_uuid);
2370 g_otr_force_typing_stop = false;
2371 if (pretend_they_did)
2372 {
2373 otrLogMessageGetstringName("otr_prog_they_stop");
2374 }
2375 else
2376 {
2377 //otrLogMessageGetstringName("otr_prog_I_stop");
2378 }
2379 showOtrStatus();
2380 }
2381}
2382
2383void LLFloaterIMPanel::doOtrAuth()
2384{
2385 if (mOtrSmpDialog)
2386 {
2387 llinfos << "$PLOTR$ mOtrSmpDialog SMP already in progress, ignoring request to start it" << llendl;
2388 return;
2389 }
2390 if (mOtrSmpDialog || mOtrSmpProgress)
2391 {
2392 llinfos << "$PLOTR$ SMP already in progress, ignoring request to start it" << llendl;
2393 // $TODO$ Tell the user nicely to cancel the one in progress.
2394 // $TODO$ better yet, cancel it/them for the user
2395 return;
2396 }
2397 if (gOTR && (IM_NOTHING_SPECIAL == mDialog))
2398 {
2399 llinfos << "$PLOTR$ otr menu auth" << llendl;
2400
2401 ConnContext *context = getOtrContext();
2402 if (!context)
2403 {
2404 llwarns << "$PLOTR$ doOtrAuth can't find context." << llendl;
2405 return;
2406 }
2407 char my_uuid[UUID_STR_SIZE];
2408 gAgent.getID().toString(&(my_uuid[0]));
2409 char my_fingerprint[45];
2410 otrl_privkey_fingerprint(gOTR->get_userstate(),
2411 my_fingerprint,
2412 my_uuid,
2413 gOTR->get_protocolid());
2414 char other_fingerprint[45];
2415 otrl_privkey_hash_to_human(other_fingerprint, context->active_fingerprint->fingerprint);
2416 startSmpDialog(mSessionUUID, mOtherParticipantUUID,
2417 &(my_fingerprint[0]), &(other_fingerprint[0]));
2418 }
2419}
2420
2421void LLFloaterIMPanel::doOtrMenu()
2422{
2423 if (gOTR && (IM_NOTHING_SPECIAL == mDialog))
2424 {
2425 LLComboBox *combo = getChild<LLComboBox>("otr_combo");
2426 if (!combo)
2427 {
2428 llwarns << "$PLOTR$ Can't find OTR control/status" << llendl;
2429 }
2430 else
2431 {
2432 std::string choice = combo->getSimple();
2433 if ((getString("otr_start") == choice) ||
2434 (getString("otr_restart") == choice) ||
2435 (getString("otr_refresh") == choice))
2436 {
2437 doOtrStart();
2438 }
2439 else if (getString("otr_stop") == choice)
2440 {
2441 doOtrStop();
2442 }
2443 else if (getString("otr_auth") == choice)
2444 {
2445 doOtrAuth();
2446 }
2447 else if (getString("otr_help") == choice)
2448 {
2449 llinfos << "$PLOTR$ otr help" << llendl;
2450 LLWeb::loadURL("http://www.cypherpunks.ca/otr/");
2451 }
2452 else if (getString("otr_levels") == choice)
2453 {
2454 llinfos << "$PLOTR$ otr levels help" << llendl;
2455 LLWeb::loadURL("http://www.cypherpunks.ca/otr/help/3.2.0/levels.php");
2456 }
2457 else
2458 {
2459 llwarns << "$PLOTR$ unknown menu item" << llendl;
2460 }
2461 }
2462 }
2463}
2464
2465ConnContext *LLFloaterIMPanel::getOtrContext(int create_if_not_found, int *context_added)
2466{
2467 ConnContext *context = NULL;
2468 if (gOTR && (IM_NOTHING_SPECIAL == mDialog))
2469 {
2470 char my_uuid[UUID_STR_SIZE];
2471 char their_uuid[UUID_STR_SIZE];
2472 gAgent.getID().toString(&(my_uuid[0]));
2473 mOtherParticipantUUID.toString(&(their_uuid[0]));
2474 context = otrl_context_find(
2475 gOTR->get_userstate(),
2476 their_uuid,
2477 my_uuid,
2478 gOTR->get_protocolid(),
2479 create_if_not_found, context_added, NULL, NULL);
2480 }
2481 return context;
2482}
2483
2484bool LLFloaterIMPanel::otherIsOtrAuthenticated()
2485{
2486 if (gOTR && (IM_NOTHING_SPECIAL == mDialog))
2487 {
2488 ConnContext *context = getOtrContext();
2489 if (context && context->active_fingerprint &&
2490 context->active_fingerprint->trust &&
2491 *(context->active_fingerprint->trust))
2492 {
2493 llinfos << "$PLOTR$ they are authenticated -- trust level is "
2494 << (context->active_fingerprint->trust) << llendl;
2495 return true;
2496 }
2497 }
2498 llinfos << "$PLOTR$ they are NOT authenticated" << llendl;
2499 return false;
2500}
2501
2502void LLFloaterIMPanel::showOtrStatus()
2503{
2504 if (gOTR && (IM_NOTHING_SPECIAL == mDialog))
2505 {
2506 LLComboBox *combo = getChild<LLComboBox>("otr_combo");
2507 if (!combo)
2508 {
2509 llwarns << "$PLOTR$ Can't find OTR control/status" << llendl;
2510 }
2511 else
2512 {
2513 ConnContext *context = getOtrContext();
2514 U32 otrpref = gSavedSettings.getU32("EmeraldUseOTR");
2515 // otrpref: 0 == Require OTR, 1 == Request OTR, 2 == Accept OTR, 3 == Decline OTR
2516 if (3 == otrpref)
2517 {
2518 if (context && (OTRL_MSGSTATE_ENCRYPTED == context->msgstate))
2519 {
2520 doOtrStop();
2521 }
2522 combo->removeall();
2523 combo->add(getString("otr_start"), ADD_BOTTOM, TRUE); // to tell them where to turn it back on
2524 combo->add(getString("otr_stop"), ADD_BOTTOM, FALSE);
2525 combo->add(getString("otr_auth"), ADD_BOTTOM, FALSE);
2526 combo->add(getString("otr_help"), ADD_BOTTOM, TRUE);
2527 combo->add(getString("otr_levels"), ADD_BOTTOM, TRUE);
2528 combo->setLabel(getString("otr_not_private"));
2529 }
2530 else if (context && (OTRL_MSGSTATE_ENCRYPTED == context->msgstate))
2531 {
2532 combo->removeall();
2533 combo->add(getString("otr_refresh"), ADD_BOTTOM, TRUE);
2534 combo->add(getString("otr_stop"), ADD_BOTTOM, TRUE);
2535 combo->add(getString("otr_auth"), ADD_BOTTOM, TRUE);
2536 combo->add(getString("otr_help"), ADD_BOTTOM, TRUE);
2537 combo->add(getString("otr_levels"), ADD_BOTTOM, TRUE);
2538 if (otherIsOtrAuthenticated())
2539 combo->setLabel(getString("otr_private"));
2540 else
2541 combo->setLabel(getString("otr_unverified"));
2542 }
2543 else if (context && (OTRL_MSGSTATE_FINISHED == context->msgstate))
2544 {
2545 if (OTRL_MSGSTATE_ENCRYPTED == mOtrLastStatus)
2546 {
2547 if (otherIsOtrAuthenticated())
2548 otrLogMessageGetstringName("otr_prog_they_stop_private");
2549 else
2550 otrLogMessageGetstringName("otr_prog_they_stop_unverified");
2551 }
2552 combo->removeall();
2553 combo->add(getString("otr_restart"), ADD_BOTTOM, TRUE);
2554 combo->add(getString("otr_stop"), ADD_BOTTOM, TRUE);
2555 combo->add(getString("otr_auth"), ADD_BOTTOM, FALSE);
2556 combo->add(getString("otr_help"), ADD_BOTTOM, TRUE);
2557 combo->add(getString("otr_levels"), ADD_BOTTOM, TRUE);
2558 combo->setLabel(getString("otr_finished"));
2559 }
2560 else // OTRL_MSGSTATE_PLAINTEXT, or no context yet
2561 {
2562 combo->removeall();
2563 combo->add(getString("otr_start"), ADD_BOTTOM, TRUE);
2564 combo->add(getString("otr_stop"), ADD_BOTTOM, FALSE);
2565 combo->add(getString("otr_auth"), ADD_BOTTOM, FALSE);
2566 combo->add(getString("otr_help"), ADD_BOTTOM, TRUE);
2567 combo->add(getString("otr_levels"), ADD_BOTTOM, TRUE);
2568 combo->setLabel(getString("otr_not_private"));
2569 }
2570 if (context)
2571 {
2572 mOtrLastStatus = context->msgstate;
2573 }
2574 }
2575 }
2576}
2577
2578void LLFloaterIMPanel::otrLogMessage(std::string message)
2579{
2580 addHistoryLine(message, gSavedSettings.getColor("SystemChatColor"), true, mOtherParticipantUUID);
2581}
2582
2583void LLFloaterIMPanel::otrLogMessageGetstring(const char *message_name)
2584{
2585 LLUIString msg = getString(message_name);
2586 otrLogMessage(msg);
2587}
2588
2589void LLFloaterIMPanel::otrLogMessageGetstringName(const char *message_name)
2590{
2591 LLUIString msg = getString(message_name);
2592 std::string them;
2593 if (!gCacheName->getFullName(mOtherParticipantUUID, them)) them = getString("otr_generic_name");
2594 msg.setArg("[NAME]", them);
2595 otrLogMessage(msg);
2596}
2597
2598void otr_log_message(LLUUID session_id, const char *message)
2599{
2600 LLFloaterIMPanel* floater = gIMMgr->findFloaterBySession(session_id);
2601 if (floater) floater->otrLogMessage(message);
2602 else
2603 {
2604 llinfos << "$PLOTR$ otr_log_message(" << message << ") failed to find floater." << llendl;
2605 }
2606}
2607
2608void otr_log_message_getstring(LLUUID session_id, const char *message_name)
2609{
2610 LLFloaterIMPanel* floater = gIMMgr->findFloaterBySession(session_id);
2611 if (floater) floater->otrLogMessageGetstring(message_name);
2612 else
2613 {
2614 llinfos << "$PLOTR$ otr_log_message_getstring(" << message_name << ") failed to find floater." << llendl;
2615 }
2616}
2617
2618void otr_log_message_getstring_name(LLUUID session_id, const char *message_name)
2619{
2620 LLFloaterIMPanel* floater = gIMMgr->findFloaterBySession(session_id);
2621 if (floater) floater->otrLogMessageGetstringName(message_name);
2622 else
2623 {
2624 llinfos << "$PLOTR$ otr_log_message_getstring_name(" << message_name << ") failed to find floater." << llendl;
2625 }
2626}
2627
2628void LLFloaterIMPanel::otrAuthenticateKey(const char *trust)
2629{
2630 int context_added = 0;
2631 ConnContext *context = getOtrContext(0, &context_added);
2632 if (gOTR && context)
2633 {
2634 otrl_context_set_trust(context->active_fingerprint, trust);
2635 otrLogMessageGetstringName("otr_log_authenticated");
2636 otrLogMessageGetstringName("otr_log_start_private");
2637 std::string pubpath =
2638 gDirUtilp->getExpandedFilename(
2639 LL_PATH_PER_SL_ACCOUNT, OTR_PUBLIC_KEYS_FILE);
2640 otrl_privkey_write_fingerprints(gOTR->get_userstate(), pubpath.c_str());
2641 showOtrStatus();
2642 }
2643}
2644
2645void otr_authenticate_key(LLUUID session_id, const char *trust)
2646{
2647 LLFloaterIMPanel* floater = gIMMgr->findFloaterBySession(session_id);
2648 if (floater) floater->otrAuthenticateKey(trust);
2649 else
2650 {
2651 llinfos << "$PLOTR$ otr_authenticate_key(" << session_id << ", " << trust << ") failed to find floater." << llendl;
2652 }
2653}
2654
2655void otr_show_status(LLUUID session_id)
2656{
2657 LLFloaterIMPanel* floater = gIMMgr->findFloaterBySession(session_id);
2658 if (floater) floater->showOtrStatus();
2659 else
2660 {
2661 llinfos << "$PLOTR$ can't find floater." << llendl;
2662 }
2663}
2664
2665void LLFloaterIMPanel::pretendTheyOtrStop()
2666{
2667 llinfos << "$PLOTR$ pretending they did doOtrStop()" << llendl;
2668 // we really stop our end, but...
2669 doOtrStop(true); // ... pretend that they did it
2670 ConnContext *context = getOtrContext();
2671 if (context) context->msgstate = OTRL_MSGSTATE_FINISHED;
2672 else
2673 {
2674 llwarns << "$PLOTR$ can't find context." << llendl;
2675 }
2676 showOtrStatus();
2677}
2678
2679void LLFloaterIMPanel::startSmpDialog(
2680 LLUUID session_id, LLUUID other_id,
2681 std::string my_fingerprint, std::string other_fingerprint)
2682{
2683 if (mOtrSmpDialog)
2684 {
2685 mOtrSmpDialog->close();
2686 delete mOtrSmpDialog;
2687 }
2688 mOtrSmpDialog = new OtrFloaterSmpDialog(
2689 this, mSessionUUID, mOtherParticipantUUID,
2690 my_fingerprint, other_fingerprint);
2691 if (mOtrSmpDialog) mOtrSmpDialog->show();
2692 else
2693 {
2694 llwarns << "$PLOTR$ couldn't new OtrFloaterSmpDialog" << llendl;
2695 }
2696}
2697
2698void LLFloaterIMPanel::startSmpDialogQA(
2699 LLUUID session_id, LLUUID other_id, std::string question, OtrlTLV *tlv)
2700{
2701 if (mOtrSmpDialog)
2702 {
2703 mOtrSmpDialog->close();
2704 delete mOtrSmpDialog;
2705 }
2706 mOtrSmpDialog = new OtrFloaterSmpDialog(
2707 this, mSessionUUID, mOtherParticipantUUID, question, tlv);
2708 if (mOtrSmpDialog) mOtrSmpDialog->show();
2709 else
2710 {
2711 llwarns << "$PLOTR$ couldn't new OtrFloaterSmpDialog" << llendl;
2712 }
2713}
2714
2715void LLFloaterIMPanel::startSmpDialogSS(
2716 LLUUID session_id, LLUUID other_id, OtrlTLV *tlv)
2717{
2718 if (mOtrSmpDialog)
2719 {
2720 mOtrSmpDialog->close();
2721 delete mOtrSmpDialog;
2722 }
2723 mOtrSmpDialog = new OtrFloaterSmpDialog(
2724 this, mSessionUUID, mOtherParticipantUUID, tlv);
2725 if (mOtrSmpProgress) mOtrSmpDialog->show();
2726 else
2727 {
2728 llwarns << "$PLOTR$ couldn't new OtrFloaterSmpDialog" << llendl;
2729 }
2730}
2731
2732void LLFloaterIMPanel::endSmpDialog()
2733{
2734 if (!mOtrSmpDialog)
2735 {
2736 llwarns << "$PLOTR$ couldn't find OtrFloaterSmpDialog" << llendl;
2737 }
2738 else
2739 {
2740 delete mOtrSmpDialog;
2741 mOtrSmpDialog = NULL;
2742 }
2743}
2744
2745void LLFloaterIMPanel::startSmpProgress(
2746 LLUUID session_id, LLUUID other_id,
2747 std::string a_question, std::string a_secret_answer, bool is_reply)
2748{
2749 if (mOtrSmpProgress)
2750 {
2751 mOtrSmpProgress->close();
2752 delete mOtrSmpProgress;
2753 }
2754 mOtrSmpProgress =
2755 new OtrFloaterSmpProgress(this, mSessionUUID, mOtherParticipantUUID,
2756 a_question, a_secret_answer, is_reply);
2757 if (mOtrSmpProgress) mOtrSmpProgress->show();
2758 else
2759 {
2760 llwarns << "$PLOTR$ couldn't new OtrFloaterSmpProgress" << llendl;
2761 }
2762}
2763
2764void LLFloaterIMPanel::startSmpProgress(
2765 LLUUID session_id, LLUUID other_id,
2766 std::string a_secret, bool is_reply)
2767{
2768 if (mOtrSmpProgress)
2769 {
2770 mOtrSmpProgress->close();
2771 delete mOtrSmpProgress;
2772 }
2773 mOtrSmpProgress =
2774 new OtrFloaterSmpProgress(this, mSessionUUID, mOtherParticipantUUID,
2775 a_secret, is_reply);
2776 if (mOtrSmpProgress) mOtrSmpProgress->show();
2777 else
2778 {
2779 llwarns << "$PLOTR$ couldn't new OtrFloaterSmpProgress" << llendl;
2780 }
2781}
2782
2783void LLFloaterIMPanel::endSmpProgress()
2784{
2785 if (!mOtrSmpProgress)
2786 {
2787 llwarns << "$PLOTR$ couldn't find OtrFloaterSmpProgress" << llendl;
2788 }
2789 else
2790 {
2791 delete mOtrSmpProgress;
2792 mOtrSmpProgress = NULL;
2793 }
2794}
2795
2796void LLFloaterIMPanel::handleOtrTlvs(OtrlTLV *tlvs)
2797{
2798 ConnContext *context = getOtrContext();
2799 if (! context)
2800 {
2801 llwarns << "$PLOTR$ Can't find otr context" << llendl;
2802 return;
2803 }
2804 if (! context->smstate)
2805 {
2806 llwarns << "$PLOTR$ OTR context doesn't have smstate" << llendl;
2807 return;
2808 }
2809 if (context->smstate->sm_prog_state == OTRL_SMP_PROG_CHEATED)
2810 {
2811 if (mOtrSmpProgress) mOtrSmpProgress->setFinalStatus("otr_smp_prog_auth_errored");
2812 context->smstate->nextExpected = OTRL_SMP_EXPECT1;
2813 context->smstate->sm_prog_state = OTRL_SMP_PROG_OK;
2814 return;
2815 }
2816 NextExpectedSMP nextMsg = context->smstate->nextExpected;
2817 OtrlTLV *tlv = NULL;
2818 tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP1Q);
2819 if (tlv)
2820 {
2821 if (nextMsg != OTRL_SMP_EXPECT1)
2822 {
2823 if (mOtrSmpProgress) mOtrSmpProgress->setFinalStatus("otr_smp_prog_auth_errored");
2824 return;
2825 }
2826 // Start a challenge SMP dialog
2827 char *question = (char *)tlv->data;
2828 char *eoq = (char *)memchr(question, '\0', tlv->len);
2829 if (!eoq)
2830 {
2831 llwarns << "$PLOTR$ bad format in OTRL_TLV_SMP1Q, no end to question." << llendl;
2832 if (mOtrSmpProgress) mOtrSmpProgress->setFinalStatus("otr_smp_prog_auth_errored");
2833 return;
2834 }
2835 startSmpDialogQA(mSessionUUID, mOtherParticipantUUID, question, tlv);
2836 if (mOtrSmpProgress) mOtrSmpProgress->setPercent(25);
2837 return;
2838 }
2839 tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP1);
2840 if (tlv)
2841 {
2842 if (nextMsg != OTRL_SMP_EXPECT1)
2843 {
2844 if (mOtrSmpProgress) mOtrSmpProgress->setFinalStatus("otr_smp_prog_auth_errored");
2845 return;
2846 }
2847 // Start a challenge SMP dialog
2848 startSmpDialogSS(mSessionUUID, mOtherParticipantUUID, tlv);
2849 if (mOtrSmpProgress) mOtrSmpProgress->setPercent(25);
2850 return;
2851 }
2852 tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP2);
2853 if (tlv)
2854 {
2855 if (nextMsg != OTRL_SMP_EXPECT2)
2856 {
2857 if (mOtrSmpProgress) mOtrSmpProgress->setFinalStatus("otr_smp_prog_auth_errored");
2858 return;
2859 }
2860 else
2861 {
2862 // If we received TLV2, we will send TLV3 and expect TLV4
2863 context->smstate->nextExpected = OTRL_SMP_EXPECT4;
2864 if (mOtrSmpProgress) mOtrSmpProgress->setPercent(75);
2865 }
2866 }
2867 tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP3);
2868 if (tlv)
2869 {
2870 if (nextMsg != OTRL_SMP_EXPECT3)
2871 {
2872 if (mOtrSmpProgress) mOtrSmpProgress->setFinalStatus("otr_smp_prog_auth_errored");
2873 return;
2874 }
2875 else
2876 {
2877 // If we received TLV3, we will send TLV4
2878 // We will not expect more messages, so prepare for next SMP
2879 context->smstate->nextExpected = OTRL_SMP_EXPECT1;
2880 // Report result to user
2881 if (context->smstate->sm_prog_state == OTRL_SMP_PROG_SUCCEEDED)
2882 {
2883 if (context->active_fingerprint &&
2884 context->active_fingerprint->trust &&
2885 *(context->active_fingerprint->trust))
2886 {
2887 // they authed me OK, and I already authed them in the past
2888 if (mOtrSmpProgress) mOtrSmpProgress->setFinalStatus("otr_smp_prog_auth_ok");
2889 }
2890 else
2891 {
2892 // they authed me OK, but I haven't authed them yet
2893 if (mOtrSmpProgress) mOtrSmpProgress->setFinalStatus("otr_smp_prog_auth_ok_name_next");
2894 }
2895 }
2896 else
2897 {
2898 if (mOtrSmpProgress) mOtrSmpProgress->setFinalStatus("otr_smp_prog_auth_failed");
2899 }
2900 }
2901 }
2902 tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP4);
2903 if (tlv)
2904 {
2905 if (nextMsg != OTRL_SMP_EXPECT4)
2906 {
2907 if (mOtrSmpProgress) mOtrSmpProgress->setFinalStatus("otr_smp_prog_auth_errored");
2908 return;
2909 }
2910 else {
2911 // We will not expect more messages, so prepare for next SMP
2912 context->smstate->nextExpected = OTRL_SMP_EXPECT1;
2913 // Report result to user
2914 if (context->active_fingerprint &&
2915 context->active_fingerprint->trust &&
2916 *(context->active_fingerprint->trust))
2917 {
2918 if (mOtrSmpProgress) mOtrSmpProgress->setFinalStatus("otr_smp_prog_auth_ok");
2919 }
2920 else
2921 {
2922 if (mOtrSmpProgress) mOtrSmpProgress->setFinalStatus("otr_smp_prog_auth_failed");
2923 }
2924 }
2925 }
2926 tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP_ABORT);
2927 if (tlv)
2928 {
2929 // The message we are waiting for will not arrive, so reset
2930 // and prepare for the next SMP
2931 context->smstate->nextExpected = OTRL_SMP_EXPECT1;
2932 if (mOtrSmpProgress) mOtrSmpProgress->setFinalStatus("otr_smp_prog_auth_aborted");
2933 }
2934}
2935#endif // USE_OTR // [/$PLOTR$]
2936
2115void LLFloaterIMPanel::sendMsg() 2937void LLFloaterIMPanel::sendMsg()
2116{ 2938{
2117 if (!gAgent.isGodlike() 2939 if (!gAgent.isGodlike()
@@ -2204,11 +3026,137 @@ void LLFloaterIMPanel::sendMsg()
2204 3026
2205 if ( mSessionInitialized ) 3027 if ( mSessionInitialized )
2206 { 3028 {
3029#if USE_OTR // [$PLOTR$]
3030 const LLRelationship* info = NULL;
3031 info = LLAvatarTracker::instance().getBuddyInfo(mOtherParticipantUUID);
3032 ConnContext *context = getOtrContext(1);
3033 if (info && (!info->isOnline()) && context &&
3034 ( (OTRL_MSGSTATE_ENCRYPTED == context->msgstate)
3035 || (OTRL_MSGSTATE_FINISHED == context->msgstate)))
3036 {
3037 // we can't continue this encrypted session but we
3038 // can't let the user accidentally send unencrypted
3039 if (OTRL_MSGSTATE_ENCRYPTED == context->msgstate)
3040 pretendTheyOtrStop();
3041 otrLogMessageGetstringName("otr_err_offline_send");
3042 return; // leave the unsent message in the edit box
3043 }
3044
3045 gcry_error_t err = 0;
3046 char *newmessage = NULL;
3047 char my_uuid[UUID_STR_SIZE];
3048 char their_uuid[UUID_STR_SIZE];
3049 gAgent.getID().toString(&(my_uuid[0]));
3050 mOtherParticipantUUID.toString(&(their_uuid[0]));
3051
3052 bool was_finished = false;
3053 if (gOTR && context && (context->msgstate == OTRL_MSGSTATE_FINISHED))
3054 {
3055 was_finished = true;
3056 }
3057 else if (gOTR && (IM_NOTHING_SPECIAL == mDialog))
3058 {
3059 // only try OTR for 1 on 1 IM's
3060 err = otrl_message_sending(
3061 gOTR->get_userstate(),
3062 gOTR->get_uistate(),
3063 &mSessionUUID,
3064 my_uuid,
3065 gOTR->get_protocolid(),
3066 their_uuid,
3067 &(utf8_text[0]), NULL, &newmessage,
3068 NULL, NULL);
3069 }
3070 context = getOtrContext();
3071 if (err)
3072 {
3073 otrLogMessageGetstring("otr_err_failed_sending");
3074 return; // leave the unsent message in the edit box
3075 }
3076 if (was_finished)
3077 {
3078 llinfos << "$PLOTR$ OTR tried to send into finished conv, not sending message!" << llendl;
3079 //otrLogMessageGetstringName("otr_err_send_in_finished"); //Don't error and tell the user to restart, just restart instead!
3080 doOtrStart();
3081 return; // leave the unsent message in the edit box
3082 }
3083 OtrlMessageType msgtype = OTRL_MSGTYPE_NOTOTR;
3084 if (newmessage) msgtype = otrl_proto_message_type(newmessage);
3085 if (newmessage && (OTRL_MSGTYPE_TAGGEDPLAINTEXT == msgtype))
3086 {
3087 // OTR just added the whitespace tag.
3088 otrl_message_free(newmessage); // don't send the message with whitespace tag
3089 err = otrl_message_sending(
3090 gOTR->get_userstate(),
3091 gOTR->get_uistate(),
3092 &mSessionUUID,
3093 my_uuid,
3094 gOTR->get_protocolid(),
3095 their_uuid,
3096 "typing", NULL, &newmessage,
3097 NULL, NULL);
3098 if (!newmessage)
3099 {
3100 llwarns << "$PLOTR$ shouldn't happen, OTR should keep adding whitespace tags till we get a reply from them." << llendl;
3101 }
3102 else
3103 {
3104 // deliver a whitespace tagged "typing" in a IM_TYPING_STOP packet
3105 std::string my_name;
3106 gAgent.buildFullname(my_name);
3107 const LLRelationship* info = NULL;
3108 info = LLAvatarTracker::instance().getBuddyInfo(mOtherParticipantUUID);
3109 U8 offline = (!info || info->isOnline()) ? IM_ONLINE : IM_OFFLINE;
3110 pack_instant_message(
3111 gMessageSystem,
3112 gAgent.getID(),
3113 FALSE,
3114 gAgent.getSessionID(),
3115 mOtherParticipantUUID,
3116 my_name,
3117 newmessage,
3118 offline,
3119 IM_TYPING_STOP,
3120 mSessionUUID);
3121 gAgent.sendReliableMessage();
3122 otrl_message_free(newmessage);
3123 newmessage = NULL;
3124 }
3125 }
3126 if (newmessage)
3127 {
3128 // OTR encrypted the message
3129 if (! context)
3130 {
3131 llwarns << "$PLOTR$ can't find context, not sending message." << llendl;
3132 otrLogMessageGetstring("otr_err_failed_sending");
3133 return; // leave the unsent message in the edit box
3134 }
3135
3136 {
3137 // Handle fragmentation of the message
3138 char *extrafragment = NULL;
3139 err = otrl_message_fragment_and_send(
3140 gOTR->get_uistate(),
3141 &mSessionUUID,
3142 context,
3143 newmessage,
3144 OTRL_FRAGMENT_SEND_ALL,
3145 &extrafragment);
3146 }
3147 if (newmessage) otrl_message_free(newmessage);
3148 showOtrStatus();
3149 }
3150 else
3151 { // OTR didn't encrypt, or we didn't try cause it's not 1:1 IM
3152#endif // USE_OTR // [/$PLOTR$]
2207 deliver_message(utf8_text, 3153 deliver_message(utf8_text,
2208 mSessionUUID, 3154 mSessionUUID,
2209 mOtherParticipantUUID, 3155 mOtherParticipantUUID,
2210 mDialog); 3156 mDialog);
2211 3157#if USE_OTR // [$PLOTR$]
3158 }
3159#endif // USE_OTR // [/$PLOTR$]
2212 // local echo 3160 // local echo
2213 if((mDialog == IM_NOTHING_SPECIAL) && 3161 if((mDialog == IM_NOTHING_SPECIAL) &&
2214 (mOtherParticipantUUID.notNull())) 3162 (mOtherParticipantUUID.notNull()))
@@ -2475,7 +3423,27 @@ void LLFloaterIMPanel::chatFromLogFile(LLLogChat::ELogLineType type, std::string
2475 //self->addHistoryLine(line, LLColor4::grey, FALSE); 3423 //self->addHistoryLine(line, LLColor4::grey, FALSE);
2476 self->mHistoryEditor->appendColoredText(message, false, true, LLColor4::grey); 3424 self->mHistoryEditor->appendColoredText(message, false, true, LLColor4::grey);
2477} 3425}
2478 3426/*
3427// user is known to be offline when we receive this
3428void LLFloaterIMPanel::setOffline()
3429{
3430 if(!gAgent.isGodlike())
3431 {
3432 childSetEnabled("profile_tele_btn", false);
3433 }
3434#if USE_OTR // [$PLOTR$]
3435 llinfos << "$PLOTR$ friend went offline" << llendl;
3436 if (gOTR)
3437 {
3438 ConnContext *context = getOtrContext();
3439 if (context && (context->msgstate == OTRL_MSGSTATE_ENCRYPTED))
3440 {
3441 pretendTheyOtrStop();
3442 }
3443 }
3444#endif // USE_OTR // [/$PLOTR$]
3445}
3446*/
2479void LLFloaterIMPanel::showSessionStartError( 3447void LLFloaterIMPanel::showSessionStartError(
2480 const std::string& error_string) 3448 const std::string& error_string)
2481{ 3449{
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 @@
158#include "llwindebug.h" // For the invalid message handler 158#include "llwindebug.h" // For the invalid message handler
159#endif 159#endif
160 160
161#if USE_OTR // [$PLOTR$]
162#include "otr_wrapper.h"
163#endif // USE_OTR // [/$PLOTR$]
164
161//silly spam define D: 165//silly spam define D:
162bool dialogSpamOn; 166bool dialogSpamOn;
163static LLFrameTimer d_spam; 167static LLFrameTimer d_spam;
@@ -1582,14 +1586,135 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
1582 is_owned_by_me = source->permYouOwner(); 1586 is_owned_by_me = source->permYouOwner();
1583 } 1587 }
1584 1588
1589#if USE_OTR // [$PLOTR$]
1590 std::string decrypted_msg;
1591 bool encrypted = false;
1592// if ((CHAT_SOURCE_SYSTEM == chat.mSourceType) &&
1593// ((std::string::npos != message.find("not online")) ||
1594// (std::string::npos != message.find("stored and delivered later"))))
1595// {
1596// llinfos << "$PLOTR$ Looks like " << from_id << " went offline." << llendl;
1597// }
1598 U32 otrpref = gSavedSettings.getU32("EmeraldUseOTR");
1599 // otrpref: 0 == Require use of OTR in IMs, 1 == Request OTR if available, 2 == Accept OTR requests, 3 == Decline use of OTR
1600 if ((otrpref != 3) && !is_muted && (chat.mSourceType == CHAT_SOURCE_AGENT))
1601 {
1602 int ignore_message = 0;
1603 char *newmessage = NULL;
1604 OtrlTLV *tlvs = NULL;
1605 char my_uuid[UUID_STR_SIZE];
1606 char their_uuid[UUID_STR_SIZE];
1607
1608 if (gOTR &&
1609 ((IM_NOTHING_SPECIAL == dialog) ||
1610 ((IM_TYPING_STOP == dialog) &&
1611 (! ((message == "typing") || (message == "cryo::ping"))))))
1612 {
1613 // only try OTR for 1 on 1 IM's or special tagged typing_stop packets
1614 gAgent.getID().toString(&(my_uuid[0]));
1615 from_id.toString(&(their_uuid[0]));
1616 ignore_message = otrl_message_receiving(
1617 gOTR->get_userstate(),
1618 gOTR->get_uistate(),
1619 &session_id,
1620 my_uuid,
1621 gOTR->get_protocolid(),
1622 their_uuid,
1623 &(message[0]), &newmessage,
1624 &tlvs,
1625 NULL, NULL);
1626 }
1627 if (tlvs)
1628 {
1629 llinfos << "$PLOTR$ recieved TLVs" << llendl;
1630 LLUUID session = LLIMMgr::computeSessionID(dialog,from_id);
1631
1632 if(!otrl_tlv_find(tlvs, OTRL_TLV_DISCONNECTED))
1633 {
1634 // currently the only TLVs we deal with are SMP, and they require an IM panel
1635 if(!gIMMgr->hasSession(session))
1636 {
1637 gIMMgr->addSession(name,IM_NOTHING_SPECIAL,from_id);
1638 }
1639
1640 }
1641 LLFloaterIMPanel* pan = gIMMgr->findFloaterBySession(session);
1642 if (pan) pan->handleOtrTlvs(tlvs);
1643 otrl_tlv_free(tlvs);
1644 }
1645 if (1 == ignore_message)
1646 {
1647 OtrlMessageType msgtype = otrl_proto_message_type(&(message[0]));
1648 if (OTRL_MSGTYPE_NOTOTR == msgtype)
1649 {
1650 llinfos << "$PLOTR$ [not otr, but to be ignored (" << message << ")]" << llendl;
1651 if ((0 == otrpref) && (IM_NOTHING_SPECIAL == dialog) && !is_muted)
1652 {
1653 LLUUID session = LLIMMgr::computeSessionID(dialog,from_id);
1654 if(!gIMMgr->hasSession(session))
1655 {
1656 gIMMgr->addSession(name,IM_NOTHING_SPECIAL,from_id);
1657 }
1658 // NOT deliver_otr_message since those might go via typing_stop
1659 deliver_message( // $TODO$ move the following message to some .xml file
1660 "/me's settings require OTR encrypted instant messages. Your message was not displayed.",
1661 session, from_id, IM_NOTHING_SPECIAL);
1662 LLFloaterIMPanel* pan = gIMMgr->findFloaterBySession(session);
1663 if(pan)pan->doOtrStart();
1664 }
1665 }
1666 else
1667 {
1668 // an internal OTR protocol message was recieved, don't show anything to the user
1669 llinfos << "$PLOTR$ [OTR PROTOCOL MESSAGE (" << message << ")]" << llendl;
1670 }
1671 otr_show_status(session_id);
1672 return;
1673 }
1674 if (newmessage)
1675 {
1676 // message was processed by OTR. Maybe decrypted, maybe just stripping off the
1677 // white-space "I have OTR" tag
1678 decrypted_msg = newmessage; // use processed message
1679 message = newmessage; // use processed message
1680 otrl_message_free(newmessage);
1681 ConnContext *context = otrl_context_find(
1682 gOTR->get_userstate(),
1683 their_uuid,
1684 my_uuid,
1685 gOTR->get_protocolid(),
1686 0, NULL, NULL, NULL);
1687 encrypted = (context && (OTRL_MSGSTATE_ENCRYPTED == context->msgstate));
1688 if (IM_TYPING_STOP == dialog)
1689 {
1690 if ("typing" == message) return; // don't display whitespace tagged "typing" stop messages
1691 dialog = IM_NOTHING_SPECIAL; // display messages received in typing_stop packets
1692 }
1693 }
1694 }
1695
1696#endif // USE_OTR // [/$PLOTR$]
1697
1585 std::string separator_string(": "); 1698 std::string separator_string(": ");
1586 int message_offset = 0; 1699 int message_offset = 0;
1587 1700
1701#if USE_OTR // [$PLOTR$]
1702 if(encrypted)
1703 {
1704 separator_string = "\xe2\x80\xa7: ";
1705 message = decrypted_msg;
1706 }
1707#endif // USE_OTR // [/$PLOTR$]
1708
1588 //Handle IRC styled /me messages. 1709 //Handle IRC styled /me messages.
1589 std::string prefix = message.substr(0, 4); 1710 std::string prefix = message.substr(0, 4);
1590 if (prefix == "/me " || prefix == "/me'") 1711 if (prefix == "/me " || prefix == "/me'")
1591 { 1712 {
1713#if USE_OTR // [$PLOTR$]
1714 separator_string = encrypted ? "\xe2\x80\xa7" : "";
1715#else
1592 separator_string = ""; 1716 separator_string = "";
1717#endif // USE_OTR // [/$PLOTR$]
1593 message_offset = 3; 1718 message_offset = 3;
1594 } 1719 }
1595 1720
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):
596 self.path("libopenal.1.dylib") 596 self.path("libopenal.1.dylib")
597 self.path("libalut.0.dylib") 597 self.path("libalut.0.dylib")
598 598
599 # otr lib and deps
600 self.path("libotr.dylib");
601 self.path("libintl.8.dylib");
602 self.path("libgcrypt.11.dylib");
603 self.path("libgpg-error.0.dylib");
604 self.path("libiconv.2.dylib");
605 # self.path("../../libraries/universal-darwin/lib_release/libotr.dylib", "MacOS/libotr.dylib");
606 # self.path("../../libraries/universal-darwin/lib_release/libintl.8.dylib", "MacOS/libintl.8.dylib");
607 # self.path("../../libraries/universal-darwin/lib_release/libgcrypt.11.dylib", "MacOS/libgcrypt.11.dylib");
608 # self.path("../../libraries/universal-darwin/lib_release/libgpg-error.0.dylib", "MacOS/libgpg-error.0.dylib");
609 # self.path("../../libraries/universal-darwin/lib_release/libiconv.2.dylib", "MacOS/libiconv.2.dylib");
610
611
599 # self.path("libglib-2.0.dylib") 612 # self.path("libglib-2.0.dylib")
600 # self.path("libgmodule-2.0.dylib") 613 # self.path("libgmodule-2.0.dylib")
601 # self.path("libgobject-2.0.dylib") 614 # self.path("libgobject-2.0.dylib")
@@ -1105,6 +1118,8 @@ class Linux_i686Manifest(LinuxManifest):
1105 1118
1106 #self.end_prefix("gstreamer-plugins") 1119 #self.end_prefix("gstreamer-plugins")
1107 1120
1121 self.path("libotr.so.2.2.0")
1122 self.path("libotr.so.2")
1108 self.end_prefix("lib") 1123 self.end_prefix("lib")
1109 1124
1110 # Vivox runtimes and libs 1125 # Vivox runtimes and libs
@@ -1237,6 +1252,8 @@ class Linux_x86_64Manifest(LinuxManifest):
1237 #self.path("libgstwavparse.so") 1252 #self.path("libgstwavparse.so")
1238 1253
1239 #self.end_prefix("gstreamer-plugins") 1254 #self.end_prefix("gstreamer-plugins")
1255 self.path("libotr.so.2.2.0")
1256 self.path("libotr.so.2")
1240 self.end_prefix("lib64") 1257 self.end_prefix("lib64")
1241 1258
1242 1259