diff --git a/indra/newview/llfloatermessagebuilder.cpp b/indra/newview/llfloatermessagebuilder.cpp index 9825833cd..d78a29f3e 100644 --- a/indra/newview/llfloatermessagebuilder.cpp +++ b/indra/newview/llfloatermessagebuilder.cpp @@ -1,810 +1,965 @@ -// -#include "llviewerprecompiledheaders.h" -#include "llfloatermessagebuilder.h" -#include "lluictrlfactory.h" -#include "llmessagetemplate.h" -#include "llagent.h" -#include "llchat.h" -#include "llfloaterchat.h" -#include "llviewerregion.h" // getHandle -#include "llcombobox.h" -#include "llselectmgr.h" // fill in stuff about selected object -#include "llparcel.h" -#include "llviewerparcelmgr.h" // same for parcel -LLFloaterMessageBuilder::LLFloaterMessageBuilder(std::string initial_text) -: LLFloater(), - mInitialText(initial_text) -{ - LLUICtrlFactory::getInstance()->buildFloater(this, "floater_message_builder.xml"); -} -LLFloaterMessageBuilder::~LLFloaterMessageBuilder() -{ -} -void LLFloaterMessageBuilder::show(std::string initial_text) -{ - (new LLFloaterMessageBuilder(initial_text))->open(); -} -BOOL LLFloaterMessageBuilder::postBuild() -{ - childSetText("message_edit", mInitialText); - childSetAction("send_btn", onClickSend, this); - std::vector names; - LLComboBox* combo; - LLMessageSystem::message_template_name_map_t::iterator temp_end = gMessageSystem->mMessageTemplates.end(); - LLMessageSystem::message_template_name_map_t::iterator temp_iter; - std::vector::iterator names_end; - std::vector::iterator names_iter; - for(temp_iter = gMessageSystem->mMessageTemplates.begin(); temp_iter != temp_end; ++temp_iter) - if((*temp_iter).second->getTrust() == MT_NOTRUST) - names.push_back((*temp_iter).second->mName); - std::sort(names.begin(), names.end()); - combo = getChild("untrusted_message_combo"); - names_end = names.end(); - for(names_iter = names.begin(); names_iter != names_end; ++names_iter) - combo->add((*names_iter)); - names.clear(); - for(temp_iter = gMessageSystem->mMessageTemplates.begin(); temp_iter != temp_end; ++temp_iter) - if((*temp_iter).second->getTrust() == MT_TRUST) - names.push_back((*temp_iter).second->mName); - std::sort(names.begin(), names.end()); - combo = getChild("trusted_message_combo"); - names_end = names.end(); - for(names_iter = names.begin(); names_iter != names_end; ++names_iter) - combo->add((*names_iter)); - childSetCommitCallback("untrusted_message_combo", onCommitPacketCombo, this); - childSetCommitCallback("trusted_message_combo", onCommitPacketCombo, this); - return TRUE; -} -inline std::vector split(std::string input, std::string separator) -{ - S32 size = input.length(); - char* buffer = new char[size + 1]; - strncpy(buffer, input.c_str(), size); - buffer[size] = '\0'; - std::vector lines; - char* result = strtok(buffer, separator.c_str()); - while(result) - { - lines.push_back(result); - result = strtok(NULL, separator.c_str()); - } - delete[] buffer; - return lines; -} -std::string mvtstr(e_message_variable_type var_type) -{ - switch(var_type) - { - case MVT_U8: - return "U8"; - break; - case MVT_U16: - return "U16"; - break; - case MVT_U32: - return "U32"; - break; - case MVT_U64: - return "U64"; - break; - case MVT_S8: - return "S8"; - break; - case MVT_S16: - return "S16"; - break; - case MVT_S32: - return "S32"; - break; - case MVT_S64: - return "S64"; - break; - case MVT_F32: - return "F32"; - break; - case MVT_F64: - return "F64"; - break; - case MVT_LLVector3: - return "LLVector3"; - break; - case MVT_LLVector3d: - return "LLVector3d"; - break; - case MVT_LLVector4: - return "LLVector4"; - break; - case MVT_LLQuaternion: - return "LLQuaternion"; - break; - case MVT_LLUUID: - return "LLUUID"; - break; - case MVT_BOOL: - return "BOOL"; - break; - case MVT_IP_ADDR: - return "IPADDR"; - break; - case MVT_IP_PORT: - return "IPPORT"; - break; - case MVT_VARIABLE: - return "Variable"; - break; - case MVT_FIXED: - return "Fixed"; - break; - default: - return "Missingno."; - break; - } -} -// static -BOOL LLFloaterMessageBuilder::addField(e_message_variable_type var_type, const char* var_name, std::string input, BOOL hex) -{ - LLStringUtil::trim(input); - if(input.length() < 1 && var_type != MVT_VARIABLE) - return FALSE; - U8 valueU8; - U16 valueU16; - U32 valueU32; - U64 valueU64; - S8 valueS8; - S16 valueS16; - S32 valueS32; - // S64 valueS64; - F32 valueF32; - F64 valueF64; - LLVector3 valueVector3; - LLVector3d valueVector3d; - LLVector4 valueVector4; - LLQuaternion valueQuaternion; - LLUUID valueLLUUID; - BOOL valueBOOL; - std::string input_lower = input; - LLStringUtil::toLower(input_lower); - if(input_lower == "$agentid") - input = gAgent.getID().asString(); - else if(input_lower == "$sessionid") - input = gAgent.getSessionID().asString(); - else if(input_lower == "$uuid") - { - LLUUID id; - id.generate(); - input = id.asString(); - } - else if(input_lower == "$circuitcode") - { - std::stringstream temp_stream; - temp_stream << gMessageSystem->mOurCircuitCode; - input = temp_stream.str(); - } - else if(input_lower == "$regionhandle") - { - std::stringstream temp_stream; - temp_stream << (gAgent.getRegion() ? gAgent.getRegion()->getHandle() : 0); - input = temp_stream.str(); - } - else if(input_lower == "$position" || input_lower == "$pos") - { - std::stringstream temp_stream; - valueVector3 = gAgent.getPositionAgent(); - temp_stream << "<" << valueVector3[0] << ", " << valueVector3[1] << ", " << valueVector3[2] << ">"; - input = temp_stream.str(); - } - if(hex) - { - if(var_type != MVT_VARIABLE && var_type != MVT_FIXED) - return FALSE; - int len = input_lower.length(); - const char* cstr = input_lower.c_str(); - std::string new_input(""); - BOOL nibble = FALSE; - char byte = 0; - for(int i = 0; i < len; i++) - { - char c = cstr[i]; - if(c >= 0x30 && c <= 0x39) - c -= 0x30; - else if(c >= 0x61 && c <= 0x66) - c -= 0x57; - else if(c != 0x20) - return FALSE; - else - continue; - if(!nibble) - byte = c << 4; - else - new_input.push_back(byte | c); - nibble = !nibble; - } - if(nibble) - return FALSE; - input = new_input; - } - std::stringstream stream(input); - std::vector tokens; - switch(var_type) - { - case MVT_U8: - if(input.substr(0, 1) == "-") - return FALSE; - if((stream >> valueU32).fail()) - return FALSE; - valueU8 = (U8)valueU32; - gMessageSystem->addU8(var_name, valueU8); - return TRUE; - break; - case MVT_U16: - if(input.substr(0, 1) == "-") - return FALSE; - if((stream >> valueU16).fail()) - return FALSE; - gMessageSystem->addU16(var_name, valueU16); - return TRUE; - break; - case MVT_U32: - if(input.substr(0, 1) == "-") - return FALSE; - if((stream >> valueU32).fail()) - return FALSE; - gMessageSystem->addU32(var_name, valueU32); - return TRUE; - break; - case MVT_U64: - if(input.substr(0, 1) == "-") - return FALSE; - if((stream >> valueU64).fail()) - return FALSE; - gMessageSystem->addU64(var_name, valueU64); - return TRUE; - break; - case MVT_S8: - if((stream >> valueS8).fail()) - return FALSE; - gMessageSystem->addS8(var_name, valueS8); - return TRUE; - break; - case MVT_S16: - if((stream >> valueS16).fail()) - return FALSE; - gMessageSystem->addS16(var_name, valueS16); - return TRUE; - break; - case MVT_S32: - if((stream >> valueS32).fail()) - return FALSE; - gMessageSystem->addS32(var_name, valueS32); - return TRUE; - break; - /* - case MVT_S64: - if((stream >> valueS64).fail()) - return FALSE; - gMessageSystem->addS64(var_name, valueS64); - return TRUE; - break; - */ - case MVT_F32: - if((stream >> valueF32).fail()) - return FALSE; - gMessageSystem->addF32(var_name, valueF32); - return TRUE; - break; - case MVT_F64: - if((stream >> valueF64).fail()) - return FALSE; - gMessageSystem->addF64(var_name, valueF64); - return TRUE; - break; - case MVT_LLVector3: - LLStringUtil::trim(input); - if(input.substr(0, 1) != "<" || input.substr(input.length() - 1, 1) != ">") - return FALSE; - tokens = split(input.substr(1, input.length() - 2), ","); - if(tokens.size() != 3) - return FALSE; - for(int i = 0; i < 3; i++) - { - stream.clear(); - stream.str(tokens[i]); - if((stream >> valueF32).fail()) - return FALSE; - valueVector3.mV[i] = valueF32; - } - gMessageSystem->addVector3(var_name, valueVector3); - return TRUE; - break; - case MVT_LLVector3d: - LLStringUtil::trim(input); - if(input.substr(0, 1) != "<" || input.substr(input.length() - 1, 1) != ">") - return FALSE; - tokens = split(input.substr(1, input.length() - 2), ","); - if(tokens.size() != 3) - return FALSE; - for(int i = 0; i < 3; i++) - { - stream.clear(); - stream.str(tokens[i]); - if((stream >> valueF64).fail()) - return FALSE; - valueVector3d.mdV[i] = valueF64; - } - gMessageSystem->addVector3d(var_name, valueVector3d); - return TRUE; - break; - case MVT_LLVector4: - LLStringUtil::trim(input); - if(input.substr(0, 1) != "<" || input.substr(input.length() - 1, 1) != ">") - return FALSE; - tokens = split(input.substr(1, input.length() - 2), ","); - if(tokens.size() != 4) - return FALSE; - for(int i = 0; i < 4; i++) - { - stream.clear(); - stream.str(tokens[i]); - if((stream >> valueF32).fail()) - return FALSE; - valueVector4.mV[i] = valueF32; - } - gMessageSystem->addVector4(var_name, valueVector4); - return TRUE; - break; - case MVT_LLQuaternion: - LLStringUtil::trim(input); - if(input.substr(0, 1) != "<" || input.substr(input.length() - 1, 1) != ">") - return FALSE; - tokens = split(input.substr(1, input.length() - 2), ","); - if(tokens.size() != 3) - return FALSE; - for(int i = 0; i < 3; i++) - { - stream.clear(); - stream.str(tokens[i]); - if((stream >> valueF32).fail()) - return FALSE; - valueVector3.mV[i] = valueF32; - } - valueQuaternion.unpackFromVector3(valueVector3); - gMessageSystem->addQuat(var_name, valueQuaternion); - return TRUE; - break; - case MVT_LLUUID: - if((stream >> valueLLUUID).fail()) - return FALSE; - gMessageSystem->addUUID(var_name, valueLLUUID); - return TRUE; - break; - case MVT_BOOL: - if(input_lower == "true") - valueBOOL = TRUE; - else if(input_lower == "false") - valueBOOL = FALSE; - else if((stream >> valueBOOL).fail()) - return FALSE; - //gMessageSystem->addBOOL(var_name, valueBOOL); - gMessageSystem->addU8(var_name, (U8)valueBOOL); - return TRUE; - break; - case MVT_IP_ADDR: - if((stream >> valueU32).fail()) - return FALSE; - gMessageSystem->addIPAddr(var_name, valueU32); - return TRUE; - break; - case MVT_IP_PORT: - if((stream >> valueU16).fail()) - return FALSE; - gMessageSystem->addIPPort(var_name, valueU16); - return TRUE; - break; - case MVT_VARIABLE: - if(!hex) - { - char* buffer = new char[input.size() + 1]; - strncpy(buffer, input.c_str(), input.size()); - buffer[input.size()] = '\0'; - gMessageSystem->addBinaryData(var_name, buffer, input.size() + 1); - delete[] buffer; - } - else - gMessageSystem->addBinaryData(var_name, input.c_str(), input.size()); - return TRUE; - break; - case MVT_FIXED: - if(!hex) - { - char* buffer = new char[input.size() + 1]; - strncpy(buffer, input.c_str(), input.size()); - buffer[input.size()] = '\0'; - gMessageSystem->addBinaryData(var_name, buffer, input.size()); - delete[] buffer; - } - else - gMessageSystem->addBinaryData(var_name, input.c_str(), input.size()); - return TRUE; - break; - default: - break; - } - return FALSE; -} -// static -void LLFloaterMessageBuilder::onCommitPacketCombo(LLUICtrl* ctrl, void* user_data) -{ - LLFloaterMessageBuilder* floaterp = (LLFloaterMessageBuilder*)user_data; - LLViewerObject* selected_objectp = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); - LLParcel* agent_parcelp = LLViewerParcelMgr::getInstance()->getAgentParcel(); - std::string message = ctrl->getValue(); - std::map::iterator template_iter; - template_iter = gMessageSystem->mMessageTemplates.find( LLMessageStringTable::getInstance()->getString(message.c_str()) ); - if(template_iter == gMessageSystem->mMessageTemplates.end()) - { - floaterp->childSetText("message_edit", std::string("")); - return; - } - std::string text(llformat((*template_iter).second->getTrust() == MT_NOTRUST ? "out %s\n" : "in %s\n", message.c_str())); - LLMessageTemplate* temp = (*template_iter).second; - LLMessageTemplate::message_block_map_t::iterator blocks_end = temp->mMemberBlocks.end(); - for (LLMessageTemplate::message_block_map_t::iterator blocks_iter = temp->mMemberBlocks.begin(); - blocks_iter != blocks_end; ++blocks_iter) - { - LLMessageBlock* block = (*blocks_iter); - const char* block_name = block->mName; - std::string block_name_string = std::string(block_name); - S32 num_blocks = 1; - if(block->mType == MBT_MULTIPLE) - num_blocks = block->mNumber; - else if(("ObjectLink" == message && "ObjectData" == block_name_string)) - num_blocks = 2; - for(S32 i = 0; i < num_blocks; i++) - { - text.append(llformat("[%s]\n", block_name)); - LLMessageBlock::message_variable_map_t::iterator var_end = block->mMemberVariables.end(); - for (LLMessageBlock::message_variable_map_t::iterator var_iter = block->mMemberVariables.begin(); - var_iter != var_end; ++var_iter) - { - LLMessageVariable* variable = (*var_iter); - const char* var_name = variable->getName(); - std::string var_name_string = std::string(var_name); - text.append(llformat("%s = ", var_name)); - std::string value(""); - S32 size = variable->getSize(); - switch(variable->getType()) - { - case MVT_U8: - case MVT_U16: - case MVT_U32: - case MVT_U64: - case MVT_S8: - case MVT_S16: - case MVT_S32: - case MVT_IP_ADDR: - case MVT_IP_PORT: - if("RegionHandle" == var_name_string || "Handle" == var_name_string) - value = "$RegionHandle"; - else if("CircuitCode" == var_name_string || "ViewerCircuitCode" == var_name_string - || ("Code" == var_name_string && "CircuitCode" == block_name_string) ) - { - value = "$CircuitCode"; - } - else if(selected_objectp && - ( - "ObjectLocalID" == var_name_string - || "TaskLocalID" == var_name_string - || ("LocalID" == var_name_string && - ( - "ObjectData" == block_name_string - || "UpdateData" == block_name_string - || "InventoryData" == block_name_string - ) - ) - ) - ) - { - std::stringstream temp_stream; - temp_stream << selected_objectp->getLocalID(); - value = temp_stream.str(); - } - else if( agent_parcelp && - "LocalID" == var_name_string && - ( - "ParcelData" == block_name_string - || message.find("Parcel") != message.npos - ) - ) - { - std::stringstream temp_stream; - temp_stream << agent_parcelp->getLocalID(); - value = temp_stream.str(); - } - else if("PCode" == var_name_string) - value = "9"; - else if("PathCurve" == var_name_string) - value = "16"; - else if("ProfileCurve" == var_name_string) - value = "1"; - else if("PathScaleX" == var_name_string || "PathScaleY" == var_name_string) - value = "100"; - else if("BypassRaycast" == var_name_string) - value = "1"; - else - value = "0"; - break; - case MVT_F32: - case MVT_F64: - value = "0.0"; - break; - case MVT_LLVector3: - case MVT_LLVector3d: - case MVT_LLQuaternion: - if("Position" == var_name_string || "RayStart" == var_name_string || "RayEnd" == var_name_string) - value = "$Position"; - else if("Scale" == var_name_string) - value = "<0.5, 0.5, 0.5>"; - else - value = "<0, 0, 0>"; - break; - case MVT_LLVector4: - value = "<0, 0, 0, 0>"; - break; - case MVT_LLUUID: - if("AgentID" == var_name_string) - value = "$AgentID"; - else if("SessionID" == var_name_string) - value = "$SessionID"; - else if("ObjectID" == var_name_string && selected_objectp) - value = selected_objectp->getID().asString(); - else if("ParcelID" == var_name_string && agent_parcelp) - value = agent_parcelp->getID().asString(); - else - value = "00000000-0000-0000-0000-000000000000"; - break; - case MVT_BOOL: - value = "false"; - break; - case MVT_VARIABLE: - value = "Hello, world!"; - break; - case MVT_FIXED: - for(S32 si = 0; si < size; si++) - //value.append(std::string("0123456789abcdef").substr(si & 0xf, 1)); - value.append("a"); - break; - default: - value = ""; - break; - } - text.append(llformat("%s\n", value.c_str())); - } - } - } - text = text.substr(0, text.length() - 1); - floaterp->childSetText("message_edit", text); -} -// static -void LLFloaterMessageBuilder::onClickSend(void* user_data) -{ - LLFloaterMessageBuilder* floaterp = (LLFloaterMessageBuilder*)user_data; - std::vector lines = split(floaterp->childGetText("message_edit"), "\n"); - if(!lines.size()) - { - LLFloaterChat::addChat(LLChat("Not enough information :O")); - return; - } - std::vector tokens = split(lines[0], " "); - if(!tokens.size()) - { - LLFloaterChat::addChat(LLChat("Not enough information :O")); - return; - } - std::string dir_str = tokens[0]; - LLStringUtil::toLower(dir_str); - // Direction - BOOL outgoing; - if(dir_str == "out") - outgoing = TRUE; - else if(dir_str == "in") - outgoing = FALSE; - else - { - LLFloaterChat::addChat(LLChat("Expected direction 'in' or 'out'")); - return; - } - // Message - std::string message = "Invalid"; - if(tokens.size() > 1) - { - if(tokens.size() > 2) - { - LLFloaterChat::addChat(LLChat("Unexpected extra stuff at the top")); - return; - } - message = tokens[1]; - LLStringUtil::trim(message); - } - // Body - std::vector parts; - if(lines.size() > 1) - { - std::vector::iterator line_end = lines.end(); - std::vector::iterator line_iter = lines.begin(); - ++line_iter; - std::string current_block(""); - int current_block_index = -1; - for( ; line_iter != line_end; ++line_iter) - { - std::string line = (*line_iter); - LLStringUtil::trim(line); - if(!line.length()) - continue; - if(line.substr(0, 1) == "[" && line.substr(line.size() - 1, 1) == "]") - { - current_block = line.substr(1, line.length() - 2); - LLStringUtil::trim(current_block); - ++current_block_index; - parts_block pb; - pb.name = current_block; - parts.push_back(pb); - } - else - { - if(current_block.empty()) - { - LLFloaterChat::addChat(LLChat("Unexpected field when no block yet")); - return; - } - int eqpos = line.find("="); - if(eqpos == line.npos) - { - LLFloaterChat::addChat(LLChat("Missing an equal sign")); - return; - } - std::string field = line.substr(0, eqpos); - LLStringUtil::trim(field); - if(!field.length()) - { - LLFloaterChat::addChat(LLChat("Missing name of field")); - return; - } - std::string value = line.substr(eqpos + 1); - LLStringUtil::trim(value); - parts_var pv; - if(value.substr(0, 1) == "|") - { - pv.hex = TRUE; - value = value.substr(1); - LLStringUtil::trim(value); - } - else - pv.hex = FALSE; - pv.name = field; - pv.value = value; - parts[current_block_index].vars.push_back(pv); - } - } - } - // Verification - std::map::iterator template_iter; - template_iter = gMessageSystem->mMessageTemplates.find( LLMessageStringTable::getInstance()->getString(message.c_str()) ); - if(template_iter == gMessageSystem->mMessageTemplates.end()) - { - LLFloaterChat::addChat(LLChat(llformat("Don't know how to build a '%s' message", message.c_str()))); - return; - } - LLMessageTemplate* temp = (*template_iter).second; - std::vector::iterator parts_end = parts.end(); - std::vector::iterator parts_iter = parts.begin(); - LLMessageTemplate::message_block_map_t::iterator blocks_end = temp->mMemberBlocks.end(); - for (LLMessageTemplate::message_block_map_t::iterator blocks_iter = temp->mMemberBlocks.begin(); - blocks_iter != blocks_end; ) - { - LLMessageBlock* block = (*blocks_iter); - const char* block_name = block->mName; - if(parts_iter == parts_end) - { - if(block->mType != MBT_VARIABLE) - LLFloaterChat::addChat(LLChat(llformat("Expected '%s' block", block_name))); - else - { - ++blocks_iter; - continue; - } - return; - } - else if((*parts_iter).name != block_name) - { - if(block->mType != MBT_VARIABLE) - LLFloaterChat::addChat(LLChat(llformat("Expected '%s' block", block_name))); - else - { - ++blocks_iter; - continue; - } - return; - } - std::vector::iterator part_var_end = (*parts_iter).vars.end(); - std::vector::iterator part_var_iter = (*parts_iter).vars.begin(); - LLMessageBlock::message_variable_map_t::iterator var_end = block->mMemberVariables.end(); - for (LLMessageBlock::message_variable_map_t::iterator var_iter = block->mMemberVariables.begin(); - var_iter != var_end; ++var_iter) - { - LLMessageVariable* variable = (*var_iter); - const char* var_name = variable->getName(); - if(part_var_iter == part_var_end) - { - LLFloaterChat::addChat(LLChat(llformat("Expected '%s' field under '%s' block", var_name, block_name))); - return; - } - else if((*part_var_iter).name != var_name) - { - LLFloaterChat::addChat(LLChat(llformat("Expected '%s' field under '%s' block", var_name, block_name))); - return; - } - (*part_var_iter).var_type = variable->getType(); - ++part_var_iter; - } - if(part_var_iter != part_var_end) - { - LLFloaterChat::addChat(LLChat(llformat("Unexpected field(s) at end of '%s' block", block_name))); - return; - } - ++parts_iter; - // test - if((block->mType != MBT_SINGLE) && (parts_iter != parts_end) && ((*parts_iter).name == block_name)) - { - // block will repeat - } - else ++blocks_iter; - } - if(parts_iter != parts_end) - { - LLFloaterChat::addChat(LLChat("Unexpected block(s) at end")); - return; - } - // Build and send - if(outgoing) - { - gMessageSystem->newMessage( message.c_str() ); - for(parts_iter = parts.begin(); parts_iter != parts_end; ++parts_iter) - { - const char* block_name = (*parts_iter).name.c_str(); - gMessageSystem->nextBlock(block_name); - std::vector::iterator part_var_end = (*parts_iter).vars.end(); - for(std::vector::iterator part_var_iter = (*parts_iter).vars.begin(); - part_var_iter != part_var_end; ++part_var_iter) - { - parts_var pv = (*part_var_iter); - if(!addField(pv.var_type, pv.name.c_str(), pv.value, pv.hex)) - { - 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))); - gMessageSystem->clearMessage(); - return; - } - } - } - gMessageSystem->sendMessage(gAgent.getRegionHost()); - } - else - { - LLFloaterChat::addChat(LLChat("Incoming message isn't supported yet :(")); - return; - } -} -BOOL LLFloaterMessageBuilder::handleKeyHere(KEY key, MASK mask) -{ - if(key == KEY_RETURN && (mask & MASK_CONTROL)) - { - onClickSend(this); - return TRUE; - } - if(key == KEY_ESCAPE) - { - releaseFocus(); - return TRUE; - } - return FALSE; -} -// +// +#include "llviewerprecompiledheaders.h" +#include "llfloatermessagebuilder.h" +#include "lluictrlfactory.h" +#include "llmessagetemplate.h" +#include "llagent.h" +#include "llchat.h" +#include "llfloaterchat.h" +#include "llviewerregion.h" // getHandle +#include "llcombobox.h" +#include "llselectmgr.h" // fill in stuff about selected object +#include "llparcel.h" +#include "llviewerparcelmgr.h" // same for parcel +#include "llscrolllistctrl.h" +#include "llworld.h" + +//////////////////////////////// +// LLNetListItem +//////////////////////////////// +LLNetListItem::LLNetListItem(LLUUID id) +: mID(id), + mAutoName(TRUE), + mName("No name"), + mPreviousRegionName(""), + mCircuitData(NULL) +{ +} + +//////////////////////////////// +// LLFloaterMessageBuilder +//////////////////////////////// +std::list LLFloaterMessageBuilder::sNetListItems; + +LLFloaterMessageBuilder::LLFloaterMessageBuilder(std::string initial_text) +: LLFloater(), + LLEventTimer(1.0f), + mNetInfoMode(NI_NET), + mInitialText(initial_text) +{ + LLUICtrlFactory::getInstance()->buildFloater(this, "floater_message_builder.xml"); +} +LLFloaterMessageBuilder::~LLFloaterMessageBuilder() +{ +} +void LLFloaterMessageBuilder::show(std::string initial_text) +{ + (new LLFloaterMessageBuilder(initial_text))->open(); +} +BOOL LLFloaterMessageBuilder::tick() +{ + refreshNetList(); + return FALSE; +} +LLNetListItem* LLFloaterMessageBuilder::findNetListItem(LLHost host) +{ + std::list::iterator end = sNetListItems.end(); + for(std::list::iterator iter = sNetListItems.begin(); iter != end; ++iter) + if((*iter)->mCircuitData && (*iter)->mCircuitData->getHost() == host) + return (*iter); + return NULL; +} +LLNetListItem* LLFloaterMessageBuilder::findNetListItem(LLUUID id) +{ + std::list::iterator end = sNetListItems.end(); + for(std::list::iterator iter = sNetListItems.begin(); iter != end; ++iter) + if((*iter)->mID == id) + return (*iter); + return NULL; +} +void LLFloaterMessageBuilder::refreshNetList() +{ + LLScrollListCtrl* scrollp = getChild("net_list"); + // Update circuit data of net list items + std::vector circuits = gMessageSystem->getCircuit()->getCircuitDataList(); + std::vector::iterator circuits_end = circuits.end(); + for(std::vector::iterator iter = circuits.begin(); iter != circuits_end; ++iter) + { + LLNetListItem* itemp = findNetListItem((*iter)->getHost()); + if(!itemp) + { + LLUUID id; id.generate(); + itemp = new LLNetListItem(id); + sNetListItems.push_back(itemp); + } + itemp->mCircuitData = (*iter); + } + // Clear circuit data of items whose circuits are gone + std::list::iterator items_end = sNetListItems.end(); + for(std::list::iterator iter = sNetListItems.begin(); iter != items_end; ++iter) + { + if(std::find(circuits.begin(), circuits.end(), (*iter)->mCircuitData) == circuits.end()) + (*iter)->mCircuitData = NULL; + } + // Remove net list items that are totally useless now + for(std::list::iterator iter = sNetListItems.begin(); iter != sNetListItems.end();) + { + if((*iter)->mCircuitData == NULL) + iter = sNetListItems.erase(iter); + else ++iter; + } + // Update names of net list items + items_end = sNetListItems.end(); + for(std::list::iterator iter = sNetListItems.begin(); iter != items_end; ++iter) + { + LLNetListItem* itemp = (*iter); + if(itemp->mAutoName) + { + if(itemp->mCircuitData) + { + LLViewerRegion* regionp = LLWorld::getInstance()->getRegion(itemp->mCircuitData->getHost()); + if(regionp) + { + std::string name = regionp->getName(); + if(name == "") name = llformat("%s (awaiting region name)", itemp->mCircuitData->getHost().getString().c_str()); + itemp->mName = name; + itemp->mPreviousRegionName = name; + } + else + { + itemp->mName = itemp->mCircuitData->getHost().getString(); + if(itemp->mPreviousRegionName != "") + itemp->mName.append(llformat(" (was %s)", itemp->mPreviousRegionName.c_str())); + } + } + else + { + // an item just for an event queue, not handled yet + itemp->mName = "Something else"; + } + } + } + // Rebuild scroll list from scratch + LLUUID selected_id = scrollp->getFirstSelected() ? scrollp->getFirstSelected()->getUUID() : LLUUID::null; + S32 scroll_pos = scrollp->getScrollPos(); + scrollp->clearRows(); + for(std::list::iterator iter = sNetListItems.begin(); iter != items_end; ++iter) + { + LLNetListItem* itemp = (*iter); + LLSD element; + element["id"] = itemp->mID; + LLSD& text_column = element["columns"][0]; + text_column["column"] = "text"; + text_column["value"] = itemp->mName + (itemp->mCircuitData->getHost() == gAgent.getRegionHost() ? " (main)" : ""); + + LLSD& state_column = element["columns"][ 1]; + state_column["column"] = "state"; + state_column["value"] = ""; + + LLScrollListItem* scroll_itemp = scrollp->addElement(element); + BOOL has_live_circuit = itemp->mCircuitData && itemp->mCircuitData->isAlive(); + + LLScrollListText* state = (LLScrollListText*)scroll_itemp->getColumn(1); + + if(has_live_circuit) + state->setText(std::string("Alive")); + else + state->setText(std::string("Alive")); + } + if(selected_id.notNull()) scrollp->selectByID(selected_id); + if(scroll_pos < scrollp->getItemCount()) scrollp->setScrollPos(scroll_pos); +} +BOOL LLFloaterMessageBuilder::postBuild() +{ + childSetText("message_edit", mInitialText); + childSetAction("send_btn", onClickSend, this); + std::vector names; + LLComboBox* combo; + LLMessageSystem::message_template_name_map_t::iterator temp_end = gMessageSystem->mMessageTemplates.end(); + LLMessageSystem::message_template_name_map_t::iterator temp_iter; + std::vector::iterator names_end; + std::vector::iterator names_iter; + for(temp_iter = gMessageSystem->mMessageTemplates.begin(); temp_iter != temp_end; ++temp_iter) + if((*temp_iter).second->getTrust() == MT_NOTRUST) + names.push_back((*temp_iter).second->mName); + std::sort(names.begin(), names.end()); + combo = getChild("untrusted_message_combo"); + names_end = names.end(); + for(names_iter = names.begin(); names_iter != names_end; ++names_iter) + combo->add((*names_iter)); + names.clear(); + for(temp_iter = gMessageSystem->mMessageTemplates.begin(); temp_iter != temp_end; ++temp_iter) + if((*temp_iter).second->getTrust() == MT_TRUST) + names.push_back((*temp_iter).second->mName); + std::sort(names.begin(), names.end()); + combo = getChild("trusted_message_combo"); + names_end = names.end(); + for(names_iter = names.begin(); names_iter != names_end; ++names_iter) + combo->add((*names_iter)); + childSetCommitCallback("untrusted_message_combo", onCommitPacketCombo, this); + childSetCommitCallback("trusted_message_combo", onCommitPacketCombo, this); + return TRUE; +} +inline std::vector split(std::string input, std::string separator) +{ + S32 size = input.length(); + char* buffer = new char[size + 1]; + strncpy(buffer, input.c_str(), size); + buffer[size] = '\0'; + std::vector lines; + char* result = strtok(buffer, separator.c_str()); + while(result) + { + lines.push_back(result); + result = strtok(NULL, separator.c_str()); + } + delete[] buffer; + return lines; +} +std::string mvtstr(e_message_variable_type var_type) +{ + switch(var_type) + { + case MVT_U8: + return "U8"; + break; + case MVT_U16: + return "U16"; + break; + case MVT_U32: + return "U32"; + break; + case MVT_U64: + return "U64"; + break; + case MVT_S8: + return "S8"; + break; + case MVT_S16: + return "S16"; + break; + case MVT_S32: + return "S32"; + break; + case MVT_S64: + return "S64"; + break; + case MVT_F32: + return "F32"; + break; + case MVT_F64: + return "F64"; + break; + case MVT_LLVector3: + return "LLVector3"; + break; + case MVT_LLVector3d: + return "LLVector3d"; + break; + case MVT_LLVector4: + return "LLVector4"; + break; + case MVT_LLQuaternion: + return "LLQuaternion"; + break; + case MVT_LLUUID: + return "LLUUID"; + break; + case MVT_BOOL: + return "BOOL"; + break; + case MVT_IP_ADDR: + return "IPADDR"; + break; + case MVT_IP_PORT: + return "IPPORT"; + break; + case MVT_VARIABLE: + return "Variable"; + break; + case MVT_FIXED: + return "Fixed"; + break; + default: + return "Missingno."; + break; + } +} +// static +BOOL LLFloaterMessageBuilder::addField(e_message_variable_type var_type, const char* var_name, std::string input, BOOL hex) +{ + LLStringUtil::trim(input); + if(input.length() < 1 && var_type != MVT_VARIABLE) + return FALSE; + U8 valueU8; + U16 valueU16; + U32 valueU32; + U64 valueU64; + S8 valueS8; + S16 valueS16; + S32 valueS32; + // S64 valueS64; + F32 valueF32; + F64 valueF64; + LLVector3 valueVector3; + LLVector3d valueVector3d; + LLVector4 valueVector4; + LLQuaternion valueQuaternion; + LLUUID valueLLUUID; + BOOL valueBOOL; + std::string input_lower = input; + LLStringUtil::toLower(input_lower); + if(input_lower == "$agentid") + input = gAgent.getID().asString(); + else if(input_lower == "$sessionid") + input = gAgent.getSessionID().asString(); + else if(input_lower == "$uuid") + { + LLUUID id; + id.generate(); + input = id.asString(); + } + else if(input_lower == "$circuitcode") + { + std::stringstream temp_stream; + temp_stream << gMessageSystem->mOurCircuitCode; + input = temp_stream.str(); + } + else if(input_lower == "$regionhandle") + { + std::stringstream temp_stream; + temp_stream << (gAgent.getRegion() ? gAgent.getRegion()->getHandle() : 0); + input = temp_stream.str(); + } + else if(input_lower == "$position" || input_lower == "$pos") + { + std::stringstream temp_stream; + valueVector3 = gAgent.getPositionAgent(); + temp_stream << "<" << valueVector3[0] << ", " << valueVector3[1] << ", " << valueVector3[2] << ">"; + input = temp_stream.str(); + } + if(hex) + { + if(var_type != MVT_VARIABLE && var_type != MVT_FIXED) + return FALSE; + int len = input_lower.length(); + const char* cstr = input_lower.c_str(); + std::string new_input(""); + BOOL nibble = FALSE; + char byte = 0; + for(int i = 0; i < len; i++) + { + char c = cstr[i]; + if(c >= 0x30 && c <= 0x39) + c -= 0x30; + else if(c >= 0x61 && c <= 0x66) + c -= 0x57; + else if(c != 0x20) + return FALSE; + else + continue; + if(!nibble) + byte = c << 4; + else + new_input.push_back(byte | c); + nibble = !nibble; + } + if(nibble) + return FALSE; + input = new_input; + } + std::stringstream stream(input); + std::vector tokens; + switch(var_type) + { + case MVT_U8: + if(input.substr(0, 1) == "-") + return FALSE; + if((stream >> valueU32).fail()) + return FALSE; + valueU8 = (U8)valueU32; + gMessageSystem->addU8(var_name, valueU8); + return TRUE; + break; + case MVT_U16: + if(input.substr(0, 1) == "-") + return FALSE; + if((stream >> valueU16).fail()) + return FALSE; + gMessageSystem->addU16(var_name, valueU16); + return TRUE; + break; + case MVT_U32: + if(input.substr(0, 1) == "-") + return FALSE; + if((stream >> valueU32).fail()) + return FALSE; + gMessageSystem->addU32(var_name, valueU32); + return TRUE; + break; + case MVT_U64: + if(input.substr(0, 1) == "-") + return FALSE; + if((stream >> valueU64).fail()) + return FALSE; + gMessageSystem->addU64(var_name, valueU64); + return TRUE; + break; + case MVT_S8: + if((stream >> valueS8).fail()) + return FALSE; + gMessageSystem->addS8(var_name, valueS8); + return TRUE; + break; + case MVT_S16: + if((stream >> valueS16).fail()) + return FALSE; + gMessageSystem->addS16(var_name, valueS16); + return TRUE; + break; + case MVT_S32: + if((stream >> valueS32).fail()) + return FALSE; + gMessageSystem->addS32(var_name, valueS32); + return TRUE; + break; + /* + case MVT_S64: + if((stream >> valueS64).fail()) + return FALSE; + gMessageSystem->addS64(var_name, valueS64); + return TRUE; + break; + */ + case MVT_F32: + if((stream >> valueF32).fail()) + return FALSE; + gMessageSystem->addF32(var_name, valueF32); + return TRUE; + break; + case MVT_F64: + if((stream >> valueF64).fail()) + return FALSE; + gMessageSystem->addF64(var_name, valueF64); + return TRUE; + break; + case MVT_LLVector3: + LLStringUtil::trim(input); + if(input.substr(0, 1) != "<" || input.substr(input.length() - 1, 1) != ">") + return FALSE; + tokens = split(input.substr(1, input.length() - 2), ","); + if(tokens.size() != 3) + return FALSE; + for(int i = 0; i < 3; i++) + { + stream.clear(); + stream.str(tokens[i]); + if((stream >> valueF32).fail()) + return FALSE; + valueVector3.mV[i] = valueF32; + } + gMessageSystem->addVector3(var_name, valueVector3); + return TRUE; + break; + case MVT_LLVector3d: + LLStringUtil::trim(input); + if(input.substr(0, 1) != "<" || input.substr(input.length() - 1, 1) != ">") + return FALSE; + tokens = split(input.substr(1, input.length() - 2), ","); + if(tokens.size() != 3) + return FALSE; + for(int i = 0; i < 3; i++) + { + stream.clear(); + stream.str(tokens[i]); + if((stream >> valueF64).fail()) + return FALSE; + valueVector3d.mdV[i] = valueF64; + } + gMessageSystem->addVector3d(var_name, valueVector3d); + return TRUE; + break; + case MVT_LLVector4: + LLStringUtil::trim(input); + if(input.substr(0, 1) != "<" || input.substr(input.length() - 1, 1) != ">") + return FALSE; + tokens = split(input.substr(1, input.length() - 2), ","); + if(tokens.size() != 4) + return FALSE; + for(int i = 0; i < 4; i++) + { + stream.clear(); + stream.str(tokens[i]); + if((stream >> valueF32).fail()) + return FALSE; + valueVector4.mV[i] = valueF32; + } + gMessageSystem->addVector4(var_name, valueVector4); + return TRUE; + break; + case MVT_LLQuaternion: + LLStringUtil::trim(input); + if(input.substr(0, 1) != "<" || input.substr(input.length() - 1, 1) != ">") + return FALSE; + tokens = split(input.substr(1, input.length() - 2), ","); + if(tokens.size() != 3) + return FALSE; + for(int i = 0; i < 3; i++) + { + stream.clear(); + stream.str(tokens[i]); + if((stream >> valueF32).fail()) + return FALSE; + valueVector3.mV[i] = valueF32; + } + valueQuaternion.unpackFromVector3(valueVector3); + gMessageSystem->addQuat(var_name, valueQuaternion); + return TRUE; + break; + case MVT_LLUUID: + if((stream >> valueLLUUID).fail()) + return FALSE; + gMessageSystem->addUUID(var_name, valueLLUUID); + return TRUE; + break; + case MVT_BOOL: + if(input_lower == "true") + valueBOOL = TRUE; + else if(input_lower == "false") + valueBOOL = FALSE; + else if((stream >> valueBOOL).fail()) + return FALSE; + //gMessageSystem->addBOOL(var_name, valueBOOL); + gMessageSystem->addU8(var_name, (U8)valueBOOL); + return TRUE; + break; + case MVT_IP_ADDR: + if((stream >> valueU32).fail()) + return FALSE; + gMessageSystem->addIPAddr(var_name, valueU32); + return TRUE; + break; + case MVT_IP_PORT: + if((stream >> valueU16).fail()) + return FALSE; + gMessageSystem->addIPPort(var_name, valueU16); + return TRUE; + break; + case MVT_VARIABLE: + if(!hex) + { + char* buffer = new char[input.size() + 1]; + strncpy(buffer, input.c_str(), input.size()); + buffer[input.size()] = '\0'; + gMessageSystem->addBinaryData(var_name, buffer, input.size() + 1); + delete[] buffer; + } + else + gMessageSystem->addBinaryData(var_name, input.c_str(), input.size()); + return TRUE; + break; + case MVT_FIXED: + if(!hex) + { + char* buffer = new char[input.size() + 1]; + strncpy(buffer, input.c_str(), input.size()); + buffer[input.size()] = '\0'; + gMessageSystem->addBinaryData(var_name, buffer, input.size()); + delete[] buffer; + } + else + gMessageSystem->addBinaryData(var_name, input.c_str(), input.size()); + return TRUE; + break; + default: + break; + } + return FALSE; +} +// static +void LLFloaterMessageBuilder::onCommitPacketCombo(LLUICtrl* ctrl, void* user_data) +{ + LLFloaterMessageBuilder* floaterp = (LLFloaterMessageBuilder*)user_data; + LLViewerObject* selected_objectp = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); + LLParcel* agent_parcelp = LLViewerParcelMgr::getInstance()->getAgentParcel(); + std::string message = ctrl->getValue(); + std::map::iterator template_iter; + template_iter = gMessageSystem->mMessageTemplates.find( LLMessageStringTable::getInstance()->getString(message.c_str()) ); + if(template_iter == gMessageSystem->mMessageTemplates.end()) + { + floaterp->childSetText("message_edit", std::string("")); + return; + } + std::string text(llformat((*template_iter).second->getTrust() == MT_NOTRUST ? "out %s\n" : "in %s\n", message.c_str())); + LLMessageTemplate* temp = (*template_iter).second; + LLMessageTemplate::message_block_map_t::iterator blocks_end = temp->mMemberBlocks.end(); + for (LLMessageTemplate::message_block_map_t::iterator blocks_iter = temp->mMemberBlocks.begin(); + blocks_iter != blocks_end; ++blocks_iter) + { + LLMessageBlock* block = (*blocks_iter); + const char* block_name = block->mName; + std::string block_name_string = std::string(block_name); + S32 num_blocks = 1; + if(block->mType == MBT_MULTIPLE) + num_blocks = block->mNumber; + else if(("ObjectLink" == message && "ObjectData" == block_name_string)) + num_blocks = 2; + for(S32 i = 0; i < num_blocks; i++) + { + text.append(llformat("[%s]\n", block_name)); + LLMessageBlock::message_variable_map_t::iterator var_end = block->mMemberVariables.end(); + for (LLMessageBlock::message_variable_map_t::iterator var_iter = block->mMemberVariables.begin(); + var_iter != var_end; ++var_iter) + { + LLMessageVariable* variable = (*var_iter); + const char* var_name = variable->getName(); + std::string var_name_string = std::string(var_name); + text.append(llformat("%s = ", var_name)); + std::string value(""); + S32 size = variable->getSize(); + switch(variable->getType()) + { + case MVT_U8: + case MVT_U16: + case MVT_U32: + case MVT_U64: + case MVT_S8: + case MVT_S16: + case MVT_S32: + case MVT_IP_ADDR: + case MVT_IP_PORT: + if("RegionHandle" == var_name_string || "Handle" == var_name_string) + value = "$RegionHandle"; + else if("CircuitCode" == var_name_string || "ViewerCircuitCode" == var_name_string + || ("Code" == var_name_string && "CircuitCode" == block_name_string) ) + { + value = "$CircuitCode"; + } + else if(selected_objectp && + ( + "ObjectLocalID" == var_name_string + || "TaskLocalID" == var_name_string + || ("LocalID" == var_name_string && + ( + "ObjectData" == block_name_string + || "UpdateData" == block_name_string + || "InventoryData" == block_name_string + ) + ) + ) + ) + { + std::stringstream temp_stream; + temp_stream << selected_objectp->getLocalID(); + value = temp_stream.str(); + } + else if( agent_parcelp && + "LocalID" == var_name_string && + ( + "ParcelData" == block_name_string + || message.find("Parcel") != message.npos + ) + ) + { + std::stringstream temp_stream; + temp_stream << agent_parcelp->getLocalID(); + value = temp_stream.str(); + } + else if("PCode" == var_name_string) + value = "9"; + else if("PathCurve" == var_name_string) + value = "16"; + else if("ProfileCurve" == var_name_string) + value = "1"; + else if("PathScaleX" == var_name_string || "PathScaleY" == var_name_string) + value = "100"; + else if("BypassRaycast" == var_name_string) + value = "1"; + else + value = "0"; + break; + case MVT_F32: + case MVT_F64: + value = "0.0"; + break; + case MVT_LLVector3: + case MVT_LLVector3d: + case MVT_LLQuaternion: + if("Position" == var_name_string || "RayStart" == var_name_string || "RayEnd" == var_name_string) + value = "$Position"; + else if("Scale" == var_name_string) + value = "<0.5, 0.5, 0.5>"; + else + value = "<0, 0, 0>"; + break; + case MVT_LLVector4: + value = "<0, 0, 0, 0>"; + break; + case MVT_LLUUID: + if("AgentID" == var_name_string) + value = "$AgentID"; + else if("SessionID" == var_name_string) + value = "$SessionID"; + else if("ObjectID" == var_name_string && selected_objectp) + value = selected_objectp->getID().asString(); + else if("ParcelID" == var_name_string && agent_parcelp) + value = agent_parcelp->getID().asString(); + else + value = "00000000-0000-0000-0000-000000000000"; + break; + case MVT_BOOL: + value = "false"; + break; + case MVT_VARIABLE: + value = "Hello, world!"; + break; + case MVT_FIXED: + for(S32 si = 0; si < size; si++) + //value.append(std::string("0123456789abcdef").substr(si & 0xf, 1)); + value.append("a"); + break; + default: + value = ""; + break; + } + text.append(llformat("%s\n", value.c_str())); + } + } + } + text = text.substr(0, text.length() - 1); + floaterp->childSetText("message_edit", text); +} +// static +void LLFloaterMessageBuilder::onClickSend(void* user_data) +{ + LLFloaterMessageBuilder* floaterp = (LLFloaterMessageBuilder*)user_data; + std::vector lines = split(floaterp->childGetText("message_edit"), "\n"); + if(!lines.size()) + { + LLFloaterChat::addChat(LLChat("Not enough information :O")); + return; + } + std::vector tokens = split(lines[0], " "); + if(!tokens.size()) + { + LLFloaterChat::addChat(LLChat("Not enough information :O")); + return; + } + std::string dir_str = tokens[0]; + LLStringUtil::toLower(dir_str); + // Direction + BOOL outgoing; + if(dir_str == "out") + outgoing = TRUE; + else if(dir_str == "in") + outgoing = FALSE; + else + { + LLFloaterChat::addChat(LLChat("Expected direction 'in' or 'out'")); + return; + } + // Message + std::string message = "Invalid"; + if(tokens.size() > 1) + { + if(tokens.size() > 2) + { + LLFloaterChat::addChat(LLChat("Unexpected extra stuff at the top")); + return; + } + message = tokens[1]; + LLStringUtil::trim(message); + } + // Body + std::vector parts; + if(lines.size() > 1) + { + std::vector::iterator line_end = lines.end(); + std::vector::iterator line_iter = lines.begin(); + ++line_iter; + std::string current_block(""); + int current_block_index = -1; + for( ; line_iter != line_end; ++line_iter) + { + std::string line = (*line_iter); + LLStringUtil::trim(line); + if(!line.length()) + continue; + if(line.substr(0, 1) == "[" && line.substr(line.size() - 1, 1) == "]") + { + current_block = line.substr(1, line.length() - 2); + LLStringUtil::trim(current_block); + ++current_block_index; + parts_block pb; + pb.name = current_block; + parts.push_back(pb); + } + else + { + if(current_block.empty()) + { + LLFloaterChat::addChat(LLChat("Unexpected field when no block yet")); + return; + } + int eqpos = line.find("="); + if(eqpos == line.npos) + { + LLFloaterChat::addChat(LLChat("Missing an equal sign")); + return; + } + std::string field = line.substr(0, eqpos); + LLStringUtil::trim(field); + if(!field.length()) + { + LLFloaterChat::addChat(LLChat("Missing name of field")); + return; + } + std::string value = line.substr(eqpos + 1); + LLStringUtil::trim(value); + parts_var pv; + if(value.substr(0, 1) == "|") + { + pv.hex = TRUE; + value = value.substr(1); + LLStringUtil::trim(value); + } + else + pv.hex = FALSE; + pv.name = field; + pv.value = value; + parts[current_block_index].vars.push_back(pv); + } + } + } + // Verification + std::map::iterator template_iter; + template_iter = gMessageSystem->mMessageTemplates.find( LLMessageStringTable::getInstance()->getString(message.c_str()) ); + if(template_iter == gMessageSystem->mMessageTemplates.end()) + { + LLFloaterChat::addChat(LLChat(llformat("Don't know how to build a '%s' message", message.c_str()))); + return; + } + LLMessageTemplate* temp = (*template_iter).second; + std::vector::iterator parts_end = parts.end(); + std::vector::iterator parts_iter = parts.begin(); + LLMessageTemplate::message_block_map_t::iterator blocks_end = temp->mMemberBlocks.end(); + for (LLMessageTemplate::message_block_map_t::iterator blocks_iter = temp->mMemberBlocks.begin(); + blocks_iter != blocks_end; ) + { + LLMessageBlock* block = (*blocks_iter); + const char* block_name = block->mName; + if(parts_iter == parts_end) + { + if(block->mType != MBT_VARIABLE) + LLFloaterChat::addChat(LLChat(llformat("Expected '%s' block", block_name))); + else + { + ++blocks_iter; + continue; + } + return; + } + else if((*parts_iter).name != block_name) + { + if(block->mType != MBT_VARIABLE) + LLFloaterChat::addChat(LLChat(llformat("Expected '%s' block", block_name))); + else + { + ++blocks_iter; + continue; + } + return; + } + std::vector::iterator part_var_end = (*parts_iter).vars.end(); + std::vector::iterator part_var_iter = (*parts_iter).vars.begin(); + LLMessageBlock::message_variable_map_t::iterator var_end = block->mMemberVariables.end(); + for (LLMessageBlock::message_variable_map_t::iterator var_iter = block->mMemberVariables.begin(); + var_iter != var_end; ++var_iter) + { + LLMessageVariable* variable = (*var_iter); + const char* var_name = variable->getName(); + if(part_var_iter == part_var_end) + { + LLFloaterChat::addChat(LLChat(llformat("Expected '%s' field under '%s' block", var_name, block_name))); + return; + } + else if((*part_var_iter).name != var_name) + { + LLFloaterChat::addChat(LLChat(llformat("Expected '%s' field under '%s' block", var_name, block_name))); + return; + } + (*part_var_iter).var_type = variable->getType(); + ++part_var_iter; + } + if(part_var_iter != part_var_end) + { + LLFloaterChat::addChat(LLChat(llformat("Unexpected field(s) at end of '%s' block", block_name))); + return; + } + ++parts_iter; + // test + if((block->mType != MBT_SINGLE) && (parts_iter != parts_end) && ((*parts_iter).name == block_name)) + { + // block will repeat + } + else ++blocks_iter; + } + if(parts_iter != parts_end) + { + LLFloaterChat::addChat(LLChat("Unexpected block(s) at end")); + return; + } + // Build and send + if(outgoing) + { + gMessageSystem->newMessage( message.c_str() ); + for(parts_iter = parts.begin(); parts_iter != parts_end; ++parts_iter) + { + const char* block_name = (*parts_iter).name.c_str(); + gMessageSystem->nextBlock(block_name); + std::vector::iterator part_var_end = (*parts_iter).vars.end(); + for(std::vector::iterator part_var_iter = (*parts_iter).vars.begin(); + part_var_iter != part_var_end; ++part_var_iter) + { + parts_var pv = (*part_var_iter); + if(!addField(pv.var_type, pv.name.c_str(), pv.value, pv.hex)) + { + 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))); + gMessageSystem->clearMessage(); + return; + } + } + } + + LLScrollListCtrl* scrollp = floaterp->getChild("net_list"); + LLScrollListItem* selected_itemp = scrollp->getFirstSelected(); + + //if a specific circuit is selected, send it to that, otherwise send it to the current sim + if(selected_itemp) + { + LLNetListItem* itemp = findNetListItem(selected_itemp->getUUID()); + LLScrollListText* textColumn = (LLScrollListText*)selected_itemp->getColumn(1); + + //why would you send data through a dead circuit? + if(textColumn->getValue().asString() == "Dead") + { + LLFloaterChat::addChat(LLChat("No sending messages through dead circuits!")); + return; + } + + gMessageSystem->sendMessage(itemp->mCircuitData->getHost()); + } else { + gMessageSystem->sendMessage(gAgent.getRegionHost()); + } + } + else + { + LLFloaterChat::addChat(LLChat("Incoming message isn't supported yet :(")); + return; + } +} +BOOL LLFloaterMessageBuilder::handleKeyHere(KEY key, MASK mask) +{ + if(key == KEY_RETURN && (mask & MASK_CONTROL)) + { + onClickSend(this); + return TRUE; + } + if(key == KEY_ESCAPE) + { + releaseFocus(); + return TRUE; + } + return FALSE; +} +// diff --git a/indra/newview/llfloatermessagebuilder.h b/indra/newview/llfloatermessagebuilder.h index 65b040420..5dc9b4297 100644 --- a/indra/newview/llfloatermessagebuilder.h +++ b/indra/newview/llfloatermessagebuilder.h @@ -1,32 +1,55 @@ -// ] -#ifndef LL_LLFLOATERMESSAGEBUILDER_H -#define LL_LLFLOATERMESSAGEBUILDER_H -#include "llfloater.h" -class LLFloaterMessageBuilder : public LLFloater -{ -public: - LLFloaterMessageBuilder(std::string initial_text); - ~LLFloaterMessageBuilder(); - static void show(std::string initial_text); - BOOL postBuild(); - static BOOL addField(e_message_variable_type var_type, const char* var_name, std::string input, BOOL hex); - static void onClickSend(void* user_data); - static void onCommitPacketCombo(LLUICtrl* ctrl, void* user_data); - static LLFloaterMessageBuilder* sInstance; - BOOL handleKeyHere(KEY key, MASK mask); - std::string mInitialText; - struct parts_var - { - std::string name; - std::string value; - BOOL hex; - e_message_variable_type var_type; - }; - struct parts_block - { - std::string name; - std::vector vars; - }; -}; -#endif -// +// ] +#ifndef LL_LLFLOATERMESSAGEBUILDER_H +#define LL_LLFLOATERMESSAGEBUILDER_H +#include "llfloater.h" +#include "lltemplatemessagereader.h" +#include "llmessagelog.h" + +class LLNetListItem +{ +public: + LLNetListItem(LLUUID id); + LLUUID mID; + BOOL mAutoName; + std::string mName; + std::string mPreviousRegionName; + LLCircuitData* mCircuitData; +}; + +class LLFloaterMessageBuilder : public LLFloater, public LLEventTimer +{ +public: + LLFloaterMessageBuilder(std::string initial_text); + ~LLFloaterMessageBuilder(); + static void show(std::string initial_text); + static std::list sNetListItems; + BOOL postBuild(); + BOOL tick(); + static BOOL addField(e_message_variable_type var_type, const char* var_name, std::string input, BOOL hex); + static void onClickSend(void* user_data); + static void onCommitPacketCombo(LLUICtrl* ctrl, void* user_data); + static LLFloaterMessageBuilder* sInstance; + BOOL handleKeyHere(KEY key, MASK mask); + std::string mInitialText; + struct parts_var + { + std::string name; + std::string value; + BOOL hex; + e_message_variable_type var_type; + }; + struct parts_block + { + std::string name; + std::vector vars; + }; + static LLNetListItem* findNetListItem(LLHost host); + static LLNetListItem* findNetListItem(LLUUID id); + void refreshNetList(); + enum ENetInfoMode { NI_NET, NI_LOG }; + ENetInfoMode mNetInfoMode; + static void onCommitMessageLog(LLUICtrl* ctrl, void* user_data); + static void onCommitFilter(LLUICtrl* ctrl, void* user_data); +}; +#endif +// diff --git a/indra/newview/llfloatermessagelog.cpp b/indra/newview/llfloatermessagelog.cpp index 38d6f031b..357495ca3 100644 --- a/indra/newview/llfloatermessagelog.cpp +++ b/indra/newview/llfloatermessagelog.cpp @@ -13,17 +13,6 @@ #include "llfloatermessagebuilder.h" #include "llagent.h" //////////////////////////////// -// LLNetListItem -//////////////////////////////// -LLNetListItem::LLNetListItem(LLUUID id) -: mID(id), - mAutoName(TRUE), - mName("No name"), - mPreviousRegionName(""), - mCircuitData(NULL) -{ -} -//////////////////////////////// // LLFloaterMessageLogItem //////////////////////////////// #define MAX_PACKET_LEN (0x2000) @@ -619,7 +608,7 @@ void LLFloaterMessageLog::refreshNetList() LLSD& text_column = element["columns"][0]; text_column["column"] = "text"; text_column["value"] = itemp->mName + (itemp->mCircuitData->getHost() == gAgent.getRegionHost() ? " (main)" : ""); - for(int i = 0; i < 3; i++) + for(int i = 0; i < 2; i++) { LLSD& icon_column = element["columns"][i + 1]; icon_column["column"] = llformat("icon%d", i); @@ -630,18 +619,18 @@ void LLFloaterMessageLog::refreshNetList() BOOL has_live_circuit = itemp->mCircuitData && itemp->mCircuitData->isAlive(); if(has_live_circuit) { - LLScrollListIcon* icon = (LLScrollListIcon*)scroll_itemp->getColumn(2); + LLScrollListIcon* icon = (LLScrollListIcon*)scroll_itemp->getColumn(1); icon->setValue("icon_net_close_circuit.tga"); icon->setClickCallback(onClickCloseCircuit, itemp); } else { - LLScrollListIcon* icon = (LLScrollListIcon*)scroll_itemp->getColumn(2); + LLScrollListIcon* icon = (LLScrollListIcon*)scroll_itemp->getColumn(1); icon->setValue("icon_net_close_circuit_gray.tga"); icon->setClickCallback(NULL, NULL); } // Event queue isn't even supported yet... FIXME - LLScrollListIcon* icon = (LLScrollListIcon*)scroll_itemp->getColumn(3); + LLScrollListIcon* icon = (LLScrollListIcon*)scroll_itemp->getColumn(2); icon->setValue("icon_net_close_eventpoll_gray.tga"); icon->setClickCallback(NULL, NULL); } diff --git a/indra/newview/llfloatermessagelog.h b/indra/newview/llfloatermessagelog.h index b87ffaa6f..82d82f772 100644 --- a/indra/newview/llfloatermessagelog.h +++ b/indra/newview/llfloatermessagelog.h @@ -2,16 +2,8 @@ #include "llfloater.h" #include "llmessagelog.h" #include "lltemplatemessagereader.h" -class LLNetListItem -{ -public: - LLNetListItem(LLUUID id); - LLUUID mID; - BOOL mAutoName; - std::string mName; - std::string mPreviousRegionName; - LLCircuitData* mCircuitData; -}; +#include "llfloatermessagebuilder.h" + class LLFloaterMessageLogItem : public LLMessageLogEntry { public: diff --git a/indra/newview/skins/default/xui/en-us/floater_message_builder.xml b/indra/newview/skins/default/xui/en-us/floater_message_builder.xml index 41c58a542..c7c49d839 100755 --- a/indra/newview/skins/default/xui/en-us/floater_message_builder.xml +++ b/indra/newview/skins/default/xui/en-us/floater_message_builder.xml @@ -3,9 +3,7 @@ - - - + diff --git a/indra/newview/skins/default/xui/en-us/floater_message_log.xml b/indra/newview/skins/default/xui/en-us/floater_message_log.xml index 40dc09f21..e1ebfe2f1 100755 --- a/indra/newview/skins/default/xui/en-us/floater_message_log.xml +++ b/indra/newview/skins/default/xui/en-us/floater_message_log.xml @@ -5,7 +5,6 @@ -