Merge branch 'DRTVWR-573-maint-R' of https://github.com/secondlife/viewer

# Conflicts:
#	indra/newview/llimprocessing.cpp
#	indra/newview/llimview.cpp
#	indra/newview/llimview.h
#	indra/newview/lllogchat.cpp
meow-7.2.2
Ansariel 2023-02-14 23:23:36 +01:00
commit 86253a8d8a
8 changed files with 709 additions and 244 deletions

View File

@ -878,6 +878,7 @@ void LLIMProcessing::processNewMessage(LLUUID from_id,
region_id,
position,
false,
timestamp,
false,
keyword_alert_performed);
@ -909,6 +910,7 @@ void LLIMProcessing::processNewMessage(LLUUID from_id,
region_id,
position,
false,
0,
true
);
// </FS:LO>
@ -932,6 +934,7 @@ void LLIMProcessing::processNewMessage(LLUUID from_id,
region_id,
position,
false,
0,
true);
LLGiveInventory::doGiveInventoryItem(from_id, item, session_id);
}
@ -1028,6 +1031,7 @@ void LLIMProcessing::processNewMessage(LLUUID from_id,
region_id,
position,
region_message,
timestamp,
false,
keyword_alert_performed);
}
@ -1704,7 +1708,9 @@ void LLIMProcessing::processNewMessage(LLUUID from_id,
IM_SESSION_INVITE,
parent_estate_id,
region_id,
position);
position,
false, // is_region_msg
timestamp);
}
else
{
@ -1735,13 +1741,14 @@ void LLIMProcessing::processNewMessage(LLUUID from_id,
from_id,
name,
buffer,
IM_OFFLINE == offline,
ll_safe_string((char*)binary_bucket),
(IM_OFFLINE == offline),
ll_safe_string((char*)binary_bucket), // session name
IM_SESSION_INVITE,
parent_estate_id,
region_id,
position,
false,
timestamp,
false,
keyword_alert_performed);
}

File diff suppressed because it is too large Load Diff

View File

@ -42,6 +42,7 @@ class LLAvatarName;
class LLFriendObserver;
class LLCallDialogManager;
class LLIMSpeakerMgr;
/**
* Timeout Timer for outgoing Ad-Hoc/Group IM sessions which being initialized by the server
*/
@ -63,11 +64,14 @@ private:
class LLIMModel : public LLSingleton<LLIMModel>
{
LLSINGLETON(LLIMModel);
public:
struct LLIMSession : public boost::signals2::trackable
typedef std::list<LLSD> chat_message_list_t;
struct LLIMSession : public boost::signals2::trackable
{
typedef enum e_session_type
typedef enum e_session_type
{ // for now we have 4 predefined types for a session
P2P_SESSION,
GROUP_SESSION,
@ -84,15 +88,23 @@ public:
} SCloseAction;
// [/SL:KB]
LLIMSession(const LLUUID& session_id, const std::string& name,
LLIMSession(const LLUUID& session_id, const std::string& name,
const EInstantMessage& type, const LLUUID& other_participant_id, const uuid_vec_t& ids, bool voice, bool has_offline_msg);
virtual ~LLIMSession();
void sessionInitReplyReceived(const LLUUID& new_session_id);
void addMessagesFromHistory(const std::list<LLSD>& history);
void addMessage(const std::string& from, const LLUUID& from_id, const std::string& utf8_text, const std::string& time, const bool is_history = false, bool is_region_msg = false);
void onVoiceChannelStateChanged(const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state, const LLVoiceChannel::EDirection& direction);
void addMessagesFromHistoryCache(const std::list<LLSD>& history); // From local file
void addMessagesFromServerHistory(const LLSD& history, const std::string& target_from, const std::string& target_message, U32 timestamp); // From chat server
void addMessage(const std::string& from,
const LLUUID& from_id,
const std::string& utf8_text,
const std::string& time,
const bool is_history,
const bool is_region_msg,
U32 timestamp);
void onVoiceChannelStateChanged(const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state, const LLVoiceChannel::EDirection& direction);
/** @deprecated */
static void chatFromLogFile(LLLogChat::ELogLineType type, const LLSD& msg, void* userdata);
@ -127,6 +139,10 @@ public:
uuid_vec_t mInitialInvitedIDs;
std::string mHistoryFileName;
// Saved messages from the last minute of history read from the local group chat cache file
std::string mLastHistoryCacheDateTime;
chat_message_list_t mLastHistoryCacheMsgs;
// connection to voice channel state change signal
boost::signals2::connection mVoiceChannelStateChangeConnection;
@ -136,7 +152,7 @@ public:
// does include all incoming messages
S32 mNumUnread;
std::list<LLSD> mMsgs;
chat_message_list_t mMsgs;
LLVoiceChannel* mVoiceChannel;
LLIMSpeakerMgr* mSpeakers;
@ -239,20 +255,36 @@ public:
* and also saved into a file if log2file is specified.
* It sends new message signal for each added message.
*/
// <FS:Ansariel> Added is_announcement parameter
//void addMessage(const LLUUID& session_id, const std::string& from, const LLUUID& other_participant_id, const std::string& utf8_text, bool log2file = true, bool is_region_msg = false);
//void processAddingMessage(const LLUUID& session_id, const std::string& from, const LLUUID& from_id, const std::string& utf8_text, bool log2file = true, bool is_region_msg = false);
void addMessage(const LLUUID& session_id, const std::string& from, const LLUUID& other_participant_id, const std::string& utf8_text, bool log2file = true, bool is_region_msg = false, bool is_announcement = false, bool keyword_alert_performed = false);
void processAddingMessage(const LLUUID& session_id, const std::string& from, const LLUUID& from_id, const std::string& utf8_text, bool log2file = true, bool is_region_msg = false, bool is_announcement = false, bool keyword_alert_performed = false);
void addMessage(const LLUUID& session_id,
const std::string& from,
const LLUUID& other_participant_id,
const std::string& utf8_text,
bool log2file = true,
bool is_region_msg = false,
U32 time_stamp = 0,
// <FS:Ansariel> FS extra params
bool is_announcement = false,
bool keyword_alert_performed = false);
void processAddingMessage(const LLUUID& session_id,
const std::string& from,
const LLUUID& from_id,
const std::string& utf8_text,
bool log2file,
bool is_region_msg,
U32 time_stamp,
// <FS:Ansariel> FS extra params
bool is_announcement,
bool keyword_alert_performed = false);
/**
* Similar to addMessage(...) above but won't send a signal about a new message added
*/
// <FS:Ansariel> Added is_announcement parameter
//LLIMModel::LLIMSession* addMessageSilently(const LLUUID& session_id, const std::string& from, const LLUUID& from_id,
// const std::string& utf8_text, bool log2file = true);
// const std::string& utf8_text, bool log2file = true, U32 timestamp = 0);
LLIMModel::LLIMSession* addMessageSilently(const LLUUID& session_id, const std::string& from, const LLUUID& from_id,
const std::string& utf8_text, bool log2file = true, bool is_region_msg = false, bool is_announcement = false);
const std::string& utf8_text, bool log2file = true, bool is_region_msg = false, U32 timestamp = 0, bool is_announcement = false);
/**
* Add a system message to an IM Model
@ -260,15 +292,15 @@ public:
void proccessOnlineOfflineNotification(const LLUUID& session_id, const std::string& utf8_text);
/**
* Get a session's name.
* For a P2P chat - it's an avatar's name,
* Get a session's name.
* For a P2P chat - it's an avatar's name,
* For a group chat - it's a group's name
* For an incoming ad-hoc chat - is received from the server and is in a from of "<Avatar's name> Conference"
* It is updated in LLIMModel::LLIMSession's constructor to localize the "Conference".
*/
const std::string getName(const LLUUID& session_id) const;
/**
/**
* Get number of unread messages in a session with session_id
* Returns -1 if the session with session_id doesn't exist
*/
@ -320,7 +352,7 @@ public:
bool logToFile(const std::string& file_name, const std::string& from, const LLUUID& from_id, const std::string& utf8_text);
private:
// <FS:CR> Post CHUI - Move this public for FS Communications UI
/**
* Populate supplied std::list with messages starting from index specified by start_index without
@ -333,8 +365,8 @@ private:
* Add message to a list of message associated with session specified by session_id
*/
// <FS:Ansariel> Added is_announcement parameter
//bool addToHistory(const LLUUID& session_id, const std::string& from, const LLUUID& from_id, const std::string& utf8_text, bool is_region_msg = false);
bool addToHistory(const LLUUID& session_id, const std::string& from, const LLUUID& from_id, const std::string& utf8_text, bool is_region_msg = false, bool is_announcement = false);
//bool addToHistory(const LLUUID& session_id, const std::string& from, const LLUUID& from_id, const std::string& utf8_text, bool is_region_msg, U32 timestamp);
bool addToHistory(const LLUUID& session_id, const std::string& from, const LLUUID& from_id, const std::string& utf8_text, bool is_region_msg, U32 timestamp, bool is_announcement);
};
class LLIMSessionObserver
@ -376,6 +408,7 @@ public:
const LLUUID& region_id = LLUUID::null,
const LLVector3& position = LLVector3::zero,
bool is_region_msg = false,
U32 timestamp = 0,
bool is_announcement = false, // <FS:Ansariel> Special parameter indicating announcement
bool keyword_alert_performed = false // <FS:Ansariel> Pass info if keyword alert has been performed
);

View File

@ -66,6 +66,7 @@
const S32 LOG_RECALL_SIZE = 2048;
const std::string LL_IM_TIME("time");
const std::string LL_IM_DATE_TIME("datetime");
const std::string LL_IM_TEXT("message");
const std::string LL_IM_FROM("from");
const std::string LL_IM_FROM_ID("from_id");
@ -147,14 +148,14 @@ void append_to_last_message(std::list<LLSD>& messages, const std::string& line)
messages.back()[LL_IM_TEXT] = im_text;
}
std::string remove_utf8_bom(const char* buf)
const char* remove_utf8_bom(const char* buf)
{
std::string res(buf);
if (res[0] == (char)0xEF && res[1] == (char)0xBB && res[2] == (char)0xBF)
{
res.erase(0, 3);
const char* start = buf;
if (start[0] == (char)0xEF && start[1] == (char)0xBB && start[2] == (char)0xBF)
{ // If string starts with the magic bytes, return pointer after it.
start += 3;
}
return res;
return start;
}
class LLLogChatTimeScanner: public LLSingleton<LLLogChatTimeScanner>
@ -386,7 +387,7 @@ std::string LLLogChat::cleanFileName(std::string filename)
return filename;
}
std::string LLLogChat::timestamp(bool withdate)
std::string LLLogChat::timestamp2LogString(U32 timestamp, bool withdate)
{
std::string timeStr;
if (withdate)
@ -416,7 +417,14 @@ std::string LLLogChat::timestamp(bool withdate)
}
LLSD substitution;
substitution["datetime"] = (S32)time_corrected();
if (timestamp == 0)
{
substitution["datetime"] = (S32)time_corrected();
}
else
{ // timestamp is correct utc already
substitution["datetime"] = (S32)timestamp;
}
LLStringUtil::format (timeStr, substitution);
return timeStr;
@ -442,7 +450,7 @@ void LLLogChat::saveHistory(const std::string& filename,
llassert(tmp_filename.size());
return;
}
llofstream file(LLLogChat::makeLogFileName(filename).c_str(), std::ios_base::app);
if (!file.is_open())
{
@ -453,7 +461,7 @@ void LLLogChat::saveHistory(const std::string& filename,
LLSD item;
if (gSavedPerAccountSettings.getBOOL("LogTimestamp"))
item["time"] = LLLogChat::timestamp(gSavedPerAccountSettings.getBOOL("LogTimestampDate"));
item["time"] = LLLogChat::timestamp2LogString(0, gSavedPerAccountSettings.getBOOL("LogTimestampDate"));
item["from_id"] = from_id;
item["message"] = line;
@ -461,7 +469,7 @@ void LLLogChat::saveHistory(const std::string& filename,
//adding "Second Life:" for all system messages to make chat log history parsing more reliable
if (from.empty() && from_id.isNull())
{
item["from"] = SYSTEM_FROM;
item["from"] = SYSTEM_FROM;
}
else
{
@ -480,43 +488,66 @@ void LLLogChat::loadChatHistory(const std::string& file_name, std::list<LLSD>& m
{
if (file_name.empty())
{
LL_WARNS("LLLogChat::loadChatHistory") << "Session name is Empty!" << LL_ENDL;
LL_WARNS("LLLogChat::loadChatHistory") << "Local history file name is empty!" << LL_ENDL;
return ;
}
bool load_all_history = load_params.has("load_all_history") ? load_params["load_all_history"].asBoolean() : false;
LLFILE* fptr = LLFile::fopen(LLLogChat::makeLogFileName(file_name), "r");/*Flawfinder: ignore*/
if (!fptr)
{
if (is_group)
{
std::string old_name(file_name);
// Stat the file to find it and get the last history entry time
llstat stat_data;
std::string log_file_name = LLLogChat::makeLogFileName(file_name);
LL_DEBUGS("ChatHistory") << "First attempt to stat chat history file " << log_file_name << LL_ENDL;
S32 no_stat = LLFile::stat(log_file_name, &stat_data);
if (no_stat)
{
if (is_group)
{
std::string old_name(file_name);
// <FS:Ansariel> FIRE-30582: Fix out of range crash
//old_name.erase(old_name.size() - GROUP_CHAT_SUFFIX.size());
//old_name.erase(old_name.size() - GROUP_CHAT_SUFFIX.size()); // trim off " (group)"
if (LLStringUtil::endsWith(old_name, GROUP_CHAT_SUFFIX))
{
old_name.erase(old_name.size() - GROUP_CHAT_SUFFIX.size());
}
// </FS:Ansariel>
fptr = LLFile::fopen(LLLogChat::makeLogFileName(old_name), "r");
if (fptr)
{
fclose(fptr);
LLFile::copy(LLLogChat::makeLogFileName(old_name), LLLogChat::makeLogFileName(file_name));
}
fptr = LLFile::fopen(LLLogChat::makeLogFileName(file_name), "r");
}
if (!fptr)
{
fptr = LLFile::fopen(LLLogChat::oldLogFileName(file_name), "r");/*Flawfinder: ignore*/
if (!fptr)
{
return; //No previous conversation with this name.
}
}
log_file_name = LLLogChat::makeLogFileName(old_name);
LL_DEBUGS("ChatHistory") << "Attempting to stat adjusted chat history file " << log_file_name << LL_ENDL;
no_stat = LLFile::stat(log_file_name, &stat_data);
if (!no_stat)
{ // Found it without "(group)", copy to new naming style. We already have the mod time in stat_data
log_file_name = LLLogChat::makeLogFileName(file_name);
LL_DEBUGS("ChatHistory") << "Attempt to stat copied history file " << log_file_name << LL_ENDL;
LLFile::copy(LLLogChat::makeLogFileName(old_name), log_file_name);
}
}
if (no_stat)
{
log_file_name = LLLogChat::oldLogFileName(file_name);
LL_DEBUGS("ChatHistory") << "Attempt to stat old history file name " << log_file_name << LL_ENDL;
no_stat = LLFile::stat(log_file_name, &stat_data);
if (no_stat)
{
LL_DEBUGS("ChatHistory") << "No previous conversation log file found for " << file_name << LL_ENDL;
return; //No previous conversation with this name.
}
}
}
// If we got here, we managed to stat the file.
// Open the file to read
LLFILE* fptr = LLFile::fopen(log_file_name, "r"); /*Flawfinder: ignore*/
if (!fptr)
{ // Ok, this is strange but not really tragic in the big picture of things
LL_WARNS("ChatHistory") << "Unable to read file " << log_file_name << " after stat was successful" << LL_ENDL;
return;
}
S32 save_num_messages = messages.size();
char buffer[LOG_RECALL_SIZE]; /*Flawfinder: ignore*/
char *bptr;
S32 len;
@ -534,6 +565,7 @@ void LLLogChat::loadChatHistory(const std::string& file_name, std::list<LLSD>& m
while (fgets(buffer, LOG_RECALL_SIZE, fptr) && !feof(fptr))
{
len = strlen(buffer) - 1; /*Flawfinder: ignore*/
// backfill any end of line characters with nulls
for (bptr = (buffer + len); (*bptr == '\n' || *bptr == '\r') && bptr>buffer; bptr--) *bptr='\0';
if (firstline)
@ -566,6 +598,10 @@ void LLLogChat::loadChatHistory(const std::string& file_name, std::list<LLSD>& m
}
}
fclose(fptr);
LL_DEBUGS("ChatHistory") << "Read " << (messages.size() - save_num_messages)
<< " messages of chat history from " << log_file_name
<< " file mod time " << (F64)stat_data.st_mtime << LL_ENDL;
}
bool LLLogChat::historyThreadsFinished(LLUUID session_id)
@ -948,9 +984,10 @@ bool LLLogChat::isTranscriptFileFound(std::string fullname)
{
//matching a timestamp
boost::match_results<std::string::const_iterator> matches;
std::string line(remove_utf8_bom(buffer));
// <FS:Ansariel> Seconds in timestamp
//if (ll_regex_match(remove_utf8_bom(buffer), matches, TIMESTAMP))
if (ll_regex_match(remove_utf8_bom(buffer), matches, TIMESTAMP) || ll_regex_match(remove_utf8_bom(buffer), matches, TIMESTAMP_AND_SEC))
//if (ll_regex_match(line, matches, TIMESTAMP))
if (ll_regex_match(line, matches, TIMESTAMP) || ll_regex_match(line, matches, TIMESTAMP_AND_SEC))
// </FS:Ansariel>
{
result = true;
@ -961,7 +998,7 @@ bool LLLogChat::isTranscriptFileFound(std::string fullname)
return result;
}
//*TODO mark object's names in a special way so that they will be distinguishable form avatar name
//*TODO mark object's names in a special way so that they will be distinguishable form avatar name
//which are more strict by its nature (only firstname and secondname)
//Example, an object's name can be written like "Object <actual_object's_name>"
void LLChatLogFormatter::format(const LLSD& im, std::ostream& ostr) const
@ -979,7 +1016,7 @@ void LLChatLogFormatter::format(const LLSD& im, std::ostream& ostr) const
ostr << '[' << timestamp << ']' << TWO_SPACES;
}
//*TODO mark object's names in a special way so that they will be distinguishable form avatar name
//*TODO mark object's names in a special way so that they will be distinguishable from avatar name
//which are more strict by its nature (only firstname and secondname)
//Example, an object's name can be written like "Object <actual_object's_name>"
if (im[LL_IM_FROM].isDefined())
@ -1061,7 +1098,9 @@ bool LLChatLogParser::parse(std::string& raw, LLSD& im, const LLSD& parse_params
timestamp.erase(0, 1);
timestamp.erase(timestamp.length()-1, 1);
if (cut_off_todays_date)
im[LL_IM_DATE_TIME] = timestamp; // Retain full date-time for merging chat histories
if (cut_off_todays_date)
{
// <FS:Ansariel> Seconds in timestamps
//LLLogChatTimeScanner::instance().checkAndCutOffDate(timestamp);
@ -1079,9 +1118,9 @@ bool LLChatLogParser::parse(std::string& raw, LLSD& im, const LLSD& parse_params
im[LL_IM_TIME] = timestamp;
}
else
{
//timestamp is optional
im[LL_IM_TIME] = "";
{ //timestamp is optional
im[LL_IM_DATE_TIME] = "";
im[LL_IM_TIME] = "";
}
bool has_stuff = matches[IDX_STUFF].matched;

View File

@ -92,7 +92,7 @@ public:
LOG_END
};
static std::string timestamp(bool withdate = false);
static std::string timestamp2LogString(U32 timestamp, bool withdate);
static std::string makeLogFileName(std::string(filename));
static void renameLogFile(const std::string& old_filename, const std::string& new_filename);
/**
@ -201,6 +201,7 @@ extern const std::string GROUP_CHAT_SUFFIX;
// LLSD map lookup constants
extern const std::string LL_IM_TIME; //("time");
extern const std::string LL_IM_DATE_TIME; //("datetime");
extern const std::string LL_IM_TEXT; //("message");
extern const std::string LL_IM_FROM; //("from");
extern const std::string LL_IM_FROM_ID; //("from_id");

View File

@ -367,7 +367,7 @@ void LLHandlerUtil::addNotifPanelToIM(const LLNotificationPtr& notification)
LLSD offer;
offer["notification_id"] = notification->getID();
offer["from"] = SYSTEM_FROM;
offer["time"] = LLLogChat::timestamp(false);
offer["time"] = LLLogChat::timestamp2LogString(0, false); // Use current time
offer["index"] = (LLSD::Integer)session->mMsgs.size();
session->mMsgs.push_front(offer);

View File

@ -51,6 +51,7 @@ public:
virtual LLTool* getOverrideTool(MASK mask) { return NULL; }
void setClickPickPending() { mClickPickPending = true; }
static void pickCallback(const LLPickInfo& pick_info);
BOOL mouseSteerMode() { return mMouseSteering; }

View File

@ -506,6 +506,7 @@ BOOL LLToolPie::handleLeftClickPick()
LLToolMgr::getInstance()->setTransientTool(LLToolCamera::getInstance());
gViewerWindow->hideCursor();
LLToolCamera::getInstance()->setMouseCapture(TRUE);
LLToolCamera::getInstance()->setClickPickPending();
LLToolCamera::getInstance()->pickCallback(mPick);
if(!gSavedSettings.getBOOL("ClickOnAvatarKeepsCamera")) // <FS:Zi> keep camera in place when clicking on ourselves
gAgentCamera.setFocusOnAvatar(TRUE, TRUE);