From ce4c51763f7952008ce7e9561e08493af7c4aa55 Mon Sep 17 00:00:00 2001 From: Moritz Maisel Date: Fri, 19 Oct 2007 19:35:44 +0200 Subject: [PATCH] initial checkin --- COPYING | 459 +++++++++++++ CREDITS | 8 + group/ABLD.BAT | 15 + group/bld.inf | 21 + group/xmlrpc4s.mmp | 47 ++ inc/Base64.h | 65 ++ inc/HttpClientEngine.h | 169 +++++ inc/KeyValueTable.h | 193 ++++++ inc/RpcExecutableInterface.h | 63 ++ inc/Vector.h | 152 +++++ inc/XmlRpcClient.h | 131 ++++ inc/XmlRpcClientInterface.h | 52 ++ inc/XmlRpcConstants.h | 125 ++++ inc/XmlRpcResponseHandlerInterface.h | 33 + inc/XmlRpcUtil.h | 71 ++ inc/XmlRpcValue.h | 373 +++++++++++ inc/XmlUtil.h | 111 ++++ src/Base64.cpp | 144 ++++ src/HttpClientEngine.cpp | 303 +++++++++ src/KeyValueTable.cpp | 168 +++++ src/Vector.cpp | 138 ++++ src/XMLUtil.cpp | 117 ++++ src/XmlRpcClient.cpp | 216 ++++++ src/XmlRpcUtil.cpp | 97 +++ src/XmlRpcValue.cpp | 1201 ++++++++++++++++++++++++++++++++++ 25 files changed, 4472 insertions(+) create mode 100644 COPYING create mode 100644 CREDITS create mode 100644 group/ABLD.BAT create mode 100644 group/bld.inf create mode 100644 group/xmlrpc4s.mmp create mode 100644 inc/Base64.h create mode 100644 inc/HttpClientEngine.h create mode 100644 inc/KeyValueTable.h create mode 100644 inc/RpcExecutableInterface.h create mode 100644 inc/Vector.h create mode 100644 inc/XmlRpcClient.h create mode 100644 inc/XmlRpcClientInterface.h create mode 100644 inc/XmlRpcConstants.h create mode 100644 inc/XmlRpcResponseHandlerInterface.h create mode 100644 inc/XmlRpcUtil.h create mode 100644 inc/XmlRpcValue.h create mode 100644 inc/XmlUtil.h create mode 100644 src/Base64.cpp create mode 100644 src/HttpClientEngine.cpp create mode 100644 src/KeyValueTable.cpp create mode 100644 src/Vector.cpp create mode 100644 src/XMLUtil.cpp create mode 100644 src/XmlRpcClient.cpp create mode 100644 src/XmlRpcUtil.cpp create mode 100644 src/XmlRpcValue.cpp diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..91accfb --- /dev/null +++ b/COPYING @@ -0,0 +1,459 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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 + diff --git a/CREDITS b/CREDITS new file mode 100644 index 0000000..64c2864 --- /dev/null +++ b/CREDITS @@ -0,0 +1,8 @@ +Author of xmlrpc-s (base of xmlrpc4s) + + Timo Salminen + +HTTP communication and asynchronous callback + + Moritz Maisel + \ No newline at end of file diff --git a/group/ABLD.BAT b/group/ABLD.BAT new file mode 100644 index 0000000..f064eef --- /dev/null +++ b/group/ABLD.BAT @@ -0,0 +1,15 @@ +@ECHO OFF + +REM Bldmake-generated batch file - ABLD.BAT +REM ** DO NOT EDIT ** + +perl -S ABLD.PL "\Symbian\Carbide\workspace\xmlrpc4s\group\\" %1 %2 %3 %4 %5 %6 %7 %8 %9 +if errorlevel==1 goto CheckPerl +goto End + +:CheckPerl +perl -v >NUL +if errorlevel==1 echo Is Perl, version 5.003_07 or later, installed? +goto End + +:End diff --git a/group/bld.inf b/group/bld.inf new file mode 100644 index 0000000..d06de9c --- /dev/null +++ b/group/bld.inf @@ -0,0 +1,21 @@ +/* +============================================================================ + Name : bld.inf + Author : Moritz Maisel + Copyright : LGPL + Description : This file provides the information required for building the + whole of a xmlrpc4s. +============================================================================ +*/ + +PRJ_PLATFORMS +#ifdef EKA2 +WINSCW ARMV5 GCCE ARMV5_ABIV2 +#else +WINSCW THUMB ARMI +#endif + +PRJ_EXPORTS + +PRJ_MMPFILES +xmlrpc4s.mmp diff --git a/group/xmlrpc4s.mmp b/group/xmlrpc4s.mmp new file mode 100644 index 0000000..ebbfe31 --- /dev/null +++ b/group/xmlrpc4s.mmp @@ -0,0 +1,47 @@ +/* +============================================================================ + Name : xmlrpc4s.mmp + Author : Moritz Maisel + Copyright : LGPL v2.1 + Description : A XMLRPC library for Symbian with asynchronous callback interface. +============================================================================ +*/ + +TARGET xmlrpc4s.dll +TARGETTYPE dll +UID 0x1000008d 0xE849C9AF + +USERINCLUDE ..\inc +SYSTEMINCLUDE \epoc32\include + + + +//By default, the build tools look for the WINSCW def file in a BWINS directory +//(at the same level as the directory containing the mmp file), +//the GCC ARM def file in a BMARM directory, and the ARMV5 def file in a EABI directory. +//If def files are stored in these locations, the project files does not need to specify +//the location of the def files explicitly. If you want to store the def files in some other +//location, you will need to specify in the project file where the .def files are using +//the deffile keyword. + +//The following commented out code shows how the build system uses the implicit +// location for defiles. To create the DEF files Choose Project > Freeze Exports from Carbide +// or run 'abld freeze' from the command-line +//#if defined (WINS) +// DEFFILE ..\bwins\xmlrpc4s.def +//#elif defined (GCC32) +// DEFFILE ..\bmarm\xmlrpc4s.def +//#else +// DEFFILE ..\eabi\xmlrpc4s.def +//#endif + +nostrictdef + +LIBRARY euser.lib bafl.lib http.lib inetprotutil.lib ecom.lib + + +SOURCEPATH ..\src +SOURCE Base64.cpp KeyValueTable.cpp Vector.cpp XMLUtil.cpp XmlRpcClient.cpp XmlRpcUtil.cpp XmlRpcValue.cpp HttpClientEngine.cpp + +EXPORTUNFROZEN + diff --git a/inc/Base64.h b/inc/Base64.h new file mode 100644 index 0000000..14e5b3a --- /dev/null +++ b/inc/Base64.h @@ -0,0 +1,65 @@ +/* + * Base64.h + * + * xmlrpc4s - XML-RPC library for Symbian environments + * based on xmlrpc-s - Copyright (C) 2007 Timo Salminen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation. + * + * 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 + * + * Contact: Timo Salminen + */ + + +#ifndef __BASE64_H_ +#define __BASE64_H_ + + +#include + + +/** +* Contains methods for encoding and decoding base64 data: +* +* @author: Timo Salminen +*/ + +class TBase64 { + + + +public: + + + /** + * Encodes the given binary data into base64 form + * + * @param aSrcString Source data + * + * @return HBufC8, encoded data + */ + IMPORT_C static HBufC8* Base64_EncodeL( const TDesC8& aSrcString ); + + + /** + * Decodes the given base64 data into binary form + * + * @param aSrcString Source data + * + * @return HBufC8, decoded data + */ + IMPORT_C static HBufC8* Base64_DecodeL( const TDesC8& aSrcString ); + + +}; +#endif \ No newline at end of file diff --git a/inc/HttpClientEngine.h b/inc/HttpClientEngine.h new file mode 100644 index 0000000..fb3d3ef --- /dev/null +++ b/inc/HttpClientEngine.h @@ -0,0 +1,169 @@ +/* + * HttpClientEngine.h + * + * xmlrpc4s - XML-RPC library for Symbian environments + * Copyright (C) 2007 Moritz Maisel, indigo networks GmbH + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation. + * + * 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 + * + * Contact: Moritz Maisel + */ + +#ifndef HTTPCLIENTENGINE_H_ +#define HTTPCLIENTENGINE_H_ + +#include +#include +#include +#include +#include "XmlRpcClientInterface.h" +#include +#include +#include + +/* Constants: */ +_LIT8(KClientVendor, "Moritz Maisel, indigo networks"); +_LIT8(KClientName, "xmlrpc4s"); +_LIT8(KClientVersion, "0.1 alpha"); + +/* + Class: HttpClientEngine + Implements HTTP client comminication for use by SamuraiCLient class. + + See Also: + + */ +class CHttpClientEngine : public CBase, public MHTTPTransactionCallback, + public MHTTPDataSupplier, public MHTTPAuthenticationCallback + { + public: + /* + Function: ~CHttpClientEngine + Destructor. + */ + virtual ~CHttpClientEngine( ); + /* + Function: NewL + Creates an instance of HttpClientEngine. + */ + static CHttpClientEngine* NewL( ); + + /* + Function: NewLC + Creates an instance of HttpClientEngine. + */ + static CHttpClientEngine* NewLC( ); + + /* + Function: IssueHttpPostL + Issues a HTTP POST request. + */ + void IssueHttpPostL(MXmlRpcResponseHandlerInterface* aHandler, const TDesC8* aUri, const TDesC8* aContentType, + const TDesC8* aBody, RBuf8* aResultBody); + + /* + Function: CancelTransaction + Closes a running transaction and frees its resources. + */ + void CancelTransaction( ); + + /* + Function: IsRunning + Check if the transaction is running. + */ + inline TBool IsRunning( ) + { + return iRunning; + } + ; + + /* + Function: MHFRunL + Implements the "per-transaction callback for receiving HTTP events". + The HTTP API calls this method on HTTP events and HTTP errors (e.g. + HTTP 404). Note that Errors with the API itself are handled by + MHFRunError()! + + See Also: + MHFRunError() + */ + void MHFRunL( RHTTPTransaction aTransaction, const THTTPEvent & aEvent ); + + /* + Function: MHFRunError + Called from the HTTP API when there is an error with the API itself, + like lacking internet connection settings in the Control Panel. + Note that HTTP errors are handled in MHFRunL()! + + See Also: + MHFRunL() + */ + TInt MHFRunError(TInt aError, RHTTPTransaction aTransaction, const THTTPEvent& aEvent ); + + TBool GetNextDataPart( TPtrC8 & aDataPart ); + + void ReleaseData( ); + + TInt OverallDataSize( ); + + /* Function: Reset + Called whenever the HTTP API fails to send the entire body of + the request. + */ + TInt Reset( ); + + /* Function: SetCredentialsL + To set the credentials used for HTTP POST + */ + TBool SetCredentialsL(const TDesC8* aUser, const TDesC8* aPass); + + /* Function: GetCredentialsL + Called by the framework to obtain HTTP Auth credentials + */ + TBool GetCredentialsL(const TUriC8& aUri, RString aRealm, + RStringF aAuthenticationType, RString& aUsername, + RString& aPassword); + private: + /* + Function: CHttpClientEngine + First phase constructor. + */ + CHttpClientEngine( ); + + /* + Function: ConstructL + Initializes attributes after object construction. + */ + void ConstructL( ); + + /* + Function: SetHeaderL + Set HTTP header fields. + */ + void SetHeaderL(RHTTPHeaders aHeaders, TInt aHdrField, + const TDesC8& aHdrValue ); + + /* Attributes: */ + TBool iRunning; + RHTTPSession iSession; + RBuf8* iResponseBodyPtr; + RBuf8 iPostData; + RHTTPTransaction iTransaction; + MXmlRpcResponseHandlerInterface* iResponseHandler; + RBuf8 iHttpUsername; + RBuf8 iHttpPassword; + TBool iCredentialsSet; + }; + +#endif /*CHTTPCLIENTENGINE_H_*/ diff --git a/inc/KeyValueTable.h b/inc/KeyValueTable.h new file mode 100644 index 0000000..18e11d1 --- /dev/null +++ b/inc/KeyValueTable.h @@ -0,0 +1,193 @@ +/* + * KeyValueTable.h + * + * xmlrpc4s - XML-RPC library for Symbian environments + * based on xmlrpc-s - Copyright (C) 2007 Timo Salminen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation. + * + * 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 + * + * Contact: Timo Salminen + */ + + +#ifndef __KEYVALUETABLE_H_ +#define __KEYVALUETABLE_H_ + +#include +#include +#include + + +#include "XmlRpcValue.h" + + +//Forward declarations +class CXmlRpcValue; + + +/** +* This class is a container for key-value pair, similar to Java Hashtable. +* The key can be of any type, derived from TDesC class. Usually it represents +* a simple string value. The value is of a CXmlRpcValue class, that can contain +* primitive types, CVector or another CKeyValueTable. For more information +* see the CKeyValueTable API document +* +* @author Timo Salminen +*/ + +class CKeyValueTable : public CBase { +public: + + //! Two-phased contructor + IMPORT_C static CKeyValueTable* NewL(); + + //! Two-phased contructor + IMPORT_C static CKeyValueTable* NewLC(); + + //! Destructor + IMPORT_C virtual ~CKeyValueTable(); + + + /** + * Appends the given value to the table with given key. The ownership of + * the given XmlRpcValue parameter will be transferred. If value with given + * key already exists in the table, it will be deleted and replaced by the + * new one. + * + * @param aKey A key for the value to be stored. + * @param aValue A value to be stored. + */ + IMPORT_C void AddElementL( const TDesC8& aKey, CXmlRpcValue* aValue ); + + + /** + * Returns the value indicated by the given key. The ownership will not be + * transferred!. If the given key is not found, returns NULL. + * + * @param aKey A pointer to the value to be searched or NULL if key is not found. + * @return Value indicated by the given key. + */ + IMPORT_C CXmlRpcValue* GetValue( const TDesC8& aKey ) const; + + + /** + * Returns HBufC* the key value at given position. If the given + * parameter is out of scope, that is, negative or bigger than + * the element count of the table, method will return zero length + * empty buffer. + * + * @param aPos Position of the value. + * @return Key at given position. + */ + IMPORT_C HBufC8* KeyAtL( TInt aPos ) const; + + + /** + * Returns the value stored at the given position. If + * the given position is out of scope, that is, negative or + * bigger than the element count of the table, the method will + * return NULL! + * + * @param aPos Position of the value. + * @return Value at given position. + */ + IMPORT_C CXmlRpcValue* ValueAt( TInt aPos ) const; + + + /** + * Finds the position of the given key in a table. If key is found, + * the method will return 0 and the position will be stored in given + * parameter. If no key is found with given parameter, the method will + * return non-zero value, and a size of the table in given aPos parameter. + * + * @param aKey A reference to the key to be searched. + * @param aPos The position of found key will be stored in here. + * @return 0, if a key is found, otherwise non-zero integer value. + */ + IMPORT_C TInt Find( const TDesC8& aKey, TInt* aPos ) const; + + + /** + * Returns ETrue, if the given key is found in the table, otherwise EFalse. + * + * @param aKey Key to be searched. + * @return ETrue, if the given key is found. Otherwise EFalse. + */ + IMPORT_C TBool ContainsKey( const TDesC8& aKey ); + + + /** + * Deletes the table element in given position. + * + * @param aPos A table element to be deleted. + * @return ETrue, if the deletion was successful, otherwise EFalse. + */ + IMPORT_C TBool Delete( const TInt aPos ); + + + /** + * Deletes the table element of given key value. + * + * @param aKey Key of the table element to be deleted. + * @return ETrue, if the deletion was successful, otherwise EFalse. + */ + IMPORT_C TBool Delete( const TDesC8& aKey ); + + + /** + * Indicates whether the table is empty or not. + * + * @return ETrue, if the table is empty, otherwise EFalse. + */ + IMPORT_C TBool IsEmpty(); + + + /** + * Returns amount of elements stored into this table. + * + * @return Amount of elements stored into the table. + */ + IMPORT_C TInt ElementCount() const; + + + /** + * Duplicates the table. + * + * @return Duplicated table. + */ + IMPORT_C CKeyValueTable* DuplicateL() const; + + + /** + * Checks if table equals to the given CKeyValue table. Tables are + * equal if they contain same amount of values and if contained keys + * and values are equal. + * + * @return ETrue, if tables are equal, otherwise EFalse. + */ + IMPORT_C TBool Equals( CKeyValueTable* aTable ) const; + +private: + + //!< Constructor + CKeyValueTable(); + //!< Constructs the member data + void ConstructL(); + + CDesC8ArrayFlat* iKeyArray; + RPointerArray* iValueArray; +}; +#endif + + diff --git a/inc/RpcExecutableInterface.h b/inc/RpcExecutableInterface.h new file mode 100644 index 0000000..3ca8aaa --- /dev/null +++ b/inc/RpcExecutableInterface.h @@ -0,0 +1,63 @@ +/* + * RpcExecutableInterface.h + * + * xmlrpc4s - XML-RPC library for Symbian environments + * based on xmlrpc-s - Copyright (C) 2007 Timo Salminen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation. + * + * 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 + * + * Contact: Timo Salminen + */ + +#ifndef __RPCEXECUTABLEINTERFACE_H_ +#define __RPCEXECUTABLEINTERFACE_H_ + + +#include "XmlRpcValue.h" + + +/** + * Interface, using which XmlRpcServer executes incoming RPC calls on target + * object. Must be implemented by objects that offers RPC executable services. + * + * @author Timo Salminen + */ + +class MRpcExecutableInterface { +public: + + + /** + * Executes the given method. Used by XmlRpcServer. + * + * @param aMethod A name of the method to be executed + * @param aArray Parameters of the method call + * @param aResult Return value + * @return ETrue, if successful. Otherwise EFalse. + */ + virtual TBool ExecuteL( const TDesC& aMethod, + const RPointerArray& aArray, + CXmlRpcValue& aResult ) = 0; + + + /** + * Returns ID of the RPC executable component + * + * @return Descriptor containing ID of the RPC executable component + */ + virtual TDesC& GetRpcExecutableId() const = 0; + + +}; +#endif diff --git a/inc/Vector.h b/inc/Vector.h new file mode 100644 index 0000000..bb600fd --- /dev/null +++ b/inc/Vector.h @@ -0,0 +1,152 @@ +/* + * Vector.h + * + * xmlrpc4s - XML-RPC library for Symbian environments + * based on xmlrpc-s - Copyright (C) 2007 Timo Salminen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation. + * + * 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 + * + * Contact: Timo Salminen + */ + + +#ifndef __VECTOR_H_ +#define __VECTOR_H_ + + +#include +#include +#include + + +#include "XmlRpcValue.h" + + +//Forward declarations +class CXmlRpcValue; + + + +/** +* This class is a container for CXmlRpcValue objects, similar to Java Vector. +* +* @author Timo Salminen +*/ +class CVector : public CBase { + +public: + + //! Two-phased contructor + IMPORT_C static CVector* NewL(); + + //! Two-phased contructor + IMPORT_C static CVector* NewLC(); + + //! Destructor + IMPORT_C virtual ~CVector(); + + + /** + * Appends the given value to the vector. The ownership of the appended value + * will be transferred. Returns ETrue if operation was successful, otherwise + * EFalse. + * + * @param aValue A value to be stored. + * @return ETrue, if the operation was successful, otherwise EFalse. + */ + IMPORT_C TBool Add( CXmlRpcValue* aValue ); + + + /** + * Returns the value, stored at the given position. If the given position + * is out of scope, that is, negative or bigger than the element count + * of the table, the method will return NULL! + * + * @param aPos Position of the desired value. Ownership is not + * transferred. + * @return Pointer to the requested CXmlRpcValue. + */ + IMPORT_C CXmlRpcValue* ValueAt( TInt aPos ) const; + + + /** + * Finds the position of the given value. If the value is found, the method + * will return the position index, otherwise KErrNotFound. + * + * @param aValue A value to be searched. + * @return Position or KErrNotFound. + */ + IMPORT_C TInt Find( const CXmlRpcValue* aValue ) const; + + + /** + * Returns ETrue, if the given value is found in the vector, otherwise EFalse. + * + * @param aValue A value to be searched. + * @return ETrue, if the given value is found. Otherwise EFalse. + */ + IMPORT_C TBool Contains( const CXmlRpcValue* aValue ); + + + /** + * Deletes element at the given position. + * + * @param aPos Element to be deleted. + * @return ETrue, if the deletion was successful, otherwise EFalse. + */ + IMPORT_C TBool Delete( TInt aPos ); + + + /** + * Indicates whether the vector is empty or not. + * + * @return ETrue, if the table is empty, otherwise EFalse. + */ + IMPORT_C TBool IsEmpty(); + + + /** + * Returns amount of elements stored into this vector. + * + * @return Amount of elements stored into the table. + */ + IMPORT_C TInt ElementCount() const; + + + /** + * Duplicates the vector. + * + * @return Duplicated vector. + */ + IMPORT_C CVector* DuplicateL() const; + + + /** + * Checks if equals to the given Vector. Vectors are equal, if they contain + * same amount of values and if they contain equal values. Order of the objects + * does not matter. + * + * @return ETrue, if tables are equal, otherwise EFalse. + */ + IMPORT_C TBool Equals( CVector* aValue ) const; + + +private: + CVector(); + void ConstructL(); + + RPointerArray* iValueArray; +}; +#endif + diff --git a/inc/XmlRpcClient.h b/inc/XmlRpcClient.h new file mode 100644 index 0000000..80d1370 --- /dev/null +++ b/inc/XmlRpcClient.h @@ -0,0 +1,131 @@ +/* + * XmlRpcClient.h + * + * xmlrpc4s - XML-RPC library for Symbian environments + * based on xmlrpc-s - Copyright (C) 2007 Timo Salminen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation. + * + * 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 + * + * Contact: Timo Salminen + */ + +#ifndef __XMLRPCCLIENT_H_ +#define __XMLRPCCLIENT_H_ + +#include +#include +#include "XmlRpcValue.h" +#include "XmlRpcConstants.h" +#include "XmlRpcClientInterface.h" +#include "HttpClientEngine.h" +#include "XmlRpcResponseHandlerInterface.h" + +//Forward declarations: +class CXmlRpcValue; + +/** + * Invokes the XML-RPC calls using the given RpcInvocationInterface and + * returns the valus obtained as a result for remote method call. Used + * in client side of distributed system + * + * @author Timo Salminen + */ +class CXmlRpcClient : public MXmlRpcClientInterface, public MXmlRpcResponseHandlerInterface, public CBase + { + public: + + /** + * Constructs the new CXmlRpcClient. + * + * @param aHostAddress Address of the server. + * @param aUri Uri parameter of XmlRpc call (for instance '/RPC2'). + * @param aTargetId Identifier of the target object. (For a call to method "foo.bar()" the aTargetId would be "foo".) + * @param aInterface Interface, using which the client communicates. + */ + IMPORT_C static CXmlRpcClient* NewL( const TDesC8& aHostAddress, + const TDesC8& aHostPath, + const TDesC8& aTargetId, + const TBool aUseTls); + + /** + * Constructs the new CXmlRpcClient. + * + * @param aHostAddress Address of the server. + * @param aUri Uri parameter of XmlRpc call (for instance '/RPC2'). + * @param aTargetId Identifier of the target object. + * @param aInterface Interface, using which the client communicates. + */ + IMPORT_C static CXmlRpcClient* NewLC( const TDesC8& aHostAddress, + const TDesC8& aHostPath, + const TDesC8& aTargetId, + const TBool aUseTls); + + //! Destructor + IMPORT_C virtual ~CXmlRpcClient(); + + // From MXmlRpcClientInterface + IMPORT_C TBool InvokeL(MXmlRpcResponseHandlerInterface* aInterface, const TDesC8& aMethod, + RPointerArray* aArray, + CXmlRpcValue& aResult ); + + /* + Function: RespondL() + Callback handler of XmlRpcResponseHandlerInterface to notify the + object about an available response. + */ + void RespondL(); + + private: + + //! Generates the body for XML-RPC call + virtual TBool GenerateXmlRpcBodyL( const TDesC8& aMethod, + const RPointerArray* aArray ); + + //! For parsing the XmlRpc call response + virtual TBool ParseResponseL( ); + + CXmlRpcClient( ); + + void ConstructL( const TDesC8& aHostAddress, const TDesC8& aHostPath, + const TDesC8& aTargetId, + const TBool aUseTls); + + /* + Function: DoCancel() + Implements cancellation of an outstanding request. Implements + cancellation of an outstanding request. + */ + void DoCancel( ); + + /* + Function: RespondError + Called if there was a Fault in the RPC. + */ + TInt RespondErrorL (TInt aError); + + RBuf8 iHostAddr; + RBuf8 iHostPath; + RBuf8 iTargetId; + CHttpClientEngine* iHttpClientEngine; + RBuf8 iRequest; + // buffer storing the "RAW" HTTP response body: + RBuf8 iResponse; + CXmlRpcValue* iResponseParsedPtr; + TBool iUseTls; + + MXmlRpcResponseHandlerInterface* iResponseHandlerInterface; + RCriticalSection iMutex; + }; +#endif + diff --git a/inc/XmlRpcClientInterface.h b/inc/XmlRpcClientInterface.h new file mode 100644 index 0000000..2d8f5f3 --- /dev/null +++ b/inc/XmlRpcClientInterface.h @@ -0,0 +1,52 @@ +/* + * XmlRpcClientInterface.h + * + * xmlrpc4s - XML-RPC library for Symbian environments + * based on xmlrpc-s - Copyright (C) 2007 Timo Salminen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation. + * + * 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 + * + * Contact: Timo Salminen + */ + +#ifndef __XMLRPCCLIENTINTERFACE_H_ +#define __XMLRPCCLIENTINTERFACE_H_ + +#include "XmlRpcValue.h" +#include "XmlRpcResponseHandlerInterface.h" + +/** + * Interface implemented by the CXmlRpcClient. + * + * @author Timo Salminen + */ +class MXmlRpcClientInterface + { + + public: + + /** + * InvokeL - method + * + * @param aMethod Name of the method to be called + * @param aArray Parameters in array. Ownership will be transferred! + * @param aResult CXmlRpcValue container, where the result will be stored + * @return ETrue, if successful. Otherwise EFalse. + */ + virtual TBool InvokeL(MXmlRpcResponseHandlerInterface* aInterface, + const TDesC8& aMethod, RPointerArray* aArray, + CXmlRpcValue& aResult ) = 0; + + }; +#endif /* __XMLRPCCLIENTINTERFACE_H_ */ diff --git a/inc/XmlRpcConstants.h b/inc/XmlRpcConstants.h new file mode 100644 index 0000000..92c4404 --- /dev/null +++ b/inc/XmlRpcConstants.h @@ -0,0 +1,125 @@ +/* + * XmlRpcConstants.h + * + * xmlrpc4s - XML-RPC library for Symbian environments + * based on xmlrpc-s - Copyright (C) 2005 Timo Salminen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation + * + * 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 + * + * Contact: Timo Salminen + */ + + +#ifndef __XMLRPCCONSTANTS_H_ +#define __XMLRPCCONSTANTS_H_ + + + + +/** +* Contains constant variables for XmlRpc-S +* +* @author: Timpe +*/ + + +// For XmlRpcUtil + _LIT8( K_LT, "lt;" ); + _LIT8( K_RAW_LT, "<" ); + _LIT8( K_AMP, "amp;" ); + _LIT8( K_RAW_AMP, "&" ); + _LIT8( K_AMP_Patter, "&"); + _LIT8( K_LT_Pattern, "<"); + + +// For CXmlRpcClient: + + _LIT8( KPROTOHTTPS, "https://"); + _LIT8( KPROTOHTTP, "http://"); +// Tags for building request encapsulation. + + _LIT8( KPOST, "POST " ); + _LIT8( KURI, "/RPC2" ); + _LIT8( KHTTPVER, " HTTP/1.1" ); + _LIT8( KUSERA, "User-Agent: xmlrpc-s" ); + _LIT8( KHOST, "Host: " ); + _LIT8( KCONTLEN, "Content-length: " ); + _LIT8( KCONTTYPE, "Content-Type: text/xml" ); + _LIT8( KCRNL, "\r\n" ); + + + // For XmlRpcResponse + _LIT8( KHTTP_OK, "HTTP/1.1 200 OK" ); + _LIT8( KCONNECTION, "Connection: close" ); + _LIT8( KDATE, "Date: "); + _LIT8( KSERVER, "Server: xmlrpc-s v0.7"); + + + _LIT8( KVERSION, "" ); + _LIT8( KREQUEST_START, "" ); + _LIT8( KMETHODNAME, "" ); + _LIT8( KMETHODNAME_END, "" ); + + _LIT8( KMETHODCALL_TAG, "" ); + _LIT8( KPARAMS_TAG, "" ); + _LIT8( KPARAMS_ETAG, "" ); + _LIT8( KPARAM_TAG, "" ); + _LIT8( KPARAM_ETAG, "" ); + _LIT8( KMETHODCALL_ETAG, "" ); + + _LIT8( KMETHODRESPONSE_TAG, "" ); + _LIT8( KMETHODRESPONSE_ETAG, "" ); + _LIT8( KFAULT_TAG, "" ); + _LIT8( KFAULT_ETAG, "" ); + + _LIT8( KFAULTCODE, "faultCode" ); + _LIT8( KFAULTSTRING, "faultString" ); + + + +// For CXmlRpcValue: + +//! Tags for building XML representation of the function call + _LIT8( KVALUE_TAG, "" ); + _LIT8( KVALUE_ETAG, "" ); + + _LIT8( KBOOLEAN_TAG, "" ); + _LIT8( KBOOLEAN_ETAG, "" ); + _LIT8( KDOUBLE_TAG, "" ); + _LIT8( KDOUBLE_ETAG, "" ); + _LIT8( KINT_TAG, "" ); + _LIT8( KINT_ETAG, "" ); + _LIT8( KI4_TAG, "" ); + _LIT8( KI4_ETAG, "" ); + _LIT8( KSTRING_TAG, "" ); + _LIT8( KSTRING_ETAG, "" ); + _LIT8( KDATETIME_TAG, "" ); + _LIT8( KDATETIME_ETAG, "" ); + _LIT8( KBASE64_TAG, "" ); + _LIT8( KBASE64_ETAG, "" ); + + + _LIT8( KARRAY_TAG, "" ); + _LIT8( KARRAY_ETAG, "" ); + _LIT8( KDATA_TAG, "" ); + _LIT8( KDATA_ETAG, "" ); + + _LIT8( KSTRUCT_TAG, "" ); + _LIT8( KSTRUCT_ETAG, "" ); + _LIT8( KMEMBER_TAG, "" ); + _LIT8( KMEMBER_ETAG, "" ); + _LIT8( KNAME_TAG, "" ); + _LIT8( KNAME_ETAG, "" ); + +#endif diff --git a/inc/XmlRpcResponseHandlerInterface.h b/inc/XmlRpcResponseHandlerInterface.h new file mode 100644 index 0000000..ca75ec1 --- /dev/null +++ b/inc/XmlRpcResponseHandlerInterface.h @@ -0,0 +1,33 @@ +/* + * HttpClientEngine.h + * + * xmlrpc4s - XML-RPC library for Symbian environments + * Copyright (C) 2007 Moritz Maisel, indigo networks GmbH + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation. + * + * 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 + * + * Contact: Moritz Maisel + */ + +#ifndef XMLRPCRESPONSEHANDLERINTERFACE_H_ +#define XMLRPCRESPONSEHANDLERINTERFACE_H_ + +class MXmlRpcResponseHandlerInterface + { + public: + virtual void RespondL( ) = 0; + virtual TInt RespondErrorL( TInt aError )= 0; + }; + +#endif /*XMLRPCRESPONSEHANDLERINTERFACE_H_*/ diff --git a/inc/XmlRpcUtil.h b/inc/XmlRpcUtil.h new file mode 100644 index 0000000..fa3da6c --- /dev/null +++ b/inc/XmlRpcUtil.h @@ -0,0 +1,71 @@ +/* + * XmlRpcUtil.h + * + * xmlrpc4s - XML-RPC library for Symbian environments + * based on xmlrpc-s - Copyright (C) 2007 Timo Salminen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation + * + * 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 + * + * Contact: Timo Salminen + */ + + +#ifndef __XMLRPCUTIL_H_ +#define __XMLRPCUTIL_H__ + +#include + + + +/** +* Contains utility methods for XMLRPC library: +* +* \li XmlDecodeL() Decodes string payload for XMLRPC call +* and returns the decoded data in a buffer +* +* \li XmlEncodeL() Encodes string payload from XMLRPC call +* and returns the encoded data in a buffer +* +* @author: Timo Salminen +*/ + +class CXmlRpcUtil { + +public: + + /** + * Decodes the encoded data to string and returns it as a buffer. + * Leaves on failure. For encoding rules, refer to XMLRPC specification. + * + * @param aDecode Data to be decoded + * @return Decoded string + */ + IMPORT_C static HBufC8* XmlDecodeL( const TDesC8& aDecode ); + + + /** + * Encodes the string and returns it as a buffer. + * Leaves on failure. For encoding rules, refer to XMLRPC specification. + * + * @param aEncode String to be encoded + * @return Encoded data + */ + IMPORT_C static HBufC8* XmlEncodeL( const TDesC8& aEncode ); + +private: + + //! Calculates a length for a new data buffer. Used by XmlEncodeL() + static TInt CalcNewLength( const TDesC8& aData ); +}; +#endif diff --git a/inc/XmlRpcValue.h b/inc/XmlRpcValue.h new file mode 100644 index 0000000..7924b2d --- /dev/null +++ b/inc/XmlRpcValue.h @@ -0,0 +1,373 @@ +/* + * XmlRpcValue.h + * + * xmlrpc4s - XML-RPC library for Symbian environments + * based on xmlrpc-s - Copyright (C) 2007 Timo Salminen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation + * + * 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 + * + * Contact: Timo Salminen + */ + + +#ifndef __XMLRPCVALUE_H_ +#define __XMLRPCVALUE_H_ + + +#include +#include "Vector.h" +#include "KeyValueTable.h" + + +// Forward declarations +class CKeyValueTable; +class CVector; + + + +/** +* This class is used by XMLRPC library for parameter passing and +* data exchange between the library and the applications. +* In RPC call, the RPC method arguments and return values are +* represented by XmlRpcValue objects +* +* \author Timo Salminen +*/ +class CXmlRpcValue { + +public: + +//! Indicates type of the data stored in this class +IMPORT_C enum EType { + ETypeInvalid = 0, //!< Invalid type + ETypeBoolean, //!< TBool type + ETypeDouble, //!< TReal type + ETypeInt, //!< TInt type + ETypeString, //!< HBufC* type + ETypeDateTime, //!< TDateTime* type + ETypeBase64, //!< HBufC8* type + ETypeArray, //!< CVector* type + ETypeStruct //!< CKeyValueTable* type +}; + + //! Type of data stored in this class + EType iType; + + //! Creates an empty CXmlRpcValue + IMPORT_C static CXmlRpcValue* NewL(); + //! Creates an empty CXmlRpcValue + IMPORT_C static CXmlRpcValue* NewLC(); + + //! Creates a new CXmlRpcValue and initializes it with the given parameter + IMPORT_C static CXmlRpcValue* NewBooleanL( const TBool aValue ); + //! Creates a new CXmlRpcValue and initializes it with the given parameter + IMPORT_C static CXmlRpcValue* NewBooleanLC( const TBool aValue); + + //! Creates a new CXmlRpcValue and initializes it with the given parameter + IMPORT_C static CXmlRpcValue* NewL( const TInt aValue ); + //! Creates a new CXmlRpcValue and initializes it with the given parameter + IMPORT_C static CXmlRpcValue* NewLC( const TInt aValue ); + + //! Creates a new CXmlRpcValue and initializes it with the given parameter + IMPORT_C static CXmlRpcValue* NewL( const TReal aValue ); + //! Creates a new CXmlRpcValue and initializes it with the given parameter + IMPORT_C static CXmlRpcValue* NewLC( const TReal aValue ); + + //! Creates a new CXmlRpcValue and initializes it with the given parameter + IMPORT_C static CXmlRpcValue* NewL( const TDateTime& aValue ); + //! Creates a new CXmlRpcValue and initializes it with the given parameter + IMPORT_C static CXmlRpcValue* NewLC( const TDateTime& aValue ); + + //! Creates a new CXmlRpcValue and initializes it with the given parameter + IMPORT_C static CXmlRpcValue* NewL( const TDesC& aValue ); + //! Creates a new CXmlRpcValue and initializes it with the given parameter + IMPORT_C static CXmlRpcValue* NewLC( const TDesC& aValue ); + + //! Creates a new CXmlRpcValue and initializes it with the given parameter + IMPORT_C static CXmlRpcValue* NewL( HBufC* aValue ); + //! Creates a new CXmlRpcValue and initializes it with the given parameter + IMPORT_C static CXmlRpcValue* NewLC( HBufC* aValue ); + + //! Creates a new CXmlRpcValue and initializes it with the given parameter + IMPORT_C static CXmlRpcValue* NewL( const TDesC8& aValue ); + //! Creates a new CXmlRpcValue and initializes it with the given parameter + IMPORT_C static CXmlRpcValue* NewLC( const TDesC8& aValue ); + + //! Creates a new CXmlRpcValue and initializes it with the given parameter + IMPORT_C static CXmlRpcValue* NewL( HBufC8* aValue ); + //! Creates a new CXmlRpcValue and initializes it with the given parameter + IMPORT_C static CXmlRpcValue* NewLC( HBufC8* aValue ); + + //! Creates a new CXmlRpcValue and initializes it with the given parameter + IMPORT_C static CXmlRpcValue* NewL( const CVector& aValue ); + //! Creates a new CXmlRpcValue and initializes it with the given parameter + IMPORT_C static CXmlRpcValue* NewLC( const CVector& aValue ); + + //! Creates a new CXmlRpcValue and initializes it with the given parameter + IMPORT_C static CXmlRpcValue* NewL( CVector* aValue ); + //! Creates a new CXmlRpcValue and initializes it with the given parameter + IMPORT_C static CXmlRpcValue* NewLC( CVector* aValue ); + + //! Creates a new CXmlRpcValue and initializes it with the given parameter + //! Ownership of the given parameter will not be transferred + IMPORT_C static CXmlRpcValue* NewL( const CKeyValueTable& aValue ); + //! Creates a new CXmlRpcValue and initializes it with the given parameter + //! Ownership of the given parameter will not be transferred + IMPORT_C static CXmlRpcValue* NewLC( const CKeyValueTable& aValue ); + + //! Creates a new CXmlRpcValue and initializes it with the given parameter + //! Ownership of the given parameter will not be transferred + IMPORT_C static CXmlRpcValue* NewL( CKeyValueTable* aValue ); + //! Creates a new CXmlRpcValue and initializes it with the given parameter + //! Ownership of the given parameter will not be transferred + IMPORT_C static CXmlRpcValue* NewLC( CKeyValueTable* aValue ); + + + //! Creates a new CXmlRpcValue from XML representation and updates an offset + IMPORT_C static CXmlRpcValue* NewL( const TDesC8& aXml, TInt* aOffset ); + + //! Destructor: + IMPORT_C virtual ~CXmlRpcValue(); + + +private: + //! Constructor: + CXmlRpcValue(); + + //! Constructs a new CXmlRpvValue with the given parameter \attention Integer value MUST NOT exceed 2147483647! + CXmlRpcValue( const TInt& aValue ) : iType(ETypeInt) { iValue.asInt = aValue; } + //! Constructs a new CXmlRpvValue with the given parameter + CXmlRpcValue( const TReal aValue ) : iType(ETypeDouble) { iValue.asDouble = aValue; } + //! Constructs a new CXmlRpvValue with the given parameter + CXmlRpcValue( const TDesC& aValue ) : iType(ETypeString) { iValue.asString = aValue.Alloc(); } + + //! Constructs a new CXmlRpvValue with the given parameter + void ConstructBooleanL( TBool aValue ) { iType = ETypeBoolean; iValue.asBool = aValue; } + + //! Constructs a new CXmlRpvValue with the given parameter + void ConstructL( const TDesC& aValue ); + + //! Constructs a new CXmlRpvValue with the given parameter + void ConstructL( HBufC* aValue ); + + //! Constructs a new CXmlRpvValue with the given parameter + void ConstructL( const TDateTime& aValue ); + + //! Constructs a new CXmlRpvValue with the given parameter + void ConstructL( const TDesC8& aValue ); + + //! Constructs a new CXmlRpvValue with the given parameter + void ConstructL( HBufC8* aValue ); + + //! Constructs a new CXmlRpvValue with the given parameter + void ConstructL( const CVector& aValue ); + + //! Constructs a new CXmlRpvValue with the given parameter + void ConstructL( CVector* aValue ); + + //! Constructs a new CXmlRpvValue with the given parameter + void ConstructL( const CKeyValueTable& aValue ); + + //! Constructs a new CXmlRpvValue with the given parameter + void ConstructL( CKeyValueTable* aValue ); + +public: + + //! Checks the equality of XmlRpcValue instances + IMPORT_C TBool operator==( const CXmlRpcValue& aValue ) const; + + //! Checks the inequality of XmlRpcValue instances + IMPORT_C TBool operator!=( const CXmlRpcValue& aValue ) const; + + //! Returns the TBool value + IMPORT_C TBool& GetBoolValue(); + //! Returns the TInt value + IMPORT_C TInt& GetIntValue(); + //! Returns the TReal value + IMPORT_C TReal& GetRealValue(); + //! Returns the TDateTime value + IMPORT_C TDateTime& GetDateTimeValue(); + //! Returns the TDesC (string) value + IMPORT_C TDesC& GetStringValue(); + //! Returns the TDesC8 (binary) value + IMPORT_C TDesC8& GetBinaryValue(); + //! Returns the CVector (array) value + IMPORT_C CVector& GetArrayValue(); + //! Returns the CKeyValueTable (struct) value + IMPORT_C CKeyValueTable& GetStructValue(); + + + //! Sets a given value to the XmlRpcValue. Erases any existing value. + IMPORT_C void SetBoolValueL( TInt aValue ); + //! Sets a given value to the XmlRpcValue. Erases any existing value. + IMPORT_C void SetValueL( TInt aValue ); + //! Sets a given value to the XmlRpcValue. Erases any existing value. + IMPORT_C void SetValueL( TReal aValue ); + //! Sets a given value to the XmlRpcValue. Erases any existing value. + IMPORT_C void SetValueL( const TDesC& aValue ); + //! Sets a given value to the XmlRpcValue. Erases any existing value. + IMPORT_C void SetValueL( HBufC* aValue ); + //! Sets a given value to the XmlRpcValue. Erases any existing value. + IMPORT_C void SetValueL( const TDateTime& aValue ); + //! Sets a given value to the XmlRpcValue. Erases any existing value. + IMPORT_C void SetValueL( const TDesC8& aValue ); + //! Sets a given value to the XmlRpcValue. Erases any existing value. + IMPORT_C void SetValueL( HBufC8* aValue ); + //! Sets a given value to the XmlRpcValue. Erases any existing value. + IMPORT_C void SetValueL( CVector* aValue ); + //! Sets a given value to the XmlRpcValue. Erases any existing value. + IMPORT_C void SetValueL( CKeyValueTable* aValue ); + //! Sets a given value to the XmlRpcValue. Erases any existing value. + IMPORT_C void SetValueL( const CXmlRpcValue* aValue ); + + + /** + * Duplicates the value. + * + * @return Duplicated value. + */ + IMPORT_C CXmlRpcValue* DuplicateL() const; + + + /** + * Returns ETrue if the object contains valid value. + * + * @return ETrue, if the value is valid, otherwise EFalse. + */ + IMPORT_C TBool Valid() const; + + + /** + * Returns type of the stored value. + * + * @return Type of the stored value. + */ + IMPORT_C EType GetType() const; + + + /** + * Encodes and creates the CXmlRpcValue from XML data. + * Destroys any existing value! The given XML MUST begin with + * tag (whitespace allowed) otherwise EFalse will be returned. + * + * Used by the CXmlRpcServer. + * + * @param aXml XML data, where the value is extracted from + * @param aOffset Indicates the start of data to be extracted ( tag) + * @return ETrue, if the operation was successful. Otherwise EFalse + */ + IMPORT_C TBool FromXmlnL( const TDesC8& aXml, TInt* aOffset ); + + + /** + * Returns the XML representation of the value stored in this object. + * For details about the XML representation, see the XMLRPC + * specification. + * + * Used by the CXmlRpcServer. + * + * @return Xml representation of the value stored in this object. + */ + IMPORT_C HBufC8* ToXmlnL(); + + +protected: + + //! Erases the data that is stored in this class + void Invalidate(); + + //! Makes sure there is a value of given type + void AssertTypeOrInvalid( EType aType ); + + //! Creates a new CXmlRpcValue from given XML representation + TBool BoolFromXmlnL( const TDesC8& aXml ); + + //! Creates a new CXmlRpcValue from given XML representation + TBool IntFromXmlnL( const TDesC8& aXml ); + + //! Creates a new CXmlRpcValue from given XML representation + TBool Int4FromXmlnL( const TDesC8& aXml ); + + //! Creates a new CXmlRpcValue from given XML representation + TBool DoubleFromXmlnL( const TDesC8& aXml ); + + //! Creates a new CXmlRpcValue from given XML representation + TBool StringFromXmlnL( const TDesC8& aXml ); + + //! Creates a new CXmlRpcValue from given XML representation + TBool NonTaggedStringFromXmlnL( const TDesC8& aXml ); + + //! Creates a new CXmlRpcValue from given XML representation + TBool TimeFromXmlnL( const TDesC8& aXml ); + + //! Creates a new CXmlRpcValue from given XML representation + TBool BinaryFromXmlnL( const TDesC8& aXml ); + + //! Creates a new CXmlRpcValue from given XML representation + TBool ArrayFromXmlnL( const TDesC8& aXml ); + + //! Creates a new CXmlRpcValue from given XML representation + TBool StructFromXmlnL( const TDesC8& aXml ); + + + + // Returns the XmlRpcValue as XML representation. + // Used by ToXmlnL() - method + + //! Returns the XML representation of the stored value + HBufC8* BoolToXmlnL(); + + //! Returns the XML representation of the stored value + HBufC8* DoubleToXmlnL(); + + //! Returns the XML representation of the stored value + HBufC8* IntToXmlnL(); + + //! Returns the XML representation of the stored value + HBufC8* StringToXmlnL(); + + //! Returns the XML representation of the stored value + HBufC8* TimeToXmlnL(); + + //! Returns the XML representation of the stored value + HBufC8* BinaryToXmlnL(); + + //! Returns the XML representation of the stored value + HBufC8* ArrayToXmlnL(); + + //! Returns the XML representation of the stored value + HBufC8* StructToXmlnL(); + + + // Data containers + + //! Contains the value stored in this class + union { + TBool asBool; + TInt asInt; + TReal asDouble; + TDateTime* asTime; + HBufC* asString; + HBufC8* asBinary; + CVector* asArray; + CKeyValueTable* asStruct; + } iValue; + + +private: + // No copy constructors allowed! + CXmlRpcValue( CXmlRpcValue const& aValue ); + +}; +#endif diff --git a/inc/XmlUtil.h b/inc/XmlUtil.h new file mode 100644 index 0000000..a463897 --- /dev/null +++ b/inc/XmlUtil.h @@ -0,0 +1,111 @@ +/* + * XmlUtil.h + * + * xmlrpc4s - XML-RPC library for Symbian environments + * based on xmlrpc-s - Copyright (C) 2007 Timo Salminen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation + * + * 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 + * + * Contact: Timo Salminen + */ + + +#ifndef __XMLUTIL_H_ +#define __XMLUTIL_H_ + +#include + + +/** +* Contains methods for handling XML data: +* +* \li NextTagIs() Returns true, if the given tag +* is found from given offset +* \li GetNextTagL() Returns next tag +* \li FindTag() Finds the given tag, beginning from +* the given offset +* \li ParseTagL() Parses, and returns the contents +* of the tag from given offset +* +* @author: Timo Salminen +*/ + + +class TXmlUtil { + +public: + + /** + * Returns ETrue, if the given tag is found at the specified offset. + * Updates offset to the char after the tag if the tag is found. Returns + * EFalse, if the next non-whitespace character is not '<' + * + * @param aTag A tag to be searched + * @param aXml Xml string where a tag is searched from + * @param aOffset offset, indicating the start of tag. Will be + * updated to the next char after the tag, if the tag is found! + * + * @return ETrue, if the tag is found. Otherwise EFalse + */ + IMPORT_C static TBool NextTagIs( const TDesC8& aTag, const TDesC8& aXml, TInt* aOffset ); + + + + /** + * Returns the next tag and updates the offset to the char after the + * tag. Returns empty string if the next non-whitespace character + * is not '<'. + * + * @param aXml XML string where a tag is to be searched + * @param aOffset offset, indicating the start of tag + * + * @return Buffer pointer containing the found tag + */ + IMPORT_C static HBufC8* GetNextTagL( const TDesC8& aXml, TInt* aOffset ); + + + + /** + * Returns true if the given tag is found from the beginning of + * the given offset. Updates offset to the char after the tag. + * Otherwise, returns false. Will return EFalse, if empty tag is + * passed. + * + * @param aTag - A tag to be found + * @param aXml - XML string where a tag is to be searched + * @param aOffset - Offset where the search is started + * + * @return ETrue if tag is found, otherwise EFalse + */ + IMPORT_C static TBool FindTag( const TDesC8& aTag, const TDesC8& aXml, TInt* aOffset ); + + + + /** + * Finds the given tag beginning from the given offset. Parses and returns + * the content between tags and updates the offset to the char after . + * If given tag is not found or it is invalid, empty buffer will be returned. + * If given offset is out of bounds, empty buffer will be returned. + * + * @param aTag - A tag to be parsed + * @param aXml - XML string where a tag is to be searched + * @param aOffset - Offset where the search is started + * + * @return HBufC* - Buffer pointer containing parsed content + */ + IMPORT_C static HBufC8* ParseTagL( const TDesC8& aTag, const TDesC8& aXml, TInt* aOffset ); + +}; + +#endif diff --git a/src/Base64.cpp b/src/Base64.cpp new file mode 100644 index 0000000..651d196 --- /dev/null +++ b/src/Base64.cpp @@ -0,0 +1,144 @@ +#include "Base64.h" + + + + +EXPORT_C HBufC8* TBase64::Base64_EncodeL( const TDesC8& aSrcString ) { + + const TInt 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','+','/' }; + + + TInt encodedLength = 0; + + if ( aSrcString.Length() % 3 == 0 ) + encodedLength = (aSrcString.Length() / 3) * 4; + else + encodedLength = (aSrcString.Length() / 3) * 4 + 4; + + HBufC8* encoded = HBufC8::NewL( encodedLength ); + + TBuf8<3> char_array_3; + char_array_3.Zero(); + char_array_3.SetLength( 3 ); + + TBuf8<4> char_array_4; + char_array_4.Zero(); + char_array_4.SetLength( 4 ); + + TInt index = aSrcString.Length(); + TInt i = 0; + TInt j = 0; + + while ( index-- ) { + char_array_3[i++] = aSrcString[j++]; + + if (i == 3) { + char_array_4[0] = (char_array_3[0] & 0xfc) >> 2; + char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4); + char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6); + char_array_4[3] = char_array_3[2] & 0x3f; + + for(i = 0; (i <4) ; i++) + encoded->Des().Append( base64Chars[char_array_4[i]] ); + i = 0; + } + } + + if (i) + { + for(j = i; j < 3; j++) + char_array_3[j] = '\0'; + + char_array_4[0] = (char_array_3[0] & 0xfc) >> 2; + char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4); + char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6); + char_array_4[3] = char_array_3[2] & 0x3f; + + for (j = 0; (j < i + 1); j++) + encoded->Des().Append( base64Chars[char_array_4[j]] ); + + while((i++ < 3)) + encoded->Des().Append( '=' ); + + } + + return encoded; +} + + +EXPORT_C HBufC8* TBase64::Base64_DecodeL( const TDesC8& aSrcString ) { + + const TInt 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','+','/' }; + + TInt decodedLength = aSrcString.Length() / 4 * 3 + 3; + HBufC8* decoded = HBufC8::NewL( decodedLength ); + + TInt index = aSrcString.Length(); + TInt i = 0; + TInt j = 0; + TInt in_ = 0; + + TBuf8<3> char_array_3; + char_array_3.Zero(); + char_array_3.SetLength( 3 ); + + TBuf8<4> char_array_4; + char_array_4.Zero(); + char_array_4.SetLength( 4 ); + + while (index-- && ( aSrcString[in_] != '=') /*&& is_base64(encoded_string[in_])*/ ) { + + TInt inchar = aSrcString[in_++]; + // Include only '+', '/0123456789', 'A....Z' and 'a....z' + if( !(inchar == 43 || (inchar >= 47 && inchar <= 57) || (inchar >= 65 && inchar <= 90) || + (inchar >= 97 && inchar <= 122)) ) + continue; + + char_array_4[i++] = TChar(inchar); + + if (i == 4) { + for (i = 0; i < 4; i++) + for( TInt charIndex = 0; charIndex < 64 ; charIndex++ ) { + if( base64Chars[charIndex] == char_array_4[i] ) { + char_array_4[i] = charIndex; + break; + } + } + + char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4); + char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2); + char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3]; + + for (i = 0; (i < 3); i++) + decoded->Des().Append( char_array_3[i] ); + + i = 0; + } + } + + if (i) { + for (j = i; j < 4; j++) + char_array_4[j] = 0; + + for (j = 0; j <4; j++) + for( TInt charIndex = 0; charIndex<64 ; charIndex++ ) { + if( base64Chars[charIndex] == char_array_4[j] ) { + char_array_4[j] = charIndex; + break; + } + } + + char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4); + char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2); + char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3]; + + for (j = 0; (j < i - 1); j++) decoded->Des().Append( char_array_3[j] ); + } + + return decoded; + +} diff --git a/src/HttpClientEngine.cpp b/src/HttpClientEngine.cpp new file mode 100644 index 0000000..ba6acc9 --- /dev/null +++ b/src/HttpClientEngine.cpp @@ -0,0 +1,303 @@ +#include "../inc/HttpClientEngine.h" + +CHttpClientEngine::~CHttpClientEngine( ) + { + // close RHTTPSession: + iSession.Close ( ); + + // free memory: + iPostData.Close ( ); + iHttpUsername.Close ( ); + iHttpPassword.Close ( ); + + } + +CHttpClientEngine::CHttpClientEngine( ) + { + } + +CHttpClientEngine* CHttpClientEngine::NewL( ) + { + CHttpClientEngine* self = CHttpClientEngine::NewLC ( ); + CleanupStack::Pop ( self ); + return self; + } + +CHttpClientEngine* CHttpClientEngine::NewLC( ) + { + CHttpClientEngine* self = new (ELeave) CHttpClientEngine(); + CleanupStack::PushL (self ); + self->ConstructL ( ); + return self; + } + +void CHttpClientEngine::ConstructL( ) + { + // open RHTTPSession: + iSession.OpenL ( ); + + // register HttpCallback: + InstallAuthenticationL (iSession ); + + iCredentialsSet = EFalse; + } + +void CHttpClientEngine::IssueHttpPostL( + MXmlRpcResponseHandlerInterface* aHandler, const TDesC8* aUri, + const TDesC8* aContentType, const TDesC8* aBody, RBuf8* aResultBodyPtr ) + { + // store reference to calling object: + iResponseHandler = aHandler; + + // store referece to result buffer: + iResponseBodyPtr = aResultBodyPtr; + + iPostData.CleanupClosePushL ( ); + iPostData.CreateL (aBody->Length ( ) ); + iPostData.Append ( *aBody ); + + // parse string to uri-type: + TUriParser8 uri; + uri.Parse (*aUri ); + + //get string from session string pool for HTTP method: + RStringF httpMethod = iSession.StringPool().StringF (HTTP::EPOST, RHTTPSession::GetTable ( ) ); + iTransaction = (RHTTPTransaction) iSession.OpenTransactionL(uri, *this, httpMethod); + // the RStringF instance is not needed anymore: + httpMethod.Close ( ); + + // set UserAgent: + RHTTPHeaders httpHeader = iTransaction.Request().GetHeaderCollection ( ); + RBuf8 httpUserAgent; + httpUserAgent.CleanupClosePushL ( ); + httpUserAgent.CreateL ( KClientName().Length ( )+ 1 + KClientVersion().Length ( ) ); + httpUserAgent.Copy (KClientName ); + httpUserAgent.Append (_L("/") ); + httpUserAgent.Append (KClientVersion ); + SetHeaderL (httpHeader, HTTP::EUserAgent, httpUserAgent ); + CleanupStack::PopAndDestroy(&httpUserAgent); // calls httpUserAgent.Close() + + // set ContentType: + RBuf8 httpContentType; + httpContentType.CleanupClosePushL(); + httpContentType.CreateL ( aContentType->Length ( ) ); + httpContentType.Copy ( *aContentType ); + SetHeaderL (httpHeader, HTTP::EContentType, httpContentType ); + CleanupStack::PopAndDestroy(&httpContentType); // calls httpContentType.Close() + + // set body data + iTransaction.Request().SetBody (*this ); + + // submit the request: + iTransaction.SubmitL ( ); + + CleanupStack::Pop(); // iPostData + } + +void CHttpClientEngine::CancelTransaction( ) + { + if (!iRunning ) + { + return; + } + + iTransaction.Close ( ); + + iRunning = EFalse; + } + +void CHttpClientEngine::SetHeaderL(RHTTPHeaders aHeaders, TInt aHdrField, + const TDesC8& aHdrValue ) + { + RStringF valStr = iSession.StringPool().OpenFStringL (aHdrValue ); + CleanupClosePushL (valStr ); + THTTPHdrVal val(valStr); + aHeaders.SetFieldL (iSession.StringPool().StringF (aHdrField, RHTTPSession::GetTable ( ) ), val ); + CleanupStack::PopAndDestroy(); // call valStr.Close() + } + +// implementation of MHTTPTransactionCallback interface methods +void CHttpClientEngine::MHFRunL( RHTTPTransaction aTransaction, + const THTTPEvent & aEvent ) + { + switch (aEvent.iStatus ) + { + case THTTPEvent::EGotResponseHeaders: + { + // HTTP response headers have been received. Use + // aTransaction.Response() to get the response. However, it's not + // necessary to do anything with the response when this event occurs. + } + break; + + case THTTPEvent::EGotResponseBodyData: + { + // Part (or all) of response's body data received. Use + // aTransaction.Response().Body()->GetNextDataPart() to get the + // actual body data. + + // Get the body data supplier + MHTTPDataSupplier* body = aTransaction.Response().Body ( ); + CleanupStack::PushL(body); + TPtrC8 dataChunk8bit; + + // GetNextDataPart() returns ETrue, if the received part is the last + // one. + TBool isLast = body->GetNextDataPart (dataChunk8bit ); + + // convert from 8bit to 16bit representation: + RBuf dataChunk; + dataChunk.CleanupClosePushL(); + dataChunk.CreateL(dataChunk8bit.Length()); + dataChunk.Copy(dataChunk8bit); + + // NOTE: isLast may not be ETrue even if last data part received. + // (e.g. multipart response without content length field) + // Use EResponseComplete to reliably determine when body is completely + // received. + + // Add chunk to iResponseBody buffer. + iResponseBodyPtr->ReAllocL (iResponseBodyPtr->Length ( ) + dataChunk8bit.Length ( ) ); + iResponseBodyPtr->Append ( dataChunk ); + + CleanupStack::PopAndDestroy(); // calls dataChunk.Close() + + // Always remember to release the body data. + body->ReleaseData ( ); + CleanupStack::Pop(body); + } + break; + + case THTTPEvent::EResponseComplete: + { + // Indicates that header & body of response is completely received. + // The SDK doc says "The transaction's response is + // complete. An incoming event." + + + // Notify the calling object: + iResponseHandler->RespondL ( ); + + // Transaction can be closed now. It's not needed anymore. + aTransaction.Close ( ); + + iPostData.Close(); // temp. fix; see "ReleaseData()" + + iRunning = EFalse; + } + break; + + case THTTPEvent::EFailed: + { + // Transaction completed with failure. + aTransaction.Close ( ); + iRunning = EFalse; + } + break; + + default: + // There are more events in THTTPEvent, but they are not usually + // needed. However, event status smaller than zero should be handled + // correctly since it's error. (TODO: Store error-info?) + { + if ( aEvent.iStatus < 0 ) + { + // Just close the transaction on errors + aTransaction.Close ( ); + iRunning = EFalse; + } + else + { + // Other events are not errors (e.g. permanent and temporary + // redirections) + } + } + break; + } + } + +TInt CHttpClientEngine::MHFRunError(TInt aError, RHTTPTransaction aTransaction, + const THTTPEvent& aEvent ) + { + // TODO: Notify about the error (?!) and return KErrNone. + return KErrNone; + } + +// implemntation of MHTTPDataSupplier interface methods +TBool CHttpClientEngine::GetNextDataPart( TPtrC8 & aDataPart ) + { + if (iPostData.Length ( ) ) + { + // Provide pointer to next chunk of data (return ETrue, if last chunk) + // (Usually only one chunk is needed, but sending big file could require + // loading the file in small parts.) + aDataPart.Set (iPostData ); + } + return ETrue; + } + +void CHttpClientEngine::ReleaseData( ) + { + //iPostData.Close ( ); // causes the body to be deleted before the POST! + // (The Close() is temp. done after successful reception in MHFRunL()!) + } + +TInt CHttpClientEngine::OverallDataSize( ) + { + return iPostData.Length ( ); + } + +TInt CHttpClientEngine::Reset( ) + { + // Nothing needed since iPostData still exists and contains all the data. + // (If a file is used and read in small parts we should seek to beginning + // of file and provide the first chunk again in GetNextDataPart() ) + return KErrNone; + } + +TBool CHttpClientEngine::SetCredentialsL(const TDesC8* aUser, + const TDesC8* aPass ) + { + iHttpUsername.Close ( ); + iHttpPassword.Close ( ); + + iHttpUsername.CleanupClosePushL(); + iHttpPassword.CleanupClosePushL(); + + TRAPD(err, iHttpUsername.CreateL(*aUser)) + ; + if (!err ) + { + TRAPD(err, iHttpPassword.CreateL(*aPass)) + ; + if (!err ) + { + iCredentialsSet = ETrue; + CleanupStack::Pop(2); + return ETrue; // on success + } + } + return EFalse; // if setting user and pass failed + } + +TBool CHttpClientEngine::GetCredentialsL(const TUriC8& aUri, RString aRealm, + RStringF aAuthenticationType, RString& aUsername, RString& aPassword ) + { + if (!iCredentialsSet ) + { + return EFalse; + } + + TRAPD(err, aUsername = aRealm.Pool().OpenStringL(iHttpUsername)) + ; + if (!err ) + { + TRAPD(err, aPassword = aRealm.Pool().OpenStringL(iHttpPassword)) + ; + if (!err ) + { + return ETrue; // on success + } + } + return EFalse; // if setting user and pass failed + } diff --git a/src/KeyValueTable.cpp b/src/KeyValueTable.cpp new file mode 100644 index 0000000..2f17304 --- /dev/null +++ b/src/KeyValueTable.cpp @@ -0,0 +1,168 @@ +#include "KeyValueTable.h" + + + +EXPORT_C CKeyValueTable* CKeyValueTable::NewL() { + CKeyValueTable* self = CKeyValueTable::NewLC(); + CleanupStack::Pop(); + return self; +} + + +EXPORT_C CKeyValueTable* CKeyValueTable::NewLC() { + CKeyValueTable* self = new (ELeave) CKeyValueTable(); + CleanupStack::PushL( self ); + self->ConstructL(); + return self; +} + + +CKeyValueTable::CKeyValueTable() { + +} + + +void CKeyValueTable::ConstructL() { + iKeyArray = new (ELeave) CDesC8ArrayFlat(8); + iValueArray = new (ELeave) RPointerArray(8); + +} + + +CKeyValueTable::~CKeyValueTable() { + if( iValueArray ) { + iValueArray->ResetAndDestroy(); + delete iValueArray; + } + + if ( iKeyArray ) { + iKeyArray->Reset(); + delete iKeyArray; + } + +} + + +EXPORT_C void CKeyValueTable::AddElementL( const TDesC8& aKey, CXmlRpcValue* aValue ) { + + if ( ContainsKey( aKey ) ) + Delete( aKey ); + + iKeyArray->AppendL( aKey ); + iValueArray->Append( aValue ); +} + + +EXPORT_C CXmlRpcValue* CKeyValueTable::GetValue( const TDesC8& aKey ) const { + + TInt position = 0; + + if( Find(aKey, &position) == 0 ) { + return ValueAt( position ); + } + + return NULL; +} + + +EXPORT_C HBufC8* CKeyValueTable::KeyAtL( TInt aPos ) const { + if ( aPos < 0 || aPos > (iKeyArray->Count() -1) || iKeyArray->Count() == 0) + return HBufC8::NewL(0); + return (*iKeyArray)[aPos].AllocL(); +} + + +EXPORT_C CXmlRpcValue* CKeyValueTable::ValueAt( TInt aPos ) const { + if ( aPos < 0 || aPos > iKeyArray->Count() -1 ) return NULL; + return (*iValueArray)[aPos]; +} + + +EXPORT_C TInt CKeyValueTable::Find( const TDesC8& aKey, TInt* aPos ) const { + return iKeyArray->Find( aKey, *aPos, ECmpFolded ); +} + + +EXPORT_C TBool CKeyValueTable::ContainsKey( const TDesC8& aKey ) { + TInt temp = 1; + TInt ret = Find( aKey, &temp ); + if ( ret == 0 ) + return ETrue; + else + return EFalse; +} + + +EXPORT_C TBool CKeyValueTable::Delete( const TInt aPos ) { + if ( aPos < 0 || aPos > iKeyArray->Count() ) return EFalse; + + iKeyArray->Delete( aPos ); + CXmlRpcValue* value = (*iValueArray)[aPos]; + iValueArray->Remove( aPos ); + delete value; + return ETrue; +} + + +EXPORT_C TBool CKeyValueTable::Delete( const TDesC8& aKey ) { + TInt position; position = 10; + if ( Find( aKey, &position) == 0 ) { + Delete( position ); + return ETrue; + } + return EFalse; +} + + +EXPORT_C TBool CKeyValueTable::IsEmpty() { + if ( iKeyArray->Count() == 0 ) + return ETrue; + + return EFalse; +} + + +EXPORT_C TInt CKeyValueTable::ElementCount() const { + return iKeyArray->Count(); +} + + +EXPORT_C CKeyValueTable* CKeyValueTable::DuplicateL() const { + + CKeyValueTable* duplicate = CKeyValueTable::NewL(); + + TInt count = iValueArray->Count(); + for( TInt i=0 ; i < count ; i++ ) { + CXmlRpcValue* value = (*iValueArray)[i]->DuplicateL(); + duplicate->AddElementL( (*iKeyArray)[i], value ); + } + return duplicate; +} + + +EXPORT_C TBool CKeyValueTable::Equals( CKeyValueTable* aTable ) const { + TInt count = ElementCount(); + + if( count != aTable->ElementCount() ) + return EFalse; + + for( TInt index=0 ; indexContainsKey( key )) ) { + return EFalse; + } + + TInt tmp = 0; + if( Find( key, &tmp ) != KErrNone ) { + return EFalse; + } + + if( *ValueAt( index ) != *aTable->ValueAt( index ) ) { + return EFalse; + } + } + return ETrue; +} + diff --git a/src/Vector.cpp b/src/Vector.cpp new file mode 100644 index 0000000..8cdb70c --- /dev/null +++ b/src/Vector.cpp @@ -0,0 +1,138 @@ +#include "Vector.h" + + + +//////////////////// +// Class CVector // +//////////////////// + +EXPORT_C CVector* CVector::NewL() { + CVector* self = CVector::NewLC(); + CleanupStack::Pop(); + return self; +} + + +EXPORT_C CVector* CVector::NewLC() { + CVector* self = new (ELeave) CVector(); + CleanupStack::PushL( self ); + self->ConstructL(); + return self; +} + + +void CVector::ConstructL() { + iValueArray = new (ELeave) RPointerArray(8); +} + + +EXPORT_C CVector::~CVector() { + + if (iValueArray) { + iValueArray->ResetAndDestroy(); + delete iValueArray; + } + +} + + +CVector::CVector() { +} + + +EXPORT_C TBool CVector::Add( CXmlRpcValue* aValue ) { + if ( iValueArray->Append( aValue ) != KErrNone) + return EFalse; + + return ETrue; +} + + +EXPORT_C CXmlRpcValue* CVector::ValueAt( TInt aPos ) const { + if ( aPos < 0 || aPos > iValueArray->Count() - 1 ) return NULL; + return (*iValueArray)[aPos]; +} + + +EXPORT_C TInt CVector::Find( const CXmlRpcValue* aValue ) const { + + for ( TInt index=0; indexCount(); index++ ) { + if ( *aValue == *((*iValueArray)[index]) ) + return index; + } + + return KErrNotFound; +} + + +EXPORT_C TBool CVector::Contains( const CXmlRpcValue* aValue ) { + + for ( TInt index=0; indexCount(); index++ ) { + if ( *aValue == *((*iValueArray)[index]) ) + return ETrue; + } + + return EFalse; +} + + +EXPORT_C TBool CVector::Delete( TInt aPos ) { + if ( aPos < 0 || aPos > iValueArray->Count() - 1 ) + return EFalse; + + CXmlRpcValue* toBeRemoved = (*iValueArray)[aPos]; + iValueArray->Remove( aPos ); + delete toBeRemoved; + + return ETrue; +} + + +EXPORT_C TBool CVector::IsEmpty() { + if ( iValueArray->Count() != 0 ) + return EFalse; + + return ETrue; +} + + +EXPORT_C TInt CVector::ElementCount() const { + return iValueArray->Count(); +} + + +EXPORT_C CVector* CVector::DuplicateL() const { + + CVector* duplicate = CVector::NewL(); + + TInt count = iValueArray->Count(); + for( TInt i=0 ; i < count ; i++ ) { + CXmlRpcValue* value = (*iValueArray)[i]->DuplicateL(); + duplicate->Add( value ); + } + + return duplicate; +} + + +EXPORT_C TBool CVector::Equals( CVector* aValue ) const { + TInt count = ElementCount(); + + if( count != aValue->ElementCount() ) + return EFalse; + + for( TInt ind=0 ; indValueAt( index ) ) { + break; + } + + if( index == count ) + return EFalse; + } + } + + return ETrue; +} + diff --git a/src/XMLUtil.cpp b/src/XMLUtil.cpp new file mode 100644 index 0000000..2720184 --- /dev/null +++ b/src/XMLUtil.cpp @@ -0,0 +1,117 @@ +#include "XmlUtil.h" + + + +EXPORT_C TBool TXmlUtil::NextTagIs( const TDesC8& aTag, const TDesC8& aXml, TInt* offset ) { + TInt start = *offset; + + if( start < 0 || start >= aXml.Length() ) return EFalse; + if( aXml.Length() < aTag.Length() || aTag.Length() == 0 ) return EFalse; + + TChar ch; + ch = aXml[start]; + + while( ch.IsSpace() ) { + start++; + if( start >= aXml.Length() ) return EFalse; + ch = aXml[start]; + } + + if( aXml.Length() < start + aTag.Length() ) return EFalse; + TPtrC8 matching; + matching.Set( aXml.Mid( start, aTag.Length() )); + + if( aTag.Compare( matching ) == 0 ) { + *offset = start + aTag.Length(); + return ETrue; + } + + return EFalse; +} + + + + +EXPORT_C HBufC8* TXmlUtil::GetNextTagL( const TDesC8& aXml, TInt* offset ) { + if( *offset < 0 || aXml.Length() <= *offset ) return KNullDesC8().AllocL(); + + + TChar ch; + TInt start = *offset; + ch = aXml[start]; + + while ( ch.IsSpace() ) { + start++; + if( start >= aXml.Length() ) return KNullDesC8().AllocL(); + ch = aXml[start]; + } + + if ( ch != '<' ) return KNullDesC8().AllocL(); + + TPtrC8 startPoint; + startPoint.Set( aXml.Right( aXml.Length() - start )); + TInt length = startPoint.Find( _L8(">") ); + //! You have to increase 'length' by 1 to get next character over ">" + + if( length == KErrNotFound ) + return KNullDesC8().AllocL(); + + + TPtrC8 tagPtr; + tagPtr.Set( aXml.Mid( start, length + 1 ) ); + HBufC8* foundTag = HBufC8::NewL( tagPtr.Length() ); + foundTag->Des().Copy( tagPtr ); + *offset = start + length + 1; + + return foundTag; +} + + +EXPORT_C TBool TXmlUtil::FindTag( const TDesC8& aTag, const TDesC8& aXml, TInt* offset ) { + if( aXml.Length() <= *offset || *offset < 0 ) return EFalse; + if( aXml.Length() < aTag.Length() ) return EFalse; + if( aTag.Length() == 0 ) return EFalse; + + TPtrC8 startPoint; + startPoint.Set( aXml.Right( aXml.Length() - *offset ) ); + TInt tagPlacement = startPoint.Find( aTag ); + + if( tagPlacement == KErrNotFound ) return EFalse; + + *offset += (tagPlacement + aTag.Length()); + return ETrue; +} + + +EXPORT_C HBufC8* TXmlUtil::ParseTagL( const TDesC8& aTag, const TDesC8& aXml, TInt* offset ) { + + if ( aXml.Length() <= *offset || *offset < 0 ) return KNullDesC8().AllocL(); + + TPtrC8 tempPtr; + tempPtr.Set( aXml.Right( aXml.Length() - *offset ) ); + TInt start = tempPtr.Find( aTag ); + if ( start == KErrNotFound ) return KNullDesC8().AllocL(); + start += aTag.Length(); + + tempPtr.Set( aXml.Right( aXml.Length() - *offset - start ) ); + HBufC8* eTag = HBufC8::NewL( aTag.Length() + 1 ); + eTag->Des().Copy( aTag ); + eTag->Des().Insert( 1, _L8("/") ); + TInt length = tempPtr.Find( eTag->Des() ); + + if ( length == KErrNotFound ) { + delete eTag; + eTag = NULL; + return KNullDesC8().AllocL(); + } + + TPtrC8 tagPtr; + tagPtr.Set( aXml.Mid( *offset + start, length ) ); + HBufC8* content = HBufC8::NewL( tagPtr.Length() ); + content->Des().Copy( tagPtr ); + *offset = start + length + eTag->Length(); + + delete eTag; + eTag = NULL; + return content; +} diff --git a/src/XmlRpcClient.cpp b/src/XmlRpcClient.cpp new file mode 100644 index 0000000..ca34381 --- /dev/null +++ b/src/XmlRpcClient.cpp @@ -0,0 +1,216 @@ +#include "XmlRpcClient.h" +#include "XmlUtil.h" + +EXPORT_C CXmlRpcClient* CXmlRpcClient::NewL( const TDesC8& aHostAddress, + const TDesC8& aHostPath, + const TDesC8& aTargetId, + const TBool aUseTls) + { + CXmlRpcClient* self = CXmlRpcClient::NewLC( aHostAddress, aHostPath, aTargetId, aUseTls); + CleanupStack::Pop(); + return self; + } + +EXPORT_C CXmlRpcClient* CXmlRpcClient::NewLC( const TDesC8& aHostAddress, + const TDesC8& aHostPath, + const TDesC8& aTargetId, + const TBool aUseTls) + { + CXmlRpcClient* self = new (ELeave) CXmlRpcClient(); + CleanupStack::PushL( self ); + self->ConstructL( aHostAddress, aHostPath, aTargetId, aUseTls); + return self; + } + +void CXmlRpcClient::ConstructL( const TDesC8& aHostAddress, + const TDesC8& aHostPath, const TDesC8& aTargetId, const TBool aUseTls ) + { + iHostAddr.CreateL ( aHostAddress ); + + iTargetId.CreateL ( aTargetId ); + + iHostPath.CreateL ( aHostPath ); + + iUseTls = aUseTls; + + iMutex.CreateLocal ( ); + } + +CXmlRpcClient::CXmlRpcClient( ) + { + + } + +EXPORT_C CXmlRpcClient::~CXmlRpcClient() + { + iHostPath.Close(); + iTargetId.Close(); + iHostAddr.Close(); + iRequest.Close(); + iResponse.Close(); + + CleanupStack::Pop(5); + + iMutex.Close(); + } + +EXPORT_C TBool CXmlRpcClient::InvokeL(MXmlRpcResponseHandlerInterface* aInterface, const TDesC8& aMethod, + RPointerArray* aArray, + CXmlRpcValue& aResult ) + { + + // Only one call per client at the same time + iMutex.Wait(); + + iResponseHandlerInterface = aInterface; + + // set pointer on caller's CXmlRpcValue to store the result to: + iResponseParsedPtr = &aResult; + + if ( !GenerateXmlRpcBodyL( aMethod, aArray ) ) + { + iMutex.Signal(); + return EFalse; + } + + RBuf8 remoteUri; + remoteUri.CleanupClosePushL(); + if (iUseTls) + { + remoteUri.CreateL( KPROTOHTTPS, KPROTOHTTPS().Length() + iHostAddr.Length() + iHostPath.Length() ); + } + else + { + remoteUri.CreateL( KPROTOHTTP, KPROTOHTTP().Length() + iHostAddr.Length() + iHostPath.Length() ); + } + remoteUri.Append(iHostAddr); + remoteUri.Append(iHostPath); + + iHttpClientEngine = CHttpClientEngine::NewL(); + + iHttpClientEngine->IssueHttpPostL((MXmlRpcResponseHandlerInterface*) this, &remoteUri, &_L8("text/xml"), &iRequest, &iResponse); + + CleanupStack::Pop(&remoteUri); //CleanupStack::PopAndDestroy(); + remoteUri.Close(); + + CleanupStack::Pop(&iRequest); + iRequest.Close(); + + //aArray->ResetAndDestroy(); + //delete aArray; + return ETrue; + } + +void CXmlRpcClient::DoCancel( ) + { + if (iHttpClientEngine != NULL ) + { + iHttpClientEngine->CancelTransaction ( ); + } + } + +void CXmlRpcClient::RespondL( ) + { + //delete iHttpClientEngine; + //iHttpClientEngine = NULL; + + TBool retVal = ParseResponseL ( ); + + iResponse.Close(); + + if (retVal ) + { + iResponseHandlerInterface->RespondL ( ); + } + else + { + iResponseHandlerInterface->RespondErrorL ( -1 ); + } + + iMutex.Signal ( ); + } + +TInt CXmlRpcClient::RespondErrorL( TInt aError ) + { + return iResponseHandlerInterface->RespondErrorL (aError ); + } + +TBool CXmlRpcClient::GenerateXmlRpcBodyL( const TDesC8& aMethod, + const RPointerArray* aArray ) + { + iRequest.CleanupClosePushL ( ); + iRequest.CreateL ( + KVERSION, + KVERSION().Length ( )+ KREQUEST_START().Length ( )+iTargetId.Length ( )+ 1 + aMethod.Length ( )+KMETHODNAME_END().Length ( ) ); + iRequest.Append ( KREQUEST_START ); + iRequest.Append ( iTargetId ); + iRequest.Append ( _L(".") ); + iRequest.Append ( aMethod ); + iRequest.Append ( KMETHODNAME_END ); + + TInt arrayCount = aArray->Count ( ); + + if ( arrayCount == 0 ) + { + iRequest.ReAllocL (iRequest.Length ( )+ KMETHODCALL_ETAG().Length ( )+ 2 * KCRNL().Length ( ) ); + + iRequest.Append ( KMETHODCALL_ETAG ); + iRequest.Append ( KCRNL ); + iRequest.Append ( KCRNL ); + + return ETrue; + } + + iRequest.ReAllocL (iRequest.Length ( )+ KPARAMS_TAG().Length ( ) ); + + iRequest.Append ( KPARAMS_TAG ); + + if ( arrayCount > 0 ) + { + + for (TInt index = 0; index < arrayCount; index++ ) + { + + HBufC8* paramData = (*aArray)[index]->ToXmlnL ( ); + CleanupStack::PushL ( paramData ); + + iRequest.ReAllocL (iRequest.Length ( )+ KPARAM_TAG().Length ( )+ paramData->Length ( )+ KPARAM_ETAG().Length ( ) ); + + iRequest.Append ( KPARAM_TAG ); + iRequest.Append ( paramData->Des ( ) ); + iRequest.Append ( KPARAM_ETAG ); + + CleanupStack::PopAndDestroy ( paramData ); + } + + } + + iRequest.ReAllocL (iRequest.Length ( )+ KPARAMS_ETAG().Length ( )+ KMETHODCALL_ETAG().Length ( )+ 2 * KCRNL().Length ( ) ); + + iRequest.Append ( KPARAMS_ETAG ); + iRequest.Append ( KMETHODCALL_ETAG ); + iRequest.Append ( KCRNL ); + iRequest.Append ( KCRNL ); + + return ETrue; + } + +TBool CXmlRpcClient::ParseResponseL( ) + { + TInt offset = 0; + if ( !TXmlUtil::FindTag( KMETHODRESPONSE_TAG, iResponse, &offset ) ) + return EFalse; + + if ( ( TXmlUtil::NextTagIs(KPARAMS_TAG, iResponse, &offset) && + TXmlUtil::NextTagIs(KPARAM_TAG, iResponse, &offset) ) ||TXmlUtil::NextTagIs ( + KFAULT_TAG, iResponse, &offset ) ) + { + if ( !iResponseParsedPtr->FromXmlnL( iResponse, &offset ) ) + return EFalse; // No valid value found + + } + else + return EFalse; //Not valid response + + return iResponseParsedPtr->Valid ( ); + } \ No newline at end of file diff --git a/src/XmlRpcUtil.cpp b/src/XmlRpcUtil.cpp new file mode 100644 index 0000000..8c05729 --- /dev/null +++ b/src/XmlRpcUtil.cpp @@ -0,0 +1,97 @@ + +#include "XmlRpcUtil.h" +#include "XmlRpcConstants.h" + + +EXPORT_C HBufC8* CXmlRpcUtil::XmlDecodeL(const TDesC8& aDecode) { + if( aDecode.Length() == 0 ) + return KNullDesC8().AllocL(); + + HBufC8* tempBuf = aDecode.AllocL(); + TPtr8 tempPtr = tempBuf->Des(); + + TInt offset = tempBuf->Find( K_AMP_Patter ); + + while ( offset != KErrNotFound ) { + tempPtr.Replace( offset, 5, K_RAW_AMP ); + offset = tempBuf->Find( K_AMP_Patter ); + } + + offset = tempBuf->Find( K_LT_Pattern() ); + while ( offset != KErrNotFound ) { + tempPtr.Replace( offset, 4, K_RAW_LT ); + offset = tempBuf->Find( K_LT_Pattern ); + } + + return tempBuf; +} + + +EXPORT_C HBufC8* CXmlRpcUtil::XmlEncodeL(const TDesC8& aEncode ) { + const TChar LT_Char = '<'; + const TChar AMP_Char = '&'; + + if( aEncode.Length() == 0 ) + return KNullDesC8().AllocL(); + + HBufC8* tempBuf = HBufC8::NewL( CalcNewLength( aEncode ) ); + TPtr8 tempPtr = tempBuf->Des(); + tempPtr.Copy( aEncode ); + TPtrC8 encodePtrC; + + // Remove all non-printable characters + for(TInt index = tempPtr.Length() - 1; index >= 0; index--) { + TChar ch = tempPtr[index]; + if(!ch.IsPrint()) + tempPtr.Delete(index, 1); + } + + // Let's change all '&':s first + TInt offset = aEncode.LocateReverse( AMP_Char ); + while( offset != KErrNotFound ) { + tempPtr.Replace( offset, 1, K_AMP_Patter ); + encodePtrC.Set( aEncode.Left( offset )); + offset = encodePtrC.LocateReverse( AMP_Char ); + } + + // Okay, let's move forward to '>':es + encodePtrC.Set( tempBuf->Des() ); + + offset = encodePtrC.LocateReverse( LT_Char ); + while( offset != KErrNotFound ) { + tempPtr.Replace( offset, 1, K_LT_Pattern ); + encodePtrC.Set( encodePtrC.Left( offset )); + offset = encodePtrC.LocateReverse( LT_Char ); + } + + return tempBuf; +} + + +// Calculates a new length for the HBufC to be constructed (by XMLEncode method) +TInt CXmlRpcUtil::CalcNewLength( const TDesC8& aData ) { + TInt length = aData.Length(); + TPtrC8 restData = aData; + + TInt offset = restData.Find( K_RAW_LT ); + + //Find out the "<":s + while( offset != KErrNotFound ) { + + length += K_LT().Length(); + restData.Set( restData.Right( restData.Length() - offset - 1 ) ); + offset = restData.Find( K_RAW_LT ); + } + + restData.Set( aData ); + offset = restData.Find( K_RAW_AMP ); + + //Find out the "&":s + while( offset != KErrNotFound ) { + length += K_AMP().Length(); + restData.Set( restData.Right( restData.Length() - offset - 1 ) ); + offset = restData.Find( K_RAW_AMP ); + } + + return length; +} diff --git a/src/XmlRpcValue.cpp b/src/XmlRpcValue.cpp new file mode 100644 index 0000000..95f0fe1 --- /dev/null +++ b/src/XmlRpcValue.cpp @@ -0,0 +1,1201 @@ + +#include "XmlRpcValue.h" +#include "XmlRpcUtil.h" +#include "XmlUtil.h" +#include "XmlRpcConstants.h" +#include "Base64.h" + + +EXPORT_C CXmlRpcValue* CXmlRpcValue::NewL() { + CXmlRpcValue* self = CXmlRpcValue::NewLC(); + CleanupStack::Pop( self ); + return self; +} + + +EXPORT_C CXmlRpcValue* CXmlRpcValue::NewLC() { + CXmlRpcValue* self = new (ELeave) CXmlRpcValue(); + CleanupStack::PushL( self ); + return self; +} + + +EXPORT_C CXmlRpcValue* CXmlRpcValue::NewL( const TInt aValue ) { + CXmlRpcValue* self = CXmlRpcValue::NewLC( aValue ); + CleanupStack::Pop( self ); + return self; +} + + +EXPORT_C CXmlRpcValue* CXmlRpcValue::NewLC( const TInt aValue ) { + CXmlRpcValue* self = new (ELeave) CXmlRpcValue( aValue ); + CleanupStack::PushL( self ); + return self; +} + + +EXPORT_C CXmlRpcValue* CXmlRpcValue::NewBooleanL( const TBool aValue ) { + CXmlRpcValue* self = CXmlRpcValue::NewBooleanLC( aValue ); + CleanupStack::Pop( self ); + return self; +} + + +EXPORT_C CXmlRpcValue* CXmlRpcValue::NewBooleanLC( const TBool aValue ) { + CXmlRpcValue* self = new (ELeave) CXmlRpcValue(); + CleanupStack::PushL( self ); + self->ConstructBooleanL( aValue ); + return self; +} + + +EXPORT_C CXmlRpcValue* CXmlRpcValue::NewL( const TReal aValue ) { + CXmlRpcValue* self = CXmlRpcValue::NewLC( aValue ); + CleanupStack::Pop( self ); + return self; +} + + +EXPORT_C CXmlRpcValue* CXmlRpcValue::NewLC( const TReal aValue ) { + CXmlRpcValue* self = new (ELeave) CXmlRpcValue( aValue ); + CleanupStack::PushL( self ); + return self; +} + + +EXPORT_C CXmlRpcValue* CXmlRpcValue::NewL( const TDateTime& aValue ) { + CXmlRpcValue* self = CXmlRpcValue::NewLC( aValue ); + CleanupStack::Pop( self ); + return self; +} + + +EXPORT_C CXmlRpcValue* CXmlRpcValue::NewLC( const TDateTime& aValue ) { + CXmlRpcValue* self = new (ELeave) CXmlRpcValue( ); + CleanupStack::PushL( self ); + self->ConstructL( aValue ); + return self; +} + + +EXPORT_C CXmlRpcValue* CXmlRpcValue::NewL( const TDesC& aValue ) { + CXmlRpcValue* self = CXmlRpcValue::NewLC( aValue ); + CleanupStack::Pop( self ); + return self; +} + + +EXPORT_C CXmlRpcValue* CXmlRpcValue::NewLC( const TDesC& aValue ) { + CXmlRpcValue* self = new (ELeave) CXmlRpcValue( ); + CleanupStack::PushL( self ); + self->ConstructL(aValue); + return self; +} + + +EXPORT_C CXmlRpcValue* CXmlRpcValue::NewL( HBufC* aValue ) { + CXmlRpcValue* self = CXmlRpcValue::NewLC( aValue ); + CleanupStack::Pop( self ); + return self; +} + + +EXPORT_C CXmlRpcValue* CXmlRpcValue::NewLC( HBufC* aValue ) { + CXmlRpcValue* self = new (ELeave) CXmlRpcValue( ); + CleanupStack::PushL( self ); + self->ConstructL(aValue); + return self; +} + + +EXPORT_C CXmlRpcValue* CXmlRpcValue::NewL( const TDesC8& aValue ) { + CXmlRpcValue* self = CXmlRpcValue::NewLC( aValue ); + CleanupStack::Pop( self ); + return self; +} + + +EXPORT_C CXmlRpcValue* CXmlRpcValue::NewLC( const TDesC8& aValue ) { + CXmlRpcValue* self = new (ELeave) CXmlRpcValue( ); + CleanupStack::PushL( self ); + self->ConstructL(aValue); + return self; +} + + +EXPORT_C CXmlRpcValue* CXmlRpcValue::NewL( HBufC8* aValue ) { + CXmlRpcValue* self = CXmlRpcValue::NewLC( aValue ); + CleanupStack::Pop( self ); + return self; +} + + +EXPORT_C CXmlRpcValue* CXmlRpcValue::NewLC( HBufC8* aValue ) { + CXmlRpcValue* self = new (ELeave) CXmlRpcValue( ); + CleanupStack::PushL( self ); + self->ConstructL(aValue); + return self; +} + + +EXPORT_C CXmlRpcValue* CXmlRpcValue::NewL( const CVector& aValue ) { + CXmlRpcValue* self = CXmlRpcValue::NewLC( aValue ); + CleanupStack::Pop( self ); + return self; +} + + +EXPORT_C CXmlRpcValue* CXmlRpcValue::NewLC( const CVector& aValue ) { + CXmlRpcValue* self = new (ELeave) CXmlRpcValue(); + CleanupStack::PushL( self ); + self->ConstructL( aValue ); + return self; +} + + +EXPORT_C CXmlRpcValue* CXmlRpcValue::NewL( CVector* aValue ) { + CXmlRpcValue* self = CXmlRpcValue::NewLC( aValue ); + CleanupStack::Pop(); + return self; +} + + +EXPORT_C CXmlRpcValue* CXmlRpcValue::NewLC( CVector* aValue ) { + CXmlRpcValue* self = new (ELeave) CXmlRpcValue(); + CleanupStack::PushL( self ); + self->ConstructL( (CVector*)aValue ); + return self; +} + + +EXPORT_C CXmlRpcValue* CXmlRpcValue::NewL( const CKeyValueTable& aValue ) { + CXmlRpcValue* self = CXmlRpcValue::NewLC( aValue ); + CleanupStack::Pop( self ); + return self; +} + + +EXPORT_C CXmlRpcValue* CXmlRpcValue::NewLC( const CKeyValueTable& aValue ) { + CXmlRpcValue* self = new (ELeave) CXmlRpcValue(); + CleanupStack::PushL( self ); + self->ConstructL( aValue ); + return self; +} + + +EXPORT_C CXmlRpcValue* CXmlRpcValue::NewL( CKeyValueTable* aValue ) { + CXmlRpcValue* self = CXmlRpcValue::NewLC( aValue ); + CleanupStack::Pop( self); + return self; +} + + +EXPORT_C CXmlRpcValue* CXmlRpcValue::NewLC( CKeyValueTable* aValue ) { + CXmlRpcValue* self = new (ELeave) CXmlRpcValue(); + CleanupStack::PushL( self ); + self->ConstructL( aValue ); + return self; +} + + +EXPORT_C CXmlRpcValue* CXmlRpcValue::NewL( const TDesC8& aXml, TInt* aOffset ) { + CXmlRpcValue* value = CXmlRpcValue::NewL(); + CleanupStack::PushL( value ); + value->FromXmlnL( aXml, aOffset ); + CleanupStack::Pop( value ); + return value; +} + + +EXPORT_C CXmlRpcValue::~CXmlRpcValue() { + Invalidate(); +} + + +//! Defaut constructor +CXmlRpcValue::CXmlRpcValue() : iType(CXmlRpcValue::ETypeInvalid) { + +} + + +//! Sets the String data +void CXmlRpcValue::ConstructL( const TDesC& aValue ) { + iType = CXmlRpcValue::ETypeString; + iValue.asString = aValue.AllocL(); +} + + +//! Sets the String data +void CXmlRpcValue::ConstructL( HBufC* aValue ) { + iType = CXmlRpcValue::ETypeString; + iValue.asString = aValue; +} + +//! Sets the Time data +void CXmlRpcValue::ConstructL( const TDateTime& aValue ) { + TDateTime* time = new (ELeave) TDateTime(); + time->Set( aValue.Year(), aValue.Month(), aValue.Day(), + aValue.Hour() ,aValue.Minute() ,aValue.Second() ,aValue.MicroSecond() ); + + iType = CXmlRpcValue::ETypeDateTime; + iValue.asTime = time; +} + + +//! Sets the Binary data +void CXmlRpcValue::ConstructL( const TDesC8& aValue ) { + iType = CXmlRpcValue::ETypeBase64; + iValue.asBinary = aValue.AllocL(); +} + +//! Sets the Binary data +void CXmlRpcValue::ConstructL( HBufC8* aValue ) { + iType = CXmlRpcValue::ETypeBase64; + iValue.asBinary = aValue; +} + +//! Sets the Array data +void CXmlRpcValue::ConstructL( const CVector& aValue ) { + iType = CXmlRpcValue::ETypeArray; + iValue.asArray = aValue.DuplicateL(); +} + + +//! Sets the Array data +void CXmlRpcValue::ConstructL( CVector* aValue ) { + iType = CXmlRpcValue::ETypeArray; + iValue.asArray = aValue; +} + + +//! Sets the Struct data +void CXmlRpcValue::ConstructL( const CKeyValueTable& aValue ) { + iType = CXmlRpcValue::ETypeStruct; + iValue.asStruct = aValue.DuplicateL(); +} + + +//! Sets the Struct data +void CXmlRpcValue::ConstructL( CKeyValueTable* aValue ) { + iType = CXmlRpcValue::ETypeStruct; + iValue.asStruct = aValue; +} + + +EXPORT_C TBool CXmlRpcValue::operator==( const CXmlRpcValue& aValue ) const { + + if( iType != aValue.GetType() ) + return EFalse; + + switch(iType) { + case CXmlRpcValue::ETypeBoolean: return( iValue.asBool && aValue.iValue.asBool || + !iValue.asBool && !aValue.iValue.asBool ); + case CXmlRpcValue::ETypeDouble: return( iValue.asDouble == aValue.iValue.asDouble ); + case CXmlRpcValue::ETypeInt: return( iValue.asInt == aValue.iValue.asInt ); + case CXmlRpcValue::ETypeString: return( *iValue.asString == *aValue.iValue.asString ); + case CXmlRpcValue::ETypeDateTime: return( + iValue.asTime->Year() == aValue.iValue.asTime->Year() && + iValue.asTime->Month() == aValue.iValue.asTime->Month() && + iValue.asTime->Day() == aValue.iValue.asTime->Day() && + iValue.asTime->Hour() == aValue.iValue.asTime->Hour() && + iValue.asTime->Minute() == aValue.iValue.asTime->Minute() && + iValue.asTime->Second() == aValue.iValue.asTime->Second() ); + // Microseconds not needed! (Not supported by XmlRpc) + + case CXmlRpcValue::ETypeBase64: return( *iValue.asBinary == *aValue.iValue.asBinary ); + case CXmlRpcValue::ETypeArray: return ( iValue.asArray->Equals( aValue.iValue.asArray ) ); + case CXmlRpcValue::ETypeStruct: return ( iValue.asStruct->Equals( aValue.iValue.asStruct ) ); + default: break; + } + + return EFalse; +} + + +EXPORT_C TBool CXmlRpcValue::operator!=( const CXmlRpcValue& aValue ) const { + return !(*this == aValue); +} + + +EXPORT_C TBool& CXmlRpcValue::GetBoolValue() { + AssertTypeOrInvalid( CXmlRpcValue::ETypeBoolean ); + return iValue.asBool; +} + + +EXPORT_C TInt& CXmlRpcValue::GetIntValue() { + AssertTypeOrInvalid( CXmlRpcValue::ETypeInt ); + return iValue.asInt; +} + + +EXPORT_C TReal& CXmlRpcValue::GetRealValue() { + AssertTypeOrInvalid( CXmlRpcValue::ETypeDouble ); + return iValue.asDouble; +} + + +EXPORT_C TDateTime& CXmlRpcValue::GetDateTimeValue() { + AssertTypeOrInvalid( CXmlRpcValue::ETypeDateTime ); + return *iValue.asTime; +} + + +EXPORT_C TDesC& CXmlRpcValue::GetStringValue() { + AssertTypeOrInvalid( CXmlRpcValue::ETypeString ); + return *iValue.asString; +} + + +EXPORT_C TDesC8& CXmlRpcValue::GetBinaryValue() { + AssertTypeOrInvalid( CXmlRpcValue::ETypeBase64 ); + return *iValue.asBinary; +} + + +EXPORT_C CVector& CXmlRpcValue::GetArrayValue() { + AssertTypeOrInvalid( CXmlRpcValue::ETypeArray ); + return *iValue.asArray; +} + + +EXPORT_C CKeyValueTable& CXmlRpcValue::GetStructValue() { + AssertTypeOrInvalid( CXmlRpcValue::ETypeStruct ); + return *iValue.asStruct; +} + + +EXPORT_C void CXmlRpcValue::SetBoolValueL( TInt aValue ) { + Invalidate(); + ConstructBooleanL(aValue); + iType=CXmlRpcValue::ETypeBoolean; +} + + +EXPORT_C void CXmlRpcValue::SetValueL( TInt aValue ) { + Invalidate(); + iValue.asInt = aValue; + iType=CXmlRpcValue::ETypeInt; +} + + +EXPORT_C void CXmlRpcValue::SetValueL( TReal aValue ) { + Invalidate(); + iValue.asDouble = aValue; + iType=CXmlRpcValue::ETypeDouble; +} + + +EXPORT_C void CXmlRpcValue::SetValueL( const TDesC& aValue ) { + Invalidate(); + ConstructL( aValue ); + iType=CXmlRpcValue::ETypeString; +} + + +EXPORT_C void CXmlRpcValue::SetValueL( HBufC* aValue ) { + Invalidate(); + iValue.asString = aValue; + iType=CXmlRpcValue::ETypeString; +} + + +EXPORT_C void CXmlRpcValue::SetValueL( const TDateTime& aValue ) { + Invalidate(); + ConstructL( aValue ); + iType=CXmlRpcValue::ETypeDateTime; +} + + +EXPORT_C void CXmlRpcValue::SetValueL( const TDesC8& aValue ) { + Invalidate(); + ConstructL( aValue ); + iType=CXmlRpcValue::ETypeBase64; +} + + +EXPORT_C void CXmlRpcValue::SetValueL( HBufC8* aValue ) { + Invalidate(); + iValue.asBinary = aValue; + iType=CXmlRpcValue::ETypeBase64; +} + + +EXPORT_C void CXmlRpcValue::SetValueL( CVector* aValue ) { + Invalidate(); + iValue.asArray = aValue; + iType=CXmlRpcValue::ETypeArray; +} + + +EXPORT_C void CXmlRpcValue::SetValueL( CKeyValueTable* aValue ) { + Invalidate(); + iValue.asStruct = aValue; + iType=CXmlRpcValue::ETypeStruct; +} + + +EXPORT_C void CXmlRpcValue::SetValueL( const CXmlRpcValue* aValue ) { + + switch( aValue->iType ) { + case CXmlRpcValue::ETypeBoolean: + SetBoolValueL( aValue->iValue.asBool ); + break; + case CXmlRpcValue::ETypeDouble: + SetValueL( aValue->iValue.asDouble ); + break; + case CXmlRpcValue::ETypeInt: + SetValueL( aValue->iValue.asInt ); + break; + case CXmlRpcValue::ETypeDateTime: + SetValueL( *aValue->iValue.asTime ); + break; + case CXmlRpcValue::ETypeString: + SetValueL( *aValue->iValue.asString ); + break; + case CXmlRpcValue::ETypeBase64: + SetValueL( *aValue->iValue.asBinary ); + break; + case CXmlRpcValue::ETypeArray: + SetValueL( aValue->iValue.asArray ); + break; + case CXmlRpcValue::ETypeStruct: + SetValueL( aValue->iValue.asStruct ); + break; + case CXmlRpcValue::ETypeInvalid: + break; + } +} + + +EXPORT_C CXmlRpcValue* CXmlRpcValue::DuplicateL() const { + CXmlRpcValue* duplicate = CXmlRpcValue::NewL(); + + switch( iType ) { + case CXmlRpcValue::ETypeBoolean: + duplicate->SetBoolValueL( iValue.asBool ); + break; + case CXmlRpcValue::ETypeDouble: + duplicate->SetValueL( iValue.asDouble ); + break; + case CXmlRpcValue::ETypeInt: + duplicate->SetValueL( iValue.asInt ); + break; + case CXmlRpcValue::ETypeDateTime: + duplicate->SetValueL( *iValue.asTime ); + break; + case CXmlRpcValue::ETypeString: + duplicate->SetValueL( iValue.asString->Alloc() ); + break; + case CXmlRpcValue::ETypeBase64: + duplicate->SetValueL( iValue.asBinary->Alloc() ); + break; + case CXmlRpcValue::ETypeArray: + duplicate->SetValueL( iValue.asArray->DuplicateL() ); + break; + case CXmlRpcValue::ETypeStruct: + duplicate->SetValueL( iValue.asStruct->DuplicateL() ); + break; + case CXmlRpcValue::ETypeInvalid: + break; + } + + return duplicate; +} + + +EXPORT_C TBool CXmlRpcValue::Valid() const { + return iType != CXmlRpcValue::ETypeInvalid; +} + + +EXPORT_C CXmlRpcValue::EType CXmlRpcValue::GetType() const { + return iType; +} + + +void CXmlRpcValue::Invalidate() { + switch(iType) { + case CXmlRpcValue::ETypeString: delete iValue.asString; break; + case CXmlRpcValue::ETypeDateTime: delete iValue.asTime; break; + case CXmlRpcValue::ETypeBase64: delete iValue.asBinary; break; + case CXmlRpcValue::ETypeArray: delete iValue.asArray; break; + case CXmlRpcValue::ETypeStruct: delete iValue.asStruct; break; + default: break; + } + iType = CXmlRpcValue::ETypeInvalid; +} + + +void CXmlRpcValue::AssertTypeOrInvalid( CXmlRpcValue::EType aType ) { + + TRAPD( err, { + if( iType == CXmlRpcValue::ETypeInvalid ) { + iType = aType; + + switch( iType ) { + case CXmlRpcValue::ETypeString: iValue.asString = KNullDesC().AllocL(); break; + case CXmlRpcValue::ETypeDateTime: iValue.asTime = new (ELeave) TDateTime(0,TMonth(0),0,0,0,0,0); break; + case CXmlRpcValue::ETypeBase64: iValue.asBinary = KNullDesC8().AllocL(); break; + case CXmlRpcValue::ETypeArray: iValue.asArray = CVector::NewL(); break; + case CXmlRpcValue::ETypeStruct: iValue.asStruct = CKeyValueTable::NewL(); break; + default: break; + } + } else if( iType != aType ) { + // Invalidate the value! + Invalidate(); + } + }); + + if( err != KErrNone ) { + // Invalicate the value + Invalidate(); + } +} + + +// Returns the XmlRpcValue as XML +EXPORT_C HBufC8* CXmlRpcValue::ToXmlnL() { + + switch(iType) { + case CXmlRpcValue::ETypeBoolean: return BoolToXmlnL(); + case CXmlRpcValue::ETypeDouble: return DoubleToXmlnL(); + case CXmlRpcValue::ETypeInt: return IntToXmlnL(); + case CXmlRpcValue::ETypeString: return StringToXmlnL(); + case CXmlRpcValue::ETypeDateTime: return TimeToXmlnL(); + case CXmlRpcValue::ETypeBase64: return BinaryToXmlnL(); + case CXmlRpcValue::ETypeArray: return ArrayToXmlnL(); + case CXmlRpcValue::ETypeStruct: return StructToXmlnL(); + default: break; + } + HBufC8* asXml = HBufC8::NewL(44); + asXml->Des().Copy( _L8("CXmlRpcValue::ToXmlnL() ERROR: Type Invalid!")); + return asXml; +} + + +/* +* XML - Value Decoding and encoding functions: These functions de- and encodes +* the data to/from XML representation. The both (encode & decode) functions +* are in following order: +* +* Boolean +* Integer +* Double +* String +* Datetime +* Base64 +* Array +* Struct +*/ + + +EXPORT_C TBool CXmlRpcValue::FromXmlnL( const TDesC8& aXml, TInt* aOffset ) { + + Invalidate(); + if( aXml.Length() < *aOffset) return EFalse; + + TInt originalOffset = *aOffset; + if( !TXmlUtil::NextTagIs( KVALUE_TAG, aXml, aOffset ) ) + return EFalse; + + HBufC8* typeTag = TXmlUtil::GetNextTagL( aXml, aOffset ); + CleanupStack::PushL( typeTag ); + TPtr8 typeTagPtr = typeTag->Des(); + + TPtrC8 dataPtr; + TInt dataStartOffset = *aOffset; + TBool result = EFalse; + if( typeTagPtr.Compare( KBOOLEAN_TAG ) == 0 ) { + if( TXmlUtil::FindTag( KBOOLEAN_ETAG, aXml, aOffset ) ) { + dataPtr.Set( aXml.Mid( dataStartOffset, *aOffset - + dataStartOffset - + KBOOLEAN_ETAG().Length() ) ); + if( TXmlUtil::NextTagIs( KVALUE_ETAG, aXml, aOffset ) ) + result = BoolFromXmlnL( dataPtr ); + } + } else if ( typeTagPtr.Compare( KI4_TAG ) == 0 ) { + if( TXmlUtil::FindTag( KI4_ETAG, aXml, aOffset ) ) { + dataPtr.Set( aXml.Mid( dataStartOffset, *aOffset - + dataStartOffset - + KI4_ETAG().Length() ) ); + if( TXmlUtil::NextTagIs( KVALUE_ETAG, aXml, aOffset ) ) + result = Int4FromXmlnL( dataPtr ); + } + } else if ( typeTagPtr.Compare( KINT_TAG ) == 0 ) { + if( TXmlUtil::FindTag( KINT_ETAG, aXml, aOffset ) ) { + dataPtr.Set( aXml.Mid( dataStartOffset, *aOffset - + dataStartOffset - + KINT_ETAG().Length() ) ); + if( TXmlUtil::NextTagIs( KVALUE_ETAG, aXml, aOffset ) ) + result = IntFromXmlnL( dataPtr ); + } + } else if ( typeTagPtr.Compare( KDOUBLE_TAG ) == 0 ) { + if( TXmlUtil::FindTag( KDOUBLE_ETAG, aXml, aOffset ) ) { + dataPtr.Set( aXml.Mid( dataStartOffset, *aOffset - + dataStartOffset - + KDOUBLE_ETAG().Length() ) ); + if( TXmlUtil::NextTagIs( KVALUE_ETAG, aXml, aOffset ) ) + result = DoubleFromXmlnL( dataPtr ); + } + } else if ( typeTagPtr.Compare( KSTRING_TAG ) == 0 ) { + if( TXmlUtil::FindTag( KSTRING_ETAG, aXml, aOffset ) ) { + dataPtr.Set( aXml.Mid( dataStartOffset, *aOffset - + dataStartOffset - + KSTRING_ETAG().Length() ) ); + if( TXmlUtil::NextTagIs( KVALUE_ETAG, aXml, aOffset ) ) + result = StringFromXmlnL( dataPtr ); + } + } else if ( typeTagPtr.Compare( KDATETIME_TAG ) == 0 ) { + if( TXmlUtil::FindTag( KDATETIME_ETAG, aXml, aOffset ) ) { + dataPtr.Set( aXml.Mid( dataStartOffset, *aOffset - + dataStartOffset - + KDATETIME_ETAG().Length() ) ); + if( TXmlUtil::NextTagIs( KVALUE_ETAG, aXml, aOffset ) ) + result = TimeFromXmlnL( dataPtr ); + } + } else if ( typeTagPtr.Compare( KBASE64_TAG ) == 0 ) { + if( TXmlUtil::FindTag( KBASE64_ETAG, aXml, aOffset ) ) { + dataPtr.Set( aXml.Mid( dataStartOffset, *aOffset - + dataStartOffset - + KBASE64_ETAG().Length() ) ); + if( TXmlUtil::NextTagIs( KVALUE_ETAG, aXml, aOffset ) ) + result = BinaryFromXmlnL( dataPtr ); + } + } else if ( typeTagPtr.Compare( KARRAY_TAG ) == 0 ) { + TInt tempOffset = *aOffset; + TInt depth = 1; + TPtrC8 tempPtr; + + // Handle nested arrays + while( depth != 0 ) { + if( !TXmlUtil::FindTag( KARRAY_ETAG, aXml, aOffset ) ) + break; + tempPtr.Set( aXml.Mid(0, *aOffset ) ); + depth--; + + while( TXmlUtil::FindTag( KARRAY_TAG, tempPtr, &tempOffset ) ) { + depth++; + } + } + + if( depth == 0 ) { + dataPtr.Set( aXml.Mid( dataStartOffset, *aOffset - + dataStartOffset - + KARRAY_ETAG().Length() ) ); + if( TXmlUtil::NextTagIs( KVALUE_ETAG, aXml, aOffset ) ) + result = ArrayFromXmlnL( dataPtr ); + } + } else if ( typeTagPtr.Compare( KSTRUCT_TAG ) == 0 ) { + TInt tempOffset = *aOffset; + TInt depth = 1; + TPtrC8 tempPtr; + + // Handle nested structures + while( depth != 0 ) { + if( !TXmlUtil::FindTag( KSTRUCT_ETAG, aXml, aOffset ) ) + break; + tempPtr.Set( aXml.Mid(0, *aOffset ) ); + depth--; + + while( TXmlUtil::FindTag( KSTRUCT_TAG, tempPtr, &tempOffset ) ) { + depth++; + } + } + + if( depth == 0 ) { + dataPtr.Set( aXml.Mid( dataStartOffset, *aOffset - + dataStartOffset - + KSTRUCT_ETAG().Length() ) ); + if( TXmlUtil::NextTagIs( KVALUE_ETAG, aXml, aOffset ) ) + result = StructFromXmlnL( dataPtr ); + } + } else if ( typeTagPtr.Length() == 0 ) { + //Handle default type + if( TXmlUtil::FindTag( KVALUE_ETAG, aXml, aOffset ) ) { + dataPtr.Set( aXml.Mid( dataStartOffset, *aOffset - + dataStartOffset - + KVALUE_ETAG().Length() ) ); + result = NonTaggedStringFromXmlnL( dataPtr ); + } + } else if ( typeTagPtr.Compare( KVALUE_ETAG ) == 0 ) { + //Handle default type with no content (empty string) + ConstructL( KNullDesC8() ); + } + + + CleanupStack::PopAndDestroy( typeTag ); + + //! Error detected, return the original offset + if (!result) + *aOffset = originalOffset; + + return result; +} + + + +// Boolean: +HBufC8* CXmlRpcValue::BoolToXmlnL() +{ + TInt EVALUETAGSLENGTH = KVALUE_TAG().Length() + KVALUE_ETAG().Length(); + TInt boolLength = 1 + KBOOLEAN_TAG().Length() + KBOOLEAN_ETAG().Length() + EVALUETAGSLENGTH; + HBufC8* asXml = HBufC8::NewL( boolLength ); + TPtr8 asXmlPtr = asXml->Des(); + + asXmlPtr.Copy( KVALUE_TAG() ); + asXmlPtr.Append( KBOOLEAN_TAG() ); + asXmlPtr.Append( iValue.asBool ? _L("1") : _L("0") ); + asXmlPtr.Append( KBOOLEAN_ETAG() ); + asXmlPtr.Append( KVALUE_ETAG() ); + + return asXml; +} + + +TBool CXmlRpcValue::BoolFromXmlnL( const TDesC8& aXml ) +{ + TLex8 lex; + lex.Assign( aXml ); + TInt boolVal; + if ( lex.Val( boolVal ) != KErrNone ) + return EFalse; + + iType = CXmlRpcValue::ETypeBoolean; + boolVal != 0 ? iValue.asBool = ETrue : iValue.asBool = EFalse; + return ETrue; +} + + +//Integer +HBufC8* CXmlRpcValue::IntToXmlnL() +{ + TInt EVALUETAGSLENGTH = KVALUE_TAG().Length() + KVALUE_ETAG().Length(); + TInt intLength = 11 + KI4_TAG().Length() + KI4_ETAG().Length() + EVALUETAGSLENGTH; + HBufC8* asXml = HBufC8::NewL( intLength ); + TPtr8 asXmlPtr = asXml->Des(); + + asXmlPtr.Copy( KVALUE_TAG()); + asXmlPtr.Append( KI4_TAG()); + asXmlPtr.AppendNum( iValue.asInt ); + asXmlPtr.Append( KI4_ETAG() ); + asXmlPtr.Append( KVALUE_ETAG() ); + + return asXml; +} + + +TBool CXmlRpcValue::IntFromXmlnL( const TDesC8& aXml ) +{ + TInt intVal; + TLex8 lex; + lex.Assign( aXml ); + if ( lex.Val( intVal ) != KErrNone ) + return EFalse; + + iValue.asInt = intVal; + iType = CXmlRpcValue::ETypeInt; + return ETrue; +} + + +TBool CXmlRpcValue::Int4FromXmlnL( const TDesC8& aXml ) +{ + TInt intVal; + TLex8 lex; + lex.Assign( aXml ); + if ( lex.Val( intVal ) != KErrNone ) + return EFalse; + + iValue.asInt = intVal; + iType = CXmlRpcValue::ETypeInt; + return ETrue; +} + + +//Double: +HBufC8* CXmlRpcValue::DoubleToXmlnL() +{ + TInt EVALUETAGSLENGTH = KVALUE_TAG().Length() + KVALUE_ETAG().Length(); + TInt doubleLength = 64 + KDOUBLE_TAG().Length() + KDOUBLE_ETAG().Length() + EVALUETAGSLENGTH; + HBufC8* asXml = HBufC8::NewL( doubleLength ); + TPtr8 asXmlPtr = asXml->Des(); + + asXmlPtr.Copy( KVALUE_TAG() ); + asXmlPtr.Append( KDOUBLE_TAG() ); + + // Makes sure the system has a correct separator (on epoc can be different, + // depends on local settings + TLocale local; + local.SetDecimalSeparator( TChar('.') ); + local.Set(); + + asXmlPtr.AppendNum( iValue.asDouble, TRealFormat() ); + asXmlPtr.Append( KDOUBLE_ETAG() ); + asXmlPtr.Append( KVALUE_ETAG() ); + + return asXml; +} + + +TBool CXmlRpcValue::DoubleFromXmlnL( const TDesC8& aXml ) +{ + TReal doubleVal; + TLex8 lex; + lex.Assign( aXml ); + if ( lex.Val( doubleVal ) != KErrNone ) + return EFalse; + + iValue.asDouble = doubleVal; + iType = CXmlRpcValue::ETypeDouble; + return ETrue; +} + + +//String +HBufC8* CXmlRpcValue::StringToXmlnL() +{ + TInt EVALUETAGSLENGTH = KVALUE_TAG().Length() + KVALUE_ETAG().Length(); + + TPtrC valuePtr; + valuePtr.Set( *iValue.asString ); + HBufC8* stringValue8 = HBufC8::NewL( valuePtr.Length() ); + stringValue8->Des().Copy(valuePtr); + CleanupStack::PushL( stringValue8 ); + HBufC8* encodedString = CXmlRpcUtil::XmlEncodeL( *stringValue8 ); + CleanupStack::PopAndDestroy( stringValue8 ); + CleanupStack::PushL( encodedString ); + + HBufC8* asXml = HBufC8::NewL( KSTRING_TAG().Length() + + KSTRING_ETAG().Length() + + encodedString->Length() + + EVALUETAGSLENGTH ); + + TPtr8 asXmlPtr = asXml->Des(); + asXmlPtr.Copy( KVALUE_TAG ); + asXmlPtr.Append( KSTRING_TAG ); + asXmlPtr.Append( *encodedString ); + asXmlPtr.Append( KSTRING_ETAG ); + asXmlPtr.Append( KVALUE_ETAG ); + + CleanupStack::PopAndDestroy( encodedString ); + return asXml; +} + + +TBool CXmlRpcValue::StringFromXmlnL( const TDesC8& aXml ) +{ + HBufC8* decodedString = CXmlRpcUtil::XmlDecodeL( aXml ); + CleanupStack::PushL( decodedString ); + HBufC* stringValue = HBufC::NewL( decodedString->Length() ); + stringValue->Des().Copy(*decodedString); + ConstructL( stringValue ); + CleanupStack::PopAndDestroy( decodedString ); + + return ETrue; +} + + +TBool CXmlRpcValue::NonTaggedStringFromXmlnL( const TDesC8& aXml ) +{ + HBufC8* decodedString = CXmlRpcUtil::XmlDecodeL( aXml ); + CleanupStack::PushL( decodedString ); + HBufC* stringValue = HBufC::NewL( decodedString->Length() ); + stringValue->Des().Copy(*decodedString); + ConstructL( stringValue ); + CleanupStack::PopAndDestroy( decodedString ); + + return ETrue; +} + + +//DateTime +HBufC8* CXmlRpcValue::TimeToXmlnL() +{ + TInt EVALUETAGSLENGTH = KVALUE_TAG().Length() + KVALUE_ETAG().Length(); + HBufC8* asXml = HBufC8::NewL( KDATETIME_TAG().Length() + + KDATETIME_ETAG().Length() + + 17 + EVALUETAGSLENGTH); + TPtr8 asXmlPtr = asXml->Des(); + + asXmlPtr.Copy( KVALUE_TAG ); + asXmlPtr.Append( KDATETIME_TAG ); + TBuf<4> tempBuf; + tempBuf.NumFixedWidth( iValue.asTime->Year(), EDecimal, 4 ); + asXmlPtr.Append( tempBuf ); + tempBuf.NumFixedWidth( iValue.asTime->Month() + 1, EDecimal, 2 ); + asXmlPtr.Append( tempBuf ); + tempBuf.NumFixedWidth( iValue.asTime->Day() + 1, EDecimal, 2 ); + asXmlPtr.Append( tempBuf ); + asXmlPtr.Append( _L("T") ); + tempBuf.NumFixedWidth( iValue.asTime->Hour(), EDecimal, 2 ); + asXmlPtr.Append( tempBuf ); + asXmlPtr.Append( _L(":") ); + tempBuf.NumFixedWidth( iValue.asTime->Minute(), EDecimal, 2 ); + asXmlPtr.Append( tempBuf ); + asXmlPtr.Append( _L(":") ); + tempBuf.NumFixedWidth( iValue.asTime->Second(), EDecimal, 2 ); + asXmlPtr.Append( tempBuf ); + asXmlPtr.Append( KDATETIME_ETAG ); + asXmlPtr.Append( KVALUE_ETAG ); + + return asXml; +} + + +TBool CXmlRpcValue::TimeFromXmlnL( const TDesC8& aXml ) +{ + TInt tempInt; + TPtrC8 tempPtr; + TLex8 lex; + + TDateTime* dateTime = new (ELeave) TDateTime(0,TMonth(0),0,0,0,0,0); + CleanupStack::PushL( dateTime ); + + tempPtr.Set( aXml.Mid( 0, 4 ) ); + lex.Assign( tempPtr ); // Year + if ( lex.Val( tempInt ) != KErrNone ) return EFalse; + if ( dateTime->SetYear( tempInt ) != KErrNone ) return EFalse; + + tempPtr.Set( aXml.Mid( 4, 2 )); + lex.Assign( tempPtr ); // Month + if ( lex.Val( tempInt ) != KErrNone ) return EFalse; + if ( dateTime->SetMonth( TMonth( tempInt - 1 )) != KErrNone ) return EFalse; + + tempPtr.Set( aXml.Mid( 6, 2 )); + lex.Assign( tempPtr ); // Day + if ( lex.Val( tempInt ) != KErrNone ) return EFalse; + if ( dateTime->SetDay( tempInt - 1 ) != KErrNone ) return EFalse; + + tempPtr.Set( aXml.Mid( 9, 2 )); + lex.Assign( tempPtr ); // Hour + if ( lex.Val( tempInt ) != KErrNone ) return EFalse; + if ( dateTime->SetHour( tempInt ) != KErrNone ) return EFalse; + + tempPtr.Set( aXml.Mid( 12, 2 )); + lex.Assign( tempPtr ); // Minute + if ( lex.Val( tempInt ) != KErrNone ) return EFalse; + if ( dateTime->SetMinute( tempInt ) != KErrNone ) return EFalse; + + tempPtr.Set( aXml.Mid( 15, 2 )); + lex.Assign( tempPtr ); // Second + if ( lex.Val( tempInt ) != KErrNone ) return EFalse; + if ( dateTime->SetSecond( tempInt ) != KErrNone ) return EFalse; + + ConstructL( *dateTime ); + CleanupStack::PopAndDestroy( dateTime ); + + return ETrue; +} + + +//Base64 + HBufC8* CXmlRpcValue::BinaryToXmlnL() +{ + TPtrC8 valuePtr; + valuePtr.Set( *iValue.asBinary ); + HBufC8* encodedBinary = TBase64::Base64_EncodeL( valuePtr ); + CleanupStack::PushL( encodedBinary ); + + TInt EVALUETAGSLENGTH = KVALUE_TAG().Length() + KVALUE_ETAG().Length(); + HBufC8* asXml = HBufC8::NewL( KBASE64_TAG().Length() + + KBASE64_ETAG().Length() + + encodedBinary->Length() * 2+ + EVALUETAGSLENGTH ); + + TPtr8 asXmlPtr = asXml->Des(); + + + asXmlPtr.Copy( *encodedBinary ); + asXmlPtr.Insert( 0, KBASE64_TAG ); + asXmlPtr.Insert( 0, KVALUE_TAG ); + asXmlPtr.Append( KBASE64_ETAG ); + asXmlPtr.Append( KVALUE_ETAG ); + + CleanupStack::PopAndDestroy( encodedBinary ); + return asXml; +} + + +TBool CXmlRpcValue::BinaryFromXmlnL( const TDesC8& aXml ) +{ + HBufC8* tempBuf = HBufC8::NewL( aXml.Length() ); + tempBuf->Des().Copy( aXml ); + + CleanupStack::PushL( tempBuf ); + + HBufC8* decodedBinary = TBase64::Base64_DecodeL( *tempBuf ); + CleanupStack::PopAndDestroy( tempBuf ); + + CleanupStack::PushL( decodedBinary ); + ConstructL( *decodedBinary ); + CleanupStack::PopAndDestroy( decodedBinary ); + + return ETrue; +} + + +//Array + HBufC8* CXmlRpcValue::ArrayToXmlnL() +{ + TInt EVALUETAGSLENGTH = KVALUE_TAG().Length() + KVALUE_ETAG().Length(); + HBufC8* asXml = HBufC8::NewL( KARRAY_TAG().Length() + KARRAY_ETAG().Length() + + KDATA_TAG().Length() + KDATA_ETAG().Length() + + EVALUETAGSLENGTH ); + + TPtr8 asXmlPtr = asXml->Des(); + TInt elementCount = iValue.asArray->ElementCount(); + TInt endTagsLength = KDATA_ETAG().Length() + + KARRAY_ETAG().Length() + + KVALUE_ETAG().Length(); + + asXmlPtr.Copy( KVALUE_TAG ); + asXmlPtr.Append( KARRAY_TAG ); + asXmlPtr.Append( KDATA_TAG ); + + for (TInt index = 0 ; index < elementCount ; index++ ) { + CXmlRpcValue* rpcValue = iValue.asArray->ValueAt( index ); + CleanupStack::PushL( asXml ); + HBufC8* value = rpcValue->ToXmlnL(); + CleanupStack::Pop( asXml ); + asXml = asXml->ReAllocL( asXml->Length() + value->Length() + endTagsLength ); + asXmlPtr.Set( asXml->Des() ); + asXmlPtr.Append( *value ); + delete value; + } + + asXmlPtr.Append( KDATA_ETAG ); + asXmlPtr.Append( KARRAY_ETAG ); + asXmlPtr.Append( KVALUE_ETAG ); + + return asXml; +} + + +TBool CXmlRpcValue::ArrayFromXmlnL( const TDesC8& aXml ) +{ + TInt offset = 0; + if ( !TXmlUtil::NextTagIs( KDATA_TAG, aXml, &offset ) ) return EFalse; + TInt tempOffset = 0; + if ( !TXmlUtil::FindTag( KDATA_ETAG, aXml, &tempOffset ) ) return EFalse; + + CVector* vector = CVector::NewL(); + CleanupStack::PushL( vector ); + + while ( !TXmlUtil::NextTagIs( KDATA_ETAG, aXml, &offset ) ) { + CXmlRpcValue* value = CXmlRpcValue::NewL(); + CleanupStack::PushL( value ); + if( !value->FromXmlnL( aXml, &offset ) ) { + CleanupStack::PopAndDestroy( value ); + CleanupStack::PopAndDestroy( vector ); + return EFalse; + } + vector->Add( value ); + CleanupStack::Pop( value ); + } + + ConstructL( vector ); + CleanupStack::Pop( vector ); + + return ETrue; +} + + +//Struct + HBufC8* CXmlRpcValue::StructToXmlnL() +{ + TInt endTags = KSTRUCT_ETAG().Length() + KVALUE_ETAG().Length(); + TInt memberNameTags = KMEMBER_TAG().Length() + KMEMBER_ETAG().Length() + + KNAME_TAG().Length() + KNAME_ETAG().Length(); + + HBufC8* asXml = HBufC8::NewL( KVALUE_TAG().Length() + + KSTRUCT_TAG().Length() + + endTags ); + + TPtr8 asXmlPtr = asXml->Des(); + + asXmlPtr.Copy( KVALUE_TAG ); + asXmlPtr.Append( KSTRUCT_TAG ); + + TInt elementCount = iValue.asStruct->ElementCount(); + for (TInt index = 0 ; index < elementCount ; index++ ) { + CleanupStack::PushL( asXml ); + HBufC8* key = iValue.asStruct->KeyAtL( index ); + CXmlRpcValue* rpcValue = iValue.asStruct->ValueAt( index ); + HBufC8* value = rpcValue->ToXmlnL(); + + CleanupStack::Pop( asXml ); + CleanupStack::PushL( key ); + CleanupStack::PushL( value ); + asXml = asXml->ReAllocL( asXml->Length() + key->Length() + + value->Length() + memberNameTags + endTags ); + asXmlPtr.Set( asXml->Des() ); + + asXmlPtr.Append( KMEMBER_TAG ); + asXmlPtr.Append( KNAME_TAG ); + asXmlPtr.Append( *key ); + asXmlPtr.Append( KNAME_ETAG ); + asXmlPtr.Append( *value); + asXmlPtr.Append( KMEMBER_ETAG ); + + + CleanupStack::PopAndDestroy( value ); + CleanupStack::PopAndDestroy( key ); + } + + asXmlPtr.Append( KSTRUCT_ETAG ); + asXmlPtr.Append( KVALUE_ETAG ); + + return asXml; +} + + +TBool CXmlRpcValue::StructFromXmlnL( const TDesC8& aXml ) +{ + TInt offset = 0; + + CKeyValueTable* structure = CKeyValueTable::NewL(); + CleanupStack::PushL( structure ); + + while ( TXmlUtil::NextTagIs( KMEMBER_TAG, aXml, &offset ) ) { + if ( !TXmlUtil::NextTagIs( KNAME_TAG, aXml, &offset ) ) { + CleanupStack::PopAndDestroy( structure ); + return EFalse; + } + + TInt nameStart = offset; + + if ( !TXmlUtil::FindTag( KNAME_ETAG, aXml, &offset ) ) { + CleanupStack::PopAndDestroy( structure ); + return EFalse; + } + + TPtrC8 namePtr; + namePtr.Set( aXml.Mid( nameStart, offset - nameStart - KNAME_ETAG().Length() )); + + CXmlRpcValue* rpcValue = CXmlRpcValue::NewL(); + CleanupStack::PushL( rpcValue ); + + if ( !rpcValue->FromXmlnL( aXml, &offset ) ) { + CleanupStack::PopAndDestroy( rpcValue ); + CleanupStack::PopAndDestroy( structure ); + return EFalse; + } + + structure->AddElementL( namePtr, rpcValue ); + CleanupStack::Pop( rpcValue ); + + // Eat the tag + if ( !TXmlUtil::NextTagIs( KMEMBER_ETAG, aXml, &offset ) ) { + CleanupStack::PopAndDestroy( structure ); + return EFalse; + } + } + + ConstructL( structure ); + CleanupStack::Pop( structure ); + + return ETrue; +} + + -- 2.11.4.GIT