File: xmlrpc-client.lsp

package info (click to toggle)
newlisp 10.7.5-3
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 6,292 kB
  • sloc: ansic: 33,280; lisp: 4,181; sh: 609; makefile: 215
file content (236 lines) | stat: -rw-r--r-- 7,721 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
;; @module xmlrpc-client.lsp 
;; @description XMLRPC protocol client routines
;; @version 0.3 - comments redone for automatic documentation
;; @version 0.4 - multiple indices with <tt>nth</tt> redone to be compatible with future versions
;; @version 0.5 - doc changes
;; @version 0.6 - fixed bug in error handler
;; @version 0.61 - fixed doc typo
;; @version 0.7 - check for valid list type in (get-value expr) thanks Kosh
;; @version 0.8 - changed references to /usr/ to /usr/local/
;; @version 0.9 - make system.listMethods more flexible for no of args - thanks Ofoe
;; @author Lutz Mueller 2005-2011, Kosh 2012, Oofoe 2016
;;
;; <h2>Functions for XML-RPC client</h2>
;; To use this module include a 'load' statement at the beginning of the program:
;; <pre>
;; (load "/usr/local/share/newlisp/modules/xmlrpc-client.lsp")
;; ; or shorter
;; (module "xmlrpc-client.lsp")
;; </pre>
;; The script 'xmlrpc.cgi' implements a method 'newLISP.evalString'. This  module contains 
;; a client side function for this method for testing purposes. The file 'xmlrpc.cgi'
;; can be found in the 'example' directory of the newLISP source distribution.
;; 
;; For further information on XML-RPC consult 
;; @link http://www.xmlrpc.com/ http://www.xmlrpc.com/ .
;;
;; Whenever a connection could be made, method functions will return a response
;; formatted by the XML-RPC server in XML. If a connection failed the function will
;; return 'nil' and a call to '(XMLRPC:error)' will return an error text.
;;
;; If the XML received cannot be parsed into SXML, the function returns 'nil'
;; and '(XMLRPC:error)' will return an XML error. SXML is XML transformed into
;; LISP S-expressions.

;; If the XML received is syntactically correct but not correctly formatted,
;; XML garbage is returned or 'nil' is returned and an error message in 
;; '(XMLRPC:error)'.

;; @syntax (XMLRPC:system.listMethods <str-url>)                    
;; @param <str-url> The URL of the XML-RPC server
;; @return A list of methods supported.
;; The server at <url> returns a list of methods supported.

;; @syntax (XMLRPC:system.methodHelp <str-url> <str-method-name>)        
;; @param <str-url> The URL of the XML-RPC server.
;; @param <method-name> The name of the method to get help for.
;; @return Help for <str-method-name>
;; The server at <str-url> returns help for the method in <str-method-name>

;; @syntax (XMLRPC:system.methodSignatures <str-url> <str-method-name>) 
;; @param <str-url> The URL of the XML-RPC server.
;; @param <method-name> The name of the method to get the signature for.
;; @return The signature for a server method.
;; Gets the calling parameter conventions (signature) for a method
;; <method-name> at <str-url>.

;; @syntax (XMLRPC:execute <str-url> <str-xml-request>)
;; @param <str-url> The URL of the XML-RPC server.
;; @param <str-xml-request> A XML formatted request.
;; @return XML formatted server response
;; This is a generic method for making XML-RPC requests.
;; The request must be XML formatted correctly by the sender (client).


;; @syntax (XMLRPC:newLISP.evalString <str-url> <str-expression>)
;; @param <str-url> The URL of the XML-RPC server.
;; @param <str-expression> The expresssion to be evaluated in a string.
;; @return The result of the expression evaluation.
;; The expression in <str-expression> is encoded in base64 and then
;; transmitted to the remote server.

;; @syntax (XMLRPC:error)
;; @return Error text of last error occured.

(context 'XMLRPC)

(set 'request
[text]<?xml version="1.0"?>
<methodCall>
   <methodName>%s</methodName>
   <params>
      <param>
         <value>%s</value>
       </param>
    </params>
</methodCall>
[/text])

(set 'error-msg "")


######### extract value(s) from XML-RPC response XML with <params> #############

; get result data from result structure
;
(define (get-result-data xml)
    (if (starts-with xml "ERR:") 
        (begin
            (set 'error-msg xml)
            (throw nil)))
    (xml-type-tags nil nil nil nil)
    (set 'sxml (xml-parse xml (+ 1 2 4)))   
    (if (not sxml) (throw (format "XML error: %s" (first (xml-error)))))

    (if (match '(("methodResponse" ("fault" *))) sxml) 
        (begin
            (set 'error-msg 
                (let (fault (sxml 0 1 1 1 1 2 1 1) 
                      text (sxml 0 1 1 1 2 2 1 1))
                     (append "Fault " fault ": " text)))
                (throw nil)))

    (get-value (sxml 0 1 1 1)))
   

; get contents from expr = (value ...)
;
(define (get-value expr)
    (if 
        (empty? expr) nil
        
        (list? (expr 1))
        (case (expr 1 0)
            ("i4" (int (expr 1 1)))
            ("int" (int (expr 1 1)))
            ("boolean" (if (= "0" (expr 1 1) ) nil true))
            ("double" (float (expr 1 1)))
            ("base64" (base64-dec (expr 1 1)))
            ("dateTime.iso8601" (expr 1 1))
            ("array" (if (= (expr 1) "array") 
                         "array" ;; if untagged string "array"
                         (get-array (rest (expr 1 1)))) )
            ("struct" (get-struct (rest (expr 1))))
            ("string" (expr 1 1))
            (true (expr 1))
        ) ; end case
        
        true (string (expr 1))
    ) ; end if
) 

; get contents from expr = ((value ...) (value ...) ...)
;
(define (get-array expr)
    (if (empty? expr) 
        '()
        (cons (get-value (first expr)) (get-array (rest expr)))))


; get contents from expr = ((member ...) (member) ...)
;
(define (get-struct expr)
    (if (empty? expr)
        '()
        (cons (get-member (first expr)) (get-struct (rest expr)))))


; get contents from expr = (member ...)
;
(define (get-member expr)
    (list (expr 1 1)  (get-value (last expr))))


################################ standard system methods #######################

# convert to SXML
(xml-type-tags nil nil nil nil)

# ( method /arg.../ -- XML) Compose XML request.
(define (format-request method)
  (let ((xml (format
             "<?xml version=\"1.0\"?><methodCall><methodName>%s</methodName><params>"
             method)))
    (dolist (value (args))
      (push (format "<param><value>%s</value></param>" value) xml -1))
    (push "</params></methodCall>\n" xml -1)))

# return method names in a list of strings
#
# (XMLRPC:system.listMethods <url>)  
#
(define (system.listMethods url)
    (execute url (format-request "system.listMethods")))

# get help for a methodName at url
# return help in a string
#
# (XMLRPC:system.methodHelp <url> <method-name) 
#
(define (system.methodHelp url methodName)
    (execute url (format request "system.methodHelp" methodName) ))


# get method signatures of methodName at url
# return ans array of strings
#
# (XMLRPC:system.methodSignatures <url> <method-name>) 
#
(define (system.methodSignature url methodName)
    (execute url (format request "system.methodSignature" methodName) ))


(define (error) error-msg)


# Execute a method on url with XML formatted request
#
# This is a generic method, but with XML formatted by caller.
#
# (XMLRPC:execute <url> <xml-request>)
#
(define (execute url parameter-XML)
    (if (not (catch (begin
        (set 'error-msg "")
        (set 'xml (post-url url parameter-XML "text/xml"))
        (get-result-data xml)) 'result))

        (begin (set 'error-msg "Wrong format in XML-RPC") nil)
        result))

######################### newLISP XML-RPC specific methods #####################

# evaluate a newLISP expression in str at newLISP XML-RPC server at url
# return evaluation result in a string 
#

(define (newLISP.evalString url str)
    (execute url 
        (format request 
                "newLISP.evalString" (append "<base64>" (base64-enc str) "</base64>")))
)

(context MAIN)

# eof