home *** CD-ROM | disk | FTP | other *** search
- # XMLRPC.tcl - Copyright (C) 2001 Pat Thoyts <Pat.Thoyts@bigfoot.com>
- #
- # Provide Tcl access to XML-RPC provided methods.
- #
- # See http://tclsoap.sourceforge.net/ for usage details.
- #
- # -------------------------------------------------------------------------
- # This software 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 accompanying file `LICENSE'
- # for more details.
- # -------------------------------------------------------------------------
-
- package provide XMLRPC 1.0
-
- package require SOAP 1.4
- package require rpcvar
-
- namespace eval XMLRPC {
- variable version 1.0
- variable rcs_version { $Id: XMLRPC.tcl,v 1.5 2001/08/08 15:35:34 patthoyts Exp $ }
-
- namespace export create cget dump configure proxyconfig export
- catch {namespace import -force [uplevel {namespace current}]::rpcvar::*}
- }
-
- # -------------------------------------------------------------------------
-
- # Delegate all these methods to the SOAP package. The only difference between
- # a SOAP and XML-RPC call are the method call wrapper and unwrapper.
-
- proc XMLRPC::create {args} {
- set args [linsert $args 1 \
- -wrapProc [namespace origin \
- [namespace parent]::SOAP::xmlrpc_request] \
- -parseProc [namespace origin \
- [namespace parent]::SOAP::parse_xmlrpc_response]]
- return [uplevel 1 "SOAP::create $args"]
- }
-
- proc XMLRPC::configure { args } {
- return [uplevel 1 "SOAP::configure $args"]
- }
-
- proc XMLRPC::cget { args } {
- return [uplevel 1 "SOAP::cget $args"]
- }
-
- proc XMLRPC::dump { args } {
- return [uplevel 1 "SOAP::dump $args"]
- }
-
- proc XMLRPC::proxyconfig { args } {
- return [uplevel 1 "SOAP::proxyconfig $args"]
- }
-
- proc XMLRPC::export {args} {
- foreach item $args {
- uplevel "set \[namespace current\]::__xmlrpc_exports($item)\
- \[namespace code $item\]"
- }
- return
- }
-
- # -------------------------------------------------------------------------
-
- # Description:
- # Prepare an XML-RPC fault response
- # Parameters:
- # faultcode the XML-RPC fault code (numeric)
- # faultstring summary of the fault
- # detail list of {detailName detailInfo}
- # Result:
- # Returns the XML text of the SOAP Fault packet.
- #
- proc XMLRPC::fault {faultcode faultstring {detail {}}} {
- set xml [join [list \
- "<?xml version=\"1.0\" ?>" \
- "<methodResponse>" \
- " <fault>" \
- " <value>" \
- " <struct>" \
- " <member>" \
- " <name>faultCode</name>"\
- " <value><int>${faultcode}</int></value>" \
- " </member>" \
- " <member>" \
- " <name>faultString</name>"\
- " <value><string>${faultstring}</string></value>" \
- " </member>" \
- " </struct> "\
- " </value>" \
- " </fault>" \
- "</methodResponse>"] "\n"]
- return $xml
- }
-
- # -------------------------------------------------------------------------
-
- # Description:
- # Generate a reply packet for a simple reply containing one result element
- # Parameters:
- # doc empty DOM document element
- # uri URI of the SOAP method
- # methodName the SOAP method name
- # result the reply data
- # Result:
- # Returns the DOM document root of the generated reply packet
- #
- proc XMLRPC::reply {doc uri methodName result} {
- set d_root [dom::document createElement $doc "methodResponse"]
- set d_params [dom::document createElement $d_root "params"]
- set d_param [dom::document createElement $d_params "param"]
- insert_value $d_param $result
- return $doc
- }
-
- # -------------------------------------------------------------------------
-
- # node is the <param> element
- proc XMLRPC::insert_value {node value} {
-
- set type [rpctype $value]
- set value [rpcvalue $value]
- set typeinfo [typedef -info $type]
-
- set value_elt [dom::document createElement $node "value"]
-
- if {[string match {*()} $type] || [string match array $type]} {
- # array type: arrays are indicated by a () suffix of the word 'array'
- set itemtype [string trimright $type ()]
- if {$itemtype == "array"} {
- set itemtype "any"
- }
- set array_elt [dom::document createElement $value_elt "array"]
- set data_elt [dom::document createElement $array_elt "data"]
- foreach elt $value {
- if {[string match $itemtype "any"] || \
- [string match $itemtype "ur-type"] || \
- [string match $itemtype "anyType"]} {
- XMLRPC::insert_value $data_elt $elt
- } else {
- XMLRPC::insert_value $data_elt [rpcvar $itemtype $elt]
- }
- }
- } elseif {[llength $typeinfo] > 1} {
- # a typedef'd struct
- set struct_elt [dom::document createElement $value_elt "struct"]
- array set ti $typeinfo
- foreach {eltname eltvalue} $value {
- set member_elt [dom::document createElement $struct_elt "member"]
- set name_elt [dom::document createElement $member_elt "name"]
- dom::document createTextNode $name_elt $eltname
- if {![info exists ti($eltname)]} {
- error "invalid member name: \"$eltname\" is not a member of\
- the $type type."
- }
- XMLRPC::insert_value $member_elt [rpcvar $ti($eltname) $eltvalue]
- }
-
- } elseif {[string match struct $type]} {
- # an undefined struct
- set struct_elt [dom::document createElement $value_elt "struct"]
- foreach {eltname eltvalue} $value {
- set member_elt [dom::document createElement $struct_elt "member"]
- set name_elt [dom::document createElement $member_elt "name"]
- dom::document createTextNode $name_elt $eltname
- XMLRPC::insert_value $member_elt $eltvalue
- }
- } else {
- # simple type.
- set type_elt [dom::document createElement $value_elt $type]
- dom::document createTextNode $type_elt $value
- }
- }
-
- # -------------------------------------------------------------------------
-
- # Local variables:
- # indent-tabs-mode: nil
- # End:
-