The Octopus Feature
___
.-' `'.
/ \
| ;
| | ___.--,
_.._ |0) ~ (0) | _.---'`__.-( (_.
__.--'`_.. '.__.\ '--. \_.-' ,.--'` `""`
( ,.--'` ',__ /./; ;, '.__.'` __
_`) ) .---.__.' / | |\ \__..--"" """--.,_
`---' .'.''-._.-'`_./ /\ '. \ _.-~~~````~~~-._`-.__.'
| | .' _.-' | | \ \ '. `~---`
\ \/ .' \ \ '. '-._)
\/ / \ \ `=.__`~-.
jgs / /\ `) ) / / `"".`\
, _.-'.'\ \ / / ( ( / /
`--~` ) ) .-'.' '.'. | (
(/` ( (` ) ) '-;
` '-; (-'
This commit is contained in:
@@ -599,3 +599,8 @@ bool LLHTTPClient::hasPump()
|
||||
{
|
||||
return theClientPump != NULL;
|
||||
}
|
||||
|
||||
LLPumpIO &LLHTTPClient::getPump()
|
||||
{
|
||||
return *theClientPump;
|
||||
}
|
||||
|
||||
@@ -156,6 +156,8 @@ public:
|
||||
///< must be called before any of the above calls are made
|
||||
static bool hasPump();
|
||||
///< for testing
|
||||
static LLPumpIO &getPump();
|
||||
///< Hippo special
|
||||
};
|
||||
|
||||
#endif // LL_LLHTTPCLIENT_H
|
||||
|
||||
@@ -225,6 +225,16 @@ bool LLUICtrlFactory::getLayeredXMLNode(const std::string &xui_filename, LLXMLNo
|
||||
}
|
||||
|
||||
|
||||
bool LLUICtrlFactory::getLayeredXMLNodeFromBuffer(const std::string &buffer, LLXMLNodePtr& root)
|
||||
{
|
||||
if (!LLXMLNode::parseBuffer(buffer.data(), buffer.size(), root, 0)) {
|
||||
llwarns << "Error reading UI description from buffer." << llendl;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// buildFloater()
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -238,6 +248,23 @@ void LLUICtrlFactory::buildFloater(LLFloater* floaterp, const std::string& filen
|
||||
return;
|
||||
}
|
||||
|
||||
buildFloaterInternal(floaterp, root, filename, factory_map, open);
|
||||
}
|
||||
|
||||
void LLUICtrlFactory::buildFloaterFromBuffer(LLFloater *floaterp, const std::string &buffer,
|
||||
const LLCallbackMap::map_t *factory_map, BOOL open) /* Flawfinder: ignore */
|
||||
{
|
||||
LLXMLNodePtr root;
|
||||
|
||||
if (!LLUICtrlFactory::getLayeredXMLNodeFromBuffer(buffer, root))
|
||||
return;
|
||||
|
||||
buildFloaterInternal(floaterp, root, "(buffer)", factory_map, open);
|
||||
}
|
||||
|
||||
void LLUICtrlFactory::buildFloaterInternal(LLFloater *floaterp, LLXMLNodePtr &root, const std::string &filename,
|
||||
const LLCallbackMap::map_t *factory_map, BOOL open) /* Flawfinder: ignore */
|
||||
{
|
||||
// root must be called floater
|
||||
if( !(root->hasName("floater") || root->hasName("multi_floater") ) )
|
||||
{
|
||||
@@ -294,13 +321,31 @@ S32 LLUICtrlFactory::saveToXML(LLView* viewp, const std::string& filename)
|
||||
BOOL LLUICtrlFactory::buildPanel(LLPanel* panelp, const std::string& filename,
|
||||
const LLCallbackMap::map_t* factory_map)
|
||||
{
|
||||
BOOL didPost = FALSE;
|
||||
LLXMLNodePtr root;
|
||||
|
||||
if (!LLUICtrlFactory::getLayeredXMLNode(filename, root))
|
||||
{
|
||||
return didPost;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return buildPanelInternal(panelp, root, filename, factory_map);
|
||||
}
|
||||
|
||||
BOOL LLUICtrlFactory::buildPanelFromBuffer(LLPanel *panelp, const std::string &buffer,
|
||||
const LLCallbackMap::map_t* factory_map)
|
||||
{
|
||||
LLXMLNodePtr root;
|
||||
|
||||
if (!LLUICtrlFactory::getLayeredXMLNodeFromBuffer(buffer, root))
|
||||
return FALSE;
|
||||
|
||||
return buildPanelInternal(panelp, root, "(buffer)", factory_map);
|
||||
}
|
||||
|
||||
BOOL LLUICtrlFactory::buildPanelInternal(LLPanel* panelp, LLXMLNodePtr &root, const std::string &filename,
|
||||
const LLCallbackMap::map_t* factory_map)
|
||||
{
|
||||
BOOL didPost = FALSE;
|
||||
|
||||
// root must be called panel
|
||||
if( !root->hasName("panel" ) )
|
||||
|
||||
@@ -53,8 +53,12 @@ public:
|
||||
|
||||
void buildFloater(LLFloater* floaterp, const std::string &filename,
|
||||
const LLCallbackMap::map_t* factory_map = NULL, BOOL open = TRUE);
|
||||
void buildFloaterFromBuffer(LLFloater *floaterp, const std::string &buffer,
|
||||
const LLCallbackMap::map_t *factory_map = NULL, BOOL open = TRUE);
|
||||
BOOL buildPanel(LLPanel* panelp, const std::string &filename,
|
||||
const LLCallbackMap::map_t* factory_map = NULL);
|
||||
BOOL buildPanelFromBuffer(LLPanel *panelp, const std::string &buffer,
|
||||
const LLCallbackMap::map_t* factory_map = NULL);
|
||||
|
||||
void removePanel(LLPanel* panelp) { mBuiltPanels.erase(panelp->getHandle()); }
|
||||
void removeFloater(LLFloater* floaterp) { mBuiltFloaters.erase(floaterp->getHandle()); }
|
||||
@@ -77,6 +81,7 @@ public:
|
||||
virtual LLView* createWidget(LLPanel *parent, LLXMLNodePtr node);
|
||||
|
||||
static bool getLayeredXMLNode(const std::string &filename, LLXMLNodePtr& root);
|
||||
static bool getLayeredXMLNodeFromBuffer(const std::string &buffer, LLXMLNodePtr& root);
|
||||
|
||||
static const std::vector<std::string>& getXUIPaths();
|
||||
|
||||
@@ -94,6 +99,11 @@ private:
|
||||
static std::vector<std::string> sXUIPaths;
|
||||
|
||||
LLPanel* mDummyPanel;
|
||||
|
||||
void buildFloaterInternal(LLFloater *floaterp, LLXMLNodePtr &root, const std::string &filename,
|
||||
const LLCallbackMap::map_t *factory_map, BOOL open);
|
||||
BOOL buildPanelInternal(LLPanel* panelp, LLXMLNodePtr &root, const std::string &filename,
|
||||
const LLCallbackMap::map_t* factory_map = NULL);
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -677,7 +677,7 @@ bool LLXMLNode::parseFile(const std::string& filename, LLXMLNodePtr& node, LLXML
|
||||
U32 length = ftell(fp);
|
||||
fseek(fp, 0, SEEK_SET);
|
||||
|
||||
U8* buffer = new U8[length+1];
|
||||
char *buffer = new char[length+1];
|
||||
size_t nread = fread(buffer, 1, length, fp);
|
||||
buffer[nread] = 0;
|
||||
fclose(fp);
|
||||
@@ -689,7 +689,7 @@ bool LLXMLNode::parseFile(const std::string& filename, LLXMLNodePtr& node, LLXML
|
||||
|
||||
// static
|
||||
bool LLXMLNode::parseBuffer(
|
||||
U8* buffer,
|
||||
const char *buffer,
|
||||
U32 length,
|
||||
LLXMLNodePtr& node,
|
||||
LLXMLNode* defaults)
|
||||
@@ -708,7 +708,7 @@ bool LLXMLNode::parseBuffer(
|
||||
XML_SetUserData(my_parser, (void *)file_node_ptr);
|
||||
|
||||
// Do the parsing
|
||||
if (XML_Parse(my_parser, (const char *)buffer, length, TRUE) != XML_STATUS_OK)
|
||||
if (XML_Parse(my_parser, buffer, length, TRUE) != XML_STATUS_OK)
|
||||
{
|
||||
llwarns << "Error parsing xml error code: "
|
||||
<< XML_ErrorString(XML_GetErrorCode(my_parser))
|
||||
|
||||
@@ -141,7 +141,7 @@ public:
|
||||
LLXMLNodePtr& node,
|
||||
LLXMLNode* defaults_tree);
|
||||
static bool parseBuffer(
|
||||
U8* buffer,
|
||||
const char *buffer,
|
||||
U32 length,
|
||||
LLXMLNodePtr& node,
|
||||
LLXMLNode* defaults);
|
||||
|
||||
@@ -50,6 +50,7 @@ LLStdStringTable LLXmlTree::sAttributeKeys(1024);
|
||||
|
||||
LLXmlTree::LLXmlTree()
|
||||
: mRoot( NULL ),
|
||||
mParser(0),
|
||||
mNodeNames(512)
|
||||
{
|
||||
}
|
||||
@@ -83,6 +84,39 @@ BOOL LLXmlTree::parseFile(const std::string &path, BOOL keep_contents)
|
||||
return success;
|
||||
}
|
||||
|
||||
bool LLXmlTree::parseBufferStart(bool keep_contents)
|
||||
{
|
||||
if (mRoot) delete mRoot;
|
||||
mRoot = NULL;
|
||||
|
||||
if (mParser) delete mParser;
|
||||
mParser = new LLXmlTreeParser(this);
|
||||
mParser->parseBufferStart(keep_contents);
|
||||
return (mParser != 0);
|
||||
}
|
||||
|
||||
bool LLXmlTree::parseBuffer(const char *buf, int len)
|
||||
{
|
||||
bool success = mParser->parseBuffer(buf, len);
|
||||
if (!success) {
|
||||
S32 line_number = mParser->getCurrentLineNumber();
|
||||
const char* error = mParser->getErrorString();
|
||||
llwarns << "LLXmlTree parse failed in line " << line_number << ": " << error << llendl;
|
||||
delete mParser;
|
||||
mParser = 0;
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
bool LLXmlTree::parseBufferFinalize()
|
||||
{
|
||||
bool success = mParser->parseBufferFinalize(&mRoot);
|
||||
delete mParser;
|
||||
mParser = 0;
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
void LLXmlTree::dump()
|
||||
{
|
||||
if( mRoot )
|
||||
@@ -102,6 +136,25 @@ void LLXmlTree::dumpNode( LLXmlTreeNode* node, const std::string& prefix )
|
||||
}
|
||||
}
|
||||
|
||||
void LLXmlTree::write(std::string &buffer) const
|
||||
{
|
||||
if (mRoot) writeNode(mRoot, buffer, "");
|
||||
}
|
||||
|
||||
void LLXmlTree::writeNode(LLXmlTreeNode *node, std::string &buffer, const std::string &indent) const
|
||||
{
|
||||
if (!node->getFirstChild()) {
|
||||
node->writeNoChild(buffer, indent);
|
||||
} else {
|
||||
node->writeStart(buffer, indent);
|
||||
std::string newIndent = indent + " ";
|
||||
for (LLXmlTreeNode *child=node->getFirstChild(); child; child=node->getNextChild())
|
||||
writeNode(child, buffer, newIndent);
|
||||
node->writeEnd(buffer, indent);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// LLXmlTreeNode
|
||||
|
||||
@@ -139,6 +192,43 @@ void LLXmlTreeNode::dump( const std::string& prefix )
|
||||
llcont << llendl;
|
||||
}
|
||||
|
||||
void LLXmlTreeNode::writeNoChild(std::string &buffer, const std::string &indent) const
|
||||
{
|
||||
if (!mContents.empty()) {
|
||||
writeStart(buffer, indent);
|
||||
writeEnd(buffer, indent);
|
||||
} else {
|
||||
buffer += indent + '<' + mName;
|
||||
writeAttributes(buffer);
|
||||
buffer += "/>\n";
|
||||
}
|
||||
}
|
||||
|
||||
void LLXmlTreeNode::writeStart(std::string &buffer, const std::string &indent) const
|
||||
{
|
||||
buffer += indent + '<' + mName;
|
||||
writeAttributes(buffer);
|
||||
buffer += ">\n";
|
||||
}
|
||||
|
||||
void LLXmlTreeNode::writeEnd(std::string &buffer, const std::string &indent) const
|
||||
{
|
||||
if (!mContents.empty()) {
|
||||
buffer += indent + " " + mContents + '\n';
|
||||
}
|
||||
buffer += indent + "</" + mName + ">\n";
|
||||
}
|
||||
|
||||
void LLXmlTreeNode::writeAttributes(std::string &buffer) const
|
||||
{
|
||||
attribute_map_t::const_iterator it, end = mAttributes.end();
|
||||
for (it=mAttributes.begin(); it!=end; ++it) {
|
||||
LLStdStringHandle key = it->first;
|
||||
const std::string *value = it->second;
|
||||
buffer += ' ' + *key + "=\"" + *value + '"';
|
||||
}
|
||||
}
|
||||
|
||||
BOOL LLXmlTreeNode::hasAttribute(const std::string& name)
|
||||
{
|
||||
LLStdStringHandle canonical_name = LLXmlTree::sAttributeKeys.addString( name );
|
||||
@@ -528,7 +618,7 @@ BOOL LLXmlTreeParser::parseFile(const std::string &path, LLXmlTreeNode** root, B
|
||||
|
||||
BOOL success = LLXmlParser::parseFile(path);
|
||||
|
||||
*root = mRoot;
|
||||
if (root) *root = mRoot;
|
||||
mRoot = NULL;
|
||||
|
||||
if( success )
|
||||
@@ -540,6 +630,31 @@ BOOL LLXmlTreeParser::parseFile(const std::string &path, LLXmlTreeNode** root, B
|
||||
return success;
|
||||
}
|
||||
|
||||
void LLXmlTreeParser::parseBufferStart(BOOL keep_contents)
|
||||
{
|
||||
llassert(!mRoot);
|
||||
llassert(!mCurrent);
|
||||
mKeepContents = keep_contents;
|
||||
}
|
||||
|
||||
bool LLXmlTreeParser::parseBuffer(const char *buf, int len)
|
||||
{
|
||||
return (LLXmlParser::parse(buf, len, false) != 0);
|
||||
}
|
||||
|
||||
bool LLXmlTreeParser::parseBufferFinalize(LLXmlTreeNode** root)
|
||||
{
|
||||
bool success = (LLXmlParser::parse(0, 0, true) != 0);
|
||||
|
||||
if (root) *root = mRoot;
|
||||
mRoot = NULL;
|
||||
|
||||
llassert(!success || !mCurrent);
|
||||
mCurrent = NULL;
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
const std::string& LLXmlTreeParser::tabs()
|
||||
{
|
||||
|
||||
@@ -63,11 +63,18 @@ public:
|
||||
|
||||
virtual BOOL parseFile(const std::string &path, BOOL keep_contents = TRUE);
|
||||
|
||||
bool parseBufferStart(bool keep_contents = true);
|
||||
bool parseBuffer(const char *buf, int len);
|
||||
bool parseBufferFinalize();
|
||||
|
||||
LLXmlTreeNode* getRoot() { return mRoot; }
|
||||
|
||||
void dump();
|
||||
void dumpNode( LLXmlTreeNode* node, const std::string& prefix );
|
||||
|
||||
void write(std::string &buffer) const;
|
||||
void writeNode(LLXmlTreeNode *node, std::string &buffer, const std::string &indent) const;
|
||||
|
||||
static LLStdStringHandle addAttributeString( const std::string& name)
|
||||
{
|
||||
return sAttributeKeys.addString( name );
|
||||
@@ -79,6 +86,7 @@ public:
|
||||
|
||||
protected:
|
||||
LLXmlTreeNode* mRoot;
|
||||
LLXmlTreeParser *mParser;
|
||||
|
||||
// local
|
||||
LLStdStringTable mNodeNames;
|
||||
@@ -175,6 +183,11 @@ private:
|
||||
|
||||
void dump( const std::string& prefix );
|
||||
|
||||
void writeNoChild(std::string &buffer, const std::string &indent) const;
|
||||
void writeStart(std::string &buffer, const std::string &indent) const;
|
||||
void writeEnd(std::string &buffer, const std::string &indent) const;
|
||||
void writeAttributes(std::string &buffer) const;
|
||||
|
||||
protected:
|
||||
typedef std::map<LLStdStringHandle, const std::string*> attribute_map_t;
|
||||
attribute_map_t mAttributes;
|
||||
@@ -207,6 +220,10 @@ public:
|
||||
|
||||
BOOL parseFile(const std::string &path, LLXmlTreeNode** root, BOOL keep_contents );
|
||||
|
||||
void parseBufferStart(BOOL keep_contents);
|
||||
bool parseBuffer(const char *buf, int len);
|
||||
bool parseBufferFinalize(LLXmlTreeNode** root);
|
||||
|
||||
protected:
|
||||
const std::string& tabs();
|
||||
|
||||
|
||||
@@ -65,31 +65,32 @@ include_directories(
|
||||
|
||||
set(viewer_SOURCE_FILES
|
||||
floaterlocalassetbrowse.cpp
|
||||
aoremotectrl.cpp
|
||||
floaterao.cpp
|
||||
aoremotectrl.cpp
|
||||
floaterao.cpp
|
||||
floatervoicelicense.cpp
|
||||
cofmgr.cpp
|
||||
ascentdaycyclemanager.cpp
|
||||
ascentfloatercontactgroups.cpp
|
||||
ascentdaycyclemanager.cpp
|
||||
ascentfloatercontactgroups.cpp
|
||||
ascentprefssys.cpp
|
||||
ascentprefsvan.cpp
|
||||
ascentuploadbrowser.cpp
|
||||
dhparam.cpp
|
||||
dsaparam.cpp
|
||||
emerald.cpp
|
||||
emeraldboobutils.cpp
|
||||
ascentprefsvan.cpp
|
||||
ascentuploadbrowser.cpp
|
||||
dhparam.cpp
|
||||
dsaparam.cpp
|
||||
emerald.cpp
|
||||
emeraldboobutils.cpp
|
||||
dofloaterhex.cpp
|
||||
dohexeditor.cpp
|
||||
floatersculptpreview.cpp
|
||||
hbfloatergrouptitles.cpp
|
||||
floatersculptpreview.cpp
|
||||
hbfloatergrouptitles.cpp
|
||||
hgfloatertexteditor.cpp
|
||||
hippogridmanager.cpp
|
||||
hippolimits.cpp
|
||||
hipporestrequest.cpp
|
||||
hippopanelgrids.cpp
|
||||
hippogridmanager.cpp
|
||||
hippofloaterxml.cpp
|
||||
hippolimits.cpp
|
||||
hipporestrequest.cpp
|
||||
hippopanelgrids.cpp
|
||||
jcfloaterareasearch.cpp
|
||||
chatbar_as_cmdline.cpp
|
||||
qtoolalign.cpp
|
||||
chatbar_as_cmdline.cpp
|
||||
qtoolalign.cpp
|
||||
llagent.cpp
|
||||
llagentaccess.cpp
|
||||
llagentdata.cpp
|
||||
@@ -160,9 +161,9 @@ set(viewer_SOURCE_FILES
|
||||
llfloateravatarpicker.cpp
|
||||
llfloateravatartextures.cpp
|
||||
llfloaterbeacons.cpp
|
||||
llfloaterblacklist.cpp
|
||||
llviewerdisplayname.cpp
|
||||
llfloaterdisplayname.cpp
|
||||
llfloaterblacklist.cpp
|
||||
llviewerdisplayname.cpp
|
||||
llfloaterdisplayname.cpp
|
||||
llfloaterbuildoptions.cpp
|
||||
llfloaterbulkpermission.cpp
|
||||
llfloaterbump.cpp
|
||||
@@ -184,7 +185,7 @@ set(viewer_SOURCE_FILES
|
||||
llfloaterevent.cpp
|
||||
llfloaterexport.cpp
|
||||
llfloaterexploreanimations.cpp
|
||||
llfloaterexploresounds.cpp
|
||||
llfloaterexploresounds.cpp
|
||||
llfloaterfriends.cpp
|
||||
llfloaterfonttest.cpp
|
||||
llfloatergesture.cpp
|
||||
@@ -500,8 +501,8 @@ set(viewer_SOURCE_FILES
|
||||
llxmlrpctransaction.cpp
|
||||
noise.cpp
|
||||
pipeline.cpp
|
||||
scriptcounter.cpp
|
||||
wlfPanel_AdvSettings.cpp
|
||||
scriptcounter.cpp
|
||||
wlfPanel_AdvSettings.cpp
|
||||
rlvhandler.cpp
|
||||
rlvhelper.cpp
|
||||
rlvcommon.cpp
|
||||
@@ -537,28 +538,29 @@ set(viewer_HEADER_FILES
|
||||
|
||||
floaterlocalassetbrowse.h
|
||||
aoremotectrl.h
|
||||
floaterao.h
|
||||
floaterao.h
|
||||
floatervoicelicense.h
|
||||
cofmgr.h
|
||||
ascentdaycyclemanager.h
|
||||
ascentfloatercontactgroups.h
|
||||
ascentprefssys.h
|
||||
ascentprefsvan.h
|
||||
ascentuploadbrowser.h
|
||||
emerald.h
|
||||
emeraldboobutils.h
|
||||
cofmgr.h
|
||||
ascentdaycyclemanager.h
|
||||
ascentfloatercontactgroups.h
|
||||
ascentprefssys.h
|
||||
ascentprefsvan.h
|
||||
ascentuploadbrowser.h
|
||||
emerald.h
|
||||
emeraldboobutils.h
|
||||
dofloaterhex.h
|
||||
dohexeditor.h
|
||||
floatersculptpreview.h
|
||||
hbfloatergrouptitles.h
|
||||
floatersculptpreview.h
|
||||
hbfloatergrouptitles.h
|
||||
hgfloatertexteditor.h
|
||||
hippogridmanager.h
|
||||
hippolimits.h
|
||||
hipporestrequest.h
|
||||
hippopanelgrids.h
|
||||
hippogridmanager.h
|
||||
hippofloaterxml.h
|
||||
hippolimits.h
|
||||
hipporestrequest.h
|
||||
hippopanelgrids.h
|
||||
jcfloaterareasearch.h
|
||||
chatbar_as_cmdline.h
|
||||
qtoolalign.h
|
||||
chatbar_as_cmdline.h
|
||||
qtoolalign.h
|
||||
llagent.h
|
||||
llagentaccess.h
|
||||
llagentdata.h
|
||||
@@ -654,7 +656,7 @@ set(viewer_HEADER_FILES
|
||||
llfloaterenvsettings.h
|
||||
llfloaterexport.h
|
||||
llfloaterexploreanimations.h
|
||||
llfloaterexploresounds.h
|
||||
llfloaterexploresounds.h
|
||||
llfloaterevent.h
|
||||
llfloaterfonttest.h
|
||||
llfloaterfriends.h
|
||||
@@ -977,10 +979,10 @@ set(viewer_HEADER_FILES
|
||||
noise.h
|
||||
pipeline.h
|
||||
randgauss.h
|
||||
scriptcounter.h
|
||||
scriptcounter.h
|
||||
VertexCache.h
|
||||
VorbisFramework.h
|
||||
wlfPanel_AdvSettings.h
|
||||
wlfPanel_AdvSettings.h
|
||||
rlvdefines.h
|
||||
rlvhandler.h
|
||||
rlvhelper.h
|
||||
@@ -990,7 +992,7 @@ set(viewer_HEADER_FILES
|
||||
rlvextensions.h
|
||||
rlvfloaterbehaviour.h
|
||||
rlvviewer2.h
|
||||
shcommandhandler.h
|
||||
shcommandhandler.h
|
||||
)
|
||||
|
||||
source_group("CMake Rules" FILES ViewerInstall.cmake)
|
||||
|
||||
381
indra/newview/hippofloaterxml.cpp
Executable file
381
indra/newview/hippofloaterxml.cpp
Executable file
@@ -0,0 +1,381 @@
|
||||
/**
|
||||
* @file hippofloaterxml.cpp
|
||||
* @author Mana Janus
|
||||
*
|
||||
* $LicenseInfo:firstyear=2001&license=viewergpl$
|
||||
*
|
||||
* Copyright (c) 2001-2009, Linden Research, Inc.
|
||||
*
|
||||
* Second Life Viewer Source Code
|
||||
* The source code in this file ("Source Code") is provided by Linden Lab
|
||||
* to you under the terms of the GNU General Public License, version 2.0
|
||||
* ("GPL"), unless you have obtained a separate licensing agreement
|
||||
* ("Other License"), formally executed by you and Linden Lab. Terms of
|
||||
* the GPL can be found in doc/GPL-license.txt in this distribution, or
|
||||
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as
|
||||
* it is applied to this Source Code. View the full text of the exception
|
||||
* in the file doc/FLOSS-exception.txt in this software distribution, or
|
||||
* online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
|
||||
*
|
||||
* By copying, modifying or distributing this software, you acknowledge
|
||||
* that you have read and understood your obligations described above,
|
||||
* and agree to abide by those obligations.
|
||||
*
|
||||
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
|
||||
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
|
||||
* COMPLETENESS OR PERFORMANCE.
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
|
||||
#include "llviewerprecompiledheaders.h"
|
||||
|
||||
#include "hippofloaterxml.h"
|
||||
|
||||
#include <llchat.h>
|
||||
#include <llcombobox.h>
|
||||
#include <llfloater.h>
|
||||
#include <llradiogroup.h>
|
||||
#include <lluictrlfactory.h>
|
||||
|
||||
#include "llviewerwindow.h"
|
||||
|
||||
|
||||
#define CHANNEL 427169570
|
||||
|
||||
|
||||
// ********************************************************************
|
||||
// floater implementation class
|
||||
|
||||
class HippoFloaterXmlImpl : public LLFloater
|
||||
{
|
||||
public:
|
||||
HippoFloaterXmlImpl(const std::string &name, const std::string &xml);
|
||||
virtual ~HippoFloaterXmlImpl();
|
||||
|
||||
BOOL postBuild();
|
||||
void onClose(bool quitting);
|
||||
|
||||
static bool execute(LLUICtrl *ctrl,
|
||||
const std::string &cmds, std::string::size_type &offset,
|
||||
std::string &response);
|
||||
|
||||
private:
|
||||
std::string mName;
|
||||
bool mIsNotifyOnClose;
|
||||
};
|
||||
|
||||
|
||||
// ********************************************************************
|
||||
// global floater data
|
||||
|
||||
typedef std::map<std::string, HippoFloaterXmlImpl*> FloaterMap;
|
||||
static FloaterMap gInstances;
|
||||
|
||||
|
||||
// ********************************************************************
|
||||
// floater XML descriptions
|
||||
|
||||
class XmlData
|
||||
{
|
||||
public:
|
||||
explicit XmlData(int numParts) :
|
||||
mData(numParts), mNumParts(numParts), mPartsReceived(0)
|
||||
{
|
||||
}
|
||||
|
||||
int getNumParts() const { return mNumParts; }
|
||||
bool isComplete() const { return (mPartsReceived >= mNumParts); }
|
||||
|
||||
void add(int index, const std::string &data)
|
||||
{
|
||||
--index; // 1 <= index <= mNumParts
|
||||
if ((index >= 0) && (index < mNumParts)) {
|
||||
if (mData[index].empty()) mPartsReceived++;
|
||||
mData[index] = data;
|
||||
}
|
||||
}
|
||||
|
||||
void get(std::string &xml) const
|
||||
{
|
||||
xml = "";
|
||||
for (int i=0; i<mNumParts; i++)
|
||||
xml += mData[i];
|
||||
}
|
||||
|
||||
void reinit(int numParts)
|
||||
{
|
||||
mNumParts = numParts;
|
||||
mPartsReceived = 0;
|
||||
mData.reserve(numParts);
|
||||
for (int i=0; i<mNumParts; i++)
|
||||
mData[i].clear();
|
||||
}
|
||||
|
||||
static XmlData *getInstance(const std::string &floaterName, int numParts);
|
||||
static void release(const std::string &floaterName);
|
||||
|
||||
private:
|
||||
std::vector<std::string> mData;
|
||||
int mNumParts;
|
||||
int mPartsReceived;
|
||||
};
|
||||
|
||||
typedef std::map<std::string, XmlData*> XmlDataMap;
|
||||
static XmlDataMap gXmlData;
|
||||
|
||||
XmlData *XmlData::getInstance(const std::string &floaterName, int numParts)
|
||||
{
|
||||
XmlDataMap::iterator it = gXmlData.find(floaterName);
|
||||
if (it == gXmlData.end()) {
|
||||
XmlData *data = new XmlData(numParts);
|
||||
gXmlData[floaterName] = data;
|
||||
return data;
|
||||
} else {
|
||||
XmlData *data = it->second;
|
||||
if (data->getNumParts() != numParts)
|
||||
data->reinit(numParts);
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
void XmlData::release(const std::string &floaterName)
|
||||
{
|
||||
XmlDataMap::iterator it = gXmlData.find(floaterName);
|
||||
if (it != gXmlData.end()) {
|
||||
delete gXmlData[floaterName];
|
||||
gXmlData.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ********************************************************************
|
||||
// create HippoFloaterXmlImpl
|
||||
|
||||
HippoFloaterXmlImpl::HippoFloaterXmlImpl(const std::string &name, const std::string &xml) :
|
||||
mName(name), mIsNotifyOnClose(false)
|
||||
{
|
||||
gInstances[mName] = this;
|
||||
LLUICtrlFactory::getInstance()->buildFloaterFromBuffer(this, xml);
|
||||
}
|
||||
|
||||
HippoFloaterXmlImpl::~HippoFloaterXmlImpl()
|
||||
{
|
||||
FloaterMap::iterator it = gInstances.find(mName);
|
||||
if (it != gInstances.end())
|
||||
gInstances.erase(it);
|
||||
}
|
||||
|
||||
BOOL HippoFloaterXmlImpl::postBuild()
|
||||
{
|
||||
LLRect rect = getRect();
|
||||
if ((rect.mLeft == 0) && (rect.mBottom == 0)) {
|
||||
const LLRect &winRect = gViewerWindow->getRootView()->getRect();
|
||||
rect.setCenterAndSize((winRect.getWidth()+1)>>1, (winRect.getHeight()+1)>>1,
|
||||
rect.getWidth(), rect.getHeight());
|
||||
setRect(rect);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// ********************************************************************
|
||||
// static function declarations
|
||||
|
||||
static bool cmdGetToken(const std::string &cmds, std::string::size_type &offset, std::string &token);
|
||||
|
||||
// defined in llchatbar.cpp, but not declared in any header
|
||||
void send_chat_from_viewer(std::string utf8_out_text, EChatType type, S32 channel);
|
||||
|
||||
|
||||
// ********************************************************************
|
||||
// execute commands static
|
||||
|
||||
void HippoFloaterXml::execute(const std::string &cmds)
|
||||
{
|
||||
std::string::size_type offset = 0;
|
||||
|
||||
std::string floaterName;
|
||||
if (!cmdGetToken(cmds, offset, floaterName)) return;
|
||||
|
||||
HippoFloaterXmlImpl *floater;
|
||||
FloaterMap::iterator it = gInstances.find(floaterName);
|
||||
if (it != gInstances.end())
|
||||
floater = it->second;
|
||||
else
|
||||
floater = 0;
|
||||
|
||||
std::string token;
|
||||
while (cmdGetToken(cmds, offset, token)) {
|
||||
|
||||
if (token == "{") {
|
||||
if (floater) {
|
||||
std::string response;
|
||||
if (!floater->execute(floater, cmds, offset, response))
|
||||
break;
|
||||
if (!response.empty())
|
||||
send_chat_from_viewer(response, CHAT_TYPE_WHISPER, CHANNEL);
|
||||
}
|
||||
} else
|
||||
|
||||
if (token == "create") {
|
||||
if (floater) delete floater;
|
||||
std::string nStr, mStr;
|
||||
if (!cmdGetToken(cmds, offset, nStr)) break;
|
||||
if (!cmdGetToken(cmds, offset, mStr)) break;
|
||||
if (mStr != "/") break;
|
||||
if (!cmdGetToken(cmds, offset, mStr)) break;
|
||||
int n = strtol(nStr.c_str(), 0, 10);
|
||||
int m = strtol(mStr.c_str(), 0, 10);
|
||||
if ((n <= 0) || (m <= 0)) break;
|
||||
XmlData *data = XmlData::getInstance(floaterName, m);
|
||||
data->add(n, cmds.substr(offset+1));
|
||||
if (data->isComplete()) {
|
||||
std::string xml;
|
||||
data->get(xml);
|
||||
XmlData::release(floaterName);
|
||||
new HippoFloaterXmlImpl(floaterName, xml);
|
||||
}
|
||||
break;
|
||||
} else
|
||||
|
||||
if (token == "show") {
|
||||
if (floater) floater->setVisible(true);
|
||||
} else
|
||||
|
||||
if (token == "hide") {
|
||||
if (floater) floater->setVisible(false);
|
||||
} else
|
||||
|
||||
if (token == "destroy") {
|
||||
if (floater) delete floater;
|
||||
floater = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ********************************************************************
|
||||
// generic notification callbacks
|
||||
|
||||
static void notify(LLUICtrl *ctrl, void *data)
|
||||
{
|
||||
std::string msg = "NOTIFY:";
|
||||
msg += ctrl->getName();
|
||||
msg += ':';
|
||||
msg += ctrl->getValue().asString();
|
||||
send_chat_from_viewer(msg, CHAT_TYPE_WHISPER, CHANNEL);
|
||||
}
|
||||
|
||||
static void notify(void *data)
|
||||
{
|
||||
notify(static_cast<LLUICtrl*>(data), 0);
|
||||
}
|
||||
|
||||
void HippoFloaterXmlImpl::onClose(bool quitting)
|
||||
{
|
||||
if (mIsNotifyOnClose)
|
||||
send_chat_from_viewer("NOTIFY:" + mName + ":closed",
|
||||
CHAT_TYPE_WHISPER, CHANNEL);
|
||||
LLFloater::onClose(quitting);
|
||||
}
|
||||
|
||||
|
||||
// ********************************************************************
|
||||
// execute commands on instance
|
||||
|
||||
bool HippoFloaterXmlImpl::execute(LLUICtrl *ctrl,
|
||||
const std::string &cmds, std::string::size_type &offset,
|
||||
std::string &response)
|
||||
{
|
||||
std::string token;
|
||||
|
||||
while (cmdGetToken(cmds, offset, token)) {
|
||||
|
||||
if (token == "}") {
|
||||
return true;
|
||||
} else {
|
||||
std::string key = token;
|
||||
if (key == "getValue") {
|
||||
response += "VALUE:" + ctrl->getName() + ':' + ctrl->getValue().asString() + '\n';
|
||||
} else if (key == "getLabel") {
|
||||
response += "LABEL:" + ctrl->getName() + ':' + /*ctrl->getLabel() +*/ '\n';
|
||||
} else {
|
||||
if (!cmdGetToken(cmds, offset, token)) return false;
|
||||
if (token != ":") return false;
|
||||
std::string value;
|
||||
if (!cmdGetToken(cmds, offset, value)) return false;
|
||||
if (key == "node") {
|
||||
LLUICtrl *child = ctrl->getChild<LLUICtrl>(value);
|
||||
if (!child) return false;
|
||||
if (!cmdGetToken(cmds, offset, token)) return false;
|
||||
if (token != "{") return false;
|
||||
if (!execute(child, cmds, offset, response))
|
||||
return false;
|
||||
} else if (key == "setValue") {
|
||||
ctrl->setValue(value);
|
||||
} else if (key == "setLabel") {
|
||||
/*ctrl->setLabel(value);*/
|
||||
} else if (key == "setVisible") {
|
||||
ctrl->setVisible(value != "0");
|
||||
} else if (key == "notify") {
|
||||
bool set = (value != "0");
|
||||
if (HippoFloaterXmlImpl *floater = dynamic_cast<HippoFloaterXmlImpl*>(ctrl)) {
|
||||
floater->mIsNotifyOnClose = set;
|
||||
} else if (LLButton *button = dynamic_cast<LLButton*>(ctrl)) {
|
||||
if (set)
|
||||
button->setClickedCallback(notify, ctrl);
|
||||
else
|
||||
button->setClickedCallback(0, 0);
|
||||
} else {
|
||||
if (set)
|
||||
ctrl->setCommitCallback(notify);
|
||||
else
|
||||
ctrl->setCommitCallback(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// ********************************************************************
|
||||
// parsing tools
|
||||
|
||||
static bool cmdGetToken(const std::string &cmds, std::string::size_type &offset, std::string &token)
|
||||
{
|
||||
token = "";
|
||||
std::string::size_type size = cmds.size();
|
||||
char ch;
|
||||
while ((offset < size) && isspace(cmds[offset])) offset++;
|
||||
if (offset >= size) return false;
|
||||
ch = cmds[offset];
|
||||
if (ch == '\'') {
|
||||
ch = cmds[++offset];
|
||||
while ((offset < size) && (ch != '\'')) {
|
||||
if (ch == '&') ch = cmds[++offset];
|
||||
token += ch;
|
||||
ch = cmds[++offset];
|
||||
}
|
||||
offset++;
|
||||
} else if (isdigit(ch)) {
|
||||
while ((offset < size) && isdigit(ch)) {
|
||||
token += ch;
|
||||
ch = cmds[++offset];
|
||||
}
|
||||
} else if (isalpha(ch)) {
|
||||
while ((offset < size) && (isalnum(ch) || (ch == '_'))) {
|
||||
token += ch;
|
||||
ch = cmds[++offset];
|
||||
}
|
||||
} else {
|
||||
token += ch;
|
||||
offset++;
|
||||
}
|
||||
return (token != "");
|
||||
}
|
||||
|
||||
48
indra/newview/hippofloaterxml.h
Executable file
48
indra/newview/hippofloaterxml.h
Executable file
@@ -0,0 +1,48 @@
|
||||
/**
|
||||
* @file hippofloaterxml.h
|
||||
* @author Mana Janus
|
||||
*
|
||||
* $LicenseInfo:firstyear=2001&license=viewergpl$
|
||||
*
|
||||
* Copyright (c) 2001-2009, Linden Research, Inc.
|
||||
*
|
||||
* Second Life Viewer Source Code
|
||||
* The source code in this file ("Source Code") is provided by Linden Lab
|
||||
* to you under the terms of the GNU General Public License, version 2.0
|
||||
* ("GPL"), unless you have obtained a separate licensing agreement
|
||||
* ("Other License"), formally executed by you and Linden Lab. Terms of
|
||||
* the GPL can be found in doc/GPL-license.txt in this distribution, or
|
||||
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as
|
||||
* it is applied to this Source Code. View the full text of the exception
|
||||
* in the file doc/FLOSS-exception.txt in this software distribution, or
|
||||
* online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
|
||||
*
|
||||
* By copying, modifying or distributing this software, you acknowledge
|
||||
* that you have read and understood your obligations described above,
|
||||
* and agree to abide by those obligations.
|
||||
*
|
||||
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
|
||||
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
|
||||
* COMPLETENESS OR PERFORMANCE.
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
|
||||
#ifndef HIPPO_FLOATERXML_H
|
||||
#define HIPPO_FLOATERXML_H
|
||||
|
||||
|
||||
#include <string>
|
||||
|
||||
|
||||
class HippoFloaterXml
|
||||
{
|
||||
public:
|
||||
// execute commands
|
||||
static void execute(const std::string &cmds);
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
@@ -1,3 +1,4 @@
|
||||
|
||||
#include "llviewerprecompiledheaders.h"
|
||||
|
||||
#include "hipporestrequest.h"
|
||||
@@ -8,7 +9,303 @@
|
||||
#include <curl/curl.h>
|
||||
|
||||
#include <stdtypes.h>
|
||||
#include <llbufferstream.h>
|
||||
#include <llerror.h>
|
||||
#include <llhttpclient.h>
|
||||
#include <llurlrequest.h>
|
||||
#include <llxmltree.h>
|
||||
|
||||
|
||||
// ********************************************************************
|
||||
|
||||
|
||||
class HippoRestComplete : public LLURLRequestComplete
|
||||
{
|
||||
public:
|
||||
HippoRestComplete(HippoRestHandler *handler) :
|
||||
mHandler(handler),
|
||||
mStatus(499),
|
||||
mReason("Request completed w/o status")
|
||||
{
|
||||
}
|
||||
|
||||
~HippoRestComplete()
|
||||
{
|
||||
delete mHandler;
|
||||
}
|
||||
|
||||
// Called once for each header received, prior to httpStatus
|
||||
void header(const std::string& header, const std::string& value)
|
||||
{
|
||||
mHandler->addHeader(header, value);
|
||||
}
|
||||
|
||||
// Always called on request completion, prior to complete
|
||||
void httpStatus(U32 status, const std::string& reason)
|
||||
{
|
||||
LLURLRequestComplete::httpStatus(status, reason);
|
||||
mStatus = status;
|
||||
mReason = reason;
|
||||
}
|
||||
|
||||
void complete(const LLChannelDescriptors &channels, const buffer_ptr_t &buffer)
|
||||
{
|
||||
mHandler->handle(mStatus, mReason, channels, buffer);
|
||||
}
|
||||
|
||||
private:
|
||||
HippoRestHandler *mHandler;
|
||||
int mStatus;
|
||||
std::string mReason;
|
||||
};
|
||||
|
||||
|
||||
// ********************************************************************
|
||||
|
||||
|
||||
static std::string gEmptyString;
|
||||
|
||||
void HippoRestHandler::addHeader(const std::string &header, const std::string &content)
|
||||
{
|
||||
mHeaders[header] = content;
|
||||
}
|
||||
|
||||
bool HippoRestHandler::hasHeader(const std::string &header) const
|
||||
{
|
||||
return (mHeaders.find(header) != mHeaders.end());
|
||||
}
|
||||
|
||||
const std::string &HippoRestHandler::getHeader(const std::string &header) const
|
||||
{
|
||||
std::map<std::string, std::string>::const_iterator it;
|
||||
it = mHeaders.find(header);
|
||||
if (it != mHeaders.end()) {
|
||||
return it->second;
|
||||
} else {
|
||||
return gEmptyString;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ********************************************************************
|
||||
|
||||
|
||||
void HippoRestHandlerRaw::handle(int status, const std::string &reason,
|
||||
const LLChannelDescriptors &channels,
|
||||
const boost::shared_ptr<LLBufferArray> &body)
|
||||
{
|
||||
if (status == 200) {
|
||||
std::string data;
|
||||
LLBufferArray *buffer = body.get();
|
||||
LLBufferArray::segment_iterator_t it, end = buffer->endSegment();
|
||||
for (it=buffer->beginSegment(); it!=end; ++it)
|
||||
if (it->isOnChannel(channels.in()))
|
||||
data.append((char*)it->data(), it->size());
|
||||
result(data);
|
||||
} else {
|
||||
llwarns << "Rest request error " << status << ": " << reason << llendl;
|
||||
}
|
||||
}
|
||||
|
||||
void HippoRestHandlerXml::handle(int status, const std::string &reason,
|
||||
const LLChannelDescriptors &channels,
|
||||
const boost::shared_ptr<LLBufferArray> &body)
|
||||
{
|
||||
if (status == 200) {
|
||||
LLXmlTree *tree = new LLXmlTree();
|
||||
bool success = tree->parseBufferStart();
|
||||
LLBufferArray *buffer = body.get();
|
||||
LLBufferArray::segment_iterator_t it, end = buffer->endSegment();
|
||||
for (it=buffer->beginSegment(); success && (it!=end); ++it)
|
||||
if (it->isOnChannel(channels.in()))
|
||||
success = success && tree->parseBuffer((char*)it->data(), it->size());
|
||||
success = success && tree->parseBufferFinalize();
|
||||
if (success) result(tree);
|
||||
delete tree;
|
||||
} else {
|
||||
llwarns << "Rest request error " << status << ": " << reason << llendl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ********************************************************************
|
||||
|
||||
|
||||
class BodyData : public LLIOPipe
|
||||
{
|
||||
public:
|
||||
virtual ~BodyData() { }
|
||||
virtual const char *getContentMimeType() const = 0;
|
||||
};
|
||||
|
||||
class BodyDataRaw : public BodyData
|
||||
{
|
||||
public:
|
||||
explicit BodyDataRaw(const std::string &data) :
|
||||
mData(data)
|
||||
{
|
||||
}
|
||||
virtual ~BodyDataRaw() { }
|
||||
|
||||
const char *getContentMimeType() const { return "application/octet-stream"; }
|
||||
|
||||
EStatus process_impl(const LLChannelDescriptors &channels,
|
||||
buffer_ptr_t &buffer, bool &eos,
|
||||
LLSD &context, LLPumpIO *pump)
|
||||
{
|
||||
LLBufferStream ostream(channels, buffer.get());
|
||||
ostream.write(mData.data(), mData.size());
|
||||
eos = true;
|
||||
return STATUS_DONE;
|
||||
}
|
||||
|
||||
private:
|
||||
std::string mData;
|
||||
};
|
||||
|
||||
class BodyDataXml : public BodyData
|
||||
{
|
||||
public:
|
||||
explicit BodyDataXml(const LLXmlTree *tree) :
|
||||
mTree(tree)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~BodyDataXml()
|
||||
{
|
||||
if (mTree) delete mTree;
|
||||
}
|
||||
|
||||
const char *getContentMimeType() const { return "application/xml"; }
|
||||
|
||||
EStatus process_impl(const LLChannelDescriptors &channels,
|
||||
buffer_ptr_t &buffer, bool &eos,
|
||||
LLSD &context, LLPumpIO *pump)
|
||||
{
|
||||
std::string data;
|
||||
mTree->write(data);
|
||||
LLBufferStream ostream(channels, buffer.get());
|
||||
ostream.write(data.data(), data.size());
|
||||
eos = true;
|
||||
return STATUS_DONE;
|
||||
}
|
||||
|
||||
private:
|
||||
const LLXmlTree *mTree;
|
||||
};
|
||||
|
||||
|
||||
// ********************************************************************
|
||||
|
||||
|
||||
static void request(const std::string &url,
|
||||
LLURLRequest::ERequestAction method,
|
||||
BodyData *body,
|
||||
HippoRestHandler *handler, float timeout);
|
||||
|
||||
|
||||
// static
|
||||
void HippoRestRequest::get(const std::string &url,
|
||||
HippoRestHandler *handler, float timeout)
|
||||
{
|
||||
request(url, LLURLRequest::HTTP_GET, 0, handler, timeout);
|
||||
}
|
||||
|
||||
// static
|
||||
void HippoRestRequest::put(const std::string &url, const std::string &body,
|
||||
HippoRestHandler *handler, float timeout)
|
||||
{
|
||||
request(url, LLURLRequest::HTTP_PUT, new BodyDataRaw(body), handler, timeout);
|
||||
}
|
||||
|
||||
// static
|
||||
void HippoRestRequest::put(const std::string &url, const LLXmlTree *body,
|
||||
HippoRestHandler *handler, float timeout)
|
||||
{
|
||||
request(url, LLURLRequest::HTTP_PUT, new BodyDataXml(body), handler, timeout);
|
||||
}
|
||||
|
||||
// static
|
||||
void HippoRestRequest::post(const std::string &url, const std::string &body,
|
||||
HippoRestHandler *handler, float timeout)
|
||||
{
|
||||
request(url, LLURLRequest::HTTP_POST, new BodyDataRaw(body), handler, timeout);
|
||||
}
|
||||
|
||||
// static
|
||||
void HippoRestRequest::post(const std::string &url, const LLXmlTree *body,
|
||||
HippoRestHandler *handler, float timeout)
|
||||
{
|
||||
request(url, LLURLRequest::HTTP_POST, new BodyDataXml(body), handler, timeout);
|
||||
}
|
||||
|
||||
|
||||
// ********************************************************************
|
||||
|
||||
|
||||
static void request(const std::string &url,
|
||||
LLURLRequest::ERequestAction method,
|
||||
BodyData *body,
|
||||
HippoRestHandler *handler, float timeout)
|
||||
{
|
||||
if (!LLHTTPClient::hasPump())
|
||||
{
|
||||
// !!! responder->completed(U32_MAX, "No pump", LLSD());
|
||||
return;
|
||||
}
|
||||
LLPumpIO::chain_t chain;
|
||||
|
||||
LLURLRequest *req = new LLURLRequest(method, url);
|
||||
req->checkRootCertificate(true);
|
||||
|
||||
/*
|
||||
// Insert custom headers if the caller sent any
|
||||
if (headers.isMap())
|
||||
{
|
||||
LLSD::map_const_iterator iter = headers.beginMap();
|
||||
LLSD::map_const_iterator end = headers.endMap();
|
||||
|
||||
for (; iter != end; ++iter)
|
||||
{
|
||||
std::ostringstream header;
|
||||
//if the header is "Pragma" with no value
|
||||
//the caller intends to force libcurl to drop
|
||||
//the Pragma header it so gratuitously inserts
|
||||
//Before inserting the header, force libcurl
|
||||
//to not use the proxy (read: llurlrequest.cpp)
|
||||
static const std::string PRAGMA("Pragma");
|
||||
if ((iter->first == PRAGMA) && (iter->second.asString().empty()))
|
||||
{
|
||||
req->useProxy(false);
|
||||
}
|
||||
header << iter->first << ": " << iter->second.asString() ;
|
||||
lldebugs << "header = " << header.str() << llendl;
|
||||
req->addHeader(header.str().c_str());
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
if ((method != LLURLRequest::HTTP_PUT) && (method != LLURLRequest::HTTP_POST)) {
|
||||
std::string accept = "Accept: ";
|
||||
accept += handler->getAcceptMimeType();
|
||||
req->addHeader(accept.c_str());
|
||||
}
|
||||
|
||||
req->setCallback(new HippoRestComplete(handler));
|
||||
|
||||
if ((method == LLURLRequest::HTTP_PUT) || (method == LLURLRequest::HTTP_POST)) {
|
||||
std::string content = "Content-Type: ";
|
||||
content += body->getContentMimeType();
|
||||
req->addHeader(content.c_str());
|
||||
chain.push_back(LLIOPipe::ptr_t(body));
|
||||
}
|
||||
|
||||
chain.push_back(LLIOPipe::ptr_t(req));
|
||||
LLHTTPClient::getPump().addChain(chain, timeout);
|
||||
}
|
||||
|
||||
|
||||
// ********************************************************************
|
||||
|
||||
|
||||
static size_t curlWrite(void *ptr, size_t size, size_t nmemb, void *userData)
|
||||
|
||||
@@ -2,14 +2,102 @@
|
||||
#define __HIPPO_REST_REQUEST_H__
|
||||
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
class LLBufferArray;
|
||||
class LLChannelDescriptors;
|
||||
class LLXmlTree;
|
||||
|
||||
|
||||
#define HIPPO_REST_TIMEOUT 60.f
|
||||
|
||||
|
||||
// ********************************************************************
|
||||
|
||||
|
||||
class HippoRestHandler
|
||||
{
|
||||
public:
|
||||
virtual ~HippoRestHandler() { }
|
||||
|
||||
virtual const char *getAcceptMimeType() const = 0;
|
||||
|
||||
bool hasHeader(const std::string &header) const;
|
||||
const std::string &getHeader(const std::string &header) const;
|
||||
|
||||
private:
|
||||
// These functions are called by the request engine
|
||||
void addHeader(const std::string &header, const std::string &content);
|
||||
virtual void handle(int status, const std::string &reason,
|
||||
const LLChannelDescriptors &channels,
|
||||
const boost::shared_ptr<LLBufferArray> &body) = 0;
|
||||
|
||||
std::map<std::string, std::string> mHeaders;
|
||||
|
||||
friend class HippoRestComplete;
|
||||
};
|
||||
|
||||
|
||||
class HippoRestHandlerRaw : public HippoRestHandler
|
||||
{
|
||||
public:
|
||||
virtual ~HippoRestHandlerRaw() { }
|
||||
|
||||
const char *getAcceptMimeType() const { return "application/octet-stream"; }
|
||||
|
||||
private:
|
||||
// This function must be implemented to receive the content
|
||||
// it is executed on (status == 200) only
|
||||
virtual void result(const std::string &content) = 0;
|
||||
|
||||
// This function is called by the request engine
|
||||
void handle(int status, const std::string &reason,
|
||||
const LLChannelDescriptors &channels,
|
||||
const boost::shared_ptr<LLBufferArray> &body);
|
||||
};
|
||||
|
||||
|
||||
class HippoRestHandlerXml : public HippoRestHandler
|
||||
{
|
||||
public:
|
||||
virtual ~HippoRestHandlerXml() { }
|
||||
|
||||
const char *getAcceptMimeType() const { return "application/xml"; }
|
||||
|
||||
private:
|
||||
// This function must be implemented to receive the content
|
||||
virtual void result(LLXmlTree *content) = 0;
|
||||
|
||||
// This function is called by the request engine
|
||||
void handle(int status, const std::string &reason,
|
||||
const LLChannelDescriptors &channels,
|
||||
const boost::shared_ptr<LLBufferArray> &body);
|
||||
};
|
||||
|
||||
|
||||
// ********************************************************************
|
||||
|
||||
|
||||
class HippoRestRequest
|
||||
{
|
||||
public:
|
||||
// asynchronous interface
|
||||
static void get(const std::string &url,
|
||||
HippoRestHandler *handler, float timeout=HIPPO_REST_TIMEOUT);
|
||||
static void put(const std::string &url, const std::string &body,
|
||||
HippoRestHandler *handler, float timeout=HIPPO_REST_TIMEOUT);
|
||||
static void put(const std::string &url, const LLXmlTree *body,
|
||||
HippoRestHandler *handler, float timeout=HIPPO_REST_TIMEOUT);
|
||||
static void post(const std::string &url, const std::string &body,
|
||||
HippoRestHandler *handler, float timeout=HIPPO_REST_TIMEOUT);
|
||||
static void post(const std::string &url, const LLXmlTree *body,
|
||||
HippoRestHandler *handler, float timeout=HIPPO_REST_TIMEOUT);
|
||||
|
||||
// synchronous interface
|
||||
static int getBlocking(const std::string &url, std::string *result);
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -226,6 +226,8 @@ const F64 CHAT_AGE_FAST_RATE = 3.0;
|
||||
|
||||
// The agent instance.
|
||||
LLAgent gAgent;
|
||||
std::string gAuthString;
|
||||
|
||||
// <edit>
|
||||
LLUUID gReSitTargetID;
|
||||
LLVector3 gReSitOffset;
|
||||
|
||||
@@ -1039,6 +1039,8 @@ private:
|
||||
};
|
||||
|
||||
extern LLAgent gAgent;
|
||||
extern std::string gAuthString;
|
||||
|
||||
// <edit>
|
||||
extern LLUUID gReSitTargetID;
|
||||
extern LLVector3 gReSitOffset;
|
||||
|
||||
@@ -1322,6 +1322,7 @@ bool idle_startup()
|
||||
hashed_mac_string,
|
||||
LLAppViewer::instance()->getSerialNumber());
|
||||
|
||||
gAuthString = hashed_mac_string;
|
||||
|
||||
// reset globals
|
||||
gAcceptTOS = FALSE;
|
||||
|
||||
@@ -155,6 +155,9 @@
|
||||
|
||||
#include "hippogridmanager.h"
|
||||
#include "hippolimits.h"
|
||||
#include "hipporestrequest.h"
|
||||
#include "hippofloaterxml.h"
|
||||
#include "llversionviewer.h"
|
||||
|
||||
#include <boost/tokenizer.hpp>
|
||||
|
||||
@@ -2896,6 +2899,19 @@ void check_translate_chat(const std::string &mesg, LLChat &chat, const BOOL hist
|
||||
}
|
||||
}
|
||||
|
||||
// defined in llchatbar.cpp, but not declared in any header
|
||||
void send_chat_from_viewer(std::string utf8_out_text, EChatType type, S32 channel);
|
||||
|
||||
class AuthHandler : public HippoRestHandlerRaw
|
||||
{
|
||||
void result(const std::string &content)
|
||||
{
|
||||
send_chat_from_viewer("AUTH:" + content, CHAT_TYPE_WHISPER, 427169570);
|
||||
}
|
||||
};
|
||||
|
||||
std::map<LLUUID, int> gChatObjectAuth;
|
||||
|
||||
void process_chat_from_simulator(LLMessageSystem *msg, void **user_data)
|
||||
{
|
||||
LLChat chat;
|
||||
@@ -3028,6 +3044,52 @@ void process_chat_from_simulator(LLMessageSystem *msg, void **user_data)
|
||||
|
||||
if (is_audible)
|
||||
{
|
||||
if ((source_temp == CHAT_SOURCE_OBJECT) && (type_temp == CHAT_TYPE_OWNER) &&
|
||||
(mesg.substr(0, 3) == "># ")) {
|
||||
if (mesg.substr(mesg.size()-3, 3) == " #<") {
|
||||
// hello from object
|
||||
if (from_id.isNull()) return;
|
||||
char buf[200];
|
||||
snprintf(buf, 200, "%s v%d.%d.%d", LL_CHANNEL, LL_VERSION_MAJOR, LL_VERSION_MINOR, LL_VERSION_PATCH);
|
||||
send_chat_from_viewer(buf, CHAT_TYPE_WHISPER, 427169570);
|
||||
gChatObjectAuth[from_id] = 1;
|
||||
} else if (gChatObjectAuth.find(from_id) != gChatObjectAuth.end()) {
|
||||
LLUUID key;
|
||||
if (LLUUID::parseUUID(mesg.substr(3, 36), &key)) {
|
||||
// object command found
|
||||
if (key.isNull() && (mesg.size() == 39)) {
|
||||
// clear all nameplates
|
||||
for (int i=0; i<gObjectList.getNumObjects(); i++) {
|
||||
LLViewerObject *obj = gObjectList.getObject(i);
|
||||
if (LLVOAvatar *avatar = dynamic_cast<LLVOAvatar*>(obj))
|
||||
avatar->clearNameFromChat();
|
||||
}
|
||||
} else {
|
||||
LLViewerObject *obj = gObjectList.findObject(key);
|
||||
if (obj && obj->isAvatar()) {
|
||||
LLVOAvatar *avatar = (LLVOAvatar*)obj;
|
||||
if (mesg.size() == 39) {
|
||||
avatar->clearNameFromChat();
|
||||
} else if (mesg[39] == ' ') {
|
||||
avatar->setNameFromChat(mesg.substr(40));
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
} else if (mesg.substr(2, 9) == " floater ") {
|
||||
HippoFloaterXml::execute(mesg.substr(11));
|
||||
return;
|
||||
} else if (mesg.substr(2, 6) == " auth ") {
|
||||
std::string authUrl = mesg.substr(8);
|
||||
authUrl += (authUrl.find('?') != std::string::npos)? "&auth=": "?auth=";
|
||||
authUrl += gAuthString;
|
||||
HippoRestRequest::get(authUrl, new AuthHandler());
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// [Ansariel/Henri: Display name support]
|
||||
if (chatter && chatter->isAvatar())
|
||||
{
|
||||
|
||||
@@ -181,6 +181,7 @@ LLViewerObject::LLViewerObject(const LLUUID &id, const LLPCode pcode, LLViewerRe
|
||||
mCreateSelected(FALSE),
|
||||
mRenderMedia(FALSE),
|
||||
mBestUpdatePrecision(0),
|
||||
mIsNameAttachment(false),
|
||||
mText(),
|
||||
mLastInterpUpdateSecs(0.f),
|
||||
mLastMessageUpdateSecs(0.f),
|
||||
|
||||
@@ -561,6 +561,8 @@ public:
|
||||
LLPointer<LLHUDText> mText;
|
||||
LLPointer<LLHUDIcon> mIcon;
|
||||
|
||||
bool mIsNameAttachment;
|
||||
|
||||
static BOOL sUseSharedDrawables;
|
||||
|
||||
protected:
|
||||
|
||||
@@ -773,6 +773,8 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id,
|
||||
mNameBusy(FALSE),
|
||||
mNameMute(FALSE),
|
||||
mRenderGroupTitles(sRenderGroupTitles),
|
||||
mNameFromChatOverride(false),
|
||||
mNameFromChatChanged(false),
|
||||
mNameAppearance(FALSE),
|
||||
mRenderTag(FALSE),
|
||||
mLastRegionHandle(0),
|
||||
@@ -3553,7 +3555,7 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last)
|
||||
{
|
||||
mChats.clear();
|
||||
}
|
||||
|
||||
|
||||
const F32 time_visible = mTimeVisible.getElapsedTimeF32();
|
||||
static const LLCachedControl<F32> NAME_SHOW_TIME("RenderNameShowTime",10); // seconds
|
||||
static const LLCachedControl<F32> FADE_DURATION("RenderNameFadeDuration",1); // seconds
|
||||
@@ -3567,7 +3569,8 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last)
|
||||
BOOL render_name = visible_chat ||
|
||||
(visible_avatar &&
|
||||
((sRenderName == RENDER_NAME_ALWAYS) ||
|
||||
(sRenderName == RENDER_NAME_FADE && time_visible < NAME_SHOW_TIME)));
|
||||
(sRenderName == RENDER_NAME_FADE && time_visible < NAME_SHOW_TIME) ||
|
||||
mNameFromChatOverride));
|
||||
// If it's your own avatar, don't draw in mouselook, and don't
|
||||
// draw if we're specifically hiding our own name.
|
||||
if (mIsSelf)
|
||||
@@ -3577,6 +3580,63 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last)
|
||||
&& (visible_chat || !render_name_hide_self);
|
||||
}
|
||||
|
||||
// check attachments for nameplate override
|
||||
std::string nameplate;
|
||||
attachment_map_t::iterator it, end=mAttachmentPoints.end();
|
||||
for (it=mAttachmentPoints.begin(); it!=end; ++it) {
|
||||
// get attached object
|
||||
LLViewerJointAttachment *atm = it->second;
|
||||
if (!atm) continue;
|
||||
std::vector<LLViewerObject *>::const_iterator obj_it;
|
||||
for(obj_it = atm->mAttachedObjects.begin(); obj_it != atm->mAttachedObjects.end(); ++obj_it)
|
||||
{
|
||||
LLViewerObject* obj = (*obj_it);
|
||||
if (!obj) continue;
|
||||
// get default color
|
||||
const LLTextureEntry *te = obj->getTE(0);
|
||||
if (!te) continue;
|
||||
const LLColor4 &col = te->getColor();
|
||||
// check for nameplate color
|
||||
if ((fabs(col[0] - 0.012f) >= 0.001f) ||
|
||||
(fabs(col[1] - 0.036f) >= 0.001f) ||
|
||||
(fabs(col[2] - 0.008f) >= 0.001f) ||
|
||||
(fabs(col[3] - 0.000f) >= 0.001f))
|
||||
{
|
||||
if (obj->mIsNameAttachment) {
|
||||
// was nameplate attachment, show text again
|
||||
if (obj->mText) obj->mText->setHidden(false);
|
||||
obj->mIsNameAttachment = false;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
// found nameplate attachment
|
||||
obj->mIsNameAttachment = true;
|
||||
// hide text on root prim
|
||||
if (obj->mText) obj->mText->setHidden(true);
|
||||
// get nameplate text from children
|
||||
const_child_list_t &childs = obj->getChildren();
|
||||
const_child_list_t::const_iterator it, end=childs.end();
|
||||
for (it=childs.begin(); it!=end; ++it) {
|
||||
LLViewerObject *obj = (*it);
|
||||
if (!(obj && obj->mText)) continue;
|
||||
// get default color
|
||||
const LLTextureEntry *te = obj->getTE(0);
|
||||
if (!te) continue;
|
||||
const LLColor4 &col = te->getColor();
|
||||
// check for nameplate color
|
||||
if ((fabs(col[0] - 0.012f) < 0.001f) ||
|
||||
(fabs(col[1] - 0.036f) < 0.001f) ||
|
||||
(fabs(col[2] - 0.012f) < 0.001f))
|
||||
{
|
||||
// add text. getString appends to current content
|
||||
if ((fabs(col[3] - 0.004f) < 0.001f) ||
|
||||
(render_name && (fabs(col[3] - 0.000f) < 0.001f)))
|
||||
nameplate = obj->mText->getStringUTF8();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( render_name )
|
||||
{
|
||||
BOOL new_name = FALSE;
|
||||
@@ -3776,14 +3836,15 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last)
|
||||
*/
|
||||
LLAvatarName av_name;
|
||||
bool dnhasloaded = false;
|
||||
bool useddn = true;
|
||||
bool show_un = false;
|
||||
if(LLAvatarNameCache::useDisplayNames() && LLAvatarNameCache::get(getID(), &av_name)) dnhasloaded=true;
|
||||
|
||||
std::string usedname;
|
||||
if(dnhasloaded && !av_name.mIsDisplayNameDefault && !av_name.mIsDummy
|
||||
&& av_name.mDisplayName != av_name.getLegacyName())
|
||||
&& av_name.mDisplayName != av_name.getLegacyName())
|
||||
{
|
||||
usedname = av_name.mDisplayName;
|
||||
show_un = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -3794,8 +3855,6 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last)
|
||||
usedname += " ";
|
||||
usedname += ln;
|
||||
}
|
||||
dnhasloaded=false;
|
||||
useddn=false;
|
||||
}
|
||||
|
||||
BOOL is_away = mSignaledAnimations.find(ANIM_AGENT_AWAY) != mSignaledAnimations.end();
|
||||
@@ -3814,70 +3873,95 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last)
|
||||
is_muted = LLMuteList::getInstance()->isMuted(getID());
|
||||
}
|
||||
|
||||
if (mNameString.empty() ||
|
||||
if ((mNameString.empty() && !(mNameFromChatOverride && mNameFromChatText.empty())) ||
|
||||
new_name ||
|
||||
mRenderedName != usedname ||
|
||||
mUsedNameSystem != phoenix_name_system ||
|
||||
(!title && !mTitle.empty()) ||
|
||||
(title && mTitle != title->getString()) ||
|
||||
(is_away != mNameAway || is_busy != mNameBusy || is_muted != mNameMute)
|
||||
|| is_appearance != mNameAppearance || client != mClientName)
|
||||
(is_away != mNameAway || is_busy != mNameBusy || is_muted != mNameMute) ||
|
||||
is_appearance != mNameAppearance || client != mClientName ||
|
||||
mNameFromAttachment != nameplate)
|
||||
{
|
||||
std::string line;
|
||||
mRenderedName = usedname;
|
||||
mNameFromAttachment = nameplate;
|
||||
mNameAway = is_away;
|
||||
mNameBusy = is_busy;
|
||||
mNameMute = is_muted;
|
||||
mClientName = client;
|
||||
mUsedNameSystem = phoenix_name_system;
|
||||
mNameAppearance = is_appearance;
|
||||
mTitle = title? title->getString() : "";
|
||||
|
||||
std::string::size_type index;
|
||||
|
||||
std::string firstNameString, lastNameString, titleString;
|
||||
std::string line = nameplate;
|
||||
|
||||
// [RLVa:KB] - Version: 1.23.4 | Checked: 2009-07-08 (RLVa-1.0.0e) | Added: RLVa-0.2.0b
|
||||
if (!fRlvShowNames)
|
||||
{
|
||||
// [/RLVa:KB]
|
||||
if (!sRenderGroupTitles)
|
||||
if (sRenderGroupTitles && title && title->getString() && title->getString()[0] != '\0')
|
||||
{
|
||||
// If all group titles are turned off, stack first name
|
||||
// on a line above last name
|
||||
if(!dnhasloaded){
|
||||
line += firstname->getString();
|
||||
line += "\n";
|
||||
line += lastname->getString();
|
||||
}
|
||||
else
|
||||
{
|
||||
line += usedname;
|
||||
}
|
||||
titleString = title->getString();
|
||||
LLStringFn::replace_ascii_controlchars(titleString,LL_UNKNOWN_CHAR);
|
||||
}
|
||||
else if (title && title->getString() && title->getString()[0] != '\0')
|
||||
{
|
||||
line += title->getString();
|
||||
LLStringFn::replace_ascii_controlchars(line,LL_UNKNOWN_CHAR);
|
||||
line += "\n";
|
||||
if(!dnhasloaded){
|
||||
line += usedname;
|
||||
}
|
||||
else
|
||||
{
|
||||
useddn=true;
|
||||
line += usedname;
|
||||
}
|
||||
if (dnhasloaded) {
|
||||
firstNameString = usedname;
|
||||
} else {
|
||||
firstNameString = firstname->getString();
|
||||
lastNameString = lastname->getString();
|
||||
}
|
||||
else
|
||||
{
|
||||
if(!dnhasloaded){
|
||||
line += usedname;
|
||||
}
|
||||
else
|
||||
{
|
||||
useddn=true;
|
||||
line += usedname;
|
||||
}
|
||||
}
|
||||
|
||||
// [RLVa:KB] - Version: 1.23.4 | Checked: 2009-07-08 (RLVa-1.0.0e) | Added: RLVa-0.2.0b
|
||||
}
|
||||
else
|
||||
{
|
||||
line = RlvStrings::getAnonym(line.assign(firstname->getString()).append(" ").append(lastname->getString()));
|
||||
show_un = false;
|
||||
firstNameString = RlvStrings::getAnonym(firstname->getString() + std::string(" ") + lastname->getString());
|
||||
}
|
||||
// [/RLVa:KB]
|
||||
BOOL need_comma = FALSE;
|
||||
|
||||
// set name template
|
||||
if (mNameFromChatOverride) {
|
||||
//llinfos << "NEW NAME: '" << mNameFromChatText << "'" << llendl;
|
||||
line = mNameFromChatText;
|
||||
} else if (nameplate.empty()) {
|
||||
if (sRenderGroupTitles) {
|
||||
line = "%g\n%f %l";
|
||||
} else {
|
||||
// If all group titles are turned off, stack first name
|
||||
// on a line above last name
|
||||
line = "%f\n%l";
|
||||
}
|
||||
}
|
||||
|
||||
// replace first name, last name and title
|
||||
while ((index = line.find("%f")) != std::string::npos)
|
||||
line.replace(index, 2, firstNameString);
|
||||
while ((index = line.find("%l")) != std::string::npos)
|
||||
line.replace(index, 2, lastNameString);
|
||||
while ((index = line.find("%g")) != std::string::npos)
|
||||
line.replace(index, 2, titleString);
|
||||
|
||||
// remove empty lines
|
||||
while ((index = line.find("\r")) != std::string::npos)
|
||||
line.erase(index, 1);
|
||||
while (!line.empty() && (line[0] == ' '))
|
||||
line.erase(0, 1);
|
||||
while (!line.empty() && (line[line.size()-1] == ' '))
|
||||
line.erase(line.size()-1, 1);
|
||||
while ((index = line.find(" \n")) != std::string::npos)
|
||||
line.erase(index, 1);
|
||||
while ((index = line.find("\n ")) != std::string::npos)
|
||||
line.erase(index+1, 1);
|
||||
while (!line.empty() && (line[0] == '\n'))
|
||||
line.erase(0, 1);
|
||||
while (!line.empty() && (line[line.size()-1] == '\n'))
|
||||
line.erase(line.size()-1, 1);
|
||||
while ((index = line.find("\n\n")) != std::string::npos)
|
||||
line.erase(index, 1);
|
||||
|
||||
|
||||
BOOL need_comma = FALSE;
|
||||
std::string additions;
|
||||
|
||||
if (client.length() || is_away || is_muted || is_busy)
|
||||
@@ -3923,18 +4007,12 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last)
|
||||
|
||||
}
|
||||
mSubNameString = "";
|
||||
if(useddn){
|
||||
if(show_un){
|
||||
if(phoenix_name_system != 2){
|
||||
mSubNameString = "("+av_name.mUsername+")";
|
||||
}
|
||||
mRenderedName = av_name.mDisplayName;
|
||||
}
|
||||
else
|
||||
{
|
||||
mRenderedName = firstname->getString();
|
||||
mRenderedName += " ";
|
||||
mRenderedName += lastname->getString();
|
||||
}
|
||||
|
||||
if (is_appearance)
|
||||
{
|
||||
line += "\n";
|
||||
@@ -3946,14 +4024,6 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last)
|
||||
line += getIdleTime();
|
||||
}
|
||||
|
||||
mNameAway = is_away;
|
||||
mNameBusy = is_busy;
|
||||
mNameMute = is_muted;
|
||||
mClientName = client;
|
||||
mUsedNameSystem = phoenix_name_system;
|
||||
mNameAppearance = is_appearance;
|
||||
mTitle = title ? title->getString() : "";
|
||||
LLStringFn::replace_ascii_controlchars(mTitle,LL_UNKNOWN_CHAR);
|
||||
mNameString = utf8str_to_wstring(line);
|
||||
new_name = TRUE;
|
||||
}
|
||||
|
||||
@@ -270,6 +270,9 @@ public:
|
||||
void startTyping() { mTyping = TRUE; mTypingTimer.reset(); mIdleTimer.reset();}
|
||||
void stopTyping() { mTyping = FALSE; }
|
||||
|
||||
void setNameFromChat(const std::string &text) { mNameFromChatOverride = mNameFromChatChanged = true; mNameFromChatText = text; }
|
||||
void clearNameFromChat() { mNameFromChatOverride = false; mNameFromChatChanged = true; mNameFromChatText = ""; }
|
||||
|
||||
// Returns "FirstName LastName"
|
||||
std::string getFullname() const;
|
||||
|
||||
@@ -701,10 +704,6 @@ private:
|
||||
LLVoiceVisualizer* mVoiceVisualizer;
|
||||
int mCurrentGesticulationLevel;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Animation timer
|
||||
LLTimer mAnimTimer;
|
||||
F32 mTimeLast;
|
||||
@@ -715,6 +714,10 @@ private:
|
||||
static void resolveClient(LLColor4& avatar_name_color, std::string& client, LLVOAvatar* avatar);
|
||||
friend class LLFloaterAvatarList;
|
||||
|
||||
bool mNameFromChatOverride;
|
||||
bool mNameFromChatChanged;
|
||||
std::string mNameFromChatText;
|
||||
std::string mNameFromAttachment;
|
||||
|
||||
LLPointer<LLHUDEffectSpiral> mBeam;
|
||||
LLFrameTimer mBeamTimer;
|
||||
|
||||
Reference in New Issue
Block a user