newlisp/examples/xmlrpc.cgi

227 lines
5.7 KiB
Text
Executable file

#!/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