xmlrpc.c 73 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545
  1. /*
  2. * Copyright (C) 2005 iptelorg GmbH
  3. * Written by Jan Janak <[email protected]>
  4. *
  5. * This file is part of SER, a free SIP server.
  6. *
  7. * SER is free software; you can redistribute it and/or modify it under the
  8. * terms of the GNU General Public License as published by the Free Software
  9. * Foundation; either version 2 of the License, or (at your option) any later
  10. * version
  11. *
  12. * For a license to use the SER software under conditions other than those
  13. * described here, or to purchase support for this software, please contact
  14. * iptel.org by e-mail at the following addresses: [email protected]
  15. *
  16. * SER is distributed in the hope that it will be useful, but WITHOUT ANY
  17. * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  18. * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
  19. * details.
  20. *
  21. * You should have received a copy of the GNU General Public License along
  22. * with this program; if not, write to the Free Software Foundation, Inc., 59
  23. * Temple Place, Suite 330, Boston, MA 02111-1307 USA
  24. */
  25. /*This define breaks on Solaris OS */
  26. #ifndef __OS_solaris
  27. #define _XOPEN_SOURCE 4 /* strptime */
  28. #endif
  29. #define _XOPEN_SOURCE_EXTENDED 1 /* solaris */
  30. #define _SVID_SOURCE 1 /* timegm */
  31. #include <strings.h>
  32. #include <time.h>
  33. #include <string.h>
  34. #include <stdlib.h>
  35. #include <stdio.h>
  36. #include <string.h>
  37. #include <stdarg.h>
  38. #include <sys/types.h>
  39. #include <signal.h>
  40. #include <libxml/xmlreader.h>
  41. #include "../../str.h"
  42. #include "../../sr_module.h"
  43. #include "../../error.h"
  44. #include "../../usr_avp.h"
  45. #include "../../mem/mem.h"
  46. #include "../../parser/parse_uri.h"
  47. #include "../../parser/msg_parser.h"
  48. #include "../../ut.h"
  49. #include "../../dset.h"
  50. #include "../../str.h"
  51. #include "../../dprint.h"
  52. #include "../../data_lump.h"
  53. #include "../../data_lump_rpl.h"
  54. #include "../../msg_translator.h"
  55. #include "../../select.h"
  56. #include "../../receive.h" /* needed by process_rpc / receive_msg() */
  57. #include "../../modules/sl/sl.h"
  58. #include "../../nonsip_hooks.h"
  59. #include "../../action.h" /* run_actions */
  60. #include "../../script_cb.h" /* exec_*_script_cb */
  61. #include "../../route.h" /* route_get */
  62. #include "../../sip_msg_clone.h" /* sip_msg_shm_clone */
  63. #include "http.h"
  64. /** @addtogroup xmlrpc
  65. * @ingroup modules
  66. * @{
  67. *
  68. * <h1>Overview of Operation</h1>
  69. * This module provides XML-RPC based interface to management functions in
  70. * SER. You can send XML-RPC requests to SER when the module is loaded and
  71. * configured and it will send XML-RPC replies back. XML-RPC requests are
  72. * encoded as XML documents in the body of HTTP requests. Due to similarity
  73. * between HTTP and SIP SER can easily parse HTTP requests and extract the XML
  74. * document from their body.
  75. *
  76. * When you load this module into SER, it will register a callback function
  77. * that will be called whenever the SER core receives a request with method it
  78. * does not understand. The main callback function is process_xmlrpc(). The
  79. * function first verifies if the protocol identifier inside the request is
  80. * HTTP and whether the request method is either GET or POST. If both
  81. * conditions are met then it will signal to the SER core that it is
  82. * processing the request, otherwise it will reject the request and the SER
  83. * core will pass the requests to other callbacks if they exist.
  84. *
  85. * As the next step the request will be converted from HTTP request to a SIP
  86. * request to ensure that it can be processed by SER and its modules. The
  87. * conversion will modify the URI in the Request-URI of the request, the new
  88. * URI will be a SIP URI. In addition to that it will add a fake Via header
  89. * field and copy all remaining header fields from the original HTTP request.
  90. * The conversion is implemented in http_xmlrpc2sip() function.
  91. *
  92. * After the conversion the module will execute the route statement whose
  93. * number is configured in "route" module parameter. That route stament may
  94. * perform additional security checks and when it ensures that the client is
  95. * authorized to execute management functions then it will call dispatch_rpc()
  96. * module function provided by this module.
  97. *
  98. * dispatch_rpc() function extracts the XML-RPC document from the body of the
  99. * request to determine the name of the method to be called and then it
  100. * searches through the list of all management functions to find a function
  101. * with matching name. If such a function is found then dispatch_rpc() will
  102. * pass control to the function to handle the request. dispatch_rpc() will
  103. * send a reply back to the client when the management function terminates, if
  104. * the function did not do that explicitly.
  105. *
  106. * <h2>Memory Management</h2>
  107. * The module provides implementation for all the functions required by the
  108. * management interface in SER, such as rpc->printf, rpc->add, rpc->struct_add
  109. * and so on. Whenever the management function calls one of the functions then
  110. * corresponding function in this module will be called to handle the request.
  111. *
  112. * The implementation functions build the reply, that will be sent to the
  113. * client, as they execute and they need to allocate memory to do that. That
  114. * memory must be freed again after the reply has been sent to the client. To
  115. * remember all the memory regions allocated during the execution of the
  116. * management function all functions within this module record all allocated
  117. * memory in the global variable called waste_bin. dispatch_rpc() functions
  118. * executes function collect_garbage() after the reply has been sent to the
  119. * client to free all memory that was allocated from the management function.
  120. * that was executed.
  121. *
  122. * <h2>Request Context</h2>
  123. * Before the module calls a management function it prepares a structure
  124. * called context. The context is defined in structure rpc_ctx and it is
  125. * passed as one of parameter to the management function being called. The
  126. * context contains all the data that is needed during the execution of the
  127. * management function, such as the pointer to the request being processed, a
  128. * pointer to the reply being built, and so on.
  129. *
  130. * Another parameter to the management function being called is a structure
  131. * that contains pointers to all implementation functions. This structure is
  132. * of type rpc_t, this module keeps one global variable of that type called
  133. * func_param and a pointer to that variable is passed to all management
  134. * functions. The global variable is initialized in mod_init().
  135. */
  136. /** @file
  137. *
  138. * This is the main file of XMLRPC SER module which contains all the functions
  139. * related to XML-RPC processing, as well as the module interface.
  140. */
  141. /*
  142. * FIXME: Decouple code and reason phrase from reply body
  143. * Escape special characters in strings
  144. */
  145. MODULE_VERSION
  146. #if defined (__OS_darwin) || defined (__OS_freebsd)
  147. /* redeclaration of functions from stdio.h throws errors */
  148. #else
  149. int snprintf(char *str, size_t size, const char *format, ...);
  150. int vsnprintf(char *str, size_t size, const char *format, va_list ap);
  151. #endif
  152. static int process_xmlrpc(sip_msg_t* msg);
  153. static int dispatch_rpc(sip_msg_t* msg, char* s1, char* s2);
  154. static int xmlrpc_reply(sip_msg_t* msg, char* code, char* reason);
  155. static int mod_init(void);
  156. /* first line (w/o the version) of the sip msg created from the http xmlrpc */
  157. #define XMLRPC_URI "sip:127.0.0.1:9"
  158. #define XMLRPC_URI_LEN (sizeof(XMLRPC_URI)-1)
  159. #define HTTP_GET "GET"
  160. #define HTTP_GET_LEN (sizeof(HTTP_GET)-1)
  161. #define HTTP_POST "POST"
  162. #define HTTP_POST_LEN (sizeof(HTTP_POST)-1)
  163. #define N_HTTP_GET 0x00746567U
  164. #define N_HTTP_POST 0x74736f70U
  165. #define LF "\n"
  166. /** The beginning of XML document indicating an error.
  167. *
  168. * This is the beginning of the XML document that will be sent back to the
  169. * client when the server encountered an error. It will be immediately
  170. * followed by a reason phrase.
  171. */
  172. #define FAULT_PREFIX \
  173. "<?xml version=\"1.0\"?>" LF \
  174. "<methodResponse>" LF \
  175. "<fault>" LF \
  176. "<value>" LF \
  177. "<struct>" LF \
  178. "<member>" LF \
  179. "<name>faultCode</name>" LF \
  180. "<value><int>"
  181. /** The text of XML document indicating error that goes between reason code
  182. * and reason phrase.
  183. */
  184. #define FAULT_BODY \
  185. "</int></value>" LF \
  186. "</member>" LF \
  187. "<member>" LF \
  188. "<name>faultString</name>" LF \
  189. "<value><string>"
  190. /** The end of XML document that indicates an error.
  191. *
  192. * This is the closing part of the XML-RPC document that indicates an error on
  193. * the server.
  194. */
  195. #define FAULT_SUFFIX \
  196. "</string></value>" LF \
  197. "</member>" LF \
  198. "</struct>" LF \
  199. "</value>" LF \
  200. "</fault>" LF \
  201. "</methodResponse>"
  202. /** The beginning of XML-RPC reply sent to the client.
  203. */
  204. #define SUCCESS_PREFIX \
  205. "<?xml version=\"1.0\"?>" LF \
  206. "<methodResponse>" LF \
  207. "<params>" LF \
  208. "<param>" LF \
  209. "<value>"
  210. /** The closing part of XML-RPC reply document sent to
  211. * the client.
  212. */
  213. #define SUCCESS_SUFFIX \
  214. "</value>" LF \
  215. "</param>" LF \
  216. "</params>" LF \
  217. "</methodResponse>"
  218. static str fault_prefix = STR_STATIC_INIT(FAULT_PREFIX);
  219. static str fault_body = STR_STATIC_INIT(FAULT_BODY);
  220. static str fault_suffix = STR_STATIC_INIT(FAULT_SUFFIX);
  221. static str success_prefix = STR_STATIC_INIT(SUCCESS_PREFIX);
  222. static str success_suffix = STR_STATIC_INIT(SUCCESS_SUFFIX);
  223. static str lf = STR_STATIC_INIT(LF);
  224. static str int_prefix = STR_STATIC_INIT("<int>");
  225. static str int_suffix = STR_STATIC_INIT("</int>");
  226. static str double_prefix = STR_STATIC_INIT("<double>");
  227. static str double_suffix = STR_STATIC_INIT("</double>");
  228. static str string_prefix = STR_STATIC_INIT("<string>");
  229. static str string_suffix = STR_STATIC_INIT("</string>");
  230. static str date_prefix = STR_STATIC_INIT("<dateTime.iso8601>");
  231. static str date_suffix = STR_STATIC_INIT("</dateTime.iso8601>");
  232. static str bool_prefix = STR_STATIC_INIT("<boolean>");
  233. static str bool_suffix = STR_STATIC_INIT("</boolean>");
  234. static str value_prefix = STR_STATIC_INIT("<value>");
  235. static str value_suffix = STR_STATIC_INIT("</value>");
  236. static str array_prefix = STR_STATIC_INIT("<array><data>" LF);
  237. static str array_suffix = STR_STATIC_INIT("</data></array>");
  238. static str struct_prefix = STR_STATIC_INIT("<struct>");
  239. static str struct_suffix = STR_STATIC_INIT("</struct>");
  240. static str member_prefix = STR_STATIC_INIT("<member>");
  241. static str member_suffix = STR_STATIC_INIT("</member>");
  242. static str name_prefix = STR_STATIC_INIT("<name>");
  243. static str name_suffix = STR_STATIC_INIT("</name>");
  244. /** Garbage collection data structure.
  245. *
  246. * This is the data structure used by the garbage collector in this module.
  247. * When the xmlrpc SER module identifies the management function to be called,
  248. * it calls corresponding function in SER. The function being called adds data
  249. * to the reply, that will be later sent to the client, as it executes. This
  250. * module needs to allocate memory for such data and the memory will be
  251. * re-claimed after the reply was sent out. All the memory allocated this way
  252. * is recorded in this data structure so that it can be identified and
  253. * re-claimed later (when the reply is being sent out).
  254. *
  255. */
  256. static struct garbage {
  257. enum {
  258. JUNK_XMLCHAR,
  259. JUNK_RPCSTRUCT, /**< This type indicates that the memory block was
  260. * allocated for the RPC structure data type, this
  261. * type needs to be freed differently as it may
  262. * contain more allocated memory blocks
  263. */
  264. JUNK_PKGCHAR /** This type indicates a pkg_malloc'ed string */
  265. } type; /**< Type of the memory block */
  266. void* ptr; /**< Pointer to the memory block obtained from
  267. pkg_malloc */
  268. struct garbage* next; /**< The linked list of all allocated memory
  269. blocks */
  270. } *waste_bin = 0;
  271. /** Representation of the XML-RPC reply being constructed.
  272. *
  273. * This data structure describes the XML-RPC reply that is being constructed
  274. * and will be sent to the client.
  275. */
  276. struct xmlrpc_reply {
  277. int code; /**< Reply code which indicates the type of the reply */
  278. char* reason; /**< Reason phrase text which provides human-readable
  279. * description that augments the reply code */
  280. str body; /**< The XML-RPC document body built so far */
  281. str buf; /**< The memory buffer allocated for the reply, this is
  282. * where the body attribute of the structure points to
  283. */
  284. };
  285. /** The context of the XML-RPC request being processed.
  286. *
  287. * This is the data structure that contains all data related to the XML-RPC
  288. * request being processed, such as the reply code and reason, data to be sent
  289. * to the client in the reply, and so on.
  290. *
  291. * There is always one context per XML-RPC request.
  292. */
  293. typedef struct rpc_ctx {
  294. sip_msg_t* msg; /**< The SIP/HTTP through which the RPC has been
  295. received */
  296. struct xmlrpc_reply reply; /**< XML-RPC reply to be sent to the client */
  297. struct rpc_struct* structs; /**< Structures to be added to the reply */
  298. int msg_shm_block_size; /**< non-zero for delayed reply contexts with
  299. shm cloned msgs */
  300. int reply_sent; /**< The flag is set after a reply is sent,
  301. this prevents a single reply being sent
  302. twice */
  303. char* method; /**< Name of the management function to be
  304. called */
  305. unsigned int flags; /**< Various flags, such as return value
  306. type */
  307. xmlDocPtr doc; /**< Pointer to the XML-RPC request
  308. document */
  309. xmlNodePtr act_param; /**< Pointer to the parameter being processed
  310. in the XML-RPC request document */
  311. } rpc_ctx_t;
  312. /* extra rpc_ctx_t flags */
  313. /* first 8 bits reserved for rpc flags (e.g. RET_ARRAY) */
  314. #define XMLRPC_DELAYED_CTX_F 256
  315. #define XMLRPC_DELAYED_REPLY_F 512
  316. /** The structure represents a XML-RPC document structure.
  317. *
  318. * This is the data structure that represents XML-RPC structures that are sent
  319. * to the client in the XML-RPC reply documents. A XML-RPC document structure
  320. * is compound consting of name-value pairs.
  321. * @sa http://www.xml-rpc.com
  322. */
  323. struct rpc_struct {
  324. xmlNodePtr struct_in; /**< Pointer to the structure parameter */
  325. struct xmlrpc_reply struct_out; /**< Structure to be sent in reply */
  326. struct xmlrpc_reply* reply; /**< Print errors here */
  327. int n; /**< Number of structure members
  328. created */
  329. xmlDocPtr doc; /**< XML-RPC document */
  330. int offset; /**< Offset in the reply where the
  331. structure should be printed */
  332. struct rpc_struct* nnext; /**< nested structure support - a recursive list of nested structrures */
  333. struct rpc_struct* parent; /**< access to parent structure - used for flattening structure before reply */
  334. struct rpc_struct* next;
  335. };
  336. /** The context of the XML-RPC request being processed.
  337. *
  338. * This is a global variable that records the context of the XML-RPC request
  339. * being currently processed.
  340. * @sa rpc_ctx
  341. */
  342. static rpc_ctx_t ctx;
  343. static void close_doc(rpc_ctx_t* ctx);
  344. static void set_fault(struct xmlrpc_reply* reply, int code, char* fmt, ...);
  345. static int fixup_xmlrpc_reply(void** param, int param_no);
  346. /** Pointers to the functions that implement the RPC interface
  347. * of xmlrpc SER module
  348. */
  349. static rpc_t func_param;
  350. /** Enable/disable additional introspection methods. If set to 1 then the
  351. * functions defined in http://scripts.incutio.com/xmlrpc/introspection.html
  352. * will be available on the server. If set to 0 then the functions will be
  353. * disabled.
  354. */
  355. static char* xmlrpc_route=0; /* default is the main route */
  356. /** Reference to the sl (stateless replies) module of SER The sl module of SER
  357. * is needed so that the xmlrpc SER module can send replies back to clients
  358. */
  359. sl_api_t slb;
  360. static int xmlrpc_route_no=DEFAULT_RT;
  361. /* if set, try autoconverting to the requested type if possible
  362. (e.g. convert 1 to "1" if string is requested) */
  363. static int autoconvert=0;
  364. /* in replies, escape CR to &#xD (according to the xml specs) */
  365. static int escape_cr=1; /* default on */
  366. /* convert double LF to CR LF (when on, LFLF becomes an escape for CRLF, needed
  367. with some xmlrpc clients that are not escaping CR to &#xD; )*/
  368. static int lflf2crlf=0; /* default off */
  369. /* do not register for non-sip requests */
  370. static int xmlrpc_mode = 0;
  371. static char* xmlrpc_url_match = NULL;
  372. static regex_t xmlrpc_url_match_regexp;
  373. static char* xmlrpc_url_skip = NULL;
  374. static regex_t xmlrpc_url_skip_regexp;
  375. /*
  376. * Exported functions
  377. */
  378. static cmd_export_t cmds[] = {
  379. {"dispatch_rpc", dispatch_rpc, 0, 0, REQUEST_ROUTE},
  380. {"xmlrpc_reply", xmlrpc_reply, 2, fixup_xmlrpc_reply, REQUEST_ROUTE},
  381. {0, 0, 0, 0, 0}
  382. };
  383. /*
  384. * Exported parameters
  385. */
  386. static param_export_t params[] = {
  387. {"route", PARAM_STRING, &xmlrpc_route},
  388. {"autoconversion", PARAM_INT, &autoconvert},
  389. {"escape_cr", PARAM_INT, &escape_cr},
  390. {"double_lf_to_crlf", PARAM_INT, &lflf2crlf},
  391. {"mode", PARAM_INT, &xmlrpc_mode},
  392. {"url_match", PARAM_STRING, &xmlrpc_url_match},
  393. {"url_skip", PARAM_STRING, &xmlrpc_url_skip},
  394. {0, 0, 0}
  395. };
  396. struct module_exports exports = {
  397. "xmlrpc",
  398. cmds, /* Exported commands */
  399. 0, /* Exported RPC methods */
  400. params, /* Exported parameters */
  401. mod_init, /* module initialization function */
  402. 0, /* response function*/
  403. 0, /* destroy function */
  404. 0, /* oncancel function */
  405. 0 /* per-child init function */
  406. };
  407. /* XML-RPC reply helper functions */
  408. #define ESC_LT "&lt;"
  409. #define ESC_AMP "&amp;"
  410. #define ESC_CR "&#xD;"
  411. static void clean_context(rpc_ctx_t* ctx);
  412. /** Adds arbitrary text to the XML-RPC reply being constructed, special
  413. * characters < and & will be escaped.
  414. *
  415. * This function adds arbitrary text to the body of the XML-RPC reply being
  416. * constructed. Note well that the function does not check whether the XML
  417. * document being constructed is well-formed or valid. Use with care.
  418. *
  419. * @param reply Pointer to the structure representing the XML-RPC reply
  420. * being constructed.
  421. * @param text The text to be appended to the XML-RPC reply.
  422. * @return -1 on error, 0 if the text was added successfuly.
  423. * @sa add_xmlrpc_reply()
  424. */
  425. static int add_xmlrpc_reply_esc(struct xmlrpc_reply* reply, str* text)
  426. {
  427. char* p;
  428. int i;
  429. for(i = 0; i < text->len; i++) {
  430. /* 10 must be bigger than size of longest escape sequence */
  431. if (reply->body.len >= reply->buf.len - 10) {
  432. p = pkg_malloc(reply->buf.len + 1024);
  433. if (!p) {
  434. set_fault(reply, 500,
  435. "Internal Server Error (No memory left)");
  436. ERR("No memory left: %d\n", reply->body.len + 1024);
  437. return -1;
  438. }
  439. memcpy(p, reply->body.s, reply->body.len);
  440. pkg_free(reply->buf.s);
  441. reply->buf.s = p;
  442. reply->buf.len += 1024;
  443. reply->body.s = p;
  444. }
  445. switch(text->s[i]) {
  446. case '<':
  447. memcpy(reply->body.s + reply->body.len, ESC_LT,
  448. sizeof(ESC_LT) - 1);
  449. reply->body.len += sizeof(ESC_LT) - 1;
  450. break;
  451. case '&':
  452. memcpy(reply->body.s + reply->body.len, ESC_AMP,
  453. sizeof(ESC_AMP) - 1);
  454. reply->body.len += sizeof(ESC_AMP) - 1;
  455. break;
  456. case '\r':
  457. if (likely(escape_cr)){
  458. memcpy(reply->body.s + reply->body.len, ESC_CR,
  459. sizeof(ESC_CR) - 1);
  460. reply->body.len += sizeof(ESC_CR) - 1;
  461. break;
  462. }
  463. /* no break */
  464. default:
  465. reply->body.s[reply->body.len] = text->s[i];
  466. reply->body.len++;
  467. break;
  468. }
  469. }
  470. return 0;
  471. }
  472. /** Add arbitrary text to the XML-RPC reply being constructed, no escaping
  473. * done.
  474. *
  475. * This is a more efficient version of add_xmlrpc_reply_esc(), the function
  476. * appends arbitrary text to the end of the XML-RPC reply being constructed,
  477. * but the text must not contain any characters that need to be escaped in
  478. * XML, such as < and & (or the characters must be escaped already).
  479. *
  480. * @param reply Pointer to the structure representing the XML-RPC reply
  481. * being constructed.
  482. * @param text The text to be appended to the XML-RPC reply.
  483. * @return -1 on error, 0 if the text was added successfuly.
  484. * @sa add_xmlrpc_reply_esc()
  485. */
  486. static int add_xmlrpc_reply(struct xmlrpc_reply* reply, str* text)
  487. {
  488. char* p;
  489. if (text->len > (reply->buf.len - reply->body.len)) {
  490. p = pkg_malloc(reply->buf.len + text->len + 1024);
  491. if (!p) {
  492. set_fault(reply, 500, "Internal Server Error (No memory left)");
  493. ERR("No memory left: %d\n", reply->buf.len + text->len + 1024);
  494. return -1;
  495. }
  496. memcpy(p, reply->body.s, reply->body.len);
  497. pkg_free(reply->buf.s);
  498. reply->buf.s = p;
  499. reply->buf.len += text->len + 1024;
  500. reply->body.s = p;
  501. }
  502. memcpy(reply->body.s + reply->body.len, text->s, text->len);
  503. reply->body.len += text->len;
  504. return 0;
  505. }
  506. /** Adds arbitrary text to the XML-RPC reply being constructed, the text will
  507. * be inserted at a specified offset within the XML-RPC reply.
  508. *
  509. * This function inserts arbitrary text in the XML-RPC reply that is being
  510. * constructed, unlike add_xmlrp_reply(), this function will not append the
  511. * text at the end of the reply, but it will insert the text in the middle of
  512. * the reply at the position provided to the function in "offset"
  513. * parameter. The function does not escape special characters and thus the
  514. * text must not contain such characters (or the must be escaped already).
  515. *
  516. * @param reply The XML-RPC reply structure representing the reply being
  517. * constructed.
  518. * @param offset The position of the first character where the text should be
  519. * inserted.
  520. * @param text The text to be inserted.
  521. * @return 0 of the text was inserted successfuly, a negative number on error.
  522. */
  523. static int add_xmlrpc_reply_offset(struct xmlrpc_reply* reply, unsigned int offset, str* text)
  524. {
  525. char* p;
  526. if (text->len > (reply->buf.len - reply->body.len)) {
  527. p = pkg_malloc(reply->buf.len + text->len + 1024);
  528. if (!p) {
  529. set_fault(reply, 500, "Internal Server Error (No memory left)");
  530. ERR("No memory left: %d\n", reply->buf.len + text->len + 1024);
  531. return -1;
  532. }
  533. memcpy(p, reply->body.s, reply->body.len);
  534. pkg_free(reply->buf.s);
  535. reply->buf.s = p;
  536. reply->buf.len += text->len + 1024;
  537. reply->body.s = p;
  538. }
  539. memmove(reply->body.s + offset + text->len, reply->body.s + offset,
  540. reply->body.len - offset);
  541. memcpy(reply->body.s + offset, text->s, text->len);
  542. reply->body.len += text->len;
  543. return 0;
  544. }
  545. /** Returns the current length of the XML-RPC reply body.
  546. *
  547. * @param reply The XML-RPC reply being constructed
  548. * @return Number of bytes of the XML-RPC reply body.
  549. */
  550. static unsigned int get_reply_len(struct xmlrpc_reply* reply)
  551. {
  552. return reply->body.len;
  553. }
  554. /* Resets XMLRPC reply body.
  555. *
  556. * This function discards everything that has been written so far and starts
  557. * constructing the XML-RPC reply body from the beginning.
  558. *
  559. * @param reply The XML-RPC reply being constructed.
  560. */
  561. static void reset_xmlrpc_reply(struct xmlrpc_reply* reply)
  562. {
  563. reply->body.len = 0;
  564. }
  565. /** Initialize XML-RPC reply data structure.
  566. *
  567. * This function initializes the data structure that contains all data related
  568. * to the XML-RPC reply being created. The function must be called before any
  569. * other function that adds data to the reply.
  570. * @param reply XML-RPC reply structure to be initialized.
  571. * @return 0 on success, a negative number on error.
  572. */
  573. static int init_xmlrpc_reply(struct xmlrpc_reply* reply)
  574. {
  575. reply->code = 200;
  576. reply->reason = "OK";
  577. reply->buf.s = pkg_malloc(1024);
  578. if (!reply->buf.s) {
  579. set_fault(reply, 500, "Internal Server Error (No memory left)");
  580. ERR("No memory left\n");
  581. return -1;
  582. }
  583. reply->buf.len = 1024;
  584. reply->body.s = reply->buf.s;
  585. reply->body.len = 0;
  586. return 0;
  587. }
  588. /** Clear the XML-RPC reply code and sets it back to a success reply.
  589. *
  590. * @param reply XML-RPC reply structure to be cleared.
  591. */
  592. static void clear_xmlrpc_reply(struct xmlrpc_reply* reply)
  593. {
  594. reply->code = 200;
  595. reply->reason = "OK";
  596. }
  597. /* if this a delayed reply context, and it's never been use before, fix it */
  598. static int fix_delayed_reply_ctx(rpc_ctx_t* ctx)
  599. {
  600. if ((ctx->flags & XMLRPC_DELAYED_CTX_F) && (ctx->reply.buf.s==0)){
  601. if (init_xmlrpc_reply(&ctx->reply) <0) return -1;
  602. add_xmlrpc_reply(&ctx->reply, &success_prefix);
  603. if (ctx->flags & RET_ARRAY)
  604. return add_xmlrpc_reply(&ctx->reply, &array_prefix);
  605. }
  606. return 0;
  607. }
  608. /** Free all memory used by the XML-RPC reply structure. */
  609. static void clean_xmlrpc_reply(struct xmlrpc_reply* reply)
  610. {
  611. if (reply->buf.s) pkg_free(reply->buf.s);
  612. }
  613. /** Create XML-RPC reply that indicates an error to the caller.
  614. *
  615. * This function is used to build the XML-RPC reply body that indicates that
  616. * an error ocurred on the server. It is called when a management function in
  617. * SER reports an error. The reply will contain the reason code and reason
  618. * phrase text provided by the management function that indicated the error.
  619. */
  620. static int build_fault_reply(struct xmlrpc_reply* reply)
  621. {
  622. str reason_s, code_s;
  623. reason_s.s = reply->reason;
  624. reason_s.len = strlen(reply->reason);
  625. code_s.s = int2str(reply->code, &code_s.len);
  626. reset_xmlrpc_reply(reply);
  627. if (add_xmlrpc_reply(reply, &fault_prefix) < 0) return -1;
  628. if (add_xmlrpc_reply_esc(reply, &code_s) < 0) return -1;
  629. if (add_xmlrpc_reply(reply, &fault_body) < 0) return -1;
  630. if (add_xmlrpc_reply_esc(reply, &reason_s) < 0) return -1;
  631. if (add_xmlrpc_reply(reply, &fault_suffix) < 0) return -1;
  632. return 0;
  633. }
  634. /** Add a memory registion to the list of memory blocks that
  635. * need to be re-claimed later.
  636. *
  637. * @param type The type of the memory block (ordinary text or structure).
  638. * @param ptr A pointer to the memory block.
  639. * @param reply The XML-RPC the memory block is associated with.
  640. * @return 0 on success, a negative number on error.
  641. * @sa collect_garbage()
  642. */
  643. static int add_garbage(int type, void* ptr, struct xmlrpc_reply* reply)
  644. {
  645. struct garbage* p;
  646. p = (struct garbage*)pkg_malloc(sizeof(struct garbage));
  647. if (!p) {
  648. set_fault(reply, 500, "Internal Server Error (No memory left)");
  649. ERR("Not enough memory\n");
  650. return -1;
  651. }
  652. p->type = type;
  653. p->ptr = ptr;
  654. p->next = waste_bin;
  655. waste_bin = p;
  656. return 0;
  657. }
  658. /** Re-claims all memory allocated in the process of building XML-RPC
  659. * reply.
  660. */
  661. static void collect_garbage(void)
  662. {
  663. struct rpc_struct* s;
  664. struct garbage* p;
  665. /* Collect garbage */
  666. while(waste_bin) {
  667. p = waste_bin;
  668. waste_bin = waste_bin->next;
  669. switch(p->type) {
  670. case JUNK_XMLCHAR:
  671. if (p->ptr) xmlFree(p->ptr);
  672. break;
  673. case JUNK_RPCSTRUCT:
  674. s = (struct rpc_struct*)p->ptr;
  675. if (s && s->struct_out.buf.s) pkg_free(s->struct_out.buf.s);
  676. if (s) pkg_free(s);
  677. break;
  678. case JUNK_PKGCHAR:
  679. if (p->ptr){
  680. pkg_free(p->ptr);
  681. p->ptr=0;
  682. }
  683. break;
  684. default:
  685. ERR("BUG: Unsupported junk type\n");
  686. }
  687. pkg_free(p);
  688. }
  689. }
  690. /** Extract XML-RPC query from a SIP/HTTP message.
  691. *
  692. * @param doc A pointer to string descriptor that will be filled
  693. * with the pointer to the beginning of the XML-RPC
  694. * document and length of the document.
  695. * @param msg A structure representing the SIP/HTTP message
  696. * carrying the XML-RPC document in body.
  697. */
  698. static int get_rpc_document(str* doc, sip_msg_t* msg)
  699. {
  700. doc->s = get_body(msg);
  701. if (!doc->s) {
  702. ERR("Error while extracting message body\n");
  703. return -1;
  704. }
  705. doc->len = strlen(doc->s);
  706. return 0;
  707. }
  708. /** Send a reply to the client with given body.
  709. *
  710. * This function sends a 200 OK reply back to the client, the body of the
  711. * reply will contain text provided to the function in "body" parameter.
  712. *
  713. * @param msg The request that generated the reply.
  714. * @param body The text that will be put in the body of the reply.
  715. */
  716. static int send_reply(sip_msg_t* msg, str* body)
  717. {
  718. if (add_lump_rpl(msg, body->s, body->len, LUMP_RPL_BODY) < 0) {
  719. ERR("Error while adding reply lump\n");
  720. return -1;
  721. }
  722. if (slb.zreply(msg, 200, "OK") == -1) {
  723. ERR("Error while sending reply\n");
  724. return -1;
  725. }
  726. return 0;
  727. }
  728. static int flatten_nests(struct rpc_struct* st, struct xmlrpc_reply* reply) {
  729. if (!st)
  730. return 1;
  731. if (!st->nnext) {
  732. if (add_xmlrpc_reply(&st->struct_out, &struct_suffix) < 0) return -1;
  733. if (add_xmlrpc_reply_offset(&st->parent->struct_out, st->offset, &st->struct_out.body) < 0) return -1;
  734. } else {
  735. flatten_nests(st->nnext, reply);
  736. if (add_xmlrpc_reply(&st->struct_out, &struct_suffix) < 0) return -1;
  737. if (add_xmlrpc_reply_offset(&st->parent->struct_out, st->offset, &st->struct_out.body) < 0) return -1;
  738. }
  739. return 1;
  740. }
  741. static int print_structures(struct xmlrpc_reply* reply,
  742. struct rpc_struct* st)
  743. {
  744. while(st) {
  745. /* Close the structure first */
  746. if (add_xmlrpc_reply(&st->struct_out, &struct_suffix) < 0) return -1;
  747. if (flatten_nests(st->nnext, &st->struct_out) < 0) return -1;
  748. if (add_xmlrpc_reply_offset(reply, st->offset, &st->struct_out.body) < 0) return -1;
  749. st = st->next;
  750. }
  751. return 0;
  752. }
  753. /** Implementation of rpc_send function required by the management API in SER.
  754. *
  755. * This is the function that will be called whenever a management function in
  756. * SER asks the management interface to send the reply to the client. The
  757. * function will generate the XML-RPC document, put it in body of a SIP
  758. * response and send the response to the client. The SIP/HTTP reply sent to
  759. * the client will be always 200 OK, if an error ocurred on the server then it
  760. * will be indicated in the XML document in body.
  761. *
  762. * @param ctx A pointer to the context structure of the XML-RPC request that
  763. * generated the reply.
  764. * @return 1 if the reply was already sent, 0 on success, a negative number on
  765. * error
  766. */
  767. static int rpc_send(rpc_ctx_t* ctx)
  768. {
  769. struct xmlrpc_reply* reply;
  770. if (ctx->reply_sent) return 1;
  771. reply = &ctx->reply;
  772. if (reply->code >= 300) {
  773. if (build_fault_reply(reply) < 0) return -1;
  774. } else {
  775. if (ctx->flags & RET_ARRAY &&
  776. add_xmlrpc_reply(reply, &array_suffix) < 0) return -1;
  777. if (ctx->structs &&
  778. print_structures(reply, ctx->structs) < 0) return -1;
  779. if (add_xmlrpc_reply(reply, &success_suffix) < 0) return -1;
  780. }
  781. if (send_reply(ctx->msg, &reply->body) < 0) return -1;
  782. ctx->reply_sent = 1;
  783. return 0;
  784. }
  785. #define REASON_BUF_LEN 1024
  786. static void set_fault(struct xmlrpc_reply* reply, int code, char* fmt, ...)
  787. {
  788. static char buf[REASON_BUF_LEN];
  789. va_list ap;
  790. reply->code = code;
  791. va_start(ap, fmt);
  792. vsnprintf(buf, REASON_BUF_LEN, fmt, ap);
  793. va_end(ap);
  794. reply->reason = buf;
  795. }
  796. /** Implementation of rpc_fault function required by the management API in
  797. * SER.
  798. *
  799. * This function will be called whenever a management function in SER
  800. * indicates that an error ocurred while it was processing the request. The
  801. * function takes the reply code and reason phrase as parameters, these will
  802. * be put in the body of the reply.
  803. *
  804. * @param ctx A pointer to the context structure of the request being
  805. * processed.
  806. * @param code Reason code.
  807. * @param fmt Formatting string used to build the reason phrase.
  808. */
  809. static void rpc_fault(rpc_ctx_t* ctx, int code, char* fmt, ...)
  810. {
  811. static char buf[REASON_BUF_LEN];
  812. va_list ap;
  813. ctx->reply.code = code;
  814. va_start(ap, fmt);
  815. vsnprintf(buf, REASON_BUF_LEN, fmt, ap);
  816. va_end(ap);
  817. ctx->reply.reason = buf;
  818. }
  819. /** Create and initialize a new rpc_structure data structure.
  820. *
  821. * This function allocates and initializes memory for a new rpc_struct
  822. * structure. If the caller provided non-NULL pointers in doc and structure
  823. * parameters then the structure is coming from an XML-RPC request. If either
  824. * of the pointers is NULL then we are creating a structure that will be
  825. * attached to a XML-RPC reply sent to the client. The memory allocated in
  826. * this function will be added to the garbage collection list.
  827. *
  828. * @param doc A pointer to the XML-RPC request document or NULL if we create
  829. * a structure that will be put in a reply.
  830. * @param structure A pointer to opening tag of the structure in the XML-RPC
  831. * request document or NULL if we create a structure that
  832. * will be put in a XML-RPC reply.
  833. * @param reply A pointer to xml_reply structure, NULL if it is a structure
  834. * coming from a XML-RPC request.
  835. */
  836. static struct rpc_struct* new_rpcstruct(xmlDocPtr doc, xmlNodePtr structure,
  837. struct xmlrpc_reply* reply)
  838. {
  839. struct rpc_struct* p;
  840. p = (struct rpc_struct*)pkg_malloc(sizeof(struct rpc_struct));
  841. if (!p) {
  842. set_fault(reply, 500, "Internal Server Error (No Memory Left");
  843. return 0;
  844. }
  845. memset(p, 0, sizeof(struct rpc_struct));
  846. p->struct_in = structure;
  847. p->reply = reply;
  848. p->n = 0;
  849. if (doc && structure) {
  850. /* We will be parsing structure from request */
  851. p->doc = doc;
  852. p->struct_in = structure;
  853. } else {
  854. /* We will build a reply structure */
  855. if (init_xmlrpc_reply(&p->struct_out) < 0) goto err;
  856. if (add_xmlrpc_reply(&p->struct_out, &struct_prefix) < 0) goto err;
  857. }
  858. if (add_garbage(JUNK_RPCSTRUCT, p, reply) < 0) goto err;
  859. return p;
  860. err:
  861. if (p->struct_out.buf.s) pkg_free(p->struct_out.buf.s);
  862. pkg_free(p);
  863. return 0;
  864. }
  865. /** Converts the variables provided in parameter ap according to formatting
  866. * string provided in parameter fmt into parameters in XML-RPC format.
  867. *
  868. * This function takes the parameters provided in ap parameter and creates
  869. * XML-RPC formatted parameters that will be put in the document in res
  870. * parameter. The format of input parameters is described in formatting string
  871. * fmt which follows the syntax of the management API in SER. In the case of
  872. * an error the function will generate an error reply in err_reply parameter
  873. * instead.
  874. * @param res A pointer to the XML-RPC result structure where the parameters
  875. * will be written.
  876. * @param err_reply An error reply document will be generated here if the
  877. * function encounters a problem while processing input
  878. * parameters.
  879. * @param fmt Formatting string of the management API in SER.
  880. * @param ap A pointer to the array of input parameters.
  881. *
  882. */
  883. static int print_value(struct xmlrpc_reply* res,
  884. struct xmlrpc_reply* err_reply, char fmt, va_list* ap)
  885. {
  886. str prefix, body, suffix;
  887. str* sp;
  888. char buf[256];
  889. time_t dt;
  890. struct tm* t;
  891. switch(fmt) {
  892. case 'd':
  893. prefix = int_prefix;
  894. suffix = int_suffix;
  895. body.s = int2str(va_arg(*ap, int), &body.len);
  896. break;
  897. case 'f':
  898. prefix = double_prefix;
  899. suffix = double_suffix;
  900. body.s = buf;
  901. body.len = snprintf(buf, 256, "%f", va_arg(*ap, double));
  902. if (body.len < 0) {
  903. set_fault(err_reply, 400, "Error While Converting double");
  904. ERR("Error while converting double\n");
  905. goto err;
  906. }
  907. break;
  908. case 'b':
  909. prefix = bool_prefix;
  910. suffix = bool_suffix;
  911. body.len = 1;
  912. body.s = ((va_arg(*ap, int) == 0) ? "0" : "1");
  913. break;
  914. case 't':
  915. prefix = date_prefix;
  916. suffix = date_suffix;
  917. body.s = buf;
  918. body.len = sizeof("19980717T14:08:55") - 1;
  919. dt = va_arg(*ap, time_t);
  920. t = gmtime(&dt);
  921. if (strftime(buf, 256, "%Y%m%dT%H:%M:%S", t) == 0) {
  922. set_fault(err_reply, 400, "Error While Converting datetime");
  923. ERR("Error while converting time\n");
  924. goto err;
  925. }
  926. break;
  927. case 's':
  928. prefix = string_prefix;
  929. suffix = string_suffix;
  930. body.s = va_arg(*ap, char*);
  931. body.len = strlen(body.s);
  932. break;
  933. case 'S':
  934. prefix = string_prefix;
  935. suffix = string_suffix;
  936. sp = va_arg(*ap, str*);
  937. body = *sp;
  938. break;
  939. default:
  940. set_fault(err_reply, 500, "Bug In SER (Invalid formatting character)");
  941. ERR("Invalid formatting character [%c]\n", fmt);
  942. goto err;
  943. }
  944. if (add_xmlrpc_reply(res, &prefix) < 0) goto err;
  945. if (add_xmlrpc_reply_esc(res, &body) < 0) goto err;
  946. if (add_xmlrpc_reply(res, &suffix) < 0) goto err;
  947. return 0;
  948. err:
  949. return -1;
  950. }
  951. /** Implementation of rpc_add function required by the management API in SER.
  952. *
  953. * This function will be called when a management function in SER calls
  954. * rpc->add to add a parameter to the XML-RPC reply being generated.
  955. */
  956. static int rpc_add(rpc_ctx_t* ctx, char* fmt, ...)
  957. {
  958. void* void_ptr;
  959. va_list ap;
  960. struct xmlrpc_reply* reply;
  961. struct rpc_struct* p;
  962. fix_delayed_reply_ctx(ctx);
  963. va_start(ap, fmt);
  964. reply = &ctx->reply;
  965. while(*fmt) {
  966. if (ctx->flags & RET_ARRAY &&
  967. add_xmlrpc_reply(reply, &value_prefix) < 0) goto err;
  968. if (*fmt == '{') {
  969. void_ptr = va_arg(ap, void**);
  970. p = new_rpcstruct(0, 0, reply);
  971. if (!p) goto err;
  972. *(struct rpc_struct**)void_ptr = p;
  973. p->offset = get_reply_len(reply);
  974. p->next = ctx->structs;
  975. ctx->structs = p;
  976. } else {
  977. if (print_value(reply, reply, *fmt, &ap) < 0) goto err;
  978. }
  979. if (ctx->flags & RET_ARRAY &&
  980. add_xmlrpc_reply(reply, &value_suffix) < 0) goto err;
  981. if (add_xmlrpc_reply(reply, &lf) < 0) goto err;
  982. fmt++;
  983. }
  984. va_end(ap);
  985. return 0;
  986. err:
  987. va_end(ap);
  988. return -1;
  989. }
  990. /** Convert time in XML-RPC format to time_t */
  991. static time_t xmlrpc2time(const char* str)
  992. {
  993. struct tm time;
  994. memset(&time, '\0', sizeof(struct tm));
  995. strptime(str, "%Y%m%dT%H:%M:%S", &time);
  996. time.tm_isdst = -1;
  997. #ifdef HAVE_TIMEGM
  998. return timegm(&time);
  999. #else
  1000. return _timegm(&time);
  1001. #endif /* HAVE_TIMEGM */
  1002. }
  1003. /* get_* flags: */
  1004. #define GET_X_AUTOCONV 1
  1005. #define GET_X_NOREPLY 2
  1006. #define GET_X_LFLF2CRLF 4 /* replace "\n\n" with "\r\n" */
  1007. /* xml value types */
  1008. enum xmlrpc_val_type{
  1009. XML_T_STR,
  1010. XML_T_TXT,
  1011. XML_T_INT,
  1012. XML_T_BOOL,
  1013. XML_T_DATE,
  1014. XML_T_DOUBLE,
  1015. XML_T_ERR=-1
  1016. };
  1017. /** Returns the XML-RPC value type.
  1018. * @return value type (>= on success, XML_T_ERR on error/unknown type)
  1019. */
  1020. static enum xmlrpc_val_type xml_get_type(xmlNodePtr value)
  1021. {
  1022. if (!xmlStrcmp(value->name, BAD_CAST "string")){
  1023. return XML_T_STR;
  1024. } else if (!xmlStrcmp(value->name, BAD_CAST "text")) {
  1025. return XML_T_TXT;
  1026. } else if ( !xmlStrcmp(value->name, BAD_CAST "i4") ||
  1027. !xmlStrcmp(value->name, BAD_CAST "int")) {
  1028. return XML_T_INT;
  1029. } else if (!xmlStrcmp(value->name, BAD_CAST "boolean")) {
  1030. return XML_T_BOOL;
  1031. } else if (!xmlStrcmp(value->name, BAD_CAST "dateTime.iso8601")) {
  1032. return XML_T_DATE;
  1033. }else if (!(xmlStrcmp(value->name, BAD_CAST "double"))){
  1034. return XML_T_DOUBLE;
  1035. }
  1036. return XML_T_ERR;
  1037. }
  1038. /** Converts an XML-RPC encoded parameter into integer if possible.
  1039. *
  1040. * This function receives a pointer to a parameter encoded in XML-RPC format
  1041. * and tries to convert the value of the parameter into integer. Only
  1042. * &lt;i4&gt;, &lt;int&gt;, &lt;boolean&gt;, &lt;dateTime.iso8601&gt; XML-RPC
  1043. * parameters can be converted to integer, attempts to conver other types will
  1044. * fail.
  1045. * @param val A pointer to an integer variable where the result will be
  1046. * stored.
  1047. * @param reply A pointer to XML-RPC reply being constructed (used to
  1048. * indicate conversion errors).
  1049. * @param doc A pointer to the XML-RPC request document.
  1050. * @param value A pointer to the element containing the parameter to be
  1051. * converted within the document.
  1052. * @param flags : GET_X_AUTOCONV - try autoconverting
  1053. * GET_X_NOREPLY - do not reply
  1054. * @return <0 on error, 0 on success
  1055. */
  1056. static int get_int(int* val, struct xmlrpc_reply* reply,
  1057. xmlDocPtr doc, xmlNodePtr value, int flags)
  1058. {
  1059. enum xmlrpc_val_type type;
  1060. int ret;
  1061. xmlNodePtr i4;
  1062. char* val_str;
  1063. char* end_ptr;
  1064. if (!value || xmlStrcmp(value->name, BAD_CAST "value")) {
  1065. if (!(flags & GET_X_NOREPLY))
  1066. set_fault(reply, 400, "Invalid parameter value");
  1067. return -1;
  1068. }
  1069. i4 = value->xmlChildrenNode;
  1070. if (!i4){
  1071. if (!(flags & GET_X_NOREPLY))
  1072. set_fault(reply, 400, "Invalid Parameter Type");
  1073. return -1;
  1074. }
  1075. type=xml_get_type(i4);
  1076. switch(type){
  1077. case XML_T_INT:
  1078. case XML_T_BOOL:
  1079. case XML_T_DATE:
  1080. break;
  1081. case XML_T_DOUBLE:
  1082. case XML_T_STR:
  1083. case XML_T_TXT:
  1084. if (flags & GET_X_AUTOCONV)
  1085. break;
  1086. case XML_T_ERR:
  1087. if (!(flags & GET_X_NOREPLY))
  1088. set_fault(reply, 400, "Invalid Parameter Type");
  1089. return -1;
  1090. }
  1091. if (type == XML_T_TXT)
  1092. val_str = (char*)i4->content;
  1093. else
  1094. val_str = (char*)xmlNodeListGetString(doc, i4->xmlChildrenNode, 1);
  1095. if (!val_str) {
  1096. if (!(flags & GET_X_NOREPLY))
  1097. set_fault(reply, 400, "Empty Parameter Value");
  1098. return -1;
  1099. }
  1100. ret=0;
  1101. switch(type){
  1102. case XML_T_INT:
  1103. case XML_T_BOOL:
  1104. case XML_T_STR:
  1105. case XML_T_TXT:
  1106. /* Integer/bool conversion */
  1107. *val = strtol(val_str, &end_ptr, 10);
  1108. if (val_str==end_ptr)
  1109. ret=-1;
  1110. break;
  1111. case XML_T_DATE:
  1112. *val = xmlrpc2time(val_str);
  1113. break;
  1114. case XML_T_DOUBLE:
  1115. *val = (int)strtod(val_str, &end_ptr);
  1116. if (val_str==end_ptr)
  1117. ret=-1;
  1118. break;
  1119. case XML_T_ERR:
  1120. *val=0;
  1121. ret=-1;
  1122. break;
  1123. }
  1124. xmlFree(val_str);
  1125. if (ret==-1 && !(flags & GET_X_NOREPLY))
  1126. set_fault(reply, 400, "Invalid Value");
  1127. return ret;
  1128. }
  1129. /** Converts an XML-RPC encoded parameter into double if possible.
  1130. *
  1131. * This function receives a pointer to a parameter encoded in XML-RPC format
  1132. * and tries to convert the value of the parameter into double. Only
  1133. * &lt;i4&gt;, &lt;int&gt;, &lt;double&gt; XML-RPC parameters can be converted
  1134. * to double, attempts to conver other types will fail.
  1135. * @param val A pointer to an integer variable where the result will be
  1136. * stored.
  1137. * @param reply A pointer to XML-RPC reply being constructed (used to indicate
  1138. * conversion errors).
  1139. * @param doc A pointer to the XML-RPC request document.
  1140. * @param value A pointer to the element containing the parameter to be
  1141. * converted within the document.
  1142. * @param flags : GET_X_AUTOCONV - try autoconverting
  1143. * GET_X_NOREPLY - do not reply
  1144. * @return <0 on error, 0 on success
  1145. */
  1146. static int get_double(double* val, struct xmlrpc_reply* reply,
  1147. xmlDocPtr doc, xmlNodePtr value, int flags)
  1148. {
  1149. xmlNodePtr dbl;
  1150. char* val_str;
  1151. char* end_ptr;
  1152. enum xmlrpc_val_type type;
  1153. int ret;
  1154. if (!value || xmlStrcmp(value->name, BAD_CAST "value")) {
  1155. if (!(flags & GET_X_NOREPLY))
  1156. set_fault(reply, 400, "Invalid Parameter Value");
  1157. return -1;
  1158. }
  1159. dbl = value->xmlChildrenNode;
  1160. if (!dbl){
  1161. if (!(flags & GET_X_NOREPLY))
  1162. set_fault(reply, 400, "Invalid Parameter Type");
  1163. return -1;
  1164. }
  1165. type=xml_get_type(dbl);
  1166. switch(type){
  1167. case XML_T_DOUBLE:
  1168. case XML_T_INT:
  1169. break;
  1170. case XML_T_BOOL:
  1171. case XML_T_DATE:
  1172. case XML_T_STR:
  1173. case XML_T_TXT:
  1174. if (flags & GET_X_AUTOCONV)
  1175. break;
  1176. case XML_T_ERR:
  1177. if (!(flags & GET_X_NOREPLY))
  1178. set_fault(reply, 400, "Invalid Parameter Type");
  1179. return -1;
  1180. }
  1181. if (type == XML_T_TXT)
  1182. val_str = (char*)dbl->content;
  1183. else
  1184. val_str = (char*)xmlNodeListGetString(doc, dbl->xmlChildrenNode, 1);
  1185. if (!val_str) {
  1186. if (!(flags & GET_X_NOREPLY))
  1187. set_fault(reply, 400, "Empty Double Parameter");
  1188. return -1;
  1189. }
  1190. ret=0;
  1191. switch(type){
  1192. case XML_T_DOUBLE:
  1193. case XML_T_INT:
  1194. case XML_T_BOOL:
  1195. case XML_T_STR:
  1196. case XML_T_TXT:
  1197. *val = strtod(val_str, &end_ptr);
  1198. if (val_str==end_ptr)
  1199. ret=-1;
  1200. break;
  1201. case XML_T_DATE:
  1202. *val = (double)xmlrpc2time(val_str);
  1203. break;
  1204. case XML_T_ERR:
  1205. *val=0;
  1206. ret=-1;
  1207. break;
  1208. }
  1209. xmlFree(val_str);
  1210. if (ret==-1 && !(flags & GET_X_NOREPLY))
  1211. set_fault(reply, 400, "Invalid Value");
  1212. return ret;
  1213. }
  1214. /** Convert a parameter encoded in XML-RPC to a zero terminated string.
  1215. *
  1216. * @param val A pointer to a char* variable where the result will be
  1217. * stored (the result is dynamically allocated, but it's garbage
  1218. * collected, so it doesn't have to be freed)
  1219. * @param reply A pointer to XML-RPC reply being constructed (used to indicate
  1220. * conversion errors).
  1221. * @param doc A pointer to the XML-RPC request document.
  1222. * @param value A pointer to the element containing the parameter to be
  1223. * converted within the document.
  1224. * @param flags
  1225. * - GET_X_AUTOCONV - try autoconverting
  1226. * - GET_X_LFLF2CRLF - replace double '\\n' with `\\r\\n'
  1227. * - GET_X_NOREPLY - do not reply
  1228. * @return <0 on error, 0 on success
  1229. */
  1230. static int get_string(char** val, struct xmlrpc_reply* reply,
  1231. xmlDocPtr doc, xmlNodePtr value, int flags)
  1232. {
  1233. static char* null_str = "";
  1234. xmlNodePtr dbl;
  1235. char* val_str;
  1236. char* end_ptr;
  1237. char* s;
  1238. char* p;
  1239. int i;
  1240. int len;
  1241. enum xmlrpc_val_type type;
  1242. int ret;
  1243. if (!value || xmlStrcmp(value->name, BAD_CAST "value")) {
  1244. if (!(flags & GET_X_NOREPLY))
  1245. set_fault(reply, 400, "Invalid Parameter Value");
  1246. return -1;
  1247. }
  1248. dbl = value->xmlChildrenNode;
  1249. if (!dbl){
  1250. if (!(flags & GET_X_NOREPLY))
  1251. set_fault(reply, 400, "Invalid Parameter Type");
  1252. return -1;
  1253. }
  1254. type=xml_get_type(dbl);
  1255. switch(type){
  1256. case XML_T_STR:
  1257. case XML_T_TXT:
  1258. break;
  1259. case XML_T_INT:
  1260. case XML_T_BOOL:
  1261. case XML_T_DATE:
  1262. case XML_T_DOUBLE:
  1263. if (flags & GET_X_AUTOCONV)
  1264. break;
  1265. case XML_T_ERR:
  1266. if (!(flags & GET_X_NOREPLY))
  1267. set_fault(reply, 400, "Invalid Parameter Type");
  1268. return -1;
  1269. }
  1270. if (type == XML_T_TXT)
  1271. val_str = (char*)dbl->content;
  1272. else
  1273. val_str = (char*)xmlNodeListGetString(doc, dbl->xmlChildrenNode, 1);
  1274. if (!val_str) {
  1275. if (type==XML_T_STR || type==XML_T_TXT){
  1276. *val = null_str;
  1277. return 0;
  1278. }else{
  1279. if (!(flags & GET_X_NOREPLY))
  1280. set_fault(reply, 400, "Empty Parameter Value");
  1281. return -1;
  1282. }
  1283. }
  1284. ret=0;
  1285. switch(type){
  1286. case XML_T_STR:
  1287. case XML_T_TXT:
  1288. if (flags & GET_X_LFLF2CRLF){
  1289. p=val_str;
  1290. while(*p){
  1291. if (*p=='\n' && *(p+1)=='\n'){
  1292. *p='\r';
  1293. p+=2;
  1294. continue;
  1295. }
  1296. p++;
  1297. }
  1298. }
  1299. /* no break */
  1300. case XML_T_DATE: /* no special conversion */
  1301. case XML_T_DOUBLE: /* no special conversion */
  1302. if (add_garbage(JUNK_XMLCHAR, val_str, reply) < 0){
  1303. xmlFree(val_str);
  1304. return -1;
  1305. }
  1306. *val = val_str;
  1307. break;
  1308. case XML_T_INT:
  1309. case XML_T_BOOL:
  1310. /* convert str to int an back to str */
  1311. i = strtol(val_str, &end_ptr, 10);
  1312. if (val_str==end_ptr){
  1313. ret=-1;
  1314. }else{
  1315. s=sint2str(i, &len);
  1316. p=pkg_malloc(len+1);
  1317. if (p && add_garbage(JUNK_PKGCHAR, p, reply) == 0){
  1318. memcpy(p, s, len);
  1319. p[len]=0;
  1320. *val=p;
  1321. }else{
  1322. ret=-1;
  1323. if (p) pkg_free(p);
  1324. }
  1325. }
  1326. xmlFree(val_str);
  1327. break;
  1328. case XML_T_ERR:
  1329. xmlFree(val_str);
  1330. ret=-1;
  1331. break;
  1332. }
  1333. return ret;
  1334. }
  1335. /** Implementation of rpc->scan function required by the management API in
  1336. * SER.
  1337. *
  1338. * This is the function that will be called whenever a management function in
  1339. * SER calls rpc->scan to get the value of parameter from the XML-RPC
  1340. * request. This function will extract the current parameter from the XML-RPC
  1341. * document and attempts to convert it to the type requested by the management
  1342. * function that called it.
  1343. */
  1344. static int rpc_scan(rpc_ctx_t* ctx, char* fmt, ...)
  1345. {
  1346. int read;
  1347. int* int_ptr;
  1348. char** char_ptr;
  1349. str* str_ptr;
  1350. double* double_ptr;
  1351. void** void_ptr;
  1352. xmlNodePtr value;
  1353. struct xmlrpc_reply* reply;
  1354. struct rpc_struct* p;
  1355. int modifiers;
  1356. int f;
  1357. va_list ap;
  1358. reply = &ctx->reply;
  1359. /* clear the previously saved error code */
  1360. clear_xmlrpc_reply(reply);
  1361. va_start(ap, fmt);
  1362. modifiers=0;
  1363. read = 0;
  1364. f=(autoconvert?GET_X_AUTOCONV:0) |
  1365. (lflf2crlf?GET_X_LFLF2CRLF:0);
  1366. while(*fmt) {
  1367. if (!ctx->act_param) goto error;
  1368. value = ctx->act_param->xmlChildrenNode;
  1369. switch(*fmt) {
  1370. case '*': /* start of optional parameters */
  1371. modifiers++;
  1372. read++;
  1373. fmt++;
  1374. continue; /* do not advance ctx->act-param */
  1375. case '.': /* autoconvert */
  1376. modifiers++;
  1377. read++;
  1378. fmt++;
  1379. f|=GET_X_AUTOCONV;
  1380. continue; /* do not advance ctx->act-param */
  1381. case 'b': /* Bool */
  1382. case 't': /* Date and time */
  1383. case 'd': /* Integer */
  1384. int_ptr = va_arg(ap, int*);
  1385. if (get_int(int_ptr, reply, ctx->doc, value, f) < 0) goto error;
  1386. break;
  1387. case 'f': /* double */
  1388. double_ptr = va_arg(ap, double*);
  1389. if (get_double(double_ptr, reply, ctx->doc, value, f) < 0) {
  1390. goto error;
  1391. }
  1392. break;
  1393. case 's': /* zero terminated string */
  1394. char_ptr = va_arg(ap, char**);
  1395. if (get_string(char_ptr, reply, ctx->doc, value, f) < 0)
  1396. goto error;
  1397. break;
  1398. case 'S': /* str structure */
  1399. str_ptr = va_arg(ap, str*);
  1400. if (get_string(&str_ptr->s, reply, ctx->doc, value, f) < 0) {
  1401. goto error;
  1402. }
  1403. str_ptr->len = strlen(str_ptr->s);
  1404. break;
  1405. case '{':
  1406. void_ptr = va_arg(ap, void**);
  1407. if (!value->xmlChildrenNode) goto error;
  1408. p = new_rpcstruct(ctx->doc, value->xmlChildrenNode, reply);
  1409. if (!p) goto error;
  1410. *void_ptr = p;
  1411. break;
  1412. default:
  1413. ERR("Invalid parameter type in formatting string: %c\n", *fmt);
  1414. set_fault(reply, 500,
  1415. "Server Internal Error (Invalid Formatting String)");
  1416. goto error;
  1417. }
  1418. ctx->act_param = ctx->act_param->next;
  1419. /* clear autoconv if not globally on */
  1420. f=autoconvert?GET_X_AUTOCONV:(f&~GET_X_AUTOCONV);
  1421. read++;
  1422. fmt++;
  1423. }
  1424. va_end(ap);
  1425. return read-modifiers;
  1426. error:
  1427. va_end(ap);
  1428. return -(read-modifiers);
  1429. }
  1430. #define RPC_BUF_SIZE 1024
  1431. /** Implementation of rpc_printf function required by the management API in
  1432. * SER.
  1433. *
  1434. * This function will be called whenever a management function in SER calls
  1435. * rpc-printf to add a parameter to the XML-RPC reply being constructed.
  1436. */
  1437. static int rpc_printf(rpc_ctx_t* ctx, char* fmt, ...)
  1438. {
  1439. int n, buf_size;
  1440. char* buf;
  1441. va_list ap;
  1442. str s;
  1443. struct xmlrpc_reply* reply;
  1444. fix_delayed_reply_ctx(ctx);
  1445. reply = &ctx->reply;
  1446. buf = (char*)pkg_malloc(RPC_BUF_SIZE);
  1447. if (!buf) {
  1448. set_fault(reply, 500, "Internal Server Error (No memory left)");
  1449. ERR("No memory left\n");
  1450. return -1;
  1451. }
  1452. buf_size = RPC_BUF_SIZE;
  1453. while (1) {
  1454. /* Try to print in the allocated space. */
  1455. va_start(ap, fmt);
  1456. n = vsnprintf(buf, buf_size, fmt, ap);
  1457. va_end(ap);
  1458. /* If that worked, return the string. */
  1459. if (n > -1 && n < buf_size) {
  1460. s.s = buf;
  1461. s.len = n;
  1462. if (ctx->flags & RET_ARRAY &&
  1463. add_xmlrpc_reply(reply, &value_prefix) < 0) goto err;
  1464. if (add_xmlrpc_reply(reply, &string_prefix) < 0) goto err;
  1465. if (add_xmlrpc_reply_esc(reply, &s) < 0) goto err;
  1466. if (add_xmlrpc_reply(reply, &string_suffix) < 0) goto err;
  1467. if (ctx->flags & RET_ARRAY &&
  1468. add_xmlrpc_reply(reply, &value_suffix) < 0) goto err;
  1469. if (add_xmlrpc_reply(reply, &lf) < 0) goto err;
  1470. pkg_free(buf);
  1471. return 0;
  1472. }
  1473. /* Else try again with more space. */
  1474. if (n > -1) { /* glibc 2.1 */
  1475. buf_size = n + 1; /* precisely what is needed */
  1476. } else { /* glibc 2.0 */
  1477. buf_size *= 2; /* twice the old size */
  1478. }
  1479. if ((buf = pkg_realloc(buf, buf_size)) == 0) {
  1480. set_fault(reply, 500, "Internal Server Error (No memory left)");
  1481. ERR("No memory left\n");
  1482. goto err;
  1483. }
  1484. }
  1485. return 0;
  1486. err:
  1487. if (buf) pkg_free(buf);
  1488. return -1;
  1489. }
  1490. /* Structure manipulation functions */
  1491. /** Find a structure member by name.
  1492. */
  1493. static int find_member(xmlNodePtr* value, xmlDocPtr doc, xmlNodePtr structure,
  1494. struct xmlrpc_reply* reply, char* member_name)
  1495. {
  1496. char* name_str;
  1497. xmlNodePtr member, name;
  1498. if (!structure) {
  1499. set_fault(reply, 400, "Invalid Structure Parameter");
  1500. return -1;
  1501. }
  1502. member = structure->xmlChildrenNode;
  1503. while(member) {
  1504. name = member->xmlChildrenNode;
  1505. /* Find <name> node in the member */
  1506. while(name) {
  1507. if (!xmlStrcmp(name->name, BAD_CAST "name")) break;
  1508. name = name->next;
  1509. }
  1510. if (!name) {
  1511. set_fault(reply, 400, "Member Name Not Found In Structure");
  1512. return -1;
  1513. }
  1514. /* Check the value of <name> node in the structure member */
  1515. name_str = (char*)xmlNodeListGetString(doc, name->xmlChildrenNode, 1);
  1516. if (!name_str) {
  1517. set_fault(reply, 400, "Empty name Element of Structure Parameter");
  1518. return -1;
  1519. }
  1520. if (strcmp(name_str, member_name)) {
  1521. xmlFree(name_str);
  1522. goto skip;
  1523. }
  1524. xmlFree(name_str);
  1525. *value = member->xmlChildrenNode;
  1526. while(*value) {
  1527. if (!xmlStrcmp((*value)->name, BAD_CAST "value")) break;
  1528. (*value) = (*value)->next;
  1529. }
  1530. if (!(*value)) {
  1531. set_fault(reply, 400, "Member Value Not Found In Structure");
  1532. return -1;
  1533. }
  1534. return 0;
  1535. skip:
  1536. member = member->next;
  1537. }
  1538. return 1;
  1539. }
  1540. /** Adds a new member to structure.
  1541. */
  1542. static int rpc_struct_add(struct rpc_struct* s, char* fmt, ...)
  1543. {
  1544. va_list ap;
  1545. str member_name;
  1546. struct xmlrpc_reply* reply;
  1547. void* void_ptr;
  1548. struct rpc_struct* p, *tmp;
  1549. reply = &s->struct_out;
  1550. va_start(ap, fmt);
  1551. while(*fmt) {
  1552. member_name.s = va_arg(ap, char*);
  1553. member_name.len = (member_name.s ? strlen(member_name.s) : 0);
  1554. if (add_xmlrpc_reply(reply, &member_prefix) < 0) goto err;
  1555. if (add_xmlrpc_reply(reply, &name_prefix) < 0) goto err;
  1556. if (add_xmlrpc_reply_esc(reply, &member_name) < 0) goto err;
  1557. if (add_xmlrpc_reply(reply, &name_suffix) < 0) goto err;
  1558. if (add_xmlrpc_reply(reply, &value_prefix) < 0) goto err;
  1559. if (*fmt == '{') {
  1560. void_ptr = va_arg(ap, void**);
  1561. p = new_rpcstruct(0, 0, s->reply);
  1562. if (!p)
  1563. goto err;
  1564. *(struct rpc_struct**) void_ptr = p;
  1565. p->offset = get_reply_len(reply);
  1566. p->parent = s;
  1567. if (!s->nnext) {
  1568. s->nnext = p;
  1569. } else {
  1570. for (tmp = s; tmp->nnext; tmp=tmp->nnext);
  1571. tmp->nnext = p;
  1572. }
  1573. } else {
  1574. if (print_value(reply, reply, *fmt, &ap) < 0) goto err;
  1575. }
  1576. if (add_xmlrpc_reply(reply, &value_suffix) < 0) goto err;
  1577. if (add_xmlrpc_reply(reply, &member_suffix) < 0) goto err;
  1578. fmt++;
  1579. }
  1580. va_end(ap);
  1581. return 0;
  1582. err:
  1583. va_end(ap);
  1584. return -1;
  1585. }
  1586. /** Create a new member from formatting string and add it to a structure.
  1587. */
  1588. static int rpc_struct_printf(struct rpc_struct* s, char* member_name,
  1589. char* fmt, ...)
  1590. {
  1591. int n, buf_size;
  1592. char* buf;
  1593. va_list ap;
  1594. str st, name;
  1595. struct xmlrpc_reply* reply;
  1596. struct xmlrpc_reply* out;
  1597. out = &s->struct_out;
  1598. buf = (char*)pkg_malloc(RPC_BUF_SIZE);
  1599. reply = s->reply;
  1600. if (!buf) {
  1601. set_fault(reply, 500, "Internal Server Error (No memory left)");
  1602. ERR("No memory left\n");
  1603. return -1;
  1604. }
  1605. buf_size = RPC_BUF_SIZE;
  1606. while (1) {
  1607. /* Try to print in the allocated space. */
  1608. va_start(ap, fmt);
  1609. n = vsnprintf(buf, buf_size, fmt, ap);
  1610. va_end(ap);
  1611. /* If that worked, return the string. */
  1612. if (n > -1 && n < buf_size) {
  1613. st.s = buf;
  1614. st.len = n;
  1615. name.s = member_name;
  1616. name.len = strlen(member_name);
  1617. if (add_xmlrpc_reply(out, &member_prefix) < 0) goto err;
  1618. if (add_xmlrpc_reply(out, &name_prefix) < 0) goto err;
  1619. if (add_xmlrpc_reply_esc(out, &name) < 0) goto err;
  1620. if (add_xmlrpc_reply(out, &name_suffix) < 0) goto err;
  1621. if (add_xmlrpc_reply(out, &value_prefix) < 0) goto err;
  1622. if (add_xmlrpc_reply(out, &string_prefix) < 0) goto err;
  1623. if (add_xmlrpc_reply_esc(out, &st) < 0) goto err;
  1624. if (add_xmlrpc_reply(out, &string_suffix) < 0) goto err;
  1625. if (add_xmlrpc_reply(out, &value_suffix) < 0) goto err;
  1626. if (add_xmlrpc_reply(out, &member_suffix) < 0) goto err;
  1627. return 0;
  1628. }
  1629. /* Else try again with more space. */
  1630. if (n > -1) { /* glibc 2.1 */
  1631. buf_size = n + 1; /* precisely what is needed */
  1632. } else { /* glibc 2.0 */
  1633. buf_size *= 2; /* twice the old size */
  1634. }
  1635. if ((buf = pkg_realloc(buf, buf_size)) == 0) {
  1636. set_fault(reply, 500, "Internal Server Error (No memory left)");
  1637. ERR("No memory left\n");
  1638. goto err;
  1639. }
  1640. }
  1641. return 0;
  1642. err:
  1643. if (buf) pkg_free(buf);
  1644. return -1;
  1645. }
  1646. static int rpc_struct_scan(struct rpc_struct* s, char* fmt, ...)
  1647. {
  1648. int read;
  1649. va_list ap;
  1650. int* int_ptr;
  1651. double* double_ptr;
  1652. char** char_ptr;
  1653. str* str_ptr;
  1654. xmlNodePtr value;
  1655. char* member_name;
  1656. struct xmlrpc_reply* reply;
  1657. int ret;
  1658. int f;
  1659. read = 0;
  1660. f=(autoconvert?GET_X_AUTOCONV:0) |
  1661. (lflf2crlf?GET_X_LFLF2CRLF:0);
  1662. va_start(ap, fmt);
  1663. while(*fmt) {
  1664. member_name = va_arg(ap, char*);
  1665. reply = s->reply;
  1666. /* clear the previously saved error code */
  1667. clear_xmlrpc_reply(reply);
  1668. ret = find_member(&value, s->doc, s->struct_in, reply, member_name);
  1669. if (ret != 0) goto error;
  1670. switch(*fmt) {
  1671. case 'b': /* Bool */
  1672. case 't': /* Date and time */
  1673. case 'd': /* Integer */
  1674. int_ptr = va_arg(ap, int*);
  1675. if (get_int(int_ptr, reply, s->doc, value, f) < 0) goto error;
  1676. break;
  1677. case 'f': /* double */
  1678. double_ptr = va_arg(ap, double*);
  1679. if (get_double(double_ptr, reply, s->doc, value, f) < 0)
  1680. goto error;
  1681. break;
  1682. case 's': /* zero terminated string */
  1683. char_ptr = va_arg(ap, char**);
  1684. if (get_string(char_ptr, reply, s->doc, value, f) < 0) goto error;
  1685. break;
  1686. case 'S': /* str structure */
  1687. str_ptr = va_arg(ap, str*);
  1688. if (get_string(&str_ptr->s, reply, s->doc, value, f) < 0)
  1689. goto error;
  1690. str_ptr->len = strlen(str_ptr->s);
  1691. break;
  1692. default:
  1693. ERR("Invalid parameter type in formatting string: %c\n", *fmt);
  1694. return -1;
  1695. }
  1696. fmt++;
  1697. read++;
  1698. }
  1699. va_end(ap);
  1700. return read;
  1701. error:
  1702. va_end(ap);
  1703. return -read;
  1704. }
  1705. /** Returns the RPC capabilities supported by the xmlrpc driver.
  1706. */
  1707. static rpc_capabilities_t rpc_capabilities(rpc_ctx_t* ctx)
  1708. {
  1709. return RPC_DELAYED_REPLY;
  1710. }
  1711. /** Returns a new "delayed reply" context.
  1712. * Creates a new delayed reply context in shm and returns it.
  1713. * @return 0 - not supported, already replied, or no more memory;
  1714. * !=0 pointer to the special delayed ctx.
  1715. * Note1: one should use the returned ctx reply context to build a reply and
  1716. * when finished call rpc_delayed_ctx_close().
  1717. * Note2: adding pieces to the reply in different processes is not supported.
  1718. */
  1719. static struct rpc_delayed_ctx* rpc_delayed_ctx_new(rpc_ctx_t* ctx)
  1720. {
  1721. struct rpc_delayed_ctx* ret;
  1722. int size;
  1723. rpc_ctx_t* r_ctx;
  1724. struct sip_msg* shm_msg;
  1725. int len;
  1726. ret=0;
  1727. shm_msg=0;
  1728. if (ctx->reply_sent)
  1729. return 0; /* no delayed reply if already replied */
  1730. /* clone the sip msg */
  1731. shm_msg=sip_msg_shm_clone(ctx->msg, &len, 1);
  1732. if (shm_msg==0)
  1733. goto error;
  1734. /* alloc into one block */
  1735. size=ROUND_POINTER(sizeof(*ret))+sizeof(rpc_ctx_t);
  1736. if ((ret=shm_malloc(size))==0)
  1737. goto error;
  1738. memset(ret, 0, size);
  1739. ret->rpc=func_param;
  1740. ret->reply_ctx=(char*)ret+ROUND_POINTER(sizeof(*ret));
  1741. r_ctx=ret->reply_ctx;
  1742. r_ctx->flags=ctx->flags | XMLRPC_DELAYED_CTX_F;
  1743. ctx->flags |= XMLRPC_DELAYED_REPLY_F;
  1744. r_ctx->msg=shm_msg;
  1745. r_ctx->msg_shm_block_size=len;
  1746. return ret;
  1747. error:
  1748. if (shm_msg)
  1749. shm_free(shm_msg);
  1750. if (ret)
  1751. shm_free(ret);
  1752. return 0;
  1753. }
  1754. /** Closes a "delayed reply" context and sends the reply.
  1755. * If no reply has been sent the reply will be built and sent automatically.
  1756. * See the notes from rpc_new_delayed_ctx()
  1757. */
  1758. static void rpc_delayed_ctx_close(struct rpc_delayed_ctx* dctx)
  1759. {
  1760. rpc_ctx_t* r_ctx;
  1761. struct hdr_field* hdr;
  1762. r_ctx=dctx->reply_ctx;
  1763. if (unlikely(!(r_ctx->flags & XMLRPC_DELAYED_CTX_F))){
  1764. BUG("reply ctx not marked as async/delayed\n");
  1765. goto error;
  1766. }
  1767. if (fix_delayed_reply_ctx(r_ctx)<0)
  1768. goto error;
  1769. if (!r_ctx->reply_sent){
  1770. rpc_send(r_ctx);
  1771. }
  1772. error:
  1773. clean_context(r_ctx);
  1774. /* collect possible garbage (e.g. generated by structures) */
  1775. collect_garbage();
  1776. /* free added lumps (rpc_send adds a body lump) */
  1777. del_nonshm_lump( &(r_ctx->msg->add_rm) );
  1778. del_nonshm_lump( &(r_ctx->msg->body_lumps) );
  1779. del_nonshm_lump_rpl( &(r_ctx->msg->reply_lump) );
  1780. /* free header's parsed structures that were added by failure handlers */
  1781. for( hdr=r_ctx->msg->headers ; hdr ; hdr=hdr->next ) {
  1782. if ( hdr->parsed && hdr_allocs_parse(hdr) &&
  1783. (hdr->parsed<(void*)r_ctx->msg ||
  1784. hdr->parsed>=(void*)(r_ctx->msg+r_ctx->msg_shm_block_size))) {
  1785. /* header parsed filed doesn't point inside uas.request memory
  1786. * chunck -> it was added by failure funcs.-> free it as pkg */
  1787. DBG("DBG:free_faked_req: removing hdr->parsed %d\n",
  1788. hdr->type);
  1789. clean_hdr_field(hdr);
  1790. hdr->parsed = 0;
  1791. }
  1792. }
  1793. shm_free(r_ctx->msg);
  1794. r_ctx->msg=0;
  1795. dctx->reply_ctx=0;
  1796. shm_free(dctx);
  1797. }
  1798. /** Starts parsing XML-RPC document, get the name of the method to be called
  1799. * and position the cursor at the first parameter in the document.
  1800. */
  1801. static int open_doc(rpc_ctx_t* ctx, sip_msg_t* msg)
  1802. {
  1803. str doc;
  1804. xmlNodePtr root;
  1805. xmlNodePtr cur;
  1806. struct xmlrpc_reply* reply;
  1807. reply = &ctx->reply;
  1808. if (get_rpc_document(&doc, msg) < 0) {
  1809. set_fault(reply, 400, "Malformed Message Body");
  1810. ERR("Error extracting message body\n");
  1811. return -1;
  1812. }
  1813. ctx->doc = xmlReadMemory(doc.s, doc.len, 0, 0,
  1814. XML_PARSE_NOBLANKS |
  1815. XML_PARSE_NONET |
  1816. XML_PARSE_NOCDATA);
  1817. if (!ctx->doc) {
  1818. set_fault(reply, 400, "Invalid XML-RPC Document");
  1819. ERR("Invalid XML-RPC document: \n[%.*s]\n", doc.len, doc.s);
  1820. goto err;
  1821. }
  1822. root = xmlDocGetRootElement(ctx->doc);
  1823. if (!root) {
  1824. set_fault(reply, 400, "Empty XML-RPC Document");
  1825. ERR("Empty XML-RPC document\n");
  1826. goto err;
  1827. }
  1828. if (xmlStrcmp(root->name, (const xmlChar*)"methodCall")) {
  1829. set_fault(reply, 400, "Root Element Is Not methodCall");
  1830. ERR("Root element is not methodCall\n");
  1831. goto err;
  1832. }
  1833. cur = root->xmlChildrenNode;
  1834. while(cur) {
  1835. if (!xmlStrcmp(cur->name, (const xmlChar*)"methodName")) {
  1836. ctx->method = (char*)xmlNodeListGetString(ctx->doc, cur->xmlChildrenNode, 1);
  1837. if (!ctx->method) {
  1838. set_fault(reply, 400, "Cannot Extract Method Name");
  1839. ERR("Cannot extract method name\n");
  1840. goto err;
  1841. }
  1842. break;
  1843. }
  1844. cur = cur->next;
  1845. }
  1846. if (!cur) {
  1847. set_fault(reply, 400, "Method Name Not Found");
  1848. ERR("Method name not found\n");
  1849. goto err;
  1850. }
  1851. cur = root->xmlChildrenNode;
  1852. while(cur) {
  1853. if (!xmlStrcmp(cur->name, (const xmlChar*)"params")) {
  1854. ctx->act_param = cur->xmlChildrenNode;
  1855. break;
  1856. }
  1857. cur = cur->next;
  1858. }
  1859. if (!cur) ctx->act_param = 0;
  1860. return 0;
  1861. err:
  1862. close_doc(ctx);
  1863. return -1;
  1864. }
  1865. static void close_doc(rpc_ctx_t* ctx)
  1866. {
  1867. if (ctx->method) xmlFree(ctx->method);
  1868. if (ctx->doc) xmlFreeDoc(ctx->doc);
  1869. ctx->method = 0;
  1870. ctx->doc = 0;
  1871. }
  1872. static int init_context(rpc_ctx_t* ctx, sip_msg_t* msg)
  1873. {
  1874. ctx->msg = msg;
  1875. ctx->msg_shm_block_size=0;
  1876. ctx->method = 0;
  1877. ctx->reply_sent = 0;
  1878. ctx->act_param = 0;
  1879. ctx->doc = 0;
  1880. ctx->structs = 0;
  1881. if (init_xmlrpc_reply(&ctx->reply) < 0) return -1;
  1882. add_xmlrpc_reply(&ctx->reply, &success_prefix);
  1883. if (open_doc(ctx, msg) < 0) return -1;
  1884. return 0;
  1885. }
  1886. static void clean_context(rpc_ctx_t* ctx)
  1887. {
  1888. if (!ctx) return;
  1889. clean_xmlrpc_reply(&ctx->reply);
  1890. close_doc(ctx);
  1891. }
  1892. /** Creates a SIP message (in "buffer" form) from a HTTP XML-RPC request).
  1893. *
  1894. * NOTE: the result must be pkg_free()'ed when not needed anymore.
  1895. * @return 0 on error, buffer allocated using pkg_malloc on success.
  1896. */
  1897. static char* http_xmlrpc2sip(sip_msg_t* msg, int* new_msg_len)
  1898. {
  1899. unsigned int len, via_len;
  1900. char* via, *new_msg, *p;
  1901. str ip, port;
  1902. struct hostport hp;
  1903. struct dest_info dst;
  1904. /* create a via */
  1905. ip.s = ip_addr2a(&msg->rcv.src_ip);
  1906. ip.len = strlen(ip.s);
  1907. port.s = int2str(msg->rcv.src_port, &port.len);
  1908. hp.host = &ip;
  1909. hp.port = &port;
  1910. init_dst_from_rcv(&dst, &msg->rcv);
  1911. via = via_builder(&via_len, &dst, 0, 0, &hp);
  1912. if (via == 0) {
  1913. DEBUG("failed to build via\n");
  1914. return 0;
  1915. }
  1916. len = msg->first_line.u.request.method.len + 1 /* space */ +
  1917. XMLRPC_URI_LEN + 1 /* space */ +
  1918. msg->first_line.u.request.version.len + CRLF_LEN + via_len +
  1919. (msg->len-msg->first_line.len);
  1920. p = new_msg = pkg_malloc(len + 1);
  1921. if (new_msg == 0) {
  1922. DEBUG("memory allocation failure (%d bytes)\n", len);
  1923. pkg_free(via);
  1924. return 0;
  1925. }
  1926. /* new message:
  1927. * <orig_http_method> sip:127.0.0.1:9 HTTP/1.x
  1928. * Via: <faked via>
  1929. * <orig. http message w/o the first line>
  1930. */
  1931. memcpy(p, msg->first_line.u.request.method.s,
  1932. msg->first_line.u.request.method.len);
  1933. p += msg->first_line.u.request.method.len;
  1934. *p = ' ';
  1935. p++;
  1936. memcpy(p, XMLRPC_URI, XMLRPC_URI_LEN);
  1937. p += XMLRPC_URI_LEN;
  1938. *p = ' ';
  1939. p++;
  1940. memcpy(p, msg->first_line.u.request.version.s,
  1941. msg->first_line.u.request.version.len);
  1942. p += msg->first_line.u.request.version.len;
  1943. memcpy(p, CRLF, CRLF_LEN);
  1944. p += CRLF_LEN;
  1945. memcpy(p, via, via_len);
  1946. p += via_len;
  1947. memcpy(p, SIP_MSG_START(msg) + msg->first_line.len,
  1948. msg->len - msg->first_line.len);
  1949. new_msg[len] = 0; /* null terminate, required by receive_msg() */
  1950. pkg_free(via);
  1951. *new_msg_len = len;
  1952. return new_msg;
  1953. }
  1954. /** Emulate receive_msg for an XML-RPC request .
  1955. */
  1956. static int em_receive_request(sip_msg_t* orig_msg,
  1957. char* new_buf, unsigned int new_len)
  1958. {
  1959. int ret;
  1960. sip_msg_t tmp_msg, *msg;
  1961. struct run_act_ctx ra_ctx;
  1962. ret=0;
  1963. if (new_buf && new_len) {
  1964. memset(&tmp_msg, 0, sizeof(sip_msg_t));
  1965. tmp_msg.buf = new_buf;
  1966. tmp_msg.len = new_len;
  1967. tmp_msg.rcv = orig_msg->rcv;
  1968. tmp_msg.id = orig_msg->id;
  1969. tmp_msg.set_global_address = orig_msg->set_global_address;
  1970. tmp_msg.set_global_port = orig_msg->set_global_port;
  1971. if (parse_msg(new_buf, new_len, &tmp_msg) != 0) {
  1972. ERR("xmlrpc: parse_msg failed\n");
  1973. goto error;
  1974. }
  1975. msg = &tmp_msg;
  1976. } else {
  1977. msg = orig_msg;
  1978. }
  1979. /* not needed, performed by the "real" receive_msg()
  1980. clear_branches();
  1981. reset_static_buffer();
  1982. */
  1983. if ((msg->first_line.type != SIP_REQUEST) || (msg->via1 == 0) ||
  1984. (msg->via1->error != PARSE_OK)) {
  1985. BUG("xmlrpc: strange message: %.*s\n", msg->len, msg->buf);
  1986. goto error;
  1987. }
  1988. if (exec_pre_script_cb(msg, REQUEST_CB_TYPE) == 0) {
  1989. goto end; /* drop request */
  1990. }
  1991. /* exec routing script */
  1992. init_run_actions_ctx(&ra_ctx);
  1993. if (run_actions(&ra_ctx, main_rt.rlist[xmlrpc_route_no], msg) < 0) {
  1994. ret=-1;
  1995. DBG("xmlrpc: error while trying script\n");
  1996. goto end;
  1997. }
  1998. end:
  1999. exec_post_script_cb(msg, REQUEST_CB_TYPE); /* needed for example if tm is used */
  2000. /* reset_avps(); non needed, performed by the real receive_msg */
  2001. if (msg != orig_msg) { /* avoid double free (freed from receive_msg
  2002. too) */
  2003. free_sip_msg(msg);
  2004. }
  2005. return ret;
  2006. error:
  2007. return -1;
  2008. }
  2009. /** The main handler that will be called when SER core receives a non-SIP
  2010. * request (i.e. HTTP request carrying XML-RPC document in the body).
  2011. */
  2012. static int process_xmlrpc(sip_msg_t* msg)
  2013. {
  2014. int ret;
  2015. char* fake_msg;
  2016. int fake_msg_len;
  2017. unsigned char* method;
  2018. unsigned int method_len, n_method;
  2019. regmatch_t pmatch;
  2020. char c;
  2021. ret=NONSIP_MSG_DROP;
  2022. if (!IS_HTTP(msg))
  2023. return NONSIP_MSG_PASS;
  2024. if(xmlrpc_url_skip!=NULL || xmlrpc_url_match!=NULL)
  2025. {
  2026. c = msg->first_line.u.request.uri.s[msg->first_line.u.request.uri.len];
  2027. msg->first_line.u.request.uri.s[msg->first_line.u.request.uri.len]
  2028. = '\0';
  2029. if (xmlrpc_url_skip!=NULL &&
  2030. regexec(&xmlrpc_url_skip_regexp, msg->first_line.u.request.uri.s,
  2031. 1, &pmatch, 0)==0)
  2032. {
  2033. LM_DBG("URL matched skip re\n");
  2034. msg->first_line.u.request.uri.s[msg->first_line.u.request.uri.len]
  2035. = c;
  2036. return NONSIP_MSG_PASS;
  2037. }
  2038. if (xmlrpc_url_match!=NULL &&
  2039. regexec(&xmlrpc_url_match_regexp, msg->first_line.u.request.uri.s,
  2040. 1, &pmatch, 0)!=0)
  2041. {
  2042. LM_DBG("URL not matched\n");
  2043. msg->first_line.u.request.uri.s[msg->first_line.u.request.uri.len]
  2044. = c;
  2045. return NONSIP_MSG_PASS;
  2046. }
  2047. msg->first_line.u.request.uri.s[msg->first_line.u.request.uri.len] = c;
  2048. }
  2049. method = (unsigned char*)msg->first_line.u.request.method.s;
  2050. method_len = msg->first_line.u.request.method.len;
  2051. /* first line is always > 4, so it's always safe to try to read the
  2052. * 1st 4 bytes from method, even if method is shorter*/
  2053. n_method = method[0] + (method[1] << 8) + (method[2] << 16) +
  2054. (method[3] << 24);
  2055. n_method |= 0x20202020;
  2056. n_method &= ((method_len < 4) * (1U << method_len * 8) - 1);
  2057. /* accept only GET or POST */
  2058. if ((n_method == N_HTTP_GET) ||
  2059. ((n_method == N_HTTP_POST) && (method_len == HTTP_POST_LEN))) {
  2060. if (msg->via1 == 0){
  2061. /* create a fake sip message */
  2062. fake_msg = http_xmlrpc2sip(msg, &fake_msg_len);
  2063. if (fake_msg == 0) {
  2064. ERR("xmlrpc: out of memory\n");
  2065. ret=NONSIP_MSG_ERROR;
  2066. } else {
  2067. /* send it */
  2068. DBG("new fake xml msg created (%d bytes):\n<%.*s>\n",
  2069. fake_msg_len, fake_msg_len, fake_msg);
  2070. if (em_receive_request(msg, fake_msg, fake_msg_len)<0)
  2071. ret=NONSIP_MSG_ERROR;
  2072. pkg_free(fake_msg);
  2073. }
  2074. return ret; /* we "ate" the message, stop processing */
  2075. } else { /* the message has a via */
  2076. DBG("http xml msg unchanged (%d bytes):\n<%.*s>\n",
  2077. msg->len, msg->len, msg->buf);
  2078. if (em_receive_request(msg, 0, 0)<0)
  2079. ret=NONSIP_MSG_ERROR;
  2080. return ret;
  2081. }
  2082. } else {
  2083. ERR("xmlrpc: bad HTTP request method: \"%.*s\"\n",
  2084. msg->first_line.u.request.method.len,
  2085. msg->first_line.u.request.method.s);
  2086. /* the message was for us, but it is an error */
  2087. return NONSIP_MSG_ERROR;
  2088. }
  2089. return NONSIP_MSG_PASS; /* message not for us, maybe somebody
  2090. else needs it */
  2091. }
  2092. /** The main processing function of xmlrpc module.
  2093. *
  2094. * This is the main function of this module. It extracts the name
  2095. * of the method to be called from XML-RPC request and then it
  2096. * searches through the list of all available management function,
  2097. * when a function with matching name is found then it will be
  2098. * executed.
  2099. */
  2100. static int dispatch_rpc(sip_msg_t* msg, char* s1, char* s2)
  2101. {
  2102. rpc_export_t* exp;
  2103. int ret = 1;
  2104. if (init_context(&ctx, msg) < 0) goto skip;
  2105. exp = find_rpc_export(ctx.method, 0);
  2106. if (!exp || !exp->function) {
  2107. rpc_fault(&ctx, 500, "Method Not Found");
  2108. goto skip;
  2109. }
  2110. ctx.flags = exp->flags;
  2111. if (exp->flags & RET_ARRAY &&
  2112. add_xmlrpc_reply(&ctx.reply, &array_prefix) < 0) goto skip;
  2113. exp->function(&func_param, &ctx);
  2114. skip:
  2115. /* The function may have sent the reply itself */
  2116. if (!ctx.reply_sent && !(ctx.flags&XMLRPC_DELAYED_REPLY_F)) {
  2117. ret = rpc_send(&ctx);
  2118. }
  2119. clean_context(&ctx);
  2120. collect_garbage();
  2121. if (ret < 0) return -1;
  2122. else return 1;
  2123. }
  2124. /** This function can be called from SER scripts to generate
  2125. * an XML-RPC reply.
  2126. */
  2127. static int xmlrpc_reply(sip_msg_t* msg, char* p1, char* p2)
  2128. {
  2129. str reason;
  2130. static str succ = STR_STATIC_INIT("1");
  2131. struct xmlrpc_reply reply;
  2132. memset(&reply, 0, sizeof(struct xmlrpc_reply));
  2133. if (init_xmlrpc_reply(&reply) < 0) return -1;
  2134. if (get_int_fparam(&reply.code, msg, (fparam_t*)p1) < 0) return -1;
  2135. if (get_str_fparam(&reason, msg, (fparam_t*)p2) < 0) return -1;
  2136. reply.reason = as_asciiz(&reason);
  2137. if (reply.reason == NULL) {
  2138. ERR("No memory left\n");
  2139. return -1;
  2140. }
  2141. if (reply.code >= 300) {
  2142. if (build_fault_reply(&reply) < 0) goto error;
  2143. } else {
  2144. if (add_xmlrpc_reply(&reply, &success_prefix) < 0) goto error;
  2145. if (add_xmlrpc_reply(&reply, &int_prefix) < 0) goto error;
  2146. if (add_xmlrpc_reply_esc(&reply, &succ) < 0) goto error;
  2147. if (add_xmlrpc_reply(&reply, &int_suffix) < 0) goto error;
  2148. if (add_xmlrpc_reply(&reply, &success_suffix) < 0) return -1;
  2149. }
  2150. if (send_reply(msg, &reply.body) < 0) goto error;
  2151. if (reply.reason) pkg_free(reply.reason);
  2152. clean_xmlrpc_reply(&reply);
  2153. return 1;
  2154. error:
  2155. if (reply.reason) pkg_free(reply.reason);
  2156. clean_xmlrpc_reply(&reply);
  2157. return -1;
  2158. }
  2159. /** Implementation of \@xmlrpc.method select that can be used in
  2160. * SER scripts to retrieve the method string from XML-RPC documents
  2161. */
  2162. static int select_method(str* res, struct select* s, sip_msg_t* msg)
  2163. {
  2164. static char buf[1024];
  2165. str doc;
  2166. xmlDocPtr xmldoc;
  2167. xmlNodePtr cur;
  2168. char* method;
  2169. xmldoc = 0;
  2170. method = 0;
  2171. if (get_rpc_document(&doc, msg) < 0) goto err;
  2172. xmldoc = xmlReadMemory(doc.s, doc.len, 0, 0,
  2173. XML_PARSE_NOBLANKS |
  2174. XML_PARSE_NONET |
  2175. XML_PARSE_NOCDATA);
  2176. if (!xmldoc) goto err;
  2177. cur = xmlDocGetRootElement(xmldoc);
  2178. if (!cur) goto err;
  2179. if (xmlStrcmp(cur->name, (const xmlChar*)"methodCall")) goto err;
  2180. cur = cur->xmlChildrenNode;
  2181. while(cur) {
  2182. if (!xmlStrcmp(cur->name, (const xmlChar*)"methodName")) {
  2183. method = (char*)xmlNodeListGetString(xmldoc, cur->xmlChildrenNode,
  2184. 1);
  2185. if (!method) goto err;
  2186. break;
  2187. }
  2188. cur = cur->next;
  2189. }
  2190. if (!cur) goto err;
  2191. res->len = strlen(method);
  2192. if (res->len >= 1024) goto err;
  2193. memcpy(buf, method, res->len);
  2194. res->s = buf;
  2195. return 0;
  2196. err:
  2197. if (method) xmlFree(method);
  2198. if (xmldoc) xmlFreeDoc(xmldoc);
  2199. return -1;
  2200. }
  2201. static ABSTRACT_F(select_xmlrpc);
  2202. select_row_t xmlrpc_sel[] = {
  2203. { NULL, SEL_PARAM_STR, STR_STATIC_INIT("xmlrpc"), select_xmlrpc, SEL_PARAM_EXPECTED},
  2204. { select_xmlrpc, SEL_PARAM_STR, STR_STATIC_INIT("method"), select_method, 0},
  2205. { NULL, SEL_PARAM_INT, STR_NULL, NULL, 0}
  2206. };
  2207. static int mod_init(void)
  2208. {
  2209. struct nonsip_hook nsh;
  2210. int route_no;
  2211. /* try to fix the xmlrpc route */
  2212. if (xmlrpc_route){
  2213. route_no=route_get(&main_rt, xmlrpc_route);
  2214. if (route_no==-1){
  2215. ERR("xmlrpc: failed to fix route \"%s\": route_get() failed\n",
  2216. xmlrpc_route);
  2217. return -1;
  2218. }
  2219. if (main_rt.rlist[route_no]==0){
  2220. WARN("xmlrpc: xmlrpc route \"%s\" is empty / doesn't exist\n",
  2221. xmlrpc_route);
  2222. }
  2223. xmlrpc_route_no=route_no;
  2224. }
  2225. /* bind the SL API */
  2226. if (sl_load_api(&slb)!=0) {
  2227. LM_ERR("cannot bind to SL API\n");
  2228. return -1;
  2229. }
  2230. func_param.send = (rpc_send_f)rpc_send;
  2231. func_param.fault = (rpc_fault_f)rpc_fault;
  2232. func_param.add = (rpc_add_f)rpc_add;
  2233. func_param.scan = (rpc_scan_f)rpc_scan;
  2234. func_param.printf = (rpc_printf_f)rpc_printf;
  2235. func_param.struct_add = (rpc_struct_add_f)rpc_struct_add;
  2236. func_param.struct_scan = (rpc_struct_scan_f)rpc_struct_scan;
  2237. func_param.struct_printf = (rpc_struct_printf_f)rpc_struct_printf;
  2238. func_param.capabilities = (rpc_capabilities_f)rpc_capabilities;
  2239. func_param.delayed_ctx_new = (rpc_delayed_ctx_new_f)rpc_delayed_ctx_new;
  2240. func_param.delayed_ctx_close =
  2241. (rpc_delayed_ctx_close_f)rpc_delayed_ctx_close;
  2242. register_select_table(xmlrpc_sel);
  2243. /* register non-sip hooks */
  2244. if(xmlrpc_mode==0)
  2245. {
  2246. memset(&nsh, 0, sizeof(nsh));
  2247. nsh.name="xmlrpc";
  2248. nsh.destroy=0;
  2249. nsh.on_nonsip_req=process_xmlrpc;
  2250. if (register_nonsip_msg_hook(&nsh)<0){
  2251. ERR("Failed to register non sip msg hooks\n");
  2252. return -1;
  2253. }
  2254. }
  2255. if(xmlrpc_url_match!=NULL)
  2256. {
  2257. memset(&xmlrpc_url_match_regexp, 0, sizeof(regex_t));
  2258. if (regcomp(&xmlrpc_url_match_regexp, xmlrpc_url_match, REG_EXTENDED)!=0) {
  2259. LM_ERR("bad match re %s\n", xmlrpc_url_match);
  2260. return E_BAD_RE;
  2261. }
  2262. }
  2263. if(xmlrpc_url_skip!=NULL)
  2264. {
  2265. memset(&xmlrpc_url_skip_regexp, 0, sizeof(regex_t));
  2266. if (regcomp(&xmlrpc_url_skip_regexp, xmlrpc_url_skip, REG_EXTENDED)!=0) {
  2267. LM_ERR("bad skip re %s\n", xmlrpc_url_skip);
  2268. return E_BAD_RE;
  2269. }
  2270. }
  2271. return 0;
  2272. }
  2273. /**
  2274. * advertise that sip workers handle rpc commands
  2275. */
  2276. int mod_register(char *path, int *dlflags, void *p1, void *p2)
  2277. {
  2278. set_child_sip_rpc_mode();
  2279. return 0;
  2280. }
  2281. static int fixup_xmlrpc_reply(void** param, int param_no)
  2282. {
  2283. int ret;
  2284. if (param_no == 1) {
  2285. ret = fix_param(FPARAM_AVP, param);
  2286. if (ret <= 0) return ret;
  2287. if (fix_param(FPARAM_INT, param) != 0) return -1;
  2288. } else if (param_no == 2) {
  2289. return fixup_var_str_12(param, 2);
  2290. }
  2291. return 0;
  2292. }
  2293. /** @} */