diff options
Diffstat (limited to '')
-rw-r--r-- | linden/indra/newview/llimpanel.cpp | 992 |
1 files changed, 989 insertions, 3 deletions
diff --git a/linden/indra/newview/llimpanel.cpp b/linden/indra/newview/llimpanel.cpp index 4953a27..85ab779 100644 --- a/linden/indra/newview/llimpanel.cpp +++ b/linden/indra/newview/llimpanel.cpp | |||
@@ -83,6 +83,14 @@ | |||
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 | #endif // USE_OTR // [/$PLOTR$] | ||
93 | |||
86 | // | 94 | // |
87 | // Constants | 95 | // Constants |
88 | // | 96 | // |
@@ -1107,6 +1115,10 @@ LLFloaterIMPanel::LLFloaterIMPanel( | |||
1107 | mCallBackEnabled(TRUE), | 1115 | mCallBackEnabled(TRUE), |
1108 | mSpeakers(NULL), | 1116 | mSpeakers(NULL), |
1109 | mSpeakerPanel(NULL), | 1117 | mSpeakerPanel(NULL), |
1118 | #if USE_OTR // [$PLOTR$] | ||
1119 | mOtrSmpDialog(NULL), | ||
1120 | mOtrSmpProgress(NULL), | ||
1121 | #endif // USE_OTR // [/$PLOTR$] | ||
1110 | mFirstKeystrokeTimer(), | 1122 | mFirstKeystrokeTimer(), |
1111 | mLastKeystrokeTimer() | 1123 | mLastKeystrokeTimer() |
1112 | { | 1124 | { |
@@ -1140,6 +1152,10 @@ LLFloaterIMPanel::LLFloaterIMPanel( | |||
1140 | mCallBackEnabled(TRUE), | 1152 | mCallBackEnabled(TRUE), |
1141 | mSpeakers(NULL), | 1153 | mSpeakers(NULL), |
1142 | mSpeakerPanel(NULL), | 1154 | mSpeakerPanel(NULL), |
1155 | #if USE_OTR // [$PLOTR$] | ||
1156 | mOtrSmpDialog(NULL), | ||
1157 | mOtrSmpProgress(NULL), | ||
1158 | #endif // USE_OTR // [/$PLOTR$] | ||
1143 | mFirstKeystrokeTimer(), | 1159 | mFirstKeystrokeTimer(), |
1144 | mLastKeystrokeTimer(), | 1160 | mLastKeystrokeTimer(), |
1145 | mIMPanelType(IM_PANEL_PLAIN) | 1161 | mIMPanelType(IM_PANEL_PLAIN) |
@@ -1319,6 +1335,11 @@ LLFloaterIMPanel::~LLFloaterIMPanel() | |||
1319 | { | 1335 | { |
1320 | mInputEditor->setFocusLostCallback( NULL ); | 1336 | mInputEditor->setFocusLostCallback( NULL ); |
1321 | } | 1337 | } |
1338 | |||
1339 | #if USE_OTR // [$PLOTR$] | ||
1340 | if (mOtrSmpDialog) delete mOtrSmpDialog; | ||
1341 | if (mOtrSmpProgress) delete mOtrSmpProgress; | ||
1342 | #endif // USE_OTR // [/$PLOTR$] | ||
1322 | } | 1343 | } |
1323 | 1344 | ||
1324 | BOOL LLFloaterIMPanel::postBuild() | 1345 | BOOL LLFloaterIMPanel::postBuild() |
@@ -1388,6 +1409,27 @@ BOOL LLFloaterIMPanel::postBuild() | |||
1388 | childSetCommitCallback("speaker_volume", onVolumeChange, this); | 1409 | childSetCommitCallback("speaker_volume", onVolumeChange, this); |
1389 | } | 1410 | } |
1390 | 1411 | ||
1412 | #if USE_OTR // [$PLOTR$] | ||
1413 | if (!gOTR) OTR_Wrapper::init(); | ||
1414 | if (gOTR && (IM_NOTHING_SPECIAL == mDialog)) | ||
1415 | { | ||
1416 | childSetCommitCallback("otr_btn", onClickOtr, this); | ||
1417 | LLComboBox *combo = getChild<LLComboBox>("otr_btn"); | ||
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 | } |
@@ -1627,7 +1669,7 @@ void LLFloaterIMPanel::addHistoryLine(const std::string &utf8msg, const LLColor4 | |||
1627 | // 'name' is a sender name that we want to hotlink so that clicking on it opens a profile. | 1669 | // 'name' is a sender name that we want to hotlink so that clicking on it opens a profile. |
1628 | if (!name.empty()) // If name exists, then add it to the front of the message. | 1670 | if (!name.empty()) // If name exists, then add it to the front of the message. |
1629 | { | 1671 | { |
1630 | // Don't hotlink any messages from the system (e.g. "Second Life:"), so just add those in plain text. | 1672 | // Don't hotlink any messages from the system, so just add those in plain text. |
1631 | if (name == SYSTEM_FROM) | 1673 | if (name == SYSTEM_FROM) |
1632 | { | 1674 | { |
1633 | mHistoryEditor->appendColoredText(name,false,prepend_newline,color); | 1675 | mHistoryEditor->appendColoredText(name,false,prepend_newline,color); |
@@ -2119,6 +2161,778 @@ void deliver_message(const std::string& utf8_text, | |||
2119 | } | 2161 | } |
2120 | } | 2162 | } |
2121 | 2163 | ||
2164 | #if USE_OTR // [$PLOTR$] | ||
2165 | static bool g_otr_force_typing_stop = false; // ugly hack... | ||
2166 | // sometimes we must send messages, but don't know if they are offline | ||
2167 | |||
2168 | void otr_deliver_message(const std::string& utf8_text, | ||
2169 | const LLUUID& im_session_id, | ||
2170 | const LLUUID& other_participant_id, | ||
2171 | EInstantMessage dialog) | ||
2172 | { | ||
2173 | // llinfos | ||
2174 | // << "$PLOTR$ message length:" << utf8_text.length() | ||
2175 | // << " [" << utf8_text.substr(0, 24) | ||
2176 | // << "]...[" << utf8_text.substr(utf8_text.length()-10, utf8_text.length()-1) | ||
2177 | // << "]" << llendl; | ||
2178 | std::string name; | ||
2179 | gAgent.buildFullname(name); | ||
2180 | |||
2181 | const LLRelationship* info = NULL; | ||
2182 | info = LLAvatarTracker::instance().getBuddyInfo(other_participant_id); | ||
2183 | |||
2184 | U8 offline = (!info || info->isOnline()) ? IM_ONLINE : IM_OFFLINE; | ||
2185 | |||
2186 | // default to IM_SESSION_SEND unless it's nothing special - in | ||
2187 | // which case it's probably an IM to everyone. | ||
2188 | U8 new_dialog = dialog; | ||
2189 | |||
2190 | if ( dialog != IM_NOTHING_SPECIAL ) | ||
2191 | { | ||
2192 | new_dialog = IM_SESSION_SEND; | ||
2193 | } | ||
2194 | if ((new_dialog == IM_NOTHING_SPECIAL) && | ||
2195 | (g_otr_force_typing_stop || | ||
2196 | (gSavedSettings.getBOOL("EmeraldOTRInTypingStop")))) | ||
2197 | { | ||
2198 | OtrlMessageType mtype = otrl_proto_message_type(utf8_text.c_str()); | ||
2199 | switch (mtype) | ||
2200 | { | ||
2201 | case OTRL_MSGTYPE_UNKNOWN: | ||
2202 | llwarns << "Sending unknown type of OTR message" << llendl; | ||
2203 | // fall through | ||
2204 | case OTRL_MSGTYPE_QUERY: | ||
2205 | case OTRL_MSGTYPE_DH_COMMIT: | ||
2206 | case OTRL_MSGTYPE_DH_KEY: | ||
2207 | case OTRL_MSGTYPE_REVEALSIG: | ||
2208 | case OTRL_MSGTYPE_SIGNATURE: | ||
2209 | case OTRL_MSGTYPE_V1_KEYEXCH: | ||
2210 | case OTRL_MSGTYPE_DATA: | ||
2211 | case OTRL_MSGTYPE_TAGGEDPLAINTEXT: | ||
2212 | new_dialog = IM_TYPING_STOP; | ||
2213 | break; | ||
2214 | case OTRL_MSGTYPE_NOTOTR: | ||
2215 | case OTRL_MSGTYPE_ERROR: | ||
2216 | default: | ||
2217 | /* new_dialog = IM_NOTHING_SPECIAL */ ; | ||
2218 | } | ||
2219 | } | ||
2220 | pack_instant_message( | ||
2221 | gMessageSystem, | ||
2222 | gAgent.getID(), | ||
2223 | FALSE, | ||
2224 | gAgent.getSessionID(), | ||
2225 | other_participant_id, | ||
2226 | name.c_str(), | ||
2227 | utf8_text.c_str(), | ||
2228 | offline, | ||
2229 | (EInstantMessage)new_dialog, | ||
2230 | im_session_id); | ||
2231 | gAgent.sendReliableMessage(); | ||
2232 | |||
2233 | // If there is a mute list and this is not a group chat... | ||
2234 | if ( LLMuteList::getInstance() ) | ||
2235 | { | ||
2236 | // ... the target should not be in our mute list for some message types. | ||
2237 | // Auto-remove them if present. | ||
2238 | switch( dialog ) | ||
2239 | { | ||
2240 | case IM_NOTHING_SPECIAL: | ||
2241 | case IM_GROUP_INVITATION: | ||
2242 | case IM_INVENTORY_OFFERED: | ||
2243 | case IM_SESSION_INVITE: | ||
2244 | case IM_SESSION_P2P_INVITE: | ||
2245 | case IM_SESSION_CONFERENCE_START: | ||
2246 | case IM_SESSION_SEND: // This one is marginal - erring on the side of hearing. | ||
2247 | case IM_LURE_USER: | ||
2248 | case IM_GODLIKE_LURE_USER: | ||
2249 | case IM_FRIENDSHIP_OFFERED: | ||
2250 | LLMuteList::getInstance()->autoRemove(other_participant_id, LLMuteList::AR_IM); | ||
2251 | break; | ||
2252 | default: ; // do nothing | ||
2253 | } | ||
2254 | } | ||
2255 | } | ||
2256 | |||
2257 | // static | ||
2258 | void LLFloaterIMPanel::onClickOtr(LLUICtrl* source, void* userdata) | ||
2259 | { | ||
2260 | LLFloaterIMPanel* self = (LLFloaterIMPanel*) userdata; | ||
2261 | if (self) | ||
2262 | { | ||
2263 | self->doOtrMenu(); | ||
2264 | self->showOtrStatus(); | ||
2265 | } | ||
2266 | else | ||
2267 | { | ||
2268 | llwarns << "$PLOTR$ onClickOtr() can't find floater." << llendl; | ||
2269 | } | ||
2270 | } | ||
2271 | |||
2272 | void LLFloaterIMPanel::doOtrStart() | ||
2273 | { | ||
2274 | U32 otrpref = gSavedSettings.getU32("EmeraldUseOTR"); | ||
2275 | // otrpref: 0 == Require use of OTR in IMs, 1 == Request OTR if available, 2 == Accept OTR requests, 3 == Decline use of OTR | ||
2276 | if (3 == otrpref) | ||
2277 | { | ||
2278 | //otrLogMessageGetstring("otr_err_deacivated"); | ||
2279 | showOtrStatus(); | ||
2280 | return; | ||
2281 | } | ||
2282 | if (gOTR && (IM_NOTHING_SPECIAL == mDialog)) | ||
2283 | { | ||
2284 | llinfos << "$PLOTR$ otr menu start/restart/refresh" << llendl; | ||
2285 | gcry_error_t err = 0; | ||
2286 | char *newmessage = NULL; | ||
2287 | char my_uuid[UUID_STR_SIZE]; | ||
2288 | char their_uuid[UUID_STR_SIZE]; | ||
2289 | gAgent.getID().toString(&(my_uuid[0])); | ||
2290 | mOtherParticipantUUID.toString(&(their_uuid[0])); | ||
2291 | |||
2292 | const LLRelationship* info = NULL; | ||
2293 | info = LLAvatarTracker::instance().getBuddyInfo(mOtherParticipantUUID); | ||
2294 | if (info && (!info->isOnline())) | ||
2295 | { | ||
2296 | otrLogMessageGetstringName("otr_err_offline_start"); | ||
2297 | return; | ||
2298 | } | ||
2299 | |||
2300 | if (gOTR && (IM_NOTHING_SPECIAL == mDialog)) | ||
2301 | { | ||
2302 | // only try OTR for 1 on 1 IM's | ||
2303 | err = otrl_message_sending( | ||
2304 | gOTR->get_userstate(), | ||
2305 | gOTR->get_uistate(), | ||
2306 | &mSessionUUID, | ||
2307 | my_uuid, | ||
2308 | gOTR->get_protocolid(), | ||
2309 | their_uuid, | ||
2310 | "?OTRv2?", NULL, &newmessage, | ||
2311 | NULL, NULL); | ||
2312 | } | ||
2313 | if (err) | ||
2314 | { | ||
2315 | llwarns << "$PLOTR$ OTR failed to encrypt start message" << llendl; | ||
2316 | otrLogMessageGetstring("otr_err_failed_starting"); | ||
2317 | return; | ||
2318 | } | ||
2319 | else if (newmessage) | ||
2320 | { | ||
2321 | // OTR encrypted the message. Handle fragmentation of the message | ||
2322 | int context_added = 0; | ||
2323 | ConnContext *context = getOtrContext(1, &context_added); | ||
2324 | if (context_added) | ||
2325 | { | ||
2326 | llwarns << "$PLOTR$ context added *after* send start but before fragmentation." << llendl; | ||
2327 | } | ||
2328 | if (! context) | ||
2329 | { | ||
2330 | otrLogMessageGetstring("otr_err_failed_starting"); | ||
2331 | llwarns << "$PLOTR$ can't find context, not sending start message." << llendl; | ||
2332 | return; | ||
2333 | } | ||
2334 | else | ||
2335 | { | ||
2336 | char *extrafragment = NULL; | ||
2337 | err = otrl_message_fragment_and_send( | ||
2338 | gOTR->get_uistate(), | ||
2339 | &mSessionUUID, | ||
2340 | context, | ||
2341 | newmessage, | ||
2342 | OTRL_FRAGMENT_SEND_ALL, | ||
2343 | &extrafragment); | ||
2344 | } | ||
2345 | if (newmessage) otrl_message_free(newmessage); | ||
2346 | //otrLogMessageGetstringName("otr_prog_I_start"); | ||
2347 | } | ||
2348 | else | ||
2349 | { | ||
2350 | llwarns << "$PLOTR$ can't start OTR for some reason." << llendl; | ||
2351 | otrLogMessageGetstring("otr_err_failed_starting"); | ||
2352 | return; | ||
2353 | } | ||
2354 | } | ||
2355 | } | ||
2356 | |||
2357 | void LLFloaterIMPanel::doOtrStop(bool pretend_they_did) | ||
2358 | { | ||
2359 | llinfos << "$PLOTR$ otr menu stop 1" << llendl; | ||
2360 | // do not disable this bassed on gSavedSettings.getU32("EmeraldUseOTR"); | ||
2361 | // when the user disables OTR we may still need to stop currently encrypted conversations | ||
2362 | if (gOTR && (IM_NOTHING_SPECIAL == mDialog)) | ||
2363 | { | ||
2364 | char my_uuid[UUID_STR_SIZE]; | ||
2365 | char their_uuid[UUID_STR_SIZE]; | ||
2366 | gAgent.getID().toString(&(my_uuid[0])); | ||
2367 | mOtherParticipantUUID.toString(&(their_uuid[0])); | ||
2368 | llinfos << "$PLOTR$ otr menu stop 2 their_uuid:" << mOtherParticipantUUID << llendl; | ||
2369 | g_otr_force_typing_stop = true; // ugly hack | ||
2370 | otrl_message_disconnect( | ||
2371 | gOTR->get_userstate(), | ||
2372 | gOTR->get_uistate(), | ||
2373 | &mSessionUUID, | ||
2374 | my_uuid, | ||
2375 | gOTR->get_protocolid(), | ||
2376 | their_uuid); | ||
2377 | g_otr_force_typing_stop = false; | ||
2378 | if (pretend_they_did) | ||
2379 | { | ||
2380 | otrLogMessageGetstringName("otr_prog_they_stop"); | ||
2381 | } | ||
2382 | else | ||
2383 | { | ||
2384 | //otrLogMessageGetstringName("otr_prog_I_stop"); | ||
2385 | } | ||
2386 | showOtrStatus(); | ||
2387 | } | ||
2388 | } | ||
2389 | |||
2390 | void LLFloaterIMPanel::doOtrAuth() | ||
2391 | { | ||
2392 | if (mOtrSmpDialog) | ||
2393 | { | ||
2394 | llinfos << "$PLOTR$ mOtrSmpDialog SMP already in progress, ignoring request to start it" << llendl; | ||
2395 | return; | ||
2396 | } | ||
2397 | if (mOtrSmpDialog || mOtrSmpProgress) | ||
2398 | { | ||
2399 | llinfos << "$PLOTR$ SMP already in progress, ignoring request to start it" << llendl; | ||
2400 | // $TODO$ Tell the user nicely to cancel the one in progress. | ||
2401 | // $TODO$ better yet, cancel it/them for the user | ||
2402 | return; | ||
2403 | } | ||
2404 | if (gOTR && (IM_NOTHING_SPECIAL == mDialog)) | ||
2405 | { | ||
2406 | llinfos << "$PLOTR$ otr menu auth" << llendl; | ||
2407 | |||
2408 | ConnContext *context = getOtrContext(); | ||
2409 | if (!context) | ||
2410 | { | ||
2411 | llwarns << "$PLOTR$ doOtrAuth can't find context." << llendl; | ||
2412 | return; | ||
2413 | } | ||
2414 | char my_uuid[UUID_STR_SIZE]; | ||
2415 | gAgent.getID().toString(&(my_uuid[0])); | ||
2416 | char my_fingerprint[45]; | ||
2417 | otrl_privkey_fingerprint(gOTR->get_userstate(), | ||
2418 | my_fingerprint, | ||
2419 | my_uuid, | ||
2420 | gOTR->get_protocolid()); | ||
2421 | char other_fingerprint[45]; | ||
2422 | otrl_privkey_hash_to_human(other_fingerprint, context->active_fingerprint->fingerprint); | ||
2423 | startSmpDialog(mSessionUUID, mOtherParticipantUUID, | ||
2424 | &(my_fingerprint[0]), &(other_fingerprint[0])); | ||
2425 | } | ||
2426 | } | ||
2427 | |||
2428 | |||
2429 | void LLFloaterIMPanel::doOtrMenu() | ||
2430 | { | ||
2431 | if (gOTR && (IM_NOTHING_SPECIAL == mDialog)) | ||
2432 | { | ||
2433 | LLComboBox *combo = getChild<LLComboBox>("otr_btn"); | ||
2434 | if (!combo) | ||
2435 | { | ||
2436 | llwarns << "$PLOTR$ Can't find OTR control/status" << llendl; | ||
2437 | } | ||
2438 | else | ||
2439 | { | ||
2440 | ConnContext *context = getOtrContext(); | ||
2441 | U32 otrpref = gSavedSettings.getU32("EmeraldUseOTR"); | ||
2442 | if (combo->getValue().asString() == "otr_auth_entry") | ||
2443 | { | ||
2444 | // Instant crash when doing this with someone that has no OTR capability. | ||
2445 | // So guard it if no encryption is happening. | ||
2446 | if (context && (OTRL_MSGSTATE_ENCRYPTED == context->msgstate)) | ||
2447 | { | ||
2448 | doOtrAuth(); | ||
2449 | } | ||
2450 | } | ||
2451 | else if (combo->getValue().asString() == "otr_help_entry") | ||
2452 | { | ||
2453 | llinfos << "$PLOTR$ otr help" << llendl; | ||
2454 | LLWeb::loadURL("http://www.cypherpunks.ca/otr/"); | ||
2455 | } | ||
2456 | else if (combo->getValue().asString() == "otr_levels_entry") | ||
2457 | { | ||
2458 | llinfos << "$PLOTR$ otr levels help" << llendl; | ||
2459 | LLWeb::loadURL("http://www.cypherpunks.ca/otr/help/3.2.0/levels.php"); | ||
2460 | } | ||
2461 | else // Clicked the flyout itself. Sort out what level to put them in based on the old level. | ||
2462 | { | ||
2463 | // otrpref: 0 == Require OTR, 1 == Request OTR, 2 == Accept OTR, 3 == Decline OTR | ||
2464 | if (3 == otrpref) | ||
2465 | { | ||
2466 | if (context && (OTRL_MSGSTATE_ENCRYPTED == context->msgstate)) | ||
2467 | { | ||
2468 | doOtrStop(); | ||
2469 | } | ||
2470 | } | ||
2471 | else if (context && (OTRL_MSGSTATE_ENCRYPTED == context->msgstate)) | ||
2472 | { | ||
2473 | doOtrStop(); | ||
2474 | } | ||
2475 | else if (context && (OTRL_MSGSTATE_FINISHED == context->msgstate)) | ||
2476 | { | ||
2477 | doOtrStop(); | ||
2478 | } | ||
2479 | else // OTRL_MSGSTATE_PLAINTEXT, or no context yet | ||
2480 | { | ||
2481 | doOtrStart(); | ||
2482 | } | ||
2483 | } | ||
2484 | } | ||
2485 | } | ||
2486 | } | ||
2487 | |||
2488 | ConnContext *LLFloaterIMPanel::getOtrContext(int create_if_not_found, int *context_added) | ||
2489 | { | ||
2490 | ConnContext *context = NULL; | ||
2491 | if (gOTR && (IM_NOTHING_SPECIAL == mDialog)) | ||
2492 | { | ||
2493 | char my_uuid[UUID_STR_SIZE]; | ||
2494 | char their_uuid[UUID_STR_SIZE]; | ||
2495 | gAgent.getID().toString(&(my_uuid[0])); | ||
2496 | mOtherParticipantUUID.toString(&(their_uuid[0])); | ||
2497 | context = otrl_context_find( | ||
2498 | gOTR->get_userstate(), | ||
2499 | their_uuid, | ||
2500 | my_uuid, | ||
2501 | gOTR->get_protocolid(), | ||
2502 | create_if_not_found, context_added, NULL, NULL); | ||
2503 | } | ||
2504 | return context; | ||
2505 | } | ||
2506 | |||
2507 | bool LLFloaterIMPanel::otherIsOtrAuthenticated() | ||
2508 | { | ||
2509 | if (gOTR && (IM_NOTHING_SPECIAL == mDialog)) | ||
2510 | { | ||
2511 | ConnContext *context = getOtrContext(); | ||
2512 | if (context && context->active_fingerprint && | ||
2513 | context->active_fingerprint->trust && | ||
2514 | *(context->active_fingerprint->trust)) | ||
2515 | { | ||
2516 | llinfos << "$PLOTR$ they are authenticated -- trust level is " | ||
2517 | << (context->active_fingerprint->trust) << llendl; | ||
2518 | return true; | ||
2519 | } | ||
2520 | } | ||
2521 | llinfos << "$PLOTR$ they are NOT authenticated" << llendl; | ||
2522 | return false; | ||
2523 | } | ||
2524 | |||
2525 | void LLFloaterIMPanel::showOtrStatus() | ||
2526 | { | ||
2527 | if (gOTR && (IM_NOTHING_SPECIAL == mDialog)) | ||
2528 | { | ||
2529 | LLFlyoutButton *combo = (LLFlyoutButton *) getChild<LLComboBox>("otr_btn"); | ||
2530 | if (!combo) | ||
2531 | { | ||
2532 | llerrs << "$PLOTR$ Can't find OTR control/status" << llendl; | ||
2533 | } | ||
2534 | else | ||
2535 | { | ||
2536 | ConnContext *context = getOtrContext(); | ||
2537 | U32 otrpref = gSavedSettings.getU32("EmeraldUseOTR"); | ||
2538 | // otrpref: 0 == Require OTR, 1 == Request OTR, 2 == Accept OTR, 3 == Decline OTR | ||
2539 | if (3 == otrpref) | ||
2540 | { | ||
2541 | if (context && (OTRL_MSGSTATE_ENCRYPTED == context->msgstate)) | ||
2542 | { | ||
2543 | doOtrStop(); | ||
2544 | } | ||
2545 | combo->setLabel(getString("otr_not_private")); | ||
2546 | } | ||
2547 | else if (context && (OTRL_MSGSTATE_ENCRYPTED == context->msgstate)) | ||
2548 | { | ||
2549 | if (otherIsOtrAuthenticated()) | ||
2550 | combo->setLabel(getString("otr_private")); | ||
2551 | else | ||
2552 | combo->setLabel(getString("otr_unverified")); | ||
2553 | } | ||
2554 | else if (context && (OTRL_MSGSTATE_FINISHED == context->msgstate)) | ||
2555 | { | ||
2556 | if (OTRL_MSGSTATE_ENCRYPTED == mOtrLastStatus) | ||
2557 | { | ||
2558 | if (otherIsOtrAuthenticated()) | ||
2559 | otrLogMessageGetstringName("otr_prog_they_stop_private"); | ||
2560 | else | ||
2561 | otrLogMessageGetstringName("otr_prog_they_stop_unverified"); | ||
2562 | } | ||
2563 | combo->setLabel(getString("otr_finished")); | ||
2564 | } | ||
2565 | else // OTRL_MSGSTATE_PLAINTEXT, or no context yet | ||
2566 | { | ||
2567 | combo->setLabel(getString("otr_not_private")); | ||
2568 | } | ||
2569 | if (context) | ||
2570 | { | ||
2571 | mOtrLastStatus = context->msgstate; | ||
2572 | } | ||
2573 | } | ||
2574 | } | ||
2575 | } | ||
2576 | |||
2577 | void LLFloaterIMPanel::otrLogMessage(std::string message) | ||
2578 | { | ||
2579 | addHistoryLine(message, gSavedSettings.getColor("SystemChatColor"), true, mOtherParticipantUUID); | ||
2580 | } | ||
2581 | |||
2582 | void LLFloaterIMPanel::otrLogMessageGetstring(const char *message_name) | ||
2583 | { | ||
2584 | LLUIString msg = getString(message_name); | ||
2585 | otrLogMessage(msg); | ||
2586 | } | ||
2587 | |||
2588 | void LLFloaterIMPanel::otrLogMessageGetstringName(const char *message_name) | ||
2589 | { | ||
2590 | LLUIString msg = getString(message_name); | ||
2591 | std::string them; | ||
2592 | if (!gCacheName->getFullName(mOtherParticipantUUID, them)) them = getString("otr_generic_name"); | ||
2593 | msg.setArg("[NAME]", them); | ||
2594 | otrLogMessage(msg); | ||
2595 | } | ||
2596 | |||
2597 | void otr_log_message(LLUUID session_id, const char *message) | ||
2598 | { | ||
2599 | LLFloaterIMPanel* floater = gIMMgr->findFloaterBySession(session_id); | ||
2600 | if (floater) floater->otrLogMessage(message); | ||
2601 | else | ||
2602 | { | ||
2603 | llinfos << "$PLOTR$ otr_log_message(" << message << ") failed to find floater." << llendl; | ||
2604 | } | ||
2605 | } | ||
2606 | |||
2607 | void otr_log_message_getstring(LLUUID session_id, const char *message_name) | ||
2608 | { | ||
2609 | LLFloaterIMPanel* floater = gIMMgr->findFloaterBySession(session_id); | ||
2610 | if (floater) floater->otrLogMessageGetstring(message_name); | ||
2611 | else | ||
2612 | { | ||
2613 | llinfos << "$PLOTR$ otr_log_message_getstring(" << message_name << ") failed to find floater." << llendl; | ||
2614 | } | ||
2615 | } | ||
2616 | |||
2617 | void otr_log_message_getstring_name(LLUUID session_id, const char *message_name) | ||
2618 | { | ||
2619 | LLFloaterIMPanel* floater = gIMMgr->findFloaterBySession(session_id); | ||
2620 | if (floater) floater->otrLogMessageGetstringName(message_name); | ||
2621 | else | ||
2622 | { | ||
2623 | llinfos << "$PLOTR$ otr_log_message_getstring_name(" << message_name << ") failed to find floater." << llendl; | ||
2624 | } | ||
2625 | } | ||
2626 | |||
2627 | void LLFloaterIMPanel::otrAuthenticateKey(const char *trust) | ||
2628 | { | ||
2629 | int context_added = 0; | ||
2630 | ConnContext *context = getOtrContext(0, &context_added); | ||
2631 | if (gOTR && context) | ||
2632 | { | ||
2633 | otrl_context_set_trust(context->active_fingerprint, trust); | ||
2634 | otrLogMessageGetstringName("otr_log_authenticated"); | ||
2635 | otrLogMessageGetstringName("otr_log_start_private"); | ||
2636 | std::string pubpath = | ||
2637 | gDirUtilp->getExpandedFilename( | ||
2638 | LL_PATH_PER_SL_ACCOUNT, OTR_PUBLIC_KEYS_FILE); | ||
2639 | otrl_privkey_write_fingerprints(gOTR->get_userstate(), pubpath.c_str()); | ||
2640 | showOtrStatus(); | ||
2641 | } | ||
2642 | } | ||
2643 | |||
2644 | void otr_authenticate_key(LLUUID session_id, const char *trust) | ||
2645 | { | ||
2646 | LLFloaterIMPanel* floater = gIMMgr->findFloaterBySession(session_id); | ||
2647 | if (floater) floater->otrAuthenticateKey(trust); | ||
2648 | else | ||
2649 | { | ||
2650 | llinfos << "$PLOTR$ otr_authenticate_key(" << session_id << ", " << trust << ") failed to find floater." << llendl; | ||
2651 | } | ||
2652 | } | ||
2653 | |||
2654 | void otr_show_status(LLUUID session_id) | ||
2655 | { | ||
2656 | LLFloaterIMPanel* floater = gIMMgr->findFloaterBySession(session_id); | ||
2657 | if (floater) floater->showOtrStatus(); | ||
2658 | else | ||
2659 | { | ||
2660 | llinfos << "$PLOTR$ can't find floater." << llendl; | ||
2661 | } | ||
2662 | } | ||
2663 | |||
2664 | void LLFloaterIMPanel::pretendTheyOtrStop() | ||
2665 | { | ||
2666 | llinfos << "$PLOTR$ pretending they did doOtrStop()" << llendl; | ||
2667 | // we really stop our end, but... | ||
2668 | doOtrStop(true); // ... pretend that they did it | ||
2669 | ConnContext *context = getOtrContext(); | ||
2670 | if (context) context->msgstate = OTRL_MSGSTATE_FINISHED; | ||
2671 | else | ||
2672 | { | ||
2673 | llwarns << "$PLOTR$ can't find context." << llendl; | ||
2674 | } | ||
2675 | showOtrStatus(); | ||
2676 | } | ||
2677 | |||
2678 | void LLFloaterIMPanel::startSmpDialog( | ||
2679 | LLUUID session_id, LLUUID other_id, | ||
2680 | std::string my_fingerprint, std::string other_fingerprint) | ||
2681 | { | ||
2682 | if (mOtrSmpDialog) | ||
2683 | { | ||
2684 | mOtrSmpDialog->close(); | ||
2685 | delete mOtrSmpDialog; | ||
2686 | } | ||
2687 | mOtrSmpDialog = new OtrFloaterSmpDialog( | ||
2688 | this, mSessionUUID, mOtherParticipantUUID, | ||
2689 | my_fingerprint, other_fingerprint); | ||
2690 | if (mOtrSmpDialog) mOtrSmpDialog->show(); | ||
2691 | else | ||
2692 | { | ||
2693 | llwarns << "$PLOTR$ couldn't new OtrFloaterSmpDialog" << llendl; | ||
2694 | } | ||
2695 | } | ||
2696 | |||
2697 | void LLFloaterIMPanel::startSmpDialogQA( | ||
2698 | LLUUID session_id, LLUUID other_id, std::string question, OtrlTLV *tlv) | ||
2699 | { | ||
2700 | if (mOtrSmpDialog) | ||
2701 | { | ||
2702 | mOtrSmpDialog->close(); | ||
2703 | delete mOtrSmpDialog; | ||
2704 | } | ||
2705 | mOtrSmpDialog = new OtrFloaterSmpDialog( | ||
2706 | this, mSessionUUID, mOtherParticipantUUID, question, tlv); | ||
2707 | if (mOtrSmpDialog) mOtrSmpDialog->show(); | ||
2708 | else | ||
2709 | { | ||
2710 | llwarns << "$PLOTR$ couldn't new OtrFloaterSmpDialog" << llendl; | ||
2711 | } | ||
2712 | } | ||
2713 | |||
2714 | void LLFloaterIMPanel::startSmpDialogSS( | ||
2715 | LLUUID session_id, LLUUID other_id, OtrlTLV *tlv) | ||
2716 | { | ||
2717 | if (mOtrSmpDialog) | ||
2718 | { | ||
2719 | mOtrSmpDialog->close(); | ||
2720 | delete mOtrSmpDialog; | ||
2721 | } | ||
2722 | mOtrSmpDialog = new OtrFloaterSmpDialog( | ||
2723 | this, mSessionUUID, mOtherParticipantUUID, tlv); | ||
2724 | if (mOtrSmpProgress) mOtrSmpDialog->show(); | ||
2725 | else | ||
2726 | { | ||
2727 | llwarns << "$PLOTR$ couldn't new OtrFloaterSmpDialog" << llendl; | ||
2728 | } | ||
2729 | } | ||
2730 | |||
2731 | void LLFloaterIMPanel::endSmpDialog() | ||
2732 | { | ||
2733 | if (!mOtrSmpDialog) | ||
2734 | { | ||
2735 | llwarns << "$PLOTR$ couldn't find OtrFloaterSmpDialog" << llendl; | ||
2736 | } | ||
2737 | else | ||
2738 | { | ||
2739 | delete mOtrSmpDialog; | ||
2740 | mOtrSmpDialog = NULL; | ||
2741 | } | ||
2742 | } | ||
2743 | |||
2744 | void LLFloaterIMPanel::startSmpProgress( | ||
2745 | LLUUID session_id, LLUUID other_id, | ||
2746 | std::string a_question, std::string a_secret_answer, bool is_reply) | ||
2747 | { | ||
2748 | if (mOtrSmpProgress) | ||
2749 | { | ||
2750 | mOtrSmpProgress->close(); | ||
2751 | delete mOtrSmpProgress; | ||
2752 | } | ||
2753 | mOtrSmpProgress = | ||
2754 | new OtrFloaterSmpProgress(this, mSessionUUID, mOtherParticipantUUID, | ||
2755 | a_question, a_secret_answer, is_reply); | ||
2756 | if (mOtrSmpProgress) mOtrSmpProgress->show(); | ||
2757 | else | ||
2758 | { | ||
2759 | llwarns << "$PLOTR$ couldn't new OtrFloaterSmpProgress" << llendl; | ||
2760 | } | ||
2761 | } | ||
2762 | |||
2763 | void LLFloaterIMPanel::startSmpProgress( | ||
2764 | LLUUID session_id, LLUUID other_id, | ||
2765 | std::string a_secret, bool is_reply) | ||
2766 | { | ||
2767 | if (mOtrSmpProgress) | ||
2768 | { | ||
2769 | mOtrSmpProgress->close(); | ||
2770 | delete mOtrSmpProgress; | ||
2771 | } | ||
2772 | mOtrSmpProgress = | ||
2773 | new OtrFloaterSmpProgress(this, mSessionUUID, mOtherParticipantUUID, | ||
2774 | a_secret, is_reply); | ||
2775 | if (mOtrSmpProgress) mOtrSmpProgress->show(); | ||
2776 | else | ||
2777 | { | ||
2778 | llwarns << "$PLOTR$ couldn't new OtrFloaterSmpProgress" << llendl; | ||
2779 | } | ||
2780 | } | ||
2781 | |||
2782 | void LLFloaterIMPanel::endSmpProgress() | ||
2783 | { | ||
2784 | if (!mOtrSmpProgress) | ||
2785 | { | ||
2786 | llwarns << "$PLOTR$ couldn't find OtrFloaterSmpProgress" << llendl; | ||
2787 | } | ||
2788 | else | ||
2789 | { | ||
2790 | delete mOtrSmpProgress; | ||
2791 | mOtrSmpProgress = NULL; | ||
2792 | } | ||
2793 | } | ||
2794 | |||
2795 | void LLFloaterIMPanel::handleOtrTlvs(OtrlTLV *tlvs) | ||
2796 | { | ||
2797 | ConnContext *context = getOtrContext(); | ||
2798 | if (! context) | ||
2799 | { | ||
2800 | llwarns << "$PLOTR$ Can't find otr context" << llendl; | ||
2801 | return; | ||
2802 | } | ||
2803 | if (! context->smstate) | ||
2804 | { | ||
2805 | llwarns << "$PLOTR$ OTR context doesn't have smstate" << llendl; | ||
2806 | return; | ||
2807 | } | ||
2808 | if (context->smstate->sm_prog_state == OTRL_SMP_PROG_CHEATED) | ||
2809 | { | ||
2810 | if (mOtrSmpProgress) mOtrSmpProgress->setFinalStatus("otr_smp_prog_auth_errored"); | ||
2811 | context->smstate->nextExpected = OTRL_SMP_EXPECT1; | ||
2812 | context->smstate->sm_prog_state = OTRL_SMP_PROG_OK; | ||
2813 | return; | ||
2814 | } | ||
2815 | NextExpectedSMP nextMsg = context->smstate->nextExpected; | ||
2816 | OtrlTLV *tlv = NULL; | ||
2817 | tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP1Q); | ||
2818 | if (tlv) | ||
2819 | { | ||
2820 | if (nextMsg != OTRL_SMP_EXPECT1) | ||
2821 | { | ||
2822 | if (mOtrSmpProgress) mOtrSmpProgress->setFinalStatus("otr_smp_prog_auth_errored"); | ||
2823 | return; | ||
2824 | } | ||
2825 | // Start a challenge SMP dialog | ||
2826 | char *question = (char *)tlv->data; | ||
2827 | char *eoq = (char *)memchr(question, '\0', tlv->len); | ||
2828 | if (!eoq) | ||
2829 | { | ||
2830 | llwarns << "$PLOTR$ bad format in OTRL_TLV_SMP1Q, no end to question." << llendl; | ||
2831 | if (mOtrSmpProgress) mOtrSmpProgress->setFinalStatus("otr_smp_prog_auth_errored"); | ||
2832 | return; | ||
2833 | } | ||
2834 | startSmpDialogQA(mSessionUUID, mOtherParticipantUUID, question, tlv); | ||
2835 | if (mOtrSmpProgress) mOtrSmpProgress->setPercent(25); | ||
2836 | return; | ||
2837 | } | ||
2838 | tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP1); | ||
2839 | if (tlv) | ||
2840 | { | ||
2841 | if (nextMsg != OTRL_SMP_EXPECT1) | ||
2842 | { | ||
2843 | if (mOtrSmpProgress) mOtrSmpProgress->setFinalStatus("otr_smp_prog_auth_errored"); | ||
2844 | return; | ||
2845 | } | ||
2846 | // Start a challenge SMP dialog | ||
2847 | startSmpDialogSS(mSessionUUID, mOtherParticipantUUID, tlv); | ||
2848 | if (mOtrSmpProgress) mOtrSmpProgress->setPercent(25); | ||
2849 | return; | ||
2850 | } | ||
2851 | tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP2); | ||
2852 | if (tlv) | ||
2853 | { | ||
2854 | if (nextMsg != OTRL_SMP_EXPECT2) | ||
2855 | { | ||
2856 | if (mOtrSmpProgress) mOtrSmpProgress->setFinalStatus("otr_smp_prog_auth_errored"); | ||
2857 | return; | ||
2858 | } | ||
2859 | else | ||
2860 | { | ||
2861 | // If we received TLV2, we will send TLV3 and expect TLV4 | ||
2862 | context->smstate->nextExpected = OTRL_SMP_EXPECT4; | ||
2863 | if (mOtrSmpProgress) mOtrSmpProgress->setPercent(75); | ||
2864 | } | ||
2865 | } | ||
2866 | tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP3); | ||
2867 | if (tlv) | ||
2868 | { | ||
2869 | if (nextMsg != OTRL_SMP_EXPECT3) | ||
2870 | { | ||
2871 | if (mOtrSmpProgress) mOtrSmpProgress->setFinalStatus("otr_smp_prog_auth_errored"); | ||
2872 | return; | ||
2873 | } | ||
2874 | else | ||
2875 | { | ||
2876 | // If we received TLV3, we will send TLV4 | ||
2877 | // We will not expect more messages, so prepare for next SMP | ||
2878 | context->smstate->nextExpected = OTRL_SMP_EXPECT1; | ||
2879 | // Report result to user | ||
2880 | if (context->smstate->sm_prog_state == OTRL_SMP_PROG_SUCCEEDED) | ||
2881 | { | ||
2882 | if (context->active_fingerprint && | ||
2883 | context->active_fingerprint->trust && | ||
2884 | *(context->active_fingerprint->trust)) | ||
2885 | { | ||
2886 | // they authed me OK, and I already authed them in the past | ||
2887 | if (mOtrSmpProgress) mOtrSmpProgress->setFinalStatus("otr_smp_prog_auth_ok"); | ||
2888 | } | ||
2889 | else | ||
2890 | { | ||
2891 | // they authed me OK, but I haven't authed them yet | ||
2892 | if (mOtrSmpProgress) mOtrSmpProgress->setFinalStatus("otr_smp_prog_auth_ok_name_next"); | ||
2893 | } | ||
2894 | } | ||
2895 | else | ||
2896 | { | ||
2897 | if (mOtrSmpProgress) mOtrSmpProgress->setFinalStatus("otr_smp_prog_auth_failed"); | ||
2898 | } | ||
2899 | } | ||
2900 | } | ||
2901 | tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP4); | ||
2902 | if (tlv) | ||
2903 | { | ||
2904 | if (nextMsg != OTRL_SMP_EXPECT4) | ||
2905 | { | ||
2906 | if (mOtrSmpProgress) mOtrSmpProgress->setFinalStatus("otr_smp_prog_auth_errored"); | ||
2907 | return; | ||
2908 | } | ||
2909 | else { | ||
2910 | // We will not expect more messages, so prepare for next SMP | ||
2911 | context->smstate->nextExpected = OTRL_SMP_EXPECT1; | ||
2912 | // Report result to user | ||
2913 | if (context->active_fingerprint && | ||
2914 | context->active_fingerprint->trust && | ||
2915 | *(context->active_fingerprint->trust)) | ||
2916 | { | ||
2917 | if (mOtrSmpProgress) mOtrSmpProgress->setFinalStatus("otr_smp_prog_auth_ok"); | ||
2918 | } | ||
2919 | else | ||
2920 | { | ||
2921 | if (mOtrSmpProgress) mOtrSmpProgress->setFinalStatus("otr_smp_prog_auth_failed"); | ||
2922 | } | ||
2923 | } | ||
2924 | } | ||
2925 | tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP_ABORT); | ||
2926 | if (tlv) | ||
2927 | { | ||
2928 | // The message we are waiting for will not arrive, so reset | ||
2929 | // and prepare for the next SMP | ||
2930 | context->smstate->nextExpected = OTRL_SMP_EXPECT1; | ||
2931 | if (mOtrSmpProgress) mOtrSmpProgress->setFinalStatus("otr_smp_prog_auth_aborted"); | ||
2932 | } | ||
2933 | } | ||
2934 | #endif // USE_OTR // [/$PLOTR$] | ||
2935 | |||
2122 | void LLFloaterIMPanel::sendMsg() | 2936 | void LLFloaterIMPanel::sendMsg() |
2123 | { | 2937 | { |
2124 | if (!gAgent.isGodlike() | 2938 | if (!gAgent.isGodlike() |
@@ -2211,11 +3025,137 @@ void LLFloaterIMPanel::sendMsg() | |||
2211 | 3025 | ||
2212 | if ( mSessionInitialized ) | 3026 | if ( mSessionInitialized ) |
2213 | { | 3027 | { |
3028 | #if USE_OTR // [$PLOTR$] | ||
3029 | const LLRelationship* info = NULL; | ||
3030 | info = LLAvatarTracker::instance().getBuddyInfo(mOtherParticipantUUID); | ||
3031 | ConnContext *context = getOtrContext(1); | ||
3032 | if (info && (!info->isOnline()) && context && | ||
3033 | ( (OTRL_MSGSTATE_ENCRYPTED == context->msgstate) | ||
3034 | || (OTRL_MSGSTATE_FINISHED == context->msgstate))) | ||
3035 | { | ||
3036 | // we can't continue this encrypted session but we | ||
3037 | // can't let the user accidentally send unencrypted | ||
3038 | if (OTRL_MSGSTATE_ENCRYPTED == context->msgstate) | ||
3039 | pretendTheyOtrStop(); | ||
3040 | otrLogMessageGetstringName("otr_err_offline_send"); | ||
3041 | return; // leave the unsent message in the edit box | ||
3042 | } | ||
3043 | |||
3044 | gcry_error_t err = 0; | ||
3045 | char *newmessage = NULL; | ||
3046 | char my_uuid[UUID_STR_SIZE]; | ||
3047 | char their_uuid[UUID_STR_SIZE]; | ||
3048 | gAgent.getID().toString(&(my_uuid[0])); | ||
3049 | mOtherParticipantUUID.toString(&(their_uuid[0])); | ||
3050 | |||
3051 | bool was_finished = false; | ||
3052 | if (gOTR && context && (context->msgstate == OTRL_MSGSTATE_FINISHED)) | ||
3053 | { | ||
3054 | was_finished = true; | ||
3055 | } | ||
3056 | else if (gOTR && (IM_NOTHING_SPECIAL == mDialog)) | ||
3057 | { | ||
3058 | // only try OTR for 1 on 1 IM's | ||
3059 | err = otrl_message_sending( | ||
3060 | gOTR->get_userstate(), | ||
3061 | gOTR->get_uistate(), | ||
3062 | &mSessionUUID, | ||
3063 | my_uuid, | ||
3064 | gOTR->get_protocolid(), | ||
3065 | their_uuid, | ||
3066 | &(utf8_text[0]), NULL, &newmessage, | ||
3067 | NULL, NULL); | ||
3068 | } | ||
3069 | context = getOtrContext(); | ||
3070 | if (err) | ||
3071 | { | ||
3072 | otrLogMessageGetstring("otr_err_failed_sending"); | ||
3073 | return; // leave the unsent message in the edit box | ||
3074 | } | ||
3075 | if (was_finished) | ||
3076 | { | ||
3077 | llinfos << "$PLOTR$ OTR tried to send into finished conv, not sending message!" << llendl; | ||
3078 | //otrLogMessageGetstringName("otr_err_send_in_finished"); //Don't error and tell the user to restart, just restart instead! | ||
3079 | doOtrStart(); | ||
3080 | return; // leave the unsent message in the edit box | ||
3081 | } | ||
3082 | OtrlMessageType msgtype = OTRL_MSGTYPE_NOTOTR; | ||
3083 | if (newmessage) msgtype = otrl_proto_message_type(newmessage); | ||
3084 | if (newmessage && (OTRL_MSGTYPE_TAGGEDPLAINTEXT == msgtype)) | ||
3085 | { | ||
3086 | // OTR just added the whitespace tag. | ||
3087 | otrl_message_free(newmessage); // don't send the message with whitespace tag | ||
3088 | err = otrl_message_sending( | ||
3089 | gOTR->get_userstate(), | ||
3090 | gOTR->get_uistate(), | ||
3091 | &mSessionUUID, | ||
3092 | my_uuid, | ||
3093 | gOTR->get_protocolid(), | ||
3094 | their_uuid, | ||
3095 | "typing", NULL, &newmessage, | ||
3096 | NULL, NULL); | ||
3097 | if (!newmessage) | ||
3098 | { | ||
3099 | llwarns << "$PLOTR$ shouldn't happen, OTR should keep adding whitespace tags till we get a reply from them." << llendl; | ||
3100 | } | ||
3101 | else | ||
3102 | { | ||
3103 | // deliver a whitespace tagged "typing" in a IM_TYPING_STOP packet | ||
3104 | std::string my_name; | ||
3105 | gAgent.buildFullname(my_name); | ||
3106 | const LLRelationship* info = NULL; | ||
3107 | info = LLAvatarTracker::instance().getBuddyInfo(mOtherParticipantUUID); | ||
3108 | U8 offline = (!info || info->isOnline()) ? IM_ONLINE : IM_OFFLINE; | ||
3109 | pack_instant_message( | ||
3110 | gMessageSystem, | ||
3111 | gAgent.getID(), | ||
3112 | FALSE, | ||
3113 | gAgent.getSessionID(), | ||
3114 | mOtherParticipantUUID, | ||
3115 | my_name, | ||
3116 | newmessage, | ||
3117 | offline, | ||
3118 | IM_TYPING_STOP, | ||
3119 | mSessionUUID); | ||
3120 | gAgent.sendReliableMessage(); | ||
3121 | otrl_message_free(newmessage); | ||
3122 | newmessage = NULL; | ||
3123 | } | ||
3124 | } | ||
3125 | if (newmessage) | ||
3126 | { | ||
3127 | // OTR encrypted the message | ||
3128 | if (! context) | ||
3129 | { | ||
3130 | llwarns << "$PLOTR$ can't find context, not sending message." << llendl; | ||
3131 | otrLogMessageGetstring("otr_err_failed_sending"); | ||
3132 | return; // leave the unsent message in the edit box | ||
3133 | } | ||
3134 | |||
3135 | { | ||
3136 | // Handle fragmentation of the message | ||
3137 | char *extrafragment = NULL; | ||
3138 | err = otrl_message_fragment_and_send( | ||
3139 | gOTR->get_uistate(), | ||
3140 | &mSessionUUID, | ||
3141 | context, | ||
3142 | newmessage, | ||
3143 | OTRL_FRAGMENT_SEND_ALL, | ||
3144 | &extrafragment); | ||
3145 | } | ||
3146 | if (newmessage) otrl_message_free(newmessage); | ||
3147 | showOtrStatus(); | ||
3148 | } | ||
3149 | else | ||
3150 | { // OTR didn't encrypt, or we didn't try cause it's not 1:1 IM | ||
3151 | #endif // USE_OTR // [/$PLOTR$] | ||
2214 | deliver_message(utf8_text, | 3152 | deliver_message(utf8_text, |
2215 | mSessionUUID, | 3153 | mSessionUUID, |
2216 | mOtherParticipantUUID, | 3154 | mOtherParticipantUUID, |
2217 | mDialog); | 3155 | mDialog); |
2218 | 3156 | #if USE_OTR // [$PLOTR$] | |
3157 | } | ||
3158 | #endif // USE_OTR // [/$PLOTR$] | ||
2219 | // local echo | 3159 | // local echo |
2220 | if((mDialog == IM_NOTHING_SPECIAL) && | 3160 | if((mDialog == IM_NOTHING_SPECIAL) && |
2221 | (mOtherParticipantUUID.notNull())) | 3161 | (mOtherParticipantUUID.notNull())) |
@@ -2242,16 +3182,31 @@ void LLFloaterIMPanel::sendMsg() | |||
2242 | std::string prefix = utf8_text.substr(0, 4); | 3182 | std::string prefix = utf8_text.substr(0, 4); |
2243 | if (prefix == "/me " || prefix == "/me'") | 3183 | if (prefix == "/me " || prefix == "/me'") |
2244 | { | 3184 | { |
3185 | #if USE_OTR // [$PLOTR$] | ||
3186 | if (isEncrypted()) | ||
3187 | utf8_text.replace(0,3,"\xe2\x80\xa7"); | ||
3188 | else | ||
3189 | #endif // USE_OTR // [/$PLOTR$] | ||
2245 | utf8_text.replace(0,3,""); | 3190 | utf8_text.replace(0,3,""); |
2246 | } | 3191 | } |
2247 | else | 3192 | else |
2248 | { | 3193 | { |
3194 | #if USE_OTR // [$PLOTR$] | ||
3195 | if (isEncrypted()) | ||
3196 | history_echo += "\xe2\x80\xa7: "; | ||
3197 | else | ||
3198 | #endif // USE_OTR // [/$PLOTR$] | ||
2249 | history_echo += ": "; | 3199 | history_echo += ": "; |
2250 | } | 3200 | } |
2251 | history_echo += utf8_text; | 3201 | history_echo += utf8_text; |
2252 | 3202 | ||
2253 | BOOL other_was_typing = mOtherTyping; | 3203 | BOOL other_was_typing = mOtherTyping; |
2254 | 3204 | ||
3205 | #if USE_OTR // [$PLOTR$] | ||
3206 | if (isEncrypted()) | ||
3207 | addHistoryLine(history_echo, gSavedSettings.getColor("IMEncryptedChatColor"), true, gAgent.getID()); | ||
3208 | else | ||
3209 | #endif // USE_OTR // [/$PLOTR$] | ||
2255 | addHistoryLine(history_echo, gSavedSettings.getColor("IMChatColor"), true, gAgent.getID()); | 3210 | addHistoryLine(history_echo, gSavedSettings.getColor("IMChatColor"), true, gAgent.getID()); |
2256 | 3211 | ||
2257 | if (other_was_typing) | 3212 | if (other_was_typing) |
@@ -2482,7 +3437,27 @@ void LLFloaterIMPanel::chatFromLogFile(LLLogChat::ELogLineType type, std::string | |||
2482 | //self->addHistoryLine(line, LLColor4::grey, FALSE); | 3437 | //self->addHistoryLine(line, LLColor4::grey, FALSE); |
2483 | self->mHistoryEditor->appendColoredText(message, false, true, LLColor4::grey); | 3438 | self->mHistoryEditor->appendColoredText(message, false, true, LLColor4::grey); |
2484 | } | 3439 | } |
2485 | 3440 | #if 0 | |
3441 | // user is known to be offline when we receive this | ||
3442 | void LLFloaterIMPanel::setOffline() | ||
3443 | { | ||
3444 | if(!gAgent.isGodlike()) | ||
3445 | { | ||
3446 | childSetEnabled("profile_tele_btn", false); | ||
3447 | } | ||
3448 | #if USE_OTR // [$PLOTR$] | ||
3449 | llinfos << "$PLOTR$ friend went offline" << llendl; | ||
3450 | if (gOTR) | ||
3451 | { | ||
3452 | ConnContext *context = getOtrContext(); | ||
3453 | if (context && (context->msgstate == OTRL_MSGSTATE_ENCRYPTED)) | ||
3454 | { | ||
3455 | pretendTheyOtrStop(); | ||
3456 | } | ||
3457 | } | ||
3458 | #endif // USE_OTR // [/$PLOTR$] | ||
3459 | } | ||
3460 | #endif // 0 | ||
2486 | void LLFloaterIMPanel::showSessionStartError( | 3461 | void LLFloaterIMPanel::showSessionStartError( |
2487 | const std::string& error_string) | 3462 | const std::string& error_string) |
2488 | { | 3463 | { |
@@ -2568,3 +3543,14 @@ bool LLFloaterIMPanel::onConfirmForceCloseError(const LLSD& notification, const | |||
2568 | } | 3543 | } |
2569 | 3544 | ||
2570 | 3545 | ||
3546 | #if USE_OTR // [$PLOTR$] | ||
3547 | bool LLFloaterIMPanel::isEncrypted() | ||
3548 | { | ||
3549 | if (gOTR) | ||
3550 | { | ||
3551 | ConnContext *context = getOtrContext(); | ||
3552 | if (context && (context->msgstate == OTRL_MSGSTATE_ENCRYPTED)) return true; | ||
3553 | } | ||
3554 | return false; | ||
3555 | } | ||
3556 | #endif // USE_OTR // [/$PLOTR$] | ||