#!/usr/bin/env newlisp # # xmlrpc.cgi - CGI script to handle XML-RPC requests # # This is similar to xmlrpc-server, but stateless as a new # newLISP process is invoked everytime this script is executed. # For a XML-RPC server maintaining state run xmlrpc-server. # # v.1.0 - 2005-01-14 Lutz Mueller # # v.1.1 - 2005-03-20 # method name for newLISP.evalString was listed wrong # v.1.2 - 2010-02-09 # method name for newLISP.evalString was listed wrong # v.1.3 - 2010-10-07 # replaced obsolete 'error-text' with 'last-error' # v.1.4 - 2012-03-16 bugfixes, thanks Kosh # # supports the following methods: # # Method Return Parameter # ------ ------ --------- # system.listMethods string n/a # system.methodHelp string string # system.methodSignature array string # newLISP.evalString base64 base64 # # (set 'version "1.4") # formatting templates for responses (set 'normal-response [text]<?xml version="1.0"?> <methodResponse> <params> <param> <value>%s</value> </param> </params> </methodResponse> [/text]) (set 'fault-response [text]<?xml version="1.0"?> <methodResponse> <fault> <value> <struct> <member> <name>faultCode</name> <value><int>%d</int></value> </member> <member> <name>faultString</name> <value><string>%s</string></value> </member> </struct> </value> </fault> </methodResponse> [/text]) # event handler called when newLISP receives a request (define (process-post request) (if (not (catch (handle request) 'page)) (set 'page (format fault-response 0 page))) (print "Content-Type: text/xml\r\n" "Content-Length: " (length page) "\r\n\r\n" page)) (define (handle input, XML contentlength methodName params) (set 'XML "") (xml-type-tags nil nil nil nil) (if (not (set 'XML (xml-parse input (+ 1 2 4 8 16)))) (begin (if (not (xml-error)) (error 3 "No XML or XML is empty") (error 4 (append "XML error: " (first (xml-error)))))) (set 'XML (first XML))) ; get methodName and parameter section (set 'm (match '(methodCall (methodName *) *) XML)) (if (not m) (error 5 "Invalid XML-RPC format")) (set 'methodName (first (first m))) (set 'params (last m)) (case methodName ("newLISP.evalString" (newLISP.evalString params)) ("system.listMethods" (system.listMethods)) ("system.methodHelp" (system.methodHelp params)) ("system.methodSignature" (system.methodSignature params)) (true (error 6 "Method name not known"))) ) (define (error no msg) (throw (format fault-response no (append "newLISP XML-RPC v." version " - " msg)))) ######################### remote callable methods ############################## (define (system.listMethods) [text]<?xml version="1.0"?> <methodResponse> <params> <param><value><array><data> <value><string>system.listMethods</string></value> <value><string>system.methodHelp</string></value> <value><string>system.methodSignature</string></value> <value><string>newLISP.evalString</string></value> </data></array></value></param> </params> </methodResponse> [/text]) (define (system.methodHelp params, methodName) (set 'methodName (params 0 1 1 1 1)) (case methodName ("system.listMethods" (format normal-response "Lists all methods implemented.")) ("system.methodHelp" (format normal-response "Documents a method.")) ("system.methodSignature" (format normal-response "Shows the signatures of a method.")) ("newLISP.evalString" (format normal-response "Evaluate a base64 encoded string.")) (true (error 7 "Method name in system.methodHelp not known"))) ) (define (system.methodSignature params) (set 'methodName (params 0 1 1 1 1)) (case methodName ("system.listMethods" (format normal-response "<array> <data> <value> <array> <data> <value>array</value> </data> </array> </value> </data> </array>")) ("system.methodHelp" (format normal-response "<array> <data> <value> <array> <data> <value>string</value> <value>string</value> </data> </array> </value> </data> </array>")) ("system.methodSignature" (format normal-response "<array> <data> <value> <array> <data> <value>array</value> <value>string</value> </data> </array> </value> </data> </array>")) ("newLISP.evalString" (format normal-response "<array> <data> <value> <array> <data> <value>base64</value> <value>base64</value> </data> </array> </value> </data> </array>")) (true (error 7 "Method name in system.methodSignature not known"))) ) (define (newLISP.evalString params, m, result) (set 'm (match '((params (param (value (base64 *))))) params)) (if (not m) (error 8 "Invalid format for method newLISP.evalString") (set 'result (string (eval-string (base64-dec (first (first m))) MAIN (last (last-error))))) (format normal-response (append "<base64>" (base64-enc result) "</base64>")) ) ) ########################### MAIN ENTRY POINT ####################### (set 'input (read-line)) (if (not input) (print "Content-type: text/html\r\n\r\n" "<h2>newLISP XML-RPC v." version ": not a valid XML-RPC request</h2>") (begin (while (read-line) (write input (current-line))) (process-post input)) ) (exit) # eof