xmlrpc.c 79 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013
  1. /*
  2. This file is part of libXMLRPC - a C library for xml-encoded function calls.
  3. Author: Dan Libby (dan@libby.com)
  4. Epinions.com may be contacted at feedback@epinions-inc.com
  5. */
  6. /*
  7. Copyright 2000 Epinions, Inc.
  8. Subject to the following 3 conditions, Epinions, Inc. permits you, free
  9. of charge, to (a) use, copy, distribute, modify, perform and display this
  10. software and associated documentation files (the "Software"), and (b)
  11. permit others to whom the Software is furnished to do so as well.
  12. 1) The above copyright notice and this permission notice shall be included
  13. without modification in all copies or substantial portions of the
  14. Software.
  15. 2) THE SOFTWARE IS PROVIDED "AS IS", WITHOUT ANY WARRANTY OR CONDITION OF
  16. ANY KIND, EXPRESS, IMPLIED OR STATUTORY, INCLUDING WITHOUT LIMITATION ANY
  17. IMPLIED WARRANTIES OF ACCURACY, MERCHANTABILITY, FITNESS FOR A PARTICULAR
  18. PURPOSE OR NONINFRINGEMENT.
  19. 3) IN NO EVENT SHALL EPINIONS, INC. BE LIABLE FOR ANY DIRECT, INDIRECT,
  20. SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES OR LOST PROFITS ARISING OUT
  21. OF OR IN CONNECTION WITH THE SOFTWARE (HOWEVER ARISING, INCLUDING
  22. NEGLIGENCE), EVEN IF EPINIONS, INC. IS AWARE OF THE POSSIBILITY OF SUCH
  23. DAMAGES.
  24. */
  25. static const char rcsid[] = "#(@) $Id$";
  26. /****h* ABOUT/xmlrpc
  27. * NAME
  28. * XMLRPC_VALUE
  29. * AUTHOR
  30. * Dan Libby, aka danda (dan@libby.com)
  31. * CREATION DATE
  32. * 9/1999 - 10/2000
  33. * HISTORY
  34. * $Log$
  35. * Revision 1.8.4.3.2.1 2008/09/10 00:07:44 felipe
  36. * MFH:
  37. * - Merged fix from SF project (Import Jeff Lawsons patches for XML datetime bug fixes)
  38. * Fixed bugs:
  39. * #45226 (xmlrpc_set_type() segfaults with valid ISO8601 date string)
  40. * #18916 (xmlrpc_set_type() "not working")
  41. *
  42. * Revision 1.8.4.3 2007/09/18 19:49:53 iliaa
  43. *
  44. * Fixed bug #42189 (xmlrpc_set_type() crashes php on invalid datetime
  45. * values).
  46. *
  47. * Revision 1.8.4.2 2007/06/07 09:07:36 tony2001
  48. * MFH: php_localtime_r() checks
  49. *
  50. * Revision 1.8.4.1 2006/11/30 16:38:37 iliaa
  51. * last set of zts fixes
  52. *
  53. * Revision 1.8 2005/03/28 00:07:24 edink
  54. * Reshufle includes to make it compile on windows
  55. *
  56. * Revision 1.7 2005/03/26 03:13:58 sniper
  57. * - Made it possible to build ext/xmlrpc with libxml2
  58. *
  59. * Revision 1.6 2004/04/27 17:33:59 iliaa
  60. * Removed C++ style comments.
  61. *
  62. * Revision 1.5 2003/12/16 21:00:21 sniper
  63. * Fix some compile warnings (patch by Joe Orton)
  64. *
  65. * Revision 1.4 2002/07/05 04:43:53 danda
  66. * merged in updates from SF project. bring php repository up to date with xmlrpc-epi version 0.51
  67. *
  68. * Revision 1.22 2002/03/09 23:15:44 danda
  69. * add fault interrogation funcs
  70. *
  71. * Revision 1.21 2002/03/09 22:27:41 danda
  72. * win32 build patches contributed by Jeff Lawson
  73. *
  74. * Revision 1.20 2002/02/13 20:58:50 danda
  75. * patch to make source more windows friendly, contributed by Jeff Lawson
  76. *
  77. * Revision 1.19 2001/10/12 23:25:54 danda
  78. * default to writing xmlrpc
  79. *
  80. * Revision 1.18 2001/09/29 21:58:05 danda
  81. * adding cvs log to history section
  82. *
  83. * 10/15/2000 -- danda -- adding robodoc documentation
  84. * 08/2000 -- danda -- PHP C extension that uses XMLRPC
  85. * 08/2000 -- danda -- support for two vocabularies: danda-rpc and xml-rpc
  86. * 09/1999 -- danda -- Initial API, before I even knew of standard XMLRPC vocab. Response only.
  87. * 07/2000 -- danda -- wrote new implementation to be compatible with xmlrpc standard and
  88. * incorporated some ideas from ensor, most notably the separation of
  89. * xml dom from xmlrpc api.
  90. * 06/2000 -- danda -- played with expat-ensor from www.ensor.org. Cool, but some flaws.
  91. * TODO
  92. * PORTABILITY
  93. * Coded on RedHat Linux 6.2. Builds on Solaris x86. Should build on just
  94. * about anything with minor mods.
  95. * NOTES
  96. * Welcome to XMLRPC. For more info on the specification and history, see
  97. * http://www.xmlrpc.org.
  98. *
  99. * This code aims to be a full-featured C implementation of XMLRPC. It does not
  100. * have any networking code. Rather, it is intended to be plugged into apps
  101. * or libraries with existing networking facilities, eg PHP, apache, perl, mozilla,
  102. * home-brew application servers, etc.
  103. *
  104. * Usage Paradigm:
  105. * The user of this library will typically be implementing either an XMLRPC server,
  106. * an XMLRPC client, or both. The client will use the library to build an in-memory
  107. * representation of a request, and then serialize (encode) that request into XML. The
  108. * client will then send the XML to the server via external mechanism. The server will
  109. * de-serialize the XML back into an binary representation, call the appropriate registered
  110. * method -- thereby generating a response. The response will be serialized into XML and
  111. * sent back to the client. The client will de-serialize it into memory, and can
  112. * iterate through the results via API.
  113. *
  114. * Both the request and the response may consist of arbitrarily long, arbitrarily nested
  115. * values. The values may be one of several types, as defined by XMLRPC_VALUE_TYPE.
  116. *
  117. * Features and Architecture:
  118. * - The XML parsing (xml_element.c) is completely independent of the XMLRPC api. In fact,
  119. * it can be used as a standalone dom implementation.
  120. * - Because of this, the same XMLRPC data can be serialized into multiple xml vocabularies.
  121. * It is simply a matter of writing a transport. So far, two transports have been defined.
  122. * The default xmlrpc vocab (xml_to_xmlrpc.c), and simple-rpc (xml_to_dandarpc.c) which is
  123. * proprietary, but imho more readable, and nice for proprietary legacy reasons.
  124. * - Various output options, including: xml escaping via CDATA or entity, case folding,
  125. * vocab version, and character encoding.
  126. * - One to One mapping between C structures and actual values, unlike ensor which forces
  127. * one to understand the arcana of the xmlrpc vocab.
  128. * - support for mixed indexed/keyed vector types, making it more compatible with
  129. * languages such as PHP.
  130. * - quite speedy compared to implementations written in interpreted languages. Also, uses
  131. * intelligent string handling, so not many strlen() calls, etc.
  132. * - comprehensive API for manipulation of values
  133. *******/
  134. #include "ext/xml/expat_compat.h"
  135. #include "main/php_reentrancy.h"
  136. #ifdef _WIN32
  137. #include "xmlrpc_win32.h"
  138. #endif
  139. #include <stdio.h>
  140. #include <stdlib.h>
  141. #include <string.h>
  142. #include <stdarg.h>
  143. #include <time.h>
  144. #include <ctype.h>
  145. #include "queue.h"
  146. #include "xmlrpc.h"
  147. #include "base64.h"
  148. #include "xml_to_xmlrpc.h"
  149. #include "xml_to_dandarpc.h"
  150. #include "xml_to_soap.h"
  151. #include "xml_element.h"
  152. #include "xmlrpc_private.h"
  153. #include "xmlrpc_introspection_private.h"
  154. #include "system_methods_private.h"
  155. /*-*********************
  156. * Begin Time Functions *
  157. ***********************/
  158. static time_t mkgmtime(struct tm *tm)
  159. {
  160. static const int mdays[12] = {0,31,59,90,120,151,181,212,243,273,304,334};
  161. return ((((((tm->tm_year - 70) * 365) + mdays[tm->tm_mon] + tm->tm_mday-1 +
  162. (tm->tm_year-68-1+(tm->tm_mon>=2))/4) * 24) + tm->tm_hour) * 60 +
  163. tm->tm_min) * 60 + tm->tm_sec;
  164. }
  165. static int date_from_ISO8601 (const char *text, time_t * value) {
  166. struct tm tm;
  167. int n;
  168. int i;
  169. char buf[30];
  170. if (strchr (text, '-')) {
  171. char *p = (char *) text, *p2 = buf;
  172. while (p && *p) {
  173. if (*p != '-') {
  174. *p2 = *p;
  175. p2++;
  176. if (p2-buf >= sizeof(buf)) {
  177. return -1;
  178. }
  179. }
  180. p++;
  181. }
  182. *p2 = 0;
  183. text = buf;
  184. }
  185. if (strlen(text)<17) {
  186. return -1;
  187. }
  188. tm.tm_isdst = -1;
  189. #define XMLRPC_IS_NUMBER(x) if (x < '0' || x > '9') return -1;
  190. n = 1000;
  191. tm.tm_year = 0;
  192. for(i = 0; i < 4; i++) {
  193. XMLRPC_IS_NUMBER(text[i])
  194. tm.tm_year += (text[i]-'0')*n;
  195. n /= 10;
  196. }
  197. n = 10;
  198. tm.tm_mon = 0;
  199. for(i = 0; i < 2; i++) {
  200. XMLRPC_IS_NUMBER(text[i+4])
  201. tm.tm_mon += (text[i+4]-'0')*n;
  202. n /= 10;
  203. }
  204. tm.tm_mon --;
  205. if(tm.tm_mon < 0 || tm.tm_mon > 11) {
  206. return -1;
  207. }
  208. n = 10;
  209. tm.tm_mday = 0;
  210. for(i = 0; i < 2; i++) {
  211. XMLRPC_IS_NUMBER(text[i+6])
  212. tm.tm_mday += (text[i+6]-'0')*n;
  213. n /= 10;
  214. }
  215. n = 10;
  216. tm.tm_hour = 0;
  217. for(i = 0; i < 2; i++) {
  218. XMLRPC_IS_NUMBER(text[i+9])
  219. tm.tm_hour += (text[i+9]-'0')*n;
  220. n /= 10;
  221. }
  222. n = 10;
  223. tm.tm_min = 0;
  224. for(i = 0; i < 2; i++) {
  225. XMLRPC_IS_NUMBER(text[i+12])
  226. tm.tm_min += (text[i+12]-'0')*n;
  227. n /= 10;
  228. }
  229. n = 10;
  230. tm.tm_sec = 0;
  231. for(i = 0; i < 2; i++) {
  232. XMLRPC_IS_NUMBER(text[i+15])
  233. tm.tm_sec += (text[i+15]-'0')*n;
  234. n /= 10;
  235. }
  236. tm.tm_year -= 1900;
  237. *value = mkgmtime(&tm);
  238. return 0;
  239. }
  240. static int date_to_ISO8601 (time_t value, char *buf, int length) {
  241. struct tm *tm, tmbuf;
  242. tm = php_gmtime_r(&value, &tmbuf);
  243. if (!tm) {
  244. return 0;
  245. }
  246. #if 0 /* TODO: soap seems to favor this method. xmlrpc the latter. */
  247. return strftime (buf, length, "%Y-%m-%dT%H:%M:%SZ", tm);
  248. #else
  249. return strftime(buf, length, "%Y%m%dT%H:%M:%SZ", tm);
  250. #endif
  251. }
  252. /*-*******************
  253. * End Time Functions *
  254. *********************/
  255. /*-***************************
  256. * Begin XMLRPC_REQUEST funcs *
  257. *****************************/
  258. /****f* REQUEST/XMLRPC_RequestNew
  259. * NAME
  260. * XMLRPC_RequestNew
  261. * SYNOPSIS
  262. * XMLRPC_REQUEST XMLRPC_RequestNew()
  263. * FUNCTION
  264. * Creates a new XMLRPC_Request data struct
  265. * INPUTS
  266. * none
  267. * SEE ALSO
  268. * XMLRPC_RequestFree ()
  269. * SOURCE
  270. */
  271. XMLRPC_REQUEST XMLRPC_RequestNew() {
  272. XMLRPC_REQUEST xRequest = calloc(1, sizeof(STRUCT_XMLRPC_REQUEST));
  273. if(xRequest) {
  274. simplestring_init(&xRequest->methodName);
  275. }
  276. return xRequest;
  277. }
  278. /*******/
  279. /****f* REQUEST/XMLRPC_RequestFree
  280. * NAME
  281. * XMLRPC_RequestFree
  282. * SYNOPSIS
  283. * void XMLRPC_RequestFree(XMLRPC_REQUEST request, int bFreeIO)
  284. * FUNCTION
  285. * Free XMLRPC Request and all sub-values
  286. * INPUTS
  287. * request -- previously allocated request struct
  288. * bFreeIO -- 1 = also free request value data, if any, 0 = ignore.
  289. * SEE ALSO
  290. * XMLRPC_RequestNew ()
  291. * XMLRPC_CleanupValue ()
  292. * SOURCE
  293. */
  294. void XMLRPC_RequestFree(XMLRPC_REQUEST request, int bFreeIO) {
  295. if(request) {
  296. simplestring_free(&request->methodName);
  297. if(request->io && bFreeIO) {
  298. XMLRPC_CleanupValue(request->io);
  299. }
  300. if(request->error) {
  301. XMLRPC_CleanupValue(request->error);
  302. }
  303. my_free(request);
  304. }
  305. }
  306. /*******/
  307. /* Set Method Name to call */
  308. /****f* REQUEST/XMLRPC_RequestSetMethodName
  309. * NAME
  310. * XMLRPC_RequestSetMethodName
  311. * SYNOPSIS
  312. * const char* XMLRPC_RequestSetMethodName(XMLRPC_REQUEST request, const char* methodName)
  313. * FUNCTION
  314. * Set name of method to call with this request.
  315. * INPUTS
  316. * request -- previously allocated request struct
  317. * methodName -- name of method
  318. * SEE ALSO
  319. * XMLRPC_RequestNew ()
  320. * XMLRPC_RequestGetMethodName ()
  321. * XMLRPC_RequestFree ()
  322. * SOURCE
  323. */
  324. const char* XMLRPC_RequestSetMethodName(XMLRPC_REQUEST request, const char* methodName) {
  325. if(request) {
  326. simplestring_clear(&request->methodName);
  327. simplestring_add(&request->methodName, methodName);
  328. return request->methodName.str;
  329. }
  330. return NULL;
  331. }
  332. /*******/
  333. /****f* REQUEST/XMLRPC_RequestGetMethodName
  334. * NAME
  335. * XMLRPC_RequestGetMethodName
  336. * SYNOPSIS
  337. * const char* XMLRPC_RequestGetMethodName(XMLRPC_REQUEST request)
  338. * FUNCTION
  339. * Get name of method called by this request
  340. * INPUTS
  341. * request -- previously allocated request struct
  342. * SEE ALSO
  343. * XMLRPC_RequestNew ()
  344. * XMLRPC_RequestSetMethodName ()
  345. * XMLRPC_RequestFree ()
  346. * SOURCE
  347. */
  348. const char* XMLRPC_RequestGetMethodName(XMLRPC_REQUEST request) {
  349. return request ? request->methodName.str : NULL;
  350. }
  351. /*******/
  352. /****f* REQUEST/XMLRPC_RequestSetRequestType
  353. * NAME
  354. * XMLRPC_RequestSetRequestType
  355. * SYNOPSIS
  356. * XMLRPC_REQUEST_TYPE XMLRPC_RequestSetRequestType(XMLRPC_REQUEST request, XMLRPC_REQUEST_TYPE type)
  357. * FUNCTION
  358. * A request struct may be allocated by a caller or by xmlrpc
  359. * in response to a request. This allows setting the
  360. * request type.
  361. * INPUTS
  362. * request -- previously allocated request struct
  363. * type -- request type [xmlrpc_method_call | xmlrpc_method_response]
  364. * SEE ALSO
  365. * XMLRPC_RequestNew ()
  366. * XMLRPC_RequestGetRequestType ()
  367. * XMLRPC_RequestFree ()
  368. * XMLRPC_REQUEST_TYPE
  369. * SOURCE
  370. */
  371. XMLRPC_REQUEST_TYPE XMLRPC_RequestSetRequestType (XMLRPC_REQUEST request,
  372. XMLRPC_REQUEST_TYPE type) {
  373. if(request) {
  374. request->request_type = type;
  375. return request->request_type;
  376. }
  377. return xmlrpc_request_none;
  378. }
  379. /*******/
  380. /****f* REQUEST/XMLRPC_RequestGetRequestType
  381. * NAME
  382. * XMLRPC_RequestGetRequestType
  383. * SYNOPSIS
  384. * XMLRPC_REQUEST_TYPE XMLRPC_RequestGetRequestType(XMLRPC_REQUEST request)
  385. * FUNCTION
  386. * A request struct may be allocated by a caller or by xmlrpc
  387. * in response to a request. This allows setting the
  388. * request type.
  389. * INPUTS
  390. * request -- previously allocated request struct
  391. * RESULT
  392. * type -- request type [xmlrpc_method_call | xmlrpc_method_response]
  393. * SEE ALSO
  394. * XMLRPC_RequestNew ()
  395. * XMLRPC_RequestSetRequestType ()
  396. * XMLRPC_RequestFree ()
  397. * XMLRPC_REQUEST_TYPE
  398. * SOURCE
  399. */
  400. XMLRPC_REQUEST_TYPE XMLRPC_RequestGetRequestType(XMLRPC_REQUEST request) {
  401. return request ? request->request_type : xmlrpc_request_none;
  402. }
  403. /*******/
  404. /****f* REQUEST/XMLRPC_RequestSetData
  405. * NAME
  406. * XMLRPC_RequestSetData
  407. * SYNOPSIS
  408. * XMLRPC_VALUE XMLRPC_RequestSetData(XMLRPC_REQUEST request, XMLRPC_VALUE data)
  409. * FUNCTION
  410. * Associates a block of xmlrpc data with the request. The
  411. * data is *not* copied. A pointer is kept. The caller
  412. * should be careful not to doubly free the data value,
  413. * which may optionally be free'd by XMLRPC_RequestFree().
  414. * INPUTS
  415. * request -- previously allocated request struct
  416. * data -- previously allocated data struct
  417. * RESULT
  418. * XMLRPC_VALUE -- pointer to value stored, or NULL
  419. * SEE ALSO
  420. * XMLRPC_RequestNew ()
  421. * XMLRPC_RequestGetData ()
  422. * XMLRPC_RequestFree ()
  423. * XMLRPC_REQUEST
  424. * XMLRPC_VALUE
  425. * SOURCE
  426. */
  427. XMLRPC_VALUE XMLRPC_RequestSetData(XMLRPC_REQUEST request, XMLRPC_VALUE data) {
  428. if(request && data) {
  429. if (request->io) {
  430. XMLRPC_CleanupValue (request->io);
  431. }
  432. request->io = XMLRPC_CopyValue(data);
  433. return request->io;
  434. }
  435. return NULL;
  436. }
  437. /*******/
  438. /****f* REQUEST/XMLRPC_RequestGetData
  439. * NAME
  440. * XMLRPC_RequestGetData
  441. * SYNOPSIS
  442. * XMLRPC_VALUE XMLRPC_RequestGetData(XMLRPC_REQUEST request)
  443. * FUNCTION
  444. * Returns data associated with request, if any.
  445. * INPUTS
  446. * request -- previously allocated request struct
  447. * RESULT
  448. * XMLRPC_VALUE -- pointer to value stored, or NULL
  449. * SEE ALSO
  450. * XMLRPC_RequestNew ()
  451. * XMLRPC_RequestSetData ()
  452. * XMLRPC_RequestFree ()
  453. * XMLRPC_REQUEST
  454. * XMLRPC_VALUE
  455. * SOURCE
  456. */
  457. XMLRPC_VALUE XMLRPC_RequestGetData(XMLRPC_REQUEST request) {
  458. return request ? request->io : NULL;
  459. }
  460. /*******/
  461. /****f* REQUEST/XMLRPC_RequestSetError
  462. * NAME
  463. * XMLRPC_RequestSetError
  464. * SYNOPSIS
  465. * XMLRPC_VALUE XMLRPC_RequestSetError(XMLRPC_REQUEST request, XMLRPC_VALUE error)
  466. * FUNCTION
  467. * Associates a block of xmlrpc data, representing an error
  468. * condition, with the request.
  469. * INPUTS
  470. * request -- previously allocated request struct
  471. * error -- previously allocated error code or struct
  472. * RESULT
  473. * XMLRPC_VALUE -- pointer to value stored, or NULL
  474. * NOTES
  475. * This is a private function for usage by internals only.
  476. * SEE ALSO
  477. * XMLRPC_RequestGetError ()
  478. * SOURCE
  479. */
  480. XMLRPC_VALUE XMLRPC_RequestSetError (XMLRPC_REQUEST request, XMLRPC_VALUE error) {
  481. if (request && error) {
  482. if (request->error) {
  483. XMLRPC_CleanupValue (request->error);
  484. }
  485. request->error = XMLRPC_CopyValue (error);
  486. return request->error;
  487. }
  488. return NULL;
  489. }
  490. /*******/
  491. /****f* REQUEST/XMLRPC_RequestGetError
  492. * NAME
  493. * XMLRPC_RequestGetError
  494. * SYNOPSIS
  495. * XMLRPC_VALUE XMLRPC_RequestGetError(XMLRPC_REQUEST request)
  496. * FUNCTION
  497. * Returns error data associated with request, if any.
  498. * INPUTS
  499. * request -- previously allocated request struct
  500. * RESULT
  501. * XMLRPC_VALUE -- pointer to error value stored, or NULL
  502. * NOTES
  503. * This is a private function for usage by internals only.
  504. * SEE ALSO
  505. * XMLRPC_RequestSetError ()
  506. * XMLRPC_RequestFree ()
  507. * SOURCE
  508. */
  509. XMLRPC_VALUE XMLRPC_RequestGetError (XMLRPC_REQUEST request) {
  510. return request ? request->error : NULL;
  511. }
  512. /*******/
  513. /****f* REQUEST/XMLRPC_RequestSetOutputOptions
  514. * NAME
  515. * XMLRPC_RequestSetOutputOptions
  516. * SYNOPSIS
  517. * XMLRPC_REQUEST_OUTPUT_OPTIONS XMLRPC_RequestSetOutputOptions(XMLRPC_REQUEST request, XMLRPC_REQUEST_OUTPUT_OPTIONS output)
  518. * FUNCTION
  519. * Sets output options used for generating XML. The output struct
  520. * is copied, and may be freed by the caller.
  521. * INPUTS
  522. * request -- previously allocated request struct
  523. * output -- output options struct initialized by caller
  524. * RESULT
  525. * XMLRPC_REQUEST_OUTPUT_OPTIONS -- pointer to value stored, or NULL
  526. * SEE ALSO
  527. * XMLRPC_RequestNew ()
  528. * XMLRPC_RequestGetOutputOptions ()
  529. * XMLRPC_RequestFree ()
  530. * XMLRPC_REQUEST
  531. * XMLRPC_REQUEST_OUTPUT_OPTIONS
  532. * SOURCE
  533. */
  534. XMLRPC_REQUEST_OUTPUT_OPTIONS XMLRPC_RequestSetOutputOptions(XMLRPC_REQUEST request, XMLRPC_REQUEST_OUTPUT_OPTIONS output) {
  535. if(request && output) {
  536. memcpy (&request->output, output,
  537. sizeof (STRUCT_XMLRPC_REQUEST_OUTPUT_OPTIONS));
  538. return &request->output;
  539. }
  540. return NULL;
  541. }
  542. /*******/
  543. /****f* REQUEST/XMLRPC_RequestGetOutputOptions
  544. * NAME
  545. * XMLRPC_RequestGetOutputOptions
  546. * SYNOPSIS
  547. * XMLRPC_REQUEST_OUTPUT_OPTIONS XMLRPC_RequestGetOutputOptions(XMLRPC_REQUEST request)
  548. * FUNCTION
  549. * Gets a pointer to output options used for generating XML.
  550. * INPUTS
  551. * request -- previously allocated request struct
  552. * RESULT
  553. * XMLRPC_REQUEST_OUTPUT_OPTIONS -- pointer to options stored, or NULL
  554. * SEE ALSO
  555. * XMLRPC_RequestNew ()
  556. * XMLRPC_RequestSetOutputOptions ()
  557. * XMLRPC_RequestFree ()
  558. * XMLRPC_REQUEST
  559. * XMLRPC_REQUEST_OUTPUT_OPTIONS
  560. * SOURCE
  561. */
  562. XMLRPC_REQUEST_OUTPUT_OPTIONS XMLRPC_RequestGetOutputOptions(XMLRPC_REQUEST request) {
  563. return request ? &request->output : NULL;
  564. }
  565. /*******/
  566. /*-*************************
  567. * End XMLRPC_REQUEST funcs *
  568. ***************************/
  569. /*-***************************
  570. * Begin Serializiation funcs *
  571. *****************************/
  572. /****f* SERIALIZE/XMLRPC_VALUE_ToXML
  573. * NAME
  574. * XMLRPC_VALUE_ToXML
  575. * SYNOPSIS
  576. * char* XMLRPC_VALUE_ToXML(XMLRPC_VALUE val)
  577. * FUNCTION
  578. * encode XMLRPC_VALUE into XML buffer. Note that the generated
  579. * buffer will not contain a methodCall.
  580. * INPUTS
  581. * val -- previously allocated XMLRPC_VALUE
  582. * buf_len -- length of returned buffer, if not null
  583. * RESULT
  584. * char* -- newly allocated buffer containing XML.
  585. * It is the caller's responsibility to free it.
  586. * SEE ALSO
  587. * XMLRPC_REQUEST_ToXML ()
  588. * XMLRPC_VALUE_FromXML ()
  589. * XMLRPC_Free ()
  590. * XMLRPC_VALUE
  591. * SOURCE
  592. */
  593. char* XMLRPC_VALUE_ToXML(XMLRPC_VALUE val, int* buf_len) {
  594. xml_element *root_elem = XMLRPC_VALUE_to_xml_element(val);
  595. char* pRet = NULL;
  596. if(root_elem) {
  597. pRet = xml_elem_serialize_to_string(root_elem, NULL, buf_len);
  598. xml_elem_free(root_elem);
  599. }
  600. return pRet;
  601. }
  602. /*******/
  603. /****f* SERIALIZE/XMLRPC_REQUEST_ToXML
  604. * NAME
  605. * XMLRPC_REQUEST_ToXML
  606. * SYNOPSIS
  607. * char* XMLRPC_REQUEST_ToXML(XMLRPC_REQUEST request)
  608. * FUNCTION
  609. * encode XMLRPC_REQUEST into XML buffer
  610. * INPUTS
  611. * request -- previously allocated XMLRPC_REQUEST
  612. * buf_len -- size of returned buf, if not null
  613. * RESULT
  614. * char* -- newly allocated buffer containing XML.
  615. * It is the caller's responsibility to free it.
  616. * SEE ALSO
  617. * XMLRPC_REQUEST_ToXML ()
  618. * XMLRPC_REQUEST_FromXML ()
  619. * XMLRPC_Free ()
  620. * XMLRPC_VALUE_ToXML ()
  621. * XMLRPC_REQUEST
  622. * SOURCE
  623. */
  624. char* XMLRPC_REQUEST_ToXML(XMLRPC_REQUEST request, int* buf_len) {
  625. char* pRet = NULL;
  626. if (request) {
  627. xml_element *root_elem = NULL;
  628. if (request->output.version == xmlrpc_version_simple) {
  629. root_elem = DANDARPC_REQUEST_to_xml_element (request);
  630. }
  631. else if (request->output.version == xmlrpc_version_1_0 ||
  632. request->output.version == xmlrpc_version_none) {
  633. root_elem = XMLRPC_REQUEST_to_xml_element (request);
  634. }
  635. else if (request->output.version == xmlrpc_version_soap_1_1) {
  636. root_elem = SOAP_REQUEST_to_xml_element (request);
  637. }
  638. if(root_elem) {
  639. pRet =
  640. xml_elem_serialize_to_string (root_elem,
  641. &request->output.xml_elem_opts,
  642. buf_len);
  643. xml_elem_free(root_elem);
  644. }
  645. }
  646. return pRet;
  647. }
  648. /*******/
  649. /****f* SERIALIZE/XMLRPC_VALUE_FromXML
  650. * NAME
  651. * XMLRPC_VALUE_FromXML
  652. * SYNOPSIS
  653. * XMLRPC_VALUE XMLRPC_VALUE_FromXML(const char* in_buf, int le
  654. * FUNCTION
  655. * Retrieve XMLRPC_VALUE from XML buffer. Note that this will
  656. * ignore any methodCall. See XMLRPC_REQUEST_FromXML
  657. * INPUTS
  658. * in_buf -- character buffer containing XML
  659. * len -- length of buffer
  660. * RESULT
  661. * XMLRPC_VALUE -- newly allocated data, or NULL if error. Should
  662. * be free'd by caller.
  663. * SEE ALSO
  664. * XMLRPC_VALUE_ToXML ()
  665. * XMLRPC_REQUEST_FromXML ()
  666. * XMLRPC_VALUE
  667. * SOURCE
  668. */
  669. XMLRPC_VALUE XMLRPC_VALUE_FromXML (const char *in_buf, int len, XMLRPC_REQUEST_INPUT_OPTIONS in_options) {
  670. XMLRPC_VALUE xResponse = NULL;
  671. XMLRPC_REQUEST req = XMLRPC_REQUEST_FromXML(in_buf, len, in_options);
  672. if(req) {
  673. xResponse = req->io;
  674. XMLRPC_RequestFree(req, 0);
  675. }
  676. return xResponse;
  677. }
  678. /*******/
  679. /* map parser errors to standard xml-rpc errors */
  680. static XMLRPC_VALUE map_expat_errors(XML_ELEM_ERROR error) {
  681. XMLRPC_VALUE xReturn = NULL;
  682. if(error) {
  683. XMLRPC_ERROR_CODE code;
  684. char buf[1024];
  685. snprintf(buf, sizeof(buf),
  686. "error occurred at line %ld, column %ld, byte index %ld",
  687. error->line, error->column, error->byte_index);
  688. /* expat specific errors */
  689. switch(error->parser_code) {
  690. case XML_ERROR_UNKNOWN_ENCODING:
  691. code = xmlrpc_error_parse_unknown_encoding;
  692. break;
  693. case XML_ERROR_INCORRECT_ENCODING:
  694. code = xmlrpc_error_parse_bad_encoding;
  695. break;
  696. default:
  697. code = xmlrpc_error_parse_xml_syntax;
  698. break;
  699. }
  700. xReturn = XMLRPC_UtilityCreateFault(code, buf);
  701. }
  702. return xReturn;
  703. }
  704. /****f* SERIALIZE/XMLRPC_REQUEST_FromXML
  705. * NAME
  706. * XMLRPC_REQUEST_FromXML
  707. * SYNOPSIS
  708. * XMLRPC_REQUEST XMLRPC_REQUEST_FromXML(const char* in_buf, int le
  709. * FUNCTION
  710. * Retrieve XMLRPC_REQUEST from XML buffer
  711. * INPUTS
  712. * in_buf -- character buffer containing XML
  713. * len -- length of buffer
  714. * RESULT
  715. * XMLRPC_REQUEST -- newly allocated data, or NULL if error. Should
  716. * be free'd by caller.
  717. * SEE ALSO
  718. * XMLRPC_REQUEST_ToXML ()
  719. * XMLRPC_VALUE_FromXML ()
  720. * XMLRPC_REQUEST
  721. * SOURCE
  722. */
  723. XMLRPC_REQUEST XMLRPC_REQUEST_FromXML (const char *in_buf, int len,
  724. XMLRPC_REQUEST_INPUT_OPTIONS in_options) {
  725. XMLRPC_REQUEST request = XMLRPC_RequestNew();
  726. STRUCT_XML_ELEM_ERROR error = {0};
  727. if(request) {
  728. xml_element *root_elem =
  729. xml_elem_parse_buf (in_buf, len,
  730. (in_options ? &in_options->xml_elem_opts : NULL),
  731. &error);
  732. if(root_elem) {
  733. if(!strcmp(root_elem->name, "simpleRPC")) {
  734. request->output.version = xmlrpc_version_simple;
  735. xml_element_to_DANDARPC_REQUEST(request, root_elem);
  736. }
  737. else if (!strcmp (root_elem->name, "SOAP-ENV:Envelope")) {
  738. request->output.version = xmlrpc_version_soap_1_1;
  739. xml_element_to_SOAP_REQUEST (request, root_elem);
  740. }
  741. else {
  742. request->output.version = xmlrpc_version_1_0;
  743. xml_element_to_XMLRPC_REQUEST(request, root_elem);
  744. }
  745. xml_elem_free(root_elem);
  746. }
  747. else {
  748. if(error.parser_error) {
  749. XMLRPC_RequestSetError (request, map_expat_errors (&error));
  750. }
  751. }
  752. }
  753. return request;
  754. }
  755. /*******/
  756. /*-************************
  757. * End Serialization Funcs *
  758. **************************/
  759. /****f* VALUE/XMLRPC_CreateValueEmpty
  760. * NAME
  761. * XMLRPC_CreateValueEmpty
  762. * SYNOPSIS
  763. * XMLRPC_VALUE XMLRPC_CreateValueEmpty ()
  764. * FUNCTION
  765. * Create an XML value to be used/modified elsewhere.
  766. * INPUTS
  767. * RESULT
  768. * XMLRPC_VALUE. The new value, or NULL on failure.
  769. * SEE ALSO
  770. * XMLRPC_CleanupValue ()
  771. * XMLRPC_VALUE
  772. * SOURCE
  773. */
  774. XMLRPC_VALUE XMLRPC_CreateValueEmpty() {
  775. XMLRPC_VALUE v = calloc(1, sizeof(STRUCT_XMLRPC_VALUE));
  776. if(v) {
  777. #ifdef XMLRPC_DEBUG_REFCOUNT
  778. printf ("calloc'd 0x%x\n", v);
  779. #endif
  780. v->type = xmlrpc_empty;
  781. simplestring_init(&v->id);
  782. simplestring_init(&v->str);
  783. }
  784. return v;
  785. }
  786. /*******/
  787. /****f* VALUE/XMLRPC_SetValueID_Case
  788. * NAME
  789. * XMLRPC_SetValueID_Case
  790. * SYNOPSIS
  791. * const char *XMLRPC_SetValueID_Case(XMLRPC_VALUE value, const char* id, int len, XMLRPC_CASE id_case)
  792. * FUNCTION
  793. * Assign an ID (key) to an XMLRPC value.
  794. * INPUTS
  795. * value The xml value who's ID we will set.
  796. * id The desired new id.
  797. * len length of id string if known, or 0 if unknown.
  798. * id_case one of XMLRPC_CASE
  799. * RESULT
  800. * const char* pointer to the newly allocated id string, or NULL
  801. * SEE ALSO
  802. * XMLRPC_SetValueID ()
  803. * XMLRPC_GetValueID ()
  804. * XMLRPC_VALUE
  805. * XMLRPC_CASE
  806. * SOURCE
  807. */
  808. const char *XMLRPC_SetValueID_Case(XMLRPC_VALUE value, const char* id, int len, XMLRPC_CASE id_case) {
  809. const char* pRetval = NULL;
  810. if(value) {
  811. if(id) {
  812. simplestring_clear(&value->id);
  813. (len > 0) ? simplestring_addn(&value->id, id, len) :
  814. simplestring_add(&value->id, id);
  815. /* upper or lower case string in place if required. could be a separate func. */
  816. if(id_case == xmlrpc_case_lower || id_case == xmlrpc_case_upper) {
  817. int i;
  818. for(i = 0; i < value->id.len; i++) {
  819. value->id.str[i] =
  820. (id_case ==
  821. xmlrpc_case_lower) ? tolower (value->id.
  822. str[i]) : toupper (value->
  823. id.
  824. str[i]);
  825. }
  826. }
  827. pRetval = value->id.str;
  828. #ifdef XMLRPC_DEBUG_REFCOUNT
  829. printf("set value id: %s\n", pRetval);
  830. #endif
  831. }
  832. }
  833. return pRetval;
  834. }
  835. /*******/
  836. /****f* VALUE/XMLRPC_SetValueString
  837. * NAME
  838. * XMLRPC_SetValueString
  839. * SYNOPSIS
  840. * const char *XMLRPC_SetValueString(XMLRPC_VALUE value, const char* val, int len)
  841. * FUNCTION
  842. * Assign a string value to an XMLRPC_VALUE, and set it to type xmlrpc_string
  843. * INPUTS
  844. * value The xml value who's ID we will set.
  845. * val The desired new string val.
  846. * len length of val string if known, or 0 if unknown.
  847. * RESULT
  848. * const char* pointer to the newly allocated value string, or NULL
  849. * SEE ALSO
  850. * XMLRPC_GetValueString ()
  851. * XMLRPC_VALUE
  852. * XMLRPC_VALUE_TYPE
  853. * SOURCE
  854. */
  855. const char *XMLRPC_SetValueString(XMLRPC_VALUE value, const char* val, int len) {
  856. char *pRetval = NULL;
  857. if(value && val) {
  858. simplestring_clear(&value->str);
  859. (len > 0) ? simplestring_addn(&value->str, val, len) :
  860. simplestring_add(&value->str, val);
  861. value->type = xmlrpc_string;
  862. pRetval = (char *)value->str.str;
  863. }
  864. return pRetval;
  865. }
  866. /*******/
  867. /****f* VALUE/XMLRPC_SetValueInt
  868. * NAME
  869. * XMLRPC_SetValueInt
  870. * SYNOPSIS
  871. * void XMLRPC_SetValueInt(XMLRPC_VALUE value, int val)
  872. * FUNCTION
  873. * Assign an int value to an XMLRPC_VALUE, and set it to type xmlrpc_int
  874. * INPUTS
  875. * value The xml value who's ID we will set.
  876. * val The desired new integer value
  877. * RESULT
  878. * SEE ALSO
  879. * XMLRPC_GetValueInt ()
  880. * XMLRPC_VALUE
  881. * XMLRPC_VALUE_TYPE
  882. * SOURCE
  883. */
  884. void XMLRPC_SetValueInt(XMLRPC_VALUE value, int val) {
  885. if(value) {
  886. value->type = xmlrpc_int;
  887. value->i = val;
  888. }
  889. }
  890. /*******/
  891. /****f* VALUE/XMLRPC_SetValueBoolean
  892. * NAME
  893. * XMLRPC_SetValueBoolean
  894. * SYNOPSIS
  895. * void XMLRPC_SetValueBoolean(XMLRPC_VALUE value, int val)
  896. * FUNCTION
  897. * Assign a boolean value to an XMLRPC_VALUE, and set it to type xmlrpc_boolean
  898. * INPUTS
  899. * value The xml value who's value we will set.
  900. * val The desired new boolean value. [0 | 1]
  901. * RESULT
  902. * SEE ALSO
  903. * XMLRPC_GetValueBoolean ()
  904. * XMLRPC_VALUE
  905. * XMLRPC_VALUE_TYPE
  906. * SOURCE
  907. */
  908. void XMLRPC_SetValueBoolean(XMLRPC_VALUE value, int val) {
  909. if(value) {
  910. value->type = xmlrpc_boolean;
  911. value->i = val ? 1 : 0;
  912. }
  913. }
  914. /*******/
  915. /****f* VECTOR/XMLRPC_SetIsVector
  916. * NAME
  917. * XMLRPC_SetIsVector
  918. * SYNOPSIS
  919. * int XMLRPC_SetIsVector(XMLRPC_VALUE value, XMLRPC_VECTOR_TYPE type)
  920. * FUNCTION
  921. * Set the XMLRPC_VALUE to be a vector (list) type. The vector may be one of
  922. * [xmlrpc_array | xmlrpc_struct | xmlrpc_mixed]. An array has only index values.
  923. * A struct has key/val pairs. Mixed allows both index and key/val combinations.
  924. * INPUTS
  925. * value The xml value who's vector type we will set
  926. * type New type of vector as enumerated by XMLRPC_VECTOR_TYPE
  927. * RESULT
  928. * int 1 if successful, 0 otherwise
  929. * SEE ALSO
  930. * XMLRPC_GetValueType ()
  931. * XMLRPC_GetVectorType ()
  932. * XMLRPC_VALUE
  933. * XMLRPC_VECTOR_TYPE
  934. * XMLRPC_VALUE_TYPE
  935. * SOURCE
  936. */
  937. int XMLRPC_SetIsVector(XMLRPC_VALUE value, XMLRPC_VECTOR_TYPE type) {
  938. int bSuccess = 0;
  939. if (value) {
  940. /* we can change the type so long as nothing is currently stored. */
  941. if(value->type == xmlrpc_vector) {
  942. if(value->v) {
  943. if(!Q_Size(value->v->q)) {
  944. value->v->type = type;
  945. }
  946. }
  947. }
  948. else {
  949. value->v = calloc(1, sizeof(STRUCT_XMLRPC_VECTOR));
  950. if(value->v) {
  951. value->v->q = (queue*)malloc(sizeof(queue));
  952. if(value->v->q) {
  953. Q_Init(value->v->q);
  954. value->v->type = type;
  955. value->type = xmlrpc_vector;
  956. bSuccess = 1;
  957. }
  958. }
  959. }
  960. }
  961. return bSuccess;
  962. }
  963. /*******/
  964. /****f* VECTOR/XMLRPC_CreateVector
  965. * NAME
  966. * XMLRPC_CreateVector
  967. * SYNOPSIS
  968. * XMLRPC_VALUE XMLRPC_CreateVector(const char* id, XMLRPC_VECTOR_TYPE type)
  969. * FUNCTION
  970. * Create a new vector and optionally set an id.
  971. * INPUTS
  972. * id The id of the vector, or NULL
  973. * type New type of vector as enumerated by XMLRPC_VECTOR_TYPE
  974. * RESULT
  975. * XMLRPC_VALUE The new vector, or NULL on failure.
  976. * SEE ALSO
  977. * XMLRPC_CreateValueEmpty ()
  978. * XMLRPC_SetIsVector ()
  979. * XMLRPC_GetValueType ()
  980. * XMLRPC_GetVectorType ()
  981. * XMLRPC_VALUE
  982. * XMLRPC_VECTOR_TYPE
  983. * XMLRPC_VALUE_TYPE
  984. * SOURCE
  985. */
  986. XMLRPC_VALUE XMLRPC_CreateVector(const char* id, XMLRPC_VECTOR_TYPE type) {
  987. XMLRPC_VALUE val = NULL;
  988. val = XMLRPC_CreateValueEmpty();
  989. if(val) {
  990. if(XMLRPC_SetIsVector(val, type)) {
  991. if(id) {
  992. const char *pSVI = NULL;
  993. pSVI = XMLRPC_SetValueID(val, id, 0);
  994. if(NULL == pSVI) {
  995. val = NULL;
  996. }
  997. }
  998. }
  999. else {
  1000. val = NULL;
  1001. }
  1002. }
  1003. return val;
  1004. }
  1005. /*******/
  1006. /* Not yet implemented.
  1007. *
  1008. * This should use a hash to determine if a given target id has already
  1009. * been appended.
  1010. *
  1011. * Alternately, it could walk the entire vector, but that could be quite
  1012. * slow for very large lists.
  1013. */
  1014. static int isDuplicateEntry(XMLRPC_VALUE target, XMLRPC_VALUE source) {
  1015. return 0;
  1016. }
  1017. /****f* VECTOR/XMLRPC_AddValueToVector
  1018. * NAME
  1019. * XMLRPC_AddValueToVector
  1020. * SYNOPSIS
  1021. * int XMLRPC_AddValueToVector(XMLRPC_VALUE target, XMLRPC_VALUE source)
  1022. * FUNCTION
  1023. * Add (append) an existing XMLRPC_VALUE to a vector.
  1024. * INPUTS
  1025. * target The target vector
  1026. * source The source value to append
  1027. * RESULT
  1028. * int 1 if successful, else 0
  1029. * SEE ALSO
  1030. * XMLRPC_AddValuesToVector ()
  1031. * XMLRPC_VectorGetValueWithID_Case ()
  1032. * XMLRPC_VALUE
  1033. * NOTES
  1034. * The function will fail and return 0 if an attempt is made to add
  1035. * a value with an ID into a vector of type xmlrpc_vector_array. Such
  1036. * values can only be added to xmlrpc_vector_struct.
  1037. * SOURCE
  1038. */
  1039. int XMLRPC_AddValueToVector(XMLRPC_VALUE target, XMLRPC_VALUE source) {
  1040. if(target && source) {
  1041. if(target->type == xmlrpc_vector && target->v &&
  1042. target->v->q && target->v->type != xmlrpc_vector_none) {
  1043. /* guard against putting value of unknown type into vector */
  1044. switch(source->type) {
  1045. case xmlrpc_empty:
  1046. case xmlrpc_base64:
  1047. case xmlrpc_boolean:
  1048. case xmlrpc_datetime:
  1049. case xmlrpc_double:
  1050. case xmlrpc_int:
  1051. case xmlrpc_string:
  1052. case xmlrpc_vector:
  1053. /* Guard against putting a key/val pair into an array vector */
  1054. if( !(source->id.len && target->v->type == xmlrpc_vector_array) ) {
  1055. if (isDuplicateEntry (target, source)
  1056. || Q_PushTail (target->v->q, XMLRPC_CopyValue (source))) {
  1057. return 1;
  1058. }
  1059. }
  1060. else {
  1061. /* fprintf (stderr,
  1062. "xmlrpc: attempted to add key/val pair to vector of type array\n"); */
  1063. }
  1064. break;
  1065. default:
  1066. /* fprintf (stderr,
  1067. "xmlrpc: attempted to add value of unknown type to vector\n"); */
  1068. break;
  1069. }
  1070. }
  1071. }
  1072. return 0;
  1073. }
  1074. /*******/
  1075. /****f* VECTOR/XMLRPC_AddValuesToVector
  1076. * NAME
  1077. * XMLRPC_AddValuesToVector
  1078. * SYNOPSIS
  1079. * XMLRPC_AddValuesToVector ( target, val1, val2, val3, val(n), 0 )
  1080. * XMLRPC_AddValuesToVector( XMLRPC_VALUE, ... )
  1081. * FUNCTION
  1082. * Add (append) a series of existing XMLRPC_VALUE to a vector.
  1083. * INPUTS
  1084. * target The target vector
  1085. * ... The source value(s) to append. The last item *must* be 0.
  1086. * RESULT
  1087. * int 1 if successful, else 0
  1088. * SEE ALSO
  1089. * XMLRPC_AddValuesToVector ()
  1090. * XMLRPC_VectorGetValueWithID_Case ()
  1091. * XMLRPC_VALUE
  1092. * NOTES
  1093. * This function may actually return failure after it has already modified
  1094. * or added items to target. You can not trust the state of target
  1095. * if this function returns failure.
  1096. * SOURCE
  1097. */
  1098. int XMLRPC_AddValuesToVector(XMLRPC_VALUE target, ...) {
  1099. int iRetval = 0;
  1100. if(target) {
  1101. if(target->type == xmlrpc_vector) {
  1102. XMLRPC_VALUE v = NULL;
  1103. va_list vl;
  1104. va_start(vl, target);
  1105. do {
  1106. v = va_arg(vl, XMLRPC_VALUE);
  1107. if(v) {
  1108. if(!XMLRPC_AddValueToVector(target, v)) {
  1109. iRetval = 0;
  1110. break;
  1111. }
  1112. }
  1113. }
  1114. while (v);
  1115. va_end(vl);
  1116. if(NULL == v) {
  1117. iRetval = 1;
  1118. }
  1119. }
  1120. }
  1121. return iRetval;
  1122. }
  1123. /*******/
  1124. /****f* VECTOR/XMLRPC_VectorGetValueWithID_Case
  1125. * NAME
  1126. * XMLRPC_VectorGetValueWithID_Case
  1127. * SYNOPSIS
  1128. * XMLRPC_VALUE XMLRPC_VectorGetValueWithID_Case(XMLRPC_VALUE vector, const char* id, XMLRPC_CASE_COMPARISON id_case)
  1129. * FUNCTION
  1130. * Get value from vector matching id (key)
  1131. * INPUTS
  1132. * vector The source vector
  1133. * id The key to find
  1134. * id_case Rule for how to match key
  1135. * RESULT
  1136. * int 1 if successful, else 0
  1137. * SEE ALSO
  1138. * XMLRPC_SetValueID_Case ()
  1139. * XMLRPC_VALUE
  1140. * XMLRPC_CASE_COMPARISON
  1141. * SOURCE
  1142. */
  1143. XMLRPC_VALUE XMLRPC_VectorGetValueWithID_Case (XMLRPC_VALUE vector, const char *id,
  1144. XMLRPC_CASE_COMPARISON id_case) {
  1145. if(vector && vector->v && vector->v->q) {
  1146. q_iter qi = Q_Iter_Head_F(vector->v->q);
  1147. while(qi) {
  1148. XMLRPC_VALUE xIter = Q_Iter_Get_F(qi);
  1149. if(xIter && xIter->id.str) {
  1150. if(id_case == xmlrpc_case_sensitive) {
  1151. if(!strcmp(xIter->id.str, id)) {
  1152. return xIter;
  1153. }
  1154. }
  1155. else if(id_case == xmlrpc_case_insensitive) {
  1156. if(!strcasecmp(xIter->id.str, id)) {
  1157. return xIter;
  1158. }
  1159. }
  1160. }
  1161. qi = Q_Iter_Next_F(qi);
  1162. }
  1163. }
  1164. return NULL;
  1165. }
  1166. /*******/
  1167. int XMLRPC_VectorRemoveValue(XMLRPC_VALUE vector, XMLRPC_VALUE value) {
  1168. if(vector && vector->v && vector->v->q && value) {
  1169. q_iter qi = Q_Iter_Head_F(vector->v->q);
  1170. while(qi) {
  1171. XMLRPC_VALUE xIter = Q_Iter_Get_F(qi);
  1172. if(xIter == value) {
  1173. XMLRPC_CleanupValue(xIter);
  1174. Q_Iter_Del(vector->v->q, qi);
  1175. return 1;
  1176. }
  1177. qi = Q_Iter_Next_F(qi);
  1178. }
  1179. }
  1180. return 0;
  1181. }
  1182. /****f* VALUE/XMLRPC_CreateValueString
  1183. * NAME
  1184. * XMLRPC_CreateValueString
  1185. * SYNOPSIS
  1186. * XMLRPC_VALUE XMLRPC_CreateValueString(const char* id, const char* val, int len)
  1187. * FUNCTION
  1188. * Create an XMLRPC_VALUE, and assign a string to it
  1189. * INPUTS
  1190. * id The id of the value, or NULL
  1191. * val The desired new string val.
  1192. * len length of val string if known, or 0 if unknown.
  1193. * RESULT
  1194. * newly allocated XMLRPC_VALUE, or NULL
  1195. * SEE ALSO
  1196. * XMLRPC_GetValueString ()
  1197. * XMLRPC_CreateValueEmpty ()
  1198. * XMLRPC_VALUE
  1199. * XMLRPC_VALUE_TYPE
  1200. * SOURCE
  1201. */
  1202. XMLRPC_VALUE XMLRPC_CreateValueString(const char* id, const char* val, int len) {
  1203. XMLRPC_VALUE value = NULL;
  1204. if(val) {
  1205. value = XMLRPC_CreateValueEmpty();
  1206. if(value) {
  1207. XMLRPC_SetValueString(value, val, len);
  1208. if(id) {
  1209. XMLRPC_SetValueID(value, id, 0);
  1210. }
  1211. }
  1212. }
  1213. return value;
  1214. }
  1215. /*******/
  1216. /****f* VALUE/XMLRPC_CreateValueInt
  1217. * NAME
  1218. * XMLRPC_CreateValueInt
  1219. * SYNOPSIS
  1220. * XMLRPC_VALUE XMLRPC_CreateValueInt(const char* id, int i)
  1221. * FUNCTION
  1222. * Create an XMLRPC_VALUE, and assign an int to it
  1223. * INPUTS
  1224. * id The id of the value, or NULL
  1225. * i The desired new int val.
  1226. * RESULT
  1227. * newly allocated XMLRPC_VALUE, or NULL
  1228. * SEE ALSO
  1229. * XMLRPC_GetValueInt ()
  1230. * XMLRPC_CreateValueEmpty ()
  1231. * XMLRPC_VALUE
  1232. * XMLRPC_VALUE_TYPE
  1233. * SOURCE
  1234. */
  1235. XMLRPC_VALUE XMLRPC_CreateValueInt(const char* id, int i) {
  1236. XMLRPC_VALUE val = XMLRPC_CreateValueEmpty();
  1237. if(val) {
  1238. XMLRPC_SetValueInt(val, i);
  1239. if(id) {
  1240. XMLRPC_SetValueID(val, id, 0);
  1241. }
  1242. }
  1243. return val;
  1244. }
  1245. /*******/
  1246. /****f* VALUE/XMLRPC_CreateValueBoolean
  1247. * NAME
  1248. * XMLRPC_CreateValueBoolean
  1249. * SYNOPSIS
  1250. * XMLRPC_VALUE XMLRPC_CreateValueBoolean(const char* id, int i)
  1251. * FUNCTION
  1252. * Create an XMLRPC_VALUE, and assign an int to it
  1253. * INPUTS
  1254. * id The id of the value, or NULL
  1255. * i The desired new int val.
  1256. * RESULT
  1257. * newly allocated XMLRPC_VALUE, or NULL
  1258. * SEE ALSO
  1259. * XMLRPC_GetValueBoolean ()
  1260. * XMLRPC_CreateValueEmpty ()
  1261. * XMLRPC_VALUE
  1262. * XMLRPC_VALUE_TYPE
  1263. * SOURCE
  1264. */
  1265. XMLRPC_VALUE XMLRPC_CreateValueBoolean(const char* id, int i) {
  1266. XMLRPC_VALUE val = XMLRPC_CreateValueEmpty();
  1267. if(val) {
  1268. XMLRPC_SetValueBoolean(val, i);
  1269. if(id) {
  1270. XMLRPC_SetValueID(val, id, 0);
  1271. }
  1272. }
  1273. return val;
  1274. }
  1275. /*******/
  1276. /****f* VALUE/XMLRPC_CleanupValue
  1277. * NAME
  1278. * XMLRPC_CleanupValue
  1279. * SYNOPSIS
  1280. * void XMLRPC_CleanupValue(XMLRPC_VALUE value)
  1281. * FUNCTION
  1282. * Frees all memory allocated for an XMLRPC_VALUE and any of its children (if a vector)
  1283. * INPUTS
  1284. * value The id of the value to be cleaned up.
  1285. * RESULT
  1286. * void
  1287. * NOTES
  1288. * Normally this function will be called for the topmost vector, thus free-ing
  1289. * all children. If a child of a vector is free'd first, results are undefined.
  1290. * Failure to call this function *will* cause memory leaks.
  1291. *
  1292. * Also, this function is implemented using reference counting. Thus a value
  1293. * may be added and freed from multiple parents so long as a reference is added
  1294. * first using XMLRPC_CopyValue()
  1295. * SEE ALSO
  1296. * XMLRPC_RequestFree ()
  1297. * XMLRPC_CreateValueEmpty ()
  1298. * XMLRPC_CopyValue()
  1299. * XMLRPC_VALUE
  1300. * SOURCE
  1301. */
  1302. void XMLRPC_CleanupValue(XMLRPC_VALUE value) {
  1303. if(value) {
  1304. if(value->iRefCount > 0) {
  1305. value->iRefCount --;
  1306. }
  1307. #ifdef XMLRPC_DEBUG_REFCOUNT
  1308. if(value->id.str) {
  1309. printf ("decremented refcount of %s, now %i\n", value->id.str,
  1310. value->iRefCount);
  1311. }
  1312. else {
  1313. printf ("decremented refcount of 0x%x, now %i\n", value,
  1314. value->iRefCount);
  1315. }
  1316. #endif
  1317. if(value->type == xmlrpc_vector) {
  1318. if(value->v) {
  1319. if(value->iRefCount == 0) {
  1320. XMLRPC_VALUE cur = (XMLRPC_VALUE)Q_Head(value->v->q);
  1321. while( cur ) {
  1322. XMLRPC_CleanupValue(cur);
  1323. /* Make sure some idiot didn't include a vector as a child of itself
  1324. * and thus it would have already free'd these.
  1325. */
  1326. if(value->v && value->v->q) {
  1327. cur = Q_Next(value->v->q);
  1328. }
  1329. else {
  1330. break;
  1331. }
  1332. }
  1333. Q_Destroy(value->v->q);
  1334. my_free(value->v->q);
  1335. my_free(value->v);
  1336. }
  1337. }
  1338. }
  1339. if(value->iRefCount == 0) {
  1340. /* guard against freeing invalid types */
  1341. switch(value->type) {
  1342. case xmlrpc_empty:
  1343. case xmlrpc_base64:
  1344. case xmlrpc_boolean:
  1345. case xmlrpc_datetime:
  1346. case xmlrpc_double:
  1347. case xmlrpc_int:
  1348. case xmlrpc_string:
  1349. case xmlrpc_vector:
  1350. #ifdef XMLRPC_DEBUG_REFCOUNT
  1351. if(value->id.str) {
  1352. printf("free'd %s\n", value->id.str);
  1353. }
  1354. else {
  1355. printf("free'd 0x%x\n", value);
  1356. }
  1357. #endif
  1358. simplestring_free(&value->id);
  1359. simplestring_free(&value->str);
  1360. memset(value, 0, sizeof(STRUCT_XMLRPC_VALUE));
  1361. my_free(value);
  1362. break;
  1363. default:
  1364. /* fprintf (stderr,
  1365. "xmlrpc: attempted to free value of invalid type\n"); */
  1366. break;
  1367. }
  1368. }
  1369. }
  1370. }
  1371. /*******/
  1372. /****f* VALUE/XMLRPC_SetValueDateTime
  1373. * NAME
  1374. * XMLRPC_SetValueDateTime
  1375. * SYNOPSIS
  1376. * void XMLRPC_SetValueDateTime(XMLRPC_VALUE value, time_t time)
  1377. * FUNCTION
  1378. * Assign time value to XMLRPC_VALUE
  1379. * INPUTS
  1380. * value The target XMLRPC_VALUE
  1381. * time The desired new unix time value (time_t)
  1382. * RESULT
  1383. * void
  1384. * SEE ALSO
  1385. * XMLRPC_GetValueDateTime ()
  1386. * XMLRPC_SetValueDateTime_ISO8601 ()
  1387. * XMLRPC_CreateValueDateTime ()
  1388. * XMLRPC_VALUE
  1389. * SOURCE
  1390. */
  1391. void XMLRPC_SetValueDateTime(XMLRPC_VALUE value, time_t time) {
  1392. if(value) {
  1393. char timeBuf[30];
  1394. value->type = xmlrpc_datetime;
  1395. value->i = time;
  1396. timeBuf[0] = 0;
  1397. date_to_ISO8601(time, timeBuf, sizeof(timeBuf));
  1398. if(timeBuf[0]) {
  1399. XMLRPC_SetValueDateTime_ISO8601 (value, timeBuf);
  1400. }
  1401. }
  1402. }
  1403. /*******/
  1404. /****f* VALUE/XMLRPC_CopyValue
  1405. * NAME
  1406. * XMLRPC_CopyValue
  1407. * SYNOPSIS
  1408. * XMLRPC_VALUE XMLRPC_CopyValue(XMLRPC_VALUE value)
  1409. * FUNCTION
  1410. * Make a copy (reference) of an XMLRPC_VALUE
  1411. * INPUTS
  1412. * value The target XMLRPC_VALUE
  1413. * RESULT
  1414. * XMLRPC_VALUE -- address of the copy
  1415. * SEE ALSO
  1416. * XMLRPC_CleanupValue ()
  1417. * XMLRPC_DupValueNew ()
  1418. * NOTES
  1419. * This function is implemented via reference counting, so the
  1420. * returned value is going to be the same as the passed in value.
  1421. * The value must be freed the same number of times it is copied
  1422. * or there will be a memory leak.
  1423. * SOURCE
  1424. */
  1425. XMLRPC_VALUE XMLRPC_CopyValue(XMLRPC_VALUE value) {
  1426. if(value) {
  1427. value->iRefCount ++;
  1428. #ifdef XMLRPC_DEBUG_REFCOUNT
  1429. if(value->id.str) {
  1430. printf ("incremented refcount of %s, now %i\n", value->id.str,
  1431. value->iRefCount);
  1432. }
  1433. else {
  1434. printf ("incremented refcount of 0x%x, now %i\n", value,
  1435. value->iRefCount);
  1436. }
  1437. #endif
  1438. }
  1439. return value;
  1440. }
  1441. /*******/
  1442. /****f* VALUE/XMLRPC_DupValueNew
  1443. * NAME
  1444. * XMLRPC_DupValueNew
  1445. * SYNOPSIS
  1446. * XMLRPC_VALUE XMLRPC_DupValueNew(XMLRPC_VALUE value)
  1447. * FUNCTION
  1448. * Make a duplicate (non reference) of an XMLRPC_VALUE with newly allocated mem.
  1449. * INPUTS
  1450. * value The source XMLRPC_VALUE to duplicate
  1451. * RESULT
  1452. * XMLRPC_VALUE -- address of the duplicate value
  1453. * SEE ALSO
  1454. * XMLRPC_CleanupValue ()
  1455. * XMLRPC_CopyValue ()
  1456. * NOTES
  1457. * Use this when function when you need to modify the contents of
  1458. * the copied value separately from the original.
  1459. *
  1460. * this function is recursive, thus the value and all of its children
  1461. * (if any) will be duplicated.
  1462. * SOURCE
  1463. */
  1464. XMLRPC_VALUE XMLRPC_DupValueNew (XMLRPC_VALUE xSource) {
  1465. XMLRPC_VALUE xReturn = NULL;
  1466. if (xSource) {
  1467. xReturn = XMLRPC_CreateValueEmpty ();
  1468. if (xSource->id.len) {
  1469. XMLRPC_SetValueID (xReturn, xSource->id.str, xSource->id.len);
  1470. }
  1471. switch (xSource->type) {
  1472. case xmlrpc_int:
  1473. case xmlrpc_boolean:
  1474. XMLRPC_SetValueInt (xReturn, xSource->i);
  1475. break;
  1476. case xmlrpc_string:
  1477. case xmlrpc_base64:
  1478. XMLRPC_SetValueString (xReturn, xSource->str.str, xSource->str.len);
  1479. break;
  1480. case xmlrpc_datetime:
  1481. XMLRPC_SetValueDateTime (xReturn, xSource->i);
  1482. break;
  1483. case xmlrpc_double:
  1484. XMLRPC_SetValueDouble (xReturn, xSource->d);
  1485. break;
  1486. case xmlrpc_vector:
  1487. {
  1488. q_iter qi = Q_Iter_Head_F (xSource->v->q);
  1489. XMLRPC_SetIsVector (xReturn, xSource->v->type);
  1490. while (qi) {
  1491. XMLRPC_VALUE xIter = Q_Iter_Get_F (qi);
  1492. XMLRPC_AddValueToVector (xReturn, XMLRPC_DupValueNew (xIter));
  1493. qi = Q_Iter_Next_F (qi);
  1494. }
  1495. }
  1496. break;
  1497. default:
  1498. break;
  1499. }
  1500. }
  1501. return xReturn;
  1502. }
  1503. /*******/
  1504. /****f* VALUE/XMLRPC_CreateValueDateTime
  1505. * NAME
  1506. * XMLRPC_CreateValueDateTime
  1507. * SYNOPSIS
  1508. * XMLRPC_VALUE XMLRPC_CreateValueDateTime(const char* id, time_t time)
  1509. * FUNCTION
  1510. * Create new datetime value from time_t
  1511. * INPUTS
  1512. * id id of the new value, or NULL
  1513. * time The desired unix time value (time_t)
  1514. * RESULT
  1515. * void
  1516. * SEE ALSO
  1517. * XMLRPC_GetValueDateTime ()
  1518. * XMLRPC_SetValueDateTime ()
  1519. * XMLRPC_CreateValueDateTime_ISO8601 ()
  1520. * XMLRPC_VALUE
  1521. * SOURCE
  1522. */
  1523. XMLRPC_VALUE XMLRPC_CreateValueDateTime(const char* id, time_t time) {
  1524. XMLRPC_VALUE val = XMLRPC_CreateValueEmpty();
  1525. if(val) {
  1526. XMLRPC_SetValueDateTime(val, time);
  1527. if(id) {
  1528. XMLRPC_SetValueID(val, id, 0);
  1529. }
  1530. }
  1531. return val;
  1532. }
  1533. /*******/
  1534. /****f* VALUE/XMLRPC_SetValueDateTime_ISO8601
  1535. * NAME
  1536. * XMLRPC_SetValueDateTime_ISO8601
  1537. * SYNOPSIS
  1538. * void XMLRPC_SetValueDateTime_ISO8601(XMLRPC_VALUE value, const char* s)
  1539. * FUNCTION
  1540. * Set datetime value from IS08601 encoded string
  1541. * INPUTS
  1542. * value The target XMLRPC_VALUE
  1543. * s The desired new time value
  1544. * RESULT
  1545. * void
  1546. * BUGS
  1547. * This function currently attempts to convert the time string to a valid unix time
  1548. * value before passing it. Behavior when the string is invalid or out of range
  1549. * is not well defined, but will probably result in Jan 1, 1970 (0) being passed.
  1550. * SEE ALSO
  1551. * XMLRPC_GetValueDateTime_ISO8601 ()
  1552. * XMLRPC_CreateValueDateTime_ISO8601 ()
  1553. * XMLRPC_CreateValueDateTime ()
  1554. * XMLRPC_VALUE
  1555. * SOURCE
  1556. */
  1557. void XMLRPC_SetValueDateTime_ISO8601(XMLRPC_VALUE value, const char* s) {
  1558. if(value) {
  1559. time_t time_val = 0;
  1560. if(s) {
  1561. value->type = xmlrpc_datetime;
  1562. date_from_ISO8601(s, &time_val);
  1563. value->i = time_val;
  1564. simplestring_clear(&value->str);
  1565. simplestring_add(&value->str, s);
  1566. }
  1567. }
  1568. }
  1569. /*******/
  1570. /****f* VALUE/XMLRPC_CreateValueDateTime_ISO8601
  1571. * NAME
  1572. * XMLRPC_CreateValueDateTime_ISO8601
  1573. * SYNOPSIS
  1574. * XMLRPC_VALUE XMLRPC_CreateValueDateTime_ISO8601(const char* id, const char *s)
  1575. * FUNCTION
  1576. * Create datetime value from IS08601 encoded string
  1577. * INPUTS
  1578. * id The id of the new value, or NULL
  1579. * s The desired new time value
  1580. * RESULT
  1581. * newly allocated XMLRPC_VALUE, or NULL if no value created.
  1582. * BUGS
  1583. * See XMLRPC_SetValueDateTime_ISO8601 ()
  1584. * SEE ALSO
  1585. * XMLRPC_GetValueDateTime_ISO8601 ()
  1586. * XMLRPC_SetValueDateTime_ISO8601 ()
  1587. * XMLRPC_CreateValueDateTime ()
  1588. * XMLRPC_VALUE
  1589. * SOURCE
  1590. */
  1591. XMLRPC_VALUE XMLRPC_CreateValueDateTime_ISO8601(const char* id, const char *s) {
  1592. XMLRPC_VALUE val = XMLRPC_CreateValueEmpty();
  1593. if(val) {
  1594. XMLRPC_SetValueDateTime_ISO8601(val, s);
  1595. if(id) {
  1596. XMLRPC_SetValueID(val, id, 0);
  1597. }
  1598. }
  1599. return val;
  1600. }
  1601. /*******/
  1602. /****f* VALUE/XMLRPC_SetValueBase64
  1603. * NAME
  1604. * XMLRPC_SetValueBase64
  1605. * SYNOPSIS
  1606. * void XMLRPC_SetValueBase64(XMLRPC_VALUE value, const char* s, int len)
  1607. * FUNCTION
  1608. * Set base64 value. Base64 is useful for transferring binary data, such as an image.
  1609. * INPUTS
  1610. * value The target XMLRPC_VALUE
  1611. * s The desired new binary value
  1612. * len The length of s, or NULL. If buffer is not null terminated, len *must* be passed.
  1613. * RESULT
  1614. * void
  1615. * NOTES
  1616. * Data is set/stored/retrieved as passed in, but is base64 encoded for XML transfer, and
  1617. * decoded on the other side. This is transparent to the caller.
  1618. * SEE ALSO
  1619. * XMLRPC_GetValueBase64 ()
  1620. * XMLRPC_CreateValueBase64 ()
  1621. * XMLRPC_VALUE
  1622. * SOURCE
  1623. */
  1624. void XMLRPC_SetValueBase64(XMLRPC_VALUE value, const char* s, int len) {
  1625. if(value && s) {
  1626. simplestring_clear(&value->str);
  1627. (len > 0) ? simplestring_addn(&value->str, s, len) :
  1628. simplestring_add(&value->str, s);
  1629. value->type = xmlrpc_base64;
  1630. }
  1631. }
  1632. /*******/
  1633. /****f* VALUE/XMLRPC_CreateValueBase64
  1634. * NAME
  1635. * XMLRPC_CreateValueBase64
  1636. * SYNOPSIS
  1637. * XMLRPC_VALUE XMLRPC_CreateValueBase64(const char* id, const char* s, int len)
  1638. * FUNCTION
  1639. * Create base64 value. Base64 is useful for transferring binary data, such as an image.
  1640. * INPUTS
  1641. * id id of the new value, or NULL
  1642. * s The desired new binary value
  1643. * len The length of s, or NULL. If buffer is not null terminated, len *must* be passed.
  1644. * RESULT
  1645. * newly allocated XMLRPC_VALUE, or NULL if error
  1646. * NOTES
  1647. * See XMLRPC_SetValueBase64 ()
  1648. * SEE ALSO
  1649. * XMLRPC_GetValueBase64 ()
  1650. * XMLRPC_SetValueBase64 ()
  1651. * XMLRPC_VALUE
  1652. * SOURCE
  1653. */
  1654. XMLRPC_VALUE XMLRPC_CreateValueBase64(const char* id, const char* s, int len) {
  1655. XMLRPC_VALUE val = XMLRPC_CreateValueEmpty();
  1656. if(val) {
  1657. XMLRPC_SetValueBase64(val, s, len);
  1658. if(id) {
  1659. XMLRPC_SetValueID(val, id, 0);
  1660. }
  1661. }
  1662. return val;
  1663. }
  1664. /*******/
  1665. /****f* VALUE/XMLRPC_SetValueDouble
  1666. * NAME
  1667. * XMLRPC_SetValueDouble
  1668. * SYNOPSIS
  1669. * void XMLRPC_SetValueDouble(XMLRPC_VALUE value, double val)
  1670. * FUNCTION
  1671. * Set double (floating point) value.
  1672. * INPUTS
  1673. * value The target XMLRPC_VALUE
  1674. * val The desired new double value
  1675. * RESULT
  1676. * void
  1677. * SEE ALSO
  1678. * XMLRPC_GetValueDouble ()
  1679. * XMLRPC_CreateValueDouble ()
  1680. * XMLRPC_VALUE
  1681. * SOURCE
  1682. */
  1683. void XMLRPC_SetValueDouble(XMLRPC_VALUE value, double val) {
  1684. if(value) {
  1685. value->type = xmlrpc_double;
  1686. value->d = val;
  1687. }
  1688. }
  1689. /*******/
  1690. /****f* VALUE/XMLRPC_CreateValueDouble
  1691. * NAME
  1692. * XMLRPC_CreateValueDouble
  1693. * SYNOPSIS
  1694. * XMLRPC_VALUE XMLRPC_CreateValueDouble(const char* id, double d)
  1695. * FUNCTION
  1696. * Create double (floating point) value.
  1697. * INPUTS
  1698. * id id of the newly created value, or NULL
  1699. * d The desired new double value
  1700. * RESULT
  1701. * void
  1702. * SEE ALSO
  1703. * XMLRPC_GetValueDouble ()
  1704. * XMLRPC_CreateValueDouble ()
  1705. * XMLRPC_VALUE
  1706. * SOURCE
  1707. */
  1708. XMLRPC_VALUE XMLRPC_CreateValueDouble(const char* id, double d) {
  1709. XMLRPC_VALUE val = XMLRPC_CreateValueEmpty();
  1710. if(val) {
  1711. XMLRPC_SetValueDouble(val, d);
  1712. if(id) {
  1713. XMLRPC_SetValueID(val, id, 0);
  1714. }
  1715. }
  1716. return val;
  1717. }
  1718. /*******/
  1719. /****f* VALUE/XMLRPC_GetValueString
  1720. * NAME
  1721. * XMLRPC_GetValueString
  1722. * SYNOPSIS
  1723. * const char* XMLRPC_GetValueString(XMLRPC_VALUE value)
  1724. * FUNCTION
  1725. * retrieve string value
  1726. * INPUTS
  1727. * value source XMLRPC_VALUE of type xmlrpc_string
  1728. * RESULT
  1729. * void
  1730. * SEE ALSO
  1731. * XMLRPC_SetValueString ()
  1732. * XMLRPC_GetValueType ()
  1733. * XMLRPC_VALUE
  1734. * SOURCE
  1735. */
  1736. const char* XMLRPC_GetValueString(XMLRPC_VALUE value) {
  1737. return ((value && value->type == xmlrpc_string) ? value->str.str : 0);
  1738. }
  1739. /*******/
  1740. /****f* VALUE/XMLRPC_GetValueStringLen
  1741. * NAME
  1742. * XMLRPC_GetValueStringLen
  1743. * SYNOPSIS
  1744. * int XMLRPC_GetValueStringLen(XMLRPC_VALUE value)
  1745. * FUNCTION
  1746. * determine length of string value
  1747. * INPUTS
  1748. * value XMLRPC_VALUE of type xmlrpc_string
  1749. * RESULT
  1750. * length of string, or 0
  1751. * NOTES
  1752. * SEE ALSO
  1753. * XMLRPC_SetValueString ()
  1754. * XMLRPC_GetValueString ()
  1755. * SOURCE
  1756. */
  1757. int XMLRPC_GetValueStringLen(XMLRPC_VALUE value) {
  1758. return ((value) ? value->str.len : 0);
  1759. }
  1760. /*******/
  1761. /****f* VALUE/XMLRPC_GetValueInt
  1762. * NAME
  1763. * XMLRPC_GetValueInt
  1764. * SYNOPSIS
  1765. * int XMLRPC_GetValueInt(XMLRPC_VALUE value)
  1766. * FUNCTION
  1767. * retrieve integer value.
  1768. * INPUTS
  1769. * value XMLRPC_VALUE of type xmlrpc_int
  1770. * RESULT
  1771. * integer value or 0 if value is not valid int
  1772. * NOTES
  1773. * use XMLRPC_GetValueType () to be sure if 0 is real return value or not
  1774. * SEE ALSO
  1775. * XMLRPC_SetValueInt ()
  1776. * XMLRPC_CreateValueInt ()
  1777. * SOURCE
  1778. */
  1779. int XMLRPC_GetValueInt(XMLRPC_VALUE value) {
  1780. return ((value && value->type == xmlrpc_int) ? value->i : 0);
  1781. }
  1782. /*******/
  1783. /****f* VALUE/XMLRPC_GetValueBoolean
  1784. * NAME
  1785. * XMLRPC_GetValueBoolean
  1786. * SYNOPSIS
  1787. * int XMLRPC_GetValueBoolean(XMLRPC_VALUE value)
  1788. * FUNCTION
  1789. * retrieve boolean value.
  1790. * INPUTS
  1791. * XMLRPC_VALUE of type xmlrpc_boolean
  1792. * RESULT
  1793. * boolean value or 0 if value is not valid boolean
  1794. * NOTES
  1795. * use XMLRPC_GetValueType() to be sure if 0 is real value or not
  1796. * SEE ALSO
  1797. * XMLRPC_SetValueBoolean ()
  1798. * XMLRPC_CreateValueBoolean ()
  1799. * SOURCE
  1800. */
  1801. int XMLRPC_GetValueBoolean(XMLRPC_VALUE value) {
  1802. return ((value && value->type == xmlrpc_boolean) ? value->i : 0);
  1803. }
  1804. /*******/
  1805. /****f* VALUE/XMLRPC_GetValueDouble
  1806. * NAME
  1807. * XMLRPC_GetValueDouble
  1808. * SYNOPSIS
  1809. * double XMLRPC_GetValueDouble(XMLRPC_VALUE value)
  1810. * FUNCTION
  1811. * retrieve double value
  1812. * INPUTS
  1813. * XMLRPC_VALUE of type xmlrpc_double
  1814. * RESULT
  1815. * double value or 0 if value is not valid double.
  1816. * NOTES
  1817. * use XMLRPC_GetValueType() to be sure if 0 is real value or not
  1818. * SEE ALSO
  1819. * XMLRPC_SetValueDouble ()
  1820. * XMLRPC_CreateValueDouble ()
  1821. * SOURCE
  1822. */
  1823. double XMLRPC_GetValueDouble(XMLRPC_VALUE value) {
  1824. return ((value && value->type == xmlrpc_double) ? value->d : 0);
  1825. }
  1826. /*******/
  1827. /****f* VALUE/XMLRPC_GetValueBase64
  1828. * NAME
  1829. * XMLRPC_GetValueBase64
  1830. * SYNOPSIS
  1831. * const char* XMLRPC_GetValueBase64(XMLRPC_VALUE value)
  1832. * FUNCTION
  1833. * retrieve binary value
  1834. * INPUTS
  1835. * XMLRPC_VALUE of type xmlrpc_base64
  1836. * RESULT
  1837. * pointer to binary value or 0 if value is not valid.
  1838. * SEE ALSO
  1839. * XMLRPC_SetValueBase64 ()
  1840. * XMLRPC_CreateValueBase64 ()
  1841. * NOTES
  1842. * Call XMLRPC_GetValueStringLen() to retrieve real length of binary data. strlen()
  1843. * will not be accurate, as returned data may contain embedded nulls.
  1844. * SOURCE
  1845. */
  1846. const char* XMLRPC_GetValueBase64(XMLRPC_VALUE value) {
  1847. return ((value && value->type == xmlrpc_base64) ? value->str.str : 0);
  1848. }
  1849. /*******/
  1850. /****f* VALUE/XMLRPC_GetValueDateTime
  1851. * NAME
  1852. * XMLRPC_GetValueDateTime
  1853. * SYNOPSIS
  1854. * time_t XMLRPC_GetValueDateTime(XMLRPC_VALUE value)
  1855. * FUNCTION
  1856. * retrieve time_t value
  1857. * INPUTS
  1858. * XMLRPC_VALUE of type xmlrpc_datetime
  1859. * RESULT
  1860. * time_t value or 0 if value is not valid datetime.
  1861. * NOTES
  1862. * use XMLRPC_GetValueType() to be sure if 0 is real value or not
  1863. * SEE ALSO
  1864. * XMLRPC_SetValueDateTime ()
  1865. * XMLRPC_GetValueDateTime_ISO8601 ()
  1866. * XMLRPC_CreateValueDateTime ()
  1867. * SOURCE
  1868. */
  1869. time_t XMLRPC_GetValueDateTime(XMLRPC_VALUE value) {
  1870. return (time_t)((value && value->type == xmlrpc_datetime) ? value->i : 0);
  1871. }
  1872. /*******/
  1873. /****f* VALUE/XMLRPC_GetValueDateTime_IOS8601
  1874. * NAME
  1875. * XMLRPC_GetValueDateTime_IOS8601
  1876. * SYNOPSIS
  1877. * const char* XMLRPC_GetValueDateTime_IOS8601(XMLRPC_VALUE value)
  1878. * FUNCTION
  1879. * retrieve ISO8601 formatted time value
  1880. * INPUTS
  1881. * XMLRPC_VALUE of type xmlrpc_datetime
  1882. * RESULT
  1883. * const char* value or 0 if value is not valid datetime.
  1884. * SEE ALSO
  1885. * XMLRPC_SetValueDateTime_IOS8601 ()
  1886. * XMLRPC_GetValueDateTime ()
  1887. * XMLRPC_CreateValueDateTime_IOS8601 ()
  1888. * SOURCE
  1889. */
  1890. const char* XMLRPC_GetValueDateTime_ISO8601(XMLRPC_VALUE value) {
  1891. return ((value && value->type == xmlrpc_datetime) ? value->str.str : 0);
  1892. }
  1893. /*******/
  1894. /* Get ID (key) of value or NULL */
  1895. /****f* VALUE/XMLRPC_GetValueID
  1896. * NAME
  1897. * XMLRPC_GetValueID
  1898. * SYNOPSIS
  1899. * const char* XMLRPC_GetValueID(XMLRPC_VALUE value)
  1900. * FUNCTION
  1901. * retrieve id (key) of value
  1902. * INPUTS
  1903. * XMLRPC_VALUE of any type
  1904. * RESULT
  1905. * const char* pointer to id of value, or NULL
  1906. * NOTES
  1907. * SEE ALSO
  1908. * XMLRPC_SetValueID()
  1909. * XMLRPC_CreateValueEmpty()
  1910. * SOURCE
  1911. */
  1912. const char* XMLRPC_GetValueID(XMLRPC_VALUE value) {
  1913. return (const char*)((value && value->id.len) ? value->id.str : 0);
  1914. }
  1915. /*******/
  1916. /****f* VECTOR/XMLRPC_VectorSize
  1917. * NAME
  1918. * XMLRPC_VectorSize
  1919. * SYNOPSIS
  1920. * int XMLRPC_VectorSize(XMLRPC_VALUE value)
  1921. * FUNCTION
  1922. * retrieve size of vector
  1923. * INPUTS
  1924. * XMLRPC_VALUE of type xmlrpc_vector
  1925. * RESULT
  1926. * count of items in vector
  1927. * NOTES
  1928. * This is a cheap operation even on large vectors. Vector size is
  1929. * maintained by queue during add/remove ops.
  1930. * SEE ALSO
  1931. * XMLRPC_AddValueToVector ()
  1932. * SOURCE
  1933. */
  1934. int XMLRPC_VectorSize(XMLRPC_VALUE value) {
  1935. int size = 0;
  1936. if(value && value->type == xmlrpc_vector && value->v) {
  1937. size = Q_Size(value->v->q);
  1938. }
  1939. return size;
  1940. }
  1941. /*******/
  1942. /****f* VECTOR/XMLRPC_VectorRewind
  1943. * NAME
  1944. * XMLRPC_VectorRewind
  1945. * SYNOPSIS
  1946. * XMLRPC_VALUE XMLRPC_VectorRewind(XMLRPC_VALUE value)
  1947. * FUNCTION
  1948. * reset vector to first item
  1949. * INPUTS
  1950. * XMLRPC_VALUE of type xmlrpc_vector
  1951. * RESULT
  1952. * first XMLRPC_VALUE in list, or NULL if empty or error.
  1953. * NOTES
  1954. * Be careful to rewind any vector passed in to you if you expect to
  1955. * iterate through the entire list.
  1956. * SEE ALSO
  1957. * XMLRPC_VectorNext ()
  1958. * SOURCE
  1959. */
  1960. XMLRPC_VALUE XMLRPC_VectorRewind(XMLRPC_VALUE value) {
  1961. XMLRPC_VALUE xReturn = NULL;
  1962. if(value && value->type == xmlrpc_vector && value->v) {
  1963. xReturn = (XMLRPC_VALUE)Q_Head(value->v->q);
  1964. }
  1965. return xReturn;
  1966. }
  1967. /*******/
  1968. /****f* VECTOR/XMLRPC_VectorNext
  1969. * NAME
  1970. * XMLRPC_VectorNext
  1971. * SYNOPSIS
  1972. * XMLRPC_VALUE XMLRPC_VectorNext(XMLRPC_VALUE value)
  1973. * FUNCTION
  1974. * Iterate vector to next item in list.
  1975. * INPUTS
  1976. * XMLRPC_VALUE of type xmlrpc_vector
  1977. * RESULT
  1978. * Next XMLRPC_VALUE in vector, or NULL if at end.
  1979. * NOTES
  1980. * SEE ALSO
  1981. * XMLRPC_VectorRewind ()
  1982. * SOURCE
  1983. */
  1984. XMLRPC_VALUE XMLRPC_VectorNext(XMLRPC_VALUE value) {
  1985. XMLRPC_VALUE xReturn = NULL;
  1986. if(value && value->type == xmlrpc_vector && value->v) {
  1987. xReturn = (XMLRPC_VALUE)Q_Next(value->v->q);
  1988. }
  1989. return xReturn;
  1990. }
  1991. /*******/
  1992. /****f* VALUE/XMLRPC_GetValueType
  1993. * NAME
  1994. * XMLRPC_GetValueType
  1995. * SYNOPSIS
  1996. * XMLRPC_VALUE_TYPE XMLRPC_GetValueType(XMLRPC_VALUE value)
  1997. * FUNCTION
  1998. * determine data type of the XMLRPC_VALUE
  1999. * INPUTS
  2000. * XMLRPC_VALUE target of query
  2001. * RESULT
  2002. * data type of value as enumerated by XMLRPC_VALUE_TYPE
  2003. * NOTES
  2004. * all values are of type xmlrpc_empty until set.
  2005. * Deprecated for public use. See XMLRPC_GetValueTypeEasy
  2006. * SEE ALSO
  2007. * XMLRPC_SetValue*
  2008. * XMLRPC_CreateValue*
  2009. * XMLRPC_Append*
  2010. * XMLRPC_GetValueTypeEasy ()
  2011. * SOURCE
  2012. */
  2013. XMLRPC_VALUE_TYPE XMLRPC_GetValueType(XMLRPC_VALUE value) {
  2014. return value ? value->type : xmlrpc_empty;
  2015. }
  2016. /*******/
  2017. /* Vector type accessor */
  2018. /****f* VALUE/XMLRPC_GetVectorType
  2019. * NAME
  2020. * XMLRPC_GetVectorType
  2021. * SYNOPSIS
  2022. * XMLRPC_VECTOR_TYPE XMLRPC_GetVectorType(XMLRPC_VALUE value)
  2023. * FUNCTION
  2024. * determine vector type of the XMLRPC_VALUE
  2025. * INPUTS
  2026. * XMLRPC_VALUE of type xmlrpc_vector
  2027. * RESULT
  2028. * vector type of value as enumerated by XMLRPC_VECTOR_TYPE.
  2029. * xmlrpc_none if not a value.
  2030. * NOTES
  2031. * xmlrpc_none is returned if value is not a vector
  2032. * Deprecated for public use. See XMLRPC_GetValueTypeEasy
  2033. * SEE ALSO
  2034. * XMLRPC_SetIsVector ()
  2035. * XMLRPC_GetValueType ()
  2036. * XMLRPC_GetValueTypeEasy ()
  2037. * SOURCE
  2038. */
  2039. XMLRPC_VECTOR_TYPE XMLRPC_GetVectorType(XMLRPC_VALUE value) {
  2040. return(value && value->v) ? value->v->type : xmlrpc_none;
  2041. }
  2042. /*******/
  2043. /****f* VALUE/XMLRPC_GetValueTypeEasy
  2044. * NAME
  2045. * XMLRPC_GetValueTypeEasy
  2046. * SYNOPSIS
  2047. * XMLRPC_VALUE_TYPE_EASY XMLRPC_GetValueTypeEasy(XMLRPC_VALUE value)
  2048. * FUNCTION
  2049. * determine data type of the XMLRPC_VALUE. includes vector types.
  2050. * INPUTS
  2051. * XMLRPC_VALUE target of query
  2052. * RESULT
  2053. * data type of value as enumerated by XMLRPC_VALUE_TYPE_EASY
  2054. * xmlrpc_type_none if not a value.
  2055. * NOTES
  2056. * all values are of type xmlrpc_type_empty until set.
  2057. * SEE ALSO
  2058. * XMLRPC_SetValue*
  2059. * XMLRPC_CreateValue*
  2060. * XMLRPC_Append*
  2061. * SOURCE
  2062. */
  2063. XMLRPC_VALUE_TYPE_EASY XMLRPC_GetValueTypeEasy (XMLRPC_VALUE value) {
  2064. if (value) {
  2065. switch (value->type) {
  2066. case xmlrpc_vector:
  2067. switch (value->v->type) {
  2068. case xmlrpc_vector_none:
  2069. return xmlrpc_type_none;
  2070. case xmlrpc_vector_struct:
  2071. return xmlrpc_type_struct;
  2072. case xmlrpc_vector_mixed:
  2073. return xmlrpc_type_mixed;
  2074. case xmlrpc_vector_array:
  2075. return xmlrpc_type_array;
  2076. }
  2077. default:
  2078. /* evil cast, but we know they are the same */
  2079. return(XMLRPC_VALUE_TYPE_EASY) value->type;
  2080. }
  2081. }
  2082. return xmlrpc_none;
  2083. }
  2084. /*******/
  2085. /*-*******************
  2086. * Begin Server Funcs *
  2087. *********************/
  2088. /****f* VALUE/XMLRPC_ServerCreate
  2089. * NAME
  2090. * XMLRPC_ServerCreate
  2091. * SYNOPSIS
  2092. * XMLRPC_SERVER XMLRPC_ServerCreate()
  2093. * FUNCTION
  2094. * Allocate/Init XMLRPC Server Resources.
  2095. * INPUTS
  2096. * none
  2097. * RESULT
  2098. * newly allocated XMLRPC_SERVER
  2099. * NOTES
  2100. * SEE ALSO
  2101. * XMLRPC_ServerDestroy ()
  2102. * XMLRPC_GetGlobalServer ()
  2103. * SOURCE
  2104. */
  2105. XMLRPC_SERVER XMLRPC_ServerCreate() {
  2106. XMLRPC_SERVER server = calloc(1, sizeof(STRUCT_XMLRPC_SERVER));
  2107. if(server) {
  2108. Q_Init(&server->methodlist);
  2109. Q_Init(&server->docslist);
  2110. /* register system methods */
  2111. xsm_register(server);
  2112. }
  2113. return server;
  2114. }
  2115. /*******/
  2116. /* Return global server. Not locking! Not Thread Safe! */
  2117. /****f* VALUE/XMLRPC_GetGlobalServer
  2118. * NAME
  2119. * XMLRPC_GetGlobalServer
  2120. * SYNOPSIS
  2121. * XMLRPC_SERVER XMLRPC_GetGlobalServer()
  2122. * FUNCTION
  2123. * Allocates a global (process-wide) server, or returns pointer if pre-existing.
  2124. * INPUTS
  2125. * none
  2126. * RESULT
  2127. * pointer to global server, or 0 if error.
  2128. * NOTES
  2129. * ***WARNING*** This function is not thread safe. It is included only for the very lazy.
  2130. * Multi-threaded programs that use this may experience problems.
  2131. * BUGS
  2132. * There is currently no way to cleanup the global server gracefully.
  2133. * SEE ALSO
  2134. * XMLRPC_ServerCreate ()
  2135. * SOURCE
  2136. */
  2137. XMLRPC_SERVER XMLRPC_GetGlobalServer() {
  2138. static XMLRPC_SERVER xsServer = 0;
  2139. if(!xsServer) {
  2140. xsServer = XMLRPC_ServerCreate();
  2141. }
  2142. return xsServer;
  2143. }
  2144. /*******/
  2145. /****f* VALUE/XMLRPC_ServerDestroy
  2146. * NAME
  2147. * XMLRPC_ServerDestroy
  2148. * SYNOPSIS
  2149. * void XMLRPC_ServerDestroy(XMLRPC_SERVER server)
  2150. * FUNCTION
  2151. * Free Server Resources
  2152. * INPUTS
  2153. * server The server to be free'd
  2154. * RESULT
  2155. * void
  2156. * NOTES
  2157. * This frees the server struct and any methods that have been added.
  2158. * SEE ALSO
  2159. * XMLRPC_ServerCreate ()
  2160. * SOURCE
  2161. */
  2162. void XMLRPC_ServerDestroy(XMLRPC_SERVER server) {
  2163. if(server) {
  2164. doc_method* dm = Q_Head(&server->docslist);
  2165. server_method* sm = Q_Head(&server->methodlist);
  2166. while( dm ) {
  2167. my_free(dm);
  2168. dm = Q_Next(&server->docslist);
  2169. }
  2170. while( sm ) {
  2171. if(sm->name) {
  2172. my_free(sm->name);
  2173. }
  2174. if(sm->desc) {
  2175. XMLRPC_CleanupValue(sm->desc);
  2176. }
  2177. my_free(sm);
  2178. sm = Q_Next(&server->methodlist);
  2179. }
  2180. if(server->xIntrospection) {
  2181. XMLRPC_CleanupValue(server->xIntrospection);
  2182. }
  2183. Q_Destroy(&server->methodlist);
  2184. Q_Destroy(&server->docslist);
  2185. my_free(server);
  2186. }
  2187. }
  2188. /*******/
  2189. /****f* VALUE/XMLRPC_ServerRegisterMethod
  2190. * NAME
  2191. * XMLRPC_ServerRegisterMethod
  2192. * SYNOPSIS
  2193. * void XMLRPC_ServerRegisterMethod(XMLRPC_SERVER server, const char *name, XMLRPC_Callback cb)
  2194. * FUNCTION
  2195. * Register new XMLRPC method with server
  2196. * INPUTS
  2197. * server The XMLRPC_SERVER to register the method with
  2198. * name public name of the method
  2199. * cb C function that implements the method
  2200. * RESULT
  2201. * int - 1 if success, else 0
  2202. * NOTES
  2203. * A C function must be registered for every "method" that the server recognizes. The
  2204. * method name is equivalent to <methodCall><name> method name </name></methodCall> in the
  2205. * XML syntax.
  2206. * SEE ALSO
  2207. * XMLRPC_ServerFindMethod ()
  2208. * XMLRPC_ServerCallMethod ()
  2209. * SOURCE
  2210. */
  2211. int XMLRPC_ServerRegisterMethod(XMLRPC_SERVER server, const char *name, XMLRPC_Callback cb) {
  2212. if(server && name && cb) {
  2213. server_method* sm = malloc(sizeof(server_method));
  2214. if(sm) {
  2215. sm->name = strdup(name);
  2216. sm->method = cb;
  2217. sm->desc = NULL;
  2218. return Q_PushTail(&server->methodlist, sm);
  2219. }
  2220. }
  2221. return 0;
  2222. }
  2223. /*******/
  2224. server_method* find_method(XMLRPC_SERVER server, const char* name) {
  2225. server_method* sm;
  2226. q_iter qi = Q_Iter_Head_F(&server->methodlist);
  2227. while( qi ) {
  2228. sm = Q_Iter_Get_F(qi);
  2229. if(sm && !strcmp(sm->name, name)) {
  2230. return sm;
  2231. }
  2232. qi = Q_Iter_Next_F(qi);
  2233. }
  2234. return NULL;
  2235. }
  2236. const char* type_to_str(XMLRPC_VALUE_TYPE type, XMLRPC_VECTOR_TYPE vtype) {
  2237. switch(type) {
  2238. case xmlrpc_none:
  2239. return "none";
  2240. case xmlrpc_empty:
  2241. return "empty";
  2242. case xmlrpc_base64:
  2243. return "base64";
  2244. case xmlrpc_boolean:
  2245. return "boolean";
  2246. case xmlrpc_datetime:
  2247. return "datetime";
  2248. case xmlrpc_double:
  2249. return "double";
  2250. case xmlrpc_int:
  2251. return "int";
  2252. case xmlrpc_string:
  2253. return "string";
  2254. case xmlrpc_vector:
  2255. switch(vtype) {
  2256. case xmlrpc_vector_none:
  2257. return "none";
  2258. case xmlrpc_vector_array:
  2259. return "array";
  2260. case xmlrpc_vector_mixed:
  2261. return "mixed vector (struct)";
  2262. case xmlrpc_vector_struct:
  2263. return "struct";
  2264. }
  2265. }
  2266. return "unknown";
  2267. }
  2268. /****f* VALUE/XMLRPC_ServerFindMethod
  2269. * NAME
  2270. * XMLRPC_ServerFindMethod
  2271. * SYNOPSIS
  2272. * XMLRPC_Callback XMLRPC_ServerFindMethod(XMLRPC_SERVER server, const char* callName)
  2273. * FUNCTION
  2274. * retrieve C callback associated with a given method name.
  2275. * INPUTS
  2276. * server The XMLRPC_SERVER the method is registered with
  2277. * callName the method to find
  2278. * RESULT
  2279. * previously registered XMLRPC_Callback, or NULL
  2280. * NOTES
  2281. * Typically, this is used to determine if a requested method exists, without actually calling it.
  2282. * SEE ALSO
  2283. * XMLRPC_ServerCallMethod ()
  2284. * XMLRPC_ServerRegisterMethod ()
  2285. * SOURCE
  2286. */
  2287. XMLRPC_Callback XMLRPC_ServerFindMethod(XMLRPC_SERVER server, const char* callName) {
  2288. if(server && callName) {
  2289. q_iter qi = Q_Iter_Head_F(&server->methodlist);
  2290. while( qi ) {
  2291. server_method* sm = Q_Iter_Get_F(qi);
  2292. if(sm && !strcmp(sm->name, callName)) {
  2293. return sm->method;
  2294. }
  2295. qi = Q_Iter_Next_F(qi);
  2296. }
  2297. }
  2298. return NULL;
  2299. }
  2300. /*******/
  2301. /* Call method specified in request */
  2302. /****f* VALUE/XMLRPC_ServerCallMethod
  2303. * NAME
  2304. * XMLRPC_ServerCallMethod
  2305. * SYNOPSIS
  2306. * XMLRPC_VALUE XMLRPC_ServerCallMethod(XMLRPC_SERVER server, XMLRPC_REQUEST request, void* userData)
  2307. * FUNCTION
  2308. *
  2309. * INPUTS
  2310. * server The XMLRPC_SERVER the method is registered with
  2311. * request the request to handle
  2312. * userData any additional data to pass to the C callback, or NULL
  2313. * RESULT
  2314. * XMLRPC_VALUE allocated by the callback, or NULL
  2315. * NOTES
  2316. * It is typically the caller's responsibility to free the returned value.
  2317. *
  2318. * Often the caller will want to serialize the result as XML, via
  2319. * XMLRPC_VALUE_To_XML () or XMLRPC_REQUEST_To_XML ()
  2320. * SEE ALSO
  2321. * XMLRPC_ServerFindMethod ()
  2322. * XMLRPC_ServerRegisterMethod ()
  2323. * XMLRPC_CleanupValue ()
  2324. * SOURCE
  2325. */
  2326. XMLRPC_VALUE XMLRPC_ServerCallMethod(XMLRPC_SERVER server, XMLRPC_REQUEST request, void* userData) {
  2327. XMLRPC_VALUE xReturn = NULL;
  2328. /* check for error set during request parsing / generation */
  2329. if(request && request->error) {
  2330. xReturn = XMLRPC_CopyValue(request->error);
  2331. }
  2332. else if (server && request) {
  2333. XMLRPC_Callback cb =
  2334. XMLRPC_ServerFindMethod (server, request->methodName.str);
  2335. if(cb) {
  2336. xReturn = cb(server, request, userData);
  2337. }
  2338. else {
  2339. xReturn =
  2340. XMLRPC_UtilityCreateFault (xmlrpc_error_unknown_method,
  2341. request->methodName.str);
  2342. }
  2343. }
  2344. return xReturn;
  2345. }
  2346. /*******/
  2347. /*-*****************
  2348. * End server funcs *
  2349. *******************/
  2350. /*-***********************************
  2351. * Begin XMLRPC General Options funcs *
  2352. *************************************/
  2353. /* For options used by XMLRPC_VALUE funcs that otherwise do not have
  2354. * parameters for options. Kind of gross. :(
  2355. */
  2356. typedef struct _xmlrpc_options {
  2357. XMLRPC_CASE id_case;
  2358. XMLRPC_CASE_COMPARISON id_case_compare;
  2359. }
  2360. STRUCT_XMLRPC_OPTIONS, *XMLRPC_OPTIONS;
  2361. static XMLRPC_OPTIONS XMLRPC_GetDefaultOptions() {
  2362. static STRUCT_XMLRPC_OPTIONS options = {
  2363. xmlrpc_case_exact,
  2364. xmlrpc_case_sensitive
  2365. };
  2366. return &options;
  2367. }
  2368. /****f* VALUE/XMLRPC_GetDefaultIdCase
  2369. * NAME
  2370. * XMLRPC_GetDefaultIdCase
  2371. * SYNOPSIS
  2372. * XMLRPC_CASE XMLRPC_GetDefaultIdCase()
  2373. * FUNCTION
  2374. * Gets default case options used by XMLRPC_VALUE funcs
  2375. * INPUTS
  2376. * none
  2377. * RESULT
  2378. * XMLRPC_CASE
  2379. * BUGS
  2380. * Nasty and gross. Should be server specific, but that requires changing all
  2381. * the XMLRPC_VALUE api's.
  2382. * SEE ALSO
  2383. * XMLRPC_SetDefaultIdCase ()
  2384. * SOURCE
  2385. */
  2386. XMLRPC_CASE XMLRPC_GetDefaultIdCase() {
  2387. XMLRPC_OPTIONS options = XMLRPC_GetDefaultOptions();
  2388. return options->id_case;
  2389. }
  2390. /*******/
  2391. /****f* VALUE/XMLRPC_SetDefaultIdCase
  2392. * NAME
  2393. * XMLRPC_SetDefaultIdCase
  2394. * SYNOPSIS
  2395. * XMLRPC_CASE XMLRPC_SetDefaultIdCase(XMLRPC_CASE id_case)
  2396. * FUNCTION
  2397. * Sets default case options used by XMLRPC_VALUE funcs
  2398. * INPUTS
  2399. * id_case case options as enumerated by XMLRPC_CASE
  2400. * RESULT
  2401. * XMLRPC_CASE -- newly set option
  2402. * BUGS
  2403. * Nasty and gross. Should be server specific, but that requires changing all
  2404. * the XMLRPC_VALUE api's.
  2405. * SEE ALSO
  2406. * XMLRPC_GetDefaultIdCase ()
  2407. * SOURCE
  2408. */
  2409. XMLRPC_CASE XMLRPC_SetDefaultIdCase(XMLRPC_CASE id_case) {
  2410. XMLRPC_OPTIONS options = XMLRPC_GetDefaultOptions();
  2411. options->id_case = id_case;
  2412. return options->id_case;
  2413. }
  2414. /*******/
  2415. /****f* VALUE/XMLRPC_GetDefaultIdCaseComparison
  2416. * NAME
  2417. * XMLRPC_GetDefaultIdCaseComparison
  2418. * SYNOPSIS
  2419. * XMLRPC_CASE XMLRPC_GetDefaultIdCaseComparison( )
  2420. * FUNCTION
  2421. * Gets default case comparison options used by XMLRPC_VALUE funcs
  2422. * INPUTS
  2423. * none
  2424. * RESULT
  2425. * XMLRPC_CASE_COMPARISON default
  2426. * BUGS
  2427. * Nasty and gross. Should be server specific, but that requires changing all
  2428. * the XMLRPC_VALUE api's.
  2429. * SEE ALSO
  2430. * XMLRPC_SetDefaultIdCaseComparison ()
  2431. * SOURCE
  2432. */
  2433. XMLRPC_CASE_COMPARISON XMLRPC_GetDefaultIdCaseComparison() {
  2434. XMLRPC_OPTIONS options = XMLRPC_GetDefaultOptions();
  2435. return options->id_case_compare;
  2436. }
  2437. /*******/
  2438. /****f* VALUE/XMLRPC_SetDefaultIdCaseComparison
  2439. * NAME
  2440. * XMLRPC_SetDefaultIdCaseComparison
  2441. * SYNOPSIS
  2442. * XMLRPC_CASE XMLRPC_SetDefaultIdCaseComparison( XMLRPC_CASE_COMPARISON id_case_compare )
  2443. * FUNCTION
  2444. * Gets default case comparison options used by XMLRPC_VALUE funcs
  2445. * INPUTS
  2446. * id_case_compare case comparison rule to set as default
  2447. * RESULT
  2448. * XMLRPC_CASE_COMPARISON newly set default
  2449. * BUGS
  2450. * Nasty and gross. Should be server specific, but that requires changing all
  2451. * the XMLRPC_VALUE api's.
  2452. * SEE ALSO
  2453. * XMLRPC_GetDefaultIdCaseComparison ()
  2454. * SOURCE
  2455. */
  2456. XMLRPC_CASE_COMPARISON XMLRPC_SetDefaultIdCaseComparison(XMLRPC_CASE_COMPARISON id_case_compare) {
  2457. XMLRPC_OPTIONS options = XMLRPC_GetDefaultOptions();
  2458. options->id_case_compare = id_case_compare;
  2459. return options->id_case_compare;
  2460. }
  2461. /*******/
  2462. /*-*********************************
  2463. * End XMLRPC General Options funcs *
  2464. ***********************************/
  2465. /*-******************
  2466. * Fault API funcs *
  2467. ********************/
  2468. /****f* UTILITY/XMLRPC_UtilityCreateFault
  2469. * NAME
  2470. * XMLRPC_UtilityCreateFault
  2471. * SYNOPSIS
  2472. * XMLRPC_VALUE XMLRPC_UtilityCreateFault( int fault_code, const char* fault_string )
  2473. * FUNCTION
  2474. * generates a struct containing a string member with id "faultString" and an int member
  2475. * with id "faultCode". When using the xmlrpc xml serialization, these will be translated
  2476. * to <fault><value><struct>... format.
  2477. * INPUTS
  2478. * fault_code application specific error code. can be 0.
  2479. * fault_string application specific error string. cannot be null.
  2480. * RESULT
  2481. * XMLRPC_VALUE a newly created struct vector representing the error, or null on error.
  2482. * NOTES
  2483. * This is a utility function. xmlrpc "faults" are not directly represented in this xmlrpc
  2484. * API or data structures. It is the author's view, that this API is intended for simple
  2485. * data types, and a "fault" is a complex data type consisting of multiple simple data
  2486. * types. This function is provided for convenience only, the same result could be
  2487. * achieved directly by the application.
  2488. *
  2489. * This function now supports some "standardized" fault codes, as specified at.
  2490. * http://xmlrpc-epi.sourceforge.net/specs/rfc.fault_codes.php.
  2491. * If one of these fault codes is received, the description string will automatically
  2492. * be prefixed with a standard error string and 2 newlines.
  2493. *
  2494. * The actual transformation between this complex type and the xml "<fault>" element takes
  2495. * place in the xmlrpc to xml serialization layer. This step is not performed when using the
  2496. * simplerpc serialization, meaning that there will be no "<fault>" element in that
  2497. * serialization. There will simply be a standard struct with 2 child elements.
  2498. * imho, the "<fault>" element is unnecessary and/or out of place as part of the standard API.
  2499. *
  2500. * SOURCE
  2501. */
  2502. XMLRPC_VALUE XMLRPC_UtilityCreateFault(int fault_code, const char* fault_string) {
  2503. XMLRPC_VALUE xOutput = NULL;
  2504. char* string = NULL;
  2505. simplestring description;
  2506. simplestring_init(&description);
  2507. switch (fault_code) {
  2508. case xmlrpc_error_parse_xml_syntax:
  2509. string = xmlrpc_error_parse_xml_syntax_str;
  2510. break;
  2511. case xmlrpc_error_parse_unknown_encoding:
  2512. string = xmlrpc_error_parse_unknown_encoding_str;
  2513. break;
  2514. case xmlrpc_error_parse_bad_encoding:
  2515. string = xmlrpc_error_parse_bad_encoding_str;
  2516. break;
  2517. case xmlrpc_error_invalid_xmlrpc:
  2518. string = xmlrpc_error_invalid_xmlrpc_str;
  2519. break;
  2520. case xmlrpc_error_unknown_method:
  2521. string = xmlrpc_error_unknown_method_str;
  2522. break;
  2523. case xmlrpc_error_invalid_params:
  2524. string = xmlrpc_error_invalid_params_str;
  2525. break;
  2526. case xmlrpc_error_internal_server:
  2527. string = xmlrpc_error_internal_server_str;
  2528. break;
  2529. case xmlrpc_error_application:
  2530. string = xmlrpc_error_application_str;
  2531. break;
  2532. case xmlrpc_error_system:
  2533. string = xmlrpc_error_system_str;
  2534. break;
  2535. case xmlrpc_error_transport:
  2536. string = xmlrpc_error_transport_str;
  2537. break;
  2538. }
  2539. simplestring_add(&description, string);
  2540. if(string && fault_string) {
  2541. simplestring_add(&description, "\n\n");
  2542. }
  2543. simplestring_add(&description, fault_string);
  2544. if(description.len) {
  2545. xOutput = XMLRPC_CreateVector(NULL, xmlrpc_vector_struct);
  2546. XMLRPC_VectorAppendString (xOutput, "faultString", description.str,
  2547. description.len);
  2548. XMLRPC_VectorAppendInt(xOutput, "faultCode", fault_code);
  2549. }
  2550. simplestring_free(&description);
  2551. return xOutput;
  2552. }
  2553. /*******/
  2554. /****f* FAULT/XMLRPC_ValueIsFault
  2555. * NAME
  2556. * XMLRPC_ValueIsFault
  2557. * SYNOPSIS
  2558. * int XMLRPC_ValueIsFault (XMLRPC_VALUE value)
  2559. * FUNCTION
  2560. * Determines if a value encapsulates a fault "object"
  2561. * INPUTS
  2562. * value any XMLRPC_VALUE
  2563. * RESULT
  2564. * 1 if it is a fault, else 0
  2565. * SEE ALSO
  2566. * XMLRPC_ResponseIsFault ()
  2567. * SOURCE
  2568. */
  2569. int XMLRPC_ValueIsFault (XMLRPC_VALUE value) {
  2570. if( XMLRPC_VectorGetValueWithID(value, "faultCode") &&
  2571. XMLRPC_VectorGetValueWithID(value, "faultString") ) {
  2572. return 1;
  2573. }
  2574. return 0;
  2575. }
  2576. /*******/
  2577. /****f* FAULT/XMLRPC_ResponseIsFault
  2578. * NAME
  2579. * XMLRPC_ResponseIsFault
  2580. * SYNOPSIS
  2581. * int XMLRPC_ResponseIsFault (XMLRPC_REQUEST response)
  2582. * FUNCTION
  2583. * Determines if a response contains an encapsulated fault "object"
  2584. * INPUTS
  2585. * value any XMLRPC_REQUEST. typically of type xmlrpc_request_response
  2586. * RESULT
  2587. * 1 if it contains a fault, else 0
  2588. * SEE ALSO
  2589. * XMLRPC_ValueIsFault ()
  2590. * SOURCE
  2591. */
  2592. int XMLRPC_ResponseIsFault(XMLRPC_REQUEST response) {
  2593. return XMLRPC_ValueIsFault( XMLRPC_RequestGetData(response) );
  2594. }
  2595. /*******/
  2596. /****f* FAULT/XMLRPC_GetValueFaultCode
  2597. * NAME
  2598. * XMLRPC_GetValueFaultCode
  2599. * SYNOPSIS
  2600. * int XMLRPC_GetValueFaultCode (XMLRPC_VALUE value)
  2601. * FUNCTION
  2602. * returns fault code from a struct, if any
  2603. * INPUTS
  2604. * value XMLRPC_VALUE of type xmlrpc_vector_struct.
  2605. * RESULT
  2606. * fault code, else 0.
  2607. * BUGS
  2608. * impossible to distinguish faultCode == 0 from faultCode not present.
  2609. * SEE ALSO
  2610. * XMLRPC_GetResponseFaultCode ()
  2611. * SOURCE
  2612. */
  2613. int XMLRPC_GetValueFaultCode (XMLRPC_VALUE value) {
  2614. return XMLRPC_VectorGetIntWithID(value, "faultCode");
  2615. }
  2616. /*******/
  2617. /****f* FAULT/XMLRPC_GetResponseFaultCode
  2618. * NAME
  2619. * XMLRPC_GetResponseFaultCode
  2620. * SYNOPSIS
  2621. * int XMLRPC_GetResponseFaultCode(XMLRPC_REQUEST response)
  2622. * FUNCTION
  2623. * returns fault code from a response, if any
  2624. * INPUTS
  2625. * response XMLRPC_REQUEST. typically of type xmlrpc_request_response.
  2626. * RESULT
  2627. * fault code, else 0.
  2628. * BUGS
  2629. * impossible to distinguish faultCode == 0 from faultCode not present.
  2630. * SEE ALSO
  2631. * XMLRPC_GetValueFaultCode ()
  2632. * SOURCE
  2633. */
  2634. int XMLRPC_GetResponseFaultCode(XMLRPC_REQUEST response) {
  2635. return XMLRPC_GetValueFaultCode( XMLRPC_RequestGetData(response) );
  2636. }
  2637. /*******/
  2638. /****f* FAULT/XMLRPC_GetValueFaultString
  2639. * NAME
  2640. * XMLRPC_GetValueFaultString
  2641. * SYNOPSIS
  2642. * const char* XMLRPC_GetValueFaultString (XMLRPC_VALUE value)
  2643. * FUNCTION
  2644. * returns fault string from a struct, if any
  2645. * INPUTS
  2646. * value XMLRPC_VALUE of type xmlrpc_vector_struct.
  2647. * RESULT
  2648. * fault string, else 0.
  2649. * SEE ALSO
  2650. * XMLRPC_GetResponseFaultString ()
  2651. * SOURCE
  2652. */
  2653. const char* XMLRPC_GetValueFaultString (XMLRPC_VALUE value) {
  2654. return XMLRPC_VectorGetStringWithID(value, "faultString");
  2655. }
  2656. /*******/
  2657. /****f* FAULT/XMLRPC_GetResponseFaultString
  2658. * NAME
  2659. * XMLRPC_GetResponseFaultString
  2660. * SYNOPSIS
  2661. * const char* XMLRPC_GetResponseFaultString (XMLRPC_REQUEST response)
  2662. * FUNCTION
  2663. * returns fault string from a response, if any
  2664. * INPUTS
  2665. * response XMLRPC_REQUEST. typically of type xmlrpc_request_response.
  2666. * RESULT
  2667. * fault string, else 0.
  2668. * SEE ALSO
  2669. * XMLRPC_GetValueFaultString ()
  2670. * SOURCE
  2671. */
  2672. const char* XMLRPC_GetResponseFaultString (XMLRPC_REQUEST response) {
  2673. return XMLRPC_GetValueFaultString( XMLRPC_RequestGetData(response) );
  2674. }
  2675. /*******/
  2676. /*-******************
  2677. * Utility API funcs *
  2678. ********************/
  2679. /****f* UTILITY/XMLRPC_Free
  2680. * NAME
  2681. * XMLRPC_Free
  2682. * SYNOPSIS
  2683. * void XMLRPC_Free(void* mem)
  2684. * FUNCTION
  2685. * frees a block of memory allocated by xmlrpc.
  2686. * INPUTS
  2687. * mem memory to free
  2688. * RESULT
  2689. * void
  2690. * NOTES
  2691. * Useful for OS's where memory must be free'd
  2692. * in the same library in which it is allocated.
  2693. * SOURCE
  2694. */
  2695. void XMLRPC_Free(void* mem) {
  2696. my_free(mem);
  2697. }
  2698. /*******/
  2699. /****f* UTILITY/XMLRPC_GetVersionString
  2700. * NAME
  2701. * XMLRPC_GetVersionString
  2702. * SYNOPSIS
  2703. * const char* XMLRPC_GetVersionString()
  2704. * FUNCTION
  2705. * returns library version string
  2706. * INPUTS
  2707. *
  2708. * RESULT
  2709. * const char*
  2710. * NOTES
  2711. * SOURCE
  2712. */
  2713. const char* XMLRPC_GetVersionString() {
  2714. return XMLRPC_VERSION_STR;
  2715. }
  2716. /*******/
  2717. /*-**********************
  2718. * End Utility API funcs *
  2719. ************************/