llfiltersd2xmlrpc.cpp
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:19k
源码类别:

游戏引擎

开发平台:

C++ Builder

  1. /** 
  2.  * @file llfiltersd2xmlrpc.cpp
  3.  * @author Phoenix
  4.  * @date 2005-04-26
  5.  *
  6.  * $LicenseInfo:firstyear=2005&license=viewergpl$
  7.  * 
  8.  * Copyright (c) 2005-2010, Linden Research, Inc.
  9.  * 
  10.  * Second Life Viewer Source Code
  11.  * The source code in this file ("Source Code") is provided by Linden Lab
  12.  * to you under the terms of the GNU General Public License, version 2.0
  13.  * ("GPL"), unless you have obtained a separate licensing agreement
  14.  * ("Other License"), formally executed by you and Linden Lab.  Terms of
  15.  * the GPL can be found in doc/GPL-license.txt in this distribution, or
  16.  * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  17.  * 
  18.  * There are special exceptions to the terms and conditions of the GPL as
  19.  * it is applied to this Source Code. View the full text of the exception
  20.  * in the file doc/FLOSS-exception.txt in this software distribution, or
  21.  * online at
  22.  * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  23.  * 
  24.  * By copying, modifying or distributing this software, you acknowledge
  25.  * that you have read and understood your obligations described above,
  26.  * and agree to abide by those obligations.
  27.  * 
  28.  * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  29.  * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  30.  * COMPLETENESS OR PERFORMANCE.
  31.  * $/LicenseInfo$
  32.  */
  33. /** 
  34.  * xml rpc request: 
  35.  * <code>
  36.  * <?xml version="1.0"?>
  37.  * <methodCall><methodName>examples.getStateName</methodName>
  38.  * <params><param><value><i4>41</i4></value></param></params>
  39.  * </methodCall>
  40.  * </code>
  41.  *
  42.  * xml rpc response:
  43.  * <code>
  44.  * <?xml version="1.0"?>
  45.  * <methodResponse>
  46.  * <params><param><value><string>South Dakota</string></value></param></params>
  47.  * </methodResponse>
  48.  * </code>
  49.  *
  50.  * xml rpc fault:
  51.  * </code>
  52.  * <?xml version="1.0"?>
  53.  * <methodResponse>
  54.  * <fault><value><struct>
  55.  * <member><name>faultCode</name><value><int>4</int></value></member>
  56.  * <member><name>faultString</name><value><string>...</string></value></member>
  57.  * </struct></value></fault>
  58.  * </methodResponse>
  59.  * </code>
  60.  *
  61.  * llsd rpc request:
  62.  * <code>
  63.  * { 'method':'...', 'parameter':...]}
  64.  * </code>
  65.  * 
  66.  * llsd rpc response:
  67.  * <code>
  68.  * { 'response':... }
  69.  * </code>
  70.  * 
  71.  * llsd rpc fault: 
  72.  * <code>
  73.  * { 'fault': {'code':i..., 'description':'...'} }
  74.  * </code>
  75.  * 
  76.  */
  77. #include "linden_common.h"
  78. #include "llfiltersd2xmlrpc.h"
  79. #include <sstream>
  80. #include <iterator>
  81. #include <xmlrpc-epi/xmlrpc.h>
  82. #include "apr_base64.h"
  83. #include "llbuffer.h"
  84. #include "llbufferstream.h"
  85. #include "llmemorystream.h"
  86. #include "llsd.h"
  87. #include "llsdserialize.h"
  88. #include "lluuid.h"
  89. // spammy mode
  90. //#define LL_SPEW_STREAM_OUT_DEBUGGING 1
  91. /**
  92.  * String constants
  93.  */
  94. static const char XML_HEADER[] = "<?xml version="1.0" encoding="UTF-8"?>";
  95. static const char XMLRPC_REQUEST_HEADER_1[] = "<methodCall><methodName>";
  96. static const char XMLRPC_REQUEST_HEADER_2[] = "</methodName><params>";
  97. static const char XMLRPC_REQUEST_FOOTER[] = "</params></methodCall>";
  98. static const char XMLRPC_METHOD_RESPONSE_HEADER[] = "<methodResponse>";
  99. static const char XMLRPC_METHOD_RESPONSE_FOOTER[] = "</methodResponse>";
  100. static const char XMLRPC_RESPONSE_HEADER[] = "<params><param>";
  101. static const char XMLRPC_RESPONSE_FOOTER[] = "</param></params>";
  102. static const char XMLRPC_FAULT_1[] = "<fault><value><struct><member><name>faultCode</name><value><int>";
  103. static const char XMLRPC_FAULT_2[] = "</int></value></member><member><name>faultString</name><value><string>";
  104. static const char XMLRPC_FAULT_3[] = "</string></value></member></struct></value></fault>";
  105. static const char LLSDRPC_RESPONSE_HEADER[] = "{'response':";
  106. static const char LLSDRPC_RESPONSE_FOOTER[] = "}";
  107. const char LLSDRPC_REQUEST_HEADER_1[] = "{'method':'";
  108. const char LLSDRPC_REQUEST_HEADER_2[] = "', 'parameter': ";
  109. const char LLSDRPC_REQUEST_FOOTER[] = "}";
  110. static const char LLSDRPC_FAULT_HADER_1[] = "{ 'fault': {'code':i";
  111. static const char LLSDRPC_FAULT_HADER_2[] = ", 'description':";
  112. static const char LLSDRPC_FAULT_FOOTER[] = "} }";
  113. static const S32 DEFAULT_PRECISION = 20;
  114. /**
  115.  * LLFilterSD2XMLRPC
  116.  */
  117. LLFilterSD2XMLRPC::LLFilterSD2XMLRPC()
  118. {
  119. }
  120. LLFilterSD2XMLRPC::~LLFilterSD2XMLRPC()
  121. {
  122. }
  123. std::string xml_escape_string(const std::string& in)
  124. {
  125. std::ostringstream out;
  126. std::string::const_iterator it = in.begin();
  127. std::string::const_iterator end = in.end();
  128. for(; it != end; ++it)
  129. {
  130. switch((*it))
  131. {
  132. case '<':
  133. out << "&lt;";
  134. break;
  135. case '>':
  136. out << "&gt;";
  137. break;
  138. case '&':
  139. out << "&amp;";
  140. break;
  141. case ''':
  142. out << "&apos;";
  143. break;
  144. case '"':
  145. out << "&quot;";
  146. break;
  147. default:
  148. out << (*it);
  149. break;
  150. }
  151. }
  152. return out.str();
  153. }
  154. void LLFilterSD2XMLRPC::streamOut(std::ostream& ostr, const LLSD& sd)
  155. {
  156. ostr << "<value>";
  157. switch(sd.type())
  158. {
  159. case LLSD::TypeMap:
  160. {
  161. #if LL_SPEW_STREAM_OUT_DEBUGGING
  162. llinfos << "streamOut(map) BEGIN" << llendl;
  163. #endif
  164. ostr << "<struct>";
  165. if(ostr.fail())
  166. {
  167. llinfos << "STREAM FAILURE writing struct" << llendl;
  168. }
  169. LLSD::map_const_iterator it = sd.beginMap();
  170. LLSD::map_const_iterator end = sd.endMap();
  171. for(; it != end; ++it)
  172. {
  173. ostr << "<member><name>" << xml_escape_string((*it).first)
  174. << "</name>";
  175. streamOut(ostr, (*it).second);
  176. if(ostr.fail())
  177. {
  178. llinfos << "STREAM FAILURE writing '" << (*it).first
  179. << "' with sd type " << (*it).second.type() << llendl;
  180. }
  181. ostr << "</member>";
  182. }
  183. ostr << "</struct>";
  184. #if LL_SPEW_STREAM_OUT_DEBUGGING
  185. llinfos << "streamOut(map) END" << llendl;
  186. #endif
  187. break;
  188. }
  189. case LLSD::TypeArray:
  190. {
  191. #if LL_SPEW_STREAM_OUT_DEBUGGING
  192. llinfos << "streamOut(array) BEGIN" << llendl;
  193. #endif
  194. ostr << "<array><data>";
  195. LLSD::array_const_iterator it = sd.beginArray();
  196. LLSD::array_const_iterator end = sd.endArray();
  197. for(; it != end; ++it)
  198. {
  199. streamOut(ostr, *it);
  200. if(ostr.fail())
  201. {
  202. llinfos << "STREAM FAILURE writing array element sd type "
  203. << (*it).type() << llendl;
  204. }
  205. }
  206. #if LL_SPEW_STREAM_OUT_DEBUGGING
  207. llinfos << "streamOut(array) END" << llendl;
  208. #endif
  209. ostr << "</data></array>";
  210. break;
  211. }
  212. case LLSD::TypeUndefined:
  213. // treat undefined as a bool with a false value.
  214. case LLSD::TypeBoolean:
  215. #if LL_SPEW_STREAM_OUT_DEBUGGING
  216. llinfos << "streamOut(bool)" << llendl;
  217. #endif
  218. ostr << "<boolean>" << (sd.asBoolean() ? "1" : "0") << "</boolean>";
  219. break;
  220. case LLSD::TypeInteger:
  221. #if LL_SPEW_STREAM_OUT_DEBUGGING
  222. llinfos << "streamOut(int)" << llendl;
  223. #endif
  224. ostr << "<i4>" << sd.asInteger() << "</i4>";
  225. break;
  226. case LLSD::TypeReal:
  227. #if LL_SPEW_STREAM_OUT_DEBUGGING
  228. llinfos << "streamOut(real)" << llendl;
  229. #endif
  230. ostr << "<double>" << sd.asReal() << "</double>";
  231. break;
  232. case LLSD::TypeString:
  233. #if LL_SPEW_STREAM_OUT_DEBUGGING
  234. llinfos << "streamOut(string)" << llendl;
  235. #endif
  236. ostr << "<string>" << xml_escape_string(sd.asString()) << "</string>";
  237. break;
  238. case LLSD::TypeUUID:
  239. #if LL_SPEW_STREAM_OUT_DEBUGGING
  240. llinfos << "streamOut(uuid)" << llendl;
  241. #endif
  242. // serialize it as a string
  243. ostr << "<string>" << sd.asString() << "</string>";
  244. break;
  245. case LLSD::TypeURI:
  246. {
  247. #if LL_SPEW_STREAM_OUT_DEBUGGING
  248. llinfos << "streamOut(uri)" << llendl;
  249. #endif
  250. // serialize it as a string
  251. ostr << "<string>" << xml_escape_string(sd.asString()) << "</string>";
  252. break;
  253. }
  254. case LLSD::TypeBinary:
  255. {
  256. #if LL_SPEW_STREAM_OUT_DEBUGGING
  257. llinfos << "streamOut(binary)" << llendl;
  258. #endif
  259. // this is pretty inefficient, but we'll deal with that
  260. // problem when it becomes one.
  261. ostr << "<base64>";
  262. LLSD::Binary buffer = sd.asBinary();
  263. if(!buffer.empty())
  264. {
  265. // *TODO: convert to LLBase64
  266. int b64_buffer_length = apr_base64_encode_len(buffer.size());
  267. char* b64_buffer = new char[b64_buffer_length];
  268. b64_buffer_length = apr_base64_encode_binary(
  269. b64_buffer,
  270. &buffer[0],
  271. buffer.size());
  272. ostr.write(b64_buffer, b64_buffer_length - 1);
  273. delete[] b64_buffer;
  274. }
  275. ostr << "</base64>";
  276. break;
  277. }
  278. case LLSD::TypeDate:
  279. #if LL_SPEW_STREAM_OUT_DEBUGGING
  280. llinfos << "streamOut(date)" << llendl;
  281. #endif
  282. // no need to escape this since it will be alpha-numeric.
  283. ostr << "<dateTime.iso8601>" << sd.asString() << "</dateTime.iso8601>";
  284. break;
  285. default:
  286. // unhandled type
  287. llwarns << "Unhandled structured data type: " << sd.type()
  288. << llendl;
  289. break;
  290. }
  291. ostr << "</value>";
  292. }
  293. /**
  294.  * LLFilterSD2XMLRPCResponse
  295.  */
  296. LLFilterSD2XMLRPCResponse::LLFilterSD2XMLRPCResponse()
  297. {
  298. }
  299. LLFilterSD2XMLRPCResponse::~LLFilterSD2XMLRPCResponse()
  300. {
  301. }
  302. // virtual
  303. LLIOPipe::EStatus LLFilterSD2XMLRPCResponse::process_impl(
  304. const LLChannelDescriptors& channels,
  305. buffer_ptr_t& buffer,
  306. bool& eos,
  307. LLSD& context,
  308. LLPumpIO* pump)
  309. {
  310. PUMP_DEBUG;
  311. // This pipe does not work if it does not have everyting. This
  312. // could be addressed by making a stream parser for llsd which
  313. // handled partial information.
  314. if(!eos)
  315. {
  316. return STATUS_BREAK;
  317. }
  318. PUMP_DEBUG;
  319. // we have everyting in the buffer, so turn the structure data rpc
  320. // response into an xml rpc response.
  321. LLBufferStream stream(channels, buffer.get());
  322. stream << XML_HEADER << XMLRPC_METHOD_RESPONSE_HEADER;
  323. LLSD sd;
  324. LLSDSerialize::fromNotation(sd, stream, buffer->count(channels.in()));
  325. PUMP_DEBUG;
  326. LLIOPipe::EStatus rv = STATUS_ERROR;
  327. if(sd.has("response"))
  328. {
  329. PUMP_DEBUG;
  330. // it is a normal response. pack it up and ship it out.
  331. stream.precision(DEFAULT_PRECISION);
  332. stream << XMLRPC_RESPONSE_HEADER;
  333. streamOut(stream, sd["response"]);
  334. stream << XMLRPC_RESPONSE_FOOTER << XMLRPC_METHOD_RESPONSE_FOOTER;
  335. rv = STATUS_DONE;
  336. }
  337. else if(sd.has("fault"))
  338. {
  339. PUMP_DEBUG;
  340. // it is a fault.
  341. stream << XMLRPC_FAULT_1 << sd["fault"]["code"].asInteger()
  342. << XMLRPC_FAULT_2
  343. << xml_escape_string(sd["fault"]["description"].asString())
  344. << XMLRPC_FAULT_3 << XMLRPC_METHOD_RESPONSE_FOOTER;
  345. rv = STATUS_DONE;
  346. }
  347. else
  348. {
  349. llwarns << "Unable to determine the type of LLSD response." << llendl;
  350. }
  351. PUMP_DEBUG;
  352. return rv;
  353. }
  354. /**
  355.  * LLFilterSD2XMLRPCRequest
  356.  */
  357. LLFilterSD2XMLRPCRequest::LLFilterSD2XMLRPCRequest()
  358. {
  359. }
  360. LLFilterSD2XMLRPCRequest::LLFilterSD2XMLRPCRequest(const char* method)
  361. {
  362. if(method)
  363. {
  364. mMethod.assign(method);
  365. }
  366. }
  367. LLFilterSD2XMLRPCRequest::~LLFilterSD2XMLRPCRequest()
  368. {
  369. }
  370. // virtual
  371. LLIOPipe::EStatus LLFilterSD2XMLRPCRequest::process_impl(
  372. const LLChannelDescriptors& channels,
  373. buffer_ptr_t& buffer,
  374. bool& eos,
  375. LLSD& context,
  376. LLPumpIO* pump)
  377. {
  378. // This pipe does not work if it does not have everyting. This
  379. // could be addressed by making a stream parser for llsd which
  380. // handled partial information.
  381. PUMP_DEBUG;
  382. if(!eos)
  383. {
  384. llinfos << "!eos" << llendl;
  385. return STATUS_BREAK;
  386. }
  387. // See if we can parse it
  388. LLBufferStream stream(channels, buffer.get());
  389. LLSD sd;
  390. LLSDSerialize::fromNotation(sd, stream, buffer->count(channels.in()));
  391. if(stream.fail())
  392. {
  393. llinfos << "STREAM FAILURE reading structure data." << llendl;
  394. }
  395. PUMP_DEBUG;
  396. // We can get the method and parameters from either the member
  397. // function or passed in via the buffer. We prefer the buffer if
  398. // we found a parameter and a method, or fall back to using
  399. // mMethod and putting everyting in the buffer into the parameter.
  400. std::string method;
  401. LLSD param_sd;
  402. if(sd.has("method") && sd.has("parameter"))
  403. {
  404. method = sd["method"].asString();
  405. param_sd = sd["parameter"];
  406. }
  407. else
  408. {
  409. method = mMethod;
  410. param_sd = sd;
  411. }
  412. if(method.empty())
  413. {
  414. llwarns << "SD -> XML Request no method found." << llendl;
  415. return STATUS_ERROR;
  416. }
  417. PUMP_DEBUG;
  418. // We have a method, and some kind of parameter, so package it up
  419. // and send it out.
  420. LLBufferStream ostream(channels, buffer.get());
  421. ostream.precision(DEFAULT_PRECISION);
  422. if(ostream.fail())
  423. {
  424. llinfos << "STREAM FAILURE setting precision" << llendl;
  425. }
  426. ostream << XML_HEADER << XMLRPC_REQUEST_HEADER_1
  427. << xml_escape_string(method) << XMLRPC_REQUEST_HEADER_2;
  428. if(ostream.fail())
  429. {
  430. llinfos << "STREAM FAILURE writing method headers" << llendl;
  431. }
  432. switch(param_sd.type())
  433. {
  434. case LLSD::TypeMap:
  435. // If the params are a map, then we do not want to iterate
  436. // through them since the iterators returned will be map
  437. // ordered un-named values, which will lose the names, and
  438. // only stream the values, turning it into an array.
  439. ostream << "<param>";
  440. streamOut(ostream, param_sd);
  441. ostream << "</param>";
  442. break;
  443. case LLSD::TypeArray:
  444. {
  445. LLSD::array_iterator it = param_sd.beginArray();
  446. LLSD::array_iterator end = param_sd.endArray();
  447. for(; it != end; ++it)
  448. {
  449. ostream << "<param>";
  450. streamOut(ostream, *it);
  451. ostream << "</param>";
  452. }
  453. break;
  454. }
  455. default:
  456. ostream << "<param>";
  457. streamOut(ostream, param_sd);
  458. ostream << "</param>";
  459. break;
  460. }
  461. stream << XMLRPC_REQUEST_FOOTER;
  462. return STATUS_DONE;
  463. }
  464. /**
  465.  * LLFilterXMLRPCResponse2LLSD
  466.  */
  467. // this is a c function here since it's really an implementation
  468. // detail that requires a header file just get the definition of the
  469. // parameters.
  470. LLIOPipe::EStatus stream_out(std::ostream& ostr, XMLRPC_VALUE value)
  471. {
  472. XMLRPC_VALUE_TYPE_EASY type = XMLRPC_GetValueTypeEasy(value);
  473. LLIOPipe::EStatus status = LLIOPipe::STATUS_OK;
  474. switch(type)
  475. {
  476. case xmlrpc_type_base64:
  477. {
  478. S32 len = XMLRPC_GetValueStringLen(value);
  479. const char* buf = XMLRPC_GetValueBase64(value);
  480. ostr << " b(";
  481. if((len > 0) && buf)
  482. {
  483. ostr << len << ")"";
  484. ostr.write(buf, len);
  485. ostr << """;
  486. }
  487. else
  488. {
  489. ostr << "0)""";
  490. }
  491. break;
  492. }
  493. case xmlrpc_type_boolean:
  494. //lldebugs << "stream_out() bool" << llendl;
  495. ostr << " " << (XMLRPC_GetValueBoolean(value) ? "true" : "false");
  496. break;
  497. case xmlrpc_type_datetime:
  498. ostr << " d"" << XMLRPC_GetValueDateTime_ISO8601(value) << """;
  499. break;
  500. case xmlrpc_type_double:
  501. ostr << " r" << XMLRPC_GetValueDouble(value);
  502. //lldebugs << "stream_out() double" << XMLRPC_GetValueDouble(value)
  503. //  << llendl;
  504. break;
  505. case xmlrpc_type_int:
  506. ostr << " i" << XMLRPC_GetValueInt(value);
  507. //lldebugs << "stream_out() integer:" << XMLRPC_GetValueInt(value)
  508. //  << llendl;
  509. break;
  510. case xmlrpc_type_string:
  511. //lldebugs << "stream_out() string: " << str << llendl;
  512. ostr << " s(" << XMLRPC_GetValueStringLen(value) << ")'"
  513. << XMLRPC_GetValueString(value) << "'";
  514. break;
  515. case xmlrpc_type_array: // vector
  516. case xmlrpc_type_mixed: // vector
  517. {
  518. //lldebugs << "stream_out() array" << llendl;
  519. ostr << " [";
  520. U32 needs_comma = 0;
  521. XMLRPC_VALUE current = XMLRPC_VectorRewind(value);
  522. while(current && (LLIOPipe::STATUS_OK == status))
  523. {
  524. if(needs_comma++) ostr << ",";
  525. status = stream_out(ostr, current);
  526. current = XMLRPC_VectorNext(value);
  527. }
  528. ostr << "]";
  529. break;
  530. }
  531. case xmlrpc_type_struct: // still vector
  532. {
  533. //lldebugs << "stream_out() struct" << llendl;
  534. ostr << " {";
  535. std::string name;
  536. U32 needs_comma = 0;
  537. XMLRPC_VALUE current = XMLRPC_VectorRewind(value);
  538. while(current && (LLIOPipe::STATUS_OK == status))
  539. {
  540. if(needs_comma++) ostr << ",";
  541. name.assign(XMLRPC_GetValueID(current));
  542. ostr << "'" << LLSDNotationFormatter::escapeString(name) << "':";
  543. status = stream_out(ostr, current);
  544. current = XMLRPC_VectorNext(value);
  545. }
  546. ostr << "}";
  547. break;
  548. }
  549. case xmlrpc_type_empty:
  550. case xmlrpc_type_none:
  551. default:
  552. status = LLIOPipe::STATUS_ERROR;
  553. llwarns << "Found an empty xmlrpc type.." << llendl;
  554. // not much we can do here...
  555. break;
  556. };
  557. return status;
  558. }
  559. LLFilterXMLRPCResponse2LLSD::LLFilterXMLRPCResponse2LLSD()
  560. {
  561. }
  562. LLFilterXMLRPCResponse2LLSD::~LLFilterXMLRPCResponse2LLSD()
  563. {
  564. }
  565. LLIOPipe::EStatus LLFilterXMLRPCResponse2LLSD::process_impl(
  566. const LLChannelDescriptors& channels,
  567. buffer_ptr_t& buffer,
  568. bool& eos,
  569. LLSD& context,
  570. LLPumpIO* pump)
  571. {
  572. PUMP_DEBUG;
  573. if(!eos) return STATUS_BREAK;
  574. if(!buffer) return STATUS_ERROR;
  575. PUMP_DEBUG;
  576. // *FIX: This technique for reading data is far from optimal. We
  577. // need to have some kind of istream interface into the xml
  578. // parser...
  579. S32 bytes = buffer->countAfter(channels.in(), NULL);
  580. if(!bytes) return STATUS_ERROR;
  581. char* buf = new char[bytes + 1];
  582. buf[bytes] = '';
  583. buffer->readAfter(channels.in(), NULL, (U8*)buf, bytes);
  584. //lldebugs << "xmlrpc response: " << buf << llendl;
  585. PUMP_DEBUG;
  586. XMLRPC_REQUEST response = XMLRPC_REQUEST_FromXML(
  587. buf,
  588. bytes,
  589. NULL);
  590. if(!response)
  591. {
  592. llwarns << "XML -> SD Response unable to parse xml." << llendl;
  593. delete[] buf;
  594. return STATUS_ERROR;
  595. }
  596. PUMP_DEBUG;
  597. LLBufferStream stream(channels, buffer.get());
  598. stream.precision(DEFAULT_PRECISION);
  599. if(XMLRPC_ResponseIsFault(response))
  600. {
  601. PUMP_DEBUG;
  602. stream << LLSDRPC_FAULT_HADER_1
  603.    << XMLRPC_GetResponseFaultCode(response)
  604.    << LLSDRPC_FAULT_HADER_2;
  605. const char* fault_str = XMLRPC_GetResponseFaultString(response);
  606. std::string fault_string;
  607. if(fault_str)
  608. {
  609. fault_string.assign(fault_str);
  610. }
  611. stream << "'" << LLSDNotationFormatter::escapeString(fault_string)
  612.    << "'" <<LLSDRPC_FAULT_FOOTER;
  613. }
  614. else
  615. {
  616. PUMP_DEBUG;
  617. stream << LLSDRPC_RESPONSE_HEADER;
  618. XMLRPC_VALUE param = XMLRPC_RequestGetData(response);
  619. if(param)
  620. {
  621. stream_out(stream, param);
  622. }
  623. stream << LLSDRPC_RESPONSE_FOOTER;
  624. }
  625. PUMP_DEBUG;
  626. XMLRPC_RequestFree(response, 1);
  627. delete[] buf;
  628. PUMP_DEBUG;
  629. return STATUS_DONE;
  630. }
  631. /**
  632.  * LLFilterXMLRPCRequest2LLSD
  633.  */
  634. LLFilterXMLRPCRequest2LLSD::LLFilterXMLRPCRequest2LLSD()
  635. {
  636. }
  637. LLFilterXMLRPCRequest2LLSD::~LLFilterXMLRPCRequest2LLSD()
  638. {
  639. }
  640. LLIOPipe::EStatus LLFilterXMLRPCRequest2LLSD::process_impl(
  641. const LLChannelDescriptors& channels,
  642. buffer_ptr_t& buffer,
  643. bool& eos,
  644. LLSD& context,
  645. LLPumpIO* pump)
  646. {
  647. PUMP_DEBUG;
  648. if(!eos) return STATUS_BREAK;
  649. if(!buffer) return STATUS_ERROR;
  650. PUMP_DEBUG;
  651. // *FIX: This technique for reading data is far from optimal. We
  652. // need to have some kind of istream interface into the xml
  653. // parser...
  654. S32 bytes = buffer->countAfter(channels.in(), NULL);
  655. if(!bytes) return STATUS_ERROR;
  656. char* buf = new char[bytes + 1];
  657. buf[bytes] = '';
  658. buffer->readAfter(channels.in(), NULL, (U8*)buf, bytes);
  659. //lldebugs << "xmlrpc request: " << buf << llendl;
  660. // Check the value in the buffer. XMLRPC_REQUEST_FromXML will report a error code 4 if 
  661. // values that are less than 0x20 are passed to it, except
  662. // 0x09: Horizontal tab; 0x0a: New Line; 0x0d: Carriage
  663. U8* cur_pBuf = (U8*)buf;
  664.     U8 cur_char;
  665. for (S32 i=0; i<bytes; i++) 
  666. {
  667.         cur_char = *cur_pBuf;
  668. if (   cur_char < 0x20
  669.             && 0x09 != cur_char
  670.             && 0x0a != cur_char
  671.             && 0x0d != cur_char )
  672.         {
  673. *cur_pBuf = '?';
  674.         }
  675. ++cur_pBuf;
  676. }
  677. PUMP_DEBUG;
  678. XMLRPC_REQUEST request = XMLRPC_REQUEST_FromXML(
  679. buf,
  680. bytes,
  681. NULL);
  682. if(!request)
  683. {
  684. llwarns << "XML -> SD Request process parse error." << llendl;
  685. delete[] buf;
  686. return STATUS_ERROR;
  687. }
  688. PUMP_DEBUG;
  689. LLBufferStream stream(channels, buffer.get());
  690. stream.precision(DEFAULT_PRECISION);
  691. const char* name = XMLRPC_RequestGetMethodName(request);
  692. stream << LLSDRPC_REQUEST_HEADER_1 << (name ? name : "")
  693.    << LLSDRPC_REQUEST_HEADER_2;
  694. XMLRPC_VALUE param = XMLRPC_RequestGetData(request);
  695. if(param)
  696. {
  697. PUMP_DEBUG;
  698. S32 size = XMLRPC_VectorSize(param);
  699. if(size > 1)
  700. {
  701. // if there are multiple parameters, stuff the values into
  702. // an array so that the next step in the chain can read them.
  703. stream << "[";
  704. }
  705.   XMLRPC_VALUE current = XMLRPC_VectorRewind(param);
  706. bool needs_comma = false;
  707.   while(current)
  708.   {
  709. if(needs_comma)
  710. {
  711. stream << ",";
  712. }
  713. needs_comma = true;
  714.   stream_out(stream, current);
  715.   current = XMLRPC_VectorNext(param);
  716.   }
  717. if(size > 1)
  718. {
  719. // close the array
  720. stream << "]";
  721. }
  722. }
  723. stream << LLSDRPC_REQUEST_FOOTER;
  724. XMLRPC_RequestFree(request, 1);
  725. delete[] buf;
  726. PUMP_DEBUG;
  727. return STATUS_DONE;
  728. }