aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorRevolutionSmythe2010-10-23 20:51:07 -0500
committerMcCabe Maxsted2010-11-01 17:01:36 -0700
commit72c4d73706267a32bb31d93e14425b1c0c8a5715 (patch)
treeaff00c532e35fc421ac955b7719483c818f2d21e
parentFinishes the OpenRegionSettings module, adds a new panel to Region/Estate for... (diff)
downloadmeta-impy-72c4d73706267a32bb31d93e14425b1c0c8a5715.zip
meta-impy-72c4d73706267a32bb31d93e14425b1c0c8a5715.tar.gz
meta-impy-72c4d73706267a32bb31d93e14425b1c0c8a5715.tar.bz2
meta-impy-72c4d73706267a32bb31d93e14425b1c0c8a5715.tar.xz
Merges the Message log and Message builder from Inertia in.
Diffstat (limited to '')
-rw-r--r--linden/indra/llmessage/llcircuit.cpp11
-rw-r--r--linden/indra/llmessage/llcircuit.h3
-rw-r--r--linden/indra/llmessage/llmessagelog.cpp54
-rw-r--r--linden/indra/llmessage/llmessagelog.h41
-rw-r--r--linden/indra/llmessage/llpacketring.cpp5
-rw-r--r--linden/indra/llmessage/lltemplatemessagereader.cpp50
-rw-r--r--linden/indra/llmessage/lltemplatemessagereader.h16
-rw-r--r--linden/indra/llmessage/message.cpp18
-rw-r--r--linden/indra/llmessage/message.h18
-rw-r--r--linden/indra/llui/llscrolllistctrl.cpp17
-rw-r--r--linden/indra/llui/llscrolllistctrl.h11
-rw-r--r--linden/indra/newview/llfloatermessagebuilder.cpp978
-rw-r--r--linden/indra/newview/llfloatermessagebuilder.h55
-rw-r--r--linden/indra/newview/llfloatermessagelog.cpp962
-rw-r--r--linden/indra/newview/llfloatermessagelog.h84
-rw-r--r--linden/indra/newview/llviewermenu.cpp45
-rw-r--r--linden/indra/newview/skins/default/xui/en-us/menu_viewer.xml9
17 files changed, 2358 insertions, 19 deletions
diff --git a/linden/indra/llmessage/llcircuit.cpp b/linden/indra/llmessage/llcircuit.cpp
index 725425c..0ff5093 100644
--- a/linden/indra/llmessage/llcircuit.cpp
+++ b/linden/indra/llmessage/llcircuit.cpp
@@ -1231,6 +1231,17 @@ void LLCircuit::getCircuitRange(
1231 first = mCircuitData.upper_bound(key); 1231 first = mCircuitData.upper_bound(key);
1232} 1232}
1233 1233
1234// <edit>
1235std::vector<LLCircuitData*> LLCircuit::getCircuitDataList()
1236{
1237 std::vector<LLCircuitData*> list;
1238 circuit_data_map::iterator end = mCircuitData.end();
1239 for(circuit_data_map::iterator iter = mCircuitData.begin(); iter != end; ++iter)
1240 list.push_back((*iter).second);
1241 return list;
1242}
1243// </edit>
1244
1234TPACKETID LLCircuitData::nextPacketOutID() 1245TPACKETID LLCircuitData::nextPacketOutID()
1235{ 1246{
1236 mPacketsOut++; 1247 mPacketsOut++;
diff --git a/linden/indra/llmessage/llcircuit.h b/linden/indra/llmessage/llcircuit.h
index e373cb1..379453e 100644
--- a/linden/indra/llmessage/llcircuit.h
+++ b/linden/indra/llmessage/llcircuit.h
@@ -336,6 +336,9 @@ public:
336 // HACK - this should become protected eventually, but stupid !@$@# message system/circuit classes are jumbling things up. 336 // HACK - this should become protected eventually, but stupid !@$@# message system/circuit classes are jumbling things up.
337 circuit_data_map mUnackedCircuitMap; // Map of circuits with unacked data 337 circuit_data_map mUnackedCircuitMap; // Map of circuits with unacked data
338 circuit_data_map mSendAckMap; // Map of circuits which need to send acks 338 circuit_data_map mSendAckMap; // Map of circuits which need to send acks
339
340 std::vector<LLCircuitData*> getCircuitDataList();
341
339protected: 342protected:
340 circuit_data_map mCircuitData; 343 circuit_data_map mCircuitData;
341 344
diff --git a/linden/indra/llmessage/llmessagelog.cpp b/linden/indra/llmessage/llmessagelog.cpp
new file mode 100644
index 0000000..965b8c0
--- /dev/null
+++ b/linden/indra/llmessage/llmessagelog.cpp
@@ -0,0 +1,54 @@
1// <edit>
2#include "llmessagelog.h"
3
4LLMessageLogEntry::LLMessageLogEntry(EType type, LLHost from_host, LLHost to_host, U8* data, S32 data_size)
5: mType(type),
6 mFromHost(from_host),
7 mToHost(to_host),
8 mDataSize(data_size)
9{
10 if(data)
11 {
12 mData.resize(data_size);
13 memcpy(&(mData[0]), data, data_size);
14 }
15}
16LLMessageLogEntry::LLMessageLogEntry(EType type, LLHost from_host, LLHost to_host, std::vector<U8> data, S32 data_size)
17: mType(type),
18 mFromHost(from_host),
19 mToHost(to_host),
20 mDataSize(data_size),
21 mData(data)
22{
23}
24LLMessageLogEntry::~LLMessageLogEntry()
25{
26}
27U32 LLMessageLog::sMaxSize = 4096; // testzone fixme todo boom
28std::deque<LLMessageLogEntry> LLMessageLog::sDeque;
29void (*(LLMessageLog::sCallback))(LLMessageLogEntry);
30void LLMessageLog::setMaxSize(U32 size)
31{
32 sMaxSize = size;
33 while(sDeque.size() > sMaxSize)
34 sDeque.pop_front();
35}
36void LLMessageLog::setCallback(void (*callback)(LLMessageLogEntry))
37{
38 sCallback = callback;
39}
40void LLMessageLog::log(LLHost from_host, LLHost to_host, U8* data, S32 data_size)
41{
42 LLMessageLogEntry entry = LLMessageLogEntry(LLMessageLogEntry::TEMPLATE, from_host, to_host, data, data_size);
43 if(!entry.mDataSize || !entry.mData.size()) return;
44 if(sCallback) sCallback(entry);
45 if(!sMaxSize) return;
46 sDeque.push_back(entry);
47 if(sDeque.size() > sMaxSize)
48 sDeque.pop_front();
49}
50std::deque<LLMessageLogEntry> LLMessageLog::getDeque()
51{
52 return sDeque;
53}
54// </edit>
diff --git a/linden/indra/llmessage/llmessagelog.h b/linden/indra/llmessage/llmessagelog.h
new file mode 100644
index 0000000..5046d80
--- /dev/null
+++ b/linden/indra/llmessage/llmessagelog.h
@@ -0,0 +1,41 @@
1// <edit>
2#ifndef LL_LLMESSAGELOG_H
3#define LL_LLMESSAGELOG_H
4#include "stdtypes.h"
5#include "llhost.h"
6#include <queue>
7#include <string.h>
8
9class LLMessageSystem;
10class LLMessageLogEntry
11{
12public:
13 enum EType
14 {
15 TEMPLATE,
16 HTTP_REQUEST,
17 HTTP_RESPONSE
18 };
19 LLMessageLogEntry(EType type, LLHost from_host, LLHost to_host, U8* data, S32 data_size);
20 LLMessageLogEntry(EType type, LLHost from_host, LLHost to_host, std::vector<U8> data, S32 data_size);
21 ~LLMessageLogEntry();
22 EType mType;
23 LLHost mFromHost;
24 LLHost mToHost;
25 S32 mDataSize;
26 std::vector<U8> mData;
27};
28class LLMessageLog
29{
30public:
31 static void setMaxSize(U32 size);
32 static void setCallback(void (*callback)(LLMessageLogEntry));
33 static void log(LLHost from_host, LLHost to_host, U8* data, S32 data_size);
34 static std::deque<LLMessageLogEntry> getDeque();
35private:
36 static U32 sMaxSize;
37 static void (*sCallback)(LLMessageLogEntry);
38 static std::deque<LLMessageLogEntry> sDeque;
39};
40#endif
41// </edit>
diff --git a/linden/indra/llmessage/llpacketring.cpp b/linden/indra/llmessage/llpacketring.cpp
index 35d5aac..7dcb606 100644
--- a/linden/indra/llmessage/llpacketring.cpp
+++ b/linden/indra/llmessage/llpacketring.cpp
@@ -40,6 +40,8 @@
40#include "timing.h" 40#include "timing.h"
41#include "llrand.h" 41#include "llrand.h"
42#include "u64.h" 42#include "u64.h"
43#include "llmessagelog.h"
44#include "message.h"
43 45
44/////////////////////////////////////////////////////////// 46///////////////////////////////////////////////////////////
45LLPacketRing::LLPacketRing () : 47LLPacketRing::LLPacketRing () :
@@ -246,6 +248,9 @@ S32 LLPacketRing::receivePacket (S32 socket, char *datap)
246 248
247BOOL LLPacketRing::sendPacket(int h_socket, char * send_buffer, S32 buf_size, LLHost host) 249BOOL LLPacketRing::sendPacket(int h_socket, char * send_buffer, S32 buf_size, LLHost host)
248{ 250{
251 //<edit>
252 LLMessageLog::log(LLHost(16777343, gMessageSystem->getListenPort()), host, (U8*)send_buffer, buf_size);
253 //</edit>
249 BOOL status = TRUE; 254 BOOL status = TRUE;
250 if (!mUseOutThrottle) 255 if (!mUseOutThrottle)
251 { 256 {
diff --git a/linden/indra/llmessage/lltemplatemessagereader.cpp b/linden/indra/llmessage/lltemplatemessagereader.cpp
index d8904a9..9f68fe9 100644
--- a/linden/indra/llmessage/lltemplatemessagereader.cpp
+++ b/linden/indra/llmessage/lltemplatemessagereader.cpp
@@ -449,7 +449,10 @@ S32 LLTemplateMessageReader::getMessageSize() const
449// Returns template for the message contained in buffer 449// Returns template for the message contained in buffer
450BOOL LLTemplateMessageReader::decodeTemplate( 450BOOL LLTemplateMessageReader::decodeTemplate(
451 const U8* buffer, S32 buffer_size, // inputs 451 const U8* buffer, S32 buffer_size, // inputs
452 LLMessageTemplate** msg_template ) // outputs 452 // <edit>
453 //LLMessageTemplate** msg_template ) // outputs
454 LLMessageTemplate** msg_template, BOOL custom)
455 // </edit>
453{ 456{
454 const U8* header = buffer + LL_PACKET_ID_SIZE; 457 const U8* header = buffer + LL_PACKET_ID_SIZE;
455 458
@@ -491,6 +494,9 @@ BOOL LLTemplateMessageReader::decodeTemplate(
491 } 494 }
492 else // bogus packet received (too short) 495 else // bogus packet received (too short)
493 { 496 {
497 // <edit>
498 if(!custom)
499 // </edit>
494 llwarns << "Packet with unusable length received (too short): " 500 llwarns << "Packet with unusable length received (too short): "
495 << buffer_size << llendl; 501 << buffer_size << llendl;
496 return(FALSE); 502 return(FALSE);
@@ -503,9 +509,16 @@ BOOL LLTemplateMessageReader::decodeTemplate(
503 } 509 }
504 else 510 else
505 { 511 {
512 // <edit>
513 if(!custom)
514 {
515 // </edit>
506 llwarns << "Message #" << std::hex << num << std::dec 516 llwarns << "Message #" << std::hex << num << std::dec
507 << " received but not registered!" << llendl; 517 << " received but not registered!" << llendl;
508 gMessageSystem->callExceptionFunc(MX_UNREGISTERED_MESSAGE); 518 gMessageSystem->callExceptionFunc(MX_UNREGISTERED_MESSAGE);
519 // <edit>
520 }
521 // </edit>
509 return(FALSE); 522 return(FALSE);
510 } 523 }
511 524
@@ -532,7 +545,8 @@ void LLTemplateMessageReader::logRanOffEndOfPacket( const LLHost& host, const S3
532} 545}
533 546
534// decode a given message 547// decode a given message
535BOOL LLTemplateMessageReader::decodeData(const U8* buffer, const LLHost& sender ) 548BOOL LLTemplateMessageReader::decodeData(const U8* buffer, const LLHost& sender, BOOL custom)
549// </edit>
536{ 550{
537 llassert( mReceiveSize >= 0 ); 551 llassert( mReceiveSize >= 0 );
538 llassert( mCurrentRMessageTemplate); 552 llassert( mCurrentRMessageTemplate);
@@ -594,6 +608,9 @@ BOOL LLTemplateMessageReader::decodeData(const U8* buffer, const LLHost& sender
594 } 608 }
595 else 609 else
596 { 610 {
611 // <edit>
612 if(!custom)
613 // </edit>
597 llerrs << "Unknown block type" << llendl; 614 llerrs << "Unknown block type" << llendl;
598 return FALSE; 615 return FALSE;
599 } 616 }
@@ -640,6 +657,9 @@ BOOL LLTemplateMessageReader::decodeData(const U8* buffer, const LLHost& sender
640 657
641 if ((decode_pos + data_size) > mReceiveSize) 658 if ((decode_pos + data_size) > mReceiveSize)
642 { 659 {
660 // <edit>
661 if(!custom)
662 // </edit>
643 logRanOffEndOfPacket(sender, decode_pos, data_size); 663 logRanOffEndOfPacket(sender, decode_pos, data_size);
644 664
645 // default to 0 length variable blocks 665 // default to 0 length variable blocks
@@ -676,6 +696,9 @@ BOOL LLTemplateMessageReader::decodeData(const U8* buffer, const LLHost& sender
676 // so, copy data pointer and set data size to fixed size 696 // so, copy data pointer and set data size to fixed size
677 if ((decode_pos + mvci.getSize()) > mReceiveSize) 697 if ((decode_pos + mvci.getSize()) > mReceiveSize)
678 { 698 {
699 // <edit>
700 if(!custom)
701 // </edit>
679 logRanOffEndOfPacket(sender, decode_pos, mvci.getSize()); 702 logRanOffEndOfPacket(sender, decode_pos, mvci.getSize());
680 703
681 // default to 0s. 704 // default to 0s.
@@ -703,7 +726,10 @@ BOOL LLTemplateMessageReader::decodeData(const U8* buffer, const LLHost& sender
703 lldebugs << "Empty message '" << mCurrentRMessageTemplate->mName << "' (no blocks)" << llendl; 726 lldebugs << "Empty message '" << mCurrentRMessageTemplate->mName << "' (no blocks)" << llendl;
704 return FALSE; 727 return FALSE;
705 } 728 }
706 729
730 // <edit>
731 if(!custom)
732 // </edit>
707 { 733 {
708 static LLTimer decode_timer; 734 static LLTimer decode_timer;
709 735
@@ -756,14 +782,26 @@ BOOL LLTemplateMessageReader::decodeData(const U8* buffer, const LLHost& sender
756 return TRUE; 782 return TRUE;
757} 783}
758 784
785// <edit>
786LLMessageTemplate* LLTemplateMessageReader::getTemplate()
787{
788 return mCurrentRMessageTemplate;
789}
790// </edit>
791
759BOOL LLTemplateMessageReader::validateMessage(const U8* buffer, 792BOOL LLTemplateMessageReader::validateMessage(const U8* buffer,
760 S32 buffer_size, 793 S32 buffer_size,
761 const LLHost& sender, 794 const LLHost& sender,
762 bool trusted) 795 bool trusted,
796 BOOL custom)
763{ 797{
764 mReceiveSize = buffer_size; 798 mReceiveSize = buffer_size;
765 BOOL valid = decodeTemplate(buffer, buffer_size, &mCurrentRMessageTemplate ); 799 // <edit>
766 if(valid) 800 //BOOL valid = decodeTemplate(buffer, buffer_size, &mCurrentRMessageTemplate );
801 BOOL valid = decodeTemplate(buffer, buffer_size, &mCurrentRMessageTemplate, custom );
802 //if(result)
803 if(valid && !custom)
804 // </edit>
767 { 805 {
768 mCurrentRMessageTemplate->mReceiveCount++; 806 mCurrentRMessageTemplate->mReceiveCount++;
769 //lldebugs << "MessageRecvd:" 807 //lldebugs << "MessageRecvd:"
diff --git a/linden/indra/llmessage/lltemplatemessagereader.h b/linden/indra/llmessage/lltemplatemessagereader.h
index ab06ab4..0eef93a 100644
--- a/linden/indra/llmessage/lltemplatemessagereader.h
+++ b/linden/indra/llmessage/lltemplatemessagereader.h
@@ -102,28 +102,32 @@ public:
102 virtual const char* getMessageName() const; 102 virtual const char* getMessageName() const;
103 virtual S32 getMessageSize() const; 103 virtual S32 getMessageSize() const;
104 104
105 // <edit>
106 LLMessageTemplate* getTemplate();
107 // </edit>
108
105 virtual void copyToBuilder(LLMessageBuilder&) const; 109 virtual void copyToBuilder(LLMessageBuilder&) const;
106 110
107 BOOL validateMessage(const U8* buffer, S32 buffer_size, 111 BOOL validateMessage(const U8* buffer, S32 buffer_size,
108 const LLHost& sender, bool trusted = false); 112 const LLHost& sender, bool trusted = false, BOOL custom = FALSE);
109 BOOL readMessage(const U8* buffer, const LLHost& sender); 113 BOOL readMessage(const U8* buffer, const LLHost& sender);
110 114
111 bool isTrusted() const; 115 bool isTrusted() const;
112 bool isBanned(bool trusted_source) const; 116 bool isBanned(bool trusted_source) const;
113 bool isUdpBanned() const; 117 bool isUdpBanned() const;
118
119 BOOL decodeData(const U8* buffer, const LLHost& sender, BOOL custom = FALSE);
120
121 BOOL decodeTemplate(const U8* buffer, S32 buffer_size, // inputs
122 LLMessageTemplate** msg_template, BOOL custom = FALSE); // outputs
114 123
115private: 124private:
116 125
117 void getData(const char *blockname, const char *varname, void *datap, 126 void getData(const char *blockname, const char *varname, void *datap,
118 S32 size = 0, S32 blocknum = 0, S32 max_size = S32_MAX); 127 S32 size = 0, S32 blocknum = 0, S32 max_size = S32_MAX);
119 128
120 BOOL decodeTemplate(const U8* buffer, S32 buffer_size, // inputs
121 LLMessageTemplate** msg_template ); // outputs
122
123 void logRanOffEndOfPacket( const LLHost& host, const S32 where, const S32 wanted ); 129 void logRanOffEndOfPacket( const LLHost& host, const S32 where, const S32 wanted );
124 130
125 BOOL decodeData(const U8* buffer, const LLHost& sender );
126
127 S32 mReceiveSize; 131 S32 mReceiveSize;
128 LLMessageTemplate* mCurrentRMessageTemplate; 132 LLMessageTemplate* mCurrentRMessageTemplate;
129 LLMsgData* mCurrentRMessageData; 133 LLMsgData* mCurrentRMessageData;
diff --git a/linden/indra/llmessage/message.cpp b/linden/indra/llmessage/message.cpp
index 78af35b..7e8aff1 100644
--- a/linden/indra/llmessage/message.cpp
+++ b/linden/indra/llmessage/message.cpp
@@ -86,6 +86,7 @@
86#include "v3math.h" 86#include "v3math.h"
87#include "v4math.h" 87#include "v4math.h"
88#include "lltransfertargetvfile.h" 88#include "lltransfertargetvfile.h"
89#include "llmessagelog.h"
89 90
90// Constants 91// Constants
91//const char* MESSAGE_LOG_FILENAME = "message.log"; 92//const char* MESSAGE_LOG_FILENAME = "message.log";
@@ -524,10 +525,10 @@ LLCircuitData* LLMessageSystem::findCircuit(const LLHost& host,
524} 525}
525 526
526// Returns TRUE if a valid, on-circuit message has been received. 527// Returns TRUE if a valid, on-circuit message has been received.
527BOOL LLMessageSystem::checkMessages( S64 frame_count ) 528BOOL LLMessageSystem::checkMessages( S64 frame_count, bool faked_message, U8 fake_buffer[MAX_BUFFER_SIZE], LLHost fake_host, S32 fake_size )
528{ 529{
529 // Pump 530 // Pump
530 BOOL valid_packet = FALSE; 531 BOOL valid_packet = FALSE;
531 mMessageReader = mTemplateMessageReader; 532 mMessageReader = mTemplateMessageReader;
532 533
533 LLTransferTargetVFile::updateQueue(); 534 LLTransferTargetVFile::updateQueue();
@@ -557,6 +558,13 @@ BOOL LLMessageSystem::checkMessages( S64 frame_count )
557 mTrueReceiveSize = mPacketRing.receivePacket(mSocket, (char *)mTrueReceiveBuffer); 558 mTrueReceiveSize = mPacketRing.receivePacket(mSocket, (char *)mTrueReceiveBuffer);
558 // If you want to dump all received packets into SecondLife.log, uncomment this 559 // If you want to dump all received packets into SecondLife.log, uncomment this
559 //dumpPacketToLog(); 560 //dumpPacketToLog();
561 // <edit>
562 if(mTrueReceiveSize && receive_size > (S32) LL_MINIMUM_VALID_PACKET_SIZE)
563 {
564 LLMessageLog::log(mLastSender, LLHost(16777343, mPort), buffer, mTrueReceiveSize);
565 }
566 // </edit>
567
560 568
561 receive_size = mTrueReceiveSize; 569 receive_size = mTrueReceiveSize;
562 mLastSender = mPacketRing.getLastSender(); 570 mLastSender = mPacketRing.getLastSender();
@@ -1549,6 +1557,12 @@ U32 LLMessageSystem::getOurCircuitCode()
1549 return mOurCircuitCode; 1557 return mOurCircuitCode;
1550} 1558}
1551 1559
1560// <edit>
1561LLCircuit* LLMessageSystem::getCircuit()
1562{
1563 return &mCircuitInfo;
1564}
1565
1552void LLMessageSystem::getCircuitInfo(LLSD& info) const 1566void LLMessageSystem::getCircuitInfo(LLSD& info) const
1553{ 1567{
1554 mCircuitInfo.getInfo(info); 1568 mCircuitInfo.getInfo(info);
diff --git a/linden/indra/llmessage/message.h b/linden/indra/llmessage/message.h
index b25b27e..e6391d9 100644
--- a/linden/indra/llmessage/message.h
+++ b/linden/indra/llmessage/message.h
@@ -230,11 +230,14 @@ class LLMessageSystem : public LLMessageSenderInterface
230 typedef std::map<const char *, LLMessageTemplate*> message_template_name_map_t; 230 typedef std::map<const char *, LLMessageTemplate*> message_template_name_map_t;
231 typedef std::map<U32, LLMessageTemplate*> message_template_number_map_t; 231 typedef std::map<U32, LLMessageTemplate*> message_template_number_map_t;
232 232
233private: 233// <edit>
234//private:
235// </edit>
234 message_template_name_map_t mMessageTemplates; 236 message_template_name_map_t mMessageTemplates;
235 message_template_number_map_t mMessageNumbers; 237 message_template_number_map_t mMessageNumbers;
236 238// <edit>
237public: 239//public:
240// </edit>
238 S32 mSystemVersionMajor; 241 S32 mSystemVersionMajor;
239 S32 mSystemVersionMinor; 242 S32 mSystemVersionMinor;
240 S32 mSystemVersionPatch; 243 S32 mSystemVersionPatch;
@@ -341,7 +344,7 @@ public:
341 bool addCircuitCode(U32 code, const LLUUID& session_id); 344 bool addCircuitCode(U32 code, const LLUUID& session_id);
342 345
343 BOOL poll(F32 seconds); // Number of seconds that we want to block waiting for data, returns if data was received 346 BOOL poll(F32 seconds); // Number of seconds that we want to block waiting for data, returns if data was received
344 BOOL checkMessages( S64 frame_count = 0 ); 347 BOOL checkMessages( S64 frame_count = 0, bool faked_message = false, U8 fake_buffer[MAX_BUFFER_SIZE] = NULL, LLHost fake_host = LLHost(), S32 fake_size = 0 );
345 void processAcks(); 348 void processAcks();
346 349
347 BOOL isMessageFast(const char *msg); 350 BOOL isMessageFast(const char *msg);
@@ -569,6 +572,10 @@ public:
569 void showCircuitInfo(); 572 void showCircuitInfo();
570 void getCircuitInfo(LLSD& info) const; 573 void getCircuitInfo(LLSD& info) const;
571 574
575 // <edit>
576 LLCircuit* getCircuit();
577 // </edit>
578
572 U32 getOurCircuitCode(); 579 U32 getOurCircuitCode();
573 580
574 void enableCircuit(const LLHost &host, BOOL trusted); 581 void enableCircuit(const LLHost &host, BOOL trusted);
@@ -733,6 +740,8 @@ public:
733 // This will cause all trust queries to return true until the next message 740 // This will cause all trust queries to return true until the next message
734 // is read: use with caution! 741 // is read: use with caution!
735 void receivedMessageFromTrustedSender(); 742 void receivedMessageFromTrustedSender();
743
744 LLTemplateMessageBuilder* mTemplateMessageBuilder;
736 745
737private: 746private:
738 747
@@ -807,7 +816,6 @@ private:
807 TPACKETID mCurrentRecvPacketID; // packet ID of current receive packet (for reporting) 816 TPACKETID mCurrentRecvPacketID; // packet ID of current receive packet (for reporting)
808 817
809 LLMessageBuilder* mMessageBuilder; 818 LLMessageBuilder* mMessageBuilder;
810 LLTemplateMessageBuilder* mTemplateMessageBuilder;
811 LLSDMessageBuilder* mLLSDMessageBuilder; 819 LLSDMessageBuilder* mLLSDMessageBuilder;
812 LLMessageReader* mMessageReader; 820 LLMessageReader* mMessageReader;
813 LLTemplateMessageReader* mTemplateMessageReader; 821 LLTemplateMessageReader* mTemplateMessageReader;
diff --git a/linden/indra/llui/llscrolllistctrl.cpp b/linden/indra/llui/llscrolllistctrl.cpp
index 3c2293f..9635f99 100644
--- a/linden/indra/llui/llscrolllistctrl.cpp
+++ b/linden/indra/llui/llscrolllistctrl.cpp
@@ -103,6 +103,10 @@ struct SortScrollListItem
103LLScrollListIcon::LLScrollListIcon(LLUIImagePtr icon, S32 width) 103LLScrollListIcon::LLScrollListIcon(LLUIImagePtr icon, S32 width)
104 : LLScrollListCell(width), 104 : LLScrollListCell(width),
105 mIcon(icon), 105 mIcon(icon),
106 // <edit>
107 mCallback(NULL),
108 mUserData(NULL),
109 // </edit>
106 mColor(LLColor4::white) 110 mColor(LLColor4::white)
107{ 111{
108} 112}
@@ -145,6 +149,19 @@ void LLScrollListIcon::setValue(const LLSD& value)
145 } 149 }
146} 150}
147 151
152// <edit>
153void LLScrollListIcon::setClickCallback(BOOL (*callback)(void*), void* user_data)
154{
155 mCallback = callback;
156 mUserData = user_data;
157}
158
159BOOL LLScrollListIcon::handleClick()
160{
161 if(mCallback) return mCallback(mUserData);
162 return FALSE;
163}
164// </edit>
148 165
149void LLScrollListIcon::setColor(const LLColor4& color) 166void LLScrollListIcon::setColor(const LLColor4& color)
150{ 167{
diff --git a/linden/indra/llui/llscrolllistctrl.h b/linden/indra/llui/llscrolllistctrl.h
index 516e4f1..e875d7a 100644
--- a/linden/indra/llui/llscrolllistctrl.h
+++ b/linden/indra/llui/llscrolllistctrl.h
@@ -163,10 +163,18 @@ public:
163 virtual void setColor(const LLColor4&); 163 virtual void setColor(const LLColor4&);
164 virtual BOOL isText()const { return FALSE; } 164 virtual BOOL isText()const { return FALSE; }
165 virtual void setValue(const LLSD& value); 165 virtual void setValue(const LLSD& value);
166 // <edit>
167 void setClickCallback(BOOL (*callback)(void*), void* user_data);
168 virtual BOOL handleClick();
169 // </edit>
166 170
167private: 171private:
168 LLUIImagePtr mIcon; 172 LLUIImagePtr mIcon;
169 LLColor4 mColor; 173 LLColor4 mColor;
174 // <edit>
175 BOOL (*mCallback)(void*);
176 void* mUserData;
177 // </edit>
170}; 178};
171 179
172/* 180/*
@@ -493,6 +501,9 @@ public:
493 501
494 virtual S32 getScrollPos() const; 502 virtual S32 getScrollPos() const;
495 virtual void setScrollPos( S32 pos ); 503 virtual void setScrollPos( S32 pos );
504 // <edit>
505 S32 getPageLines() { return mPageLines; }
506 // </edit>
496 S32 getSearchColumn(); 507 S32 getSearchColumn();
497 void setSearchColumn(S32 column) { mSearchColumn = column; } 508 void setSearchColumn(S32 column) { mSearchColumn = column; }
498 S32 getColumnIndexFromOffset(S32 x); 509 S32 getColumnIndexFromOffset(S32 x);
diff --git a/linden/indra/newview/llfloatermessagebuilder.cpp b/linden/indra/newview/llfloatermessagebuilder.cpp
new file mode 100644
index 0000000..90c0f9e
--- /dev/null
+++ b/linden/indra/newview/llfloatermessagebuilder.cpp
@@ -0,0 +1,978 @@
1// <edit>
2#include "llviewerprecompiledheaders.h"
3#include "llfloatermessagebuilder.h"
4#include "lluictrlfactory.h"
5#include "llmessagetemplate.h"
6#include "llagent.h"
7#include "llchat.h"
8#include "llfloaterchat.h"
9#include "llviewerregion.h" // getHandle
10#include "llcombobox.h"
11#include "llselectmgr.h" // fill in stuff about selected object
12#include "llparcel.h"
13#include "llviewerparcelmgr.h" // same for parcel
14#include "llscrolllistctrl.h"
15#include "llworld.h"
16#include "lltemplatemessagebuilder.h"
17
18////////////////////////////////
19// LLNetListItem
20////////////////////////////////
21LLNetListItem::LLNetListItem(LLUUID id)
22: mID(id),
23 mAutoName(TRUE),
24 mName("No name"),
25 mPreviousRegionName(""),
26 mCircuitData(NULL)
27{
28}
29
30////////////////////////////////
31// LLFloaterMessageBuilder
32////////////////////////////////
33std::list<LLNetListItem*> LLFloaterMessageBuilder::sNetListItems;
34
35LLFloaterMessageBuilder::LLFloaterMessageBuilder(std::string initial_text)
36: LLFloater(),
37 LLEventTimer(1.0f),
38 mNetInfoMode(NI_NET),
39 mInitialText(initial_text)
40{
41 LLUICtrlFactory::getInstance()->buildFloater(this, "floater_message_builder.xml");
42}
43LLFloaterMessageBuilder::~LLFloaterMessageBuilder()
44{
45}
46void LLFloaterMessageBuilder::show(std::string initial_text)
47{
48 (new LLFloaterMessageBuilder(initial_text))->open();
49}
50BOOL LLFloaterMessageBuilder::tick()
51{
52 refreshNetList();
53 return FALSE;
54}
55LLNetListItem* LLFloaterMessageBuilder::findNetListItem(LLHost host)
56{
57 std::list<LLNetListItem*>::iterator end = sNetListItems.end();
58 for(std::list<LLNetListItem*>::iterator iter = sNetListItems.begin(); iter != end; ++iter)
59 if((*iter)->mCircuitData && (*iter)->mCircuitData->getHost() == host)
60 return (*iter);
61 return NULL;
62}
63LLNetListItem* LLFloaterMessageBuilder::findNetListItem(LLUUID id)
64{
65 std::list<LLNetListItem*>::iterator end = sNetListItems.end();
66 for(std::list<LLNetListItem*>::iterator iter = sNetListItems.begin(); iter != end; ++iter)
67 if((*iter)->mID == id)
68 return (*iter);
69 return NULL;
70}
71void LLFloaterMessageBuilder::refreshNetList()
72{
73 LLScrollListCtrl* scrollp = getChild<LLScrollListCtrl>("net_list");
74 // Update circuit data of net list items
75 std::vector<LLCircuitData*> circuits = gMessageSystem->getCircuit()->getCircuitDataList();
76 std::vector<LLCircuitData*>::iterator circuits_end = circuits.end();
77 for(std::vector<LLCircuitData*>::iterator iter = circuits.begin(); iter != circuits_end; ++iter)
78 {
79 LLNetListItem* itemp = findNetListItem((*iter)->getHost());
80 if(!itemp)
81 {
82 LLUUID id; id.generate();
83 itemp = new LLNetListItem(id);
84 sNetListItems.push_back(itemp);
85 }
86 itemp->mCircuitData = (*iter);
87 }
88 // Clear circuit data of items whose circuits are gone
89 std::list<LLNetListItem*>::iterator items_end = sNetListItems.end();
90 for(std::list<LLNetListItem*>::iterator iter = sNetListItems.begin(); iter != items_end; ++iter)
91 {
92 if(std::find(circuits.begin(), circuits.end(), (*iter)->mCircuitData) == circuits.end())
93 (*iter)->mCircuitData = NULL;
94 }
95 // Remove net list items that are totally useless now
96 for(std::list<LLNetListItem*>::iterator iter = sNetListItems.begin(); iter != sNetListItems.end();)
97 {
98 if((*iter)->mCircuitData == NULL)
99 iter = sNetListItems.erase(iter);
100 else ++iter;
101 }
102 // Update names of net list items
103 items_end = sNetListItems.end();
104 for(std::list<LLNetListItem*>::iterator iter = sNetListItems.begin(); iter != items_end; ++iter)
105 {
106 LLNetListItem* itemp = (*iter);
107 if(itemp->mAutoName)
108 {
109 if(itemp->mCircuitData)
110 {
111 LLViewerRegion* regionp = LLWorld::getInstance()->getRegion(itemp->mCircuitData->getHost());
112 if(regionp)
113 {
114 std::string name = regionp->getName();
115 if(name == "") name = llformat("%s (awaiting region name)", itemp->mCircuitData->getHost().getString().c_str());
116 itemp->mName = name;
117 itemp->mPreviousRegionName = name;
118 }
119 else
120 {
121 itemp->mName = itemp->mCircuitData->getHost().getString();
122 if(itemp->mPreviousRegionName != "")
123 itemp->mName.append(llformat(" (was %s)", itemp->mPreviousRegionName.c_str()));
124 }
125 }
126 else
127 {
128 // an item just for an event queue, not handled yet
129 itemp->mName = "Something else";
130 }
131 }
132 }
133 // Rebuild scroll list from scratch
134 LLUUID selected_id = scrollp->getFirstSelected() ? scrollp->getFirstSelected()->getUUID() : LLUUID::null;
135 S32 scroll_pos = scrollp->getScrollPos();
136 scrollp->clearRows();
137 for(std::list<LLNetListItem*>::iterator iter = sNetListItems.begin(); iter != items_end; ++iter)
138 {
139 LLNetListItem* itemp = (*iter);
140 LLSD element;
141 element["id"] = itemp->mID;
142 LLSD& text_column = element["columns"][0];
143 text_column["column"] = "text";
144 text_column["value"] = itemp->mName + (itemp->mCircuitData->getHost() == gAgent.getRegionHost() ? " (main)" : "");
145
146 LLSD& state_column = element["columns"][ 1];
147 state_column["column"] = "state";
148 state_column["value"] = "";
149
150 LLScrollListItem* scroll_itemp = scrollp->addElement(element);
151 BOOL has_live_circuit = itemp->mCircuitData && itemp->mCircuitData->isAlive();
152
153 LLScrollListText* state = (LLScrollListText*)scroll_itemp->getColumn(1);
154
155 if(has_live_circuit)
156 state->setText(std::string("Alive"));
157 else
158 state->setText(std::string("Alive"));
159 }
160 if(selected_id.notNull()) scrollp->selectByID(selected_id);
161 if(scroll_pos < scrollp->getItemCount()) scrollp->setScrollPos(scroll_pos);
162}
163BOOL LLFloaterMessageBuilder::postBuild()
164{
165 childSetText("message_edit", mInitialText);
166 childSetAction("send_btn", onClickSend, this);
167 std::vector<std::string> names;
168 LLComboBox* combo;
169 LLMessageSystem::message_template_name_map_t::iterator temp_end = gMessageSystem->mMessageTemplates.end();
170 LLMessageSystem::message_template_name_map_t::iterator temp_iter;
171 std::vector<std::string>::iterator names_end;
172 std::vector<std::string>::iterator names_iter;
173 for(temp_iter = gMessageSystem->mMessageTemplates.begin(); temp_iter != temp_end; ++temp_iter)
174 if((*temp_iter).second->getTrust() == MT_NOTRUST)
175 names.push_back((*temp_iter).second->mName);
176 std::sort(names.begin(), names.end());
177 combo = getChild<LLComboBox>("untrusted_message_combo");
178 names_end = names.end();
179 for(names_iter = names.begin(); names_iter != names_end; ++names_iter)
180 combo->add((*names_iter));
181 names.clear();
182 for(temp_iter = gMessageSystem->mMessageTemplates.begin(); temp_iter != temp_end; ++temp_iter)
183 if((*temp_iter).second->getTrust() == MT_TRUST)
184 names.push_back((*temp_iter).second->mName);
185 std::sort(names.begin(), names.end());
186 combo = getChild<LLComboBox>("trusted_message_combo");
187 names_end = names.end();
188 for(names_iter = names.begin(); names_iter != names_end; ++names_iter)
189 combo->add((*names_iter));
190 childSetCommitCallback("untrusted_message_combo", onCommitPacketCombo, this);
191 childSetCommitCallback("trusted_message_combo", onCommitPacketCombo, this);
192 return TRUE;
193}
194inline std::vector<std::string> split(std::string input, std::string separator)
195{
196 S32 size = input.length();
197 char* buffer = new char[size + 1];
198 strncpy(buffer, input.c_str(), size);
199 buffer[size] = '\0';
200 std::vector<std::string> lines;
201 char* result = strtok(buffer, separator.c_str());
202 while(result)
203 {
204 lines.push_back(result);
205 result = strtok(NULL, separator.c_str());
206 }
207 delete[] buffer;
208 return lines;
209}
210std::string mvtstr(e_message_variable_type var_type)
211{
212 switch(var_type)
213 {
214 case MVT_U8:
215 return "U8";
216 break;
217 case MVT_U16:
218 return "U16";
219 break;
220 case MVT_U32:
221 return "U32";
222 break;
223 case MVT_U64:
224 return "U64";
225 break;
226 case MVT_S8:
227 return "S8";
228 break;
229 case MVT_S16:
230 return "S16";
231 break;
232 case MVT_S32:
233 return "S32";
234 break;
235 case MVT_S64:
236 return "S64";
237 break;
238 case MVT_F32:
239 return "F32";
240 break;
241 case MVT_F64:
242 return "F64";
243 break;
244 case MVT_LLVector3:
245 return "LLVector3";
246 break;
247 case MVT_LLVector3d:
248 return "LLVector3d";
249 break;
250 case MVT_LLVector4:
251 return "LLVector4";
252 break;
253 case MVT_LLQuaternion:
254 return "LLQuaternion";
255 break;
256 case MVT_LLUUID:
257 return "LLUUID";
258 break;
259 case MVT_BOOL:
260 return "BOOL";
261 break;
262 case MVT_IP_ADDR:
263 return "IPADDR";
264 break;
265 case MVT_IP_PORT:
266 return "IPPORT";
267 break;
268 case MVT_VARIABLE:
269 return "Variable";
270 break;
271 case MVT_FIXED:
272 return "Fixed";
273 break;
274 default:
275 return "Missingno.";
276 break;
277 }
278}
279// static
280BOOL LLFloaterMessageBuilder::addField(e_message_variable_type var_type, const char* var_name, std::string input, BOOL hex)
281{
282 LLStringUtil::trim(input);
283 if(input.length() < 1 && var_type != MVT_VARIABLE)
284 return FALSE;
285 U8 valueU8;
286 U16 valueU16;
287 U32 valueU32;
288 U64 valueU64;
289 S8 valueS8;
290 S16 valueS16;
291 S32 valueS32;
292 // S64 valueS64;
293 F32 valueF32;
294 F64 valueF64;
295 LLVector3 valueVector3;
296 LLVector3d valueVector3d;
297 LLVector4 valueVector4;
298 LLQuaternion valueQuaternion;
299 LLUUID valueLLUUID;
300 BOOL valueBOOL;
301 std::string input_lower = input;
302 LLStringUtil::toLower(input_lower);
303 if(input_lower == "$agentid")
304 input = gAgent.getID().asString();
305 else if(input_lower == "$sessionid")
306 input = gAgent.getSessionID().asString();
307 else if(input_lower == "$uuid")
308 {
309 LLUUID id;
310 id.generate();
311 input = id.asString();
312 }
313 else if(input_lower == "$circuitcode")
314 {
315 std::stringstream temp_stream;
316 temp_stream << gMessageSystem->mOurCircuitCode;
317 input = temp_stream.str();
318 }
319 else if(input_lower == "$regionhandle")
320 {
321 std::stringstream temp_stream;
322 temp_stream << (gAgent.getRegion() ? gAgent.getRegion()->getHandle() : 0);
323 input = temp_stream.str();
324 }
325 else if(input_lower == "$position" || input_lower == "$pos")
326 {
327 std::stringstream temp_stream;
328 valueVector3 = gAgent.getPositionAgent();
329 temp_stream << "<" << valueVector3[0] << ", " << valueVector3[1] << ", " << valueVector3[2] << ">";
330 input = temp_stream.str();
331 }
332 if(hex)
333 {
334 if(var_type != MVT_VARIABLE && var_type != MVT_FIXED)
335 return FALSE;
336 int len = input_lower.length();
337 const char* cstr = input_lower.c_str();
338 std::string new_input("");
339 BOOL nibble = FALSE;
340 char byte = 0;
341 for(int i = 0; i < len; i++)
342 {
343 char c = cstr[i];
344 if(c >= 0x30 && c <= 0x39)
345 c -= 0x30;
346 else if(c >= 0x61 && c <= 0x66)
347 c -= 0x57;
348 else if(c != 0x20)
349 return FALSE;
350 else
351 continue;
352 if(!nibble)
353 byte = c << 4;
354 else
355 new_input.push_back(byte | c);
356 nibble = !nibble;
357 }
358 if(nibble)
359 return FALSE;
360 input = new_input;
361 }
362 std::stringstream stream(input);
363 std::vector<std::string> tokens;
364 switch(var_type)
365 {
366 case MVT_U8:
367 if(input.substr(0, 1) == "-")
368 return FALSE;
369 if((stream >> valueU32).fail())
370 return FALSE;
371 valueU8 = (U8)valueU32;
372 gMessageSystem->addU8(var_name, valueU8);
373 return TRUE;
374 break;
375 case MVT_U16:
376 if(input.substr(0, 1) == "-")
377 return FALSE;
378 if((stream >> valueU16).fail())
379 return FALSE;
380 gMessageSystem->addU16(var_name, valueU16);
381 return TRUE;
382 break;
383 case MVT_U32:
384 if(input.substr(0, 1) == "-")
385 return FALSE;
386 if((stream >> valueU32).fail())
387 return FALSE;
388 gMessageSystem->addU32(var_name, valueU32);
389 return TRUE;
390 break;
391 case MVT_U64:
392 if(input.substr(0, 1) == "-")
393 return FALSE;
394 if((stream >> valueU64).fail())
395 return FALSE;
396 gMessageSystem->addU64(var_name, valueU64);
397 return TRUE;
398 break;
399 case MVT_S8:
400 if((stream >> valueS8).fail())
401 return FALSE;
402 gMessageSystem->addS8(var_name, valueS8);
403 return TRUE;
404 break;
405 case MVT_S16:
406 if((stream >> valueS16).fail())
407 return FALSE;
408 gMessageSystem->addS16(var_name, valueS16);
409 return TRUE;
410 break;
411 case MVT_S32:
412 if((stream >> valueS32).fail())
413 return FALSE;
414 gMessageSystem->addS32(var_name, valueS32);
415 return TRUE;
416 break;
417 /*
418 case MVT_S64:
419 if((stream >> valueS64).fail())
420 return FALSE;
421 gMessageSystem->addS64(var_name, valueS64);
422 return TRUE;
423 break;
424 */
425 case MVT_F32:
426 if((stream >> valueF32).fail())
427 return FALSE;
428 gMessageSystem->addF32(var_name, valueF32);
429 return TRUE;
430 break;
431 case MVT_F64:
432 if((stream >> valueF64).fail())
433 return FALSE;
434 gMessageSystem->addF64(var_name, valueF64);
435 return TRUE;
436 break;
437 case MVT_LLVector3:
438 LLStringUtil::trim(input);
439 if(input.substr(0, 1) != "<" || input.substr(input.length() - 1, 1) != ">")
440 return FALSE;
441 tokens = split(input.substr(1, input.length() - 2), ",");
442 if(tokens.size() != 3)
443 return FALSE;
444 for(int i = 0; i < 3; i++)
445 {
446 stream.clear();
447 stream.str(tokens[i]);
448 if((stream >> valueF32).fail())
449 return FALSE;
450 valueVector3.mV[i] = valueF32;
451 }
452 gMessageSystem->addVector3(var_name, valueVector3);
453 return TRUE;
454 break;
455 case MVT_LLVector3d:
456 LLStringUtil::trim(input);
457 if(input.substr(0, 1) != "<" || input.substr(input.length() - 1, 1) != ">")
458 return FALSE;
459 tokens = split(input.substr(1, input.length() - 2), ",");
460 if(tokens.size() != 3)
461 return FALSE;
462 for(int i = 0; i < 3; i++)
463 {
464 stream.clear();
465 stream.str(tokens[i]);
466 if((stream >> valueF64).fail())
467 return FALSE;
468 valueVector3d.mdV[i] = valueF64;
469 }
470 gMessageSystem->addVector3d(var_name, valueVector3d);
471 return TRUE;
472 break;
473 case MVT_LLVector4:
474 LLStringUtil::trim(input);
475 if(input.substr(0, 1) != "<" || input.substr(input.length() - 1, 1) != ">")
476 return FALSE;
477 tokens = split(input.substr(1, input.length() - 2), ",");
478 if(tokens.size() != 4)
479 return FALSE;
480 for(int i = 0; i < 4; i++)
481 {
482 stream.clear();
483 stream.str(tokens[i]);
484 if((stream >> valueF32).fail())
485 return FALSE;
486 valueVector4.mV[i] = valueF32;
487 }
488 gMessageSystem->addVector4(var_name, valueVector4);
489 return TRUE;
490 break;
491 case MVT_LLQuaternion:
492 LLStringUtil::trim(input);
493 if(input.substr(0, 1) != "<" || input.substr(input.length() - 1, 1) != ">")
494 return FALSE;
495 tokens = split(input.substr(1, input.length() - 2), ",");
496 if(tokens.size() != 3)
497 return FALSE;
498 for(int i = 0; i < 3; i++)
499 {
500 stream.clear();
501 stream.str(tokens[i]);
502 if((stream >> valueF32).fail())
503 return FALSE;
504 valueVector3.mV[i] = valueF32;
505 }
506 valueQuaternion.unpackFromVector3(valueVector3);
507 gMessageSystem->addQuat(var_name, valueQuaternion);
508 return TRUE;
509 break;
510 case MVT_LLUUID:
511 if((stream >> valueLLUUID).fail())
512 return FALSE;
513 gMessageSystem->addUUID(var_name, valueLLUUID);
514 return TRUE;
515 break;
516 case MVT_BOOL:
517 if(input_lower == "true")
518 valueBOOL = TRUE;
519 else if(input_lower == "false")
520 valueBOOL = FALSE;
521 else if((stream >> valueBOOL).fail())
522 return FALSE;
523 //gMessageSystem->addBOOL(var_name, valueBOOL);
524 gMessageSystem->addU8(var_name, (U8)valueBOOL);
525 return TRUE;
526 break;
527 case MVT_IP_ADDR:
528 if((stream >> valueU32).fail())
529 return FALSE;
530 gMessageSystem->addIPAddr(var_name, valueU32);
531 return TRUE;
532 break;
533 case MVT_IP_PORT:
534 if((stream >> valueU16).fail())
535 return FALSE;
536 gMessageSystem->addIPPort(var_name, valueU16);
537 return TRUE;
538 break;
539 case MVT_VARIABLE:
540 if(!hex)
541 {
542 char* buffer = new char[input.size() + 1];
543 strncpy(buffer, input.c_str(), input.size());
544 buffer[input.size()] = '\0';
545 gMessageSystem->addBinaryData(var_name, buffer, input.size() + 1);
546 delete[] buffer;
547 }
548 else
549 gMessageSystem->addBinaryData(var_name, input.c_str(), input.size());
550 return TRUE;
551 break;
552 case MVT_FIXED:
553 if(!hex)
554 {
555 char* buffer = new char[input.size() + 1];
556 strncpy(buffer, input.c_str(), input.size());
557 buffer[input.size()] = '\0';
558 gMessageSystem->addBinaryData(var_name, buffer, input.size());
559 delete[] buffer;
560 }
561 else
562 gMessageSystem->addBinaryData(var_name, input.c_str(), input.size());
563 return TRUE;
564 break;
565 default:
566 break;
567 }
568 return FALSE;
569}
570// static
571void LLFloaterMessageBuilder::onCommitPacketCombo(LLUICtrl* ctrl, void* user_data)
572{
573 LLFloaterMessageBuilder* floaterp = (LLFloaterMessageBuilder*)user_data;
574 LLViewerObject* selected_objectp = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
575 LLParcel* agent_parcelp = LLViewerParcelMgr::getInstance()->getAgentParcel();
576 std::string message = ctrl->getValue();
577 std::map<const char *, LLMessageTemplate*>::iterator template_iter;
578 template_iter = gMessageSystem->mMessageTemplates.find( LLMessageStringTable::getInstance()->getString(message.c_str()) );
579 if(template_iter == gMessageSystem->mMessageTemplates.end())
580 {
581 floaterp->childSetText("message_edit", std::string(""));
582 return;
583 }
584 std::string text(llformat((*template_iter).second->getTrust() == MT_NOTRUST ? "out %s\n" : "in %s\n", message.c_str()));
585 LLMessageTemplate* temp = (*template_iter).second;
586 LLMessageTemplate::message_block_map_t::iterator blocks_end = temp->mMemberBlocks.end();
587 for (LLMessageTemplate::message_block_map_t::iterator blocks_iter = temp->mMemberBlocks.begin();
588 blocks_iter != blocks_end; ++blocks_iter)
589 {
590 LLMessageBlock* block = (*blocks_iter);
591 const char* block_name = block->mName;
592 std::string block_name_string = std::string(block_name);
593 S32 num_blocks = 1;
594 if(block->mType == MBT_MULTIPLE)
595 num_blocks = block->mNumber;
596 else if(("ObjectLink" == message && "ObjectData" == block_name_string))
597 num_blocks = 2;
598 for(S32 i = 0; i < num_blocks; i++)
599 {
600 text.append(llformat("[%s]\n", block_name));
601 LLMessageBlock::message_variable_map_t::iterator var_end = block->mMemberVariables.end();
602 for (LLMessageBlock::message_variable_map_t::iterator var_iter = block->mMemberVariables.begin();
603 var_iter != var_end; ++var_iter)
604 {
605 LLMessageVariable* variable = (*var_iter);
606 const char* var_name = variable->getName();
607 std::string var_name_string = std::string(var_name);
608 text.append(llformat("%s = ", var_name));
609 std::string value("");
610 S32 size = variable->getSize();
611 switch(variable->getType())
612 {
613 case MVT_U8:
614 case MVT_U16:
615 case MVT_U32:
616 case MVT_U64:
617 case MVT_S8:
618 case MVT_S16:
619 case MVT_S32:
620 case MVT_IP_ADDR:
621 case MVT_IP_PORT:
622 if("RegionHandle" == var_name_string || "Handle" == var_name_string)
623 value = "$RegionHandle";
624 else if("CircuitCode" == var_name_string || "ViewerCircuitCode" == var_name_string
625 || ("Code" == var_name_string && "CircuitCode" == block_name_string) )
626 {
627 value = "$CircuitCode";
628 }
629 else if(selected_objectp &&
630 (
631 "ObjectLocalID" == var_name_string
632 || "TaskLocalID" == var_name_string
633 || ("LocalID" == var_name_string &&
634 (
635 "ObjectData" == block_name_string
636 || "UpdateData" == block_name_string
637 || "InventoryData" == block_name_string
638 )
639 )
640 )
641 )
642 {
643 std::stringstream temp_stream;
644 temp_stream << selected_objectp->getLocalID();
645 value = temp_stream.str();
646 }
647 else if( agent_parcelp &&
648 "LocalID" == var_name_string &&
649 (
650 "ParcelData" == block_name_string
651 || message.find("Parcel") != message.npos
652 )
653 )
654 {
655 std::stringstream temp_stream;
656 temp_stream << agent_parcelp->getLocalID();
657 value = temp_stream.str();
658 }
659 else if("PCode" == var_name_string)
660 value = "9";
661 else if("PathCurve" == var_name_string)
662 value = "16";
663 else if("ProfileCurve" == var_name_string)
664 value = "1";
665 else if("PathScaleX" == var_name_string || "PathScaleY" == var_name_string)
666 value = "100";
667 else if("BypassRaycast" == var_name_string)
668 value = "1";
669 else
670 value = "0";
671 break;
672 case MVT_F32:
673 case MVT_F64:
674 value = "0.0";
675 break;
676 case MVT_LLVector3:
677 case MVT_LLVector3d:
678 case MVT_LLQuaternion:
679 if("Position" == var_name_string || "RayStart" == var_name_string || "RayEnd" == var_name_string)
680 value = "$Position";
681 else if("Scale" == var_name_string)
682 value = "<0.5, 0.5, 0.5>";
683 else
684 value = "<0, 0, 0>";
685 break;
686 case MVT_LLVector4:
687 value = "<0, 0, 0, 0>";
688 break;
689 case MVT_LLUUID:
690 if("AgentID" == var_name_string)
691 value = "$AgentID";
692 else if("SessionID" == var_name_string)
693 value = "$SessionID";
694 else if("ObjectID" == var_name_string && selected_objectp)
695 value = selected_objectp->getID().asString();
696 else if("ParcelID" == var_name_string && agent_parcelp)
697 value = agent_parcelp->getID().asString();
698 else
699 value = "00000000-0000-0000-0000-000000000000";
700 break;
701 case MVT_BOOL:
702 value = "false";
703 break;
704 case MVT_VARIABLE:
705 value = "Hello, world!";
706 break;
707 case MVT_FIXED:
708 for(S32 si = 0; si < size; si++)
709 //value.append(std::string("0123456789abcdef").substr(si & 0xf, 1));
710 value.append("a");
711 break;
712 default:
713 value = "";
714 break;
715 }
716 text.append(llformat("%s\n", value.c_str()));
717 }
718 }
719 }
720 text = text.substr(0, text.length() - 1);
721 floaterp->childSetText("message_edit", text);
722}
723// static
724void LLFloaterMessageBuilder::onClickSend(void* user_data)
725{
726 LLFloaterMessageBuilder* floaterp = (LLFloaterMessageBuilder*)user_data;
727 std::vector<std::string> lines = split(floaterp->childGetText("message_edit"), "\n");
728 if(!lines.size())
729 {
730 LLFloaterChat::addChat(LLChat("Not enough information :O"));
731 return;
732 }
733 std::vector<std::string> tokens = split(lines[0], " ");
734 if(!tokens.size())
735 {
736 LLFloaterChat::addChat(LLChat("Not enough information :O"));
737 return;
738 }
739 std::string dir_str = tokens[0];
740 LLStringUtil::toLower(dir_str);
741 // Direction
742 BOOL outgoing;
743 if(dir_str == "out")
744 outgoing = TRUE;
745 else if(dir_str == "in")
746 outgoing = FALSE;
747 else
748 {
749 LLFloaterChat::addChat(LLChat("Expected direction 'in' or 'out'"));
750 return;
751 }
752 // Message
753 std::string message = "Invalid";
754 if(tokens.size() > 1)
755 {
756 if(tokens.size() > 2)
757 {
758 LLFloaterChat::addChat(LLChat("Unexpected extra stuff at the top"));
759 return;
760 }
761 message = tokens[1];
762 LLStringUtil::trim(message);
763 }
764 // Body
765 std::vector<parts_block> parts;
766 if(lines.size() > 1)
767 {
768 std::vector<std::string>::iterator line_end = lines.end();
769 std::vector<std::string>::iterator line_iter = lines.begin();
770 ++line_iter;
771 std::string current_block("");
772 int current_block_index = -1;
773 for( ; line_iter != line_end; ++line_iter)
774 {
775 std::string line = (*line_iter);
776 LLStringUtil::trim(line);
777 if(!line.length())
778 continue;
779 if(line.substr(0, 1) == "[" && line.substr(line.size() - 1, 1) == "]")
780 {
781 current_block = line.substr(1, line.length() - 2);
782 LLStringUtil::trim(current_block);
783 ++current_block_index;
784 parts_block pb;
785 pb.name = current_block;
786 parts.push_back(pb);
787 }
788 else
789 {
790 if(current_block.empty())
791 {
792 LLFloaterChat::addChat(LLChat("Unexpected field when no block yet"));
793 return;
794 }
795 int eqpos = line.find("=");
796 if(eqpos == line.npos)
797 {
798 LLFloaterChat::addChat(LLChat("Missing an equal sign"));
799 return;
800 }
801 std::string field = line.substr(0, eqpos);
802 LLStringUtil::trim(field);
803 if(!field.length())
804 {
805 LLFloaterChat::addChat(LLChat("Missing name of field"));
806 return;
807 }
808 std::string value = line.substr(eqpos + 1);
809 LLStringUtil::trim(value);
810 parts_var pv;
811 if(value.substr(0, 1) == "|")
812 {
813 pv.hex = TRUE;
814 value = value.substr(1);
815 LLStringUtil::trim(value);
816 }
817 else
818 pv.hex = FALSE;
819 pv.name = field;
820 pv.value = value;
821 parts[current_block_index].vars.push_back(pv);
822 }
823 }
824 }
825 // Verification
826 std::map<const char *, LLMessageTemplate*>::iterator template_iter;
827 template_iter = gMessageSystem->mMessageTemplates.find( LLMessageStringTable::getInstance()->getString(message.c_str()) );
828 if(template_iter == gMessageSystem->mMessageTemplates.end())
829 {
830 LLFloaterChat::addChat(LLChat(llformat("Don't know how to build a '%s' message", message.c_str())));
831 return;
832 }
833 LLMessageTemplate* temp = (*template_iter).second;
834 std::vector<parts_block>::iterator parts_end = parts.end();
835 std::vector<parts_block>::iterator parts_iter = parts.begin();
836 LLMessageTemplate::message_block_map_t::iterator blocks_end = temp->mMemberBlocks.end();
837 for (LLMessageTemplate::message_block_map_t::iterator blocks_iter = temp->mMemberBlocks.begin();
838 blocks_iter != blocks_end; )
839 {
840 LLMessageBlock* block = (*blocks_iter);
841 const char* block_name = block->mName;
842 if(parts_iter == parts_end)
843 {
844 if(block->mType != MBT_VARIABLE)
845 LLFloaterChat::addChat(LLChat(llformat("Expected '%s' block", block_name)));
846 else
847 {
848 ++blocks_iter;
849 continue;
850 }
851 return;
852 }
853 else if((*parts_iter).name != block_name)
854 {
855 if(block->mType != MBT_VARIABLE)
856 LLFloaterChat::addChat(LLChat(llformat("Expected '%s' block", block_name)));
857 else
858 {
859 ++blocks_iter;
860 continue;
861 }
862 return;
863 }
864 std::vector<parts_var>::iterator part_var_end = (*parts_iter).vars.end();
865 std::vector<parts_var>::iterator part_var_iter = (*parts_iter).vars.begin();
866 LLMessageBlock::message_variable_map_t::iterator var_end = block->mMemberVariables.end();
867 for (LLMessageBlock::message_variable_map_t::iterator var_iter = block->mMemberVariables.begin();
868 var_iter != var_end; ++var_iter)
869 {
870 LLMessageVariable* variable = (*var_iter);
871 const char* var_name = variable->getName();
872 if(part_var_iter == part_var_end)
873 {
874 LLFloaterChat::addChat(LLChat(llformat("Expected '%s' field under '%s' block", var_name, block_name)));
875 return;
876 }
877 else if((*part_var_iter).name != var_name)
878 {
879 LLFloaterChat::addChat(LLChat(llformat("Expected '%s' field under '%s' block", var_name, block_name)));
880 return;
881 }
882 (*part_var_iter).var_type = variable->getType();
883 ++part_var_iter;
884 }
885 if(part_var_iter != part_var_end)
886 {
887 LLFloaterChat::addChat(LLChat(llformat("Unexpected field(s) at end of '%s' block", block_name)));
888 return;
889 }
890 ++parts_iter;
891 // test
892 if((block->mType != MBT_SINGLE) && (parts_iter != parts_end) && ((*parts_iter).name == block_name))
893 {
894 // block will repeat
895 }
896 else ++blocks_iter;
897 }
898 if(parts_iter != parts_end)
899 {
900 LLFloaterChat::addChat(LLChat("Unexpected block(s) at end"));
901 return;
902 }
903 // Build and send
904 gMessageSystem->newMessage( message.c_str() );
905 for(parts_iter = parts.begin(); parts_iter != parts_end; ++parts_iter)
906 {
907 const char* block_name = (*parts_iter).name.c_str();
908 gMessageSystem->nextBlock(block_name);
909 std::vector<parts_var>::iterator part_var_end = (*parts_iter).vars.end();
910 for(std::vector<parts_var>::iterator part_var_iter = (*parts_iter).vars.begin();
911 part_var_iter != part_var_end; ++part_var_iter)
912 {
913 parts_var pv = (*part_var_iter);
914 if(!addField(pv.var_type, pv.name.c_str(), pv.value, pv.hex))
915 {
916 LLFloaterChat::addChat(LLChat(llformat("Error adding the provided data for %s '%s' to '%s' block", mvtstr(pv.var_type).c_str(), pv.name.c_str(), block_name)));
917 gMessageSystem->clearMessage();
918 return;
919 }
920 }
921 }
922
923 LLScrollListCtrl* scrollp = floaterp->getChild<LLScrollListCtrl>("net_list");
924 LLScrollListItem* selected_itemp = scrollp->getFirstSelected();
925
926 //if a specific circuit is selected, send it to that, otherwise send it to the current sim
927 if(selected_itemp)
928 {
929 LLNetListItem* itemp = findNetListItem(selected_itemp->getUUID());
930 LLScrollListText* textColumn = (LLScrollListText*)selected_itemp->getColumn(1);
931
932 //why would you send data through a dead circuit?
933 if(textColumn->getValue().asString() == "Dead")
934 {
935 LLFloaterChat::addChat(LLChat("No sending messages through dead circuits!"));
936 return;
937 }
938 if(outgoing)
939 {
940 gMessageSystem->sendMessage(itemp->mCircuitData->getHost());
941 } else {
942 U8 builtMessageBuffer[MAX_BUFFER_SIZE];
943
944 S32 message_size = gMessageSystem->mTemplateMessageBuilder->buildMessage(builtMessageBuffer, MAX_BUFFER_SIZE, 0);
945 gMessageSystem->clearMessage();
946 gMessageSystem->checkMessages(0, true, builtMessageBuffer, itemp->mCircuitData->getHost(), message_size);
947
948 }
949 } else {
950 if(outgoing)
951 {
952 gMessageSystem->sendMessage(gAgent.getRegionHost());
953 } else {
954 U8 builtMessageBuffer[MAX_BUFFER_SIZE];
955
956 S32 message_size = gMessageSystem->mTemplateMessageBuilder->buildMessage(builtMessageBuffer, MAX_BUFFER_SIZE, 0);
957 gMessageSystem->clearMessage();
958 gMessageSystem->checkMessages(0, true, builtMessageBuffer, gAgent.getRegionHost(), message_size);
959
960 }
961 }
962}
963
964BOOL LLFloaterMessageBuilder::handleKeyHere(KEY key, MASK mask)
965{
966 if(key == KEY_RETURN && (mask & MASK_CONTROL))
967 {
968 onClickSend(this);
969 return TRUE;
970 }
971 if(key == KEY_ESCAPE)
972 {
973 releaseFocus();
974 return TRUE;
975 }
976 return FALSE;
977}
978// </edit>
diff --git a/linden/indra/newview/llfloatermessagebuilder.h b/linden/indra/newview/llfloatermessagebuilder.h
new file mode 100644
index 0000000..5dc9b42
--- /dev/null
+++ b/linden/indra/newview/llfloatermessagebuilder.h
@@ -0,0 +1,55 @@
1// <edit>]
2#ifndef LL_LLFLOATERMESSAGEBUILDER_H
3#define LL_LLFLOATERMESSAGEBUILDER_H
4#include "llfloater.h"
5#include "lltemplatemessagereader.h"
6#include "llmessagelog.h"
7
8class LLNetListItem
9{
10public:
11 LLNetListItem(LLUUID id);
12 LLUUID mID;
13 BOOL mAutoName;
14 std::string mName;
15 std::string mPreviousRegionName;
16 LLCircuitData* mCircuitData;
17};
18
19class LLFloaterMessageBuilder : public LLFloater, public LLEventTimer
20{
21public:
22 LLFloaterMessageBuilder(std::string initial_text);
23 ~LLFloaterMessageBuilder();
24 static void show(std::string initial_text);
25 static std::list<LLNetListItem*> sNetListItems;
26 BOOL postBuild();
27 BOOL tick();
28 static BOOL addField(e_message_variable_type var_type, const char* var_name, std::string input, BOOL hex);
29 static void onClickSend(void* user_data);
30 static void onCommitPacketCombo(LLUICtrl* ctrl, void* user_data);
31 static LLFloaterMessageBuilder* sInstance;
32 BOOL handleKeyHere(KEY key, MASK mask);
33 std::string mInitialText;
34 struct parts_var
35 {
36 std::string name;
37 std::string value;
38 BOOL hex;
39 e_message_variable_type var_type;
40 };
41 struct parts_block
42 {
43 std::string name;
44 std::vector<parts_var> vars;
45 };
46 static LLNetListItem* findNetListItem(LLHost host);
47 static LLNetListItem* findNetListItem(LLUUID id);
48 void refreshNetList();
49 enum ENetInfoMode { NI_NET, NI_LOG };
50 ENetInfoMode mNetInfoMode;
51 static void onCommitMessageLog(LLUICtrl* ctrl, void* user_data);
52 static void onCommitFilter(LLUICtrl* ctrl, void* user_data);
53};
54#endif
55// </edit>
diff --git a/linden/indra/newview/llfloatermessagelog.cpp b/linden/indra/newview/llfloatermessagelog.cpp
new file mode 100644
index 0000000..161779b
--- /dev/null
+++ b/linden/indra/newview/llfloatermessagelog.cpp
@@ -0,0 +1,962 @@
1// <edit>
2#include "llviewerprecompiledheaders.h"
3#include "llfloatermessagelog.h"
4#include "lluictrlfactory.h"
5#include "llworld.h"
6#include "llviewerregion.h"
7#include "llscrolllistctrl.h"
8#include "lltexteditor.h"
9#include "llviewerwindow.h" // alertXml
10#include "llmessagetemplate.h"
11#include <boost/tokenizer.hpp>
12#include "llmenugl.h"
13#include "llfloatermessagebuilder.h"
14#include "llagent.h"
15////////////////////////////////
16// LLFloaterMessageLogItem
17////////////////////////////////
18#define MAX_PACKET_LEN (0x2000)
19LLTemplateMessageReader* LLFloaterMessageLogItem::sTemplateMessageReader = NULL;
20LLFloaterMessageLogItem::LLFloaterMessageLogItem(LLMessageLogEntry entry)
21: LLMessageLogEntry(entry.mType, entry.mFromHost, entry.mToHost, entry.mData, entry.mDataSize)
22{
23 if(!sTemplateMessageReader)
24 {
25 sTemplateMessageReader = new LLTemplateMessageReader(gMessageSystem->mMessageNumbers);
26 }
27 mID.generate();
28 mSequenceID = 0;
29 if(mType == TEMPLATE)
30 {
31 BOOL decode_invalid = FALSE;
32 S32 decode_len = mDataSize;
33 std::vector<U8> DecodeBuffer(MAX_PACKET_LEN,0);
34 memcpy(&(DecodeBuffer[0]),&(mData[0]),decode_len);
35 U8* decodep = &(DecodeBuffer[0]);
36 mFlags = DecodeBuffer[0];
37 gMessageSystem->zeroCodeExpand(&decodep, &decode_len);
38 if(decode_len < 7)
39 decode_invalid = TRUE;
40 else
41 {
42 mSequenceID = ntohl(*((U32*)(&decodep[1])));
43 sTemplateMessageReader->clearMessage();
44 if(!sTemplateMessageReader->validateMessage(decodep, decode_len, mFromHost, TRUE))
45 decode_invalid = TRUE;
46 else
47 {
48 if(!sTemplateMessageReader->decodeData(decodep, mFromHost, TRUE))
49 decode_invalid = TRUE;
50 else
51 {
52 LLMessageTemplate* temp = sTemplateMessageReader->getTemplate();
53 mName = temp->mName;
54 mSummary = "";
55
56 if(mFlags)
57 {
58 mSummary.append(" [ ");
59 if(mFlags & LL_ZERO_CODE_FLAG)
60 mSummary.append(" Zer ");
61 if(mFlags & LL_RELIABLE_FLAG)
62 mSummary.append(" Rel ");
63 if(mFlags & LL_RESENT_FLAG)
64 mSummary.append(" Rsd ");
65 if(mFlags & LL_ACK_FLAG)
66 mSummary.append(" Ack ");
67 mSummary.append(" ] ");
68 }
69
70 LLMessageTemplate::message_block_map_t::iterator blocks_end = temp->mMemberBlocks.end();
71 for (LLMessageTemplate::message_block_map_t::iterator blocks_iter = temp->mMemberBlocks.begin();
72 blocks_iter != blocks_end; ++blocks_iter)
73 {
74 LLMessageBlock* block = (*blocks_iter);
75 const char* block_name = block->mName;
76 S32 num_blocks = sTemplateMessageReader->getNumberOfBlocks(block_name);
77 if(!num_blocks)
78 mSummary.append(" { } ");
79 else if(num_blocks > 1)
80 mSummary.append(llformat(" %s [ %d ] { ... } ", block_name, num_blocks));
81 else for(S32 i = 0; i < 1; i++)
82 {
83 mSummary.append(" { ");
84 LLMessageBlock::message_variable_map_t::iterator var_end = block->mMemberVariables.end();
85 for (LLMessageBlock::message_variable_map_t::iterator var_iter = block->mMemberVariables.begin();
86 var_iter != var_end; ++var_iter)
87 {
88 LLMessageVariable* variable = (*var_iter);
89 const char* var_name = variable->getName();
90 BOOL returned_hex;
91 std::string value = getString(sTemplateMessageReader, block_name, i, var_name, variable->getType(), returned_hex, TRUE);
92 mSummary.append(llformat(" %s=%s ", var_name, value.c_str()));
93 }
94 mSummary.append(" } ");
95 if(mSummary.length() > 255) break;
96 }
97 if(mSummary.length() > 255)
98 {
99 mSummary.append(" ... ");
100 break;
101 }
102 } // blocks_iter
103 } // decode_valid
104 }
105 }
106 if(decode_invalid)
107 {
108 mName = "Invalid";
109 mSummary = "";
110 for(S32 i = 0; i < mDataSize; i++)
111 mSummary.append(llformat("%02X ", mData[i]));
112 }
113 }
114 else // not template
115 {
116 mName = "SOMETHING ELSE";
117 mSummary = "TODO: SOMETHING ELSE";
118 }
119}
120LLFloaterMessageLogItem::~LLFloaterMessageLogItem()
121{
122}
123BOOL LLFloaterMessageLogItem::isOutgoing()
124{
125 return mFromHost == LLHost(16777343, gMessageSystem->getListenPort());
126}
127std::string LLFloaterMessageLogItem::getFull(BOOL show_header)
128{
129 std::string full("");
130 if(mType == TEMPLATE)
131 {
132 BOOL decode_invalid = FALSE;
133 S32 decode_len = mDataSize;
134 std::vector<U8> DecodeBuffer(MAX_PACKET_LEN,0);
135 memcpy(&(DecodeBuffer[0]),&(mData[0]),decode_len);
136 U8* decodep = &(DecodeBuffer[0]);
137 gMessageSystem->zeroCodeExpand(&decodep, &decode_len);
138 if(decode_len < 7)
139 decode_invalid = TRUE;
140 else
141 {
142 sTemplateMessageReader->clearMessage();
143 if(!sTemplateMessageReader->validateMessage(decodep, decode_len, mFromHost, TRUE))
144 decode_invalid = TRUE;
145 else
146 {
147 if(!sTemplateMessageReader->decodeData(decodep, mFromHost, TRUE))
148 decode_invalid = TRUE;
149 else
150 {
151 LLMessageTemplate* temp = sTemplateMessageReader->getTemplate();
152 full.append(isOutgoing() ? "out " : "in ");
153 full.append(llformat("%s\n", temp->mName));
154 if(show_header)
155 {
156 full.append("[Header]\n");
157 full.append(llformat("SequenceID = %u\n", mSequenceID));
158 full.append(llformat("LL_ZERO_CODE_FLAG = %s\n", (mFlags & LL_ZERO_CODE_FLAG) ? "True" : "False"));
159 full.append(llformat("LL_RELIABLE_FLAG = %s\n", (mFlags & LL_RELIABLE_FLAG) ? "True" : "False"));
160 full.append(llformat("LL_RESENT_FLAG = %s\n", (mFlags & LL_RESENT_FLAG) ? "True" : "False"));
161 full.append(llformat("LL_ACK_FLAG = %s\n", (mFlags & LL_ACK_FLAG) ? "True" : "False"));
162 }
163 LLMessageTemplate::message_block_map_t::iterator blocks_end = temp->mMemberBlocks.end();
164 for (LLMessageTemplate::message_block_map_t::iterator blocks_iter = temp->mMemberBlocks.begin();
165 blocks_iter != blocks_end; ++blocks_iter)
166 {
167 LLMessageBlock* block = (*blocks_iter);
168 const char* block_name = block->mName;
169 S32 num_blocks = sTemplateMessageReader->getNumberOfBlocks(block_name);
170 for(S32 i = 0; i < num_blocks; i++)
171 {
172 full.append(llformat("[%s]\n", block->mName));
173 LLMessageBlock::message_variable_map_t::iterator var_end = block->mMemberVariables.end();
174 for (LLMessageBlock::message_variable_map_t::iterator var_iter = block->mMemberVariables.begin();
175 var_iter != var_end; ++var_iter)
176 {
177 LLMessageVariable* variable = (*var_iter);
178 const char* var_name = variable->getName();
179 BOOL returned_hex;
180 std::string value = getString(sTemplateMessageReader, block_name, i, var_name, variable->getType(), returned_hex);
181 if(returned_hex)
182 full.append(llformat("%s =| ", var_name));
183 else
184 full.append(llformat("%s = ", var_name));
185 // llformat has a 1024 char limit!?
186 full.append(value);
187 full.append("\n");
188 }
189 }
190 } // blocks_iter
191 } // decode_valid
192 }
193 }
194 if(decode_invalid)
195 {
196 full = isOutgoing() ? "out" : "in";
197 full.append("\n");
198 for(S32 i = 0; i < mDataSize; i++)
199 full.append(llformat("%02X ", mData[i]));
200 }
201 }
202 else // not template
203 {
204 full = "FIXME";
205 }
206 return full;
207}
208// static
209std::string LLFloaterMessageLogItem::getString(LLTemplateMessageReader* readerp, const char* block_name, S32 block_num, const char* var_name, e_message_variable_type var_type, BOOL &returned_hex, BOOL summary_mode)
210{
211 returned_hex = FALSE;
212 std::stringstream stream;
213 char* value;
214 U32 valueU32;
215 U16 valueU16;
216 LLVector3 valueVector3;
217 LLVector3d valueVector3d;
218 LLVector4 valueVector4;
219 LLQuaternion valueQuaternion;
220 LLUUID valueLLUUID;
221 switch(var_type)
222 {
223 case MVT_U8:
224 U8 valueU8;
225 readerp->getU8(block_name, var_name, valueU8, block_num);
226 stream << U32(valueU8);
227 break;
228 case MVT_U16:
229 readerp->getU16(block_name, var_name, valueU16, block_num);
230 stream << valueU16;
231 break;
232 case MVT_U32:
233 readerp->getU32(block_name, var_name, valueU32, block_num);
234 stream << valueU32;
235 break;
236 case MVT_U64:
237 U64 valueU64;
238 readerp->getU64(block_name, var_name, valueU64, block_num);
239 stream << valueU64;
240 break;
241 case MVT_S8:
242 S8 valueS8;
243 readerp->getS8(block_name, var_name, valueS8, block_num);
244 stream << S32(valueS8);
245 break;
246 case MVT_S16:
247 S16 valueS16;
248 readerp->getS16(block_name, var_name, valueS16, block_num);
249 stream << valueS16;
250 break;
251 case MVT_S32:
252 S32 valueS32;
253 readerp->getS32(block_name, var_name, valueS32, block_num);
254 stream << valueS32;
255 break;
256 /*case MVT_S64:
257 S64 valueS64;
258 readerp->getS64(block_name, var_name, valueS64, block_num);
259 stream << valueS64;
260 break;*/
261 case MVT_F32:
262 F32 valueF32;
263 readerp->getF32(block_name, var_name, valueF32, block_num);
264 stream << valueF32;
265 break;
266 case MVT_F64:
267 F64 valueF64;
268 readerp->getF64(block_name, var_name, valueF64, block_num);
269 stream << valueF64;
270 break;
271 case MVT_LLVector3:
272 readerp->getVector3(block_name, var_name, valueVector3, block_num);
273 //stream << valueVector3;
274 stream << "<" << valueVector3.mV[0] << ", " << valueVector3.mV[1] << ", " << valueVector3.mV[2] << ">";
275 break;
276 case MVT_LLVector3d:
277 readerp->getVector3d(block_name, var_name, valueVector3d, block_num);
278 //stream << valueVector3d;
279 stream << "<" << valueVector3d.mdV[0] << ", " << valueVector3d.mdV[1] << ", " << valueVector3d.mdV[2] << ">";
280 break;
281 case MVT_LLVector4:
282 readerp->getVector4(block_name, var_name, valueVector4, block_num);
283 //stream << valueVector4;
284 stream << "<" << valueVector4.mV[0] << ", " << valueVector4.mV[1] << ", " << valueVector4.mV[2] << ", " << valueVector4.mV[3] << ">";
285 break;
286 case MVT_LLQuaternion:
287 readerp->getQuat(block_name, var_name, valueQuaternion, block_num);
288 //stream << valueQuaternion;
289 stream << "<" << valueQuaternion.mQ[0] << ", " << valueQuaternion.mQ[1] << ", " << valueQuaternion.mQ[2] << ", " << valueQuaternion.mQ[3] << ">";
290 break;
291 case MVT_LLUUID:
292 readerp->getUUID(block_name, var_name, valueLLUUID, block_num);
293 stream << valueLLUUID;
294 break;
295 case MVT_BOOL:
296 BOOL valueBOOL;
297 readerp->getBOOL(block_name, var_name, valueBOOL, block_num);
298 stream << valueBOOL;
299 break;
300 case MVT_IP_ADDR:
301 readerp->getIPAddr(block_name, var_name, valueU32, block_num);
302 stream << LLHost(valueU32, 0).getIPString();
303 break;
304 case MVT_IP_PORT:
305 readerp->getIPPort(block_name, var_name, valueU16, block_num);
306 stream << valueU16;
307 case MVT_VARIABLE:
308 case MVT_FIXED:
309 default:
310 S32 size = readerp->getSize(block_name, block_num, var_name);
311 if(size)
312 {
313 value = new char[size + 1];
314 readerp->getBinaryData(block_name, var_name, value, size, block_num);
315 value[size] = '\0';
316 S32 readable = 0;
317 S32 unreadable = 0;
318 S32 end = (summary_mode && (size > 64)) ? 64 : size;
319 for(S32 i = 0; i < end; i++)
320 {
321 if(!value[i])
322 {
323 if(i != (end - 1))
324 { // don't want null terminator hiding data
325 unreadable = S32_MAX;
326 break;
327 }
328 }
329 else if(value[i] < 0x20 || value[i] >= 0x7F)
330 {
331 if(summary_mode)
332 unreadable++;
333 else
334 { // never want any wrong characters outside of summary mode
335 unreadable = S32_MAX;
336 break;
337 }
338 }
339 else readable++;
340 }
341 if(readable >= unreadable)
342 {
343 if(summary_mode && (size > 64))
344 {
345 for(S32 i = 60; i < 63; i++)
346 value[i] = '.';
347 value[63] = '\0';
348 }
349 stream << value;
350
351 delete[] value;
352 }
353 else
354 {
355 returned_hex = TRUE;
356 S32 end = (summary_mode && (size > 8)) ? 8 : size;
357 for(S32 i = 0; i < end; i++)
358 //stream << std::uppercase << std::hex << U32(value[i]) << " ";
359 stream << llformat("%02X ", (U8)value[i]);
360 if(summary_mode && (size > 8))
361 stream << " ... ";
362 }
363 }
364 break;
365 }
366
367 return stream.str();
368}
369LLMessageLogFilter::LLMessageLogFilter()
370{
371}
372LLMessageLogFilter::~LLMessageLogFilter()
373{
374}
375BOOL LLMessageLogFilter::set(std::string filter)
376{
377 mPositiveNames.clear();
378 mNegativeNames.clear();
379 typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
380 boost::char_separator<char> sep(" ","",boost::keep_empty_tokens);
381 boost::tokenizer<boost::char_separator<char> > tokens(filter, sep);
382 boost::tokenizer<boost::char_separator<char> >::iterator end = tokens.end();
383 for(boost::tokenizer<boost::char_separator<char> >::iterator iter = tokens.begin(); iter != end; ++iter)
384 {
385 std::string token = (*iter);
386 LLStringUtil::trim(token);
387 LLStringUtil::toLower(token);
388 BOOL negative = token.find("!") == 0;
389 if(negative)
390 {
391 token = token.substr(1);
392 mNegativeNames.push_back(token);
393 }
394 else
395 mPositiveNames.push_back(token);
396 }
397 return TRUE;
398}
399////////////////////////////////
400// LLMessageLogFilterApply
401////////////////////////////////
402LLMessageLogFilterApply::LLMessageLogFilterApply()
403: LLEventTimer(0.1f),
404 mFinished(FALSE),
405 mProgress(0)
406{
407 mIter = LLFloaterMessageLog::sMessageLogEntries.begin();
408}
409void LLMessageLogFilterApply::cancel()
410{
411 mFinished = TRUE;
412}
413BOOL LLMessageLogFilterApply::tick()
414{
415 std::deque<LLMessageLogEntry>::iterator end = LLFloaterMessageLog::sMessageLogEntries.end();
416 if(mIter == end || !LLFloaterMessageLog::sInstance)
417 {
418 mFinished = TRUE;
419 if(LLFloaterMessageLog::sInstance)
420 {
421 if(LLFloaterMessageLog::sInstance->mMessageLogFilterApply == this)
422 {
423 LLFloaterMessageLog::sInstance->stopApplyingFilter();
424 }
425 }
426 return TRUE;
427 }
428 for(S32 i = 0; i < 256; i++)
429 {
430 if(mIter == end)
431 {
432 mFinished = TRUE;
433 if(LLFloaterMessageLog::sInstance)
434 {
435 if(LLFloaterMessageLog::sInstance->mMessageLogFilterApply == this)
436 {
437 LLFloaterMessageLog::sInstance->stopApplyingFilter();
438
439 //we're done messing with the deque, push all queued items to the main deque
440 std::deque<LLMessageLogEntry>::iterator queueIter = mQueuedMessages.begin();
441 std::deque<LLMessageLogEntry>::iterator queueEnd = mQueuedMessages.end();
442
443 while(queueIter != queueEnd)
444 {
445 LLFloaterMessageLog::sInstance->conditionalLog(LLFloaterMessageLogItem((*queueIter)));
446 ++queueIter;
447 }
448
449 mQueuedMessages.clear();
450 }
451 }
452
453 return TRUE;
454 }
455
456 LLFloaterMessageLog::sInstance->conditionalLog(LLFloaterMessageLogItem((*mIter)));
457
458 mIter++;
459 mProgress++;
460 }
461 LLFloaterMessageLog::sInstance->updateFilterStatus();
462 return FALSE;
463}
464////////////////////////////////
465// LLFloaterMessageLog
466////////////////////////////////
467LLFloaterMessageLog* LLFloaterMessageLog::sInstance;
468std::list<LLNetListItem*> LLFloaterMessageLog::sNetListItems;
469std::deque<LLMessageLogEntry> LLFloaterMessageLog::sMessageLogEntries;
470std::vector<LLFloaterMessageLogItem> LLFloaterMessageLog::sFloaterMessageLogItems;
471LLMessageLogFilter LLFloaterMessageLog::sMessageLogFilter = LLMessageLogFilter();
472std::string LLFloaterMessageLog::sMessageLogFilterString("!StartPingCheck !CompletePingCheck !PacketAck !SimulatorViewerTimeMessage !SimStats !AgentUpdate !AgentAnimation !AvatarAnimation !ViewerEffect !CoarseLocationUpdate !LayerData !CameraConstraint !ObjectUpdateCached !RequestMultipleObjects !ObjectUpdate !ObjectUpdateCompressed !ImprovedTerseObjectUpdate !KillObject !ImagePacket !SendXferPacket !ConfirmXferPacket !TransferPacket !SoundTrigger !AttachedSound !PreloadSound");
473BOOL LLFloaterMessageLog::sBusyApplyingFilter = FALSE;
474LLFloaterMessageLog::LLFloaterMessageLog()
475: LLFloater(),
476 LLEventTimer(1.0f),
477 mNetInfoMode(NI_NET),
478 mMessageLogFilterApply(NULL)
479{
480 sInstance = this;
481 LLMessageLog::setCallback(onLog);
482 sMessageLogEntries = LLMessageLog::getDeque();
483 LLUICtrlFactory::getInstance()->buildFloater(this, "floater_message_log.xml");
484}
485LLFloaterMessageLog::~LLFloaterMessageLog()
486{
487 LLMessageLog::setCallback(NULL);
488 stopApplyingFilter();
489 sInstance = NULL;
490 sNetListItems.clear();
491 sMessageLogEntries.clear();
492 sFloaterMessageLogItems.clear();
493}
494// static
495void LLFloaterMessageLog::show()
496{
497 if(!sInstance) sInstance = new LLFloaterMessageLog();
498 sInstance->open();
499}
500BOOL LLFloaterMessageLog::postBuild()
501{
502 childSetCommitCallback("net_list", onCommitNetList, this);
503 childSetCommitCallback("message_log", onCommitMessageLog, this);
504 childSetAction("filter_choice_btn", onClickFilterChoice, this);
505 childSetAction("filter_apply_btn", onClickFilterApply, this);
506 childSetCommitCallback("filter_edit", onCommitFilter, this);
507 childSetAction("clear_log_btn", onClickClearLog, this);
508 childSetAction("send_to_message_builder_btn", onClickSendToMessageBuilder, this);
509 childSetText("filter_edit", sMessageLogFilterString);
510 refreshNetList();
511 refreshNetInfo(TRUE);
512 startApplyingFilter(sMessageLogFilterString, TRUE);
513 return TRUE;
514}
515BOOL LLFloaterMessageLog::tick()
516{
517 refreshNetList();
518 refreshNetInfo(FALSE);
519 return FALSE;
520}
521LLNetListItem* LLFloaterMessageLog::findNetListItem(LLHost host)
522{
523 std::list<LLNetListItem*>::iterator end = sNetListItems.end();
524 for(std::list<LLNetListItem*>::iterator iter = sNetListItems.begin(); iter != end; ++iter)
525 if((*iter)->mCircuitData && (*iter)->mCircuitData->getHost() == host)
526 return (*iter);
527 return NULL;
528}
529LLNetListItem* LLFloaterMessageLog::findNetListItem(LLUUID id)
530{
531 std::list<LLNetListItem*>::iterator end = sNetListItems.end();
532 for(std::list<LLNetListItem*>::iterator iter = sNetListItems.begin(); iter != end; ++iter)
533 if((*iter)->mID == id)
534 return (*iter);
535 return NULL;
536}
537void LLFloaterMessageLog::refreshNetList()
538{
539 LLScrollListCtrl* scrollp = getChild<LLScrollListCtrl>("net_list");
540 // Update circuit data of net list items
541 std::vector<LLCircuitData*> circuits = gMessageSystem->getCircuit()->getCircuitDataList();
542 std::vector<LLCircuitData*>::iterator circuits_end = circuits.end();
543 for(std::vector<LLCircuitData*>::iterator iter = circuits.begin(); iter != circuits_end; ++iter)
544 {
545 LLNetListItem* itemp = findNetListItem((*iter)->getHost());
546 if(!itemp)
547 {
548 LLUUID id; id.generate();
549 itemp = new LLNetListItem(id);
550 sNetListItems.push_back(itemp);
551 }
552 itemp->mCircuitData = (*iter);
553 }
554 // Clear circuit data of items whose circuits are gone
555 std::list<LLNetListItem*>::iterator items_end = sNetListItems.end();
556 for(std::list<LLNetListItem*>::iterator iter = sNetListItems.begin(); iter != items_end; ++iter)
557 {
558 if(std::find(circuits.begin(), circuits.end(), (*iter)->mCircuitData) == circuits.end())
559 (*iter)->mCircuitData = NULL;
560 }
561 // Remove net list items that are totally useless now
562 for(std::list<LLNetListItem*>::iterator iter = sNetListItems.begin(); iter != sNetListItems.end();)
563 {
564 if((*iter)->mCircuitData == NULL)
565 iter = sNetListItems.erase(iter);
566 else ++iter;
567 }
568 // Update names of net list items
569 items_end = sNetListItems.end();
570 for(std::list<LLNetListItem*>::iterator iter = sNetListItems.begin(); iter != items_end; ++iter)
571 {
572 LLNetListItem* itemp = (*iter);
573 if(itemp->mAutoName)
574 {
575 if(itemp->mCircuitData)
576 {
577 LLViewerRegion* regionp = LLWorld::getInstance()->getRegion(itemp->mCircuitData->getHost());
578 if(regionp)
579 {
580 std::string name = regionp->getName();
581 if(name == "") name = llformat("%s (awaiting region name)", itemp->mCircuitData->getHost().getString().c_str());
582 itemp->mName = name;
583 itemp->mPreviousRegionName = name;
584 }
585 else
586 {
587 itemp->mName = itemp->mCircuitData->getHost().getString();
588 if(itemp->mPreviousRegionName != "")
589 itemp->mName.append(llformat(" (was %s)", itemp->mPreviousRegionName.c_str()));
590 }
591 }
592 else
593 {
594 // an item just for an event queue, not handled yet
595 itemp->mName = "Something else";
596 }
597 }
598 }
599 // Rebuild scroll list from scratch
600 LLUUID selected_id = scrollp->getFirstSelected() ? scrollp->getFirstSelected()->getUUID() : LLUUID::null;
601 S32 scroll_pos = scrollp->getScrollPos();
602 scrollp->clearRows();
603 for(std::list<LLNetListItem*>::iterator iter = sNetListItems.begin(); iter != items_end; ++iter)
604 {
605 LLNetListItem* itemp = (*iter);
606 LLSD element;
607 element["id"] = itemp->mID;
608 LLSD& text_column = element["columns"][0];
609 text_column["column"] = "text";
610 text_column["value"] = itemp->mName + (itemp->mCircuitData->getHost() == gAgent.getRegionHost() ? " (main)" : "");
611 for(int i = 0; i < 2; i++)
612 {
613 LLSD& icon_column = element["columns"][i + 1];
614 icon_column["column"] = llformat("icon%d", i);
615 icon_column["type"] = "icon";
616 icon_column["value"] = "";
617 }
618 LLScrollListItem* scroll_itemp = scrollp->addElement(element);
619 BOOL has_live_circuit = itemp->mCircuitData && itemp->mCircuitData->isAlive();
620 if(has_live_circuit)
621 {
622 LLScrollListIcon* icon = (LLScrollListIcon*)scroll_itemp->getColumn(1);
623 icon->setValue("icon_net_close_circuit.tga");
624 icon->setClickCallback(onClickCloseCircuit, itemp);
625 }
626 else
627 {
628 LLScrollListIcon* icon = (LLScrollListIcon*)scroll_itemp->getColumn(1);
629 icon->setValue("icon_net_close_circuit_gray.tga");
630 icon->setClickCallback(NULL, NULL);
631 }
632 // Event queue isn't even supported yet... FIXME
633 LLScrollListIcon* icon = (LLScrollListIcon*)scroll_itemp->getColumn(2);
634 icon->setValue("icon_net_close_eventpoll_gray.tga");
635 icon->setClickCallback(NULL, NULL);
636 }
637 if(selected_id.notNull()) scrollp->selectByID(selected_id);
638 if(scroll_pos < scrollp->getItemCount()) scrollp->setScrollPos(scroll_pos);
639}
640void LLFloaterMessageLog::refreshNetInfo(BOOL force)
641{
642 if(mNetInfoMode != NI_NET) return;
643 LLScrollListCtrl* scrollp = getChild<LLScrollListCtrl>("net_list");
644 LLScrollListItem* selected_itemp = scrollp->getFirstSelected();
645 if(selected_itemp)
646 {
647 if(!force) if(getChild<LLTextEditor>("net_info")->hasSelection()) return;
648 LLNetListItem* itemp = findNetListItem(selected_itemp->getUUID());
649 if(itemp)
650 {
651 std::string info(llformat("%s\n--------------------------------\n\n", itemp->mName.c_str()));
652 if(itemp->mCircuitData)
653 {
654 LLCircuitData* cdp = itemp->mCircuitData;
655 info.append("Circuit\n--------------------------------\n");
656 info.append(llformat(" * Host: %s\n", cdp->getHost().getString().c_str()));
657 S32 seconds = (S32)cdp->getAgeInSeconds();
658 S32 minutes = seconds / 60;
659 seconds = seconds % 60;
660 S32 hours = minutes / 60;
661 minutes = minutes % 60;
662 info.append(llformat(" * Age: %dh %dm %ds\n", hours, minutes, seconds));
663 info.append(llformat(" * Alive: %s\n", cdp->isAlive() ? "yes" : "no"));
664 info.append(llformat(" * Blocked: %s\n", cdp->isBlocked() ? "yes" : "no"));
665 info.append(llformat(" * Allow timeout: %s\n", cdp->getAllowTimeout() ? "yes" : "no"));
666 info.append(llformat(" * Trusted: %s\n", cdp->getTrusted() ? "yes" : "no"));
667 info.append(llformat(" * Ping delay: %d\n", cdp->getPingDelay()));
668 info.append(llformat(" * Packets out: %d\n", cdp->getPacketsOut()));
669 info.append(llformat(" * Bytes out: %d\n", cdp->getBytesOut()));
670 info.append(llformat(" * Packets in: %d\n", cdp->getPacketsIn()));
671 info.append(llformat(" * Bytes in: %d\n", cdp->getBytesIn()));
672 info.append(llformat(" * Endpoint ID: %s\n", cdp->getLocalEndPointID().asString().c_str()));
673 info.append(llformat(" * Remote ID: %s\n", cdp->getRemoteID().asString().c_str()));
674 info.append(llformat(" * Remote session ID: %s\n", cdp->getRemoteSessionID().asString().c_str()));
675 }
676 childSetText("net_info", info);
677 }
678 else childSetText("net_info", std::string(""));
679 }
680 else childSetText("net_info", std::string(""));
681}
682void LLFloaterMessageLog::setNetInfoMode(ENetInfoMode mode)
683{
684 mNetInfoMode = mode;
685 if(mNetInfoMode == NI_NET)
686 refreshNetInfo(TRUE);
687 childSetEnabled("send_to_message_builder_btn", mNetInfoMode == NI_LOG);
688}
689// static
690void LLFloaterMessageLog::onLog(LLMessageLogEntry entry)
691{
692 //don't mess with the queue while a filter's being applied, or face invalid iterators
693 if(!sBusyApplyingFilter)
694 {
695 sMessageLogEntries.push_back(entry);
696 conditionalLog(LLFloaterMessageLogItem(entry));
697 }
698}
699// static
700void LLFloaterMessageLog::conditionalLog(LLFloaterMessageLogItem item)
701{
702 if(!sBusyApplyingFilter)
703 sInstance->childSetText("log_status_text", llformat("Showing %d messages from %d", sFloaterMessageLogItems.size(), sMessageLogEntries.size()));
704 std::string find_name = item.mName;
705 LLStringUtil::toLower(find_name);
706 if(sMessageLogFilter.mPositiveNames.size())
707 if(std::find(sMessageLogFilter.mPositiveNames.begin(), sMessageLogFilter.mPositiveNames.end(), find_name) == sMessageLogFilter.mPositiveNames.end())
708 return;
709 if(std::find(sMessageLogFilter.mNegativeNames.begin(), sMessageLogFilter.mNegativeNames.end(), find_name) != sMessageLogFilter.mNegativeNames.end())
710 return;
711 sFloaterMessageLogItems.push_back(item); // moved from beginning...
712 BOOL outgoing = item.isOutgoing();
713 std::string net_name("\?\?\?");
714 if(item.mType == LLFloaterMessageLogItem::TEMPLATE)
715 {
716 LLHost find_host = outgoing ? item.mToHost : item.mFromHost;
717 net_name = find_host.getIPandPort();
718 std::list<LLNetListItem*>::iterator end = sNetListItems.end();
719 for(std::list<LLNetListItem*>::iterator iter = sNetListItems.begin(); iter != end; ++iter)
720 {
721 if((*iter)->mCircuitData->getHost() == find_host)
722 {
723 net_name = (*iter)->mName;
724 break;
725 }
726 }
727 }
728 LLSD element;
729 element["id"] = item.mID;
730 LLSD& sequence_column = element["columns"][0];
731 sequence_column["column"] = "sequence";
732 sequence_column["value"] = llformat("%u", item.mSequenceID);
733 LLSD& type_column = element["columns"][1];
734 type_column["column"] = "type";
735 type_column["value"] = item.mType == LLFloaterMessageLogItem::TEMPLATE ? "UDP" : "\?\?\?";
736 LLSD& direction_column = element["columns"][2];
737 direction_column["column"] = "direction";
738 direction_column["value"] = outgoing ? "to" : "from";
739 LLSD& net_column = element["columns"][3];
740 net_column["column"] = "net";
741 net_column["value"] = net_name;
742 LLSD& name_column = element["columns"][4];
743 name_column["column"] = "name";
744 name_column["value"] = item.mName;
745 /*
746 LLSD& zer_column = element["columns"][5];
747 zer_column["column"] = "flag_zer";
748 zer_column["type"] = "icon";
749 zer_column["value"] = (item.mFlags & LL_ZERO_CODE_FLAG) ? "flag_zer.tga" : "";
750 LLSD& rel_column = element["columns"][6];
751 rel_column["column"] = "flag_rel";
752 rel_column["type"] = "icon";
753 rel_column["value"] = (item.mFlags & LL_RELIABLE_FLAG) ? "flag_rel.tga" : "";
754 LLSD& rsd_column = element["columns"][7];
755 rsd_column["column"] = "flag_rsd";
756 rsd_column["type"] = "icon";
757 rsd_column["value"] = (item.mFlags & LL_RESENT_FLAG) ? "flag_rsd.tga" : "";
758 LLSD& ack_column = element["columns"][8];
759 ack_column["column"] = "flag_ack";
760 ack_column["type"] = "icon";
761 ack_column["value"] = (item.mFlags & LL_ACK_FLAG) ? "flag_ack.tga" : "";
762 */
763 LLSD& summary_column = element["columns"][5];
764 summary_column["column"] = "summary";
765 summary_column["value"] = item.mSummary;
766 LLScrollListCtrl* scrollp = sInstance->getChild<LLScrollListCtrl>("message_log");
767 S32 scroll_pos = scrollp->getScrollPos();
768 scrollp->addElement(element);
769 if(scroll_pos > scrollp->getItemCount() - scrollp->getPageLines() - 4)
770 scrollp->setScrollPos(scrollp->getItemCount());
771}
772// static
773void LLFloaterMessageLog::onCommitNetList(LLUICtrl* ctrl, void* user_data)
774{
775 LLFloaterMessageLog* floaterp = (LLFloaterMessageLog*)user_data;
776 floaterp->setNetInfoMode(NI_NET);
777 floaterp->refreshNetInfo(TRUE);
778}
779// static
780void LLFloaterMessageLog::onCommitMessageLog(LLUICtrl* ctrl, void* user_data)
781{
782 LLFloaterMessageLog* floaterp = (LLFloaterMessageLog*)user_data;
783 LLScrollListCtrl* scrollp = floaterp->getChild<LLScrollListCtrl>("message_log");
784 LLScrollListItem* selected_itemp = scrollp->getFirstSelected();
785 if(!selected_itemp) return;
786 LLUUID id = selected_itemp->getUUID();
787 std::vector<LLFloaterMessageLogItem>::iterator end = sFloaterMessageLogItems.end();
788 for(std::vector<LLFloaterMessageLogItem>::iterator iter = sFloaterMessageLogItems.begin(); iter != end; ++iter)
789 {
790 if(iter->mID == id)
791 {
792 floaterp->setNetInfoMode(NI_LOG);
793 floaterp->childSetText("net_info", iter->getFull(FALSE));
794 break;
795 }
796 }
797}
798// static
799BOOL LLFloaterMessageLog::onClickCloseCircuit(void* user_data)
800{
801 LLNetListItem* itemp = (LLNetListItem*)user_data;
802 LLCircuitData* cdp = (LLCircuitData*)itemp->mCircuitData;
803 if(!cdp) return FALSE;
804 LLHost myhost = cdp->getHost();
805 LLSD args;
806 args["MESSAGE"] = "This will delete local circuit data.\nDo you want to tell the remote host to close the circuit too?";
807 LLSD payload;
808 payload["circuittoclose"] = myhost.getString();
809 LLNotifications::instance().add("GenericAlertYesCancel", args, payload, onConfirmCloseCircuit);
810 return TRUE;
811}
812// static
813bool LLFloaterMessageLog::onConfirmCloseCircuit(const LLSD& notification, const LLSD& response )
814{
815 S32 option = LLNotification::getSelectedOption(notification, response);
816 LLCircuitData* cdp = gMessageSystem->mCircuitInfo.findCircuit(LLHost(notification["payload"]["circuittoclose"].asString()));
817 if(!cdp) return false;
818 LLViewerRegion* regionp = LLWorld::getInstance()->getRegion(cdp->getHost());
819 switch(option)
820 {
821 case 0: // yes
822 gMessageSystem->newMessageFast(_PREHASH_CloseCircuit);
823 gMessageSystem->sendReliable(cdp->getHost());
824 break;
825 case 2: // cancel
826 return false;
827 break;
828 case 1: // no
829 default:
830 break;
831 }
832 if(gMessageSystem->findCircuitCode(cdp->getHost()))
833 gMessageSystem->disableCircuit(cdp->getHost());
834 else
835 gMessageSystem->getCircuit()->removeCircuitData(cdp->getHost());
836 if(regionp)
837 {
838 LLHost myhost = regionp->getHost();
839 LLSD args;
840 args["MESSAGE"] = "That host had a region associated with it.\nDo you want to clean that up?";
841 LLSD payload;
842 payload["regionhost"] = myhost.getString();
843 LLNotifications::instance().add("GenericAlertYesCancel", args, payload, onConfirmRemoveRegion);
844 }
845 return false;
846}
847// static
848bool LLFloaterMessageLog::onConfirmRemoveRegion(const LLSD& notification, const LLSD& response )
849{
850 S32 option = LLNotification::getSelectedOption(notification, response);
851 if(option == 0) // yes
852 LLWorld::getInstance()->removeRegion(LLHost(notification["payload"]["regionhost"].asString()));
853 return false;
854}
855// static
856void LLFloaterMessageLog::onClickFilterApply(void* user_data)
857{
858 LLFloaterMessageLog* floaterp = (LLFloaterMessageLog*)user_data;
859 floaterp->startApplyingFilter(floaterp->childGetValue("filter_edit"), FALSE);
860}
861void LLFloaterMessageLog::startApplyingFilter(std::string filter, BOOL force)
862{
863 LLMessageLogFilter new_filter = LLMessageLogFilter();
864 sMessageLogFilterString = filter;
865 new_filter.set(sMessageLogFilterString);
866 if(!filter.length() || filter.at(filter.length()-1) != ' ')
867 childSetText("filter_edit", filter + " ");
868 if(force
869 || (new_filter.mNegativeNames != sMessageLogFilter.mNegativeNames)
870 || (new_filter.mPositiveNames != sMessageLogFilter.mPositiveNames))
871 {
872 stopApplyingFilter();
873 sMessageLogFilter = new_filter;
874 sFloaterMessageLogItems.clear();
875 getChild<LLScrollListCtrl>("message_log")->clearRows();
876 sBusyApplyingFilter = TRUE;
877 childSetVisible("message_log", false);
878 //childSetVisible("log_status_text", true);
879 mMessageLogFilterApply = new LLMessageLogFilterApply();
880 }
881}
882void LLFloaterMessageLog::stopApplyingFilter()
883{
884 if(mMessageLogFilterApply)
885 {
886 if(!(mMessageLogFilterApply->mFinished))
887 mMessageLogFilterApply->cancel();
888 //delete mMessageLogFilterApply;
889 sBusyApplyingFilter = FALSE;
890 //childSetVisible("log_status_text", false);
891 childSetVisible("message_log", true);
892 childSetText("log_status_text", llformat("Showing %d messages from %d", sFloaterMessageLogItems.size(), sMessageLogEntries.size()));
893 }
894}
895void LLFloaterMessageLog::updateFilterStatus()
896{
897 if(!mMessageLogFilterApply || !sBusyApplyingFilter) return;
898 S32 progress = mMessageLogFilterApply->mProgress;
899 S32 packets = sMessageLogEntries.size();
900 S32 matches = sFloaterMessageLogItems.size();
901 std::string text = llformat("Applying filter ( %d / %d ), %d matches ...", progress, packets, matches);
902 childSetText("log_status_text", text);
903}
904// static
905void LLFloaterMessageLog::onCommitFilter(LLUICtrl* ctrl, void* user_data)
906{
907 LLFloaterMessageLog* floaterp = (LLFloaterMessageLog*)user_data;
908 floaterp->startApplyingFilter(floaterp->childGetValue("filter_edit"), FALSE);
909}
910// static
911void LLFloaterMessageLog::onClickClearLog(void* user_data)
912{
913 LLFloaterMessageLog* floaterp = (LLFloaterMessageLog*)user_data;
914 floaterp->stopApplyingFilter();
915 floaterp->getChild<LLScrollListCtrl>("message_log")->clearRows();
916 floaterp->setNetInfoMode(NI_NET);
917 sMessageLogEntries.clear();
918 sFloaterMessageLogItems.clear();
919}
920// static
921void LLFloaterMessageLog::onClickFilterChoice(void* user_data)
922{
923 LLMenuGL* menu = new LLMenuGL(LLStringUtil::null);
924 menu->append(new LLMenuItemCallGL("No filter", onClickFilterMenu, NULL, (void*)""));
925 menu->append(new LLMenuItemCallGL("Fewer spammy messages", onClickFilterMenu, NULL, (void*)"!StartPingCheck !CompletePingCheck !PacketAck !SimulatorViewerTimeMessage !SimStats !AgentUpdate !AgentAnimation !AvatarAnimation !ViewerEffect !CoarseLocationUpdate !LayerData !CameraConstraint !ObjectUpdateCached !RequestMultipleObjects !ObjectUpdate !ObjectUpdateCompressed !ImprovedTerseObjectUpdate !KillObject !ImagePacket !SendXferPacket !ConfirmXferPacket !TransferPacket"));
926 menu->append(new LLMenuItemCallGL("Fewer spammy messages (minus sound crap)", onClickFilterMenu, NULL, (void*)"!StartPingCheck !CompletePingCheck !PacketAck !SimulatorViewerTimeMessage !SimStats !AgentUpdate !AgentAnimation !AvatarAnimation !ViewerEffect !CoarseLocationUpdate !LayerData !CameraConstraint !ObjectUpdateCached !RequestMultipleObjects !ObjectUpdate !ObjectUpdateCompressed !ImprovedTerseObjectUpdate !KillObject !ImagePacket !SendXferPacket !ConfirmXferPacket !TransferPacket !SoundTrigger !AttachedSound !PreloadSound"));
927 menu->append(new LLMenuItemCallGL("Object updates", onClickFilterMenu, NULL, (void*)"ObjectUpdateCached ObjectUpdate ObjectUpdateCompressed ImprovedTerseObjectUpdate KillObject RequestMultipleObjects"));
928 menu->append(new LLMenuItemCallGL("Abnormal", onClickFilterMenu, NULL, (void*)"Invalid TestMessage AddCircuitCode NeighborList AvatarTextureUpdate SimulatorMapUpdate SimulatorSetMap SubscribeLoad UnsubscribeLoad SimulatorReady SimulatorPresentAtLocation SimulatorLoad SimulatorShutdownRequest RegionPresenceRequestByRegionID RegionPresenceRequestByHandle RegionPresenceResponse UpdateSimulator LogDwellTime FeatureDisabled LogFailedMoneyTransaction UserReportInternal SetSimStatusInDatabase SetSimPresenceInDatabase OpenCircuit CloseCircuit DirFindQueryBackend DirPlacesQueryBackend DirClassifiedQueryBackend DirLandQueryBackend DirPopularQueryBackend GroupNoticeAdd DataHomeLocationRequest DataHomeLocationReply DerezContainer ObjectCategory ObjectExportSelected StateSave ReportAutosaveCrash AgentAlertMessage NearestLandingRegionRequest NearestLandingRegionReply NearestLandingRegionUpdated TeleportLandingStatusChanged ConfirmEnableSimulator KickUserAck SystemKickUser AvatarPropertiesRequestBackend UpdateParcel RemoveParcel MergeParcel LogParcelChanges CheckParcelSales ParcelSales StartAuction ConfirmAuctionStart CompleteAuction CancelAuction CheckParcelAuctions ParcelAuctions ChatPass EdgeDataPacket SimStatus ChildAgentUpdate ChildAgentAlive ChildAgentPositionUpdate ChildAgentDying ChildAgentUnknown AtomicPassObject KillChildAgents ScriptSensorRequest ScriptSensorReply DataServerLogout RequestInventoryAsset InventoryAssetResponse TransferInventory TransferInventoryAck EventLocationRequest EventLocationReply MoneyTransferBackend RoutedMoneyBalanceReply SetStartLocation NetTest SetCPURatio SimCrashed NameValuePair RemoveNameValuePair UpdateAttachment RemoveAttachment EmailMessageRequest EmailMessageReply InternalScriptMail ScriptDataRequest ScriptDataReply InviteGroupResponse TallyVotes LiveHelpGroupRequest LiveHelpGroupReply GroupDataUpdate LogTextMessage CreateTrustedCircuit ParcelRename SystemMessage RpcChannelRequest RpcChannelReply RpcScriptRequestInbound RpcScriptRequestInboundForward RpcScriptReplyInbound ScriptMailRegistration Error"));
929 menu->updateParent(LLMenuGL::sMenuContainer);
930 menu->setCanTearOff(FALSE);
931 LLView* buttonp = sInstance->getChild<LLView>("filter_choice_btn");
932 S32 x = buttonp->getRect().mLeft;
933 S32 y = buttonp->getRect().mBottom;
934 LLMenuGL::showPopup(sInstance, menu, x, y);
935}
936// static
937void LLFloaterMessageLog::onClickFilterMenu(void* user_data)
938{
939 std::string filter = std::string((char*)user_data);
940 sInstance->childSetText("filter_edit", filter);
941 sInstance->startApplyingFilter(filter, FALSE);
942}
943// static
944void LLFloaterMessageLog::onClickSendToMessageBuilder(void* user_data)
945{
946 LLFloaterMessageLog* floaterp = (LLFloaterMessageLog*)user_data;
947 LLScrollListCtrl* scrollp = floaterp->getChild<LLScrollListCtrl>("message_log");
948 LLScrollListItem* selected_itemp = scrollp->getFirstSelected();
949 if(!selected_itemp) return;
950 LLUUID id = selected_itemp->getUUID();
951 std::vector<LLFloaterMessageLogItem>::iterator end = sFloaterMessageLogItems.end();
952 for(std::vector<LLFloaterMessageLogItem>::iterator iter = sFloaterMessageLogItems.begin(); iter != end; ++iter)
953 {
954 if(iter->mID == id)
955 {
956 std::string message_text = iter->getFull(FALSE);
957 LLFloaterMessageBuilder::show(message_text);
958 break;
959 }
960 }
961}
962// </edit>
diff --git a/linden/indra/newview/llfloatermessagelog.h b/linden/indra/newview/llfloatermessagelog.h
new file mode 100644
index 0000000..ebc4f2a
--- /dev/null
+++ b/linden/indra/newview/llfloatermessagelog.h
@@ -0,0 +1,84 @@
1// <edit>
2#include "llfloater.h"
3#include "llmessagelog.h"
4#include "lltemplatemessagereader.h"
5#include "llfloatermessagebuilder.h"
6
7class LLFloaterMessageLogItem : public LLMessageLogEntry
8{
9public:
10 LLFloaterMessageLogItem(LLMessageLogEntry entry);
11 ~LLFloaterMessageLogItem();
12 LLUUID mID;
13 U32 mSequenceID;
14 std::string mName;
15 std::string mSummary;
16 U32 mFlags;
17 std::string getFull(BOOL show_header = TRUE);
18 BOOL isOutgoing();
19private:
20 static LLTemplateMessageReader* sTemplateMessageReader;
21 static std::string getString(LLTemplateMessageReader* readerp, const char* block_name, S32 block_num, const char* var_name, e_message_variable_type var_type, BOOL &returned_hex, BOOL summary_mode = FALSE);
22};
23class LLMessageLogFilter
24{
25public:
26 LLMessageLogFilter();
27 ~LLMessageLogFilter();
28 BOOL set(std::string filter);
29 std::list<std::string> mPositiveNames;
30 std::list<std::string> mNegativeNames;
31};
32class LLMessageLogFilterApply : public LLEventTimer
33{
34public:
35 LLMessageLogFilterApply();
36 void cancel();
37 BOOL tick();
38 S32 mProgress;
39 BOOL mFinished;
40private:
41 std::deque<LLMessageLogEntry> mQueuedMessages;
42 std::deque<LLMessageLogEntry>::iterator mIter;
43};
44class LLFloaterMessageLog : public LLFloater, public LLEventTimer
45{
46public:
47 LLFloaterMessageLog();
48 ~LLFloaterMessageLog();
49 static void show();
50 BOOL postBuild();
51 BOOL tick();
52 LLNetListItem* findNetListItem(LLHost host);
53 LLNetListItem* findNetListItem(LLUUID id);
54 void refreshNetList();
55 void refreshNetInfo(BOOL force);
56 enum ENetInfoMode { NI_NET, NI_LOG };
57 void setNetInfoMode(ENetInfoMode mode);
58 static void onLog(LLMessageLogEntry entry);
59 static void conditionalLog(LLFloaterMessageLogItem item);
60 static void onCommitNetList(LLUICtrl* ctrl, void* user_data);
61 static void onCommitMessageLog(LLUICtrl* ctrl, void* user_data);
62 static void onCommitFilter(LLUICtrl* ctrl, void* user_data);
63 static BOOL onClickCloseCircuit(void* user_data);
64 static bool onConfirmCloseCircuit(const LLSD& notification, const LLSD& response );
65 static bool onConfirmRemoveRegion(const LLSD& notification, const LLSD& response );
66 static void onClickFilterApply(void* user_data);
67 void startApplyingFilter(std::string filter, BOOL force);
68 void stopApplyingFilter();
69 void updateFilterStatus();
70 static BOOL sBusyApplyingFilter;
71 LLMessageLogFilterApply* mMessageLogFilterApply;
72 static void onClickClearLog(void* user_data);
73 static LLFloaterMessageLog* sInstance;
74 static std::list<LLNetListItem*> sNetListItems;
75 static std::deque<LLMessageLogEntry> sMessageLogEntries;
76 static std::vector<LLFloaterMessageLogItem> sFloaterMessageLogItems;
77 static LLMessageLogFilter sMessageLogFilter;
78 static std::string sMessageLogFilterString;
79 ENetInfoMode mNetInfoMode;
80 static void onClickFilterChoice(void* user_data);
81 static void onClickFilterMenu(void* user_data);
82 static void onClickSendToMessageBuilder(void* user_data);
83};
84// </edit>
diff --git a/linden/indra/newview/llviewermenu.cpp b/linden/indra/newview/llviewermenu.cpp
index 524654a..3e502c0 100644
--- a/linden/indra/newview/llviewermenu.cpp
+++ b/linden/indra/newview/llviewermenu.cpp
@@ -121,6 +121,8 @@
121#include "llfloaterland.h" 121#include "llfloaterland.h"
122#include "llfloaterlandholdings.h" 122#include "llfloaterlandholdings.h"
123#include "llfloatermap.h" 123#include "llfloatermap.h"
124#include "llfloatermessagebuilder.h"
125#include "llfloatermessagelog.h"
124#include "llfloatermute.h" 126#include "llfloatermute.h"
125#include "llfloateropenobject.h" 127#include "llfloateropenobject.h"
126#include "llfloaterpermissionsmgr.h" 128#include "llfloaterpermissionsmgr.h"
@@ -394,6 +396,8 @@ void handle_god_mode(void*);
394// God menu 396// God menu
395void handle_leave_god_mode(void*); 397void handle_leave_god_mode(void*);
396 398
399void handle_open_message_log(void*);
400void handle_open_message_builder(void*);
397BOOL is_inventory_visible( void* user_data ); 401BOOL is_inventory_visible( void* user_data );
398void handle_reset_view(); 402void handle_reset_view();
399 403
@@ -778,6 +782,11 @@ void init_client_menu(LLMenuGL* menu)
778 782
779 sub->appendSeparator(); 783 sub->appendSeparator();
780 784
785 sub->append(new LLMenuItemCallGL( "Message Log", &handle_open_message_log, NULL));
786 sub->append(new LLMenuItemCallGL( "Message Builder", &handle_open_message_builder, NULL));
787
788 sub->appendSeparator();
789
781 sub->append(new LLMenuItemCallGL("Region Info to Debug Console", 790 sub->append(new LLMenuItemCallGL("Region Info to Debug Console",
782 &handle_region_dump_settings, NULL)); 791 &handle_region_dump_settings, NULL));
783 sub->append(new LLMenuItemCallGL("Group Info to Debug Console", 792 sub->append(new LLMenuItemCallGL("Group Info to Debug Console",
@@ -3280,6 +3289,16 @@ void process_grant_godlike_powers(LLMessageSystem* msg, void**)
3280 } 3289 }
3281} 3290}
3282 3291
3292
3293void handle_open_message_log(void*)
3294{
3295 LLFloaterMessageLog::show();
3296}
3297
3298void handle_open_message_builder(void*)
3299{
3300 LLFloaterMessageBuilder::show("");
3301}
3283/* 3302/*
3284class LLHaveCallingcard : public LLInventoryCollectFunctor 3303class LLHaveCallingcard : public LLInventoryCollectFunctor
3285{ 3304{
@@ -8672,6 +8691,30 @@ class LLAdvancedDumpInfoToConsole : public view_listener_t
8672 8691
8673 8692
8674 8693
8694/////////////////////////
8695// MESSAGE LOG/BUILDER //
8696/////////////////////////
8697
8698
8699class LLMessageLogBuilder : public view_listener_t
8700{
8701 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
8702 {
8703 std::string info_type = userdata.asString();
8704 if ("MessageLog" == info_type)
8705 {
8706 handle_open_message_log(NULL);
8707 }
8708 else if ("MessageBuilder" == info_type)
8709 {
8710 handle_open_message_builder(NULL);
8711 }
8712 return true;
8713 }
8714};
8715
8716
8717
8675/////////////////////////////// 8718///////////////////////////////
8676// RELOAD SETTINGS OVERRIDES // 8719// RELOAD SETTINGS OVERRIDES //
8677/////////////////////////////// 8720///////////////////////////////
@@ -11260,6 +11303,8 @@ void initialize_menus()
11260 addMenu(new LLAdvancedToggleConsole(), "Advanced.ToggleConsole"); 11303 addMenu(new LLAdvancedToggleConsole(), "Advanced.ToggleConsole");
11261 addMenu(new LLAdvancedCheckConsole(), "Advanced.CheckConsole"); 11304 addMenu(new LLAdvancedCheckConsole(), "Advanced.CheckConsole");
11262 addMenu(new LLAdvancedDumpInfoToConsole(), "Advanced.DumpInfoToConsole"); 11305 addMenu(new LLAdvancedDumpInfoToConsole(), "Advanced.DumpInfoToConsole");
11306 addMenu(new LLMessageLogBuilder(), "Advanced.MessageLog");
11307 addMenu(new LLMessageLogBuilder(), "Advanced.MessageBuilder");
11263 addMenu(new LLAdvancedReloadSettingsOverrides(), "Advanced.ReloadSettingsOverrides"); 11308 addMenu(new LLAdvancedReloadSettingsOverrides(), "Advanced.ReloadSettingsOverrides");
11264 addMenu(new LLAdvancedToggleSit(), "Advanced.ToggleSit"); 11309 addMenu(new LLAdvancedToggleSit(), "Advanced.ToggleSit");
11265 addMenu(new LLAdvancedCheckSit(), "Advanced.CheckSit"); 11310 addMenu(new LLAdvancedCheckSit(), "Advanced.CheckSit");
diff --git a/linden/indra/newview/skins/default/xui/en-us/menu_viewer.xml b/linden/indra/newview/skins/default/xui/en-us/menu_viewer.xml
index c85dd47..53e9e2d 100644
--- a/linden/indra/newview/skins/default/xui/en-us/menu_viewer.xml
+++ b/linden/indra/newview/skins/default/xui/en-us/menu_viewer.xml
@@ -908,6 +908,15 @@
908 userdata="notifications" /> 908 userdata="notifications" />
909 </menu_item_call> 909 </menu_item_call>
910 <menu_item_separator /> 910 <menu_item_separator />
911 <menu_item_call name="Message Log" label="Message Log">
912 <on_click function="Advanced.MessageLog"
913 userdata="MessageLog" />
914 </menu_item_call>
915 <menu_item_call name="Message Builder" label="Message Builder">
916 <on_click function="Advanced.MessageBuilder"
917 userdata="MessageBuilder" />
918 </menu_item_call>
919 <menu_item_separator />
911 <menu_item_call name="Region Info to Debug Console" 920 <menu_item_call name="Region Info to Debug Console"
912 label="Region Info to Debug Console"> 921 label="Region Info to Debug Console">
913 <on_click function="Advanced.DumpInfoToConsole" 922 <on_click function="Advanced.DumpInfoToConsole"