summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--indra/newview/llimview.cpp5
-rw-r--r--indra/newview/lllogchat.cpp179
-rw-r--r--indra/newview/lllogchat.h47
-rw-r--r--indra/newview/llnearbychat.cpp17
-rw-r--r--indra/newview/llviewermessage.cpp29
-rw-r--r--indra/newview/skins/default/xui/en/strings.xml3
6 files changed, 93 insertions, 187 deletions
diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp
index 00e7537b8b..d0bb98fc8c 100644
--- a/indra/newview/llimview.cpp
+++ b/indra/newview/llimview.cpp
@@ -71,11 +71,6 @@
#include "llviewerparcelmgr.h"
-const static std::string IM_TIME("time");
-const static std::string IM_TEXT("message");
-const static std::string IM_FROM("from");
-const static std::string IM_FROM_ID("from_id");
-
const static std::string NO_SESSION("(IM Session Doesn't Exist)");
const static std::string ADHOC_NAME_SUFFIX(" Conference");
diff --git a/indra/newview/lllogchat.cpp b/indra/newview/lllogchat.cpp
index 1d348834fe..d4ebdd768b 100644
--- a/indra/newview/lllogchat.cpp
+++ b/indra/newview/lllogchat.cpp
@@ -32,13 +32,18 @@
#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>
@@ -62,12 +67,13 @@
const S32 LOG_RECALL_SIZE = 2048;
-const static std::string IM_TIME("time");
-const static std::string IM_TEXT("message");
-const static std::string IM_FROM("from");
-const static std::string IM_FROM_ID("from_id");
-const static std::string IM_SEPARATOR(": ");
+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");
const static std::string NEW_LINE_SPACE_PREFIX("\n ");
const static std::string TWO_SPACES(" ");
@@ -190,7 +196,8 @@ std::string LLLogChat::makeLogFileName(std::string filename)
{
filename = cleanFileName(filename);
filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_ACCOUNT_CHAT_LOGS,filename);
- filename += ".txt";
+ // new files are llsd notation format
+ filename += ".llsd";
return filename;
}
@@ -240,6 +247,18 @@ void LLLogChat::saveHistory(const std::string& filename,
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);
if (tmp_filename.empty())
@@ -260,89 +279,27 @@ void LLLogChat::saveHistory(const std::string& filename,
LLSD item;
if (gSavedPerAccountSettings.getBOOL("LogTimestamp"))
- item["time"] = LLLogChat::timestamp(gSavedPerAccountSettings.getBOOL("LogTimestampDate"));
+ item[IM_TIME] = LLLogChat::timestamp(gSavedPerAccountSettings.getBOOL("LogTimestampDate"));
- item["from_id"] = from_id;
- item["message"] = line;
+ item[IM_FROM_ID] = chat.mFromID;
+ item[IM_TEXT] = chat.mText;
+ item[IM_SOURCE_TYPE] = chat.mSourceType;
//adding "Second Life:" for all system messages to make chat log history parsing more reliable
- if (from.empty() && from_id.isNull())
+ if (chat.mFromName.empty() && chat.mFromID.isNull())
{
- item["from"] = SYSTEM_FROM;
+ item[IM_FROM] = SYSTEM_FROM;
}
else
{
- item["from"] = from;
+ item[IM_FROM] = chat.mFromName;
}
- file << LLChatLogFormatter(item) << std::endl;
+ file << LLSDOStreamer<LLSDNotationFormatter>(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;
@@ -352,6 +309,7 @@ void append_to_last_message(std::list<LLSD>& messages, const std::string& line)
messages.back()[IM_TEXT] = im_text;
}
+// static
void LLLogChat::loadAllHistory(const std::string& file_name, std::list<LLSD>& messages)
{
if (file_name.empty())
@@ -415,53 +373,7 @@ void LLLogChat::loadAllHistory(const std::string& file_name, std::list<LLSD>& me
fclose(fptr);
}
-//*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_FROM_ID].isDefined())
- {
- LLUUID from_id = im[IM_FROM_ID].asUUID();
- ostr << '{' << from_id.asString() << '}';
- }
-
- 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;
- }
-}
-
+// static
bool LLChatLogParser::parse(const std::string& raw, LLSD& im)
{
if (!raw.length()) return false;
@@ -470,24 +382,19 @@ bool LLChatLogParser::parse(const std::string& raw, LLSD& im)
// In Viewer 2.1 we added UUID to chat/IM logging so we can look up
// display names
- std::string line = raw;
if (raw[0] == '{')
{
- const S32 UUID_LEN = 36;
- size_t pos = line.find_first_of('}');
- // If it matches, pos will be 37
- if (pos != line.npos && pos > UUID_LEN)
- {
- std::string uuid_string = line.substr(1, UUID_LEN);
- LLUUID from_id(uuid_string);
- im[IM_FROM_ID] = from_id;
- line = line.substr(pos + 1);
- }
+ // ...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(line, matches, TIMESTAMP_AND_STUFF)) return false;
+ if (!boost::regex_match(raw, matches, TIMESTAMP_AND_STUFF)) return false;
bool has_timestamp = matches[IDX_TIMESTAMP].matched;
if (has_timestamp)
diff --git a/indra/newview/lllogchat.h b/indra/newview/lllogchat.h
index a67b58e55b..674f27407e 100644
--- a/indra/newview/lllogchat.h
+++ b/indra/newview/lllogchat.h
@@ -30,10 +30,11 @@
* $/LicenseInfo$
*/
-
#ifndef LL_LLLOGCHAT_H
#define LL_LLLOGCHAT_H
+class LLChat;
+
class LLLogChat
{
public:
@@ -46,49 +47,22 @@ 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
*/
class LLChatLogParser
@@ -113,4 +87,11 @@ protected:
virtual ~LLChatLogParser() {};
};
+// LLSD map lookup constants
+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
diff --git a/indra/newview/llnearbychat.cpp b/indra/newview/llnearbychat.cpp
index 74ede67c97..631d1fcac7 100644
--- a/indra/newview/llnearbychat.cpp
+++ b/indra/newview/llnearbychat.cpp
@@ -62,12 +62,6 @@
static const S32 RESIZE_BAR_THICKNESS = 3;
-const static std::string IM_TIME("time");
-const static std::string IM_TEXT("message");
-const static std::string IM_FROM("from");
-const static std::string IM_FROM_ID("from_id");
-
-
LLNearbyChat::LLNearbyChat(const LLSD& key)
: LLDockableFloater(NULL, false, false, key)
,mChatHistory(NULL)
@@ -211,7 +205,7 @@ void LLNearbyChat::addMessage(const LLChat& chat,bool archive,const LLSD &args)
if (gSavedPerAccountSettings.getBOOL("LogNearbyChat"))
{
- LLLogChat::saveHistory("chat", chat.mFromName, chat.mFromID, chat.mText);
+ LLLogChat::saveHistory("chat", chat);
}
}
@@ -318,11 +312,14 @@ void LLNearbyChat::loadHistory()
chat.mTimeStr = msg[IM_TIME].asString();
chat.mChatStyle = CHAT_STYLE_HISTORY;
- chat.mSourceType = CHAT_SOURCE_AGENT;
- if (from_id.isNull() && SYSTEM_FROM == from)
+ 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_SYSTEM;
-
}
else if (from_id.isNull())
{
diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp
index 86865343a8..4d3a6c24e2 100644
--- a/indra/newview/llviewermessage.cpp
+++ b/indra/newview/llviewermessage.cpp
@@ -4974,6 +4974,9 @@ static std::string reason_from_transaction_type(S32 transaction_type,
case TRANS_UPLOAD_CHARGE:
return LLTrans::getString("to upload");
+
+ case TRANS_CLASSIFIED_CHARGE:
+ return LLTrans::getString("to publish a classified ad");
// These have no reason to display, but are expected and should not
// generate warnings
@@ -5038,6 +5041,12 @@ static void process_money_balance_reply_extended(LLMessageSystem* msg)
<< " type " << transaction_type
<< " item " << item_description << LL_ENDL;
+ if (source_id.isNull() && dest_id.isNull())
+ {
+ // this is a pure balance update, no notification required
+ return;
+ }
+
const char* source_type = (is_source_group ? "group" : "agent");
std::string source_slurl =
LLSLURL( source_type, source_id, "inspect").getSLURLString();
@@ -5070,11 +5079,27 @@ static void process_money_balance_reply_extended(LLMessageSystem* msg)
name_id = dest_id;
if (!reason.empty())
{
- message = LLTrans::getString("you_paid_ldollars", args);
+ if (dest_id.notNull())
+ {
+ message = LLTrans::getString("you_paid_ldollars", args);
+ }
+ else
+ {
+ // transaction fee to the system, eg, to create a group
+ message = LLTrans::getString("you_paid_ldollars_no_name", args);
+ }
}
else
{
- message = LLTrans::getString("you_paid_ldollars_no_reason", args);
+ if (dest_id.notNull())
+ {
+ message = LLTrans::getString("you_paid_ldollars_no_reason", args);
+ }
+ else
+ {
+ // no target, no reason, you just paid money
+ message = LLTrans::getString("you_paid_ldollars_no_info", args);
+ }
}
final_args["MESSAGE"] = message;
notification = "PaymentSent";
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index 614b681853..695c6d0793 100644
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -3103,7 +3103,8 @@ If you continue to receive this message, contact the [SUPPORT_SITE].
<string name="to create a group">to create a group</string>
<string name="to join a group">to join a group</string>
<string name="to upload">to upload</string>
-
+ <string name="to publish a classified ad">to publish a classified ad</string>
+
<string name="giving">Giving L$ [AMOUNT]</string>
<string name="uploading_costs">Uploading costs L$ [AMOUNT]</string>
<string name="this_costs">This costs L$ [AMOUNT]</string>