DN-181 Chat & IM logs saved in unreadable .llsd instead of .txt
parent
48e6f36f98
commit
cb5d8d1a92
|
|
@ -38,6 +38,8 @@
|
|||
#include "message.h"
|
||||
#include "llmemtype.h"
|
||||
|
||||
#include <boost/regex.hpp>
|
||||
|
||||
// llsd serialization constants
|
||||
static const std::string AGENTS("agents");
|
||||
static const std::string GROUPS("groups");
|
||||
|
|
@ -551,6 +553,31 @@ std::string LLCacheName::buildUsername(const std::string& full_name)
|
|||
return full_name;
|
||||
}
|
||||
|
||||
//static
|
||||
std::string LLCacheName::buildLegacyName(const std::string& complete_name)
|
||||
{
|
||||
boost::regex complete_name_regex("(.+)( \\()([A-Za-z]+)(.[A-Za-z]+)*(\\))");
|
||||
boost::match_results<std::string::const_iterator> name_results;
|
||||
if (!boost::regex_match(complete_name, name_results, complete_name_regex)) return complete_name;
|
||||
|
||||
std::string legacy_name = name_results[3];
|
||||
// capitalize the first letter
|
||||
std::string cap_letter = legacy_name.substr(0, 1);
|
||||
LLStringUtil::toUpper(cap_letter);
|
||||
legacy_name = cap_letter + legacy_name.substr(1);
|
||||
|
||||
if (name_results[4].matched)
|
||||
{
|
||||
std::string last_name = name_results[4];
|
||||
std::string cap_letter = last_name.substr(1, 1);
|
||||
LLStringUtil::toUpper(cap_letter);
|
||||
last_name = cap_letter + last_name.substr(2);
|
||||
legacy_name = legacy_name + " " + last_name;
|
||||
}
|
||||
|
||||
return legacy_name;
|
||||
}
|
||||
|
||||
// This is a little bit kludgy. LLCacheNameCallback is a slot instead of a function pointer.
|
||||
// The reason it is a slot is so that the legacy get() function below can bind an old callback
|
||||
// and pass it as a slot. The reason it isn't a boost::function is so that trackable behavior
|
||||
|
|
|
|||
|
|
@ -90,6 +90,12 @@ public:
|
|||
// "Random Linden" -> "random.linden"
|
||||
static std::string buildUsername(const std::string& name);
|
||||
|
||||
// Converts a complete display name to a legacy name
|
||||
// if possible, otherwise returns the input
|
||||
// "Alias (random.linden)" -> "Random Linden"
|
||||
// "Something random" -> "Something random"
|
||||
static std::string buildLegacyName(const std::string& name);
|
||||
|
||||
// If available, this method copies the group name into the string
|
||||
// provided. The caller must allocate at least
|
||||
// DB_GROUP_NAME_BUF_SIZE characters. If not available, this
|
||||
|
|
|
|||
|
|
@ -54,6 +54,7 @@
|
|||
#include "llviewertexteditor.h"
|
||||
#include "llworld.h"
|
||||
#include "lluiconstants.h"
|
||||
#include "llstring.h"
|
||||
|
||||
#include "llviewercontrol.h"
|
||||
|
||||
|
|
@ -260,7 +261,7 @@ public:
|
|||
if((chat.mFromID.isNull() && chat.mFromName.empty()) || chat.mFromName == SYSTEM_FROM && chat.mFromID.isNull())
|
||||
{
|
||||
mSourceType = CHAT_SOURCE_SYSTEM;
|
||||
}
|
||||
}
|
||||
|
||||
mUserNameFont = style_params.font();
|
||||
LLTextBox* user_name = getChild<LLTextBox>("user_name");
|
||||
|
|
@ -268,14 +269,14 @@ public:
|
|||
user_name->setColor(style_params.color());
|
||||
|
||||
if (chat.mFromName.empty()
|
||||
|| mSourceType == CHAT_SOURCE_SYSTEM
|
||||
|| mAvatarID.isNull())
|
||||
|| mSourceType == CHAT_SOURCE_SYSTEM)
|
||||
{
|
||||
mFrom = LLTrans::getString("SECOND_LIFE");
|
||||
user_name->setValue(mFrom);
|
||||
updateMinUserNameWidth();
|
||||
}
|
||||
else if (mSourceType == CHAT_SOURCE_AGENT
|
||||
&& !mAvatarID.isNull()
|
||||
&& chat.mChatStyle != CHAT_STYLE_HISTORY)
|
||||
{
|
||||
// ...from a normal user, lookup the name and fill in later.
|
||||
|
|
@ -288,7 +289,41 @@ public:
|
|||
LLAvatarNameCache::get(mAvatarID,
|
||||
boost::bind(&LLChatHistoryHeader::onAvatarNameCache, this, _1, _2));
|
||||
}
|
||||
else {
|
||||
else if (chat.mChatStyle == CHAT_STYLE_HISTORY ||
|
||||
mSourceType == CHAT_SOURCE_AGENT)
|
||||
{
|
||||
//if it's an avatar name with a username add formatting
|
||||
S32 username_start = chat.mFromName.rfind(" (");
|
||||
S32 username_end = chat.mFromName.rfind(')');
|
||||
|
||||
if (username_start != std::string::npos &&
|
||||
username_end == (chat.mFromName.length() - 1))
|
||||
{
|
||||
mFrom = chat.mFromName.substr(0, username_start);
|
||||
user_name->setValue(mFrom);
|
||||
|
||||
if (gSavedSettings.getBOOL("NameTagShowUsernames"))
|
||||
{
|
||||
std::string username = chat.mFromName.substr(username_start + 2);
|
||||
username = username.substr(0, username.length() - 1);
|
||||
LLStyle::Params style_params_name;
|
||||
LLColor4 userNameColor = LLUIColorTable::instance().getColor("EmphasisColor");
|
||||
style_params_name.color(userNameColor);
|
||||
style_params_name.font.name("SansSerifSmall");
|
||||
style_params_name.font.style("NORMAL");
|
||||
style_params_name.readonly_color(userNameColor);
|
||||
user_name->appendText(" - " + username, FALSE, style_params_name);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mFrom = chat.mFromName;
|
||||
user_name->setValue(mFrom);
|
||||
updateMinUserNameWidth();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// ...from an object, just use name as given
|
||||
mFrom = chat.mFromName;
|
||||
user_name->setValue(mFrom);
|
||||
|
|
@ -367,7 +402,9 @@ public:
|
|||
user_name->setValue( LLSD(av_name.mDisplayName ) );
|
||||
user_name->setToolTip( av_name.mUsername );
|
||||
|
||||
if (gSavedSettings.getBOOL("NameTagShowUsernames") && LLAvatarNameCache::useDisplayNames())
|
||||
if (gSavedSettings.getBOOL("NameTagShowUsernames") &&
|
||||
LLAvatarNameCache::useDisplayNames() &&
|
||||
!av_name.mIsDisplayNameDefault)
|
||||
{
|
||||
LLStyle::Params style_params_name;
|
||||
LLColor4 userNameColor = LLUIColorTable::instance().getColor("EmphasisColor");
|
||||
|
|
|
|||
|
|
@ -430,8 +430,9 @@ void LLIMModel::LLIMSession::addMessagesFromHistory(const std::list<LLSD>& histo
|
|||
}
|
||||
else
|
||||
{
|
||||
// Legacy chat logs only wrote the legacy name, not the agent_id
|
||||
gCacheName->getUUID(from, from_id);
|
||||
// convert it to a legacy name if we have a complete name
|
||||
std::string legacy_name = gCacheName->buildLegacyName(from);
|
||||
gCacheName->getUUID(legacy_name, from_id);
|
||||
}
|
||||
|
||||
std::string timestamp = msg[IM_TIME];
|
||||
|
|
@ -526,8 +527,15 @@ bool LLIMModel::LLIMSession::isOtherParticipantAvaline()
|
|||
|
||||
void LLIMModel::LLIMSession::onAvatarNameCache(const LLUUID& avatar_id, const LLAvatarName& av_name)
|
||||
{
|
||||
// if username is empty, display names isn't enabled, use the display name
|
||||
mHistoryFileName = av_name.mUsername.empty() ? av_name.mDisplayName : av_name.mUsername;
|
||||
if (av_name.getLegacyName().empty())
|
||||
{
|
||||
// if display names is off the legacy name will be the display name
|
||||
mHistoryFileName = LLCacheName::cleanFullName(av_name.mDisplayName);
|
||||
}
|
||||
else
|
||||
{
|
||||
mHistoryFileName = LLCacheName::cleanFullName(av_name.getLegacyName());
|
||||
}
|
||||
}
|
||||
|
||||
void LLIMModel::LLIMSession::buildHistoryFileName()
|
||||
|
|
@ -737,8 +745,18 @@ bool LLIMModel::addToHistory(const LLUUID& session_id, const std::string& from,
|
|||
bool LLIMModel::logToFile(const std::string& file_name, const std::string& from, const LLUUID& from_id, const std::string& utf8_text)
|
||||
{
|
||||
if (gSavedPerAccountSettings.getBOOL("LogInstantMessages"))
|
||||
{
|
||||
LLLogChat::saveHistory(file_name, from, from_id, utf8_text);
|
||||
{
|
||||
std::string from_name = from;
|
||||
|
||||
LLAvatarName av_name;
|
||||
if (!from_id.isNull() &&
|
||||
LLAvatarNameCache::get(from_id, &av_name) &&
|
||||
!av_name.mIsDisplayNameDefault)
|
||||
{
|
||||
from_name = av_name.getCompleteName();
|
||||
}
|
||||
|
||||
LLLogChat::saveHistory(file_name, from_name, from_id, utf8_text);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
|
|
|
|||
|
|
@ -26,18 +26,13 @@
|
|||
|
||||
#include "llviewerprecompiledheaders.h"
|
||||
|
||||
#include "lllogchat.h"
|
||||
|
||||
// viewer includes
|
||||
#include "llagent.h"
|
||||
#include "llagentui.h"
|
||||
#include "lllogchat.h"
|
||||
#include "lltrans.h"
|
||||
#include "llviewercontrol.h"
|
||||
|
||||
// library includes
|
||||
#include "llchat.h"
|
||||
#include "llinstantmessage.h"
|
||||
#include "llsdserialize.h"
|
||||
#include "llsingleton.h" // for LLSingleton
|
||||
|
||||
#include <boost/algorithm/string/trim.hpp>
|
||||
|
|
@ -65,7 +60,6 @@ const std::string IM_TIME("time");
|
|||
const std::string IM_TEXT("message");
|
||||
const std::string IM_FROM("from");
|
||||
const std::string IM_FROM_ID("from_id");
|
||||
const std::string IM_SOURCE_TYPE("source_type");
|
||||
|
||||
const static std::string IM_SEPARATOR(": ");
|
||||
const static std::string NEW_LINE("\n");
|
||||
|
|
@ -93,7 +87,7 @@ const static boost::regex TIMESTAMP_AND_STUFF("^(\\[\\d{4}/\\d{1,2}/\\d{1,2}\\s+
|
|||
* Regular expression suitable to match names like
|
||||
* "You", "Second Life", "Igor ProductEngine", "Object", "Mega House"
|
||||
*/
|
||||
const static boost::regex NAME_AND_TEXT("(You:|Second Life:|[^\\s:]+\\s*[:]{1}|\\S+\\s+[^\\s:]+[:]{1})?(\\s*)(.*)");
|
||||
const static boost::regex NAME_AND_TEXT("([^:]+[:]{1})?(\\s*)(.*)");
|
||||
|
||||
//is used to parse complex object names like "Xstreet SL Terminal v2.2.5 st"
|
||||
const static std::string NAME_TEXT_DIVIDER(": ");
|
||||
|
|
@ -190,8 +184,7 @@ std::string LLLogChat::makeLogFileName(std::string filename)
|
|||
{
|
||||
filename = cleanFileName(filename);
|
||||
filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_ACCOUNT_CHAT_LOGS,filename);
|
||||
// new files are llsd notation format
|
||||
filename += ".llsd";
|
||||
filename += ".txt";
|
||||
return filename;
|
||||
}
|
||||
|
||||
|
|
@ -240,18 +233,6 @@ void LLLogChat::saveHistory(const std::string& filename,
|
|||
const std::string& from,
|
||||
const LLUUID& from_id,
|
||||
const std::string& line)
|
||||
{
|
||||
LLChat chat;
|
||||
chat.mText = line;
|
||||
chat.mFromName = from;
|
||||
chat.mFromID = from_id;
|
||||
// default to being from an agent
|
||||
chat.mSourceType = CHAT_SOURCE_AGENT;
|
||||
saveHistory(filename, chat);
|
||||
}
|
||||
|
||||
//static
|
||||
void LLLogChat::saveHistory(const std::string& filename, const LLChat& chat)
|
||||
{
|
||||
std::string tmp_filename = filename;
|
||||
LLStringUtil::trim(tmp_filename);
|
||||
|
|
@ -273,27 +254,89 @@ void LLLogChat::saveHistory(const std::string& filename, const LLChat& chat)
|
|||
LLSD item;
|
||||
|
||||
if (gSavedPerAccountSettings.getBOOL("LogTimestamp"))
|
||||
item[IM_TIME] = LLLogChat::timestamp(gSavedPerAccountSettings.getBOOL("LogTimestampDate"));
|
||||
item["time"] = LLLogChat::timestamp(gSavedPerAccountSettings.getBOOL("LogTimestampDate"));
|
||||
|
||||
item[IM_FROM_ID] = chat.mFromID;
|
||||
item[IM_TEXT] = chat.mText;
|
||||
item[IM_SOURCE_TYPE] = chat.mSourceType;
|
||||
item["from_id"] = from_id;
|
||||
item["message"] = line;
|
||||
|
||||
//adding "Second Life:" for all system messages to make chat log history parsing more reliable
|
||||
if (chat.mFromName.empty() && chat.mFromID.isNull())
|
||||
if (from.empty() && from_id.isNull())
|
||||
{
|
||||
item[IM_FROM] = SYSTEM_FROM;
|
||||
item["from"] = SYSTEM_FROM;
|
||||
}
|
||||
else
|
||||
{
|
||||
item[IM_FROM] = chat.mFromName;
|
||||
item["from"] = from;
|
||||
}
|
||||
|
||||
file << LLSDOStreamer<LLSDNotationFormatter>(item) << std::endl;
|
||||
file << LLChatLogFormatter(item) << std::endl;
|
||||
|
||||
file.close();
|
||||
}
|
||||
|
||||
void LLLogChat::loadHistory(const std::string& filename, void (*callback)(ELogLineType, const LLSD&, void*), void* userdata)
|
||||
{
|
||||
if(!filename.size())
|
||||
{
|
||||
llwarns << "Filename is Empty!" << llendl;
|
||||
return ;
|
||||
}
|
||||
|
||||
LLFILE* fptr = LLFile::fopen(makeLogFileName(filename), "r"); /*Flawfinder: ignore*/
|
||||
if (!fptr)
|
||||
{
|
||||
callback(LOG_EMPTY, LLSD(), userdata);
|
||||
return; //No previous conversation with this name.
|
||||
}
|
||||
else
|
||||
{
|
||||
char buffer[LOG_RECALL_SIZE]; /*Flawfinder: ignore*/
|
||||
char *bptr;
|
||||
S32 len;
|
||||
bool firstline=TRUE;
|
||||
|
||||
if ( fseek(fptr, (LOG_RECALL_SIZE - 1) * -1 , SEEK_END) )
|
||||
{ //File is smaller than recall size. Get it all.
|
||||
firstline = FALSE;
|
||||
if ( fseek(fptr, 0, SEEK_SET) )
|
||||
{
|
||||
fclose(fptr);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
while ( fgets(buffer, LOG_RECALL_SIZE, fptr) && !feof(fptr) )
|
||||
{
|
||||
len = strlen(buffer) - 1; /*Flawfinder: ignore*/
|
||||
for ( bptr = (buffer + len); (*bptr == '\n' || *bptr == '\r') && bptr>buffer; bptr--) *bptr='\0';
|
||||
|
||||
if (!firstline)
|
||||
{
|
||||
LLSD item;
|
||||
std::string line(buffer);
|
||||
std::istringstream iss(line);
|
||||
|
||||
if (!LLChatLogParser::parse(line, item))
|
||||
{
|
||||
item["message"] = line;
|
||||
callback(LOG_LINE, item, userdata);
|
||||
}
|
||||
else
|
||||
{
|
||||
callback(LOG_LLSD, item, userdata);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
firstline = FALSE;
|
||||
}
|
||||
}
|
||||
callback(LOG_END, LLSD(), userdata);
|
||||
|
||||
fclose(fptr);
|
||||
}
|
||||
}
|
||||
|
||||
void append_to_last_message(std::list<LLSD>& messages, const std::string& line)
|
||||
{
|
||||
if (!messages.size()) return;
|
||||
|
|
@ -367,25 +410,53 @@ void LLLogChat::loadAllHistory(const std::string& file_name, std::list<LLSD>& me
|
|||
fclose(fptr);
|
||||
}
|
||||
|
||||
// static
|
||||
bool LLChatLogParser::parse(const std::string& raw, LLSD& im)
|
||||
//*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 writen like "Object <actual_object's_name>"
|
||||
void LLChatLogFormatter::format(const LLSD& im, std::ostream& ostr) const
|
||||
{
|
||||
if (!im.isMap())
|
||||
{
|
||||
llwarning("invalid LLSD type of an instant message", 0);
|
||||
return;
|
||||
}
|
||||
|
||||
if (im[IM_TIME].isDefined())
|
||||
{
|
||||
std::string timestamp = im[IM_TIME].asString();
|
||||
boost::trim(timestamp);
|
||||
ostr << '[' << timestamp << ']' << TWO_SPACES;
|
||||
}
|
||||
|
||||
//*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 writen like "Object <actual_object's_name>"
|
||||
if (im[IM_FROM].isDefined())
|
||||
{
|
||||
std::string from = im[IM_FROM].asString();
|
||||
boost::trim(from);
|
||||
if (from.size())
|
||||
{
|
||||
ostr << from << IM_SEPARATOR;
|
||||
}
|
||||
}
|
||||
|
||||
if (im[IM_TEXT].isDefined())
|
||||
{
|
||||
std::string im_text = im[IM_TEXT].asString();
|
||||
|
||||
//multilined text will be saved with prepended spaces
|
||||
boost::replace_all(im_text, NEW_LINE, NEW_LINE_SPACE_PREFIX);
|
||||
ostr << im_text;
|
||||
}
|
||||
}
|
||||
|
||||
bool LLChatLogParser::parse(std::string& raw, LLSD& im)
|
||||
{
|
||||
if (!raw.length()) return false;
|
||||
|
||||
im = LLSD::emptyMap();
|
||||
|
||||
// In Viewer 2.1 we added UUID to chat/IM logging so we can look up
|
||||
// display names
|
||||
if (raw[0] == '{')
|
||||
{
|
||||
// ...this is a viewer 2.1, new-style LLSD notation format log
|
||||
std::istringstream raw_stream(raw);
|
||||
LLPointer<LLSDParser> parser = new LLSDNotationParser();
|
||||
S32 count = parser->parse(raw_stream, im, raw.length());
|
||||
// expect several map items per parsed line
|
||||
return (count != LLSDParser::PARSE_FAILURE);
|
||||
}
|
||||
|
||||
//matching a timestamp
|
||||
boost::match_results<std::string::const_iterator> matches;
|
||||
if (!boost::regex_match(raw, matches, TIMESTAMP_AND_STUFF)) return false;
|
||||
|
|
|
|||
|
|
@ -41,21 +41,48 @@ public:
|
|||
};
|
||||
static std::string timestamp(bool withdate = false);
|
||||
static std::string makeLogFileName(std::string(filename));
|
||||
|
||||
// Log a single line item to the appropriate chat file
|
||||
static void saveHistory(const std::string& filename, const LLChat& chat);
|
||||
|
||||
// Prefer the above version - it saves more metadata about the item
|
||||
static void saveHistory(const std::string& filename,
|
||||
const std::string& from,
|
||||
const LLUUID& from_id,
|
||||
const std::string& line);
|
||||
|
||||
/** @deprecated @see loadAllHistory() */
|
||||
static void loadHistory(const std::string& filename,
|
||||
void (*callback)(ELogLineType, const LLSD&, void*),
|
||||
void* userdata);
|
||||
|
||||
static void loadAllHistory(const std::string& file_name, std::list<LLSD>& messages);
|
||||
private:
|
||||
static std::string cleanFileName(std::string filename);
|
||||
};
|
||||
|
||||
/**
|
||||
* Formatter for the plain text chat log files
|
||||
*/
|
||||
class LLChatLogFormatter
|
||||
{
|
||||
public:
|
||||
LLChatLogFormatter(const LLSD& im) : mIM(im) {}
|
||||
virtual ~LLChatLogFormatter() {};
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& str, const LLChatLogFormatter& formatter)
|
||||
{
|
||||
formatter.format(formatter.mIM, str);
|
||||
return str;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
* Format an instant message to a stream
|
||||
* Timestamps and sender names are required
|
||||
* New lines of multilined messages are prepended with a space
|
||||
*/
|
||||
void format(const LLSD& im, std::ostream& ostr) const;
|
||||
|
||||
LLSD mIM;
|
||||
};
|
||||
|
||||
/**
|
||||
* Parser for the plain text chat log files
|
||||
*/
|
||||
|
|
@ -74,7 +101,7 @@ public:
|
|||
*
|
||||
* @return false if failed to parse mandatory data - message text
|
||||
*/
|
||||
static bool parse(const std::string& raw, LLSD& im);
|
||||
static bool parse(std::string& raw, LLSD& im);
|
||||
|
||||
protected:
|
||||
LLChatLogParser();
|
||||
|
|
@ -86,6 +113,5 @@ extern const std::string IM_TIME; //("time");
|
|||
extern const std::string IM_TEXT; //("message");
|
||||
extern const std::string IM_FROM; //("from");
|
||||
extern const std::string IM_FROM_ID; //("from_id");
|
||||
extern const std::string IM_SOURCE_TYPE; //("source_type");
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -46,6 +46,8 @@
|
|||
#include "llchathistory.h"
|
||||
#include "llstylemap.h"
|
||||
|
||||
#include "llavatarnamecache.h"
|
||||
|
||||
#include "lldraghandle.h"
|
||||
|
||||
#include "llbottomtray.h"
|
||||
|
|
@ -179,7 +181,21 @@ void LLNearbyChat::addMessage(const LLChat& chat,bool archive,const LLSD &args)
|
|||
|
||||
if (gSavedPerAccountSettings.getBOOL("LogNearbyChat"))
|
||||
{
|
||||
LLLogChat::saveHistory("chat", chat);
|
||||
std::string from_name = chat.mFromName;
|
||||
|
||||
if (chat.mSourceType == CHAT_SOURCE_AGENT)
|
||||
{
|
||||
// if the chat is coming from an agent, log the complete name
|
||||
LLAvatarName av_name;
|
||||
LLAvatarNameCache::get(chat.mFromID, &av_name);
|
||||
|
||||
if (!av_name.mIsDisplayNameDefault)
|
||||
{
|
||||
from_name = av_name.getCompleteName();
|
||||
}
|
||||
}
|
||||
|
||||
LLLogChat::saveHistory("chat", from_name, chat.mFromID, chat.mText);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -248,11 +264,23 @@ void LLNearbyChat::processChatHistoryStyleUpdate(const LLSD& newvalue)
|
|||
nearby_chat->updateChatHistoryStyle();
|
||||
}
|
||||
|
||||
bool isTwoWordsName(const std::string& name)
|
||||
bool isWordsName(const std::string& name)
|
||||
{
|
||||
//checking for a single space
|
||||
S32 pos = name.find(' ', 0);
|
||||
return std::string::npos != pos && name.rfind(' ', name.length()) == pos && 0 != pos && name.length()-1 != pos;
|
||||
// checking to see if it's display name plus username in parentheses
|
||||
S32 open_paren = name.find(" (", 0);
|
||||
S32 close_paren = name.find(')', 0);
|
||||
|
||||
if (open_paren != std::string::npos &&
|
||||
close_paren == name.length()-1)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
//checking for a single space
|
||||
S32 pos = name.find(' ', 0);
|
||||
return std::string::npos != pos && name.rfind(' ', name.length()) == pos && 0 != pos && name.length()-1 != pos;
|
||||
}
|
||||
}
|
||||
|
||||
void LLNearbyChat::loadHistory()
|
||||
|
|
@ -275,9 +303,10 @@ void LLNearbyChat::loadHistory()
|
|||
from_id = msg[IM_FROM_ID].asUUID();
|
||||
}
|
||||
else
|
||||
{
|
||||
gCacheName->getUUID(from, from_id);
|
||||
}
|
||||
{
|
||||
std::string legacy_name = gCacheName->buildLegacyName(from);
|
||||
gCacheName->getUUID(legacy_name, from_id);
|
||||
}
|
||||
|
||||
LLChat chat;
|
||||
chat.mFromName = from;
|
||||
|
|
@ -286,18 +315,15 @@ void LLNearbyChat::loadHistory()
|
|||
chat.mTimeStr = msg[IM_TIME].asString();
|
||||
chat.mChatStyle = CHAT_STYLE_HISTORY;
|
||||
|
||||
if (msg.has(IM_SOURCE_TYPE))
|
||||
{
|
||||
S32 source_type = msg[IM_SOURCE_TYPE].asInteger();
|
||||
chat.mSourceType = (EChatSourceType)source_type;
|
||||
}
|
||||
else if (from_id.isNull() && SYSTEM_FROM == from)
|
||||
chat.mSourceType = CHAT_SOURCE_AGENT;
|
||||
if (from_id.isNull() && SYSTEM_FROM == from)
|
||||
{
|
||||
chat.mSourceType = CHAT_SOURCE_SYSTEM;
|
||||
|
||||
}
|
||||
else if (from_id.isNull())
|
||||
{
|
||||
chat.mSourceType = isTwoWordsName(from) ? CHAT_SOURCE_UNKNOWN : CHAT_SOURCE_OBJECT;
|
||||
chat.mSourceType = isWordsName(from) ? CHAT_SOURCE_UNKNOWN : CHAT_SOURCE_OBJECT;
|
||||
}
|
||||
|
||||
addMessage(chat, true, do_not_log);
|
||||
|
|
|
|||
Loading…
Reference in New Issue