aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorhsbt <hsbt@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2016-05-16 02:41:11 +0000
committerhsbt <hsbt@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2016-05-16 02:41:11 +0000
commit0f5050c513d616dfcb5a0eee9549e4d3d5061414 (patch)
tree004c8510182e620692051a84f1ee34e276a5107a /lib
parent38bd293b267c3e457c137dc75b100bd7a7d14d46 (diff)
downloadruby-0f5050c513d616dfcb5a0eee9549e4d3d5061414.tar.gz
* lib/xmlrpc.rb, lib/xmlrpc/*, test/xmlrpc: XMLRPC is bundled gem
on Ruby 2.4. [Feature #12160][ruby-core:74239] * gems/bundled_gems: ditto. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@55013 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'lib')
-rw-r--r--lib/xmlrpc.rb291
-rw-r--r--lib/xmlrpc/base64.rb63
-rw-r--r--lib/xmlrpc/client.rb629
-rw-r--r--lib/xmlrpc/config.rb39
-rw-r--r--lib/xmlrpc/create.rb287
-rw-r--r--lib/xmlrpc/datetime.rb130
-rw-r--r--lib/xmlrpc/marshal.rb67
-rw-r--r--lib/xmlrpc/parser.rb642
-rw-r--r--lib/xmlrpc/server.rb708
-rw-r--r--lib/xmlrpc/utils.rb172
10 files changed, 0 insertions, 3028 deletions
diff --git a/lib/xmlrpc.rb b/lib/xmlrpc.rb
deleted file mode 100644
index 94d93a18b9..0000000000
--- a/lib/xmlrpc.rb
+++ /dev/null
@@ -1,291 +0,0 @@
-# frozen_string_literal: false
-# == Author and Copyright
-#
-# Copyright (C) 2001-2004 by Michael Neumann (mailto:mneumann@ntecs.de)
-#
-# Released under the same term of license as Ruby.
-#
-# == Overview
-#
-# XMLRPC is a lightweight protocol that enables remote procedure calls over
-# HTTP. It is defined at http://www.xmlrpc.com.
-#
-# XMLRPC allows you to create simple distributed computing solutions that span
-# computer languages. Its distinctive feature is its simplicity compared to
-# other approaches like SOAP and CORBA.
-#
-# The Ruby standard library package 'xmlrpc' enables you to create a server that
-# implements remote procedures and a client that calls them. Very little code
-# is required to achieve either of these.
-#
-# == Example
-#
-# Try the following code. It calls a standard demonstration remote procedure.
-#
-# require 'xmlrpc/client'
-# require 'pp'
-#
-# server = XMLRPC::Client.new2("http://xmlrpc-c.sourceforge.net/api/sample.php")
-# result = server.call("sample.sumAndDifference", 5, 3)
-# pp result
-#
-# == Documentation
-#
-# See http://www.ntecs.de/ruby/xmlrpc4r/. There is plenty of detail there to
-# use the client and implement a server.
-#
-# == Features of XMLRPC for Ruby
-#
-# * Extensions
-# * Introspection
-# * multiCall
-# * optionally nil values and integers larger than 32 Bit
-#
-# * Server
-# * Standalone XML-RPC server
-# * CGI-based (works with FastCGI)
-# * Apache mod_ruby server
-# * WEBrick servlet
-#
-# * Client
-# * synchronous/asynchronous calls
-# * Basic HTTP-401 Authentication
-# * HTTPS protocol (SSL)
-#
-# * Parsers
-# * REXML (XMLParser::REXMLStreamParser)
-# * Not compiled (pure ruby)
-# * See ruby standard library
-# * libxml (LibXMLStreamParser)
-# * Compiled
-# * See https://rubygems.org/gems/libxml-ruby/
-#
-# * General
-# * possible to choose between XMLParser module (Expat wrapper) and REXML (pure Ruby) parsers
-# * Marshalling Ruby objects to Hashes and reconstruct them later from a Hash
-# * SandStorm component architecture XMLRPC::Client interface
-#
-# == Howto
-#
-# === Client
-#
-# require "xmlrpc/client"
-#
-# # Make an object to represent the XML-RPC server.
-# server = XMLRPC::Client.new( "xmlrpc-c.sourceforge.net", "/api/sample.php")
-#
-# # Call the remote server and get our result
-# result = server.call("sample.sumAndDifference", 5, 3)
-#
-# sum = result["sum"]
-# difference = result["difference"]
-#
-# puts "Sum: #{sum}, Difference: #{difference}"
-#
-# === XMLRPC::Client with XML-RPC fault-structure handling
-#
-# There are two possible ways, of handling a fault-structure:
-#
-# ==== by catching a XMLRPC::FaultException exception
-#
-# require "xmlrpc/client"
-#
-# # Make an object to represent the XML-RPC server.
-# server = XMLRPC::Client.new( "xmlrpc-c.sourceforge.net", "/api/sample.php")
-#
-# begin
-# # Call the remote server and get our result
-# result = server.call("sample.sumAndDifference", 5, 3)
-#
-# sum = result["sum"]
-# difference = result["difference"]
-#
-# puts "Sum: #{sum}, Difference: #{difference}"
-#
-# rescue XMLRPC::FaultException => e
-# puts "Error: "
-# puts e.faultCode
-# puts e.faultString
-# end
-#
-# ==== by calling "call2" which returns a boolean
-#
-# require "xmlrpc/client"
-#
-# # Make an object to represent the XML-RPC server.
-# server = XMLRPC::Client.new( "xmlrpc-c.sourceforge.net", "/api/sample.php")
-#
-# # Call the remote server and get our result
-# ok, result = server.call2("sample.sumAndDifference", 5, 3)
-#
-# if ok
-# sum = result["sum"]
-# difference = result["difference"]
-#
-# puts "Sum: #{sum}, Difference: #{difference}"
-# else
-# puts "Error: "
-# puts result.faultCode
-# puts result.faultString
-# end
-#
-# === Using XMLRPC::Client::Proxy
-#
-# You can create a Proxy object onto which you can call methods. This way it
-# looks nicer. Both forms, _call_ and _call2_ are supported through _proxy_ and
-# _proxy2_. You can additionally give arguments to the Proxy, which will be
-# given to each XML-RPC call using that Proxy.
-#
-# require "xmlrpc/client"
-#
-# # Make an object to represent the XML-RPC server.
-# server = XMLRPC::Client.new( "xmlrpc-c.sourceforge.net", "/api/sample.php")
-#
-# # Create a Proxy object
-# sample = server.proxy("sample")
-#
-# # Call the remote server and get our result
-# result = sample.sumAndDifference(5,3)
-#
-# sum = result["sum"]
-# difference = result["difference"]
-#
-# puts "Sum: #{sum}, Difference: #{difference}"
-#
-# === CGI-based server using XMLRPC::CGIServer
-#
-# There are also two ways to define handler, the first is
-# like C/PHP, the second like Java, of course both ways
-# can be mixed:
-#
-# ==== C/PHP-like (handler functions)
-#
-# require "xmlrpc/server"
-#
-# s = XMLRPC::CGIServer.new
-#
-# s.add_handler("sample.sumAndDifference") do |a,b|
-# { "sum" => a + b, "difference" => a - b }
-# end
-#
-# s.serve
-#
-# ==== Java-like (handler classes)
-#
-# require "xmlrpc/server"
-#
-# s = XMLRPC::CGIServer.new
-#
-# class MyHandler
-# def sumAndDifference(a, b)
-# { "sum" => a + b, "difference" => a - b }
-# end
-# end
-#
-# # NOTE: Security Hole (read below)!!!
-# s.add_handler("sample", MyHandler.new)
-# s.serve
-#
-#
-# To return a fault-structure you have to raise an XMLRPC::FaultException e.g.:
-#
-# raise XMLRPC::FaultException.new(3, "division by Zero")
-#
-# ===== Security Note
-#
-# From Brian Candler:
-#
-# Above code sample has an extremely nasty security hole, in that you can now call
-# any method of 'MyHandler' remotely, including methods inherited from Object
-# and Kernel! For example, in the client code, you can use
-#
-# puts server.call("sample.send","`","ls")
-#
-# (backtick being the method name for running system processes). Needless to
-# say, 'ls' can be replaced with something else.
-#
-# The version which binds proc objects (or the version presented below in the next section)
-# doesn't have this problem, but people may be tempted to use the second version because it's
-# so nice and 'Rubyesque'. I think it needs a big red disclaimer.
-#
-#
-# From Michael:
-#
-# A solution is to undef insecure methods or to use
-# XMLRPC::Service::PublicInstanceMethodsInterface as shown below:
-#
-# class MyHandler
-# def sumAndDifference(a, b)
-# { "sum" => a + b, "difference" => a - b }
-# end
-# end
-#
-# # ... server initialization ...
-#
-# s.add_handler(XMLRPC::iPIMethods("sample"), MyHandler.new)
-#
-# # ...
-#
-# This adds only public instance methods explicitly declared in class MyHandler
-# (and not those inherited from any other class).
-#
-# ==== With interface declarations
-#
-# Code sample from the book Ruby Developer's Guide:
-#
-# require "xmlrpc/server"
-#
-# class Num
-# INTERFACE = XMLRPC::interface("num") {
-# meth 'int add(int, int)', 'Add two numbers', 'add'
-# meth 'int div(int, int)', 'Divide two numbers'
-# }
-#
-# def add(a, b) a + b end
-# def div(a, b) a / b end
-# end
-#
-#
-# s = XMLRPC::CGIServer.new
-# s.add_handler(Num::INTERFACE, Num.new)
-# s.serve
-#
-# === Standalone XMLRPC::Server
-#
-# Same as CGI-based server, the only difference being
-#
-# server = XMLRPC::CGIServer.new
-#
-# must be changed to
-#
-# server = XMLRPC::Server.new(8080)
-#
-# if you want a server listening on port 8080.
-# The rest is the same.
-#
-# === Choosing a different XMLParser or XMLWriter
-#
-# The examples above all use the default parser (which is now since 1.8
-# XMLParser::REXMLStreamParser) and a default XMLRPC::XMLWriter.
-# If you want to use a different XMLParser, then you have to call the
-# ParserWriterChooseMixin#set_parser method of XMLRPC::Client instances
-# or instances of subclasses of XMLRPC::BasicServer or by editing
-# xmlrpc/config.rb.
-#
-# XMLRPC::Client Example:
-#
-# # ...
-# server = XMLRPC::Client.new( "xmlrpc-c.sourceforge.net", "/api/sample.php")
-# server.set_parser(XMLRPC::XMLParser::XMLParser.new)
-# # ...
-#
-# XMLRPC::Server Example:
-#
-# # ...
-# s = XMLRPC::CGIServer.new
-# s.set_parser(XMLRPC::XMLParser::XMLParser.new)
-# # ...
-#
-#
-# You can change the XML-writer by calling method ParserWriterChooseMixin#set_writer.
-module XMLRPC; end
diff --git a/lib/xmlrpc/base64.rb b/lib/xmlrpc/base64.rb
deleted file mode 100644
index 21f8c65ce2..0000000000
--- a/lib/xmlrpc/base64.rb
+++ /dev/null
@@ -1,63 +0,0 @@
-# frozen_string_literal: false
-#
-# xmlrpc/base64.rb
-# Copyright (C) 2001, 2002, 2003 by Michael Neumann (mneumann@ntecs.de)
-#
-# Released under the same term of license as Ruby.
-
-module XMLRPC # :nodoc:
-
-# This class is necessary for 'xmlrpc4r' to determine that a string should
-# be transmitted base64-encoded and not as a raw-string.
-#
-# You can use XMLRPC::Base64 on the client and server-side as a
-# parameter and/or return-value.
-class Base64
-
- # Creates a new XMLRPC::Base64 instance with string +str+ as the
- # internal string. When +state+ is +:dec+ it assumes that the
- # string +str+ is not in base64 format (perhaps already decoded),
- # otherwise if +state+ is +:enc+ it decodes +str+
- # and stores it as the internal string.
- def initialize(str, state = :dec)
- case state
- when :enc
- @str = Base64.decode(str)
- when :dec
- @str = str
- else
- raise ArgumentError, "wrong argument; either :enc or :dec"
- end
- end
-
- # Returns the decoded internal string.
- def decoded
- @str
- end
-
- # Returns the base64 encoded internal string.
- def encoded
- Base64.encode(@str)
- end
-
-
- # Decodes string +str+ with base64 and returns that value.
- def Base64.decode(str)
- str.gsub(/\s+/, "").unpack("m")[0]
- end
-
- # Encodes string +str+ with base64 and returns that value.
- def Base64.encode(str)
- [str].pack("m")
- end
-
-end
-
-
-end # module XMLRPC
-
-
-=begin
-= History
- $Id$
-=end
diff --git a/lib/xmlrpc/client.rb b/lib/xmlrpc/client.rb
deleted file mode 100644
index 587a80bea3..0000000000
--- a/lib/xmlrpc/client.rb
+++ /dev/null
@@ -1,629 +0,0 @@
-# frozen_string_literal: false
-# xmlrpc/client.rb
-# Copyright (C) 2001, 2002, 2003 by Michael Neumann (mneumann@ntecs.de)
-#
-# Released under the same term of license as Ruby.
-#
-# History
-# $Id$
-#
-require "xmlrpc/parser"
-require "xmlrpc/create"
-require "xmlrpc/config"
-require "xmlrpc/utils" # ParserWriterChooseMixin
-require "net/http"
-require "uri"
-
-module XMLRPC # :nodoc:
-
- # Provides remote procedure calls to a XML-RPC server.
- #
- # After setting the connection-parameters with XMLRPC::Client.new which
- # creates a new XMLRPC::Client instance, you can execute a remote procedure
- # by sending the XMLRPC::Client#call or XMLRPC::Client#call2
- # message to this new instance.
- #
- # The given parameters indicate which method to call on the remote-side and
- # of course the parameters for the remote procedure.
- #
- # require "xmlrpc/client"
- #
- # server = XMLRPC::Client.new("www.ruby-lang.org", "/RPC2", 80)
- # begin
- # param = server.call("michael.add", 4, 5)
- # puts "4 + 5 = #{param}"
- # rescue XMLRPC::FaultException => e
- # puts "Error:"
- # puts e.faultCode
- # puts e.faultString
- # end
- #
- # or
- #
- # require "xmlrpc/client"
- #
- # server = XMLRPC::Client.new("www.ruby-lang.org", "/RPC2", 80)
- # ok, param = server.call2("michael.add", 4, 5)
- # if ok then
- # puts "4 + 5 = #{param}"
- # else
- # puts "Error:"
- # puts param.faultCode
- # puts param.faultString
- # end
- class Client
-
- USER_AGENT = "XMLRPC::Client (Ruby #{RUBY_VERSION})"
-
- include ParserWriterChooseMixin
- include ParseContentType
-
-
- # Creates an object which represents the remote XML-RPC server on the
- # given +host+. If the server is CGI-based, +path+ is the
- # path to the CGI-script, which will be called, otherwise (in the
- # case of a standalone server) +path+ should be <tt>"/RPC2"</tt>.
- # +port+ is the port on which the XML-RPC server listens.
- #
- # If +proxy_host+ is given, then a proxy server listening at
- # +proxy_host+ is used. +proxy_port+ is the port of the
- # proxy server.
- #
- # Default values for +host+, +path+ and +port+ are 'localhost', '/RPC2' and
- # '80' respectively using SSL '443'.
- #
- # If +user+ and +password+ are given, each time a request is sent,
- # an Authorization header is sent. Currently only Basic Authentication is
- # implemented, no Digest.
- #
- # If +use_ssl+ is set to +true+, communication over SSL is enabled.
- #
- # Parameter +timeout+ is the time to wait for a XML-RPC response, defaults to 30.
- def initialize(host=nil, path=nil, port=nil, proxy_host=nil, proxy_port=nil,
- user=nil, password=nil, use_ssl=nil, timeout=nil)
-
- @http_header_extra = nil
- @http_last_response = nil
- @cookie = nil
-
- @host = host || "localhost"
- @path = path || "/RPC2"
- @proxy_host = proxy_host
- @proxy_port = proxy_port
- @proxy_host ||= 'localhost' if @proxy_port != nil
- @proxy_port ||= 8080 if @proxy_host != nil
- @use_ssl = use_ssl || false
- @timeout = timeout || 30
-
- if use_ssl
- require "net/https"
- @port = port || 443
- else
- @port = port || 80
- end
-
- @user, @password = user, password
-
- set_auth
-
- # convert ports to integers
- @port = @port.to_i if @port != nil
- @proxy_port = @proxy_port.to_i if @proxy_port != nil
-
- # HTTP object for synchronous calls
- @http = net_http(@host, @port, @proxy_host, @proxy_port)
- @http.use_ssl = @use_ssl if @use_ssl
- @http.read_timeout = @timeout
- @http.open_timeout = @timeout
-
- @parser = nil
- @create = nil
- end
-
-
- class << self
-
- # Creates an object which represents the remote XML-RPC server at the
- # given +uri+. The URI should have a host, port, path, user and password.
- # Example: https://user:password@host:port/path
- #
- # Raises an ArgumentError if the +uri+ is invalid,
- # or if the protocol isn't http or https.
- #
- # If a +proxy+ is given it should be in the form of "host:port".
- #
- # The optional +timeout+ defaults to 30 seconds.
- def new2(uri, proxy=nil, timeout=nil)
- begin
- url = URI(uri)
- rescue URI::InvalidURIError => e
- raise ArgumentError, e.message, e.backtrace
- end
-
- unless URI::HTTP === url
- raise ArgumentError, "Wrong protocol specified. Only http or https allowed!"
- end
-
- proto = url.scheme
- user = url.user
- passwd = url.password
- host = url.host
- port = url.port
- path = url.path.empty? ? nil : url.request_uri
-
- proxy_host, proxy_port = (proxy || "").split(":")
- proxy_port = proxy_port.to_i if proxy_port
-
- self.new(host, path, port, proxy_host, proxy_port, user, passwd, (proto == "https"), timeout)
- end
-
- alias new_from_uri new2
-
- # Receives a Hash and calls XMLRPC::Client.new
- # with the corresponding values.
- #
- # The +hash+ parameter has following case-insensitive keys:
- # * host
- # * path
- # * port
- # * proxy_host
- # * proxy_port
- # * user
- # * password
- # * use_ssl
- # * timeout
- def new3(hash={})
-
- # convert all keys into lowercase strings
- h = {}
- hash.each { |k,v| h[k.to_s.downcase] = v }
-
- self.new(h['host'], h['path'], h['port'], h['proxy_host'], h['proxy_port'], h['user'], h['password'],
- h['use_ssl'], h['timeout'])
- end
-
- alias new_from_hash new3
-
- end
-
-
- # Returns the Net::HTTP object for the client. If you want to
- # change HTTP client options except header, cookie, timeout,
- # user and password, use Net::HTTP directly.
- #
- # Since 2.1.0.
- attr_reader :http
-
- # Add additional HTTP headers to the request
- attr_accessor :http_header_extra
-
- # Returns the Net::HTTPResponse object of the last RPC.
- attr_reader :http_last_response
-
- # Get and set the HTTP Cookie header.
- attr_accessor :cookie
-
-
- # Return the corresponding attributes.
- attr_reader :timeout, :user, :password
-
- # Sets the Net::HTTP#read_timeout and Net::HTTP#open_timeout to
- # +new_timeout+
- def timeout=(new_timeout)
- @timeout = new_timeout
- @http.read_timeout = @timeout
- @http.open_timeout = @timeout
- end
-
- # Changes the user for the Basic Authentication header to +new_user+
- def user=(new_user)
- @user = new_user
- set_auth
- end
-
- # Changes the password for the Basic Authentication header to
- # +new_password+
- def password=(new_password)
- @password = new_password
- set_auth
- end
-
- # Invokes the method named +method+ with the parameters given by
- # +args+ on the XML-RPC server.
- #
- # The +method+ parameter is converted into a String and should
- # be a valid XML-RPC method-name.
- #
- # Each parameter of +args+ must be of one of the following types,
- # where Hash, Struct and Array can contain any of these listed _types_:
- #
- # * Fixnum, Bignum
- # * TrueClass, FalseClass, +true+, +false+
- # * String, Symbol
- # * Float
- # * Hash, Struct
- # * Array
- # * Date, Time, XMLRPC::DateTime
- # * XMLRPC::Base64
- # * A Ruby object which class includes XMLRPC::Marshallable
- # (only if Config::ENABLE_MARSHALLING is +true+).
- # That object is converted into a hash, with one additional key/value
- # pair <code>___class___</code> which contains the class name
- # for restoring that object later.
- #
- # The method returns the return-value from the Remote Procedure Call.
- #
- # The type of the return-value is one of the types shown above.
- #
- # A Bignum is only allowed when it fits in 32-bit. A XML-RPC
- # +dateTime.iso8601+ type is always returned as a XMLRPC::DateTime object.
- # Struct is never returned, only a Hash, the same for a Symbol, where as a
- # String is always returned. XMLRPC::Base64 is returned as a String from
- # xmlrpc4r version 1.6.1 on.
- #
- # If the remote procedure returned a fault-structure, then a
- # XMLRPC::FaultException exception is raised, which has two accessor-methods
- # +faultCode+ an Integer, and +faultString+ a String.
- def call(method, *args)
- ok, param = call2(method, *args)
- if ok
- param
- else
- raise param
- end
- end
-
- # The difference between this method and XMLRPC::Client#call is, that
- # this method will <b>NOT</b> raise a XMLRPC::FaultException exception.
- #
- # The method returns an array of two values. The first value indicates if
- # the second value is +true+ or an XMLRPC::FaultException.
- #
- # Both are explained in XMLRPC::Client#call.
- #
- # Simple to remember: The "2" in "call2" denotes the number of values it returns.
- def call2(method, *args)
- request = create().methodCall(method, *args)
- data = do_rpc(request, false)
- parser().parseMethodResponse(data)
- end
-
- # Similar to XMLRPC::Client#call, however can be called concurrently and
- # use a new connection for each request. In contrast to the corresponding
- # method without the +_async+ suffix, which use connect-alive (one
- # connection for all requests).
- #
- # Note, that you have to use Thread to call these methods concurrently.
- # The following example calls two methods concurrently:
- #
- # Thread.new {
- # p client.call_async("michael.add", 4, 5)
- # }
- #
- # Thread.new {
- # p client.call_async("michael.div", 7, 9)
- # }
- #
- def call_async(method, *args)
- ok, param = call2_async(method, *args)
- if ok
- param
- else
- raise param
- end
- end
-
- # Same as XMLRPC::Client#call2, but can be called concurrently.
- #
- # See also XMLRPC::Client#call_async
- def call2_async(method, *args)
- request = create().methodCall(method, *args)
- data = do_rpc(request, true)
- parser().parseMethodResponse(data)
- end
-
-
- # You can use this method to execute several methods on a XMLRPC server
- # which support the multi-call extension.
- #
- # s.multicall(
- # ['michael.add', 3, 4],
- # ['michael.sub', 4, 5]
- # )
- # # => [7, -1]
- def multicall(*methods)
- ok, params = multicall2(*methods)
- if ok
- params
- else
- raise params
- end
- end
-
- # Same as XMLRPC::Client#multicall, but returns two parameters instead of
- # raising an XMLRPC::FaultException.
- #
- # See XMLRPC::Client#call2
- def multicall2(*methods)
- gen_multicall(methods, false)
- end
-
- # Similar to XMLRPC::Client#multicall, however can be called concurrently and
- # use a new connection for each request. In contrast to the corresponding
- # method without the +_async+ suffix, which use connect-alive (one
- # connection for all requests).
- #
- # Note, that you have to use Thread to call these methods concurrently.
- # The following example calls two methods concurrently:
- #
- # Thread.new {
- # p client.multicall_async("michael.add", 4, 5)
- # }
- #
- # Thread.new {
- # p client.multicall_async("michael.div", 7, 9)
- # }
- #
- def multicall_async(*methods)
- ok, params = multicall2_async(*methods)
- if ok
- params
- else
- raise params
- end
- end
-
- # Same as XMLRPC::Client#multicall2, but can be called concurrently.
- #
- # See also XMLRPC::Client#multicall_async
- def multicall2_async(*methods)
- gen_multicall(methods, true)
- end
-
-
- # Returns an object of class XMLRPC::Client::Proxy, initialized with
- # +prefix+ and +args+.
- #
- # A proxy object returned by this method behaves like XMLRPC::Client#call,
- # i.e. a call on that object will raise a XMLRPC::FaultException when a
- # fault-structure is returned by that call.
- def proxy(prefix=nil, *args)
- Proxy.new(self, prefix, args, :call)
- end
-
- # Almost the same like XMLRPC::Client#proxy only that a call on the returned
- # XMLRPC::Client::Proxy object will return two parameters.
- #
- # See XMLRPC::Client#call2
- def proxy2(prefix=nil, *args)
- Proxy.new(self, prefix, args, :call2)
- end
-
- # Similar to XMLRPC::Client#proxy, however can be called concurrently and
- # use a new connection for each request. In contrast to the corresponding
- # method without the +_async+ suffix, which use connect-alive (one
- # connection for all requests).
- #
- # Note, that you have to use Thread to call these methods concurrently.
- # The following example calls two methods concurrently:
- #
- # Thread.new {
- # p client.proxy_async("michael.add", 4, 5)
- # }
- #
- # Thread.new {
- # p client.proxy_async("michael.div", 7, 9)
- # }
- #
- def proxy_async(prefix=nil, *args)
- Proxy.new(self, prefix, args, :call_async)
- end
-
- # Same as XMLRPC::Client#proxy2, but can be called concurrently.
- #
- # See also XMLRPC::Client#proxy_async
- def proxy2_async(prefix=nil, *args)
- Proxy.new(self, prefix, args, :call2_async)
- end
-
-
- private
-
- def net_http(host, port, proxy_host, proxy_port)
- Net::HTTP.new host, port, proxy_host, proxy_port
- end
-
- def dup_net_http
- http = net_http(@http.address,
- @http.port,
- @http.proxy_address,
- @http.proxy_port)
- http.proxy_user = @http.proxy_user
- http.proxy_pass = @http.proxy_pass
- if @http.use_ssl?
- http.use_ssl = true
- Net::HTTP::SSL_ATTRIBUTES.each do |attribute|
- http.__send__("#{attribute}=", @http.__send__(attribute))
- end
- end
- http.read_timeout = @http.read_timeout
- http.open_timeout = @http.open_timeout
- http
- end
-
- def set_auth
- if @user.nil?
- @auth = nil
- else
- a = "#@user"
- a << ":#@password" if @password != nil
- @auth = "Basic " + [a].pack("m0")
- end
- end
-
- def do_rpc(request, async=false)
- header = {
- "User-Agent" => USER_AGENT,
- "Content-Type" => "text/xml; charset=utf-8",
- "Content-Length" => request.bytesize.to_s,
- "Connection" => (async ? "close" : "keep-alive")
- }
-
- header["Cookie"] = @cookie if @cookie
- header.update(@http_header_extra) if @http_header_extra
-
- if @auth != nil
- # add authorization header
- header["Authorization"] = @auth
- end
-
- resp = nil
- @http_last_response = nil
-
- if async
- # use a new HTTP object for each call
- http = dup_net_http
-
- # post request
- http.start {
- resp = http.request_post(@path, request, header)
- }
- else
- # reuse the HTTP object for each call => connection alive is possible
- # we must start connection explicitly first time so that http.request
- # does not assume that we don't want keepalive
- @http.start if not @http.started?
-
- # post request
- resp = @http.request_post(@path, request, header)
- end
-
- @http_last_response = resp
-
- data = resp.body
-
- if resp.code == "401"
- # Authorization Required
- raise "Authorization failed.\nHTTP-Error: #{resp.code} #{resp.message}"
- elsif resp.code[0,1] != "2"
- raise "HTTP-Error: #{resp.code} #{resp.message}"
- end
-
- # assume text/xml on instances where Content-Type header is not set
- ct_expected = resp["Content-Type"] || 'text/xml'
- ct = parse_content_type(ct_expected).first
- if ct != "text/xml"
- if ct == "text/html"
- raise "Wrong content-type (received '#{ct}' but expected 'text/xml'): \n#{data}"
- else
- raise "Wrong content-type (received '#{ct}' but expected 'text/xml')"
- end
- end
-
- expected = resp["Content-Length"] || "<unknown>"
- if data.nil? or data.bytesize == 0
- raise "Wrong size. Was #{data.bytesize}, should be #{expected}"
- end
-
- parse_set_cookies(resp.get_fields("Set-Cookie"))
-
- return data
- end
-
- def parse_set_cookies(set_cookies)
- return if set_cookies.nil?
- return if set_cookies.empty?
- require 'webrick/cookie'
- pairs = {}
- set_cookies.each do |set_cookie|
- cookie = WEBrick::Cookie.parse_set_cookie(set_cookie)
- pairs.delete(cookie.name)
- pairs[cookie.name] = cookie.value
- end
- cookies = pairs.collect do |name, value|
- WEBrick::Cookie.new(name, value).to_s
- end
- @cookie = cookies.join("; ")
- end
-
- def gen_multicall(methods=[], async=false)
- meth = :call2
- meth = :call2_async if async
-
- ok, params = self.send(meth, "system.multicall",
- methods.collect {|m| {'methodName' => m[0], 'params' => m[1..-1]} }
- )
-
- if ok
- params = params.collect do |param|
- if param.is_a? Array
- param[0]
- elsif param.is_a? Hash
- XMLRPC::FaultException.new(param["faultCode"], param["faultString"])
- else
- raise "Wrong multicall return value"
- end
- end
- end
-
- return ok, params
- end
-
-
-
- # XML-RPC calls look nicer!
- #
- # You can call any method onto objects of that class - the object handles
- # XMLRPC::Client::Proxy#method_missing and will forward the method call to
- # a XML-RPC server.
- #
- # Don't use this class directly, instead use the public instance method
- # XMLRPC::Client#proxy or XMLRPC::Client#proxy2.
- #
- # require "xmlrpc/client"
- #
- # server = XMLRPC::Client.new("www.ruby-lang.org", "/RPC2", 80)
- #
- # michael = server.proxy("michael")
- # michael2 = server.proxy("michael", 4)
- #
- # # both calls should return the same value '9'.
- # p michael.add(4,5)
- # p michael2.add(5)
- class Proxy
-
- # Creates an object which provides XMLRPC::Client::Proxy#method_missing.
- #
- # The given +server+ must be an instance of XMLRPC::Client, which is the
- # XML-RPC server to be used for a XML-RPC call.
- #
- # +prefix+ and +delim+ will be prepended to the method name called onto this object.
- #
- # An optional parameter +meth+ is the method to use for a RPC.
- # It can be either, call, call2, call_async, call2_async
- #
- # +args+ are arguments which are automatically given to every XML-RPC
- # call before being provided through +method_missing+.
- def initialize(server, prefix, args=[], meth=:call, delim=".")
- @server = server
- @prefix = prefix ? prefix + delim : ""
- @args = args
- @meth = meth
- end
-
- # Every method call is forwarded to the XML-RPC server defined in
- # XMLRPC::Client::Proxy#new.
- #
- # Note: Inherited methods from class Object cannot be used as XML-RPC
- # names, because they get around +method_missing+.
- def method_missing(mid, *args)
- pre = @prefix + mid.to_s
- arg = @args + args
- @server.send(@meth, pre, *arg)
- end
-
- end # class Proxy
-
- end # class Client
-
-end # module XMLRPC
diff --git a/lib/xmlrpc/config.rb b/lib/xmlrpc/config.rb
deleted file mode 100644
index b7ed7a9f71..0000000000
--- a/lib/xmlrpc/config.rb
+++ /dev/null
@@ -1,39 +0,0 @@
-# frozen_string_literal: false
-#
-# $Id$
-# Configuration file for XML-RPC for Ruby
-#
-
-module XMLRPC # :nodoc:
-
- module Config
-
- # or XMLWriter::XMLParser
- DEFAULT_WRITER = XMLWriter::Simple
-
- # === Available parsers
- #
- # * XMLParser::REXMLStreamParser
- # * XMLParser::LibXMLStreamParser
- DEFAULT_PARSER = XMLParser::REXMLStreamParser
-
- # enable <code><nil/></code> tag
- ENABLE_NIL_CREATE = false
- ENABLE_NIL_PARSER = false
-
- # allows integers greater than 32-bit if +true+
- ENABLE_BIGINT = false
-
- # enable marshalling Ruby objects which include XMLRPC::Marshallable
- ENABLE_MARSHALLING = true
-
- # enable multiCall extension by default
- ENABLE_MULTICALL = false
-
- # enable Introspection extension by default
- ENABLE_INTROSPECTION = false
-
- end
-
-end
-
diff --git a/lib/xmlrpc/create.rb b/lib/xmlrpc/create.rb
deleted file mode 100644
index 93822c4dd2..0000000000
--- a/lib/xmlrpc/create.rb
+++ /dev/null
@@ -1,287 +0,0 @@
-# frozen_string_literal: false
-#
-# Copyright (C) 2001, 2002, 2003 by Michael Neumann (mneumann@ntecs.de)
-#
-# $Id$
-#
-
-require "date"
-require "xmlrpc/base64"
-
-module XMLRPC # :nodoc:
-
- module XMLWriter
-
- class Abstract
- def ele(name, *children)
- element(name, nil, *children)
- end
-
- def tag(name, txt)
- element(name, nil, text(txt))
- end
- end
-
-
- class Simple < Abstract
-
- def document_to_str(doc)
- doc
- end
-
- def document(*params)
- params.join("")
- end
-
- def pi(name, *params)
- "<?#{name} " + params.join(" ") + " ?>"
- end
-
- def element(name, attrs, *children)
- raise "attributes not yet implemented" unless attrs.nil?
- if children.empty?
- "<#{name}/>"
- else
- "<#{name}>" + children.join("") + "</#{name}>"
- end
- end
-
- def text(txt)
- cleaned = txt.dup
- cleaned.gsub!(/&/, '&amp;')
- cleaned.gsub!(/</, '&lt;')
- cleaned.gsub!(/>/, '&gt;')
- cleaned
- end
-
- end # class Simple
-
-
- class XMLParser < Abstract
-
- def initialize
- require "xmltreebuilder"
- end
-
- def document_to_str(doc)
- doc.to_s
- end
-
- def document(*params)
- XML::SimpleTree::Document.new(*params)
- end
-
- def pi(name, *params)
- XML::SimpleTree::ProcessingInstruction.new(name, *params)
- end
-
- def element(name, attrs, *children)
- XML::SimpleTree::Element.new(name, attrs, *children)
- end
-
- def text(txt)
- XML::SimpleTree::Text.new(txt)
- end
-
- end # class XMLParser
-
- Classes = [Simple, XMLParser]
-
- # yields an instance of each installed XML writer
- def self.each_installed_writer
- XMLRPC::XMLWriter::Classes.each do |klass|
- begin
- yield klass.new
- rescue LoadError
- end
- end
- end
-
- end # module XMLWriter
-
- # Creates XML-RPC call/response documents
- #
- class Create
-
- def initialize(xml_writer = nil)
- @writer = xml_writer || Config::DEFAULT_WRITER.new
- end
-
-
- def methodCall(name, *params)
- name = name.to_s
-
- if name !~ /[a-zA-Z0-9_.:\/]+/
- raise ArgumentError, "Wrong XML-RPC method-name"
- end
-
- parameter = params.collect do |param|
- @writer.ele("param", conv2value(param))
- end
-
- tree = @writer.document(
- @writer.pi("xml", 'version="1.0"'),
- @writer.ele("methodCall",
- @writer.tag("methodName", name),
- @writer.ele("params", *parameter)
- )
- )
-
- @writer.document_to_str(tree) + "\n"
- end
-
-
-
- #
- # Generates a XML-RPC methodResponse document
- #
- # When +is_ret+ is +false+ then the +params+ array must
- # contain only one element, which is a structure
- # of a fault return-value.
- #
- # When +is_ret+ is +true+ then a normal
- # return-value of all the given +params+ is created.
- #
- def methodResponse(is_ret, *params)
-
- if is_ret
- resp = params.collect do |param|
- @writer.ele("param", conv2value(param))
- end
-
- resp = [@writer.ele("params", *resp)]
- else
- if params.size != 1 or params[0] === XMLRPC::FaultException
- raise ArgumentError, "no valid fault-structure given"
- end
- resp = @writer.ele("fault", conv2value(params[0].to_h))
- end
-
-
- tree = @writer.document(
- @writer.pi("xml", 'version="1.0"'),
- @writer.ele("methodResponse", resp)
- )
-
- @writer.document_to_str(tree) + "\n"
- end
-
-
-
- private
-
- #
- # Converts a Ruby object into a XML-RPC <code><value></code> tag
- #
- def conv2value(param) # :doc:
-
- val = case param
- when Fixnum, Bignum
- # XML-RPC's int is 32bit int, and Fixnum also may be beyond 32bit
- if Config::ENABLE_BIGINT
- @writer.tag("i4", param.to_s)
- else
- if param >= -(2**31) and param <= (2**31-1)
- @writer.tag("i4", param.to_s)
- else
- raise "Bignum is too big! Must be signed 32-bit integer!"
- end
- end
- when TrueClass, FalseClass
- @writer.tag("boolean", param ? "1" : "0")
-
- when Symbol
- @writer.tag("string", param.to_s)
-
- when String
- @writer.tag("string", param)
-
- when NilClass
- if Config::ENABLE_NIL_CREATE
- @writer.ele("nil")
- else
- raise "Wrong type NilClass. Not allowed!"
- end
-
- when Float
- raise "Wrong value #{param}. Not allowed!" unless param.finite?
- @writer.tag("double", param.to_s)
-
- when Struct
- h = param.members.collect do |key|
- value = param[key]
- @writer.ele("member",
- @writer.tag("name", key.to_s),
- conv2value(value)
- )
- end
-
- @writer.ele("struct", *h)
-
- when Hash
- # TODO: can a Hash be empty?
-
- h = param.collect do |key, value|
- @writer.ele("member",
- @writer.tag("name", key.to_s),
- conv2value(value)
- )
- end
-
- @writer.ele("struct", *h)
-
- when Array
- # TODO: can an Array be empty?
- a = param.collect {|v| conv2value(v) }
-
- @writer.ele("array",
- @writer.ele("data", *a)
- )
-
- when Time, Date, ::DateTime
- @writer.tag("dateTime.iso8601", param.strftime("%Y%m%dT%H:%M:%S"))
-
- when XMLRPC::DateTime
- @writer.tag("dateTime.iso8601",
- format("%.4d%02d%02dT%02d:%02d:%02d", *param.to_a))
-
- when XMLRPC::Base64
- @writer.tag("base64", param.encoded)
-
- else
- if Config::ENABLE_MARSHALLING and param.class.included_modules.include? XMLRPC::Marshallable
- # convert Ruby object into Hash
- ret = {"___class___" => param.class.name}
- param.instance_variables.each {|v|
- name = v[1..-1]
- val = param.instance_variable_get(v)
-
- if val.nil?
- ret[name] = val if Config::ENABLE_NIL_CREATE
- else
- ret[name] = val
- end
- }
- return conv2value(ret)
- else
- ok, pa = wrong_type(param)
- if ok
- return conv2value(pa)
- else
- raise "Wrong type!"
- end
- end
- end
-
- @writer.ele("value", val)
- end
-
- def wrong_type(value)
- false
- end
-
-
- end # class Create
-
-end # module XMLRPC
-
diff --git a/lib/xmlrpc/datetime.rb b/lib/xmlrpc/datetime.rb
deleted file mode 100644
index 431ac24aa9..0000000000
--- a/lib/xmlrpc/datetime.rb
+++ /dev/null
@@ -1,130 +0,0 @@
-# frozen_string_literal: false
-#
-# xmlrpc/datetime.rb
-# Copyright (C) 2001, 2002, 2003 by Michael Neumann (mneumann@ntecs.de)
-#
-# Released under the same term of license as Ruby.
-#
-require "date"
-
-module XMLRPC # :nodoc:
-
-# This class is important to handle XMLRPC +dateTime.iso8601+ values,
-# correctly, because normal UNIX-dates, ie: Date, only handle dates
-# from year 1970 on, and ruby's native Time class handles dates without the
-# time component.
-#
-# XMLRPC::DateTime is able to store a XMLRPC +dateTime.iso8601+ value correctly.
-class DateTime
-
- # Return the value of the specified date/time component.
- attr_reader :year, :month, :day, :hour, :min, :sec
-
- # Set +value+ as the new date/time component.
- #
- # Raises ArgumentError if the given +value+ is out of range, or in the case
- # of XMLRPC::DateTime#year= if +value+ is not of type Integer.
- def year= (value)
- raise ArgumentError, "date/time out of range" unless value.is_a? Integer
- @year = value
- end
-
- # Set +value+ as the new date/time component.
- #
- # Raises an ArgumentError if the given +value+ isn't between 1 and 12.
- def month= (value)
- raise ArgumentError, "date/time out of range" unless (1..12).include? value
- @month = value
- end
-
- # Set +value+ as the new date/time component.
- #
- # Raises an ArgumentError if the given +value+ isn't between 1 and 31.
- def day= (value)
- raise ArgumentError, "date/time out of range" unless (1..31).include? value
- @day = value
- end
-
- # Set +value+ as the new date/time component.
- #
- # Raises an ArgumentError if the given +value+ isn't between 0 and 24.
- def hour= (value)
- raise ArgumentError, "date/time out of range" unless (0..24).include? value
- @hour = value
- end
-
- # Set +value+ as the new date/time component.
- #
- # Raises an ArgumentError if the given +value+ isn't between 0 and 59.
- def min= (value)
- raise ArgumentError, "date/time out of range" unless (0..59).include? value
- @min = value
- end
-
- # Set +value+ as the new date/time component.
- #
- # Raises an ArgumentError if the given +value+ isn't between 0 and 59.
- def sec= (value)
- raise ArgumentError, "date/time out of range" unless (0..59).include? value
- @sec = value
- end
-
- # Alias for XMLRPC::DateTime#month.
- alias mon month
- # Alias for XMLRPC::DateTime#month=.
- alias mon= month=
-
-
- # Creates a new XMLRPC::DateTime instance with the
- # parameters +year+, +month+, +day+ as date and
- # +hour+, +min+, +sec+ as time.
- #
- # Raises an ArgumentError if a parameter is out of range,
- # or if +year+ is not of the Integer type.
- def initialize(year, month, day, hour, min, sec)
- self.year, self.month, self.day = year, month, day
- self.hour, self.min, self.sec = hour, min, sec
- end
-
- # Return a Time object of the date/time which represents +self+.
- # If the <code>@year</code> is below 1970, this method returns +nil+,
- # because Time cannot handle years below 1970.
- #
- # The timezone used is GMT.
- def to_time
- if @year >= 1970
- Time.gm(*to_a)
- else
- nil
- end
- end
-
- # Return a Date object of the date which represents +self+.
- #
- # The Date object do _not_ contain the time component (only date).
- def to_date
- Date.new(*to_a[0,3])
- end
-
- # Returns all date/time components in an array.
- #
- # Returns +[year, month, day, hour, min, sec]+.
- def to_a
- [@year, @month, @day, @hour, @min, @sec]
- end
-
- # Returns whether or not all date/time components are an array.
- def ==(o)
- self.to_a == Array(o) rescue false
- end
-
-end
-
-
-end # module XMLRPC
-
-
-=begin
-= History
- $Id$
-=end
diff --git a/lib/xmlrpc/marshal.rb b/lib/xmlrpc/marshal.rb
deleted file mode 100644
index 42b7b1e125..0000000000
--- a/lib/xmlrpc/marshal.rb
+++ /dev/null
@@ -1,67 +0,0 @@
-# frozen_string_literal: false
-#
-# Copyright (C) 2001, 2002, 2003 by Michael Neumann (mneumann@ntecs.de)
-#
-# $Id$
-#
-
-require "xmlrpc/parser"
-require "xmlrpc/create"
-require "xmlrpc/config"
-require "xmlrpc/utils"
-
-module XMLRPC # :nodoc:
-
- # Marshalling of XMLRPC::Create#methodCall and XMLRPC::Create#methodResponse
- class Marshal
- include ParserWriterChooseMixin
-
- class << self
-
- def dump_call( methodName, *params )
- new.dump_call( methodName, *params )
- end
-
- def dump_response( param )
- new.dump_response( param )
- end
-
- def load_call( stringOrReadable )
- new.load_call( stringOrReadable )
- end
-
- def load_response( stringOrReadable )
- new.load_response( stringOrReadable )
- end
-
- alias dump dump_response
- alias load load_response
-
- end # class self
-
- def initialize( parser = nil, writer = nil )
- set_parser( parser )
- set_writer( writer )
- end
-
- def dump_call( methodName, *params )
- create.methodCall( methodName, *params )
- end
-
- def dump_response( param )
- create.methodResponse( ! param.kind_of?( XMLRPC::FaultException ) , param )
- end
-
- # Returns <code>[ methodname, params ]</code>
- def load_call( stringOrReadable )
- parser.parseMethodCall( stringOrReadable )
- end
-
- # Returns +paramOrFault+
- def load_response( stringOrReadable )
- parser.parseMethodResponse( stringOrReadable )[1]
- end
-
- end # class Marshal
-
-end
diff --git a/lib/xmlrpc/parser.rb b/lib/xmlrpc/parser.rb
deleted file mode 100644
index a58da33720..0000000000
--- a/lib/xmlrpc/parser.rb
+++ /dev/null
@@ -1,642 +0,0 @@
-# frozen_string_literal: false
-# Copyright (C) 2001, 2002, 2003 by Michael Neumann (mneumann@ntecs.de)
-#
-# $Id$
-#
-
-
-require "date"
-require "xmlrpc/base64"
-require "xmlrpc/datetime"
-
-
-module XMLRPC # :nodoc:
-
- # Raised when the remote procedure returns a fault-structure, which has two
- # accessor-methods +faultCode+ an Integer, and +faultString+ a String.
- class FaultException < StandardError
- attr_reader :faultCode, :faultString
-
- # Creates a new XMLRPC::FaultException instance.
- #
- # +faultString+ is passed to StandardError as the +msg+ of the Exception.
- def initialize(faultCode, faultString)
- @faultCode = faultCode
- @faultString = faultString
- super(@faultString)
- end
-
- # The +faultCode+ and +faultString+ of the exception in a Hash.
- def to_h
- {"faultCode" => @faultCode, "faultString" => @faultString}
- end
- end
-
- # Helper class used to convert types.
- module Convert
-
- # Converts a String to an Integer
- #
- # See also String.to_i
- def self.int(str)
- str.to_i
- end
-
- # Converts a String to +true+ or +false+
- #
- # Raises an exception if +str+ is not +0+ or +1+
- def self.boolean(str)
- case str
- when "0" then false
- when "1" then true
- else
- raise "RPC-value of type boolean is wrong"
- end
- end
-
- # Converts a String to a Float
- #
- # See also String.to_f
- def self.double(str)
- str.to_f
- end
-
- # Converts a the given +str+ to a +dateTime.iso8601+ formatted date.
- #
- # Raises an exception if the String isn't in +dateTime.iso8601+ format.
- #
- # See also, XMLRPC::DateTime
- def self.dateTime(str)
- case str
- when /^(-?\d\d\d\d)-?(\d\d)-?(\d\d)T(\d\d):(\d\d):(\d\d)(?:Z|([+-])(\d\d):?(\d\d))?$/
- a = [$1, $2, $3, $4, $5, $6].collect{|i| i.to_i}
- if $7
- ofs = $8.to_i*3600 + $9.to_i*60
- ofs = -ofs if $7=='+'
- utc = Time.utc(*a) + ofs
- a = [ utc.year, utc.month, utc.day, utc.hour, utc.min, utc.sec ]
- end
- XMLRPC::DateTime.new(*a)
- when /^(-?\d\d)-?(\d\d)-?(\d\d)T(\d\d):(\d\d):(\d\d)(Z|([+-]\d\d):(\d\d))?$/
- a = [$1, $2, $3, $4, $5, $6].collect{|i| i.to_i}
- if a[0] < 70
- a[0] += 2000
- else
- a[0] += 1900
- end
- if $7
- ofs = $8.to_i*3600 + $9.to_i*60
- ofs = -ofs if $7=='+'
- utc = Time.utc(*a) + ofs
- a = [ utc.year, utc.month, utc.day, utc.hour, utc.min, utc.sec ]
- end
- XMLRPC::DateTime.new(*a)
- else
- raise "wrong dateTime.iso8601 format " + str
- end
- end
-
- # Decodes the given +str+ using XMLRPC::Base64.decode
- def self.base64(str)
- XMLRPC::Base64.decode(str)
- end
-
- # Converts the given +hash+ to a marshalled object.
- #
- # Returns the given +hash+ if an exception occurs.
- def self.struct(hash)
- # convert to marshalled object
- klass = hash["___class___"]
- if klass.nil? or Config::ENABLE_MARSHALLING == false
- hash
- else
- begin
- mod = Module
- klass.split("::").each {|const| mod = mod.const_get(const.strip)}
-
- obj = mod.allocate
-
- hash.delete "___class___"
- hash.each {|key, value|
- obj.instance_variable_set("@#{ key }", value) if key =~ /^([a-zA-Z_]\w*)$/
- }
- obj
- rescue
- hash
- end
- end
- end
-
- # Converts the given +hash+ to an XMLRPC::FaultException object by passing
- # the +faultCode+ and +faultString+ attributes of the Hash to
- # XMLRPC::FaultException.new
- #
- # Raises an Exception if the given +hash+ doesn't meet the requirements.
- # Those requirements being:
- # * 2 keys
- # * <code>'faultCode'</code> key is an Integer
- # * <code>'faultString'</code> key is a String
- def self.fault(hash)
- if hash.kind_of? Hash and hash.size == 2 and
- hash.has_key? "faultCode" and hash.has_key? "faultString" and
- hash["faultCode"].kind_of? Integer and hash["faultString"].kind_of? String
-
- XMLRPC::FaultException.new(hash["faultCode"], hash["faultString"])
- else
- raise "wrong fault-structure: #{hash.inspect}"
- end
- end
-
- end # module Convert
-
- # Parser for XML-RPC call and response
- module XMLParser
-
- class AbstractTreeParser
-
- def parseMethodResponse(str)
- methodResponse_document(createCleanedTree(str))
- end
-
- def parseMethodCall(str)
- methodCall_document(createCleanedTree(str))
- end
-
- private
-
- # Removes all whitespaces but in the tags i4, i8, int, boolean....
- # and all comments
- def removeWhitespacesAndComments(node)
- remove = []
- childs = node.childNodes.to_a
- childs.each do |nd|
- case _nodeType(nd)
- when :TEXT
- # TODO: add nil?
- unless %w(i4 i8 int boolean string double dateTime.iso8601 base64).include? node.nodeName
-
- if node.nodeName == "value"
- if not node.childNodes.to_a.detect {|n| _nodeType(n) == :ELEMENT}.nil?
- remove << nd if nd.nodeValue.strip == ""
- end
- else
- remove << nd if nd.nodeValue.strip == ""
- end
- end
- when :COMMENT
- remove << nd
- else
- removeWhitespacesAndComments(nd)
- end
- end
-
- remove.each { |i| node.removeChild(i) }
- end
-
-
- def nodeMustBe(node, name)
- cmp = case name
- when Array
- name.include?(node.nodeName)
- when String
- name == node.nodeName
- else
- raise "error"
- end
-
- if not cmp then
- raise "wrong xml-rpc (name)"
- end
-
- node
- end
-
- # Returns, when successfully the only child-node
- def hasOnlyOneChild(node, name=nil)
- if node.childNodes.to_a.size != 1
- raise "wrong xml-rpc (size)"
- end
- if name != nil then
- nodeMustBe(node.firstChild, name)
- end
- end
-
-
- def assert(b)
- if not b then
- raise "assert-fail"
- end
- end
-
- # The node `node` has empty string or string
- def text_zero_one(node)
- nodes = node.childNodes.to_a.size
-
- if nodes == 1
- text(node.firstChild)
- elsif nodes == 0
- ""
- else
- raise "wrong xml-rpc (size)"
- end
- end
-
-
- def integer(node)
- #TODO: check string for float because to_i returnsa
- # 0 when wrong string
- nodeMustBe(node, %w(i4 i8 int))
- hasOnlyOneChild(node)
-
- Convert.int(text(node.firstChild))
- end
-
- def boolean(node)
- nodeMustBe(node, "boolean")
- hasOnlyOneChild(node)
-
- Convert.boolean(text(node.firstChild))
- end
-
- def v_nil(node)
- nodeMustBe(node, "nil")
- assert( node.childNodes.to_a.size == 0 )
- nil
- end
-
- def string(node)
- nodeMustBe(node, "string")
- text_zero_one(node)
- end
-
- def double(node)
- #TODO: check string for float because to_f returnsa
- # 0.0 when wrong string
- nodeMustBe(node, "double")
- hasOnlyOneChild(node)
-
- Convert.double(text(node.firstChild))
- end
-
- def dateTime(node)
- nodeMustBe(node, "dateTime.iso8601")
- hasOnlyOneChild(node)
-
- Convert.dateTime( text(node.firstChild) )
- end
-
- def base64(node)
- nodeMustBe(node, "base64")
- #hasOnlyOneChild(node)
-
- Convert.base64(text_zero_one(node))
- end
-
- def member(node)
- nodeMustBe(node, "member")
- assert( node.childNodes.to_a.size == 2 )
-
- [ name(node[0]), value(node[1]) ]
- end
-
- def name(node)
- nodeMustBe(node, "name")
- #hasOnlyOneChild(node)
- text_zero_one(node)
- end
-
- def array(node)
- nodeMustBe(node, "array")
- hasOnlyOneChild(node, "data")
- data(node.firstChild)
- end
-
- def data(node)
- nodeMustBe(node, "data")
-
- node.childNodes.to_a.collect do |val|
- value(val)
- end
- end
-
- def param(node)
- nodeMustBe(node, "param")
- hasOnlyOneChild(node, "value")
- value(node.firstChild)
- end
-
- def methodResponse(node)
- nodeMustBe(node, "methodResponse")
- hasOnlyOneChild(node, %w(params fault))
- child = node.firstChild
-
- case child.nodeName
- when "params"
- [ true, params(child,false) ]
- when "fault"
- [ false, fault(child) ]
- else
- raise "unexpected error"
- end
-
- end
-
- def methodName(node)
- nodeMustBe(node, "methodName")
- hasOnlyOneChild(node)
- text(node.firstChild)
- end
-
- def params(node, call=true)
- nodeMustBe(node, "params")
-
- if call
- node.childNodes.to_a.collect do |n|
- param(n)
- end
- else # response (only one param)
- hasOnlyOneChild(node)
- param(node.firstChild)
- end
- end
-
- def fault(node)
- nodeMustBe(node, "fault")
- hasOnlyOneChild(node, "value")
- f = value(node.firstChild)
- Convert.fault(f)
- end
-
-
-
- # _nodeType is defined in the subclass
- def text(node)
- assert( _nodeType(node) == :TEXT )
- assert( node.hasChildNodes == false )
- assert( node.nodeValue != nil )
-
- node.nodeValue.to_s
- end
-
- def struct(node)
- nodeMustBe(node, "struct")
-
- hash = {}
- node.childNodes.to_a.each do |me|
- n, v = member(me)
- hash[n] = v
- end
-
- Convert.struct(hash)
- end
-
-
- def value(node)
- nodeMustBe(node, "value")
- nodes = node.childNodes.to_a.size
- if nodes == 0
- return ""
- elsif nodes > 1
- raise "wrong xml-rpc (size)"
- end
-
- child = node.firstChild
-
- case _nodeType(child)
- when :TEXT
- text_zero_one(node)
- when :ELEMENT
- case child.nodeName
- when "i4", "i8", "int" then integer(child)
- when "boolean" then boolean(child)
- when "string" then string(child)
- when "double" then double(child)
- when "dateTime.iso8601" then dateTime(child)
- when "base64" then base64(child)
- when "struct" then struct(child)
- when "array" then array(child)
- when "nil"
- if Config::ENABLE_NIL_PARSER
- v_nil(child)
- else
- raise "wrong/unknown XML-RPC type 'nil'"
- end
- else
- raise "wrong/unknown XML-RPC type"
- end
- else
- raise "wrong type of node"
- end
-
- end
-
- def methodCall(node)
- nodeMustBe(node, "methodCall")
- assert( (1..2).include?( node.childNodes.to_a.size ) )
- name = methodName(node[0])
-
- if node.childNodes.to_a.size == 2 then
- pa = params(node[1])
- else # no parameters given
- pa = []
- end
- [name, pa]
- end
-
- end # module TreeParserMixin
-
- class AbstractStreamParser
- def parseMethodResponse(str)
- parser = @parser_class.new
- parser.parse(str)
- raise "No valid method response!" if parser.method_name != nil
- if parser.fault != nil
- # is a fault structure
- [false, parser.fault]
- else
- # is a normal return value
- raise "Missing return value!" if parser.params.size == 0
- raise "Too many return values. Only one allowed!" if parser.params.size > 1
- [true, parser.params[0]]
- end
- end
-
- def parseMethodCall(str)
- parser = @parser_class.new
- parser.parse(str)
- raise "No valid method call - missing method name!" if parser.method_name.nil?
- [parser.method_name, parser.params]
- end
- end
-
- module StreamParserMixin
- attr_reader :params
- attr_reader :method_name
- attr_reader :fault
-
- def initialize(*a)
- super(*a)
- @params = []
- @values = []
- @val_stack = []
-
- @names = []
- @name = []
-
- @structs = []
- @struct = {}
-
- @method_name = nil
- @fault = nil
-
- @data = nil
- end
-
- def startElement(name, attrs=[])
- @data = nil
- case name
- when "value"
- @value = nil
- when "nil"
- raise "wrong/unknown XML-RPC type 'nil'" unless Config::ENABLE_NIL_PARSER
- @value = :nil
- when "array"
- @val_stack << @values
- @values = []
- when "struct"
- @names << @name
- @name = []
-
- @structs << @struct
- @struct = {}
- end
- end
-
- def endElement(name)
- @data ||= ""
- case name
- when "string"
- @value = @data
- when "i4", "i8", "int"
- @value = Convert.int(@data)
- when "boolean"
- @value = Convert.boolean(@data)
- when "double"
- @value = Convert.double(@data)
- when "dateTime.iso8601"
- @value = Convert.dateTime(@data)
- when "base64"
- @value = Convert.base64(@data)
- when "value"
- @value = @data if @value.nil?
- @values << (@value == :nil ? nil : @value)
- when "array"
- @value = @values
- @values = @val_stack.pop
- when "struct"
- @value = Convert.struct(@struct)
-
- @name = @names.pop
- @struct = @structs.pop
- when "name"
- @name[0] = @data
- when "member"
- @struct[@name[0]] = @values.pop
-
- when "param"
- @params << @values[0]
- @values = []
-
- when "fault"
- @fault = Convert.fault(@values[0])
-
- when "methodName"
- @method_name = @data
- end
-
- @data = nil
- end
-
- def character(data)
- if @data
- @data << data
- else
- @data = data
- end
- end
-
- end # module StreamParserMixin
-
- class REXMLStreamParser < AbstractStreamParser
- def initialize
- require "rexml/document"
- @parser_class = StreamListener
- end
-
- class StreamListener
- include StreamParserMixin
-
- alias :tag_start :startElement
- alias :tag_end :endElement
- alias :text :character
- alias :cdata :character
-
- def method_missing(*a)
- # ignore
- end
-
- def parse(str)
- REXML::Document.parse_stream(str, self)
- end
- end
-
- end
-
- class LibXMLStreamParser < AbstractStreamParser
- def initialize
- require 'libxml'
- @parser_class = LibXMLStreamListener
- end
-
- class LibXMLStreamListener
- include StreamParserMixin
-
- def on_start_element_ns(name, attributes, prefix, uri, namespaces)
- startElement(name)
- end
-
- def on_end_element_ns(name, prefix, uri)
- endElement(name)
- end
-
- alias :on_characters :character
- alias :on_cdata_block :character
-
- def method_missing(*a)
- end
-
- def parse(str)
- parser = LibXML::XML::SaxParser.string(str)
- parser.callbacks = self
- parser.parse()
- end
- end
- end
-
- Classes = [REXMLStreamParser, LibXMLStreamParser]
-
- # yields an instance of each installed parser
- def self.each_installed_parser
- XMLRPC::XMLParser::Classes.each do |klass|
- begin
- yield klass.new
- rescue LoadError
- end
- end
- end
-
- end # module XMLParser
-
-
-end # module XMLRPC
-
diff --git a/lib/xmlrpc/server.rb b/lib/xmlrpc/server.rb
deleted file mode 100644
index cd0fdbad38..0000000000
--- a/lib/xmlrpc/server.rb
+++ /dev/null
@@ -1,708 +0,0 @@
-# frozen_string_literal: false
-# xmlrpc/server.rb
-# Copyright (C) 2001, 2002, 2003, 2005 by Michael Neumann (mneumann@ntecs.de)
-#
-# Released under the same term of license as Ruby.
-
-require "xmlrpc/parser"
-require "xmlrpc/create"
-require "xmlrpc/config"
-require "xmlrpc/utils" # ParserWriterChooseMixin
-
-
-
-module XMLRPC # :nodoc:
-
-
-# This is the base class for all XML-RPC server-types (CGI, standalone).
-# You can add handler and set a default handler.
-# Do not use this server, as this is/should be an abstract class.
-#
-# === How the method to call is found
-# The arity (number of accepted arguments) of a handler (method or Proc
-# object) is compared to the given arguments submitted by the client for a
-# RPC, or Remote Procedure Call.
-#
-# A handler is only called if it accepts the number of arguments, otherwise
-# the search for another handler will go on. When at the end no handler was
-# found, the default_handler, XMLRPC::BasicServer#set_default_handler will be
-# called.
-#
-# With this technique it is possible to do overloading by number of parameters, but
-# only for Proc handler, because you cannot define two methods of the same name in
-# the same class.
-class BasicServer
-
- include ParserWriterChooseMixin
- include ParseContentType
-
- ERR_METHOD_MISSING = 1
- ERR_UNCAUGHT_EXCEPTION = 2
- ERR_MC_WRONG_PARAM = 3
- ERR_MC_MISSING_PARAMS = 4
- ERR_MC_MISSING_METHNAME = 5
- ERR_MC_RECURSIVE_CALL = 6
- ERR_MC_WRONG_PARAM_PARAMS = 7
- ERR_MC_EXPECTED_STRUCT = 8
-
-
- # Creates a new XMLRPC::BasicServer instance, which should not be
- # done, because XMLRPC::BasicServer is an abstract class. This
- # method should be called from a subclass indirectly by a +super+ call
- # in the initialize method.
- #
- # The parameter +class_delim+ is used by add_handler, see
- # XMLRPC::BasicServer#add_handler, when an object is added as a handler, to
- # delimit the object-prefix and the method-name.
- def initialize(class_delim=".")
- @handler = []
- @default_handler = nil
- @service_hook = nil
-
- @class_delim = class_delim
- @create = nil
- @parser = nil
-
- add_multicall if Config::ENABLE_MULTICALL
- add_introspection if Config::ENABLE_INTROSPECTION
- end
-
- # Adds +aBlock+ to the list of handlers, with +name+ as the name of
- # the method.
- #
- # Parameters +signature+ and +help+ are used by the Introspection method if
- # specified, where +signature+ is either an Array containing strings each
- # representing a type of it's signature (the first is the return value) or
- # an Array of Arrays if the method has multiple signatures.
- #
- # Value type-names are "int, boolean, double, string, dateTime.iso8601,
- # base64, array, struct".
- #
- # Parameter +help+ is a String with information about how to call this method etc.
- #
- # When a method fails, it can tell the client by throwing an
- # XMLRPC::FaultException like in this example:
- #
- # s.add_handler("michael.div") do |a,b|
- # if b == 0
- # raise XMLRPC::FaultException.new(1, "division by zero")
- # else
- # a / b
- # end
- # end
- #
- # In the case of <code>b==0</code> the client gets an object back of type
- # XMLRPC::FaultException that has a +faultCode+ and +faultString+ field.
- #
- # This is the second form of ((<add_handler|XMLRPC::BasicServer#add_handler>)).
- # To add an object write:
- #
- # server.add_handler("michael", MyHandlerClass.new)
- #
- # All public methods of MyHandlerClass are accessible to
- # the XML-RPC clients by <code>michael."name of method"</code>. This is
- # where the +class_delim+ in XMLRPC::BasicServer.new plays it's role, a
- # XML-RPC method-name is defined by +prefix+ + +class_delim+ + <code>"name
- # of method"</code>.
- #
- # The third form of +add_handler is to use XMLRPC::Service::Interface to
- # generate an object, which represents an interface (with signature and
- # help text) for a handler class.
- #
- # The +interface+ parameter must be an instance of XMLRPC::Service::Interface.
- # Adds all methods of +obj+ which are defined in the +interface+ to the server.
- #
- # This is the recommended way of adding services to a server!
- def add_handler(prefix, obj_or_signature=nil, help=nil, &block)
- if block_given?
- # proc-handler
- @handler << [prefix, block, obj_or_signature, help]
- else
- if prefix.kind_of? String
- # class-handler
- raise ArgumentError, "Expected non-nil value" if obj_or_signature.nil?
- @handler << [prefix + @class_delim, obj_or_signature]
- elsif prefix.kind_of? XMLRPC::Service::BasicInterface
- # class-handler with interface
- # add all methods
- @handler += prefix.get_methods(obj_or_signature, @class_delim)
- else
- raise ArgumentError, "Wrong type for parameter 'prefix'"
- end
- end
- self
- end
-
- # Returns the service-hook, which is called on each service request (RPC)
- # unless it's +nil+.
- def get_service_hook
- @service_hook
- end
-
- # A service-hook is called for each service request (RPC).
- #
- # You can use a service-hook for example to wrap existing methods and catch
- # exceptions of them or convert values to values recognized by XMLRPC.
- #
- # You can disable it by passing +nil+ as the +handler+ parameter.
- #
- # The service-hook is called with a Proc object along with any parameters.
- #
- # An example:
- #
- # server.set_service_hook {|obj, *args|
- # begin
- # ret = obj.call(*args) # call the original service-method
- # # could convert the return value
- # rescue
- # # rescue exceptions
- # end
- # }
- #
- def set_service_hook(&handler)
- @service_hook = handler
- self
- end
-
- # Returns the default-handler, which is called when no handler for
- # a method-name is found.
- #
- # It is either a Proc object or +nil+.
- def get_default_handler
- @default_handler
- end
-
- # Sets +handler+ as the default-handler, which is called when
- # no handler for a method-name is found.
- #
- # +handler+ is a code-block.
- #
- # The default-handler is called with the (XML-RPC) method-name as first
- # argument, and the other arguments are the parameters given by the
- # client-call.
- #
- # If no block is specified the default of XMLRPC::BasicServer is
- # used, which raises a XMLRPC::FaultException saying "method missing".
- def set_default_handler(&handler)
- @default_handler = handler
- self
- end
-
- # Adds the multi-call handler <code>"system.multicall"</code>.
- def add_multicall
- add_handler("system.multicall", %w(array array), "Multicall Extension") do |arrStructs|
- unless arrStructs.is_a? Array
- raise XMLRPC::FaultException.new(ERR_MC_WRONG_PARAM, "system.multicall expects an array")
- end
-
- arrStructs.collect {|call|
- if call.is_a? Hash
- methodName = call["methodName"]
- params = call["params"]
-
- if params.nil?
- multicall_fault(ERR_MC_MISSING_PARAMS, "Missing params")
- elsif methodName.nil?
- multicall_fault(ERR_MC_MISSING_METHNAME, "Missing methodName")
- else
- if methodName == "system.multicall"
- multicall_fault(ERR_MC_RECURSIVE_CALL, "Recursive system.multicall forbidden")
- else
- unless params.is_a? Array
- multicall_fault(ERR_MC_WRONG_PARAM_PARAMS, "Parameter params have to be an Array")
- else
- ok, val = call_method(methodName, *params)
- if ok
- # correct return value
- [val]
- else
- # exception
- multicall_fault(val.faultCode, val.faultString)
- end
- end
- end
- end
-
- else
- multicall_fault(ERR_MC_EXPECTED_STRUCT, "system.multicall expected struct")
- end
- }
- end # end add_handler
- self
- end
-
- # Adds the introspection handlers <code>"system.listMethods"</code>,
- # <code>"system.methodSignature"</code> and
- # <code>"system.methodHelp"</code>, where only the first one works.
- def add_introspection
- add_handler("system.listMethods",%w(array), "List methods available on this XML-RPC server") do
- methods = []
- @handler.each do |name, obj|
- if obj.kind_of? Proc
- methods << name
- else
- obj.class.public_instance_methods(false).each do |meth|
- methods << "#{name}#{meth}"
- end
- end
- end
- methods
- end
-
- add_handler("system.methodSignature", %w(array string), "Returns method signature") do |meth|
- sigs = []
- @handler.each do |name, obj, sig|
- if obj.kind_of? Proc and sig != nil and name == meth
- if sig[0].kind_of? Array
- # sig contains multiple signatures, e.g. [["array"], ["array", "string"]]
- sig.each {|s| sigs << s}
- else
- # sig is a single signature, e.g. ["array"]
- sigs << sig
- end
- end
- end
- sigs.uniq! || sigs # remove eventually duplicated signatures
- end
-
- add_handler("system.methodHelp", %w(string string), "Returns help on using this method") do |meth|
- help = nil
- @handler.each do |name, obj, sig, hlp|
- if obj.kind_of? Proc and name == meth
- help = hlp
- break
- end
- end
- help || ""
- end
-
- self
- end
-
-
-
- def process(data)
- method, params = parser().parseMethodCall(data)
- handle(method, *params)
- end
-
- private
-
- def multicall_fault(nr, str)
- {"faultCode" => nr, "faultString" => str}
- end
-
- def dispatch(methodname, *args)
- for name, obj in @handler
- if obj.kind_of? Proc
- next unless methodname == name
- else
- next unless methodname =~ /^#{name}(.+)$/
- next unless obj.respond_to? $1
- obj = obj.method($1)
- end
-
- if check_arity(obj, args.size)
- if @service_hook.nil?
- return obj.call(*args)
- else
- return @service_hook.call(obj, *args)
- end
- end
- end
-
- if @default_handler.nil?
- raise XMLRPC::FaultException.new(ERR_METHOD_MISSING, "Method #{methodname} missing or wrong number of parameters!")
- else
- @default_handler.call(methodname, *args)
- end
- end
-
-
- # Returns +true+, if the arity of +obj+ matches +n_args+
- def check_arity(obj, n_args)
- ary = obj.arity
-
- if ary >= 0
- n_args == ary
- else
- n_args >= (ary+1).abs
- end
- end
-
-
-
- def call_method(methodname, *args)
- begin
- [true, dispatch(methodname, *args)]
- rescue XMLRPC::FaultException => e
- [false, e]
- rescue Exception => e
- [false, XMLRPC::FaultException.new(ERR_UNCAUGHT_EXCEPTION, "Uncaught exception #{e.message} in method #{methodname}")]
- end
- end
-
- def handle(methodname, *args)
- create().methodResponse(*call_method(methodname, *args))
- end
-
-
-end
-
-
-# Implements a CGI-based XML-RPC server.
-#
-# require "xmlrpc/server"
-#
-# s = XMLRPC::CGIServer.new
-#
-# s.add_handler("michael.add") do |a,b|
-# a + b
-# end
-#
-# s.add_handler("michael.div") do |a,b|
-# if b == 0
-# raise XMLRPC::FaultException.new(1, "division by zero")
-# else
-# a / b
-# end
-# end
-#
-# s.set_default_handler do |name, *args|
-# raise XMLRPC::FaultException.new(-99, "Method #{name} missing" +
-# " or wrong number of parameters!")
-# end
-#
-# s.serve
-#
-#
-# <b>Note:</b> Make sure that you don't write to standard-output in a
-# handler, or in any other part of your program, this would cause a CGI-based
-# server to fail!
-class CGIServer < BasicServer
- @@obj = nil
-
- # Creates a new XMLRPC::CGIServer instance.
- #
- # All parameters given are by-passed to XMLRPC::BasicServer.new.
- #
- # You can only create <b>one</b> XMLRPC::CGIServer instance, because more
- # than one makes no sense.
- def CGIServer.new(*a)
- @@obj = super(*a) if @@obj.nil?
- @@obj
- end
-
- def initialize(*a)
- super(*a)
- end
-
- # Call this after you have added all you handlers to the server.
- #
- # This method processes a XML-RPC method call and sends the answer
- # back to the client.
- def serve
- catch(:exit_serve) {
- length = ENV['CONTENT_LENGTH'].to_i
-
- http_error(405, "Method Not Allowed") unless ENV['REQUEST_METHOD'] == "POST"
- http_error(400, "Bad Request") unless parse_content_type(ENV['CONTENT_TYPE']).first == "text/xml"
- http_error(411, "Length Required") unless length > 0
-
- # TODO: do we need a call to binmode?
- $stdin.binmode if $stdin.respond_to? :binmode
- data = $stdin.read(length)
-
- http_error(400, "Bad Request") if data.nil? or data.bytesize != length
-
- http_write(process(data), "Content-type" => "text/xml; charset=utf-8")
- }
- end
-
-
- private
-
- def http_error(status, message)
- err = "#{status} #{message}"
- msg = <<-"MSGEND"
- <html>
- <head>
- <title>#{err}</title>
- </head>
- <body>
- <h1>#{err}</h1>
- <p>Unexpected error occurred while processing XML-RPC request!</p>
- </body>
- </html>
- MSGEND
-
- http_write(msg, "Status" => err, "Content-type" => "text/html")
- throw :exit_serve # exit from the #serve method
- end
-
- def http_write(body, header)
- h = {}
- header.each {|key, value| h[key.to_s.capitalize] = value}
- h['Status'] ||= "200 OK"
- h['Content-length'] ||= body.bytesize.to_s
-
- str = ""
- h.each {|key, value| str << "#{key}: #{value}\r\n"}
- str << "\r\n#{body}"
-
- print str
- end
-
-end
-
-
-# Implements a XML-RPC server, which works with Apache mod_ruby.
-#
-# Use it in the same way as XMLRPC::CGIServer!
-class ModRubyServer < BasicServer
-
- # Creates a new XMLRPC::ModRubyServer instance.
- #
- # All parameters given are by-passed to XMLRPC::BasicServer.new.
- def initialize(*a)
- @ap = Apache::request
- super(*a)
- end
-
- # Call this after you have added all you handlers to the server.
- #
- # This method processes a XML-RPC method call and sends the answer
- # back to the client.
- def serve
- catch(:exit_serve) {
- header = {}
- @ap.headers_in.each {|key, value| header[key.capitalize] = value}
-
- length = header['Content-length'].to_i
-
- http_error(405, "Method Not Allowed") unless @ap.request_method == "POST"
- http_error(400, "Bad Request") unless parse_content_type(header['Content-type']).first == "text/xml"
- http_error(411, "Length Required") unless length > 0
-
- # TODO: do we need a call to binmode?
- @ap.binmode
- data = @ap.read(length)
-
- http_error(400, "Bad Request") if data.nil? or data.bytesize != length
-
- http_write(process(data), 200, "Content-type" => "text/xml; charset=utf-8")
- }
- end
-
-
- private
-
- def http_error(status, message)
- err = "#{status} #{message}"
- msg = <<-"MSGEND"
- <html>
- <head>
- <title>#{err}</title>
- </head>
- <body>
- <h1>#{err}</h1>
- <p>Unexpected error occurred while processing XML-RPC request!</p>
- </body>
- </html>
- MSGEND
-
- http_write(msg, status, "Status" => err, "Content-type" => "text/html")
- throw :exit_serve # exit from the #serve method
- end
-
- def http_write(body, status, header)
- h = {}
- header.each {|key, value| h[key.to_s.capitalize] = value}
- h['Status'] ||= "200 OK"
- h['Content-length'] ||= body.bytesize.to_s
-
- h.each {|key, value| @ap.headers_out[key] = value }
- @ap.content_type = h["Content-type"]
- @ap.status = status.to_i
- @ap.send_http_header
-
- @ap.print body
- end
-
-end
-
-
-class WEBrickServlet < BasicServer; end # forward declaration
-
-# Implements a standalone XML-RPC server. The method XMLRPC::Server#serve is
-# left if a SIGHUP is sent to the program.
-#
-# require "xmlrpc/server"
-#
-# s = XMLRPC::Server.new(8080)
-#
-# s.add_handler("michael.add") do |a,b|
-# a + b
-# end
-#
-# s.add_handler("michael.div") do |a,b|
-# if b == 0
-# raise XMLRPC::FaultException.new(1, "division by zero")
-# else
-# a / b
-# end
-# end
-#
-# s.set_default_handler do |name, *args|
-# raise XMLRPC::FaultException.new(-99, "Method #{name} missing" +
-# " or wrong number of parameters!")
-# end
-#
-# s.serve
-class Server < WEBrickServlet
-
- # Creates a new XMLRPC::Server instance, which is a XML-RPC server
- # listening on the given +port+ and accepts requests for the given +host+,
- # which is +localhost+ by default.
- #
- # The server is not started, to start it you have to call
- # XMLRPC::Server#serve.
- #
- # The optional +audit+ and +debug+ parameters are obsolete!
- #
- # All additionally provided parameters in <code>*a</code> are by-passed to
- # XMLRPC::BasicServer.new.
- def initialize(port=8080, host="127.0.0.1", maxConnections=4, stdlog=$stdout, audit=true, debug=true, *a)
- super(*a)
- require 'webrick'
- @server = WEBrick::HTTPServer.new(:Port => port, :BindAddress => host, :MaxClients => maxConnections,
- :Logger => WEBrick::Log.new(stdlog))
- @server.mount("/", self)
- end
-
- # Call this after you have added all you handlers to the server.
- # This method starts the server to listen for XML-RPC requests and answer them.
- def serve
- signals = %w[INT TERM HUP] & Signal.list.keys
- signals.each { |signal| trap(signal) { @server.shutdown } }
-
- @server.start
- end
-
- # Stops and shuts the server down.
- def shutdown
- @server.shutdown
- end
-
-end
-
-
-# Implements a servlet for use with WEBrick, a pure Ruby (HTTP) server
-# framework.
-#
-# require "webrick"
-# require "xmlrpc/server"
-#
-# s = XMLRPC::WEBrickServlet.new
-# s.add_handler("michael.add") do |a,b|
-# a + b
-# end
-#
-# s.add_handler("michael.div") do |a,b|
-# if b == 0
-# raise XMLRPC::FaultException.new(1, "division by zero")
-# else
-# a / b
-# end
-# end
-#
-# s.set_default_handler do |name, *args|
-# raise XMLRPC::FaultException.new(-99, "Method #{name} missing" +
-# " or wrong number of parameters!")
-# end
-#
-# httpserver = WEBrick::HTTPServer.new(:Port => 8080)
-# httpserver.mount("/RPC2", s)
-# trap("HUP") { httpserver.shutdown } # use 1 instead of "HUP" on Windows
-# httpserver.start
-class WEBrickServlet < BasicServer
- def initialize(*a)
- super
- require "webrick/httpstatus"
- @valid_ip = nil
- end
-
- # Deprecated from WEBrick/1.2.2, but does not break anything.
- def require_path_info?
- false
- end
-
- def get_instance(config, *options)
- # TODO: set config & options
- self
- end
-
- # Specifies the valid IP addresses that are allowed to connect to the server.
- #
- # Each IP is either a String or a Regexp.
- def set_valid_ip(*ip_addr)
- if ip_addr.size == 1 and ip_addr[0].nil?
- @valid_ip = nil
- else
- @valid_ip = ip_addr
- end
- end
-
- # Return the valid IP addresses that are allowed to connect to the server.
- #
- # See also, XMLRPC::Server#set_valid_ip
- def get_valid_ip
- @valid_ip
- end
-
- def service(request, response)
-
- if @valid_ip
- raise WEBrick::HTTPStatus::Forbidden unless @valid_ip.any? { |ip| request.peeraddr[3] =~ ip }
- end
-
- if request.request_method != "POST"
- raise WEBrick::HTTPStatus::MethodNotAllowed,
- "unsupported method `#{request.request_method}'."
- end
-
- if parse_content_type(request['Content-type']).first != "text/xml"
- raise WEBrick::HTTPStatus::BadRequest
- end
-
- length = (request['Content-length'] || 0).to_i
-
- raise WEBrick::HTTPStatus::LengthRequired unless length > 0
-
- data = request.body
-
- if data.nil? or data.bytesize != length
- raise WEBrick::HTTPStatus::BadRequest
- end
-
- resp = process(data)
- if resp.nil? or resp.bytesize <= 0
- raise WEBrick::HTTPStatus::InternalServerError
- end
-
- response.status = 200
- response['Content-Length'] = resp.bytesize
- response['Content-Type'] = "text/xml; charset=utf-8"
- response.body = resp
- end
-end
-
-
-end # module XMLRPC
-
-
-=begin
-= History
- $Id$
-=end
-
diff --git a/lib/xmlrpc/utils.rb b/lib/xmlrpc/utils.rb
deleted file mode 100644
index cd2ab107d9..0000000000
--- a/lib/xmlrpc/utils.rb
+++ /dev/null
@@ -1,172 +0,0 @@
-# frozen_string_literal: false
-#
-# Copyright (C) 2001, 2002, 2003 by Michael Neumann (mneumann@ntecs.de)
-#
-# $Id$
-#
-module XMLRPC # :nodoc:
-
-
- # This module enables a user-class to be marshalled
- # by XML-RPC for Ruby into a Hash, with one additional
- # key/value pair <code>___class___ => ClassName</code>
- #
- module Marshallable
- end
-
-
- # Defines ParserWriterChooseMixin, which makes it possible to choose a
- # different XMLWriter and/or XMLParser then the default one.
- #
- # The Mixin is used in client.rb (class XMLRPC::Client)
- # and server.rb (class XMLRPC::BasicServer)
- module ParserWriterChooseMixin
-
- # Sets the XMLWriter to use for generating XML output.
- #
- # Should be an instance of a class from module XMLRPC::XMLWriter.
- #
- # If this method is not called, then XMLRPC::Config::DEFAULT_WRITER is used.
- def set_writer(writer)
- @create = Create.new(writer)
- self
- end
-
- # Sets the XMLParser to use for parsing XML documents.
- #
- # Should be an instance of a class from module XMLRPC::XMLParser.
- #
- # If this method is not called, then XMLRPC::Config::DEFAULT_PARSER is used.
- def set_parser(parser)
- @parser = parser
- self
- end
-
- private
-
- def create
- # if set_writer was not already called then call it now
- if @create.nil? then
- set_writer(Config::DEFAULT_WRITER.new)
- end
- @create
- end
-
- def parser
- # if set_parser was not already called then call it now
- if @parser.nil? then
- set_parser(Config::DEFAULT_PARSER.new)
- end
- @parser
- end
-
- end # module ParserWriterChooseMixin
-
-
- module Service
-
- # Base class for XMLRPC::Service::Interface definitions, used
- # by XMLRPC::BasicServer#add_handler
- class BasicInterface
- attr_reader :prefix, :methods
-
- def initialize(prefix)
- @prefix = prefix
- @methods = []
- end
-
- def add_method(sig, help=nil, meth_name=nil)
- mname = nil
- sig = [sig] if sig.kind_of? String
-
- sig = sig.collect do |s|
- name, si = parse_sig(s)
- raise "Wrong signatures!" if mname != nil and name != mname
- mname = name
- si
- end
-
- @methods << [mname, meth_name || mname, sig, help]
- end
-
- private
-
- def parse_sig(sig)
- # sig is a String
- if sig =~ /^\s*(\w+)\s+([^(]+)(\(([^)]*)\))?\s*$/
- params = [$1]
- name = $2.strip
- $4.split(",").each {|i| params << i.strip} if $4 != nil
- return name, params
- else
- raise "Syntax error in signature"
- end
- end
-
- end # class BasicInterface
-
- #
- # Class which wraps a XMLRPC::Service::Interface definition, used
- # by XMLRPC::BasicServer#add_handler
- #
- class Interface < BasicInterface
- def initialize(prefix, &p)
- raise "No interface specified" if p.nil?
- super(prefix)
- instance_eval(&p)
- end
-
- def get_methods(obj, delim=".")
- prefix = @prefix + delim
- @methods.collect { |name, meth, sig, help|
- [prefix + name.to_s, obj.method(meth).to_proc, sig, help]
- }
- end
-
- private
-
- def meth(*a)
- add_method(*a)
- end
-
- end # class Interface
-
- class PublicInstanceMethodsInterface < BasicInterface
- def initialize(prefix)
- super(prefix)
- end
-
- def get_methods(obj, delim=".")
- prefix = @prefix + delim
- obj.class.public_instance_methods(false).collect { |name|
- [prefix + name.to_s, obj.method(name).to_proc, nil, nil]
- }
- end
- end
-
-
- end # module Service
-
-
- #
- # Short-form to create a XMLRPC::Service::Interface
- #
- def self.interface(prefix, &p)
- Service::Interface.new(prefix, &p)
- end
-
- # Short-cut for creating a XMLRPC::Service::PublicInstanceMethodsInterface
- def self.iPIMethods(prefix)
- Service::PublicInstanceMethodsInterface.new(prefix)
- end
-
-
- module ParseContentType
- def parse_content_type(str)
- a, *b = str.split(";")
- return a.strip.downcase, *b
- end
- end
-
-end # module XMLRPC
-