first commit
This commit is contained in:
commit
88ebdb465c
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
# Bỏ qua thư mục build/
|
||||||
|
build/
|
||||||
37
CMakeLists.txt
Normal file
37
CMakeLists.txt
Normal file
|
|
@ -0,0 +1,37 @@
|
||||||
|
cmake_minimum_required(VERSION 3.10)
|
||||||
|
project(xmlrpcpp)
|
||||||
|
|
||||||
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
|
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
||||||
|
|
||||||
|
if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||||
|
add_compile_options(-Wall -Wextra -Wpedantic -fPIC)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
add_library(xmlrpcpp
|
||||||
|
src/XmlRpcClient.cpp
|
||||||
|
src/XmlRpcDispatch.cpp
|
||||||
|
src/XmlRpcServer.cpp
|
||||||
|
src/XmlRpcServerConnection.cpp
|
||||||
|
src/XmlRpcServerMethod.cpp
|
||||||
|
src/XmlRpcSocket.cpp
|
||||||
|
src/XmlRpcSource.cpp
|
||||||
|
src/XmlRpcUtil.cpp
|
||||||
|
src/XmlRpcValue.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
target_include_directories(xmlrpcpp
|
||||||
|
PUBLIC
|
||||||
|
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
|
||||||
|
$<INSTALL_INTERFACE:include/${PROJECT_NAME}>
|
||||||
|
)
|
||||||
|
|
||||||
|
install(TARGETS xmlrpcpp
|
||||||
|
ARCHIVE DESTINATION lib
|
||||||
|
LIBRARY DESTINATION lib
|
||||||
|
)
|
||||||
|
|
||||||
|
install(DIRECTORY include/
|
||||||
|
DESTINATION include/
|
||||||
|
)
|
||||||
504
COPYING
Normal file
504
COPYING
Normal file
|
|
@ -0,0 +1,504 @@
|
||||||
|
GNU LESSER GENERAL PUBLIC LICENSE
|
||||||
|
Version 2.1, February 1999
|
||||||
|
|
||||||
|
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
|
||||||
|
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
|
[This is the first released version of the Lesser GPL. It also counts
|
||||||
|
as the successor of the GNU Library Public License, version 2, hence
|
||||||
|
the version number 2.1.]
|
||||||
|
|
||||||
|
Preamble
|
||||||
|
|
||||||
|
The licenses for most software are designed to take away your
|
||||||
|
freedom to share and change it. By contrast, the GNU General Public
|
||||||
|
Licenses are intended to guarantee your freedom to share and change
|
||||||
|
free software--to make sure the software is free for all its users.
|
||||||
|
|
||||||
|
This license, the Lesser General Public License, applies to some
|
||||||
|
specially designated software packages--typically libraries--of the
|
||||||
|
Free Software Foundation and other authors who decide to use it. You
|
||||||
|
can use it too, but we suggest you first think carefully about whether
|
||||||
|
this license or the ordinary General Public License is the better
|
||||||
|
strategy to use in any particular case, based on the explanations below.
|
||||||
|
|
||||||
|
When we speak of free software, we are referring to freedom of use,
|
||||||
|
not price. Our General Public Licenses are designed to make sure that
|
||||||
|
you have the freedom to distribute copies of free software (and charge
|
||||||
|
for this service if you wish); that you receive source code or can get
|
||||||
|
it if you want it; that you can change the software and use pieces of
|
||||||
|
it in new free programs; and that you are informed that you can do
|
||||||
|
these things.
|
||||||
|
|
||||||
|
To protect your rights, we need to make restrictions that forbid
|
||||||
|
distributors to deny you these rights or to ask you to surrender these
|
||||||
|
rights. These restrictions translate to certain responsibilities for
|
||||||
|
you if you distribute copies of the library or if you modify it.
|
||||||
|
|
||||||
|
For example, if you distribute copies of the library, whether gratis
|
||||||
|
or for a fee, you must give the recipients all the rights that we gave
|
||||||
|
you. You must make sure that they, too, receive or can get the source
|
||||||
|
code. If you link other code with the library, you must provide
|
||||||
|
complete object files to the recipients, so that they can relink them
|
||||||
|
with the library after making changes to the library and recompiling
|
||||||
|
it. And you must show them these terms so they know their rights.
|
||||||
|
|
||||||
|
We protect your rights with a two-step method: (1) we copyright the
|
||||||
|
library, and (2) we offer you this license, which gives you legal
|
||||||
|
permission to copy, distribute and/or modify the library.
|
||||||
|
|
||||||
|
To protect each distributor, we want to make it very clear that
|
||||||
|
there is no warranty for the free library. Also, if the library is
|
||||||
|
modified by someone else and passed on, the recipients should know
|
||||||
|
that what they have is not the original version, so that the original
|
||||||
|
author's reputation will not be affected by problems that might be
|
||||||
|
introduced by others.
|
||||||
|
|
||||||
|
Finally, software patents pose a constant threat to the existence of
|
||||||
|
any free program. We wish to make sure that a company cannot
|
||||||
|
effectively restrict the users of a free program by obtaining a
|
||||||
|
restrictive license from a patent holder. Therefore, we insist that
|
||||||
|
any patent license obtained for a version of the library must be
|
||||||
|
consistent with the full freedom of use specified in this license.
|
||||||
|
|
||||||
|
Most GNU software, including some libraries, is covered by the
|
||||||
|
ordinary GNU General Public License. This license, the GNU Lesser
|
||||||
|
General Public License, applies to certain designated libraries, and
|
||||||
|
is quite different from the ordinary General Public License. We use
|
||||||
|
this license for certain libraries in order to permit linking those
|
||||||
|
libraries into non-free programs.
|
||||||
|
|
||||||
|
When a program is linked with a library, whether statically or using
|
||||||
|
a shared library, the combination of the two is legally speaking a
|
||||||
|
combined work, a derivative of the original library. The ordinary
|
||||||
|
General Public License therefore permits such linking only if the
|
||||||
|
entire combination fits its criteria of freedom. The Lesser General
|
||||||
|
Public License permits more lax criteria for linking other code with
|
||||||
|
the library.
|
||||||
|
|
||||||
|
We call this license the "Lesser" General Public License because it
|
||||||
|
does Less to protect the user's freedom than the ordinary General
|
||||||
|
Public License. It also provides other free software developers Less
|
||||||
|
of an advantage over competing non-free programs. These disadvantages
|
||||||
|
are the reason we use the ordinary General Public License for many
|
||||||
|
libraries. However, the Lesser license provides advantages in certain
|
||||||
|
special circumstances.
|
||||||
|
|
||||||
|
For example, on rare occasions, there may be a special need to
|
||||||
|
encourage the widest possible use of a certain library, so that it becomes
|
||||||
|
a de-facto standard. To achieve this, non-free programs must be
|
||||||
|
allowed to use the library. A more frequent case is that a free
|
||||||
|
library does the same job as widely used non-free libraries. In this
|
||||||
|
case, there is little to gain by limiting the free library to free
|
||||||
|
software only, so we use the Lesser General Public License.
|
||||||
|
|
||||||
|
In other cases, permission to use a particular library in non-free
|
||||||
|
programs enables a greater number of people to use a large body of
|
||||||
|
free software. For example, permission to use the GNU C Library in
|
||||||
|
non-free programs enables many more people to use the whole GNU
|
||||||
|
operating system, as well as its variant, the GNU/Linux operating
|
||||||
|
system.
|
||||||
|
|
||||||
|
Although the Lesser General Public License is Less protective of the
|
||||||
|
users' freedom, it does ensure that the user of a program that is
|
||||||
|
linked with the Library has the freedom and the wherewithal to run
|
||||||
|
that program using a modified version of the Library.
|
||||||
|
|
||||||
|
The precise terms and conditions for copying, distribution and
|
||||||
|
modification follow. Pay close attention to the difference between a
|
||||||
|
"work based on the library" and a "work that uses the library". The
|
||||||
|
former contains code derived from the library, whereas the latter must
|
||||||
|
be combined with the library in order to run.
|
||||||
|
|
||||||
|
GNU LESSER GENERAL PUBLIC LICENSE
|
||||||
|
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||||
|
|
||||||
|
0. This License Agreement applies to any software library or other
|
||||||
|
program which contains a notice placed by the copyright holder or
|
||||||
|
other authorized party saying it may be distributed under the terms of
|
||||||
|
this Lesser General Public License (also called "this License").
|
||||||
|
Each licensee is addressed as "you".
|
||||||
|
|
||||||
|
A "library" means a collection of software functions and/or data
|
||||||
|
prepared so as to be conveniently linked with application programs
|
||||||
|
(which use some of those functions and data) to form executables.
|
||||||
|
|
||||||
|
The "Library", below, refers to any such software library or work
|
||||||
|
which has been distributed under these terms. A "work based on the
|
||||||
|
Library" means either the Library or any derivative work under
|
||||||
|
copyright law: that is to say, a work containing the Library or a
|
||||||
|
portion of it, either verbatim or with modifications and/or translated
|
||||||
|
straightforwardly into another language. (Hereinafter, translation is
|
||||||
|
included without limitation in the term "modification".)
|
||||||
|
|
||||||
|
"Source code" for a work means the preferred form of the work for
|
||||||
|
making modifications to it. For a library, complete source code means
|
||||||
|
all the source code for all modules it contains, plus any associated
|
||||||
|
interface definition files, plus the scripts used to control compilation
|
||||||
|
and installation of the library.
|
||||||
|
|
||||||
|
Activities other than copying, distribution and modification are not
|
||||||
|
covered by this License; they are outside its scope. The act of
|
||||||
|
running a program using the Library is not restricted, and output from
|
||||||
|
such a program is covered only if its contents constitute a work based
|
||||||
|
on the Library (independent of the use of the Library in a tool for
|
||||||
|
writing it). Whether that is true depends on what the Library does
|
||||||
|
and what the program that uses the Library does.
|
||||||
|
|
||||||
|
1. You may copy and distribute verbatim copies of the Library's
|
||||||
|
complete source code as you receive it, in any medium, provided that
|
||||||
|
you conspicuously and appropriately publish on each copy an
|
||||||
|
appropriate copyright notice and disclaimer of warranty; keep intact
|
||||||
|
all the notices that refer to this License and to the absence of any
|
||||||
|
warranty; and distribute a copy of this License along with the
|
||||||
|
Library.
|
||||||
|
|
||||||
|
You may charge a fee for the physical act of transferring a copy,
|
||||||
|
and you may at your option offer warranty protection in exchange for a
|
||||||
|
fee.
|
||||||
|
|
||||||
|
2. You may modify your copy or copies of the Library or any portion
|
||||||
|
of it, thus forming a work based on the Library, and copy and
|
||||||
|
distribute such modifications or work under the terms of Section 1
|
||||||
|
above, provided that you also meet all of these conditions:
|
||||||
|
|
||||||
|
a) The modified work must itself be a software library.
|
||||||
|
|
||||||
|
b) You must cause the files modified to carry prominent notices
|
||||||
|
stating that you changed the files and the date of any change.
|
||||||
|
|
||||||
|
c) You must cause the whole of the work to be licensed at no
|
||||||
|
charge to all third parties under the terms of this License.
|
||||||
|
|
||||||
|
d) If a facility in the modified Library refers to a function or a
|
||||||
|
table of data to be supplied by an application program that uses
|
||||||
|
the facility, other than as an argument passed when the facility
|
||||||
|
is invoked, then you must make a good faith effort to ensure that,
|
||||||
|
in the event an application does not supply such function or
|
||||||
|
table, the facility still operates, and performs whatever part of
|
||||||
|
its purpose remains meaningful.
|
||||||
|
|
||||||
|
(For example, a function in a library to compute square roots has
|
||||||
|
a purpose that is entirely well-defined independent of the
|
||||||
|
application. Therefore, Subsection 2d requires that any
|
||||||
|
application-supplied function or table used by this function must
|
||||||
|
be optional: if the application does not supply it, the square
|
||||||
|
root function must still compute square roots.)
|
||||||
|
|
||||||
|
These requirements apply to the modified work as a whole. If
|
||||||
|
identifiable sections of that work are not derived from the Library,
|
||||||
|
and can be reasonably considered independent and separate works in
|
||||||
|
themselves, then this License, and its terms, do not apply to those
|
||||||
|
sections when you distribute them as separate works. But when you
|
||||||
|
distribute the same sections as part of a whole which is a work based
|
||||||
|
on the Library, the distribution of the whole must be on the terms of
|
||||||
|
this License, whose permissions for other licensees extend to the
|
||||||
|
entire whole, and thus to each and every part regardless of who wrote
|
||||||
|
it.
|
||||||
|
|
||||||
|
Thus, it is not the intent of this section to claim rights or contest
|
||||||
|
your rights to work written entirely by you; rather, the intent is to
|
||||||
|
exercise the right to control the distribution of derivative or
|
||||||
|
collective works based on the Library.
|
||||||
|
|
||||||
|
In addition, mere aggregation of another work not based on the Library
|
||||||
|
with the Library (or with a work based on the Library) on a volume of
|
||||||
|
a storage or distribution medium does not bring the other work under
|
||||||
|
the scope of this License.
|
||||||
|
|
||||||
|
3. You may opt to apply the terms of the ordinary GNU General Public
|
||||||
|
License instead of this License to a given copy of the Library. To do
|
||||||
|
this, you must alter all the notices that refer to this License, so
|
||||||
|
that they refer to the ordinary GNU General Public License, version 2,
|
||||||
|
instead of to this License. (If a newer version than version 2 of the
|
||||||
|
ordinary GNU General Public License has appeared, then you can specify
|
||||||
|
that version instead if you wish.) Do not make any other change in
|
||||||
|
these notices.
|
||||||
|
|
||||||
|
Once this change is made in a given copy, it is irreversible for
|
||||||
|
that copy, so the ordinary GNU General Public License applies to all
|
||||||
|
subsequent copies and derivative works made from that copy.
|
||||||
|
|
||||||
|
This option is useful when you wish to copy part of the code of
|
||||||
|
the Library into a program that is not a library.
|
||||||
|
|
||||||
|
4. You may copy and distribute the Library (or a portion or
|
||||||
|
derivative of it, under Section 2) in object code or executable form
|
||||||
|
under the terms of Sections 1 and 2 above provided that you accompany
|
||||||
|
it with the complete corresponding machine-readable source code, which
|
||||||
|
must be distributed under the terms of Sections 1 and 2 above on a
|
||||||
|
medium customarily used for software interchange.
|
||||||
|
|
||||||
|
If distribution of object code is made by offering access to copy
|
||||||
|
from a designated place, then offering equivalent access to copy the
|
||||||
|
source code from the same place satisfies the requirement to
|
||||||
|
distribute the source code, even though third parties are not
|
||||||
|
compelled to copy the source along with the object code.
|
||||||
|
|
||||||
|
5. A program that contains no derivative of any portion of the
|
||||||
|
Library, but is designed to work with the Library by being compiled or
|
||||||
|
linked with it, is called a "work that uses the Library". Such a
|
||||||
|
work, in isolation, is not a derivative work of the Library, and
|
||||||
|
therefore falls outside the scope of this License.
|
||||||
|
|
||||||
|
However, linking a "work that uses the Library" with the Library
|
||||||
|
creates an executable that is a derivative of the Library (because it
|
||||||
|
contains portions of the Library), rather than a "work that uses the
|
||||||
|
library". The executable is therefore covered by this License.
|
||||||
|
Section 6 states terms for distribution of such executables.
|
||||||
|
|
||||||
|
When a "work that uses the Library" uses material from a header file
|
||||||
|
that is part of the Library, the object code for the work may be a
|
||||||
|
derivative work of the Library even though the source code is not.
|
||||||
|
Whether this is true is especially significant if the work can be
|
||||||
|
linked without the Library, or if the work is itself a library. The
|
||||||
|
threshold for this to be true is not precisely defined by law.
|
||||||
|
|
||||||
|
If such an object file uses only numerical parameters, data
|
||||||
|
structure layouts and accessors, and small macros and small inline
|
||||||
|
functions (ten lines or less in length), then the use of the object
|
||||||
|
file is unrestricted, regardless of whether it is legally a derivative
|
||||||
|
work. (Executables containing this object code plus portions of the
|
||||||
|
Library will still fall under Section 6.)
|
||||||
|
|
||||||
|
Otherwise, if the work is a derivative of the Library, you may
|
||||||
|
distribute the object code for the work under the terms of Section 6.
|
||||||
|
Any executables containing that work also fall under Section 6,
|
||||||
|
whether or not they are linked directly with the Library itself.
|
||||||
|
|
||||||
|
6. As an exception to the Sections above, you may also combine or
|
||||||
|
link a "work that uses the Library" with the Library to produce a
|
||||||
|
work containing portions of the Library, and distribute that work
|
||||||
|
under terms of your choice, provided that the terms permit
|
||||||
|
modification of the work for the customer's own use and reverse
|
||||||
|
engineering for debugging such modifications.
|
||||||
|
|
||||||
|
You must give prominent notice with each copy of the work that the
|
||||||
|
Library is used in it and that the Library and its use are covered by
|
||||||
|
this License. You must supply a copy of this License. If the work
|
||||||
|
during execution displays copyright notices, you must include the
|
||||||
|
copyright notice for the Library among them, as well as a reference
|
||||||
|
directing the user to the copy of this License. Also, you must do one
|
||||||
|
of these things:
|
||||||
|
|
||||||
|
a) Accompany the work with the complete corresponding
|
||||||
|
machine-readable source code for the Library including whatever
|
||||||
|
changes were used in the work (which must be distributed under
|
||||||
|
Sections 1 and 2 above); and, if the work is an executable linked
|
||||||
|
with the Library, with the complete machine-readable "work that
|
||||||
|
uses the Library", as object code and/or source code, so that the
|
||||||
|
user can modify the Library and then relink to produce a modified
|
||||||
|
executable containing the modified Library. (It is understood
|
||||||
|
that the user who changes the contents of definitions files in the
|
||||||
|
Library will not necessarily be able to recompile the application
|
||||||
|
to use the modified definitions.)
|
||||||
|
|
||||||
|
b) Use a suitable shared library mechanism for linking with the
|
||||||
|
Library. A suitable mechanism is one that (1) uses at run time a
|
||||||
|
copy of the library already present on the user's computer system,
|
||||||
|
rather than copying library functions into the executable, and (2)
|
||||||
|
will operate properly with a modified version of the library, if
|
||||||
|
the user installs one, as long as the modified version is
|
||||||
|
interface-compatible with the version that the work was made with.
|
||||||
|
|
||||||
|
c) Accompany the work with a written offer, valid for at
|
||||||
|
least three years, to give the same user the materials
|
||||||
|
specified in Subsection 6a, above, for a charge no more
|
||||||
|
than the cost of performing this distribution.
|
||||||
|
|
||||||
|
d) If distribution of the work is made by offering access to copy
|
||||||
|
from a designated place, offer equivalent access to copy the above
|
||||||
|
specified materials from the same place.
|
||||||
|
|
||||||
|
e) Verify that the user has already received a copy of these
|
||||||
|
materials or that you have already sent this user a copy.
|
||||||
|
|
||||||
|
For an executable, the required form of the "work that uses the
|
||||||
|
Library" must include any data and utility programs needed for
|
||||||
|
reproducing the executable from it. However, as a special exception,
|
||||||
|
the materials to be distributed need not include anything that is
|
||||||
|
normally distributed (in either source or binary form) with the major
|
||||||
|
components (compiler, kernel, and so on) of the operating system on
|
||||||
|
which the executable runs, unless that component itself accompanies
|
||||||
|
the executable.
|
||||||
|
|
||||||
|
It may happen that this requirement contradicts the license
|
||||||
|
restrictions of other proprietary libraries that do not normally
|
||||||
|
accompany the operating system. Such a contradiction means you cannot
|
||||||
|
use both them and the Library together in an executable that you
|
||||||
|
distribute.
|
||||||
|
|
||||||
|
7. You may place library facilities that are a work based on the
|
||||||
|
Library side-by-side in a single library together with other library
|
||||||
|
facilities not covered by this License, and distribute such a combined
|
||||||
|
library, provided that the separate distribution of the work based on
|
||||||
|
the Library and of the other library facilities is otherwise
|
||||||
|
permitted, and provided that you do these two things:
|
||||||
|
|
||||||
|
a) Accompany the combined library with a copy of the same work
|
||||||
|
based on the Library, uncombined with any other library
|
||||||
|
facilities. This must be distributed under the terms of the
|
||||||
|
Sections above.
|
||||||
|
|
||||||
|
b) Give prominent notice with the combined library of the fact
|
||||||
|
that part of it is a work based on the Library, and explaining
|
||||||
|
where to find the accompanying uncombined form of the same work.
|
||||||
|
|
||||||
|
8. You may not copy, modify, sublicense, link with, or distribute
|
||||||
|
the Library except as expressly provided under this License. Any
|
||||||
|
attempt otherwise to copy, modify, sublicense, link with, or
|
||||||
|
distribute the Library is void, and will automatically terminate your
|
||||||
|
rights under this License. However, parties who have received copies,
|
||||||
|
or rights, from you under this License will not have their licenses
|
||||||
|
terminated so long as such parties remain in full compliance.
|
||||||
|
|
||||||
|
9. You are not required to accept this License, since you have not
|
||||||
|
signed it. However, nothing else grants you permission to modify or
|
||||||
|
distribute the Library or its derivative works. These actions are
|
||||||
|
prohibited by law if you do not accept this License. Therefore, by
|
||||||
|
modifying or distributing the Library (or any work based on the
|
||||||
|
Library), you indicate your acceptance of this License to do so, and
|
||||||
|
all its terms and conditions for copying, distributing or modifying
|
||||||
|
the Library or works based on it.
|
||||||
|
|
||||||
|
10. Each time you redistribute the Library (or any work based on the
|
||||||
|
Library), the recipient automatically receives a license from the
|
||||||
|
original licensor to copy, distribute, link with or modify the Library
|
||||||
|
subject to these terms and conditions. You may not impose any further
|
||||||
|
restrictions on the recipients' exercise of the rights granted herein.
|
||||||
|
You are not responsible for enforcing compliance by third parties with
|
||||||
|
this License.
|
||||||
|
|
||||||
|
11. If, as a consequence of a court judgment or allegation of patent
|
||||||
|
infringement or for any other reason (not limited to patent issues),
|
||||||
|
conditions are imposed on you (whether by court order, agreement or
|
||||||
|
otherwise) that contradict the conditions of this License, they do not
|
||||||
|
excuse you from the conditions of this License. If you cannot
|
||||||
|
distribute so as to satisfy simultaneously your obligations under this
|
||||||
|
License and any other pertinent obligations, then as a consequence you
|
||||||
|
may not distribute the Library at all. For example, if a patent
|
||||||
|
license would not permit royalty-free redistribution of the Library by
|
||||||
|
all those who receive copies directly or indirectly through you, then
|
||||||
|
the only way you could satisfy both it and this License would be to
|
||||||
|
refrain entirely from distribution of the Library.
|
||||||
|
|
||||||
|
If any portion of this section is held invalid or unenforceable under any
|
||||||
|
particular circumstance, the balance of the section is intended to apply,
|
||||||
|
and the section as a whole is intended to apply in other circumstances.
|
||||||
|
|
||||||
|
It is not the purpose of this section to induce you to infringe any
|
||||||
|
patents or other property right claims or to contest validity of any
|
||||||
|
such claims; this section has the sole purpose of protecting the
|
||||||
|
integrity of the free software distribution system which is
|
||||||
|
implemented by public license practices. Many people have made
|
||||||
|
generous contributions to the wide range of software distributed
|
||||||
|
through that system in reliance on consistent application of that
|
||||||
|
system; it is up to the author/donor to decide if he or she is willing
|
||||||
|
to distribute software through any other system and a licensee cannot
|
||||||
|
impose that choice.
|
||||||
|
|
||||||
|
This section is intended to make thoroughly clear what is believed to
|
||||||
|
be a consequence of the rest of this License.
|
||||||
|
|
||||||
|
12. If the distribution and/or use of the Library is restricted in
|
||||||
|
certain countries either by patents or by copyrighted interfaces, the
|
||||||
|
original copyright holder who places the Library under this License may add
|
||||||
|
an explicit geographical distribution limitation excluding those countries,
|
||||||
|
so that distribution is permitted only in or among countries not thus
|
||||||
|
excluded. In such case, this License incorporates the limitation as if
|
||||||
|
written in the body of this License.
|
||||||
|
|
||||||
|
13. The Free Software Foundation may publish revised and/or new
|
||||||
|
versions of the Lesser General Public License from time to time.
|
||||||
|
Such new versions will be similar in spirit to the present version,
|
||||||
|
but may differ in detail to address new problems or concerns.
|
||||||
|
|
||||||
|
Each version is given a distinguishing version number. If the Library
|
||||||
|
specifies a version number of this License which applies to it and
|
||||||
|
"any later version", you have the option of following the terms and
|
||||||
|
conditions either of that version or of any later version published by
|
||||||
|
the Free Software Foundation. If the Library does not specify a
|
||||||
|
license version number, you may choose any version ever published by
|
||||||
|
the Free Software Foundation.
|
||||||
|
|
||||||
|
14. If you wish to incorporate parts of the Library into other free
|
||||||
|
programs whose distribution conditions are incompatible with these,
|
||||||
|
write to the author to ask for permission. For software which is
|
||||||
|
copyrighted by the Free Software Foundation, write to the Free
|
||||||
|
Software Foundation; we sometimes make exceptions for this. Our
|
||||||
|
decision will be guided by the two goals of preserving the free status
|
||||||
|
of all derivatives of our free software and of promoting the sharing
|
||||||
|
and reuse of software generally.
|
||||||
|
|
||||||
|
NO WARRANTY
|
||||||
|
|
||||||
|
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
|
||||||
|
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
|
||||||
|
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
|
||||||
|
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
|
||||||
|
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
|
||||||
|
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
|
||||||
|
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||||
|
|
||||||
|
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
|
||||||
|
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
|
||||||
|
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
|
||||||
|
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
|
||||||
|
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
|
||||||
|
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
|
||||||
|
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
|
||||||
|
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
|
||||||
|
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||||
|
DAMAGES.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
How to Apply These Terms to Your New Libraries
|
||||||
|
|
||||||
|
If you develop a new library, and you want it to be of the greatest
|
||||||
|
possible use to the public, we recommend making it free software that
|
||||||
|
everyone can redistribute and change. You can do so by permitting
|
||||||
|
redistribution under these terms (or, alternatively, under the terms of the
|
||||||
|
ordinary General Public License).
|
||||||
|
|
||||||
|
To apply these terms, attach the following notices to the library. It is
|
||||||
|
safest to attach them to the start of each source file to most effectively
|
||||||
|
convey the exclusion of warranty; and each file should have at least the
|
||||||
|
"copyright" line and a pointer to where the full notice is found.
|
||||||
|
|
||||||
|
<one line to give the library's name and a brief idea of what it does.>
|
||||||
|
Copyright (C) <year> <name of author>
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
Also add information on how to contact you by electronic and paper mail.
|
||||||
|
|
||||||
|
You should also get your employer (if you work as a programmer) or your
|
||||||
|
school, if any, to sign a "copyright disclaimer" for the library, if
|
||||||
|
necessary. Here is a sample; alter the names:
|
||||||
|
|
||||||
|
Yoyodyne, Inc., hereby disclaims all copyright interest in the
|
||||||
|
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
|
||||||
|
|
||||||
|
<signature of Ty Coon>, 1 April 1990
|
||||||
|
Ty Coon, President of Vice
|
||||||
|
|
||||||
|
That's all there is to it!
|
||||||
|
|
||||||
|
|
||||||
94
include/xmlrpcpp/XmlRpc.h
Normal file
94
include/xmlrpcpp/XmlRpc.h
Normal file
|
|
@ -0,0 +1,94 @@
|
||||||
|
#ifndef _XMLRPC_H_
|
||||||
|
#define _XMLRPC_H_
|
||||||
|
//
|
||||||
|
// XmlRpc++ Copyright (c) 2002-2003 by Chris Morley
|
||||||
|
// This library is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU Lesser General Public
|
||||||
|
// License as published by the Free Software Foundation; either
|
||||||
|
// version 2.1 of the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||||
|
//
|
||||||
|
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
# pragma warning(disable:4786) // identifier was truncated in debug info
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef MAKEDEPEND
|
||||||
|
# include <string>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "XmlRpcClient.h"
|
||||||
|
#include "XmlRpcException.h"
|
||||||
|
#include "XmlRpcServer.h"
|
||||||
|
#include "XmlRpcServerMethod.h"
|
||||||
|
#include "XmlRpcValue.h"
|
||||||
|
#include "XmlRpcUtil.h"
|
||||||
|
|
||||||
|
namespace XmlRpc {
|
||||||
|
|
||||||
|
|
||||||
|
//! An interface allowing custom handling of error message reporting.
|
||||||
|
class XmlRpcErrorHandler {
|
||||||
|
public:
|
||||||
|
//! Returns a pointer to the currently installed error handling object.
|
||||||
|
static XmlRpcErrorHandler* getErrorHandler()
|
||||||
|
{ return _errorHandler; }
|
||||||
|
|
||||||
|
//! Specifies the error handler.
|
||||||
|
static void setErrorHandler(XmlRpcErrorHandler* eh)
|
||||||
|
{ _errorHandler = eh; }
|
||||||
|
|
||||||
|
//! Report an error. Custom error handlers should define this method.
|
||||||
|
virtual void error(const char* msg) = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
static XmlRpcErrorHandler* _errorHandler;
|
||||||
|
};
|
||||||
|
|
||||||
|
//! An interface allowing custom handling of informational message reporting.
|
||||||
|
class XmlRpcLogHandler {
|
||||||
|
public:
|
||||||
|
//! Returns a pointer to the currently installed message reporting object.
|
||||||
|
static XmlRpcLogHandler* getLogHandler()
|
||||||
|
{ return _logHandler; }
|
||||||
|
|
||||||
|
//! Specifies the message handler.
|
||||||
|
static void setLogHandler(XmlRpcLogHandler* lh)
|
||||||
|
{ _logHandler = lh; }
|
||||||
|
|
||||||
|
//! Returns the level of verbosity of informational messages. 0 is no output, 5 is very verbose.
|
||||||
|
static int getVerbosity()
|
||||||
|
{ return _verbosity; }
|
||||||
|
|
||||||
|
//! Specify the level of verbosity of informational messages. 0 is no output, 5 is very verbose.
|
||||||
|
static void setVerbosity(int v)
|
||||||
|
{ _verbosity = v; }
|
||||||
|
|
||||||
|
//! Output a message. Custom error handlers should define this method.
|
||||||
|
virtual void log(int level, const char* msg) = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
static XmlRpcLogHandler* _logHandler;
|
||||||
|
static int _verbosity;
|
||||||
|
};
|
||||||
|
|
||||||
|
//! Returns log message verbosity. This is short for XmlRpcLogHandler::getVerbosity()
|
||||||
|
int getVerbosity();
|
||||||
|
//! Sets log message verbosity. This is short for XmlRpcLogHandler::setVerbosity(level)
|
||||||
|
void setVerbosity(int level);
|
||||||
|
|
||||||
|
|
||||||
|
//! Version identifier
|
||||||
|
extern const char XMLRPC_VERSION[];
|
||||||
|
|
||||||
|
} // namespace XmlRpc
|
||||||
|
|
||||||
|
#endif // _XMLRPC_H_
|
||||||
128
include/xmlrpcpp/XmlRpcClient.h
Normal file
128
include/xmlrpcpp/XmlRpcClient.h
Normal file
|
|
@ -0,0 +1,128 @@
|
||||||
|
|
||||||
|
#ifndef _XMLRPCCLIENT_H_
|
||||||
|
#define _XMLRPCCLIENT_H_
|
||||||
|
//
|
||||||
|
// XmlRpc++ Copyright (c) 2002-2003 by Chris Morley
|
||||||
|
//
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
# pragma warning(disable:4786) // identifier was truncated in debug info
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef MAKEDEPEND
|
||||||
|
# include <string>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "xmlrpcpp/XmlRpcDispatch.h"
|
||||||
|
#include "xmlrpcpp/XmlRpcSource.h"
|
||||||
|
|
||||||
|
namespace XmlRpc {
|
||||||
|
|
||||||
|
// Arguments and results are represented by XmlRpcValues
|
||||||
|
class XmlRpcValue;
|
||||||
|
|
||||||
|
//! A class to send XML RPC requests to a server and return the results.
|
||||||
|
class XmlRpcClient : public XmlRpcSource {
|
||||||
|
public:
|
||||||
|
// Static data
|
||||||
|
static const char REQUEST_BEGIN[];
|
||||||
|
static const char REQUEST_END_METHODNAME[];
|
||||||
|
static const char PARAMS_TAG[];
|
||||||
|
static const char PARAMS_ETAG[];
|
||||||
|
static const char PARAM_TAG[];
|
||||||
|
static const char PARAM_ETAG[];
|
||||||
|
static const char REQUEST_END[];
|
||||||
|
// Result tags
|
||||||
|
static const char METHODRESPONSE_TAG[];
|
||||||
|
static const char FAULT_TAG[];
|
||||||
|
|
||||||
|
//! Construct a client to connect to the server at the specified host:port address
|
||||||
|
//! @param host The name of the remote machine hosting the server
|
||||||
|
//! @param port The port on the remote machine where the server is listening
|
||||||
|
//! @param uri An optional string to be sent as the URI in the HTTP GET header
|
||||||
|
XmlRpcClient(const char* host, int port, const char* uri=0);
|
||||||
|
|
||||||
|
//! Destructor
|
||||||
|
virtual ~XmlRpcClient();
|
||||||
|
|
||||||
|
//! Execute the named procedure on the remote server.
|
||||||
|
//! @param method The name of the remote procedure to execute
|
||||||
|
//! @param params An array of the arguments for the method
|
||||||
|
//! @param result The result value to be returned to the client
|
||||||
|
//! @return true if the request was sent and a result received
|
||||||
|
//! (although the result might be a fault).
|
||||||
|
//!
|
||||||
|
//! Currently this is a synchronous (blocking) implementation (execute
|
||||||
|
//! does not return until it receives a response or an error). Use isFault()
|
||||||
|
//! to determine whether the result is a fault response.
|
||||||
|
bool execute(const char* method, XmlRpcValue const& params, XmlRpcValue& result);
|
||||||
|
|
||||||
|
//! Returns true if the result of the last execute() was a fault response.
|
||||||
|
bool isFault() const { return _isFault; }
|
||||||
|
|
||||||
|
|
||||||
|
// XmlRpcSource interface implementation
|
||||||
|
//! Close the connection
|
||||||
|
virtual void close();
|
||||||
|
|
||||||
|
//! Handle server responses. Called by the event dispatcher during execute.
|
||||||
|
//! @param eventType The type of event that occurred.
|
||||||
|
//! @see XmlRpcDispatch::EventType
|
||||||
|
virtual unsigned handleEvent(unsigned eventType);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// Execution processing helpers
|
||||||
|
virtual bool doConnect();
|
||||||
|
virtual bool setupConnection();
|
||||||
|
|
||||||
|
virtual bool generateRequest(const char* method, XmlRpcValue const& params);
|
||||||
|
virtual std::string generateHeader(std::string const& body);
|
||||||
|
virtual bool writeRequest();
|
||||||
|
virtual bool readHeader();
|
||||||
|
virtual bool readResponse();
|
||||||
|
virtual bool parseResponse(XmlRpcValue& result);
|
||||||
|
|
||||||
|
// Possible IO states for the connection
|
||||||
|
enum ClientConnectionState { NO_CONNECTION, CONNECTING, WRITE_REQUEST, READ_HEADER, READ_RESPONSE, IDLE };
|
||||||
|
ClientConnectionState _connectionState;
|
||||||
|
|
||||||
|
// Server location
|
||||||
|
std::string _host;
|
||||||
|
std::string _uri;
|
||||||
|
int _port;
|
||||||
|
|
||||||
|
// The xml-encoded request, http header of response, and response xml
|
||||||
|
std::string _request;
|
||||||
|
std::string _header;
|
||||||
|
std::string _response;
|
||||||
|
|
||||||
|
// Number of times the client has attempted to send the request
|
||||||
|
int _sendAttempts;
|
||||||
|
|
||||||
|
// Number of bytes of the request that have been written to the socket so far
|
||||||
|
int _bytesWritten;
|
||||||
|
|
||||||
|
// True if we are currently executing a request. If you want to multithread,
|
||||||
|
// each thread should have its own client.
|
||||||
|
bool _executing;
|
||||||
|
|
||||||
|
// True if the server closed the connection
|
||||||
|
bool _eof;
|
||||||
|
|
||||||
|
|
||||||
|
// True if a fault response was returned by the server
|
||||||
|
|
||||||
|
bool _isFault;
|
||||||
|
|
||||||
|
|
||||||
|
// Number of bytes expected in the response body (parsed from response header)
|
||||||
|
int _contentLength;
|
||||||
|
|
||||||
|
// Event dispatcher
|
||||||
|
XmlRpcDispatch _disp;
|
||||||
|
|
||||||
|
}; // class XmlRpcClient
|
||||||
|
|
||||||
|
} // namespace XmlRpc
|
||||||
|
|
||||||
|
#endif // _XMLRPCCLIENT_H_
|
||||||
88
include/xmlrpcpp/XmlRpcDispatch.h
Normal file
88
include/xmlrpcpp/XmlRpcDispatch.h
Normal file
|
|
@ -0,0 +1,88 @@
|
||||||
|
|
||||||
|
#ifndef _XMLRPCDISPATCH_H_
|
||||||
|
#define _XMLRPCDISPATCH_H_
|
||||||
|
//
|
||||||
|
// XmlRpc++ Copyright (c) 2002-2003 by Chris Morley
|
||||||
|
//
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
# pragma warning(disable:4786) // identifier was truncated in debug info
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef MAKEDEPEND
|
||||||
|
# include <list>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace XmlRpc {
|
||||||
|
|
||||||
|
// An RPC source represents a file descriptor to monitor
|
||||||
|
class XmlRpcSource;
|
||||||
|
|
||||||
|
//! An object which monitors file descriptors for events and performs
|
||||||
|
//! callbacks when interesting events happen.
|
||||||
|
class XmlRpcDispatch {
|
||||||
|
public:
|
||||||
|
//! Constructor
|
||||||
|
XmlRpcDispatch();
|
||||||
|
~XmlRpcDispatch();
|
||||||
|
|
||||||
|
//! Values indicating the type of events a source is interested in
|
||||||
|
enum EventType {
|
||||||
|
ReadableEvent = 1, //!< data available to read
|
||||||
|
WritableEvent = 2, //!< connected/data can be written without blocking
|
||||||
|
Exception = 4 //!< uh oh
|
||||||
|
};
|
||||||
|
|
||||||
|
//! Monitor this source for the event types specified by the event mask
|
||||||
|
//! and call its event handler when any of the events occur.
|
||||||
|
//! @param source The source to monitor
|
||||||
|
//! @param eventMask Which event types to watch for. \see EventType
|
||||||
|
void addSource(XmlRpcSource* source, unsigned eventMask);
|
||||||
|
|
||||||
|
//! Stop monitoring this source.
|
||||||
|
//! @param source The source to stop monitoring
|
||||||
|
void removeSource(XmlRpcSource* source);
|
||||||
|
|
||||||
|
//! Modify the types of events to watch for on this source
|
||||||
|
void setSourceEvents(XmlRpcSource* source, unsigned eventMask);
|
||||||
|
|
||||||
|
|
||||||
|
//! Watch current set of sources and process events for the specified
|
||||||
|
//! duration (in ms, -1 implies wait forever, or until exit is called)
|
||||||
|
void work(double msTime);
|
||||||
|
|
||||||
|
//! Exit from work routine
|
||||||
|
void exit();
|
||||||
|
|
||||||
|
//! Clear all sources from the monitored sources list. Sources are closed.
|
||||||
|
void clear();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
// helper
|
||||||
|
double getTime();
|
||||||
|
|
||||||
|
// A source to monitor and what to monitor it for
|
||||||
|
struct MonitoredSource {
|
||||||
|
MonitoredSource(XmlRpcSource* src, unsigned mask) : _src(src), _mask(mask) {}
|
||||||
|
XmlRpcSource* getSource() const { return _src; }
|
||||||
|
unsigned& getMask() { return _mask; }
|
||||||
|
XmlRpcSource* _src;
|
||||||
|
unsigned _mask;
|
||||||
|
};
|
||||||
|
|
||||||
|
// A list of sources to monitor
|
||||||
|
typedef std::list< MonitoredSource > SourceList;
|
||||||
|
|
||||||
|
// Sources being monitored
|
||||||
|
SourceList _sources;
|
||||||
|
|
||||||
|
// When work should stop (-1 implies wait forever, or until exit is called)
|
||||||
|
double _endTime;
|
||||||
|
|
||||||
|
bool _doClear;
|
||||||
|
bool _inWork;
|
||||||
|
|
||||||
|
};
|
||||||
|
} // namespace XmlRpc
|
||||||
|
|
||||||
|
#endif // _XMLRPCDISPATCH_H_
|
||||||
42
include/xmlrpcpp/XmlRpcException.h
Normal file
42
include/xmlrpcpp/XmlRpcException.h
Normal file
|
|
@ -0,0 +1,42 @@
|
||||||
|
|
||||||
|
#ifndef _XMLRPCEXCEPTION_H_
|
||||||
|
#define _XMLRPCEXCEPTION_H_
|
||||||
|
//
|
||||||
|
// XmlRpc++ Copyright (c) 2002-2003 by Chris Morley
|
||||||
|
//
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
# pragma warning(disable:4786) // identifier was truncated in debug info
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef MAKEDEPEND
|
||||||
|
# include <string>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
namespace XmlRpc {
|
||||||
|
|
||||||
|
//! A class representing an error.
|
||||||
|
//! If server methods throw this exception, a fault response is returned
|
||||||
|
//! to the client.
|
||||||
|
class XmlRpcException {
|
||||||
|
public:
|
||||||
|
//! Constructor
|
||||||
|
//! @param message A descriptive error message
|
||||||
|
//! @param code An integer error code
|
||||||
|
XmlRpcException(const std::string& message, int code=-1) :
|
||||||
|
_message(message), _code(code) {}
|
||||||
|
|
||||||
|
//! Return the error message.
|
||||||
|
const std::string& getMessage() const { return _message; }
|
||||||
|
|
||||||
|
//! Return the error code.
|
||||||
|
int getCode() const { return _code; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string _message;
|
||||||
|
int _code;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // _XMLRPCEXCEPTION_H_
|
||||||
104
include/xmlrpcpp/XmlRpcServer.h
Normal file
104
include/xmlrpcpp/XmlRpcServer.h
Normal file
|
|
@ -0,0 +1,104 @@
|
||||||
|
|
||||||
|
#ifndef _XMLRPCSERVER_H_
|
||||||
|
#define _XMLRPCSERVER_H_
|
||||||
|
//
|
||||||
|
// XmlRpc++ Copyright (c) 2002-2003 by Chris Morley
|
||||||
|
//
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
# pragma warning(disable:4786) // identifier was truncated in debug info
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef MAKEDEPEND
|
||||||
|
# include <map>
|
||||||
|
# include <string>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "xmlrpcpp/XmlRpcDispatch.h"
|
||||||
|
#include "xmlrpcpp/XmlRpcSource.h"
|
||||||
|
|
||||||
|
namespace XmlRpc {
|
||||||
|
|
||||||
|
|
||||||
|
// An abstract class supporting XML RPC methods
|
||||||
|
class XmlRpcServerMethod;
|
||||||
|
|
||||||
|
// Class representing connections to specific clients
|
||||||
|
class XmlRpcServerConnection;
|
||||||
|
|
||||||
|
// Class representing argument and result values
|
||||||
|
class XmlRpcValue;
|
||||||
|
|
||||||
|
|
||||||
|
//! A class to handle XML RPC requests
|
||||||
|
class XmlRpcServer : public XmlRpcSource {
|
||||||
|
public:
|
||||||
|
//! Create a server object.
|
||||||
|
XmlRpcServer();
|
||||||
|
//! Destructor.
|
||||||
|
virtual ~XmlRpcServer();
|
||||||
|
|
||||||
|
//! Specify whether introspection is enabled or not. Default is not enabled.
|
||||||
|
void enableIntrospection(bool enabled=true);
|
||||||
|
|
||||||
|
//! Add a command to the RPC server
|
||||||
|
void addMethod(XmlRpcServerMethod* method);
|
||||||
|
|
||||||
|
//! Remove a command from the RPC server
|
||||||
|
void removeMethod(XmlRpcServerMethod* method);
|
||||||
|
|
||||||
|
//! Remove a command from the RPC server by name
|
||||||
|
void removeMethod(const std::string& methodName);
|
||||||
|
|
||||||
|
//! Look up a method by name
|
||||||
|
XmlRpcServerMethod* findMethod(const std::string& name) const;
|
||||||
|
|
||||||
|
//! Create a socket, bind to the specified port, and
|
||||||
|
//! set it in listen mode to make it available for clients.
|
||||||
|
bool bindAndListen(int port, int backlog = 5);
|
||||||
|
|
||||||
|
//! Process client requests for the specified time
|
||||||
|
void work(double msTime);
|
||||||
|
|
||||||
|
//! Temporarily stop processing client requests and exit the work() method.
|
||||||
|
void exit();
|
||||||
|
|
||||||
|
//! Close all connections with clients and the socket file descriptor
|
||||||
|
void shutdown();
|
||||||
|
|
||||||
|
//! Introspection support
|
||||||
|
void listMethods(XmlRpcValue& result);
|
||||||
|
|
||||||
|
// XmlRpcSource interface implementation
|
||||||
|
|
||||||
|
//! Handle client connection requests
|
||||||
|
virtual unsigned handleEvent(unsigned eventType);
|
||||||
|
|
||||||
|
//! Remove a connection from the dispatcher
|
||||||
|
virtual void removeConnection(XmlRpcServerConnection*);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
//! Accept a client connection request
|
||||||
|
virtual void acceptConnection();
|
||||||
|
|
||||||
|
//! Create a new connection object for processing requests from a specific client.
|
||||||
|
virtual XmlRpcServerConnection* createConnection(int socket);
|
||||||
|
|
||||||
|
// Whether the introspection API is supported by this server
|
||||||
|
bool _introspectionEnabled;
|
||||||
|
|
||||||
|
// Event dispatcher
|
||||||
|
XmlRpcDispatch _disp;
|
||||||
|
|
||||||
|
// Collection of methods. This could be a set keyed on method name if we wanted...
|
||||||
|
typedef std::map< std::string, XmlRpcServerMethod* > MethodMap;
|
||||||
|
MethodMap _methods;
|
||||||
|
|
||||||
|
// system methods
|
||||||
|
XmlRpcServerMethod* _listMethods;
|
||||||
|
XmlRpcServerMethod* _methodHelp;
|
||||||
|
|
||||||
|
};
|
||||||
|
} // namespace XmlRpc
|
||||||
|
|
||||||
|
#endif //_XMLRPCSERVER_H_
|
||||||
102
include/xmlrpcpp/XmlRpcServerConnection.h
Normal file
102
include/xmlrpcpp/XmlRpcServerConnection.h
Normal file
|
|
@ -0,0 +1,102 @@
|
||||||
|
#ifndef _XMLRPCSERVERCONNECTION_H_
|
||||||
|
#define _XMLRPCSERVERCONNECTION_H_
|
||||||
|
//
|
||||||
|
// XmlRpc++ Copyright (c) 2002-2003 by Chris Morley
|
||||||
|
//
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
# pragma warning(disable:4786) // identifier was truncated in debug info
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef MAKEDEPEND
|
||||||
|
# include <string>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "xmlrpcpp/XmlRpcValue.h"
|
||||||
|
#include "xmlrpcpp/XmlRpcSource.h"
|
||||||
|
|
||||||
|
namespace XmlRpc {
|
||||||
|
|
||||||
|
|
||||||
|
// The server waits for client connections and provides methods
|
||||||
|
class XmlRpcServer;
|
||||||
|
class XmlRpcServerMethod;
|
||||||
|
|
||||||
|
//! A class to handle XML RPC requests from a particular client
|
||||||
|
class XmlRpcServerConnection : public XmlRpcSource {
|
||||||
|
public:
|
||||||
|
// Static data
|
||||||
|
static const char METHODNAME_TAG[];
|
||||||
|
static const char PARAMS_TAG[];
|
||||||
|
static const char PARAMS_ETAG[];
|
||||||
|
static const char PARAM_TAG[];
|
||||||
|
static const char PARAM_ETAG[];
|
||||||
|
|
||||||
|
static const std::string SYSTEM_MULTICALL;
|
||||||
|
static const std::string METHODNAME;
|
||||||
|
static const std::string PARAMS;
|
||||||
|
|
||||||
|
static const std::string FAULTCODE;
|
||||||
|
static const std::string FAULTSTRING;
|
||||||
|
|
||||||
|
//! Constructor
|
||||||
|
XmlRpcServerConnection(int fd, XmlRpcServer* server, bool deleteOnClose = false);
|
||||||
|
//! Destructor
|
||||||
|
virtual ~XmlRpcServerConnection();
|
||||||
|
|
||||||
|
// XmlRpcSource interface implementation
|
||||||
|
//! Handle IO on the client connection socket.
|
||||||
|
//! @param eventType Type of IO event that occurred. @see XmlRpcDispatch::EventType.
|
||||||
|
virtual unsigned handleEvent(unsigned eventType);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
bool readHeader();
|
||||||
|
bool readRequest();
|
||||||
|
bool writeResponse();
|
||||||
|
|
||||||
|
// Parses the request, runs the method, generates the response xml.
|
||||||
|
virtual void executeRequest();
|
||||||
|
|
||||||
|
// Parse the methodName and parameters from the request.
|
||||||
|
std::string parseRequest(XmlRpcValue& params);
|
||||||
|
|
||||||
|
// Execute a named method with the specified params.
|
||||||
|
bool executeMethod(const std::string& methodName, XmlRpcValue& params, XmlRpcValue& result);
|
||||||
|
|
||||||
|
// Execute multiple calls and return the results in an array.
|
||||||
|
bool executeMulticall(const std::string& methodName, XmlRpcValue& params, XmlRpcValue& result);
|
||||||
|
|
||||||
|
// Construct a response from the result XML.
|
||||||
|
void generateResponse(std::string const& resultXml);
|
||||||
|
void generateFaultResponse(std::string const& msg, int errorCode = -1);
|
||||||
|
std::string generateHeader(std::string const& body);
|
||||||
|
|
||||||
|
|
||||||
|
// The XmlRpc server that accepted this connection
|
||||||
|
XmlRpcServer* _server;
|
||||||
|
|
||||||
|
// Possible IO states for the connection
|
||||||
|
enum ServerConnectionState { READ_HEADER, READ_REQUEST, WRITE_RESPONSE };
|
||||||
|
ServerConnectionState _connectionState;
|
||||||
|
|
||||||
|
// Request headers
|
||||||
|
std::string _header;
|
||||||
|
|
||||||
|
// Number of bytes expected in the request body (parsed from header)
|
||||||
|
int _contentLength;
|
||||||
|
|
||||||
|
// Request body
|
||||||
|
std::string _request;
|
||||||
|
|
||||||
|
// Response
|
||||||
|
std::string _response;
|
||||||
|
|
||||||
|
// Number of bytes of the response written so far
|
||||||
|
int _bytesWritten;
|
||||||
|
|
||||||
|
// Whether to keep the current client connection open for further requests
|
||||||
|
bool _keepAlive;
|
||||||
|
};
|
||||||
|
} // namespace XmlRpc
|
||||||
|
|
||||||
|
#endif // _XMLRPCSERVERCONNECTION_H_
|
||||||
47
include/xmlrpcpp/XmlRpcServerMethod.h
Normal file
47
include/xmlrpcpp/XmlRpcServerMethod.h
Normal file
|
|
@ -0,0 +1,47 @@
|
||||||
|
|
||||||
|
#ifndef _XMLRPCSERVERMETHOD_H_
|
||||||
|
#define _XMLRPCSERVERMETHOD_H_
|
||||||
|
//
|
||||||
|
// XmlRpc++ Copyright (c) 2002-2003 by Chris Morley
|
||||||
|
//
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
# pragma warning(disable:4786) // identifier was truncated in debug info
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef MAKEDEPEND
|
||||||
|
# include <string>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace XmlRpc {
|
||||||
|
|
||||||
|
// Representation of a parameter or result value
|
||||||
|
class XmlRpcValue;
|
||||||
|
|
||||||
|
// The XmlRpcServer processes client requests to call RPCs
|
||||||
|
class XmlRpcServer;
|
||||||
|
|
||||||
|
//! Abstract class representing a single RPC method
|
||||||
|
class XmlRpcServerMethod {
|
||||||
|
public:
|
||||||
|
//! Constructor
|
||||||
|
XmlRpcServerMethod(std::string const& name, XmlRpcServer* server = 0);
|
||||||
|
//! Destructor
|
||||||
|
virtual ~XmlRpcServerMethod();
|
||||||
|
|
||||||
|
//! Returns the name of the method
|
||||||
|
std::string& name() { return _name; }
|
||||||
|
|
||||||
|
//! Execute the method. Subclasses must provide a definition for this method.
|
||||||
|
virtual void execute(XmlRpcValue& params, XmlRpcValue& result) = 0;
|
||||||
|
|
||||||
|
//! Returns a help string for the method.
|
||||||
|
//! Subclasses should define this method if introspection is being used.
|
||||||
|
virtual std::string help() { return std::string(); }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
std::string _name;
|
||||||
|
XmlRpcServer* _server;
|
||||||
|
};
|
||||||
|
} // namespace XmlRpc
|
||||||
|
|
||||||
|
#endif // _XMLRPCSERVERMETHOD_H_
|
||||||
69
include/xmlrpcpp/XmlRpcSocket.h
Normal file
69
include/xmlrpcpp/XmlRpcSocket.h
Normal file
|
|
@ -0,0 +1,69 @@
|
||||||
|
#ifndef _XMLRPCSOCKET_H_
|
||||||
|
#define _XMLRPCSOCKET_H_
|
||||||
|
//
|
||||||
|
// XmlRpc++ Copyright (c) 2002-2003 by Chris Morley
|
||||||
|
//
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
# pragma warning(disable:4786) // identifier was truncated in debug info
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef MAKEDEPEND
|
||||||
|
# include <string>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace XmlRpc {
|
||||||
|
|
||||||
|
//! A platform-independent socket API.
|
||||||
|
class XmlRpcSocket {
|
||||||
|
public:
|
||||||
|
|
||||||
|
//! Creates a stream (TCP) socket. Returns -1 on failure.
|
||||||
|
static int socket();
|
||||||
|
|
||||||
|
//! Closes a socket.
|
||||||
|
static void close(int socket);
|
||||||
|
|
||||||
|
|
||||||
|
//! Sets a stream (TCP) socket to perform non-blocking IO. Returns false on failure.
|
||||||
|
static bool setNonBlocking(int socket);
|
||||||
|
|
||||||
|
//! Read text from the specified socket. Returns false on error.
|
||||||
|
static bool nbRead(int socket, std::string& s, bool *eof);
|
||||||
|
|
||||||
|
//! Write text to the specified socket. Returns false on error.
|
||||||
|
static bool nbWrite(int socket, std::string& s, int *bytesSoFar);
|
||||||
|
|
||||||
|
|
||||||
|
// The next four methods are appropriate for servers.
|
||||||
|
|
||||||
|
//! Allow the port the specified socket is bound to to be re-bound immediately so
|
||||||
|
//! server re-starts are not delayed. Returns false on failure.
|
||||||
|
static bool setReuseAddr(int socket);
|
||||||
|
|
||||||
|
//! Bind to a specified port
|
||||||
|
static bool bind(int socket, int port);
|
||||||
|
|
||||||
|
//! Set socket in listen mode
|
||||||
|
static bool listen(int socket, int backlog);
|
||||||
|
|
||||||
|
//! Accept a client connection request
|
||||||
|
static int accept(int socket);
|
||||||
|
|
||||||
|
|
||||||
|
//! Connect a socket to a server (from a client)
|
||||||
|
static bool connect(int socket, std::string& host, int port);
|
||||||
|
|
||||||
|
|
||||||
|
//! Returns last errno
|
||||||
|
static int getError();
|
||||||
|
|
||||||
|
//! Returns message corresponding to last error
|
||||||
|
static std::string getErrorMsg();
|
||||||
|
|
||||||
|
//! Returns message corresponding to error
|
||||||
|
static std::string getErrorMsg(int error);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace XmlRpc
|
||||||
|
|
||||||
|
#endif
|
||||||
55
include/xmlrpcpp/XmlRpcSource.h
Normal file
55
include/xmlrpcpp/XmlRpcSource.h
Normal file
|
|
@ -0,0 +1,55 @@
|
||||||
|
|
||||||
|
#ifndef _XMLRPCSOURCE_H_
|
||||||
|
#define _XMLRPCSOURCE_H_
|
||||||
|
//
|
||||||
|
// XmlRpc++ Copyright (c) 2002-2003 by Chris Morley
|
||||||
|
//
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
# pragma warning(disable:4786) // identifier was truncated in debug info
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace XmlRpc {
|
||||||
|
|
||||||
|
//! An RPC source represents a file descriptor to monitor
|
||||||
|
class XmlRpcSource {
|
||||||
|
public:
|
||||||
|
//! Constructor
|
||||||
|
//! @param fd The socket file descriptor to monitor.
|
||||||
|
//! @param deleteOnClose If true, the object deletes itself when close is called.
|
||||||
|
XmlRpcSource(int fd = -1, bool deleteOnClose = false);
|
||||||
|
|
||||||
|
//! Destructor
|
||||||
|
virtual ~XmlRpcSource();
|
||||||
|
|
||||||
|
//! Return the file descriptor being monitored.
|
||||||
|
int getfd() const { return _fd; }
|
||||||
|
//! Specify the file descriptor to monitor.
|
||||||
|
void setfd(int fd) { _fd = fd; }
|
||||||
|
|
||||||
|
//! Return whether the file descriptor should be kept open if it is no longer monitored.
|
||||||
|
bool getKeepOpen() const { return _keepOpen; }
|
||||||
|
//! Specify whether the file descriptor should be kept open if it is no longer monitored.
|
||||||
|
void setKeepOpen(bool b=true) { _keepOpen = b; }
|
||||||
|
|
||||||
|
//! Close the owned fd. If deleteOnClose was specified at construction, the object is deleted.
|
||||||
|
virtual void close();
|
||||||
|
|
||||||
|
//! Return true to continue monitoring this source
|
||||||
|
virtual unsigned handleEvent(unsigned eventType) = 0;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
// Socket. This should really be a SOCKET (an alias for unsigned int*) on windows...
|
||||||
|
int _fd;
|
||||||
|
|
||||||
|
// In the server, a new source (XmlRpcServerConnection) is created
|
||||||
|
// for each connected client. When each connection is closed, the
|
||||||
|
// corresponding source object is deleted.
|
||||||
|
bool _deleteOnClose;
|
||||||
|
|
||||||
|
// In the client, keep connections open if you intend to make multiple calls.
|
||||||
|
bool _keepOpen;
|
||||||
|
};
|
||||||
|
} // namespace XmlRpc
|
||||||
|
|
||||||
|
#endif //_XMLRPCSOURCE_H_
|
||||||
61
include/xmlrpcpp/XmlRpcUtil.h
Normal file
61
include/xmlrpcpp/XmlRpcUtil.h
Normal file
|
|
@ -0,0 +1,61 @@
|
||||||
|
#ifndef _XMLRPCUTIL_H_
|
||||||
|
#define _XMLRPCUTIL_H_
|
||||||
|
//
|
||||||
|
// XmlRpc++ Copyright (c) 2002-2003 by Chris Morley
|
||||||
|
//
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
# pragma warning(disable:4786) // identifier was truncated in debug info
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef MAKEDEPEND
|
||||||
|
# include <string>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
# define snprintf _snprintf
|
||||||
|
# define vsnprintf _vsnprintf
|
||||||
|
# define strcasecmp _stricmp
|
||||||
|
# define strncasecmp _strnicmp
|
||||||
|
#elif defined(__BORLANDC__)
|
||||||
|
# define strcasecmp stricmp
|
||||||
|
# define strncasecmp strnicmp
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace XmlRpc {
|
||||||
|
|
||||||
|
//! Utilities for XML parsing, encoding, and decoding and message handlers.
|
||||||
|
class XmlRpcUtil {
|
||||||
|
public:
|
||||||
|
// hokey xml parsing
|
||||||
|
//! Returns contents between <tag> and </tag>, updates offset to char after </tag>
|
||||||
|
static std::string parseTag(const char* tag, std::string const& xml, int* offset);
|
||||||
|
|
||||||
|
//! Returns true if the tag is found and updates offset to the char after the tag
|
||||||
|
static bool findTag(const char* tag, std::string const& xml, int* offset);
|
||||||
|
|
||||||
|
//! Returns the next tag and updates offset to the char after the tag, or empty string
|
||||||
|
//! if the next non-whitespace character is not '<'
|
||||||
|
static std::string getNextTag(std::string const& xml, int* offset);
|
||||||
|
|
||||||
|
//! Returns true if the tag is found at the specified offset (modulo any whitespace)
|
||||||
|
//! and updates offset to the char after the tag
|
||||||
|
static bool nextTagIs(const char* tag, std::string const& xml, int* offset);
|
||||||
|
|
||||||
|
|
||||||
|
//! Convert raw text to encoded xml.
|
||||||
|
static std::string xmlEncode(const std::string& raw);
|
||||||
|
|
||||||
|
//! Convert encoded xml to raw text
|
||||||
|
static std::string xmlDecode(const std::string& encoded);
|
||||||
|
|
||||||
|
|
||||||
|
//! Dump messages somewhere
|
||||||
|
static void log(int level, const char* fmt, ...);
|
||||||
|
|
||||||
|
//! Dump error messages somewhere
|
||||||
|
static void error(const char* fmt, ...);
|
||||||
|
|
||||||
|
};
|
||||||
|
} // namespace XmlRpc
|
||||||
|
|
||||||
|
#endif // _XMLRPCUTIL_H_
|
||||||
189
include/xmlrpcpp/XmlRpcValue.h
Normal file
189
include/xmlrpcpp/XmlRpcValue.h
Normal file
|
|
@ -0,0 +1,189 @@
|
||||||
|
|
||||||
|
#ifndef _XMLRPCVALUE_H_
|
||||||
|
#define _XMLRPCVALUE_H_
|
||||||
|
//
|
||||||
|
// XmlRpc++ Copyright (c) 2002-2003 by Chris Morley
|
||||||
|
//
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
# pragma warning(disable:4786) // identifier was truncated in debug info
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef MAKEDEPEND
|
||||||
|
# include <map>
|
||||||
|
# include <string>
|
||||||
|
# include <vector>
|
||||||
|
# include <time.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace XmlRpc {
|
||||||
|
|
||||||
|
//! RPC method arguments and results are represented by Values
|
||||||
|
// should probably refcount them...
|
||||||
|
class XmlRpcValue {
|
||||||
|
public:
|
||||||
|
|
||||||
|
|
||||||
|
enum Type {
|
||||||
|
TypeInvalid,
|
||||||
|
TypeBoolean,
|
||||||
|
TypeInt,
|
||||||
|
TypeDouble,
|
||||||
|
TypeString,
|
||||||
|
TypeDateTime,
|
||||||
|
TypeBase64,
|
||||||
|
TypeArray,
|
||||||
|
TypeStruct
|
||||||
|
};
|
||||||
|
|
||||||
|
// Non-primitive types
|
||||||
|
typedef std::vector<char> BinaryData;
|
||||||
|
typedef std::vector<XmlRpcValue> ValueArray;
|
||||||
|
typedef std::map<std::string, XmlRpcValue> ValueStruct;
|
||||||
|
|
||||||
|
|
||||||
|
//! Constructors
|
||||||
|
XmlRpcValue() : _type(TypeInvalid) { _value.asBinary = 0; }
|
||||||
|
XmlRpcValue(bool value) : _type(TypeBoolean) { _value.asBool = value; }
|
||||||
|
XmlRpcValue(int value) : _type(TypeInt) { _value.asInt = value; }
|
||||||
|
XmlRpcValue(double value) : _type(TypeDouble) { _value.asDouble = value; }
|
||||||
|
|
||||||
|
XmlRpcValue(std::string const& value) : _type(TypeString)
|
||||||
|
{ _value.asString = new std::string(value); }
|
||||||
|
|
||||||
|
XmlRpcValue(const char* value) : _type(TypeString)
|
||||||
|
{ _value.asString = new std::string(value); }
|
||||||
|
|
||||||
|
XmlRpcValue(struct tm* value) : _type(TypeDateTime)
|
||||||
|
{ _value.asTime = new struct tm(*value); }
|
||||||
|
|
||||||
|
|
||||||
|
XmlRpcValue(void* value, int nBytes) : _type(TypeBase64)
|
||||||
|
{
|
||||||
|
_value.asBinary = new BinaryData((char*)value, ((char*)value)+nBytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Construct from xml, beginning at *offset chars into the string, updates offset
|
||||||
|
XmlRpcValue(std::string const& xml, int* offset) : _type(TypeInvalid)
|
||||||
|
{ if ( ! fromXml(xml,offset)) _type = TypeInvalid; }
|
||||||
|
|
||||||
|
//! Copy
|
||||||
|
XmlRpcValue(XmlRpcValue const& rhs) : _type(TypeInvalid) { *this = rhs; }
|
||||||
|
|
||||||
|
//! Destructor (make virtual if you want to subclass)
|
||||||
|
/*virtual*/ ~XmlRpcValue() { invalidate(); }
|
||||||
|
|
||||||
|
//! Erase the current value
|
||||||
|
void clear() { invalidate(); }
|
||||||
|
|
||||||
|
// Operators
|
||||||
|
XmlRpcValue& operator=(XmlRpcValue const& rhs);
|
||||||
|
XmlRpcValue& operator=(int const& rhs) { return operator=(XmlRpcValue(rhs)); }
|
||||||
|
XmlRpcValue& operator=(double const& rhs) { return operator=(XmlRpcValue(rhs)); }
|
||||||
|
XmlRpcValue& operator=(const char* rhs) { return operator=(XmlRpcValue(std::string(rhs))); }
|
||||||
|
|
||||||
|
bool operator==(XmlRpcValue const& other) const;
|
||||||
|
bool operator!=(XmlRpcValue const& other) const;
|
||||||
|
|
||||||
|
operator bool&() { assertTypeOrInvalid(TypeBoolean); return _value.asBool; }
|
||||||
|
operator int&() { assertTypeOrInvalid(TypeInt); return _value.asInt; }
|
||||||
|
operator double&() { assertTypeOrInvalid(TypeDouble); return _value.asDouble; }
|
||||||
|
operator std::string&() { assertTypeOrInvalid(TypeString); return *_value.asString; }
|
||||||
|
operator BinaryData&() { assertTypeOrInvalid(TypeBase64); return *_value.asBinary; }
|
||||||
|
operator struct tm&() { assertTypeOrInvalid(TypeDateTime); return *_value.asTime; }
|
||||||
|
|
||||||
|
XmlRpcValue const& operator[](int i) const { assertArray(i+1); return _value.asArray->at(i); }
|
||||||
|
XmlRpcValue& operator[](int i) { assertArray(i+1); return _value.asArray->at(i); }
|
||||||
|
|
||||||
|
XmlRpcValue& operator[](std::string const& k) { assertStruct(); return (*_value.asStruct)[k]; }
|
||||||
|
XmlRpcValue& operator[](const char* k) { assertStruct(); std::string s(k); return (*_value.asStruct)[s]; }
|
||||||
|
|
||||||
|
// Accessors
|
||||||
|
//! Return true if the value has been set to something.
|
||||||
|
bool valid() const { return _type != TypeInvalid; }
|
||||||
|
|
||||||
|
//! Return the type of the value stored. \see Type.
|
||||||
|
Type const &getType() const { return _type; }
|
||||||
|
|
||||||
|
//! Return the size for string, base64, array, and struct values.
|
||||||
|
int size() const;
|
||||||
|
|
||||||
|
//! Specify the size for array values. Array values will grow beyond this size if needed.
|
||||||
|
void setSize(int size) { assertArray(size); }
|
||||||
|
|
||||||
|
//! Check for the existence of a struct member by name.
|
||||||
|
bool hasMember(const std::string& name) const;
|
||||||
|
|
||||||
|
//! Decode xml. Destroys any existing value.
|
||||||
|
bool fromXml(std::string const& valueXml, int* offset);
|
||||||
|
|
||||||
|
//! Encode the Value in xml
|
||||||
|
std::string toXml() const;
|
||||||
|
|
||||||
|
//! Write the value (no xml encoding)
|
||||||
|
std::ostream& write(std::ostream& os) const;
|
||||||
|
|
||||||
|
// Formatting
|
||||||
|
//! Return the format used to write double values.
|
||||||
|
static std::string const& getDoubleFormat() { return _doubleFormat; }
|
||||||
|
|
||||||
|
//! Specify the format used to write double values.
|
||||||
|
static void setDoubleFormat(const char* f) { _doubleFormat = f; }
|
||||||
|
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// Clean up
|
||||||
|
void invalidate();
|
||||||
|
|
||||||
|
// Type checking
|
||||||
|
void assertTypeOrInvalid(Type t);
|
||||||
|
void assertArray(int size) const;
|
||||||
|
void assertArray(int size);
|
||||||
|
void assertStruct();
|
||||||
|
|
||||||
|
// XML decoding
|
||||||
|
bool boolFromXml(std::string const& valueXml, int* offset);
|
||||||
|
bool intFromXml(std::string const& valueXml, int* offset);
|
||||||
|
bool doubleFromXml(std::string const& valueXml, int* offset);
|
||||||
|
bool stringFromXml(std::string const& valueXml, int* offset);
|
||||||
|
bool timeFromXml(std::string const& valueXml, int* offset);
|
||||||
|
bool binaryFromXml(std::string const& valueXml, int* offset);
|
||||||
|
bool arrayFromXml(std::string const& valueXml, int* offset);
|
||||||
|
bool structFromXml(std::string const& valueXml, int* offset);
|
||||||
|
|
||||||
|
// XML encoding
|
||||||
|
std::string boolToXml() const;
|
||||||
|
std::string intToXml() const;
|
||||||
|
std::string doubleToXml() const;
|
||||||
|
std::string stringToXml() const;
|
||||||
|
std::string timeToXml() const;
|
||||||
|
std::string binaryToXml() const;
|
||||||
|
std::string arrayToXml() const;
|
||||||
|
std::string structToXml() const;
|
||||||
|
|
||||||
|
// Format strings
|
||||||
|
static std::string _doubleFormat;
|
||||||
|
|
||||||
|
// Type tag and values
|
||||||
|
Type _type;
|
||||||
|
|
||||||
|
// At some point I will split off Arrays and Structs into
|
||||||
|
// separate ref-counted objects for more efficient copying.
|
||||||
|
union {
|
||||||
|
bool asBool;
|
||||||
|
int asInt;
|
||||||
|
double asDouble;
|
||||||
|
struct tm* asTime;
|
||||||
|
std::string* asString;
|
||||||
|
BinaryData* asBinary;
|
||||||
|
ValueArray* asArray;
|
||||||
|
ValueStruct* asStruct;
|
||||||
|
} _value;
|
||||||
|
|
||||||
|
};
|
||||||
|
} // namespace XmlRpc
|
||||||
|
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream& os, XmlRpc::XmlRpcValue& v);
|
||||||
|
|
||||||
|
|
||||||
|
#endif // _XMLRPCVALUE_H_
|
||||||
379
include/xmlrpcpp/base64.h
Normal file
379
include/xmlrpcpp/base64.h
Normal file
|
|
@ -0,0 +1,379 @@
|
||||||
|
|
||||||
|
|
||||||
|
// base64.hpp
|
||||||
|
// Autor Konstantin Pilipchuk
|
||||||
|
// mailto:lostd@ukr.net
|
||||||
|
//
|
||||||
|
//
|
||||||
|
|
||||||
|
#if !defined(__BASE64_H_INCLUDED__)
|
||||||
|
#define __BASE64_H_INCLUDED__ 1
|
||||||
|
|
||||||
|
#ifndef MAKEDEPEND
|
||||||
|
# include <iterator>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static
|
||||||
|
int _base64Chars[]= {'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
|
||||||
|
'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z',
|
||||||
|
'0','1','2','3','4','5','6','7','8','9',
|
||||||
|
'+','/' };
|
||||||
|
|
||||||
|
|
||||||
|
#define _0000_0011 0x03
|
||||||
|
#define _1111_1100 0xFC
|
||||||
|
#define _1111_0000 0xF0
|
||||||
|
#define _0011_0000 0x30
|
||||||
|
#define _0011_1100 0x3C
|
||||||
|
#define _0000_1111 0x0F
|
||||||
|
#define _1100_0000 0xC0
|
||||||
|
#define _0011_1111 0x3F
|
||||||
|
|
||||||
|
#define _EQUAL_CHAR (-1)
|
||||||
|
#define _UNKNOWN_CHAR (-2)
|
||||||
|
|
||||||
|
#define _IOS_FAILBIT std::ios_base::failbit
|
||||||
|
#define _IOS_EOFBIT std::ios_base::eofbit
|
||||||
|
#define _IOS_BADBIT std::ios_base::badbit
|
||||||
|
#define _IOS_GOODBIT std::ios_base::goodbit
|
||||||
|
|
||||||
|
// TEMPLATE CLASS base64_put
|
||||||
|
template<class _E = char, class _Tr = std::char_traits<_E> >
|
||||||
|
class base64
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
typedef unsigned char byte_t;
|
||||||
|
typedef _E char_type;
|
||||||
|
typedef _Tr traits_type;
|
||||||
|
|
||||||
|
// base64 requires max line length <= 72 characters
|
||||||
|
// you can fill end of line
|
||||||
|
// it may be crlf, crlfsp, noline or other class like it
|
||||||
|
|
||||||
|
|
||||||
|
struct crlf
|
||||||
|
{
|
||||||
|
template<class _OI>
|
||||||
|
_OI operator()(_OI _To) const{
|
||||||
|
*_To = _Tr::to_char_type('\r'); ++_To;
|
||||||
|
*_To = _Tr::to_char_type('\n'); ++_To;
|
||||||
|
|
||||||
|
return (_To);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct crlfsp
|
||||||
|
{
|
||||||
|
template<class _OI>
|
||||||
|
_OI operator()(_OI _To) const{
|
||||||
|
*_To = _Tr::to_char_type('\r'); ++_To;
|
||||||
|
*_To = _Tr::to_char_type('\n'); ++_To;
|
||||||
|
*_To = _Tr::to_char_type(' '); ++_To;
|
||||||
|
|
||||||
|
return (_To);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct noline
|
||||||
|
{
|
||||||
|
template<class _OI>
|
||||||
|
_OI operator()(_OI _To) const{
|
||||||
|
return (_To);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct three2four
|
||||||
|
{
|
||||||
|
void zero()
|
||||||
|
{
|
||||||
|
_data[0] = 0;
|
||||||
|
_data[1] = 0;
|
||||||
|
_data[2] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
byte_t get_0() const
|
||||||
|
{
|
||||||
|
return _data[0];
|
||||||
|
}
|
||||||
|
byte_t get_1() const
|
||||||
|
{
|
||||||
|
return _data[1];
|
||||||
|
}
|
||||||
|
byte_t get_2() const
|
||||||
|
{
|
||||||
|
return _data[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_0(byte_t _ch)
|
||||||
|
{
|
||||||
|
_data[0] = _ch;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_1(byte_t _ch)
|
||||||
|
{
|
||||||
|
_data[1] = _ch;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_2(byte_t _ch)
|
||||||
|
{
|
||||||
|
_data[2] = _ch;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 0000 0000 1111 1111 2222 2222
|
||||||
|
// xxxx xxxx xxxx xxxx xxxx xxxx
|
||||||
|
// 0000 0011 1111 2222 2233 3333
|
||||||
|
|
||||||
|
int b64_0() const {return (_data[0] & _1111_1100) >> 2;}
|
||||||
|
int b64_1() const {return ((_data[0] & _0000_0011) << 4) + ((_data[1] & _1111_0000)>>4);}
|
||||||
|
int b64_2() const {return ((_data[1] & _0000_1111) << 2) + ((_data[2] & _1100_0000)>>6);}
|
||||||
|
int b64_3() const {return (_data[2] & _0011_1111);}
|
||||||
|
|
||||||
|
void b64_0(int _ch) {_data[0] = ((_ch & _0011_1111) << 2) | (_0000_0011 & _data[0]);}
|
||||||
|
|
||||||
|
void b64_1(int _ch) {
|
||||||
|
_data[0] = ((_ch & _0011_0000) >> 4) | (_1111_1100 & _data[0]);
|
||||||
|
_data[1] = ((_ch & _0000_1111) << 4) | (_0000_1111 & _data[1]); }
|
||||||
|
|
||||||
|
void b64_2(int _ch) {
|
||||||
|
_data[1] = ((_ch & _0011_1100) >> 2) | (_1111_0000 & _data[1]);
|
||||||
|
_data[2] = ((_ch & _0000_0011) << 6) | (_0011_1111 & _data[2]); }
|
||||||
|
|
||||||
|
void b64_3(int _ch){
|
||||||
|
_data[2] = (_ch & _0011_1111) | (_1100_0000 & _data[2]);}
|
||||||
|
|
||||||
|
private:
|
||||||
|
byte_t _data[3];
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
template<class _II, class _OI, class _State, class _Endline>
|
||||||
|
_II put(_II _First, _II _Last, _OI _To, _State& _St, _Endline _Endl) const
|
||||||
|
{
|
||||||
|
three2four _3to4;
|
||||||
|
int line_octets = 0;
|
||||||
|
|
||||||
|
while(_First != _Last)
|
||||||
|
{
|
||||||
|
_3to4.zero();
|
||||||
|
|
||||||
|
// áåð¸ì ïî 3 ñèìâîëà
|
||||||
|
_3to4.set_0(*_First);
|
||||||
|
_First++;
|
||||||
|
|
||||||
|
if(_First == _Last)
|
||||||
|
{
|
||||||
|
*_To = _Tr::to_char_type(_base64Chars[_3to4.b64_0()]); ++_To;
|
||||||
|
*_To = _Tr::to_char_type(_base64Chars[_3to4.b64_1()]); ++_To;
|
||||||
|
*_To = _Tr::to_char_type('='); ++_To;
|
||||||
|
*_To = _Tr::to_char_type('='); ++_To;
|
||||||
|
goto __end;
|
||||||
|
}
|
||||||
|
|
||||||
|
_3to4.set_1(*_First);
|
||||||
|
_First++;
|
||||||
|
|
||||||
|
if(_First == _Last)
|
||||||
|
{
|
||||||
|
*_To = _Tr::to_char_type(_base64Chars[_3to4.b64_0()]); ++_To;
|
||||||
|
*_To = _Tr::to_char_type(_base64Chars[_3to4.b64_1()]); ++_To;
|
||||||
|
*_To = _Tr::to_char_type(_base64Chars[_3to4.b64_2()]); ++_To;
|
||||||
|
*_To = _Tr::to_char_type('='); ++_To;
|
||||||
|
goto __end;
|
||||||
|
}
|
||||||
|
|
||||||
|
_3to4.set_2(*_First);
|
||||||
|
_First++;
|
||||||
|
|
||||||
|
*_To = _Tr::to_char_type(_base64Chars[_3to4.b64_0()]); ++_To;
|
||||||
|
*_To = _Tr::to_char_type(_base64Chars[_3to4.b64_1()]); ++_To;
|
||||||
|
*_To = _Tr::to_char_type(_base64Chars[_3to4.b64_2()]); ++_To;
|
||||||
|
*_To = _Tr::to_char_type(_base64Chars[_3to4.b64_3()]); ++_To;
|
||||||
|
|
||||||
|
if(line_octets == 17) // base64 ïîçâîëÿåò äëèíó ñòðîêè íå áîëåå 72 ñèìâîëîâ
|
||||||
|
{
|
||||||
|
//_To = _Endl(_To);
|
||||||
|
*_To = '\n'; ++_To;
|
||||||
|
line_octets = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
++line_octets;
|
||||||
|
}
|
||||||
|
|
||||||
|
__end: ;
|
||||||
|
|
||||||
|
return (_First);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<class _II, class _OI, class _State>
|
||||||
|
_II get(_II _First, _II _Last, _OI _To, _State& _St) const
|
||||||
|
{
|
||||||
|
three2four _3to4;
|
||||||
|
int _Char;
|
||||||
|
|
||||||
|
while(_First != _Last)
|
||||||
|
{
|
||||||
|
|
||||||
|
// Take octet
|
||||||
|
_3to4.zero();
|
||||||
|
|
||||||
|
// -- 0 --
|
||||||
|
// Search next valid char...
|
||||||
|
while((_Char = _getCharType(*_First)) < 0 && _Char == _UNKNOWN_CHAR)
|
||||||
|
{
|
||||||
|
if(++_First == _Last)
|
||||||
|
{
|
||||||
|
_St |= _IOS_FAILBIT|_IOS_EOFBIT; return _First; // unexpected EOF
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(_Char == _EQUAL_CHAR){
|
||||||
|
// Error! First character in octet can't be '='
|
||||||
|
_St |= _IOS_FAILBIT;
|
||||||
|
return _First;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
_3to4.b64_0(_Char);
|
||||||
|
|
||||||
|
|
||||||
|
// -- 1 --
|
||||||
|
// Search next valid char...
|
||||||
|
while(++_First != _Last)
|
||||||
|
if((_Char = _getCharType(*_First)) != _UNKNOWN_CHAR)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if(_First == _Last) {
|
||||||
|
_St |= _IOS_FAILBIT|_IOS_EOFBIT; // unexpected EOF
|
||||||
|
return _First;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(_Char == _EQUAL_CHAR){
|
||||||
|
// Error! Second character in octet can't be '='
|
||||||
|
_St |= _IOS_FAILBIT;
|
||||||
|
return _First;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
_3to4.b64_1(_Char);
|
||||||
|
|
||||||
|
|
||||||
|
// -- 2 --
|
||||||
|
// Search next valid char...
|
||||||
|
while(++_First != _Last)
|
||||||
|
if((_Char = _getCharType(*_First)) != _UNKNOWN_CHAR)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if(_First == _Last) {
|
||||||
|
// Error! Unexpected EOF. Must be '=' or base64 character
|
||||||
|
_St |= _IOS_FAILBIT|_IOS_EOFBIT;
|
||||||
|
return _First;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(_Char == _EQUAL_CHAR){
|
||||||
|
// OK!
|
||||||
|
_3to4.b64_2(0);
|
||||||
|
_3to4.b64_3(0);
|
||||||
|
|
||||||
|
// chek for EOF
|
||||||
|
if(++_First == _Last)
|
||||||
|
{
|
||||||
|
// Error! Unexpected EOF. Must be '='. Ignore it.
|
||||||
|
//_St |= _IOS_BADBIT|_IOS_EOFBIT;
|
||||||
|
_St |= _IOS_EOFBIT;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if(_getCharType(*_First) != _EQUAL_CHAR)
|
||||||
|
{
|
||||||
|
// Error! Must be '='. Ignore it.
|
||||||
|
//_St |= _IOS_BADBIT;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
++_First; // Skip '='
|
||||||
|
|
||||||
|
// write 1 byte to output
|
||||||
|
*_To = (byte_t) _3to4.get_0();
|
||||||
|
return _First;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
_3to4.b64_2(_Char);
|
||||||
|
|
||||||
|
|
||||||
|
// -- 3 --
|
||||||
|
// Search next valid char...
|
||||||
|
while(++_First != _Last)
|
||||||
|
if((_Char = _getCharType(*_First)) != _UNKNOWN_CHAR)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if(_First == _Last) {
|
||||||
|
// Unexpected EOF. It's error. But ignore it.
|
||||||
|
//_St |= _IOS_FAILBIT|_IOS_EOFBIT;
|
||||||
|
_St |= _IOS_EOFBIT;
|
||||||
|
|
||||||
|
return _First;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(_Char == _EQUAL_CHAR)
|
||||||
|
{
|
||||||
|
// OK!
|
||||||
|
_3to4.b64_3(0);
|
||||||
|
|
||||||
|
// write to output 2 bytes
|
||||||
|
*_To = (byte_t) _3to4.get_0();
|
||||||
|
*_To = (byte_t) _3to4.get_1();
|
||||||
|
|
||||||
|
++_First; // set position to next character
|
||||||
|
|
||||||
|
return _First;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
_3to4.b64_3(_Char);
|
||||||
|
|
||||||
|
|
||||||
|
// write to output 3 bytes
|
||||||
|
*_To = (byte_t) _3to4.get_0();
|
||||||
|
*_To = (byte_t) _3to4.get_1();
|
||||||
|
*_To = (byte_t) _3to4.get_2();
|
||||||
|
|
||||||
|
++_First;
|
||||||
|
|
||||||
|
|
||||||
|
} // while(_First != _Last)
|
||||||
|
|
||||||
|
return (_First);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
int _getCharType(int _Ch) const
|
||||||
|
{
|
||||||
|
if(_base64Chars[62] == _Ch)
|
||||||
|
return 62;
|
||||||
|
|
||||||
|
if(_base64Chars[63] == _Ch)
|
||||||
|
return 63;
|
||||||
|
|
||||||
|
if((_base64Chars[0] <= _Ch) && (_base64Chars[25] >= _Ch))
|
||||||
|
return _Ch - _base64Chars[0];
|
||||||
|
|
||||||
|
if((_base64Chars[26] <= _Ch) && (_base64Chars[51] >= _Ch))
|
||||||
|
return _Ch - _base64Chars[26] + 26;
|
||||||
|
|
||||||
|
if((_base64Chars[52] <= _Ch) && (_base64Chars[61] >= _Ch))
|
||||||
|
return _Ch - _base64Chars[52] + 52;
|
||||||
|
|
||||||
|
if(_Ch == _Tr::to_int_type('='))
|
||||||
|
return _EQUAL_CHAR;
|
||||||
|
|
||||||
|
return _UNKNOWN_CHAR;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
1041
src/Doxyfile
Normal file
1041
src/Doxyfile
Normal file
File diff suppressed because it is too large
Load Diff
416
src/XmlRpcClient.cpp
Normal file
416
src/XmlRpcClient.cpp
Normal file
|
|
@ -0,0 +1,416 @@
|
||||||
|
|
||||||
|
#include "xmlrpcpp/XmlRpcClient.h"
|
||||||
|
|
||||||
|
#include "xmlrpcpp/XmlRpcSocket.h"
|
||||||
|
#include "xmlrpcpp/XmlRpc.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <cstring> // cho strncmp
|
||||||
|
#include <strings.h> // cho strncasecmp
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
using namespace XmlRpc;
|
||||||
|
|
||||||
|
// Static data
|
||||||
|
const char XmlRpcClient::REQUEST_BEGIN[] =
|
||||||
|
"<?xml version=\"1.0\"?>\r\n"
|
||||||
|
"<methodCall><methodName>";
|
||||||
|
const char XmlRpcClient::REQUEST_END_METHODNAME[] = "</methodName>\r\n";
|
||||||
|
const char XmlRpcClient::PARAMS_TAG[] = "<params>";
|
||||||
|
const char XmlRpcClient::PARAMS_ETAG[] = "</params>";
|
||||||
|
const char XmlRpcClient::PARAM_TAG[] = "<param>";
|
||||||
|
const char XmlRpcClient::PARAM_ETAG[] = "</param>";
|
||||||
|
const char XmlRpcClient::REQUEST_END[] = "</methodCall>\r\n";
|
||||||
|
const char XmlRpcClient::METHODRESPONSE_TAG[] = "<methodResponse>";
|
||||||
|
const char XmlRpcClient::FAULT_TAG[] = "<fault>";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
XmlRpcClient::XmlRpcClient(const char* host, int port, const char* uri/*=0*/)
|
||||||
|
{
|
||||||
|
XmlRpcUtil::log(1, "XmlRpcClient new client: host %s, port %d.", host, port);
|
||||||
|
|
||||||
|
_host = host;
|
||||||
|
_port = port;
|
||||||
|
if (uri)
|
||||||
|
_uri = uri;
|
||||||
|
else
|
||||||
|
_uri = "/RPC2";
|
||||||
|
_connectionState = NO_CONNECTION;
|
||||||
|
_executing = false;
|
||||||
|
_eof = false;
|
||||||
|
|
||||||
|
// Default to keeping the connection open until an explicit close is done
|
||||||
|
setKeepOpen();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
XmlRpcClient::~XmlRpcClient()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close the owned fd
|
||||||
|
void
|
||||||
|
XmlRpcClient::close()
|
||||||
|
{
|
||||||
|
XmlRpcUtil::log(4, "XmlRpcClient::close: fd %d.", getfd());
|
||||||
|
_connectionState = NO_CONNECTION;
|
||||||
|
_disp.exit();
|
||||||
|
_disp.removeSource(this);
|
||||||
|
XmlRpcSource::close();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Clear the referenced flag even if exceptions or errors occur.
|
||||||
|
struct ClearFlagOnExit {
|
||||||
|
ClearFlagOnExit(bool& flag) : _flag(flag) {}
|
||||||
|
~ClearFlagOnExit() { _flag = false; }
|
||||||
|
bool& _flag;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Execute the named procedure on the remote server.
|
||||||
|
// Params should be an array of the arguments for the method.
|
||||||
|
// Returns true if the request was sent and a result received (although the result
|
||||||
|
// might be a fault).
|
||||||
|
bool
|
||||||
|
XmlRpcClient::execute(const char* method, XmlRpcValue const& params, XmlRpcValue& result)
|
||||||
|
{
|
||||||
|
XmlRpcUtil::log(1, "XmlRpcClient::execute: method %s (_connectionState %d).", method, _connectionState);
|
||||||
|
|
||||||
|
// This is not a thread-safe operation, if you want to do multithreading, use separate
|
||||||
|
// clients for each thread. If you want to protect yourself from multiple threads
|
||||||
|
// accessing the same client, replace this code with a real mutex.
|
||||||
|
if (_executing)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
_executing = true;
|
||||||
|
ClearFlagOnExit cf(_executing);
|
||||||
|
|
||||||
|
_sendAttempts = 0;
|
||||||
|
_isFault = false;
|
||||||
|
|
||||||
|
if ( ! setupConnection())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if ( ! generateRequest(method, params))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
result.clear();
|
||||||
|
double msTime = -1.0; // Process until exit is called
|
||||||
|
_disp.work(msTime);
|
||||||
|
|
||||||
|
if (_connectionState != IDLE || ! parseResponse(result))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
XmlRpcUtil::log(1, "XmlRpcClient::execute: method %s completed.", method);
|
||||||
|
_response = "";
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// XmlRpcSource interface implementation
|
||||||
|
// Handle server responses. Called by the event dispatcher during execute.
|
||||||
|
unsigned
|
||||||
|
XmlRpcClient::handleEvent(unsigned eventType)
|
||||||
|
{
|
||||||
|
if (eventType == XmlRpcDispatch::Exception)
|
||||||
|
{
|
||||||
|
if (_connectionState == WRITE_REQUEST && _bytesWritten == 0)
|
||||||
|
XmlRpcUtil::error("Error in XmlRpcClient::handleEvent: could not connect to server (%s).",
|
||||||
|
XmlRpcSocket::getErrorMsg().c_str());
|
||||||
|
else
|
||||||
|
XmlRpcUtil::error("Error in XmlRpcClient::handleEvent (state %d): %s.",
|
||||||
|
_connectionState, XmlRpcSocket::getErrorMsg().c_str());
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_connectionState == WRITE_REQUEST)
|
||||||
|
if ( ! writeRequest()) return 0;
|
||||||
|
|
||||||
|
if (_connectionState == READ_HEADER)
|
||||||
|
if ( ! readHeader()) return 0;
|
||||||
|
|
||||||
|
if (_connectionState == READ_RESPONSE)
|
||||||
|
if ( ! readResponse()) return 0;
|
||||||
|
|
||||||
|
// This should probably always ask for Exception events too
|
||||||
|
return (_connectionState == WRITE_REQUEST)
|
||||||
|
? XmlRpcDispatch::WritableEvent : XmlRpcDispatch::ReadableEvent;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Create the socket connection to the server if necessary
|
||||||
|
bool
|
||||||
|
XmlRpcClient::setupConnection()
|
||||||
|
{
|
||||||
|
// If an error occurred last time through, or if the server closed the connection, close our end
|
||||||
|
if ((_connectionState != NO_CONNECTION && _connectionState != IDLE) || _eof)
|
||||||
|
close();
|
||||||
|
|
||||||
|
_eof = false;
|
||||||
|
if (_connectionState == NO_CONNECTION)
|
||||||
|
if (! doConnect())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Prepare to write the request
|
||||||
|
_connectionState = WRITE_REQUEST;
|
||||||
|
_bytesWritten = 0;
|
||||||
|
|
||||||
|
// Notify the dispatcher to listen on this source (calls handleEvent when the socket is writable)
|
||||||
|
_disp.removeSource(this); // Make sure nothing is left over
|
||||||
|
_disp.addSource(this, XmlRpcDispatch::WritableEvent | XmlRpcDispatch::Exception);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Connect to the xmlrpc server
|
||||||
|
bool
|
||||||
|
XmlRpcClient::doConnect()
|
||||||
|
{
|
||||||
|
int fd = XmlRpcSocket::socket();
|
||||||
|
if (fd < 0)
|
||||||
|
{
|
||||||
|
XmlRpcUtil::error("Error in XmlRpcClient::doConnect: Could not create socket (%s).", XmlRpcSocket::getErrorMsg().c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
XmlRpcUtil::log(3, "XmlRpcClient::doConnect: fd %d.", fd);
|
||||||
|
this->setfd(fd);
|
||||||
|
|
||||||
|
// Don't block on connect/reads/writes
|
||||||
|
if ( ! XmlRpcSocket::setNonBlocking(fd))
|
||||||
|
{
|
||||||
|
this->close();
|
||||||
|
XmlRpcUtil::error("Error in XmlRpcClient::doConnect: Could not set socket to non-blocking IO mode (%s).", XmlRpcSocket::getErrorMsg().c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ! XmlRpcSocket::connect(fd, _host, _port))
|
||||||
|
{
|
||||||
|
this->close();
|
||||||
|
XmlRpcUtil::error("Error in XmlRpcClient::doConnect: Could not connect to server (%s).", XmlRpcSocket::getErrorMsg().c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Encode the request to call the specified method with the specified parameters into xml
|
||||||
|
bool
|
||||||
|
XmlRpcClient::generateRequest(const char* methodName, XmlRpcValue const& params)
|
||||||
|
{
|
||||||
|
std::string body = REQUEST_BEGIN;
|
||||||
|
body += methodName;
|
||||||
|
body += REQUEST_END_METHODNAME;
|
||||||
|
|
||||||
|
// If params is an array, each element is a separate parameter
|
||||||
|
if (params.valid()) {
|
||||||
|
body += PARAMS_TAG;
|
||||||
|
if (params.getType() == XmlRpcValue::TypeArray)
|
||||||
|
{
|
||||||
|
for (int i=0; i<params.size(); ++i) {
|
||||||
|
body += PARAM_TAG;
|
||||||
|
body += params[i].toXml();
|
||||||
|
body += PARAM_ETAG;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
body += PARAM_TAG;
|
||||||
|
body += params.toXml();
|
||||||
|
body += PARAM_ETAG;
|
||||||
|
}
|
||||||
|
|
||||||
|
body += PARAMS_ETAG;
|
||||||
|
}
|
||||||
|
body += REQUEST_END;
|
||||||
|
|
||||||
|
std::string header = generateHeader(body);
|
||||||
|
XmlRpcUtil::log(4, "XmlRpcClient::generateRequest: header is %d bytes, content-length is %d.",
|
||||||
|
header.length(), body.length());
|
||||||
|
|
||||||
|
_request = header + body;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prepend http headers
|
||||||
|
std::string
|
||||||
|
XmlRpcClient::generateHeader(std::string const& body)
|
||||||
|
{
|
||||||
|
std::string header =
|
||||||
|
"POST " + _uri + " HTTP/1.1\r\n"
|
||||||
|
"User-Agent: ";
|
||||||
|
header += XMLRPC_VERSION;
|
||||||
|
header += "\r\nHost: ";
|
||||||
|
header += _host;
|
||||||
|
|
||||||
|
char buff[40];
|
||||||
|
sprintf(buff,":%d\r\n", _port);
|
||||||
|
|
||||||
|
header += buff;
|
||||||
|
header += "Content-Type: text/xml\r\nContent-length: ";
|
||||||
|
|
||||||
|
sprintf(buff,"%d\r\n\r\n", body.size());
|
||||||
|
|
||||||
|
return header + buff;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
XmlRpcClient::writeRequest()
|
||||||
|
{
|
||||||
|
if (_bytesWritten == 0)
|
||||||
|
XmlRpcUtil::log(5, "XmlRpcClient::writeRequest (attempt %d):\n%s\n", _sendAttempts+1, _request.c_str());
|
||||||
|
|
||||||
|
// Try to write the request
|
||||||
|
if ( ! XmlRpcSocket::nbWrite(this->getfd(), _request, &_bytesWritten)) {
|
||||||
|
XmlRpcUtil::error("Error in XmlRpcClient::writeRequest: write error (%s).",XmlRpcSocket::getErrorMsg().c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
XmlRpcUtil::log(3, "XmlRpcClient::writeRequest: wrote %d of %d bytes.", _bytesWritten, _request.length());
|
||||||
|
|
||||||
|
// Wait for the result
|
||||||
|
if (_bytesWritten == int(_request.length())) {
|
||||||
|
_header = "";
|
||||||
|
_response = "";
|
||||||
|
_connectionState = READ_HEADER;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Read the header from the response
|
||||||
|
bool
|
||||||
|
XmlRpcClient::readHeader()
|
||||||
|
{
|
||||||
|
// Read available data
|
||||||
|
if ( ! XmlRpcSocket::nbRead(this->getfd(), _header, &_eof) ||
|
||||||
|
(_eof && _header.length() == 0)) {
|
||||||
|
|
||||||
|
// If we haven't read any data yet and this is a keep-alive connection, the server may
|
||||||
|
// have timed out, so we try one more time.
|
||||||
|
if (getKeepOpen() && _header.length() == 0 && _sendAttempts++ == 0) {
|
||||||
|
XmlRpcUtil::log(4, "XmlRpcClient::readHeader: re-trying connection");
|
||||||
|
XmlRpcSource::close();
|
||||||
|
_connectionState = NO_CONNECTION;
|
||||||
|
_eof = false;
|
||||||
|
return setupConnection();
|
||||||
|
}
|
||||||
|
|
||||||
|
XmlRpcUtil::error("Error in XmlRpcClient::readHeader: error while reading header (%s) on fd %d.",
|
||||||
|
XmlRpcSocket::getErrorMsg().c_str(), getfd());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
XmlRpcUtil::log(4, "XmlRpcClient::readHeader: client has read %d bytes", _header.length());
|
||||||
|
|
||||||
|
char *hp = (char*)_header.c_str(); // Start of header
|
||||||
|
char *ep = hp + _header.length(); // End of string
|
||||||
|
char *bp = 0; // Start of body
|
||||||
|
char *lp = 0; // Start of content-length value
|
||||||
|
|
||||||
|
for (char *cp = hp; (bp == 0) && (cp < ep); ++cp) {
|
||||||
|
if ((ep - cp > 16) && (strncasecmp(cp, "Content-length: ", 16) == 0))
|
||||||
|
lp = cp + 16;
|
||||||
|
else if ((ep - cp > 4) && (strncmp(cp, "\r\n\r\n", 4) == 0))
|
||||||
|
bp = cp + 4;
|
||||||
|
else if ((ep - cp > 2) && (strncmp(cp, "\n\n", 2) == 0))
|
||||||
|
bp = cp + 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we haven't gotten the entire header yet, return (keep reading)
|
||||||
|
if (bp == 0) {
|
||||||
|
if (_eof) // EOF in the middle of a response is an error
|
||||||
|
{
|
||||||
|
XmlRpcUtil::error("Error in XmlRpcClient::readHeader: EOF while reading header");
|
||||||
|
return false; // Close the connection
|
||||||
|
}
|
||||||
|
|
||||||
|
return true; // Keep reading
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decode content length
|
||||||
|
if (lp == 0) {
|
||||||
|
XmlRpcUtil::error("Error XmlRpcClient::readHeader: No Content-length specified");
|
||||||
|
return false; // We could try to figure it out by parsing as we read, but for now...
|
||||||
|
}
|
||||||
|
|
||||||
|
_contentLength = atoi(lp);
|
||||||
|
if (_contentLength <= 0) {
|
||||||
|
XmlRpcUtil::error("Error in XmlRpcClient::readHeader: Invalid Content-length specified (%d).", _contentLength);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
XmlRpcUtil::log(4, "client read content length: %d", _contentLength);
|
||||||
|
|
||||||
|
// Otherwise copy non-header data to response buffer and set state to read response.
|
||||||
|
_response = bp;
|
||||||
|
_header = ""; // should parse out any interesting bits from the header (connection, etc)...
|
||||||
|
_connectionState = READ_RESPONSE;
|
||||||
|
return true; // Continue monitoring this source
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
XmlRpcClient::readResponse()
|
||||||
|
{
|
||||||
|
// If we dont have the entire response yet, read available data
|
||||||
|
if (int(_response.length()) < _contentLength) {
|
||||||
|
if ( ! XmlRpcSocket::nbRead(this->getfd(), _response, &_eof)) {
|
||||||
|
XmlRpcUtil::error("Error in XmlRpcClient::readResponse: read error (%s).",XmlRpcSocket::getErrorMsg().c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we haven't gotten the entire _response yet, return (keep reading)
|
||||||
|
if (int(_response.length()) < _contentLength) {
|
||||||
|
if (_eof) {
|
||||||
|
XmlRpcUtil::error("Error in XmlRpcClient::readResponse: EOF while reading response");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise, parse and return the result
|
||||||
|
XmlRpcUtil::log(3, "XmlRpcClient::readResponse (read %d bytes)", _response.length());
|
||||||
|
XmlRpcUtil::log(5, "response:\n%s", _response.c_str());
|
||||||
|
|
||||||
|
_connectionState = IDLE;
|
||||||
|
|
||||||
|
return false; // Stop monitoring this source (causes return from work)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Convert the response xml into a result value
|
||||||
|
bool
|
||||||
|
XmlRpcClient::parseResponse(XmlRpcValue& result)
|
||||||
|
{
|
||||||
|
// Parse response xml into result
|
||||||
|
int offset = 0;
|
||||||
|
if ( ! XmlRpcUtil::findTag(METHODRESPONSE_TAG,_response,&offset)) {
|
||||||
|
XmlRpcUtil::error("Error in XmlRpcClient::parseResponse: Invalid response - no methodResponse. Response:\n%s", _response.c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Expect either <params><param>... or <fault>...
|
||||||
|
if ((XmlRpcUtil::nextTagIs(PARAMS_TAG,_response,&offset) &&
|
||||||
|
XmlRpcUtil::nextTagIs(PARAM_TAG,_response,&offset)) ||
|
||||||
|
XmlRpcUtil::nextTagIs(FAULT_TAG,_response,&offset) && (_isFault = true))
|
||||||
|
{
|
||||||
|
if ( ! result.fromXml(_response, &offset)) {
|
||||||
|
XmlRpcUtil::error("Error in XmlRpcClient::parseResponse: Invalid response value. Response:\n%s", _response.c_str());
|
||||||
|
_response = "";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
XmlRpcUtil::error("Error in XmlRpcClient::parseResponse: Invalid response - no param or fault tag. Response:\n%s", _response.c_str());
|
||||||
|
_response = "";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
_response = "";
|
||||||
|
return result.valid();
|
||||||
|
}
|
||||||
|
|
||||||
209
src/XmlRpcDispatch.cpp
Normal file
209
src/XmlRpcDispatch.cpp
Normal file
|
|
@ -0,0 +1,209 @@
|
||||||
|
|
||||||
|
#include "xmlrpcpp/XmlRpcDispatch.h"
|
||||||
|
#include "xmlrpcpp/XmlRpcSource.h"
|
||||||
|
#include "xmlrpcpp/XmlRpcUtil.h"
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
#include <sys/timeb.h>
|
||||||
|
|
||||||
|
#if defined(_WINDOWS)
|
||||||
|
# include <winsock2.h>
|
||||||
|
|
||||||
|
# define USE_FTIME
|
||||||
|
# if defined(_MSC_VER)
|
||||||
|
# define timeb _timeb
|
||||||
|
# define ftime _ftime
|
||||||
|
# endif
|
||||||
|
#else
|
||||||
|
# include <sys/time.h>
|
||||||
|
#endif // _WINDOWS
|
||||||
|
|
||||||
|
|
||||||
|
using namespace XmlRpc;
|
||||||
|
|
||||||
|
|
||||||
|
XmlRpcDispatch::XmlRpcDispatch()
|
||||||
|
{
|
||||||
|
_endTime = -1.0;
|
||||||
|
_doClear = false;
|
||||||
|
_inWork = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
XmlRpcDispatch::~XmlRpcDispatch()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// Monitor this source for the specified events and call its event handler
|
||||||
|
// when the event occurs
|
||||||
|
void
|
||||||
|
XmlRpcDispatch::addSource(XmlRpcSource* source, unsigned mask)
|
||||||
|
{
|
||||||
|
_sources.push_back(MonitoredSource(source, mask));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stop monitoring this source. Does not close the source.
|
||||||
|
void
|
||||||
|
XmlRpcDispatch::removeSource(XmlRpcSource* source)
|
||||||
|
{
|
||||||
|
for (SourceList::iterator it=_sources.begin(); it!=_sources.end(); ++it)
|
||||||
|
if (it->getSource() == source)
|
||||||
|
{
|
||||||
|
_sources.erase(it);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Modify the types of events to watch for on this source
|
||||||
|
void
|
||||||
|
XmlRpcDispatch::setSourceEvents(XmlRpcSource* source, unsigned eventMask)
|
||||||
|
{
|
||||||
|
for (SourceList::iterator it=_sources.begin(); it!=_sources.end(); ++it)
|
||||||
|
if (it->getSource() == source)
|
||||||
|
{
|
||||||
|
it->getMask() = eventMask;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Watch current set of sources and process events
|
||||||
|
void
|
||||||
|
XmlRpcDispatch::work(double timeout)
|
||||||
|
{
|
||||||
|
// Compute end time
|
||||||
|
_endTime = (timeout < 0.0) ? -1.0 : (getTime() + timeout);
|
||||||
|
_doClear = false;
|
||||||
|
_inWork = true;
|
||||||
|
|
||||||
|
// Only work while there is something to monitor
|
||||||
|
while (_sources.size() > 0) {
|
||||||
|
|
||||||
|
// Construct the sets of descriptors we are interested in
|
||||||
|
fd_set inFd, outFd, excFd;
|
||||||
|
FD_ZERO(&inFd);
|
||||||
|
FD_ZERO(&outFd);
|
||||||
|
FD_ZERO(&excFd);
|
||||||
|
|
||||||
|
int maxFd = -1; // Not used on windows
|
||||||
|
SourceList::iterator it;
|
||||||
|
for (it=_sources.begin(); it!=_sources.end(); ++it) {
|
||||||
|
int fd = it->getSource()->getfd();
|
||||||
|
if (it->getMask() & ReadableEvent) FD_SET(fd, &inFd);
|
||||||
|
if (it->getMask() & WritableEvent) FD_SET(fd, &outFd);
|
||||||
|
if (it->getMask() & Exception) FD_SET(fd, &excFd);
|
||||||
|
if (it->getMask() && fd > maxFd) maxFd = fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for events
|
||||||
|
int nEvents;
|
||||||
|
if (timeout < 0.0)
|
||||||
|
nEvents = select(maxFd+1, &inFd, &outFd, &excFd, NULL);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
struct timeval tv;
|
||||||
|
tv.tv_sec = (int)floor(timeout);
|
||||||
|
tv.tv_usec = ((int)floor(1000000.0 * (timeout-floor(timeout)))) % 1000000;
|
||||||
|
nEvents = select(maxFd+1, &inFd, &outFd, &excFd, &tv);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nEvents < 0)
|
||||||
|
{
|
||||||
|
XmlRpcUtil::error("Error in XmlRpcDispatch::work: error in select (%d).", nEvents);
|
||||||
|
_inWork = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process events
|
||||||
|
for (it=_sources.begin(); it != _sources.end(); )
|
||||||
|
{
|
||||||
|
SourceList::iterator thisIt = it++;
|
||||||
|
XmlRpcSource* src = thisIt->getSource();
|
||||||
|
int fd = src->getfd();
|
||||||
|
unsigned newMask = (unsigned) -1;
|
||||||
|
if (fd <= maxFd) {
|
||||||
|
// If you select on multiple event types this could be ambiguous
|
||||||
|
if (FD_ISSET(fd, &inFd))
|
||||||
|
newMask &= src->handleEvent(ReadableEvent);
|
||||||
|
if (FD_ISSET(fd, &outFd))
|
||||||
|
newMask &= src->handleEvent(WritableEvent);
|
||||||
|
if (FD_ISSET(fd, &excFd))
|
||||||
|
newMask &= src->handleEvent(Exception);
|
||||||
|
|
||||||
|
if ( ! newMask) {
|
||||||
|
_sources.erase(thisIt); // Stop monitoring this one
|
||||||
|
if ( ! src->getKeepOpen())
|
||||||
|
src->close();
|
||||||
|
} else if (newMask != (unsigned) -1) {
|
||||||
|
thisIt->getMask() = newMask;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check whether to clear all sources
|
||||||
|
if (_doClear)
|
||||||
|
{
|
||||||
|
SourceList closeList = _sources;
|
||||||
|
_sources.clear();
|
||||||
|
for (SourceList::iterator it=closeList.begin(); it!=closeList.end(); ++it) {
|
||||||
|
XmlRpcSource *src = it->getSource();
|
||||||
|
src->close();
|
||||||
|
}
|
||||||
|
|
||||||
|
_doClear = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check whether end time has passed
|
||||||
|
if (0 <= _endTime && getTime() > _endTime)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
_inWork = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Exit from work routine. Presumably this will be called from
|
||||||
|
// one of the source event handlers.
|
||||||
|
void
|
||||||
|
XmlRpcDispatch::exit()
|
||||||
|
{
|
||||||
|
_endTime = 0.0; // Return from work asap
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear all sources from the monitored sources list
|
||||||
|
void
|
||||||
|
XmlRpcDispatch::clear()
|
||||||
|
{
|
||||||
|
if (_inWork)
|
||||||
|
_doClear = true; // Finish reporting current events before clearing
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SourceList closeList = _sources;
|
||||||
|
_sources.clear();
|
||||||
|
for (SourceList::iterator it=closeList.begin(); it!=closeList.end(); ++it)
|
||||||
|
it->getSource()->close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
double
|
||||||
|
XmlRpcDispatch::getTime()
|
||||||
|
{
|
||||||
|
#ifdef USE_FTIME
|
||||||
|
struct timeb tbuff;
|
||||||
|
|
||||||
|
ftime(&tbuff);
|
||||||
|
return ((double) tbuff.time + ((double)tbuff.millitm / 1000.0) +
|
||||||
|
((double) tbuff.timezone * 60));
|
||||||
|
#else
|
||||||
|
struct timeval tv;
|
||||||
|
struct timezone tz;
|
||||||
|
|
||||||
|
gettimeofday(&tv, &tz);
|
||||||
|
return (tv.tv_sec + tv.tv_usec / 1000000.0);
|
||||||
|
#endif /* USE_FTIME */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
284
src/XmlRpcServer.cpp
Normal file
284
src/XmlRpcServer.cpp
Normal file
|
|
@ -0,0 +1,284 @@
|
||||||
|
|
||||||
|
#include "xmlrpcpp/XmlRpcServer.h"
|
||||||
|
#include "xmlrpcpp/XmlRpcServerConnection.h"
|
||||||
|
#include "xmlrpcpp/XmlRpcServerMethod.h"
|
||||||
|
#include "xmlrpcpp/XmlRpcSocket.h"
|
||||||
|
#include "xmlrpcpp/XmlRpcUtil.h"
|
||||||
|
#include "xmlrpcpp/XmlRpcException.h"
|
||||||
|
|
||||||
|
|
||||||
|
using namespace XmlRpc;
|
||||||
|
|
||||||
|
|
||||||
|
XmlRpcServer::XmlRpcServer()
|
||||||
|
{
|
||||||
|
_introspectionEnabled = false;
|
||||||
|
_listMethods = 0;
|
||||||
|
_methodHelp = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
XmlRpcServer::~XmlRpcServer()
|
||||||
|
{
|
||||||
|
this->shutdown();
|
||||||
|
_methods.clear();
|
||||||
|
delete _listMethods;
|
||||||
|
delete _methodHelp;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Add a command to the RPC server
|
||||||
|
void
|
||||||
|
XmlRpcServer::addMethod(XmlRpcServerMethod* method)
|
||||||
|
{
|
||||||
|
_methods[method->name()] = method;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove a command from the RPC server
|
||||||
|
void
|
||||||
|
XmlRpcServer::removeMethod(XmlRpcServerMethod* method)
|
||||||
|
{
|
||||||
|
MethodMap::iterator i = _methods.find(method->name());
|
||||||
|
if (i != _methods.end())
|
||||||
|
_methods.erase(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove a command from the RPC server by name
|
||||||
|
void
|
||||||
|
XmlRpcServer::removeMethod(const std::string& methodName)
|
||||||
|
{
|
||||||
|
MethodMap::iterator i = _methods.find(methodName);
|
||||||
|
if (i != _methods.end())
|
||||||
|
_methods.erase(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Look up a method by name
|
||||||
|
XmlRpcServerMethod*
|
||||||
|
XmlRpcServer::findMethod(const std::string& name) const
|
||||||
|
{
|
||||||
|
MethodMap::const_iterator i = _methods.find(name);
|
||||||
|
if (i == _methods.end())
|
||||||
|
return 0;
|
||||||
|
return i->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Create a socket, bind to the specified port, and
|
||||||
|
// set it in listen mode to make it available for clients.
|
||||||
|
bool
|
||||||
|
XmlRpcServer::bindAndListen(int port, int backlog /*= 5*/)
|
||||||
|
{
|
||||||
|
int fd = XmlRpcSocket::socket();
|
||||||
|
if (fd < 0)
|
||||||
|
{
|
||||||
|
XmlRpcUtil::error("XmlRpcServer::bindAndListen: Could not create socket (%s).", XmlRpcSocket::getErrorMsg().c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->setfd(fd);
|
||||||
|
|
||||||
|
// Don't block on reads/writes
|
||||||
|
if ( ! XmlRpcSocket::setNonBlocking(fd))
|
||||||
|
{
|
||||||
|
this->close();
|
||||||
|
XmlRpcUtil::error("XmlRpcServer::bindAndListen: Could not set socket to non-blocking input mode (%s).", XmlRpcSocket::getErrorMsg().c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allow this port to be re-bound immediately so server re-starts are not delayed
|
||||||
|
if ( ! XmlRpcSocket::setReuseAddr(fd))
|
||||||
|
{
|
||||||
|
this->close();
|
||||||
|
XmlRpcUtil::error("XmlRpcServer::bindAndListen: Could not set SO_REUSEADDR socket option (%s).", XmlRpcSocket::getErrorMsg().c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bind to the specified port on the default interface
|
||||||
|
if ( ! XmlRpcSocket::bind(fd, port))
|
||||||
|
{
|
||||||
|
this->close();
|
||||||
|
XmlRpcUtil::error("XmlRpcServer::bindAndListen: Could not bind to specified port (%s).", XmlRpcSocket::getErrorMsg().c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set in listening mode
|
||||||
|
if ( ! XmlRpcSocket::listen(fd, backlog))
|
||||||
|
{
|
||||||
|
this->close();
|
||||||
|
XmlRpcUtil::error("XmlRpcServer::bindAndListen: Could not set socket in listening mode (%s).", XmlRpcSocket::getErrorMsg().c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
XmlRpcUtil::log(2, "XmlRpcServer::bindAndListen: server listening on port %d fd %d", port, fd);
|
||||||
|
|
||||||
|
// Notify the dispatcher to listen on this source when we are in work()
|
||||||
|
_disp.addSource(this, XmlRpcDispatch::ReadableEvent);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Process client requests for the specified time
|
||||||
|
void
|
||||||
|
XmlRpcServer::work(double msTime)
|
||||||
|
{
|
||||||
|
XmlRpcUtil::log(2, "XmlRpcServer::work: waiting for a connection");
|
||||||
|
_disp.work(msTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Handle input on the server socket by accepting the connection
|
||||||
|
// and reading the rpc request.
|
||||||
|
unsigned
|
||||||
|
XmlRpcServer::handleEvent(unsigned mask)
|
||||||
|
{
|
||||||
|
acceptConnection();
|
||||||
|
return XmlRpcDispatch::ReadableEvent; // Continue to monitor this fd
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Accept a client connection request and create a connection to
|
||||||
|
// handle method calls from the client.
|
||||||
|
void
|
||||||
|
XmlRpcServer::acceptConnection()
|
||||||
|
{
|
||||||
|
int s = XmlRpcSocket::accept(this->getfd());
|
||||||
|
XmlRpcUtil::log(2, "XmlRpcServer::acceptConnection: socket %d", s);
|
||||||
|
if (s < 0)
|
||||||
|
{
|
||||||
|
//this->close();
|
||||||
|
XmlRpcUtil::error("XmlRpcServer::acceptConnection: Could not accept connection (%s).", XmlRpcSocket::getErrorMsg().c_str());
|
||||||
|
}
|
||||||
|
else if ( ! XmlRpcSocket::setNonBlocking(s))
|
||||||
|
{
|
||||||
|
XmlRpcSocket::close(s);
|
||||||
|
XmlRpcUtil::error("XmlRpcServer::acceptConnection: Could not set socket to non-blocking input mode (%s).", XmlRpcSocket::getErrorMsg().c_str());
|
||||||
|
}
|
||||||
|
else // Notify the dispatcher to listen for input on this source when we are in work()
|
||||||
|
{
|
||||||
|
XmlRpcUtil::log(2, "XmlRpcServer::acceptConnection: creating a connection");
|
||||||
|
_disp.addSource(this->createConnection(s), XmlRpcDispatch::ReadableEvent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Create a new connection object for processing requests from a specific client.
|
||||||
|
XmlRpcServerConnection*
|
||||||
|
XmlRpcServer::createConnection(int s)
|
||||||
|
{
|
||||||
|
// Specify that the connection object be deleted when it is closed
|
||||||
|
return new XmlRpcServerConnection(s, this, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
XmlRpcServer::removeConnection(XmlRpcServerConnection* sc)
|
||||||
|
{
|
||||||
|
_disp.removeSource(sc);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Stop processing client requests
|
||||||
|
void
|
||||||
|
XmlRpcServer::exit()
|
||||||
|
{
|
||||||
|
_disp.exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Close the server socket file descriptor and stop monitoring connections
|
||||||
|
void
|
||||||
|
XmlRpcServer::shutdown()
|
||||||
|
{
|
||||||
|
// This closes and destroys all connections as well as closing this socket
|
||||||
|
_disp.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Introspection support
|
||||||
|
static const std::string LIST_METHODS("system.listMethods");
|
||||||
|
static const std::string METHOD_HELP("system.methodHelp");
|
||||||
|
static const std::string MULTICALL("system.multicall");
|
||||||
|
|
||||||
|
|
||||||
|
// List all methods available on a server
|
||||||
|
class ListMethods : public XmlRpcServerMethod
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ListMethods(XmlRpcServer* s) : XmlRpcServerMethod(LIST_METHODS, s) {}
|
||||||
|
|
||||||
|
void execute(XmlRpcValue& params, XmlRpcValue& result)
|
||||||
|
{
|
||||||
|
_server->listMethods(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string help() { return std::string("List all methods available on a server as an array of strings"); }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Retrieve the help string for a named method
|
||||||
|
class MethodHelp : public XmlRpcServerMethod
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MethodHelp(XmlRpcServer* s) : XmlRpcServerMethod(METHOD_HELP, s) {}
|
||||||
|
|
||||||
|
void execute(XmlRpcValue& params, XmlRpcValue& result)
|
||||||
|
{
|
||||||
|
if (params[0].getType() != XmlRpcValue::TypeString)
|
||||||
|
throw XmlRpcException(METHOD_HELP + ": Invalid argument type");
|
||||||
|
|
||||||
|
XmlRpcServerMethod* m = _server->findMethod(params[0]);
|
||||||
|
if ( ! m)
|
||||||
|
throw XmlRpcException(METHOD_HELP + ": Unknown method name");
|
||||||
|
|
||||||
|
result = m->help();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string help() { return std::string("Retrieve the help string for a named method"); }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Specify whether introspection is enabled or not. Default is enabled.
|
||||||
|
void
|
||||||
|
XmlRpcServer::enableIntrospection(bool enabled)
|
||||||
|
{
|
||||||
|
if (_introspectionEnabled == enabled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_introspectionEnabled = enabled;
|
||||||
|
|
||||||
|
if (enabled)
|
||||||
|
{
|
||||||
|
if ( ! _listMethods)
|
||||||
|
{
|
||||||
|
_listMethods = new ListMethods(this);
|
||||||
|
_methodHelp = new MethodHelp(this);
|
||||||
|
} else {
|
||||||
|
addMethod(_listMethods);
|
||||||
|
addMethod(_methodHelp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
removeMethod(LIST_METHODS);
|
||||||
|
removeMethod(METHOD_HELP);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
XmlRpcServer::listMethods(XmlRpcValue& result)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
result.setSize(_methods.size()+1);
|
||||||
|
for (MethodMap::iterator it=_methods.begin(); it != _methods.end(); ++it)
|
||||||
|
result[i++] = it->first;
|
||||||
|
|
||||||
|
// Multicall support is built into XmlRpcServerConnection
|
||||||
|
result[i] = MULTICALL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
374
src/XmlRpcServerConnection.cpp
Normal file
374
src/XmlRpcServerConnection.cpp
Normal file
|
|
@ -0,0 +1,374 @@
|
||||||
|
|
||||||
|
#include "xmlrpcpp/XmlRpcServerConnection.h"
|
||||||
|
|
||||||
|
#include "xmlrpcpp/XmlRpcSocket.h"
|
||||||
|
#include "xmlrpcpp/XmlRpc.h"
|
||||||
|
#ifndef MAKEDEPEND
|
||||||
|
# include <stdio.h>
|
||||||
|
# include <stdlib.h>
|
||||||
|
#include <cstring> // cho strncmp
|
||||||
|
#include <strings.h> // cho strncasecmp
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
using namespace XmlRpc;
|
||||||
|
|
||||||
|
// Static data
|
||||||
|
const char XmlRpcServerConnection::METHODNAME_TAG[] = "<methodName>";
|
||||||
|
const char XmlRpcServerConnection::PARAMS_TAG[] = "<params>";
|
||||||
|
const char XmlRpcServerConnection::PARAMS_ETAG[] = "</params>";
|
||||||
|
const char XmlRpcServerConnection::PARAM_TAG[] = "<param>";
|
||||||
|
const char XmlRpcServerConnection::PARAM_ETAG[] = "</param>";
|
||||||
|
|
||||||
|
const std::string XmlRpcServerConnection::SYSTEM_MULTICALL = "system.multicall";
|
||||||
|
const std::string XmlRpcServerConnection::METHODNAME = "methodName";
|
||||||
|
const std::string XmlRpcServerConnection::PARAMS = "params";
|
||||||
|
|
||||||
|
const std::string XmlRpcServerConnection::FAULTCODE = "faultCode";
|
||||||
|
const std::string XmlRpcServerConnection::FAULTSTRING = "faultString";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// The server delegates handling client requests to a serverConnection object.
|
||||||
|
XmlRpcServerConnection::XmlRpcServerConnection(int fd, XmlRpcServer* server, bool deleteOnClose /*= false*/) :
|
||||||
|
XmlRpcSource(fd, deleteOnClose)
|
||||||
|
{
|
||||||
|
XmlRpcUtil::log(2,"XmlRpcServerConnection: new socket %d.", fd);
|
||||||
|
_server = server;
|
||||||
|
_connectionState = READ_HEADER;
|
||||||
|
_keepAlive = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
XmlRpcServerConnection::~XmlRpcServerConnection()
|
||||||
|
{
|
||||||
|
XmlRpcUtil::log(4,"XmlRpcServerConnection dtor.");
|
||||||
|
_server->removeConnection(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Handle input on the server socket by accepting the connection
|
||||||
|
// and reading the rpc request. Return true to continue to monitor
|
||||||
|
// the socket for events, false to remove it from the dispatcher.
|
||||||
|
unsigned
|
||||||
|
XmlRpcServerConnection::handleEvent(unsigned /*eventType*/)
|
||||||
|
{
|
||||||
|
if (_connectionState == READ_HEADER)
|
||||||
|
if ( ! readHeader()) return 0;
|
||||||
|
|
||||||
|
if (_connectionState == READ_REQUEST)
|
||||||
|
if ( ! readRequest()) return 0;
|
||||||
|
|
||||||
|
if (_connectionState == WRITE_RESPONSE)
|
||||||
|
if ( ! writeResponse()) return 0;
|
||||||
|
|
||||||
|
return (_connectionState == WRITE_RESPONSE)
|
||||||
|
? XmlRpcDispatch::WritableEvent : XmlRpcDispatch::ReadableEvent;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
XmlRpcServerConnection::readHeader()
|
||||||
|
{
|
||||||
|
// Read available data
|
||||||
|
bool eof;
|
||||||
|
if ( ! XmlRpcSocket::nbRead(this->getfd(), _header, &eof)) {
|
||||||
|
// Its only an error if we already have read some data
|
||||||
|
if (_header.length() > 0)
|
||||||
|
XmlRpcUtil::error("XmlRpcServerConnection::readHeader: error while reading header (%s).",XmlRpcSocket::getErrorMsg().c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
XmlRpcUtil::log(4, "XmlRpcServerConnection::readHeader: read %d bytes.", _header.length());
|
||||||
|
char *hp = (char*)_header.c_str(); // Start of header
|
||||||
|
char *ep = hp + _header.length(); // End of string
|
||||||
|
char *bp = 0; // Start of body
|
||||||
|
char *lp = 0; // Start of content-length value
|
||||||
|
char *kp = 0; // Start of connection value
|
||||||
|
|
||||||
|
for (char *cp = hp; (bp == 0) && (cp < ep); ++cp) {
|
||||||
|
if ((ep - cp > 16) && (strncasecmp(cp, "Content-length: ", 16) == 0))
|
||||||
|
lp = cp + 16;
|
||||||
|
else if ((ep - cp > 12) && (strncasecmp(cp, "Connection: ", 12) == 0))
|
||||||
|
kp = cp + 12;
|
||||||
|
else if ((ep - cp > 4) && (strncmp(cp, "\r\n\r\n", 4) == 0))
|
||||||
|
bp = cp + 4;
|
||||||
|
else if ((ep - cp > 2) && (strncmp(cp, "\n\n", 2) == 0))
|
||||||
|
bp = cp + 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we haven't gotten the entire header yet, return (keep reading)
|
||||||
|
if (bp == 0) {
|
||||||
|
// EOF in the middle of a request is an error, otherwise its ok
|
||||||
|
if (eof) {
|
||||||
|
XmlRpcUtil::log(4, "XmlRpcServerConnection::readHeader: EOF");
|
||||||
|
if (_header.length() > 0)
|
||||||
|
XmlRpcUtil::error("XmlRpcServerConnection::readHeader: EOF while reading header");
|
||||||
|
return false; // Either way we close the connection
|
||||||
|
}
|
||||||
|
|
||||||
|
return true; // Keep reading
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decode content length
|
||||||
|
if (lp == 0) {
|
||||||
|
XmlRpcUtil::error("XmlRpcServerConnection::readHeader: No Content-length specified");
|
||||||
|
return false; // We could try to figure it out by parsing as we read, but for now...
|
||||||
|
}
|
||||||
|
|
||||||
|
_contentLength = atoi(lp);
|
||||||
|
if (_contentLength <= 0) {
|
||||||
|
XmlRpcUtil::error("XmlRpcServerConnection::readHeader: Invalid Content-length specified (%d).", _contentLength);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
XmlRpcUtil::log(3, "XmlRpcServerConnection::readHeader: specified content length is %d.", _contentLength);
|
||||||
|
|
||||||
|
// Otherwise copy non-header data to request buffer and set state to read request.
|
||||||
|
_request = bp;
|
||||||
|
|
||||||
|
// Parse out any interesting bits from the header (HTTP version, connection)
|
||||||
|
_keepAlive = true;
|
||||||
|
if (_header.find("HTTP/1.0") != std::string::npos) {
|
||||||
|
if (kp == 0 || strncasecmp(kp, "keep-alive", 10) != 0)
|
||||||
|
_keepAlive = false; // Default for HTTP 1.0 is to close the connection
|
||||||
|
} else {
|
||||||
|
if (kp != 0 && strncasecmp(kp, "close", 5) == 0)
|
||||||
|
_keepAlive = false;
|
||||||
|
}
|
||||||
|
XmlRpcUtil::log(3, "KeepAlive: %d", _keepAlive);
|
||||||
|
|
||||||
|
|
||||||
|
_header = "";
|
||||||
|
_connectionState = READ_REQUEST;
|
||||||
|
return true; // Continue monitoring this source
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
XmlRpcServerConnection::readRequest()
|
||||||
|
{
|
||||||
|
// If we dont have the entire request yet, read available data
|
||||||
|
if (int(_request.length()) < _contentLength) {
|
||||||
|
bool eof;
|
||||||
|
if ( ! XmlRpcSocket::nbRead(this->getfd(), _request, &eof)) {
|
||||||
|
XmlRpcUtil::error("XmlRpcServerConnection::readRequest: read error (%s).",XmlRpcSocket::getErrorMsg().c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we haven't gotten the entire request yet, return (keep reading)
|
||||||
|
if (int(_request.length()) < _contentLength) {
|
||||||
|
if (eof) {
|
||||||
|
XmlRpcUtil::error("XmlRpcServerConnection::readRequest: EOF while reading request");
|
||||||
|
return false; // Either way we close the connection
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise, parse and dispatch the request
|
||||||
|
XmlRpcUtil::log(3, "XmlRpcServerConnection::readRequest read %d bytes.", _request.length());
|
||||||
|
//XmlRpcUtil::log(5, "XmlRpcServerConnection::readRequest:\n%s\n", _request.c_str());
|
||||||
|
|
||||||
|
_connectionState = WRITE_RESPONSE;
|
||||||
|
|
||||||
|
return true; // Continue monitoring this source
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
XmlRpcServerConnection::writeResponse()
|
||||||
|
{
|
||||||
|
if (_response.length() == 0) {
|
||||||
|
executeRequest();
|
||||||
|
_bytesWritten = 0;
|
||||||
|
if (_response.length() == 0) {
|
||||||
|
XmlRpcUtil::error("XmlRpcServerConnection::writeResponse: empty response.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try to write the response
|
||||||
|
if ( ! XmlRpcSocket::nbWrite(this->getfd(), _response, &_bytesWritten)) {
|
||||||
|
XmlRpcUtil::error("XmlRpcServerConnection::writeResponse: write error (%s).",XmlRpcSocket::getErrorMsg().c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
XmlRpcUtil::log(3, "XmlRpcServerConnection::writeResponse: wrote %d of %d bytes.", _bytesWritten, _response.length());
|
||||||
|
|
||||||
|
// Prepare to read the next request
|
||||||
|
if (_bytesWritten == int(_response.length())) {
|
||||||
|
_header = "";
|
||||||
|
_request = "";
|
||||||
|
_response = "";
|
||||||
|
_connectionState = READ_HEADER;
|
||||||
|
}
|
||||||
|
|
||||||
|
return _keepAlive; // Continue monitoring this source if true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run the method, generate _response string
|
||||||
|
void
|
||||||
|
XmlRpcServerConnection::executeRequest()
|
||||||
|
{
|
||||||
|
XmlRpcValue params, resultValue;
|
||||||
|
std::string methodName = parseRequest(params);
|
||||||
|
XmlRpcUtil::log(2, "XmlRpcServerConnection::executeRequest: server calling method '%s'",
|
||||||
|
methodName.c_str());
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
if ( ! executeMethod(methodName, params, resultValue) &&
|
||||||
|
! executeMulticall(methodName, params, resultValue))
|
||||||
|
generateFaultResponse(methodName + ": unknown method name");
|
||||||
|
else
|
||||||
|
generateResponse(resultValue.toXml());
|
||||||
|
|
||||||
|
} catch (const XmlRpcException& fault) {
|
||||||
|
XmlRpcUtil::log(2, "XmlRpcServerConnection::executeRequest: fault %s.",
|
||||||
|
fault.getMessage().c_str());
|
||||||
|
generateFaultResponse(fault.getMessage(), fault.getCode());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse the method name and the argument values from the request.
|
||||||
|
std::string
|
||||||
|
XmlRpcServerConnection::parseRequest(XmlRpcValue& params)
|
||||||
|
{
|
||||||
|
int offset = 0; // Number of chars parsed from the request
|
||||||
|
|
||||||
|
std::string methodName = XmlRpcUtil::parseTag(METHODNAME_TAG, _request, &offset);
|
||||||
|
|
||||||
|
if (methodName.size() > 0 && XmlRpcUtil::findTag(PARAMS_TAG, _request, &offset))
|
||||||
|
{
|
||||||
|
int nArgs = 0;
|
||||||
|
while (XmlRpcUtil::nextTagIs(PARAM_TAG, _request, &offset)) {
|
||||||
|
params[nArgs++] = XmlRpcValue(_request, &offset);
|
||||||
|
(void) XmlRpcUtil::nextTagIs(PARAM_ETAG, _request, &offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
(void) XmlRpcUtil::nextTagIs(PARAMS_ETAG, _request, &offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
return methodName;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Execute a named method with the specified params.
|
||||||
|
bool
|
||||||
|
XmlRpcServerConnection::executeMethod(const std::string& methodName,
|
||||||
|
XmlRpcValue& params, XmlRpcValue& result)
|
||||||
|
{
|
||||||
|
XmlRpcServerMethod* method = _server->findMethod(methodName);
|
||||||
|
|
||||||
|
if ( ! method) return false;
|
||||||
|
|
||||||
|
method->execute(params, result);
|
||||||
|
|
||||||
|
// Ensure a valid result value
|
||||||
|
if ( ! result.valid())
|
||||||
|
result = std::string();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Execute multiple calls and return the results in an array.
|
||||||
|
bool
|
||||||
|
XmlRpcServerConnection::executeMulticall(const std::string& methodName,
|
||||||
|
XmlRpcValue& params, XmlRpcValue& result)
|
||||||
|
{
|
||||||
|
if (methodName != SYSTEM_MULTICALL) return false;
|
||||||
|
|
||||||
|
// There ought to be 1 parameter, an array of structs
|
||||||
|
if (params.size() != 1 || params[0].getType() != XmlRpcValue::TypeArray)
|
||||||
|
throw XmlRpcException(SYSTEM_MULTICALL + ": Invalid argument (expected an array)");
|
||||||
|
|
||||||
|
int nc = params[0].size();
|
||||||
|
result.setSize(nc);
|
||||||
|
|
||||||
|
for (int i=0; i<nc; ++i) {
|
||||||
|
|
||||||
|
if ( ! params[0][i].hasMember(METHODNAME) ||
|
||||||
|
! params[0][i].hasMember(PARAMS)) {
|
||||||
|
result[i][FAULTCODE] = -1;
|
||||||
|
result[i][FAULTSTRING] = SYSTEM_MULTICALL +
|
||||||
|
": Invalid argument (expected a struct with members methodName and params)";
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string& methodName = params[0][i][METHODNAME];
|
||||||
|
XmlRpcValue& methodParams = params[0][i][PARAMS];
|
||||||
|
|
||||||
|
XmlRpcValue resultValue;
|
||||||
|
resultValue.setSize(1);
|
||||||
|
try {
|
||||||
|
if ( ! executeMethod(methodName, methodParams, resultValue[0]) &&
|
||||||
|
! executeMulticall(methodName, params, resultValue[0]))
|
||||||
|
{
|
||||||
|
result[i][FAULTCODE] = -1;
|
||||||
|
result[i][FAULTSTRING] = methodName + ": unknown method name";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
result[i] = resultValue;
|
||||||
|
|
||||||
|
} catch (const XmlRpcException& fault) {
|
||||||
|
result[i][FAULTCODE] = fault.getCode();
|
||||||
|
result[i][FAULTSTRING] = fault.getMessage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Create a response from results xml
|
||||||
|
void
|
||||||
|
XmlRpcServerConnection::generateResponse(std::string const& resultXml)
|
||||||
|
{
|
||||||
|
const char RESPONSE_1[] =
|
||||||
|
"<?xml version=\"1.0\"?>\r\n"
|
||||||
|
"<methodResponse><params><param>\r\n\t";
|
||||||
|
const char RESPONSE_2[] =
|
||||||
|
"\r\n</param></params></methodResponse>\r\n";
|
||||||
|
|
||||||
|
std::string body = RESPONSE_1 + resultXml + RESPONSE_2;
|
||||||
|
std::string header = generateHeader(body);
|
||||||
|
|
||||||
|
_response = header + body;
|
||||||
|
XmlRpcUtil::log(5, "XmlRpcServerConnection::generateResponse:\n%s\n", _response.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prepend http headers
|
||||||
|
std::string
|
||||||
|
XmlRpcServerConnection::generateHeader(std::string const& body)
|
||||||
|
{
|
||||||
|
std::string header =
|
||||||
|
"HTTP/1.1 200 OK\r\n"
|
||||||
|
"Server: ";
|
||||||
|
header += XMLRPC_VERSION;
|
||||||
|
header += "\r\n"
|
||||||
|
"Content-Type: text/xml\r\n"
|
||||||
|
"Content-length: ";
|
||||||
|
|
||||||
|
char buffLen[40];
|
||||||
|
sprintf(buffLen,"%d\r\n\r\n", body.size());
|
||||||
|
|
||||||
|
return header + buffLen;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
XmlRpcServerConnection::generateFaultResponse(std::string const& errorMsg, int errorCode)
|
||||||
|
{
|
||||||
|
const char RESPONSE_1[] =
|
||||||
|
"<?xml version=\"1.0\"?>\r\n"
|
||||||
|
"<methodResponse><fault>\r\n\t";
|
||||||
|
const char RESPONSE_2[] =
|
||||||
|
"\r\n</fault></methodResponse>\r\n";
|
||||||
|
|
||||||
|
XmlRpcValue faultStruct;
|
||||||
|
faultStruct[FAULTCODE] = errorCode;
|
||||||
|
faultStruct[FAULTSTRING] = errorMsg;
|
||||||
|
std::string body = RESPONSE_1 + faultStruct.toXml() + RESPONSE_2;
|
||||||
|
std::string header = generateHeader(body);
|
||||||
|
|
||||||
|
_response = header + body;
|
||||||
|
}
|
||||||
|
|
||||||
21
src/XmlRpcServerMethod.cpp
Normal file
21
src/XmlRpcServerMethod.cpp
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
|
||||||
|
#include "xmlrpcpp/XmlRpcServerMethod.h"
|
||||||
|
#include "xmlrpcpp/XmlRpcServer.h"
|
||||||
|
|
||||||
|
namespace XmlRpc {
|
||||||
|
|
||||||
|
|
||||||
|
XmlRpcServerMethod::XmlRpcServerMethod(std::string const& name, XmlRpcServer* server)
|
||||||
|
{
|
||||||
|
_name = name;
|
||||||
|
_server = server;
|
||||||
|
if (_server) _server->addMethod(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
XmlRpcServerMethod::~XmlRpcServerMethod()
|
||||||
|
{
|
||||||
|
if (_server) _server->removeMethod(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace XmlRpc
|
||||||
272
src/XmlRpcSocket.cpp
Normal file
272
src/XmlRpcSocket.cpp
Normal file
|
|
@ -0,0 +1,272 @@
|
||||||
|
|
||||||
|
#include "xmlrpcpp/XmlRpcSocket.h"
|
||||||
|
#include "xmlrpcpp/XmlRpcUtil.h"
|
||||||
|
|
||||||
|
#ifndef MAKEDEPEND
|
||||||
|
|
||||||
|
#if defined(_WINDOWS)
|
||||||
|
# include <stdio.h>
|
||||||
|
|
||||||
|
# include <winsock2.h>
|
||||||
|
//# pragma lib(WS2_32.lib)
|
||||||
|
|
||||||
|
# define EINPROGRESS WSAEINPROGRESS
|
||||||
|
# define EWOULDBLOCK WSAEWOULDBLOCK
|
||||||
|
# define ETIMEDOUT WSAETIMEDOUT
|
||||||
|
#else
|
||||||
|
extern "C" {
|
||||||
|
# include <unistd.h>
|
||||||
|
# include <stdio.h>
|
||||||
|
# include <sys/types.h>
|
||||||
|
# include <sys/socket.h>
|
||||||
|
# include <netinet/in.h>
|
||||||
|
# include <netdb.h>
|
||||||
|
# include <errno.h>
|
||||||
|
# include <fcntl.h>
|
||||||
|
#include <cstring> // cho memset, memcpy
|
||||||
|
}
|
||||||
|
#endif // _WINDOWS
|
||||||
|
|
||||||
|
#endif // MAKEDEPEND
|
||||||
|
|
||||||
|
|
||||||
|
using namespace XmlRpc;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(_WINDOWS)
|
||||||
|
|
||||||
|
static void initWinSock()
|
||||||
|
{
|
||||||
|
static bool wsInit = false;
|
||||||
|
if (! wsInit)
|
||||||
|
{
|
||||||
|
WORD wVersionRequested = MAKEWORD( 2, 0 );
|
||||||
|
WSADATA wsaData;
|
||||||
|
WSAStartup(wVersionRequested, &wsaData);
|
||||||
|
wsInit = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#define initWinSock()
|
||||||
|
|
||||||
|
#endif // _WINDOWS
|
||||||
|
|
||||||
|
|
||||||
|
// These errors are not considered fatal for an IO operation; the operation will be re-tried.
|
||||||
|
|
||||||
|
static inline bool
|
||||||
|
|
||||||
|
nonFatalError()
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
int err = XmlRpcSocket::getError();
|
||||||
|
|
||||||
|
return (err == EINPROGRESS || err == EAGAIN || err == EWOULDBLOCK || err == EINTR);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
XmlRpcSocket::socket()
|
||||||
|
{
|
||||||
|
initWinSock();
|
||||||
|
return (int) ::socket(AF_INET, SOCK_STREAM, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
XmlRpcSocket::close(int fd)
|
||||||
|
{
|
||||||
|
XmlRpcUtil::log(4, "XmlRpcSocket::close: fd %d.", fd);
|
||||||
|
#if defined(_WINDOWS)
|
||||||
|
closesocket(fd);
|
||||||
|
#else
|
||||||
|
::close(fd);
|
||||||
|
#endif // _WINDOWS
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
XmlRpcSocket::setNonBlocking(int fd)
|
||||||
|
{
|
||||||
|
#if defined(_WINDOWS)
|
||||||
|
unsigned long flag = 1;
|
||||||
|
return (ioctlsocket((SOCKET)fd, FIONBIO, &flag) == 0);
|
||||||
|
#else
|
||||||
|
return (fcntl(fd, F_SETFL, O_NONBLOCK) == 0);
|
||||||
|
#endif // _WINDOWS
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
XmlRpcSocket::setReuseAddr(int fd)
|
||||||
|
{
|
||||||
|
// Allow this port to be re-bound immediately so server re-starts are not delayed
|
||||||
|
int sflag = 1;
|
||||||
|
return (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const char *)&sflag, sizeof(sflag)) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Bind to a specified port
|
||||||
|
bool
|
||||||
|
XmlRpcSocket::bind(int fd, int port)
|
||||||
|
{
|
||||||
|
struct sockaddr_in saddr;
|
||||||
|
memset(&saddr, 0, sizeof(saddr));
|
||||||
|
saddr.sin_family = AF_INET;
|
||||||
|
saddr.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||||
|
saddr.sin_port = htons((u_short) port);
|
||||||
|
return (::bind(fd, (struct sockaddr *)&saddr, sizeof(saddr)) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Set socket in listen mode
|
||||||
|
bool
|
||||||
|
XmlRpcSocket::listen(int fd, int backlog)
|
||||||
|
{
|
||||||
|
return (::listen(fd, backlog) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
XmlRpcSocket::accept(int fd)
|
||||||
|
{
|
||||||
|
struct sockaddr_in addr;
|
||||||
|
#if defined(_WINDOWS)
|
||||||
|
int
|
||||||
|
#else
|
||||||
|
socklen_t
|
||||||
|
#endif
|
||||||
|
addrlen = sizeof(addr);
|
||||||
|
|
||||||
|
return (int) ::accept(fd, (struct sockaddr*)&addr, &addrlen);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Connect a socket to a server (from a client)
|
||||||
|
bool
|
||||||
|
XmlRpcSocket::connect(int fd, std::string& host, int port)
|
||||||
|
{
|
||||||
|
struct sockaddr_in saddr;
|
||||||
|
memset(&saddr, 0, sizeof(saddr));
|
||||||
|
saddr.sin_family = AF_INET;
|
||||||
|
|
||||||
|
struct hostent *hp = gethostbyname(host.c_str());
|
||||||
|
if (hp == 0) return false;
|
||||||
|
|
||||||
|
saddr.sin_family = hp->h_addrtype;
|
||||||
|
memcpy(&saddr.sin_addr, hp->h_addr, hp->h_length);
|
||||||
|
saddr.sin_port = htons((u_short) port);
|
||||||
|
|
||||||
|
// For asynch operation, this will return EWOULDBLOCK (windows) or
|
||||||
|
// EINPROGRESS (linux) and we just need to wait for the socket to be writable...
|
||||||
|
int result = ::connect(fd, (struct sockaddr *)&saddr, sizeof(saddr));
|
||||||
|
return result == 0 || nonFatalError();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Read available text from the specified socket. Returns false on error.
|
||||||
|
bool
|
||||||
|
XmlRpcSocket::nbRead(int fd, std::string& s, bool *eof)
|
||||||
|
{
|
||||||
|
const int READ_SIZE = 4096; // Number of bytes to attempt to read at a time
|
||||||
|
char readBuf[READ_SIZE];
|
||||||
|
|
||||||
|
bool wouldBlock = false;
|
||||||
|
*eof = false;
|
||||||
|
|
||||||
|
while ( ! wouldBlock && ! *eof) {
|
||||||
|
#if defined(_WINDOWS)
|
||||||
|
int n = recv(fd, readBuf, READ_SIZE-1, 0);
|
||||||
|
#else
|
||||||
|
int n = read(fd, readBuf, READ_SIZE-1);
|
||||||
|
#endif
|
||||||
|
XmlRpcUtil::log(5, "XmlRpcSocket::nbRead: read/recv returned %d.", n);
|
||||||
|
|
||||||
|
|
||||||
|
if (n > 0) {
|
||||||
|
readBuf[n] = 0;
|
||||||
|
s.append(readBuf, n);
|
||||||
|
} else if (n == 0) {
|
||||||
|
*eof = true;
|
||||||
|
} else if (nonFatalError()) {
|
||||||
|
wouldBlock = true;
|
||||||
|
} else {
|
||||||
|
return false; // Error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Write text to the specified socket. Returns false on error.
|
||||||
|
bool
|
||||||
|
XmlRpcSocket::nbWrite(int fd, std::string& s, int *bytesSoFar)
|
||||||
|
{
|
||||||
|
int nToWrite = int(s.length()) - *bytesSoFar;
|
||||||
|
char *sp = const_cast<char*>(s.c_str()) + *bytesSoFar;
|
||||||
|
bool wouldBlock = false;
|
||||||
|
|
||||||
|
while ( nToWrite > 0 && ! wouldBlock ) {
|
||||||
|
#if defined(_WINDOWS)
|
||||||
|
int n = send(fd, sp, nToWrite, 0);
|
||||||
|
#else
|
||||||
|
int n = write(fd, sp, nToWrite);
|
||||||
|
#endif
|
||||||
|
XmlRpcUtil::log(5, "XmlRpcSocket::nbWrite: send/write returned %d.", n);
|
||||||
|
|
||||||
|
if (n > 0) {
|
||||||
|
sp += n;
|
||||||
|
*bytesSoFar += n;
|
||||||
|
nToWrite -= n;
|
||||||
|
} else if (nonFatalError()) {
|
||||||
|
wouldBlock = true;
|
||||||
|
} else {
|
||||||
|
return false; // Error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Returns last errno
|
||||||
|
int
|
||||||
|
XmlRpcSocket::getError()
|
||||||
|
{
|
||||||
|
#if defined(_WINDOWS)
|
||||||
|
return WSAGetLastError();
|
||||||
|
#else
|
||||||
|
return errno;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Returns message corresponding to last errno
|
||||||
|
std::string
|
||||||
|
XmlRpcSocket::getErrorMsg()
|
||||||
|
{
|
||||||
|
return getErrorMsg(getError());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns message corresponding to errno... well, it should anyway
|
||||||
|
std::string
|
||||||
|
XmlRpcSocket::getErrorMsg(int error)
|
||||||
|
{
|
||||||
|
char err[60];
|
||||||
|
snprintf(err,sizeof(err),"error %d", error);
|
||||||
|
return std::string(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
35
src/XmlRpcSource.cpp
Normal file
35
src/XmlRpcSource.cpp
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
|
||||||
|
#include "xmlrpcpp/XmlRpcSource.h"
|
||||||
|
#include "xmlrpcpp/XmlRpcSocket.h"
|
||||||
|
#include "xmlrpcpp/XmlRpcUtil.h"
|
||||||
|
|
||||||
|
namespace XmlRpc {
|
||||||
|
|
||||||
|
|
||||||
|
XmlRpcSource::XmlRpcSource(int fd /*= -1*/, bool deleteOnClose /*= false*/)
|
||||||
|
: _fd(fd), _deleteOnClose(deleteOnClose), _keepOpen(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
XmlRpcSource::~XmlRpcSource()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
XmlRpcSource::close()
|
||||||
|
{
|
||||||
|
if (_fd != -1) {
|
||||||
|
XmlRpcUtil::log(2,"XmlRpcSource::close: closing socket %d.", _fd);
|
||||||
|
XmlRpcSocket::close(_fd);
|
||||||
|
XmlRpcUtil::log(2,"XmlRpcSource::close: done closing socket %d.", _fd);
|
||||||
|
_fd = -1;
|
||||||
|
}
|
||||||
|
if (_deleteOnClose) {
|
||||||
|
XmlRpcUtil::log(2,"XmlRpcSource::close: deleting this");
|
||||||
|
_deleteOnClose = false;
|
||||||
|
delete this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace XmlRpc
|
||||||
250
src/XmlRpcUtil.cpp
Normal file
250
src/XmlRpcUtil.cpp
Normal file
|
|
@ -0,0 +1,250 @@
|
||||||
|
|
||||||
|
#include "xmlrpcpp/XmlRpcUtil.h"
|
||||||
|
|
||||||
|
#ifndef MAKEDEPEND
|
||||||
|
# include <ctype.h>
|
||||||
|
# include <iostream>
|
||||||
|
# include <stdarg.h>
|
||||||
|
# include <stdio.h>
|
||||||
|
# include <string.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "xmlrpcpp/XmlRpc.h"
|
||||||
|
|
||||||
|
using namespace XmlRpc;
|
||||||
|
|
||||||
|
|
||||||
|
//#define USE_WINDOWS_DEBUG // To make the error and log messages go to VC++ debug output
|
||||||
|
#ifdef USE_WINDOWS_DEBUG
|
||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
#include <windows.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Version id
|
||||||
|
const char XmlRpc::XMLRPC_VERSION[] = "XMLRPC++ 0.7";
|
||||||
|
|
||||||
|
// Default log verbosity: 0 for no messages through 5 (writes everything)
|
||||||
|
int XmlRpcLogHandler::_verbosity = 0;
|
||||||
|
|
||||||
|
// Default log handler
|
||||||
|
static class DefaultLogHandler : public XmlRpcLogHandler {
|
||||||
|
public:
|
||||||
|
|
||||||
|
void log(int level, const char* msg) {
|
||||||
|
#ifdef USE_WINDOWS_DEBUG
|
||||||
|
if (level <= _verbosity) { OutputDebugString(msg); OutputDebugString("\n"); }
|
||||||
|
#else
|
||||||
|
if (level <= _verbosity) std::cout << msg << std::endl;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
} defaultLogHandler;
|
||||||
|
|
||||||
|
// Message log singleton
|
||||||
|
XmlRpcLogHandler* XmlRpcLogHandler::_logHandler = &defaultLogHandler;
|
||||||
|
|
||||||
|
|
||||||
|
// Default error handler
|
||||||
|
static class DefaultErrorHandler : public XmlRpcErrorHandler {
|
||||||
|
public:
|
||||||
|
|
||||||
|
void error(const char* msg) {
|
||||||
|
#ifdef USE_WINDOWS_DEBUG
|
||||||
|
OutputDebugString(msg); OutputDebugString("\n");
|
||||||
|
#else
|
||||||
|
std::cerr << msg << std::endl;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
} defaultErrorHandler;
|
||||||
|
|
||||||
|
|
||||||
|
// Error handler singleton
|
||||||
|
XmlRpcErrorHandler* XmlRpcErrorHandler::_errorHandler = &defaultErrorHandler;
|
||||||
|
|
||||||
|
|
||||||
|
// Easy API for log verbosity
|
||||||
|
int XmlRpc::getVerbosity() { return XmlRpcLogHandler::getVerbosity(); }
|
||||||
|
void XmlRpc::setVerbosity(int level) { XmlRpcLogHandler::setVerbosity(level); }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void XmlRpcUtil::log(int level, const char* fmt, ...)
|
||||||
|
{
|
||||||
|
if (level <= XmlRpcLogHandler::getVerbosity())
|
||||||
|
{
|
||||||
|
va_list va;
|
||||||
|
char buf[1024];
|
||||||
|
va_start( va, fmt);
|
||||||
|
vsnprintf(buf,sizeof(buf)-1,fmt,va);
|
||||||
|
buf[sizeof(buf)-1] = 0;
|
||||||
|
XmlRpcLogHandler::getLogHandler()->log(level, buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void XmlRpcUtil::error(const char* fmt, ...)
|
||||||
|
{
|
||||||
|
va_list va;
|
||||||
|
va_start(va, fmt);
|
||||||
|
char buf[1024];
|
||||||
|
vsnprintf(buf,sizeof(buf)-1,fmt,va);
|
||||||
|
buf[sizeof(buf)-1] = 0;
|
||||||
|
XmlRpcErrorHandler::getErrorHandler()->error(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Returns contents between <tag> and </tag>, updates offset to char after </tag>
|
||||||
|
std::string
|
||||||
|
XmlRpcUtil::parseTag(const char* tag, std::string const& xml, int* offset)
|
||||||
|
{
|
||||||
|
if (*offset >= int(xml.length())) return std::string();
|
||||||
|
size_t istart = xml.find(tag, *offset);
|
||||||
|
if (istart == std::string::npos) return std::string();
|
||||||
|
istart += strlen(tag);
|
||||||
|
std::string etag = "</";
|
||||||
|
etag += tag + 1;
|
||||||
|
size_t iend = xml.find(etag, istart);
|
||||||
|
if (iend == std::string::npos) return std::string();
|
||||||
|
|
||||||
|
*offset = int(iend + etag.length());
|
||||||
|
return xml.substr(istart, iend-istart);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Returns true if the tag is found and updates offset to the char after the tag
|
||||||
|
bool
|
||||||
|
XmlRpcUtil::findTag(const char* tag, std::string const& xml, int* offset)
|
||||||
|
{
|
||||||
|
if (*offset >= int(xml.length())) return false;
|
||||||
|
size_t istart = xml.find(tag, *offset);
|
||||||
|
if (istart == std::string::npos)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
*offset = int(istart + strlen(tag));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Returns true if the tag is found at the specified offset (modulo any whitespace)
|
||||||
|
// and updates offset to the char after the tag
|
||||||
|
bool
|
||||||
|
XmlRpcUtil::nextTagIs(const char* tag, std::string const& xml, int* offset)
|
||||||
|
{
|
||||||
|
if (*offset >= int(xml.length())) return false;
|
||||||
|
const char* cp = xml.c_str() + *offset;
|
||||||
|
int nc = 0;
|
||||||
|
while (*cp && isspace(*cp)) {
|
||||||
|
++cp;
|
||||||
|
++nc;
|
||||||
|
}
|
||||||
|
|
||||||
|
int len = int(strlen(tag));
|
||||||
|
if (*cp && (strncmp(cp, tag, len) == 0)) {
|
||||||
|
*offset += nc + len;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the next tag and updates offset to the char after the tag, or empty string
|
||||||
|
// if the next non-whitespace character is not '<'
|
||||||
|
std::string
|
||||||
|
XmlRpcUtil::getNextTag(std::string const& xml, int* offset)
|
||||||
|
{
|
||||||
|
if (*offset >= int(xml.length())) return std::string();
|
||||||
|
|
||||||
|
size_t pos = *offset;
|
||||||
|
const char* cp = xml.c_str() + pos;
|
||||||
|
while (*cp && isspace(*cp)) {
|
||||||
|
++cp;
|
||||||
|
++pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*cp != '<') return std::string();
|
||||||
|
|
||||||
|
std::string s;
|
||||||
|
do {
|
||||||
|
s += *cp;
|
||||||
|
++pos;
|
||||||
|
} while (*cp++ != '>' && *cp != 0);
|
||||||
|
|
||||||
|
*offset = int(pos);
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// xml encodings (xml-encoded entities are preceded with '&')
|
||||||
|
static const char AMP = '&';
|
||||||
|
static const char rawEntity[] = { '<', '>', '&', '\'', '\"', 0 };
|
||||||
|
static const char* xmlEntity[] = { "lt;", "gt;", "amp;", "apos;", "quot;", 0 };
|
||||||
|
static const int xmlEntLen[] = { 3, 3, 4, 5, 5 };
|
||||||
|
|
||||||
|
|
||||||
|
// Replace xml-encoded entities with the raw text equivalents.
|
||||||
|
|
||||||
|
std::string
|
||||||
|
XmlRpcUtil::xmlDecode(const std::string& encoded)
|
||||||
|
{
|
||||||
|
std::string::size_type iAmp = encoded.find(AMP);
|
||||||
|
if (iAmp == std::string::npos)
|
||||||
|
return encoded;
|
||||||
|
|
||||||
|
std::string decoded(encoded, 0, iAmp);
|
||||||
|
std::string::size_type iSize = encoded.size();
|
||||||
|
decoded.reserve(iSize);
|
||||||
|
|
||||||
|
const char* ens = encoded.c_str();
|
||||||
|
while (iAmp != iSize) {
|
||||||
|
if (encoded[iAmp] == AMP && iAmp+1 < iSize) {
|
||||||
|
int iEntity;
|
||||||
|
for (iEntity=0; xmlEntity[iEntity] != 0; ++iEntity)
|
||||||
|
//if (encoded.compare(iAmp+1, xmlEntLen[iEntity], xmlEntity[iEntity]) == 0)
|
||||||
|
if (strncmp(ens+iAmp+1, xmlEntity[iEntity], xmlEntLen[iEntity]) == 0)
|
||||||
|
{
|
||||||
|
decoded += rawEntity[iEntity];
|
||||||
|
iAmp += xmlEntLen[iEntity]+1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (xmlEntity[iEntity] == 0) // unrecognized sequence
|
||||||
|
decoded += encoded[iAmp++];
|
||||||
|
|
||||||
|
} else {
|
||||||
|
decoded += encoded[iAmp++];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return decoded;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Replace raw text with xml-encoded entities.
|
||||||
|
|
||||||
|
std::string
|
||||||
|
XmlRpcUtil::xmlEncode(const std::string& raw)
|
||||||
|
{
|
||||||
|
std::string::size_type iRep = raw.find_first_of(rawEntity);
|
||||||
|
if (iRep == std::string::npos)
|
||||||
|
return raw;
|
||||||
|
|
||||||
|
std::string encoded(raw, 0, iRep);
|
||||||
|
std::string::size_type iSize = raw.size();
|
||||||
|
|
||||||
|
while (iRep != iSize) {
|
||||||
|
int iEntity;
|
||||||
|
for (iEntity=0; rawEntity[iEntity] != 0; ++iEntity)
|
||||||
|
if (raw[iRep] == rawEntity[iEntity])
|
||||||
|
{
|
||||||
|
encoded += AMP;
|
||||||
|
encoded += xmlEntity[iEntity];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (rawEntity[iEntity] == 0)
|
||||||
|
encoded += raw[iRep];
|
||||||
|
++iRep;
|
||||||
|
}
|
||||||
|
return encoded;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
610
src/XmlRpcValue.cpp
Normal file
610
src/XmlRpcValue.cpp
Normal file
|
|
@ -0,0 +1,610 @@
|
||||||
|
|
||||||
|
#include "xmlrpcpp/XmlRpcValue.h"
|
||||||
|
#include "xmlrpcpp/XmlRpcException.h"
|
||||||
|
#include "xmlrpcpp/XmlRpcUtil.h"
|
||||||
|
#include "xmlrpcpp/base64.h"
|
||||||
|
|
||||||
|
#ifndef MAKEDEPEND
|
||||||
|
# include <iostream>
|
||||||
|
# include <ostream>
|
||||||
|
# include <stdlib.h>
|
||||||
|
# include <stdio.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace XmlRpc {
|
||||||
|
|
||||||
|
|
||||||
|
static const char VALUE_TAG[] = "<value>";
|
||||||
|
static const char VALUE_ETAG[] = "</value>";
|
||||||
|
|
||||||
|
static const char BOOLEAN_TAG[] = "<boolean>";
|
||||||
|
static const char BOOLEAN_ETAG[] = "</boolean>";
|
||||||
|
static const char DOUBLE_TAG[] = "<double>";
|
||||||
|
static const char DOUBLE_ETAG[] = "</double>";
|
||||||
|
static const char INT_TAG[] = "<int>";
|
||||||
|
static const char I4_TAG[] = "<i4>";
|
||||||
|
static const char I4_ETAG[] = "</i4>";
|
||||||
|
static const char STRING_TAG[] = "<string>";
|
||||||
|
static const char DATETIME_TAG[] = "<dateTime.iso8601>";
|
||||||
|
static const char DATETIME_ETAG[] = "</dateTime.iso8601>";
|
||||||
|
static const char BASE64_TAG[] = "<base64>";
|
||||||
|
static const char BASE64_ETAG[] = "</base64>";
|
||||||
|
|
||||||
|
static const char ARRAY_TAG[] = "<array>";
|
||||||
|
static const char DATA_TAG[] = "<data>";
|
||||||
|
static const char DATA_ETAG[] = "</data>";
|
||||||
|
static const char ARRAY_ETAG[] = "</array>";
|
||||||
|
|
||||||
|
static const char STRUCT_TAG[] = "<struct>";
|
||||||
|
static const char MEMBER_TAG[] = "<member>";
|
||||||
|
static const char NAME_TAG[] = "<name>";
|
||||||
|
static const char NAME_ETAG[] = "</name>";
|
||||||
|
static const char MEMBER_ETAG[] = "</member>";
|
||||||
|
static const char STRUCT_ETAG[] = "</struct>";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Format strings
|
||||||
|
std::string XmlRpcValue::_doubleFormat("%f");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Clean up
|
||||||
|
void XmlRpcValue::invalidate()
|
||||||
|
{
|
||||||
|
switch (_type) {
|
||||||
|
case TypeString: delete _value.asString; break;
|
||||||
|
case TypeDateTime: delete _value.asTime; break;
|
||||||
|
case TypeBase64: delete _value.asBinary; break;
|
||||||
|
case TypeArray: delete _value.asArray; break;
|
||||||
|
case TypeStruct: delete _value.asStruct; break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
_type = TypeInvalid;
|
||||||
|
_value.asBinary = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Type checking
|
||||||
|
void XmlRpcValue::assertTypeOrInvalid(Type t)
|
||||||
|
{
|
||||||
|
if (_type == TypeInvalid)
|
||||||
|
{
|
||||||
|
_type = t;
|
||||||
|
switch (_type) { // Ensure there is a valid value for the type
|
||||||
|
case TypeString: _value.asString = new std::string(); break;
|
||||||
|
case TypeDateTime: _value.asTime = new struct tm(); break;
|
||||||
|
case TypeBase64: _value.asBinary = new BinaryData(); break;
|
||||||
|
case TypeArray: _value.asArray = new ValueArray(); break;
|
||||||
|
case TypeStruct: _value.asStruct = new ValueStruct(); break;
|
||||||
|
default: _value.asBinary = 0; break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (_type != t)
|
||||||
|
throw XmlRpcException("type error");
|
||||||
|
}
|
||||||
|
|
||||||
|
void XmlRpcValue::assertArray(int size) const
|
||||||
|
{
|
||||||
|
if (_type != TypeArray)
|
||||||
|
throw XmlRpcException("type error: expected an array");
|
||||||
|
else if (int(_value.asArray->size()) < size)
|
||||||
|
throw XmlRpcException("range error: array index too large");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void XmlRpcValue::assertArray(int size)
|
||||||
|
{
|
||||||
|
if (_type == TypeInvalid) {
|
||||||
|
_type = TypeArray;
|
||||||
|
_value.asArray = new ValueArray(size);
|
||||||
|
} else if (_type == TypeArray) {
|
||||||
|
if (int(_value.asArray->size()) < size)
|
||||||
|
_value.asArray->resize(size);
|
||||||
|
} else
|
||||||
|
throw XmlRpcException("type error: expected an array");
|
||||||
|
}
|
||||||
|
|
||||||
|
void XmlRpcValue::assertStruct()
|
||||||
|
{
|
||||||
|
if (_type == TypeInvalid) {
|
||||||
|
_type = TypeStruct;
|
||||||
|
_value.asStruct = new ValueStruct();
|
||||||
|
} else if (_type != TypeStruct)
|
||||||
|
throw XmlRpcException("type error: expected a struct");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Operators
|
||||||
|
XmlRpcValue& XmlRpcValue::operator=(XmlRpcValue const& rhs)
|
||||||
|
{
|
||||||
|
if (this != &rhs)
|
||||||
|
{
|
||||||
|
invalidate();
|
||||||
|
_type = rhs._type;
|
||||||
|
switch (_type) {
|
||||||
|
case TypeBoolean: _value.asBool = rhs._value.asBool; break;
|
||||||
|
case TypeInt: _value.asInt = rhs._value.asInt; break;
|
||||||
|
case TypeDouble: _value.asDouble = rhs._value.asDouble; break;
|
||||||
|
case TypeDateTime: _value.asTime = new struct tm(*rhs._value.asTime); break;
|
||||||
|
case TypeString: _value.asString = new std::string(*rhs._value.asString); break;
|
||||||
|
case TypeBase64: _value.asBinary = new BinaryData(*rhs._value.asBinary); break;
|
||||||
|
case TypeArray: _value.asArray = new ValueArray(*rhs._value.asArray); break;
|
||||||
|
case TypeStruct: _value.asStruct = new ValueStruct(*rhs._value.asStruct); break;
|
||||||
|
default: _value.asBinary = 0; break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Predicate for tm equality
|
||||||
|
static bool tmEq(struct tm const& t1, struct tm const& t2) {
|
||||||
|
return t1.tm_sec == t2.tm_sec && t1.tm_min == t2.tm_min &&
|
||||||
|
t1.tm_hour == t2.tm_hour && t1.tm_mday == t2.tm_mday &&
|
||||||
|
t1.tm_mon == t2.tm_mon && t1.tm_year == t2.tm_year;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool XmlRpcValue::operator==(XmlRpcValue const& other) const
|
||||||
|
{
|
||||||
|
if (_type != other._type)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
switch (_type) {
|
||||||
|
case TypeBoolean: return ( !_value.asBool && !other._value.asBool) ||
|
||||||
|
( _value.asBool && other._value.asBool);
|
||||||
|
case TypeInt: return _value.asInt == other._value.asInt;
|
||||||
|
case TypeDouble: return _value.asDouble == other._value.asDouble;
|
||||||
|
case TypeDateTime: return tmEq(*_value.asTime, *other._value.asTime);
|
||||||
|
case TypeString: return *_value.asString == *other._value.asString;
|
||||||
|
case TypeBase64: return *_value.asBinary == *other._value.asBinary;
|
||||||
|
case TypeArray: return *_value.asArray == *other._value.asArray;
|
||||||
|
|
||||||
|
// The map<>::operator== requires the definition of value< for kcc
|
||||||
|
case TypeStruct: //return *_value.asStruct == *other._value.asStruct;
|
||||||
|
{
|
||||||
|
if (_value.asStruct->size() != other._value.asStruct->size())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
ValueStruct::const_iterator it1=_value.asStruct->begin();
|
||||||
|
ValueStruct::const_iterator it2=other._value.asStruct->begin();
|
||||||
|
while (it1 != _value.asStruct->end()) {
|
||||||
|
const XmlRpcValue& v1 = it1->second;
|
||||||
|
const XmlRpcValue& v2 = it2->second;
|
||||||
|
if ( ! (v1 == v2))
|
||||||
|
return false;
|
||||||
|
it1++;
|
||||||
|
it2++;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
return true; // Both invalid values ...
|
||||||
|
}
|
||||||
|
|
||||||
|
bool XmlRpcValue::operator!=(XmlRpcValue const& other) const
|
||||||
|
{
|
||||||
|
return !(*this == other);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Works for strings, binary data, arrays, and structs.
|
||||||
|
int XmlRpcValue::size() const
|
||||||
|
{
|
||||||
|
switch (_type) {
|
||||||
|
case TypeString: return int(_value.asString->size());
|
||||||
|
case TypeBase64: return int(_value.asBinary->size());
|
||||||
|
case TypeArray: return int(_value.asArray->size());
|
||||||
|
case TypeStruct: return int(_value.asStruct->size());
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw XmlRpcException("type error");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Checks for existence of struct member
|
||||||
|
bool XmlRpcValue::hasMember(const std::string& name) const
|
||||||
|
{
|
||||||
|
return _type == TypeStruct && _value.asStruct->find(name) != _value.asStruct->end();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the value from xml. The chars at *offset into valueXml
|
||||||
|
// should be the start of a <value> tag. Destroys any existing value.
|
||||||
|
bool XmlRpcValue::fromXml(std::string const& valueXml, int* offset)
|
||||||
|
{
|
||||||
|
int savedOffset = *offset;
|
||||||
|
|
||||||
|
invalidate();
|
||||||
|
if ( ! XmlRpcUtil::nextTagIs(VALUE_TAG, valueXml, offset))
|
||||||
|
return false; // Not a value, offset not updated
|
||||||
|
|
||||||
|
int afterValueOffset = *offset;
|
||||||
|
std::string typeTag = XmlRpcUtil::getNextTag(valueXml, offset);
|
||||||
|
bool result = false;
|
||||||
|
if (typeTag == BOOLEAN_TAG)
|
||||||
|
result = boolFromXml(valueXml, offset);
|
||||||
|
else if (typeTag == I4_TAG || typeTag == INT_TAG)
|
||||||
|
result = intFromXml(valueXml, offset);
|
||||||
|
else if (typeTag == DOUBLE_TAG)
|
||||||
|
result = doubleFromXml(valueXml, offset);
|
||||||
|
else if (typeTag.empty() || typeTag == STRING_TAG)
|
||||||
|
result = stringFromXml(valueXml, offset);
|
||||||
|
else if (typeTag == DATETIME_TAG)
|
||||||
|
result = timeFromXml(valueXml, offset);
|
||||||
|
else if (typeTag == BASE64_TAG)
|
||||||
|
result = binaryFromXml(valueXml, offset);
|
||||||
|
else if (typeTag == ARRAY_TAG)
|
||||||
|
result = arrayFromXml(valueXml, offset);
|
||||||
|
else if (typeTag == STRUCT_TAG)
|
||||||
|
result = structFromXml(valueXml, offset);
|
||||||
|
// Watch for empty/blank strings with no <string>tag
|
||||||
|
else if (typeTag == VALUE_ETAG)
|
||||||
|
{
|
||||||
|
*offset = afterValueOffset; // back up & try again
|
||||||
|
result = stringFromXml(valueXml, offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result) // Skip over the </value> tag
|
||||||
|
XmlRpcUtil::findTag(VALUE_ETAG, valueXml, offset);
|
||||||
|
else // Unrecognized tag after <value>
|
||||||
|
*offset = savedOffset;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Encode the Value in xml
|
||||||
|
std::string XmlRpcValue::toXml() const
|
||||||
|
{
|
||||||
|
switch (_type) {
|
||||||
|
case TypeBoolean: return boolToXml();
|
||||||
|
case TypeInt: return intToXml();
|
||||||
|
case TypeDouble: return doubleToXml();
|
||||||
|
case TypeString: return stringToXml();
|
||||||
|
case TypeDateTime: return timeToXml();
|
||||||
|
case TypeBase64: return binaryToXml();
|
||||||
|
case TypeArray: return arrayToXml();
|
||||||
|
case TypeStruct: return structToXml();
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
return std::string(); // Invalid value
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Boolean
|
||||||
|
bool XmlRpcValue::boolFromXml(std::string const& valueXml, int* offset)
|
||||||
|
{
|
||||||
|
const char* valueStart = valueXml.c_str() + *offset;
|
||||||
|
char* valueEnd;
|
||||||
|
long ivalue = strtol(valueStart, &valueEnd, 10);
|
||||||
|
if (valueEnd == valueStart || (ivalue != 0 && ivalue != 1))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
_type = TypeBoolean;
|
||||||
|
_value.asBool = (ivalue == 1);
|
||||||
|
*offset += int(valueEnd - valueStart);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string XmlRpcValue::boolToXml() const
|
||||||
|
{
|
||||||
|
std::string xml = VALUE_TAG;
|
||||||
|
xml += BOOLEAN_TAG;
|
||||||
|
xml += (_value.asBool ? "1" : "0");
|
||||||
|
xml += BOOLEAN_ETAG;
|
||||||
|
xml += VALUE_ETAG;
|
||||||
|
return xml;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Int
|
||||||
|
bool XmlRpcValue::intFromXml(std::string const& valueXml, int* offset)
|
||||||
|
{
|
||||||
|
const char* valueStart = valueXml.c_str() + *offset;
|
||||||
|
char* valueEnd;
|
||||||
|
long ivalue = strtol(valueStart, &valueEnd, 10);
|
||||||
|
if (valueEnd == valueStart)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
_type = TypeInt;
|
||||||
|
_value.asInt = int(ivalue);
|
||||||
|
*offset += int(valueEnd - valueStart);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string XmlRpcValue::intToXml() const
|
||||||
|
{
|
||||||
|
char buf[256];
|
||||||
|
snprintf(buf, sizeof(buf)-1, "%d", _value.asInt);
|
||||||
|
buf[sizeof(buf)-1] = 0;
|
||||||
|
std::string xml = VALUE_TAG;
|
||||||
|
xml += I4_TAG;
|
||||||
|
xml += buf;
|
||||||
|
xml += I4_ETAG;
|
||||||
|
xml += VALUE_ETAG;
|
||||||
|
return xml;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Double
|
||||||
|
bool XmlRpcValue::doubleFromXml(std::string const& valueXml, int* offset)
|
||||||
|
{
|
||||||
|
const char* valueStart = valueXml.c_str() + *offset;
|
||||||
|
char* valueEnd;
|
||||||
|
double dvalue = strtod(valueStart, &valueEnd);
|
||||||
|
if (valueEnd == valueStart)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
_type = TypeDouble;
|
||||||
|
_value.asDouble = dvalue;
|
||||||
|
*offset += int(valueEnd - valueStart);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string XmlRpcValue::doubleToXml() const
|
||||||
|
{
|
||||||
|
char buf[256];
|
||||||
|
snprintf(buf, sizeof(buf)-1, getDoubleFormat().c_str(), _value.asDouble);
|
||||||
|
buf[sizeof(buf)-1] = 0;
|
||||||
|
|
||||||
|
std::string xml = VALUE_TAG;
|
||||||
|
xml += DOUBLE_TAG;
|
||||||
|
xml += buf;
|
||||||
|
xml += DOUBLE_ETAG;
|
||||||
|
xml += VALUE_ETAG;
|
||||||
|
return xml;
|
||||||
|
}
|
||||||
|
|
||||||
|
// String
|
||||||
|
bool XmlRpcValue::stringFromXml(std::string const& valueXml, int* offset)
|
||||||
|
{
|
||||||
|
size_t valueEnd = valueXml.find('<', *offset);
|
||||||
|
if (valueEnd == std::string::npos)
|
||||||
|
return false; // No end tag;
|
||||||
|
|
||||||
|
_type = TypeString;
|
||||||
|
_value.asString = new std::string(XmlRpcUtil::xmlDecode(valueXml.substr(*offset, valueEnd-*offset)));
|
||||||
|
*offset += int(_value.asString->length());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string XmlRpcValue::stringToXml() const
|
||||||
|
{
|
||||||
|
std::string xml = VALUE_TAG;
|
||||||
|
//xml += STRING_TAG; optional
|
||||||
|
xml += XmlRpcUtil::xmlEncode(*_value.asString);
|
||||||
|
//xml += STRING_ETAG;
|
||||||
|
xml += VALUE_ETAG;
|
||||||
|
return xml;
|
||||||
|
}
|
||||||
|
|
||||||
|
// DateTime (stored as a struct tm)
|
||||||
|
bool XmlRpcValue::timeFromXml(std::string const& valueXml, int* offset)
|
||||||
|
{
|
||||||
|
size_t valueEnd = valueXml.find('<', *offset);
|
||||||
|
if (valueEnd == std::string::npos)
|
||||||
|
return false; // No end tag;
|
||||||
|
|
||||||
|
std::string stime = valueXml.substr(*offset, valueEnd-*offset);
|
||||||
|
|
||||||
|
struct tm t;
|
||||||
|
if (sscanf(stime.c_str(),"%4d%2d%2dT%2d:%2d:%2d",&t.tm_year,&t.tm_mon,&t.tm_mday,&t.tm_hour,&t.tm_min,&t.tm_sec) != 6)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
t.tm_isdst = -1;
|
||||||
|
_type = TypeDateTime;
|
||||||
|
_value.asTime = new struct tm(t);
|
||||||
|
*offset += int(stime.length());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string XmlRpcValue::timeToXml() const
|
||||||
|
{
|
||||||
|
struct tm* t = _value.asTime;
|
||||||
|
char buf[20];
|
||||||
|
snprintf(buf, sizeof(buf)-1, "%4d%02d%02dT%02d:%02d:%02d",
|
||||||
|
t->tm_year,t->tm_mon,t->tm_mday,t->tm_hour,t->tm_min,t->tm_sec);
|
||||||
|
buf[sizeof(buf)-1] = 0;
|
||||||
|
|
||||||
|
std::string xml = VALUE_TAG;
|
||||||
|
xml += DATETIME_TAG;
|
||||||
|
xml += buf;
|
||||||
|
xml += DATETIME_ETAG;
|
||||||
|
xml += VALUE_ETAG;
|
||||||
|
return xml;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Base64
|
||||||
|
bool XmlRpcValue::binaryFromXml(std::string const& valueXml, int* offset)
|
||||||
|
{
|
||||||
|
size_t valueEnd = valueXml.find('<', *offset);
|
||||||
|
if (valueEnd == std::string::npos)
|
||||||
|
return false; // No end tag;
|
||||||
|
|
||||||
|
_type = TypeBase64;
|
||||||
|
std::string asString = valueXml.substr(*offset, valueEnd-*offset);
|
||||||
|
_value.asBinary = new BinaryData();
|
||||||
|
// check whether base64 encodings can contain chars xml encodes...
|
||||||
|
|
||||||
|
// convert from base64 to binary
|
||||||
|
int iostatus = 0;
|
||||||
|
base64<char> decoder;
|
||||||
|
std::back_insert_iterator<BinaryData> ins = std::back_inserter(*(_value.asBinary));
|
||||||
|
decoder.get(asString.begin(), asString.end(), ins, iostatus);
|
||||||
|
|
||||||
|
*offset += int(asString.length());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::string XmlRpcValue::binaryToXml() const
|
||||||
|
{
|
||||||
|
// convert to base64
|
||||||
|
std::vector<char> base64data;
|
||||||
|
int iostatus = 0;
|
||||||
|
base64<char> encoder;
|
||||||
|
std::back_insert_iterator<std::vector<char> > ins = std::back_inserter(base64data);
|
||||||
|
encoder.put(_value.asBinary->begin(), _value.asBinary->end(), ins, iostatus, base64<>::crlf());
|
||||||
|
|
||||||
|
// Wrap with xml
|
||||||
|
std::string xml = VALUE_TAG;
|
||||||
|
xml += BASE64_TAG;
|
||||||
|
xml.append(base64data.begin(), base64data.end());
|
||||||
|
xml += BASE64_ETAG;
|
||||||
|
xml += VALUE_ETAG;
|
||||||
|
return xml;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Array
|
||||||
|
bool XmlRpcValue::arrayFromXml(std::string const& valueXml, int* offset)
|
||||||
|
{
|
||||||
|
if ( ! XmlRpcUtil::nextTagIs(DATA_TAG, valueXml, offset))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
_type = TypeArray;
|
||||||
|
_value.asArray = new ValueArray;
|
||||||
|
XmlRpcValue v;
|
||||||
|
while (v.fromXml(valueXml, offset))
|
||||||
|
_value.asArray->push_back(v); // copy...
|
||||||
|
|
||||||
|
// Skip the trailing </data>
|
||||||
|
(void) XmlRpcUtil::nextTagIs(DATA_ETAG, valueXml, offset);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// In general, its preferable to generate the xml of each element of the
|
||||||
|
// array as it is needed rather than glomming up one big string.
|
||||||
|
std::string XmlRpcValue::arrayToXml() const
|
||||||
|
{
|
||||||
|
std::string xml = VALUE_TAG;
|
||||||
|
xml += ARRAY_TAG;
|
||||||
|
xml += DATA_TAG;
|
||||||
|
|
||||||
|
int s = int(_value.asArray->size());
|
||||||
|
for (int i=0; i<s; ++i)
|
||||||
|
xml += _value.asArray->at(i).toXml();
|
||||||
|
|
||||||
|
xml += DATA_ETAG;
|
||||||
|
xml += ARRAY_ETAG;
|
||||||
|
xml += VALUE_ETAG;
|
||||||
|
return xml;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Struct
|
||||||
|
bool XmlRpcValue::structFromXml(std::string const& valueXml, int* offset)
|
||||||
|
{
|
||||||
|
_type = TypeStruct;
|
||||||
|
_value.asStruct = new ValueStruct;
|
||||||
|
|
||||||
|
while (XmlRpcUtil::nextTagIs(MEMBER_TAG, valueXml, offset)) {
|
||||||
|
// name
|
||||||
|
const std::string name = XmlRpcUtil::parseTag(NAME_TAG, valueXml, offset);
|
||||||
|
// value
|
||||||
|
XmlRpcValue val(valueXml, offset);
|
||||||
|
if ( ! val.valid()) {
|
||||||
|
invalidate();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const std::pair<const std::string, XmlRpcValue> p(name, val);
|
||||||
|
_value.asStruct->insert(p);
|
||||||
|
|
||||||
|
(void) XmlRpcUtil::nextTagIs(MEMBER_ETAG, valueXml, offset);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// In general, its preferable to generate the xml of each element
|
||||||
|
// as it is needed rather than glomming up one big string.
|
||||||
|
std::string XmlRpcValue::structToXml() const
|
||||||
|
{
|
||||||
|
std::string xml = VALUE_TAG;
|
||||||
|
xml += STRUCT_TAG;
|
||||||
|
|
||||||
|
ValueStruct::const_iterator it;
|
||||||
|
for (it=_value.asStruct->begin(); it!=_value.asStruct->end(); ++it) {
|
||||||
|
xml += MEMBER_TAG;
|
||||||
|
xml += NAME_TAG;
|
||||||
|
xml += XmlRpcUtil::xmlEncode(it->first);
|
||||||
|
xml += NAME_ETAG;
|
||||||
|
xml += it->second.toXml();
|
||||||
|
xml += MEMBER_ETAG;
|
||||||
|
}
|
||||||
|
|
||||||
|
xml += STRUCT_ETAG;
|
||||||
|
xml += VALUE_ETAG;
|
||||||
|
return xml;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Write the value without xml encoding it
|
||||||
|
std::ostream& XmlRpcValue::write(std::ostream& os) const {
|
||||||
|
switch (_type) {
|
||||||
|
default: break;
|
||||||
|
case TypeBoolean: os << _value.asBool; break;
|
||||||
|
case TypeInt: os << _value.asInt; break;
|
||||||
|
case TypeDouble: os << _value.asDouble; break;
|
||||||
|
case TypeString: os << *_value.asString; break;
|
||||||
|
case TypeDateTime:
|
||||||
|
{
|
||||||
|
struct tm* t = _value.asTime;
|
||||||
|
char buf[20];
|
||||||
|
snprintf(buf, sizeof(buf)-1, "%4d%02d%02dT%02d:%02d:%02d",
|
||||||
|
t->tm_year,t->tm_mon,t->tm_mday,t->tm_hour,t->tm_min,t->tm_sec);
|
||||||
|
buf[sizeof(buf)-1] = 0;
|
||||||
|
os << buf;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TypeBase64:
|
||||||
|
{
|
||||||
|
int iostatus = 0;
|
||||||
|
std::ostreambuf_iterator<char> out(os);
|
||||||
|
base64<char> encoder;
|
||||||
|
encoder.put(_value.asBinary->begin(), _value.asBinary->end(), out, iostatus, base64<>::crlf());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TypeArray:
|
||||||
|
{
|
||||||
|
int s = int(_value.asArray->size());
|
||||||
|
os << '{';
|
||||||
|
for (int i=0; i<s; ++i)
|
||||||
|
{
|
||||||
|
if (i > 0) os << ',';
|
||||||
|
_value.asArray->at(i).write(os);
|
||||||
|
}
|
||||||
|
os << '}';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TypeStruct:
|
||||||
|
{
|
||||||
|
os << '[';
|
||||||
|
ValueStruct::const_iterator it;
|
||||||
|
for (it=_value.asStruct->begin(); it!=_value.asStruct->end(); ++it)
|
||||||
|
{
|
||||||
|
if (it!=_value.asStruct->begin()) os << ',';
|
||||||
|
os << it->first << ':';
|
||||||
|
it->second.write(os);
|
||||||
|
}
|
||||||
|
os << ']';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace XmlRpc
|
||||||
|
|
||||||
|
|
||||||
|
// ostream
|
||||||
|
std::ostream& operator<<(std::ostream& os, XmlRpc::XmlRpcValue& v)
|
||||||
|
{
|
||||||
|
// If you want to output in xml format:
|
||||||
|
//return os << v.toXml();
|
||||||
|
return v.write(os);
|
||||||
|
}
|
||||||
|
|
||||||
108
test/FileClient.cpp
Normal file
108
test/FileClient.cpp
Normal file
|
|
@ -0,0 +1,108 @@
|
||||||
|
// FileClient.cpp : A simple xmlrpc client. Usage: FileClient serverHost serverPort xmlfile
|
||||||
|
// Reads an xmlrpc request from the specified xmlfile and calls the method on the server.
|
||||||
|
//
|
||||||
|
// Link against xmlrpc lib and whatever socket libs your system needs (ws2_32.lib on windows)
|
||||||
|
|
||||||
|
#include "XmlRpc.h"
|
||||||
|
#include <iostream>
|
||||||
|
#include <fstream>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
using namespace XmlRpc;
|
||||||
|
|
||||||
|
std::string parseRequest(std::string const& xml, XmlRpcValue& params);
|
||||||
|
|
||||||
|
|
||||||
|
int main(int argc, char* argv[])
|
||||||
|
{
|
||||||
|
if (argc != 4) {
|
||||||
|
std::cerr << "Usage: FileClient serverHost serverPort requestXmlFile\n";
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
int port = atoi(argv[2]);
|
||||||
|
|
||||||
|
XmlRpc::setVerbosity(5);
|
||||||
|
XmlRpcClient c(argv[1], port);
|
||||||
|
|
||||||
|
//
|
||||||
|
std::ifstream infile(argv[3]);
|
||||||
|
if (infile.fail()) {
|
||||||
|
std::cerr << "Could not open file '" << argv[3] << "'.\n";
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Suck in the file. This is a one-liner in good compilers (which vc++ 6 is not)...
|
||||||
|
infile.seekg(0L, std::ios::end);
|
||||||
|
long nb = infile.tellg();
|
||||||
|
infile.clear();
|
||||||
|
infile.seekg(0L);
|
||||||
|
char* b = new char[nb+1];
|
||||||
|
infile.read(b, nb);
|
||||||
|
b[nb] = 0;
|
||||||
|
|
||||||
|
std::cout << "Read file.\n";
|
||||||
|
|
||||||
|
// Find the methodName and parse the params
|
||||||
|
std::string s(b);
|
||||||
|
XmlRpcValue params;
|
||||||
|
std::string name = parseRequest(s, params);
|
||||||
|
|
||||||
|
if (name.empty()) {
|
||||||
|
std::cerr << "Could not parse file\n";
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
XmlRpcValue result;
|
||||||
|
std::cout << "Calling " << name << std::endl;
|
||||||
|
if (c.execute(name.c_str(), params, result))
|
||||||
|
std::cout << result << "\n\n";
|
||||||
|
else
|
||||||
|
std::cout << "Error calling '" << name << "'\n\n";
|
||||||
|
std::cout << "Again? [y]: ";
|
||||||
|
std::string ans;
|
||||||
|
std::cin >> ans;
|
||||||
|
if (ans != "" && ans != "y") break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
std::string
|
||||||
|
parseRequest(std::string const& xml, XmlRpcValue& params)
|
||||||
|
{
|
||||||
|
const char METHODNAME_TAG[] = "<methodName>";
|
||||||
|
const char PARAMS_TAG[] = "<params>";
|
||||||
|
const char PARAMS_ETAG[] = "</params>";
|
||||||
|
const char PARAM_TAG[] = "<param>";
|
||||||
|
const char PARAM_ETAG[] = "</param>";
|
||||||
|
|
||||||
|
int offset = 0; // Number of chars parsed from the request
|
||||||
|
|
||||||
|
std::string methodName = XmlRpcUtil::parseTag(METHODNAME_TAG, xml, &offset);
|
||||||
|
XmlRpcUtil::log(3, "XmlRpcServerConnection::parseRequest: parsed methodName %s.", methodName.c_str());
|
||||||
|
|
||||||
|
if (! methodName.empty() && XmlRpcUtil::findTag(PARAMS_TAG, xml, &offset))
|
||||||
|
{
|
||||||
|
int nArgs = 0;
|
||||||
|
while (XmlRpcUtil::nextTagIs(PARAM_TAG, xml, &offset)) {
|
||||||
|
std::cout << "Parsing arg " << nArgs+1 << std::endl;
|
||||||
|
XmlRpcValue arg(xml, &offset);
|
||||||
|
if ( ! arg.valid()) {
|
||||||
|
std::cerr << "Invalid argument\n";
|
||||||
|
return std::string();
|
||||||
|
}
|
||||||
|
std::cout << "Adding arg " << nArgs+1 << " to params array." << std::endl;
|
||||||
|
params[nArgs++] = arg;
|
||||||
|
(void) XmlRpcUtil::nextTagIs(PARAM_ETAG, xml, &offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
XmlRpcUtil::log(3, "XmlRpcServerConnection::parseRequest: parsed %d params.", nArgs);
|
||||||
|
|
||||||
|
(void) XmlRpcUtil::nextTagIs(PARAMS_ETAG, xml, &offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
return methodName;
|
||||||
|
}
|
||||||
96
test/FileClient.dsp
Normal file
96
test/FileClient.dsp
Normal file
|
|
@ -0,0 +1,96 @@
|
||||||
|
# Microsoft Developer Studio Project File - Name="FileClient" - Package Owner=<4>
|
||||||
|
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||||
|
# ** DO NOT EDIT **
|
||||||
|
|
||||||
|
# TARGTYPE "Win32 (x86) Console Application" 0x0103
|
||||||
|
|
||||||
|
CFG=FileClient - Win32 Debug
|
||||||
|
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||||
|
!MESSAGE use the Export Makefile command and run
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE NMAKE /f "FileClient.mak".
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE You can specify a configuration when running NMAKE
|
||||||
|
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE NMAKE /f "FileClient.mak" CFG="FileClient - Win32 Debug"
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE Possible choices for configuration are:
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE "FileClient - Win32 Release" (based on "Win32 (x86) Console Application")
|
||||||
|
!MESSAGE "FileClient - Win32 Debug" (based on "Win32 (x86) Console Application")
|
||||||
|
!MESSAGE
|
||||||
|
|
||||||
|
# Begin Project
|
||||||
|
# PROP AllowPerConfigDependencies 0
|
||||||
|
# PROP Scc_ProjName ""
|
||||||
|
# PROP Scc_LocalPath ""
|
||||||
|
CPP=cl.exe
|
||||||
|
RSC=rc.exe
|
||||||
|
|
||||||
|
!IF "$(CFG)" == "FileClient - Win32 Release"
|
||||||
|
|
||||||
|
# PROP BASE Use_MFC 0
|
||||||
|
# PROP BASE Use_Debug_Libraries 0
|
||||||
|
# PROP BASE Output_Dir "Release"
|
||||||
|
# PROP BASE Intermediate_Dir "Release"
|
||||||
|
# PROP BASE Target_Dir ""
|
||||||
|
# PROP Use_MFC 0
|
||||||
|
# PROP Use_Debug_Libraries 0
|
||||||
|
# PROP Output_Dir "Release"
|
||||||
|
# PROP Intermediate_Dir "Release"
|
||||||
|
# PROP Ignore_Export_Lib 0
|
||||||
|
# PROP Target_Dir ""
|
||||||
|
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /c
|
||||||
|
# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\src" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /D "_WINDOWS" /FD /c
|
||||||
|
# SUBTRACT CPP /YX /Yc /Yu
|
||||||
|
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||||
|
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||||
|
BSC32=bscmake.exe
|
||||||
|
# ADD BASE BSC32 /nologo
|
||||||
|
# ADD BSC32 /nologo
|
||||||
|
LINK32=link.exe
|
||||||
|
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
|
||||||
|
# ADD LINK32 xmlrpc.lib Ws2_32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /libpath:"..\release"
|
||||||
|
|
||||||
|
!ELSEIF "$(CFG)" == "FileClient - Win32 Debug"
|
||||||
|
|
||||||
|
# PROP BASE Use_MFC 0
|
||||||
|
# PROP BASE Use_Debug_Libraries 1
|
||||||
|
# PROP BASE Output_Dir "Debug"
|
||||||
|
# PROP BASE Intermediate_Dir "Debug"
|
||||||
|
# PROP BASE Target_Dir ""
|
||||||
|
# PROP Use_MFC 0
|
||||||
|
# PROP Use_Debug_Libraries 1
|
||||||
|
# PROP Output_Dir "Debug"
|
||||||
|
# PROP Intermediate_Dir "Debug"
|
||||||
|
# PROP Ignore_Export_Lib 0
|
||||||
|
# PROP Target_Dir ""
|
||||||
|
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c
|
||||||
|
# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "..\src" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "_WINDOWS" /FD /GZ /c
|
||||||
|
# SUBTRACT CPP /YX /Yc /Yu
|
||||||
|
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||||
|
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||||
|
BSC32=bscmake.exe
|
||||||
|
# ADD BASE BSC32 /nologo
|
||||||
|
# ADD BSC32 /nologo
|
||||||
|
LINK32=link.exe
|
||||||
|
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
|
||||||
|
# ADD LINK32 xmlrpc.lib Ws2_32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\Debug"
|
||||||
|
|
||||||
|
!ENDIF
|
||||||
|
|
||||||
|
# Begin Target
|
||||||
|
|
||||||
|
# Name "FileClient - Win32 Release"
|
||||||
|
# Name "FileClient - Win32 Debug"
|
||||||
|
# Begin Group "Source Files"
|
||||||
|
|
||||||
|
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\FileClient.cpp
|
||||||
|
# End Source File
|
||||||
|
# End Group
|
||||||
|
# End Target
|
||||||
|
# End Project
|
||||||
164
test/FileClient.vcproj
Normal file
164
test/FileClient.vcproj
Normal file
|
|
@ -0,0 +1,164 @@
|
||||||
|
<?xml version="1.0" encoding = "Windows-1252"?>
|
||||||
|
<VisualStudioProject
|
||||||
|
ProjectType="Visual C++"
|
||||||
|
Version="7.00"
|
||||||
|
Name="FileClient"
|
||||||
|
ProjectGUID="{C3B49855-CD45-448E-991E-3E4C9B02F465}"
|
||||||
|
SccProjectName=""
|
||||||
|
SccLocalPath="">
|
||||||
|
<Platforms>
|
||||||
|
<Platform
|
||||||
|
Name="Win32"/>
|
||||||
|
</Platforms>
|
||||||
|
<Configurations>
|
||||||
|
<Configuration
|
||||||
|
Name="Release|Win32"
|
||||||
|
OutputDirectory=".\Release"
|
||||||
|
IntermediateDirectory=".\Release"
|
||||||
|
ConfigurationType="1"
|
||||||
|
UseOfMFC="0"
|
||||||
|
ATLMinimizesCRunTimeLibraryUsage="FALSE"
|
||||||
|
CharacterSet="2">
|
||||||
|
<Tool
|
||||||
|
Name="VCCLCompilerTool"
|
||||||
|
InlineFunctionExpansion="1"
|
||||||
|
AdditionalIncludeDirectories="..\src"
|
||||||
|
PreprocessorDefinitions="WIN32,NDEBUG,_CONSOLE,_WINDOWS"
|
||||||
|
StringPooling="TRUE"
|
||||||
|
RuntimeLibrary="2"
|
||||||
|
EnableFunctionLevelLinking="TRUE"
|
||||||
|
PrecompiledHeaderFile=".\Release/FileClient.pch"
|
||||||
|
AssemblerListingLocation=".\Release/"
|
||||||
|
ObjectFile=".\Release/"
|
||||||
|
ProgramDataBaseFileName=".\Release/"
|
||||||
|
WarningLevel="3"
|
||||||
|
SuppressStartupBanner="TRUE"
|
||||||
|
CompileAs="0"
|
||||||
|
AdditionalOptions="">
|
||||||
|
<IntelOptions
|
||||||
|
Optimization="2"
|
||||||
|
InlineFuncExpansion="1"
|
||||||
|
OmitFramePtrs="1"
|
||||||
|
StringPooling="1"
|
||||||
|
RuntimeLibrary="2"
|
||||||
|
BufferSecurityCheck="1"
|
||||||
|
FunctionLevelLinking="1"
|
||||||
|
AllOptions="/c /I "..\src" /nologo /W3 /O2 /Ob1 /Oy /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_WINDOWS" /D "_MBCS" /GF /FD /EHsc /MD /GS /Gy /Fp".\Release/FileClient.pch" /Fo".\Release/" /Fd".\Release/" /Gd"
|
||||||
|
MSOriginalAdditionalOptions=""/>
|
||||||
|
</Tool>
|
||||||
|
<Tool
|
||||||
|
Name="VCCustomBuildTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCLinkerTool"
|
||||||
|
AdditionalOptions="/MACHINE:I386"
|
||||||
|
AdditionalDependencies="xmlrpc.lib Ws2_32.lib odbc32.lib odbccp32.lib"
|
||||||
|
OutputFile=".\Release/FileClient.exe"
|
||||||
|
LinkIncremental="1"
|
||||||
|
SuppressStartupBanner="TRUE"
|
||||||
|
AdditionalLibraryDirectories="..\release"
|
||||||
|
ProgramDatabaseFile=".\Release/FileClient.pdb"
|
||||||
|
SubSystem="1">
|
||||||
|
<IntelOptions
|
||||||
|
AllOptions="/NOLOGO /OUT:".\Release/FileClient.exe" /INCREMENTAL:NO /LIBPATH:"..\release" xmlrpc.lib Ws2_32.lib odbc32.lib odbccp32.lib /PDB:".\Release/FileClient.pdb" /SUBSYSTEM:CONSOLE /TLBID:1 /MACHINE:I386 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib"
|
||||||
|
MSOriginalAdditionalOptions="/MACHINE:I386"/>
|
||||||
|
</Tool>
|
||||||
|
<Tool
|
||||||
|
Name="VCMIDLTool"
|
||||||
|
TypeLibraryName=".\Release/FileClient.tlb"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPostBuildEventTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreBuildEventTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreLinkEventTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCResourceCompilerTool"
|
||||||
|
PreprocessorDefinitions="NDEBUG"
|
||||||
|
Culture="1033"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCWebServiceProxyGeneratorTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCWebDeploymentTool"/>
|
||||||
|
<IntelOptions
|
||||||
|
CompilerName="1"/>
|
||||||
|
</Configuration>
|
||||||
|
<Configuration
|
||||||
|
Name="Debug|Win32"
|
||||||
|
OutputDirectory=".\Debug"
|
||||||
|
IntermediateDirectory=".\Debug"
|
||||||
|
ConfigurationType="1"
|
||||||
|
UseOfMFC="0"
|
||||||
|
ATLMinimizesCRunTimeLibraryUsage="FALSE"
|
||||||
|
CharacterSet="2">
|
||||||
|
<Tool
|
||||||
|
Name="VCCLCompilerTool"
|
||||||
|
Optimization="0"
|
||||||
|
AdditionalIncludeDirectories="..\src"
|
||||||
|
PreprocessorDefinitions="WIN32,_DEBUG,_CONSOLE,_WINDOWS"
|
||||||
|
BasicRuntimeChecks="3"
|
||||||
|
RuntimeLibrary="3"
|
||||||
|
PrecompiledHeaderFile=".\Debug/FileClient.pch"
|
||||||
|
AssemblerListingLocation=".\Debug/"
|
||||||
|
ObjectFile=".\Debug/"
|
||||||
|
ProgramDataBaseFileName=".\Debug/"
|
||||||
|
WarningLevel="3"
|
||||||
|
SuppressStartupBanner="TRUE"
|
||||||
|
DebugInformationFormat="4"
|
||||||
|
CompileAs="0"
|
||||||
|
AdditionalOptions="">
|
||||||
|
<IntelOptions
|
||||||
|
Optimization="0"
|
||||||
|
MinimalRebuild="1"
|
||||||
|
BasicRuntimeChecks="3"
|
||||||
|
RuntimeLibrary="3"
|
||||||
|
AllOptions="/c /I "..\src" /ZI /nologo /W3 /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_WINDOWS" /D "_MBCS" /Gm /EHsc /RTC1 /MDd /Fp".\Debug/FileClient.pch" /Fo".\Debug/" /Fd".\Debug/" /Gd"
|
||||||
|
MSOriginalAdditionalOptions=""/>
|
||||||
|
</Tool>
|
||||||
|
<Tool
|
||||||
|
Name="VCCustomBuildTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCLinkerTool"
|
||||||
|
AdditionalOptions="/MACHINE:I386"
|
||||||
|
AdditionalDependencies="xmlrpc.lib Ws2_32.lib odbc32.lib odbccp32.lib"
|
||||||
|
OutputFile=".\Debug/FileClient.exe"
|
||||||
|
LinkIncremental="2"
|
||||||
|
SuppressStartupBanner="TRUE"
|
||||||
|
AdditionalLibraryDirectories="..\Debug"
|
||||||
|
GenerateDebugInformation="TRUE"
|
||||||
|
ProgramDatabaseFile=".\Debug/FileClient.pdb"
|
||||||
|
SubSystem="1">
|
||||||
|
<IntelOptions
|
||||||
|
AllOptions="/NOLOGO /OUT:".\Debug/FileClient.exe" /INCREMENTAL /LIBPATH:"..\Debug" xmlrpc.lib Ws2_32.lib odbc32.lib odbccp32.lib /DEBUG /PDB:".\Debug/FileClient.pdb" /SUBSYSTEM:CONSOLE /TLBID:1 /MACHINE:I386 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib"
|
||||||
|
MSOriginalAdditionalOptions="/MACHINE:I386"/>
|
||||||
|
</Tool>
|
||||||
|
<Tool
|
||||||
|
Name="VCMIDLTool"
|
||||||
|
TypeLibraryName=".\Debug/FileClient.tlb"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPostBuildEventTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreBuildEventTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreLinkEventTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCResourceCompilerTool"
|
||||||
|
PreprocessorDefinitions="_DEBUG"
|
||||||
|
Culture="1033"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCWebServiceProxyGeneratorTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCWebDeploymentTool"/>
|
||||||
|
<IntelOptions
|
||||||
|
CompilerName="1"/>
|
||||||
|
</Configuration>
|
||||||
|
</Configurations>
|
||||||
|
<Files>
|
||||||
|
<Filter
|
||||||
|
Name="Source Files"
|
||||||
|
Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat">
|
||||||
|
<File
|
||||||
|
RelativePath=".\FileClient.cpp"/>
|
||||||
|
</Filter>
|
||||||
|
</Files>
|
||||||
|
<Globals/>
|
||||||
|
</VisualStudioProject>
|
||||||
85
test/HelloClient.cpp
Normal file
85
test/HelloClient.cpp
Normal file
|
|
@ -0,0 +1,85 @@
|
||||||
|
// HelloClient.cpp : A simple xmlrpc client. Usage: HelloClient serverHost serverPort
|
||||||
|
// Link against xmlrpc lib and whatever socket libs your system needs (ws2_32.lib
|
||||||
|
// on windows)
|
||||||
|
#include "XmlRpc.h"
|
||||||
|
#include <iostream>
|
||||||
|
using namespace XmlRpc;
|
||||||
|
|
||||||
|
int main(int argc, char* argv[])
|
||||||
|
{
|
||||||
|
if (argc != 3) {
|
||||||
|
std::cerr << "Usage: HelloClient serverHost serverPort\n";
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
int port = atoi(argv[2]);
|
||||||
|
//XmlRpc::setVerbosity(5);
|
||||||
|
|
||||||
|
// Use introspection API to look up the supported methods
|
||||||
|
XmlRpcClient c(argv[1], port);
|
||||||
|
XmlRpcValue noArgs, result;
|
||||||
|
if (c.execute("system.listMethods", noArgs, result))
|
||||||
|
std::cout << "\nMethods:\n " << result << "\n\n";
|
||||||
|
else
|
||||||
|
std::cout << "Error calling 'listMethods'\n\n";
|
||||||
|
|
||||||
|
// Use introspection API to get the help string for the Hello method
|
||||||
|
XmlRpcValue oneArg;
|
||||||
|
oneArg[0] = "Hello";
|
||||||
|
if (c.execute("system.methodHelp", oneArg, result))
|
||||||
|
std::cout << "Help for 'Hello' method: " << result << "\n\n";
|
||||||
|
else
|
||||||
|
std::cout << "Error calling 'methodHelp'\n\n";
|
||||||
|
|
||||||
|
// Call the Hello method
|
||||||
|
if (c.execute("Hello", noArgs, result))
|
||||||
|
std::cout << result << "\n\n";
|
||||||
|
else
|
||||||
|
std::cout << "Error calling 'Hello'\n\n";
|
||||||
|
|
||||||
|
// Call the HelloName method
|
||||||
|
oneArg[0] = "Chris";
|
||||||
|
if (c.execute("HelloName", oneArg, result))
|
||||||
|
std::cout << result << "\n\n";
|
||||||
|
else
|
||||||
|
std::cout << "Error calling 'HelloName'\n\n";
|
||||||
|
|
||||||
|
// Add up an array of numbers
|
||||||
|
XmlRpcValue numbers;
|
||||||
|
numbers[0] = 33.33;
|
||||||
|
numbers[1] = 112.57;
|
||||||
|
numbers[2] = 76.1;
|
||||||
|
std::cout << "numbers.size() is " << numbers.size() << std::endl;
|
||||||
|
if (c.execute("Sum", numbers, result))
|
||||||
|
std::cout << "Sum = " << double(result) << "\n\n";
|
||||||
|
else
|
||||||
|
std::cout << "Error calling 'Sum'\n\n";
|
||||||
|
|
||||||
|
// Test the "no such method" fault
|
||||||
|
if (c.execute("NoSuchMethod", numbers, result))
|
||||||
|
std::cout << "NoSuchMethod call: fault: " << c.isFault() << ", result = " << result << std::endl;
|
||||||
|
else
|
||||||
|
std::cout << "Error calling 'Sum'\n";
|
||||||
|
|
||||||
|
// Test the multicall method. It accepts one arg, an array of structs
|
||||||
|
XmlRpcValue multicall;
|
||||||
|
multicall[0][0]["methodName"] = "Sum";
|
||||||
|
multicall[0][0]["params"][0] = 5.0;
|
||||||
|
multicall[0][0]["params"][1] = 9.0;
|
||||||
|
|
||||||
|
multicall[0][1]["methodName"] = "NoSuchMethod";
|
||||||
|
multicall[0][1]["params"][0] = "";
|
||||||
|
|
||||||
|
multicall[0][2]["methodName"] = "Sum";
|
||||||
|
// Missing params
|
||||||
|
|
||||||
|
multicall[0][3]["methodName"] = "Sum";
|
||||||
|
multicall[0][3]["params"][0] = 10.5;
|
||||||
|
multicall[0][3]["params"][1] = 12.5;
|
||||||
|
|
||||||
|
if (c.execute("system.multicall", multicall, result))
|
||||||
|
std::cout << "\nmulticall result = " << result << std::endl;
|
||||||
|
else
|
||||||
|
std::cout << "\nError calling 'system.multicall'\n";
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
96
test/HelloClient.dsp
Normal file
96
test/HelloClient.dsp
Normal file
|
|
@ -0,0 +1,96 @@
|
||||||
|
# Microsoft Developer Studio Project File - Name="HelloClient" - Package Owner=<4>
|
||||||
|
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||||
|
# ** DO NOT EDIT **
|
||||||
|
|
||||||
|
# TARGTYPE "Win32 (x86) Console Application" 0x0103
|
||||||
|
|
||||||
|
CFG=HelloClient - Win32 Debug
|
||||||
|
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||||
|
!MESSAGE use the Export Makefile command and run
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE NMAKE /f "HelloClient.mak".
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE You can specify a configuration when running NMAKE
|
||||||
|
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE NMAKE /f "HelloClient.mak" CFG="HelloClient - Win32 Debug"
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE Possible choices for configuration are:
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE "HelloClient - Win32 Release" (based on "Win32 (x86) Console Application")
|
||||||
|
!MESSAGE "HelloClient - Win32 Debug" (based on "Win32 (x86) Console Application")
|
||||||
|
!MESSAGE
|
||||||
|
|
||||||
|
# Begin Project
|
||||||
|
# PROP AllowPerConfigDependencies 0
|
||||||
|
# PROP Scc_ProjName ""
|
||||||
|
# PROP Scc_LocalPath ""
|
||||||
|
CPP=cl.exe
|
||||||
|
RSC=rc.exe
|
||||||
|
|
||||||
|
!IF "$(CFG)" == "HelloClient - Win32 Release"
|
||||||
|
|
||||||
|
# PROP BASE Use_MFC 0
|
||||||
|
# PROP BASE Use_Debug_Libraries 0
|
||||||
|
# PROP BASE Output_Dir "Release"
|
||||||
|
# PROP BASE Intermediate_Dir "Release"
|
||||||
|
# PROP BASE Target_Dir ""
|
||||||
|
# PROP Use_MFC 0
|
||||||
|
# PROP Use_Debug_Libraries 0
|
||||||
|
# PROP Output_Dir "Release"
|
||||||
|
# PROP Intermediate_Dir "Release"
|
||||||
|
# PROP Ignore_Export_Lib 0
|
||||||
|
# PROP Target_Dir ""
|
||||||
|
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /c
|
||||||
|
# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\src" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /D "_WINDOWS" /FD /c
|
||||||
|
# SUBTRACT CPP /YX /Yc /Yu
|
||||||
|
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||||
|
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||||
|
BSC32=bscmake.exe
|
||||||
|
# ADD BASE BSC32 /nologo
|
||||||
|
# ADD BSC32 /nologo
|
||||||
|
LINK32=link.exe
|
||||||
|
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
|
||||||
|
# ADD LINK32 xmlrpc.lib Ws2_32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /libpath:"..\release"
|
||||||
|
|
||||||
|
!ELSEIF "$(CFG)" == "HelloClient - Win32 Debug"
|
||||||
|
|
||||||
|
# PROP BASE Use_MFC 0
|
||||||
|
# PROP BASE Use_Debug_Libraries 1
|
||||||
|
# PROP BASE Output_Dir "Debug"
|
||||||
|
# PROP BASE Intermediate_Dir "Debug"
|
||||||
|
# PROP BASE Target_Dir ""
|
||||||
|
# PROP Use_MFC 0
|
||||||
|
# PROP Use_Debug_Libraries 1
|
||||||
|
# PROP Output_Dir "Debug"
|
||||||
|
# PROP Intermediate_Dir "Debug"
|
||||||
|
# PROP Ignore_Export_Lib 0
|
||||||
|
# PROP Target_Dir ""
|
||||||
|
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c
|
||||||
|
# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "..\src" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "_WINDOWS" /FD /GZ /c
|
||||||
|
# SUBTRACT CPP /YX /Yc /Yu
|
||||||
|
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||||
|
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||||
|
BSC32=bscmake.exe
|
||||||
|
# ADD BASE BSC32 /nologo
|
||||||
|
# ADD BSC32 /nologo
|
||||||
|
LINK32=link.exe
|
||||||
|
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
|
||||||
|
# ADD LINK32 xmlrpc.lib Ws2_32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\Debug"
|
||||||
|
|
||||||
|
!ENDIF
|
||||||
|
|
||||||
|
# Begin Target
|
||||||
|
|
||||||
|
# Name "HelloClient - Win32 Release"
|
||||||
|
# Name "HelloClient - Win32 Debug"
|
||||||
|
# Begin Group "Source Files"
|
||||||
|
|
||||||
|
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\HelloClient.cpp
|
||||||
|
# End Source File
|
||||||
|
# End Group
|
||||||
|
# End Target
|
||||||
|
# End Project
|
||||||
164
test/HelloClient.vcproj
Normal file
164
test/HelloClient.vcproj
Normal file
|
|
@ -0,0 +1,164 @@
|
||||||
|
<?xml version="1.0" encoding = "Windows-1252"?>
|
||||||
|
<VisualStudioProject
|
||||||
|
ProjectType="Visual C++"
|
||||||
|
Version="7.00"
|
||||||
|
Name="HelloClient"
|
||||||
|
ProjectGUID="{F6860B2F-0F3B-445E-92F2-6DF3D36C90F0}"
|
||||||
|
SccProjectName=""
|
||||||
|
SccLocalPath="">
|
||||||
|
<Platforms>
|
||||||
|
<Platform
|
||||||
|
Name="Win32"/>
|
||||||
|
</Platforms>
|
||||||
|
<Configurations>
|
||||||
|
<Configuration
|
||||||
|
Name="Release|Win32"
|
||||||
|
OutputDirectory=".\Release"
|
||||||
|
IntermediateDirectory=".\Release"
|
||||||
|
ConfigurationType="1"
|
||||||
|
UseOfMFC="0"
|
||||||
|
ATLMinimizesCRunTimeLibraryUsage="FALSE"
|
||||||
|
CharacterSet="2">
|
||||||
|
<Tool
|
||||||
|
Name="VCCLCompilerTool"
|
||||||
|
InlineFunctionExpansion="1"
|
||||||
|
AdditionalIncludeDirectories="..\src"
|
||||||
|
PreprocessorDefinitions="WIN32,NDEBUG,_CONSOLE"
|
||||||
|
StringPooling="TRUE"
|
||||||
|
RuntimeLibrary="2"
|
||||||
|
EnableFunctionLevelLinking="TRUE"
|
||||||
|
PrecompiledHeaderFile=".\Release/HelloClient.pch"
|
||||||
|
AssemblerListingLocation=".\Release/"
|
||||||
|
ObjectFile=".\Release/"
|
||||||
|
ProgramDataBaseFileName=".\Release/"
|
||||||
|
WarningLevel="3"
|
||||||
|
SuppressStartupBanner="TRUE"
|
||||||
|
CompileAs="0"
|
||||||
|
AdditionalOptions="">
|
||||||
|
<IntelOptions
|
||||||
|
Optimization="2"
|
||||||
|
InlineFuncExpansion="1"
|
||||||
|
OmitFramePtrs="1"
|
||||||
|
StringPooling="1"
|
||||||
|
RuntimeLibrary="2"
|
||||||
|
BufferSecurityCheck="1"
|
||||||
|
FunctionLevelLinking="1"
|
||||||
|
AllOptions="/c /I "..\src" /nologo /W3 /O2 /Ob1 /Oy /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /GF /FD /EHsc /MD /GS /Gy /Fp".\Release/HelloClient.pch" /Fo".\Release/" /Fd".\Release/" /Gd"
|
||||||
|
MSOriginalAdditionalOptions=""/>
|
||||||
|
</Tool>
|
||||||
|
<Tool
|
||||||
|
Name="VCCustomBuildTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCLinkerTool"
|
||||||
|
AdditionalOptions="/MACHINE:I386"
|
||||||
|
AdditionalDependencies="xmlrpc.lib Ws2_32.lib odbc32.lib odbccp32.lib"
|
||||||
|
OutputFile=".\Release/HelloClient.exe"
|
||||||
|
LinkIncremental="1"
|
||||||
|
SuppressStartupBanner="TRUE"
|
||||||
|
AdditionalLibraryDirectories="..\release"
|
||||||
|
ProgramDatabaseFile=".\Release/HelloClient.pdb"
|
||||||
|
SubSystem="1">
|
||||||
|
<IntelOptions
|
||||||
|
AllOptions="/NOLOGO /OUT:".\Release/HelloClient.exe" /INCREMENTAL:NO /LIBPATH:"..\release" xmlrpc.lib Ws2_32.lib odbc32.lib odbccp32.lib /PDB:".\Release/HelloClient.pdb" /SUBSYSTEM:CONSOLE /TLBID:1 /MACHINE:I386 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib"
|
||||||
|
MSOriginalAdditionalOptions="/MACHINE:I386"/>
|
||||||
|
</Tool>
|
||||||
|
<Tool
|
||||||
|
Name="VCMIDLTool"
|
||||||
|
TypeLibraryName=".\Release/HelloClient.tlb"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPostBuildEventTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreBuildEventTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreLinkEventTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCResourceCompilerTool"
|
||||||
|
PreprocessorDefinitions="NDEBUG"
|
||||||
|
Culture="1033"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCWebServiceProxyGeneratorTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCWebDeploymentTool"/>
|
||||||
|
<IntelOptions
|
||||||
|
CompilerName="1"/>
|
||||||
|
</Configuration>
|
||||||
|
<Configuration
|
||||||
|
Name="Debug|Win32"
|
||||||
|
OutputDirectory=".\Debug"
|
||||||
|
IntermediateDirectory=".\Debug"
|
||||||
|
ConfigurationType="1"
|
||||||
|
UseOfMFC="0"
|
||||||
|
ATLMinimizesCRunTimeLibraryUsage="FALSE"
|
||||||
|
CharacterSet="2">
|
||||||
|
<Tool
|
||||||
|
Name="VCCLCompilerTool"
|
||||||
|
Optimization="0"
|
||||||
|
AdditionalIncludeDirectories="..\src"
|
||||||
|
PreprocessorDefinitions="WIN32,_DEBUG,_CONSOLE"
|
||||||
|
BasicRuntimeChecks="3"
|
||||||
|
RuntimeLibrary="3"
|
||||||
|
PrecompiledHeaderFile=".\Debug/HelloClient.pch"
|
||||||
|
AssemblerListingLocation=".\Debug/"
|
||||||
|
ObjectFile=".\Debug/"
|
||||||
|
ProgramDataBaseFileName=".\Debug/"
|
||||||
|
WarningLevel="3"
|
||||||
|
SuppressStartupBanner="TRUE"
|
||||||
|
DebugInformationFormat="4"
|
||||||
|
CompileAs="0"
|
||||||
|
AdditionalOptions="">
|
||||||
|
<IntelOptions
|
||||||
|
Optimization="0"
|
||||||
|
MinimalRebuild="1"
|
||||||
|
BasicRuntimeChecks="3"
|
||||||
|
RuntimeLibrary="3"
|
||||||
|
AllOptions="/c /I "..\src" /ZI /nologo /W3 /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Gm /EHsc /RTC1 /MDd /Fp".\Debug/HelloClient.pch" /Fo".\Debug/" /Fd".\Debug/" /Gd"
|
||||||
|
MSOriginalAdditionalOptions=""/>
|
||||||
|
</Tool>
|
||||||
|
<Tool
|
||||||
|
Name="VCCustomBuildTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCLinkerTool"
|
||||||
|
AdditionalOptions="/MACHINE:I386 "c:\home\cmm\dev\sourceforge\xmlrpc++\Debug\xmlrpc.lib""
|
||||||
|
AdditionalDependencies="xmlrpc.lib Ws2_32.lib odbc32.lib odbccp32.lib"
|
||||||
|
OutputFile=".\Debug/HelloClient.exe"
|
||||||
|
LinkIncremental="2"
|
||||||
|
SuppressStartupBanner="TRUE"
|
||||||
|
AdditionalLibraryDirectories="..\Debug"
|
||||||
|
GenerateDebugInformation="TRUE"
|
||||||
|
ProgramDatabaseFile=".\Debug/HelloClient.pdb"
|
||||||
|
SubSystem="1">
|
||||||
|
<IntelOptions
|
||||||
|
AllOptions="/NOLOGO /OUT:".\Debug/HelloClient.exe" /INCREMENTAL /LIBPATH:"..\Debug" xmlrpc.lib Ws2_32.lib odbc32.lib odbccp32.lib /DEBUG /PDB:".\Debug/HelloClient.pdb" /SUBSYSTEM:CONSOLE /TLBID:1 /MACHINE:I386 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib"
|
||||||
|
MSOriginalAdditionalOptions="/MACHINE:I386 "c:\home\cmm\dev\sourceforge\xmlrpc++\Debug\xmlrpc.lib""/>
|
||||||
|
</Tool>
|
||||||
|
<Tool
|
||||||
|
Name="VCMIDLTool"
|
||||||
|
TypeLibraryName=".\Debug/HelloClient.tlb"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPostBuildEventTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreBuildEventTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreLinkEventTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCResourceCompilerTool"
|
||||||
|
PreprocessorDefinitions="_DEBUG"
|
||||||
|
Culture="1033"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCWebServiceProxyGeneratorTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCWebDeploymentTool"/>
|
||||||
|
<IntelOptions
|
||||||
|
CompilerName="1"/>
|
||||||
|
</Configuration>
|
||||||
|
</Configurations>
|
||||||
|
<Files>
|
||||||
|
<Filter
|
||||||
|
Name="Source Files"
|
||||||
|
Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat">
|
||||||
|
<File
|
||||||
|
RelativePath=".\HelloClient.cpp"/>
|
||||||
|
</Filter>
|
||||||
|
</Files>
|
||||||
|
<Globals/>
|
||||||
|
</VisualStudioProject>
|
||||||
82
test/HelloServer.cpp
Normal file
82
test/HelloServer.cpp
Normal file
|
|
@ -0,0 +1,82 @@
|
||||||
|
// HelloServer.cpp : Simple XMLRPC server example. Usage: HelloServer serverPort
|
||||||
|
//
|
||||||
|
#include "XmlRpc.h"
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
using namespace XmlRpc;
|
||||||
|
|
||||||
|
// The server
|
||||||
|
XmlRpcServer s;
|
||||||
|
|
||||||
|
// No arguments, result is "Hello".
|
||||||
|
class Hello : public XmlRpcServerMethod
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Hello(XmlRpcServer* s) : XmlRpcServerMethod("Hello", s) {}
|
||||||
|
|
||||||
|
void execute(XmlRpcValue& params, XmlRpcValue& result)
|
||||||
|
{
|
||||||
|
result = "Hello";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string help() { return std::string("Say hello"); }
|
||||||
|
|
||||||
|
} hello(&s); // This constructor registers the method with the server
|
||||||
|
|
||||||
|
|
||||||
|
// One argument is passed, result is "Hello, " + arg.
|
||||||
|
class HelloName : public XmlRpcServerMethod
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
HelloName(XmlRpcServer* s) : XmlRpcServerMethod("HelloName", s) {}
|
||||||
|
|
||||||
|
void execute(XmlRpcValue& params, XmlRpcValue& result)
|
||||||
|
{
|
||||||
|
std::string resultString = "Hello, ";
|
||||||
|
resultString += std::string(params[0]);
|
||||||
|
result = resultString;
|
||||||
|
}
|
||||||
|
} helloName(&s);
|
||||||
|
|
||||||
|
|
||||||
|
// A variable number of arguments are passed, all doubles, result is their sum.
|
||||||
|
class Sum : public XmlRpcServerMethod
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Sum(XmlRpcServer* s) : XmlRpcServerMethod("Sum", s) {}
|
||||||
|
|
||||||
|
void execute(XmlRpcValue& params, XmlRpcValue& result)
|
||||||
|
{
|
||||||
|
int nArgs = params.size();
|
||||||
|
double sum = 0.0;
|
||||||
|
for (int i=0; i<nArgs; ++i)
|
||||||
|
sum += double(params[i]);
|
||||||
|
result = sum;
|
||||||
|
}
|
||||||
|
} sum(&s);
|
||||||
|
|
||||||
|
|
||||||
|
int main(int argc, char* argv[])
|
||||||
|
{
|
||||||
|
if (argc != 2) {
|
||||||
|
std::cerr << "Usage: HelloServer serverPort\n";
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
int port = atoi(argv[1]);
|
||||||
|
|
||||||
|
XmlRpc::setVerbosity(5);
|
||||||
|
|
||||||
|
// Create the server socket on the specified port
|
||||||
|
s.bindAndListen(port);
|
||||||
|
|
||||||
|
// Enable introspection
|
||||||
|
s.enableIntrospection(true);
|
||||||
|
|
||||||
|
// Wait for requests indefinitely
|
||||||
|
s.work(-1.0);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
96
test/HelloServer.dsp
Normal file
96
test/HelloServer.dsp
Normal file
|
|
@ -0,0 +1,96 @@
|
||||||
|
# Microsoft Developer Studio Project File - Name="HelloServer" - Package Owner=<4>
|
||||||
|
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||||
|
# ** DO NOT EDIT **
|
||||||
|
|
||||||
|
# TARGTYPE "Win32 (x86) Console Application" 0x0103
|
||||||
|
|
||||||
|
CFG=HelloServer - Win32 Debug
|
||||||
|
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||||
|
!MESSAGE use the Export Makefile command and run
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE NMAKE /f "HelloServer.mak".
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE You can specify a configuration when running NMAKE
|
||||||
|
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE NMAKE /f "HelloServer.mak" CFG="HelloServer - Win32 Debug"
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE Possible choices for configuration are:
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE "HelloServer - Win32 Release" (based on "Win32 (x86) Console Application")
|
||||||
|
!MESSAGE "HelloServer - Win32 Debug" (based on "Win32 (x86) Console Application")
|
||||||
|
!MESSAGE
|
||||||
|
|
||||||
|
# Begin Project
|
||||||
|
# PROP AllowPerConfigDependencies 0
|
||||||
|
# PROP Scc_ProjName ""
|
||||||
|
# PROP Scc_LocalPath ""
|
||||||
|
CPP=cl.exe
|
||||||
|
RSC=rc.exe
|
||||||
|
|
||||||
|
!IF "$(CFG)" == "HelloServer - Win32 Release"
|
||||||
|
|
||||||
|
# PROP BASE Use_MFC 0
|
||||||
|
# PROP BASE Use_Debug_Libraries 0
|
||||||
|
# PROP BASE Output_Dir "Release"
|
||||||
|
# PROP BASE Intermediate_Dir "Release"
|
||||||
|
# PROP BASE Target_Dir ""
|
||||||
|
# PROP Use_MFC 0
|
||||||
|
# PROP Use_Debug_Libraries 0
|
||||||
|
# PROP Output_Dir "Release"
|
||||||
|
# PROP Intermediate_Dir "Release"
|
||||||
|
# PROP Ignore_Export_Lib 0
|
||||||
|
# PROP Target_Dir ""
|
||||||
|
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /c
|
||||||
|
# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\src" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /D "_WINDOWS" /FD /c
|
||||||
|
# SUBTRACT CPP /YX /Yc /Yu
|
||||||
|
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||||
|
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||||
|
BSC32=bscmake.exe
|
||||||
|
# ADD BASE BSC32 /nologo
|
||||||
|
# ADD BSC32 /nologo
|
||||||
|
LINK32=link.exe
|
||||||
|
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
|
||||||
|
# ADD LINK32 xmlrpc.lib Ws2_32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /libpath:"..\release"
|
||||||
|
|
||||||
|
!ELSEIF "$(CFG)" == "HelloServer - Win32 Debug"
|
||||||
|
|
||||||
|
# PROP BASE Use_MFC 0
|
||||||
|
# PROP BASE Use_Debug_Libraries 1
|
||||||
|
# PROP BASE Output_Dir "Debug"
|
||||||
|
# PROP BASE Intermediate_Dir "Debug"
|
||||||
|
# PROP BASE Target_Dir ""
|
||||||
|
# PROP Use_MFC 0
|
||||||
|
# PROP Use_Debug_Libraries 1
|
||||||
|
# PROP Output_Dir "Debug"
|
||||||
|
# PROP Intermediate_Dir "Debug"
|
||||||
|
# PROP Ignore_Export_Lib 0
|
||||||
|
# PROP Target_Dir ""
|
||||||
|
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c
|
||||||
|
# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "..\src" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "_WINDOWS" /FD /GZ /c
|
||||||
|
# SUBTRACT CPP /YX /Yc /Yu
|
||||||
|
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||||
|
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||||
|
BSC32=bscmake.exe
|
||||||
|
# ADD BASE BSC32 /nologo
|
||||||
|
# ADD BSC32 /nologo
|
||||||
|
LINK32=link.exe
|
||||||
|
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
|
||||||
|
# ADD LINK32 xmlrpc.lib Ws2_32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\Debug"
|
||||||
|
|
||||||
|
!ENDIF
|
||||||
|
|
||||||
|
# Begin Target
|
||||||
|
|
||||||
|
# Name "HelloServer - Win32 Release"
|
||||||
|
# Name "HelloServer - Win32 Debug"
|
||||||
|
# Begin Group "Source Files"
|
||||||
|
|
||||||
|
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\HelloServer.cpp
|
||||||
|
# End Source File
|
||||||
|
# End Group
|
||||||
|
# End Target
|
||||||
|
# End Project
|
||||||
164
test/HelloServer.vcproj
Normal file
164
test/HelloServer.vcproj
Normal file
|
|
@ -0,0 +1,164 @@
|
||||||
|
<?xml version="1.0" encoding = "Windows-1252"?>
|
||||||
|
<VisualStudioProject
|
||||||
|
ProjectType="Visual C++"
|
||||||
|
Version="7.00"
|
||||||
|
Name="HelloServer"
|
||||||
|
ProjectGUID="{08C4FFA8-A9E5-4EEA-9703-53C293C2F724}"
|
||||||
|
SccProjectName=""
|
||||||
|
SccLocalPath="">
|
||||||
|
<Platforms>
|
||||||
|
<Platform
|
||||||
|
Name="Win32"/>
|
||||||
|
</Platforms>
|
||||||
|
<Configurations>
|
||||||
|
<Configuration
|
||||||
|
Name="Release|Win32"
|
||||||
|
OutputDirectory=".\Release"
|
||||||
|
IntermediateDirectory=".\Release"
|
||||||
|
ConfigurationType="1"
|
||||||
|
UseOfMFC="0"
|
||||||
|
ATLMinimizesCRunTimeLibraryUsage="FALSE"
|
||||||
|
CharacterSet="2">
|
||||||
|
<Tool
|
||||||
|
Name="VCCLCompilerTool"
|
||||||
|
InlineFunctionExpansion="1"
|
||||||
|
AdditionalIncludeDirectories="..\src"
|
||||||
|
PreprocessorDefinitions="WIN32,NDEBUG,_CONSOLE"
|
||||||
|
StringPooling="TRUE"
|
||||||
|
RuntimeLibrary="2"
|
||||||
|
EnableFunctionLevelLinking="TRUE"
|
||||||
|
PrecompiledHeaderFile=".\Release/HelloServer.pch"
|
||||||
|
AssemblerListingLocation=".\Release/"
|
||||||
|
ObjectFile=".\Release/"
|
||||||
|
ProgramDataBaseFileName=".\Release/"
|
||||||
|
WarningLevel="3"
|
||||||
|
SuppressStartupBanner="TRUE"
|
||||||
|
CompileAs="0"
|
||||||
|
AdditionalOptions="">
|
||||||
|
<IntelOptions
|
||||||
|
Optimization="2"
|
||||||
|
InlineFuncExpansion="1"
|
||||||
|
OmitFramePtrs="1"
|
||||||
|
StringPooling="1"
|
||||||
|
RuntimeLibrary="2"
|
||||||
|
BufferSecurityCheck="1"
|
||||||
|
FunctionLevelLinking="1"
|
||||||
|
AllOptions="/c /I "..\src" /nologo /W3 /O2 /Ob1 /Oy /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /GF /FD /EHsc /MD /GS /Gy /Fp".\Release/HelloServer.pch" /Fo".\Release/" /Fd".\Release/" /Gd"
|
||||||
|
MSOriginalAdditionalOptions=""/>
|
||||||
|
</Tool>
|
||||||
|
<Tool
|
||||||
|
Name="VCCustomBuildTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCLinkerTool"
|
||||||
|
AdditionalOptions="/MACHINE:I386"
|
||||||
|
AdditionalDependencies="xmlrpc.lib Ws2_32.lib odbc32.lib odbccp32.lib"
|
||||||
|
OutputFile=".\Release/HelloServer.exe"
|
||||||
|
LinkIncremental="1"
|
||||||
|
SuppressStartupBanner="TRUE"
|
||||||
|
AdditionalLibraryDirectories="..\release"
|
||||||
|
ProgramDatabaseFile=".\Release/HelloServer.pdb"
|
||||||
|
SubSystem="1">
|
||||||
|
<IntelOptions
|
||||||
|
AllOptions="/NOLOGO /OUT:".\Release/HelloServer.exe" /INCREMENTAL:NO /LIBPATH:"..\release" xmlrpc.lib Ws2_32.lib odbc32.lib odbccp32.lib /PDB:".\Release/HelloServer.pdb" /SUBSYSTEM:CONSOLE /TLBID:1 /MACHINE:I386 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib"
|
||||||
|
MSOriginalAdditionalOptions="/MACHINE:I386"/>
|
||||||
|
</Tool>
|
||||||
|
<Tool
|
||||||
|
Name="VCMIDLTool"
|
||||||
|
TypeLibraryName=".\Release/HelloServer.tlb"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPostBuildEventTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreBuildEventTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreLinkEventTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCResourceCompilerTool"
|
||||||
|
PreprocessorDefinitions="NDEBUG"
|
||||||
|
Culture="1033"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCWebServiceProxyGeneratorTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCWebDeploymentTool"/>
|
||||||
|
<IntelOptions
|
||||||
|
CompilerName="1"/>
|
||||||
|
</Configuration>
|
||||||
|
<Configuration
|
||||||
|
Name="Debug|Win32"
|
||||||
|
OutputDirectory=".\Debug"
|
||||||
|
IntermediateDirectory=".\Debug"
|
||||||
|
ConfigurationType="1"
|
||||||
|
UseOfMFC="0"
|
||||||
|
ATLMinimizesCRunTimeLibraryUsage="FALSE"
|
||||||
|
CharacterSet="2">
|
||||||
|
<Tool
|
||||||
|
Name="VCCLCompilerTool"
|
||||||
|
Optimization="0"
|
||||||
|
AdditionalIncludeDirectories="..\src"
|
||||||
|
PreprocessorDefinitions="WIN32,_DEBUG,_CONSOLE"
|
||||||
|
BasicRuntimeChecks="3"
|
||||||
|
RuntimeLibrary="3"
|
||||||
|
PrecompiledHeaderFile=".\Debug/HelloServer.pch"
|
||||||
|
AssemblerListingLocation=".\Debug/"
|
||||||
|
ObjectFile=".\Debug/"
|
||||||
|
ProgramDataBaseFileName=".\Debug/"
|
||||||
|
WarningLevel="3"
|
||||||
|
SuppressStartupBanner="TRUE"
|
||||||
|
DebugInformationFormat="4"
|
||||||
|
CompileAs="0"
|
||||||
|
AdditionalOptions="">
|
||||||
|
<IntelOptions
|
||||||
|
Optimization="0"
|
||||||
|
MinimalRebuild="1"
|
||||||
|
BasicRuntimeChecks="3"
|
||||||
|
RuntimeLibrary="3"
|
||||||
|
AllOptions="/c /I "..\src" /ZI /nologo /W3 /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Gm /EHsc /RTC1 /MDd /Fp".\Debug/HelloServer.pch" /Fo".\Debug/" /Fd".\Debug/" /Gd"
|
||||||
|
MSOriginalAdditionalOptions=""/>
|
||||||
|
</Tool>
|
||||||
|
<Tool
|
||||||
|
Name="VCCustomBuildTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCLinkerTool"
|
||||||
|
AdditionalOptions="/MACHINE:I386"
|
||||||
|
AdditionalDependencies="xmlrpc.lib Ws2_32.lib odbc32.lib odbccp32.lib"
|
||||||
|
OutputFile=".\Debug/HelloServer.exe"
|
||||||
|
LinkIncremental="2"
|
||||||
|
SuppressStartupBanner="TRUE"
|
||||||
|
AdditionalLibraryDirectories="..\Debug"
|
||||||
|
GenerateDebugInformation="TRUE"
|
||||||
|
ProgramDatabaseFile=".\Debug/HelloServer.pdb"
|
||||||
|
SubSystem="1">
|
||||||
|
<IntelOptions
|
||||||
|
AllOptions="/NOLOGO /OUT:".\Debug/HelloServer.exe" /INCREMENTAL /LIBPATH:"..\Debug" xmlrpc.lib Ws2_32.lib odbc32.lib odbccp32.lib /DEBUG /PDB:".\Debug/HelloServer.pdb" /SUBSYSTEM:CONSOLE /TLBID:1 /MACHINE:I386 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib"
|
||||||
|
MSOriginalAdditionalOptions="/MACHINE:I386"/>
|
||||||
|
</Tool>
|
||||||
|
<Tool
|
||||||
|
Name="VCMIDLTool"
|
||||||
|
TypeLibraryName=".\Debug/HelloServer.tlb"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPostBuildEventTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreBuildEventTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreLinkEventTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCResourceCompilerTool"
|
||||||
|
PreprocessorDefinitions="_DEBUG"
|
||||||
|
Culture="1033"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCWebServiceProxyGeneratorTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCWebDeploymentTool"/>
|
||||||
|
<IntelOptions
|
||||||
|
CompilerName="1"/>
|
||||||
|
</Configuration>
|
||||||
|
</Configurations>
|
||||||
|
<Files>
|
||||||
|
<Filter
|
||||||
|
Name="Source Files"
|
||||||
|
Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat">
|
||||||
|
<File
|
||||||
|
RelativePath=".\HelloServer.cpp"/>
|
||||||
|
</Filter>
|
||||||
|
</Files>
|
||||||
|
<Globals/>
|
||||||
|
</VisualStudioProject>
|
||||||
26
test/Makefile
Normal file
26
test/Makefile
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
# makefile written for gnu make
|
||||||
|
CXX = /usr/local/gcc-3.1/bin/g++
|
||||||
|
SRC = ../src
|
||||||
|
CPPFLAGS = -I$(SRC)
|
||||||
|
DEBUG = -g
|
||||||
|
#OPTIMIZE = -O2
|
||||||
|
GCCWARN = -Wall -Wstrict-prototypes
|
||||||
|
CXXFLAGS = $(DEBUG) $(GCCWARN) $(OPTIMIZE) $(INCLUDES)
|
||||||
|
|
||||||
|
LIB = ../libXmlRpc.a
|
||||||
|
|
||||||
|
# Add your system-dependent network libs here
|
||||||
|
# Solaris: -lsocket -lnsl
|
||||||
|
SYSTEMLIBS =
|
||||||
|
|
||||||
|
LDLIBS = $(SYSTEMLIBS) $(LIB)
|
||||||
|
|
||||||
|
TESTS = HelloClient HelloServer TestBase64Client TestBase64Server TestValues TestXml Validator
|
||||||
|
|
||||||
|
all: $(TESTS)
|
||||||
|
|
||||||
|
$(TESTS): $(LIB)
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f *.o
|
||||||
|
rm -f $(TESTS)
|
||||||
45
test/TestBase64Client.cpp
Normal file
45
test/TestBase64Client.cpp
Normal file
|
|
@ -0,0 +1,45 @@
|
||||||
|
// TestBase64Client.cpp : A simple xmlrpc client that returns a png file
|
||||||
|
// encoded as base64 data to the client.
|
||||||
|
//
|
||||||
|
// Usage: TestBase64Client serverHost serverPort outputfile
|
||||||
|
// Requests a png file from the specified server and saves it in outputfile.
|
||||||
|
// Link against xmlrpc lib and whatever socket libs your system needs (ws2_32.lib on windows)
|
||||||
|
|
||||||
|
#include "XmlRpc.h"
|
||||||
|
#include <iostream>
|
||||||
|
#include <fstream>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
using namespace XmlRpc;
|
||||||
|
|
||||||
|
int main(int argc, char* argv[])
|
||||||
|
{
|
||||||
|
if (argc != 4) {
|
||||||
|
std::cerr << "Usage: TestBase64Client serverHost serverPort outputFile\n";
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
int port = atoi(argv[2]);
|
||||||
|
|
||||||
|
//XmlRpc::setVerbosity(5);
|
||||||
|
XmlRpcClient c(argv[1], port);
|
||||||
|
|
||||||
|
XmlRpcValue noArgs, result;
|
||||||
|
if (c.execute("TestBase64", noArgs, result))
|
||||||
|
{
|
||||||
|
const XmlRpcValue::BinaryData& data = result;
|
||||||
|
std::ofstream outfile(argv[3], std::ios::binary | std::ios::trunc);
|
||||||
|
if (outfile.fail())
|
||||||
|
std::cerr << "Error opening " << argv[3] << " for output.\n";
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int n = int(data.size());
|
||||||
|
for (int i=0; i<n; ++i)
|
||||||
|
outfile << data[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
std::cout << "Error calling 'TestBase64'\n\n";
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
96
test/TestBase64Client.dsp
Normal file
96
test/TestBase64Client.dsp
Normal file
|
|
@ -0,0 +1,96 @@
|
||||||
|
# Microsoft Developer Studio Project File - Name="TestBase64Client" - Package Owner=<4>
|
||||||
|
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||||
|
# ** DO NOT EDIT **
|
||||||
|
|
||||||
|
# TARGTYPE "Win32 (x86) Console Application" 0x0103
|
||||||
|
|
||||||
|
CFG=TestBase64Client - Win32 Debug
|
||||||
|
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||||
|
!MESSAGE use the Export Makefile command and run
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE NMAKE /f "TestBase64Client.mak".
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE You can specify a configuration when running NMAKE
|
||||||
|
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE NMAKE /f "TestBase64Client.mak" CFG="TestBase64Client - Win32 Debug"
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE Possible choices for configuration are:
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE "TestBase64Client - Win32 Release" (based on "Win32 (x86) Console Application")
|
||||||
|
!MESSAGE "TestBase64Client - Win32 Debug" (based on "Win32 (x86) Console Application")
|
||||||
|
!MESSAGE
|
||||||
|
|
||||||
|
# Begin Project
|
||||||
|
# PROP AllowPerConfigDependencies 0
|
||||||
|
# PROP Scc_ProjName ""
|
||||||
|
# PROP Scc_LocalPath ""
|
||||||
|
CPP=cl.exe
|
||||||
|
RSC=rc.exe
|
||||||
|
|
||||||
|
!IF "$(CFG)" == "TestBase64Client - Win32 Release"
|
||||||
|
|
||||||
|
# PROP BASE Use_MFC 0
|
||||||
|
# PROP BASE Use_Debug_Libraries 0
|
||||||
|
# PROP BASE Output_Dir "Release"
|
||||||
|
# PROP BASE Intermediate_Dir "Release"
|
||||||
|
# PROP BASE Target_Dir ""
|
||||||
|
# PROP Use_MFC 0
|
||||||
|
# PROP Use_Debug_Libraries 0
|
||||||
|
# PROP Output_Dir "Release"
|
||||||
|
# PROP Intermediate_Dir "Release"
|
||||||
|
# PROP Ignore_Export_Lib 0
|
||||||
|
# PROP Target_Dir ""
|
||||||
|
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /c
|
||||||
|
# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\src" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /D "_WINDOWS" /FD /c
|
||||||
|
# SUBTRACT CPP /YX /Yc /Yu
|
||||||
|
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||||
|
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||||
|
BSC32=bscmake.exe
|
||||||
|
# ADD BASE BSC32 /nologo
|
||||||
|
# ADD BSC32 /nologo
|
||||||
|
LINK32=link.exe
|
||||||
|
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
|
||||||
|
# ADD LINK32 xmlrpc.lib Ws2_32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /libpath:"..\release"
|
||||||
|
|
||||||
|
!ELSEIF "$(CFG)" == "TestBase64Client - Win32 Debug"
|
||||||
|
|
||||||
|
# PROP BASE Use_MFC 0
|
||||||
|
# PROP BASE Use_Debug_Libraries 1
|
||||||
|
# PROP BASE Output_Dir "Debug"
|
||||||
|
# PROP BASE Intermediate_Dir "Debug"
|
||||||
|
# PROP BASE Target_Dir ""
|
||||||
|
# PROP Use_MFC 0
|
||||||
|
# PROP Use_Debug_Libraries 1
|
||||||
|
# PROP Output_Dir "Debug"
|
||||||
|
# PROP Intermediate_Dir "Debug"
|
||||||
|
# PROP Ignore_Export_Lib 0
|
||||||
|
# PROP Target_Dir ""
|
||||||
|
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c
|
||||||
|
# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "..\src" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "_WINDOWS" /FD /GZ /c
|
||||||
|
# SUBTRACT CPP /YX /Yc /Yu
|
||||||
|
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||||
|
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||||
|
BSC32=bscmake.exe
|
||||||
|
# ADD BASE BSC32 /nologo
|
||||||
|
# ADD BSC32 /nologo
|
||||||
|
LINK32=link.exe
|
||||||
|
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
|
||||||
|
# ADD LINK32 xmlrpc.lib Ws2_32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\Debug"
|
||||||
|
|
||||||
|
!ENDIF
|
||||||
|
|
||||||
|
# Begin Target
|
||||||
|
|
||||||
|
# Name "TestBase64Client - Win32 Release"
|
||||||
|
# Name "TestBase64Client - Win32 Debug"
|
||||||
|
# Begin Group "Source Files"
|
||||||
|
|
||||||
|
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\TestBase64Client.cpp
|
||||||
|
# End Source File
|
||||||
|
# End Group
|
||||||
|
# End Target
|
||||||
|
# End Project
|
||||||
164
test/TestBase64Client.vcproj
Normal file
164
test/TestBase64Client.vcproj
Normal file
|
|
@ -0,0 +1,164 @@
|
||||||
|
<?xml version="1.0" encoding = "Windows-1252"?>
|
||||||
|
<VisualStudioProject
|
||||||
|
ProjectType="Visual C++"
|
||||||
|
Version="7.00"
|
||||||
|
Name="TestBase64Client"
|
||||||
|
ProjectGUID="{1E8B725B-E898-494C-84C6-DB77EF38E6CB}"
|
||||||
|
SccProjectName=""
|
||||||
|
SccLocalPath="">
|
||||||
|
<Platforms>
|
||||||
|
<Platform
|
||||||
|
Name="Win32"/>
|
||||||
|
</Platforms>
|
||||||
|
<Configurations>
|
||||||
|
<Configuration
|
||||||
|
Name="Debug|Win32"
|
||||||
|
OutputDirectory=".\Debug"
|
||||||
|
IntermediateDirectory=".\Debug"
|
||||||
|
ConfigurationType="1"
|
||||||
|
UseOfMFC="0"
|
||||||
|
ATLMinimizesCRunTimeLibraryUsage="FALSE"
|
||||||
|
CharacterSet="2">
|
||||||
|
<Tool
|
||||||
|
Name="VCCLCompilerTool"
|
||||||
|
Optimization="0"
|
||||||
|
AdditionalIncludeDirectories="..\src"
|
||||||
|
PreprocessorDefinitions="WIN32,_DEBUG,_CONSOLE,_WINDOWS"
|
||||||
|
BasicRuntimeChecks="3"
|
||||||
|
RuntimeLibrary="3"
|
||||||
|
PrecompiledHeaderFile=".\Debug/TestBase64Client.pch"
|
||||||
|
AssemblerListingLocation=".\Debug/"
|
||||||
|
ObjectFile=".\Debug/"
|
||||||
|
ProgramDataBaseFileName=".\Debug/"
|
||||||
|
WarningLevel="3"
|
||||||
|
SuppressStartupBanner="TRUE"
|
||||||
|
DebugInformationFormat="4"
|
||||||
|
CompileAs="0"
|
||||||
|
AdditionalOptions="">
|
||||||
|
<IntelOptions
|
||||||
|
Optimization="0"
|
||||||
|
MinimalRebuild="1"
|
||||||
|
BasicRuntimeChecks="3"
|
||||||
|
RuntimeLibrary="3"
|
||||||
|
AllOptions="/c /I "..\src" /ZI /nologo /W3 /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_WINDOWS" /D "_MBCS" /Gm /EHsc /RTC1 /MDd /Fp".\Debug/TestBase64Client.pch" /Fo".\Debug/" /Fd".\Debug/" /Gd"
|
||||||
|
MSOriginalAdditionalOptions=""/>
|
||||||
|
</Tool>
|
||||||
|
<Tool
|
||||||
|
Name="VCCustomBuildTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCLinkerTool"
|
||||||
|
AdditionalOptions="/MACHINE:I386"
|
||||||
|
AdditionalDependencies="xmlrpc.lib Ws2_32.lib odbc32.lib odbccp32.lib"
|
||||||
|
OutputFile=".\Debug/TestBase64Client.exe"
|
||||||
|
LinkIncremental="2"
|
||||||
|
SuppressStartupBanner="TRUE"
|
||||||
|
AdditionalLibraryDirectories="..\Debug"
|
||||||
|
GenerateDebugInformation="TRUE"
|
||||||
|
ProgramDatabaseFile=".\Debug/TestBase64Client.pdb"
|
||||||
|
SubSystem="1">
|
||||||
|
<IntelOptions
|
||||||
|
AllOptions="/NOLOGO /OUT:".\Debug/TestBase64Client.exe" /INCREMENTAL /LIBPATH:"..\Debug" xmlrpc.lib Ws2_32.lib odbc32.lib odbccp32.lib /DEBUG /PDB:".\Debug/TestBase64Client.pdb" /SUBSYSTEM:CONSOLE /TLBID:1 /MACHINE:I386 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib"
|
||||||
|
MSOriginalAdditionalOptions="/MACHINE:I386"/>
|
||||||
|
</Tool>
|
||||||
|
<Tool
|
||||||
|
Name="VCMIDLTool"
|
||||||
|
TypeLibraryName=".\Debug/TestBase64Client.tlb"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPostBuildEventTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreBuildEventTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreLinkEventTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCResourceCompilerTool"
|
||||||
|
PreprocessorDefinitions="_DEBUG"
|
||||||
|
Culture="1033"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCWebServiceProxyGeneratorTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCWebDeploymentTool"/>
|
||||||
|
<IntelOptions
|
||||||
|
CompilerName="1"/>
|
||||||
|
</Configuration>
|
||||||
|
<Configuration
|
||||||
|
Name="Release|Win32"
|
||||||
|
OutputDirectory=".\Release"
|
||||||
|
IntermediateDirectory=".\Release"
|
||||||
|
ConfigurationType="1"
|
||||||
|
UseOfMFC="0"
|
||||||
|
ATLMinimizesCRunTimeLibraryUsage="FALSE"
|
||||||
|
CharacterSet="2">
|
||||||
|
<Tool
|
||||||
|
Name="VCCLCompilerTool"
|
||||||
|
InlineFunctionExpansion="1"
|
||||||
|
AdditionalIncludeDirectories="..\src"
|
||||||
|
PreprocessorDefinitions="WIN32,NDEBUG,_CONSOLE,_WINDOWS"
|
||||||
|
StringPooling="TRUE"
|
||||||
|
RuntimeLibrary="2"
|
||||||
|
EnableFunctionLevelLinking="TRUE"
|
||||||
|
PrecompiledHeaderFile=".\Release/TestBase64Client.pch"
|
||||||
|
AssemblerListingLocation=".\Release/"
|
||||||
|
ObjectFile=".\Release/"
|
||||||
|
ProgramDataBaseFileName=".\Release/"
|
||||||
|
WarningLevel="3"
|
||||||
|
SuppressStartupBanner="TRUE"
|
||||||
|
CompileAs="0"
|
||||||
|
AdditionalOptions="">
|
||||||
|
<IntelOptions
|
||||||
|
Optimization="2"
|
||||||
|
InlineFuncExpansion="1"
|
||||||
|
OmitFramePtrs="1"
|
||||||
|
StringPooling="1"
|
||||||
|
RuntimeLibrary="2"
|
||||||
|
BufferSecurityCheck="1"
|
||||||
|
FunctionLevelLinking="1"
|
||||||
|
AllOptions="/c /I "..\src" /nologo /W3 /O2 /Ob1 /Oy /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_WINDOWS" /D "_MBCS" /GF /FD /EHsc /MD /GS /Gy /Fp".\Release/TestBase64Client.pch" /Fo".\Release/" /Fd".\Release/" /Gd"
|
||||||
|
MSOriginalAdditionalOptions=""/>
|
||||||
|
</Tool>
|
||||||
|
<Tool
|
||||||
|
Name="VCCustomBuildTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCLinkerTool"
|
||||||
|
AdditionalOptions="/MACHINE:I386"
|
||||||
|
AdditionalDependencies="xmlrpc.lib Ws2_32.lib odbc32.lib odbccp32.lib"
|
||||||
|
OutputFile=".\Release/TestBase64Client.exe"
|
||||||
|
LinkIncremental="1"
|
||||||
|
SuppressStartupBanner="TRUE"
|
||||||
|
AdditionalLibraryDirectories="..\release"
|
||||||
|
ProgramDatabaseFile=".\Release/TestBase64Client.pdb"
|
||||||
|
SubSystem="1">
|
||||||
|
<IntelOptions
|
||||||
|
AllOptions="/NOLOGO /OUT:".\Release/TestBase64Client.exe" /INCREMENTAL:NO /LIBPATH:"..\release" xmlrpc.lib Ws2_32.lib odbc32.lib odbccp32.lib /PDB:".\Release/TestBase64Client.pdb" /SUBSYSTEM:CONSOLE /TLBID:1 /MACHINE:I386 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib"
|
||||||
|
MSOriginalAdditionalOptions="/MACHINE:I386"/>
|
||||||
|
</Tool>
|
||||||
|
<Tool
|
||||||
|
Name="VCMIDLTool"
|
||||||
|
TypeLibraryName=".\Release/TestBase64Client.tlb"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPostBuildEventTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreBuildEventTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreLinkEventTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCResourceCompilerTool"
|
||||||
|
PreprocessorDefinitions="NDEBUG"
|
||||||
|
Culture="1033"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCWebServiceProxyGeneratorTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCWebDeploymentTool"/>
|
||||||
|
<IntelOptions
|
||||||
|
CompilerName="1"/>
|
||||||
|
</Configuration>
|
||||||
|
</Configurations>
|
||||||
|
<Files>
|
||||||
|
<Filter
|
||||||
|
Name="Source Files"
|
||||||
|
Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat">
|
||||||
|
<File
|
||||||
|
RelativePath=".\TestBase64Client.cpp"/>
|
||||||
|
</Filter>
|
||||||
|
</Files>
|
||||||
|
<Globals/>
|
||||||
|
</VisualStudioProject>
|
||||||
68
test/TestBase64Server.cpp
Normal file
68
test/TestBase64Server.cpp
Normal file
|
|
@ -0,0 +1,68 @@
|
||||||
|
// TestBase64Server.cpp : Simple XMLRPC server example. Usage: TestBase64Server serverPort
|
||||||
|
//
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
# pragma warning(disable:4786) // identifier was truncated in debug info
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <fstream>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
|
||||||
|
#include "XmlRpc.h"
|
||||||
|
using namespace XmlRpc;
|
||||||
|
|
||||||
|
|
||||||
|
// The server
|
||||||
|
XmlRpcServer s;
|
||||||
|
|
||||||
|
// No arguments, result is Base64-encoded pngnow.png data.
|
||||||
|
class TestBase64 : public XmlRpcServerMethod
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
TestBase64(XmlRpcServer* s) : XmlRpcServerMethod("TestBase64", s) {}
|
||||||
|
|
||||||
|
void execute(XmlRpcValue& params, XmlRpcValue& result)
|
||||||
|
{
|
||||||
|
std::ifstream infile("pngnow.png", std::ios::binary);
|
||||||
|
if (infile.fail())
|
||||||
|
infile.open("../pngnow.png", std::ios::binary);
|
||||||
|
if (infile.fail())
|
||||||
|
result = "Could not open file pngnow.png";
|
||||||
|
else {
|
||||||
|
|
||||||
|
XmlRpcValue::BinaryData& data = result;
|
||||||
|
int n = 0;
|
||||||
|
for (;; ++n) {
|
||||||
|
char c = infile.get();
|
||||||
|
if (infile.eof()) break;
|
||||||
|
data.push_back(c);
|
||||||
|
}
|
||||||
|
std::cerr << "Read " << n << " bytes from pngnow.png\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} TestBase64(&s); // This constructor registers the method with the server
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int main(int argc, char* argv[])
|
||||||
|
{
|
||||||
|
if (argc != 2) {
|
||||||
|
std::cerr << "Usage: TestBase64Server serverPort\n";
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
int port = atoi(argv[1]);
|
||||||
|
|
||||||
|
//XmlRpc::setVerbosity(5);
|
||||||
|
|
||||||
|
// Create the server socket on the specified port
|
||||||
|
s.bindAndListen(port);
|
||||||
|
|
||||||
|
// Wait for requests indefinitely
|
||||||
|
s.work(-1.0);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
96
test/TestBase64Server.dsp
Normal file
96
test/TestBase64Server.dsp
Normal file
|
|
@ -0,0 +1,96 @@
|
||||||
|
# Microsoft Developer Studio Project File - Name="TestBase64Server" - Package Owner=<4>
|
||||||
|
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||||
|
# ** DO NOT EDIT **
|
||||||
|
|
||||||
|
# TARGTYPE "Win32 (x86) Console Application" 0x0103
|
||||||
|
|
||||||
|
CFG=TestBase64Server - Win32 Debug
|
||||||
|
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||||
|
!MESSAGE use the Export Makefile command and run
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE NMAKE /f "TestBase64Server.mak".
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE You can specify a configuration when running NMAKE
|
||||||
|
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE NMAKE /f "TestBase64Server.mak" CFG="TestBase64Server - Win32 Debug"
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE Possible choices for configuration are:
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE "TestBase64Server - Win32 Release" (based on "Win32 (x86) Console Application")
|
||||||
|
!MESSAGE "TestBase64Server - Win32 Debug" (based on "Win32 (x86) Console Application")
|
||||||
|
!MESSAGE
|
||||||
|
|
||||||
|
# Begin Project
|
||||||
|
# PROP AllowPerConfigDependencies 0
|
||||||
|
# PROP Scc_ProjName ""
|
||||||
|
# PROP Scc_LocalPath ""
|
||||||
|
CPP=cl.exe
|
||||||
|
RSC=rc.exe
|
||||||
|
|
||||||
|
!IF "$(CFG)" == "TestBase64Server - Win32 Release"
|
||||||
|
|
||||||
|
# PROP BASE Use_MFC 0
|
||||||
|
# PROP BASE Use_Debug_Libraries 0
|
||||||
|
# PROP BASE Output_Dir "Release"
|
||||||
|
# PROP BASE Intermediate_Dir "Release"
|
||||||
|
# PROP BASE Target_Dir ""
|
||||||
|
# PROP Use_MFC 0
|
||||||
|
# PROP Use_Debug_Libraries 0
|
||||||
|
# PROP Output_Dir "Release"
|
||||||
|
# PROP Intermediate_Dir "Release"
|
||||||
|
# PROP Ignore_Export_Lib 0
|
||||||
|
# PROP Target_Dir ""
|
||||||
|
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /c
|
||||||
|
# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\src" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /D "_WINDOWS" /FD /c
|
||||||
|
# SUBTRACT CPP /Fr /YX /Yc /Yu
|
||||||
|
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||||
|
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||||
|
BSC32=bscmake.exe
|
||||||
|
# ADD BASE BSC32 /nologo
|
||||||
|
# ADD BSC32 /nologo
|
||||||
|
LINK32=link.exe
|
||||||
|
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
|
||||||
|
# ADD LINK32 xmlrpc.lib Ws2_32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /libpath:"..\release"
|
||||||
|
|
||||||
|
!ELSEIF "$(CFG)" == "TestBase64Server - Win32 Debug"
|
||||||
|
|
||||||
|
# PROP BASE Use_MFC 0
|
||||||
|
# PROP BASE Use_Debug_Libraries 1
|
||||||
|
# PROP BASE Output_Dir "Debug"
|
||||||
|
# PROP BASE Intermediate_Dir "Debug"
|
||||||
|
# PROP BASE Target_Dir ""
|
||||||
|
# PROP Use_MFC 0
|
||||||
|
# PROP Use_Debug_Libraries 1
|
||||||
|
# PROP Output_Dir "Debug"
|
||||||
|
# PROP Intermediate_Dir "Debug"
|
||||||
|
# PROP Ignore_Export_Lib 0
|
||||||
|
# PROP Target_Dir ""
|
||||||
|
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c
|
||||||
|
# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "..\src" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "_WINDOWS" /FD /GZ /c
|
||||||
|
# SUBTRACT CPP /YX /Yc /Yu
|
||||||
|
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||||
|
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||||
|
BSC32=bscmake.exe
|
||||||
|
# ADD BASE BSC32 /nologo
|
||||||
|
# ADD BSC32 /nologo
|
||||||
|
LINK32=link.exe
|
||||||
|
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
|
||||||
|
# ADD LINK32 xmlrpc.lib Ws2_32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\Debug"
|
||||||
|
|
||||||
|
!ENDIF
|
||||||
|
|
||||||
|
# Begin Target
|
||||||
|
|
||||||
|
# Name "TestBase64Server - Win32 Release"
|
||||||
|
# Name "TestBase64Server - Win32 Debug"
|
||||||
|
# Begin Group "Source Files"
|
||||||
|
|
||||||
|
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\TestBase64Server.cpp
|
||||||
|
# End Source File
|
||||||
|
# End Group
|
||||||
|
# End Target
|
||||||
|
# End Project
|
||||||
164
test/TestBase64Server.vcproj
Normal file
164
test/TestBase64Server.vcproj
Normal file
|
|
@ -0,0 +1,164 @@
|
||||||
|
<?xml version="1.0" encoding = "Windows-1252"?>
|
||||||
|
<VisualStudioProject
|
||||||
|
ProjectType="Visual C++"
|
||||||
|
Version="7.00"
|
||||||
|
Name="TestBase64Server"
|
||||||
|
ProjectGUID="{D3107CC6-6300-47DE-B183-255B75CFE85A}"
|
||||||
|
SccProjectName=""
|
||||||
|
SccLocalPath="">
|
||||||
|
<Platforms>
|
||||||
|
<Platform
|
||||||
|
Name="Win32"/>
|
||||||
|
</Platforms>
|
||||||
|
<Configurations>
|
||||||
|
<Configuration
|
||||||
|
Name="Release|Win32"
|
||||||
|
OutputDirectory=".\Release"
|
||||||
|
IntermediateDirectory=".\Release"
|
||||||
|
ConfigurationType="1"
|
||||||
|
UseOfMFC="0"
|
||||||
|
ATLMinimizesCRunTimeLibraryUsage="FALSE"
|
||||||
|
CharacterSet="2">
|
||||||
|
<Tool
|
||||||
|
Name="VCCLCompilerTool"
|
||||||
|
InlineFunctionExpansion="1"
|
||||||
|
AdditionalIncludeDirectories="..\src"
|
||||||
|
PreprocessorDefinitions="WIN32,NDEBUG,_CONSOLE,_WINDOWS"
|
||||||
|
StringPooling="TRUE"
|
||||||
|
RuntimeLibrary="2"
|
||||||
|
EnableFunctionLevelLinking="TRUE"
|
||||||
|
PrecompiledHeaderFile=".\Release/TestBase64Server.pch"
|
||||||
|
AssemblerListingLocation=".\Release/"
|
||||||
|
ObjectFile=".\Release/"
|
||||||
|
ProgramDataBaseFileName=".\Release/"
|
||||||
|
WarningLevel="3"
|
||||||
|
SuppressStartupBanner="TRUE"
|
||||||
|
CompileAs="0"
|
||||||
|
AdditionalOptions="">
|
||||||
|
<IntelOptions
|
||||||
|
Optimization="2"
|
||||||
|
InlineFuncExpansion="1"
|
||||||
|
OmitFramePtrs="1"
|
||||||
|
StringPooling="1"
|
||||||
|
RuntimeLibrary="2"
|
||||||
|
BufferSecurityCheck="1"
|
||||||
|
FunctionLevelLinking="1"
|
||||||
|
AllOptions="/c /I "..\src" /nologo /W3 /O2 /Ob1 /Oy /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_WINDOWS" /D "_MBCS" /GF /FD /EHsc /MD /GS /Gy /Fp".\Release/TestBase64Server.pch" /Fo".\Release/" /Fd".\Release/" /Gd"
|
||||||
|
MSOriginalAdditionalOptions=""/>
|
||||||
|
</Tool>
|
||||||
|
<Tool
|
||||||
|
Name="VCCustomBuildTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCLinkerTool"
|
||||||
|
AdditionalOptions="/MACHINE:I386"
|
||||||
|
AdditionalDependencies="xmlrpc.lib Ws2_32.lib odbc32.lib odbccp32.lib"
|
||||||
|
OutputFile=".\Release/TestBase64Server.exe"
|
||||||
|
LinkIncremental="1"
|
||||||
|
SuppressStartupBanner="TRUE"
|
||||||
|
AdditionalLibraryDirectories="..\release"
|
||||||
|
ProgramDatabaseFile=".\Release/TestBase64Server.pdb"
|
||||||
|
SubSystem="1">
|
||||||
|
<IntelOptions
|
||||||
|
AllOptions="/NOLOGO /OUT:".\Release/TestBase64Server.exe" /INCREMENTAL:NO /LIBPATH:"..\release" xmlrpc.lib Ws2_32.lib odbc32.lib odbccp32.lib /PDB:".\Release/TestBase64Server.pdb" /SUBSYSTEM:CONSOLE /TLBID:1 /MACHINE:I386 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib"
|
||||||
|
MSOriginalAdditionalOptions="/MACHINE:I386"/>
|
||||||
|
</Tool>
|
||||||
|
<Tool
|
||||||
|
Name="VCMIDLTool"
|
||||||
|
TypeLibraryName=".\Release/TestBase64Server.tlb"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPostBuildEventTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreBuildEventTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreLinkEventTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCResourceCompilerTool"
|
||||||
|
PreprocessorDefinitions="NDEBUG"
|
||||||
|
Culture="1033"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCWebServiceProxyGeneratorTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCWebDeploymentTool"/>
|
||||||
|
<IntelOptions
|
||||||
|
CompilerName="1"/>
|
||||||
|
</Configuration>
|
||||||
|
<Configuration
|
||||||
|
Name="Debug|Win32"
|
||||||
|
OutputDirectory=".\Debug"
|
||||||
|
IntermediateDirectory=".\Debug"
|
||||||
|
ConfigurationType="1"
|
||||||
|
UseOfMFC="0"
|
||||||
|
ATLMinimizesCRunTimeLibraryUsage="FALSE"
|
||||||
|
CharacterSet="2">
|
||||||
|
<Tool
|
||||||
|
Name="VCCLCompilerTool"
|
||||||
|
Optimization="0"
|
||||||
|
AdditionalIncludeDirectories="..\src"
|
||||||
|
PreprocessorDefinitions="WIN32,_DEBUG,_CONSOLE,_WINDOWS"
|
||||||
|
BasicRuntimeChecks="3"
|
||||||
|
RuntimeLibrary="3"
|
||||||
|
PrecompiledHeaderFile=".\Debug/TestBase64Server.pch"
|
||||||
|
AssemblerListingLocation=".\Debug/"
|
||||||
|
ObjectFile=".\Debug/"
|
||||||
|
ProgramDataBaseFileName=".\Debug/"
|
||||||
|
WarningLevel="3"
|
||||||
|
SuppressStartupBanner="TRUE"
|
||||||
|
DebugInformationFormat="4"
|
||||||
|
CompileAs="0"
|
||||||
|
AdditionalOptions="">
|
||||||
|
<IntelOptions
|
||||||
|
Optimization="0"
|
||||||
|
MinimalRebuild="1"
|
||||||
|
BasicRuntimeChecks="3"
|
||||||
|
RuntimeLibrary="3"
|
||||||
|
AllOptions="/c /I "..\src" /ZI /nologo /W3 /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_WINDOWS" /D "_MBCS" /Gm /EHsc /RTC1 /MDd /Fp".\Debug/TestBase64Server.pch" /Fo".\Debug/" /Fd".\Debug/" /Gd"
|
||||||
|
MSOriginalAdditionalOptions=""/>
|
||||||
|
</Tool>
|
||||||
|
<Tool
|
||||||
|
Name="VCCustomBuildTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCLinkerTool"
|
||||||
|
AdditionalOptions="/MACHINE:I386"
|
||||||
|
AdditionalDependencies="xmlrpc.lib Ws2_32.lib odbc32.lib odbccp32.lib"
|
||||||
|
OutputFile=".\Debug/TestBase64Server.exe"
|
||||||
|
LinkIncremental="2"
|
||||||
|
SuppressStartupBanner="TRUE"
|
||||||
|
AdditionalLibraryDirectories="..\Debug"
|
||||||
|
GenerateDebugInformation="TRUE"
|
||||||
|
ProgramDatabaseFile=".\Debug/TestBase64Server.pdb"
|
||||||
|
SubSystem="1">
|
||||||
|
<IntelOptions
|
||||||
|
AllOptions="/NOLOGO /OUT:".\Debug/TestBase64Server.exe" /INCREMENTAL /LIBPATH:"..\Debug" xmlrpc.lib Ws2_32.lib odbc32.lib odbccp32.lib /DEBUG /PDB:".\Debug/TestBase64Server.pdb" /SUBSYSTEM:CONSOLE /TLBID:1 /MACHINE:I386 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib"
|
||||||
|
MSOriginalAdditionalOptions="/MACHINE:I386"/>
|
||||||
|
</Tool>
|
||||||
|
<Tool
|
||||||
|
Name="VCMIDLTool"
|
||||||
|
TypeLibraryName=".\Debug/TestBase64Server.tlb"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPostBuildEventTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreBuildEventTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreLinkEventTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCResourceCompilerTool"
|
||||||
|
PreprocessorDefinitions="_DEBUG"
|
||||||
|
Culture="1033"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCWebServiceProxyGeneratorTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCWebDeploymentTool"/>
|
||||||
|
<IntelOptions
|
||||||
|
CompilerName="1"/>
|
||||||
|
</Configuration>
|
||||||
|
</Configurations>
|
||||||
|
<Files>
|
||||||
|
<Filter
|
||||||
|
Name="Source Files"
|
||||||
|
Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat">
|
||||||
|
<File
|
||||||
|
RelativePath=".\TestBase64Server.cpp"/>
|
||||||
|
</Filter>
|
||||||
|
</Files>
|
||||||
|
<Globals/>
|
||||||
|
</VisualStudioProject>
|
||||||
233
test/TestValues.cpp
Normal file
233
test/TestValues.cpp
Normal file
|
|
@ -0,0 +1,233 @@
|
||||||
|
// TestValues.cpp : Test XML encoding and decoding of XmlRpcValues.
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "XmlRpcValue.h"
|
||||||
|
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
|
||||||
|
using namespace XmlRpc;
|
||||||
|
|
||||||
|
|
||||||
|
void testBoolean()
|
||||||
|
{
|
||||||
|
XmlRpcValue booleanFalse(false);
|
||||||
|
XmlRpcValue booleanTrue(true);
|
||||||
|
int offset = 0;
|
||||||
|
XmlRpcValue booleanFalseXml("<value><boolean>0</boolean></value>", &offset);
|
||||||
|
offset = 0;
|
||||||
|
XmlRpcValue booleanTrueXml("<value><boolean>1</boolean></value>", &offset);
|
||||||
|
assert(booleanFalse != booleanTrue);
|
||||||
|
assert(booleanFalse == booleanFalseXml);
|
||||||
|
assert(booleanFalse != booleanTrueXml);
|
||||||
|
|
||||||
|
if (bool(booleanFalse))
|
||||||
|
assert(false);
|
||||||
|
|
||||||
|
if ( ! bool(booleanTrue))
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Int
|
||||||
|
void testInt()
|
||||||
|
{
|
||||||
|
XmlRpcValue int0(0);
|
||||||
|
XmlRpcValue int1(1);
|
||||||
|
XmlRpcValue int10(10);
|
||||||
|
XmlRpcValue int_1(-1);
|
||||||
|
int offset = 0;
|
||||||
|
XmlRpcValue int0Xml("<value><int>0</int></value>", &offset);
|
||||||
|
offset = 0;
|
||||||
|
XmlRpcValue int9Xml("<value><i4>9</i4></value>", &offset);
|
||||||
|
assert(int0 == int0Xml);
|
||||||
|
assert(int(int10) - int(int1) == int(int9Xml));
|
||||||
|
assert(9 == int(int9Xml));
|
||||||
|
assert(int(int10) + int(int_1) == int(int9Xml));
|
||||||
|
}
|
||||||
|
|
||||||
|
void testDouble()
|
||||||
|
{
|
||||||
|
// Double
|
||||||
|
XmlRpcValue d(43.7);
|
||||||
|
int offset = 0;
|
||||||
|
XmlRpcValue dXml("<value><double>56.3</double></value>", &offset);
|
||||||
|
assert(double(d) + double(dXml) == 100.0); // questionable practice...
|
||||||
|
}
|
||||||
|
|
||||||
|
void testString()
|
||||||
|
{
|
||||||
|
// String
|
||||||
|
XmlRpcValue s("Now is the time <&");
|
||||||
|
char csxml[] = "<value><string>Now is the time <&</string></value>";
|
||||||
|
std::string ssxml = csxml;
|
||||||
|
int offset = 0;
|
||||||
|
XmlRpcValue vscXml(csxml, &offset);
|
||||||
|
offset = 0;
|
||||||
|
XmlRpcValue vssXml(ssxml, &offset);
|
||||||
|
assert(s == vscXml);
|
||||||
|
assert(s == vssXml);
|
||||||
|
offset = 0;
|
||||||
|
XmlRpcValue fromXml(vssXml.toXml(), &offset);
|
||||||
|
assert(s == fromXml);
|
||||||
|
|
||||||
|
// Empty or blank strings with no <string> tags
|
||||||
|
std::string emptyStringXml("<value></value>");
|
||||||
|
offset = 0;
|
||||||
|
XmlRpcValue emptyStringVal1(emptyStringXml, &offset);
|
||||||
|
XmlRpcValue emptyStringVal2("");
|
||||||
|
assert(emptyStringVal1 == emptyStringVal2);
|
||||||
|
|
||||||
|
emptyStringXml = "<value> </value>";
|
||||||
|
offset = 0;
|
||||||
|
XmlRpcValue blankStringVal(emptyStringXml, &offset);
|
||||||
|
assert(std::string(blankStringVal) == " ");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void testDateTime()
|
||||||
|
{
|
||||||
|
// DateTime
|
||||||
|
int offset = 0;
|
||||||
|
XmlRpcValue dateTime("<value><dateTime.iso8601>19040101T03:12:35</dateTime.iso8601></value>", &offset);
|
||||||
|
struct tm &t = dateTime;
|
||||||
|
assert(t.tm_year == 1904 && t.tm_min == 12);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void testArray(XmlRpcValue const& d)
|
||||||
|
{
|
||||||
|
// Array
|
||||||
|
XmlRpcValue a;
|
||||||
|
a.setSize(4);
|
||||||
|
a[0] = 1;
|
||||||
|
a[1] = std::string("two");
|
||||||
|
a[2] = 43.7;
|
||||||
|
a[3] = "four";
|
||||||
|
assert(int(a[0]) == 1);
|
||||||
|
assert(a[2] == d);
|
||||||
|
|
||||||
|
char csaXml[] =
|
||||||
|
"<value><array>\n"
|
||||||
|
" <data>\n"
|
||||||
|
" <value><i4>1</i4></value> \n"
|
||||||
|
" <value> <string>two</string></value>\n"
|
||||||
|
" <value><double>43.7</double></value>\n"
|
||||||
|
" <value>four</value>\n"
|
||||||
|
" </data>\n"
|
||||||
|
"</array></value>";
|
||||||
|
|
||||||
|
int offset = 0;
|
||||||
|
XmlRpcValue aXml(csaXml, &offset);
|
||||||
|
assert(a == aXml);
|
||||||
|
}
|
||||||
|
|
||||||
|
void testStruct()
|
||||||
|
{
|
||||||
|
// Struct
|
||||||
|
XmlRpcValue struct1;
|
||||||
|
struct1["i4"] = 1;
|
||||||
|
struct1["str"] = "two";
|
||||||
|
struct1["d"] = 43.7;
|
||||||
|
|
||||||
|
XmlRpcValue a;
|
||||||
|
a.setSize(4);
|
||||||
|
a[0] = 1;
|
||||||
|
a[1] = std::string("two");
|
||||||
|
a[2] = 43.7;
|
||||||
|
a[3] = "four";
|
||||||
|
|
||||||
|
assert(struct1["d"] == a[2]);
|
||||||
|
|
||||||
|
char csStructXml[] =
|
||||||
|
"<value><struct>\n"
|
||||||
|
" <member>\n"
|
||||||
|
" <name>i4</name> \n"
|
||||||
|
" <value><i4>1</i4></value> \n"
|
||||||
|
" </member>\n"
|
||||||
|
" <member>\n"
|
||||||
|
" <name>d</name> \n"
|
||||||
|
" <value><double>43.7</double></value>\n"
|
||||||
|
" </member>\n"
|
||||||
|
" <member>\n"
|
||||||
|
" <name>str</name> \n"
|
||||||
|
" <value> <string>two</string></value>\n"
|
||||||
|
" </member>\n"
|
||||||
|
"</struct></value>";
|
||||||
|
|
||||||
|
int offset = 0;
|
||||||
|
XmlRpcValue structXml(csStructXml, &offset);
|
||||||
|
assert(struct1 == structXml);
|
||||||
|
|
||||||
|
XmlRpcValue astruct;
|
||||||
|
astruct["array"] = a;
|
||||||
|
assert(astruct["array"][2] == struct1["d"]);
|
||||||
|
|
||||||
|
for (int i=0; i<10; i++) {
|
||||||
|
XmlRpcValue Event;
|
||||||
|
Event["Name"] = "string";
|
||||||
|
|
||||||
|
Event.clear();
|
||||||
|
|
||||||
|
const int NELMTS = 100;
|
||||||
|
int ii;
|
||||||
|
|
||||||
|
for (ii=0; ii< NELMTS; ++ii) {
|
||||||
|
char buf[40];
|
||||||
|
sprintf(buf,"%d", ii);
|
||||||
|
Event[std::string(buf)] = buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
Event.clear();
|
||||||
|
|
||||||
|
for (ii=0; ii< NELMTS; ++ii) {
|
||||||
|
char buf[40];
|
||||||
|
sprintf(buf,"%d", ii);
|
||||||
|
if (ii != NELMTS/2)
|
||||||
|
Event[std::string(buf)] = ii;
|
||||||
|
else
|
||||||
|
for (int jj=0; jj< NELMTS; ++jj) {
|
||||||
|
char bufj[40];
|
||||||
|
sprintf(bufj,"%d", jj);
|
||||||
|
Event[std::string(buf)][std::string(bufj)] = bufj;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (ii=0; ii< NELMTS; ++ii) {
|
||||||
|
char buf[40];
|
||||||
|
sprintf(buf,"%d", ii);
|
||||||
|
if (ii != NELMTS/2)
|
||||||
|
assert(Event[std::string(buf)] == XmlRpcValue(ii));
|
||||||
|
else
|
||||||
|
assert(Event[std::string(buf)].size() == NELMTS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int main(int argc, char* argv[])
|
||||||
|
{
|
||||||
|
testBoolean();
|
||||||
|
|
||||||
|
testInt();
|
||||||
|
|
||||||
|
|
||||||
|
testDouble();
|
||||||
|
|
||||||
|
|
||||||
|
testString();
|
||||||
|
|
||||||
|
|
||||||
|
testDateTime();
|
||||||
|
|
||||||
|
|
||||||
|
testArray(43.7);
|
||||||
|
|
||||||
|
|
||||||
|
testStruct();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
95
test/TestValues.dsp
Normal file
95
test/TestValues.dsp
Normal file
|
|
@ -0,0 +1,95 @@
|
||||||
|
# Microsoft Developer Studio Project File - Name="TestValues" - Package Owner=<4>
|
||||||
|
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||||
|
# ** DO NOT EDIT **
|
||||||
|
|
||||||
|
# TARGTYPE "Win32 (x86) Console Application" 0x0103
|
||||||
|
|
||||||
|
CFG=TestValues - Win32 Debug
|
||||||
|
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||||
|
!MESSAGE use the Export Makefile command and run
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE NMAKE /f "TestValues.mak".
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE You can specify a configuration when running NMAKE
|
||||||
|
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE NMAKE /f "TestValues.mak" CFG="TestValues - Win32 Debug"
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE Possible choices for configuration are:
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE "TestValues - Win32 Release" (based on "Win32 (x86) Console Application")
|
||||||
|
!MESSAGE "TestValues - Win32 Debug" (based on "Win32 (x86) Console Application")
|
||||||
|
!MESSAGE
|
||||||
|
|
||||||
|
# Begin Project
|
||||||
|
# PROP AllowPerConfigDependencies 0
|
||||||
|
# PROP Scc_ProjName ""
|
||||||
|
# PROP Scc_LocalPath ""
|
||||||
|
CPP=cl.exe
|
||||||
|
RSC=rc.exe
|
||||||
|
|
||||||
|
!IF "$(CFG)" == "TestValues - Win32 Release"
|
||||||
|
|
||||||
|
# PROP BASE Use_MFC 0
|
||||||
|
# PROP BASE Use_Debug_Libraries 0
|
||||||
|
# PROP BASE Output_Dir "Release"
|
||||||
|
# PROP BASE Intermediate_Dir "Release"
|
||||||
|
# PROP BASE Target_Dir ""
|
||||||
|
# PROP Use_MFC 0
|
||||||
|
# PROP Use_Debug_Libraries 0
|
||||||
|
# PROP Output_Dir "Release"
|
||||||
|
# PROP Intermediate_Dir "Release"
|
||||||
|
# PROP Ignore_Export_Lib 0
|
||||||
|
# PROP Target_Dir ""
|
||||||
|
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||||
|
# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\src" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||||
|
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||||
|
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||||
|
BSC32=bscmake.exe
|
||||||
|
# ADD BASE BSC32 /nologo
|
||||||
|
# ADD BSC32 /nologo
|
||||||
|
LINK32=link.exe
|
||||||
|
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
|
||||||
|
# ADD LINK32 xmlrpc.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /libpath:"..\Release"
|
||||||
|
|
||||||
|
!ELSEIF "$(CFG)" == "TestValues - Win32 Debug"
|
||||||
|
|
||||||
|
# PROP BASE Use_MFC 0
|
||||||
|
# PROP BASE Use_Debug_Libraries 1
|
||||||
|
# PROP BASE Output_Dir "Debug"
|
||||||
|
# PROP BASE Intermediate_Dir "Debug"
|
||||||
|
# PROP BASE Target_Dir ""
|
||||||
|
# PROP Use_MFC 0
|
||||||
|
# PROP Use_Debug_Libraries 1
|
||||||
|
# PROP Output_Dir "Debug"
|
||||||
|
# PROP Intermediate_Dir "Debug"
|
||||||
|
# PROP Ignore_Export_Lib 0
|
||||||
|
# PROP Target_Dir ""
|
||||||
|
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
|
||||||
|
# ADD CPP /MDd /W3 /GX /Zi /Od /I "..\src" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "_WINDOWS" /FR /FD /c
|
||||||
|
# SUBTRACT CPP /nologo
|
||||||
|
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||||
|
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||||
|
BSC32=bscmake.exe
|
||||||
|
# ADD BASE BSC32 /nologo
|
||||||
|
# ADD BSC32 /nologo
|
||||||
|
LINK32=link.exe
|
||||||
|
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
|
||||||
|
# ADD LINK32 xmlrpc.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\Debug"
|
||||||
|
|
||||||
|
!ENDIF
|
||||||
|
|
||||||
|
# Begin Target
|
||||||
|
|
||||||
|
# Name "TestValues - Win32 Release"
|
||||||
|
# Name "TestValues - Win32 Debug"
|
||||||
|
# Begin Group "Source Files"
|
||||||
|
|
||||||
|
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\TestValuesWin32.cpp
|
||||||
|
# End Source File
|
||||||
|
# End Group
|
||||||
|
# End Target
|
||||||
|
# End Project
|
||||||
162
test/TestValues.vcproj
Normal file
162
test/TestValues.vcproj
Normal file
|
|
@ -0,0 +1,162 @@
|
||||||
|
<?xml version="1.0" encoding = "Windows-1252"?>
|
||||||
|
<VisualStudioProject
|
||||||
|
ProjectType="Visual C++"
|
||||||
|
Version="7.00"
|
||||||
|
Name="TestValues"
|
||||||
|
ProjectGUID="{6181BBE3-DA50-4EEE-8D52-1F4245A1D603}"
|
||||||
|
SccProjectName=""
|
||||||
|
SccLocalPath="">
|
||||||
|
<Platforms>
|
||||||
|
<Platform
|
||||||
|
Name="Win32"/>
|
||||||
|
</Platforms>
|
||||||
|
<Configurations>
|
||||||
|
<Configuration
|
||||||
|
Name="Release|Win32"
|
||||||
|
OutputDirectory=".\Release"
|
||||||
|
IntermediateDirectory=".\Release"
|
||||||
|
ConfigurationType="1"
|
||||||
|
UseOfMFC="0"
|
||||||
|
ATLMinimizesCRunTimeLibraryUsage="FALSE"
|
||||||
|
CharacterSet="2">
|
||||||
|
<Tool
|
||||||
|
Name="VCCLCompilerTool"
|
||||||
|
InlineFunctionExpansion="1"
|
||||||
|
PreprocessorDefinitions="WIN32,NDEBUG,_CONSOLE"
|
||||||
|
StringPooling="TRUE"
|
||||||
|
RuntimeLibrary="2"
|
||||||
|
EnableFunctionLevelLinking="TRUE"
|
||||||
|
UsePrecompiledHeader="2"
|
||||||
|
PrecompiledHeaderFile=".\Release/TestValues.pch"
|
||||||
|
AssemblerListingLocation=".\Release/"
|
||||||
|
ObjectFile=".\Release/"
|
||||||
|
ProgramDataBaseFileName=".\Release/"
|
||||||
|
WarningLevel="3"
|
||||||
|
SuppressStartupBanner="TRUE"
|
||||||
|
AdditionalOptions="">
|
||||||
|
<IntelOptions
|
||||||
|
Optimization="2"
|
||||||
|
InlineFuncExpansion="1"
|
||||||
|
OmitFramePtrs="1"
|
||||||
|
StringPooling="1"
|
||||||
|
RuntimeLibrary="2"
|
||||||
|
BufferSecurityCheck="1"
|
||||||
|
FunctionLevelLinking="1"
|
||||||
|
AllOptions="/c /nologo /W3 /O2 /Ob1 /Oy /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /GF /FD /EHsc /MD /GS /Gy /YX"StdAfx.h" /Fp".\Release/TestValues.pch" /Fo".\Release/" /Fd".\Release/" /Gd /TP"
|
||||||
|
MSOriginalAdditionalOptions=""/>
|
||||||
|
</Tool>
|
||||||
|
<Tool
|
||||||
|
Name="VCCustomBuildTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCLinkerTool"
|
||||||
|
AdditionalOptions="/MACHINE:I386"
|
||||||
|
AdditionalDependencies="odbc32.lib odbccp32.lib"
|
||||||
|
OutputFile=".\Release/TestValues.exe"
|
||||||
|
LinkIncremental="1"
|
||||||
|
SuppressStartupBanner="TRUE"
|
||||||
|
ProgramDatabaseFile=".\Release/TestValues.pdb"
|
||||||
|
SubSystem="1">
|
||||||
|
<IntelOptions
|
||||||
|
AllOptions="/NOLOGO /OUT:".\Release/TestValues.exe" /INCREMENTAL:NO odbc32.lib odbccp32.lib /PDB:".\Release/TestValues.pdb" /SUBSYSTEM:CONSOLE /TLBID:1 /MACHINE:I386 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib"
|
||||||
|
MSOriginalAdditionalOptions="/MACHINE:I386"/>
|
||||||
|
</Tool>
|
||||||
|
<Tool
|
||||||
|
Name="VCMIDLTool"
|
||||||
|
TypeLibraryName=".\Release/TestValues.tlb"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPostBuildEventTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreBuildEventTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreLinkEventTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCResourceCompilerTool"
|
||||||
|
PreprocessorDefinitions="NDEBUG"
|
||||||
|
Culture="1033"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCWebServiceProxyGeneratorTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCWebDeploymentTool"/>
|
||||||
|
<IntelOptions
|
||||||
|
CompilerName="1"/>
|
||||||
|
</Configuration>
|
||||||
|
<Configuration
|
||||||
|
Name="Debug|Win32"
|
||||||
|
OutputDirectory=".\Debug"
|
||||||
|
IntermediateDirectory=".\Debug"
|
||||||
|
ConfigurationType="1"
|
||||||
|
UseOfMFC="0"
|
||||||
|
ATLMinimizesCRunTimeLibraryUsage="FALSE"
|
||||||
|
CharacterSet="2">
|
||||||
|
<Tool
|
||||||
|
Name="VCCLCompilerTool"
|
||||||
|
Optimization="0"
|
||||||
|
AdditionalIncludeDirectories="..\src"
|
||||||
|
PreprocessorDefinitions="WIN32,_DEBUG,_CONSOLE,_WINDOWS"
|
||||||
|
BasicRuntimeChecks="3"
|
||||||
|
RuntimeLibrary="3"
|
||||||
|
PrecompiledHeaderFile=".\Debug/TestValues.pch"
|
||||||
|
AssemblerListingLocation=".\Debug/"
|
||||||
|
ObjectFile=".\Debug/"
|
||||||
|
ProgramDataBaseFileName=".\Debug/"
|
||||||
|
WarningLevel="3"
|
||||||
|
SuppressStartupBanner="TRUE"
|
||||||
|
DebugInformationFormat="4"
|
||||||
|
CompileAs="0"
|
||||||
|
AdditionalOptions="">
|
||||||
|
<IntelOptions
|
||||||
|
Optimization="0"
|
||||||
|
MinimalRebuild="1"
|
||||||
|
BasicRuntimeChecks="3"
|
||||||
|
RuntimeLibrary="3"
|
||||||
|
AllOptions="/c /I "..\src" /ZI /nologo /W3 /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_WINDOWS" /D "_MBCS" /Gm /EHsc /RTC1 /MDd /Fp".\Debug/TestValues.pch" /Fo".\Debug/" /Fd".\Debug/" /Gd"
|
||||||
|
MSOriginalAdditionalOptions=""/>
|
||||||
|
</Tool>
|
||||||
|
<Tool
|
||||||
|
Name="VCCustomBuildTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCLinkerTool"
|
||||||
|
AdditionalOptions="/MACHINE:I386"
|
||||||
|
AdditionalDependencies="xmlrpc.lib odbc32.lib odbccp32.lib"
|
||||||
|
OutputFile=".\Debug/TestValues.exe"
|
||||||
|
LinkIncremental="2"
|
||||||
|
SuppressStartupBanner="TRUE"
|
||||||
|
AdditionalLibraryDirectories="..\Debug"
|
||||||
|
GenerateDebugInformation="TRUE"
|
||||||
|
ProgramDatabaseFile=".\Debug/TestValues.pdb"
|
||||||
|
SubSystem="1">
|
||||||
|
<IntelOptions
|
||||||
|
AllOptions="/NOLOGO /OUT:".\Debug/TestValues.exe" /INCREMENTAL /LIBPATH:"..\Debug" xmlrpc.lib odbc32.lib odbccp32.lib /DEBUG /PDB:".\Debug/TestValues.pdb" /SUBSYSTEM:CONSOLE /TLBID:1 /MACHINE:I386 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib"
|
||||||
|
MSOriginalAdditionalOptions="/MACHINE:I386"/>
|
||||||
|
</Tool>
|
||||||
|
<Tool
|
||||||
|
Name="VCMIDLTool"
|
||||||
|
TypeLibraryName=".\Debug/TestValues.tlb"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPostBuildEventTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreBuildEventTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreLinkEventTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCResourceCompilerTool"
|
||||||
|
PreprocessorDefinitions="_DEBUG"
|
||||||
|
Culture="1033"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCWebServiceProxyGeneratorTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCWebDeploymentTool"/>
|
||||||
|
<IntelOptions
|
||||||
|
CompilerName="1"/>
|
||||||
|
</Configuration>
|
||||||
|
</Configurations>
|
||||||
|
<Files>
|
||||||
|
<Filter
|
||||||
|
Name="Source Files"
|
||||||
|
Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat">
|
||||||
|
<File
|
||||||
|
RelativePath=".\TestValues.cpp"/>
|
||||||
|
</Filter>
|
||||||
|
</Files>
|
||||||
|
<Globals/>
|
||||||
|
</VisualStudioProject>
|
||||||
253
test/TestValuesWin32.cpp
Normal file
253
test/TestValuesWin32.cpp
Normal file
|
|
@ -0,0 +1,253 @@
|
||||||
|
// TestValues.cpp : Test XML encoding and decoding of XmlRpcValues.
|
||||||
|
|
||||||
|
#define _CRTDBG_MAP_ALLOC
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <crtdbg.h>
|
||||||
|
|
||||||
|
#include "XmlRpcValue.h"
|
||||||
|
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
|
||||||
|
using namespace XmlRpc;
|
||||||
|
|
||||||
|
|
||||||
|
void testBoolean()
|
||||||
|
{
|
||||||
|
XmlRpcValue booleanFalse(false);
|
||||||
|
XmlRpcValue booleanTrue(true);
|
||||||
|
int offset = 0;
|
||||||
|
XmlRpcValue booleanFalseXml("<value><boolean>0</boolean></value>", &offset);
|
||||||
|
offset = 0;
|
||||||
|
XmlRpcValue booleanTrueXml("<value><boolean>1</boolean></value>", &offset);
|
||||||
|
assert(booleanFalse != booleanTrue);
|
||||||
|
assert(booleanFalse == booleanFalseXml);
|
||||||
|
assert(booleanFalse == booleanFalseXml);
|
||||||
|
if (booleanFalse)
|
||||||
|
assert(false);
|
||||||
|
|
||||||
|
if (booleanTrue)
|
||||||
|
assert( ! false);
|
||||||
|
else
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Int
|
||||||
|
void testInt()
|
||||||
|
{
|
||||||
|
XmlRpcValue int0(0);
|
||||||
|
XmlRpcValue int1(1);
|
||||||
|
XmlRpcValue int10(10);
|
||||||
|
XmlRpcValue int_1(-1);
|
||||||
|
int offset = 0;
|
||||||
|
XmlRpcValue int0Xml("<value><int>0</int></value>", &offset);
|
||||||
|
offset = 0;
|
||||||
|
XmlRpcValue int9Xml("<value><i4>9</i4></value>", &offset);
|
||||||
|
assert(int0 == int0Xml);
|
||||||
|
assert(int(int10) - int(int1) == int(int9Xml));
|
||||||
|
assert(9 == int(int9Xml));
|
||||||
|
assert(int(int10) + int(int_1) == int(int9Xml));
|
||||||
|
}
|
||||||
|
|
||||||
|
void testDouble()
|
||||||
|
{
|
||||||
|
// Double
|
||||||
|
XmlRpcValue d(43.7);
|
||||||
|
int offset = 0;
|
||||||
|
XmlRpcValue dXml("<value><double>56.3</double></value>", &offset);
|
||||||
|
assert(double(d) + double(dXml) == 100.0); // questionable practice...
|
||||||
|
}
|
||||||
|
|
||||||
|
void testString()
|
||||||
|
{
|
||||||
|
// String
|
||||||
|
XmlRpcValue s("Now is the time <&");
|
||||||
|
char csxml[] = "<value><string>Now is the time <&</string></value>";
|
||||||
|
std::string ssxml = csxml;
|
||||||
|
int offset = 0;
|
||||||
|
XmlRpcValue vscXml(csxml, &offset);
|
||||||
|
offset = 0;
|
||||||
|
XmlRpcValue vssXml(ssxml, &offset);
|
||||||
|
assert(s == vscXml);
|
||||||
|
assert(s == vssXml);
|
||||||
|
offset = 0;
|
||||||
|
XmlRpcValue fromXml(vssXml.toXml(), &offset);
|
||||||
|
assert(s == fromXml);
|
||||||
|
|
||||||
|
// Empty or blank strings with no <string> tags
|
||||||
|
std::string emptyStringXml("<value></value>");
|
||||||
|
offset = 0;
|
||||||
|
XmlRpcValue emptyStringVal1(emptyStringXml, &offset);
|
||||||
|
XmlRpcValue emptyStringVal2("");
|
||||||
|
assert(emptyStringVal1 == emptyStringVal2);
|
||||||
|
|
||||||
|
emptyStringXml = "<value> </value>";
|
||||||
|
offset = 0;
|
||||||
|
XmlRpcValue blankStringVal(emptyStringXml, &offset);
|
||||||
|
assert(std::string(blankStringVal) == " ");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void testDateTime()
|
||||||
|
{
|
||||||
|
// DateTime
|
||||||
|
int offset = 0;
|
||||||
|
XmlRpcValue dateTime("<value><dateTime.iso8601>19040101T03:12:35</dateTime.iso8601></value>", &offset);
|
||||||
|
struct tm &t = dateTime;
|
||||||
|
assert(t.tm_year == 1904 && t.tm_min == 12);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void testArray(XmlRpcValue const& d)
|
||||||
|
{
|
||||||
|
// Array
|
||||||
|
XmlRpcValue a;
|
||||||
|
a.setSize(4);
|
||||||
|
a[0] = 1;
|
||||||
|
a[1] = std::string("two");
|
||||||
|
a[2] = 43.7;
|
||||||
|
a[3] = "four";
|
||||||
|
assert(int(a[0]) == 1);
|
||||||
|
assert(a[2] == d);
|
||||||
|
|
||||||
|
char csaXml[] =
|
||||||
|
"<value><array>\n"
|
||||||
|
" <data>\n"
|
||||||
|
" <value><i4>1</i4></value> \n"
|
||||||
|
" <value> <string>two</string></value>\n"
|
||||||
|
" <value><double>43.7</double></value>\n"
|
||||||
|
" <value>four</value>\n"
|
||||||
|
" </data>\n"
|
||||||
|
"</array></value>";
|
||||||
|
|
||||||
|
int offset = 0;
|
||||||
|
XmlRpcValue aXml(csaXml, &offset);
|
||||||
|
assert(a == aXml);
|
||||||
|
}
|
||||||
|
|
||||||
|
void testStruct()
|
||||||
|
{
|
||||||
|
// Struct
|
||||||
|
XmlRpcValue struct1;
|
||||||
|
struct1["i4"] = 1;
|
||||||
|
struct1["str"] = "two";
|
||||||
|
struct1["d"] = 43.7;
|
||||||
|
|
||||||
|
XmlRpcValue a;
|
||||||
|
a.setSize(4);
|
||||||
|
a[0] = 1;
|
||||||
|
a[1] = std::string("two");
|
||||||
|
a[2] = 43.7;
|
||||||
|
a[3] = "four";
|
||||||
|
|
||||||
|
assert(struct1["d"] == a[2]);
|
||||||
|
|
||||||
|
char csStructXml[] =
|
||||||
|
"<value><struct>\n"
|
||||||
|
" <member>\n"
|
||||||
|
" <name>i4</name> \n"
|
||||||
|
" <value><i4>1</i4></value> \n"
|
||||||
|
" </member>\n"
|
||||||
|
" <member>\n"
|
||||||
|
" <name>d</name> \n"
|
||||||
|
" <value><double>43.7</double></value>\n"
|
||||||
|
" </member>\n"
|
||||||
|
" <member>\n"
|
||||||
|
" <name>str</name> \n"
|
||||||
|
" <value> <string>two</string></value>\n"
|
||||||
|
" </member>\n"
|
||||||
|
"</struct></value>";
|
||||||
|
|
||||||
|
int offset = 0;
|
||||||
|
XmlRpcValue structXml(csStructXml, &offset);
|
||||||
|
assert(struct1 == structXml);
|
||||||
|
|
||||||
|
XmlRpcValue astruct;
|
||||||
|
astruct["array"] = a;
|
||||||
|
assert(astruct["array"][2] == struct1["d"]);
|
||||||
|
|
||||||
|
for (int i=0; i<10; i++) {
|
||||||
|
XmlRpcValue Event;
|
||||||
|
Event["Name"] = "string";
|
||||||
|
|
||||||
|
Event.clear();
|
||||||
|
|
||||||
|
const int NELMTS = 100;
|
||||||
|
int ii;
|
||||||
|
|
||||||
|
for (ii=0; ii< NELMTS; ++ii) {
|
||||||
|
char buf[40];
|
||||||
|
sprintf(buf,"%d", ii);
|
||||||
|
Event[buf] = buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
Event.clear();
|
||||||
|
|
||||||
|
for (ii=0; ii< NELMTS; ++ii) {
|
||||||
|
char buf[40];
|
||||||
|
sprintf(buf,"%d", ii);
|
||||||
|
if (ii != NELMTS/2)
|
||||||
|
Event[buf] = ii;
|
||||||
|
else
|
||||||
|
for (int jj=0; jj< NELMTS; ++jj) {
|
||||||
|
char bufj[40];
|
||||||
|
sprintf(bufj,"%d", jj);
|
||||||
|
Event[buf][bufj] = bufj;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (ii=0; ii< NELMTS; ++ii) {
|
||||||
|
char buf[40];
|
||||||
|
sprintf(buf,"%d", ii);
|
||||||
|
if (ii != NELMTS/2)
|
||||||
|
assert(Event[buf] == XmlRpcValue(ii));
|
||||||
|
else
|
||||||
|
assert(Event[buf].size() == NELMTS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int main(int argc, char* argv[])
|
||||||
|
{
|
||||||
|
_CrtDumpMemoryLeaks();
|
||||||
|
_CrtCheckMemory( );
|
||||||
|
|
||||||
|
testBoolean();
|
||||||
|
_CrtDumpMemoryLeaks();
|
||||||
|
_CrtCheckMemory( );
|
||||||
|
|
||||||
|
testInt();
|
||||||
|
_CrtDumpMemoryLeaks();
|
||||||
|
_CrtCheckMemory( );
|
||||||
|
|
||||||
|
|
||||||
|
testDouble();
|
||||||
|
_CrtDumpMemoryLeaks();
|
||||||
|
_CrtCheckMemory( );
|
||||||
|
|
||||||
|
|
||||||
|
testString();
|
||||||
|
_CrtDumpMemoryLeaks();
|
||||||
|
_CrtCheckMemory( );
|
||||||
|
|
||||||
|
|
||||||
|
testDateTime();
|
||||||
|
_CrtDumpMemoryLeaks();
|
||||||
|
_CrtCheckMemory( );
|
||||||
|
|
||||||
|
|
||||||
|
testArray(43.7);
|
||||||
|
_CrtDumpMemoryLeaks();
|
||||||
|
_CrtCheckMemory( );
|
||||||
|
|
||||||
|
|
||||||
|
testStruct();
|
||||||
|
_CrtDumpMemoryLeaks();
|
||||||
|
_CrtCheckMemory( );
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
53
test/TestXml.cpp
Normal file
53
test/TestXml.cpp
Normal file
|
|
@ -0,0 +1,53 @@
|
||||||
|
// TestXml.cpp : Test XML encoding and decoding.
|
||||||
|
// The characters <>&'" are illegal in xml and must be encoded.
|
||||||
|
|
||||||
|
|
||||||
|
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
// If you are using MSVC++6, you should update <string> to fix
|
||||||
|
// BUG: getline Template Function Reads Extra Character
|
||||||
|
#include <string>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "XmlRpcUtil.h"
|
||||||
|
|
||||||
|
using namespace XmlRpc;
|
||||||
|
|
||||||
|
|
||||||
|
int main(int argc, char* argv[])
|
||||||
|
{
|
||||||
|
// Basic tests
|
||||||
|
std::string empty;
|
||||||
|
assert(empty == XmlRpcUtil::xmlEncode(empty));
|
||||||
|
assert(empty == XmlRpcUtil::xmlDecode(empty));
|
||||||
|
assert(empty == XmlRpcUtil::xmlEncode(""));
|
||||||
|
assert(empty == XmlRpcUtil::xmlDecode(""));
|
||||||
|
|
||||||
|
std::string raw("<>&'\"");
|
||||||
|
assert(XmlRpcUtil::xmlDecode(XmlRpcUtil::xmlEncode(raw)) == raw);
|
||||||
|
|
||||||
|
std::cout << "Basic tests passed.\n";
|
||||||
|
|
||||||
|
// Interactive tests
|
||||||
|
std::string s;
|
||||||
|
for (;;) {
|
||||||
|
std::cout << "\nEnter line of raw text to encode:\n";
|
||||||
|
std::getline(std::cin, s);
|
||||||
|
if (s.empty()) break;
|
||||||
|
|
||||||
|
std::cout << XmlRpcUtil::xmlEncode(s) << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
std::cout << "\nEnter line of xml-encoded text to decode:\n";
|
||||||
|
std::getline(std::cin, s);
|
||||||
|
if (s.empty()) break;
|
||||||
|
|
||||||
|
std::cout << XmlRpcUtil::xmlDecode(s) << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
96
test/TestXml.dsp
Normal file
96
test/TestXml.dsp
Normal file
|
|
@ -0,0 +1,96 @@
|
||||||
|
# Microsoft Developer Studio Project File - Name="TestXml" - Package Owner=<4>
|
||||||
|
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||||
|
# ** DO NOT EDIT **
|
||||||
|
|
||||||
|
# TARGTYPE "Win32 (x86) Console Application" 0x0103
|
||||||
|
|
||||||
|
CFG=TestXml - Win32 Debug
|
||||||
|
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||||
|
!MESSAGE use the Export Makefile command and run
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE NMAKE /f "TestXml.mak".
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE You can specify a configuration when running NMAKE
|
||||||
|
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE NMAKE /f "TestXml.mak" CFG="TestXml - Win32 Debug"
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE Possible choices for configuration are:
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE "TestXml - Win32 Release" (based on "Win32 (x86) Console Application")
|
||||||
|
!MESSAGE "TestXml - Win32 Debug" (based on "Win32 (x86) Console Application")
|
||||||
|
!MESSAGE
|
||||||
|
|
||||||
|
# Begin Project
|
||||||
|
# PROP AllowPerConfigDependencies 0
|
||||||
|
# PROP Scc_ProjName ""
|
||||||
|
# PROP Scc_LocalPath ""
|
||||||
|
CPP=cl.exe
|
||||||
|
RSC=rc.exe
|
||||||
|
|
||||||
|
!IF "$(CFG)" == "TestXml - Win32 Release"
|
||||||
|
|
||||||
|
# PROP BASE Use_MFC 0
|
||||||
|
# PROP BASE Use_Debug_Libraries 0
|
||||||
|
# PROP BASE Output_Dir "Release"
|
||||||
|
# PROP BASE Intermediate_Dir "Release"
|
||||||
|
# PROP BASE Target_Dir ""
|
||||||
|
# PROP Use_MFC 0
|
||||||
|
# PROP Use_Debug_Libraries 0
|
||||||
|
# PROP Output_Dir "Release"
|
||||||
|
# PROP Intermediate_Dir "Release"
|
||||||
|
# PROP Ignore_Export_Lib 0
|
||||||
|
# PROP Target_Dir ""
|
||||||
|
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /c
|
||||||
|
# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\src" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /FD /c
|
||||||
|
# SUBTRACT CPP /YX /Yc /Yu
|
||||||
|
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||||
|
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||||
|
BSC32=bscmake.exe
|
||||||
|
# ADD BASE BSC32 /nologo
|
||||||
|
# ADD BSC32 /nologo
|
||||||
|
LINK32=link.exe
|
||||||
|
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
|
||||||
|
# ADD LINK32 xmlrpc.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /libpath:"..\release"
|
||||||
|
|
||||||
|
!ELSEIF "$(CFG)" == "TestXml - Win32 Debug"
|
||||||
|
|
||||||
|
# PROP BASE Use_MFC 0
|
||||||
|
# PROP BASE Use_Debug_Libraries 1
|
||||||
|
# PROP BASE Output_Dir "Debug"
|
||||||
|
# PROP BASE Intermediate_Dir "Debug"
|
||||||
|
# PROP BASE Target_Dir ""
|
||||||
|
# PROP Use_MFC 0
|
||||||
|
# PROP Use_Debug_Libraries 1
|
||||||
|
# PROP Output_Dir "Debug"
|
||||||
|
# PROP Intermediate_Dir "Debug"
|
||||||
|
# PROP Ignore_Export_Lib 0
|
||||||
|
# PROP Target_Dir ""
|
||||||
|
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c
|
||||||
|
# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "..\src" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FD /GZ /c
|
||||||
|
# SUBTRACT CPP /YX /Yc /Yu
|
||||||
|
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||||
|
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||||
|
BSC32=bscmake.exe
|
||||||
|
# ADD BASE BSC32 /nologo
|
||||||
|
# ADD BSC32 /nologo
|
||||||
|
LINK32=link.exe
|
||||||
|
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
|
||||||
|
# ADD LINK32 xmlrpc.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\Debug"
|
||||||
|
|
||||||
|
!ENDIF
|
||||||
|
|
||||||
|
# Begin Target
|
||||||
|
|
||||||
|
# Name "TestXml - Win32 Release"
|
||||||
|
# Name "TestXml - Win32 Debug"
|
||||||
|
# Begin Group "Source Files"
|
||||||
|
|
||||||
|
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\TestXml.cpp
|
||||||
|
# End Source File
|
||||||
|
# End Group
|
||||||
|
# End Target
|
||||||
|
# End Project
|
||||||
164
test/TestXml.vcproj
Normal file
164
test/TestXml.vcproj
Normal file
|
|
@ -0,0 +1,164 @@
|
||||||
|
<?xml version="1.0" encoding = "Windows-1252"?>
|
||||||
|
<VisualStudioProject
|
||||||
|
ProjectType="Visual C++"
|
||||||
|
Version="7.00"
|
||||||
|
Name="TestXml"
|
||||||
|
ProjectGUID="{6F0C2ADA-0341-4183-8FAA-576668F1788A}"
|
||||||
|
SccProjectName=""
|
||||||
|
SccLocalPath="">
|
||||||
|
<Platforms>
|
||||||
|
<Platform
|
||||||
|
Name="Win32"/>
|
||||||
|
</Platforms>
|
||||||
|
<Configurations>
|
||||||
|
<Configuration
|
||||||
|
Name="Release|Win32"
|
||||||
|
OutputDirectory=".\Release"
|
||||||
|
IntermediateDirectory=".\Release"
|
||||||
|
ConfigurationType="1"
|
||||||
|
UseOfMFC="0"
|
||||||
|
ATLMinimizesCRunTimeLibraryUsage="FALSE"
|
||||||
|
CharacterSet="2">
|
||||||
|
<Tool
|
||||||
|
Name="VCCLCompilerTool"
|
||||||
|
InlineFunctionExpansion="1"
|
||||||
|
AdditionalIncludeDirectories="..\src"
|
||||||
|
PreprocessorDefinitions="WIN32,NDEBUG,_CONSOLE"
|
||||||
|
StringPooling="TRUE"
|
||||||
|
RuntimeLibrary="2"
|
||||||
|
EnableFunctionLevelLinking="TRUE"
|
||||||
|
PrecompiledHeaderFile=".\Release/TestXml.pch"
|
||||||
|
AssemblerListingLocation=".\Release/"
|
||||||
|
ObjectFile=".\Release/"
|
||||||
|
ProgramDataBaseFileName=".\Release/"
|
||||||
|
WarningLevel="3"
|
||||||
|
SuppressStartupBanner="TRUE"
|
||||||
|
CompileAs="0"
|
||||||
|
AdditionalOptions="">
|
||||||
|
<IntelOptions
|
||||||
|
Optimization="2"
|
||||||
|
InlineFuncExpansion="1"
|
||||||
|
OmitFramePtrs="1"
|
||||||
|
StringPooling="1"
|
||||||
|
RuntimeLibrary="2"
|
||||||
|
BufferSecurityCheck="1"
|
||||||
|
FunctionLevelLinking="1"
|
||||||
|
AllOptions="/c /I "..\src" /nologo /W3 /O2 /Ob1 /Oy /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /GF /FD /EHsc /MD /GS /Gy /Fp".\Release/TestXml.pch" /Fo".\Release/" /Fd".\Release/" /Gd"
|
||||||
|
MSOriginalAdditionalOptions=""/>
|
||||||
|
</Tool>
|
||||||
|
<Tool
|
||||||
|
Name="VCCustomBuildTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCLinkerTool"
|
||||||
|
AdditionalOptions="/MACHINE:I386"
|
||||||
|
AdditionalDependencies="xmlrpc.lib odbc32.lib odbccp32.lib"
|
||||||
|
OutputFile=".\Release/TestXml.exe"
|
||||||
|
LinkIncremental="1"
|
||||||
|
SuppressStartupBanner="TRUE"
|
||||||
|
AdditionalLibraryDirectories="..\release"
|
||||||
|
ProgramDatabaseFile=".\Release/TestXml.pdb"
|
||||||
|
SubSystem="1">
|
||||||
|
<IntelOptions
|
||||||
|
AllOptions="/NOLOGO /OUT:".\Release/TestXml.exe" /INCREMENTAL:NO /LIBPATH:"..\release" xmlrpc.lib odbc32.lib odbccp32.lib /PDB:".\Release/TestXml.pdb" /SUBSYSTEM:CONSOLE /TLBID:1 /MACHINE:I386 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib"
|
||||||
|
MSOriginalAdditionalOptions="/MACHINE:I386"/>
|
||||||
|
</Tool>
|
||||||
|
<Tool
|
||||||
|
Name="VCMIDLTool"
|
||||||
|
TypeLibraryName=".\Release/TestXml.tlb"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPostBuildEventTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreBuildEventTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreLinkEventTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCResourceCompilerTool"
|
||||||
|
PreprocessorDefinitions="NDEBUG"
|
||||||
|
Culture="1033"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCWebServiceProxyGeneratorTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCWebDeploymentTool"/>
|
||||||
|
<IntelOptions
|
||||||
|
CompilerName="1"/>
|
||||||
|
</Configuration>
|
||||||
|
<Configuration
|
||||||
|
Name="Debug|Win32"
|
||||||
|
OutputDirectory=".\Debug"
|
||||||
|
IntermediateDirectory=".\Debug"
|
||||||
|
ConfigurationType="1"
|
||||||
|
UseOfMFC="0"
|
||||||
|
ATLMinimizesCRunTimeLibraryUsage="FALSE"
|
||||||
|
CharacterSet="2">
|
||||||
|
<Tool
|
||||||
|
Name="VCCLCompilerTool"
|
||||||
|
Optimization="0"
|
||||||
|
AdditionalIncludeDirectories="..\src"
|
||||||
|
PreprocessorDefinitions="WIN32,_DEBUG,_CONSOLE"
|
||||||
|
BasicRuntimeChecks="3"
|
||||||
|
RuntimeLibrary="3"
|
||||||
|
PrecompiledHeaderFile=".\Debug/TestXml.pch"
|
||||||
|
AssemblerListingLocation=".\Debug/"
|
||||||
|
ObjectFile=".\Debug/"
|
||||||
|
ProgramDataBaseFileName=".\Debug/"
|
||||||
|
WarningLevel="3"
|
||||||
|
SuppressStartupBanner="TRUE"
|
||||||
|
DebugInformationFormat="4"
|
||||||
|
CompileAs="0"
|
||||||
|
AdditionalOptions="">
|
||||||
|
<IntelOptions
|
||||||
|
Optimization="0"
|
||||||
|
MinimalRebuild="1"
|
||||||
|
BasicRuntimeChecks="3"
|
||||||
|
RuntimeLibrary="3"
|
||||||
|
AllOptions="/c /I "..\src" /ZI /nologo /W3 /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Gm /EHsc /RTC1 /MDd /Fp".\Debug/TestXml.pch" /Fo".\Debug/" /Fd".\Debug/" /Gd"
|
||||||
|
MSOriginalAdditionalOptions=""/>
|
||||||
|
</Tool>
|
||||||
|
<Tool
|
||||||
|
Name="VCCustomBuildTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCLinkerTool"
|
||||||
|
AdditionalOptions="/MACHINE:I386"
|
||||||
|
AdditionalDependencies="xmlrpc.lib odbc32.lib odbccp32.lib"
|
||||||
|
OutputFile=".\Debug/TestXml.exe"
|
||||||
|
LinkIncremental="2"
|
||||||
|
SuppressStartupBanner="TRUE"
|
||||||
|
AdditionalLibraryDirectories="..\Debug"
|
||||||
|
GenerateDebugInformation="TRUE"
|
||||||
|
ProgramDatabaseFile=".\Debug/TestXml.pdb"
|
||||||
|
SubSystem="1">
|
||||||
|
<IntelOptions
|
||||||
|
AllOptions="/NOLOGO /OUT:".\Debug/TestXml.exe" /INCREMENTAL /LIBPATH:"..\Debug" xmlrpc.lib odbc32.lib odbccp32.lib /DEBUG /PDB:".\Debug/TestXml.pdb" /SUBSYSTEM:CONSOLE /TLBID:1 /MACHINE:I386 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib"
|
||||||
|
MSOriginalAdditionalOptions="/MACHINE:I386"/>
|
||||||
|
</Tool>
|
||||||
|
<Tool
|
||||||
|
Name="VCMIDLTool"
|
||||||
|
TypeLibraryName=".\Debug/TestXml.tlb"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPostBuildEventTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreBuildEventTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreLinkEventTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCResourceCompilerTool"
|
||||||
|
PreprocessorDefinitions="_DEBUG"
|
||||||
|
Culture="1033"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCWebServiceProxyGeneratorTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCWebDeploymentTool"/>
|
||||||
|
<IntelOptions
|
||||||
|
CompilerName="1"/>
|
||||||
|
</Configuration>
|
||||||
|
</Configurations>
|
||||||
|
<Files>
|
||||||
|
<Filter
|
||||||
|
Name="Source Files"
|
||||||
|
Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat">
|
||||||
|
<File
|
||||||
|
RelativePath=".\TestXml.cpp"/>
|
||||||
|
</Filter>
|
||||||
|
</Files>
|
||||||
|
<Globals/>
|
||||||
|
</VisualStudioProject>
|
||||||
207
test/Validator.cpp
Normal file
207
test/Validator.cpp
Normal file
|
|
@ -0,0 +1,207 @@
|
||||||
|
// Validator.cpp : XMLRPC server based on the compliancy test at validator.xmlrpc.com.
|
||||||
|
//
|
||||||
|
#include "XmlRpc.h"
|
||||||
|
using namespace XmlRpc;
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
|
||||||
|
XmlRpcServer s;
|
||||||
|
|
||||||
|
|
||||||
|
// One argument is passed, an array of structs, each with a member named curly with
|
||||||
|
// an integer value. Return the sum of those values.
|
||||||
|
|
||||||
|
class ArrayOfStructsTest : public XmlRpcServerMethod
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ArrayOfStructsTest(XmlRpcServer* s) : XmlRpcServerMethod("validator1.arrayOfStructsTest", s) {}
|
||||||
|
|
||||||
|
void execute(XmlRpcValue& params, XmlRpcValue& result)
|
||||||
|
{
|
||||||
|
std::cerr << "ArrayOfStructsTest\n";
|
||||||
|
XmlRpcValue& arg1 = params[0];
|
||||||
|
int n = arg1.size(), sum = 0;
|
||||||
|
for (int i=0; i<n; ++i)
|
||||||
|
sum += int(arg1[i]["curly"]);
|
||||||
|
|
||||||
|
result = sum;
|
||||||
|
}
|
||||||
|
} arrayOfStructsTest(&s);
|
||||||
|
|
||||||
|
|
||||||
|
// This handler takes a single parameter, a string, that contains any number of predefined
|
||||||
|
// entities, namely <, >, &, ' and ".
|
||||||
|
// The handler must return a struct that contains five fields, all numbers: ctLeftAngleBrackets,
|
||||||
|
// ctRightAngleBrackets, ctAmpersands, ctApostrophes, ctQuotes.
|
||||||
|
// To validate, the numbers must be correct.
|
||||||
|
|
||||||
|
class CountTheEntities : public XmlRpcServerMethod
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CountTheEntities(XmlRpcServer* s) : XmlRpcServerMethod("validator1.countTheEntities", s) {}
|
||||||
|
|
||||||
|
void execute(XmlRpcValue& params, XmlRpcValue& result)
|
||||||
|
{
|
||||||
|
std::cerr << "CountTheEntities\n";
|
||||||
|
std::string& arg = params[0];
|
||||||
|
int ctLeftAngleBrackets = 0;
|
||||||
|
int ctRightAngleBrackets = 0;
|
||||||
|
int ctAmpersands = 0;
|
||||||
|
int ctApostrophes = 0;
|
||||||
|
int ctQuotes = 0;
|
||||||
|
|
||||||
|
int n = int(arg.length());
|
||||||
|
for (int i=0; i<n; ++i)
|
||||||
|
switch (arg[i])
|
||||||
|
{
|
||||||
|
case '<': ++ctLeftAngleBrackets; break;
|
||||||
|
case '>': ++ctRightAngleBrackets; break;
|
||||||
|
case '&': ++ctAmpersands; break;
|
||||||
|
case '\'': ++ctApostrophes; break;
|
||||||
|
case '\"': ++ctQuotes; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
result["ctLeftAngleBrackets"] = ctLeftAngleBrackets;
|
||||||
|
result["ctRightAngleBrackets"] = ctRightAngleBrackets;
|
||||||
|
result["ctAmpersands"] = ctAmpersands;
|
||||||
|
result["ctApostrophes"] = ctApostrophes;
|
||||||
|
result["ctQuotes"] = ctQuotes;
|
||||||
|
}
|
||||||
|
} countTheEntities(&s);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// This handler takes a single parameter, a struct, containing at least three elements
|
||||||
|
// named moe, larry and curly, all <i4>s. Your handler must add the three numbers and
|
||||||
|
// return the result.
|
||||||
|
|
||||||
|
class EasyStructTest : public XmlRpcServerMethod
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
EasyStructTest(XmlRpcServer* s) : XmlRpcServerMethod("validator1.easyStructTest", s) {}
|
||||||
|
|
||||||
|
void execute(XmlRpcValue& params, XmlRpcValue& result)
|
||||||
|
{
|
||||||
|
std::cerr << "EasyStructTest\n";
|
||||||
|
XmlRpcValue& arg1 = params[0];
|
||||||
|
int sum = int(arg1["moe"]) + int(arg1["larry"]) + int(arg1["curly"]);
|
||||||
|
result = sum;
|
||||||
|
}
|
||||||
|
} easyStructTest(&s);
|
||||||
|
|
||||||
|
|
||||||
|
// This handler takes a single parameter, a struct. Your handler must return the struct.
|
||||||
|
|
||||||
|
class EchoStructTest : public XmlRpcServerMethod
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
EchoStructTest(XmlRpcServer* s) : XmlRpcServerMethod("validator1.echoStructTest", s) {}
|
||||||
|
|
||||||
|
void execute(XmlRpcValue& params, XmlRpcValue& result)
|
||||||
|
{
|
||||||
|
std::cerr << "EchoStructTest\n";
|
||||||
|
result = params[0];
|
||||||
|
}
|
||||||
|
} echoStructTest(&s);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// This handler takes six parameters, and returns an array containing all the parameters.
|
||||||
|
|
||||||
|
class ManyTypesTest : public XmlRpcServerMethod
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ManyTypesTest(XmlRpcServer* s) : XmlRpcServerMethod("validator1.manyTypesTest", s) {}
|
||||||
|
|
||||||
|
void execute(XmlRpcValue& params, XmlRpcValue& result)
|
||||||
|
{
|
||||||
|
std::cerr << "ManyTypesTest\n";
|
||||||
|
result = params;
|
||||||
|
}
|
||||||
|
} manyTypesTest(&s);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// This handler takes a single parameter, which is an array containing between 100 and
|
||||||
|
// 200 elements. Each of the items is a string, your handler must return a string
|
||||||
|
// containing the concatenated text of the first and last elements.
|
||||||
|
|
||||||
|
|
||||||
|
class ModerateSizeArrayCheck : public XmlRpcServerMethod
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ModerateSizeArrayCheck(XmlRpcServer* s) : XmlRpcServerMethod("validator1.moderateSizeArrayCheck", s) {}
|
||||||
|
|
||||||
|
void execute(XmlRpcValue& params, XmlRpcValue& result)
|
||||||
|
{
|
||||||
|
std::cerr << "ModerateSizeArrayCheck\n";
|
||||||
|
std::string s = params[0][0];
|
||||||
|
s += params[0][params[0].size()-1];
|
||||||
|
result = s;
|
||||||
|
}
|
||||||
|
} moderateSizeArrayCheck(&s);
|
||||||
|
|
||||||
|
|
||||||
|
// This handler takes a single parameter, a struct, that models a daily calendar.
|
||||||
|
// At the top level, there is one struct for each year. Each year is broken down
|
||||||
|
// into months, and months into days. Most of the days are empty in the struct
|
||||||
|
// you receive, but the entry for April 1, 2000 contains a least three elements
|
||||||
|
// named moe, larry and curly, all <i4>s. Your handler must add the three numbers
|
||||||
|
// and return the result.
|
||||||
|
|
||||||
|
class NestedStructTest : public XmlRpcServerMethod
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
NestedStructTest(XmlRpcServer* s) : XmlRpcServerMethod("validator1.nestedStructTest", s) {}
|
||||||
|
|
||||||
|
void execute(XmlRpcValue& params, XmlRpcValue& result)
|
||||||
|
{
|
||||||
|
std::cerr << "NestedStructTest\n";
|
||||||
|
XmlRpcValue& dayStruct = params[0]["2000"]["04"]["01"];
|
||||||
|
int sum = int(dayStruct["moe"]) + int(dayStruct["larry"]) + int(dayStruct["curly"]);
|
||||||
|
result = sum;
|
||||||
|
}
|
||||||
|
} nestedStructTest(&s);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// This handler takes one parameter, and returns a struct containing three elements,
|
||||||
|
// times10, times100 and times1000, the result of multiplying the number by 10, 100 and 1000.
|
||||||
|
|
||||||
|
class SimpleStructReturnTest : public XmlRpcServerMethod
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SimpleStructReturnTest(XmlRpcServer* s) : XmlRpcServerMethod("validator1.simpleStructReturnTest", s) {}
|
||||||
|
|
||||||
|
void execute(XmlRpcValue& params, XmlRpcValue& result)
|
||||||
|
{
|
||||||
|
std::cerr << "SimpleStructReturnTest\n";
|
||||||
|
int n = params[0];
|
||||||
|
result["times10"] = n * 10;
|
||||||
|
result["times100"] = n * 100;
|
||||||
|
result["times1000"] = n * 1000;
|
||||||
|
}
|
||||||
|
} simpleStructReturnTest(&s);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int main(int argc, char* argv[])
|
||||||
|
{
|
||||||
|
if (argc != 2) {
|
||||||
|
std::cerr << "Usage: Validator port\n";
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
int port = atoi(argv[1]);
|
||||||
|
|
||||||
|
XmlRpc::setVerbosity(5);
|
||||||
|
|
||||||
|
// Create the server socket on the specified port
|
||||||
|
s.bindAndListen(port);
|
||||||
|
|
||||||
|
// Wait for requests indefinitely
|
||||||
|
s.work(-1.0);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
95
test/Validator.dsp
Normal file
95
test/Validator.dsp
Normal file
|
|
@ -0,0 +1,95 @@
|
||||||
|
# Microsoft Developer Studio Project File - Name="Validator" - Package Owner=<4>
|
||||||
|
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||||
|
# ** DO NOT EDIT **
|
||||||
|
|
||||||
|
# TARGTYPE "Win32 (x86) Console Application" 0x0103
|
||||||
|
|
||||||
|
CFG=Validator - Win32 Debug
|
||||||
|
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||||
|
!MESSAGE use the Export Makefile command and run
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE NMAKE /f "Validator.mak".
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE You can specify a configuration when running NMAKE
|
||||||
|
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE NMAKE /f "Validator.mak" CFG="Validator - Win32 Debug"
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE Possible choices for configuration are:
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE "Validator - Win32 Release" (based on "Win32 (x86) Console Application")
|
||||||
|
!MESSAGE "Validator - Win32 Debug" (based on "Win32 (x86) Console Application")
|
||||||
|
!MESSAGE
|
||||||
|
|
||||||
|
# Begin Project
|
||||||
|
# PROP AllowPerConfigDependencies 0
|
||||||
|
# PROP Scc_ProjName ""
|
||||||
|
# PROP Scc_LocalPath ""
|
||||||
|
CPP=cl.exe
|
||||||
|
RSC=rc.exe
|
||||||
|
|
||||||
|
!IF "$(CFG)" == "Validator - Win32 Release"
|
||||||
|
|
||||||
|
# PROP BASE Use_MFC 0
|
||||||
|
# PROP BASE Use_Debug_Libraries 0
|
||||||
|
# PROP BASE Output_Dir "Release"
|
||||||
|
# PROP BASE Intermediate_Dir "Release"
|
||||||
|
# PROP BASE Target_Dir ""
|
||||||
|
# PROP Use_MFC 0
|
||||||
|
# PROP Use_Debug_Libraries 0
|
||||||
|
# PROP Output_Dir "Release"
|
||||||
|
# PROP Intermediate_Dir "Release"
|
||||||
|
# PROP Target_Dir ""
|
||||||
|
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /c
|
||||||
|
# ADD CPP /nologo /MD /W3 /GX /Zd /O2 /I "..\src" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /D "_WINDOWS" /FD /c
|
||||||
|
# SUBTRACT CPP /YX /Yc /Yu
|
||||||
|
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||||
|
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||||
|
BSC32=bscmake.exe
|
||||||
|
# ADD BASE BSC32 /nologo
|
||||||
|
# ADD BSC32 /nologo
|
||||||
|
LINK32=link.exe
|
||||||
|
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
|
||||||
|
# ADD LINK32 xmlrpc.lib ws2_32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /libpath:"..\release"
|
||||||
|
|
||||||
|
!ELSEIF "$(CFG)" == "Validator - Win32 Debug"
|
||||||
|
|
||||||
|
# PROP BASE Use_MFC 0
|
||||||
|
# PROP BASE Use_Debug_Libraries 1
|
||||||
|
# PROP BASE Output_Dir "Debug"
|
||||||
|
# PROP BASE Intermediate_Dir "Debug"
|
||||||
|
# PROP BASE Target_Dir ""
|
||||||
|
# PROP Use_MFC 0
|
||||||
|
# PROP Use_Debug_Libraries 1
|
||||||
|
# PROP Output_Dir "Debug"
|
||||||
|
# PROP Intermediate_Dir "Debug"
|
||||||
|
# PROP Ignore_Export_Lib 0
|
||||||
|
# PROP Target_Dir ""
|
||||||
|
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c
|
||||||
|
# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "..\src" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "_WINDOWS" /FD /GZ /c
|
||||||
|
# SUBTRACT CPP /YX /Yc /Yu
|
||||||
|
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||||
|
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||||
|
BSC32=bscmake.exe
|
||||||
|
# ADD BASE BSC32 /nologo
|
||||||
|
# ADD BSC32 /nologo
|
||||||
|
LINK32=link.exe
|
||||||
|
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
|
||||||
|
# ADD LINK32 xmlrpc.lib WS2_32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\debug"
|
||||||
|
|
||||||
|
!ENDIF
|
||||||
|
|
||||||
|
# Begin Target
|
||||||
|
|
||||||
|
# Name "Validator - Win32 Release"
|
||||||
|
# Name "Validator - Win32 Debug"
|
||||||
|
# Begin Group "Source Files"
|
||||||
|
|
||||||
|
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\Validator.cpp
|
||||||
|
# End Source File
|
||||||
|
# End Group
|
||||||
|
# End Target
|
||||||
|
# End Project
|
||||||
163
test/Validator.vcproj
Normal file
163
test/Validator.vcproj
Normal file
|
|
@ -0,0 +1,163 @@
|
||||||
|
<?xml version="1.0" encoding = "Windows-1252"?>
|
||||||
|
<VisualStudioProject
|
||||||
|
ProjectType="Visual C++"
|
||||||
|
Version="7.00"
|
||||||
|
Name="Validator"
|
||||||
|
ProjectGUID="{E68AB694-4805-43EA-A96E-21B8FE285DE4}"
|
||||||
|
SccProjectName=""
|
||||||
|
SccLocalPath="">
|
||||||
|
<Platforms>
|
||||||
|
<Platform
|
||||||
|
Name="Win32"/>
|
||||||
|
</Platforms>
|
||||||
|
<Configurations>
|
||||||
|
<Configuration
|
||||||
|
Name="Release|Win32"
|
||||||
|
OutputDirectory=".\Release"
|
||||||
|
IntermediateDirectory=".\Release"
|
||||||
|
ConfigurationType="1"
|
||||||
|
UseOfMFC="0"
|
||||||
|
ATLMinimizesCRunTimeLibraryUsage="FALSE"
|
||||||
|
CharacterSet="2">
|
||||||
|
<Tool
|
||||||
|
Name="VCCLCompilerTool"
|
||||||
|
InlineFunctionExpansion="1"
|
||||||
|
PreprocessorDefinitions="WIN32,NDEBUG,_CONSOLE,_WINDOWS"
|
||||||
|
StringPooling="TRUE"
|
||||||
|
RuntimeLibrary="2"
|
||||||
|
EnableFunctionLevelLinking="TRUE"
|
||||||
|
UsePrecompiledHeader="3"
|
||||||
|
PrecompiledHeaderThrough="stdafx.h"
|
||||||
|
PrecompiledHeaderFile=".\Release/Validator.pch"
|
||||||
|
AssemblerListingLocation=".\Release/"
|
||||||
|
ObjectFile=".\Release/"
|
||||||
|
ProgramDataBaseFileName=".\Release/"
|
||||||
|
WarningLevel="3"
|
||||||
|
SuppressStartupBanner="TRUE"
|
||||||
|
AdditionalOptions="">
|
||||||
|
<IntelOptions
|
||||||
|
Optimization="2"
|
||||||
|
InlineFuncExpansion="1"
|
||||||
|
OmitFramePtrs="1"
|
||||||
|
StringPooling="1"
|
||||||
|
RuntimeLibrary="2"
|
||||||
|
BufferSecurityCheck="1"
|
||||||
|
FunctionLevelLinking="1"
|
||||||
|
AllOptions="/c /nologo /W3 /O2 /Ob1 /Oy /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_WINDOWS" /D "_MBCS" /GF /FD /EHsc /MD /GS /Gy /Yu"stdafx.h" /Fp".\Release/Validator.pch" /Fo".\Release/" /Fd".\Release/" /Gd /TP"
|
||||||
|
MSOriginalAdditionalOptions=""/>
|
||||||
|
</Tool>
|
||||||
|
<Tool
|
||||||
|
Name="VCCustomBuildTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCLinkerTool"
|
||||||
|
AdditionalOptions="/MACHINE:I386"
|
||||||
|
AdditionalDependencies="odbc32.lib odbccp32.lib"
|
||||||
|
OutputFile=".\Release/Validator.exe"
|
||||||
|
LinkIncremental="1"
|
||||||
|
SuppressStartupBanner="TRUE"
|
||||||
|
ProgramDatabaseFile=".\Release/Validator.pdb"
|
||||||
|
SubSystem="1">
|
||||||
|
<IntelOptions
|
||||||
|
AllOptions="/NOLOGO /OUT:".\Release/Validator.exe" /INCREMENTAL:NO odbc32.lib odbccp32.lib /PDB:".\Release/Validator.pdb" /SUBSYSTEM:CONSOLE /TLBID:1 /MACHINE:I386 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib"
|
||||||
|
MSOriginalAdditionalOptions="/MACHINE:I386"/>
|
||||||
|
</Tool>
|
||||||
|
<Tool
|
||||||
|
Name="VCMIDLTool"
|
||||||
|
TypeLibraryName=".\Release/Validator.tlb"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPostBuildEventTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreBuildEventTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreLinkEventTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCResourceCompilerTool"
|
||||||
|
PreprocessorDefinitions="NDEBUG"
|
||||||
|
Culture="1033"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCWebServiceProxyGeneratorTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCWebDeploymentTool"/>
|
||||||
|
<IntelOptions
|
||||||
|
CompilerName="1"/>
|
||||||
|
</Configuration>
|
||||||
|
<Configuration
|
||||||
|
Name="Debug|Win32"
|
||||||
|
OutputDirectory=".\Debug"
|
||||||
|
IntermediateDirectory=".\Debug"
|
||||||
|
ConfigurationType="1"
|
||||||
|
UseOfMFC="0"
|
||||||
|
ATLMinimizesCRunTimeLibraryUsage="FALSE"
|
||||||
|
CharacterSet="2">
|
||||||
|
<Tool
|
||||||
|
Name="VCCLCompilerTool"
|
||||||
|
Optimization="0"
|
||||||
|
AdditionalIncludeDirectories="..\src"
|
||||||
|
PreprocessorDefinitions="WIN32,_DEBUG,_CONSOLE,_WINDOWS"
|
||||||
|
BasicRuntimeChecks="3"
|
||||||
|
RuntimeLibrary="3"
|
||||||
|
PrecompiledHeaderFile=".\Debug/Validator.pch"
|
||||||
|
AssemblerListingLocation=".\Debug/"
|
||||||
|
ObjectFile=".\Debug/"
|
||||||
|
ProgramDataBaseFileName=".\Debug/"
|
||||||
|
WarningLevel="3"
|
||||||
|
SuppressStartupBanner="TRUE"
|
||||||
|
DebugInformationFormat="4"
|
||||||
|
CompileAs="0"
|
||||||
|
AdditionalOptions="">
|
||||||
|
<IntelOptions
|
||||||
|
Optimization="0"
|
||||||
|
MinimalRebuild="1"
|
||||||
|
BasicRuntimeChecks="3"
|
||||||
|
RuntimeLibrary="3"
|
||||||
|
AllOptions="/c /I "..\src" /ZI /nologo /W3 /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_WINDOWS" /D "_MBCS" /Gm /EHsc /RTC1 /MDd /Fp".\Debug/Validator.pch" /Fo".\Debug/" /Fd".\Debug/" /Gd"
|
||||||
|
MSOriginalAdditionalOptions=""/>
|
||||||
|
</Tool>
|
||||||
|
<Tool
|
||||||
|
Name="VCCustomBuildTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCLinkerTool"
|
||||||
|
AdditionalOptions="/MACHINE:I386"
|
||||||
|
AdditionalDependencies="xmlrpc.lib WS2_32.lib odbc32.lib odbccp32.lib"
|
||||||
|
OutputFile=".\Debug/Validator.exe"
|
||||||
|
LinkIncremental="2"
|
||||||
|
SuppressStartupBanner="TRUE"
|
||||||
|
AdditionalLibraryDirectories="..\debug"
|
||||||
|
GenerateDebugInformation="TRUE"
|
||||||
|
ProgramDatabaseFile=".\Debug/Validator.pdb"
|
||||||
|
SubSystem="1">
|
||||||
|
<IntelOptions
|
||||||
|
AllOptions="/NOLOGO /OUT:".\Debug/Validator.exe" /INCREMENTAL /LIBPATH:"..\debug" xmlrpc.lib WS2_32.lib odbc32.lib odbccp32.lib /DEBUG /PDB:".\Debug/Validator.pdb" /SUBSYSTEM:CONSOLE /TLBID:1 /MACHINE:I386 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib"
|
||||||
|
MSOriginalAdditionalOptions="/MACHINE:I386"/>
|
||||||
|
</Tool>
|
||||||
|
<Tool
|
||||||
|
Name="VCMIDLTool"
|
||||||
|
TypeLibraryName=".\Debug/Validator.tlb"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPostBuildEventTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreBuildEventTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreLinkEventTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCResourceCompilerTool"
|
||||||
|
PreprocessorDefinitions="_DEBUG"
|
||||||
|
Culture="1033"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCWebServiceProxyGeneratorTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCWebDeploymentTool"/>
|
||||||
|
<IntelOptions
|
||||||
|
CompilerName="1"/>
|
||||||
|
</Configuration>
|
||||||
|
</Configurations>
|
||||||
|
<Files>
|
||||||
|
<Filter
|
||||||
|
Name="Source Files"
|
||||||
|
Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat">
|
||||||
|
<File
|
||||||
|
RelativePath=".\Validator.cpp"/>
|
||||||
|
</Filter>
|
||||||
|
</Files>
|
||||||
|
<Globals/>
|
||||||
|
</VisualStudioProject>
|
||||||
255
test/arrayOfStructsTest.xml
Normal file
255
test/arrayOfStructsTest.xml
Normal file
|
|
@ -0,0 +1,255 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<methodCall>
|
||||||
|
<methodName>validator1.arrayOfStructsTest</methodName>
|
||||||
|
<params>
|
||||||
|
<param>
|
||||||
|
<value><array>
|
||||||
|
<data>
|
||||||
|
<value>
|
||||||
|
<struct>
|
||||||
|
<member>
|
||||||
|
<name>curly</name>
|
||||||
|
<value>
|
||||||
|
<i4>-84</i4>
|
||||||
|
</value>
|
||||||
|
</member>
|
||||||
|
<member>
|
||||||
|
<name>larry</name>
|
||||||
|
<value>
|
||||||
|
<i4>87</i4>
|
||||||
|
</value>
|
||||||
|
</member>
|
||||||
|
<member>
|
||||||
|
<name>moe</name>
|
||||||
|
<value>
|
||||||
|
<i4>77</i4>
|
||||||
|
</value>
|
||||||
|
</member>
|
||||||
|
</struct>
|
||||||
|
</value>
|
||||||
|
<value>
|
||||||
|
<struct>
|
||||||
|
<member>
|
||||||
|
<name>curly</name>
|
||||||
|
<value>
|
||||||
|
<i4>-46</i4>
|
||||||
|
</value>
|
||||||
|
</member>
|
||||||
|
<member>
|
||||||
|
<name>larry</name>
|
||||||
|
<value>
|
||||||
|
<i4>27</i4>
|
||||||
|
</value>
|
||||||
|
</member>
|
||||||
|
<member>
|
||||||
|
<name>moe</name>
|
||||||
|
<value>
|
||||||
|
<i4>33</i4>
|
||||||
|
</value>
|
||||||
|
</member>
|
||||||
|
</struct>
|
||||||
|
</value>
|
||||||
|
<value>
|
||||||
|
<struct>
|
||||||
|
<member>
|
||||||
|
<name>curly</name>
|
||||||
|
<value>
|
||||||
|
<i4>-70</i4>
|
||||||
|
</value>
|
||||||
|
</member>
|
||||||
|
<member>
|
||||||
|
<name>larry</name>
|
||||||
|
<value>
|
||||||
|
<i4>89</i4>
|
||||||
|
</value>
|
||||||
|
</member>
|
||||||
|
<member>
|
||||||
|
<name>moe</name>
|
||||||
|
<value>
|
||||||
|
<i4>30</i4>
|
||||||
|
</value>
|
||||||
|
</member>
|
||||||
|
</struct>
|
||||||
|
</value>
|
||||||
|
<value>
|
||||||
|
<struct>
|
||||||
|
<member>
|
||||||
|
<name>curly</name>
|
||||||
|
<value>
|
||||||
|
<i4>-90</i4>
|
||||||
|
</value>
|
||||||
|
</member>
|
||||||
|
<member>
|
||||||
|
<name>larry</name>
|
||||||
|
<value>
|
||||||
|
<i4>42</i4>
|
||||||
|
</value>
|
||||||
|
</member>
|
||||||
|
<member>
|
||||||
|
<name>moe</name>
|
||||||
|
<value>
|
||||||
|
<i4>6</i4>
|
||||||
|
</value>
|
||||||
|
</member>
|
||||||
|
</struct>
|
||||||
|
</value>
|
||||||
|
<value>
|
||||||
|
<struct>
|
||||||
|
<member>
|
||||||
|
<name>curly</name>
|
||||||
|
<value>
|
||||||
|
<i4>-28</i4>
|
||||||
|
</value>
|
||||||
|
</member>
|
||||||
|
<member>
|
||||||
|
<name>larry</name>
|
||||||
|
<value>
|
||||||
|
<i4>96</i4>
|
||||||
|
</value>
|
||||||
|
</member>
|
||||||
|
<member>
|
||||||
|
<name>moe</name>
|
||||||
|
<value>
|
||||||
|
<i4>92</i4>
|
||||||
|
</value>
|
||||||
|
</member>
|
||||||
|
</struct>
|
||||||
|
</value>
|
||||||
|
<value>
|
||||||
|
<struct>
|
||||||
|
<member>
|
||||||
|
<name>curly</name>
|
||||||
|
<value>
|
||||||
|
<i4>-31</i4>
|
||||||
|
</value>
|
||||||
|
</member>
|
||||||
|
<member>
|
||||||
|
<name>larry</name>
|
||||||
|
<value>
|
||||||
|
<i4>81</i4>
|
||||||
|
</value>
|
||||||
|
</member>
|
||||||
|
<member>
|
||||||
|
<name>moe</name>
|
||||||
|
<value>
|
||||||
|
<i4>85</i4>
|
||||||
|
</value>
|
||||||
|
</member>
|
||||||
|
</struct>
|
||||||
|
</value>
|
||||||
|
<value>
|
||||||
|
<struct>
|
||||||
|
<member>
|
||||||
|
<name>curly</name>
|
||||||
|
<value>
|
||||||
|
<i4>-18</i4>
|
||||||
|
</value>
|
||||||
|
</member>
|
||||||
|
<member>
|
||||||
|
<name>larry</name>
|
||||||
|
<value>
|
||||||
|
<i4>62</i4>
|
||||||
|
</value>
|
||||||
|
</member>
|
||||||
|
<member>
|
||||||
|
<name>moe</name>
|
||||||
|
<value>
|
||||||
|
<i4>9</i4>
|
||||||
|
</value>
|
||||||
|
</member>
|
||||||
|
</struct>
|
||||||
|
</value>
|
||||||
|
<value>
|
||||||
|
<struct>
|
||||||
|
<member>
|
||||||
|
<name>curly</name>
|
||||||
|
<value>
|
||||||
|
<i4>-98</i4>
|
||||||
|
</value>
|
||||||
|
</member>
|
||||||
|
<member>
|
||||||
|
<name>larry</name>
|
||||||
|
<value>
|
||||||
|
<i4>79</i4>
|
||||||
|
</value>
|
||||||
|
</member>
|
||||||
|
<member>
|
||||||
|
<name>moe</name>
|
||||||
|
<value>
|
||||||
|
<i4>66</i4>
|
||||||
|
</value>
|
||||||
|
</member>
|
||||||
|
</struct>
|
||||||
|
</value>
|
||||||
|
<value>
|
||||||
|
<struct>
|
||||||
|
<member>
|
||||||
|
<name>curly</name>
|
||||||
|
<value>
|
||||||
|
<i4>-3</i4>
|
||||||
|
</value>
|
||||||
|
</member>
|
||||||
|
<member>
|
||||||
|
<name>larry</name>
|
||||||
|
<value>
|
||||||
|
<i4>59</i4>
|
||||||
|
</value>
|
||||||
|
</member>
|
||||||
|
<member>
|
||||||
|
<name>moe</name>
|
||||||
|
<value>
|
||||||
|
<i4>80</i4>
|
||||||
|
</value>
|
||||||
|
</member>
|
||||||
|
</struct>
|
||||||
|
</value>
|
||||||
|
<value>
|
||||||
|
<struct>
|
||||||
|
<member>
|
||||||
|
<name>curly</name>
|
||||||
|
<value>
|
||||||
|
<i4>-83</i4>
|
||||||
|
</value>
|
||||||
|
</member>
|
||||||
|
<member>
|
||||||
|
<name>larry</name>
|
||||||
|
<value>
|
||||||
|
<i4>27</i4>
|
||||||
|
</value>
|
||||||
|
</member>
|
||||||
|
<member>
|
||||||
|
<name>moe</name>
|
||||||
|
<value>
|
||||||
|
<i4>19</i4>
|
||||||
|
</value>
|
||||||
|
</member>
|
||||||
|
</struct>
|
||||||
|
</value>
|
||||||
|
<value>
|
||||||
|
<struct>
|
||||||
|
<member>
|
||||||
|
<name>curly</name>
|
||||||
|
<value>
|
||||||
|
<i4>-85</i4>
|
||||||
|
</value>
|
||||||
|
</member>
|
||||||
|
<member>
|
||||||
|
<name>larry</name>
|
||||||
|
<value>
|
||||||
|
<i4>4</i4>
|
||||||
|
</value>
|
||||||
|
</member>
|
||||||
|
<member>
|
||||||
|
<name>moe</name>
|
||||||
|
<value>
|
||||||
|
<i4>16</i4>
|
||||||
|
</value>
|
||||||
|
</member>
|
||||||
|
</struct>
|
||||||
|
</value>
|
||||||
|
</data>
|
||||||
|
</array></value>
|
||||||
|
</param>
|
||||||
|
</params>
|
||||||
|
</methodCall>
|
||||||
|
|
||||||
10
test/countTheEntities.xml
Normal file
10
test/countTheEntities.xml
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<methodCall>
|
||||||
|
<methodName>validator1.countTheEntities</methodName>
|
||||||
|
<params>
|
||||||
|
<param>
|
||||||
|
<value>&'<p"dgt"&>'<&"'<s>>ehv<j><>iu'<<<y"'>qo>"z"f<l&'"akn<&r'c'wbm&&x''</value>
|
||||||
|
</param>
|
||||||
|
</params>
|
||||||
|
</methodCall>
|
||||||
|
|
||||||
29
test/easyStructTest.xml
Normal file
29
test/easyStructTest.xml
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<methodCall>
|
||||||
|
<methodName>validator1.easyStructTest</methodName>
|
||||||
|
<params>
|
||||||
|
<param>
|
||||||
|
<value><struct>
|
||||||
|
<member>
|
||||||
|
<name>curly</name>
|
||||||
|
<value>
|
||||||
|
<i4>-78</i4>
|
||||||
|
</value>
|
||||||
|
</member>
|
||||||
|
<member>
|
||||||
|
<name>larry</name>
|
||||||
|
<value>
|
||||||
|
<i4>23</i4>
|
||||||
|
</value>
|
||||||
|
</member>
|
||||||
|
<member>
|
||||||
|
<name>moe</name>
|
||||||
|
<value>
|
||||||
|
<i4>38</i4>
|
||||||
|
</value>
|
||||||
|
</member>
|
||||||
|
</struct></value>
|
||||||
|
</param>
|
||||||
|
</params>
|
||||||
|
</methodCall>
|
||||||
|
|
||||||
9
test/echo.xml
Normal file
9
test/echo.xml
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<methodCall>
|
||||||
|
<methodName>echo</methodName>
|
||||||
|
<params>
|
||||||
|
<param><value><string>Hello Chris</string></value></param>
|
||||||
|
<param><value><i4>123</i4></value></param>
|
||||||
|
</params>
|
||||||
|
</methodCall>
|
||||||
|
|
||||||
261
test/echoStructTest.xml
Normal file
261
test/echoStructTest.xml
Normal file
|
|
@ -0,0 +1,261 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<methodCall>
|
||||||
|
<methodName>validator1.echoStructTest</methodName>
|
||||||
|
<params>
|
||||||
|
<param>
|
||||||
|
<value><struct>
|
||||||
|
<member>
|
||||||
|
<name>substruct0</name>
|
||||||
|
<value>
|
||||||
|
<struct>
|
||||||
|
<member>
|
||||||
|
<name>curly</name>
|
||||||
|
<value>
|
||||||
|
<i4>-76</i4>
|
||||||
|
</value>
|
||||||
|
</member>
|
||||||
|
<member>
|
||||||
|
<name>larry</name>
|
||||||
|
<value>
|
||||||
|
<i4>31</i4>
|
||||||
|
</value>
|
||||||
|
</member>
|
||||||
|
<member>
|
||||||
|
<name>moe</name>
|
||||||
|
<value>
|
||||||
|
<i4>44</i4>
|
||||||
|
</value>
|
||||||
|
</member>
|
||||||
|
</struct>
|
||||||
|
</value>
|
||||||
|
</member>
|
||||||
|
<member>
|
||||||
|
<name>substruct1</name>
|
||||||
|
<value>
|
||||||
|
<struct>
|
||||||
|
<member>
|
||||||
|
<name>curly</name>
|
||||||
|
<value>
|
||||||
|
<i4>-9</i4>
|
||||||
|
</value>
|
||||||
|
</member>
|
||||||
|
<member>
|
||||||
|
<name>larry</name>
|
||||||
|
<value>
|
||||||
|
<i4>42</i4>
|
||||||
|
</value>
|
||||||
|
</member>
|
||||||
|
<member>
|
||||||
|
<name>moe</name>
|
||||||
|
<value>
|
||||||
|
<i4>57</i4>
|
||||||
|
</value>
|
||||||
|
</member>
|
||||||
|
</struct>
|
||||||
|
</value>
|
||||||
|
</member>
|
||||||
|
<member>
|
||||||
|
<name>substruct2</name>
|
||||||
|
<value>
|
||||||
|
<struct>
|
||||||
|
<member>
|
||||||
|
<name>curly</name>
|
||||||
|
<value>
|
||||||
|
<i4>-15</i4>
|
||||||
|
</value>
|
||||||
|
</member>
|
||||||
|
<member>
|
||||||
|
<name>larry</name>
|
||||||
|
<value>
|
||||||
|
<i4>69</i4>
|
||||||
|
</value>
|
||||||
|
</member>
|
||||||
|
<member>
|
||||||
|
<name>moe</name>
|
||||||
|
<value>
|
||||||
|
<i4>78</i4>
|
||||||
|
</value>
|
||||||
|
</member>
|
||||||
|
</struct>
|
||||||
|
</value>
|
||||||
|
</member>
|
||||||
|
<member>
|
||||||
|
<name>substruct3</name>
|
||||||
|
<value>
|
||||||
|
<struct>
|
||||||
|
<member>
|
||||||
|
<name>curly</name>
|
||||||
|
<value>
|
||||||
|
<i4>-91</i4>
|
||||||
|
</value>
|
||||||
|
</member>
|
||||||
|
<member>
|
||||||
|
<name>larry</name>
|
||||||
|
<value>
|
||||||
|
<i4>66</i4>
|
||||||
|
</value>
|
||||||
|
</member>
|
||||||
|
<member>
|
||||||
|
<name>moe</name>
|
||||||
|
<value>
|
||||||
|
<i4>4</i4>
|
||||||
|
</value>
|
||||||
|
</member>
|
||||||
|
</struct>
|
||||||
|
</value>
|
||||||
|
</member>
|
||||||
|
<member>
|
||||||
|
<name>substruct4</name>
|
||||||
|
<value>
|
||||||
|
<struct>
|
||||||
|
<member>
|
||||||
|
<name>curly</name>
|
||||||
|
<value>
|
||||||
|
<i4>-47</i4>
|
||||||
|
</value>
|
||||||
|
</member>
|
||||||
|
<member>
|
||||||
|
<name>larry</name>
|
||||||
|
<value>
|
||||||
|
<i4>66</i4>
|
||||||
|
</value>
|
||||||
|
</member>
|
||||||
|
<member>
|
||||||
|
<name>moe</name>
|
||||||
|
<value>
|
||||||
|
<i4>8</i4>
|
||||||
|
</value>
|
||||||
|
</member>
|
||||||
|
</struct>
|
||||||
|
</value>
|
||||||
|
</member>
|
||||||
|
<member>
|
||||||
|
<name>substruct5</name>
|
||||||
|
<value>
|
||||||
|
<struct>
|
||||||
|
<member>
|
||||||
|
<name>curly</name>
|
||||||
|
<value>
|
||||||
|
<i4>-68</i4>
|
||||||
|
</value>
|
||||||
|
</member>
|
||||||
|
<member>
|
||||||
|
<name>larry</name>
|
||||||
|
<value>
|
||||||
|
<i4>26</i4>
|
||||||
|
</value>
|
||||||
|
</member>
|
||||||
|
<member>
|
||||||
|
<name>moe</name>
|
||||||
|
<value>
|
||||||
|
<i4>87</i4>
|
||||||
|
</value>
|
||||||
|
</member>
|
||||||
|
</struct>
|
||||||
|
</value>
|
||||||
|
</member>
|
||||||
|
<member>
|
||||||
|
<name>substruct6</name>
|
||||||
|
<value>
|
||||||
|
<struct>
|
||||||
|
<member>
|
||||||
|
<name>curly</name>
|
||||||
|
<value>
|
||||||
|
<i4>-59</i4>
|
||||||
|
</value>
|
||||||
|
</member>
|
||||||
|
<member>
|
||||||
|
<name>larry</name>
|
||||||
|
<value>
|
||||||
|
<i4>20</i4>
|
||||||
|
</value>
|
||||||
|
</member>
|
||||||
|
<member>
|
||||||
|
<name>moe</name>
|
||||||
|
<value>
|
||||||
|
<i4>74</i4>
|
||||||
|
</value>
|
||||||
|
</member>
|
||||||
|
</struct>
|
||||||
|
</value>
|
||||||
|
</member>
|
||||||
|
<member>
|
||||||
|
<name>substruct7</name>
|
||||||
|
<value>
|
||||||
|
<struct>
|
||||||
|
<member>
|
||||||
|
<name>curly</name>
|
||||||
|
<value>
|
||||||
|
<i4>-57</i4>
|
||||||
|
</value>
|
||||||
|
</member>
|
||||||
|
<member>
|
||||||
|
<name>larry</name>
|
||||||
|
<value>
|
||||||
|
<i4>30</i4>
|
||||||
|
</value>
|
||||||
|
</member>
|
||||||
|
<member>
|
||||||
|
<name>moe</name>
|
||||||
|
<value>
|
||||||
|
<i4>75</i4>
|
||||||
|
</value>
|
||||||
|
</member>
|
||||||
|
</struct>
|
||||||
|
</value>
|
||||||
|
</member>
|
||||||
|
<member>
|
||||||
|
<name>substruct8</name>
|
||||||
|
<value>
|
||||||
|
<struct>
|
||||||
|
<member>
|
||||||
|
<name>curly</name>
|
||||||
|
<value>
|
||||||
|
<i4>-34</i4>
|
||||||
|
</value>
|
||||||
|
</member>
|
||||||
|
<member>
|
||||||
|
<name>larry</name>
|
||||||
|
<value>
|
||||||
|
<i4>33</i4>
|
||||||
|
</value>
|
||||||
|
</member>
|
||||||
|
<member>
|
||||||
|
<name>moe</name>
|
||||||
|
<value>
|
||||||
|
<i4>30</i4>
|
||||||
|
</value>
|
||||||
|
</member>
|
||||||
|
</struct>
|
||||||
|
</value>
|
||||||
|
</member>
|
||||||
|
<member>
|
||||||
|
<name>substruct9</name>
|
||||||
|
<value>
|
||||||
|
<struct>
|
||||||
|
<member>
|
||||||
|
<name>curly</name>
|
||||||
|
<value>
|
||||||
|
<i4>-64</i4>
|
||||||
|
</value>
|
||||||
|
</member>
|
||||||
|
<member>
|
||||||
|
<name>larry</name>
|
||||||
|
<value>
|
||||||
|
<i4>98</i4>
|
||||||
|
</value>
|
||||||
|
</member>
|
||||||
|
<member>
|
||||||
|
<name>moe</name>
|
||||||
|
<value>
|
||||||
|
<i4>17</i4>
|
||||||
|
</value>
|
||||||
|
</member>
|
||||||
|
</struct>
|
||||||
|
</value>
|
||||||
|
</member>
|
||||||
|
</struct></value>
|
||||||
|
</param>
|
||||||
|
</params>
|
||||||
|
</methodCall>
|
||||||
|
|
||||||
1
test/pngnow.png
Normal file
1
test/pngnow.png
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
‰PNG
|
||||||
Loading…
Reference in New Issue
Block a user