diff options
Diffstat (limited to '')
-rw-r--r-- | linden/indra/newview/llfloatermessagebuilder.cpp | 978 |
1 files changed, 978 insertions, 0 deletions
diff --git a/linden/indra/newview/llfloatermessagebuilder.cpp b/linden/indra/newview/llfloatermessagebuilder.cpp new file mode 100644 index 0000000..90c0f9e --- /dev/null +++ b/linden/indra/newview/llfloatermessagebuilder.cpp | |||
@@ -0,0 +1,978 @@ | |||
1 | // <edit> | ||
2 | #include "llviewerprecompiledheaders.h" | ||
3 | #include "llfloatermessagebuilder.h" | ||
4 | #include "lluictrlfactory.h" | ||
5 | #include "llmessagetemplate.h" | ||
6 | #include "llagent.h" | ||
7 | #include "llchat.h" | ||
8 | #include "llfloaterchat.h" | ||
9 | #include "llviewerregion.h" // getHandle | ||
10 | #include "llcombobox.h" | ||
11 | #include "llselectmgr.h" // fill in stuff about selected object | ||
12 | #include "llparcel.h" | ||
13 | #include "llviewerparcelmgr.h" // same for parcel | ||
14 | #include "llscrolllistctrl.h" | ||
15 | #include "llworld.h" | ||
16 | #include "lltemplatemessagebuilder.h" | ||
17 | |||
18 | //////////////////////////////// | ||
19 | // LLNetListItem | ||
20 | //////////////////////////////// | ||
21 | LLNetListItem::LLNetListItem(LLUUID id) | ||
22 | : mID(id), | ||
23 | mAutoName(TRUE), | ||
24 | mName("No name"), | ||
25 | mPreviousRegionName(""), | ||
26 | mCircuitData(NULL) | ||
27 | { | ||
28 | } | ||
29 | |||
30 | //////////////////////////////// | ||
31 | // LLFloaterMessageBuilder | ||
32 | //////////////////////////////// | ||
33 | std::list<LLNetListItem*> LLFloaterMessageBuilder::sNetListItems; | ||
34 | |||
35 | LLFloaterMessageBuilder::LLFloaterMessageBuilder(std::string initial_text) | ||
36 | : LLFloater(), | ||
37 | LLEventTimer(1.0f), | ||
38 | mNetInfoMode(NI_NET), | ||
39 | mInitialText(initial_text) | ||
40 | { | ||
41 | LLUICtrlFactory::getInstance()->buildFloater(this, "floater_message_builder.xml"); | ||
42 | } | ||
43 | LLFloaterMessageBuilder::~LLFloaterMessageBuilder() | ||
44 | { | ||
45 | } | ||
46 | void LLFloaterMessageBuilder::show(std::string initial_text) | ||
47 | { | ||
48 | (new LLFloaterMessageBuilder(initial_text))->open(); | ||
49 | } | ||
50 | BOOL LLFloaterMessageBuilder::tick() | ||
51 | { | ||
52 | refreshNetList(); | ||
53 | return FALSE; | ||
54 | } | ||
55 | LLNetListItem* LLFloaterMessageBuilder::findNetListItem(LLHost host) | ||
56 | { | ||
57 | std::list<LLNetListItem*>::iterator end = sNetListItems.end(); | ||
58 | for(std::list<LLNetListItem*>::iterator iter = sNetListItems.begin(); iter != end; ++iter) | ||
59 | if((*iter)->mCircuitData && (*iter)->mCircuitData->getHost() == host) | ||
60 | return (*iter); | ||
61 | return NULL; | ||
62 | } | ||
63 | LLNetListItem* LLFloaterMessageBuilder::findNetListItem(LLUUID id) | ||
64 | { | ||
65 | std::list<LLNetListItem*>::iterator end = sNetListItems.end(); | ||
66 | for(std::list<LLNetListItem*>::iterator iter = sNetListItems.begin(); iter != end; ++iter) | ||
67 | if((*iter)->mID == id) | ||
68 | return (*iter); | ||
69 | return NULL; | ||
70 | } | ||
71 | void LLFloaterMessageBuilder::refreshNetList() | ||
72 | { | ||
73 | LLScrollListCtrl* scrollp = getChild<LLScrollListCtrl>("net_list"); | ||
74 | // Update circuit data of net list items | ||
75 | std::vector<LLCircuitData*> circuits = gMessageSystem->getCircuit()->getCircuitDataList(); | ||
76 | std::vector<LLCircuitData*>::iterator circuits_end = circuits.end(); | ||
77 | for(std::vector<LLCircuitData*>::iterator iter = circuits.begin(); iter != circuits_end; ++iter) | ||
78 | { | ||
79 | LLNetListItem* itemp = findNetListItem((*iter)->getHost()); | ||
80 | if(!itemp) | ||
81 | { | ||
82 | LLUUID id; id.generate(); | ||
83 | itemp = new LLNetListItem(id); | ||
84 | sNetListItems.push_back(itemp); | ||
85 | } | ||
86 | itemp->mCircuitData = (*iter); | ||
87 | } | ||
88 | // Clear circuit data of items whose circuits are gone | ||
89 | std::list<LLNetListItem*>::iterator items_end = sNetListItems.end(); | ||
90 | for(std::list<LLNetListItem*>::iterator iter = sNetListItems.begin(); iter != items_end; ++iter) | ||
91 | { | ||
92 | if(std::find(circuits.begin(), circuits.end(), (*iter)->mCircuitData) == circuits.end()) | ||
93 | (*iter)->mCircuitData = NULL; | ||
94 | } | ||
95 | // Remove net list items that are totally useless now | ||
96 | for(std::list<LLNetListItem*>::iterator iter = sNetListItems.begin(); iter != sNetListItems.end();) | ||
97 | { | ||
98 | if((*iter)->mCircuitData == NULL) | ||
99 | iter = sNetListItems.erase(iter); | ||
100 | else ++iter; | ||
101 | } | ||
102 | // Update names of net list items | ||
103 | items_end = sNetListItems.end(); | ||
104 | for(std::list<LLNetListItem*>::iterator iter = sNetListItems.begin(); iter != items_end; ++iter) | ||
105 | { | ||
106 | LLNetListItem* itemp = (*iter); | ||
107 | if(itemp->mAutoName) | ||
108 | { | ||
109 | if(itemp->mCircuitData) | ||
110 | { | ||
111 | LLViewerRegion* regionp = LLWorld::getInstance()->getRegion(itemp->mCircuitData->getHost()); | ||
112 | if(regionp) | ||
113 | { | ||
114 | std::string name = regionp->getName(); | ||
115 | if(name == "") name = llformat("%s (awaiting region name)", itemp->mCircuitData->getHost().getString().c_str()); | ||
116 | itemp->mName = name; | ||
117 | itemp->mPreviousRegionName = name; | ||
118 | } | ||
119 | else | ||
120 | { | ||
121 | itemp->mName = itemp->mCircuitData->getHost().getString(); | ||
122 | if(itemp->mPreviousRegionName != "") | ||
123 | itemp->mName.append(llformat(" (was %s)", itemp->mPreviousRegionName.c_str())); | ||
124 | } | ||
125 | } | ||
126 | else | ||
127 | { | ||
128 | // an item just for an event queue, not handled yet | ||
129 | itemp->mName = "Something else"; | ||
130 | } | ||
131 | } | ||
132 | } | ||
133 | // Rebuild scroll list from scratch | ||
134 | LLUUID selected_id = scrollp->getFirstSelected() ? scrollp->getFirstSelected()->getUUID() : LLUUID::null; | ||
135 | S32 scroll_pos = scrollp->getScrollPos(); | ||
136 | scrollp->clearRows(); | ||
137 | for(std::list<LLNetListItem*>::iterator iter = sNetListItems.begin(); iter != items_end; ++iter) | ||
138 | { | ||
139 | LLNetListItem* itemp = (*iter); | ||
140 | LLSD element; | ||
141 | element["id"] = itemp->mID; | ||
142 | LLSD& text_column = element["columns"][0]; | ||
143 | text_column["column"] = "text"; | ||
144 | text_column["value"] = itemp->mName + (itemp->mCircuitData->getHost() == gAgent.getRegionHost() ? " (main)" : ""); | ||
145 | |||
146 | LLSD& state_column = element["columns"][ 1]; | ||
147 | state_column["column"] = "state"; | ||
148 | state_column["value"] = ""; | ||
149 | |||
150 | LLScrollListItem* scroll_itemp = scrollp->addElement(element); | ||
151 | BOOL has_live_circuit = itemp->mCircuitData && itemp->mCircuitData->isAlive(); | ||
152 | |||
153 | LLScrollListText* state = (LLScrollListText*)scroll_itemp->getColumn(1); | ||
154 | |||
155 | if(has_live_circuit) | ||
156 | state->setText(std::string("Alive")); | ||
157 | else | ||
158 | state->setText(std::string("Alive")); | ||
159 | } | ||
160 | if(selected_id.notNull()) scrollp->selectByID(selected_id); | ||
161 | if(scroll_pos < scrollp->getItemCount()) scrollp->setScrollPos(scroll_pos); | ||
162 | } | ||
163 | BOOL LLFloaterMessageBuilder::postBuild() | ||
164 | { | ||
165 | childSetText("message_edit", mInitialText); | ||
166 | childSetAction("send_btn", onClickSend, this); | ||
167 | std::vector<std::string> names; | ||
168 | LLComboBox* combo; | ||
169 | LLMessageSystem::message_template_name_map_t::iterator temp_end = gMessageSystem->mMessageTemplates.end(); | ||
170 | LLMessageSystem::message_template_name_map_t::iterator temp_iter; | ||
171 | std::vector<std::string>::iterator names_end; | ||
172 | std::vector<std::string>::iterator names_iter; | ||
173 | for(temp_iter = gMessageSystem->mMessageTemplates.begin(); temp_iter != temp_end; ++temp_iter) | ||
174 | if((*temp_iter).second->getTrust() == MT_NOTRUST) | ||
175 | names.push_back((*temp_iter).second->mName); | ||
176 | std::sort(names.begin(), names.end()); | ||
177 | combo = getChild<LLComboBox>("untrusted_message_combo"); | ||
178 | names_end = names.end(); | ||
179 | for(names_iter = names.begin(); names_iter != names_end; ++names_iter) | ||
180 | combo->add((*names_iter)); | ||
181 | names.clear(); | ||
182 | for(temp_iter = gMessageSystem->mMessageTemplates.begin(); temp_iter != temp_end; ++temp_iter) | ||
183 | if((*temp_iter).second->getTrust() == MT_TRUST) | ||
184 | names.push_back((*temp_iter).second->mName); | ||
185 | std::sort(names.begin(), names.end()); | ||
186 | combo = getChild<LLComboBox>("trusted_message_combo"); | ||
187 | names_end = names.end(); | ||
188 | for(names_iter = names.begin(); names_iter != names_end; ++names_iter) | ||
189 | combo->add((*names_iter)); | ||
190 | childSetCommitCallback("untrusted_message_combo", onCommitPacketCombo, this); | ||
191 | childSetCommitCallback("trusted_message_combo", onCommitPacketCombo, this); | ||
192 | return TRUE; | ||
193 | } | ||
194 | inline std::vector<std::string> split(std::string input, std::string separator) | ||
195 | { | ||
196 | S32 size = input.length(); | ||
197 | char* buffer = new char[size + 1]; | ||
198 | strncpy(buffer, input.c_str(), size); | ||
199 | buffer[size] = '\0'; | ||
200 | std::vector<std::string> lines; | ||
201 | char* result = strtok(buffer, separator.c_str()); | ||
202 | while(result) | ||
203 | { | ||
204 | lines.push_back(result); | ||
205 | result = strtok(NULL, separator.c_str()); | ||
206 | } | ||
207 | delete[] buffer; | ||
208 | return lines; | ||
209 | } | ||
210 | std::string mvtstr(e_message_variable_type var_type) | ||
211 | { | ||
212 | switch(var_type) | ||
213 | { | ||
214 | case MVT_U8: | ||
215 | return "U8"; | ||
216 | break; | ||
217 | case MVT_U16: | ||
218 | return "U16"; | ||
219 | break; | ||
220 | case MVT_U32: | ||
221 | return "U32"; | ||
222 | break; | ||
223 | case MVT_U64: | ||
224 | return "U64"; | ||
225 | break; | ||
226 | case MVT_S8: | ||
227 | return "S8"; | ||
228 | break; | ||
229 | case MVT_S16: | ||
230 | return "S16"; | ||
231 | break; | ||
232 | case MVT_S32: | ||
233 | return "S32"; | ||
234 | break; | ||
235 | case MVT_S64: | ||
236 | return "S64"; | ||
237 | break; | ||
238 | case MVT_F32: | ||
239 | return "F32"; | ||
240 | break; | ||
241 | case MVT_F64: | ||
242 | return "F64"; | ||
243 | break; | ||
244 | case MVT_LLVector3: | ||
245 | return "LLVector3"; | ||
246 | break; | ||
247 | case MVT_LLVector3d: | ||
248 | return "LLVector3d"; | ||
249 | break; | ||
250 | case MVT_LLVector4: | ||
251 | return "LLVector4"; | ||
252 | break; | ||
253 | case MVT_LLQuaternion: | ||
254 | return "LLQuaternion"; | ||
255 | break; | ||
256 | case MVT_LLUUID: | ||
257 | return "LLUUID"; | ||
258 | break; | ||
259 | case MVT_BOOL: | ||
260 | return "BOOL"; | ||
261 | break; | ||
262 | case MVT_IP_ADDR: | ||
263 | return "IPADDR"; | ||
264 | break; | ||
265 | case MVT_IP_PORT: | ||
266 | return "IPPORT"; | ||
267 | break; | ||
268 | case MVT_VARIABLE: | ||
269 | return "Variable"; | ||
270 | break; | ||
271 | case MVT_FIXED: | ||
272 | return "Fixed"; | ||
273 | break; | ||
274 | default: | ||
275 | return "Missingno."; | ||
276 | break; | ||
277 | } | ||
278 | } | ||
279 | // static | ||
280 | BOOL LLFloaterMessageBuilder::addField(e_message_variable_type var_type, const char* var_name, std::string input, BOOL hex) | ||
281 | { | ||
282 | LLStringUtil::trim(input); | ||
283 | if(input.length() < 1 && var_type != MVT_VARIABLE) | ||
284 | return FALSE; | ||
285 | U8 valueU8; | ||
286 | U16 valueU16; | ||
287 | U32 valueU32; | ||
288 | U64 valueU64; | ||
289 | S8 valueS8; | ||
290 | S16 valueS16; | ||
291 | S32 valueS32; | ||
292 | // S64 valueS64; | ||
293 | F32 valueF32; | ||
294 | F64 valueF64; | ||
295 | LLVector3 valueVector3; | ||
296 | LLVector3d valueVector3d; | ||
297 | LLVector4 valueVector4; | ||
298 | LLQuaternion valueQuaternion; | ||
299 | LLUUID valueLLUUID; | ||
300 | BOOL valueBOOL; | ||
301 | std::string input_lower = input; | ||
302 | LLStringUtil::toLower(input_lower); | ||
303 | if(input_lower == "$agentid") | ||
304 | input = gAgent.getID().asString(); | ||
305 | else if(input_lower == "$sessionid") | ||
306 | input = gAgent.getSessionID().asString(); | ||
307 | else if(input_lower == "$uuid") | ||
308 | { | ||
309 | LLUUID id; | ||
310 | id.generate(); | ||
311 | input = id.asString(); | ||
312 | } | ||
313 | else if(input_lower == "$circuitcode") | ||
314 | { | ||
315 | std::stringstream temp_stream; | ||
316 | temp_stream << gMessageSystem->mOurCircuitCode; | ||
317 | input = temp_stream.str(); | ||
318 | } | ||
319 | else if(input_lower == "$regionhandle") | ||
320 | { | ||
321 | std::stringstream temp_stream; | ||
322 | temp_stream << (gAgent.getRegion() ? gAgent.getRegion()->getHandle() : 0); | ||
323 | input = temp_stream.str(); | ||
324 | } | ||
325 | else if(input_lower == "$position" || input_lower == "$pos") | ||
326 | { | ||
327 | std::stringstream temp_stream; | ||
328 | valueVector3 = gAgent.getPositionAgent(); | ||
329 | temp_stream << "<" << valueVector3[0] << ", " << valueVector3[1] << ", " << valueVector3[2] << ">"; | ||
330 | input = temp_stream.str(); | ||
331 | } | ||
332 | if(hex) | ||
333 | { | ||
334 | if(var_type != MVT_VARIABLE && var_type != MVT_FIXED) | ||
335 | return FALSE; | ||
336 | int len = input_lower.length(); | ||
337 | const char* cstr = input_lower.c_str(); | ||
338 | std::string new_input(""); | ||
339 | BOOL nibble = FALSE; | ||
340 | char byte = 0; | ||
341 | for(int i = 0; i < len; i++) | ||
342 | { | ||
343 | char c = cstr[i]; | ||
344 | if(c >= 0x30 && c <= 0x39) | ||
345 | c -= 0x30; | ||
346 | else if(c >= 0x61 && c <= 0x66) | ||
347 | c -= 0x57; | ||
348 | else if(c != 0x20) | ||
349 | return FALSE; | ||
350 | else | ||
351 | continue; | ||
352 | if(!nibble) | ||
353 | byte = c << 4; | ||
354 | else | ||
355 | new_input.push_back(byte | c); | ||
356 | nibble = !nibble; | ||
357 | } | ||
358 | if(nibble) | ||
359 | return FALSE; | ||
360 | input = new_input; | ||
361 | } | ||
362 | std::stringstream stream(input); | ||
363 | std::vector<std::string> tokens; | ||
364 | switch(var_type) | ||
365 | { | ||
366 | case MVT_U8: | ||
367 | if(input.substr(0, 1) == "-") | ||
368 | return FALSE; | ||
369 | if((stream >> valueU32).fail()) | ||
370 | return FALSE; | ||
371 | valueU8 = (U8)valueU32; | ||
372 | gMessageSystem->addU8(var_name, valueU8); | ||
373 | return TRUE; | ||
374 | break; | ||
375 | case MVT_U16: | ||
376 | if(input.substr(0, 1) == "-") | ||
377 | return FALSE; | ||
378 | if((stream >> valueU16).fail()) | ||
379 | return FALSE; | ||
380 | gMessageSystem->addU16(var_name, valueU16); | ||
381 | return TRUE; | ||
382 | break; | ||
383 | case MVT_U32: | ||
384 | if(input.substr(0, 1) == "-") | ||
385 | return FALSE; | ||
386 | if((stream >> valueU32).fail()) | ||
387 | return FALSE; | ||
388 | gMessageSystem->addU32(var_name, valueU32); | ||
389 | return TRUE; | ||
390 | break; | ||
391 | case MVT_U64: | ||
392 | if(input.substr(0, 1) == "-") | ||
393 | return FALSE; | ||
394 | if((stream >> valueU64).fail()) | ||
395 | return FALSE; | ||
396 | gMessageSystem->addU64(var_name, valueU64); | ||
397 | return TRUE; | ||
398 | break; | ||
399 | case MVT_S8: | ||
400 | if((stream >> valueS8).fail()) | ||
401 | return FALSE; | ||
402 | gMessageSystem->addS8(var_name, valueS8); | ||
403 | return TRUE; | ||
404 | break; | ||
405 | case MVT_S16: | ||
406 | if((stream >> valueS16).fail()) | ||
407 | return FALSE; | ||
408 | gMessageSystem->addS16(var_name, valueS16); | ||
409 | return TRUE; | ||
410 | break; | ||
411 | case MVT_S32: | ||
412 | if((stream >> valueS32).fail()) | ||
413 | return FALSE; | ||
414 | gMessageSystem->addS32(var_name, valueS32); | ||
415 | return TRUE; | ||
416 | break; | ||
417 | /* | ||
418 | case MVT_S64: | ||
419 | if((stream >> valueS64).fail()) | ||
420 | return FALSE; | ||
421 | gMessageSystem->addS64(var_name, valueS64); | ||
422 | return TRUE; | ||
423 | break; | ||
424 | */ | ||
425 | case MVT_F32: | ||
426 | if((stream >> valueF32).fail()) | ||
427 | return FALSE; | ||
428 | gMessageSystem->addF32(var_name, valueF32); | ||
429 | return TRUE; | ||
430 | break; | ||
431 | case MVT_F64: | ||
432 | if((stream >> valueF64).fail()) | ||
433 | return FALSE; | ||
434 | gMessageSystem->addF64(var_name, valueF64); | ||
435 | return TRUE; | ||
436 | break; | ||
437 | case MVT_LLVector3: | ||
438 | LLStringUtil::trim(input); | ||
439 | if(input.substr(0, 1) != "<" || input.substr(input.length() - 1, 1) != ">") | ||
440 | return FALSE; | ||
441 | tokens = split(input.substr(1, input.length() - 2), ","); | ||
442 | if(tokens.size() != 3) | ||
443 | return FALSE; | ||
444 | for(int i = 0; i < 3; i++) | ||
445 | { | ||
446 | stream.clear(); | ||
447 | stream.str(tokens[i]); | ||
448 | if((stream >> valueF32).fail()) | ||
449 | return FALSE; | ||
450 | valueVector3.mV[i] = valueF32; | ||
451 | } | ||
452 | gMessageSystem->addVector3(var_name, valueVector3); | ||
453 | return TRUE; | ||
454 | break; | ||
455 | case MVT_LLVector3d: | ||
456 | LLStringUtil::trim(input); | ||
457 | if(input.substr(0, 1) != "<" || input.substr(input.length() - 1, 1) != ">") | ||
458 | return FALSE; | ||
459 | tokens = split(input.substr(1, input.length() - 2), ","); | ||
460 | if(tokens.size() != 3) | ||
461 | return FALSE; | ||
462 | for(int i = 0; i < 3; i++) | ||
463 | { | ||
464 | stream.clear(); | ||
465 | stream.str(tokens[i]); | ||
466 | if((stream >> valueF64).fail()) | ||
467 | return FALSE; | ||
468 | valueVector3d.mdV[i] = valueF64; | ||
469 | } | ||
470 | gMessageSystem->addVector3d(var_name, valueVector3d); | ||
471 | return TRUE; | ||
472 | break; | ||
473 | case MVT_LLVector4: | ||
474 | LLStringUtil::trim(input); | ||
475 | if(input.substr(0, 1) != "<" || input.substr(input.length() - 1, 1) != ">") | ||
476 | return FALSE; | ||
477 | tokens = split(input.substr(1, input.length() - 2), ","); | ||
478 | if(tokens.size() != 4) | ||
479 | return FALSE; | ||
480 | for(int i = 0; i < 4; i++) | ||
481 | { | ||
482 | stream.clear(); | ||
483 | stream.str(tokens[i]); | ||
484 | if((stream >> valueF32).fail()) | ||
485 | return FALSE; | ||
486 | valueVector4.mV[i] = valueF32; | ||
487 | } | ||
488 | gMessageSystem->addVector4(var_name, valueVector4); | ||
489 | return TRUE; | ||
490 | break; | ||
491 | case MVT_LLQuaternion: | ||
492 | LLStringUtil::trim(input); | ||
493 | if(input.substr(0, 1) != "<" || input.substr(input.length() - 1, 1) != ">") | ||
494 | return FALSE; | ||
495 | tokens = split(input.substr(1, input.length() - 2), ","); | ||
496 | if(tokens.size() != 3) | ||
497 | return FALSE; | ||
498 | for(int i = 0; i < 3; i++) | ||
499 | { | ||
500 | stream.clear(); | ||
501 | stream.str(tokens[i]); | ||
502 | if((stream >> valueF32).fail()) | ||
503 | return FALSE; | ||
504 | valueVector3.mV[i] = valueF32; | ||
505 | } | ||
506 | valueQuaternion.unpackFromVector3(valueVector3); | ||
507 | gMessageSystem->addQuat(var_name, valueQuaternion); | ||
508 | return TRUE; | ||
509 | break; | ||
510 | case MVT_LLUUID: | ||
511 | if((stream >> valueLLUUID).fail()) | ||
512 | return FALSE; | ||
513 | gMessageSystem->addUUID(var_name, valueLLUUID); | ||
514 | return TRUE; | ||
515 | break; | ||
516 | case MVT_BOOL: | ||
517 | if(input_lower == "true") | ||
518 | valueBOOL = TRUE; | ||
519 | else if(input_lower == "false") | ||
520 | valueBOOL = FALSE; | ||
521 | else if((stream >> valueBOOL).fail()) | ||
522 | return FALSE; | ||
523 | //gMessageSystem->addBOOL(var_name, valueBOOL); | ||
524 | gMessageSystem->addU8(var_name, (U8)valueBOOL); | ||
525 | return TRUE; | ||
526 | break; | ||
527 | case MVT_IP_ADDR: | ||
528 | if((stream >> valueU32).fail()) | ||
529 | return FALSE; | ||
530 | gMessageSystem->addIPAddr(var_name, valueU32); | ||
531 | return TRUE; | ||
532 | break; | ||
533 | case MVT_IP_PORT: | ||
534 | if((stream >> valueU16).fail()) | ||
535 | return FALSE; | ||
536 | gMessageSystem->addIPPort(var_name, valueU16); | ||
537 | return TRUE; | ||
538 | break; | ||
539 | case MVT_VARIABLE: | ||
540 | if(!hex) | ||
541 | { | ||
542 | char* buffer = new char[input.size() + 1]; | ||
543 | strncpy(buffer, input.c_str(), input.size()); | ||
544 | buffer[input.size()] = '\0'; | ||
545 | gMessageSystem->addBinaryData(var_name, buffer, input.size() + 1); | ||
546 | delete[] buffer; | ||
547 | } | ||
548 | else | ||
549 | gMessageSystem->addBinaryData(var_name, input.c_str(), input.size()); | ||
550 | return TRUE; | ||
551 | break; | ||
552 | case MVT_FIXED: | ||
553 | if(!hex) | ||
554 | { | ||
555 | char* buffer = new char[input.size() + 1]; | ||
556 | strncpy(buffer, input.c_str(), input.size()); | ||
557 | buffer[input.size()] = '\0'; | ||
558 | gMessageSystem->addBinaryData(var_name, buffer, input.size()); | ||
559 | delete[] buffer; | ||
560 | } | ||
561 | else | ||
562 | gMessageSystem->addBinaryData(var_name, input.c_str(), input.size()); | ||
563 | return TRUE; | ||
564 | break; | ||
565 | default: | ||
566 | break; | ||
567 | } | ||
568 | return FALSE; | ||
569 | } | ||
570 | // static | ||
571 | void LLFloaterMessageBuilder::onCommitPacketCombo(LLUICtrl* ctrl, void* user_data) | ||
572 | { | ||
573 | LLFloaterMessageBuilder* floaterp = (LLFloaterMessageBuilder*)user_data; | ||
574 | LLViewerObject* selected_objectp = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); | ||
575 | LLParcel* agent_parcelp = LLViewerParcelMgr::getInstance()->getAgentParcel(); | ||
576 | std::string message = ctrl->getValue(); | ||
577 | std::map<const char *, LLMessageTemplate*>::iterator template_iter; | ||
578 | template_iter = gMessageSystem->mMessageTemplates.find( LLMessageStringTable::getInstance()->getString(message.c_str()) ); | ||
579 | if(template_iter == gMessageSystem->mMessageTemplates.end()) | ||
580 | { | ||
581 | floaterp->childSetText("message_edit", std::string("")); | ||
582 | return; | ||
583 | } | ||
584 | std::string text(llformat((*template_iter).second->getTrust() == MT_NOTRUST ? "out %s\n" : "in %s\n", message.c_str())); | ||
585 | LLMessageTemplate* temp = (*template_iter).second; | ||
586 | LLMessageTemplate::message_block_map_t::iterator blocks_end = temp->mMemberBlocks.end(); | ||
587 | for (LLMessageTemplate::message_block_map_t::iterator blocks_iter = temp->mMemberBlocks.begin(); | ||
588 | blocks_iter != blocks_end; ++blocks_iter) | ||
589 | { | ||
590 | LLMessageBlock* block = (*blocks_iter); | ||
591 | const char* block_name = block->mName; | ||
592 | std::string block_name_string = std::string(block_name); | ||
593 | S32 num_blocks = 1; | ||
594 | if(block->mType == MBT_MULTIPLE) | ||
595 | num_blocks = block->mNumber; | ||
596 | else if(("ObjectLink" == message && "ObjectData" == block_name_string)) | ||
597 | num_blocks = 2; | ||
598 | for(S32 i = 0; i < num_blocks; i++) | ||
599 | { | ||
600 | text.append(llformat("[%s]\n", block_name)); | ||
601 | LLMessageBlock::message_variable_map_t::iterator var_end = block->mMemberVariables.end(); | ||
602 | for (LLMessageBlock::message_variable_map_t::iterator var_iter = block->mMemberVariables.begin(); | ||
603 | var_iter != var_end; ++var_iter) | ||
604 | { | ||
605 | LLMessageVariable* variable = (*var_iter); | ||
606 | const char* var_name = variable->getName(); | ||
607 | std::string var_name_string = std::string(var_name); | ||
608 | text.append(llformat("%s = ", var_name)); | ||
609 | std::string value(""); | ||
610 | S32 size = variable->getSize(); | ||
611 | switch(variable->getType()) | ||
612 | { | ||
613 | case MVT_U8: | ||
614 | case MVT_U16: | ||
615 | case MVT_U32: | ||
616 | case MVT_U64: | ||
617 | case MVT_S8: | ||
618 | case MVT_S16: | ||
619 | case MVT_S32: | ||
620 | case MVT_IP_ADDR: | ||
621 | case MVT_IP_PORT: | ||
622 | if("RegionHandle" == var_name_string || "Handle" == var_name_string) | ||
623 | value = "$RegionHandle"; | ||
624 | else if("CircuitCode" == var_name_string || "ViewerCircuitCode" == var_name_string | ||
625 | || ("Code" == var_name_string && "CircuitCode" == block_name_string) ) | ||
626 | { | ||
627 | value = "$CircuitCode"; | ||
628 | } | ||
629 | else if(selected_objectp && | ||
630 | ( | ||
631 | "ObjectLocalID" == var_name_string | ||
632 | || "TaskLocalID" == var_name_string | ||
633 | || ("LocalID" == var_name_string && | ||
634 | ( | ||
635 | "ObjectData" == block_name_string | ||
636 | || "UpdateData" == block_name_string | ||
637 | || "InventoryData" == block_name_string | ||
638 | ) | ||
639 | ) | ||
640 | ) | ||
641 | ) | ||
642 | { | ||
643 | std::stringstream temp_stream; | ||
644 | temp_stream << selected_objectp->getLocalID(); | ||
645 | value = temp_stream.str(); | ||
646 | } | ||
647 | else if( agent_parcelp && | ||
648 | "LocalID" == var_name_string && | ||
649 | ( | ||
650 | "ParcelData" == block_name_string | ||
651 | || message.find("Parcel") != message.npos | ||
652 | ) | ||
653 | ) | ||
654 | { | ||
655 | std::stringstream temp_stream; | ||
656 | temp_stream << agent_parcelp->getLocalID(); | ||
657 | value = temp_stream.str(); | ||
658 | } | ||
659 | else if("PCode" == var_name_string) | ||
660 | value = "9"; | ||
661 | else if("PathCurve" == var_name_string) | ||
662 | value = "16"; | ||
663 | else if("ProfileCurve" == var_name_string) | ||
664 | value = "1"; | ||
665 | else if("PathScaleX" == var_name_string || "PathScaleY" == var_name_string) | ||
666 | value = "100"; | ||
667 | else if("BypassRaycast" == var_name_string) | ||
668 | value = "1"; | ||
669 | else | ||
670 | value = "0"; | ||
671 | break; | ||
672 | case MVT_F32: | ||
673 | case MVT_F64: | ||
674 | value = "0.0"; | ||
675 | break; | ||
676 | case MVT_LLVector3: | ||
677 | case MVT_LLVector3d: | ||
678 | case MVT_LLQuaternion: | ||
679 | if("Position" == var_name_string || "RayStart" == var_name_string || "RayEnd" == var_name_string) | ||
680 | value = "$Position"; | ||
681 | else if("Scale" == var_name_string) | ||
682 | value = "<0.5, 0.5, 0.5>"; | ||
683 | else | ||
684 | value = "<0, 0, 0>"; | ||
685 | break; | ||
686 | case MVT_LLVector4: | ||
687 | value = "<0, 0, 0, 0>"; | ||
688 | break; | ||
689 | case MVT_LLUUID: | ||
690 | if("AgentID" == var_name_string) | ||
691 | value = "$AgentID"; | ||
692 | else if("SessionID" == var_name_string) | ||
693 | value = "$SessionID"; | ||
694 | else if("ObjectID" == var_name_string && selected_objectp) | ||
695 | value = selected_objectp->getID().asString(); | ||
696 | else if("ParcelID" == var_name_string && agent_parcelp) | ||
697 | value = agent_parcelp->getID().asString(); | ||
698 | else | ||
699 | value = "00000000-0000-0000-0000-000000000000"; | ||
700 | break; | ||
701 | case MVT_BOOL: | ||
702 | value = "false"; | ||
703 | break; | ||
704 | case MVT_VARIABLE: | ||
705 | value = "Hello, world!"; | ||
706 | break; | ||
707 | case MVT_FIXED: | ||
708 | for(S32 si = 0; si < size; si++) | ||
709 | //value.append(std::string("0123456789abcdef").substr(si & 0xf, 1)); | ||
710 | value.append("a"); | ||
711 | break; | ||
712 | default: | ||
713 | value = ""; | ||
714 | break; | ||
715 | } | ||
716 | text.append(llformat("%s\n", value.c_str())); | ||
717 | } | ||
718 | } | ||
719 | } | ||
720 | text = text.substr(0, text.length() - 1); | ||
721 | floaterp->childSetText("message_edit", text); | ||
722 | } | ||
723 | // static | ||
724 | void LLFloaterMessageBuilder::onClickSend(void* user_data) | ||
725 | { | ||
726 | LLFloaterMessageBuilder* floaterp = (LLFloaterMessageBuilder*)user_data; | ||
727 | std::vector<std::string> lines = split(floaterp->childGetText("message_edit"), "\n"); | ||
728 | if(!lines.size()) | ||
729 | { | ||
730 | LLFloaterChat::addChat(LLChat("Not enough information :O")); | ||
731 | return; | ||
732 | } | ||
733 | std::vector<std::string> tokens = split(lines[0], " "); | ||
734 | if(!tokens.size()) | ||
735 | { | ||
736 | LLFloaterChat::addChat(LLChat("Not enough information :O")); | ||
737 | return; | ||
738 | } | ||
739 | std::string dir_str = tokens[0]; | ||
740 | LLStringUtil::toLower(dir_str); | ||
741 | // Direction | ||
742 | BOOL outgoing; | ||
743 | if(dir_str == "out") | ||
744 | outgoing = TRUE; | ||
745 | else if(dir_str == "in") | ||
746 | outgoing = FALSE; | ||
747 | else | ||
748 | { | ||
749 | LLFloaterChat::addChat(LLChat("Expected direction 'in' or 'out'")); | ||
750 | return; | ||
751 | } | ||
752 | // Message | ||
753 | std::string message = "Invalid"; | ||
754 | if(tokens.size() > 1) | ||
755 | { | ||
756 | if(tokens.size() > 2) | ||
757 | { | ||
758 | LLFloaterChat::addChat(LLChat("Unexpected extra stuff at the top")); | ||
759 | return; | ||
760 | } | ||
761 | message = tokens[1]; | ||
762 | LLStringUtil::trim(message); | ||
763 | } | ||
764 | // Body | ||
765 | std::vector<parts_block> parts; | ||
766 | if(lines.size() > 1) | ||
767 | { | ||
768 | std::vector<std::string>::iterator line_end = lines.end(); | ||
769 | std::vector<std::string>::iterator line_iter = lines.begin(); | ||
770 | ++line_iter; | ||
771 | std::string current_block(""); | ||
772 | int current_block_index = -1; | ||
773 | for( ; line_iter != line_end; ++line_iter) | ||
774 | { | ||
775 | std::string line = (*line_iter); | ||
776 | LLStringUtil::trim(line); | ||
777 | if(!line.length()) | ||
778 | continue; | ||
779 | if(line.substr(0, 1) == "[" && line.substr(line.size() - 1, 1) == "]") | ||
780 | { | ||
781 | current_block = line.substr(1, line.length() - 2); | ||
782 | LLStringUtil::trim(current_block); | ||
783 | ++current_block_index; | ||
784 | parts_block pb; | ||
785 | pb.name = current_block; | ||
786 | parts.push_back(pb); | ||
787 | } | ||
788 | else | ||
789 | { | ||
790 | if(current_block.empty()) | ||
791 | { | ||
792 | LLFloaterChat::addChat(LLChat("Unexpected field when no block yet")); | ||
793 | return; | ||
794 | } | ||
795 | int eqpos = line.find("="); | ||
796 | if(eqpos == line.npos) | ||
797 | { | ||
798 | LLFloaterChat::addChat(LLChat("Missing an equal sign")); | ||
799 | return; | ||
800 | } | ||
801 | std::string field = line.substr(0, eqpos); | ||
802 | LLStringUtil::trim(field); | ||
803 | if(!field.length()) | ||
804 | { | ||
805 | LLFloaterChat::addChat(LLChat("Missing name of field")); | ||
806 | return; | ||
807 | } | ||
808 | std::string value = line.substr(eqpos + 1); | ||
809 | LLStringUtil::trim(value); | ||
810 | parts_var pv; | ||
811 | if(value.substr(0, 1) == "|") | ||
812 | { | ||
813 | pv.hex = TRUE; | ||
814 | value = value.substr(1); | ||
815 | LLStringUtil::trim(value); | ||
816 | } | ||
817 | else | ||
818 | pv.hex = FALSE; | ||
819 | pv.name = field; | ||
820 | pv.value = value; | ||
821 | parts[current_block_index].vars.push_back(pv); | ||
822 | } | ||
823 | } | ||
824 | } | ||
825 | // Verification | ||
826 | std::map<const char *, LLMessageTemplate*>::iterator template_iter; | ||
827 | template_iter = gMessageSystem->mMessageTemplates.find( LLMessageStringTable::getInstance()->getString(message.c_str()) ); | ||
828 | if(template_iter == gMessageSystem->mMessageTemplates.end()) | ||
829 | { | ||
830 | LLFloaterChat::addChat(LLChat(llformat("Don't know how to build a '%s' message", message.c_str()))); | ||
831 | return; | ||
832 | } | ||
833 | LLMessageTemplate* temp = (*template_iter).second; | ||
834 | std::vector<parts_block>::iterator parts_end = parts.end(); | ||
835 | std::vector<parts_block>::iterator parts_iter = parts.begin(); | ||
836 | LLMessageTemplate::message_block_map_t::iterator blocks_end = temp->mMemberBlocks.end(); | ||
837 | for (LLMessageTemplate::message_block_map_t::iterator blocks_iter = temp->mMemberBlocks.begin(); | ||
838 | blocks_iter != blocks_end; ) | ||
839 | { | ||
840 | LLMessageBlock* block = (*blocks_iter); | ||
841 | const char* block_name = block->mName; | ||
842 | if(parts_iter == parts_end) | ||
843 | { | ||
844 | if(block->mType != MBT_VARIABLE) | ||
845 | LLFloaterChat::addChat(LLChat(llformat("Expected '%s' block", block_name))); | ||
846 | else | ||
847 | { | ||
848 | ++blocks_iter; | ||
849 | continue; | ||
850 | } | ||
851 | return; | ||
852 | } | ||
853 | else if((*parts_iter).name != block_name) | ||
854 | { | ||
855 | if(block->mType != MBT_VARIABLE) | ||
856 | LLFloaterChat::addChat(LLChat(llformat("Expected '%s' block", block_name))); | ||
857 | else | ||
858 | { | ||
859 | ++blocks_iter; | ||
860 | continue; | ||
861 | } | ||
862 | return; | ||
863 | } | ||
864 | std::vector<parts_var>::iterator part_var_end = (*parts_iter).vars.end(); | ||
865 | std::vector<parts_var>::iterator part_var_iter = (*parts_iter).vars.begin(); | ||
866 | LLMessageBlock::message_variable_map_t::iterator var_end = block->mMemberVariables.end(); | ||
867 | for (LLMessageBlock::message_variable_map_t::iterator var_iter = block->mMemberVariables.begin(); | ||
868 | var_iter != var_end; ++var_iter) | ||
869 | { | ||
870 | LLMessageVariable* variable = (*var_iter); | ||
871 | const char* var_name = variable->getName(); | ||
872 | if(part_var_iter == part_var_end) | ||
873 | { | ||
874 | LLFloaterChat::addChat(LLChat(llformat("Expected '%s' field under '%s' block", var_name, block_name))); | ||
875 | return; | ||
876 | } | ||
877 | else if((*part_var_iter).name != var_name) | ||
878 | { | ||
879 | LLFloaterChat::addChat(LLChat(llformat("Expected '%s' field under '%s' block", var_name, block_name))); | ||
880 | return; | ||
881 | } | ||
882 | (*part_var_iter).var_type = variable->getType(); | ||
883 | ++part_var_iter; | ||
884 | } | ||
885 | if(part_var_iter != part_var_end) | ||
886 | { | ||
887 | LLFloaterChat::addChat(LLChat(llformat("Unexpected field(s) at end of '%s' block", block_name))); | ||
888 | return; | ||
889 | } | ||
890 | ++parts_iter; | ||
891 | // test | ||
892 | if((block->mType != MBT_SINGLE) && (parts_iter != parts_end) && ((*parts_iter).name == block_name)) | ||
893 | { | ||
894 | // block will repeat | ||
895 | } | ||
896 | else ++blocks_iter; | ||
897 | } | ||
898 | if(parts_iter != parts_end) | ||
899 | { | ||
900 | LLFloaterChat::addChat(LLChat("Unexpected block(s) at end")); | ||
901 | return; | ||
902 | } | ||
903 | // Build and send | ||
904 | gMessageSystem->newMessage( message.c_str() ); | ||
905 | for(parts_iter = parts.begin(); parts_iter != parts_end; ++parts_iter) | ||
906 | { | ||
907 | const char* block_name = (*parts_iter).name.c_str(); | ||
908 | gMessageSystem->nextBlock(block_name); | ||
909 | std::vector<parts_var>::iterator part_var_end = (*parts_iter).vars.end(); | ||
910 | for(std::vector<parts_var>::iterator part_var_iter = (*parts_iter).vars.begin(); | ||
911 | part_var_iter != part_var_end; ++part_var_iter) | ||
912 | { | ||
913 | parts_var pv = (*part_var_iter); | ||
914 | if(!addField(pv.var_type, pv.name.c_str(), pv.value, pv.hex)) | ||
915 | { | ||
916 | LLFloaterChat::addChat(LLChat(llformat("Error adding the provided data for %s '%s' to '%s' block", mvtstr(pv.var_type).c_str(), pv.name.c_str(), block_name))); | ||
917 | gMessageSystem->clearMessage(); | ||
918 | return; | ||
919 | } | ||
920 | } | ||
921 | } | ||
922 | |||
923 | LLScrollListCtrl* scrollp = floaterp->getChild<LLScrollListCtrl>("net_list"); | ||
924 | LLScrollListItem* selected_itemp = scrollp->getFirstSelected(); | ||
925 | |||
926 | //if a specific circuit is selected, send it to that, otherwise send it to the current sim | ||
927 | if(selected_itemp) | ||
928 | { | ||
929 | LLNetListItem* itemp = findNetListItem(selected_itemp->getUUID()); | ||
930 | LLScrollListText* textColumn = (LLScrollListText*)selected_itemp->getColumn(1); | ||
931 | |||
932 | //why would you send data through a dead circuit? | ||
933 | if(textColumn->getValue().asString() == "Dead") | ||
934 | { | ||
935 | LLFloaterChat::addChat(LLChat("No sending messages through dead circuits!")); | ||
936 | return; | ||
937 | } | ||
938 | if(outgoing) | ||
939 | { | ||
940 | gMessageSystem->sendMessage(itemp->mCircuitData->getHost()); | ||
941 | } else { | ||
942 | U8 builtMessageBuffer[MAX_BUFFER_SIZE]; | ||
943 | |||
944 | S32 message_size = gMessageSystem->mTemplateMessageBuilder->buildMessage(builtMessageBuffer, MAX_BUFFER_SIZE, 0); | ||
945 | gMessageSystem->clearMessage(); | ||
946 | gMessageSystem->checkMessages(0, true, builtMessageBuffer, itemp->mCircuitData->getHost(), message_size); | ||
947 | |||
948 | } | ||
949 | } else { | ||
950 | if(outgoing) | ||
951 | { | ||
952 | gMessageSystem->sendMessage(gAgent.getRegionHost()); | ||
953 | } else { | ||
954 | U8 builtMessageBuffer[MAX_BUFFER_SIZE]; | ||
955 | |||
956 | S32 message_size = gMessageSystem->mTemplateMessageBuilder->buildMessage(builtMessageBuffer, MAX_BUFFER_SIZE, 0); | ||
957 | gMessageSystem->clearMessage(); | ||
958 | gMessageSystem->checkMessages(0, true, builtMessageBuffer, gAgent.getRegionHost(), message_size); | ||
959 | |||
960 | } | ||
961 | } | ||
962 | } | ||
963 | |||
964 | BOOL LLFloaterMessageBuilder::handleKeyHere(KEY key, MASK mask) | ||
965 | { | ||
966 | if(key == KEY_RETURN && (mask & MASK_CONTROL)) | ||
967 | { | ||
968 | onClickSend(this); | ||
969 | return TRUE; | ||
970 | } | ||
971 | if(key == KEY_ESCAPE) | ||
972 | { | ||
973 | releaseFocus(); | ||
974 | return TRUE; | ||
975 | } | ||
976 | return FALSE; | ||
977 | } | ||
978 | // </edit> | ||