;; @module xmlrpc-client.lsp ;; @description XMLRPC protocol client routines ;; @version 0.3 - comments redone for automatic documentation ;; @author Lutz Mueller, 2005 ;; ;;

Functions for XML-RPC client

;; To use this module include a 'load' statement at the beginning of the program: ;;
;; (load "/usr/local/share/newlisp/xmlrpc-client.lsp")
;; 
;; ;; The script 'xmlrpc.cgi' together with a webserver or the script ;; 'xmlrpc-server' for a freestanding XML-RPC server can be used for ;; testing. Both scripts implement a method 'newLISP.evalString'. This ;; module contains a client side function for this method. ;; ;; 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 and 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 ) ;; @param The URL of the XML-RPC server ;; @return A list or methods supported. ;; The server at returns a list of methods supported. ;; @syntax (XMLRPC:system.methodHelp ) ;; @param The URL of the XML-RPC server. ;; @param The name of the method to get help for. ;; @return Help for ;; The server at returns help for the method in ;; @syntax (XMLRPC:system.methodSignatures ) ;; @param The URL of the XML-RPC server. ;; @param 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 ;; at . ;; @syntax (XMLRPC:execute ) ;; @param The URL of the XML-RPC server. ;; @param 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 ) ;; @param The URL of the XML-RPC server. ;; @param The expresssion to be evaluated in a string. ;; @return The result of the expression evaluation. ;; The expression in 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] %s %s [/text]) (set 'error-msg "") ######### extract value(s) from XML-RPC response XML with ############# ; 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 (nth 0 1 1 1 1 2 1 1 sxml) text (nth 0 1 1 1 2 2 1 1 sxml)) (append "Fault " fault ": " text))) (throw nil))) (get-value (nth 0 1 1 1 sxml))) ; get contents from expr = (value ...) ; (define (get-value expr) (if (empty? expr) nil (case (nth 1 0 expr) ("i4" (int (nth 1 1 expr))) ("int" (int (nth 1 1 expr))) ("boolean" (if (= "0" (nth 1 1 expr)) nil true)) ("double" (float (nth 1 1 expr))) ("base64" (base64-dec (nth 1 1 expr))) ("dateTime.iso8601" (nth 1 1 expr)) ("array" (if (= (nth 1 expr) "array") "array" ;; if untagged string "array" (get-array (rest (nth 1 1 expr)))) ) ("struct" (get-struct (rest (nth 1 expr)))) ("string" (nth 1 1 expr)) (true (nth 1 expr))))) ; 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 (nth 1 1 expr) (get-value (last expr)))) ################################ standard system methods ####################### # convert to SXML (xml-type-tags nil nil nil nil) # report all methods of XML-RPC server at url # return method names in a list of strings # # (XMLRPC:system.listMethods ) # (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 ) # (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 ) # (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-enc str) ""))) ) (context MAIN) # eof