Move XML-RPC codecs from SSP package to XML package. Logically they
authorChris Hanson <org/chris-hanson/cph>
Sat, 19 Feb 2005 04:35:45 +0000 (04:35 +0000)
committerChris Hanson <org/chris-hanson/cph>
Sat, 19 Feb 2005 04:35:45 +0000 (04:35 +0000)
are independent of the SSP mechanism.

v7/src/ssp/mod-lisp.scm
v7/src/ssp/ssp.pkg
v7/src/ssp/xmlrpc.scm
v7/src/xml/compile.scm
v7/src/xml/xml-rpc.scm [new file with mode: 0644]
v7/src/xml/xml.pkg

index d9c5f7a3c33e8c016edc7be6dbddc4177b94c51b..7584fc4cbaa9fc69270d5d011f328d734b8fceb3 100644 (file)
@@ -1,8 +1,8 @@
 #| -*-Scheme-*-
 
-$Id: mod-lisp.scm,v 1.26 2005/02/08 20:40:12 cph Exp $
+$Id: mod-lisp.scm,v 1.27 2005/02/19 04:35:28 cph Exp $
 
-Copyright 2003,2004 Massachusetts Institute of Technology
+Copyright 2003,2004,2005 Massachusetts Institute of Technology
 
 This file is part of MIT/GNU Scheme.
 
@@ -766,47 +766,6 @@ USA.
 
 (define url-bindings '())
 \f
-;;;; XML-RPC
-
-(define (xml-rpc:subtree-handler pathname port)
-  (if (eq? (http-request-method) 'post)
-      (let ((entity (http-request-entity)))
-       (if entity
-           (let ((document (read-xml (open-input-string entity))))
-             (if document
-                 (write-xml (process-xmlrpc-request document pathname) port)
-                 (http-status-response 400 "Ill-formed XML entity")))
-           (http-status-response 400 "Missing XML entity")))
-      (begin
-       (http-status-response 405 "XML-RPC requires POST method.")
-       (http-response-header 'allow "POST"))))
-
-(define (process-xmlrpc-request document pathname)
-  (call-with-current-continuation
-   (lambda (k)
-     (bind-condition-handler (list condition-type:error)
-        (lambda (condition)
-          (k (xml-rpc:condition->fault 1 condition)))
-       (lambda ()
-        (receive (name params) (xml-rpc:parse-request document)
-          (let ((handler (get-xmlrpc-method-handler pathname name)))
-            (if (not handler)
-                (error "Unknown method name:" name))
-            (xml-rpc:response
-             (with-working-directory-pathname (directory-pathname pathname)
-               (lambda ()
-                 (apply handler params)))))))))))
-
-(define (get-xmlrpc-method-handler pathname name)
-  (let ((methods (make-eq-hash-table)))
-    (let ((environment (make-expansion-environment pathname)))
-      (environment-define environment 'define-xmlrpc-method
-       (lambda (name handler)
-         (hash-table/put! methods name handler)))
-      (fluid-let ((load/suppress-loading-message? #t))
-       (load pathname environment)))
-    (hash-table/get methods name #f)))
-\f
 ;;;; Utilities
 
 (define (port->port-copy input output #!optional buffer-size)
index 5509e209fbf97549009ad241a389b2da1aae9556..ecd29f7ba4fdb9e751abd1b2aaeafb4c2da53bad 100644 (file)
@@ -1,6 +1,6 @@
 #| -*-Scheme-*-
 
-$Id: ssp.pkg,v 1.19 2005/02/06 04:41:06 cph Exp $
+$Id: ssp.pkg,v 1.20 2005/02/19 04:35:39 cph Exp $
 
 Copyright 2003,2004,2005 Massachusetts Institute of Technology
 
@@ -46,8 +46,7 @@ USA.
          dstate/subproblem
          make-initial-dstate)
   (export ()
-         start-mod-lisp-server
-         xml-rpc:subtree-handler)
+         start-mod-lisp-server)
   (export (runtime ssp)
          define-mime-handler
          define-subtree-handler
@@ -123,11 +122,4 @@ USA.
   (files "xmlrpc")
   (parent (runtime ssp))
   (export ()
-         condition-type:bad-xml-rpc-message
-         condition-type:xml-rpc-fault
-         xml-rpc:condition->fault
-         xml-rpc:fault
-         xml-rpc:parse-request
-         xml-rpc:parse-response
-         xml-rpc:response
-         xml-rpc:simple-fault))
\ No newline at end of file
+         xml-rpc:subtree-handler))
\ No newline at end of file
index ca5655b6112cde5b85b1f0c982abfec633de87eb..a3de320e90062151fce4d3a04eb114865caf6e9d 100644 (file)
@@ -1,6 +1,6 @@
 #| -*-Scheme-*-
 
-$Id: xmlrpc.scm,v 1.12 2005/02/17 17:50:54 cph Exp $
+$Id: xmlrpc.scm,v 1.13 2005/02/19 04:35:45 cph Exp $
 
 Copyright 2003,2004,2005 Massachusetts Institute of Technology
 
@@ -23,304 +23,45 @@ USA.
 
 |#
 
-;;;; XML-RPC message codecs
+;;;; XML-RPC content handler
 
 (declare (usual-integrations))
 \f
-(define (xml-rpc:request name . objects)
-  (rpc-elt:method-call (rpc-elt:method-name name)
-                      (rpc-elt:params (map (lambda (object)
-                                             (encode-param object))
-                                           objects))))
-
-(define (xml-rpc:response object)
-  (rpc-elt:method-response (rpc-elt:params (encode-param object))))
-
-(define (xml-rpc:fault code string)
-  (rpc-elt:method-response
-   (rpc-elt:fault
-    (rpc-elt:value
-     (rpc-elt:struct
-      (rpc-elt:member (rpc-elt:name '|faultCode|)
-                     (rpc-elt:value (rpc-elt:int (number->string code))))
-      (rpc-elt:member (rpc-elt:name '|faultString|)
-                     (rpc-elt:value (rpc-elt:string string))))))))
-
-(define (xml-rpc:simple-fault code message . irritants)
-  (xml-rpc:fault code
-                (call-with-output-string
-                 (lambda (port)
-                   (format-error-message message irritants port)))))
-
-(define (xml-rpc:condition->fault code condition)
-  (xml-rpc:fault code (condition/report-string condition)))
-
-(define (xml-rpc:parse-request document)
-  (fluid-let ((*document* document)
-             (*caller* 'xml-rpc:parse-request))
-    (let ((elt (xml-document-root document)))
-      (require (xml-name=? (xml-element-name elt) '|methodCall|))
-      (values (let ((s (content-string (named-child '|methodName| elt))))
-               (require (re-string-match "\\`[a-zA-Z0-9_.:/]+\\'" s))
-               (utf8-string->symbol s))
-             (let ((elt (%named-child 'params elt)))
-               (if elt
-                   (parse-params elt)
-                   '()))))))
-
-(define (xml-rpc:parse-response document)
-  (fluid-let ((*document* document)
-             (*caller* 'xml-rpc:parse-response))
-    (let ((elt (xml-document-root document)))
-      (require (xml-name=? (xml-element-name elt) '|methodResponse|))
-      (let ((elt (single-child elt)))
-       (cond ((xml-name=? (xml-element-name elt) 'params)
-              (let ((objects (parse-params elt)))
-                (require (and (pair? objects) (null? (cdr objects))))
-                (car objects)))
-             ((xml-name=? (xml-element-name elt) 'fault)
-              (let ((alist (decode-value (single-named-child 'value elt))))
-                (require (and (alist? alist) (= (length alist) 2)))
-                (let ((p1 (or (assq '|faultCode| alist) (lose)))
-                      (p2 (or (assq '|faultString| alist) (lose))))
-                  (require (exact-integer? (cdr p1)))
-                  (require (string? p2))
-                  (error:xml-rpc-fault (cdr p1) (cdr p2)))))
-             (else (lose)))))))
-
-(define (parse-params elt)
-  (map (lambda (elt)
-        (decode-value (single-named-child 'value elt)))
-       (named-children 'param elt)))
-
-(define *document*)
-(define *caller*)
-
-(define (require boolean)
-  (if (not boolean)
-      (lose)))
-
-(define (lose)
-  (error:bad-xml-rpc-message *document* *caller*))
-\f
-(define condition-type:bad-xml-rpc-message
-  (make-condition-type 'bad-xml-rpc-message condition-type:error
-      '(document caller)
-    (lambda (condition port)
-      (write-string "Malformed XML-RPC message:" port)
-      (newline port)
-      (write-xml (access-condition condition 'document) port))))
-
-(define error:bad-xml-rpc-message
-  (condition-signaller condition-type:bad-xml-rpc-message
-                      '(document caller)
-                      standard-error-handler))
-
-(define condition-type:xml-rpc-fault
-  (make-condition-type 'xml-rpc-fault condition-type:error '(code string)
-    (lambda (condition port)
-      (write-string "Remote procedure call signalled code " port)
-      (write (access-condition condition 'code) port)
-      (write-string ":" port)
-      (newline port)
-      (write-string (access-condition condition 'string) port))))
-
-(define error:xml-rpc-fault
-  (condition-signaller condition-type:xml-rpc-fault
-                      '(code string)
-                      standard-error-handler))
-
-(define (named-children name elt)
-  (let loop ((items (xml-element-contents elt)))
-    (if (pair? items)
-       (let ((item (car items))
-             (rest (loop (cdr items))))
-         (if (xml-element? item)
-             (begin
-               (require (xml-name=? (xml-element-name item) name))
-               (cons item rest))
-             (begin
-               (require
-                (or (xml-whitespace-string? item)
-                    (xml-comment? item)))
-               rest)))
-       '())))
-
-(define (all-children elt)
-  (let loop ((items (xml-element-contents elt)))
-    (if (pair? items)
-       (let ((item (car items))
-             (rest (loop (cdr items))))
-         (if (xml-element? item)
-             (cons item rest)
-             (begin
-               (require
-                (or (xml-whitespace-string? item)
-                    (xml-comment? item)))
-               rest)))
-       '())))
-
-(define (named-child name elt)
-  (let ((child (%named-child name elt)))
-    (require child)
-    child))
-
-(define (%named-child name elt)
-  (find-matching-item (xml-element-contents elt)
-    (lambda (item)
-      (and (xml-element? item)
-          (xml-name=? (xml-element-name item) name)))))
-
-(define (single-child elt)
-  (let ((children (all-children elt)))
-    (require (and (pair? children) (null? (cdr children))))
-    (car children)))
-
-(define (single-named-child name elt)
-  (let ((child (single-child elt)))
-    (require (xml-name=? (xml-element-name child) name))
-    child))
-\f
-(define (decode-value elt)
-  (let ((items (xml-element-contents elt)))
-    (if (and (pair? items)
-            (string? (car items))
-            (null? (cdr items)))
-       (car items)
-       (let ((elt (single-child elt)))
-         (case (xml-element-name elt)
-           ((boolean)
-            (let ((s (content-string elt)))
-              (cond ((string=? s "0") #f)
-                    ((string=? s "1") #t)
-                    (else (lose)))))
-           ((nil)
-            #!default)
-           ((|dateTime.iso8601|)
-            (safe-call iso8601-string->decoded-time (content-string elt)))
-           ((double)
-            (let ((x (string->number (content-string elt))))
-              (require (and x (flo:flonum? x)))
-              x))
-           ((i4 int)
-            (let ((n (string->number (content-string elt))))
-              (require
-               (and n
-                    (exact-integer? n)
-                    (<= #x-80000000 n #x7fffffff)))
-              n))
-           ((string)
-            (content-string elt))
-           ((base64)
-            (safe-call (lambda (string)
-                         (call-with-output-string
-                           (lambda (port)
-                             (call-with-decode-base64-output-port port #f
-                               (lambda (port)
-                                 (write-string string port))))))
-                       (content-string elt)))
-           ((array)
-            (map (lambda (elt) (decode-value elt))
-                 (named-children 'value
-                                 (single-named-child 'data elt)
-                                )))
-           ((struct)
-            (map (lambda (elt)
-                   (cons (utf8-string->symbol
-                          (content-string (named-child 'name elt)))
-                         (decode-value (named-child 'value elt))))
-                 (named-children 'member elt)))
-           (else (lose)))))))
-
-(define (content-string elt)
-  (let ((items (xml-element-contents elt)))
-    (require
-     (and (pair? items)
-         (string? (car items))
-         (null? (cdr items))))
-    (car items)))
-
-(define (safe-call procedure . arguments)
-  (let ((value (ignore-errors (lambda () (apply procedure arguments)))))
-    (require (not (condition? value)))
-    value))
-\f
-(define (encode-param object)
-  (rpc-elt:param (encode-value object)))
-
-(define (encode-value object)
-  (rpc-elt:value
-   (cond ((and (exact-integer? object)
-              (<= #x-80000000 object #x7fffffff))
-         (rpc-elt:int (number->string object)))
-        ((flo:flonum? object)
-         ;; Probably not right -- formatting issues
-         (rpc-elt:double (number->string object)))
-        ((boolean? object)
-         (rpc-elt:boolean (if object "1" "0")))
-        ((default-object? object)
-         (rpc-elt:nil))
-        ((string? object)
-         (encode-string object))
-        ((symbol? object)
-         (encode-string (symbol->utf8-string object)))
-        ((decoded-time? object)
-         (rpc-elt:date-time (decoded-time->iso8601-string object)))
-        ((and (pair? object)
-              (list-of-type? object
-                (lambda (item)
-                  (and (pair? item)
-                       (symbol? (car item))))))
-         (rpc-elt:struct
-          (map (lambda (item)
-                 (rpc-elt:member
-                  (rpc-elt:name (symbol->utf8-string (car item)))
-                  (encode-value (cdr item))))
-               (cdr object))))
-        ((list? object)
-         (rpc-elt:array (rpc-elt:data (map encode-value object))))
-        (else
-         (error:wrong-type-argument object
-                                    "an XML-RPC object"
-                                    'encode-value)))))
-
-(define (encode-string string)
-  (if (utf8-string-valid? string)
-      (rpc-elt:string string)
-      (call-with-output-string
-       (lambda (port)
-         (let ((context (encode-base64:initialize port #f)))
-           (encode-base64:update context string 0 (string-length string))
-           (encode-base64:finalize context))))))
-
-(define (rpc-elt name empty?)
-  (let ((make-elt
-        (standard-xml-element-constructor name
-                                          (null-xml-namespace-iri)
-                                          empty?)))
-    (if empty?
-       (lambda ()
-         (make-elt))
-       (lambda contents
-         (apply make-elt (xml-attrs) contents)))))
-
-(define rpc-elt:array (rpc-elt 'array #f))
-(define rpc-elt:base64 (rpc-elt 'base64 #f))
-(define rpc-elt:boolean (rpc-elt 'boolean #f))
-(define rpc-elt:data (rpc-elt 'data #f))
-(define rpc-elt:date-time (rpc-elt '|dateTime.iso8601| #f))
-(define rpc-elt:double (rpc-elt 'double #f))
-(define rpc-elt:fault (rpc-elt 'fault #f))
-(define rpc-elt:i4 (rpc-elt 'i4 #f))
-(define rpc-elt:int (rpc-elt 'int #f))
-(define rpc-elt:member (rpc-elt 'member #f))
-(define rpc-elt:method-call (rpc-elt '|methodCall| #f))
-(define rpc-elt:method-name (rpc-elt '|methodName| #f))
-(define rpc-elt:method-response (rpc-elt '|methodResponse| #f))
-(define rpc-elt:name (rpc-elt 'name #f))
-(define rpc-elt:nil (rpc-elt 'nil #t))
-(define rpc-elt:param (rpc-elt 'param #f))
-(define rpc-elt:params (rpc-elt 'params #f))
-(define rpc-elt:string (rpc-elt 'string #f))
-(define rpc-elt:struct (rpc-elt 'struct #f))
-(define rpc-elt:value (rpc-elt 'value #f))
\ No newline at end of file
+(define (xml-rpc:subtree-handler pathname port)
+  (if (eq? (http-request-method) 'post)
+      (let ((entity (http-request-entity)))
+       (if entity
+           (let ((document (read-xml (open-input-string entity))))
+             (if document
+                 (write-xml (process-xmlrpc-request document pathname) port)
+                 (http-status-response 400 "Ill-formed XML entity")))
+           (http-status-response 400 "Missing XML entity")))
+      (begin
+       (http-status-response 405 "XML-RPC requires POST method.")
+       (http-response-header 'allow "POST"))))
+
+(define (process-xmlrpc-request document pathname)
+  (call-with-current-continuation
+   (lambda (k)
+     (bind-condition-handler (list condition-type:error)
+        (lambda (condition)
+          (k (xml-rpc:condition->fault 1 condition)))
+       (lambda ()
+        (receive (name params) (xml-rpc:parse-request document)
+          (let ((handler (get-xmlrpc-method-handler pathname name)))
+            (if (not handler)
+                (error "Unknown method name:" name))
+            (xml-rpc:response
+             (with-working-directory-pathname (directory-pathname pathname)
+               (lambda ()
+                 (apply handler params)))))))))))
+
+(define (get-xmlrpc-method-handler pathname name)
+  (let ((methods (make-eq-hash-table)))
+    (let ((environment (make-expansion-environment pathname)))
+      (environment-define environment 'define-xmlrpc-method
+       (lambda (name handler)
+         (hash-table/put! methods name handler)))
+      (fluid-let ((load/suppress-loading-message? #t))
+       (load pathname environment)))
+    (hash-table/get methods name #f)))
\ No newline at end of file
index 92c1af8051463adedf7982b96de650ae5ba44d32..14cb7a24341428560eb5f91a66f836ea58a34851 100644 (file)
@@ -1,6 +1,6 @@
 #| -*-Scheme-*-
 
-$Id: compile.scm,v 1.15 2005/01/11 03:13:23 cph Exp $
+$Id: compile.scm,v 1.16 2005/02/19 04:34:17 cph Exp $
 
 Copyright 2001,2003,2004,2005 Massachusetts Institute of Technology
 
@@ -43,6 +43,7 @@ USA.
                    "xml-chars"
                    "xml-output"
                    "xml-parser"
+                   "xml-rpc"
                    "xhtml"
                    "xhtml-entities"))))
     (cref/generate-constructors "xml" 'ALL)))
\ No newline at end of file
diff --git a/v7/src/xml/xml-rpc.scm b/v7/src/xml/xml-rpc.scm
new file mode 100644 (file)
index 0000000..9975fa4
--- /dev/null
@@ -0,0 +1,326 @@
+#| -*-Scheme-*-
+
+$Id: xml-rpc.scm,v 1.1 2005/02/19 04:34:32 cph Exp $
+
+Copyright 2003,2004,2005 Massachusetts Institute of Technology
+
+This file is part of MIT/GNU Scheme.
+
+MIT/GNU Scheme is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+MIT/GNU Scheme is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with MIT/GNU Scheme; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+USA.
+
+|#
+
+;;;; XML-RPC message codecs
+
+(declare (usual-integrations))
+\f
+(define (xml-rpc:request name . objects)
+  (rpc-elt:method-call (rpc-elt:method-name name)
+                      (rpc-elt:params (map (lambda (object)
+                                             (encode-param object))
+                                           objects))))
+
+(define (xml-rpc:response object)
+  (rpc-elt:method-response (rpc-elt:params (encode-param object))))
+
+(define (xml-rpc:fault code string)
+  (rpc-elt:method-response
+   (rpc-elt:fault
+    (rpc-elt:value
+     (rpc-elt:struct
+      (rpc-elt:member (rpc-elt:name '|faultCode|)
+                     (rpc-elt:value (rpc-elt:int (number->string code))))
+      (rpc-elt:member (rpc-elt:name '|faultString|)
+                     (rpc-elt:value (rpc-elt:string string))))))))
+
+(define (xml-rpc:simple-fault code message . irritants)
+  (xml-rpc:fault code
+                (call-with-output-string
+                 (lambda (port)
+                   (format-error-message message irritants port)))))
+
+(define (xml-rpc:condition->fault code condition)
+  (xml-rpc:fault code (condition/report-string condition)))
+
+(define (xml-rpc:parse-request document)
+  (fluid-let ((*document* document)
+             (*caller* 'xml-rpc:parse-request))
+    (let ((elt (xml-document-root document)))
+      (require (xml-name=? (xml-element-name elt) '|methodCall|))
+      (values (let ((s (content-string (named-child '|methodName| elt))))
+               (require (re-string-match "\\`[a-zA-Z0-9_.:/]+\\'" s))
+               (utf8-string->symbol s))
+             (let ((elt (%named-child 'params elt)))
+               (if elt
+                   (parse-params elt)
+                   '()))))))
+
+(define (xml-rpc:parse-response document)
+  (fluid-let ((*document* document)
+             (*caller* 'xml-rpc:parse-response))
+    (let ((elt (xml-document-root document)))
+      (require (xml-name=? (xml-element-name elt) '|methodResponse|))
+      (let ((elt (single-child elt)))
+       (cond ((xml-name=? (xml-element-name elt) 'params)
+              (let ((objects (parse-params elt)))
+                (require (and (pair? objects) (null? (cdr objects))))
+                (car objects)))
+             ((xml-name=? (xml-element-name elt) 'fault)
+              (let ((alist (decode-value (single-named-child 'value elt))))
+                (require (and (alist? alist) (= (length alist) 2)))
+                (let ((p1 (or (assq '|faultCode| alist) (lose)))
+                      (p2 (or (assq '|faultString| alist) (lose))))
+                  (require (exact-integer? (cdr p1)))
+                  (require (string? p2))
+                  (error:xml-rpc-fault (cdr p1) (cdr p2)))))
+             (else (lose)))))))
+
+(define (parse-params elt)
+  (map (lambda (elt)
+        (decode-value (single-named-child 'value elt)))
+       (named-children 'param elt)))
+
+(define *document*)
+(define *caller*)
+
+(define (require boolean)
+  (if (not boolean)
+      (lose)))
+
+(define (lose)
+  (error:bad-xml-rpc-message *document* *caller*))
+\f
+(define condition-type:bad-xml-rpc-message
+  (make-condition-type 'bad-xml-rpc-message condition-type:error
+      '(document caller)
+    (lambda (condition port)
+      (write-string "Malformed XML-RPC message:" port)
+      (newline port)
+      (write-xml (access-condition condition 'document) port))))
+
+(define error:bad-xml-rpc-message
+  (condition-signaller condition-type:bad-xml-rpc-message
+                      '(document caller)
+                      standard-error-handler))
+
+(define condition-type:xml-rpc-fault
+  (make-condition-type 'xml-rpc-fault condition-type:error '(code string)
+    (lambda (condition port)
+      (write-string "Remote procedure call signalled code " port)
+      (write (access-condition condition 'code) port)
+      (write-string ":" port)
+      (newline port)
+      (write-string (access-condition condition 'string) port))))
+
+(define error:xml-rpc-fault
+  (condition-signaller condition-type:xml-rpc-fault
+                      '(code string)
+                      standard-error-handler))
+
+(define (named-children name elt)
+  (let loop ((items (xml-element-contents elt)))
+    (if (pair? items)
+       (let ((item (car items))
+             (rest (loop (cdr items))))
+         (if (xml-element? item)
+             (begin
+               (require (xml-name=? (xml-element-name item) name))
+               (cons item rest))
+             (begin
+               (require
+                (or (xml-whitespace-string? item)
+                    (xml-comment? item)))
+               rest)))
+       '())))
+
+(define (all-children elt)
+  (let loop ((items (xml-element-contents elt)))
+    (if (pair? items)
+       (let ((item (car items))
+             (rest (loop (cdr items))))
+         (if (xml-element? item)
+             (cons item rest)
+             (begin
+               (require
+                (or (xml-whitespace-string? item)
+                    (xml-comment? item)))
+               rest)))
+       '())))
+
+(define (named-child name elt)
+  (let ((child (%named-child name elt)))
+    (require child)
+    child))
+
+(define (%named-child name elt)
+  (find-matching-item (xml-element-contents elt)
+    (lambda (item)
+      (and (xml-element? item)
+          (xml-name=? (xml-element-name item) name)))))
+
+(define (single-child elt)
+  (let ((children (all-children elt)))
+    (require (and (pair? children) (null? (cdr children))))
+    (car children)))
+
+(define (single-named-child name elt)
+  (let ((child (single-child elt)))
+    (require (xml-name=? (xml-element-name child) name))
+    child))
+\f
+(define (decode-value elt)
+  (let ((items (xml-element-contents elt)))
+    (if (and (pair? items)
+            (string? (car items))
+            (null? (cdr items)))
+       (car items)
+       (let ((elt (single-child elt)))
+         (case (xml-element-name elt)
+           ((boolean)
+            (let ((s (content-string elt)))
+              (cond ((string=? s "0") #f)
+                    ((string=? s "1") #t)
+                    (else (lose)))))
+           ((nil)
+            #!default)
+           ((|dateTime.iso8601|)
+            (safe-call iso8601-string->decoded-time (content-string elt)))
+           ((double)
+            (let ((x (string->number (content-string elt))))
+              (require (and x (flo:flonum? x)))
+              x))
+           ((i4 int)
+            (let ((n (string->number (content-string elt))))
+              (require
+               (and n
+                    (exact-integer? n)
+                    (<= #x-80000000 n #x7fffffff)))
+              n))
+           ((string)
+            (content-string elt))
+           ((base64)
+            (safe-call (lambda (string)
+                         (call-with-output-string
+                           (lambda (port)
+                             (call-with-decode-base64-output-port port #f
+                               (lambda (port)
+                                 (write-string string port))))))
+                       (content-string elt)))
+           ((array)
+            (map (lambda (elt) (decode-value elt))
+                 (named-children 'value
+                                 (single-named-child 'data elt)
+                                )))
+           ((struct)
+            (map (lambda (elt)
+                   (cons (utf8-string->symbol
+                          (content-string (named-child 'name elt)))
+                         (decode-value (named-child 'value elt))))
+                 (named-children 'member elt)))
+           (else (lose)))))))
+
+(define (content-string elt)
+  (let ((items (xml-element-contents elt)))
+    (require
+     (and (pair? items)
+         (string? (car items))
+         (null? (cdr items))))
+    (car items)))
+
+(define (safe-call procedure . arguments)
+  (let ((value (ignore-errors (lambda () (apply procedure arguments)))))
+    (require (not (condition? value)))
+    value))
+\f
+(define (encode-param object)
+  (rpc-elt:param (encode-value object)))
+
+(define (encode-value object)
+  (rpc-elt:value
+   (cond ((and (exact-integer? object)
+              (<= #x-80000000 object #x7fffffff))
+         (rpc-elt:int (number->string object)))
+        ((flo:flonum? object)
+         ;; Probably not right -- formatting issues
+         (rpc-elt:double (number->string object)))
+        ((boolean? object)
+         (rpc-elt:boolean (if object "1" "0")))
+        ((default-object? object)
+         (rpc-elt:nil))
+        ((string? object)
+         (encode-string object))
+        ((symbol? object)
+         (encode-string (symbol->utf8-string object)))
+        ((decoded-time? object)
+         (rpc-elt:date-time (decoded-time->iso8601-string object)))
+        ((and (pair? object)
+              (list-of-type? object
+                (lambda (item)
+                  (and (pair? item)
+                       (symbol? (car item))))))
+         (rpc-elt:struct
+          (map (lambda (item)
+                 (rpc-elt:member
+                  (rpc-elt:name (symbol->utf8-string (car item)))
+                  (encode-value (cdr item))))
+               (cdr object))))
+        ((list? object)
+         (rpc-elt:array (rpc-elt:data (map encode-value object))))
+        (else
+         (error:wrong-type-argument object
+                                    "an XML-RPC object"
+                                    'encode-value)))))
+
+(define (encode-string string)
+  (if (utf8-string-valid? string)
+      (rpc-elt:string string)
+      (call-with-output-string
+       (lambda (port)
+         (let ((context (encode-base64:initialize port #f)))
+           (encode-base64:update context string 0 (string-length string))
+           (encode-base64:finalize context))))))
+
+(define (rpc-elt name empty?)
+  (let ((make-elt
+        (standard-xml-element-constructor name
+                                          (null-xml-namespace-iri)
+                                          empty?)))
+    (if empty?
+       (lambda ()
+         (make-elt))
+       (lambda contents
+         (apply make-elt (xml-attrs) contents)))))
+
+(define rpc-elt:array (rpc-elt 'array #f))
+(define rpc-elt:base64 (rpc-elt 'base64 #f))
+(define rpc-elt:boolean (rpc-elt 'boolean #f))
+(define rpc-elt:data (rpc-elt 'data #f))
+(define rpc-elt:date-time (rpc-elt '|dateTime.iso8601| #f))
+(define rpc-elt:double (rpc-elt 'double #f))
+(define rpc-elt:fault (rpc-elt 'fault #f))
+(define rpc-elt:i4 (rpc-elt 'i4 #f))
+(define rpc-elt:int (rpc-elt 'int #f))
+(define rpc-elt:member (rpc-elt 'member #f))
+(define rpc-elt:method-call (rpc-elt '|methodCall| #f))
+(define rpc-elt:method-name (rpc-elt '|methodName| #f))
+(define rpc-elt:method-response (rpc-elt '|methodResponse| #f))
+(define rpc-elt:name (rpc-elt 'name #f))
+(define rpc-elt:nil (rpc-elt 'nil #t))
+(define rpc-elt:param (rpc-elt 'param #f))
+(define rpc-elt:params (rpc-elt 'params #f))
+(define rpc-elt:string (rpc-elt 'string #f))
+(define rpc-elt:struct (rpc-elt 'struct #f))
+(define rpc-elt:value (rpc-elt 'value #f))
\ No newline at end of file
index c112d9f9d03ebbadf947e955c7275d2dc132dc54..4c8bce06acfc691e55904edb47542e9f3aec8348 100644 (file)
@@ -1,8 +1,8 @@
 #| -*-Scheme-*-
 
-$Id: xml.pkg,v 1.55 2004/11/17 05:48:43 cph Exp $
+$Id: xml.pkg,v 1.56 2005/02/19 04:34:24 cph Exp $
 
-Copyright 2001,2002,2003,2004 Massachusetts Institute of Technology
+Copyright 2001,2002,2003,2004,2005 Massachusetts Institute of Technology
 
 This file is part of MIT/GNU Scheme.
 
@@ -502,4 +502,17 @@ USA.
   (export (runtime xml parser)
          html-entities)
   (export (runtime xml output)
-         html-char->name-map))
\ No newline at end of file
+         html-char->name-map))
+
+(define-package (runtime xml xml-rpc)
+  (files "xml-rpc")
+  (parent (runtime xml))
+  (export ()
+         condition-type:bad-xml-rpc-message
+         condition-type:xml-rpc-fault
+         xml-rpc:condition->fault
+         xml-rpc:fault
+         xml-rpc:parse-request
+         xml-rpc:parse-response
+         xml-rpc:response
+         xml-rpc:simple-fault))
\ No newline at end of file