├── .gitignore ├── CHANGES.txt ├── LICENSE ├── MANIFEST.in ├── README.rst ├── SOAPpy.spec ├── TODO ├── bid ├── .cvsignore ├── inventory.servers ├── inventoryClient.py ├── inventoryServer.py └── monitorClient.py ├── contrib ├── .cvsignore ├── soap_cli.py └── soap_handler.py ├── docs ├── GettingStarted.txt ├── GlobusSupport.txt ├── MethodParameterNaming.txt ├── UsingHeaders.txt ├── WSDL.txt ├── attrs.txt ├── complexTypes.txt └── simpleTypes.txt ├── old.Changelog ├── setup.py ├── src └── SOAPpy │ ├── Client.py │ ├── Config.py │ ├── Errors.py │ ├── GSIServer.py │ ├── NS.py │ ├── Parser.py │ ├── SOAP.py │ ├── SOAPBuilder.py │ ├── Server.py │ ├── Types.py │ ├── URLopener.py │ ├── Utilities.py │ ├── WSDL.py │ ├── __init__.py │ └── version.py ├── tests ├── BabelfishWSDLTest.py ├── Bug1001646.py ├── Bug916265.py ├── Bug918216.py ├── ComplexTypes.py ├── GoogleTest.py ├── SOAPtest.py ├── TCtest.py ├── TemperatureService.wsdl ├── ZeroLengthArray.py ├── alanbushTest.py ├── cardClient.py ├── cardServer.py ├── echoClient.py ├── echoHeader.py ├── echoServer.py ├── esj_test_client.py ├── esj_test_server.py ├── excelTest.py ├── largeDataTest.py ├── newsTest.py ├── quoteTest.py ├── simpleWSDL.py ├── speedTest.py ├── storageTest.py ├── testClient1.py ├── testWSDL.py ├── testleak.py ├── testsclient.py ├── testserver.py ├── translateTest.py ├── vul_etcpasswd.txt ├── vul_lol.txt ├── weatherTest.py ├── whoisTest.py └── xmethods.py ├── tools ├── .cvsignore └── interop2html.py ├── validate ├── .cvsignore ├── server.pem ├── silab.servers ├── silabclient.py ├── silabserver.py └── soapware.py ├── vul_ok.txt └── zope ├── README ├── zope-2.5.0-soappy.diff ├── zope-2.6.2-soappy.diff └── zope-soap-client.py /.gitignore: -------------------------------------------------------------------------------- 1 | *.egg-info 2 | MANIFEST.in 3 | build/ 4 | dist/ 5 | setup.cfg 6 | venv/ 7 | *.pyc 8 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | ============================================== 2 | SOAPpy - Simple to use SOAP library for Python 3 | ============================================== 4 | 5 | Current Maintainers: 6 | 7 | Gregory R. Warnes 8 | Christopher Blunck 9 | 10 | Original Authors: 11 | 12 | Cayce Ullman 13 | Brian Matthews 14 | 15 | Contributions by: 16 | 17 | Brad Knotwell 18 | Mark Bucciarelli (ported WSDL 19 | client from ZSI) 20 | Ivan R. Judson (Globus support) 21 | Kirk Strauser 22 | Antonio Beamud Montero (patches 23 | for integrating SOAPpy into Zope) 24 | 25 | Copyright (c) 2002-2003, Pfizer, Inc. 26 | Copyright (c) 2001, Cayce Ullman. 27 | Copyright (c) 2001, Brian Matthews. 28 | All rights reserved. 29 | 30 | LICENSE: 31 | ---------------------------------------------------------------------------- 32 | Redistribution and use in source and binary forms, with or without 33 | modification, are permitted provided that the following conditions are met: 34 | 35 | Redistributions of source code must retain the above copyright notice, this 36 | list of conditions and the following disclaimer. 37 | Redistributions in binary form must reproduce the above copyright notice, 38 | this list of conditions and the following disclaimer in the documentation 39 | and/or other materials provided with the distribution. 40 | 41 | Neither the name of actzero, inc. nor the names of its contributors may 42 | be used to endorse or promote products derived from this software without 43 | specific prior written permission. 44 | 45 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 46 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 47 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 48 | ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR 49 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 50 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 51 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 52 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 53 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 54 | OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 55 | DAMAGE. 56 | 57 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include *.txt *.cfg *.rst 2 | recursive-include validate * 3 | recursive-include contrib * 4 | recursive-include src * 5 | recursive-include tests * 6 | recursive-include tools * 7 | recursive-include zope * 8 | recursive-include docs * 9 | recursive-include bid * 10 | global-exclude *pyc 11 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | ============================================== 2 | SOAPpy - Simple to use SOAP library for Python 3 | ============================================== 4 | 5 | .. contents:: 6 | 7 | DISCLAIMER - ABANDONED/UNMAINTAINED CODE / DO NOT USE 8 | ======================================================= 9 | While this repository has been inactive for some time, this formal notice, issued on **December 10, 2024**, serves as the official declaration to clarify the situation. Consequently, this repository and all associated resources (including related projects, code, documentation, and distributed packages such as Docker images, PyPI packages, etc.) are now explicitly declared **unmaintained** and **abandoned**. 10 | 11 | I would like to remind everyone that this project’s free license has always been based on the principle that the software is provided "AS-IS", without any warranty or expectation of liability or maintenance from the maintainer. 12 | As such, it is used solely at the user's own risk, with no warranty or liability from the maintainer, including but not limited to any damages arising from its use. 13 | 14 | Due to the enactment of the Cyber Resilience Act (EU Regulation 2024/2847), which significantly alters the regulatory framework, including penalties of up to €15M, combined with its demands for **unpaid** and **indefinite** liability, it has become untenable for me to continue maintaining all my Open Source Projects as a natural person. 15 | The new regulations impose personal liability risks and create an unacceptable burden, regardless of my personal situation now or in the future, particularly when the work is done voluntarily and without compensation. 16 | 17 | **No further technical support, updates (including security patches), or maintenance, of any kind, will be provided.** 18 | 19 | These resources may remain online, but solely for public archiving, documentation, and educational purposes. 20 | 21 | Users are strongly advised not to use these resources in any active or production-related projects, and to seek alternative solutions that comply with the new legal requirements (EU CRA). 22 | 23 | **Using these resources outside of these contexts is strictly prohibited and is done at your own risk.** 24 | 25 | This project has been transfered to Makina Corpus ( https://makina-corpus.com ). This project and its associated resources, including published resources related to this project (e.g., from PyPI, Docker Hub, GitHub, etc.), may be removed starting **March 15, 2025**, especially if the CRA’s risks remain disproportionate. 26 | 27 | Disclaimer 28 | ========== 29 | Please use `suds `_ rather than SOAPpy. 30 | SOAPpy is old and clamsy. 31 | 32 | Credits 33 | ======== 34 | 35 | 36 | 37 | Companies 38 | --------- 39 | |makinacom|_ 40 | 41 | * `Planet Makina Corpus `_ 42 | * `Contact us `_ 43 | 44 | .. |makinacom| image:: http://depot.makina-corpus.org/public/logo.gif 45 | .. _makinacom: http://www.makina-corpus.com 46 | 47 | Authors 48 | ------------ 49 | 50 | - Cayce Ullman 51 | - Brian Matthews 52 | - Gregory R. Warnes 53 | - Makina Corpus 54 | - Makina Corpus 55 | 56 | Contributors 57 | ---------------- 58 | - Christopher Blunck 59 | - Brad Knotwell 60 | - Mark Bucciarelli (ported WSDL client from ZSI) 61 | - Ivan R. Judson (Globus support) 62 | - Kirk Strauser 63 | - Antonio Beamud Montero (patches for integrating SOAPpy into Zope) 64 | - And others. 65 | 66 | Copyright (c) 20011 Makina Corpus 67 | Copyright (c) 2002-2005, Pfizer, Inc. 68 | Copyright (c) 2001, Cayce Ullman. 69 | Copyright (c) 2001, Brian Matthews. 70 | All rights reserved, see the file LICENSE for conditions of use. 71 | 72 | INTRODUCTION 73 | ============== 74 | 75 | The goal of the SOAPpy team is to provide a full-featured SOAP library 76 | for Python that is very simple to use and that fully supports dynamic 77 | interaction between clients and servers. 78 | 79 | 80 | INCLUDED 81 | -------- 82 | - General SOAP Parser based on sax.xml 83 | - General SOAP Builder 84 | - SOAP Proxy for RPC client code 85 | - SOAP Server framework for RPC server code 86 | 87 | FEATURES 88 | -------- 89 | - Handles all SOAP 1.0 types 90 | - Handles faults 91 | - Allows namespace specification 92 | - Allows SOAPAction specification 93 | - Homogeneous typed arrays 94 | - Supports multiple schemas 95 | - Header support (mustUnderstand and actor) 96 | - XML attribute support 97 | - Multi-referencing support (Parser/Builder) 98 | - Understands SOAP-ENC:root attribute 99 | - Good interop, passes all client tests for Frontier, SOAP::LITE, SOAPRMI 100 | - Encodings 101 | - SSL clients (with Python compiled with OpenSSL support) 102 | - SSL servers (with Python compiled with OpenSSL support and M2Crypto installed) 103 | - Encodes XML tags per SOAP 1.2 name mangling specification (Gregory Warnes) 104 | - Automatic stateful SOAP server support (Apache v2.x) (blunck2) 105 | - WSDL client support 106 | - WSDL server support 107 | 108 | TODO (See RELEASE_INFO and CHANGELOG for recent changes) 109 | ---------------------------------------------------------- 110 | - Timeout on method calls 111 | - Advanced arrays (sparse, multidimensional and partial) 112 | - Attachments 113 | - mod_python example 114 | - medusa example 115 | - Improved documentation 116 | 117 | MANIFEST 118 | -------- 119 | :: 120 | 121 | Files 122 | 123 | README This file 124 | RELEASE_NOTES General information about each release 125 | ChangeLog Detailed list of changes 126 | TODO List of tasks that need to be done 127 | setup.py Python installation control files 128 | SOAPpy.spec RPM package control file 129 | 130 | Directories 131 | 132 | SOAPpy/ Source code for the package 133 | SOAPpy/wstools/ Source code for WSDL tools 134 | tests/ unit tests and examples 135 | validate/ interop client and servers 136 | bid/ N+I interop client and server 137 | contrib/ Contributed examples (also see test/) 138 | docs/ Documentation 139 | tools/ Misc tools useful for the SOAPpy developers 140 | zope/ Patches to Zope allowing it to provide SOAP services 141 | 142 | 143 | INSTALLATION 144 | ============ 145 | 146 | USING GITHUB 147 | ------------ 148 | 149 | You can install SOAPpy and its dependencies directly from GitHub using PIP: 150 | 151 | pip install -e "git+http://github.com/kiroky/SOAPpy.git@develop#egg=SOAPpy" 152 | 153 | REQUIRED PACKAGES 154 | ------------------ 155 | 156 | - wstools 157 | 158 | 159 | OPTIONAL PACKAGES 160 | ----------------- 161 | 162 | - pyGlobus, optional support for Globus, 163 | 164 | 165 | - M2Crypto.SSL, optional support for server-side SSL 166 | 167 | 168 | - If Python is compiled with SSL support (Python 2.3 does so by 169 | default), client-side use of SSL is supported 170 | 171 | INSTALLATION STEPS 172 | ------------------ 173 | 174 | As of version 0.9.8 SOAPpy can be installed using the standard python 175 | package installation tools. 176 | 177 | To install: 178 | 179 | 1) Unpack the distribution package: 180 | 181 | On Windows, use your favorite zip file uncompression tool. 182 | 183 | On Unix:: 184 | 185 | $ tar -xvzf SOAPpy-$VERSION$.tar.gz 186 | 187 | If you have gnu tar, otherwise 188 | :: 189 | 190 | $ gzcat SOAPpy-$VERSION$.tar.gz | tar -xvf - 191 | 192 | 2) Change into the source directory 193 | :: 194 | 195 | cd SOAPpy-$VERSION$ 196 | 197 | 3) Compile the package:: 198 | 199 | $ python setup.py build 200 | 201 | 4) Install the package 202 | 203 | On Windows:: 204 | 205 | $ python setup.py install 206 | 207 | On Unix install as the owner of the python directories 208 | (usally root):: 209 | 210 | $ su root 211 | Password: XXXXXX 212 | $ python setup.py install 213 | 214 | 215 | DOCUMENTATION 216 | ============= 217 | QUICK START 218 | ----------- 219 | 220 | A simple "Hello World" http SOAP server:: 221 | 222 | import SOAPpy 223 | def hello(): 224 | return "Hello World" 225 | server = SOAPpy.SOAPServer(("localhost", 8080)) 226 | server.registerFunction(hello) 227 | server.serve_forever() 228 | 229 | And the corresponding client:: 230 | 231 | import SOAPpy 232 | server = SOAPpy.SOAPProxy("http://localhost:8080/") 233 | print server.hello() 234 | 235 | BASIC TUTORIAL 236 | -------------- 237 | Mark Pilgrims _Dive Into Python, published in printed form by 238 | Apress and online at at http://diveintopython.org provides a 239 | nice tutorial for SOAPpy in Chapter 12, "SOAP Web Services". 240 | See http://diveintopython.org/soap_web_services . 241 | 242 | OTHER DOCUMENTATION 243 | ------------------- 244 | 245 | For further information see the files in the docs/ directory. 246 | 247 | Note that documentation is one of SOAPpy's current weak points. 248 | Please help us out! 249 | 250 | 251 | Support 252 | ============ 253 | Github: https://github.com/kiorky/SOAPpy 254 | Issues: https://github.com/kiorky/SOAPpy/issues 255 | 256 | -------------------------------------------------------------------------------- /SOAPpy.spec: -------------------------------------------------------------------------------- 1 | Summary: SOAPpy 2 | Name: SOAPpy 3 | Version: 0.9.7 4 | Release: 2 5 | License: Copyright (c) 2001, Cayce Ullman. 6 | Group: Productivity/Networking/Web/Applications 7 | Source: SOAPpy-%{version}.tgz 8 | Requires: python >= 2.2 9 | BuildArch: noarch 10 | AutoReq: no 11 | Packager: Antonio Beamud Montero 12 | 13 | %description 14 | SOAP implementation by Cayce Ullman and Brian Matthews. 15 | %prep 16 | %setup SOAPpy-%{version} 17 | 18 | %build 19 | 20 | %install 21 | mkdir -p /usr/share/doc/SOAPpy/bid 22 | cp -a bid/* /usr/share/doc/SOAPpy/bid 23 | mkdir -p /usr/share/doc/SOAPpy/tests 24 | cp -a tests/* /usr/share/doc/SOAPpy/tests 25 | cp -a TCtest.py /usr/share/doc/SOAPpy/tests 26 | mkdir -p /usr/share/doc/SOAPpy/contrib 27 | cp contrib/* /usr/share/doc/SOAPpy/contrib/ 28 | cp docs/* /usr/share/doc/SOAPpy/ 29 | mkdir -p /usr/share/doc/SOAPpy/tools 30 | cp -a tools/* /usr/share/doc/SOAPpy/tools 31 | cp README /usr/share/doc/SOAPpy/ 32 | cp echoServer.py /usr/share/doc/SOAPpy/ 33 | cp speedTest.py /usr/share/doc/SOAPpy/ 34 | cp CHANGELOG /usr/share/doc/SOAPpy/ 35 | cp SOAPtest.py /usr/share/doc/SOAPpy/tests 36 | cp excelTest.py /usr/share/doc/SOAPpy/ 37 | cp echoClient.py /usr/share/doc/SOAPpy/ 38 | mkdir -p /usr/share/doc/SOAPpy/validate 39 | cp -a validate/* /usr/share/doc/SOAPpy/validate 40 | cp SOAP.py /usr/lib/python/site-packages/ 41 | 42 | %clean 43 | 44 | %pre 45 | 46 | %post 47 | 48 | %preun 49 | 50 | %postun 51 | 52 | %files 53 | %defattr(-,root,root) 54 | /usr/share/doc/SOAPpy/bid/monitorClient.py 55 | /usr/share/doc/SOAPpy/bid/inventoryServer.py 56 | /usr/share/doc/SOAPpy/bid/inventory.servers 57 | /usr/share/doc/SOAPpy/bid/inventoryClient.py 58 | /usr/share/doc/SOAPpy/tests/TCtest.py 59 | /usr/share/doc/SOAPpy/simpleTypes.txt 60 | /usr/share/doc/SOAPpy/attrs.txt 61 | /usr/share/doc/SOAPpy/quickstart.txt 62 | /usr/share/doc/SOAPpy/complexTypes.txt 63 | /usr/share/doc/SOAPpy/contrib/soap_cli.py 64 | /usr/share/doc/SOAPpy/contrib/soap_handler.py 65 | /usr/share/doc/SOAPpy/tests/cardServer.py 66 | /usr/share/doc/SOAPpy/tests/guidTest.py 67 | /usr/share/doc/SOAPpy/tests/alanbushTest.py 68 | /usr/share/doc/SOAPpy/tests/newsTest.py 69 | /usr/share/doc/SOAPpy/tests/weatherTest.py 70 | /usr/share/doc/SOAPpy/tests/fortuneTest.py 71 | /usr/share/doc/SOAPpy/tests/cardClient.py 72 | /usr/share/doc/SOAPpy/tests/quoteTest.py 73 | /usr/share/doc/SOAPpy/tests/storageTest.py 74 | /usr/share/doc/SOAPpy/tests/wordFindTest.py 75 | /usr/share/doc/SOAPpy/tests/itimeTest.py 76 | /usr/share/doc/SOAPpy/tests/whoisTest.py 77 | /usr/share/doc/SOAPpy/tests/translateTest.py 78 | /usr/share/doc/SOAPpy/tools/interop2html.py 79 | /usr/share/doc/SOAPpy/README 80 | /usr/share/doc/SOAPpy/echoServer.py 81 | /usr/share/doc/SOAPpy/speedTest.py 82 | /usr/share/doc/SOAPpy/CHANGELOG 83 | /usr/share/doc/SOAPpy/tests/SOAPtest.py 84 | /usr/share/doc/SOAPpy/excelTest.py 85 | /usr/share/doc/SOAPpy/echoClient.py 86 | /usr/share/doc/SOAPpy/validate/silab.servers 87 | /usr/share/doc/SOAPpy/validate/silabserver.py 88 | /usr/share/doc/SOAPpy/validate/server.pem 89 | /usr/share/doc/SOAPpy/validate/silabclient.py 90 | /usr/share/doc/SOAPpy/validate/soapware.py 91 | /usr/lib/python2.2/site-packages/SOAP.py -------------------------------------------------------------------------------- /TODO: -------------------------------------------------------------------------------- 1 | # $Id: TODO,v 1.6 2003/12/23 10:19:12 warnes Exp $ 2 | 3 | - figure out why parsing rules are broken 4 | 5 | - generate a test harness that will run all of the test code. 6 | 7 | - create unit-tests for all features, as well as for reported bugs. 8 | 9 | - write better documentation (!!!) 10 | - topics: WSDL, Globus, Authentication, ... 11 | - general introduction article 12 | - ... 13 | 14 | 15 | -------------------------------------------------------------------------------- /bid/.cvsignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | -------------------------------------------------------------------------------- /bid/inventory.servers: -------------------------------------------------------------------------------- 1 | # This list of servers was taken from the SOAPBuilders Interoperability Lab 2 | # (http://www.xmethods.net/ilab/ilab.html) 4/23/01. 3 | # 4 | # $Id: inventory.servers 4 2001-06-27 21:36:11Z cullman $ 5 | 6 | Name: MST Bid (Microsoft SOAP Toolkit 2.0, Microsoft Windows 2000) 7 | Endpoint: http://131.107.72.13/stk/Bid.wsdl 8 | SOAPAction: "http://www.soapinterop.org/%(methodname)s" 9 | Namespace: http://www.soapinterop.org/Bid 10 | 11 | Name: KeithBa's BidBuy Service (.NET Web Services) 12 | Endpoint: http://131.107.72.13/test/bidbuy/bidbuy.asmx 13 | SOAPAction: "http://www.soapinterop.org/%(methodname)s" 14 | Namespace: http://soapinterop.org/xsd 15 | 16 | Name: JHawk's BidBuyService (.NET Remoting, Win2K) 17 | Endpoint: http://131.107.72.13/DotNetRemotingNI/BidBuy.soap 18 | SOAPAction: "http://www.soapinterop.org/%(methodname)s" 19 | Namespace: http://www.soapinterop.org/Bid 20 | 21 | #Name: Idoox WASP 22 | #Endpoint: http://soap.idoox.net:8888/soap/servlet/Bid/ 23 | #SOAPAction: "http://www.soapinterop.org/%(methodname)s" 24 | #Namespace: http://www.soapinterop.org/Bid 25 | 26 | Name: Paul's Quick Bid (SOAP::Lite) 27 | Endpoint: http://services.soaplite.com/tradeit.cgi 28 | SOAPAction: "http://www.soapinterop.org/%(methodname)s" 29 | Namespace: http://www.soapinterop.org/Bid 30 | 31 | Name: Phalanx Bid Service 32 | Endpoint: http://www.phalanxsys.com/ni/listener.asp 33 | SOAPAction: "http://www.soapinterop.org/%(methodname)s" 34 | Namespace: http://www.soapinterop.org/Bid 35 | Nonfunctional: Buy admitted problem with the wsdl 36 | 37 | Name: PranishK's BidBuy Service (ATL Web Service) 38 | Endpoint: http://www.mssoapinterop.org/atls_soap/bidbuy.dll?Handler=Default 39 | SOAPAction: "#%(methodname)s" 40 | Namespace: http://www.soapinterop.org/Bid 41 | 42 | Name: GLUE Bid 43 | Endpoint: http://209.61.190.164:8004/glue/http://www.soapinterop.org/Bid 44 | SOAPAction: "http://www.soapinterop.org/Bid#(methodname)s" 45 | Namespace: http://www.soapinterop.org/Bid 46 | 47 | Name: Aumsoft's BidBuy 48 | Endpoint: http://soap.aumsoft.com:8080/soap/BidBuy 49 | SOAPAction: "http://www.soapinterop.org/%(methodname)s" 50 | Namespace: http://www.soapinterop.org/Bid 51 | 52 | Name: SOAP.py 0.9 (actzero.com) 53 | Endpoint: http://208.177.157.221:12080/xmethodsInterop 54 | SOAPAction: "http://www.soapinterop.org/%(methodname)s" 55 | Namespace: http://www.soapinterop.org/Bid 56 | 57 | Name: HP SOAP 58 | Endpoint: http://soap.bluestone.com/scripts/SaISAPI.dll/SaServletEngine.class/hp-soap/soap/rpc/interop/BidBuy 59 | SOAPAction: "http://www.soapinterop.org/%(methodname)s" 60 | Namespace: http://www.soapinterop.org/Bid 61 | 62 | Name: EasySoap++ Bid Service (San Diego) 63 | Endpoint: http://easysoap.no-ip.com:8080/cgi-bin/bidbuyservice 64 | SOAPAction: "http://www.soapinterop.org/%(methodname)s" 65 | Namespace: http://www.soapinterop.org/Bid 66 | 67 | Name: Jake's Frontier 7.0b43 Bid Service (Santa Clara, CA) 68 | Endpoint: http://www.soapware.org/BidBuy 69 | SOAPAction: "http://www.soapinterop.org/%(methodname)s" 70 | Namespace: http://www.soapinterop.org/Bid 71 | 72 | #Name: Pete's Clear Bids (CapeConnect/Win2000) 73 | #Endpoint: http://208.46.17.81/ccx/SOAPServlet 74 | #SOAPAction: "http://www.soapinterop.org/%(methodname)s" 75 | #Namespace: http://www.soapinterop.org/Bid 76 | 77 | #Name: (PranishK's) ATL Server BidBuy 78 | #Endpoint: http://208.46.17.121/bidbuy/bidbuy.dll?Handler=Default 79 | #SOAPAction: "http://www.soapinterop.org/%(methodname)s" 80 | #Namespace: http://www.soapinterop.org/Bid 81 | 82 | #Name: HP-SOAP @ N+I 83 | #Endpoint: http://208.46.17.112/scripts/SaISAPI.dll/SaServletEngine.class/hp-soap/soap/rpc/interop/BidBuy 84 | #SOAPAction: "http://www.soapinterop.org/%(methodname)s" 85 | #Namespace: http://www.soapinterop.org/Bid 86 | 87 | -------------------------------------------------------------------------------- /bid/inventoryClient.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | 4 | import getopt 5 | import sys 6 | import string 7 | import re 8 | import time 9 | sys.path.insert(1,"..") 10 | from SOAPpy import SOAP 11 | import traceback 12 | 13 | DEFAULT_SERVERS_FILE = './inventory.servers' 14 | 15 | DEFAULT_METHODS = ('SimpleBuy', 'RequestForQuote','Buy','Ping') 16 | 17 | def usage (error = None): 18 | sys.stdout = sys.stderr 19 | 20 | if error != None: 21 | print error 22 | 23 | print """usage: %s [options] [server ...] 24 | If a long option shows an argument is mandatory, it's mandatory for the 25 | equivalent short option also. 26 | 27 | -?, --help display this usage 28 | -d, --debug turn on debugging in the SOAP library 29 | -i, --invert test servers *not* in the list of servers given 30 | -m, --method=METHOD#[,METHOD#...] 31 | call only the given methods, specify a METHOD# of ? 32 | for the list of method numbers 33 | -o, --output=TYPE turn on output, TYPE is one or more of s(uccess), 34 | f(ailure), n(ot implemented), F(ailed (as expected)), 35 | a(ll) 36 | [f] 37 | -s, --servers=FILE use FILE as list of servers to test [%s] 38 | -t, --stacktrace print a stack trace on each unexpected failure 39 | -T, --always-stacktrace 40 | print a stack trace on any failure 41 | """ % (sys.argv[0], DEFAULT_SERVERS_FILE), 42 | 43 | sys.exit (0) 44 | 45 | 46 | def methodUsage (): 47 | sys.stdout = sys.stderr 48 | 49 | print "Methods are specified by number. Multiple methods can be " \ 50 | "specified using a\ncomma-separated list of numbers or ranges. " \ 51 | "For example 1,4-6,8 specifies\nmethods 1, 4, 5, 6, and 8.\n" 52 | 53 | print "The available methods are:\n" 54 | 55 | half = (len (DEFAULT_METHODS) + 1) / 2 56 | for i in range (half): 57 | print "%4d. %-25s" % (i + 1, DEFAULT_METHODS[i]), 58 | if i + half < len (DEFAULT_METHODS): 59 | print "%4d. %-25s" % (i + 1 + half, DEFAULT_METHODS[i + half]), 60 | print 61 | 62 | sys.exit (0) 63 | 64 | 65 | def readServers (file): 66 | servers = [] 67 | f = open (file, 'r') 68 | 69 | while 1: 70 | line = f.readline () 71 | 72 | if line == '': 73 | break 74 | 75 | if line[0] in ('#', '\n') or line[0] in string.whitespace: 76 | continue 77 | 78 | cur = {'nonfunctional': {}} 79 | tag = None 80 | servers.append (cur) 81 | 82 | while 1: 83 | if line[0] in string.whitespace: 84 | if tag == 'nonfunctional': 85 | value = method + ' ' + cur[tag][method] 86 | else: 87 | value = cur[tag] 88 | value += ' ' + line.strip () 89 | else: 90 | tag, value = line.split (':', 1) 91 | 92 | tag = tag.strip ().lower () 93 | value = value.strip () 94 | 95 | if value[0] == '"' and value[-1] == '"': 96 | value = value[1:-1] 97 | 98 | if tag == 'nonfunctional': 99 | value = value.split (' ', 1) + [''] 100 | 101 | method = value[0] 102 | cur[tag][method] = value[1] 103 | else: 104 | cur[tag] = value 105 | 106 | line = f.readline () 107 | 108 | if line == '' or line[0] == '\n': 109 | break 110 | 111 | return servers 112 | 113 | def str2list (s): 114 | l = {} 115 | 116 | for i in s.split (','): 117 | if i.find ('-') != -1: 118 | i = i.split ('-') 119 | for i in range (int (i[0]),int (i[1]) + 1): 120 | l[i] = 1 121 | else: 122 | l[int (i)] = 1 123 | 124 | l = l.keys () 125 | l.sort () 126 | 127 | return l 128 | 129 | def SimpleBuy(serv, sa, epname): 130 | serv = serv._sa (sa % {'methodname':'SimpleBuy'}) 131 | return serv.SimpleBuy(ProductName="widget", Quantity = 50, Address = "this is my address") #JHawk, Phalanx require this order of params 132 | 133 | 134 | def RequestForQuote(serv, sa, epname): 135 | serv = serv._sa (sa % {'methodname':'RequestForQuote'}) 136 | return serv.RequestForQuote(Quantity=3, ProductName = "thing") # for Phalanx, JHawk 137 | 138 | 139 | def Buy(serv, sa, epname): 140 | import copy 141 | serv = serv._sa (sa % {'methodname':'Buy'}) 142 | billTo_d = {"name":"Buyer One", "address":"1 1st Street", 143 | "city":"New York", "state":"NY", "zipCode":"10000"} 144 | shipTo_d = {"name":"Buyer One ", "address":"1 1st Street ", 145 | "city":"New York ", "state":"NY ", "zipCode":"10000 "} 146 | 147 | for k,v in shipTo_d.items(): 148 | shipTo_d[k] = v[:-1] 149 | 150 | itemd1 = SOAP.structType( {"name":"widg1","quantity":200,"price":SOAP.decimalType(45.99), "_typename":"LineItem"}) 151 | itemd2 = SOAP.structType( {"name":"widg2","quantity":400,"price":SOAP.decimalType(33.45), "_typename":"LineItem"}) 152 | 153 | items_d = SOAP.arrayType( [itemd1, itemd2] ) 154 | items_d._ns = "http://www.soapinterop.org/Bid" 155 | po_d = SOAP.structType( data = {"poID":"myord","createDate":SOAP.dateTimeType(),"shipTo":shipTo_d, "billTo":billTo_d, "items":items_d}) 156 | try: 157 | # it's called PO by MST (MS SOAP Toolkit), JHawk (.NET Remoting), 158 | # Idoox WASP, Paul (SOAP::Lite), PranishK (ATL), GLUE, Aumsoft, 159 | # HP, EasySoap, and Jake (Frontier). [Actzero accepts either] 160 | return serv.Buy(PO=po_d) 161 | except: 162 | # called PurchaseOrder by KeithBa 163 | return serv.Buy(PurchaseOrder=po_d) 164 | 165 | 166 | def Ping(serv, sa, epname): 167 | serv = serv._sa (sa % {'methodname':'Ping'}) 168 | return serv.Ping() 169 | 170 | def main(): 171 | servers = DEFAULT_SERVERS_FILE 172 | methodnums = None 173 | output = 'f' 174 | invert = 0 175 | succeed = 0 176 | printtrace = 0 177 | stats = 1 178 | total = 0 179 | fail = 0 180 | failok = 0 181 | notimp = 0 182 | 183 | try: 184 | opts,args = getopt.getopt (sys.argv[1:], '?dm:io:s:t', 185 | ['help', 'method', 'debug', 'invert', 186 | 'output', 'servers=']) 187 | for opt, arg in opts: 188 | if opt in ('-?', '--help'): 189 | usage () 190 | elif opt in ('-d', '--debug'): 191 | SOAP.Config.debug = 1 192 | elif opt in ('-i', '--invert'): 193 | invert = 1 194 | elif opt in ('-m', '--method'): 195 | if arg == '?': 196 | methodUsage () 197 | methodnums = str2list (arg) 198 | elif opt in ('-o', '--output'): 199 | output = arg 200 | elif opt in ('-s', '--servers'): 201 | servers = arg 202 | else: 203 | raise AttributeError, \ 204 | "Recognized but unimplemented option `%s'" % opt 205 | except SystemExit: 206 | raise 207 | except: 208 | usage (sys.exc_info ()[1]) 209 | 210 | if 'a' in output: 211 | output = 'fFns' 212 | 213 | servers = readServers(servers) 214 | 215 | if methodnums == None: 216 | methodnums = range (1, len (DEFAULT_METHODS) + 1) 217 | 218 | limitre = re.compile ('|'.join (args), re.IGNORECASE) 219 | 220 | for s in servers: 221 | if (not not limitre.match (s['name'])) == invert: 222 | continue 223 | 224 | serv = SOAP.SOAPProxy(s['endpoint'], namespace = s['namespace']) 225 | 226 | for num in (methodnums): 227 | if num > len(DEFAULT_METHODS): 228 | break 229 | 230 | total += 1 231 | 232 | name = DEFAULT_METHODS[num - 1] 233 | 234 | title = '%s: %s (#%d)' % (s['name'], name, num) 235 | 236 | try: 237 | fn = globals ()[name] 238 | except KeyboardInterrupt: 239 | raise 240 | except: 241 | if 'n' in output: 242 | print title, "test not yet implemented" 243 | notimp += 1 244 | continue 245 | 246 | try: 247 | res = fn (serv, s['soapaction'], s['name']) 248 | if s['nonfunctional'].has_key (name): 249 | print title, "succeeded despite marked nonfunctional" 250 | elif 's' in output: 251 | print title, "succeeded " 252 | succeed += 1 253 | except KeyboardInterrupt: 254 | print "fail" 255 | raise 256 | except: 257 | if s['nonfunctional'].has_key (name): 258 | if 'F' in output: 259 | t = 'as expected' 260 | if s['nonfunctional'][name] != '': 261 | t += ', ' + s['nonfunctional'][name] 262 | print title, "failed (%s) -" %t, sys.exc_info()[1] 263 | failok += 1 264 | else: 265 | if 'f' in output: 266 | print title, "failed -", str (sys.exc_info()[1]) 267 | fail += 1 268 | 269 | if stats: 270 | print " Tests ended at:", time.ctime (time.time()) 271 | if stats > 0: 272 | print " Total tests: %d" % total 273 | print " Successes: %d (%3.2f%%)" % \ 274 | (succeed, 100.0 * succeed / total) 275 | if stats > 0 or fail > 0: 276 | print "Failed unexpectedly: %d (%3.2f%%)" % \ 277 | (fail, 100.0 * fail / total) 278 | if stats > 0: 279 | print " Failed as expected: %d (%3.2f%%)" % \ 280 | (failok, 100.0 * failok / total) 281 | if stats > 0 or notimp > 0: 282 | print " Not implemented: %d (%3.2f%%)" % \ 283 | (notimp, 100.0 * notimp / total) 284 | 285 | return fail + notimp 286 | 287 | 288 | 289 | if __name__ == "__main__": 290 | main() 291 | 292 | -------------------------------------------------------------------------------- /bid/inventoryServer.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Copyright (c) 2001, actzero, inc. 3 | import sys 4 | sys.path.insert(1,"..") 5 | from SOAPpy import SOAP 6 | #SOAP.Config.debug = 1 7 | serverstring = "SOAP.py (actzero.com) running "+sys.platform 8 | NUMBUYS = 0 9 | NUMSIMPLEBUYS = 0 10 | NUMREQUESTS = 0 11 | NUMPINGS = 0 12 | 13 | def SimpleBuy(Address, ProductName, Quantity): 14 | # currently, this type-checks the params, and makes sure 15 | # the strings are of len > 0 16 | global NUMSIMPLEBUYS 17 | NUMSIMPLEBUYS += 1 18 | if Quantity < 1: raise ValueError, "must order at least one" 19 | else: return "Receipt for %d %s(s) bought from %s" % (int(Quantity), ProductName, serverstring) 20 | 21 | 22 | def RequestForQuote(ProductName, Quantity): 23 | # type-checks and makes sure Quantity >= 1 24 | global NUMREQUESTS 25 | NUMREQUESTS += 1 26 | if Quantity < 1: raise ValueError, "must order at least 1" 27 | else: 28 | import whrandom 29 | mult = whrandom.random() 30 | times = 0 31 | while mult > 0.25: 32 | mult = mult - 0.25 33 | times += 1 34 | mult += 0.5 35 | mult = round(mult, 3) 36 | print mult, times 37 | return SOAP.doubleType(round(mult*int(Quantity),2)) 38 | 39 | 40 | def Buy(**kw): 41 | 42 | global NUMBUYS 43 | NUMBUYS += 1 44 | try: 45 | PurchaseOrder = kw["PurchaseOrder"] 46 | except: 47 | PurchaseOrder = kw["PO"] 48 | try: 49 | POkeys = PurchaseOrder['_keyord'] 50 | POkeys.sort() 51 | POkeys_expected = ["shipTo","billTo","items","poID","createDate"] 52 | POkeys_expected.sort() 53 | if POkeys != POkeys_expected: 54 | raise ValueError, "struct 'PurchaseOrder' needs %s, %s, %s, %s, and %s" % tuple(POkeys_expected) 55 | except: 56 | raise TypeError, "'PurchaseOrder' missing one or more element(s)" 57 | 58 | try: 59 | btkeys = PurchaseOrder["billTo"]["_keyord"] 60 | btkeys.sort() 61 | btkeys_expected = ["address","zipCode","name","state","city"] 62 | btkeys_expected.sort() 63 | except: 64 | raise TypeError, "'billTo' missing one or more elements" 65 | 66 | try: 67 | stkeys = PurchaseOrder["shipTo"]["_keyord"] 68 | stkeys.sort() 69 | stkeys_expected = ["address","zipCode","name","state","city"] 70 | stkeys_expected.sort() 71 | except: 72 | raise TypeError, "'shipTo' missing one or more elements" 73 | 74 | 75 | try: 76 | items = PurchaseOrder["items"].__dict__ 77 | data = items["data"] 78 | retstring = "" 79 | for item in data: 80 | itemdict = item["_asdict"] 81 | q = itemdict["quantity"] 82 | p = itemdict["price"] 83 | name = itemdict["name"] 84 | if retstring != "": 85 | retstring += ", " 86 | else: 87 | retstring = "bought " 88 | retstring += "%d %s(s) for %.2f" % (q,name,p) 89 | retstring += " from "+serverstring 90 | return retstring 91 | 92 | except: 93 | raise TypeError, "items must be an array of 'item' structs" 94 | 95 | def Ping(): 96 | global NUMPINGS 97 | NUMPINGS += 1 98 | return 99 | 100 | def Monitor(str): 101 | if str=="actzero": 102 | global NUMBUYS 103 | global NUMREQUESTS 104 | global NUMSIMPLEBUYS 105 | global NUMPINGS 106 | return "(Buys, RequestForQuote(s),SimpleBuy(s), Ping(s)) = " + \ 107 | repr( (NUMBUYS,NUMREQUESTS,NUMSIMPLEBUYS, NUMPINGS) ) 108 | else: 109 | raise ValueError, "not the right string" 110 | 111 | def Clear(str): 112 | if str=="actzero": 113 | global NUMBUYS 114 | global NUMREQUESTS 115 | global NUMSIMPLEBUYS 116 | global NUMPINGS 117 | NUMBUYS = 0 118 | NUMREQUESTS = 0 119 | NUMSIMPLEBUYS = 0 120 | NUMPINGS = 0 121 | return "(Buys, RequestForQuote(s),SimpleBuy(s), Ping(s)) = " + \ 122 | repr( (NUMBUYS,NUMREQUESTS,NUMSIMPLEBUYS, NUMPINGS) ) 123 | else: 124 | raise ValueError, "not the right string" 125 | 126 | 127 | if __name__ == "__main__": 128 | if len(sys.argv) > 1: 129 | try: 130 | port = int(sys.argv[1]) 131 | if port not in range(2000,15000): raise ValueError 132 | except: 133 | print "port must be a number between 2000 and 15000" 134 | sys.exit(1) 135 | else: port = 9000 136 | namespace = "http://www.soapinterop.org/Bid" 137 | server = SOAP.SOAPServer( ('zoo',port) ) 138 | 139 | server.registerKWFunction(SimpleBuy, namespace ) 140 | server.registerKWFunction(RequestForQuote, namespace ) 141 | server.registerKWFunction(Buy, namespace ) 142 | server.registerKWFunction(Ping, namespace ) 143 | server.registerKWFunction(Monitor, namespace ) 144 | server.registerKWFunction(Clear, namespace ) 145 | 146 | try: 147 | server.serve_forever() 148 | except KeyboardInterrupt: 149 | pass 150 | -------------------------------------------------------------------------------- /bid/monitorClient.py: -------------------------------------------------------------------------------- 1 | from SOAPpy import SOAP 2 | import sys 3 | import getopt 4 | 5 | 6 | def usage(): 7 | print """usage: %s [options] 8 | -m, --method=METHOD#[,METHOD#...] specify METHOD# of ? for the list 9 | -p, --port=PORT# allows to specify PORT# of server 10 | """ 11 | sys.exit(1) 12 | 13 | def methodUsage(): 14 | print "The available methods are:" 15 | print "1. Monitor \t\t2. Clear" 16 | sys.exit(0) 17 | 18 | 19 | port = 12080 20 | methodnum = 1 21 | 22 | try: 23 | opts, args = getopt.getopt (sys.argv[1:], 'p:m:', ['method','port']) 24 | for opt, arg in opts: 25 | if opt in ('-m','--method'): 26 | if arg == '?': 27 | methodUsage() 28 | methodnum = int(arg) 29 | elif opt in ('-p', '--port'): 30 | port = int(arg) 31 | else: 32 | raise AttributeError, "Recognized but unimpl option '%s'" % opt 33 | except SystemExit: 34 | raise 35 | except: 36 | usage () 37 | 38 | ep = "http://208.177.157.221:%d/xmethodsInterop" % (port) 39 | sa = "urn:soapinterop" 40 | ns = "http://www.soapinterop.org/Bid" 41 | 42 | serv = SOAP.SOAPProxy(ep, namespace =ns, soapaction = sa) 43 | if methodnum == 1: 44 | print serv.Monitor(str="actzero") 45 | elif methodnum == 2: 46 | print serv.Clear(str="actzero") 47 | else: 48 | print "invalid methodnum" 49 | methodUsage() 50 | 51 | -------------------------------------------------------------------------------- /contrib/.cvsignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | -------------------------------------------------------------------------------- /contrib/soap_cli.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import time 4 | from SOAPpy import SOAP 5 | 6 | srv = SOAP.SOAPProxy('http://localhost:10080/') 7 | 8 | for p in ('good param', 'ok param'): 9 | ret = srv.badparam(p) 10 | if isinstance(ret, SOAP.faultType): 11 | print ret 12 | else: 13 | print 'ok' 14 | 15 | dt = SOAP.dateTimeType(time.localtime(time.time())) 16 | print srv.dt(dt) 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /contrib/soap_handler.py: -------------------------------------------------------------------------------- 1 | 2 | import http_server 3 | from SOAPpy.SOAP import * 4 | Fault = faultType 5 | import string, sys 6 | 7 | Config = SOAPConfig(debug=1) 8 | 9 | class soap_handler: 10 | def __init__(self, encoding='UTF-8', config=Config, namespace=None): 11 | self.namespace = namespace 12 | self.objmap = {} 13 | self.funcmap = {} 14 | self.config = config 15 | self.encoding = encoding 16 | 17 | def match (self, request): 18 | return 1 19 | 20 | def handle_request (self, request): 21 | [path, params, query, fragment] = request.split_uri() 22 | if request.command == 'post': 23 | request.collector = collector(self, request) 24 | else: 25 | request.error(400) 26 | 27 | def continue_request(self, data, request): 28 | # Everthing that follows is cripped from do_POST(). 29 | if self.config.debug: 30 | print "\n***RECEIVING***\n", data, "*" * 13 + "\n" 31 | sys.stdout.flush() 32 | 33 | try: 34 | r, header, body = parseSOAPRPC(data, header=1, body=1) 35 | 36 | method = r._name 37 | args = r._aslist 38 | kw = r._asdict 39 | 40 | ns = r._ns 41 | resp = "" 42 | # For faults messages 43 | if ns: 44 | nsmethod = "%s:%s" % (ns, method) 45 | else: 46 | nsmethod = method 47 | 48 | try: 49 | # First look for registered functions 50 | if self.funcmap.has_key(ns) and \ 51 | self.funcmap[ns].has_key(method): 52 | f = self.funcmap[ns][method] 53 | else: # Now look at registered objects 54 | # Check for nested attributes 55 | if method.find(".") != -1: 56 | t = self.objmap[ns] 57 | l = method.split(".") 58 | for i in l: 59 | t = getattr(t,i) 60 | f = t 61 | else: 62 | f = getattr(self.objmap[ns], method) 63 | except: 64 | if self.config.debug: 65 | import traceback 66 | traceback.print_exc () 67 | 68 | resp = buildSOAP(Fault("%s:Client" % NS.ENV_T, 69 | "No method %s found" % nsmethod, 70 | "%s %s" % tuple(sys.exc_info()[0:2])), 71 | encoding = self.encoding, config = self.config) 72 | status = 500 73 | else: 74 | try: 75 | # If it's wrapped to indicate it takes keywords 76 | # send it keywords 77 | if header: 78 | x = HeaderHandler(header) 79 | 80 | if isinstance(f,MethodSig): 81 | c = None 82 | if f.context: # Build context object 83 | c = SOAPContext(header, body, d, self.connection, self.headers, 84 | self.headers["soapaction"]) 85 | 86 | if f.keywords: 87 | tkw = {} 88 | # This is lame, but have to de-unicode keywords 89 | for (k,v) in kw.items(): 90 | tkw[str(k)] = v 91 | if c: 92 | tkw["_SOAPContext"] = c 93 | fr = apply(f,(),tkw) 94 | else: 95 | if c: 96 | fr = apply(f,args,{'_SOAPContext':c}) 97 | else: 98 | fr = apply(f,args,{}) 99 | else: 100 | fr = apply(f,args,{}) 101 | if type(fr) == type(self) and isinstance(fr, voidType): 102 | resp = buildSOAP(kw = {'%sResponse' % method:fr}, 103 | encoding = self.encoding, 104 | config = self.config) 105 | else: 106 | resp = buildSOAP(kw = 107 | {'%sResponse' % method:{'Result':fr}}, 108 | encoding = self.encoding, 109 | config = self.config) 110 | except Fault, e: 111 | resp = buildSOAP(e, config = self.config) 112 | status = 500 113 | except: 114 | if self.config.debug: 115 | import traceback 116 | traceback.print_exc () 117 | 118 | resp = buildSOAP(Fault("%s:Server" % NS.ENV_T, \ 119 | "Method %s failed." % nsmethod, 120 | "%s %s" % tuple(sys.exc_info()[0:2])), 121 | encoding = self.encoding, 122 | config = self.config) 123 | status = 500 124 | else: 125 | status = 200 126 | except Fault,e: 127 | resp = buildSOAP(e, encoding = self.encoding, 128 | config = self.config) 129 | status = 500 130 | except: 131 | # internal error, report as HTTP server error 132 | if self.config.debug: 133 | import traceback 134 | traceback.print_exc () 135 | request.error(500) 136 | #self.send_response(500) 137 | #self.end_headers() 138 | else: 139 | request['Content-Type'] = 'text/xml; charset="%s"' % self.encoding 140 | request.push(resp) 141 | request.done() 142 | # got a valid SOAP response 143 | #self.send_response(status) 144 | #self.send_header("Content-type", 145 | # 'text/xml; charset="%s"' % self.encoding) 146 | #self.send_header("Content-length", str(len(resp))) 147 | #self.end_headers() 148 | 149 | if self.config.debug: 150 | print "\n***SENDING***\n", resp, "*" * 13 + "\n" 151 | sys.stdout.flush() 152 | 153 | """ 154 | # We should be able to shut down both a regular and an SSL 155 | # connection, but under Python 2.1, calling shutdown on an 156 | # SSL connections drops the output, so this work-around. 157 | # This should be investigated more someday. 158 | 159 | if self.config.SSLserver and \ 160 | isinstance(self.connection, SSL.Connection): 161 | self.connection.set_shutdown(SSL.SSL_SENT_SHUTDOWN | 162 | SSL.SSL_RECEIVED_SHUTDOWN) 163 | else: 164 | self.connection.shutdown(1) 165 | """ 166 | 167 | def registerObject(self, object, namespace = ''): 168 | if namespace == '': namespace = self.namespace 169 | self.objmap[namespace] = object 170 | 171 | def registerFunction(self, function, namespace = '', funcName = None): 172 | if not funcName : funcName = function.__name__ 173 | if namespace == '': namespace = self.namespace 174 | if self.funcmap.has_key(namespace): 175 | self.funcmap[namespace][funcName] = function 176 | else: 177 | self.funcmap[namespace] = {funcName : function} 178 | 179 | 180 | 181 | class collector: 182 | "gathers input for POST and PUT requests" 183 | 184 | def __init__ (self, handler, request): 185 | 186 | self.handler = handler 187 | self.request = request 188 | self.data = '' 189 | 190 | # make sure there's a content-length header 191 | cl = request.get_header ('content-length') 192 | 193 | if not cl: 194 | request.error (411) 195 | else: 196 | cl = string.atoi (cl) 197 | # using a 'numeric' terminator 198 | self.request.channel.set_terminator (cl) 199 | 200 | def collect_incoming_data (self, data): 201 | self.data = self.data + data 202 | 203 | def found_terminator (self): 204 | # set the terminator back to the default 205 | self.request.channel.set_terminator ('\r\n\r\n') 206 | self.handler.continue_request (self.data, self.request) 207 | 208 | 209 | if __name__ == '__main__': 210 | 211 | import asyncore 212 | import http_server 213 | 214 | class Thing: 215 | 216 | def badparam(self, param): 217 | if param == 'good param': 218 | return 1 219 | else: 220 | return Fault(faultstring='bad param') 221 | 222 | def dt(self, aDateTime): 223 | return aDateTime 224 | 225 | thing = Thing() 226 | soaph = soap_handler() 227 | soaph.registerObject(thing) 228 | 229 | hs = http_server.http_server('', 10080) 230 | hs.install_handler(soaph) 231 | 232 | asyncore.loop() 233 | 234 | -------------------------------------------------------------------------------- /docs/GettingStarted.txt: -------------------------------------------------------------------------------- 1 | 2 | Getting Started 3 | =============== 4 | 5 | NEW: 6 | 7 | Mark Pilgrims' online book _Dive Into Python_ at 8 | http://diveintopython.org includes a nice tutorial for SOAPpy in 9 | Chapter 12. "SOAP Web Services" at 10 | http://diveintopython.org/soap_web_services. 11 | 12 | 13 | 14 | The easiest way to get up to speed is to run and read the scripts in the 15 | tests directory. Better documentation is coming. 16 | 17 | Here are some examples of how to use SOAPpy: 18 | 19 | 20 | CLIENT EXAMPLES: 21 | 22 | ## CODE 23 | from SOAPpy import SOAPProxy 24 | server = SOAPProxy("http://localhost:8080/") 25 | print server.echo("Hello world") 26 | ## /CODE 27 | 28 | This opens a connection to the server listening on localhost:8080, calls the 29 | method echo with the ordered parameter of "Hello World", and prints the 30 | results. 31 | 32 | 33 | ## CODE 34 | from SOAPpy import SOAPProxy 35 | server = SOAPProxy("https://localhost:8443/") 36 | print server.echo("Hello world") 37 | ## /CODE 38 | 39 | This opens a secure connection to the SSL server listening on 40 | localhost:8443, calls the method echo with the ordered parameter of 41 | "Hello World" and prints the results. Python must be built with OpenSSL. 42 | 43 | 44 | ## CODE 45 | from SOAPpy import SOAPProxy 46 | server = SOAPProxy("http://services.xmethods.com/soap", 47 | namespace = "urn:xmethods-delayed-quotes") 48 | print server.getQuote(symbol = "IBM") 49 | ## /CODE 50 | 51 | This calls method getQuote that is in the namespace URI of 52 | urn:xmethods-delayed-quotes on server services.xmethods.com. getQuote is 53 | passed a named parameter, symbol. 54 | 55 | 56 | ## CODE 57 | from SOAPpy import SOAPProxy 58 | server = SOAPProxy("http://services.xmethods.com/soap") 59 | 60 | print server._ns("urn:xmethods-delayed-quotes").getQuote(symbol = "IBM") 61 | ## /CODE 62 | 63 | This does the same thing as the previous example, however namespace is 64 | specified inline on a per call basis rather than at the server level. 65 | 66 | 67 | ## CODE 68 | from SOAPpy import SOAPProxy 69 | server = SOAPProxy("http://services.xmethods.com/soap", 70 | soapaction = "http://somesite.com/myaction") 71 | 72 | print server._ns("urn:xmethods-delayed-quotes").getQuote(symbol = "IBM") 73 | ## /CODE 74 | 75 | This is the same quote call with a soapaction specified. 76 | 77 | 78 | ## CODE 79 | from SOAPpy import SOAPProxy 80 | server = SOAPProxy("http://services.xmethods.com:80/soap") 81 | 82 | ns = "urn:xmethods-delayed-quotes") 83 | sa = "http://somesite.com/myaction" 84 | my_call = server._ns(ns)._sa(sa) 85 | my_call.getQuote(symbol = "IBM") 86 | my_call.getQuote(symbol = "IBM") 87 | my_call.getQuote(symbol = "IBM") 88 | ## /CODE 89 | 90 | The same example, this time with both the soapaction and the namespace 91 | specified inline and saved in a local variable for getQuote to be called 92 | against. 93 | 94 | ** What SOAPpy does with the results of a call could seem surprising. If 95 | there is only one element in the structType that has the return value and 96 | unwrap_results is turned on (the default) it will bubble up the single 97 | attribute, otherwise it will return you a structType object with all of the 98 | attributes. 99 | 100 | 101 | 102 | SERVER EXAMPLES: 103 | 104 | ## CODE 105 | from SOAPpy import SOAPServer 106 | def echo(s): 107 | return s + s # repeats a string twice 108 | 109 | server = SOAPServer(("localhost", 8080)) 110 | server.registerFunction(echo) 111 | server.serve_forever() 112 | ## /CODE 113 | 114 | This exposes the function echo (that takes an unnamed arguement) on a server 115 | running on localhost:8080. 116 | 117 | 118 | ## CODE 119 | from SOAPpy import SOAPServer 120 | def echo(s): 121 | return s + s # repeats a string twice 122 | 123 | server = SOAPServer() 124 | server.registerFunction(echo, "echo-space") 125 | server.serve_forever() 126 | ## /CODE 127 | 128 | The same as above, but this time the method is available in the namespace 129 | "echo-space". 130 | 131 | 132 | ## CODE 133 | from SOAPpy import SOAPServer 134 | 135 | class echoBuilder: 136 | def echo(self, val): 137 | return val + val 138 | 139 | server = SOAPServer() 140 | e = echoBuilder() 141 | server.registerObject(e) 142 | server.serve_forever() 143 | ## /CODE 144 | 145 | This registers the whole instance of the object echoBuilder, e. Every 146 | method of the instance is exposed on the server. 147 | 148 | 149 | ## CODE 150 | from SOAPpy import SOAPServer 151 | 152 | def echo(**kw): 153 | return kw['first'] + kw['second'] + kw['third'] 154 | 155 | server = SOAPServer() 156 | server.registerKWFunction(echo) 157 | server.serve_forever() 158 | ## /CODE 159 | 160 | This time the method echo is exposed and it expects named arguments. The 161 | main thing to notice here is the use of the method registerKWFunction over 162 | registerFunction. 163 | 164 | 165 | ## CODE 166 | from SOAPpy import SOAPServer 167 | 168 | from M2Crypto import SSL 169 | 170 | def echo(s): 171 | return s+s # repeats a string twice 172 | 173 | ssl_context = SSL.Context() 174 | ssl_context.load_cert('server.pem') 175 | 176 | server = SOAPServer(("localhost",8443), ssl_context = ssl_context) 177 | server.registerFunction(echo) 178 | server.serve_forever() 179 | ## /CODE 180 | 181 | This exposes the function echo (taking an unnamed arguement) on a server 182 | accepting SSL connections at localhost:8443. Ng Pheng Siong's M2Crypto 183 | package (available at ) must be 184 | installed. Also see tests/silabserver.py. 185 | 186 | $Id: GettingStarted.txt,v 1.4 2005/02/21 20:09:29 warnes Exp $ 187 | -------------------------------------------------------------------------------- /docs/GlobusSupport.txt: -------------------------------------------------------------------------------- 1 | 2 | Globus Support 3 | ============== 4 | 5 | Extensions have been added to the SOAPpy module to allow the use of the 6 | Globus Toolkit v2 for secure transport of SOAP calls. These extensions are 7 | possible by using the Globus Toolkit (http://www.globus.org) and the 8 | pyGlobus software (http://www-itg.lbl.gov/gtg/projects/pyGlobus/), which 9 | exposes the Globus Toolkit via a set of Python interfaces. This enables 10 | bi-directional PKI authentication so that the server and client are both 11 | guaranteed of the identity of the other. Using PKI this way also allows a 12 | more robust authorization solution above the SOAP hosting layer, which 13 | provides better application level authorization control. These tools are 14 | used by the Access Grid Project (http://www.accessgrid.org) to build a 15 | Grid-based, Web Services based, real-time collaboration environment. 16 | 17 | In order to use the SOAPpy module with the Globus Toolkit, you must first 18 | obtain and install the Globus Toolkit and pyGlobus software. Information on 19 | how to do that is at the respective web sites listed below. In order to use 20 | the Globus Toolkit it is necessary to have an x509 identity certificate. 21 | Information on how to obtain one of those is available on the web as well. 22 | 23 | To use GSI with an authorization method, set the SOAPConfig.authMethod = 24 | "methodname". You must have this method defined on any objects you register 25 | with SOAPpy, and/or as a registered method. It should return 0 or 1 to 26 | indicate if authorization is allowed or not. 27 | 28 | Once the software is installed, you have obtained your certificate, and the 29 | SOAPpy module is installed, the following code shows how to run a GSI 30 | secured SOAP server (These snippets are directly from the echoServer.py and 31 | echoClient.py in the test directory). 32 | 33 | Server 34 | ------ 35 | 36 | def _authorize(self, *args, **kw): 37 | return 1 38 | 39 | Config.authMethod = "_authorize" 40 | 41 | addr = ('localhost', 9900) 42 | from SOAPpy.GSIServer import GSISOAPServer 43 | server = GSISOAPServer(addr) 44 | 45 | server.registerFunction(_authorize) 46 | server.registerFunction(echo) 47 | 48 | Then you use the server like the SSL server or the standard server. 49 | 50 | Client 51 | ------ 52 | 53 | import pyGlobus 54 | 55 | # The httpg distinguishes this as a GSI TCP connection, so after 56 | # this you can use the SOAP proxy as you would any other SOAP Proxy. 57 | 58 | server = SOAPProxy("httpg://localhost:9900/") 59 | print server.echo("moo") 60 | 61 | 62 | 63 | Globus Toolkit http://www.globus.org 64 | ------------------------------------ 65 | 66 | The Globus Toolkit is an open source software toolkit used for 67 | building grids. It is being developed by the Globus Alliance and 68 | many others all over the world. A growing number of projects and 69 | companies are using the Globus Toolkit to unlock the potential 70 | of grids for their cause. 71 | 72 | PyGlobus http://www-itg.lbl.gov/gtg/projects/pyGlobus/ 73 | ------------------------------------------------------ 74 | 75 | The goal of this project is to allow the use of the entire 76 | Globus toolkit from Python, a high-level scripting 77 | language. SWIG is used to generate the necessary interface 78 | code. Currently a substantial subset of the 2.2.4 and 2.4 79 | versions of the Globus toolkit has been wrapped. 80 | 81 | The Access Grid http://www.accessgrid.org/ 82 | ------------------------------------------ 83 | 84 | The Access GridT is an ensemble of resources including 85 | multimedia large-format displays, presentation and interactive 86 | environments, and interfaces to Grid middleware and to 87 | visualization environments. These resources are used to support 88 | group-to-group interactions across the Grid. For example, the 89 | Access Grid (AG) is used for large-scale distributed meetings, 90 | collaborative work sessions, seminars, lectures, tutorials, and 91 | training. The Access Grid thus differs from desktop-to-desktop 92 | tools that focus on individual communication. 93 | 94 | - Submitted 2004-01-08 by Ivan R. Judson 95 | 96 | 97 | $Id: GlobusSupport.txt,v 1.3 2005/02/21 20:09:32 warnes Exp $ 98 | -------------------------------------------------------------------------------- /docs/MethodParameterNaming.txt: -------------------------------------------------------------------------------- 1 | 2 | Experimental method for handing ordered vs named method parameters 3 | ------------------------------------------------------------------ 4 | 5 | There is an incompatibility with the way that Python and SOAP handle 6 | method arguments: SOAP requires that all arguments have names and that 7 | they are presented in the same order as the method signature. Python 8 | (like other scripting languages, notably the S language) has the 9 | concept of unnamed arguments. Further Python does not preserve the 10 | order of named arguments, since they are handled using the dictionary 11 | data type. It seems to me that this makes it impossible to fully meet 12 | the SOAP specification without significant modifications to the Python 13 | method of handling named arguments or to the Python dictionary class. 14 | 15 | Historically SOAPpy has attempted to work around this issue by 16 | handling all arguments as unnamed unless the method or function was 17 | explicitly flagged, in which case all arguments were considered named. 18 | This has resulted in a several problems, particularly for a SOAPpy 19 | client communicating with a SOAPpy server. First, when named 20 | arguments were used in call to a non-flagged function, the argument 21 | would silently be reordered by the sender (since they were stored 22 | using a Python dictionary), *and* the names would be ignored by the 23 | receiver, which assumed that the parameters were unnamed and only the 24 | order was significant. This results in incorrect argument matching. 25 | This problem also occurred with mixed named and unnamed arguments. 26 | 27 | For my primary SOAP application, it is not reasonable to flag all of 28 | the SOAPpy methods as requiring named arguments, for a variety of 29 | reasons. One reason is that the available methods are not known 30 | apriori by the client software, hence the names of the arguments are 31 | not known. Second, many of the methods provide a large number of 32 | optional arguments, making it impractical to specify them all. 33 | 34 | In an attempt to overcome this problem, I implemented an experimental 35 | and non-standard method of handling named and unnamed arguments. This 36 | mechanism is enabled in SOAPpy by setting 37 | SOAPpy.SOAP.Config.specialArgs=1, and disabled by setting 38 | SOAPpy.SOAP.Config.specialArgs=0. 39 | 40 | When enabled, parameters with names of the form v#### (i.e., matching 41 | the regexp "^v[0-9]+$") are assumed to be unnamed parameters and are 42 | passed to the method in numeric order. All other parameters are 43 | assumed to be named and are passed using the name. Outgoing SOAP 44 | method calls now always generate names in this way--whether or not 45 | specialArgs is enabled. 46 | 47 | 48 | I selected the form v#### because it is a valid XML name, but is 49 | unlikely to be used as a parameter name. 50 | 51 | [As it turns out, this choice was fortitous because Apache's SOAP tool 52 | uses the same system.] 53 | 54 | In my testing, this mechanism for handling method parameter names 55 | works fine between a SOAPpy client and a SOAPpy server, and resolves 56 | the parameter reordering problems I was experiencing. This system 57 | seems unlikely to have any negative side effects on other SOAP 58 | applications, except in the (hopefully) rare case when v#### might be 59 | used as an actual parameter name. 60 | 61 | **In version 0.9.9-pre1, this feature is enabled by default.** Please 62 | let me know if there are situations where this causes problems. 63 | 64 | Note that this mechanism is only a partial solution, since it is still 65 | impossible to return named parameters in a specified order using 66 | SOAPpy. SOAP applications or implementations which require this 67 | feature are simply not compatible with SOAPpy. 68 | 69 | -Greg Warnes 70 | 2003-03-07 (updated 2003-11-14) 71 | 72 | -------------------------------------------------------------------------------- /docs/UsingHeaders.txt: -------------------------------------------------------------------------------- 1 | Using Headers 2 | ============= 3 | 4 | SOAPpy has a Header class to hold data for the header of a SOAP message. 5 | Each Header instance has methods to set/get the MustUnderstand attribute, and 6 | methods to set/get the Actor attribute. 7 | 8 | SOAPpy also has a SOAPContext class so that each server method can be 9 | implemented in such a way that it gets the context of the connecting client. 10 | This includes both common SOAP information and connection information (see 11 | below for an example). 12 | 13 | CLIENT EXAMPLES 14 | --------------- 15 | 16 | ## CODE 17 | import SOAPpy 18 | test = 42 19 | server = SOAPpy.SOAPProxy("http://localhost:8888") 20 | server = server._sa ("urn:soapinterop") 21 | 22 | hd = SOAPpy.Header() 23 | hd.InteropTestHeader ='This should fault, as you don\'t understand the header.' 24 | hd._setMustUnderstand ('InteropTestHeader', 0) 25 | hd._setActor ('InteropTestHeader','http://schemas.xmlsoap.org/soap/actor/next') 26 | server = server._hd (hd) 27 | 28 | print server.echoInteger (test) 29 | ## /CODE 30 | 31 | This should succeed (provided the server has defined echoInteger), as it 32 | builds a valid header into this client with MustUnderstand set to 0 33 | and then sends the SOAP with this header. 34 | 35 | 36 | ## CODE 37 | import SOAPpy 38 | test = 42 39 | server = SOAPpy.SOAPProxy("http://localhost:8888") 40 | server = server._sa ("urn:soapinterop") 41 | #Header 42 | hd = SOAPpy.Header() 43 | hd.InteropTestHeader = 'This should fault,as you don\'t understand the header.' 44 | hd._setMustUnderstand ('InteropTestHeader', 1) 45 | hd._setActor ('InteropTestHeader','http://schemas.xmlsoap.org/soap/actor/next') 46 | server = server._hd (hd) 47 | 48 | print server.echoInteger (test) 49 | ## /CODE 50 | 51 | This should fail (even if the server has defined 'echoInteger'), as it 52 | builds a valid header into this client, but sets MustUnderstand to 1 53 | for a message that the server presumably won't understand before sending. 54 | 55 | 56 | 57 | 58 | SERVER EXAMPLES 59 | --------------- 60 | 61 | ## CODE 62 | import SOAPpy 63 | def echoInteger (inputInteger): 64 | return inputInteger 65 | server = SOAPpy.SOAPServer ( ('localhost', 8080) ) 66 | server.registerFunction (echoInteger) 67 | server.serve_forever() 68 | ## /CODE 69 | 70 | This is a simple server designed to work with the first 2 clients above. 71 | 72 | 73 | ## CODE 74 | import SOAPpy 75 | def echoInteger (inputInteger, _SOAPContext): 76 | c = _SOAPContext 77 | print c.xmldata 78 | print c.header 79 | print c.body 80 | print c.connection.getpeername() 81 | print c.soapaction 82 | print c.httpheaders 83 | return inputInteger 84 | 85 | host = 'localhost' 86 | port = 8888 87 | 88 | server = SOAPpy.SOAPServer ( (host, port) ) 89 | server.registerFunction (SOAPpy.MethodSig(echoInteger, keywords=0,context=1)) 90 | 91 | server.serve_forever() 92 | ## /CODE 93 | 94 | This is a server which shows off the SOAPContext feature. This 95 | server gets a context from the client that has connected to it, and 96 | prints some of the pertinent aspects of that client before 97 | returning. This server should also work with the code for the two 98 | clients written above. 99 | 100 | 101 | 102 | 103 | 104 | $Id: UsingHeaders.txt,v 1.1 2005/02/18 15:36:12 warnes Exp $ 105 | -------------------------------------------------------------------------------- /docs/WSDL.txt: -------------------------------------------------------------------------------- 1 | 2 | WSDL NOTES: 3 | 4 | Release 0.9.9 and later include logic for dealing with web service 5 | description language (WSDL) files. 6 | 7 | - SOAPpy.WSDL provides a SOAP Proxy object that parses a WSDL file 8 | and provides access to the listed services: 9 | 10 | url = 'http://www.xmethods.org/sd/2001/TemperatureService.wsdl' 11 | zip = '01072' 12 | proxy = SOAPpy.WSDL.Proxy(url) 13 | temp = proxy.getTemp(zip) 14 | print 'Temperature at', zip, 'is', temp 15 | 16 | - On the server, you can allow the client to download the WSDL for 17 | a service by sending a request of the form by adding a do_GET 18 | method to the SOAPRequestHandler. [Not yet working when 19 | debug=FALSE. Add example here when working] 20 | 21 | 22 | $Id: WSDL.txt,v 1.2 2005/02/21 20:09:34 warnes Exp $ 23 | -------------------------------------------------------------------------------- /docs/attrs.txt: -------------------------------------------------------------------------------- 1 | 2 | Using SOAPpy Attributes 3 | ======================= 4 | 5 | All SOAPpy data classes implement methods to access and mutate 6 | individual attributes. 7 | 8 | The _setAttr method has as parameters a 'tag', the attribute name, and the 9 | value to which the attribute should be set. 10 | 11 | The _getAttrs method simply has the 'tag' parameter. 12 | 13 | 14 | 15 | $Id: attrs.txt,v 1.2 2005/02/18 15:40:46 warnes Exp $ 16 | -------------------------------------------------------------------------------- /docs/complexTypes.txt: -------------------------------------------------------------------------------- 1 | COMPLEX TYPES HOWTO 2 | =================== 3 | 4 | The easiest way (at the moment) to create complex SOAP typs is to 5 | use the SOAPpy.structType class, which allows you to create an 6 | object with named arguments of arbitraty types. For example: 7 | 8 | >>> in0 = SOAPpy.structType() 9 | >>> in0._addItem('outwardDate', dep) 10 | >>> in0._addItem('returnDate', ret) 11 | >>> in0._addItem('originAirport', 'den') 12 | >>> in0._addItem('destinationAirport', 'iad') 13 | 14 | SOAPpy has code for declaring structured object templates including 15 | the type for each component, but this broke sometime in the past and 16 | has not yet been corrected. (See tests/TCtypes.py to see how it 17 | should work.) 18 | 19 | 20 | -------------------------------------------------------------------------------- /docs/simpleTypes.txt: -------------------------------------------------------------------------------- 1 | Simple Types HOWTO 2 | ================== 3 | 4 | The easiest way to understand use of data types is look at and run the examples 5 | already written (in tests/, validate/ and bid/) , and to write your own 6 | clients, looking at the xml as it is sent (by setting SOAP.Config.debug=1). 7 | 8 | As far as the built-in types are concerned, SOAP.py will preserve type 9 | as expected. That is: python integer will be of type integer, and 10 | equivalently for string and float. To access more than just these types, 11 | there are classes in SOAP.py. These allow invoking a certain type by making 12 | an instance of the corresponding class. 13 | 14 | The SOAPBuilder in SOAP.py will automatically convert python lists to Arrays 15 | and python dictionaries to Structs- these are two of the most frequently used 16 | data types. 17 | 18 | CLIENT EXAMPLES 19 | --------------- 20 | 21 | ## CODE 22 | import SOAP 23 | server = SOAP.SOAPProxy("http://localhost:8080/") 24 | print server.echo("Hello world") 25 | ## /CODE 26 | 27 | This example (taken from quickstart.txt) sends an ordered parameter of type 28 | string. 29 | 30 | ## CODE 31 | import SOAP 32 | import time 33 | #SOAP.Config.debug = 1 34 | test = time.gmtime (time.time ()) 35 | server = SOAP.SOAPProxy("http://localhost:8080/") 36 | print server.echoDate (inputDate = SOAP.DateTime(test)) 37 | ## /CODE 38 | 39 | This test calls echoDate with the named parameter inputDate, which is a 40 | TimeInstant. It prints the the result. 41 | **Note: The reason that it is a TimeInstant and not a DateTime 42 | is that SOAP.py uses the 1999 schema intead of the 2001 schema. To make it 43 | a DateTime, one would just use SOAP.dateTimeType() in place of SOAP.DateTime(). 44 | ** 45 | 46 | 47 | ## CODE 48 | import SOAP 49 | server = SOAP.SOAPProxy("http://localhost:8080/") 50 | test = [0, 1, -1, 3853] 51 | print server.echoIntegerArray (inputIntegerArray = test) 52 | ## /CODE 53 | 54 | This calls echoIntegerArray with the named parameter inputIntegerArray, which 55 | is a four-member array of type int. It prints the result. 56 | 57 | ## CODE 58 | import SOAP 59 | test = {'varFloat': 2.256, 'varInt': 474, 'varString': 'Utah'} 60 | server = SOAP.SOAPProxy("http://localhost:8080/") 61 | print server.echoStruct (inputStruct = test) 62 | ## /CODE 63 | 64 | This code calls the method echoStruct with the named parameter inputStruct, 65 | which is of type Struct. It then prints the result. 66 | 67 | 68 | ## CODE 69 | import SOAP 70 | item1 = SOAP.Struct( data = {"name":"widget","quantity":200,"price":SOAP.decimalType(45.99), "_typename":"LineItem"}) 71 | items = SOAP.Array ( data = [item1] ) 72 | items._ns = "http://www.soapinterop.org/Bid" 73 | server = SOAP.SOAPProxy("http://localhost:8080") 74 | server = server._sa ("http://www.soapinterop.org/Buy") 75 | server = server._ns ("http://www.soapinterop.org/Bid") 76 | po = SOAP.Struct( data = {"poID":"Order 1234", "createDate": SOAP.dateTimeType(), "items": items} ) 77 | print server.Buy(PurchaseOrder = po) 78 | ## /CODE 79 | 80 | A few new things here. 81 | -First, we are creating an Array, 'items', with components of (made up) type 82 | 'LineItem'. (Notice the use of "_typename" to specify type). 83 | -This code associates a namespace with the Array, rather than use the default. 84 | -SOAP.dateTimeType() is called directly to get a dateTime instead of SOAP.py's 85 | default, 'timeInstant'. 86 | -Note that when creating a Struct or Array, the data must be passed in as a 87 | named 'data' param (as the first param, by order, is 'name'). 88 | -The proxy is instantiated and then the values for its namespace (_ns) and 89 | soapaction (_sa) are assigned. 90 | -This call will work for a server expecting a parameter with the same 91 | components as those in the variable 'po' above. It will work whether the 92 | server has a named param 'PurchaseOrder' or has an unnamed param, but will 93 | not work if the server expects a named param with a name of anything but 94 | 'PurchaseOrder'. 95 | 96 | 97 | SERVER EXAMPLES 98 | --------------- 99 | 100 | ## CODE 101 | import SOAP 102 | def echo(s): 103 | return s + s # repeats a string twice 104 | 105 | server = SOAP.SOAPServer(("localhost", 8080)) 106 | server.registerFunction(echo) 107 | server.serve_forever() 108 | ## /CODE 109 | 110 | This server example, from quickstart.txt, echoes (as type string) the 111 | string that is passed in, s. 112 | 113 | 114 | ## CODE 115 | import SOAP 116 | 117 | def echoDate (inputDate): 118 | return SOAP.DateTime(inputDate) 119 | 120 | server = SOAP.SOAPServer(("localhost", 8080)) 121 | server.registerKWFunction(echoDate ) 122 | server.serve_forever() 123 | ## /CODE 124 | 125 | This code accepts an inputDate and returns the same date, ensuring that it 126 | is of type TimeInstant by returning an instance of DateTime instead of 127 | simply returning the value. 128 | 129 | 130 | ## CODE 131 | import SOAP 132 | def echoIntegerArray (inputIntegerArray): 133 | if type(inputIntegerArray) != type([]) or len(inputIntegerArray) != 4: 134 | for elem in inputIntegerArray: 135 | if type(elem) != type(1): 136 | raise TypeError, "expected 4-member Array of ints" 137 | return inputIntegerArray 138 | server = SOAP.SOAPServer(("localhost", 8080)) 139 | server.registerKWFunction(echoIntegerArray ) 140 | server.serve_forever() 141 | ## /CODE 142 | 143 | This server supports the method echoIntegerArray, requiring the named parameter 144 | inputIntegerArray, which must be a four-member array of type int. 145 | 146 | 147 | ## CODE 148 | import SOAP 149 | 150 | def echoStruct (inputStruct): 151 | myfloat = inputStruct["varFloat"] 152 | mystr = inputStruct["varString"] 153 | myint = inputStruct["varInt"] 154 | return inputStruct 155 | 156 | server = SOAP.SOAPServer(("localhost", 8080)) 157 | server.registerKWFunction(echoStruct ) 158 | server.serve_forever() 159 | ## /CODE 160 | 161 | This code creates a server with a method echoStruct, which requires that the 162 | incoming Struct have elements named varFloat, varString, and varInt. That is, 163 | the server will fault if the incoming Struct does not have any of those 164 | elements. **Note, this server code does NOT require that these be the only 165 | elements in the struct- just that they be present**. This method simply 166 | returns the Struct passed in. 167 | 168 | 169 | ## CODE 170 | import sys 171 | import SOAP 172 | serverstring = "SOAP.py (actzero.com) running "+sys.platform 173 | def Buy(**kw): 174 | try: 175 | PurchaseOrder = kw["PurchaseOrder"] 176 | except: 177 | PurchaseOrder = kw["PO"] 178 | 179 | POkeys = PurchaseOrder['_keyord'] 180 | POkeys.sort() 181 | POkeys_expected = ["items","poID","createDate"] 182 | POkeys_expected.sort() 183 | if POkeys != POkeys_expected: 184 | raise ValueError, "struct 'PurchaseOrder' needs %s, %s, and %s" % tuple(POkeys_expected) 185 | 186 | items = PurchaseOrder["items"].__dict__ 187 | data = items["data"] 188 | retstring = "" 189 | for item in data: 190 | itemdict = item["_asdict"] 191 | q = itemdict["quantity"] 192 | p = itemdict["price"] 193 | name = itemdict["name"] 194 | if retstring != "": 195 | retstring += ", " 196 | else: 197 | retstring = "bought " 198 | retstring += "%d %s(s) for %.2f" % (q,name,p) 199 | retstring += " from "+serverstring 200 | return retstring 201 | 202 | server = SOAP.SOAPServer(("localhost", 8080)) 203 | namespace = "http://www.soapinterop.org/Bid" 204 | server.registerKWFunction(Buy, namespace ) 205 | server.serve_forever() 206 | ## /CODE 207 | 208 | This example creates a server to implement 'Buy', which takes a parameter 209 | named either PurchaseOrder or PO. (Notice the use of **kw as the input 210 | parameter to the method for this functionality). 211 | The server gets the names of the Struct's members by using the '_keyord' 212 | key of the Struct-as-dictionary. It checks these names against what it 213 | expects from the client, and raises a fault if the two are not the same. 214 | By using the __dict__ attribute, the server gets the 'items' (an elemnent of 215 | the PurchaseOrder Struct) as a dictionary. Then it checks that 'items' is 216 | formatted as expected. Finally, it returns a confirmation of what was bought. 217 | 218 | 219 | 220 | $Id: simpleTypes.txt,v 1.2 2005/02/21 20:09:39 warnes Exp $ 221 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # $Id: setup.py,v 1.11 2005/02/15 16:32:22 warnes Exp $ 4 | 5 | CVS=0 6 | 7 | from setuptools import setup, find_packages 8 | import os 9 | 10 | def read(*rnames): 11 | return "\n"+ open( 12 | os.path.join('.', *rnames) 13 | ).read() 14 | url="https://github.com/kiorky/SOAPpy.git" 15 | long_description="SOAPpy provides tools for building SOAP clients and servers. For more information see " + url\ 16 | +'\n'+read('README.rst')\ 17 | +'\n'+read('CHANGES.txt') 18 | setup( 19 | name="SOAPpy", 20 | version='0.12.23.dev0', 21 | description="SOAP Services for Python", 22 | maintainer="Gregory Warnes, kiorky", 23 | maintainer_email="Gregory.R.Warnes@Pfizer.com, freesoftware@makina-corpus.com", 24 | url = url, 25 | long_description=long_description, 26 | packages=find_packages('src'), 27 | package_dir = {'': 'src'}, 28 | include_package_data=True, 29 | install_requires=[ 30 | 'wstools', 31 | 'defusedxml', 32 | ] 33 | ) 34 | 35 | -------------------------------------------------------------------------------- /src/SOAPpy/Config.py: -------------------------------------------------------------------------------- 1 | """ 2 | ################################################################################ 3 | # Copyright (c) 2003, Pfizer 4 | # Copyright (c) 2001, Cayce Ullman. 5 | # Copyright (c) 2001, Brian Matthews. 6 | # 7 | # All rights reserved. 8 | # 9 | # Redistribution and use in source and binary forms, with or without 10 | # modification, are permitted provided that the following conditions are met: 11 | # Redistributions of source code must retain the above copyright notice, this 12 | # list of conditions and the following disclaimer. 13 | # 14 | # Redistributions in binary form must reproduce the above copyright notice, 15 | # this list of conditions and the following disclaimer in the documentation 16 | # and/or other materials provided with the distribution. 17 | # 18 | # Neither the name of actzero, inc. nor the names of its contributors may 19 | # be used to endorse or promote products derived from this software without 20 | # specific prior written permission. 21 | # 22 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 | # ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR 26 | # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 27 | # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 28 | # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 29 | # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 31 | # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | # 33 | ################################################################################ 34 | """ 35 | 36 | ident = '$Id: Config.py 1298 2006-11-07 00:54:15Z sanxiyn $' 37 | from version import __version__ 38 | 39 | import socket 40 | from types import * 41 | 42 | from NS import NS 43 | 44 | ################################################################################ 45 | # Configuration class 46 | ################################################################################ 47 | 48 | 49 | class SOAPConfig: 50 | __readonly = ('SSLserver', 'SSLclient', 'GSIserver', 'GSIclient') 51 | class SSLconfig: 52 | __slots__ = ('key_file', 'cert_file') 53 | key_file = None 54 | cert_file = None 55 | 56 | def __init__(self, config = None, **kw): 57 | d = self.__dict__ 58 | 59 | if config: 60 | if not isinstance(config, SOAPConfig): 61 | raise AttributeError, \ 62 | "initializer must be SOAPConfig instance" 63 | 64 | s = config.__dict__ 65 | 66 | for k, v in s.items(): 67 | if k[0] != '_': 68 | d[k] = v 69 | else: 70 | # Setting debug also sets returnFaultInfo, 71 | # dumpHeadersIn, dumpHeadersOut, dumpSOAPIn, and dumpSOAPOut 72 | self.debug = 0 73 | self.dumpFaultInfo = 1 74 | # Setting namespaceStyle sets typesNamespace, typesNamespaceURI, 75 | # schemaNamespace, and schemaNamespaceURI 76 | self.namespaceStyle = '1999' 77 | self.strictNamespaces = 0 78 | self.typed = 1 79 | self.buildWithNamespacePrefix = 1 80 | self.buildWithGlobalNamespacePrefix = False 81 | self.returnAllAttrs = 0 82 | 83 | # Strict checking of range for floats and doubles 84 | self.strict_range = 0 85 | 86 | # Default encoding for dictionary keys 87 | self.dict_encoding = 'ascii' 88 | 89 | # New argument name handling mechanism. See 90 | # README.MethodParameterNaming for details 91 | self.specialArgs = 1 92 | 93 | # If unwrap_results=1 and there is only element in the struct, 94 | # SOAPProxy will assume that this element is the result 95 | # and return it rather than the struct containing it. 96 | # Otherwise SOAPproxy will return the struct with all the 97 | # elements as attributes. 98 | self.unwrap_results = 1 99 | 100 | # Automatically convert SOAP complex types, and 101 | # (recursively) public contents into the corresponding 102 | # python types. (Private subobjects have names that start 103 | # with '_'.) 104 | # 105 | # Conversions: 106 | # - faultType --> raise python exception 107 | # - arrayType --> array 108 | # - compoundType --> dictionary 109 | # 110 | self.simplify_objects = 0 111 | 112 | # Per-class authorization method. If this is set, before 113 | # calling a any class method, the specified authorization 114 | # method will be called. If it returns 1, the method call 115 | # will proceed, otherwise the call will throw with an 116 | # authorization error. 117 | self.authMethod = None 118 | 119 | # The tuple of type and dump handler function pairs for 120 | # SOAPBuilder dump dispatch. Used for handling additional types 121 | # and overriding built-in types. Functions are expected to have 122 | # the same parameters as SOAPBuilder dump_ methods 123 | # (including self; possibility to call any SOAPBuilder dump method) 124 | self.dumpmap = tuple() 125 | 126 | # Globus Support if pyGlobus.io available 127 | try: 128 | from pyGlobus import io; 129 | d['GSIserver'] = 1 130 | d['GSIclient'] = 1 131 | except: 132 | d['GSIserver'] = 0 133 | d['GSIclient'] = 0 134 | 135 | 136 | # Server SSL support if M2Crypto.SSL available 137 | try: 138 | from M2Crypto import SSL 139 | d['SSLserver'] = 1 140 | except: 141 | d['SSLserver'] = 0 142 | 143 | # Client SSL support if socket.ssl available 144 | try: 145 | from socket import ssl 146 | d['SSLclient'] = 1 147 | except: 148 | d['SSLclient'] = 0 149 | 150 | # Cert support 151 | if d['SSLclient'] or d['SSLserver']: 152 | d['SSL'] = self.SSLconfig() 153 | 154 | dumpmap = kw.pop("dumpmap", None) 155 | if dumpmap: 156 | if not isinstance(dumpmap, tuple): 157 | raise TypeError("Config dumpmap parameter must be a tuple") 158 | self.dumpmap = dumpmap + self.dumpmap 159 | 160 | for k, v in kw.items(): 161 | if k[0] != '_': 162 | setattr(self, k, v) 163 | 164 | def __setattr__(self, name, value): 165 | if name in self.__readonly: 166 | raise AttributeError, "readonly configuration setting" 167 | 168 | d = self.__dict__ 169 | 170 | if name in ('typesNamespace', 'typesNamespaceURI', 171 | 'schemaNamespace', 'schemaNamespaceURI'): 172 | 173 | if name[-3:] == 'URI': 174 | base, uri = name[:-3], 1 175 | else: 176 | base, uri = name, 0 177 | 178 | if type(value) == StringType: 179 | if NS.NSMAP.has_key(value): 180 | n = (value, NS.NSMAP[value]) 181 | elif NS.NSMAP_R.has_key(value): 182 | n = (NS.NSMAP_R[value], value) 183 | else: 184 | raise AttributeError, "unknown namespace" 185 | elif type(value) in (ListType, TupleType): 186 | if uri: 187 | n = (value[1], value[0]) 188 | else: 189 | n = (value[0], value[1]) 190 | else: 191 | raise AttributeError, "unknown namespace type" 192 | 193 | d[base], d[base + 'URI'] = n 194 | 195 | try: 196 | d['namespaceStyle'] = \ 197 | NS.STMAP_R[(d['typesNamespace'], d['schemaNamespace'])] 198 | except: 199 | d['namespaceStyle'] = '' 200 | 201 | elif name == 'namespaceStyle': 202 | value = str(value) 203 | 204 | if not NS.STMAP.has_key(value): 205 | raise AttributeError, "unknown namespace style" 206 | 207 | d[name] = value 208 | n = d['typesNamespace'] = NS.STMAP[value][0] 209 | d['typesNamespaceURI'] = NS.NSMAP[n] 210 | n = d['schemaNamespace'] = NS.STMAP[value][1] 211 | d['schemaNamespaceURI'] = NS.NSMAP[n] 212 | 213 | elif name == 'debug': 214 | d[name] = \ 215 | d['returnFaultInfo'] = \ 216 | d['dumpHeadersIn'] = \ 217 | d['dumpHeadersOut'] = \ 218 | d['dumpSOAPIn'] = \ 219 | d['dumpSOAPOut'] = value 220 | 221 | else: 222 | d[name] = value 223 | 224 | 225 | Config = SOAPConfig() 226 | -------------------------------------------------------------------------------- /src/SOAPpy/Errors.py: -------------------------------------------------------------------------------- 1 | """ 2 | ################################################################################ 3 | # 4 | # SOAPpy - Cayce Ullman (cayce@actzero.com) 5 | # Brian Matthews (blm@actzero.com) 6 | # Gregory Warnes (Gregory.R.Warnes@Pfizer.com) 7 | # Christopher Blunck (blunck@gst.com) 8 | # 9 | ################################################################################ 10 | # Copyright (c) 2003, Pfizer 11 | # Copyright (c) 2001, Cayce Ullman. 12 | # Copyright (c) 2001, Brian Matthews. 13 | # 14 | # All rights reserved. 15 | # 16 | # Redistribution and use in source and binary forms, with or without 17 | # modification, are permitted provided that the following conditions are met: 18 | # Redistributions of source code must retain the above copyright notice, this 19 | # list of conditions and the following disclaimer. 20 | # 21 | # Redistributions in binary form must reproduce the above copyright notice, 22 | # this list of conditions and the following disclaimer in the documentation 23 | # and/or other materials provided with the distribution. 24 | # 25 | # Neither the name of actzero, inc. nor the names of its contributors may 26 | # be used to endorse or promote products derived from this software without 27 | # specific prior written permission. 28 | # 29 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 30 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 31 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 32 | # ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR 33 | # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 34 | # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 35 | # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 36 | # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 37 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 38 | # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 39 | # 40 | ################################################################################ 41 | """ 42 | 43 | ident = '$Id: Errors.py 921 2005-02-15 16:32:23Z warnes $' 44 | from version import __version__ 45 | 46 | import exceptions 47 | 48 | ################################################################################ 49 | # Exceptions 50 | ################################################################################ 51 | class Error(exceptions.Exception): 52 | def __init__(self, msg): 53 | self.msg = msg 54 | def __str__(self): 55 | return "" % self.msg 56 | __repr__ = __str__ 57 | def __call__(self): 58 | return (self.msg,) 59 | 60 | class RecursionError(Error): 61 | pass 62 | 63 | class UnknownTypeError(Error): 64 | pass 65 | 66 | class HTTPError(Error): 67 | # indicates an HTTP protocol error 68 | def __init__(self, code, msg): 69 | self.code = code 70 | self.msg = msg 71 | def __str__(self): 72 | return "" % (self.code, self.msg) 73 | __repr__ = __str__ 74 | def __call___(self): 75 | return (self.code, self.msg, ) 76 | 77 | class UnderflowError(exceptions.ArithmeticError): 78 | pass 79 | 80 | -------------------------------------------------------------------------------- /src/SOAPpy/GSIServer.py: -------------------------------------------------------------------------------- 1 | """ 2 | GSIServer - Contributed by Ivan R. Judson 3 | 4 | 5 | ################################################################################ 6 | # 7 | # SOAPpy - Cayce Ullman (cayce@actzero.com) 8 | # Brian Matthews (blm@actzero.com) 9 | # Gregory Warnes (Gregory.R.Warnes@Pfizer.com) 10 | # Christopher Blunck (blunck@gst.com) 11 | # 12 | ################################################################################ 13 | # Copyright (c) 2003, Pfizer 14 | # Copyright (c) 2001, Cayce Ullman. 15 | # Copyright (c) 2001, Brian Matthews. 16 | # 17 | # All rights reserved. 18 | # 19 | # Redistribution and use in source and binary forms, with or without 20 | # modification, are permitted provided that the following conditions are met: 21 | # Redistributions of source code must retain the above copyright notice, this 22 | # list of conditions and the following disclaimer. 23 | # 24 | # Redistributions in binary form must reproduce the above copyright notice, 25 | # this list of conditions and the following disclaimer in the documentation 26 | # and/or other materials provided with the distribution. 27 | # 28 | # Neither the name of actzero, inc. nor the names of its contributors may 29 | # be used to endorse or promote products derived from this software without 30 | # specific prior written permission. 31 | # 32 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 33 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 34 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 35 | # ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR 36 | # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 37 | # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 38 | # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 39 | # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 40 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 41 | # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 42 | # 43 | ################################################################################ 44 | 45 | """ 46 | from __future__ import nested_scopes 47 | 48 | ident = '$Id: GSIServer.py 1468 2008-05-24 01:55:33Z warnes $' 49 | from version import __version__ 50 | 51 | #import xml.sax 52 | import re 53 | import socket 54 | import sys 55 | import SocketServer 56 | from types import * 57 | import BaseHTTPServer 58 | 59 | # SOAPpy modules 60 | from Parser import parseSOAPRPC 61 | from Config import SOAPConfig 62 | from Types import faultType, voidType, simplify 63 | from NS import NS 64 | from SOAPBuilder import buildSOAP 65 | from Utilities import debugHeader, debugFooter 66 | 67 | try: from M2Crypto import SSL 68 | except: pass 69 | 70 | ##### 71 | 72 | from Server import * 73 | 74 | from pyGlobus.io import GSITCPSocketServer, ThreadingGSITCPSocketServer 75 | from pyGlobus import ioc 76 | 77 | def GSIConfig(): 78 | config = SOAPConfig() 79 | config.channel_mode = ioc.GLOBUS_IO_SECURE_CHANNEL_MODE_GSI_WRAP 80 | config.delegation_mode = ioc.GLOBUS_IO_SECURE_DELEGATION_MODE_FULL_PROXY 81 | config.tcpAttr = None 82 | config.authMethod = "_authorize" 83 | return config 84 | 85 | Config = GSIConfig() 86 | 87 | class GSISOAPServer(GSITCPSocketServer, SOAPServerBase): 88 | def __init__(self, addr = ('localhost', 8000), 89 | RequestHandler = SOAPRequestHandler, log = 0, 90 | encoding = 'UTF-8', config = Config, namespace = None): 91 | 92 | # Test the encoding, raising an exception if it's not known 93 | if encoding != None: 94 | ''.encode(encoding) 95 | 96 | self.namespace = namespace 97 | self.objmap = {} 98 | self.funcmap = {} 99 | self.encoding = encoding 100 | self.config = config 101 | self.log = log 102 | 103 | self.allow_reuse_address= 1 104 | 105 | GSITCPSocketServer.__init__(self, addr, RequestHandler, 106 | self.config.channel_mode, 107 | self.config.delegation_mode, 108 | tcpAttr = self.config.tcpAttr) 109 | 110 | def get_request(self): 111 | sock, addr = GSITCPSocketServer.get_request(self) 112 | 113 | return sock, addr 114 | 115 | class ThreadingGSISOAPServer(ThreadingGSITCPSocketServer, SOAPServerBase): 116 | 117 | def __init__(self, addr = ('localhost', 8000), 118 | RequestHandler = SOAPRequestHandler, log = 0, 119 | encoding = 'UTF-8', config = Config, namespace = None): 120 | 121 | # Test the encoding, raising an exception if it's not known 122 | if encoding != None: 123 | ''.encode(encoding) 124 | 125 | self.namespace = namespace 126 | self.objmap = {} 127 | self.funcmap = {} 128 | self.encoding = encoding 129 | self.config = config 130 | self.log = log 131 | 132 | self.allow_reuse_address= 1 133 | 134 | ThreadingGSITCPSocketServer.__init__(self, addr, RequestHandler, 135 | self.config.channel_mode, 136 | self.config.delegation_mode, 137 | tcpAttr = self.config.tcpAttr) 138 | 139 | def get_request(self): 140 | sock, addr = ThreadingGSITCPSocketServer.get_request(self) 141 | 142 | return sock, addr 143 | 144 | -------------------------------------------------------------------------------- /src/SOAPpy/NS.py: -------------------------------------------------------------------------------- 1 | """ 2 | ################################################################################ 3 | # 4 | # SOAPpy - Cayce Ullman (cayce@actzero.com) 5 | # Brian Matthews (blm@actzero.com) 6 | # Gregory Warnes (Gregory.R.Warnes@Pfizer.com) 7 | # Christopher Blunck (blunck@gst.com) 8 | # 9 | ################################################################################ 10 | # Copyright (c) 2003, Pfizer 11 | # Copyright (c) 2001, Cayce Ullman. 12 | # Copyright (c) 2001, Brian Matthews. 13 | # 14 | # All rights reserved. 15 | # 16 | # Redistribution and use in source and binary forms, with or without 17 | # modification, are permitted provided that the following conditions are met: 18 | # Redistributions of source code must retain the above copyright notice, this 19 | # list of conditions and the following disclaimer. 20 | # 21 | # Redistributions in binary form must reproduce the above copyright notice, 22 | # this list of conditions and the following disclaimer in the documentation 23 | # and/or other materials provided with the distribution. 24 | # 25 | # Neither the name of actzero, inc. nor the names of its contributors may 26 | # be used to endorse or promote products derived from this software without 27 | # specific prior written permission. 28 | # 29 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 30 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 31 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 32 | # ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR 33 | # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 34 | # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 35 | # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 36 | # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 37 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 38 | # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 39 | # 40 | ################################################################################ 41 | 42 | """ 43 | from __future__ import nested_scopes 44 | 45 | ident = '$Id: NS.py 1468 2008-05-24 01:55:33Z warnes $' 46 | from version import __version__ 47 | 48 | ############################################################################## 49 | # Namespace Class 50 | ################################################################################ 51 | def invertDict(dict): 52 | d = {} 53 | 54 | for k, v in dict.items(): 55 | d[v] = k 56 | 57 | return d 58 | 59 | class NS: 60 | XML = "http://www.w3.org/XML/1998/namespace" 61 | 62 | ENV = "http://schemas.xmlsoap.org/soap/envelope/" 63 | ENC = "http://schemas.xmlsoap.org/soap/encoding/" 64 | 65 | XSD = "http://www.w3.org/1999/XMLSchema" 66 | XSD2 = "http://www.w3.org/2000/10/XMLSchema" 67 | XSD3 = "http://www.w3.org/2001/XMLSchema" 68 | 69 | XSD_L = [XSD, XSD2, XSD3] 70 | EXSD_L= [ENC, XSD, XSD2, XSD3] 71 | 72 | XSI = "http://www.w3.org/1999/XMLSchema-instance" 73 | XSI2 = "http://www.w3.org/2000/10/XMLSchema-instance" 74 | XSI3 = "http://www.w3.org/2001/XMLSchema-instance" 75 | XSI_L = [XSI, XSI2, XSI3] 76 | 77 | URN = "http://soapinterop.org/xsd" 78 | 79 | # For generated messages 80 | XML_T = "xml" 81 | ENV_T = "SOAP-ENV" 82 | ENC_T = "SOAP-ENC" 83 | XSD_T = "xsd" 84 | XSD2_T= "xsd2" 85 | XSD3_T= "xsd3" 86 | XSI_T = "xsi" 87 | XSI2_T= "xsi2" 88 | XSI3_T= "xsi3" 89 | URN_T = "urn" 90 | 91 | NSMAP = {ENV_T: ENV, ENC_T: ENC, XSD_T: XSD, XSD2_T: XSD2, 92 | XSD3_T: XSD3, XSI_T: XSI, XSI2_T: XSI2, XSI3_T: XSI3, 93 | URN_T: URN} 94 | NSMAP_R = invertDict(NSMAP) 95 | 96 | STMAP = {'1999': (XSD_T, XSI_T), '2000': (XSD2_T, XSI2_T), 97 | '2001': (XSD3_T, XSI3_T)} 98 | STMAP_R = invertDict(STMAP) 99 | 100 | def __init__(self): 101 | raise Error, "Don't instantiate this" 102 | 103 | 104 | 105 | -------------------------------------------------------------------------------- /src/SOAPpy/SOAP.py: -------------------------------------------------------------------------------- 1 | """This file is here for backward compatibility with versions <= 0.9.9 2 | 3 | Delete when 1.0.0 is released! 4 | """ 5 | 6 | ident = '$Id: SOAP.py 541 2004-01-31 04:20:06Z warnes $' 7 | from version import __version__ 8 | 9 | from Client import * 10 | from Config import * 11 | from Errors import * 12 | from NS import * 13 | from Parser import * 14 | from SOAPBuilder import * 15 | from Server import * 16 | from Types import * 17 | from Utilities import * 18 | import wstools 19 | import WSDL 20 | 21 | from warnings import warn 22 | 23 | warn(""" 24 | 25 | The sub-module SOAPpy.SOAP is deprecated and is only 26 | provided for short-term backward compatibility. Objects are now 27 | available directly within the SOAPpy module. Thus, instead of 28 | 29 | from SOAPpy import SOAP 30 | ... 31 | SOAP.SOAPProxy(...) 32 | 33 | use 34 | 35 | from SOAPpy import SOAPProxy 36 | ... 37 | SOAPProxy(...) 38 | 39 | instead. 40 | """, DeprecationWarning) 41 | -------------------------------------------------------------------------------- /src/SOAPpy/URLopener.py: -------------------------------------------------------------------------------- 1 | """Provide a class for loading data from URL's that handles basic 2 | authentication""" 3 | 4 | ident = '$Id: URLopener.py 541 2004-01-31 04:20:06Z warnes $' 5 | from version import __version__ 6 | 7 | from Config import Config 8 | from urllib import FancyURLopener 9 | 10 | class URLopener(FancyURLopener): 11 | 12 | username = None 13 | passwd = None 14 | 15 | 16 | def __init__(self, username=None, passwd=None, *args, **kw): 17 | FancyURLopener.__init__( self, *args, **kw) 18 | self.username = username 19 | self.passwd = passwd 20 | 21 | 22 | def prompt_user_passwd(self, host, realm): 23 | return self.username, self.passwd 24 | -------------------------------------------------------------------------------- /src/SOAPpy/Utilities.py: -------------------------------------------------------------------------------- 1 | """ 2 | ################################################################################ 3 | # Copyright (c) 2003, Pfizer 4 | # Copyright (c) 2001, Cayce Ullman. 5 | # Copyright (c) 2001, Brian Matthews. 6 | # 7 | # All rights reserved. 8 | # 9 | # Redistribution and use in source and binary forms, with or without 10 | # modification, are permitted provided that the following conditions are met: 11 | # Redistributions of source code must retain the above copyright notice, this 12 | # list of conditions and the following disclaimer. 13 | # 14 | # Redistributions in binary form must reproduce the above copyright notice, 15 | # this list of conditions and the following disclaimer in the documentation 16 | # and/or other materials provided with the distribution. 17 | # 18 | # Neither the name of actzero, inc. nor the names of its contributors may 19 | # be used to endorse or promote products derived from this software without 20 | # specific prior written permission. 21 | # 22 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 | # ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR 26 | # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 27 | # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 28 | # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 29 | # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 31 | # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | # 33 | ################################################################################ 34 | """ 35 | 36 | ident = '$Id: Utilities.py 1298 2006-11-07 00:54:15Z sanxiyn $' 37 | from version import __version__ 38 | 39 | import re 40 | import string 41 | import sys 42 | from types import * 43 | 44 | # SOAPpy modules 45 | from Errors import * 46 | 47 | ################################################################################ 48 | # Utility infielders 49 | ################################################################################ 50 | def collapseWhiteSpace(s): 51 | return re.sub('\s+', ' ', s).strip() 52 | 53 | def decodeHexString(data): 54 | conv = { 55 | '0': 0x0, '1': 0x1, '2': 0x2, '3': 0x3, '4': 0x4, 56 | '5': 0x5, '6': 0x6, '7': 0x7, '8': 0x8, '9': 0x9, 57 | 58 | 'a': 0xa, 'b': 0xb, 'c': 0xc, 'd': 0xd, 'e': 0xe, 59 | 'f': 0xf, 60 | 61 | 'A': 0xa, 'B': 0xb, 'C': 0xc, 'D': 0xd, 'E': 0xe, 62 | 'F': 0xf, 63 | } 64 | 65 | ws = string.whitespace 66 | 67 | bin = '' 68 | 69 | i = 0 70 | 71 | while i < len(data): 72 | if data[i] not in ws: 73 | break 74 | i += 1 75 | 76 | low = 0 77 | 78 | while i < len(data): 79 | c = data[i] 80 | 81 | if c in string.whitespace: 82 | break 83 | 84 | try: 85 | c = conv[c] 86 | except KeyError: 87 | raise ValueError, \ 88 | "invalid hex string character `%s'" % c 89 | 90 | if low: 91 | bin += chr(high * 16 + c) 92 | low = 0 93 | else: 94 | high = c 95 | low = 1 96 | 97 | i += 1 98 | 99 | if low: 100 | raise ValueError, "invalid hex string length" 101 | 102 | while i < len(data): 103 | if data[i] not in string.whitespace: 104 | raise ValueError, \ 105 | "invalid hex string character `%s'" % c 106 | 107 | i += 1 108 | 109 | return bin 110 | 111 | def encodeHexString(data): 112 | h = '' 113 | 114 | for i in data: 115 | h += "%02X" % ord(i) 116 | 117 | return h 118 | 119 | def leapMonth(year, month): 120 | return month == 2 and \ 121 | year % 4 == 0 and \ 122 | (year % 100 != 0 or year % 400 == 0) 123 | 124 | def cleanDate(d, first = 0): 125 | ranges = (None, (1, 12), (1, 31), (0, 23), (0, 59), (0, 61)) 126 | months = (0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31) 127 | names = ('year', 'month', 'day', 'hours', 'minutes', 'seconds') 128 | 129 | if len(d) != 6: 130 | raise ValueError, "date must have 6 elements" 131 | 132 | for i in range(first, 6): 133 | s = d[i] 134 | 135 | if type(s) == FloatType: 136 | if i < 5: 137 | try: 138 | s = int(s) 139 | except OverflowError: 140 | if i > 0: 141 | raise 142 | s = long(s) 143 | 144 | if s != d[i]: 145 | raise ValueError, "%s must be integral" % names[i] 146 | 147 | d[i] = s 148 | elif type(s) == LongType: 149 | try: s = int(s) 150 | except: pass 151 | elif type(s) != IntType: 152 | raise TypeError, "%s isn't a valid type" % names[i] 153 | 154 | if i == first and s < 0: 155 | continue 156 | 157 | if ranges[i] != None and \ 158 | (s < ranges[i][0] or ranges[i][1] < s): 159 | raise ValueError, "%s out of range" % names[i] 160 | 161 | if first < 6 and d[5] >= 61: 162 | raise ValueError, "seconds out of range" 163 | 164 | if first < 2: 165 | leap = first < 1 and leapMonth(d[0], d[1]) 166 | 167 | if d[2] > months[d[1]] + leap: 168 | raise ValueError, "day out of range" 169 | 170 | def debugHeader(title): 171 | s = '*** ' + title + ' ' 172 | print s + ('*' * (72 - len(s))) 173 | 174 | def debugFooter(title): 175 | print '*' * 72 176 | sys.stdout.flush() 177 | -------------------------------------------------------------------------------- /src/SOAPpy/WSDL.py: -------------------------------------------------------------------------------- 1 | """Parse web services description language to get SOAP methods. 2 | 3 | Rudimentary support.""" 4 | 5 | ident = '$Id: WSDL.py 1467 2008-05-16 23:32:51Z warnes $' 6 | from version import __version__ 7 | 8 | import wstools 9 | import xml 10 | from Errors import Error 11 | from Client import SOAPProxy, SOAPAddress 12 | from Config import Config 13 | import urllib 14 | 15 | class Proxy: 16 | """WSDL Proxy. 17 | 18 | SOAPProxy wrapper that parses method names, namespaces, soap actions from 19 | the web service description language (WSDL) file passed into the 20 | constructor. The WSDL reference can be passed in as a stream, an url, a 21 | file name, or a string. 22 | 23 | Loads info into self.methods, a dictionary with methodname keys and values 24 | of WSDLTools.SOAPCallinfo. 25 | 26 | For example, 27 | 28 | url = 'http://www.xmethods.org/sd/2001/TemperatureService.wsdl' 29 | wsdl = WSDL.Proxy(url) 30 | print len(wsdl.methods) # 1 31 | print wsdl.methods.keys() # getTemp 32 | 33 | 34 | See WSDLTools.SOAPCallinfo for more info on each method's attributes. 35 | """ 36 | 37 | def __init__(self, wsdlsource, config=Config, **kw ): 38 | 39 | reader = wstools.WSDLTools.WSDLReader() 40 | self.wsdl = None 41 | 42 | # From Mark Pilgrim's "Dive Into Python" toolkit.py--open anything. 43 | if self.wsdl is None and hasattr(wsdlsource, "read"): 44 | print 'stream:', wsdlsource 45 | try: 46 | self.wsdl = reader.loadFromStream(wsdlsource) 47 | except xml.parsers.expat.ExpatError, e: 48 | newstream = urllib.URLopener(key_file=config.SSL.key_file, cert_file=config.SSL.cert_file).open(wsdlsource) 49 | buf = newstream.readlines() 50 | raise Error, "Unable to parse WSDL file at %s: \n\t%s" % \ 51 | (wsdlsource, "\t".join(buf)) 52 | 53 | 54 | # NOT TESTED (as of April 17, 2003) 55 | #if self.wsdl is None and wsdlsource == '-': 56 | # import sys 57 | # self.wsdl = reader.loadFromStream(sys.stdin) 58 | # print 'stdin' 59 | 60 | if self.wsdl is None: 61 | try: 62 | file(wsdlsource) 63 | self.wsdl = reader.loadFromFile(wsdlsource) 64 | #print 'file' 65 | except (IOError, OSError): pass 66 | except xml.parsers.expat.ExpatError, e: 67 | newstream = urllib.urlopen(wsdlsource) 68 | buf = newstream.readlines() 69 | raise Error, "Unable to parse WSDL file at %s: \n\t%s" % \ 70 | (wsdlsource, "\t".join(buf)) 71 | 72 | if self.wsdl is None: 73 | try: 74 | stream = urllib.URLopener(key_file=config.SSL.key_file, cert_file=config.SSL.cert_file).open(wsdlsource) 75 | self.wsdl = reader.loadFromStream(stream, wsdlsource) 76 | except (IOError, OSError): pass 77 | except xml.parsers.expat.ExpatError, e: 78 | newstream = urllib.urlopen(wsdlsource) 79 | buf = newstream.readlines() 80 | raise Error, "Unable to parse WSDL file at %s: \n\t%s" % \ 81 | (wsdlsource, "\t".join(buf)) 82 | 83 | if self.wsdl is None: 84 | import StringIO 85 | self.wsdl = reader.loadFromString(str(wsdlsource)) 86 | #print 'string' 87 | 88 | # Package wsdl info as a dictionary of remote methods, with method name 89 | # as key (based on ServiceProxy.__init__ in ZSI library). 90 | self.methods = {} 91 | service = self.wsdl.services[0] 92 | port = service.ports[0] 93 | name = service.name 94 | binding = port.getBinding() 95 | portType = binding.getPortType() 96 | for operation in portType.operations: 97 | callinfo = wstools.WSDLTools.callInfoFromWSDL(port, operation.name) 98 | self.methods[callinfo.methodName] = callinfo 99 | 100 | self.soapproxy = SOAPProxy('http://localhost/dummy.webservice', 101 | config=config, **kw) 102 | 103 | def __str__(self): 104 | s = '' 105 | for method in self.methods.values(): 106 | s += str(method) 107 | return s 108 | 109 | def __getattr__(self, name): 110 | """Set up environment then let parent class handle call. 111 | 112 | Raises AttributeError is method name is not found.""" 113 | 114 | if not self.methods.has_key(name): raise AttributeError, name 115 | 116 | callinfo = self.methods[name] 117 | self.soapproxy.proxy = SOAPAddress(callinfo.location) 118 | self.soapproxy.namespace = callinfo.namespace 119 | self.soapproxy.soapaction = callinfo.soapAction 120 | return self.soapproxy.__getattr__(name) 121 | 122 | def show_methods(self): 123 | for key in self.methods.keys(): 124 | method = self.methods[key] 125 | print "Method Name:", key.ljust(15) 126 | print 127 | inps = method.inparams 128 | for parm in range(len(inps)): 129 | details = inps[parm] 130 | print " In #%d: %s (%s)" % (parm, details.name, details.type) 131 | print 132 | outps = method.outparams 133 | for parm in range(len(outps)): 134 | details = outps[parm] 135 | print " Out #%d: %s (%s)" % (parm, details.name, details.type) 136 | print 137 | 138 | -------------------------------------------------------------------------------- /src/SOAPpy/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | ident = '$Id: __init__.py 541 2004-01-31 04:20:06Z warnes $' 3 | from version import __version__ 4 | 5 | from Client import * 6 | from Config import * 7 | from Errors import * 8 | from NS import * 9 | from Parser import * 10 | from SOAPBuilder import * 11 | from Server import * 12 | from Types import * 13 | from Utilities import * 14 | import wstools 15 | import WSDL 16 | -------------------------------------------------------------------------------- /src/SOAPpy/version.py: -------------------------------------------------------------------------------- 1 | try: 2 | import pkg_resources 3 | __version__ = pkg_resources.get_distribution("SOAPpy").version 4 | except: 5 | __version__="xxx" 6 | -------------------------------------------------------------------------------- /tests/BabelfishWSDLTest.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | ident = '$Id: BabelfishWSDLTest.py,v 1.1 2003/07/18 15:58:28 warnes Exp $' 4 | 5 | import os, re 6 | import sys 7 | sys.path.insert(1, "..") 8 | 9 | from SOAPpy import WSDL 10 | 11 | # Check for a web proxy definition in environment 12 | try: 13 | proxy_url=os.environ['http_proxy'] 14 | phost, pport = re.search('http://([^:]+):([0-9]+)', proxy_url).group(1,2) 15 | proxy = "%s:%s" % (phost, pport) 16 | except: 17 | proxy = None 18 | 19 | server = WSDL.Proxy('http://www.xmethods.net/sd/2001/BabelFishService.wsdl', 20 | http_proxy=proxy) 21 | 22 | english = "Hi Friend!" 23 | 24 | print "Babelfish Translations" 25 | print "------------------------" 26 | print "English: '%s'" % english 27 | print "French: '%s'" % server.BabelFish('en_fr',english) 28 | print "Spanish: '%s'" % server.BabelFish('en_es',english) 29 | print "Italian: '%s'" % server.BabelFish('en_it',english) 30 | print "German: '%s'" % server.BabelFish('en_de',english) 31 | 32 | print "Done." 33 | -------------------------------------------------------------------------------- /tests/Bug1001646.py: -------------------------------------------------------------------------------- 1 | """ 2 | Check handing of unicode. 3 | """ 4 | 5 | import sys 6 | sys.path.insert(1, "..") 7 | from SOAPpy import * 8 | 9 | # Uncomment to see outgoing HTTP headers and SOAP and incoming 10 | #Config.debug = 1 11 | #Config.dumpHeadersIn = 1 12 | #Config.dumpSOAPIn = 1 13 | #Config.dumpSOAPOut = 1 14 | 15 | # ask for returned SOAP responses to be converted to basic python types 16 | Config.simplify_objects = 1 17 | 18 | #Config.BuildWithNoType = 1 19 | #Config.BuildWithNoNamespacePrefix = 1 20 | 21 | 22 | def headers(): 23 | '''Return a soap header containing all the needed information.''' 24 | hd = Types.headerType() 25 | hd.useragent = Types.stringType("foo") 26 | return hd 27 | 28 | server = SOAPProxy("http://localhost:9900/",header=headers()) 29 | 30 | adgroupid = 197497504 31 | keyword1 = { 'status': 'Moderate', 32 | 'adGroupId': 197497504, 33 | 'destinationURL': None, 34 | 'language': '', 35 | 'text': 'does not work', 36 | 'negative': bool(0), 37 | 'maxCpc': 50000, 38 | 'type': 'Keyword', 39 | 'id': 1 } 40 | keyword2 = { 'status': 'Moderate', 41 | 'adGroupId': 197497504, 42 | 'destinationURL': None, 43 | 'language': '', 44 | 'text': 'yes it does not', 45 | 'negative': bool(0), 46 | 'maxCpc': 50000, 47 | 'type': 'Keyword', 48 | 'id': 2 } 49 | keylist = [keyword1, keyword2] 50 | 51 | # Check that the data goes through properly 52 | 53 | retval = server.echo_simple(adgroupid, keylist) 54 | 55 | kw1 = retval[1][0] 56 | kw2 = retval[1][1] 57 | 58 | assert(retval[0] == adgroupid) 59 | 60 | for key in kw1.keys(): 61 | assert(kw1[key]==keyword1[key]) 62 | 63 | for key in kw2.keys(): 64 | assert(kw2[key]==keyword2[key]) 65 | 66 | # Check that the header is preserved 67 | retval = server.echo_header((adgroupid, keylist)) 68 | 69 | assert(retval[1].has_key('useragent')) 70 | assert(retval[1]['useragent'] == 'foo') 71 | 72 | server.quit() 73 | 74 | print "Success!" 75 | 76 | -------------------------------------------------------------------------------- /tests/Bug916265.py: -------------------------------------------------------------------------------- 1 | """ 2 | Check handing of unicode. 3 | """ 4 | 5 | import sys 6 | sys.path.insert(1, "..") 7 | from SOAPpy import * 8 | 9 | # Uncomment to see outgoing HTTP headers and SOAP and incoming 10 | #Config.debug = 1 11 | #Config.dumpHeadersIn = 1 12 | #Config.dumpSOAPIn = 1 13 | #Config.dumpSOAPOut = 1 14 | 15 | # ask for returned SOAP responses to be converted to basic python types 16 | Config.simplify_objects = 0 17 | 18 | #Config.BuildWithNoType = 1 19 | #Config.BuildWithNoNamespacePrefix = 1 20 | 21 | server = SOAPProxy("http://localhost:9900/") 22 | 23 | x = u'uMOO' # Single unicode string 24 | y = server.echo_simple((x,)) 25 | assert( x==y[0] ) 26 | 27 | x = [u'uMoo1',u'uMoo2'] # array of unicode strings 28 | y = server.echo_simple(x) 29 | assert( x[0] == y[0] ) 30 | assert( x[1] == y[1] ) 31 | 32 | x = { 33 | u'A':1, 34 | u'B':u'B', 35 | 'C':u'C', 36 | 'D':'D' 37 | } 38 | y = server.echo_simple(x) 39 | 40 | for key in x.keys(): 41 | assert( x[key] == y[0][key] ) 42 | 43 | print "Success" 44 | -------------------------------------------------------------------------------- /tests/Bug918216.py: -------------------------------------------------------------------------------- 1 | import sys 2 | sys.path.insert(1, "..") 3 | from SOAPpy import * 4 | 5 | detailed_fault = \ 6 | """ 7 | 8 | 9 | 10 | 11 | 12 | soapenv:Server.generalException 13 | Exception thrown on Server 14 | 15 | 16 | 17 | ... 18 | 19 | 20 | 21 | 22 | 23 | Login failure (504):Unknown User 24 | ... 25 | ... 26 | ... 27 | ... 28 | 29 | 30 | 31 | 32 | """ 33 | 34 | z = parseSOAPRPC(detailed_fault.strip() ) 35 | assert(z.__class__==faultType) 36 | assert(z.faultstring=="Exception thrown on Server") 37 | assert(z.detail.loginFailureFault.description=='Login failure (504):Unknown User') 38 | print "Success" 39 | -------------------------------------------------------------------------------- /tests/ComplexTypes.py: -------------------------------------------------------------------------------- 1 | import sys 2 | sys.path.insert(1, "..") 3 | 4 | import SOAPpy 5 | 6 | import time 7 | dep = SOAPpy.dateTimeType((2004, 3, 24, 12, 30, 59, 4, 86, 0)) 8 | ret = SOAPpy.dateTimeType((2004, 3, 26, 12, 30, 59, 4, 86, 0)) 9 | 10 | in0 = SOAPpy.structType() 11 | in0._addItem('outwardDate', dep) 12 | in0._addItem('returnDate', ret) 13 | in0._addItem('originAirport', 'den') 14 | in0._addItem('destinationAirport', 'iad') 15 | 16 | 17 | x = SOAPpy.buildSOAP( 18 | in0, 19 | method="getAirFareQuote", 20 | namespace="urn:SBGAirFareQuotes.sbg.travel.ws.dsdata.co.uk" 21 | ) 22 | 23 | 24 | wsdl = 'http://www.xmethods.net/sd/2001/TemperatureService.wsdl' 25 | proxy = SOAPpy.WSDL.Proxy(wsdl) 26 | 27 | -------------------------------------------------------------------------------- /tests/GoogleTest.py: -------------------------------------------------------------------------------- 1 | from SOAPpy import WSDL 2 | server = WSDL.Proxy('/home/warneg/src/google/googleapi/GoogleSearch.wsdl') 3 | key = "6k0oDPZQFHL0zpjy6ZO6ufUVFKBgvqTo" 4 | 5 | results = server.doGoogleSearch(key, 'warnes', 0, 10, False, "", 6 | False, "", "utf-8", "utf-8") 7 | 8 | 9 | for i in range(len(results.resultElements)): 10 | res = results.resultElements[i] 11 | print '%d: %s --> %s' % ( i, res.title, res.URL ) 12 | -------------------------------------------------------------------------------- /tests/TCtest.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import sys, unittest 4 | sys.path.insert(1, "..") 5 | from SOAPpy import * 6 | Config.debug=1 7 | 8 | class ClientTestCase(unittest.TestCase): 9 | def testParseRules(self): 10 | x = """ 11 | 15 | 17 | 18 | 19 | 20 | My Life and Work 21 | 22 | 23 | Henry Ford 24 | 49 25 | 5.5 26 | 27 | 28 | 29 | 30 | 31 | """ 32 | 33 | def negfloat(x): 34 | return float(x) * -1.0 35 | 36 | # parse rules 37 | pr = {'SomeMethod': 38 | {'Result': 39 | { 40 | 'Book': {'title':'string'}, 41 | 'Person': {'age':'int', 42 | 'height':negfloat} 43 | } 44 | } 45 | } 46 | y = parseSOAPRPC(x, rules=pr) 47 | 48 | assert y.Result.Person.age == 49 49 | assert y.Result.Person.height == -5.5 50 | 51 | 52 | x = ''' 58 | 59 | 60 | 61 | 12 62 | 23 63 | 0 64 | -31 65 | 66 | 67 | 68 | 69 | 70 | ''' 71 | 72 | 73 | # parse rules 74 | pr = {'Bounds': 75 | {'param': 'arrayType=string[]', 76 | } 77 | } 78 | 79 | pr2 = {'Bounds': 80 | {'param': 'arrayType=int[4]', 81 | } 82 | } 83 | 84 | y = parseSOAPRPC(x, rules=pr) 85 | assert y.param[1]=='23' 86 | 87 | y = parseSOAPRPC(x, rules=pr2) 88 | assert y.param[1]==23 89 | 90 | x = ''' 96 | 97 | 98 | 99 | 100 | 12 101 | 23 102 | 0 103 | -31 104 | 105 | 106 | 107 | 108 | 109 | ''' 110 | 111 | pr = {'Bounds': 112 | {'param': 'arrayType=ur-type[]' 113 | } 114 | } 115 | y = parseSOAPRPC(x, rules=pr) 116 | assert y.param[0]==12 117 | assert y.param[1]=='23' 118 | assert y.param[2]==float(0) 119 | assert y.param[3]==-31 120 | 121 | # Try the reverse, not implemented yet. 122 | 123 | def testBuildObject(self): 124 | 125 | class Book(structType): 126 | def __init__(self): 127 | self.title = "Title of a book" 128 | 129 | class Person(structType): 130 | def __init__(self): 131 | self.age = "49" 132 | self.height = "5.5" 133 | 134 | class Library(structType): 135 | def __init__(self): 136 | self._name = "Result" 137 | self.Book = Book() 138 | self.Person = Person() 139 | 140 | obj = Library() 141 | 142 | x = buildSOAP( kw={'Library':obj} ) 143 | 144 | print(x) 145 | 146 | if __name__ == '__main__': 147 | unittest.main() 148 | -------------------------------------------------------------------------------- /tests/TemperatureService.wsdl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | Returns current temperature in a given U.S. zipcode 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /tests/ZeroLengthArray.py: -------------------------------------------------------------------------------- 1 | import sys 2 | sys.path.insert(1, "..") 3 | from SOAPpy import * 4 | 5 | one = typedArrayType(data=[1],typed=type(1)) 6 | tmp = typedArrayType(data=[], typed=type(1)) 7 | print buildSOAP( one ) 8 | print buildSOAP( tmp ) 9 | -------------------------------------------------------------------------------- /tests/alanbushTest.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | # Copyright (c) 2001 actzero, inc. All rights reserved. 4 | 5 | ident = '$Id: alanbushTest.py,v 1.5 2003/05/21 14:52:37 warnes Exp $' 6 | 7 | import os, re,sys 8 | 9 | # add local SOAPpy code to search path 10 | sys.path.insert(1, "..") 11 | 12 | from SOAPpy import * 13 | Config.debug=0 14 | 15 | # Check for a web proxy definition in environment 16 | try: 17 | proxy_url=os.environ['http_proxy'] 18 | phost, pport = re.search('http://([^:]+):([0-9]+)', proxy_url).group(1,2) 19 | proxy = "%s:%s" % (phost, pport) 20 | except: 21 | proxy = None 22 | 23 | SoapEndpointURL = 'http://www.alanbushtrust.org.uk/soap/compositions.asp' 24 | MethodNamespaceURI = 'urn:alanbushtrust-org-uk:soap.methods' 25 | SoapAction = MethodNamespaceURI + ".GetCategories" 26 | 27 | server = SOAPProxy(SoapEndpointURL, 28 | namespace=MethodNamespaceURI, 29 | soapaction=SoapAction, 30 | http_proxy=proxy 31 | ) 32 | 33 | for category in server.GetCategories(): 34 | print category 35 | -------------------------------------------------------------------------------- /tests/cardClient.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | # Copyright (c) 2001 actzero, inc. All rights reserved. 4 | 5 | import sys 6 | 7 | sys.path.insert (1, '..') 8 | 9 | from SOAPpy import * 10 | 11 | ident = '$Id: cardClient.py,v 1.4 2004/02/18 21:22:13 warnes Exp $' 12 | 13 | endpoint = "http://localhost:12027/xmethodsInterop" 14 | sa = "urn:soapinterop" 15 | ns = "http://soapinterop.org/" 16 | 17 | serv = SOAPProxy(endpoint, namespace=ns, soapaction=sa) 18 | try: hand = serv.dealHand(NumberOfCards = 13, StringSeparator = '\n') 19 | except: print "no dealHand"; hand = 0 20 | try: sortedhand = serv.dealArrangedHand(NumberOfCards=13,StringSeparator='\n') 21 | except: print "no sorted"; sortedhand = 0 22 | try: card = serv.dealCard() 23 | except: print "no card"; card = 0 24 | 25 | print "*****hand****\n",hand,"\n*********" 26 | print "******sortedhand*****\n",sortedhand,"\n*********" 27 | print "card:",card 28 | 29 | serv.quit() 30 | 31 | -------------------------------------------------------------------------------- /tests/cardServer.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | # Copyright (c) 2001 actzero, inc. All rights reserved. 4 | 5 | import string 6 | import sys 7 | 8 | sys.path.insert (1, '..') 9 | 10 | from SOAPpy import * 11 | 12 | ident = '$Id: cardServer.py,v 1.4 2004/02/18 21:22:13 warnes Exp $' 13 | 14 | # create the list of all cards, and keep strings for each suit 15 | __cs = "Clubs" 16 | __ds = "Diamonds" 17 | __hs = "Hearts" 18 | __ss = "Spades" 19 | __cards = [] 20 | for suit in [__cs, __ds, __hs, __ss]: 21 | for num in range(9): 22 | num += 1 23 | __cards.append(str(num+1)+" of "+suit) 24 | for face in ["ace","King","Queen","Jack"]: 25 | __cards.append(face+" of "+suit) 26 | 27 | 28 | def deal(num): 29 | if num not in range(1,53): 30 | return -1 31 | else: 32 | alreadydealt = [] 33 | ignore = 0 34 | handdealt = [] 35 | import whrandom 36 | while num > 0: 37 | idx = int(str(whrandom.random())[2:4]) 38 | if idx in range(52) and idx not in alreadydealt: 39 | handdealt.append(__cards[idx]) 40 | alreadydealt.append(idx) 41 | num -= 1 42 | else: 43 | ignore += 1 44 | continue 45 | return handdealt 46 | 47 | def arrangeHand(hand): 48 | c = [] 49 | d = [] 50 | h = [] 51 | s = [] 52 | import string 53 | for card in hand: 54 | if string.find(card, __cs) != -1: 55 | c.append(card) 56 | elif string.find(card, __ds) != -1: 57 | d.append(card) 58 | elif string.find(card, __hs) != -1: 59 | h.append(card) 60 | elif string.find(card, __ss) != -1: 61 | s.append(card) 62 | for cards, str in ((c, __cs),(d, __ds),(h,__hs), (s,__ss)): 63 | cards.sort() 64 | idx = 0 65 | if "10 of "+str in cards: 66 | cards.remove("10 of "+str) 67 | if "Jack of "+str in cards: idx += 1 68 | if "Queen of "+str in cards: idx += 1 69 | if "King of "+str in cards: idx += 1 70 | if "ace of "+str in cards: idx +=1 71 | cards.insert(len(cards)-idx,"10 of "+str) 72 | if "King of "+str in cards: 73 | cards.remove("King of "+str) 74 | if "ace of "+str in cards: cards.insert(len(cards)-1,"King of "+str) 75 | else: cards.append("King of "+str) 76 | return c+d+h+s 77 | 78 | def dealHand (NumberOfCards, StringSeparator): 79 | hand = deal(NumberOfCards) 80 | return string.join(hand,StringSeparator) 81 | 82 | 83 | def dealArrangedHand (NumberOfCards, StringSeparator): 84 | if NumberOfCards < 1 or NumberOfCards > 52: 85 | raise ValueError, "NumberOfCards must be between 1 and 52" 86 | unarranged = deal(NumberOfCards) 87 | hand = arrangeHand(unarranged) 88 | return string.join(hand, StringSeparator) 89 | 90 | def dealCard (): 91 | return deal(1)[0] 92 | 93 | run = 1 94 | 95 | def quit(): 96 | global run 97 | run=0; 98 | 99 | namespace = 'http://soapinterop.org/' 100 | 101 | server = SOAPServer (("localhost", 12027)) 102 | 103 | server.registerKWFunction (dealHand, namespace) 104 | server.registerKWFunction (dealArrangedHand, namespace) 105 | server.registerKWFunction (dealCard, namespace) 106 | server.registerKWFunction (quit, namespace) 107 | 108 | try: 109 | while run: 110 | server.handle_request() 111 | except KeyboardInterrupt: 112 | pass 113 | -------------------------------------------------------------------------------- /tests/echoClient.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | # Copyright (c) 2001 actzero, inc. All rights reserved. 4 | 5 | import sys 6 | sys.path.insert(1, "..") 7 | 8 | from SOAPpy import * 9 | 10 | # Uncomment to see outgoing HTTP headers and SOAP and incoming 11 | #Config.debug = 1 12 | #Config.dumpHeadersIn = 1 13 | #Config.dumpSOAPIn = 1 14 | #Config.dumpSOAPOut = 1 15 | 16 | # ask for returned SOAP responses to be converted to basic python types 17 | Config.simplify_objects = 1 18 | 19 | #Config.BuildWithNoType = 1 20 | #Config.BuildWithNoNamespacePrefix = 1 21 | 22 | if len(sys.argv) > 1 and sys.argv[1] == '-s': 23 | # Use secure http 24 | pathserver = SOAPProxy("https://localhost:9900/pathtest") 25 | server = SOAPProxy("https://localhost:9900") 26 | 27 | elif len(sys.argv) > 1 and sys.argv[1] == '-g': 28 | # use Globus for communication 29 | import pyGlobus 30 | pathserver = SOAPProxy("httpg://localhost:9900/pathtest") 31 | server = SOAPProxy("httpg://localhost:9900") 32 | 33 | else: 34 | # Default: use standard http 35 | pathserver = SOAPProxy("http://localhost:9900/pathtest") 36 | server = SOAPProxy("http://localhost:9900") 37 | 38 | # Echo... 39 | 40 | try: 41 | print server.echo("MOO") 42 | except Exception, e: 43 | print "Caught exception: ", e 44 | try: 45 | print pathserver.echo("MOO") 46 | except Exception, e: 47 | print "Caught exception: ", e 48 | 49 | # ...in an object 50 | try: 51 | print server.echo_ino("moo") 52 | except Exception, e: 53 | print "Caught exception: ", e 54 | try: 55 | print pathserver.echo_ino("cow") 56 | except Exception, e: 57 | print "Caught exception: ", e 58 | 59 | # ...in an object in an object 60 | try: 61 | print server.prop.echo2("moo") 62 | except Exception, e: 63 | print "Caught exception: ", e 64 | 65 | try: 66 | print pathserver.prop.echo2("cow") 67 | except Exception, e: 68 | print "Caught exception: ", e 69 | 70 | # ...with keyword arguments 71 | try: 72 | print server.echo_wkw(third = "three", first = "one", second = "two") 73 | except Exception, e: 74 | print "Caught exception: ", e 75 | try: 76 | print pathserver.echo_wkw(third = "three", first = "one", second = "two") 77 | except Exception, e: 78 | print "Caught exception: ", e 79 | 80 | # ...with a context object 81 | try: 82 | print server.echo_wc("moo") 83 | except Exception, e: 84 | print "Caught exception: ", e 85 | try: 86 | print pathserver.echo_wc("cow") 87 | except Exception, e: 88 | print "Caught exception: ", e 89 | 90 | # ...with a header 91 | hd = headerType(data = {"mystring": "Hello World"}) 92 | try: 93 | print server._hd(hd).echo_wc("moo") 94 | except Exception, e: 95 | print "Caught exception: ", e 96 | try: 97 | print pathserver._hd(hd).echo_wc("cow") 98 | except Exception, e: 99 | print "Caught exception: ", e 100 | 101 | # close down server 102 | server.quit() 103 | -------------------------------------------------------------------------------- /tests/echoHeader.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | # Copyright (c) 2001 actzero, inc. All rights reserved. 4 | 5 | import sys 6 | sys.path.insert(1, "..") 7 | 8 | from SOAPpy import * 9 | 10 | # Uncomment to see outgoing HTTP headers and SOAP and incoming 11 | #Config.debug = 1 12 | 13 | Config.BuildWithNoType = 1 14 | Config.BuildWithNoNamespacePrefix = 1 15 | 16 | 17 | 18 | hd = headerType(data = {"mystring": "Hello World"}) 19 | server = SOAPProxy("http://localhost:9900/", header=hd) 20 | 21 | print server.echo("Hello world") 22 | 23 | server.quit() 24 | -------------------------------------------------------------------------------- /tests/echoServer.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # Copyright (c) 2001 actzero, inc. All rights reserved. 4 | 5 | import sys 6 | sys.path.insert(1, "..") 7 | 8 | from SOAPpy import * 9 | 10 | # Uncomment to see outgoing HTTP headers and SOAP and incoming 11 | Config.dumpSOAPIn = 1 12 | Config.dumpSOAPOut = 1 13 | Config.debug = 1 14 | 15 | # specify name of authorization function 16 | Config.authMethod = "_authorize" 17 | 18 | # Set this to 0 to test authorization 19 | allowAll = 1 20 | 21 | # ask for returned SOAP responses to be converted to basic python types 22 | Config.simplify_objects = 1 23 | 24 | 25 | # provide a mechanism to stop the server 26 | run = 1 27 | def quit(): 28 | global run 29 | run=0; 30 | 31 | 32 | if Config.SSLserver: 33 | from M2Crypto import SSL 34 | 35 | def _authorize(*args, **kw): 36 | global allowAll, Config 37 | 38 | if Config.debug: 39 | print "Authorize (function) called! (result = %d)" % allowAll 40 | print "Arguments: %s" % kw 41 | 42 | if allowAll: 43 | return 1 44 | else: 45 | return 0 46 | 47 | # Simple echo 48 | def echo(s): 49 | global Config 50 | 51 | # Test of context retrieval 52 | ctx = Server.GetSOAPContext() 53 | if Config.debug: 54 | print "SOAP Context: ", ctx 55 | 56 | return s + s 57 | 58 | # An echo class 59 | class echoBuilder2: 60 | def echo2(self, val): 61 | return val * 3 62 | 63 | # A class that has an instance variable which is an echo class 64 | class echoBuilder: 65 | def __init__(self): 66 | self.prop = echoBuilder2() 67 | 68 | def echo_ino(self, val): 69 | return val + val 70 | def _authorize(self, *args, **kw): 71 | global allowAll, Config 72 | 73 | if Config.debug: 74 | print "Authorize (method) called with arguments:" 75 | print "*args=%s" % str(args) 76 | print "**kw =%s" % str(kw) 77 | print "Approved -> %d" % allowAll 78 | 79 | if allowAll: 80 | return 1 81 | else: 82 | return 0 83 | 84 | # Echo with context 85 | def echo_wc(s, _SOAPContext): 86 | global Config 87 | 88 | c = _SOAPContext 89 | 90 | sep = '-' * 72 91 | 92 | # The Context object has extra info about the call 93 | if Config.debug: 94 | print "-- XML", sep[7:] 95 | # The original XML request 96 | print c.xmldata 97 | 98 | print "-- Header", sep[10:] 99 | # The SOAP Header or None if not present 100 | print c.header 101 | 102 | if c.header: 103 | print "-- Header.mystring", sep[19:] 104 | # An element of the SOAP Header 105 | print c.header.mystring 106 | 107 | print "-- Body", sep[8:] 108 | # The whole Body object 109 | print c.body 110 | 111 | print "-- Peer", sep[8:] 112 | if not GSI: 113 | # The socket object, useful for 114 | print c.connection.getpeername() 115 | else: 116 | # The socket object, useful for 117 | print c.connection.get_remote_address() 118 | ctx = c.connection.get_security_context() 119 | print ctx.inquire()[0].display() 120 | 121 | print "-- SOAPAction", sep[14:] 122 | # The SOAPaction HTTP header 123 | print c.soapaction 124 | 125 | print "-- HTTP headers", sep[16:] 126 | # All the HTTP headers 127 | print c.httpheaders 128 | 129 | return s + s 130 | 131 | # Echo with keyword arguments 132 | def echo_wkw(**kw): 133 | return kw['first'] + kw['second'] + kw['third'] 134 | 135 | # Simple echo 136 | def echo_simple(*arg): 137 | return arg 138 | 139 | def echo_header(s, _SOAPContext): 140 | global Config 141 | 142 | c = _SOAPContext 143 | return s, c.header 144 | 145 | 146 | addr = ('localhost', 9900) 147 | GSI = 0 148 | SSL = 0 149 | if len(sys.argv) > 1 and sys.argv[1] == '-s': 150 | SSL = 1 151 | if not Config.SSLserver: 152 | raise RuntimeError, \ 153 | "this Python installation doesn't have OpenSSL and M2Crypto" 154 | ssl_context = SSL.Context() 155 | ssl_context.load_cert('validate/server.pem') 156 | server = SOAPServer(addr, ssl_context = ssl_context) 157 | prefix = 'https' 158 | elif len(sys.argv) > 1 and sys.argv[1] == '-g': 159 | GSI = 1 160 | from SOAPpy.GSIServer import GSISOAPServer 161 | server = GSISOAPServer(addr) 162 | prefix = 'httpg' 163 | else: 164 | server = SOAPServer(addr) 165 | prefix = 'http' 166 | 167 | print "Server listening at: %s://%s:%d/" % (prefix, addr[0], addr[1]) 168 | 169 | # register the method 170 | server.registerFunction(echo) 171 | server.registerFunction(echo, path = "/pathtest") 172 | server.registerFunction(_authorize) 173 | server.registerFunction(_authorize, path = "/pathtest") 174 | 175 | # Register a whole object 176 | o = echoBuilder() 177 | server.registerObject(o, path = "/pathtest") 178 | server.registerObject(o) 179 | 180 | # Register a function which gets called with the Context object 181 | server.registerFunction(MethodSig(echo_wc, keywords = 0, context = 1), 182 | path = "/pathtest") 183 | server.registerFunction(MethodSig(echo_wc, keywords = 0, context = 1)) 184 | 185 | # Register a function that takes keywords 186 | server.registerKWFunction(echo_wkw, path = "/pathtest") 187 | server.registerKWFunction(echo_wkw) 188 | 189 | server.registerFunction(echo_simple) 190 | server.registerFunction(MethodSig(echo_header, keywords=0, context=1)) 191 | server.registerFunction(quit) 192 | 193 | # Start the server 194 | try: 195 | while run: 196 | server.handle_request() 197 | except KeyboardInterrupt: 198 | pass 199 | -------------------------------------------------------------------------------- /tests/esj_test_client.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python2 2 | 3 | #standard imports 4 | import syslog, sys 5 | 6 | #domain specific imports 7 | sys.path.insert (1, '..') 8 | import SOAPpy 9 | 10 | SOAPpy.Config.simplify_objects=1 11 | 12 | ## def test_integer(self,pass_integer): 13 | ## def test_string(self,pass_string): 14 | ## def test_float(self,pass_float): 15 | ## def test_tuple(self,pass_tuple): 16 | ## def test_list(self,pass_list): 17 | ## def test_dictionary(self,pass_dictionary): 18 | 19 | if __name__ == "__main__": 20 | 21 | server = SOAPpy.SOAPProxy("http://localhost:9999") 22 | 23 | original_integer = 5 24 | result_integer = server.test_integer(original_integer) 25 | print "original_integer %s" % original_integer 26 | print "result_integer %s" % result_integer 27 | assert(result_integer==original_integer) 28 | print 29 | 30 | original_string = "five" 31 | result_string = server.test_string(original_string) 32 | print "original_string %s" % original_string 33 | print "result_string %s" % result_string 34 | assert(result_string==original_string) 35 | print 36 | 37 | original_float = 5.0 38 | result_float = server.test_float(original_float) 39 | print "original_float %s" % original_float 40 | print "result_float %s" % result_float 41 | assert(result_float==original_float) 42 | print 43 | 44 | original_tuple = (1,2,"three","four",5) 45 | result_tuple = server.test_tuple(original_tuple) 46 | print "original_tuple %s" % str(original_tuple) 47 | print "result_tuple %s" % str(result_tuple) 48 | assert(tuple(result_tuple)==original_tuple) 49 | print 50 | 51 | original_list = [5,4,"three",2,1] 52 | result_list = server.test_list(original_list) 53 | print "original_list %s" % original_list 54 | print "result_list %s" % result_list 55 | assert(result_list==original_list) 56 | print 57 | 58 | original_dictionary = { 59 | 'one': 1, 60 | "two": 2, 61 | "three": 3, 62 | "four": 4, 63 | "five": 5, 64 | } 65 | result_dictionary = server.test_dictionary(original_dictionary) 66 | print "original_dictionary %s" % original_dictionary 67 | print "result_dictionary %s" % result_dictionary 68 | assert(result_dictionary==original_dictionary) 69 | print 70 | 71 | server.quit() 72 | -------------------------------------------------------------------------------- /tests/esj_test_server.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python2 2 | 3 | #standard imports 4 | import syslog, sys 5 | 6 | #domain specific imports 7 | sys.path.insert (1, '..') 8 | import SOAPpy 9 | 10 | class test_service: 11 | 12 | run = 1 13 | 14 | def test_integer(self,pass_integer): 15 | print type(pass_integer) 16 | return pass_integer 17 | 18 | def test_string(self,pass_string): 19 | print type(pass_string) 20 | return pass_string 21 | 22 | def test_float(self,pass_float): 23 | print type(pass_float) 24 | return pass_float 25 | 26 | def test_tuple(self,pass_tuple): 27 | print type(pass_tuple), pass_tuple 28 | return pass_tuple 29 | 30 | def test_list(self,pass_list): 31 | print type(pass_list), pass_list 32 | return pass_list 33 | 34 | def test_dictionary(self,pass_dictionary): 35 | print type(pass_dictionary), pass_dictionary 36 | return pass_dictionary 37 | 38 | def quit(self): 39 | self.run = 0 40 | 41 | server = SOAPpy.SOAPServer(("localhost",9999)) 42 | SOAPpy.Config.simplify_objects=1 43 | 44 | access_object = test_service() 45 | server.registerObject(access_object) 46 | 47 | while access_object.run: 48 | server.handle_request() 49 | -------------------------------------------------------------------------------- /tests/excelTest.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import sys 4 | sys.path.insert(1, "..") 5 | 6 | from SOAPpy import * 7 | server = SOAPProxy("http://206.135.217.234:8000/") 8 | server.COM_SetProperty("Visible", 1) 9 | server.Workbooks.Open("c:\\test.xls") 10 | server.COM_NestedCall('ActiveSheet.Range("A2").EntireRow.Delete()') 11 | server.quit() 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /tests/largeDataTest.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | # Copyright (c) 2001 actzero, inc. All rights reserved. 4 | 5 | import sys 6 | sys.path.insert(1, "..") 7 | 8 | from SOAPpy import * 9 | from SOAPpy import Parser 10 | 11 | # Uncomment to see outgoing HTTP headers and SOAP and incoming 12 | #Config.debug = 1 13 | 14 | if len(sys.argv) > 1 and sys.argv[1] == '-s': 15 | server = SOAPProxy("https://localhost:9900") 16 | else: 17 | server = SOAPProxy("http://localhost:9900") 18 | 19 | 20 | # BIG data: 21 | 22 | big = repr('.' * (1<<18) ) 23 | 24 | # ...in an object 25 | print "server.echo_ino(big):..", 26 | tmp = server.echo_ino(big) 27 | print "done" 28 | 29 | # ...in an object in an object 30 | print "server.prop.echo2(big)..", 31 | tmp = server.prop.echo2(big) 32 | print "done" 33 | 34 | # ...with keyword arguments 35 | print 'server.echo_wkw(third = big, first = "one", second = "two")..', 36 | tmp = server.echo_wkw(third = big, first = "one", second = "two") 37 | print "done" 38 | 39 | # ...with a context object 40 | print "server.echo_wc(big)..", 41 | tmp = server.echo_wc(big) 42 | print "done" 43 | 44 | # ...with a header 45 | hd = headerType(data = {"mystring": "Hello World"}) 46 | print "server._hd(hd).echo_wc(big)..", 47 | tmp = server._hd(hd).echo_wc(big) 48 | print "done" 49 | 50 | server.quit() 51 | -------------------------------------------------------------------------------- /tests/newsTest.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | ident = '$Id: newsTest.py,v 1.4 2003/05/21 14:52:37 warnes Exp $' 4 | 5 | import os, re 6 | import sys 7 | sys.path.insert(1, "..") 8 | 9 | from SOAPpy import SOAPProxy 10 | 11 | # Check for a web proxy definition in environment 12 | try: 13 | proxy_url=os.environ['http_proxy'] 14 | phost, pport = re.search('http://([^:]+):([0-9]+)', proxy_url).group(1,2) 15 | proxy = "%s:%s" % (phost, pport) 16 | except: 17 | proxy = None 18 | 19 | SoapEndpointURL = 'http://www22.brinkster.com/prasads/BreakingNewsService.asmx?WSDL' 20 | 21 | MethodNamespaceURI = 'http://tempuri.org/' 22 | 23 | # Three ways to do namespaces, force it at the server level 24 | 25 | server = SOAPProxy(SoapEndpointURL, namespace = MethodNamespaceURI, 26 | soapaction='http://tempuri.org/GetCNNNews', encoding = None, 27 | http_proxy=proxy) 28 | print "[server level CNN News call]" 29 | print server.GetCNNNews() 30 | 31 | # Do it inline ala SOAP::LITE, also specify the actually ns (namespace) and 32 | # sa (soapaction) 33 | 34 | server = SOAPProxy(SoapEndpointURL, encoding = None) 35 | print "[inline CNNNews call]" 36 | print server._ns('ns1', 37 | MethodNamespaceURI)._sa('http://tempuri.org/GetCNNNews').GetCNNNews() 38 | 39 | # Create an instance of your server with specific namespace and then use 40 | # inline soapactions for each call 41 | 42 | dq = server._ns(MethodNamespaceURI) 43 | print "[namespaced CNNNews call]" 44 | print dq._sa('http://tempuri.org/GetCNNNews').GetCNNNews() 45 | print "[namespaced CBSNews call]" 46 | print dq._sa('http://tempuri.org/GetCBSNews').GetCBSNews() 47 | -------------------------------------------------------------------------------- /tests/quoteTest.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | # Copyright (c) 2001 actzero, inc. All rights reserved. 4 | ident = '$Id: quoteTest.py,v 1.5 2003/12/18 06:31:50 warnes Exp $' 5 | 6 | import os, re 7 | import sys 8 | sys.path.insert(1, "..") 9 | 10 | from SOAPpy import SOAPProxy 11 | 12 | # Check for a web proxy definition in environment 13 | try: 14 | proxy_url=os.environ['http_proxy'] 15 | phost, pport = re.search('http://([^:]+):([0-9]+)', proxy_url).group(1,2) 16 | proxy = "%s:%s" % (phost, pport) 17 | except: 18 | proxy = None 19 | 20 | # Three ways to do namespaces, force it at the server level 21 | 22 | server = SOAPProxy("http://services.xmethods.com:9090/soap", 23 | namespace = 'urn:xmethods-delayed-quotes', 24 | http_proxy=proxy) 25 | 26 | print "IBM>>", server.getQuote(symbol = 'IBM') 27 | 28 | # Do it inline ala SOAP::LITE, also specify the actually ns 29 | 30 | server = SOAPProxy("http://services.xmethods.com:9090/soap", 31 | http_proxy=proxy) 32 | print "IBM>>", server._ns('ns1', 33 | 'urn:xmethods-delayed-quotes').getQuote(symbol = 'IBM') 34 | 35 | # Create a namespaced version of your server 36 | 37 | dq = server._ns('urn:xmethods-delayed-quotes') 38 | print "IBM>>", dq.getQuote(symbol='IBM') 39 | print "ORCL>>", dq.getQuote(symbol='ORCL') 40 | print "INTC>>", dq.getQuote(symbol='INTC') 41 | -------------------------------------------------------------------------------- /tests/simpleWSDL.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | sys.path.insert(1, "..") 4 | import SOAPpy 5 | 6 | url = 'http://www.xmethods.org/sd/2001/TemperatureService.wsdl' 7 | zip = '06340' 8 | proxy = SOAPpy.WSDL.Proxy(url) 9 | temp = proxy.getTemp(zip) 10 | print 'Temperature at', zip, 'is', temp 11 | -------------------------------------------------------------------------------- /tests/speedTest.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | ident = '$Id: speedTest.py,v 1.4 2003/05/21 14:52:37 warnes Exp $' 4 | 5 | import time 6 | import sys 7 | sys.path.insert(1, "..") 8 | 9 | x=''' 13 | 14 | 15 | USA 16 | japan 17 | 18 | 19 | ''' 20 | 21 | x2=''' 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | West Virginia 33 | -546 34 | -5.398 35 | 36 | 37 | New Mexico 38 | -641 39 | -9.351 40 | 41 | 42 | Missouri 43 | -819 44 | 1.495 45 | 46 | 47 | 48 | ''' 49 | 50 | # Import in function, because for some reason they slow each other 51 | # down in same namespace ??? 52 | def SOAPParse(inxml): 53 | from SOAPpy import parseSOAPRPC 54 | t= time.time() 55 | parseSOAPRPC(inxml) 56 | return time.time()-t 57 | 58 | def SAXParse(inxml): 59 | import xml.sax 60 | y = xml.sax.handler.ContentHandler() 61 | t= time.time() 62 | xml.sax.parseString(inxml,y) 63 | return time.time()-t 64 | 65 | def DOMParse(inxml): 66 | import xml.dom.minidom 67 | t= time.time() 68 | xml.dom.minidom.parseString(inxml) 69 | return time.time()-t 70 | 71 | # Wierd but the SAX parser runs really slow the first time. 72 | # Probably got to load a c module or something 73 | SAXParse(x) 74 | print 75 | print "Simple XML" 76 | print "SAX Parse, no marshalling ", SAXParse(x) 77 | print "SOAP Parse, and marshalling ", SOAPParse(x) 78 | print "DOM Parse, no marshalling ", DOMParse(x) 79 | print 80 | print "Complex XML (references)" 81 | print "SAX Parse, no marshalling ", SAXParse(x2) 82 | print "SOAP Parse, and marshalling ", SOAPParse(x2) 83 | print "DOM Parse, no marshalling ", DOMParse(x2) 84 | -------------------------------------------------------------------------------- /tests/storageTest.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | ident = '$Id: storageTest.py,v 1.6 2005/02/16 04:24:54 warnes Exp $' 4 | 5 | import sys, os, time, signal, re 6 | sys.path.insert(1, "..") 7 | from SOAPpy import SOAPProxy, SOAPConfig, SOAPUserAgent 8 | 9 | # Check for a web proxy definition in environment 10 | try: 11 | proxy_url=os.environ['http_proxy'] 12 | phost, pport = re.search('http://([^:]+):([0-9]+)', proxy_url).group(1,2) 13 | http_proxy = "%s:%s" % (phost, pport) 14 | except: 15 | http_proxy = None 16 | 17 | 18 | PROXY="http://www.soapware.org/xmlStorageSystem" 19 | EMAIL="SOAPpy@actzero.com" 20 | NAME="test_user" 21 | PASSWORD="mypasswd" 22 | SERIAL=1123214 23 | 24 | MY_PORT=15600 25 | 26 | def resourceChanged (url): 27 | print "\n##### NOTIFICATION MESSAGE: Resource %s has changed #####\n" % url 28 | return booleanType(1) 29 | 30 | def printstatus (cmd, stat): 31 | print 32 | if stat.flError: 33 | print "### %s failed: %s ###" % (cmd, stat.message) 34 | else: 35 | print "### %s successful: %s ###" % (cmd, stat.message) 36 | return not stat.flError 37 | 38 | server = SOAPProxy(encoding="US-ASCII", 39 | proxy=PROXY, 40 | soapaction="/xmlStorageSystem", 41 | http_proxy=http_proxy, 42 | # config=SOAPConfig(debug=1) 43 | ) 44 | 45 | # Register as a new user or update user information 46 | reg = server.registerUser(email=EMAIL, name=NAME, password=PASSWORD, 47 | clientPort=MY_PORT, userAgent=SOAPUserAgent(), 48 | serialnumber=SERIAL) 49 | printstatus("registerUser", reg) 50 | 51 | # See what this server can do 52 | reg = server.getServerCapabilities (email=EMAIL, password=PASSWORD) 53 | if printstatus("getServerCapabilities", reg): 54 | print "Legal file extensions: " + str(reg.legalFileExtensions) 55 | print "Maximum file size: " + str(reg.maxFileSize) 56 | print "Maximum bytes per user: " + str(reg.maxBytesPerUser) 57 | print "Number of bytes in use by the indicated user: " + str(reg.ctBytesInUse) 58 | print "URL of the folder containing your files: " + str(reg.yourUpstreamFolderUrl) 59 | 60 | # Store some files 61 | reg = server.saveMultipleFiles (email=EMAIL, password=PASSWORD, 62 | relativepathList=['index.html','again.html'], 63 | fileTextList=['bennett@actzero.com home page' + 64 | 'Hello Earth', 65 | 'bennett@actzero.com home page' + 66 | 'Hello Earth Again']) 67 | if printstatus("saveMultipleFiles", reg): 68 | print "Files stored:" 69 | for file in reg.urlList: 70 | print " %s" % file 71 | 72 | # Save this for call to test pleaseNotify 73 | mylist = reg.urlList 74 | else: 75 | mylist = [] 76 | 77 | # Check to see what files are stored 78 | reg = server.getMyDirectory (email=EMAIL, password=PASSWORD) 79 | if printstatus("getMyDirectory", reg): 80 | i = 1 81 | while hasattr(reg.directory, "file%05d" % i): 82 | d = getattr(reg.directory, "file%05d" % i) 83 | print "Relative Path: %s" % d.relativePath 84 | print "Size: %d" % d.size 85 | print "Created: %s" % d.whenCreated 86 | print "Last Uploaded: %s" % d.whenLastUploaded 87 | print "URL: %s" % d.url 88 | print 89 | i += 1 90 | 91 | # Set up notification 92 | reg = server.pleaseNotify(notifyProcedure="resourceChanged", port=MY_PORT, path="/", protocol="soap", urlList=mylist) 93 | printstatus("notifyProcedure", reg) 94 | 95 | pid = os.fork() 96 | if pid == 0: 97 | # I am a child process. Set up SOAP server to receive notification 98 | print 99 | print "## Starting notification server ##" 100 | 101 | s = SOAPServer(('localhost', MY_PORT)) 102 | s.registerFunction(resourceChanged) 103 | s.serve_forever() 104 | 105 | else: 106 | 107 | def handler(signum, frame): 108 | # Kill child process 109 | print "Killing child process %d" % pid 110 | os.kill(pid, signal.SIGINT) 111 | 112 | signal.signal(signal.SIGINT, handler) 113 | 114 | # I am a parent process 115 | # Change some files 116 | time.sleep(3) 117 | reg = server.saveMultipleFiles (email=EMAIL, password=PASSWORD, 118 | relativepathList=['index.html'], 119 | fileTextList=['bennett@actzero.com home page' + 120 | 'Hello Bennett']) 121 | if printstatus("saveMultipleFiles", reg): 122 | print "Files stored:" 123 | for file in reg.urlList: 124 | print " %s" % file 125 | 126 | os.waitpid(pid, 0) 127 | -------------------------------------------------------------------------------- /tests/testClient1.py: -------------------------------------------------------------------------------- 1 | import gc 2 | import socket 3 | import threading 4 | import time 5 | import unittest 6 | import sys 7 | sys.path.insert(1, "..") 8 | 9 | import SOAPpy 10 | #SOAPpy.Config.debug=1 11 | 12 | # global to shut down server 13 | quit = 0 14 | 15 | def echoDateTime(dt): 16 | return dt 17 | 18 | def echo(s): 19 | """repeats a string twice""" 20 | return s + s 21 | 22 | def kill(): 23 | """tell the server to quit""" 24 | global quit 25 | quit = 1 26 | 27 | def server1(): 28 | """start a SOAP server on localhost:8000""" 29 | 30 | print "Starting SOAP Server...", 31 | server = SOAPpy.Server.SOAPServer(addr=('127.0.0.1', 8000)) 32 | server.registerFunction(echoDateTime) 33 | server.registerFunction(echo) 34 | server.registerFunction(kill) 35 | print "Done." 36 | 37 | global quit 38 | while not quit: 39 | server.handle_request() 40 | quit = 0 41 | print "Server shut down." 42 | 43 | class ClientTestCase(unittest.TestCase): 44 | 45 | server = None 46 | startup_timeout = 5 # seconds 47 | 48 | def setUp(self): 49 | '''This is run once before each unit test.''' 50 | 51 | serverthread = threading.Thread(target=server1, name="SOAPServer") 52 | serverthread.start() 53 | 54 | start = time.time() 55 | connected = False 56 | server = None 57 | while not connected and time.time() - start < self.startup_timeout: 58 | print "Trying to connect to the SOAP server...", 59 | try: 60 | server = SOAPpy.Client.SOAPProxy('127.0.0.1:8000') 61 | server.echo('Hello World') 62 | except socket.error, e: 63 | print "Failure:", e 64 | time.sleep(0.5) 65 | else: 66 | connected = True 67 | self.server = server 68 | print "Success." 69 | 70 | if not connected: raise 'Server failed to start.' 71 | 72 | def tearDown(self): 73 | '''This is run once after each unit test.''' 74 | 75 | print "Trying to shut down SOAP server..." 76 | if self.server is not None: 77 | self.server.kill() 78 | time.sleep(5) 79 | 80 | return 1 81 | 82 | def testEcho(self): 83 | '''Test echo function.''' 84 | 85 | server = SOAPpy.Client.SOAPProxy('127.0.0.1:8000') 86 | s = 'Hello World' 87 | self.assertEquals(server.echo(s), s+s) 88 | 89 | def testNamedEcho(self): 90 | '''Test echo function.''' 91 | 92 | server = SOAPpy.Client.SOAPProxy('127.0.0.1:8000') 93 | s = 'Hello World' 94 | self.assertEquals(server.echo(s=s), s+s) 95 | 96 | def testEchoDateTime(self): 97 | '''Test passing DateTime objects.''' 98 | 99 | server = SOAPpy.Client.SOAPProxy('127.0.0.1:8000') 100 | dt = SOAPpy.Types.dateTimeType(data=time.time()) 101 | dt_return = server.echoDateTime(dt) 102 | self.assertEquals(dt_return, dt) 103 | 104 | 105 | # def testNoLeak(self): 106 | # '''Test for memory leak.''' 107 | 108 | # gc.set_debug(gc.DEBUG_SAVEALL) 109 | # for i in range(400): 110 | # server = SOAPpy.Client.SOAPProxy('127.0.0.1:8000') 111 | # s = 'Hello World' 112 | # server.echo(s) 113 | # gc.collect() 114 | # self.assertEquals(len(gc.garbage), 0) 115 | 116 | 117 | if __name__ == '__main__': 118 | unittest.main() 119 | -------------------------------------------------------------------------------- /tests/testWSDL.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import unittest 4 | import os, re 5 | import sys 6 | sys.path.insert (1, '..') 7 | import SOAPpy 8 | 9 | ident = '$Id: testWSDL.py,v 1.2 2003/05/09 12:46:11 warnes Exp $' 10 | 11 | # Check for a web proxy definition in environment 12 | try: 13 | proxy_url=os.environ['http_proxy'] 14 | phost, pport = re.search('http://([^:]+):([0-9]+)', proxy_url).group(1,2) 15 | http_proxy = "%s:%s" % (phost, pport) 16 | except: 17 | http_proxy = None 18 | 19 | 20 | 21 | class IntegerArithmenticTestCase(unittest.TestCase): 22 | 23 | def setUp(self): 24 | self.wsdlstr1 = ''' 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | Returns current temperature in a given U.S. zipcode 52 | 53 | 54 | 55 | 56 | 57 | ''' 58 | 59 | def testParseWsdlString(self): 60 | '''Parse XMethods TemperatureService wsdl from a string.''' 61 | 62 | wsdl = SOAPpy.WSDL.Proxy(self.wsdlstr1, http_proxy=http_proxy) 63 | self.assertEquals(len(wsdl.methods), 1) 64 | method = wsdl.methods.values()[0] 65 | self.assertEquals(method.methodName, 'getTemp') 66 | self.assertEquals(method.namespace, 'urn:xmethods-Temperature') 67 | self.assertEquals(method.location, 68 | 'http://services.xmethods.net:80/soap/servlet/rpcrouter') 69 | 70 | def testParseWsdlFile(self): 71 | '''Parse XMethods TemperatureService wsdl from a file.''' 72 | 73 | # figure out path to the test directory 74 | dir = os.path.abspath('.') 75 | fname = './TemperatureService.wsdl' 76 | 77 | try: 78 | f = file(fname) 79 | except (IOError, OSError): 80 | self.assert_(0, 'Cound not find wsdl file "%s"' % file) 81 | 82 | wsdl = SOAPpy.WSDL.Proxy(fname, http_proxy=http_proxy) 83 | self.assertEquals(len(wsdl.methods), 1) 84 | method = wsdl.methods.values()[0] 85 | self.assertEquals(method.methodName, 'getTemp') 86 | self.assertEquals(method.namespace, 'urn:xmethods-Temperature') 87 | self.assertEquals(method.location, 88 | 'http://services.xmethods.net:80/soap/servlet/rpcrouter') 89 | 90 | def testParseWsdlUrl(self): 91 | '''Parse XMethods TemperatureService wsdl from a url.''' 92 | 93 | wsdl = SOAPpy.WSDL.Proxy('http://www.xmethods.net/sd/2001/TemperatureService.wsdl', http_proxy=http_proxy) 94 | self.assertEquals(len(wsdl.methods), 1) 95 | method = wsdl.methods.values()[0] 96 | self.assertEquals(method.methodName, 'getTemp') 97 | self.assertEquals(method.namespace, 'urn:xmethods-Temperature') 98 | self.assertEquals(method.location, 99 | 'http://services.xmethods.net:80/soap/servlet/rpcrouter') 100 | 101 | def testGetTemp(self): 102 | '''Parse TemperatureService and call getTemp.''' 103 | 104 | zip = '01072' 105 | proxy = SOAPpy.WSDL.Proxy(self.wsdlstr1, http_proxy=http_proxy) 106 | temp = proxy.getTemp(zip) 107 | print 'Temperature at', zip, 'is', temp 108 | 109 | 110 | if __name__ == '__main__': 111 | unittest.main() 112 | 113 | -------------------------------------------------------------------------------- /tests/testleak.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | import sys 4 | sys.path.insert(1, "..") 5 | import SOAPpy 6 | import time 7 | import gc 8 | import types 9 | 10 | gc.set_debug(gc.DEBUG_SAVEALL) 11 | 12 | for i in range(400): 13 | try: 14 | t = SOAPpy.SOAP.parseSOAPRPC('bad soap payload') 15 | except: pass 16 | 17 | gc.collect() 18 | if len(gc.garbage): 19 | print 'still leaking' 20 | else: 21 | print 'no leak' 22 | -------------------------------------------------------------------------------- /tests/testsclient.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | __docformat__ = 'restructuredtext en' 4 | #!/usr/bin/env python 5 | # coding:utf-8 6 | 7 | from SOAPpy import SOAPProxy 8 | server = SOAPProxy("http://localhost:8080/") 9 | print server.echo("Hello world") 10 | 11 | # vim:set et sts=4 ts=4 tw=80: 12 | -------------------------------------------------------------------------------- /tests/testserver.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | __docformat__ = 'restructuredtext en' 4 | #!/usr/bin/env python 5 | # encoding:utf-8 6 | from SOAPpy import SOAPServer 7 | def echo(s): 8 | return s # repeats a string twice 9 | server = SOAPServer(("0.0.0.0", 8080)) 10 | server.registerFunction(echo) 11 | server.serve_forever() 12 | 13 | # vim:set et sts=4 ts=4 tw=80: 14 | -------------------------------------------------------------------------------- /tests/translateTest.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | # Copyright (c) 2001 actzero, inc. All rights reserved. 4 | ident = '$Id: translateTest.py,v 1.5 2003/05/21 14:52:37 warnes Exp $' 5 | 6 | import os, re 7 | import sys 8 | sys.path.insert(1, "..") 9 | 10 | from SOAPpy import SOAPProxy 11 | 12 | # Check for a web proxy definition in environment 13 | try: 14 | proxy_url=os.environ['http_proxy'] 15 | phost, pport = re.search('http://([^:]+):([0-9]+)', proxy_url).group(1,2) 16 | proxy = "%s:%s" % (phost, pport) 17 | except: 18 | proxy = None 19 | 20 | server = SOAPProxy("http://services.xmethods.com:80/perl/soaplite.cgi", 21 | http_proxy=proxy) 22 | babel = server._ns('urn:xmethodsBabelFish#BabelFish') 23 | 24 | print babel.BabelFish(translationmode = "en_fr", 25 | sourcedata = "The quick brown fox did something or other") 26 | -------------------------------------------------------------------------------- /tests/vul_etcpasswd.txt: -------------------------------------------------------------------------------- 1 | POST / HTTP/1.0 2 | Host: localhost:8080 3 | User-agent: SOAPpy 0.12.0 (pywebsvcs.sf.net) 4 | Content-type: text/xml; charset="UTF-8" 5 | Content-length: 10000000 6 | SOAPAction: "echo" 7 | 8 | 9 | ]> 10 | 16 | 17 | 18 | &xxe; aaa 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /tests/vul_lol.txt: -------------------------------------------------------------------------------- 1 | POST / HTTP/1.0 2 | Host: localhost:8080 3 | User-agent: SOAPpy 0.12.0 (pywebsvcs.sf.net) 4 | Content-type: text/xml; charset="UTF-8" 5 | Content-length: 10000000 6 | SOAPAction: "echo" 7 | 8 | 9 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | ]> 20 | 27 | 28 | 29 | &lol9; 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /tests/weatherTest.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | ident = '$Id: weatherTest.py,v 1.4 2003/05/21 14:52:37 warnes Exp $' 4 | 5 | import os, re 6 | import sys 7 | sys.path.insert(1, "..") 8 | 9 | from SOAPpy import SOAPProxy 10 | 11 | # Check for a web proxy definition in environment 12 | try: 13 | proxy_url=os.environ['http_proxy'] 14 | phost, pport = re.search('http://([^:]+):([0-9]+)', proxy_url).group(1,2) 15 | proxy = "%s:%s" % (phost, pport) 16 | except: 17 | proxy = None 18 | 19 | SoapEndpointURL = 'http://services.xmethods.net:80/soap/servlet/rpcrouter' 20 | MethodNamespaceURI = 'urn:xmethods-Temperature' 21 | 22 | # Do it inline ala SOAP::LITE, also specify the actually ns 23 | 24 | server = SOAPProxy(SoapEndpointURL, http_proxy=proxy) 25 | print "inline", server._ns('ns1', MethodNamespaceURI).getTemp(zipcode='94063') 26 | -------------------------------------------------------------------------------- /tests/whoisTest.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | ident = '$Id: whoisTest.py,v 1.4 2003/05/21 14:52:37 warnes Exp $' 4 | 5 | import os, re 6 | import sys 7 | sys.path.insert(1, "..") 8 | 9 | from SOAPpy import SOAPProxy 10 | 11 | # Check for a web proxy definition in environment 12 | try: 13 | proxy_url=os.environ['http_proxy'] 14 | phost, pport = re.search('http://([^:]+):([0-9]+)', proxy_url).group(1,2) 15 | proxy = "%s:%s" % (phost, pport) 16 | except: 17 | proxy = None 18 | 19 | server = SOAPProxy("http://www.SoapClient.com/xml/SQLDataSoap.WSDL", 20 | http_proxy=proxy) 21 | 22 | print "whois>>", server.ProcessSRL(SRLFile="WHOIS.SRI", 23 | RequestName="whois", 24 | key = "microsoft.com") 25 | 26 | -------------------------------------------------------------------------------- /tests/xmethods.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | # Copyright (c) 2001 actzero, inc. All rights reserved. 4 | ident = '$Id: xmethods.py,v 1.4 2003/12/18 06:31:50 warnes Exp $' 5 | 6 | import os, re 7 | import sys 8 | sys.path.insert(1, "..") 9 | 10 | from SOAPpy import SOAPProxy 11 | 12 | # Check for a web proxy definition in environment 13 | try: 14 | proxy_url=os.environ['http_proxy'] 15 | phost, pport = re.search('http://([^:]+):([0-9]+)', proxy_url).group(1,2) 16 | proxy = "%s:%s" % (phost, pport) 17 | except: 18 | proxy = None 19 | 20 | 21 | print "##########################################" 22 | print " SOAP services registered at xmethods.net" 23 | print "##########################################" 24 | 25 | server = SOAPProxy("http://www.xmethods.net/interfaces/query", 26 | namespace = 'urn:xmethods-delayed-quotes', 27 | http_proxy=proxy) 28 | 29 | names = server.getAllServiceNames() 30 | 31 | for item in names: 32 | print 'name:', item['name'] 33 | print 'id :', item['id'] 34 | print 35 | -------------------------------------------------------------------------------- /tools/.cvsignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | -------------------------------------------------------------------------------- /tools/interop2html.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import string 4 | import cgi 5 | 6 | ident = '$Id: interop2html.py 4 2001-06-27 21:36:11Z cullman $' 7 | 8 | lines = open('output.txt').readlines() 9 | #preserve the tally 10 | tally = lines[-6:] 11 | #whack the tally from lines 12 | lines = lines[:-6] 13 | table={} 14 | for line in lines: 15 | if line[:3] == ' ' or line == '>\n' : continue 16 | line = line[:-1] #delete end of line char 17 | row = [line[:line.find(': ')], line[line.find(': ')+2:]] #split server name from rest of line 18 | restofrow = row[1].split(' ',3) #break out method name, number, status code, status comment 19 | if len(restofrow) > 3: 20 | if restofrow[3].find('as expected') != -1: 21 | restofrow[2] = restofrow[2] + ' (as expected)' 22 | elif restofrow[3][:2] == '- ' : 23 | restofrow[3] = restofrow[3][2:] 24 | try: table[row[0]].append([restofrow[0],restofrow[2:]]) 25 | except KeyError: table[row[0]] = [[restofrow[0],restofrow[2:]]] 26 | 27 | print "" 28 | print "" 34 | print "
" 35 | for x in tally: 36 | z = x[:-1].split(":",1) 37 | print "" 38 | print "
Summary
",z[0],"",z[1],"

" 39 | c = 0 40 | totalmethods = len(table[table.keys()[0]]) 41 | while c < totalmethods: 42 | print "
" 43 | print "" 44 | cols = [c, c + 1, c + 2] 45 | if c != 16: 46 | cols += [c + 3] 47 | for i in cols: 48 | try: header = table[table.keys()[0]][i][0] 49 | except: break 50 | print "" 51 | print "" 52 | l = table.keys() 53 | l.sort() 54 | for key in l: 55 | print "" 56 | for i in cols: 57 | try: status = table[key][i][1][0] 58 | except: break 59 | if status.find("succeed") != -1: 60 | bgcolor = "#339900" 61 | status = "Pass" 62 | elif status.find("expected") != -1: 63 | bgcolor = "#FF9900" 64 | hreftitle = table[key][i][1][1].replace("'","") # remove apostrophes from title properties 65 | popuphtml = '"' + cgi.escape(cgi.escape(table[key][i][1][1]).replace("'","'").replace('"',""")) + '"' 66 | status = "Failed (expected)" 67 | else: 68 | bgcolor = "#CC0000" 69 | hreftitle = table[key][i][1][1].replace("'","") # remove apostrophes from title properties 70 | popuphtml = '"' + cgi.escape(cgi.escape(table[key][i][1][1]).replace("'","'").replace('"',""")) + '"' 71 | status = "Failed" 72 | print "" 73 | print "" 74 | print "
",header,"
", key , "" , status , "
" 75 | c = c + len(cols) 76 | print "" 77 | -------------------------------------------------------------------------------- /validate/.cvsignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | -------------------------------------------------------------------------------- /validate/server.pem: -------------------------------------------------------------------------------- 1 | $Id: server.pem 4 2001-06-27 21:36:11Z cullman $ 2 | # Test certificate generated using CA.pl written by Steve Hensen 3 | # bundled with OpenSSL. 4 | # 5 | # Steps used to generate server.pem : 6 | # a)CA.pl -newca (creates a new CA heirarchy) 7 | # b)CA.pl -newreq (creates a new certificate request) 8 | # c)CA.pl -sign (sign the certificate request) 9 | # d)openssl rsa newkey.pem (unencrypt the private key) 10 | # e)Copy the certificate from newcert.pem, the unencrypted RSA 11 | # private key from newkey.pem and the certificate request from 12 | # newreq.pem and create server.pem to contain all three of them. 13 | -----BEGIN CERTIFICATE----- 14 | MIIDhjCCAu+gAwIBAgIBATANBgkqhkiG9w0BAQQFADCBgDELMAkGA1UEBhMCVVMx 15 | CzAJBgNVBAgTAkNBMQswCQYDVQQHEwJSQzEQMA4GA1UEChMHYWN0emVybzETMBEG 16 | A1UECxMKdGVjaG5vbG9neTEPMA0GA1UEAxMGc3lzYWRtMR8wHQYJKoZIhvcNAQkB 17 | FhBpbmZvQGFjdHplcm8uY29tMB4XDTAxMDUxNjIyMzkwM1oXDTAyMDUxNjIyMzkw 18 | M1owgYAxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTELMAkGA1UEBxMCUkMxEDAO 19 | BgNVBAoTB2FjdHplcm8xEzARBgNVBAsTCnRlY2hub2xvZ3kxDzANBgNVBAMTBnN5 20 | c2FkbTEfMB0GCSqGSIb3DQEJARYQaW5mb0BhY3R6ZXJvLmNvbTCBnzANBgkqhkiG 21 | 9w0BAQEFAAOBjQAwgYkCgYEAyRBB6l+DI3aMNeYf7IuodvZ9nNxnfQHVnGyRtwhb 22 | 1g2tugTwFsE67oHA5qvwaDBILtsqkr9agXYDbZwJmV58xtBY675tibf7/1R8mcDO 23 | d4Dremdn0CMyk4+n6Z8GpLJ59TZ3y98DXUOqbLvzzltDz0si2XVa8G7f4K5k/xxB 24 | GZcCAwEAAaOCAQwwggEIMAkGA1UdEwQCMAAwLAYJYIZIAYb4QgENBB8WHU9wZW5T 25 | U0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0GA1UdDgQWBBT/DGQzyXlwLXMWMaT4 26 | lp9O928tvzCBrQYDVR0jBIGlMIGigBSdjwZua1AI3XoUtwLyW0Optc/4O6GBhqSB 27 | gzCBgDELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMQswCQYDVQQHEwJSQzEQMA4G 28 | A1UEChMHYWN0emVybzETMBEGA1UECxMKdGVjaG5vbG9neTEPMA0GA1UEAxMGc3lz 29 | YWRtMR8wHQYJKoZIhvcNAQkBFhBpbmZvQGFjdHplcm8uY29tggEAMA0GCSqGSIb3 30 | DQEBBAUAA4GBABQodV+rrwMsvTEEza08EeS1Rf2ISuzh6e9VbfiJLVB5Xv1SeEt1 31 | sOv8ETZyN/4OXvZWQG/5md/5NNkf5K6CeKiwctztkyKTXdPIFS6FJVZdduWhiWPF 32 | 6gutQgOogtpCHTLwdSDk75n5MXFlnehORqOREMqqCJtFlHMEV1211Ssi 33 | -----END CERTIFICATE----- 34 | -----BEGIN RSA PRIVATE KEY----- 35 | MIICWwIBAAKBgQDJEEHqX4Mjdow15h/si6h29n2c3Gd9AdWcbJG3CFvWDa26BPAW 36 | wTrugcDmq/BoMEgu2yqSv1qBdgNtnAmZXnzG0Fjrvm2Jt/v/VHyZwM53gOt6Z2fQ 37 | IzKTj6fpnwaksnn1NnfL3wNdQ6psu/POW0PPSyLZdVrwbt/grmT/HEEZlwIDAQAB 38 | AoGALcho6gBjsRCObrt+63MFokkQY0aAviNLy7mhGIdrufsVYvU64kOPsr2S+jOO 39 | o3rTBPBc6ltuNWp072GHggfU61y4Bvfqxq2IRRDVH+yjmsdKSPYoBSIs3ZKjwJGx 40 | pFAT1nfNP05MfqUwZm8HbTnqqakrWm0p53Zvv6NP3vNjmzECQQD6EK5a7bD7VSVz 41 | MawUgUkZGZUtForbZL5nwIo1j94/TbnxUuuwej0MiCJ0MQsPCY/LML/gYaxTdQOg 42 | qYkGyIAPAkEAzdXbgTc81FflECxc5CXw9Yi1g0+nMkH5drlk+sct5dCzokPJZBQ3 43 | oxIaQcJP/rUMgG0A2mSpOnbAHNHX+z/F+QJAEQGbafGqTJ1wy5HAOzDDsOJNg+B5 44 | lwwV6uZsP9JF8hYuJBxYjQrzJewIM9C2CNLEpbPuCKt71b0qfv2opP5zvwJAMyjh 45 | WveAvgJuo5tzJx2rC0wEWXPVya8OMw0XZSFWbhV2YHFav+4qefSI5ClIurUDO3Rc 46 | TuvQCAD19PPPK9qI+QJADpbLUWw8NsMaHpJgeigXVIsRtJcroDw2r87bJxsgcgQz 47 | CsIH32VLvFOmpJdwnji6GX+vD2i0UH4ythnMCq4NUg== 48 | -----END RSA PRIVATE KEY----- 49 | -----BEGIN CERTIFICATE REQUEST----- 50 | MIIBwTCCASoCAQAwgYAxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTELMAkGA1UE 51 | BxMCUkMxEDAOBgNVBAoTB2FjdHplcm8xEzARBgNVBAsTCnRlY2hub2xvZ3kxDzAN 52 | BgNVBAMTBnN5c2FkbTEfMB0GCSqGSIb3DQEJARYQaW5mb0BhY3R6ZXJvLmNvbTCB 53 | nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAyRBB6l+DI3aMNeYf7IuodvZ9nNxn 54 | fQHVnGyRtwhb1g2tugTwFsE67oHA5qvwaDBILtsqkr9agXYDbZwJmV58xtBY675t 55 | ibf7/1R8mcDOd4Dremdn0CMyk4+n6Z8GpLJ59TZ3y98DXUOqbLvzzltDz0si2XVa 56 | 8G7f4K5k/xxBGZcCAwEAAaAAMA0GCSqGSIb3DQEBBAUAA4GBAIoUVScm4lAkfo1o 57 | n4b2Mpq3oV+dZnnTgYog4vmn/2UF0OSSTWlWPvINVkRtfg0iskZsbcWGn+RDY5e/ 58 | aTqN7Xz+BV5XlbQLZzuQdKPsfBcZ766El1chmUuO5tELpFtQkmlAgAXRMuh0Xeb+ 59 | A9wmVNyCMU6/+ajqwO642nSPOLM0 60 | -----END CERTIFICATE REQUEST----- 61 | -------------------------------------------------------------------------------- /validate/silab.servers: -------------------------------------------------------------------------------- 1 | # This list of servers was taken from the SOAPBuilders Interoperability Lab 2 | # (http://www.xmethods.net/ilab/ilab.html) 4/23/01. 3 | # 4 | # $Id: silab.servers 4 2001-06-27 21:36:11Z cullman $ 5 | 6 | Name: SOAP.py 0.9.6 (1999) 7 | Endpoint: http://208.177.157.221:9595/xmethodsInterop 8 | SOAPAction: "urn:soapinterop" 9 | Namespace: http://soapinterop.org/ 10 | 11 | Name: SOAP.py 0.9.6 (2001) 12 | Like: SOAP.py 0.9.6 (1999) 13 | Style: 2001 14 | 15 | Name: Apache 2.1 16 | WSDL: http://www.xmethods.net/sd/interop/ApacheInterop11.wsdl 17 | Endpoint: http://nagoya.apache.org:5089/soap/servlet/rpcrouter 18 | SOAPAction: "urn:soapinterop" 19 | Namespace: http://soapinterop.org/ 20 | Nonfunctional: echoFloatINF server returns 'Infinity' instead of 'INF' 21 | Nonfunctional: echoFloatNegINF server returns '-Infinity' instead of '-INF' 22 | Nonfunctional: echoStruct WSDL specifies 'inputStruct' parameter, method 23 | takes 'echoStruct' parameter 24 | Nonfunctional: echoDate not implemented by server 25 | Nonfunctional: echoBase64 not implemented by server 26 | 27 | Name: EasySoap++ 28 | WSDL: http://easysoap.sourceforge.net/interop.wsdl 29 | Endpoint: http://www.xmethods.net/c/easysoap.cgi 30 | SOAPAction: "urn:soapinterop" 31 | Namespace: http://soapinterop.org/ 32 | Nonfunctional: actorShouldFail server doesn't fail when mustUnderstand=1 33 | Nonfunctional: mustUnderstandEqualsOne server doesn't fail when 34 | mustUnderstand=1 35 | 36 | Name: eSoapServer 37 | Endpoint: http://www.connecttel.com/cgi-bin/esoapserver.cgi 38 | SOAPAction: "urn:soapinterop" 39 | Namespace: http://soapinterop.org/ 40 | 41 | Name: Frontier 7.0b43 42 | Endpoint: http://www.soapware.org:80/xmethodsInterop 43 | SOAPAction: "/xmethodsInterop" 44 | Namespace: http://soapinterop.org/ 45 | Style: 2001 46 | 47 | Name: 4S4C 1.3.3 48 | WSDL: http://soap.4s4c.com/ilab/soap.asp?WSDL 49 | Endpoint: http://soap.4s4c.com/ilab/soap.asp 50 | SOAPAction: "urn:soapinterop" 51 | Namespace: http://soapinterop.org/ 52 | Nonfunctional: echoFloatINF server doesn't understand 'INF' 53 | Nonfunctional: echoFloatNaN server doesn't understand 'NaN' 54 | Nonfunctional: echoFloatNegINF server doesn't understand '-INF' 55 | 56 | Name: GLUE 57 | WSDL: http://209.61.190.164:8004/glue/http://soapinterop.org/.wsdl 58 | Endpoint: http://209.61.190.164:8004/glue/http://soapinterop.org/ 59 | SOAPAction: "urn:soapinterop" 60 | Namespace: http://soapinterop.org/ 61 | Nonfunctional: actorShouldFail server doesn't fail when mustUnderstand=1 62 | Nonfunctional: mustUnderstandEqualsOne server doesn't fail when 63 | mustUnderstand=1 64 | 65 | Name: HP SOAP 66 | Page: http://soap.bluestone.com/interop/ 67 | WSDL: http://soap.bluestone.com:80/interop/EchoService/EchoService.wsdl 68 | Endpoint: http://soap.bluestone.com:80/scripts/SaISAPI.dll/SaServletEngine.class/hp-soap/soap/rpc/interop/EchoService 69 | SOAPAction: "urn:soapinterop" 70 | Namespace: http://soapinterop.org/ 71 | 72 | Name: IDOOX WASP 1.0 73 | Page: http://soap.idoox.net:7080/IopResults/jsp/index.jsp 74 | WSDL: http://soap.idoox.net:7080/soap/services/ilab.wsdl 75 | Endpoint: http://soap.idoox.net:7080/soap/servlet/soap/ilab 76 | SOAPAction: "urn:soapinterop" 77 | Namespace: http://soapinterop.org/ 78 | 79 | Name: Kafka XSLT Interop Service 80 | Page: http://www.vbxml.com/soapworkshop/services/kafka10/services/interop.htm 81 | WSDL: http://www.vbxml.com/soapworkshop/services/kafka10/services/endpoint.asp?service=ilab&type=wsdl 82 | Endpoint: http://www.vbxml.com/soapworkshop/services/kafka10/services/endpoint.asp?service=ilab 83 | SOAPAction: "urn:soapinterop" 84 | Namespace: http://soapinterop.org/ 85 | Nonfunctional: actorShouldFail server doesn't fail when mustUnderstand=1 86 | Nonfunctional: echoDate not implemented by server 87 | Nonfunctional: echoBase64 not implemented by server 88 | Nonfunctional: mustUnderstandEqualsOne server doesn't fail when 89 | mustUnderstand=1 90 | 91 | Name: MS ATL Server 92 | WSDL: http://4.34.185.52/ilab/ilab.wsdl 93 | Endpoint: http://4.34.185.52/ilab/ilab.dll?Handler=Default 94 | SOAPAction: "urn:soapinterop" 95 | Namespace: http://soapinterop.org/ 96 | Style: 2001 97 | Typed: no 98 | 99 | Name: MS SOAP Toolkit 2.0 (typed) 100 | Page: http://www.mssoapinterop.org/stk/ilab.htm 101 | WSDL: http://www.mssoapinterop.org/stk/InteropTyped.wsdl 102 | Endpoint: http://www.mssoapinterop.org/stk/InteropTyped.wsdl 103 | SOAPAction: "urn:soapinterop" 104 | Namespace: http://soapinterop.org/ 105 | Nonfunctional: echoBase64 return value doesn't have a type 106 | Nonfunctional: echoFloatINF server doesn't understand 'INF' 107 | Nonfunctional: echoFloatNaN server doesn't understand 'NaN' 108 | Nonfunctional: echoFloatNegINF server doesn't understand '-INF' 109 | 110 | Name: MS SOAP Toolkit 2.0 (untyped) 111 | Like: MS SOAP Toolkit 2.0 (typed) 112 | WSDL: http://www.mssoapinterop.org/stk/Interop.wsdl 113 | Endpoint: http://www.mssoapinterop.org/stk/Interop.wsdl 114 | Typed: no 115 | Functional: echoBase64 116 | 117 | Name: MS .NET Beta 2 (typed) 118 | WSDL: http://www.mssoapinterop.org/test/typed.asmx?WSDL 119 | Endpoint: http://www.mssoapinterop.org/test/typed.asmx 120 | SOAPAction: "http://soapinterop.org/%(methodname)s" 121 | Namespace: http://soapinterop.org/ 122 | Nonfunctional: actorShouldFail server doesn't fail when mustUnderstand=1 123 | Nonfunctional: mustUnderstandEqualsOne server doesn't fail when 124 | mustUnderstand=1 125 | Nonfunctional: echoDate server doesn't recognize time zone of Z 126 | Nonfunctional: echoBase64 not implemented by server 127 | 128 | Name: MS .NET Beta 2 (untyped) 129 | Like: MS .NET Beta 2 (typed) 130 | WSDL: http://www.mssoapinterop.org/test/simple.asmx?WSDL 131 | Endpoint: http://www.mssoapinterop.org/test/simple.asmx 132 | Typed: no 133 | 134 | Name: MS .NET Remoting (1999 typed) 135 | WSDL: http://www.mssoapinterop.org/DotNetRemoting1999Typed/InteropService.WSDL 136 | Endpoint: http://www.mssoapinterop.org/DotNetRemoting1999Typed/InteropService.soap 137 | SOAPAction: "urn:soapinterop" 138 | Namespace: http://soapinterop.org/ 139 | 140 | Name: MS .NET Remoting (1999 untyped) 141 | WSDL: http://www.mssoapinterop.org/DotNetRemoting1999/InteropService.WSDL 142 | Endpoint: http://www.mssoapinterop.org/DotNetRemoting1999/InteropService.soap 143 | SOAPAction: "urn:soapinterop" 144 | Namespace: http://soapinterop.org/ 145 | Typed: no 146 | 147 | Name: MS .NET Remoting (2001 typed) 148 | WSDL: http://www.mssoapinterop.org/DotNetRemoting2001Typed/InteropService.WSDL 149 | Endpoint: http://www.mssoapinterop.org/DotNetRemoting2001Typed/InteropService.soap 150 | SOAPAction: "urn:soapinterop" 151 | Namespace: http://soapinterop.org/ 152 | Style: 2001 153 | 154 | Name: MS .NET Remoting (2001 untyped) 155 | WSDL: http://www.mssoapinterop.org/DotNetRemoting2001/InteropService.WSDL 156 | Endpoint: http://www.mssoapinterop.org/DotNetRemoting2001/InteropService.soap 157 | SOAPAction: "urn:soapinterop" 158 | Namespace: http://soapinterop.org/ 159 | Typed: no 160 | Style: 2001 161 | 162 | Name: Phalanx 163 | WSDL: http://www.phalanxsys.com/interop/interop.wsdl 164 | Endpoint: http://www.phalanxsys.com/interop/listener.asp 165 | SOAPAction: "urn:soapinterop" 166 | Namespace: http://soapinterop.org/ 167 | Style: 2001 168 | 169 | Name: SOAP::Lite 170 | WSDL: http://services.soaplite.com/interop.wsdl 171 | Endpoint: http://services.soaplite.com/interop.cgi 172 | SOAPAction: "urn:soapinterop" 173 | Namespace: http://soapinterop.org/ 174 | 175 | Name: SOAPR4 (1999) 176 | Endpoint: http://www.jin.gr.jp/~nahi/Ruby/SOAP4R/SOAPBuildersInterop/1999/ 177 | SOAPAction: "urn:soapinterop" 178 | Namespace: http://soapinterop.org/ 179 | Nonfunctional: actorShouldFail server doesn't fail when mustUnderstand=1 180 | Nonfunctional: mustUnderstandEqualsOne server doesn't fail when 181 | mustUnderstand=1 182 | Nonfunctional: echoVoid server return nil element instead of no elements 183 | 184 | Name: SOAPR4 (2001) 185 | Like: SOAPR4 (1999) 186 | Endpoint: http://www.jin.gr.jp/~nahi/Ruby/SOAP4R/SOAPBuildersInterop/ 187 | Style: 2001 188 | 189 | Name: SOAPx4 for PHP 190 | Endpoint: http://dietrich.ganx4.com/soapx4/soap.php 191 | SOAPAction: "urn:soapinterop" 192 | Namespace: http://soapinterop.org/ 193 | Nonfunctional: actorShouldPass server returns type with no namespace 194 | Nonfunctional: actorShouldFail server doesn't fail when mustUnderstand=1 195 | Nonfunctional: echoDate not implemented by server 196 | Nonfunctional: echoBase64 not implemented by server 197 | Nonfunctional: echoFloat server returns type with no namespace 198 | Nonfunctional: echoFloatArray server returns array elements as strings 199 | Nonfunctional: echoFloatINF server returns type with no namespace 200 | Nonfunctional: echoFloatNaN server returns type with no namespace 201 | Nonfunctional: echoFloatNegINF returns float 0 instead of -INF and type 202 | has no namespace 203 | Nonfunctional: echoFloatNegZero returns 0 instead of -0 and type has no 204 | namespace 205 | Nonfunctional: echoInteger server returns type with no namespace 206 | Nonfunctional: echoIntegerArray server returns array elements as strings 207 | Nonfunctional: echoString server responds with fault when sent '<&>" 208 | Nonfunctional: echoStringArray server responds with fault when an array 209 | element is '<&>" 210 | Nonfunctional: echoVeryLargeFloat server returns type with no namespace 211 | Nonfunctional: echoVerySmallFloat server returns type with no namespace 212 | Nonfunctional: echoVoid server doesn't return anything 213 | Nonfunctional: mustUnderstandEqualsOne server doesn't fail when 214 | mustUnderstand=1 215 | Nonfunctional: mustUnderstandEqualsZero server returns type with no namespace 216 | 217 | Name: SoapRMI 218 | Endpoint: http://rainier.extreme.indiana.edu:1568 219 | SOAPAction: "urn:soapinterop" 220 | Namespace: http://soapinterop.org/ 221 | Nonfunctional: echoDate not implemented by server 222 | Nonfunctional: echoBase64 not implemented by server 223 | 224 | Name: SQLData SOAP Server 225 | WSDL: http://www.SoapClient.com/interop/SQLDataInterop.wsdl 226 | Endpoint: http://www.soapclient.com/interop/sqldatainterop.wsdl 227 | SOAPAction: "urn:soapinterop" 228 | Namespace: http://soapinterop.org/ 229 | 230 | Name: White Mesa SOAP RPC 2.2 (1999) 231 | WSDL: http://www.whitemesa.net/wsdl/interop.wsdl 232 | Endpoint: http://www.whitemesa.net/interop 233 | SOAPAction: "urn:soapinterop" 234 | Namespace: http://soapinterop.org/ 235 | Nonfunctional: echoFloatINF server doesn't understand 'INF' 236 | Nonfunctional: echoFloatNaN server doesn't understand 'NaN' 237 | Nonfunctional: echoFloatNegINF server doesn't understand '-INF' 238 | Nonfunctional: echoDate not implemented by server 239 | Nonfunctional: echoBase64 server returns data containing control character 240 | Style: 1999 241 | Typed: no 242 | 243 | Name: White Mesa SOAP RPC 2.2 (2001) 244 | WSDL: http://www.whitemesa.net/wsdl/std/interop.wsdl 245 | Endpoint: http://www.whitemesa.net/interop/std 246 | SOAPAction: http://soapinterop.org/ 247 | Namespace: http://soapinterop.org/ 248 | Nonfunctional: echoFloatINF server doesn't understand 'INF' 249 | Nonfunctional: echoFloatNaN server doesn't understand 'NaN' 250 | Nonfunctional: echoFloatNegINF server doesn't understand '-INF' 251 | Nonfunctional: echoDate not implemented by server 252 | Nonfunctional: echoBase64 server returns data containing control character 253 | Style: 2001 254 | Typed: no 255 | 256 | Name: Zolera SOAP Infrastructure 257 | Endpoint: http://63.142.188.184:7000/ 258 | SOAPAction: urn:soapinterop 259 | Namespace: http://soapinterop.org/ 260 | Style: 2001 261 | Nonfunctional: actorShouldPass server claims message is unparsable 262 | Nonfunctional: echoBase64 server returns data with invalid type 263 | Nonfunctional: echoVoid server doesn't return an empty return value 264 | Nonfunctional: mustUnderstandEqualsZero server claims message is unparsable 265 | -------------------------------------------------------------------------------- /validate/silabserver.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | # Copyright (c) 2001 actzero, inc. All rights reserved. 4 | 5 | # This is a server for the XMethods matrix 6 | # (http://jake.soapware.org/currentXmethodsResults). 7 | 8 | import getopt 9 | import sys 10 | 11 | sys.path.insert (1, '..') 12 | 13 | from SOAPpy import SOAP 14 | 15 | if SOAP.Config.SSLserver: 16 | from M2Crypto import SSL 17 | 18 | ident = '$Id: silabserver.py 98 2003-03-08 05:10:01Z warnes $' 19 | 20 | def echoFloat (inputFloat): 21 | return inputFloat 22 | 23 | def echoFloatArray (inputFloatArray): 24 | return inputFloatArray 25 | 26 | def echoInteger (inputInteger): 27 | return inputInteger 28 | 29 | def echoIntegerArray (inputIntegerArray): 30 | return inputIntegerArray 31 | 32 | def echoString (inputString): 33 | return inputString 34 | 35 | def echoStringArray (inputStringArray): 36 | return inputStringArray 37 | 38 | def echoStruct (inputStruct): 39 | return inputStruct 40 | 41 | def echoStructArray (inputStructArray): 42 | return inputStructArray 43 | 44 | def echoVoid (): 45 | return SOAP.voidType() 46 | 47 | def echoDate (inputDate): 48 | return SOAP.dateTimeType (inputDate) 49 | 50 | def echoBase64 (inputBase64): 51 | return SOAP.binaryType (inputBase64) 52 | 53 | namespace = 'http://soapinterop.org/' 54 | 55 | DEFAULT_HOST = 'localhost' 56 | DEFAULT_HTTP_PORT = 8080 57 | DEFAULT_HTTPS_PORT = 8443 58 | 59 | def usage (error = None): 60 | sys.stdout = sys.stderr 61 | 62 | if error != None: 63 | print error 64 | 65 | print """usage: %s [options] 66 | If a long option shows an argument is mandatory, it's mandatory for the 67 | equivalent short option also. The default (if any) is shown in brackets. 68 | 69 | -?, --help display this usage 70 | -h, --host=HOST use HOST in the address to listen on [%s] 71 | -p, --port=PORT listen on PORT [%d] 72 | """ % (sys.argv[0], DEFAULT_HOST, DEFAULT_HTTP_PORT), 73 | 74 | if SOAP.Config.SSLserver: 75 | print " -s, --ssl serve using SSL" 76 | 77 | sys.exit (0) 78 | 79 | def main (): 80 | host = DEFAULT_HOST 81 | port = None 82 | ssl = 0 83 | 84 | try: 85 | opts = '?h:p:' 86 | args = ['help', 'host', 'port'] 87 | 88 | if SOAP.Config.SSLserver: 89 | opts += 's' 90 | args += ['ssl'] 91 | 92 | opts, args = getopt.getopt (sys.argv[1:], opts, args) 93 | 94 | for opt, arg in opts: 95 | if opt in ('-?', '--help'): 96 | usage () 97 | elif opt in ('-h', '--host'): 98 | host = arg 99 | elif opt in ('-p', '--port'): 100 | port = int (arg) 101 | elif opt in ('-s', '--ssl'): 102 | ssl = 1 103 | else: 104 | raise AttributeError, \ 105 | "Recognized but unimplemented option `%s'" % opt 106 | except SystemExit: 107 | raise 108 | except: 109 | usage (sys.exc_info ()[1]) 110 | 111 | if port == None: 112 | port = [DEFAULT_HTTP_PORT, DEFAULT_HTTPS_PORT][ssl] 113 | 114 | if ssl: 115 | ssl_context = SSL.Context() 116 | ssl_context.load_cert('server.pem') 117 | else: 118 | ssl_context = None 119 | 120 | server = SOAP.SOAPServer ((host, port), namespace = namespace, 121 | ssl_context = ssl_context) 122 | 123 | server.registerFunction (echoFloat) 124 | server.registerFunction (echoFloatArray) 125 | server.registerFunction (echoInteger) 126 | server.registerFunction (echoIntegerArray) 127 | server.registerFunction (echoString) 128 | server.registerFunction (echoStringArray) 129 | server.registerFunction (echoStruct) 130 | server.registerFunction (echoStructArray) 131 | server.registerFunction (echoVoid) 132 | server.registerFunction (echoDate) 133 | server.registerFunction (echoBase64) 134 | 135 | server.serve_forever() 136 | 137 | if __name__ == '__main__': 138 | try: 139 | sys.exit (main ()) 140 | except KeyboardInterrupt: 141 | sys.exit (0) 142 | -------------------------------------------------------------------------------- /validate/soapware.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | # This server validates as of 4/23/01 when run with UserLand's SOAP validator 4 | # (http://validator.soapware.org/). 5 | 6 | import getopt 7 | import sys 8 | 9 | sys.path.insert (1, '..') 10 | 11 | from SOAPpy import SOAP 12 | 13 | ident = '$Id: soapware.py 98 2003-03-08 05:10:01Z warnes $' 14 | 15 | def whichToolkit (): 16 | return SOAP.SOAPUserAgent () 17 | 18 | def countTheEntities (s): 19 | counts = {'ctLeftAngleBrackets': 0, 'ctRightAngleBrackets': 0, 20 | 'ctAmpersands': 0, 'ctApostrophes': 0, 'ctQuotes': 0} 21 | 22 | for i in s: 23 | if i == '<': 24 | counts['ctLeftAngleBrackets'] += 1 25 | elif i == '>': 26 | counts['ctRightAngleBrackets'] += 1 27 | elif i == '&': 28 | counts['ctAmpersands'] += 1 29 | elif i == "'": 30 | counts['ctApostrophes'] += 1 31 | elif i == '"': 32 | counts['ctQuotes'] += 1 33 | 34 | return counts 35 | 36 | def easyStructTest (stooges): 37 | return stooges['larry'] + stooges['moe'] + stooges['curly'] 38 | 39 | def echoStructTest (myStruct): 40 | return myStruct 41 | 42 | def manyTypesTest (num, bool, state, doub, dat, bin): 43 | return [num, SOAP.booleanType (bool), state, doub, 44 | SOAP.dateTimeType (dat), bin] 45 | 46 | def moderateSizeArrayCheck (myArray): 47 | return myArray[0] + myArray[-1] 48 | 49 | def nestedStructTest (myStruct): 50 | return easyStructTest (myStruct.year2000.month04.day01) 51 | 52 | def simpleStructReturnTest (myNumber): 53 | return {'times10': myNumber * 10, 'times100': myNumber * 100, 54 | 'times1000': myNumber * 1000} 55 | 56 | namespace = 'http://www.soapware.org/' 57 | 58 | DEFAULT_HOST = 'localhost' 59 | DEFAULT_PORT = 8080 60 | 61 | def usage (error = None): 62 | sys.stdout = sys.stderr 63 | 64 | if error != None: 65 | print error 66 | 67 | print """usage: %s [options] 68 | If a long option shows an argument is mandatory, it's mandatory for the 69 | equivalent short option also. The default (if any) is shown in brackets. 70 | 71 | -?, --help display this usage 72 | -h, --host=HOST use HOST in the address to listen on [%s] 73 | -p, --port=PORT listen on PORT [%d] 74 | """ % (sys.argv[0], DEFAULT_HOST, DEFAULT_PORT), 75 | 76 | sys.exit (0) 77 | 78 | def main (): 79 | host = DEFAULT_HOST 80 | port = DEFAULT_PORT 81 | 82 | try: 83 | opts, args = getopt.getopt (sys.argv[1:], '?h:p:', 84 | ['help', 'host', 'port']) 85 | 86 | for opt, arg in opts: 87 | if opt in ('-?', '--help'): 88 | usage () 89 | elif opt in ('-h', '--host'): 90 | host = arg 91 | elif opt in ('-p', '--port'): 92 | port = int (arg) 93 | else: 94 | raise AttributeError, \ 95 | "Recognized but unimplemented option `%s'" % opt 96 | except SystemExit: 97 | raise 98 | except: 99 | usage (sys.exc_info ()[1]) 100 | 101 | server = SOAP.SOAPServer ((host, port)) 102 | 103 | server.registerFunction (whichToolkit, namespace) 104 | server.registerFunction (countTheEntities) 105 | server.registerFunction (easyStructTest) 106 | server.registerFunction (echoStructTest) 107 | server.registerFunction (manyTypesTest) 108 | server.registerFunction (moderateSizeArrayCheck) 109 | server.registerFunction (nestedStructTest) 110 | server.registerFunction (simpleStructReturnTest) 111 | 112 | server.serve_forever() 113 | 114 | if __name__ == '__main__': 115 | try: 116 | sys.exit (main ()) 117 | except KeyboardInterrupt: 118 | sys.exit (0) 119 | -------------------------------------------------------------------------------- /vul_ok.txt: -------------------------------------------------------------------------------- 1 | POST / HTTP/1.0 2 | Host: localhost:8080 3 | User-agent: SOAPpy 0.12.0 (pywebsvcs.sf.net) 4 | Content-type: text/xml; charset="UTF-8" 5 | Content-length: 484 6 | SOAPAction: "echo" 7 | 8 | 9 | 16 | 17 | 18 | Hello world 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /zope/README: -------------------------------------------------------------------------------- 1 | Using SOAP with ZOPE 2 | -------------------- 3 | 4 | We can use Zope to provide web services. The first is to support SOAP like 5 | XML-RPC. There are two patches for Zope 2.5.0 version and for Zope 2.6.2 6 | version. To apply the path, you only need to do: 7 | 8 | $ cd 9 | $ patch -p1 < //zope-2.6.2-soappy.diff 10 | 11 | You need to install SOAPpy and fpconst. You can download this two packages 12 | from here: 13 | 14 | http://sourceforge.net/projects/pywebsvcs 15 | http://software.biostat.washington.edu/statsoft/snake/fpconst/ 16 | 17 | If you are using the precompiled version of Zope, you need to add the path 18 | to the PYTHONPATH environment variable to specify where this packages 19 | lives. 20 | To do this, add a line like this to your start script: 21 | 22 | export PYTHONPATH=$PYTHONPATH:/usr/lib/python2.3/site-packages/ 23 | 24 | Note: This can be dangerous because in your machine you are using several 25 | versions of python. 26 | 27 | [NB: The contents of this directory contributed by Antonio Beamud 28 | Montero ] 29 | -------------------------------------------------------------------------------- /zope/zope-2.5.0-soappy.diff: -------------------------------------------------------------------------------- 1 | diff -urN Zope-2.5.0-linux2-x86/lib/python/ZPublisher/HTTPRequest.py Zope-2.5.0-linux2-x86.1/lib/python/ZPublisher/HTTPRequest.py 2 | --- Zope-2.5.0-linux2-x86/lib/python/ZPublisher/HTTPRequest.py 2002-01-03 20:41:05.000000000 +0100 3 | +++ Zope-2.5.0-linux2-x86.1/lib/python/ZPublisher/HTTPRequest.py 2003-11-12 13:17:57.000000000 +0100 4 | @@ -21,6 +21,7 @@ 5 | from Converters import get_converter 6 | from maybe_lock import allocate_lock 7 | xmlrpc=None # Placeholder for module that we'll import if we have to. 8 | +soap=None 9 | 10 | #cgi hotfix: 11 | if not hasattr(cgi, 'valid_boundary'): 12 | @@ -347,18 +348,28 @@ 13 | meth=None 14 | fs=FieldStorage(fp=fp,environ=environ,keep_blank_values=1) 15 | if not hasattr(fs,'list') or fs.list is None: 16 | - # Hm, maybe it's an XML-RPC 17 | - if (fs.headers.has_key('content-type') and 18 | - fs.headers['content-type'] == 'text/xml' and 19 | + # Hm, maybe it's an XML-RPC or SOAP 20 | + if (fs.headers.has_key('content-type') and 21 | + fs.headers['content-type'][:8] == 'text/xml' and 22 | method == 'POST'): 23 | - # Ye haaa, XML-RPC! 24 | - global xmlrpc 25 | - if xmlrpc is None: import xmlrpc 26 | - meth, self.args = xmlrpc.parse_input(fs.value) 27 | - response=xmlrpc.response(response) 28 | - other['RESPONSE']=self.response=response 29 | - other['REQUEST_METHOD']='' # We don't want index_html! 30 | - self.maybe_webdav_client = 0 31 | + if environ.has_key('HTTP_SOAPACTION'): 32 | + # this is a SOAP request 33 | + global soap 34 | + if soap is None: 35 | + import soap 36 | + meth, self.args = soap.parse_input(fs.value) 37 | + response = soap.response(response) 38 | + other['RESPONSE'] = self.response = response 39 | + other['REQUEST_METHOD'] = '' 40 | + else: 41 | + # Ye haaa, XML-RPC! 42 | + global xmlrpc 43 | + if xmlrpc is None: import xmlrpc 44 | + meth, self.args = xmlrpc.parse_input(fs.value) 45 | + response=xmlrpc.response(response) 46 | + other['RESPONSE']=self.response=response 47 | + other['REQUEST_METHOD']='' # We don't want index_html! 48 | + self.maybe_webdav_client = 0 49 | else: 50 | self._file=fs.file 51 | else: 52 | diff -urN Zope-2.5.0-linux2-x86/lib/python/ZPublisher/soap.py Zope-2.5.0-linux2-x86.1/lib/python/ZPublisher/soap.py 53 | --- Zope-2.5.0-linux2-x86/lib/python/ZPublisher/soap.py 1970-01-01 01:00:00.000000000 +0100 54 | +++ Zope-2.5.0-linux2-x86.1/lib/python/ZPublisher/soap.py 2003-11-12 13:20:39.000000000 +0100 55 | @@ -0,0 +1,108 @@ 56 | +"""SOAP support module 57 | + 58 | +by Antonio Beamud Montero 59 | + 60 | +Based on the XML-RPC Zope support module written by Eric Kidd at UserLand 61 | +software and the modifications made by Petru Paler, with much help 62 | +from Jim Fulton at DC. 63 | + 64 | +This code hooks Zope up to SOAPpy library. 65 | +""" 66 | + 67 | +import sys 68 | +from string import replace 69 | +from HTTPResponse import HTTPResponse 70 | +from SOAPpy import * 71 | +from zLOG import LOG, PROBLEM, ERROR, DEBUG, INFO,TRACE 72 | + 73 | +Config.specialArgs=0. 74 | + 75 | +def parse_input(data): 76 | + """Parse input data and return a method path and argument tuple 77 | + 78 | + The data is a string. 79 | + """ 80 | + obj = Parser.parseSOAPRPC(data) 81 | + method = obj._name 82 | + args = tuple(obj._aslist) 83 | + 84 | + # Translate '.' to '/' in meth to represent object traversal. 85 | + method = replace(method, '.', '/') 86 | + return method, args 87 | + 88 | +####################################################################### 89 | +# New Object response based on SOAPpy 90 | +# 91 | +class SOAPResponse: 92 | + def __init__(self, real): self.__dict__['_real']=real 93 | + def __getattr__(self, name): return getattr(self._real, name) 94 | + def __setattr__(self, name, v): return setattr(self._real, name, v) 95 | + def __delattr__(self, name): return delattr(self._real, name) 96 | + 97 | + def setBody(self, body, title='', is_error=0, bogus_str_search=None): 98 | + # Marshall our body as an SOAP response. Strings will be sent 99 | + # strings, integers as integers, etc. We do *not* convert 100 | + # everything to a string first. 101 | + status = 200 102 | + if isinstance(body, Types.faultType): 103 | + status = 500 104 | + # Convert Fault object to SOAP response. 105 | + soapbody = Types.faulType("%s:Server" % NS.ENV_T, body) 106 | + body = buildSOAP(soapbody,encoding=None) 107 | + else: 108 | + try: 109 | + body = buildSOAP((body,),encoding=None) 110 | + except Exception,e: 111 | + self.exception() 112 | + return self 113 | + 114 | + t = 'text/xml' 115 | + # Set our body to the XML-RPC message, and fix our MIME type. 116 | + self._real.setBody(body) 117 | + self._real.setHeader('content-type', t) 118 | + self._real.setHeader("content-length", str(len(body))) 119 | + self._real.setStatus(status) 120 | + return self 121 | + 122 | + def exception(self, fatal=0, info=None, 123 | + absuri_match=None, tag_search=None): 124 | + # Fetch our exception info. t is type, v is value and tb is the 125 | + # traceback object. 126 | + 127 | + if type(info) is type(()) and len(info)==3: t,v,tb = info 128 | + else: t,v,tb = sys.exc_info() 129 | + LOG('SOAPException', TRACE, tb) 130 | + # Create an appropriate Fault object. Unfortunately, we throw away 131 | + # most of the debugging information. More useful error reporting is 132 | + # left as an exercise for the reader. 133 | + Fault=Types.faultType 134 | + f=None 135 | + try: 136 | + if isinstance(v, Fault): 137 | + f=v 138 | + elif isinstance(v, Exception): 139 | + f=Fault("%s:Server" % NS.ENV_T, 140 | + "Unexpected Zope exception: %s"%str(v)) 141 | + else: 142 | + f=Fault("%s:Server" % NS.ENV_T, 143 | + "Unexpected Zope error value: %s"%str(v)) 144 | + except: 145 | + f=Fault("%s:Server" % NS.ENV_T, 146 | + "Unknown Zope fault type") 147 | + 148 | + # Do the damage. 149 | + body = buildSOAP(f) 150 | + self._real.setBody(body) 151 | + self._real.setHeader('content-type', 'text/xml') 152 | + self._real.setStatus(500) 153 | + return tb 154 | + 155 | +response=SOAPResponse 156 | + 157 | + 158 | + 159 | + 160 | + 161 | + 162 | + 163 | + 164 | -------------------------------------------------------------------------------- /zope/zope-2.6.2-soappy.diff: -------------------------------------------------------------------------------- 1 | diff -urN Zope-2.6.2-linux2-x86/lib/python/ZPublisher/HTTPRequest.py Zope-2.6.2-linux2-x86.1/lib/python/ZPublisher/HTTPRequest.py 2 | --- Zope-2.6.2-linux2-x86/lib/python/ZPublisher/HTTPRequest.py 2003-04-09 16:00:27.000000000 +0200 3 | +++ Zope-2.6.2-linux2-x86.1/lib/python/ZPublisher/HTTPRequest.py 2003-11-12 14:51:01.000000000 +0100 4 | @@ -24,6 +24,7 @@ 5 | from TaintedString import TaintedString 6 | from maybe_lock import allocate_lock 7 | xmlrpc=None # Placeholder for module that we'll import if we have to. 8 | +soap=None # Placeholder for module that we'll import if we have to. 9 | 10 | #cgi hotfix: 11 | if not hasattr(cgi, 'valid_boundary'): 12 | @@ -369,16 +370,26 @@ 13 | meth=None 14 | fs=FieldStorage(fp=fp,environ=environ,keep_blank_values=1) 15 | if not hasattr(fs,'list') or fs.list is None: 16 | - # Hm, maybe it's an XML-RPC 17 | + # Hm, maybe it's an XML-RPC or SOAP 18 | if (fs.headers.has_key('content-type') and 19 | - fs.headers['content-type'] == 'text/xml' and 20 | + fs.headers['content-type'][:8] == 'text/xml' and 21 | method == 'POST'): 22 | - # Ye haaa, XML-RPC! 23 | - global xmlrpc 24 | - if xmlrpc is None: import xmlrpc 25 | - meth, self.args = xmlrpc.parse_input(fs.value) 26 | - response=xmlrpc.response(response) 27 | - other['RESPONSE']=self.response=response 28 | + if environ.has_key('HTTP_SOAPACTION'): 29 | + # this is a SOAP request 30 | + global soap 31 | + if soap is None: 32 | + import soap 33 | + meth, self.args = soap.parse_input(fs.value) 34 | + response = soap.response(response) 35 | + other['RESPONSE'] = self.response = response 36 | + other['REQUEST_METHOD'] = '' 37 | + else: 38 | + # Ye haaa, XML-RPC! 39 | + global xmlrpc 40 | + if xmlrpc is None: import xmlrpc 41 | + meth, self.args = xmlrpc.parse_input(fs.value) 42 | + response=xmlrpc.response(response) 43 | + other['RESPONSE']=self.response=response 44 | self.maybe_webdav_client = 0 45 | else: 46 | self._file=fs.file 47 | diff -urN Zope-2.6.2-linux2-x86/lib/python/ZPublisher/soap.py Zope-2.6.2-linux2-x86.1/lib/python/ZPublisher/soap.py 48 | --- Zope-2.6.2-linux2-x86/lib/python/ZPublisher/soap.py 1970-01-01 01:00:00.000000000 +0100 49 | +++ Zope-2.6.2-linux2-x86.1/lib/python/ZPublisher/soap.py 2003-11-12 14:51:01.000000000 +0100 50 | @@ -0,0 +1,125 @@ 51 | +"""SOAP support module 52 | + 53 | +by Antonio Beamud Montero 54 | + 55 | +Based on the XML-RPC Zope support module written by Eric Kidd at UserLand 56 | +software and the modifications made by Petru Paler, with much help 57 | +from Jim Fulton at DC. 58 | + 59 | +This code hooks Zope up to SOAPpy library. 60 | +""" 61 | + 62 | +import sys 63 | +from string import replace 64 | +from HTTPResponse import HTTPResponse 65 | +from SOAPpy import * 66 | +from zLOG import LOG, PROBLEM, ERROR, DEBUG, INFO,TRACE 67 | + 68 | +Config.specialArgs=0. 69 | + 70 | +def parse_input(data): 71 | + """Parse input data and return a method path and argument tuple 72 | + 73 | + The data is a string. 74 | + """ 75 | + obj = Parser.parseSOAPRPC(data) 76 | + method = obj._name 77 | + args = tuple(obj._aslist) 78 | + 79 | + # Translate '.' to '/' in meth to represent object traversal. 80 | + method = replace(method, '.', '/') 81 | + return method, args 82 | + 83 | +# See below 84 | +# 85 | +# def response(anHTTPResponse): 86 | +# """Return a valid ZPublisher response object 87 | +# 88 | +# Use data already gathered by the existing response. 89 | +# The new response will replace the existing response. 90 | +# """ 91 | +# # As a first cut, lets just clone the response and 92 | +# # put all of the logic in our refined response class below. 93 | +# r=Response() 94 | +# r.__dict__.update(anHTTPResponse.__dict__) 95 | +# return r 96 | + 97 | + 98 | + 99 | + 100 | +####################################################################### 101 | +# New Object response based on SoapPy 102 | +# 103 | +class SOAPResponse: 104 | + def __init__(self, real): self.__dict__['_real']=real 105 | + def __getattr__(self, name): return getattr(self._real, name) 106 | + def __setattr__(self, name, v): return setattr(self._real, name, v) 107 | + def __delattr__(self, name): return delattr(self._real, name) 108 | + 109 | + def setBody(self, body, title='', is_error=0, bogus_str_search=None): 110 | + # Marshall our body as an SOAP response. Strings will be sent 111 | + # strings, integers as integers, etc. We do *not* convert 112 | + # everything to a string first. 113 | + status = 200 114 | + if isinstance(body, Types.faultType): 115 | + status = 500 116 | + # Convert Fault object to SOAP response. 117 | + soapbody = Types.faulType("%s:Server" % NS.ENV_T, body) 118 | + body = buildSOAP(soapbody,encoding=None) 119 | + else: 120 | + try: 121 | + body = buildSOAP((body,),encoding=None) 122 | + except Exception,e: 123 | + self.exception() 124 | + return self 125 | + 126 | + t = 'text/xml' 127 | + # Set our body to the XML-RPC message, and fix our MIME type. 128 | + self._real.setBody(body) 129 | + self._real.setHeader('content-type', t) 130 | + self._real.setHeader("content-length", str(len(body))) 131 | + self._real.setStatus(status) 132 | + return self 133 | + 134 | + def exception(self, fatal=0, info=None, 135 | + absuri_match=None, tag_search=None): 136 | + # Fetch our exception info. t is type, v is value and tb is the 137 | + # traceback object. 138 | + 139 | + if type(info) is type(()) and len(info)==3: t,v,tb = info 140 | + else: t,v,tb = sys.exc_info() 141 | + LOG('SOAPException', TRACE, tb) 142 | + # Create an appropriate Fault object. Unfortunately, we throw away 143 | + # most of the debugging information. More useful error reporting is 144 | + # left as an exercise for the reader. 145 | + Fault=Types.faultType 146 | + f=None 147 | + try: 148 | + if isinstance(v, Fault): 149 | + f=v 150 | + elif isinstance(v, Exception): 151 | + f=Fault("%s:Server" % NS.ENV_T, 152 | + "Unexpected Zope exception: %s"%str(v)) 153 | + else: 154 | + f=Fault("%s:Server" % NS.ENV_T, 155 | + "Unexpected Zope error value: %s"%str(v)) 156 | + except: 157 | + f=Fault("%s:Server" % NS.ENV_T, 158 | + "Unknown Zope fault type") 159 | + 160 | + # Do the damage. 161 | + body = buildSOAP(f) 162 | + self._real.setBody(body) 163 | + self._real.setHeader('content-type', 'text/xml') 164 | + self._real.setStatus(500) 165 | + return tb 166 | + 167 | +response=SOAPResponse 168 | + 169 | + 170 | + 171 | + 172 | + 173 | + 174 | + 175 | + 176 | -------------------------------------------------------------------------------- /zope/zope-soap-client.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import sys 4 | from SOAPpy import SOAP 5 | 6 | # Uncomment to see outgoing HTTP headers and SOAP and incoming SOAP. 7 | SOAP.Config.debug = 1 8 | 9 | SOAP.Config.BuildWithNoType = 0 10 | SOAP.Config.BuildWithNoNamespacePrefix = 0 11 | 12 | if len(sys.argv) > 1 and sys.argv[1] == '-s': 13 | server = SOAP.SOAPProxy("https://localhost:8080") 14 | else: 15 | server = SOAP.SOAPProxy("http://admin:pw3340@localhost:8080/",encoding=None) 16 | 17 | x = server.sopa() 18 | print x 19 | --------------------------------------------------------------------------------