libsyncml-0.5.4/COPYING100644 1750 1750 63640 11211710410 14505 0ustar00bellmichbellmich GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! libsyncml-0.5.4/cmake/modules/FindLibExslt.cmake100644 1750 1750 5033 11211710410 21503 0ustar00bellmichbellmich# - Try to find libexslt # Find libexslt headers, libraries and the answer to all questions. # # LIBEXSLT_FOUND True if libexslt got found # LIBEXSLT_INCLUDE_DIRS Location of libexslt headers # LIBEXSLT_LIBRARIES List of libaries to use libexslt # # Copyright (c) 2008 Daniel Gollub # Copyright (c) 2008 Bjoern Ricks # # Redistribution and use is allowed according to the terms of the New # BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # INCLUDE( FindPkgConfig ) # Take care about libexslt.pc settings IF ( LibExslt_FIND_REQUIRED ) SET( _pkgconfig_REQUIRED "REQUIRED" ) ELSE ( LibExslt_FIND_REQUIRED ) SET( _pkgconfig_REQUIRED "" ) ENDIF ( LibExslt_FIND_REQUIRED ) IF ( LIBEXSLT_MIN_VERSION ) PKG_SEARCH_MODULE( LIBEXSLT ${_pkgconfig_REQUIRED} libexslt >= ${LIBEXSLT_MIN_VERSION} ) ELSE( LIBEXSLT_MIN_VERSION ) PKG_SEARCH_MODULE( LIBEXSLT ${_pkgconfig_REQUIRED} libexslt ) ENDIF ( LIBEXSLT_MIN_VERSION ) # Look for libexslt include dir and libraries without pkg-config... IF ( NOT LIBEXSLT_FOUND AND NOT PKG_CONFIG_FOUND ) FIND_PATH( _libexslt_include_DIR libexslt/exslt.h PATHS /opt/local/include/ /sw/include/ /usr/local/include/ /usr/include/ ) FIND_LIBRARY( _libexslt_link_DIR NAMES exslt libexslt PATHS /opt/local/lib /sw/lib /usr/lib /usr/local/lib /usr/lib64 /usr/local/lib64 /opt/lib64 ) IF ( _libexslt_include_DIR AND _libexslt_link_DIR ) SET ( _libexslt_FOUND TRUE ) ENDIF ( _libexslt_include_DIR AND _libexslt_link_DIR ) IF ( _libexslt_FOUND ) SET ( LIBEXSLT_INCLUDE_DIRS ${_libexslt_include_DIR} ) SET ( LIBEXSLT_LIBRARIES ${_libexslt_link_DIR} ) ENDIF ( _libexslt_FOUND ) # Report results IF ( LIBEXSLT_LIBRARIES AND LIBEXSLT_INCLUDE_DIRS ) SET( LIBEXSLT_FOUND 1 ) IF ( NOT LibExslt_FIND_QUIETLY ) MESSAGE( STATUS "Found libexslt: ${LIBEXSLT_LIBRARIES} ${LIBEXSLT_INCLUDE_DIRS}" ) ENDIF ( NOT LibExslt_FIND_QUIETLY ) ELSE ( LIBEXSLT_LIBRARIES AND LIBEXSLT_INCLUDE_DIRS ) IF ( LibExslt_FIND_REQUIRED ) MESSAGE( SEND_ERROR "Could NOT find libexslt" ) ELSE ( LibExslt_FIND_REQUIRED ) IF ( NOT LibExslt_FIND_QUIETLY ) MESSAGE( STATUS "Could NOT find libexslt" ) ENDIF ( NOT LibExslt_FIND_QUIETLY ) ENDIF ( LibExslt_FIND_REQUIRED ) ENDIF ( LIBEXSLT_LIBRARIES AND LIBEXSLT_INCLUDE_DIRS ) ENDIF ( NOT LIBEXSLT_FOUND AND NOT PKG_CONFIG_FOUND ) # Hide advanced variables from CMake GUIs MARK_AS_ADVANCED( LIBEXSLT_LIBRARIES LIBEXSLT_INCLUDE_DIRS ) libsyncml-0.5.4/cmake/modules/FindSqlite.cmake100644 1750 1750 3255 11211710410 21222 0ustar00bellmichbellmich# - Try to find the sqlite library # Once done this will define # # SQLITE_FOUND - system has sqlite # SQLITE_INCLUDE_DIRS - the sqlite include directory # SQLITE_LIBRARIES - Link these to use sqlite # # Copyright (c) 2008 Bjoern Ricks # # Redistribution and use is allowed according to the terms of the New # BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # INCLUDE( FindPkgConfig ) IF ( Sqlite_FIND_REQUIRED ) SET( _pkgconfig_REQUIRED "REQUIRED" ) ELSE( Sqlite_FIND_REQUIRED ) SET( _pkgconfig_REQUIRED "" ) ENDIF ( Sqlite_FIND_REQUIRED ) IF ( SQLITE_MIN_VERSION ) PKG_SEARCH_MODULE( SQLITE ${_pkgconfig_REQUIRED} sqlite>=${SQLITE_MIN_VERSION} ) ELSE ( SQLITE_MIN_VERSION ) PKG_SEARCH_MODULE( SQLITE ${_pkgconfig_REQUIRED} sqlite ) ENDIF ( SQLITE_MIN_VERSION ) IF( NOT SQLITE_FOUND AND NOT PKG_CONFIG_FOUND ) FIND_PATH( SQLITE_INCLUDE_DIRS sqlite.h ) FIND_LIBRARY( SQLITE_LIBRARIES sqlite ) # Report results IF ( SQLITE_LIBRARIES AND SQLITE_INCLUDE_DIRS ) SET( SQLITE_FOUND 1 ) IF ( NOT Sqlite_FIND_QUIETLY ) MESSAGE( STATUS "Found Sqlite: ${SQLITE_LIBRARIES}" ) ENDIF ( NOT Sqlite_FIND_QUIETLY ) ELSE ( SQLITE_LIBRARIES AND SQLITE_INCLUDE_DIRS ) IF ( Sqlite_FIND_REQUIRED ) MESSAGE( SEND_ERROR "Could NOT find Sqlite" ) ELSE ( Sqlite_FIND_REQUIRED ) IF ( NOT Sqlite_FIND_QUIETLY ) MESSAGE( STATUS "Could NOT find Sqlite" ) ENDIF ( NOT Sqlite_FIND_QUIETLY ) ENDIF ( Sqlite_FIND_REQUIRED ) ENDIF ( SQLITE_LIBRARIES AND SQLITE_INCLUDE_DIRS ) ENDIF( NOT SQLITE_FOUND AND NOT PKG_CONFIG_FOUND ) # Hide advanced variables from CMake GUIs MARK_AS_ADVANCED( SQLITE_LIBRARIES SQLITE_INCLUDE_DIRS ) libsyncml-0.5.4/cmake/modules/FindLibGSSAPIV2.cmake100644 1750 1750 2647 11211710410 21612 0ustar00bellmichbellmich# Try and find libgssapiv2. # As soon as libgssapiv2 has been found, the following variables will be defined: # # LIBGSSAPIV2_FOUND # GSSAPIV2_LIBRARY:FILEPATH # # Copyright (c) 2009 Juergen Leising # # Redistribution and use is allowed according to the terms of the New # BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # MESSAGE(STATUS "checking for libgssapiv2...") # No header files required for the ldap plugin. FIND_LIBRARY(GSSAPIV2_LIBRARY NAMES gssapiv2 PATHS /usr/lib /lib /usr/local/lib /usr/share/lib /opt/lib /opt/share/lib /var/lib /usr/lib/sasl2 /lib/sasl2 /usr/local/lib/sasl2 /usr/share/lib/sasl2 /opt/lib/sasl2 /opt/share/lib/sasl2 /var/lib/sasl2 DOC "Try and find libgssapiv2") IF (GSSAPIV2_LIBRARY) SET (LIBGSSAPIV2_FOUND 1) get_filename_component(GSSAPIV2_LIBRARY_DIRS ${GSSAPIV2_LIBRARY} PATH) MESSAGE(STATUS " Found ${GSSAPIV2_LIBRARY}") ELSE (GSSAPIV2_LIBRARY) IF ( LibGSSAPIV2_FIND_REQUIRED ) MESSAGE( FATAL_ERROR " Could NOT find libgssapiv2. The ldap plugin needs this library.") ELSE ( LibGSSAPIV2_FIND_REQUIRED ) MESSAGE( STATUS " Could NOT find libgssapiv2. The SASL authentication mechanism GSSAPI (and KERBEROS V5) won't work, therefore. Not a fatal error, however. The ldap plugin itself does NOT need it.") ENDIF ( LibGSSAPIV2_FIND_REQUIRED ) ENDIF (GSSAPIV2_LIBRARY) libsyncml-0.5.4/cmake/modules/FindBlueZ.cmake100644 1750 1750 3544 11211710410 21003 0ustar00bellmichbellmich# - Try to find BlueZ # Find BlueZ headers, libraries and the answer to all questions. # # BLUEZ_FOUND True if BlueZ libraries got found # BLUEZ_INCLUDE_DIRS Location of BlueZ headers # BLUEZ_LIBRARIES List of libaries to use BlueZ # # Copyright (c) 2007 Daniel Gollub # Copyright (c) 2007-2009 Bjoern Ricks # # Redistribution and use is allowed according to the terms of the New # BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # INCLUDE( FindPkgConfig ) # Take care about bluez.pc settings IF ( BlueZ_FIND_REQUIRED ) SET( _pkgconfig_REQUIRED "REQUIRED" ) ELSE( BlueZ_FIND_REQUIRED ) SET( _pkgconfig_REQUIRED "" ) ENDIF ( BlueZ_FIND_REQUIRED ) IF ( BLUEZ_MIN_VERSION ) PKG_SEARCH_MODULE( BLUEZ ${_pkgconfig_REQUIRED} bluez>=${BLUEZ_MIN_VERSION} ) ELSE ( BLUEZ_MIN_VERSION ) PKG_SEARCH_MODULE( BLUEZ ${_pkgconfig_REQUIRED} bluez ) ENDIF ( BLUEZ_MIN_VERSION ) # Look for BlueZ include dir and libraries IF( NOT BLUEZ_FOUND AND NOT PKG_CONFIG_FOUND ) FIND_PATH( BLUEZ_INCLUDE_DIRS bluetooth/bluetooth.h ) FIND_LIBRARY( BLUEZ_LIBRARIES bluetooth ) # Report results IF ( BLUEZ_LIBRARIES AND BLUEZ_INCLUDE_DIRS ) SET( BLUEZ_FOUND 1 ) IF ( NOT BlueZ_FIND_QUIETLY ) MESSAGE( STATUS "Found BlueZ: ${BLUEZ_LIBRARIES}" ) ENDIF ( NOT BlueZ_FIND_QUIETLY ) ELSE ( BLUEZ_LIBRARIES AND BLUEZ_INCLUDE_DIRS ) IF ( BlueZ_FIND_REQUIRED ) MESSAGE( SEND_ERROR "Could NOT find BLUEZ" ) ELSE ( BlueZ_FIND_REQUIRED ) IF ( NOT BlueZ_FIND_QUIETLY ) MESSAGE( STATUS "Could NOT find BLUEZ" ) ENDIF ( NOT BlueZ_FIND_QUIETLY ) ENDIF ( BlueZ_FIND_REQUIRED ) ENDIF ( BLUEZ_LIBRARIES AND BLUEZ_INCLUDE_DIRS ) ENDIF( NOT BLUEZ_FOUND AND NOT PKG_CONFIG_FOUND ) # Hide advanced variables from CMake GUIs MARK_AS_ADVANCED( BLUEZ_LIBRARIES BLUEZ_INCLUDE_DIRS ) libsyncml-0.5.4/cmake/modules/FindBONOBOACTIVATION2.cmake100644 1750 1750 10562 11211710410 22422 0ustar00bellmichbellmich# - Try to find bonobo-activation-2 # Find bonobo-activation-2 headers, libraries and the answer to all questions. # # BONOBOACTIVATION2_FOUND True if bonobo-activation-2 got found # BONOBOACTIVATION2_INCLUDEDIR Location of bonobo-activation-2 headers # BONOBOACTIVATION2_LIBRARIES List of libaries to use bonobo-activation-2 # BONOBOACTIVATION2_DEFINITIONS Definitions to compile bonobo-activation-2 # # Copyright (c) 2007 Juha Tuomala # Copyright (c) 2007 Daniel Gollub # Copyright (c) 2007 Alban Browaeys # # Redistribution and use is allowed according to the terms of the New # BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # INCLUDE( FindPkgConfig ) # Take care about bonobo-activation-2.0.pc settings IF ( BONOBOACTIVATION2_FIND_REQUIRED ) SET( _pkgconfig_REQUIRED "REQUIRED" ) ELSE ( BONOBOACTIVATION2_FIND_REQUIRED ) SET( _pkgconfig_REQUIRED "" ) ENDIF ( BONOBOACTIVATION2_FIND_REQUIRED ) IF ( BONOBOACTIVATION2_MIN_VERSION ) pkg_search_module( BONOBOACTIVATION2 ${_pkgconfig_REQUIRED} bonobo-activation-2.0>=${BONOBOACTIVATION2_MIN_VERSION} ) ELSE ( BONOBOACTIVATION2_MIN_VERSION ) pkg_search_module( BONOBOACTIVATION2 ${_pkgconfig_REQUIRED} bonobo-activation-2.0 ) ENDIF ( BONOBOACTIVATION2_MIN_VERSION ) # Look for bonoboactivation2 include dir and libraries w/o pkgconfig IF ( NOT BONOBOACTIVATION2_FOUND AND NOT PKG_CONFIG_FOUND ) FIND_PATH( _bonoboactivation2_include_DIR bonobo-activation/bonobo-activation.h PATH_SUFFIXES bonobo-activation-2.0 PATHS /opt/local/include/ /sw/include/ /usr/local/include/ /usr/include/ ) FIND_LIBRARY( _bonoboactivation2_link_DIR bonobo-activation PATHS /opt/local/lib /sw/lib /usr/lib /usr/local/lib /usr/lib64 /usr/local/lib64 /opt/lib64 ) IF ( _bonoboactivation2_include_DIR AND _bonoboactivation2_link_DIR ) SET ( _bonoboactivation2_FOUND TRUE ) ENDIF ( _bonoboactivation2_include_DIR AND _bonoboactivation2_link_DIR ) IF ( _bonoboactivation2_FOUND ) SET ( BONOBOACTIVATION2_INCLUDE_DIRS ${_bonoboactivation2_include_DIR} ) SET ( BONOBOACTIVATION2_LIBRARIES ${_bonoboactivation2_link_DIR} ) ENDIF ( _bonoboactivation2_FOUND ) # Handle dependencies IF ( NOT ORBIT2_FOUND ) FIND_PACKAGE( ORBit2 REQUIRED) IF ( ORBIT2_FOUND ) SET ( BONOBOACTIVATION2_INCLUDE_DIRS ${BONOBOACTIVATION2_INCLUDE_DIRS} ${ORBIT2_INCLUDE_DIRS} ) SET ( BONOBOACTIVATION2_LIBRARIES ${BONOBOACTIVATION2_LIBRARIES} ${ORBIT2_LIBRARIES} ) ENDIF ( ORBIT2_FOUND ) ENDIF ( NOT ORBIT2_FOUND ) IF ( NOT GLIB2_FOUND ) FIND_PACKAGE( GLIB2 REQUIRED) IF ( GMODULE2_FOUND ) SET ( BONOBOACTIVATION2_INCLUDE_DIRS ${BONOBOACTIVATION2_INCLUDE_DIRS} ${GMODULE2_INCLUDE_DIR} ) SET ( BONOBOACTIVATION2_LIBRARIES ${BONOBOACTIVATION2_LIBRARIES} ${GMODULE2_LIBRARY} ) ENDIF ( GMODULE2_FOUND ) IF ( GLIB2_FOUND ) SET ( BONOBOACTIVATION2_INCLUDE_DIRS ${BONOBOACTIVATION2_INCLUDE_DIRS} ${GLIB2_INCLUDE_DIR} ${GLIBCONFIG_INCLUDE_DIR} ) SET ( BONOBOACTIVATION2_LIBRARIES ${BONOBOACTIVATION2_LIBRARIES} ${GLIB2_LIBRARY} ) ENDIF ( GLIB2_FOUND ) ENDIF ( NOT GLIB2_FOUND ) # Report results IF ( BONOBOACTIVATION2_LIBRARIES AND BONOBOACTIVATION2_INCLUDE_DIRS AND _bonoboactivation2_FOUND ) SET( BONOBOACTIVATION2_FOUND 1 ) IF ( NOT BONOBOACTIVATION2_FIND_QUIETLY ) MESSAGE( STATUS "Found bonobo-activation2: ${BONOBOACTIVATION2_LIBRARIES} ${BONOBOACTIVATION2_INCLUDE_DIRS}" ) ENDIF ( NOT BONOBOACTIVATION2_FIND_QUIETLY ) ELSE ( BONOBOACTIVATION2_LIBRARIES AND BONOBOACTIVATION2_INCLUDE_DIRS AND _bonoboactivation2_FOUND ) IF ( BONOBOACTIVATION2_FIND_REQUIRED ) MESSAGE( SEND_ERROR "Could NOT find bonobo-activation2" ) ELSE ( BONOBOACTIVATION2_FIND_REQUIRED ) IF ( NOT BONOBOACTIVATION2_FIND_QUIETLY ) MESSAGE( STATUS "Could NOT find bonobo-activation2" ) ENDIF ( NOT BONOBOACTIVATION2_FIND_QUIETLY ) ENDIF ( BONOBOACTIVATION2_FIND_REQUIRED ) ENDIF ( BONOBOACTIVATION2_LIBRARIES AND BONOBOACTIVATION2_INCLUDE_DIRS AND _bonoboactivation2_FOUND ) ENDIF ( NOT BONOBOACTIVATION2_FOUND AND NOT PKG_CONFIG_FOUND ) # Hide advanced variables from CMake GUIs MARK_AS_ADVANCED( BONOBOACTIVATION2_LIBRARIES BONOBOACTIVATION2_INCLUDE_DIRS ) libsyncml-0.5.4/cmake/modules/FindCheck.cmake100644 1750 1750 3325 11211710410 20774 0ustar00bellmichbellmich# - Try to find the CHECK libraries # Once done this will define # # CHECK_FOUND - system has check # CHECK_INCLUDE_DIRS - the check include directory # CHECK_LIBRARIES - check library # # Copyright (c) 2007 Daniel Gollub # Copyright (c) 2007-2009 Bjoern Ricks # # Redistribution and use is allowed according to the terms of the New # BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. INCLUDE( FindPkgConfig ) IF ( Check_FIND_REQUIRED ) SET( _pkgconfig_REQUIRED "REQUIRED" ) ELSE( Check_FIND_REQUIRED ) SET( _pkgconfig_REQUIRED "" ) ENDIF ( Check_FIND_REQUIRED ) IF ( CHECK_MIN_VERSION ) PKG_SEARCH_MODULE( CHECK ${_pkgconfig_REQUIRED} check>=${CHECK_MIN_VERSION} ) ELSE ( CHECK_MIN_VERSION ) PKG_SEARCH_MODULE( CHECK ${_pkgconfig_REQUIRED} check ) ENDIF ( CHECK_MIN_VERSION ) # Look for CHECK include dir and libraries IF( NOT CHECK_FOUND AND NOT PKG_CONFIG_FOUND ) FIND_PATH( CHECK_INCLUDE_DIRS check.h ) FIND_LIBRARY( CHECK_LIBRARIES NAMES check ) IF ( CHECK_INCLUDE_DIRS AND CHECK_LIBRARIES ) SET( CHECK_FOUND 1 ) IF ( NOT Check_FIND_QUIETLY ) MESSAGE ( STATUS "Found CHECK: ${CHECK_LIBRARIES}" ) ENDIF ( NOT Check_FIND_QUIETLY ) ELSE ( CHECK_INCLUDE_DIRS AND CHECK_LIBRARIES ) IF ( Check_FIND_REQUIRED ) MESSAGE( FATAL_ERROR "Could NOT find CHECK" ) ELSE ( Check_FIND_REQUIRED ) IF ( NOT Check_FIND_QUIETLY ) MESSAGE( STATUS "Could NOT find CHECK" ) ENDIF ( NOT Check_FIND_QUIETLY ) ENDIF ( Check_FIND_REQUIRED ) ENDIF ( CHECK_INCLUDE_DIRS AND CHECK_LIBRARIES ) ENDIF( NOT CHECK_FOUND AND NOT PKG_CONFIG_FOUND ) # Hide advanced variables from CMake GUIs MARK_AS_ADVANCED( CHECK_INCLUDE_DIRS CHECK_LIBRARIES ) libsyncml-0.5.4/cmake/modules/FindEDataCal1.2.cmake100644 1750 1750 12167 11211710410 21622 0ustar00bellmichbellmich# - Try to find libedatacal1.2 components # Find libedatacal 1.2 headers, libraries and the answer to all questions. # # LIBEDATACAL1.2_FOUND True if libedatacal1.2 got found # LIBEDATACAL1.2_INCLUDE_DIRS Location of libedatacal1.2 headers # LIBEDATACAL1.2_LIBRARIES List of libaries to use libedatacal1.2 # LIBEDATACAL1.2_DEFINITIONS Definitions to compile libedatacal1.2 # # Copyright (c) 2007 Juha Tuomala # Copyright (c) 2007 Daniel Gollub # Copyright (c) 2007 Alban Browaeys # # Redistribution and use is allowed according to the terms of the New # BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # INCLUDE( FindPkgConfig ) # Take care about libedata-cal-1.2.pc settings IF ( EDataCal1.2_FIND_REQUIRED ) SET( _pkgconfig_REQUIRED "REQUIRED" ) ELSE ( EDataCal1.2_FIND_REQUIRED ) SET( _pkgconfig_REQUIRED "" ) ENDIF ( EDataCal1.2_FIND_REQUIRED ) pkg_search_module( LIBEDATACAL1.2 ${_pkgconfig_REQUIRED} libedata-cal-1.2 ) # Look for libedatacal1.2 include dir and libraries w/o pkg-config. IF ( NOT LIBEDATACAL1.2_FOUND AND NOT PKG_CONFIG_FOUND ) FIND_PATH( _libedatacal1.2_include_DIR libedata-cal/e-data-cal.h PATH_SUFFIXES evolution-data-server-1.12 evolution-data-server-1.10 evolution-data-server-1.8 evolution-data-server-1.6 evolution-data-server-1.4 evolution-data-server-1.2 PATHS /opt/local/include/ /sw/include/ /usr/local/include/ /usr/include/ ) FIND_LIBRARY( _libedatacal1.2_link_DIR edata-cal-1.2 PATHS /opt/local/lib /sw/lib /usr/lib /usr/local/lib /usr/lib64 /usr/local/lib64 /opt/lib64 ) IF ( _libedatacal1.2_include_DIR AND _libedatacal1.2_link_DIR ) SET ( _libedatacal1.2_FOUND TRUE ) ENDIF ( _libedatacal1.2_include_DIR AND _libedatacal1.2_link_DIR ) IF ( _libedatacal1.2_FOUND ) SET ( LIBEDATACAL1.2_INCLUDE_DIRS ${_libedatacal1.2_include_DIR} ) SET ( LIBEDATACAL1.2_LIBRARIES ${_libedatacal1.2_link_DIR} ) ENDIF ( _libedatacal1.2_FOUND ) # Handle dependencies IF ( NOT LIBECAL1.2_FOUND ) FIND_PACKAGE ( ECal1.2 REQUIRED ) IF ( LIBECAL1.2_FOUND ) SET ( LIBEDATACAL1.2_INCLUDE_DIRS ${LIBEDATACAL1.2_INCLUDE_DIRS} ${LIBECAL1.2_INCLUDE_DIRS} ) SET ( LIBEDATACAL1.2_LIBRARIES ${LIBEDATACAL1.2_LIBRARIES} ${LIBECAL1.2_LIBRARIES} ) ENDIF ( LIBECAL1.2_FOUND ) ENDIF ( NOT LIBECAL1.2_FOUND ) IF ( NOT GNOMEVFS2_FOUND ) FIND_PACKAGE ( GnomeVfs2 REQUIRED ) IF ( GNOMEVFS2_FOUND ) SET ( LIBEDATACAL1.2_INCLUDE_DIRS ${LIBEDATACAL1.2_INCLUDE_DIRS} ${GNOMEVFS2_INCLUDE_DIRS} ) SET ( LIBEDATACAL1.2_LIBRARIES ${LIBEDATACAL1.2_LIBRARIES} ${GNOMEVFS2_LIBRARIES} ) ENDIF ( GNOMEVFS2_FOUND ) ENDIF ( NOT GNOMEVFS2_FOUND ) IF ( NOT LIBEDATASERVER1.2_FOUND ) FIND_PACKAGE ( EDataServer1.2 REQUIRED ) IF ( LIBEDATASERVER1.2_FOUND ) SET ( LIBEDATACAL1.2_INCLUDE_DIRS ${LIBEDATACAL1.2_INCLUDE_DIRS} ${LIBEDATASERVER1.2_INCLUDE_DIRS} ) SET ( LIBEDATACAL1.2_LIBRARIES ${LIBEDATACAL1.2_LIBRARIES} ${LIBEDATASERVER1.2_LIBRARIES} ) ENDIF ( LIBEDATASERVER1.2_FOUND ) ENDIF ( NOT LIBEDATASERVER1.2_FOUND ) IF ( NOT LIBGNOME2_FOUND ) FIND_PACKAGE ( LibGnome2 REQUIRED ) IF ( LIBGNOME2_FOUND ) SET ( LIBEDATACAL1.2_INCLUDE_DIRS ${LIBEDATACAL1.2_INCLUDE_DIRS} ${LIBGNOME2_INCLUDE_DIRS} ) SET ( LIBEDATACAL1.2_LIBRARIES ${LIBEDATACAL1.2_LIBRARIES} ${LIBGNOME2_LIBRARIES} ) ENDIF ( LIBGNOME2_FOUND ) ENDIF ( NOT LIBGNOME2_FOUND ) IF ( NOT BONOBO2_FOUND ) SET ( BONOBO2_MIN_VERSION "2.4.2" ) FIND_PACKAGE ( BONOBO2 REQUIRED ) IF ( BONOBO2_FOUND ) SET ( LIBEDATACAL1.2_INCLUDE_DIRS ${LIBEDATACAL1.2_INCLUDE_DIRS} ${BONOBO2_INCLUDE_DIRS} ) SET ( LIBEDATACAL1.2_LIBRARIES ${LIBEDATACAL1.2_LIBRARIES} ${BONOBO2_LIBRARIES} ) ENDIF ( BONOBO2_FOUND ) ENDIF ( NOT BONOBO2_FOUND ) # Report results IF ( LIBEDATACAL1.2_LIBRARIES AND LIBEDATACAL1.2_INCLUDE_DIRS AND _libedatacal1.2_FOUND ) SET( LIBEDATACAL1.2_FOUND 1 ) IF ( NOT EDataCal1.2_FIND_QUIETLY ) MESSAGE( STATUS "Found libedatacal-1.2: ${LIBEDATACAL1.2_LIBRARIES}" ) ENDIF ( NOT EDataCal1.2_FIND_QUIETLY ) ELSE ( LIBEDATACAL1.2_LIBRARIES AND LIBEDATACAL1.2_INCLUDE_DIRS AND _libedatacal1.2_FOUND ) IF ( EDataCal1.2_FIND_REQUIRED ) MESSAGE( SEND_ERROR "Could NOT find libedatacal-1.2" ) ELSE ( EDataCal1.2_FIND_REQUIRED ) IF ( NOT EDataCal1.2_FIND_QUIETLY ) MESSAGE( STATUS "Could NOT find libedatacal-1.2" ) ENDIF ( NOT EDataCal1.2_FIND_QUIETLY ) ENDIF ( EDataCal1.2_FIND_REQUIRED ) ENDIF ( LIBEDATACAL1.2_LIBRARIES AND LIBEDATACAL1.2_INCLUDE_DIRS AND _libedatacal1.2_FOUND ) ENDIF ( NOT LIBEDATACAL1.2_FOUND AND NOT PKG_CONFIG_FOUND ) # Hide advanced variables from CMake GUIs MARK_AS_ADVANCED( LIBEDATACAL1.2_LIBRARIES LIBEDATACAL1.2_INCLUDE_DIRS ) libsyncml-0.5.4/cmake/modules/MacroEnsureOutOfSourceBuild.cmake100644 1750 1750 1074 11211710410 24516 0ustar00bellmichbellmich# - MACRO_ENSURE_OUT_OF_SOURCE_BUILD() # MACRO_ENSURE_OUT_OF_SOURCE_BUILD() # Copyright (c) 2006, Alexander Neundorf, # # Redistribution and use is allowed according to the terms of the BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. MACRO (MACRO_ENSURE_OUT_OF_SOURCE_BUILD _errorMessage) STRING(COMPARE EQUAL "${CMAKE_SOURCE_DIR}" "${CMAKE_BINARY_DIR}" insource) IF(insource) MESSAGE(FATAL_ERROR "${_errorMessage}") ENDIF(insource) ENDMACRO (MACRO_ENSURE_OUT_OF_SOURCE_BUILD) libsyncml-0.5.4/cmake/modules/FindLibGnome2.cmake100644 1750 1750 7362 11211710410 21542 0ustar00bellmichbellmich# - Try to find libgnome2 # Find libgnome2 headers, libraries and the answer to all questions. # # LIBGNOME2_FOUND True if libgnome2 got found # LIBGNOME2_INCLUDEDIR Location of libgnome2 headers # LIBGNOME2_LIBRARIES List of libaries to use libgnome2 # LIBGNOME2_DEFINITIONS Definitions to compile libgnome2 # # Copyright (c) 2007 Juha Tuomala # Copyright (c) 2007 Daniel Gollub # Copyright (c) 2007 Alban Browaeys # # Redistribution and use is allowed according to the terms of the New # BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # INCLUDE( FindPkgConfig ) # Take care about libgnome-2.0.pc settings IF ( LibGnome2_FIND_REQUIRED ) SET( _pkgconfig_REQUIRED "REQUIRED" ) ELSE ( LibGnome2_FIND_REQUIRED ) SET( _pkgconfig_REQUIRED "" ) ENDIF ( LibGnome2_FIND_REQUIRED ) IF ( LIBGNOME2_MIN_VERSION ) pkg_search_module( LIBGNOME2 ${_pkgconfig_REQUIRED} libgnome-2.0>=${LIBGNOME2_MIN_VERSION} ) ELSE ( LIBGNOME2_MIN_VERSION ) pkg_search_module( LIBGNOME2 ${_pkgconfig_REQUIRED} libgnome-2.0 ) ENDIF ( LIBGNOME2_MIN_VERSION ) # Look for libgnome2 include dir and libraries w/o pkgconfig IF ( NOT LIBGNOME2_FOUND AND NOT PKG_CONFIG_FOUND ) FIND_PATH( _libgnome2_include_DIR libgnome/libgnome.h PATH_SUFFIXES libgnome-2.0 PATHS /opt/local/include/ /sw/include/ /usr/local/include/ /usr/include/ ) FIND_LIBRARY( _libgnome2_link_DIR gnome-2 PATHS /opt/local/lib /sw/lib /usr/lib /usr/local/lib /usr/lib64 /usr/local/lib64 /opt/lib64 ) IF ( _libgnome2_include_DIR AND _libgnome2_link_DIR ) SET ( _libgnome2_FOUND TRUE ) ENDIF ( _libgnome2_include_DIR AND _libgnome2_link_DIR ) IF ( _libgnome2_FOUND ) SET ( LIBGNOME2_INCLUDE_DIRS ${_libgnome2_include_DIR} ) SET ( LIBGNOME2_LIBRARIES ${_libgnome2_link_DIR} ) ENDIF ( _libgnome2_FOUND ) # Handle dependencies IF ( NOT BONOBO2_FOUND ) FIND_PACKAGE( BONOBO2 REQUIRED) IF ( BONOBO2_FOUND ) SET ( LIBGNOME2_INCLUDE_DIRS ${LIBGNOME2_INCLUDE_DIRS} ${BONOBO2_INCLUDE_DIRS} ) SET ( LIBGNOME2_LIBRARIES ${LIBGNOME2_LIBRARIES} ${BONOBO2_LIBRARIES} ) ENDIF ( BONOBO2_FOUND ) ENDIF ( NOT BONOBO2_FOUND ) IF ( NOT GLIB2_FOUND ) FIND_PACKAGE( GLIB2 REQUIRED) IF ( GMODULE2_FOUND ) SET ( LIBGNOME2_INCLUDE_DIRS ${LIBGNOME2_INCLUDE_DIRS} ${GMODULE2_INCLUDE_DIR} ) SET ( LIBGNOME2_LIBRARIES ${LIBGNOME2_LIBRARIES} ${GMODULE2_LIBRARY} ) ENDIF ( GMODULE2_FOUND ) IF ( GLIB2_FOUND ) SET ( LIBGNOME2_INCLUDE_DIRS ${LIBGNOME2_INCLUDE_DIRS} ${GLIB2_INCLUDE_DIR} ${GLIBCONFIG_INCLUDE_DIR} ) SET ( LIBGNOME2_LIBRARIES ${LIBGNOME2_LIBRARIES} ${GLIB2_LIBRARY} ) ENDIF ( GLIB2_FOUND ) ENDIF ( NOT GLIB2_FOUND ) # Report results IF ( LIBGNOME2_LIBRARIES AND LIBGNOME2_INCLUDE_DIRS AND _libgnome2_FOUND ) SET( LIBGNOME2_FOUND 1 ) IF ( NOT LibGnome2_FIND_QUIETLY ) MESSAGE( STATUS "Found libgnome2: ${LIBGNOME2_LIBRARIES} ${LIBGNOME2_INCLUDE_DIRS}" ) ENDIF ( NOT LibGnome2_FIND_QUIETLY ) ELSE ( LIBGNOME2_LIBRARIES AND LIBGNOME2_INCLUDE_DIRS AND _libgnome2_FOUND ) IF ( LibGnome2_FIND_REQUIRED ) MESSAGE( SEND_ERROR "Could NOT find libgnome2" ) ELSE ( LibGnome2_FIND_REQUIRED ) IF ( NOT LibGnome2_FIND_QUIETLY ) MESSAGE( STATUS "Could NOT find libgnome2" ) ENDIF ( NOT LibGnome2_FIND_QUIETLY ) ENDIF ( LibGnome2_FIND_REQUIRED ) ENDIF ( LIBGNOME2_LIBRARIES AND LIBGNOME2_INCLUDE_DIRS AND _libgnome2_FOUND ) ENDIF ( NOT LIBGNOME2_FOUND AND NOT PKG_CONFIG_FOUND ) # Hide advanced variables from CMake GUIs MARK_AS_ADVANCED( LIBGNOME2_LIBRARIES LIBGNOME2_INCLUDE_DIRS ) libsyncml-0.5.4/cmake/modules/FindLibXslt.cmake100644 1750 1750 3526 11211710410 21343 0ustar00bellmichbellmich# - Try to find LibXslt # Once done this will define # # LIBXSLT_FOUND - system has LibXslt # LIBXSLT_INCLUDE_DIRS - the LibXslt include directory # LIBXSLT_LIBRARIES - Link these to LibXslt # LIBXSLT_DEFINITIONS - Compiler switches required for using LibXslt # # Copyright (c) 2006, Alexander Neundorf, # Copyright (c) 2008 Bjoern Ricks # # Redistribution and use is allowed according to the terms of the New # BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # INCLUDE( FindPkgConfig ) IF ( LibXslt_FIND_REQUIRED ) SET( _pkgconfig_REQUIRED "REQUIRED" ) ELSE( LibXslt_FIND_REQUIRED ) SET( _pkgconfig_REQUIRED "" ) ENDIF ( LibXslt_FIND_REQUIRED ) IF ( LIBXSLT_MIN_VERSION ) PKG_SEARCH_MODULE( LIBXSLT ${_pkgconfig_REQUIRED} libxslt>=${LIBXSLT_MIN_VERSION} ) ELSE ( LIBXSLT_MIN_VERSION ) PKG_SEARCH_MODULE( LIBXSLT ${_pkgconfig_REQUIRED} libxslt ) ENDIF ( LIBXSLT_MIN_VERSION ) IF( NOT LIBXSLT_FOUND AND NOT PKG_CONFIG_FOUND ) FIND_PATH( LIBXSLT_INCLUDE_DIRS libxslt/xslt.h ) FIND_LIBRARY( LIBXSLT_LIBRARIES xslt libxslt ) # Report results IF ( LIBXSLT_LIBRARIES AND LIBXSLT_INCLUDE_DIRS ) SET( LIBXSLT_FOUND 1 ) IF ( NOT LibXslt_FIND_QUIETLY ) MESSAGE( STATUS "Found LibXslt: ${LIBXSLT_LIBRARIES}" ) ENDIF ( NOT LibXslt_FIND_QUIETLY ) ELSE ( LIBXSLT_LIBRARIES AND LIBXSLT_INCLUDE_DIRS ) IF ( LibXslt_FIND_REQUIRED ) MESSAGE( SEND_ERROR "Could NOT find LibXslt" ) ELSE ( LibXslt_FIND_REQUIRED ) IF ( NOT LibXslt_FIND_QUIETLY ) MESSAGE( STATUS "Could NOT find LibXslt" ) ENDIF ( NOT LibXslt_FIND_QUIETLY ) ENDIF ( LibXslt_FIND_REQUIRED ) ENDIF ( LIBXSLT_LIBRARIES AND LIBXSLT_INCLUDE_DIRS ) ENDIF( NOT LIBXSLT_FOUND AND NOT PKG_CONFIG_FOUND ) # Hide advanced variables from CMake GUIs MARK_AS_ADVANCED( LIBXSLT_LIBRARIES LIBXSLT_INCLUDE_DIRS ) libsyncml-0.5.4/cmake/modules/FindORBit2.cmake100644 1750 1750 6133 11211710410 21020 0ustar00bellmichbellmich# - Try to find orbit # Find orbit headers, libraries and the answer to all questions. # # ORBIT2_FOUND True if orbit got found # ORBIT2_INCLUDEDIR Location of orbit headers # ORBIT2_LIBRARIES List of libaries to use orbit # ORBIT2_DEFINITIONS Definitions to compile orbit # # Copyright (c) 2007 Juha Tuomala # Copyright (c) 2007 Daniel Gollub # Copyright (c) 2007 Alban Browaeys # # Redistribution and use is allowed according to the terms of the New # BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # INCLUDE( FindPkgConfig ) # Take care about ORBit-2.0.pc settings IF ( ORBit2_FIND_REQUIRED ) SET( _pkgconfig_REQUIRED "REQUIRED" ) ELSE ( ORBit2_FIND_REQUIRED ) SET( _pkgconfig_REQUIRED "" ) ENDIF ( ORBit2_FIND_REQUIRED ) IF ( ORBIT2_MIN_VERSION ) pkg_search_module( ORBIT2 ${_pkgconfig_REQUIRED} ORBit-2.0>=${ORBIT2_MIN_VERSION} ) ELSE ( ORBIT2_MIN_VERSION ) pkg_search_module( ORBIT2 ${_pkgconfig_REQUIRED} ORBit-2.0 ) ENDIF ( ORBIT2_MIN_VERSION ) # Look for orbit include dir and libraries w/o pkgconfig IF ( NOT ORBIT2_FOUND AND NOT PKG_CONFIG_FOUND ) FIND_PATH( _orbit2_include_DIR orbit/orbit.h PATH_SUFFIXES orbit-2.0 ) FIND_LIBRARY( _orbit2_link_DIR ORBit-2) IF ( _orbit2_include_DIR AND _orbit2_link_DIR ) SET ( _orbit2_FOUND TRUE ) ENDIF ( _orbit2_include_DIR AND _orbit2_link_DIR ) IF ( _orbit2_FOUND ) SET ( ORBIT2_INCLUDE_DIRS ${_orbit2_include_DIR} ) SET ( ORBIT2_LIBRARIES ${_orbit2_link_DIR} ) ENDIF ( _orbit2_FOUND ) IF ( NOT GLIB2_FOUND ) FIND_PACKAGE( GLIB2 REQUIRED) IF ( GTHREAD2_FOUND ) SET ( ORBIT2_INCLUDE_DIRS ${ORBIT2_INCLUDE_DIRS} ${GTHREAD2_INCLUDE_DIR} ) SET ( ORBIT2_LIBRARIES ${ORBIT2_LIBRARIES} ${GTHREAD2_LIBRARY} ) ENDIF ( GTHREAD2_FOUND ) IF ( GOBJECT2_FOUND ) SET ( ORBIT2_INCLUDE_DIRS ${ORBIT2_INCLUDE_DIRS} ${GOBJECT2_INCLUDE_DIR} ) SET ( ORBIT2_LIBRARIES ${ORBIT2_LIBRARIES} ${GOBJECT2_LIBRARY} ) ENDIF ( GOBJECT2_FOUND ) IF ( GLIB2_FOUND ) SET ( ORBIT2_INCLUDE_DIRS ${ORBIT2_INCLUDE_DIRS} ${GLIB2_INCLUDE_DIR} ${GLIBCONFIG_INCLUDE_DIR} ) SET ( ORBIT2_LIBRARIES ${ORBIT2_LIBRARIES} ${GLIB2_LIBRARY} ) ENDIF ( GLIB2_FOUND ) ENDIF ( NOT GLIB2_FOUND ) # Report results IF ( ORBIT2_LIBRARIES AND ORBIT2_INCLUDE_DIRS AND _orbit2_FOUND) SET( ORBIT2_FOUND 1 ) IF ( NOT ORBit2_FIND_QUIETLY ) MESSAGE( STATUS "Found ORBit2: ${ORBIT2_LIBRARIES} ${ORBIT2_INCLUDE_DIRS}" ) ENDIF ( NOT ORBit2_FIND_QUIETLY ) ELSE ( ORBIT2_LIBRARIES AND ORBIT2_INCLUDE_DIRS AND _orbit2_FOUND ) IF ( ORBit2_FIND_REQUIRED ) MESSAGE( SEND_ERROR "Could NOT find ORBit2" ) ELSE ( ORBit2_FIND_REQUIRED ) IF ( NOT ORBit2_FIND_QUIETLY ) MESSAGE( STATUS "Could NOT find ORBit2" ) ENDIF ( NOT ORBit2_FIND_QUIETLY ) ENDIF ( ORBit2_FIND_REQUIRED ) ENDIF ( ORBIT2_LIBRARIES AND ORBIT2_INCLUDE_DIRS AND _orbit2_FOUND ) MARK_AS_ADVANCED( _orbit2_include_DIR _orbit2_link_DIR ) ENDIF ( NOT ORBIT2_FOUND AND NOT PKG_CONFIG_FOUND ) # Hide advanced variables from CMake GUIs MARK_AS_ADVANCED( ORBIT2_LIBRARIES ORBIT2_INCLUDE_DIRS ) libsyncml-0.5.4/cmake/modules/FindEvolutionDataServer1.2.cmake100644 1750 1750 6426 11211710410 24152 0ustar00bellmichbellmich# - Try to find evolutiondataserver1.2 components # Find evolutiondataserver 1.2 headers, libraries and the answer to all questions. # # EVOLUTIONDATASERVER1.2_FOUND True if evolutiondataserver1.2 got found # EVOLUTIONDATASERVER1.2_INCLUDE_DIRS Location of evolutiondataserver1.2 headers # EVOLUTIONDATASERVER1.2_LIBRARIES List of libaries to use evolutiondataserver1.2 # EVOLUTIONDATASERVER1.2_DEFINITIONS Definitions to compile evolutiondataserver1.2 # # Copyright (c) 2007 Juha Tuomala # Copyright (c) 2007 Daniel Gollub # Copyright (c) 2007 Alban Browaeys # # Redistribution and use is allowed according to the terms of the New # BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # INCLUDE( FindPkgConfig ) # Take care about evolution-data-server-1.2.pc settings IF ( EvolutionDataServer1.2_FIND_REQUIRED ) SET( _pkgconfig_REQUIRED "REQUIRED" ) ELSE ( EvolutionDataServer1.2_FIND_REQUIRED ) SET( _pkgconfig_REQUIRED "" ) ENDIF ( EvolutionDataServer1.2_FIND_REQUIRED ) pkg_search_module( EVOLUTIONDATASERVER1.2 ${_pkgconfig_REQUIRED} evolution-data-server-1.2 ) # Look for evolutiondataserver1.2 include dir and libraries w/o pkg-config. IF ( NOT EVOLUTIONDATASERVER1.2_FOUND AND NOT PKG_CONFIG_FOUND ) # Handle dependencies IF ( NOT LIBGNOME2_FOUND ) FIND_PACKAGE ( LibGnome2 REQUIRED ) IF ( LIBGNOME2_FOUND ) SET ( EVOLUTIONDATASERVER1.2_INCLUDE_DIRS ${EVOLUTIONDATASERVER1.2_INCLUDE_DIRS} ${LIBGNOME2_INCLUDE_DIRS} ) SET ( EVOLUTIONDATASERVER1.2_LIBRARIES ${EVOLUTIONDATASERVER1.2_LIBRARIES} ${LIBGNOME2_LIBRARIES} ) ENDIF ( LIBGNOME2_FOUND ) ENDIF ( NOT LIBGNOME2_FOUND ) IF ( NOT BONOBO2_FOUND ) SET ( BONOBO2_MIN_VERSION "2.4.2" ) FIND_PACKAGE ( BONOBO2 REQUIRED ) IF ( BONOBO2_FOUND ) SET ( EVOLUTIONDATASERVER1.2_INCLUDE_DIRS ${EVOLUTIONDATASERVER1.2_INCLUDE_DIRS} ${BONOBO2_INCLUDE_DIRS} ) SET ( EVOLUTIONDATASERVER1.2_LIBRARIES ${EVOLUTIONDATASERVER1.2_LIBRARIES} ${BONOBO2_LIBRARIES} ) ENDIF ( BONOBO2_FOUND ) ENDIF ( NOT BONOBO2_FOUND ) # Report results IF ( EVOLUTIONDATASERVER1.2_LIBRARIES AND EVOLUTIONDATASERVER1.2_INCLUDE_DIRS ) SET( EVOLUTIONDATASERVER1.2_FOUND 1 ) IF ( NOT EvolutionDataServer1.2_FIND_QUIETLY ) MESSAGE( STATUS "Found evolutiondataserver-1.2: ${EVOLUTIONDATASERVER1.2_LIBRARIES}" ) ENDIF ( NOT EvolutionDataServer1.2_FIND_QUIETLY ) ELSE ( EVOLUTIONDATASERVER1.2_LIBRARIES AND EVOLUTIONDATASERVER1.2_INCLUDE_DIRS ) IF ( EvolutionDataServer1.2_FIND_REQUIRED ) MESSAGE( SEND_ERROR "Could NOT find evolutiondataserver-1.2" ) ELSE ( EvolutionDataServer1.2_FIND_REQUIRED ) IF ( NOT EvolutionDataServer1.2_FIND_QUIETLY ) MESSAGE( STATUS "Could NOT find evolutiondataserver-1.2" ) ENDIF ( NOT EvolutionDataServer1.2_FIND_QUIETLY ) ENDIF ( EvolutionDataServer1.2_FIND_REQUIRED ) ENDIF ( EVOLUTIONDATASERVER1.2_LIBRARIES AND EVOLUTIONDATASERVER1.2_INCLUDE_DIRS ) ENDIF ( NOT EVOLUTIONDATASERVER1.2_FOUND AND NOT PKG_CONFIG_FOUND ) # Hide advanced variables from CMake GUIs MARK_AS_ADVANCED( EVOLUTIONDATASERVER1.2_LIBRARIES EVOLUTIONDATASERVER1.2_INCLUDE_DIRS ) libsyncml-0.5.4/cmake/modules/FindEDataCal1.0.cmake100644 1750 1750 12167 11211710410 21620 0ustar00bellmichbellmich# - Try to find libedatacal1.0 components # Find libedatacal 1.0 headers, libraries and the answer to all questions. # # LIBEDATACAL1.0_FOUND True if libedatacal1.0 got found # LIBEDATACAL1.0_INCLUDE_DIRS Location of libedatacal1.0 headers # LIBEDATACAL1.0_LIBRARIES List of libaries to use libedatacal1.0 # LIBEDATACAL1.0_DEFINITIONS Definitions to compile libedatacal1.0 # # Copyright (c) 2007 Juha Tuomala # Copyright (c) 2007 Daniel Gollub # Copyright (c) 2007 Alban Browaeys # # Redistribution and use is allowed according to the terms of the New # BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # INCLUDE( FindPkgConfig ) # Take care about libedata-cal-1.0.pc settings IF ( EDataCal1.0_FIND_REQUIRED ) SET( _pkgconfig_REQUIRED "REQUIRED" ) ELSE ( EDataCal1.0_FIND_REQUIRED ) SET( _pkgconfig_REQUIRED "" ) ENDIF ( EDataCal1.0_FIND_REQUIRED ) pkg_search_module( LIBEDATACAL1.0 ${_pkgconfig_REQUIRED} libedata-cal-1.0 ) # Look for libedatacal1.0 include dir and libraries w/o pkg-config. IF ( NOT LIBEDATACAL1.0_FOUND AND NOT PKG_CONFIG_FOUND ) FIND_PATH( _libedatacal1.0_include_DIR libedata-cal/e-data-cal.h PATH_SUFFIXES evolution-data-server-1.12 evolution-data-server-1.10 evolution-data-server-1.8 evolution-data-server-1.6 evolution-data-server-1.4 evolution-data-server-1.0 PATHS /opt/local/include/ /sw/include/ /usr/local/include/ /usr/include/ ) FIND_LIBRARY( _libedatacal1.0_link_DIR edata-cal-1.0 PATHS /opt/local/lib /sw/lib /usr/lib /usr/local/lib /usr/lib64 /usr/local/lib64 /opt/lib64 ) IF ( _libedatacal1.0_include_DIR AND _libedatacal1.0_link_DIR ) SET ( _libedatacal1.0_FOUND TRUE ) ENDIF ( _libedatacal1.0_include_DIR AND _libedatacal1.0_link_DIR ) IF ( _libedatacal1.0_FOUND ) SET ( LIBEDATACAL1.0_INCLUDE_DIRS ${_libedatacal1.0_include_DIR} ) SET ( LIBEDATACAL1.0_LIBRARIES ${_libedatacal1.0_link_DIR} ) ENDIF ( _libedatacal1.0_FOUND ) # Handle dependencies IF ( NOT LIBECAL1.0_FOUND ) FIND_PACKAGE ( ECal1.0 REQUIRED ) IF ( LIBECAL1.0_FOUND ) SET ( LIBEDATACAL1.0_INCLUDE_DIRS ${LIBEDATACAL1.0_INCLUDE_DIRS} ${LIBECAL1.0_INCLUDE_DIRS} ) SET ( LIBEDATACAL1.0_LIBRARIES ${LIBEDATACAL1.0_LIBRARIES} ${LIBECAL1.0_LIBRARIES} ) ENDIF ( LIBECAL1.0_FOUND ) ENDIF ( NOT LIBECAL1.0_FOUND ) IF ( NOT GNOMEVFS2_FOUND ) FIND_PACKAGE ( GnomeVfs2 REQUIRED ) IF ( GNOMEVFS2_FOUND ) SET ( LIBEDATACAL1.0_INCLUDE_DIRS ${LIBEDATACAL1.0_INCLUDE_DIRS} ${GNOMEVFS2_INCLUDE_DIRS} ) SET ( LIBEDATACAL1.0_LIBRARIES ${LIBEDATACAL1.0_LIBRARIES} ${GNOMEVFS2_LIBRARIES} ) ENDIF ( GNOMEVFS2_FOUND ) ENDIF ( NOT GNOMEVFS2_FOUND ) IF ( NOT LIBEDATASERVER1.0_FOUND ) FIND_PACKAGE ( EDataServer1.0 REQUIRED ) IF ( LIBEDATASERVER1.0_FOUND ) SET ( LIBEDATACAL1.0_INCLUDE_DIRS ${LIBEDATACAL1.0_INCLUDE_DIRS} ${LIBEDATASERVER1.0_INCLUDE_DIRS} ) SET ( LIBEDATACAL1.0_LIBRARIES ${LIBEDATACAL1.0_LIBRARIES} ${LIBEDATASERVER1.0_LIBRARIES} ) ENDIF ( LIBEDATASERVER1.0_FOUND ) ENDIF ( NOT LIBEDATASERVER1.0_FOUND ) IF ( NOT LIBGNOME2_FOUND ) FIND_PACKAGE ( LibGnome2 REQUIRED ) IF ( LIBGNOME2_FOUND ) SET ( LIBEDATACAL1.0_INCLUDE_DIRS ${LIBEDATACAL1.0_INCLUDE_DIRS} ${LIBGNOME2_INCLUDE_DIRS} ) SET ( LIBEDATACAL1.0_LIBRARIES ${LIBEDATACAL1.0_LIBRARIES} ${LIBGNOME2_LIBRARIES} ) ENDIF ( LIBGNOME2_FOUND ) ENDIF ( NOT LIBGNOME2_FOUND ) IF ( NOT BONOBO2_FOUND ) SET ( BONOBO2_MIN_VERSION "2.4.2" ) FIND_PACKAGE ( BONOBO2 REQUIRED ) IF ( BONOBO2_FOUND ) SET ( LIBEDATACAL1.0_INCLUDE_DIRS ${LIBEDATACAL1.0_INCLUDE_DIRS} ${BONOBO2_INCLUDE_DIRS} ) SET ( LIBEDATACAL1.0_LIBRARIES ${LIBEDATACAL1.0_LIBRARIES} ${BONOBO2_LIBRARIES} ) ENDIF ( BONOBO2_FOUND ) ENDIF ( NOT BONOBO2_FOUND ) # Report results IF ( LIBEDATACAL1.0_LIBRARIES AND LIBEDATACAL1.0_INCLUDE_DIRS AND _libedatacal1.0_FOUND ) SET( LIBEDATACAL1.0_FOUND 1 ) IF ( NOT EDataCal1.0_FIND_QUIETLY ) MESSAGE( STATUS "Found libedatacal-1.0: ${LIBEDATACAL1.0_LIBRARIES}" ) ENDIF ( NOT EDataCal1.0_FIND_QUIETLY ) ELSE ( LIBEDATACAL1.0_LIBRARIES AND LIBEDATACAL1.0_INCLUDE_DIRS AND _libedatacal1.0_FOUND ) IF ( EDataCal1.0_FIND_REQUIRED ) MESSAGE( SEND_ERROR "Could NOT find libedatacal-1.0" ) ELSE ( EDataCal1.0_FIND_REQUIRED ) IF ( NOT EDataCal1.0_FIND_QUIETLY ) MESSAGE( STATUS "Could NOT find libedatacal-1.0" ) ENDIF ( NOT EDataCal1.0_FIND_QUIETLY ) ENDIF ( EDataCal1.0_FIND_REQUIRED ) ENDIF ( LIBEDATACAL1.0_LIBRARIES AND LIBEDATACAL1.0_INCLUDE_DIRS AND _libedatacal1.0_FOUND ) ENDIF ( NOT LIBEDATACAL1.0_FOUND AND NOT PKG_CONFIG_FOUND ) # Hide advanced variables from CMake GUIs MARK_AS_ADVANCED( LIBEDATACAL1.0_LIBRARIES LIBEDATACAL1.0_INCLUDE_DIRS ) libsyncml-0.5.4/cmake/modules/Testing.cmake100644 1750 1750 5306 11211710410 20574 0ustar00bellmichbellmichENABLE_TESTING() INCLUDE( CTest ) IF ( CMAKE_COMPILER_IS_GNUCC ) SET( CMAKE_C_FLAGS_PROFILING "-g -O0 -Wall -W -Wshadow -Wunused-variable -Wunused-parameter -Wunused-function -Wunused -Wno-system-headers -Wwrite-strings -fprofile-arcs -ftest-coverage" CACHE STRING "Profiling Compiler Flags" ) # SET( CMAKE_C_FLAGS_PROFILING "-g -O0 -Wall -W -Wextra -Wshadow -Wunused-variable -Wunused-parameter -Wunused-function -Wunused -Wno-system-headers -Wwrite-strings -pedantic -fprofile-arcs -ftest-coverage" CACHE STRING "Profiling Compiler Flags" ) SET( CMAKE_CXX_FLAGS_PROFILING "-g -O0 -Wall -W -Wshadow -Wunused-variable -Wunused-parameter -Wunused-function -Wunused -Wno-system-headers -Wwrite-strings -fprofile-arcs -ftest-coverage" CACHE STRING "Profiling Compiler Flags" ) SET( CMAKE_SHARED_LINKER_FLAGS_PROFILING " -fprofile-arcs -ftest-coverage" CACHE STRING "Profiling Linker Flags" ) SET( CMAKE_MODULE_LINKER_FLAGS_PROFILING " -fprofile-arcs -ftest-coverage" CACHE STRING "Profiling Linker Flags" ) SET( CMAKE_EXEC_LINKER_FLAGS_PROFILING " -fprofile-arcs -ftest-coverage" CACHE STRING "Profiling Linker Flags" ) ENDIF ( CMAKE_COMPILER_IS_GNUCC ) MACRO( BUILD_CHECK_TEST _testName _testSource ) if(COMMAND cmake_policy) cmake_policy(SET CMP0003 NEW) ## The macro ADD_CHECK_TEST creates false warning. cmake_policy(SET CMP0002 OLD) endif(COMMAND cmake_policy) ADD_EXECUTABLE( ${_testName} ${_testSource} ) TARGET_LINK_LIBRARIES( ${_testName} ${ARGN} ) ENDMACRO( BUILD_CHECK_TEST ) MACRO( ADD_CHECK_TEST _testName _testSource ) if(COMMAND cmake_policy) cmake_policy(SET CMP0003 NEW) ## The macro ADD_CHECK_TEST creates false warning. cmake_policy(SET CMP0002 OLD) endif(COMMAND cmake_policy) BUILD_CHECK_TEST( ${_testName} ${_testSource} ${ARGN} ) # ADD_EXECUTABLE( ${_testName} ${_testSource} ) # TARGET_LINK_LIBRARIES( ${_testName} ${ARGN} ) ADD_TEST( ${_testName} ${CMAKE_CURRENT_BINARY_DIR}/${_testName} ) ENDMACRO( ADD_CHECK_TEST ) MACRO( OSYNC_TESTCASE _testSource _testDest ) if(COMMAND cmake_policy) cmake_policy(SET CMP0003 NEW) ## The macro ADD_CHECK_TEST creates false warning. cmake_policy(SET CMP0002 OLD) endif(COMMAND cmake_policy) # 1st Argument is the testcase name # 2nd Argument is the executable name # 3rd Argument the testcase name, again, as argument for the executable ADD_TEST( ${_testDest} ${_testSource} ${_testDest} ) ENDMACRO( OSYNC_TESTCASE ) MACRO( OSYNC_TESTCASE_DISABLED _testSource _testDest _ticket ) OSYNC_TESTCASE( ${_testSource} ${_testDest} ) SET( CTEST_CUSTOM_TESTS_IGNORE ${CTEST_CUSTOM_TESTS_IGNORE} "${_testDest}" ) MESSAGE( STATUS "Testcase \"${_testDest}\" disabled/ignored! ${TICKETURL}${_ticket}" ) ENDMACRO( OSYNC_TESTCASE_DISABLED ) libsyncml-0.5.4/cmake/modules/FindKDEPIM3.cmake100644 1750 1750 3241 11211710410 21010 0ustar00bellmichbellmich# - Try to find KDEPIM3 # Find KDEPIM3 headers, libraries and the answer to all questions. # # KDEPIM3_FOUND True if KDEPIM3 got found # KDEPIM3_INCLUDE_DIR Location of KDEPIM3 headers # KDEPIM3_KCAL_LIBRARIES List of libaries to use KABC of KDEPIM3 # KDEPIM3_KABC_LIBRARIES List of libaries to use KCAL of KDEPIM3 # KDEPIM3_DEFINITIONS Definitions to compile KDEPIM3 # # Copyright (c) 2007 Daniel Gollub # # Redistribution and use is allowed according to the terms of the New # BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # FIND_PACKAGE( KDE3 REQUIRED ) FIND_PATH( KDEPIM3_INCLUDE_DIR kdepimmacros.h ${KDE3_INCLUDE_DIR} ) FIND_LIBRARY( KDEPIM3_KCAL_LIBRARIES kcal ${KDE3_LIB_DIR} ) FIND_LIBRARY( KDEPIM3_KABC_LIBRARIES kabc ${KDE3_LIB_DIR} ) # Report results IF ( KDEPIM3_KCAL_LIBRARIES AND KDEPIM3_KABC_LIBRARIES AND KDEPIM3_INCLUDE_DIR ) SET( KDEPIM3_FOUND 1 ) IF ( NOT KDEPIM3_FIND_QUIETLY ) MESSAGE( STATUS "Found KDE PIM 3: ${KDEPIM3_KABC_LIBRARIES} ${KDEPIM3_KCAL_LIBRARIES}" ) ENDIF ( NOT KDEPIM3_FIND_QUIETLY ) ELSE ( KDEPIM3_KCAL_LIBRARIES AND KDEPIM3_KABC_LIBRARIES AND KDEPIM3_INCLUDE_DIR ) IF ( KDEPIM3_FIND_REQUIRED ) MESSAGE( SEND_ERROR "Could NOT find KDE PIM 3" ) ELSE ( KDEPIM3_FIND_REQUIRED ) IF ( NOT KDEPIM3_FIND_QUIETLY ) MESSAGE( STATUS "Could NOT find KDE PIM 3" ) ENDIF ( NOT KDEPIM3_FIND_QUIETLY ) ENDIF ( KDEPIM3_FIND_REQUIRED ) ENDIF ( KDEPIM3_KCAL_LIBRARIES AND KDEPIM3_KABC_LIBRARIES AND KDEPIM3_INCLUDE_DIR ) # Hide advanced variables from CMake GUIs MARK_AS_ADVANCED( KDEPIM3_KCAL_LIBRARIES KDEPIM3_KABC_LIBRARIES KDEPIM3_INCLUDE_DIR ) libsyncml-0.5.4/cmake/modules/FindPkgConfig.cmake100644 1750 1750 37142 11211710410 21652 0ustar00bellmichbellmich# - a pkg-config module for CMake # # Usage: # pkg_check_modules( [REQUIRED] []*) # checks for all the given modules # # pkg_search_module( [REQUIRED] []*) # checks for given modules and uses the first working one # # When the 'REQUIRED' argument was set, macros will fail with an error # when module(s) could not be found # # It sets the following variables: # PKG_CONFIG_FOUND ... true iff pkg-config works on the system # PKG_CONFIG_EXECUTABLE ... pathname of the pkg-config program # _FOUND ... set to 1 iff module(s) exist # # For the following variables two sets of values exist; first one is the # common one and has the given PREFIX. The second set contains flags # which are given out when pkgconfig was called with the '--static' # option. # _LIBRARIES ... only the libraries (w/o the '-l') # _LIBRARY_DIRS ... the paths of the libraries (w/o the '-L') # _LDFLAGS ... all required linker flags # _LDFLAGS_OTHERS ... all other linker flags # _INCLUDE_DIRS ... the '-I' preprocessor flags (w/o the '-I') # _CFLAGS ... all required cflags # _CFLAGS_OTHERS ... the other compiler flags # # = for common case # = _STATIC for static linking # # There are some special variables whose prefix depends on the count # of given modules. When there is only one module, stays # unchanged. When there are multiple modules, the prefix will be # changed to _: # _VERSION ... version of the module # _PREFIX ... prefix-directory of the module # _INCLUDEDIR ... include-dir of the module # _LIBDIR ... lib-dir of the module # # = when |MODULES| == 1, else # = _ # # A parameter can have the following formats: # {MODNAME} ... matches any version # {MODNAME}>={VERSION} ... at least version is required # {MODNAME}={VERSION} ... exactly version is required # {MODNAME}<={VERSION} ... modules must not be newer than # # Examples # pkg_check_modules (GLIB2 glib-2.0) # # pkg_check_modules (GLIB2 glib-2.0>=2.10) # requires at least version 2.10 of glib2 and defines e.g. # GLIB2_VERSION=2.10.3 # # pkg_check_modules (FOO glib-2.0>=2.10 gtk+-2.0) # requires both glib2 and gtk2, and defines e.g. # FOO_glib-2.0_VERSION=2.10.3 # FOO_gtk+-2.0_VERSION=2.8.20 # # pkg_check_modules (XRENDER REQUIRED xrender) # defines e.g.: # XRENDER_LIBRARIES=Xrender;X11 # XRENDER_STATIC_LIBRARIES=Xrender;X11;pthread;Xau;Xdmcp # # pkg_search_module (BAR libxml-2.0 libxml2 libxml>=2) # Copyright (C) 2006 Enrico Scholz # # Redistribution and use, with or without modification, are permitted # provided that the following conditions are met: # # 1. Redistributions must retain the above copyright notice, this # list of conditions and the following disclaimer. # 2. The name of the author may not be used to endorse or promote # products derived from this software without specific prior # written permission. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE # GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER # IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR # OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN # IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ### Common stuff #### set(PKG_CONFIG_VERSION 1) set(PKG_CONFIG_FOUND 0) IF ( PkgConfig_FIND_REQUIRED ) SET( PKGCONFIG_REQUIRED "REQUIRED" ) ELSE( PkgConfig_FIND_REQUIRED ) SET( PKGCONFIG_REQUIRED "" ) ENDIF ( PkgConfig_FIND_REQUIRED ) find_program(PKG_CONFIG_EXECUTABLE NAMES pkg-config DOC "pkg-config executable") mark_as_advanced(PKG_CONFIG_EXECUTABLE) if(PKG_CONFIG_EXECUTABLE) set(PKG_CONFIG_FOUND 1) endif(PKG_CONFIG_EXECUTABLE) # Unsets the given variables macro(_pkgconfig_unset var) set(${var} "" CACHE INTERNAL "") endmacro(_pkgconfig_unset) macro(_pkgconfig_set var value) set(${var} ${value} CACHE INTERNAL "") endmacro(_pkgconfig_set) # Invokes pkgconfig, cleans up the result and sets variables macro(_pkgconfig_invoke _pkglist _prefix _varname _regexp) set(_pkgconfig_invoke_result) execute_process( COMMAND ${PKG_CONFIG_EXECUTABLE} ${ARGN} ${_pkglist} OUTPUT_VARIABLE _pkgconfig_invoke_result RESULT_VARIABLE _pkgconfig_failed) if (_pkgconfig_failed) set(_pkgconfig_${_varname} "") _pkgconfig_unset(${_prefix}_${_varname}) else(_pkgconfig_failed) string(REGEX REPLACE "[\r\n]" " " _pkgconfig_invoke_result "${_pkgconfig_invoke_result}") string(REGEX REPLACE " +$" "" _pkgconfig_invoke_result "${_pkgconfig_invoke_result}") if (NOT ${_regexp} STREQUAL "") string(REGEX REPLACE "${_regexp}" " " _pkgconfig_invoke_result "${_pkgconfig_invoke_result}") endif(NOT ${_regexp} STREQUAL "") separate_arguments(_pkgconfig_invoke_result) #message(STATUS " ${_varname} ... ${_pkgconfig_invoke_result}") set(_pkgconfig_${_varname} ${_pkgconfig_invoke_result}) _pkgconfig_set(${_prefix}_${_varname} "${_pkgconfig_invoke_result}") endif(_pkgconfig_failed) endmacro(_pkgconfig_invoke) # Invokes pkgconfig two times; once without '--static' and once with # '--static' macro(_pkgconfig_invoke_dyn _pkglist _prefix _varname cleanup_regexp) _pkgconfig_invoke("${_pkglist}" ${_prefix} ${_varname} "${cleanup_regexp}" ${ARGN}) _pkgconfig_invoke("${_pkglist}" ${_prefix} STATIC_${_varname} "${cleanup_regexp}" --static ${ARGN}) endmacro(_pkgconfig_invoke_dyn) # Splits given arguments into options and a package list macro(_pkgconfig_parse_options _result _is_req) set(${_is_req} 0) foreach(_pkg ${ARGN}) if (_pkg STREQUAL "REQUIRED") set(${_is_req} 1) endif (_pkg STREQUAL "REQUIRED") endforeach(_pkg ${ARGN}) set(${_result} ${ARGN}) list(REMOVE_ITEM ${_result} "REQUIRED") endmacro(_pkgconfig_parse_options) ### macro(_pkg_check_modules_internal _is_required _is_silent _prefix) _pkgconfig_unset(${_prefix}_FOUND) _pkgconfig_unset(${_prefix}_VERSION) _pkgconfig_unset(${_prefix}_PREFIX) _pkgconfig_unset(${_prefix}_INCLUDEDIR) _pkgconfig_unset(${_prefix}_LIBDIR) _pkgconfig_unset(${_prefix}_LIBS) _pkgconfig_unset(${_prefix}_LIBS_L) _pkgconfig_unset(${_prefix}_LIBS_PATHS) _pkgconfig_unset(${_prefix}_LIBS_OTHER) _pkgconfig_unset(${_prefix}_CFLAGS) _pkgconfig_unset(${_prefix}_CFLAGS_I) _pkgconfig_unset(${_prefix}_CFLAGS_OTHER) _pkgconfig_unset(${_prefix}_STATIC_LIBDIR) _pkgconfig_unset(${_prefix}_STATIC_LIBS) _pkgconfig_unset(${_prefix}_STATIC_LIBS_L) _pkgconfig_unset(${_prefix}_STATIC_LIBS_PATHS) _pkgconfig_unset(${_prefix}_STATIC_LIBS_OTHER) _pkgconfig_unset(${_prefix}_STATIC_CFLAGS) _pkgconfig_unset(${_prefix}_STATIC_CFLAGS_I) _pkgconfig_unset(${_prefix}_STATIC_CFLAGS_OTHER) # create a better addressable variable of the modules and calculate its size set(_pkg_check_modules_list ${ARGN}) list(LENGTH _pkg_check_modules_list _pkg_check_modules_cnt) if(PKG_CONFIG_FOUND) # give out status message telling checked module if (NOT ${_is_silent}) if (_pkg_check_modules_cnt EQUAL 1) message(STATUS "checking for module '${_pkg_check_modules_list}'") else(_pkg_check_modules_cnt EQUAL 1) message(STATUS "checking for modules '${_pkg_check_modules_list}'") endif(_pkg_check_modules_cnt EQUAL 1) endif(NOT ${_is_silent}) set(_pkg_check_modules_packages) set(_pkg_check_modules_failed) # iterate through module list and check whether they exist and match the required version foreach (_pkg_check_modules_pkg ${_pkg_check_modules_list}) set(_pkg_check_modules_exist_query) # check whether version is given if (_pkg_check_modules_pkg MATCHES ".*(>=|=|<=).*") string(REGEX REPLACE "(.*[^><])(>=|=|<=)(.*)" "\\1" _pkg_check_modules_pkg_name "${_pkg_check_modules_pkg}") string(REGEX REPLACE "(.*[^><])(>=|=|<=)(.*)" "\\2" _pkg_check_modules_pkg_op "${_pkg_check_modules_pkg}") string(REGEX REPLACE "(.*[^><])(>=|=|<=)(.*)" "\\3" _pkg_check_modules_pkg_ver "${_pkg_check_modules_pkg}") else(_pkg_check_modules_pkg MATCHES ".*(>=|=|<=).*") set(_pkg_check_modules_pkg_name "${_pkg_check_modules_pkg}") set(_pkg_check_modules_pkg_op) set(_pkg_check_modules_pkg_ver) endif(_pkg_check_modules_pkg MATCHES ".*(>=|=|<=).*") # handle the operands if (_pkg_check_modules_pkg_op STREQUAL ">=") list(APPEND _pkg_check_modules_exist_query --atleast-version) endif(_pkg_check_modules_pkg_op STREQUAL ">=") if (_pkg_check_modules_pkg_op STREQUAL "=") list(APPEND _pkg_check_modules_exist_query --exact-version) endif(_pkg_check_modules_pkg_op STREQUAL "=") if (_pkg_check_modules_pkg_op STREQUAL "<=") list(APPEND _pkg_check_modules_exist_query --max-version) endif(_pkg_check_modules_pkg_op STREQUAL "<=") # create the final query which is of the format: # * --atleast-version # * --exact-version # * --max-version # * --exists if (_pkg_check_modules_pkg_op) list(APPEND _pkg_check_modules_exist_query "${_pkg_check_modules_pkg_ver}") else(_pkg_check_modules_pkg_op) list(APPEND _pkg_check_modules_exist_query --exists) endif(_pkg_check_modules_pkg_op) _pkgconfig_unset(${_prefix}_${_pkg_check_modules_pkg_name}_VERSION) _pkgconfig_unset(${_prefix}_${_pkg_check_modules_pkg_name}_PREFIX) _pkgconfig_unset(${_prefix}_${_pkg_check_modules_pkg_name}_INCLUDEDIR) _pkgconfig_unset(${_prefix}_${_pkg_check_modules_pkg_name}_LIBDIR) list(APPEND _pkg_check_modules_exist_query "${_pkg_check_modules_pkg_name}") list(APPEND _pkg_check_modules_packages "${_pkg_check_modules_pkg_name}") # execute the query execute_process( COMMAND ${PKG_CONFIG_EXECUTABLE} ${_pkg_check_modules_exist_query} RESULT_VARIABLE _pkgconfig_retval) # evaluate result and tell failures if (_pkgconfig_retval) if(NOT ${_is_silent}) message(STATUS " package '${_pkg_check_modules_pkg}' not found") endif(NOT ${_is_silent}) set(_pkg_check_modules_failed 1) endif(_pkgconfig_retval) endforeach(_pkg_check_modules_pkg) if(_pkg_check_modules_failed) # fail when requested if (${_is_required}) message(SEND_ERROR "A required package was not found") endif (${_is_required}) else(_pkg_check_modules_failed) # when we are here, we checked whether requested modules # exist. Now, go through them and set variables _pkgconfig_set(${_prefix}_FOUND 1) list(LENGTH _pkg_check_modules_packages pkg_count) # iterate through all modules again and set individual variables foreach (_pkg_check_modules_pkg ${_pkg_check_modules_packages}) # handle case when there is only one package required if (pkg_count EQUAL 1) set(_pkg_check_prefix "${_prefix}") else(pkg_count EQUAL 1) set(_pkg_check_prefix "${_prefix}_${_pkg_check_modules_pkg}") endif(pkg_count EQUAL 1) _pkgconfig_invoke(${_pkg_check_modules_pkg} "${_pkg_check_prefix}" VERSION "" --modversion ) _pkgconfig_invoke(${_pkg_check_modules_pkg} "${_pkg_check_prefix}" PREFIX "" --variable=prefix ) _pkgconfig_invoke(${_pkg_check_modules_pkg} "${_pkg_check_prefix}" INCLUDEDIR "" --variable=includedir ) _pkgconfig_invoke(${_pkg_check_modules_pkg} "${_pkg_check_prefix}" LIBDIR "" --variable=libdir ) message(STATUS " found ${_pkg_check_modules_pkg}, version ${_pkgconfig_VERSION}") endforeach(_pkg_check_modules_pkg) # set variables which are combined for multiple modules _pkgconfig_invoke_dyn("${_pkg_check_modules_packages}" "${_prefix}" LIBRARIES "(^| )-l" --libs-only-l ) _pkgconfig_invoke_dyn("${_pkg_check_modules_packages}" "${_prefix}" LIBRARY_DIRS "(^| )-L" --libs-only-L ) _pkgconfig_invoke_dyn("${_pkg_check_modules_packages}" "${_prefix}" LDFLAGS "" --libs ) _pkgconfig_invoke_dyn("${_pkg_check_modules_packages}" "${_prefix}" LDFLAGS_OTHER "" --libs-only-other ) _pkgconfig_invoke_dyn("${_pkg_check_modules_packages}" "${_prefix}" INCLUDE_DIRS "(^| )-I" --cflags-only-I ) _pkgconfig_invoke_dyn("${_pkg_check_modules_packages}" "${_prefix}" CFLAGS "" --cflags ) _pkgconfig_invoke_dyn("${_pkg_check_modules_packages}" "${_prefix}" CFLAGS_OTHER "" --cflags-only-other ) endif(_pkg_check_modules_failed) else(PKG_CONFIG_FOUND) if (PKGCONFIG_REQUIRED AND ${_is_required}) message(SEND_ERROR "pkg-config tool not found") endif (PKGCONFIG_REQUIRED AND ${_is_required}) endif(PKG_CONFIG_FOUND) endmacro(_pkg_check_modules_internal) ### ### User visible macros start here ### ### macro(pkg_check_modules _prefix _module0) # check cached value if (NOT DEFINED __pkg_config_checked_${_prefix} OR __pkg_config_checked_${_prefix} LESS ${PKG_CONFIG_VERSION}) _pkgconfig_parse_options (_pkg_modules _pkg_is_required "${_module0}" ${ARGN}) _pkg_check_modules_internal("${_pkg_is_required}" 0 "${_prefix}" ${_pkg_modules}) _pkgconfig_set(__pkg_config_checked_${_prefix} ${PKG_CONFIG_VERSION}) endif(NOT DEFINED __pkg_config_checked_${_prefix} OR __pkg_config_checked_${_prefix} LESS ${PKG_CONFIG_VERSION}) endmacro(pkg_check_modules) ### macro(pkg_search_module _prefix _module0) if(PKG_CONFIG_FOUND) # check cached value if ( NOT DEFINED __pkg_config_checked_${_prefix} OR __pkg_config_checked_${_prefix} LESS ${PKG_CONFIG_VERSION} OR NOT ${_prefix}_FOUND ) set(_pkg_modules_found 0) _pkgconfig_parse_options(_pkg_modules_alt _pkg_is_required "${_module0}" ${ARGN}) message(STATUS "checking for one of the modules '${_pkg_modules_alt}'") # iterate through all modules and stop at the first working one. foreach(_pkg_alt ${_pkg_modules_alt}) if(NOT _pkg_modules_found) _pkg_check_modules_internal(0 1 "${_prefix}" "${_pkg_alt}") endif(NOT _pkg_modules_found) if (${_prefix}_FOUND) set(_pkg_modules_found 1) endif(${_prefix}_FOUND) endforeach(_pkg_alt) if (NOT ${_prefix}_FOUND) if(${_pkg_is_required}) message(SEND_ERROR "None of the required '${_pkg_modules_alt}' found") endif(${_pkg_is_required}) endif(NOT ${_prefix}_FOUND) _pkgconfig_set(__pkg_config_checked_${_prefix} ${PKG_CONFIG_VERSION}) endif(NOT DEFINED __pkg_config_checked_${_prefix} OR __pkg_config_checked_${_prefix} LESS ${PKG_CONFIG_VERSION} OR NOT ${_prefix}_FOUND ) else(PKG_CONFIG_FOUND) if (PKGCONFIG_REQUIRED) message(SEND_ERROR "pkg-config tool not found") endif (PKGCONFIG_REQUIRED) endif(PKG_CONFIG_FOUND) endmacro(pkg_search_module) ### Local Variables: ### mode: cmake ### End: libsyncml-0.5.4/cmake/modules/FindOpenObex.cmake100644 1750 1750 5037 11211710410 21500 0ustar00bellmichbellmich# - Try to find OpenObex # Find OpenObex headers, libraries and the answer to all questions. # # OPENOBEX_FOUND True if OpenObex got found # OPENOBEX_INCLUDE_DIRS Location of OpenObex headers # OPENOBEX_LIBRARIES List of libaries to use OpenObex # OPENOBEX_HAVE_TCPOBEX OpenObex supports Tcp over Obex # # Copyright (c) 2007 Daniel Gollub # Copyright (c) 2007-2008 Bjoern Ricks # # Redistribution and use is allowed according to the terms of the New # BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # INCLUDE( FindPkgConfig ) IF ( OpenObex_FIND_REQUIRED ) SET( _pkgconfig_REQUIRED "REQUIRED" ) ELSE( OpenObex_FIND_REQUIRED ) SET( _pkgconfig_REQUIRED "" ) ENDIF ( OpenObex_FIND_REQUIRED ) IF ( OPENOBEX_MIN_VERSION ) PKG_SEARCH_MODULE( OPENOBEX openobex>=${OPENOBEX_MIN_VERSION} ${_pkgconfig_REQUIRED} ) ELSE ( OPENOBEX_MIN_VERSION ) PKG_SEARCH_MODULE( OPENOBEX openobex ${_pkgconfig_REQUIRED} ) ENDIF ( OPENOBEX_MIN_VERSION ) IF( NOT OPENOBEX_FOUND AND NOT PKG_CONFIG_FOUND ) # Fallback if pkg-config doesn't exist #MESSAGE( STATUS "FALLBACK" ) FIND_PATH( OPENOBEX_INCLUDE_DIRS openobex/obex.h PATHS /opt/local/include/ /sw/include/ /usr/local/include/ /usr/include/ ) FIND_LIBRARY( OPENOBEX_LIBRARIES openobex PATHS /opt/local/lib /sw/lib /usr/lib /usr/local/lib /usr/lib64 /usr/local/lib64 /opt/lib64 ) # Report results IF ( OPENOBEX_LIBRARIES AND OPENOBEX_INCLUDE_DIRS ) SET( OPENOBEX_FOUND 1 ) IF ( NOT OpenObex_FIND_QUIETLY ) MESSAGE( STATUS "Found OpenObex: ${OPENOBEX_LIBRARIES}" ) ENDIF ( NOT OpenObex_FIND_QUIETLY ) ELSE ( OPENOBEX_LIBRARIES AND OPENOBEX_INCLUDE_DIRS ) IF ( OpenObex_FIND_REQUIRED ) MESSAGE( SEND_ERROR "Could NOT find OpenObex" ) ELSE ( OpenObex_FIND_REQUIRED ) IF ( NOT OpenObex_FIND_QUIETLY ) MESSAGE( STATUS "Could NOT find OpenObex" ) ENDIF ( NOT OpenObex_FIND_QUIETLY ) ENDIF ( OpenObex_FIND_REQUIRED ) ENDIF ( OPENOBEX_LIBRARIES AND OPENOBEX_INCLUDE_DIRS ) ENDIF( NOT OPENOBEX_FOUND AND NOT PKG_CONFIG_FOUND ) IF ( OPENOBEX_FOUND ) INCLUDE(CheckFunctionExists) SET( CMAKE_REQUIRED_INCLUDES ${OPENOBEX_INCLUDE_DIRS} ) SET( CMAKE_REQUIRED_LIBRARIES ${OPENOBEX_LIBRARIES} ) CHECK_FUNCTION_EXISTS( TcpOBEX_ServerRegister OPENOBEX_HAVE_TCPOBEX ) #MESSAGE( STATUS "OpenObex has TCP support: ${OPENOBEX_HAVE_TCPOBEX}" ) ENDIF( OPENOBEX_FOUND ) # Hide advanced variables from CMake GUIs MARK_AS_ADVANCED( OPENOBEX_LIBRARIES OPENOBEX_INCLUDE_DIRS ) libsyncml-0.5.4/cmake/modules/FindOpenSync.cmake100644 1750 1750 6400 11211710410 21512 0ustar00bellmichbellmich# - Try to find OpenSync # Find OpenSync headers, libraries and the answer to all questions. # # OPENSYNC_FOUND True if OpenSync got found # OPENSYNC_INCLUDE_DIRS Location of OpenSync headers # OPENSYNC_LIBRARIES List of libaries to use OpenSync # # Copyright (c) 2007 Daniel Gollub # Copyright (c) 2007 Alban Browaeys # Copyright (c) 2008 Bjoern Ricks # # Redistribution and use is allowed according to the terms of the New # BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # # Take care about libopensync.pc settings INCLUDE( FindPkgConfig ) IF ( OpenSync_FIND_REQUIRED ) SET( _pkgconfig_REQUIRED "REQUIRED" ) ELSE( OpenSync_FIND_REQUIRED ) SET( _pkgconfig_REQUIRED "" ) ENDIF ( OpenSync_FIND_REQUIRED ) IF ( OPENSYNC_MIN_VERSION ) PKG_SEARCH_MODULE( OPENSYNC ${_pkgconfig_REQUIRED} libopensync >=${OPENSYNC_MIN_VERSION} ) ELSE ( OPENSYNC_MIN_VERSION ) PKG_SEARCH_MODULE( OPENSYNC ${_pkgconfig_REQUIRED} libopensync ) ENDIF ( OPENSYNC_MIN_VERSION ) FIND_PROGRAM( PKGCONFIG_EXECUTABLE NAMES pkg-config ) IF ( PKGCONFIG_EXECUTABLE ) EXEC_PROGRAM( ${PKGCONFIG_EXECUTABLE} ARGS libopensync --variable=datadir OUTPUT_VARIABLE _opensync_data_DIR ) STRING( REGEX REPLACE "[\r\n]" " " _opensync_data_DIR "${_opensync_data_DIR}" ) ENDIF ( PKGCONFIG_EXECUTABLE ) FIND_PATH( OPENSYNC_CMAKE_MODULES "OpenSyncInternal.cmake" PATHS "${_opensync_data_DIR}" PATH_SUFFIXES "cmake/modules" NO_DEFAULT_PATH) FIND_PATH( OPENSYNC_CMAKE_MODULES "OpenSyncInternal.cmake" PATH_SUFFIXES "cmake/modules" ) IF ( OPENSYNC_CMAKE_MODULES ) SET( CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${OPENSYNC_CMAKE_MODULES}" ) ELSE ( OPENSYNC_CMAKE_MODULES ) IF ( OpenSync_FIND_REQUIRED ) MESSAGE( FATAL_ERROR "OpenSync cmake modules not found. Have you installed opensync core or did you set your PKG_CONFIG_PATH if installing in a non system directory ?" ) ENDIF ( OpenSync_FIND_REQUIRED ) ENDIF ( OPENSYNC_CMAKE_MODULES ) # Look for OpenSync include dir and libraries without pkg-config IF( NOT OPENSYNC_FOUND AND NOT PKG_CONFIG_FOUND ) # Fallback if pkg-config doesn't exist FIND_PATH( OPENSYNC_INCLUDE_DIRS opensync/opensync.h PATH_SUFFIXES libopensync libopensync1 PATHS /opt/local/include/ /sw/include/ /usr/local/include/ /usr/include/ ) FIND_LIBRARY( OPENSYNC_LIBRARIES opensync PATHS /opt/local/lib /sw/lib /usr/lib /usr/local/lib /usr/lib64 /usr/local/lib64 /opt/lib64 ) # Report results IF ( OPENSYNC_LIBRARIES AND OPENSYNC_INCLUDE_DIRS ) SET( OPENSYNC_FOUND 1 ) IF ( NOT OpenSync_FIND_QUIETLY ) MESSAGE( STATUS "Found OpenSync: ${OPENSYNC_LIBRARIES}" ) ENDIF ( NOT OpenSync_FIND_QUIETLY ) ELSE ( OPENSYNC_LIBRARIES AND OPENSYNC_INCLUDE_DIRS ) IF ( OpenSync_FIND_REQUIRED ) MESSAGE( SEND_ERROR "Could NOT find OpenSync" ) ELSE ( OpenSync_FIND_REQUIRED ) IF ( NOT OpenSync_FIND_QUIETLY ) MESSAGE( STATUS "Could NOT find OpenSync" ) ENDIF ( NOT OpenSync_FIND_QUIETLY ) ENDIF ( OpenSync_FIND_REQUIRED ) ENDIF ( OPENSYNC_LIBRARIES AND OPENSYNC_INCLUDE_DIRS ) ENDIF( NOT OPENSYNC_FOUND AND NOT PKG_CONFIG_FOUND ) # Hide advanced variables from CMake GUIs MARK_AS_ADVANCED( OPENSYNC_LIBRARIES OPENSYNC_INCLUDE_DIRS ) libsyncml-0.5.4/cmake/modules/FindExpat.cmake100644 1750 1750 3460 11211710410 21040 0ustar00bellmichbellmich# - Try to find Expat # Find Expat headers, libraries and the answer to all questions. # # EXPAT_FOUND True if Expat got found # EXPAT_INCLUDE_DIRS Location of Expat headers # EXPAT_LIBRARIES List of libraries to use Expat # # Copyright (c) 2008 Bjoern Ricks # # Redistribution and use is allowed according to the terms of the New # BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # # WARNING: Currently Expat doesn't provide a .pc file # Therefore it is not possible to use FindPkgConfig and to require a min version #INCLUDE( FindPkgConfig ) #IF ( EXPAT_FIND_REQUIRED ) # SET( _pkgconfig_REQUIRED "REQUIRED" ) #ELSE( EXPAT_FIND_REQUIRED ) # SET( _pkgconfig_REQUIRED "" ) #ENDIF ( EXPAT_FIND_REQUIRED ) #IF ( EXPAT_MIN_VERSION ) # PKG_SEARCH_MODULE( EXPAT ${_pkgconfig_REQUIRED} expat>=${EXPAT_MIN_VERSION} ) #ELSE ( EXPAT_MIN_VERSION ) # PKG_SEARCH_MODULE( EXPAT ${_pkgconfig_REQUIRED} expat ) #ENDIF ( EXPAT_MIN_VERSION ) #IF( NOT EXPAT_FOUND AND NOT PKG_CONFIG_FOUND ) FIND_PATH( EXPAT_INCLUDE_DIRS expat.h) FIND_LIBRARY( EXPAT_LIBRARIES expat ) # Report results IF ( EXPAT_LIBRARIES AND EXPAT_INCLUDE_DIRS ) SET( EXPAT_FOUND 1 ) IF ( NOT EXPAT_FIND_QUIETLY ) MESSAGE( STATUS "Found Expat: ${EXPAT_LIBRARIES}" ) ENDIF ( NOT EXPAT_FIND_QUIETLY ) ELSE ( EXPAT_LIBRARIES AND EXPAT_INCLUDE_DIRS ) IF ( EXPAT_FIND_REQUIRED ) MESSAGE( SEND_ERROR "Could NOT find Expat" ) ELSE ( EXPAT_FIND_REQUIRED ) IF ( NOT EXPAT_FIND_QUIETLY ) MESSAGE( STATUS "Could NOT find Expat" ) ENDIF ( NOT EXPAT_FIND_QUIETLY ) ENDIF ( EXPAT_FIND_REQUIRED ) ENDIF ( EXPAT_LIBRARIES AND EXPAT_INCLUDE_DIRS ) #ENDIF( NOT EXPAT_FOUND AND NOT PKG_CONFIG_FOUND ) MARK_AS_ADVANCED( EXPAT_LIBRARIES EXPAT_INCLUDE_DIRS )libsyncml-0.5.4/cmake/modules/AddDocumentation.cmake100644 1750 1750 5420 11211710410 22376 0ustar00bellmichbellmich# - InstallDocumentation.cmake # Installs different types of documentation # # Copyright (c) 2008 Michael Bell # # Redistribution and use is allowed according to the terms of the New # BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # INCLUDE( Documentation ) SET( SHARE_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/share" CACHE INTERNAL "share location" ) SET( DOC_MAN_INSTALL_DIR "${SHARE_INSTALL_DIR}/man" CACHE INTERNAL "man page location" ) SET( DOC_INSTALL_DIR "${SHARE_INSTALL_DIR}/doc/${PROJECT_NAME}" CACHE INTERNAL "documentation location" ) SET( DOC_TEXT_INSTALL_DIR "${DOC_INSTALL_DIR}" CACHE INTERNAL "text documentation location" ) SET( DOC_HTML_INSTALL_DIR "${DOC_INSTALL_DIR}/html" CACHE INTERNAL "HTML documentation location" ) MACRO( ADD_DOCUMENTATION _formatName _fileType ) # _formatName - HTML, TEXT, MAN # _fileType - DIRECTORY, FILE # ARGN - filenames # check _formatName STRING( TOUPPER ${_formatName} FORMAT_NAME ) STRING( COMPARE EQUAL ${FORMAT_NAME} "HTML" FORMAT_IS_HTML ) STRING( COMPARE EQUAL ${FORMAT_NAME} "TEXT" FORMAT_IS_TEXT ) STRING( COMPARE EQUAL ${FORMAT_NAME} "MAN" FORMAT_IS_MAN ) IF( NOT ${FORMAT_IS_HTML} AND NOT ${FORMAT_IS_TEXT} AND NOT ${FORMAT_IS_MAN} ) MESSAGE( SEND_ERROR "ADD_DOCUMENTATION only support HTML, TEXT and MAN as formats." ) RETURN() ENDIF( NOT ${FORMAT_IS_HTML} AND NOT ${FORMAT_IS_TEXT} AND NOT ${FORMAT_IS_MAN} ) # check _fileType STRING( TOUPPER ${_fileType} FILE_TYPE ) STRING( COMPARE EQUAL ${FILE_TYPE} "DIRECTORY" FILE_IS_DIRECTORY ) STRING( COMPARE EQUAL ${FILE_TYPE} "FILE" FILE_IS_FILE ) IF( NOT ${FILE_IS_DIRECTORY} AND NOT ${FILE_IS_FILE} ) MESSAGE( SEND_ERROR "ADD_DOCUMENTATION only support DIRECTORY and FILE as file types." ) RETURN() ENDIF( NOT ${FILE_IS_DIRECTORY} AND NOT ${FILE_IS_FILE} ) # install HTML documenation IF( ${FORMAT_IS_HTML} ) IF( ${FILE_IS_DIRECTORY} ) INSTALL( DIRECTORY ${ARGN} DESTINATION ${DOC_HTML_INSTALL_DIR} ) ELSE( ${FILE_IS_DIRECTORY} ) INSTALL( FILES ${ARGN} DESTINATION ${DOC_HTML_INSTALL_DIR} ) ENDIF( ${FILE_IS_DIRECTORY} ) ENDIF( ${FORMAT_IS_HTML} ) # install TEXT documenation IF( ${FORMAT_IS_TEXT} ) IF( ${FILE_IS_DIRECTORY} ) INSTALL( DIRECTORY ${ARGN} DESTINATION ${DOC_TEXT_INSTALL_DIR} ) ELSE( ${FILE_IS_DIRECTORY} ) INSTALL( FILES ${ARGN} DESTINATION ${DOC_TEXT_INSTALL_DIR} ) ENDIF( ${FILE_IS_DIRECTORY} ) ENDIF( ${FORMAT_IS_TEXT} ) # install man pages IF( ${FORMAT_IS_MAN} ) IF( ${FILE_IS_DIRECTORY} ) INSTALL( DIRECTORY ${ARGN} DESTINATION ${DOC_MAN_INSTALL_DIR} ) ELSE( ${FILE_IS_DIRECTORY} ) INSTALL( FILES ${ARGN} DESTINATION ${DOC_MAN_INSTALL_DIR} ) ENDIF( ${FILE_IS_DIRECTORY} ) ENDIF( ${FORMAT_IS_MAN} ) ENDMACRO( ADD_DOCUMENTATION _formatName _fileType ) libsyncml-0.5.4/cmake/modules/COPYING-CMAKE-SCRIPTS100644 1750 1750 2456 11211710410 21156 0ustar00bellmichbellmichRedistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. libsyncml-0.5.4/cmake/modules/FindGLIB2.cmake100644 1750 1750 14412 11211710410 20575 0ustar00bellmichbellmich# - Try to find GLib2 # Once done this will define # # GLIB2_FOUND - system has GLib2 # GLIB2_INCLUDE_DIRS - the GLib2 include directory # GLIB2_LIBRARIES - Link these to use GLib2 # # HAVE_GLIB_GREGEX_H glib has gregex.h header and # supports g_regex_match_simple # # Copyright (c) 2006 Andreas Schneider # Copyright (c) 2006 Philippe Bernery # Copyright (c) 2007 Daniel Gollub # Copyright (c) 2007 Alban Browaeys # Copyright (c) 2008 Michael Bell # Copyright (c) 2008-2009 Bjoern Ricks # # Redistribution and use is allowed according to the terms of the New # BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # IF (GLIB2_LIBRARIES AND GLIB2_INCLUDE_DIRS ) # in cache already SET(GLIB2_FOUND TRUE) ELSE (GLIB2_LIBRARIES AND GLIB2_INCLUDE_DIRS ) INCLUDE(FindPkgConfig) ## Glib IF ( GLIB2_FIND_REQUIRED ) SET( _pkgconfig_REQUIRED "REQUIRED" ) ELSE ( GLIB2_FIND_REQUIRED ) SET( _pkgconfig_REQUIRED "" ) ENDIF ( GLIB2_FIND_REQUIRED ) IF ( GLIB2_MIN_VERSION ) PKG_SEARCH_MODULE( GLIB2 ${_pkgconfig_REQUIRED} glib-2.0>=${GLIB2_MIN_VERSION} ) ELSE ( GLIB2_MIN_VERSION ) PKG_SEARCH_MODULE( GLIB2 ${_pkgconfig_REQUIRED} glib-2.0 ) ENDIF ( GLIB2_MIN_VERSION ) IF ( PKG_CONFIG_FOUND ) IF ( GLIB2_FOUND ) SET ( GLIB2_CORE_FOUND TRUE ) ELSE ( GLIB2_FOUND ) SET ( GLIB2_CORE_FOUND FALSE ) ENDIF ( GLIB2_FOUND ) ENDIF ( PKG_CONFIG_FOUND ) # Look for glib2 include dir and libraries w/o pkgconfig IF ( NOT GLIB2_FOUND AND NOT PKG_CONFIG_FOUND ) FIND_PATH( _glibconfig_include_DIR NAMES glibconfig.h PATHS /opt/gnome/lib64 /opt/gnome/lib /opt/lib/ /opt/local/lib /sw/lib/ /usr/lib64 /usr/lib /usr/local/include ${CMAKE_LIBRARY_PATH} PATH_SUFFIXES glib-2.0/include ) FIND_PATH( _glib2_include_DIR NAMES glib.h PATHS /opt/gnome/include /opt/local/include /sw/include /usr/include /usr/local/include PATH_SUFFIXES glib-2.0 ) #MESSAGE(STATUS "Glib headers: ${_glib2_include_DIR}") FIND_LIBRARY( _glib2_link_DIR NAMES glib-2.0 glib PATHS /opt/gnome/lib /opt/local/lib /sw/lib /usr/lib /usr/local/lib ) IF ( _glib2_include_DIR AND _glib2_link_DIR ) SET ( _glib2_FOUND TRUE ) ENDIF ( _glib2_include_DIR AND _glib2_link_DIR ) IF ( _glib2_FOUND ) SET ( GLIB2_INCLUDE_DIRS ${_glib2_include_DIR} ${_glibconfig_include_DIR} ) SET ( GLIB2_LIBRARIES ${_glib2_link_DIR} ) SET ( GLIB2_CORE_FOUND TRUE ) ELSE ( _glib2_FOUND ) SET ( GLIB2_CORE_FOUND FALSE ) ENDIF ( _glib2_FOUND ) # Handle dependencies # libintl IF ( NOT LIBINTL_FOUND ) FIND_PATH(LIBINTL_INCLUDE_DIR NAMES libintl.h PATHS /opt/gnome/include /opt/local/include /sw/include /usr/include /usr/local/include ) FIND_LIBRARY(LIBINTL_LIBRARY NAMES intl PATHS /opt/gnome/lib /opt/local/lib /sw/lib /usr/local/lib /usr/lib ) IF (LIBINTL_LIBRARY AND LIBINTL_INCLUDE_DIR) SET (LIBINTL_FOUND TRUE) ENDIF (LIBINTL_LIBRARY AND LIBINTL_INCLUDE_DIR) ENDIF ( NOT LIBINTL_FOUND ) # libiconv IF ( NOT LIBICONV_FOUND ) FIND_PATH(LIBICONV_INCLUDE_DIR NAMES iconv.h PATHS /opt/gnome/include /opt/local/include /opt/local/include /sw/include /sw/include /usr/local/include /usr/include PATH_SUFFIXES glib-2.0 ) FIND_LIBRARY(LIBICONV_LIBRARY NAMES iconv PATHS /opt/gnome/lib /opt/local/lib /sw/lib /usr/lib /usr/local/lib ) IF (LIBICONV_LIBRARY AND LIBICONV_INCLUDE_DIR) SET (LIBICONV_FOUND TRUE) ENDIF (LIBICONV_LIBRARY AND LIBICONV_INCLUDE_DIR) ENDIF ( NOT LIBICONV_FOUND ) IF (LIBINTL_FOUND) SET (GLIB2_LIBRARIES ${GLIB2_LIBRARIES} ${LIBINTL_LIBRARY}) SET (GLIB2_INCLUDE_DIRS ${GLIB2_INCLUDE_DIRS} ${LIBINTL_INCLUDE_DIR}) ENDIF (LIBINTL_FOUND) IF (LIBICONV_FOUND) SET (GLIB2_LIBRARIES ${GLIB2_LIBRARIES} ${LIBICONV_LIBRARY}) SET (GLIB2_INCLUDE_DIRS ${GLIB2_INCLUDE_DIRS} ${LIBICONV_INCLUDE_DIR}) ENDIF (LIBICONV_FOUND) ENDIF ( NOT GLIB2_FOUND AND NOT PKG_CONFIG_FOUND ) ## IF (GLIB2_CORE_FOUND AND GLIB2_INCLUDE_DIRS AND GLIB2_LIBRARIES) SET (GLIB2_FOUND TRUE) ENDIF (GLIB2_CORE_FOUND AND GLIB2_INCLUDE_DIRS AND GLIB2_LIBRARIES) IF (GLIB2_FOUND) IF (NOT GLIB2_FIND_QUIETLY) MESSAGE (STATUS "Found GLib2: ${GLIB2_LIBRARIES} ${GLIB2_INCLUDE_DIRS}") ENDIF (NOT GLIB2_FIND_QUIETLY) ELSE (GLIB2_FOUND) IF (GLIB2_FIND_REQUIRED) MESSAGE (SEND_ERROR "Could not find GLib2") ENDIF (GLIB2_FIND_REQUIRED) ENDIF (GLIB2_FOUND) # show the GLIB2_INCLUDE_DIRS and GLIB2_LIBRARIES variables only in the advanced view MARK_AS_ADVANCED(GLIB2_INCLUDE_DIRS GLIB2_LIBRARIES) MARK_AS_ADVANCED(LIBICONV_INCLUDE_DIR LIBICONV_LIBRARY) MARK_AS_ADVANCED(LIBINTL_INCLUDE_DIR LIBINTL_LIBRARY) ENDIF (GLIB2_LIBRARIES AND GLIB2_INCLUDE_DIRS) IF ( WIN32 ) # include libiconv for win32 IF ( NOT LIBICONV_FOUND ) FIND_PATH(LIBICONV_INCLUDE_DIR iconv.h PATH_SUFFIXES glib-2.0) FIND_LIBRARY(LIBICONV_LIBRARY NAMES iconv) IF (LIBICONV_LIBRARY AND LIBICONV_INCLUDE_DIR) SET (LIBICONV_FOUND TRUE) ENDIF (LIBICONV_LIBRARY AND LIBICONV_INCLUDE_DIR) ENDIF ( NOT LIBICONV_FOUND ) IF (LIBICONV_FOUND) SET (GLIB2_LIBRARIES ${GLIB2_LIBRARIES} ${LIBICONV_LIBRARY}) SET (GLIB2_INCLUDE_DIRS ${GLIB2_INCLUDE_DIRS} ${LIBICONV_INCLUDE_DIR}) ENDIF (LIBICONV_FOUND) ENDIF ( WIN32 ) IF ( GLIB2_FOUND ) # Check if system has a newer version of glib # which supports g_regex_match_simple INCLUDE( CheckIncludeFiles ) SET( CMAKE_REQUIRED_INCLUDES ${GLIB2_INCLUDE_DIRS} ) CHECK_INCLUDE_FILES ( glib/gregex.h HAVE_GLIB_GREGEX_H ) # Reset CMAKE_REQUIRED_INCLUDES SET( CMAKE_REQUIRED_INCLUDES "" ) ENDIF( GLIB2_FOUND ) libsyncml-0.5.4/cmake/modules/FindGTHREAD2.cmake100644 1750 1750 4113 11211710410 21113 0ustar00bellmichbellmich# - Try to find GThread2 # Find GThread headers, libraries and the answer to all questions. # # GTHREAD2_FOUND True if GTHREAD2 got found # GTHREAD2_INCLUDE_DIRS Location of GTHREAD2 headers # GTHREAD2_LIBRARIES List of libraries to use GTHREAD2 # # Copyright (c) 2008 Bjoern Ricks # # Redistribution and use is allowed according to the terms of the New # BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # INCLUDE( FindPkgConfig ) IF ( GTHREAD2_FIND_REQUIRED ) SET( _pkgconfig_REQUIRED "REQUIRED" ) ELSE( GTHREAD2_FIND_REQUIRED ) SET( _pkgconfig_REQUIRED "" ) ENDIF ( GTHREAD2_FIND_REQUIRED ) IF ( GTHREAD2_MIN_VERSION ) PKG_SEARCH_MODULE( GTHREAD2 ${_pkgconfig_REQUIRED} gthread-2.0>=${GTHREAD2_MIN_VERSION} ) ELSE ( GTHREAD2_MIN_VERSION ) PKG_SEARCH_MODULE( GTHREAD2 ${_pkgconfig_REQUIRED} gthread-2.0 ) ENDIF ( GTHREAD2_MIN_VERSION ) IF( NOT GTHREAD2_FOUND AND NOT PKG_CONFIG_FOUND ) FIND_PATH( GTHREAD2_INCLUDE_DIRS gthread.h PATH_SUFFIXES glib-2.0/glib GLib.framework/Headers/glib ) IF ( APPLE ) FIND_LIBRARY( GTHREAD2_LIBRARIES glib ) ELSE ( APPLE ) FIND_LIBRARY( GTHREAD2_LIBRARIES gthread-2.0 ) ENDIF ( APPLE ) #MESSAGE( STATUS "Gthread headers: ${GTHREAD2_INCLUDE_DIRS}" ) #MESSAGE( STATUS "Gthread libs: ${GTHREAD2_LIBRARIES}" ) # Report results IF ( GTHREAD2_LIBRARIES AND GTHREAD2_INCLUDE_DIRS ) SET( GTHREAD2_FOUND 1 ) IF ( NOT GTHREAD2_FIND_QUIETLY ) MESSAGE( STATUS "Found GTHREAD2: ${GTHREAD2_LIBRARIES} ${GTHREAD2_INCLUDE_DIRS}" ) ENDIF ( NOT GTHREAD2_FIND_QUIETLY ) ELSE ( GTHREAD2_LIBRARIES AND GTHREAD2_INCLUDE_DIRS ) IF ( GTHREAD2_FIND_REQUIRED ) MESSAGE( SEND_ERROR "Could NOT find GTHREAD2" ) ELSE ( GTHREAD2_FIND_REQUIRED ) IF ( NOT GTHREAD2_FIND_QUIETLY ) MESSAGE( STATUS "Could NOT find GTHREAD2" ) ENDIF ( NOT GTHREAD2_FIND_QUIETLY ) ENDIF ( GTHREAD2_FIND_REQUIRED ) ENDIF ( GTHREAD2_LIBRARIES AND GTHREAD2_INCLUDE_DIRS ) ENDIF( NOT GTHREAD2_FOUND AND NOT PKG_CONFIG_FOUND ) MARK_AS_ADVANCED( GTHREAD2_LIBRARIES GTHREAD2_INCLUDE_DIRS ) libsyncml-0.5.4/cmake/modules/FindLibGCrypt.cmake100644 1750 1750 2572 11211710410 21621 0ustar00bellmichbellmich# Try and find libgcrypt. # As soon as libgcrypt has been found, the following variables will be defined: # # LIBGCRYPT_FOUND # GCRYPT_INCLUDE_DIR # GCRYPT_LIBRARY:FILEPATH # # Copyright (c) 2009 Juergen Leising # # Redistribution and use is allowed according to the terms of the New # BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # MESSAGE(STATUS "checking for libgcrypt...") FIND_PATH(GCRYPT_INCLUDE_DIR NAMES gcrypt.h PATHS /include /usr/include /usr/local/include /usr/share/include /opt/include DOC "Try and find the header file gcrypt.h") FIND_LIBRARY(GCRYPT_LIBRARY NAMES gcrypt PATHS /usr/lib /lib /usr/local/lib /usr/share/lib /opt/lib /opt/share/lib /var/lib DOC "Try and find libgcrypt") IF (GCRYPT_INCLUDE_DIR AND GCRYPT_LIBRARY) SET (LIBGCRYPT_FOUND 1) get_filename_component(GCRYPT_LIBRARY_DIRS ${GCRYPT_LIBRARY} PATH) MESSAGE(STATUS " Found ${GCRYPT_LIBRARY}") ELSE (GCRYPT_INCLUDE_DIR AND GCRYPT_LIBRARY) IF ( LibGCrypt_FIND_REQUIRED ) MESSAGE( FATAL_ERROR " Could NOT find libgcrypt. The ldap plugin needs this library." ) ELSE ( LibGCrypt_FIND_REQUIRED ) MESSAGE ( STATUS " Could NOT find libgcrypt.") ENDIF ( LibGCrypt_FIND_REQUIRED ) ENDIF (GCRYPT_INCLUDE_DIR AND GCRYPT_LIBRARY) libsyncml-0.5.4/cmake/modules/FindQt4.cmake100644 1750 1750 164205 11211710410 20474 0ustar00bellmichbellmich# - Find QT 4 # This module can be used to find Qt4. # The most important issue is that the Qt4 qmake is available via the system path. # This qmake is then used to detect basically everything else. # This module defines a number of key variables and macros. # First is QT_USE_FILE which is the path to a CMake file that can be included # to compile Qt 4 applications and libraries. By default, the QtCore and QtGui # libraries are loaded. This behavior can be changed by setting one or more # of the following variables to true before doing INCLUDE(${QT_USE_FILE}): # QT_DONT_USE_QTCORE # QT_DONT_USE_QTGUI # QT_USE_QT3SUPPORT # QT_USE_QTASSISTANT # QT_USE_QTDESIGNER # QT_USE_QTMOTIF # QT_USE_QTMAIN # QT_USE_QTNETWORK # QT_USE_QTNSPLUGIN # QT_USE_QTOPENGL # QT_USE_QTSQL # QT_USE_QTXML # QT_USE_QTSVG # QT_USE_QTTEST # QT_USE_QTUITOOLS # QT_USE_QTDBUS # QT_USE_QTSCRIPT # QT_USE_QTASSISTANTCLIENT # QT_USE_QTHELP # QT_USE_QTWEBKIT # QT_USE_QTXMLPATTERNS # QT_USE_PHONON # # The file pointed to by QT_USE_FILE will set up your compile environment # by adding include directories, preprocessor defines, and populate a # QT_LIBRARIES variable containing all the Qt libraries and their dependencies. # Add the QT_LIBRARIES variable to your TARGET_LINK_LIBRARIES. # # Typical usage could be something like: # FIND_PACKAGE(Qt4) # SET(QT_USE_QTXML 1) # INCLUDE(${QT_USE_FILE}) # ADD_EXECUTABLE(myexe main.cpp) # TARGET_LINK_LIBRARIES(myexe ${QT_LIBRARIES}) # # # There are also some files that need processing by some Qt tools such as moc # and uic. Listed below are macros that may be used to process those files. # # macro QT4_WRAP_CPP(outfiles inputfile ... OPTIONS ...) # create moc code from a list of files containing Qt class with # the Q_OBJECT declaration. Options may be given to moc, such as those found # when executing "moc -help" # # macro QT4_WRAP_UI(outfiles inputfile ... OPTIONS ...) # create code from a list of Qt designer ui files. # Options may be given to uic, such as those found # when executing "uic -help" # # macro QT4_ADD_RESOURCES(outfiles inputfile ... OPTIONS ...) # create code from a list of Qt resource files. # Options may be given to rcc, such as those found # when executing "rcc -help" # # macro QT4_GENERATE_MOC(inputfile outputfile ) # creates a rule to run moc on infile and create outfile. # Use this if for some reason QT4_WRAP_CPP() isn't appropriate, e.g. # because you need a custom filename for the moc file or something similar. # # macro QT4_AUTOMOC(sourcefile1 sourcefile2 ... ) # This macro is still experimental. # It can be used to have moc automatically handled. # So if you have the files foo.h and foo.cpp, and in foo.h a # a class uses the Q_OBJECT macro, moc has to run on it. If you don't # want to use QT4_WRAP_CPP() (which is reliable and mature), you can insert # #include "foo.moc" # in foo.cpp and then give foo.cpp as argument to QT4_AUTOMOC(). This will the # scan all listed files at cmake-time for such included moc files and if it finds # them cause a rule to be generated to run moc at build time on the # accompanying header file foo.h. # If a source file has the SKIP_AUTOMOC property set it will be ignored by this macro. # # macro QT4_ADD_DBUS_INTERFACE(outfiles interface basename) # create a the interface header and implementation files with the # given basename from the given interface xml file and add it to # the list of sources. # To disable generating a namespace header, set the source file property # NO_NAMESPACE to TRUE on the interface file. # # macro QT4_ADD_DBUS_INTERFACES(outfiles inputfile ... ) # create the interface header and implementation files # for all listed interface xml files # the name will be automatically determined from the name of the xml file # To disable generating namespace headers, set the source file property # NO_NAMESPACE to TRUE for these inputfiles. # # macro QT4_ADD_DBUS_ADAPTOR(outfiles xmlfile parentheader parentclassname [basename] [classname]) # create a dbus adaptor (header and implementation file) from the xml file # describing the interface, and add it to the list of sources. The adaptor # forwards the calls to a parent class, defined in parentheader and named # parentclassname. The name of the generated files will be # adaptor.{cpp,h} where basename defaults to the basename of the xml file. # If is provided, then it will be used as the classname of the # adaptor itself. # # macro QT4_GENERATE_DBUS_INTERFACE( header [interfacename] OPTIONS ...) # generate the xml interface file from the given header. # If the optional argument interfacename is omitted, the name of the # interface file is constructed from the basename of the header with # the suffix .xml appended. # Options may be given to qdbuscpp2xml, such as those found when executing "qdbuscpp2xml --help" # # QT_FOUND If false, don't try to use Qt. # QT4_FOUND If false, don't try to use Qt 4. # # QT_QTCORE_FOUND True if QtCore was found. # QT_QTGUI_FOUND True if QtGui was found. # QT_QT3SUPPORT_FOUND True if Qt3Support was found. # QT_QTASSISTANT_FOUND True if QtAssistant was found. # QT_QTDBUS_FOUND True if QtDBus was found. # QT_QTDESIGNER_FOUND True if QtDesigner was found. # QT_QTDESIGNERCOMPONENTS True if QtDesignerComponents was found. # QT_QTMOTIF_FOUND True if QtMotif was found. # QT_QTNETWORK_FOUND True if QtNetwork was found. # QT_QTNSPLUGIN_FOUND True if QtNsPlugin was found. # QT_QTOPENGL_FOUND True if QtOpenGL was found. # QT_QTSQL_FOUND True if QtSql was found. # QT_QTXML_FOUND True if QtXml was found. # QT_QTSVG_FOUND True if QtSvg was found. # QT_QTSCRIPT_FOUND True if QtScript was found. # QT_QTTEST_FOUND True if QtTest was found. # QT_QTUITOOLS_FOUND True if QtUiTools was found. # QT_QTASSISTANTCLIENT_FOUND True if QtAssistantClient was found. # QT_QTHELP_FOUND True if QtHelp was found. # QT_QTWEBKIT_FOUND True if QtWebKit was found. # QT_QTXMLPATTERNS_FOUND True if QtXmlPatterns was found. # QT_PHONON_FOUND True if phonon was found. # # # QT_DEFINITIONS Definitions to use when compiling code that uses Qt. # You do not need to use this if you include QT_USE_FILE. # The QT_USE_FILE will also define QT_DEBUG and QT_NO_DEBUG # to fit your current build type. Those are not contained # in QT_DEFINITIONS. # # QT_INCLUDES List of paths to all include directories of # Qt4 QT_INCLUDE_DIR and QT_QTCORE_INCLUDE_DIR are # always in this variable even if NOTFOUND, # all other INCLUDE_DIRS are # only added if they are found. # You do not need to use this if you include QT_USE_FILE. # # # Include directories for the Qt modules are listed here. # You do not need to use these variables if you include QT_USE_FILE. # # QT_INCLUDE_DIR Path to "include" of Qt4 # QT_QT_INCLUDE_DIR Path to "include/Qt" # QT_QT3SUPPORT_INCLUDE_DIR Path to "include/Qt3Support" # QT_QTASSISTANT_INCLUDE_DIR Path to "include/QtAssistant" # QT_QTCORE_INCLUDE_DIR Path to "include/QtCore" # QT_QTDESIGNER_INCLUDE_DIR Path to "include/QtDesigner" # QT_QTDESIGNERCOMPONENTS_INCLUDE_DIR Path to "include/QtDesigner" # QT_QTDBUS_INCLUDE_DIR Path to "include/QtDBus" # QT_QTGUI_INCLUDE_DIR Path to "include/QtGui" # QT_QTMOTIF_INCLUDE_DIR Path to "include/QtMotif" # QT_QTNETWORK_INCLUDE_DIR Path to "include/QtNetwork" # QT_QTNSPLUGIN_INCLUDE_DIR Path to "include/QtNsPlugin" # QT_QTOPENGL_INCLUDE_DIR Path to "include/QtOpenGL" # QT_QTSQL_INCLUDE_DIR Path to "include/QtSql" # QT_QTXML_INCLUDE_DIR Path to "include/QtXml" # QT_QTSVG_INCLUDE_DIR Path to "include/QtSvg" # QT_QTSCRIPT_INCLUDE_DIR Path to "include/QtScript" # QT_QTTEST_INCLUDE_DIR Path to "include/QtTest" # QT_QTASSISTANTCLIENT_INCLUDE_DIR Path to "include/QtAssistant" # QT_QTHELP_INCLUDE_DIR Path to "include/QtHelp" # QT_QTWEBKIT_INCLUDE_DIR Path to "include/QtWebKit" # QT_QTXMLPATTERNS_INCLUDE_DIR Path to "include/QtXmlPatterns" # QT_PHONON_INCLUDE_DIR Path to "include/phonon" # # QT_LIBRARY_DIR Path to "lib" of Qt4 # # QT_PLUGINS_DIR Path to "plugins" for Qt4 # # For every library of Qt, a QT_QTFOO_LIBRARY variable is defined, with the full path to the library. # # So there are the following variables: # The Qt3Support library: QT_QT3SUPPORT_LIBRARY # # The QtAssistant library: QT_QTASSISTANT_LIBRARY # # The QtCore library: QT_QTCORE_LIBRARY # # The QtDBus library: QT_QTDBUS_LIBRARY # # The QtDesigner library: QT_QTDESIGNER_LIBRARY # # The QtDesignerComponents library: QT_QTDESIGNERCOMPONENTS_LIBRARY # # The QtGui library: QT_QTGUI_LIBRARY # # The QtMotif library: QT_QTMOTIF_LIBRARY # # The QtNetwork library: QT_QTNETWORK_LIBRARY # # The QtNsPLugin library: QT_QTNSPLUGIN_LIBRARY # # The QtOpenGL library: QT_QTOPENGL_LIBRARY # # The QtSql library: QT_QTSQL_LIBRARY # # The QtXml library: QT_QTXML_LIBRARY # # The QtSvg library: QT_QTSVG_LIBRARY # # The QtScript library: QT_QTSCRIPT_LIBRARY # # The QtTest library: QT_QTTEST_LIBRARY # # The qtmain library for Windows QT_QTMAIN_LIBRARY # # The QtUiTools library: QT_QTUITOOLS_LIBRARY # # The QtAssistantClient library: QT_QTASSISTANTCLIENT_LIBRARY # # The QtHelp library: QT_QTHELP_LIBRARY # # The QtWebKit library: QT_QTWEBKIT_LIBRARY # # The QtXmlPatterns library: QT_QTXMLPATTERNS_LIBRARY # # The Phonon library: QT_PHONON_LIBRARY # # also defined, but NOT for general use are # QT_MOC_EXECUTABLE Where to find the moc tool. # QT_UIC_EXECUTABLE Where to find the uic tool. # QT_UIC3_EXECUTABLE Where to find the uic3 tool. # QT_RCC_EXECUTABLE Where to find the rcc tool # QT_DBUSCPP2XML_EXECUTABLE Where to find the qdbuscpp2xml tool. # QT_DBUSXML2CPP_EXECUTABLE Where to find the qdbusxml2cpp tool. # QT_LUPDATE_EXECUTABLE Where to find the lupdate tool. # QT_LRELEASE_EXECUTABLE Where to find the lrelease tool. # # QT_DOC_DIR Path to "doc" of Qt4 # QT_MKSPECS_DIR Path to "mkspecs" of Qt4 # # # These are around for backwards compatibility # they will be set # QT_WRAP_CPP Set true if QT_MOC_EXECUTABLE is found # QT_WRAP_UI Set true if QT_UIC_EXECUTABLE is found # # These variables do _NOT_ have any effect anymore (compared to FindQt.cmake) # QT_MT_REQUIRED Qt4 is now always multithreaded # # These variables are set to "" Because Qt structure changed # (They make no sense in Qt4) # QT_QT_LIBRARY Qt-Library is now split # Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved. # See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details. if (QT4_QMAKE_FOUND) # Check already done in this cmake run, nothing more to do else (QT4_QMAKE_FOUND) # check that QT_NO_DEBUG is defined for release configurations MACRO(QT_CHECK_FLAG_EXISTS FLAG VAR DOC) IF(NOT ${VAR} MATCHES "${FLAG}") SET(${VAR} "${${VAR}} ${FLAG}" CACHE STRING "Flags used by the compiler during ${DOC} builds." FORCE) ENDIF(NOT ${VAR} MATCHES "${FLAG}") ENDMACRO(QT_CHECK_FLAG_EXISTS FLAG VAR) QT_CHECK_FLAG_EXISTS(-DQT_NO_DEBUG CMAKE_CXX_FLAGS_RELWITHDEBINFO "Release with Debug Info") QT_CHECK_FLAG_EXISTS(-DQT_NO_DEBUG CMAKE_CXX_FLAGS_RELEASE "release") QT_CHECK_FLAG_EXISTS(-DQT_NO_DEBUG CMAKE_CXX_FLAGS_MINSIZEREL "release minsize") INCLUDE(CheckSymbolExists) INCLUDE(MacroAddFileDependencies) INCLUDE(MacroPushRequiredVars) SET(QT_USE_FILE ${CMAKE_ROOT}/Modules/UseQt4.cmake) SET( QT_DEFINITIONS "") IF (WIN32) SET(QT_DEFINITIONS -DQT_DLL) ENDIF(WIN32) SET(QT4_INSTALLED_VERSION_TOO_OLD FALSE) # macro for asking qmake to process pro files MACRO(QT_QUERY_QMAKE outvar invar) FILE(WRITE ${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmpQmake/tmp.pro "message(CMAKE_MESSAGE<$$${invar}>)") # Invoke qmake with the tmp.pro program to get the desired # information. Use the same variable for both stdout and stderr # to make sure we get the output on all platforms. EXECUTE_PROCESS(COMMAND ${QT_QMAKE_EXECUTABLE} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmpQmake OUTPUT_VARIABLE _qmake_query_output RESULT_VARIABLE _qmake_result ERROR_VARIABLE _qmake_query_output ) FILE(REMOVE_RECURSE "${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmpQmake") IF(_qmake_result) MESSAGE(WARNING " querying qmake for ${invar}. qmake reported:\n${_qmake_query_output}") ELSE(_qmake_result) STRING(REGEX REPLACE ".*CMAKE_MESSAGE<([^>]*).*" "\\1" ${outvar} "${_qmake_query_output}") ENDIF(_qmake_result) ENDMACRO(QT_QUERY_QMAKE) GET_FILENAME_COMPONENT(qt_install_version "[HKEY_CURRENT_USER\\Software\\trolltech\\Versions;DefaultQtVersion]" NAME) # check for qmake FIND_PROGRAM(QT_QMAKE_EXECUTABLE NAMES qmake qmake4 qmake-qt4 PATHS "[HKEY_CURRENT_USER\\Software\\Trolltech\\Qt3Versions\\4.0.0;InstallDir]/bin" "[HKEY_CURRENT_USER\\Software\\Trolltech\\Versions\\4.0.0;InstallDir]/bin" "[HKEY_CURRENT_USER\\Software\\Trolltech\\Versions\\${qt_install_version};InstallDir]/bin" $ENV{QTDIR}/bin ) IF (QT_QMAKE_EXECUTABLE) SET(QT4_QMAKE_FOUND FALSE) EXEC_PROGRAM(${QT_QMAKE_EXECUTABLE} ARGS "-query QT_VERSION" OUTPUT_VARIABLE QTVERSION) # check for qt3 qmake and then try and find qmake4 or qmake-qt4 in the path IF("${QTVERSION}" MATCHES "Unknown") SET(QT_QMAKE_EXECUTABLE NOTFOUND CACHE FILEPATH "" FORCE) FIND_PROGRAM(QT_QMAKE_EXECUTABLE NAMES qmake4 qmake-qt4 PATHS "[HKEY_CURRENT_USER\\Software\\Trolltech\\Qt3Versions\\4.0.0;InstallDir]/bin" "[HKEY_CURRENT_USER\\Software\\Trolltech\\Versions\\4.0.0;InstallDir]/bin" $ENV{QTDIR}/bin ) IF(QT_QMAKE_EXECUTABLE) EXEC_PROGRAM(${QT_QMAKE_EXECUTABLE} ARGS "-query QT_VERSION" OUTPUT_VARIABLE QTVERSION) ENDIF(QT_QMAKE_EXECUTABLE) ENDIF("${QTVERSION}" MATCHES "Unknown") # check that we found the Qt4 qmake, Qt3 qmake output won't match here STRING(REGEX MATCH "^[0-9]+\\.[0-9]+\\.[0-9]+" qt_version_tmp "${QTVERSION}") IF (qt_version_tmp) # we need at least version 4.0.0 IF (NOT QT_MIN_VERSION) SET(QT_MIN_VERSION "4.0.0") ENDIF (NOT QT_MIN_VERSION) #now parse the parts of the user given version string into variables STRING(REGEX MATCH "^[0-9]+\\.[0-9]+\\.[0-9]+" req_qt_major_vers "${QT_MIN_VERSION}") IF (NOT req_qt_major_vers) MESSAGE( FATAL_ERROR "Invalid Qt version string given: \"${QT_MIN_VERSION}\", expected e.g. \"4.0.1\"") ENDIF (NOT req_qt_major_vers) # now parse the parts of the user given version string into variables STRING(REGEX REPLACE "^([0-9]+)\\.[0-9]+\\.[0-9]+" "\\1" req_qt_major_vers "${QT_MIN_VERSION}") STRING(REGEX REPLACE "^[0-9]+\\.([0-9])+\\.[0-9]+" "\\1" req_qt_minor_vers "${QT_MIN_VERSION}") STRING(REGEX REPLACE "^[0-9]+\\.[0-9]+\\.([0-9]+)" "\\1" req_qt_patch_vers "${QT_MIN_VERSION}") IF (NOT req_qt_major_vers EQUAL 4) MESSAGE( FATAL_ERROR "Invalid Qt version string given: \"${QT_MIN_VERSION}\", major version 4 is required, e.g. \"4.0.1\"") ENDIF (NOT req_qt_major_vers EQUAL 4) # and now the version string given by qmake STRING(REGEX REPLACE "^([0-9]+)\\.[0-9]+\\.[0-9]+.*" "\\1" found_qt_major_vers "${QTVERSION}") STRING(REGEX REPLACE "^[0-9]+\\.([0-9])+\\.[0-9]+.*" "\\1" found_qt_minor_vers "${QTVERSION}") STRING(REGEX REPLACE "^[0-9]+\\.[0-9]+\\.([0-9]+).*" "\\1" found_qt_patch_vers "${QTVERSION}") # compute an overall version number which can be compared at once MATH(EXPR req_vers "${req_qt_major_vers}*10000 + ${req_qt_minor_vers}*100 + ${req_qt_patch_vers}") MATH(EXPR found_vers "${found_qt_major_vers}*10000 + ${found_qt_minor_vers}*100 + ${found_qt_patch_vers}") IF (found_vers LESS req_vers) SET(QT4_QMAKE_FOUND FALSE) SET(QT4_INSTALLED_VERSION_TOO_OLD TRUE) ELSE (found_vers LESS req_vers) SET(QT4_QMAKE_FOUND TRUE) ENDIF (found_vers LESS req_vers) ENDIF (qt_version_tmp) ENDIF (QT_QMAKE_EXECUTABLE) IF (QT4_QMAKE_FOUND) if (WIN32) # get qt install dir get_filename_component(_DIR ${QT_QMAKE_EXECUTABLE} PATH ) get_filename_component(QT_INSTALL_DIR ${_DIR} PATH ) endif (WIN32) # ask qmake for the library dir # Set QT_LIBRARY_DIR IF (NOT QT_LIBRARY_DIR) EXEC_PROGRAM( ${QT_QMAKE_EXECUTABLE} ARGS "-query QT_INSTALL_LIBS" OUTPUT_VARIABLE QT_LIBRARY_DIR_TMP ) # make sure we have / and not \ as qmake gives on windows FILE(TO_CMAKE_PATH "${QT_LIBRARY_DIR_TMP}" QT_LIBRARY_DIR_TMP) IF(EXISTS "${QT_LIBRARY_DIR_TMP}") SET(QT_LIBRARY_DIR ${QT_LIBRARY_DIR_TMP} CACHE PATH "Qt library dir") ELSE(EXISTS "${QT_LIBRARY_DIR_TMP}") MESSAGE("Warning: QT_QMAKE_EXECUTABLE reported QT_INSTALL_LIBS as ${QT_LIBRARY_DIR_TMP}") MESSAGE("Warning: ${QT_LIBRARY_DIR_TMP} does NOT exist, Qt must NOT be installed correctly.") ENDIF(EXISTS "${QT_LIBRARY_DIR_TMP}") ENDIF(NOT QT_LIBRARY_DIR) IF (APPLE) IF (EXISTS ${QT_LIBRARY_DIR}/QtCore.framework) SET(QT_USE_FRAMEWORKS ON CACHE BOOL "Set to ON if Qt build uses frameworks.") ELSE (EXISTS ${QT_LIBRARY_DIR}/QtCore.framework) SET(QT_USE_FRAMEWORKS OFF CACHE BOOL "Set to ON if Qt build uses frameworks.") ENDIF (EXISTS ${QT_LIBRARY_DIR}/QtCore.framework) MARK_AS_ADVANCED(QT_USE_FRAMEWORKS) ENDIF (APPLE) # ask qmake for the binary dir IF (QT_LIBRARY_DIR AND NOT QT_BINARY_DIR) EXEC_PROGRAM(${QT_QMAKE_EXECUTABLE} ARGS "-query QT_INSTALL_BINS" OUTPUT_VARIABLE qt_bins ) # make sure we have / and not \ as qmake gives on windows FILE(TO_CMAKE_PATH "${qt_bins}" qt_bins) SET(QT_BINARY_DIR ${qt_bins} CACHE INTERNAL "") ENDIF (QT_LIBRARY_DIR AND NOT QT_BINARY_DIR) # ask qmake for the include dir IF (QT_LIBRARY_DIR AND NOT QT_HEADERS_DIR) EXEC_PROGRAM( ${QT_QMAKE_EXECUTABLE} ARGS "-query QT_INSTALL_HEADERS" OUTPUT_VARIABLE qt_headers ) # make sure we have / and not \ as qmake gives on windows FILE(TO_CMAKE_PATH "${qt_headers}" qt_headers) SET(QT_HEADERS_DIR ${qt_headers} CACHE INTERNAL "") ENDIF(QT_LIBRARY_DIR AND NOT QT_HEADERS_DIR) # ask qmake for the documentation directory IF (QT_LIBRARY_DIR AND NOT QT_DOC_DIR) EXEC_PROGRAM( ${QT_QMAKE_EXECUTABLE} ARGS "-query QT_INSTALL_DOCS" OUTPUT_VARIABLE qt_doc_dir ) # make sure we have / and not \ as qmake gives on windows FILE(TO_CMAKE_PATH "${qt_doc_dir}" qt_doc_dir) SET(QT_DOC_DIR ${qt_doc_dir} CACHE PATH "The location of the Qt docs") ENDIF (QT_LIBRARY_DIR AND NOT QT_DOC_DIR) # ask qmake for the mkspecs directory IF (QT_LIBRARY_DIR AND NOT QT_MKSPECS_DIR) EXEC_PROGRAM( ${QT_QMAKE_EXECUTABLE} ARGS "-query QMAKE_MKSPECS" OUTPUT_VARIABLE qt_mkspecs_dirs ) # do not replace : on windows as it might be a drive letter # and windows should already use ; as a separator IF(UNIX) STRING(REPLACE ":" ";" qt_mkspecs_dirs "${qt_mkspecs_dirs}") ENDIF(UNIX) FIND_PATH(QT_MKSPECS_DIR qconfig.pri PATHS ${qt_mkspecs_dirs} DOC "The location of the Qt mkspecs containing qconfig.pri" NO_DEFAULT_PATH ) ENDIF (QT_LIBRARY_DIR AND NOT QT_MKSPECS_DIR) # ask qmake for the plugins directory IF (QT_LIBRARY_DIR AND NOT QT_PLUGINS_DIR) EXEC_PROGRAM( ${QT_QMAKE_EXECUTABLE} ARGS "-query QT_INSTALL_PLUGINS" OUTPUT_VARIABLE qt_plugins_dir ) # make sure we have / and not \ as qmake gives on windows FILE(TO_CMAKE_PATH "${qt_plugins_dir}" qt_plugins_dir) SET(QT_PLUGINS_DIR ${qt_plugins_dir} CACHE PATH "The location of the Qt plugins") ENDIF (QT_LIBRARY_DIR AND NOT QT_PLUGINS_DIR) ######################################## # # Setting the INCLUDE-Variables # ######################################## FIND_PATH(QT_QTCORE_INCLUDE_DIR QtGlobal ${QT_HEADERS_DIR}/QtCore ${QT_LIBRARY_DIR}/QtCore.framework/Headers NO_DEFAULT_PATH ) # Set QT_INCLUDE_DIR by removine "/QtCore" in the string ${QT_QTCORE_INCLUDE_DIR} IF( QT_QTCORE_INCLUDE_DIR AND NOT QT_INCLUDE_DIR) IF (QT_USE_FRAMEWORKS) SET(QT_INCLUDE_DIR ${QT_HEADERS_DIR}) ELSE (QT_USE_FRAMEWORKS) STRING( REGEX REPLACE "/QtCore$" "" qt4_include_dir ${QT_QTCORE_INCLUDE_DIR}) SET( QT_INCLUDE_DIR ${qt4_include_dir} CACHE PATH "") ENDIF (QT_USE_FRAMEWORKS) ENDIF( QT_QTCORE_INCLUDE_DIR AND NOT QT_INCLUDE_DIR) IF( NOT QT_INCLUDE_DIR) IF( NOT Qt4_FIND_QUIETLY AND Qt4_FIND_REQUIRED) MESSAGE( FATAL_ERROR "Could NOT find QtGlobal header") ENDIF( NOT Qt4_FIND_QUIETLY AND Qt4_FIND_REQUIRED) ENDIF( NOT QT_INCLUDE_DIR) ############################################# # # Find out what window system we're using # ############################################# # Save required includes and required_flags variables macro_push_required_vars() # Add QT_INCLUDE_DIR to CMAKE_REQUIRED_INCLUDES SET(CMAKE_REQUIRED_INCLUDES "${CMAKE_REQUIRED_INCLUDES};${QT_INCLUDE_DIR}") # On Mac OS X when Qt has framework support, also add the framework path IF( QT_USE_FRAMEWORKS ) SET(CMAKE_REQUIRED_FLAGS "-F${QT_LIBRARY_DIR} ") ENDIF( QT_USE_FRAMEWORKS ) # Check for Window system symbols (note: only one should end up being set) CHECK_SYMBOL_EXISTS(Q_WS_X11 "QtCore/qglobal.h" Q_WS_X11) CHECK_SYMBOL_EXISTS(Q_WS_WIN "QtCore/qglobal.h" Q_WS_WIN) CHECK_SYMBOL_EXISTS(Q_WS_QWS "QtCore/qglobal.h" Q_WS_QWS) CHECK_SYMBOL_EXISTS(Q_WS_MAC "QtCore/qglobal.h" Q_WS_MAC) IF (QT_QTCOPY_REQUIRED) CHECK_SYMBOL_EXISTS(QT_IS_QTCOPY "QtCore/qglobal.h" QT_KDE_QT_COPY) IF (NOT QT_IS_QTCOPY) MESSAGE(FATAL_ERROR "qt-copy is required, but hasn't been found") ENDIF (NOT QT_IS_QTCOPY) ENDIF (QT_QTCOPY_REQUIRED) # Restore CMAKE_REQUIRED_INCLUDES+CMAKE_REQUIRED_FLAGS variables macro_pop_required_vars() # ############################################# IF (QT_USE_FRAMEWORKS) SET(QT_DEFINITIONS ${QT_DEFINITIONS} -F${QT_LIBRARY_DIR} -L${QT_LIBRARY_DIR} ) ENDIF (QT_USE_FRAMEWORKS) # Set QT_QT3SUPPORT_INCLUDE_DIR FIND_PATH(QT_QT3SUPPORT_INCLUDE_DIR Qt3Support PATHS ${QT_INCLUDE_DIR}/Qt3Support ${QT_LIBRARY_DIR}/Qt3Support.framework/Headers NO_DEFAULT_PATH ) # Set QT_QT_INCLUDE_DIR FIND_PATH(QT_QT_INCLUDE_DIR qglobal.h PATHS ${QT_INCLUDE_DIR}/Qt ${QT_LIBRARY_DIR}/QtCore.framework/Headers NO_DEFAULT_PATH ) # Set QT_QTGUI_INCLUDE_DIR FIND_PATH(QT_QTGUI_INCLUDE_DIR QtGui PATHS ${QT_INCLUDE_DIR}/QtGui ${QT_LIBRARY_DIR}/QtGui.framework/Headers NO_DEFAULT_PATH ) # Set QT_QTSVG_INCLUDE_DIR FIND_PATH(QT_QTSVG_INCLUDE_DIR QtSvg PATHS ${QT_INCLUDE_DIR}/QtSvg ${QT_LIBRARY_DIR}/QtSvg.framework/Headers NO_DEFAULT_PATH ) # Set QT_QTSCRIPT_INCLUDE_DIR FIND_PATH(QT_QTSCRIPT_INCLUDE_DIR QtScript PATHS ${QT_INCLUDE_DIR}/QtScript ${QT_LIBRARY_DIR}/QtScript.framework/Headers NO_DEFAULT_PATH ) # Set QT_QTTEST_INCLUDE_DIR FIND_PATH(QT_QTTEST_INCLUDE_DIR QtTest PATHS ${QT_INCLUDE_DIR}/QtTest ${QT_LIBRARY_DIR}/QtTest.framework/Headers NO_DEFAULT_PATH ) # Set QT_QTUITOOLS_INCLUDE_DIR FIND_PATH(QT_QTUITOOLS_INCLUDE_DIR QtUiTools PATHS ${QT_INCLUDE_DIR}/QtUiTools ${QT_LIBRARY_DIR}/QtUiTools.framework/Headers NO_DEFAULT_PATH ) # Set QT_QTMOTIF_INCLUDE_DIR IF(Q_WS_X11) FIND_PATH(QT_QTMOTIF_INCLUDE_DIR QtMotif PATHS ${QT_INCLUDE_DIR}/QtMotif NO_DEFAULT_PATH ) ENDIF(Q_WS_X11) # Set QT_QTNETWORK_INCLUDE_DIR FIND_PATH(QT_QTNETWORK_INCLUDE_DIR QtNetwork PATHS ${QT_INCLUDE_DIR}/QtNetwork ${QT_LIBRARY_DIR}/QtNetwork.framework/Headers NO_DEFAULT_PATH ) # Set QT_QTNSPLUGIN_INCLUDE_DIR FIND_PATH(QT_QTNSPLUGIN_INCLUDE_DIR QtNsPlugin PATHS ${QT_INCLUDE_DIR}/QtNsPlugin ${QT_LIBRARY_DIR}/QtNsPlugin.framework/Headers NO_DEFAULT_PATH ) # Set QT_QTOPENGL_INCLUDE_DIR FIND_PATH(QT_QTOPENGL_INCLUDE_DIR QtOpenGL PATHS ${QT_INCLUDE_DIR}/QtOpenGL ${QT_LIBRARY_DIR}/QtOpenGL.framework/Headers NO_DEFAULT_PATH ) # Set QT_QTSQL_INCLUDE_DIR FIND_PATH(QT_QTSQL_INCLUDE_DIR QtSql PATHS ${QT_INCLUDE_DIR}/QtSql ${QT_LIBRARY_DIR}/QtSql.framework/Headers NO_DEFAULT_PATH ) # Set QT_QTXML_INCLUDE_DIR FIND_PATH(QT_QTXML_INCLUDE_DIR QtXml PATHS ${QT_INCLUDE_DIR}/QtXml ${QT_LIBRARY_DIR}/QtXml.framework/Headers NO_DEFAULT_PATH ) # Set QT_QTASSISTANT_INCLUDE_DIR FIND_PATH(QT_QTASSISTANT_INCLUDE_DIR QtAssistant PATHS ${QT_INCLUDE_DIR}/QtAssistant ${QT_HEADERS_DIR}/QtAssistant ${QT_LIBRARY_DIR}/QtAssistant.framework/Headers NO_DEFAULT_PATH ) # Set QT_QTDESIGNER_INCLUDE_DIR FIND_PATH(QT_QTDESIGNER_INCLUDE_DIR QDesignerComponents PATHS ${QT_INCLUDE_DIR}/QtDesigner ${QT_HEADERS_DIR}/QtDesigner ${QT_LIBRARY_DIR}/QtDesigner.framework/Headers NO_DEFAULT_PATH ) # Set QT_QTDESIGNERCOMPONENTS_INCLUDE_DIR FIND_PATH(QT_QTDESIGNERCOMPONENTS_INCLUDE_DIR QDesignerComponents PATHS ${QT_INCLUDE_DIR}/QtDesigner ${QT_HEADERS_DIR}/QtDesigner NO_DEFAULT_PATH ) # Set QT_QTDBUS_INCLUDE_DIR FIND_PATH(QT_QTDBUS_INCLUDE_DIR QtDBus PATHS ${QT_INCLUDE_DIR}/QtDBus ${QT_HEADERS_DIR}/QtDBus ${QT_LIBRARY_DIR}/QtDBus.framework/Headers NO_DEFAULT_PATH ) # Set QT_QTASSISTANTCLIENT_INCLUDE_DIR FIND_PATH(QT_QTASSISTANTCLIENT_INCLUDE_DIR QAssistantClient PATHS ${QT_INCLUDE_DIR}/QtAssistant ${QT_HEADERS_DIR}/QtAssistant NO_DEFAULT_PATH ) # Set QT_QTHELP_INCLUDE_DIR FIND_PATH(QT_QTHELP_INCLUDE_DIR QtHelp PATHS ${QT_INCLUDE_DIR}/QtHelp ${QT_HEADERS_DIR}/QtHelp NO_DEFAULT_PATH ) # Set QT_QTWEBKIT_INCLUDE_DIR FIND_PATH(QT_QTWEBKIT_INCLUDE_DIR QtWebKit PATHS ${QT_INCLUDE_DIR}/QtWebKit ${QT_HEADERS_DIR}/QtWebKit NO_DEFAULT_PATH ) # Set QT_QTXMLPATTERNS_INCLUDE_DIR FIND_PATH(QT_QTXMLPATTERNS_INCLUDE_DIR QtXmlPatterns PATHS ${QT_INCLUDE_DIR}/QtXmlPatterns ${QT_HEADERS_DIR}/QtXmlPatterns NO_DEFAULT_PATH ) # Set QT_PHONON_INCLUDE_DIR FIND_PATH(QT_PHONON_INCLUDE_DIR phonon PATHS ${QT_INCLUDE_DIR}/phonon NO_DEFAULT_PATH ) # Make variables changeble to the advanced user MARK_AS_ADVANCED( QT_LIBRARY_DIR QT_INCLUDE_DIR QT_QT_INCLUDE_DIR QT_DOC_DIR QT_MKSPECS_DIR QT_PLUGINS_DIR) # Set QT_INCLUDES SET( QT_INCLUDES ${QT_QT_INCLUDE_DIR} ${QT_MKSPECS_DIR}/default ${QT_INCLUDE_DIR} ) ######################################## # # Setting the LIBRARY-Variables # ######################################## IF (QT_USE_FRAMEWORKS) # If FIND_LIBRARY found libraries in Apple frameworks, we would NOT have # to jump through these hoops. IF(EXISTS ${QT_LIBRARY_DIR}/QtCore.framework) SET(QT_QTCORE_FOUND TRUE) SET(QT_QTCORE_LIBRARY "-F${QT_LIBRARY_DIR} -framework QtCore" CACHE STRING "The QtCore library.") ELSE(EXISTS ${QT_LIBRARY_DIR}/QtCore.framework) SET(QT_QTCORE_FOUND FALSE) ENDIF(EXISTS ${QT_LIBRARY_DIR}/QtCore.framework) IF(EXISTS ${QT_LIBRARY_DIR}/QtGui.framework) SET(QT_QTGUI_FOUND TRUE) SET(QT_QTGUI_LIBRARY "-F${QT_LIBRARY_DIR} -framework QtGui" CACHE STRING "The QtGui library.") ELSE(EXISTS ${QT_LIBRARY_DIR}/QtGui.framework) SET(QT_QTGUI_FOUND FALSE) ENDIF(EXISTS ${QT_LIBRARY_DIR}/QtGui.framework) IF(EXISTS ${QT_LIBRARY_DIR}/Qt3Support.framework) SET(QT_QT3SUPPORT_FOUND TRUE) SET(QT_QT3SUPPORT_LIBRARY "-F${QT_LIBRARY_DIR} -framework Qt3Support" CACHE STRING "The Qt3Support library.") ELSE(EXISTS ${QT_LIBRARY_DIR}/Qt3Support.framework) SET(QT_QT3SUPPORT_FOUND FALSE) ENDIF(EXISTS ${QT_LIBRARY_DIR}/Qt3Support.framework) IF(EXISTS ${QT_LIBRARY_DIR}/QtNetwork.framework) SET(QT_QTNETWORK_FOUND TRUE) SET(QT_QTNETWORK_LIBRARY "-F${QT_LIBRARY_DIR} -framework QtNetwork" CACHE STRING "The QtNetwork library.") ELSE(EXISTS ${QT_LIBRARY_DIR}/QtNetwork.framework) SET(QT_QTNETWORK_FOUND FALSE) ENDIF(EXISTS ${QT_LIBRARY_DIR}/QtNetwork.framework) IF(EXISTS ${QT_LIBRARY_DIR}/QtOpenGL.framework) SET(QT_QTOPENGL_FOUND TRUE) SET(QT_QTOPENGL_LIBRARY "-F${QT_LIBRARY_DIR} -framework QtOpenGL" CACHE STRING "The QtOpenGL library.") ELSE(EXISTS ${QT_LIBRARY_DIR}/QtOpenGL.framework) SET(QT_QTOPENGL_FOUND FALSE) ENDIF(EXISTS ${QT_LIBRARY_DIR}/QtOpenGL.framework) IF(EXISTS ${QT_LIBRARY_DIR}/QtSql.framework) SET(QT_QTSQL_FOUND TRUE) SET(QT_QTSQL_LIBRARY "-F${QT_LIBRARY_DIR} -framework QtSql" CACHE STRING "The QtSql library.") ELSE(EXISTS ${QT_LIBRARY_DIR}/QtSql.framework) SET(QT_QTSQL_FOUND FALSE) ENDIF(EXISTS ${QT_LIBRARY_DIR}/QtSql.framework) IF(EXISTS ${QT_LIBRARY_DIR}/QtXml.framework) SET(QT_QTXML_FOUND TRUE) SET(QT_QTXML_LIBRARY "-F${QT_LIBRARY_DIR} -framework QtXml" CACHE STRING "The QtXml library.") ELSE(EXISTS ${QT_LIBRARY_DIR}/QtXml.framework) SET(QT_QTXML_FOUND FALSE) ENDIF(EXISTS ${QT_LIBRARY_DIR}/QtXml.framework) IF(EXISTS ${QT_LIBRARY_DIR}/QtSvg.framework) SET(QT_QTSVG_FOUND TRUE) SET(QT_QTSVG_LIBRARY "-F${QT_LIBRARY_DIR} -framework QtSvg" CACHE STRING "The QtSvg library.") ELSE(EXISTS ${QT_LIBRARY_DIR}/QtSvg.framework) SET(QT_QTSVG_FOUND FALSE) ENDIF(EXISTS ${QT_LIBRARY_DIR}/QtSvg.framework) IF(EXISTS ${QT_LIBRARY_DIR}/QtDBus.framework) SET(QT_QTDBUS_FOUND TRUE) SET(QT_QTDBUS_LIBRARY "-F${QT_LIBRARY_DIR} -framework QtDBus" CACHE STRING "The QtDBus library.") ELSE(EXISTS ${QT_LIBRARY_DIR}/QtDBus.framework) SET(QT_QTDBUS_FOUND FALSE) ENDIF(EXISTS ${QT_LIBRARY_DIR}/QtDBus.framework) IF(EXISTS ${QT_LIBRARY_DIR}/QtTest.framework) SET(QT_QTTEST_FOUND TRUE) SET(QT_QTTEST_LIBRARY "-F${QT_LIBRARY_DIR} -framework QtTest" CACHE STRING "The QtTest library.") ELSE(EXISTS ${QT_LIBRARY_DIR}/QtTest.framework) SET(QT_QTTEST_FOUND FALSE) ENDIF(EXISTS ${QT_LIBRARY_DIR}/QtTest.framework) IF(EXISTS ${QT_LIBRARY_DIR}/QtAssistantClient.framework) SET(QT_QTASSISTANTCLIENT_FOUND TRUE) SET(QT_QTASSISTANTCLIENT_LIBRARY "-F${QT_LIBRARY_DIR} -framework QtAssistantClient" CACHE STRING "The QtAssistantClient library.") ELSE(EXISTS ${QT_LIBRARY_DIR}/QtAssistantClient.framework) SET(QT_QTASSISTANTCLIENT_FOUND FALSE) ENDIF(EXISTS ${QT_LIBRARY_DIR}/QtAssistantClient.framework) IF(EXISTS ${QT_LIBRARY_DIR}/QtWebKit.framework) SET(QT_QTWEBKIT_FOUND TRUE) SET(QT_QTWEBKIT_LIBRARY "-F${QT_LIBRARY_DIR} -framework QtWebKit" CACHE STRING "The QtWebKit library.") ELSE(EXISTS ${QT_LIBRARY_DIR}/QtWebKit.framework) SET(QT_QTWEBKIT_FOUND FALSE) ENDIF(EXISTS ${QT_LIBRARY_DIR}/QtWebKit.framework) IF(EXISTS ${QT_LIBRARY_DIR}/QtXmlPatterns.framework) SET(QT_QTXMLPATTERNS_FOUND TRUE) SET(QT_QTXMLPATTERNS_LIBRARY "-F${QT_LIBRARY_DIR} -framework QtXmlPatterns" CACHE STRING "The QtXmlPatterns library.") ELSE(EXISTS ${QT_LIBRARY_DIR}/QtXmlPatterns.framework) SET(QT_QTXMLPATTERNS_FOUND FALSE) ENDIF(EXISTS ${QT_LIBRARY_DIR}/QtXmlPatterns.framework) # WTF? why don't we have frameworks? :P # Set QT_QTUITOOLS_LIBRARY FIND_LIBRARY(QT_QTUITOOLS_LIBRARY NAMES QtUiTools QtUiTools4 PATHS ${QT_LIBRARY_DIR} ) # Set QT_QTSCRIPT_LIBRARY FIND_LIBRARY(QT_QTSCRIPT_LIBRARY NAMES QtScript QtScript4 PATHS ${QT_LIBRARY_DIR} ) ELSE (QT_USE_FRAMEWORKS) # Set QT_QTCORE_LIBRARY by searching for a lib with "QtCore." as part of the filename FIND_LIBRARY(QT_QTCORE_LIBRARY NAMES QtCore QtCore4 QtCored4 QtCore_debug PATHS ${QT_LIBRARY_DIR} NO_DEFAULT_PATH ) # Set QT_QT3SUPPORT_LIBRARY FIND_LIBRARY(QT_QT3SUPPORT_LIBRARY NAMES Qt3Support Qt3Support_debug Qt3Support4 Qt3Supportd4 PATHS ${QT_LIBRARY_DIR} NO_DEFAULT_PATH) # Set QT_QTGUI_LIBRARY FIND_LIBRARY(QT_QTGUI_LIBRARY NAMES QtGui QtGui_debug QtGui_debug QtGui4 QtGuid4 PATHS ${QT_LIBRARY_DIR} NO_DEFAULT_PATH) # Set QT_QTMOTIF_LIBRARY IF(Q_WS_X11) FIND_LIBRARY(QT_QTMOTIF_LIBRARY NAMES QtMotif QtMotif_debug PATHS ${QT_LIBRARY_DIR} NO_DEFAULT_PATH) ENDIF(Q_WS_X11) # Set QT_QTNETWORK_LIBRARY FIND_LIBRARY(QT_QTNETWORK_LIBRARY NAMES QtNetwork QtNetwork_debug QtNetwork4 QtNetworkd4 PATHS ${QT_LIBRARY_DIR} NO_DEFAULT_PATH) # Set QT_QTNSPLUGIN_LIBRARY FIND_LIBRARY(QT_QTNSPLUGIN_LIBRARY NAMES QtNsPlugin QtNsPlugin_debug PATHS ${QT_LIBRARY_DIR} NO_DEFAULT_PATH) # Set QT_QTOPENGL_LIBRARY FIND_LIBRARY(QT_QTOPENGL_LIBRARY NAMES QtOpenGL QtOpenGL_debug QtOpenGL4 QtOpenGLd4 PATHS ${QT_LIBRARY_DIR} NO_DEFAULT_PATH) # Set QT_QTSQL_LIBRARY FIND_LIBRARY(QT_QTSQL_LIBRARY NAMES QtSql QtSql_debug QtSql4 QtSqld4 PATHS ${QT_LIBRARY_DIR} NO_DEFAULT_PATH) # Set QT_QTXML_LIBRARY FIND_LIBRARY(QT_QTXML_LIBRARY NAMES QtXml QtXml_debug QtXml4 QtXmld4 PATHS ${QT_LIBRARY_DIR} NO_DEFAULT_PATH) # Set QT_QTSVG_LIBRARY FIND_LIBRARY(QT_QTSVG_LIBRARY NAMES QtSvg QtSvg_debug QtSvg4 QtSvgd4 PATHS ${QT_LIBRARY_DIR} NO_DEFAULT_PATH) # Set QT_QTSCRIPT_LIBRARY FIND_LIBRARY(QT_QTSCRIPT_LIBRARY NAMES QtScript QtScript_debug QtScript4 QtScriptd4 PATHS ${QT_LIBRARY_DIR} NO_DEFAULT_PATH) # Set QT_QTUITOOLS_LIBRARY FIND_LIBRARY(QT_QTUITOOLS_LIBRARY NAMES QtUiTools QtUiTools_debug QtUiTools4 QtUiToolsd4 PATHS ${QT_LIBRARY_DIR} NO_DEFAULT_PATH) # Set QT_QTTEST_LIBRARY FIND_LIBRARY(QT_QTTEST_LIBRARY NAMES QtTest QtTest_debug QtTest4 QtTestd4 PATHS ${QT_LIBRARY_DIR} NO_DEFAULT_PATH) FIND_LIBRARY(QT_QTDBUS_LIBRARY NAMES QtDBus QtDBus_debug QtDBus4 QtDBusd4 PATHS ${QT_LIBRARY_DIR} NO_DEFAULT_PATH) FIND_LIBRARY(QT_QTASSISTANTCLIENT_LIBRARY NAMES QtAssistantClient QtAssistantClient_debug QtAssistantClient4 QtAssistantClientd4 PATHS ${QT_LIBRARY_DIR} NO_DEFAULT_PATH) FIND_LIBRARY(QT_QTHELP_LIBRARY NAMES QtHelp QtHelp_debug QtHelp4 QtHelpd4 PATHS ${QT_LIBRARY_DIR} NO_DEFAULT_PATH) FIND_LIBRARY(QT_QTWEBKIT_LIBRARY NAMES QtWebKit QtWebKit_debug QtWebKit4 QtWebKitd4 PATHS ${QT_LIBRARY_DIR} NO_DEFAULT_PATH) FIND_LIBRARY(QT_QTXMLPATTERNS_LIBRARY NAMES QtXmlPatterns QtXmlPatterns_debug QtXmlPatterns4 QtXmlPatternsd4 PATHS ${QT_LIBRARY_DIR} NO_DEFAULT_PATH) FIND_LIBRARY(QT_PHONON_LIBRARY NAMES phonon phonon4 phonon_debug phonond4 PATHS ${QT_LIBRARY_DIR} NO_DEFAULT_PATH) IF(MSVC) FIND_LIBRARY(QT_QTCORE_LIBRARY_RELEASE NAMES QtCore4 PATHS ${QT_LIBRARY_DIR} NO_DEFAULT_PATH) FIND_LIBRARY(QT_QTCORE_LIBRARY_DEBUG NAMES QtCored4 PATHS ${QT_LIBRARY_DIR} NO_DEFAULT_PATH) FIND_LIBRARY(QT_QT3SUPPORT_LIBRARY_RELEASE NAMES Qt3Support4 PATHS ${QT_LIBRARY_DIR} NO_DEFAULT_PATH) FIND_LIBRARY(QT_QT3SUPPORT_LIBRARY_DEBUG NAMES Qt3Supportd4 PATHS ${QT_LIBRARY_DIR} NO_DEFAULT_PATH) FIND_LIBRARY(QT_QTGUI_LIBRARY_RELEASE NAMES QtGui4 PATHS ${QT_LIBRARY_DIR} NO_DEFAULT_PATH) FIND_LIBRARY(QT_QTGUI_LIBRARY_DEBUG NAMES QtGuid4 PATHS ${QT_LIBRARY_DIR} NO_DEFAULT_PATH) FIND_LIBRARY(QT_QTNETWORK_LIBRARY_RELEASE NAMES QtNetwork4 PATHS ${QT_LIBRARY_DIR} NO_DEFAULT_PATH) FIND_LIBRARY(QT_QTNETWORK_LIBRARY_DEBUG NAMES QtNetworkd4 PATHS ${QT_LIBRARY_DIR} NO_DEFAULT_PATH) FIND_LIBRARY(QT_QTOPENGL_LIBRARY_RELEASE NAMES QtOpenGL4 PATHS ${QT_LIBRARY_DIR} NO_DEFAULT_PATH) FIND_LIBRARY(QT_QTOPENGL_LIBRARY_DEBUG NAMES QtOpenGLd4 PATHS ${QT_LIBRARY_DIR} NO_DEFAULT_PATH) FIND_LIBRARY(QT_QTSQL_LIBRARY_RELEASE NAMES QtSql4 PATHS ${QT_LIBRARY_DIR} NO_DEFAULT_PATH) FIND_LIBRARY(QT_QTSQL_LIBRARY_DEBUG NAMES QtSqld4 PATHS ${QT_LIBRARY_DIR} NO_DEFAULT_PATH) FIND_LIBRARY(QT_QTXML_LIBRARY_RELEASE NAMES QtXml4 PATHS ${QT_LIBRARY_DIR} NO_DEFAULT_PATH) FIND_LIBRARY(QT_QTXML_LIBRARY_DEBUG NAMES QtXmld4 PATHS ${QT_LIBRARY_DIR} NO_DEFAULT_PATH) FIND_LIBRARY(QT_QTSVG_LIBRARY_RELEASE NAMES QtSvg4 PATHS ${QT_LIBRARY_DIR} NO_DEFAULT_PATH) FIND_LIBRARY(QT_QTSVG_LIBRARY_DEBUG NAMES QtSvgd4 PATHS ${QT_LIBRARY_DIR} NO_DEFAULT_PATH) FIND_LIBRARY(QT_QTSCRIPT_LIBRARY_RELEASE NAMES QtScript4 PATHS ${QT_LIBRARY_DIR} NO_DEFAULT_PATH) FIND_LIBRARY(QT_QTSCRIPT_LIBRARY_DEBUG NAMES QtScriptd4 PATHS ${QT_LIBRARY_DIR} NO_DEFAULT_PATH) FIND_LIBRARY(QT_QTUITOOLS_LIBRARY_RELEASE NAMES QtUiTools QtUiTools4 PATHS ${QT_LIBRARY_DIR} NO_DEFAULT_PATH) FIND_LIBRARY(QT_QTUITOOLS_LIBRARY_DEBUG NAMES QtUiToolsd QtUiToolsd4 PATHS ${QT_LIBRARY_DIR} NO_DEFAULT_PATH) FIND_LIBRARY(QT_QTTEST_LIBRARY_RELEASE NAMES QtTest4 PATHS ${QT_LIBRARY_DIR} NO_DEFAULT_PATH) FIND_LIBRARY(QT_QTTEST_LIBRARY_DEBUG NAMES QtTestd4 PATHS ${QT_LIBRARY_DIR} NO_DEFAULT_PATH) FIND_LIBRARY(QT_QTDBUS_LIBRARY_RELEASE NAMES QtDBus4 PATHS ${QT_LIBRARY_DIR} NO_DEFAULT_PATH) FIND_LIBRARY(QT_QTDBUS_LIBRARY_DEBUG NAMES QtDBusd4 PATHS ${QT_LIBRARY_DIR} NO_DEFAULT_PATH) FIND_LIBRARY(QT_QTASSISTANT_LIBRARY_RELEASE NAMES QtAssistantClient4 PATHS ${QT_LIBRARY_DIR} NO_DEFAULT_PATH) FIND_LIBRARY(QT_QTASSISTANT_LIBRARY_DEBUG NAMES QtAssistantClientd4 PATHS ${QT_LIBRARY_DIR} NO_DEFAULT_PATH) FIND_LIBRARY(QT_QTDESIGNER_LIBRARY_RELEASE NAMES QtDesigner4 PATHS ${QT_LIBRARY_DIR} NO_DEFAULT_PATH) FIND_LIBRARY(QT_QTDESIGNER_LIBRARY_DEBUG NAMES QtDesignerd4 PATHS ${QT_LIBRARY_DIR} NO_DEFAULT_PATH) FIND_LIBRARY(QT_QTDESIGNERCOMPONENTS_LIBRARY_RELEASE NAMES QtDesignerComponents4 PATHS ${QT_LIBRARY_DIR} NO_DEFAULT_PATH) FIND_LIBRARY(QT_QTDESIGNERCOMPONENTS_LIBRARY_DEBUG NAMES QtDesignerComponentsd4 PATHS ${QT_LIBRARY_DIR} NO_DEFAULT_PATH) FIND_LIBRARY(QT_QTMAIN_LIBRARY_RELEASE NAMES qtmain PATHS ${QT_LIBRARY_DIR} NO_DEFAULT_PATH) FIND_LIBRARY(QT_QTMAIN_LIBRARY_DEBUG NAMES qtmaind PATHS ${QT_LIBRARY_DIR} NO_DEFAULT_PATH) ENDIF(MSVC) ENDIF (QT_USE_FRAMEWORKS) IF( NOT QT_QTCORE_LIBRARY ) IF( NOT Qt4_FIND_QUIETLY AND Qt4_FIND_REQUIRED) MESSAGE( FATAL_ERROR "Could NOT find QtCore. Check ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log for more details.") ENDIF( NOT Qt4_FIND_QUIETLY AND Qt4_FIND_REQUIRED) ENDIF( NOT QT_QTCORE_LIBRARY ) # Set QT_QTASSISTANT_LIBRARY FIND_LIBRARY(QT_QTASSISTANT_LIBRARY NAMES QtAssistantClient QtAssistantClient4 QtAssistant QtAssistant4 QtAssistantd4 PATHS ${QT_LIBRARY_DIR} NO_DEFAULT_PATH) # Set QT_QTDESIGNER_LIBRARY FIND_LIBRARY(QT_QTDESIGNER_LIBRARY NAMES QtDesigner QtDesigner_debug QtDesigner4 QtDesignerd4 PATHS ${QT_LIBRARY_DIR} NO_DEFAULT_PATH) # Set QT_QTDESIGNERCOMPONENTS_LIBRARY FIND_LIBRARY(QT_QTDESIGNERCOMPONENTS_LIBRARY NAMES QtDesignerComponents QtDesignerComponents_debug QtDesignerComponents4 QtDesignerComponentsd4 PATHS ${QT_LIBRARY_DIR} NO_DEFAULT_PATH) # Set QT_QTMAIN_LIBRARY IF(WIN32) FIND_LIBRARY(QT_QTMAIN_LIBRARY NAMES qtmain qtmaind PATHS ${QT_LIBRARY_DIR} NO_DEFAULT_PATH) ENDIF(WIN32) ############################################ # # Check the existence of the libraries. # ############################################ MACRO (_QT4_ADJUST_LIB_VARS basename) IF (QT_${basename}_LIBRARY OR QT_${basename}_LIBRARY_DEBUG) IF(MSVC) # Both set IF (QT_${basename}_LIBRARY_RELEASE AND QT_${basename}_LIBRARY_DEBUG) SET(QT_${basename}_LIBRARY optimized ${QT_${basename}_LIBRARY_RELEASE} debug ${QT_${basename}_LIBRARY_DEBUG}) ENDIF (QT_${basename}_LIBRARY_RELEASE AND QT_${basename}_LIBRARY_DEBUG) # Only debug was found IF (NOT QT_${basename}_LIBRARY_RELEASE AND QT_${basename}_LIBRARY_DEBUG) SET(QT_${basename}_LIBRARY ${QT_${basename}_LIBRARY_DEBUG}) ENDIF (NOT QT_${basename}_LIBRARY_RELEASE AND QT_${basename}_LIBRARY_DEBUG) # Only release was found IF (QT_${basename}_LIBRARY_RELEASE AND NOT QT_${basename}_LIBRARY_DEBUG) SET(QT_${basename}_LIBRARY ${QT_${basename}_LIBRARY_RELEASE}) ENDIF (QT_${basename}_LIBRARY_RELEASE AND NOT QT_${basename}_LIBRARY_DEBUG) # Hmm, is this used anywhere ? Yes, in UseQt4.cmake. We are currently incompatible :-( SET(QT_${basename}_LIBRARIES optimized ${QT_${basename}_LIBRARY} debug ${QT_${basename}_LIBRARY_DEBUG}) ENDIF(MSVC) SET(QT_${basename}_LIBRARY ${QT_${basename}_LIBRARY} CACHE FILEPATH "The Qt ${basename} library") IF (QT_${basename}_LIBRARY) SET(QT_${basename}_FOUND 1) ENDIF (QT_${basename}_LIBRARY) ENDIF (QT_${basename}_LIBRARY OR QT_${basename}_LIBRARY_DEBUG) IF (QT_${basename}_INCLUDE_DIR) #add the include directory to QT_INCLUDES SET(QT_INCLUDES "${QT_${basename}_INCLUDE_DIR}" ${QT_INCLUDES}) ENDIF (QT_${basename}_INCLUDE_DIR) # Make variables changeble to the advanced user MARK_AS_ADVANCED(QT_${basename}_LIBRARY QT_${basename}_INCLUDE_DIR) ENDMACRO (_QT4_ADJUST_LIB_VARS) # Set QT_xyz_LIBRARY variable and add # library include path to QT_INCLUDES _QT4_ADJUST_LIB_VARS(QTCORE) _QT4_ADJUST_LIB_VARS(QTGUI) _QT4_ADJUST_LIB_VARS(QT3SUPPORT) _QT4_ADJUST_LIB_VARS(QTASSISTANT) _QT4_ADJUST_LIB_VARS(QTDESIGNER) _QT4_ADJUST_LIB_VARS(QTDESIGNERCOMPONENTS) _QT4_ADJUST_LIB_VARS(QTNETWORK) _QT4_ADJUST_LIB_VARS(QTNSPLUGIN) _QT4_ADJUST_LIB_VARS(QTOPENGL) _QT4_ADJUST_LIB_VARS(QTSQL) _QT4_ADJUST_LIB_VARS(QTXML) _QT4_ADJUST_LIB_VARS(QTSVG) _QT4_ADJUST_LIB_VARS(QTSCRIPT) _QT4_ADJUST_LIB_VARS(QTUITOOLS) _QT4_ADJUST_LIB_VARS(QTTEST) _QT4_ADJUST_LIB_VARS(QTDBUS) _QT4_ADJUST_LIB_VARS(QTASSISTANTCLIENT) _QT4_ADJUST_LIB_VARS(QTHELP) _QT4_ADJUST_LIB_VARS(QTWEBKIT) _QT4_ADJUST_LIB_VARS(QTXMLPATTERNS) _QT4_ADJUST_LIB_VARS(PHONON) # platform dependent libraries IF(Q_WS_X11) _QT4_ADJUST_LIB_VARS(QTMOTIF) ENDIF(Q_WS_X11) IF(WIN32) _QT4_ADJUST_LIB_VARS(QTMAIN) ENDIF(WIN32) ####################################### # # Check the executables of Qt # ( moc, uic, rcc ) # ####################################### # find moc and uic using qmake QT_QUERY_QMAKE(QT_MOC_EXECUTABLE_INTERNAL "QMAKE_MOC") QT_QUERY_QMAKE(QT_UIC_EXECUTABLE_INTERNAL "QMAKE_UIC") # make sure we have / and not \ as qmake gives on windows FILE(TO_CMAKE_PATH "${QT_MOC_EXECUTABLE_INTERNAL}" QT_MOC_EXECUTABLE_INTERNAL) # make sure we have / and not \ as qmake gives on windows FILE(TO_CMAKE_PATH "${QT_UIC_EXECUTABLE_INTERNAL}" QT_UIC_EXECUTABLE_INTERNAL) SET(QT_MOC_EXECUTABLE ${QT_MOC_EXECUTABLE_INTERNAL} CACHE FILEPATH "The moc executable") SET(QT_UIC_EXECUTABLE ${QT_UIC_EXECUTABLE_INTERNAL} CACHE FILEPATH "The uic executable") FIND_PROGRAM(QT_UIC3_EXECUTABLE NAMES uic3 PATHS ${QT_BINARY_DIR} NO_DEFAULT_PATH ) FIND_PROGRAM(QT_RCC_EXECUTABLE NAMES rcc PATHS ${QT_BINARY_DIR} NO_DEFAULT_PATH ) FIND_PROGRAM(QT_DBUSCPP2XML_EXECUTABLE NAMES qdbuscpp2xml PATHS ${QT_BINARY_DIR} NO_DEFAULT_PATH ) FIND_PROGRAM(QT_DBUSXML2CPP_EXECUTABLE NAMES qdbusxml2cpp PATHS ${QT_BINARY_DIR} NO_DEFAULT_PATH ) FIND_PROGRAM(QT_LUPDATE_EXECUTABLE NAMES lupdate PATHS ${QT_BINARY_DIR} NO_DEFAULT_PATH ) FIND_PROGRAM(QT_LRELEASE_EXECUTABLE NAMES lrelease PATHS ${QT_BINARY_DIR} NO_DEFAULT_PATH ) IF (QT_MOC_EXECUTABLE) SET(QT_WRAP_CPP "YES") ENDIF (QT_MOC_EXECUTABLE) IF (QT_UIC_EXECUTABLE) SET(QT_WRAP_UI "YES") ENDIF (QT_UIC_EXECUTABLE) MARK_AS_ADVANCED( QT_UIC_EXECUTABLE QT_UIC3_EXECUTABLE QT_MOC_EXECUTABLE QT_RCC_EXECUTABLE QT_DBUSXML2CPP_EXECUTABLE QT_DBUSCPP2XML_EXECUTABLE QT_LUPDATE_EXECUTABLE QT_LRELEASE_EXECUTABLE) ###################################### # # Macros for building Qt files # ###################################### MACRO (QT4_EXTRACT_OPTIONS _qt4_files _qt4_options) SET(${_qt4_files}) SET(${_qt4_options}) SET(_QT4_DOING_OPTIONS FALSE) FOREACH(_currentArg ${ARGN}) IF ("${_currentArg}" STREQUAL "OPTIONS") SET(_QT4_DOING_OPTIONS TRUE) ELSE ("${_currentArg}" STREQUAL "OPTIONS") IF(_QT4_DOING_OPTIONS) LIST(APPEND ${_qt4_options} "${_currentArg}") ELSE(_QT4_DOING_OPTIONS) LIST(APPEND ${_qt4_files} "${_currentArg}") ENDIF(_QT4_DOING_OPTIONS) ENDIF ("${_currentArg}" STREQUAL "OPTIONS") ENDFOREACH(_currentArg) ENDMACRO (QT4_EXTRACT_OPTIONS) MACRO (QT4_GET_MOC_INC_DIRS _moc_INC_DIRS) SET(${_moc_INC_DIRS}) GET_DIRECTORY_PROPERTY(_inc_DIRS INCLUDE_DIRECTORIES) FOREACH(_current ${_inc_DIRS}) SET(${_moc_INC_DIRS} ${${_moc_INC_DIRS}} "-I" ${_current}) ENDFOREACH(_current ${_inc_DIRS}) # if Qt is installed only as framework, add -F /library/Frameworks to the moc arguments # otherwise moc can't find the headers in the framework include dirs IF(APPLE AND "${QT_QTCORE_INCLUDE_DIR}" MATCHES "/Library/Frameworks/") SET(${_moc_INC_DIRS} ${${_moc_INC_DIRS}} "-F/Library/Frameworks") ENDIF(APPLE AND "${QT_QTCORE_INCLUDE_DIR}" MATCHES "/Library/Frameworks/") ENDMACRO(QT4_GET_MOC_INC_DIRS) MACRO (QT4_GENERATE_MOC infile outfile ) # get include dirs QT4_GET_MOC_INC_DIRS(moc_includes) GET_FILENAME_COMPONENT(abs_infile ${infile} ABSOLUTE) IF (MSVC_IDE) SET (_moc_parameter_file ${outfile}_parameters) SET (_moc_param "${moc_includes} \n-o${outfile} \n${abs_infile}") STRING(REGEX REPLACE ";-I;" "\\n-I" _moc_param "${_moc_param}") FILE (WRITE ${_moc_parameter_file} "${_moc_param}") ADD_CUSTOM_COMMAND(OUTPUT ${outfile} COMMAND ${QT_MOC_EXECUTABLE} ARGS @"${_moc_parameter_file}" DEPENDS ${abs_infile}) ELSE (MSVC_IDE) ADD_CUSTOM_COMMAND(OUTPUT ${outfile} COMMAND ${QT_MOC_EXECUTABLE} ARGS ${moc_includes} -o ${outfile} ${abs_infile} DEPENDS ${abs_infile}) ENDIF (MSVC_IDE) SET_SOURCE_FILES_PROPERTIES(${outfile} PROPERTIES SKIP_AUTOMOC TRUE) # dont run automoc on this file MACRO_ADD_FILE_DEPENDENCIES(${abs_infile} ${outfile}) ENDMACRO (QT4_GENERATE_MOC) # QT4_WRAP_CPP(outfiles inputfile ... ) MACRO (QT4_WRAP_CPP outfiles ) # get include dirs QT4_GET_MOC_INC_DIRS(moc_includes) QT4_EXTRACT_OPTIONS(moc_files moc_options ${ARGN}) FOREACH (it ${moc_files}) GET_FILENAME_COMPONENT(it ${it} ABSOLUTE) GET_FILENAME_COMPONENT(outfile ${it} NAME_WE) SET(outfile ${CMAKE_CURRENT_BINARY_DIR}/moc_${outfile}.cxx) ADD_CUSTOM_COMMAND(OUTPUT ${outfile} COMMAND ${QT_MOC_EXECUTABLE} ARGS ${moc_includes} ${moc_options} -o ${outfile} ${it} DEPENDS ${it}) SET(${outfiles} ${${outfiles}} ${outfile}) ENDFOREACH(it) ENDMACRO (QT4_WRAP_CPP) # QT4_WRAP_UI(outfiles inputfile ... ) MACRO (QT4_WRAP_UI outfiles ) QT4_EXTRACT_OPTIONS(ui_files ui_options ${ARGN}) FOREACH (it ${ui_files}) GET_FILENAME_COMPONENT(outfile ${it} NAME_WE) GET_FILENAME_COMPONENT(infile ${it} ABSOLUTE) SET(outfile ${CMAKE_CURRENT_BINARY_DIR}/ui_${outfile}.h) ADD_CUSTOM_COMMAND(OUTPUT ${outfile} COMMAND ${QT_UIC_EXECUTABLE} ARGS ${ui_options} -o ${outfile} ${infile} MAIN_DEPENDENCY ${infile}) SET(${outfiles} ${${outfiles}} ${outfile}) ENDFOREACH (it) ENDMACRO (QT4_WRAP_UI) # QT4_ADD_RESOURCES(outfiles inputfile ... ) MACRO (QT4_ADD_RESOURCES outfiles ) QT4_EXTRACT_OPTIONS(rcc_files rcc_options ${ARGN}) FOREACH (it ${rcc_files}) GET_FILENAME_COMPONENT(outfilename ${it} NAME_WE) GET_FILENAME_COMPONENT(infile ${it} ABSOLUTE) GET_FILENAME_COMPONENT(rc_path ${infile} PATH) SET(outfile ${CMAKE_CURRENT_BINARY_DIR}/qrc_${outfilename}.cxx) # parse file for dependencies # all files are absolute paths or relative to the location of the qrc file FILE(READ "${infile}" _RC_FILE_CONTENTS) STRING(REGEX MATCHALL "]*>" "" _RC_FILE "${_RC_FILE}") STRING(REGEX MATCH "^/|([A-Za-z]:/)" _ABS_PATH_INDICATOR "${_RC_FILE}") IF(NOT _ABS_PATH_INDICATOR) SET(_RC_FILE "${rc_path}/${_RC_FILE}") ENDIF(NOT _ABS_PATH_INDICATOR) SET(_RC_DEPENDS ${_RC_DEPENDS} "${_RC_FILE}") ENDFOREACH(_RC_FILE) ADD_CUSTOM_COMMAND(OUTPUT ${outfile} COMMAND ${QT_RCC_EXECUTABLE} ARGS ${rcc_options} -name ${outfilename} -o ${outfile} ${infile} MAIN_DEPENDENCY ${infile} DEPENDS ${_RC_DEPENDS}) SET(${outfiles} ${${outfiles}} ${outfile}) ENDFOREACH (it) ENDMACRO (QT4_ADD_RESOURCES) MACRO(QT4_ADD_DBUS_INTERFACE _sources _interface _basename) GET_FILENAME_COMPONENT(_infile ${_interface} ABSOLUTE) SET(_header ${CMAKE_CURRENT_BINARY_DIR}/${_basename}.h) SET(_impl ${CMAKE_CURRENT_BINARY_DIR}/${_basename}.cpp) SET(_moc ${CMAKE_CURRENT_BINARY_DIR}/${_basename}.moc) GET_SOURCE_FILE_PROPERTY(_nonamespace ${_interface} NO_NAMESPACE) IF ( _nonamespace ) SET(_params -N -m) ELSE ( _nonamespace ) SET(_params -m) ENDIF ( _nonamespace ) GET_SOURCE_FILE_PROPERTY(_include ${_interface} INCLUDE) IF ( _include ) SET(_params ${_params} -i ${_include}) ENDIF ( _include ) ADD_CUSTOM_COMMAND(OUTPUT ${_impl} ${_header} COMMAND ${QT_DBUSXML2CPP_EXECUTABLE} ${_params} -p ${_basename} ${_infile} DEPENDS ${_infile}) SET_SOURCE_FILES_PROPERTIES(${_impl} PROPERTIES SKIP_AUTOMOC TRUE) QT4_GENERATE_MOC(${_header} ${_moc}) SET(${_sources} ${${_sources}} ${_impl} ${_header} ${_moc}) MACRO_ADD_FILE_DEPENDENCIES(${_impl} ${_moc}) ENDMACRO(QT4_ADD_DBUS_INTERFACE) MACRO(QT4_ADD_DBUS_INTERFACES _sources) FOREACH (_current_FILE ${ARGN}) GET_FILENAME_COMPONENT(_infile ${_current_FILE} ABSOLUTE) # get the part before the ".xml" suffix STRING(REGEX REPLACE "(.*[/\\.])?([^\\.]+)\\.xml" "\\2" _basename ${_current_FILE}) STRING(TOLOWER ${_basename} _basename) QT4_ADD_DBUS_INTERFACE(${_sources} ${_infile} ${_basename}interface) ENDFOREACH (_current_FILE) ENDMACRO(QT4_ADD_DBUS_INTERFACES) MACRO(QT4_GENERATE_DBUS_INTERFACE _header) # _customName OPTIONS -some -options ) QT4_EXTRACT_OPTIONS(_customName _qt4_dbus_options ${ARGN}) GET_FILENAME_COMPONENT(_in_file ${_header} ABSOLUTE) GET_FILENAME_COMPONENT(_basename ${_header} NAME_WE) IF (_customName) SET(_target ${CMAKE_CURRENT_BINARY_DIR}/${_customName}) ELSE (_customName) SET(_target ${CMAKE_CURRENT_BINARY_DIR}/${_basename}.xml) ENDIF (_customName) ADD_CUSTOM_COMMAND(OUTPUT ${_target} COMMAND ${QT_DBUSCPP2XML_EXECUTABLE} ${_qt4_dbus_options} ${_in_file} > ${_target} DEPENDS ${_in_file} ) ENDMACRO(QT4_GENERATE_DBUS_INTERFACE) MACRO(QT4_ADD_DBUS_ADAPTOR _sources _xml_file _include _parentClass) # _optionalBasename _optionalClassName) GET_FILENAME_COMPONENT(_infile ${_xml_file} ABSOLUTE) SET(_optionalBasename "${ARGV4}") IF (_optionalBasename) SET(_basename ${_optionalBasename} ) ELSE (_optionalBasename) STRING(REGEX REPLACE "(.*[/\\.])?([^\\.]+)\\.xml" "\\2adaptor" _basename ${_infile}) STRING(TOLOWER ${_basename} _basename) ENDIF (_optionalBasename) SET(_optionalClassName "${ARGV5}") SET(_header ${CMAKE_CURRENT_BINARY_DIR}/${_basename}.h) SET(_impl ${CMAKE_CURRENT_BINARY_DIR}/${_basename}.cpp) SET(_moc ${CMAKE_CURRENT_BINARY_DIR}/${_basename}.moc) IF(_optionalClassName) ADD_CUSTOM_COMMAND(OUTPUT ${_impl} ${_header} COMMAND ${QT_DBUSXML2CPP_EXECUTABLE} -m -a ${_basename} -c ${_optionalClassName} -i ${_include} -l ${_parentClass} ${_infile} DEPENDS ${_infile} ) ELSE(_optionalClassName) ADD_CUSTOM_COMMAND(OUTPUT ${_impl} ${_header} COMMAND ${QT_DBUSXML2CPP_EXECUTABLE} -m -a ${_basename} -i ${_include} -l ${_parentClass} ${_infile} DEPENDS ${_infile} ) ENDIF(_optionalClassName) QT4_GENERATE_MOC(${_header} ${_moc}) SET_SOURCE_FILES_PROPERTIES(${_impl} PROPERTIES SKIP_AUTOMOC TRUE) MACRO_ADD_FILE_DEPENDENCIES(${_impl} ${_moc}) SET(${_sources} ${${_sources}} ${_impl} ${_header} ${_moc}) ENDMACRO(QT4_ADD_DBUS_ADAPTOR) MACRO(QT4_AUTOMOC) QT4_GET_MOC_INC_DIRS(_moc_INCS) SET(_matching_FILES ) FOREACH (_current_FILE ${ARGN}) GET_FILENAME_COMPONENT(_abs_FILE ${_current_FILE} ABSOLUTE) # if "SKIP_AUTOMOC" is set to true, we will not handle this file here. # This is required to make uic work correctly: # we need to add generated .cpp files to the sources (to compile them), # but we cannot let automoc handle them, as the .cpp files don't exist yet when # cmake is run for the very first time on them -> however the .cpp files might # exist at a later run. at that time we need to skip them, so that we don't add two # different rules for the same moc file GET_SOURCE_FILE_PROPERTY(_skip ${_abs_FILE} SKIP_AUTOMOC) IF ( NOT _skip AND EXISTS ${_abs_FILE} ) FILE(READ ${_abs_FILE} _contents) GET_FILENAME_COMPONENT(_abs_PATH ${_abs_FILE} PATH) STRING(REGEX MATCHALL "#include +[^ ]+\\.moc[\">]" _match "${_contents}") IF(_match) FOREACH (_current_MOC_INC ${_match}) STRING(REGEX MATCH "[^ <\"]+\\.moc" _current_MOC "${_current_MOC_INC}") GET_filename_component(_basename ${_current_MOC} NAME_WE) # SET(_header ${CMAKE_CURRENT_SOURCE_DIR}/${_basename}.h) SET(_header ${_abs_PATH}/${_basename}.h) SET(_moc ${CMAKE_CURRENT_BINARY_DIR}/${_current_MOC}) ADD_CUSTOM_COMMAND(OUTPUT ${_moc} COMMAND ${QT_MOC_EXECUTABLE} ARGS ${_moc_INCS} ${_header} -o ${_moc} DEPENDS ${_header} ) MACRO_ADD_FILE_DEPENDENCIES(${_abs_FILE} ${_moc}) ENDFOREACH (_current_MOC_INC) ENDIF(_match) ENDIF ( NOT _skip AND EXISTS ${_abs_FILE} ) ENDFOREACH (_current_FILE) ENDMACRO(QT4_AUTOMOC) ###################################### # # decide if Qt got found # ###################################### # if the includes,libraries,moc,uic and rcc are found then we have it IF( QT_LIBRARY_DIR AND QT_INCLUDE_DIR AND QT_MOC_EXECUTABLE AND QT_UIC_EXECUTABLE AND QT_RCC_EXECUTABLE) SET( QT4_FOUND "YES" ) IF( NOT Qt4_FIND_QUIETLY) MESSAGE(STATUS "Found Qt-Version ${QTVERSION} (using ${QT_QMAKE_EXECUTABLE})") ENDIF( NOT Qt4_FIND_QUIETLY) ELSE( QT_LIBRARY_DIR AND QT_INCLUDE_DIR AND QT_MOC_EXECUTABLE AND QT_UIC_EXECUTABLE AND QT_RCC_EXECUTABLE) SET( QT4_FOUND "NO") SET(QT_QMAKE_EXECUTABLE "${QT_QMAKE_EXECUTABLE}-NOTFOUND" CACHE FILEPATH "Invalid qmake found" FORCE) IF( Qt4_FIND_REQUIRED) IF ( NOT QT_LIBRARY_DIR ) MESSAGE(STATUS "Qt libraries NOT found!") ENDIF(NOT QT_LIBRARY_DIR ) IF ( NOT QT_INCLUDE_DIR ) MESSAGE(STATUS "Qt includes NOT found!") ENDIF( NOT QT_INCLUDE_DIR ) IF ( NOT QT_MOC_EXECUTABLE ) MESSAGE(STATUS "Qt's moc NOT found!") ENDIF( NOT QT_MOC_EXECUTABLE ) IF ( NOT QT_UIC_EXECUTABLE ) MESSAGE(STATUS "Qt's uic NOT found!") ENDIF( NOT QT_UIC_EXECUTABLE ) IF ( NOT QT_RCC_EXECUTABLE ) MESSAGE(STATUS "Qt's rcc NOT found!") ENDIF( NOT QT_RCC_EXECUTABLE ) MESSAGE( FATAL_ERROR "Qt libraries, includes, moc, uic or/and rcc NOT found!") ENDIF( Qt4_FIND_REQUIRED) ENDIF( QT_LIBRARY_DIR AND QT_INCLUDE_DIR AND QT_MOC_EXECUTABLE AND QT_UIC_EXECUTABLE AND QT_RCC_EXECUTABLE) SET(QT_FOUND ${QT4_FOUND}) ####################################### # # System dependent settings # ####################################### # for unix add X11 stuff IF(UNIX) # on OS X X11 may not be required IF (Q_WS_X11) FIND_PACKAGE(X11 REQUIRED) ENDIF (Q_WS_X11) FIND_PACKAGE(Threads) SET(QT_QTCORE_LIBRARY ${QT_QTCORE_LIBRARY} ${CMAKE_THREAD_LIBS_INIT}) ENDIF(UNIX) ####################################### # # compatibility settings # ####################################### # Backwards compatibility for CMake1.4 and 1.2 SET (QT_MOC_EXE ${QT_MOC_EXECUTABLE} ) SET (QT_UIC_EXE ${QT_UIC_EXECUTABLE} ) SET( QT_QT_LIBRARY "") ELSE(QT4_QMAKE_FOUND) SET(QT_QMAKE_EXECUTABLE "${QT_QMAKE_EXECUTABLE}-NOTFOUND" CACHE FILEPATH "Invalid qmake found" FORCE) IF(Qt4_FIND_REQUIRED) IF(QT4_INSTALLED_VERSION_TOO_OLD) MESSAGE(FATAL_ERROR "The installed Qt version ${QTVERSION} is too old, at least version ${QT_MIN_VERSION} is required") ELSE(QT4_INSTALLED_VERSION_TOO_OLD) MESSAGE( FATAL_ERROR "Qt qmake not found!") ENDIF(QT4_INSTALLED_VERSION_TOO_OLD) ELSE(Qt4_FIND_REQUIRED) IF(QT4_INSTALLED_VERSION_TOO_OLD AND NOT Qt4_FIND_QUIETLY) MESSAGE(STATUS "The installed Qt version ${QTVERSION} is too old, at least version ${QT_MIN_VERSION} is required") ENDIF(QT4_INSTALLED_VERSION_TOO_OLD AND NOT Qt4_FIND_QUIETLY) ENDIF(Qt4_FIND_REQUIRED) ENDIF (QT4_QMAKE_FOUND) ENDIF (QT4_QMAKE_FOUND) libsyncml-0.5.4/cmake/modules/FindGConf2.cmake100644 1750 1750 5273 11211710410 21041 0ustar00bellmichbellmich# - Try to find gconf2 # Find gconf2 headers, libraries and the answer to all questions. # # GCONF2_FOUND True if gconf2 got found # GCONF2_INCLUDEDIR Location of gconf2 headers # GCONF2_LIBRARIES List of libaries to use gconf2 # GCONF2_DEFINITIONS Definitions to compile gconf2 # # Copyright (c) 2007 Juha Tuomala # Copyright (c) 2007 Daniel Gollub # Copyright (c) 2007 Alban Browaeys # # Redistribution and use is allowed according to the terms of the New # BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # INCLUDE( FindPkgConfig ) # Take care about gconf-2.0.pc settings IF ( GConf2_FIND_REQUIRED ) SET( _pkgconfig_REQUIRED "REQUIRED" ) ELSE ( GConf2_FIND_REQUIRED ) SET( _pkgconfig_REQUIRED "" ) ENDIF ( GConf2_FIND_REQUIRED ) pkg_search_module( GCONF2 ${_pkgconfig_REQUIRED} gconf-2.0 ) # Look for gconf2 include dir and libraries w/o pkgconfig IF ( NOT GCONF2_FOUND AND NOT PKG_CONFIG_FOUND ) FIND_PATH( _gconf2_include_DIR gconf/gconf.h PATH_SUFFIXES gconf/2 PATHS /opt/local/include/ /sw/include/ /usr/local/include/ /usr/include/ ) FIND_LIBRARY( _gconf2_link_DIR gconf-2 PATHS /opt/local/lib /sw/lib /usr/lib /usr/local/lib /usr/lib64 /usr/local/lib64 /opt/lib64 ) IF ( _gconf2_include_DIR AND _gconf2_link_DIR ) SET ( _gconf2_FOUND TRUE ) ENDIF ( _gconf2_include_DIR AND _gconf2_link_DIR ) IF ( _gconf2_FOUND ) SET ( GCONF2_INCLUDE_DIRS ${_gconf2_include_DIR} ) SET ( GCONF2_LIBRARIES ${_gconf2_link_DIR} ) ENDIF ( _gconf2_FOUND ) # Handle dependencies IF ( NOT ORBIT2_FOUND ) FIND_PACKAGE( ORBit2 REQUIRED) IF ( ORBIT2_FOUND ) SET ( GCONF2_INCLUDE_DIRS ${GCONF2_INCLUDE_DIRS} ${ORBIT2_INCLUDE_DIRS} ) SET ( GCONF2_LIBRARIES ${GCONF2_LIBRARIES} ${ORBIT2_LIBRARIES} ) ENDIF ( ORBIT2_FOUND ) ENDIF ( NOT ORBIT2_FOUND ) # Report results IF ( GCONF2_LIBRARIES AND GCONF2_INCLUDE_DIRS AND _gconf2_FOUND ) SET( GCONF2_FOUND 1 ) IF ( NOT GConf2_FIND_QUIETLY ) MESSAGE( STATUS "Found gconf2: ${GCONF2_LIBRARIES} ${GCONF2_INCLUDE_DIRS}" ) ENDIF ( NOT GConf2_FIND_QUIETLY ) ELSE ( GCONF2_LIBRARIES AND GCONF2_INCLUDE_DIRS AND _gconf2_FOUND ) IF ( GConf2_FIND_REQUIRED ) MESSAGE( SEND_ERROR "Could NOT find gconf2" ) ELSE ( GConf2_FIND_REQUIRED ) IF ( NOT GConf2_FIND_QUIETLY ) MESSAGE( STATUS "Could NOT find gconf2" ) ENDIF ( NOT GConf2_FIND_QUIETLY ) ENDIF ( GConf2_FIND_REQUIRED ) ENDIF ( GCONF2_LIBRARIES AND GCONF2_INCLUDE_DIRS AND _gconf2_FOUND ) ENDIF ( NOT GCONF2_FOUND AND NOT PKG_CONFIG_FOUND ) # Hide advanced variables from CMake GUIs MARK_AS_ADVANCED( GCONF2_LIBRARIES GCONF2_INCLUDE_DIRS ) libsyncml-0.5.4/cmake/modules/FindEDataBook1.2.cmake100644 1750 1750 11463 11211710410 22013 0ustar00bellmichbellmich# - Try to find libedatabook1.2 components # Find libedatabook 1.2 headers, libraries and the answer to all questions. # # LIBEDATABOOK1.2_FOUND True if libedatabook1.2 got found # LIBEDATABOOK1.2_INCLUDE_DIRS Location of libedatabook1.2 headers # LIBEDATABOOK1.2_LIBRARIES List of libaries to use libedatabook1.2 # LIBEDATABOOK1.2_DEFINITIONS Definitions to compile libedatabook1.2 # # Copyright (c) 2007 Juha Tuomala # Copyright (c) 2007 Daniel Gollub # Copyright (c) 2007 Alban Browaeys # # Redistribution and use is allowed according to the terms of the New # BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # INCLUDE( FindPkgConfig ) # Take care about libedata-book-1.2.pc settings IF ( EDataBook1.2_FIND_REQUIRED ) SET( _pkgconfig_REQUIRED "REQUIRED" ) ELSE ( EDataBook1.2_FIND_REQUIRED ) SET( _pkgconfig_REQUIRED "" ) ENDIF ( EDataBook1.2_FIND_REQUIRED ) pkg_search_module( LIBEDATABOOK1.2 ${_pkgconfig_REQUIRED} libedata-book-1.2 ) # Look for libedatabook1.2 include dir and libraries w/o pkg-config. IF ( NOT LIBEDATABOOK1.2_FOUND AND NOT PKG_CONFIG_FOUND ) FIND_PATH( _libedatabook1.2_include_DIR libedata-book/e-data-book.h PATH_SUFFIXES evolution-data-server-1.12 evolution-data-server-1.10 evolution-data-server-1.8 evolution-data-server-1.6 evolution-data-server-1.4 evolution-data-server-1.2 PATHS /opt/local/include/ /sw/include/ /usr/local/include/ /usr/include/ ) FIND_LIBRARY( _libedatabook1.2_link_DIR edata-book-1.2 PATHS /opt/local/lib /sw/lib /usr/lib /usr/local/lib /usr/lib64 /usr/local/lib64 /opt/lib64 ) IF ( _libedatabook1.2_include_DIR AND _libedatabook1.2_link_DIR ) SET ( _libedatabook1.2_FOUND TRUE ) ENDIF ( _libedatabook1.2_include_DIR AND _libedatabook1.2_link_DIR ) IF ( _libedatabook1.2_FOUND ) SET ( LIBEDATABOOK1.2_INCLUDE_DIRS ${_libedatabook1.2_include_DIR} ) SET ( LIBEDATABOOK1.2_LIBRARIES ${_libedatabook1.2_link_DIR} ) ENDIF ( _libedatabook1.2_FOUND ) # Handle dependencies IF ( NOT LIBEBOOK1.2_FOUND ) FIND_PACKAGE ( EBook1.2 REQUIRED ) IF ( LIBEBOOK1.2_FOUND ) SET ( LIBEDATABOOK1.2_INCLUDE_DIRS ${LIBEDATABOOK1.2_INCLUDE_DIRS} ${LIBEBOOK1.2_INCLUDE_DIRS} ) SET ( LIBEDATABOOK1.2_LIBRARIES ${LIBEDATABOOK1.2_LIBRARIES} ${LIBEBOOK1.2_LIBRARIES} ) ENDIF ( LIBEBOOK1.2_FOUND ) ENDIF ( NOT LIBEBOOK1.2_FOUND ) IF ( NOT LIBEDATASERVER1.2_FOUND ) FIND_PACKAGE ( EDataServer1.2 REQUIRED ) IF ( LIBEDATASERVER1.2_FOUND ) SET ( LIBEDATABOOK1.2_INCLUDE_DIRS ${LIBEDATABOOK1.2_INCLUDE_DIRS} ${LIBEDATASERVER1.2_INCLUDE_DIRS} ) SET ( LIBEDATABOOK1.2_LIBRARIES ${LIBEDATABOOK1.2_LIBRARIES} ${LIBEDATASERVER1.2_LIBRARIES} ) ENDIF ( LIBEDATASERVER1.2_FOUND ) ENDIF ( NOT LIBEDATASERVER1.2_FOUND ) IF ( NOT LIBGNOME2_FOUND ) FIND_PACKAGE ( LibGnome2 REQUIRED ) IF ( LIBGNOME2_FOUND ) SET ( LIBEDATABOOK1.2_INCLUDE_DIRS ${LIBEDATABOOK1.2_INCLUDE_DIRS} ${LIBGNOME2_INCLUDE_DIRS} ) SET ( LIBEDATABOOK1.2_LIBRARIES ${LIBEDATABOOK1.2_LIBRARIES} ${LIBGNOME2_LIBRARIES} ) ENDIF ( LIBGNOME2_FOUND ) ENDIF ( NOT LIBGNOME2_FOUND ) IF ( NOT BONOBO2_FOUND ) SET ( BONOBO2_MIN_VERSION "2.4.2" ) FIND_PACKAGE ( BONOBO2 REQUIRED ) IF ( BONOBO2_FOUND ) SET ( LIBEDATABOOK1.2_INCLUDE_DIRS ${LIBEDATABOOK1.2_INCLUDE_DIRS} ${BONOBO2_INCLUDE_DIRS} ) SET ( LIBEDATABOOK1.2_LIBRARIES ${LIBEDATABOOK1.2_LIBRARIES} ${BONOBO2_LIBRARIES} ) ENDIF ( BONOBO2_FOUND ) ENDIF ( NOT BONOBO2_FOUND ) # Report results IF ( LIBEDATABOOK1.2_LIBRARIES AND LIBEDATABOOK1.2_INCLUDE_DIRS AND _libedatabook1.2_FOUND ) SET( LIBEDATABOOK1.2_FOUND 1 ) IF ( NOT EDataBook1.2_FIND_QUIETLY ) MESSAGE( STATUS "Found libedatabook-1.2: ${LIBEDATABOOK1.2_LIBRARIES}" ) ENDIF ( NOT EDataBook1.2_FIND_QUIETLY ) ELSE ( LIBEDATABOOK1.2_LIBRARIES AND LIBEDATABOOK1.2_INCLUDE_DIRS AND _libedatabook1.2_FOUND ) IF ( EDataBook1.2_FIND_REQUIRED ) MESSAGE( SEND_ERROR "Could NOT find libedatabook-1.2" ) ELSE ( EDataBook1.2_FIND_REQUIRED ) IF ( NOT EDataBook1.2_FIND_QUIETLY ) MESSAGE( STATUS "Could NOT find libedatabook-1.2" ) ENDIF ( NOT EDataBook1.2_FIND_QUIETLY ) ENDIF ( EDataBook1.2_FIND_REQUIRED ) ENDIF ( LIBEDATABOOK1.2_LIBRARIES AND LIBEDATABOOK1.2_INCLUDE_DIRS AND _libedatabook1.2_FOUND ) ENDIF ( NOT LIBEDATABOOK1.2_FOUND AND NOT PKG_CONFIG_FOUND ) # Hide advanced variables from CMake GUIs MARK_AS_ADVANCED( LIBEDATABOOK1.2_LIBRARIES LIBEDATABOOK1.2_INCLUDE_DIRS ) libsyncml-0.5.4/cmake/modules/FindEDataServer1.2.cmake100644 1750 1750 12441 11211710410 22364 0ustar00bellmichbellmich# - Try to find libedataserver1.2 components # Find libedataserver 1.2 headers, libraries and the answer to all questions. # # LIBEDATASERVER1.2_FOUND True if libedataserver1.2 got found # LIBEDATASERVER1.2_INCLUDE_DIRS Location of libedataserver1.2 headers # LIBEDATASERVER1.2_LIBRARIES List of libaries to use libedataserver1.2 # LIBEDATASERVER1.2_DEFINITIONS Definitions to compile libedataserver1.2 # # Copyright (c) 2007 Juha Tuomala # Copyright (c) 2007 Daniel Gollub # Copyright (c) 2007 Alban Browaeys # # Redistribution and use is allowed according to the terms of the New # BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # INCLUDE( FindPkgConfig ) # Take care about libedataserver-1.2.pc settings IF ( EDataServer1.2_FIND_REQUIRED ) SET( _pkgconfig_REQUIRED "REQUIRED" ) ELSE ( EDataServer1.2_FIND_REQUIRED ) SET( _pkgconfig_REQUIRED "" ) ENDIF ( EDataServer1.2_FIND_REQUIRED ) pkg_search_module( LIBEDATASERVER1.2 ${_pkgconfig_REQUIRED} libedataserver-1.2 ) # Look for libedataserver1.2 include dir and libraries w/o pkg-config. IF ( NOT LIBEDATASERVER1.2_FOUND AND NOT PKG_CONFIG_FOUND ) FIND_PATH( _libedataserver1.2_include_DIR libedataserver/e-account.h PATH_SUFFIXES evolution-data-server-1.12 evolution-data-server-1.10 evolution-data-server-1.8 evolution-data-server-1.6 evolution-data-server-1.4 evolution-data-server-1.2 PATHS /opt/local/include/ /sw/include/ /usr/local/include/ /usr/include/ ) FIND_LIBRARY( _libedataserver1.2_link_DIR edataserver-1.2 PATHS /opt/local/lib /sw/lib /usr/lib /usr/local/lib /usr/lib64 /usr/local/lib64 /opt/lib64 ) IF ( _libedataserver1.2_include_DIR AND _libedataserver1.2_link_DIR ) SET ( _libedataserver1.2_FOUND TRUE ) ENDIF ( _libedataserver1.2_include_DIR AND _libedataserver1.2_link_DIR ) IF ( _libedataserver1.2_FOUND ) SET ( LIBEDATASERVER1.2_INCLUDE_DIRS ${_libedataserver1.2_include_DIR} ) SET ( LIBEDATASERVER1.2_LIBRARIES ${_libedataserver1.2_link_DIR} ) ENDIF ( _libedataserver1.2_FOUND ) # Handle dependencies IF ( NOT GCONF2_FOUND ) FIND_PACKAGE ( GConf2 REQUIRED ) IF ( GCONF2_FOUND ) SET ( LIBEDATASERVER1.2_INCLUDE_DIRS ${LIBEDATASERVER1.2_INCLUDE_DIRS} ${GCONF2_INCLUDE_DIRS} ) SET ( LIBEDATASERVER1.2_LIBRARIES ${LIBEDATASERVER1.2_LIBRARIES} ${GCONF2_LIBRARIES} ) ENDIF ( GCONF2_FOUND ) ENDIF ( NOT GCONF2_FOUND ) IF ( NOT BONOBO2_FOUND ) SET ( BONOBO2_MIN_VERSION "2.4.2" ) FIND_PACKAGE ( BONOBO2 REQUIRED ) IF ( BONOBO2_FOUND ) SET ( LIBEDATASERVER1.2_INCLUDE_DIRS ${LIBEDATASERVER1.2_INCLUDE_DIRS} ${BONOBO2_INCLUDE_DIRS} ) SET ( LIBEDATASERVER1.2_LIBRARIES ${LIBEDATASERVER1.2_LIBRARIES} ${BONOBO2_LIBRARIES} ) ENDIF ( BONOBO2_FOUND ) ENDIF ( NOT BONOBO2_FOUND ) IF ( NOT ORBIT2_FOUND ) SET ( ORBIT2_MIN_VERSION "2.9.8" ) FIND_PACKAGE ( ORBit2 REQUIRED ) IF ( ORBIT2_FOUND ) SET ( LIBEDATASERVER1.2_INCLUDE_DIRS ${LIBEDATASERVER1.2_INCLUDE_DIRS} ${ORBIT2_INCLUDE_DIRS} ) SET ( LIBEDATASERVER1.2_LIBRARIES ${LIBEDATASERVER1.2_LIBRARIES} ${ORBIT2_LIBRARIES} ) ENDIF ( ORBIT2_FOUND ) ENDIF ( NOT ORBIT2_FOUND ) IF ( NOT LIBXML2_FOUND ) FIND_PACKAGE ( LibXml2 REQUIRED ) IF ( LIBXML2_FOUND ) SET ( LIBEDATASERVER1.2_INCLUDE_DIRS ${LIBEDATASERVER1.2_INCLUDE_DIRS} ${LIBXML2_INCLUDE_DIRS} ) SET ( LIBEDATASERVER1.2_LIBRARIES ${LIBEDATASERVER1.2_LIBRARIES} ${LIBXML2_LIBRARIES} ) ENDIF ( LIBXML2_FOUND ) ENDIF ( NOT LIBXML2_FOUND ) IF ( NOT GLIB2_FOUND ) FIND_PACKAGE ( GLIB2 REQUIRED ) IF ( GLIB2_FOUND ) SET ( LIBEDATASERVER1.2_INCLUDE_DIRS ${LIBEDATASERVER1.2_INCLUDE_DIRS} ${GLIB2_INCLUDE_DIRS} ${GLIBCONFIG_INCLUDE_DIR} ) SET ( LIBEDATASERVER1.2_LIBRARIES ${LIBEDATASERVER1.2_LIBRARIES} ${GLIB2_LIBRARIES} ) ENDIF ( GLIB2_FOUND ) ENDIF ( NOT GLIB2_FOUND ) # Report results IF ( LIBEDATASERVER1.2_LIBRARIES AND LIBEDATASERVER1.2_INCLUDE_DIRS AND _libedataserver1.2_FOUND ) SET( LIBEDATASERVER1.2_FOUND 1 ) IF ( NOT LibEDataServer1.2_FIND_QUIETLY ) MESSAGE( STATUS "Found libedataserver-1.2: ${LIBEDATASERVER1.2_LIBRARIES}" ) ENDIF ( NOT LibEDataServer1.2_FIND_QUIETLY ) ELSE ( LIBEDATASERVER1.2_LIBRARIES AND LIBEDATASERVER1.2_INCLUDE_DIRS AND _libedataserver1.2_FOUND ) IF ( LibEDataServer1.2_FIND_REQUIRED ) MESSAGE( SEND_ERROR "Could NOT find libedataserver-1.2" ) ELSE ( LibEDataServer1.2_FIND_REQUIRED ) IF ( NOT LibEDataServer1.2_FIND_QUIETLY ) MESSAGE( STATUS "Could NOT find libedataserver-1.2" ) ENDIF ( NOT LibEDataServer1.2_FIND_QUIETLY ) ENDIF ( LibEDataServer1.2_FIND_REQUIRED ) ENDIF ( LIBEDATASERVER1.2_LIBRARIES AND LIBEDATASERVER1.2_INCLUDE_DIRS AND _libedataserver1.2_FOUND ) ENDIF ( NOT LIBEDATASERVER1.2_FOUND AND NOT PKG_CONFIG_FOUND ) # Hide advanced variables from CMake GUIs MARK_AS_ADVANCED( LIBEDATASERVER1.2_LIBRARIES LIBEDATASERVER1.2_INCLUDE_DIRS ) libsyncml-0.5.4/cmake/modules/FindGnomeVfs2.cmake100644 1750 1750 11024 11211710410 21600 0ustar00bellmichbellmich# - Try to find gnomevfs2 # Find gnomevfs2 headers, libraries and the answer to all questions. # # GNOMEVFS2_FOUND True if gnomevfs2 got found # GNOMEVFS2_INCLUDEDIR Location of gnomevfs2 headers # GNOMEVFS2_LIBRARIES List of libaries to use gnomevfs2 # GNOMEVFS2_DEFINITIONS Definitions to compile gnomevfs2 # # Copyright (c) 2007 Juha Tuomala # Copyright (c) 2007 Daniel Gollub # Copyright (c) 2007 Alban Browaeys # # Redistribution and use is allowed according to the terms of the New # BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # INCLUDE( FindPkgConfig ) # Take care about gnome-vfs-2.0.pc settings IF ( GnomeVfs2_FIND_REQUIRED ) SET( _pkgconfig_REQUIRED "REQUIRED" ) ELSE ( GnomeVfs2_FIND_REQUIRED ) SET( _pkgconfig_REQUIRED "" ) ENDIF ( GnomeVfs2_FIND_REQUIRED ) pkg_search_module( GNOMEVFS2 ${_pkgconfig_REQUIRED} gnome-vfs-2.0 ) # Look for gnomevfs2 include dir and libraries w/o pkgconfig IF ( NOT GNOMEVFS2_FOUND AND NOT PKG_CONFIG_FOUND ) FIND_PATH( _gnomevfs2_include_DIR libgnomevfs/gnome-vfs.h PATH_SUFFIXES gnome-vfs-2.0 PATHS /opt/local/include/ /sw/include/ /usr/local/include/ /usr/include/ ) FIND_PATH( _gnomevfs2_filesize_include_DIR gnome-vfs-file-size.h PATHS /opt/gnome/lib64/gnome-vfs-2.0/include /opt/gnome/lib/gnome-vfs-2.0/include /opt/lib/gnome-vfs-2.0/include /opt/local/lib/gnome-vfs-2.0/include /sw/lib/gnome-vfs-2.0/include /usr/lib64/gnome-vfs-2.0/include /usr/lib/gnome-vfs-2.0/include ) FIND_LIBRARY( _gnomevfs2_link_DIR gnomevfs-2 PATHS /opt/local/lib /sw/lib /usr/lib /usr/local/lib /usr/lib64 /usr/local/lib64 /opt/lib64 ) IF ( _gnomevfs2_include_DIR AND _gnomevfs2_filesize_include_DIR AND _gnomevfs2_link_DIR ) SET ( _gnomevfs2_FOUND TRUE ) ENDIF ( _gnomevfs2_include_DIR AND _gnomevfs2_filesize_include_DIR AND _gnomevfs2_link_DIR ) IF ( _gnomevfs2_FOUND ) SET ( GNOMEVFS2_INCLUDE_DIRS ${_gnomevfs2_include_DIR} ${_gnomevfs2_filesize_include_DIR} ) SET ( GNOMEVFS2_LIBRARIES ${_gnomevfs2_link_DIR} ) ENDIF ( _gnomevfs2_FOUND ) # Handle dependencies IF ( NOT GCONF2_FOUND ) FIND_PACKAGE( GConf2 REQUIRED) IF ( GCONF2_FOUND ) SET ( GNOMEVFS2_INCLUDE_DIRS ${GNOMEVFS2_INCLUDE_DIRS} ${GCONF2_INCLUDE_DIRS} ) SET ( GNOMEVFS2_LIBRARIES ${GNOMEVFS2_LIBRARIES} ${GCONF2_LIBRARIES} ) ENDIF ( GCONF2_FOUND ) ENDIF ( NOT GCONF2_FOUND ) IF ( NOT GLIB2_FOUND ) FIND_PACKAGE( GLIB2 REQUIRED) IF ( GTHREAD2_FOUND ) SET ( GNOMEVFS2_INCLUDE_DIRS ${GNOMEVFS2_INCLUDE_DIRS} ${GTHREAD2_INCLUDE_DIR} ) SET ( GNOMEVFS2_LIBRARIES ${GNOMEVFS2_LIBRARIES} ${GTHREAD2_LIBRARY} ) ENDIF ( GTHREAD2_FOUND ) IF ( GMODULE2_FOUND ) SET ( GNOMEVFS2_INCLUDE_DIRS ${GNOMEVFS2_INCLUDE_DIRS} ${GMODULE2_INCLUDE_DIR} ) SET ( GNOMEVFS2_LIBRARIES ${GNOMEVFS2_LIBRARIES} ${GMODULE2_LIBRARY} ) ENDIF ( GMODULE2_FOUND ) IF ( GOBJECT2_FOUND ) SET ( GNOMEVFS2_INCLUDE_DIRS ${GNOMEVFS2_INCLUDE_DIRS} ${GOBJECT2_INCLUDE_DIR} ) SET ( GNOMEVFS2_LIBRARIES ${GNOMEVFS2_LIBRARIES} ${GOBJECT2_LIBRARY} ) ENDIF ( GOBJECT2_FOUND ) IF ( GLIB2_FOUND ) SET ( GNOMEVFS2_INCLUDE_DIRS ${GNOMEVFS2_INCLUDE_DIRS} ${GLIB2_INCLUDE_DIR} ${GLIBCONFIG_INCLUDE_DIR} ) SET ( GNOMEVFS2_LIBRARIES ${GNOMEVFS2_LIBRARIES} ${GLIB2_LIBRARY} ) ENDIF ( GLIB2_FOUND ) ENDIF ( NOT GLIB2_FOUND ) # Report results IF ( GNOMEVFS2_LIBRARIES AND GNOMEVFS2_INCLUDE_DIRS AND _gnomevfs2_FOUND ) SET( GNOMEVFS2_FOUND 1 ) IF ( NOT GnomeVfs2_FIND_QUIETLY ) MESSAGE( STATUS "Found gnomevfs2: ${GNOMEVFS2_LIBRARIES} ${GNOMEVFS2_INCLUDE_DIRS}" ) ENDIF ( NOT GnomeVfs2_FIND_QUIETLY ) ELSE ( GNOMEVFS2_LIBRARIES AND GNOMEVFS2_INCLUDE_DIRS AND _gnomevfs2_FOUND ) IF ( GnomeVfs2_FIND_REQUIRED ) MESSAGE( SEND_ERROR "Could NOT find gnomevfs2" ) ELSE ( GnomeVfs2_FIND_REQUIRED ) IF ( NOT GnomeVfs2_FIND_QUIETLY ) MESSAGE( STATUS "Could NOT find gnomevfs2" ) ENDIF ( NOT GnomeVfs2_FIND_QUIETLY ) ENDIF ( GnomeVfs2_FIND_REQUIRED ) ENDIF ( GNOMEVFS2_LIBRARIES AND GNOMEVFS2_INCLUDE_DIRS AND _gnomevfs2_FOUND ) ENDIF ( NOT GNOMEVFS2_FOUND AND NOT PKG_CONFIG_FOUND ) # Hide advanced variables from CMake GUIs MARK_AS_ADVANCED( GNOMEVFS2_LIBRARIES GNOMEVFS2_INCLUDE_DIRS ) libsyncml-0.5.4/cmake/modules/FindGNUTLS.cmake100644 1750 1750 3302 11211710410 20766 0ustar00bellmichbellmich# - Try to find GNUTLS # Find GNUTLS headers, libraries and the answer to all questions. # # GNUTLS_FOUND True if gnutls got found # GNUTLS_INCLUDE_DIRS Location of gnutls headers # GNUTLS_LIBRARIES List of libaries to use gnutls # # Copyright (c) 2007 Bjoern Ricks # # Redistribution and use is allowed according to the terms of the New # BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # INCLUDE( FindPkgConfig ) IF ( GNUTLS_FIND_REQUIRED ) SET( _pkgconfig_REQUIRED "REQUIRED" ) ELSE( GNUTLS_FIND_REQUIRED ) SET( _pkgconfig_REQUIRED "" ) ENDIF ( GNUTLS_FIND_REQUIRED ) IF ( GNUTLS_MIN_VERSION ) PKG_SEARCH_MODULE( GNUTLS ${_pkgconfig_REQUIRED} gnutls>=${GNUTLS_MIN_VERSION} ) ELSE ( GNUTLS_MIN_VERSION ) PKG_SEARCH_MODULE( GNUTLS ${_pkgconfig_REQUIRED} gnutls ) ENDIF ( GNUTLS_MIN_VERSION ) IF( NOT GNUTLS_FOUND AND NOT PKG_CONFIG_FOUND ) FIND_PATH( GNUTLS_INCLUDE_DIRS gnutls/gnutls.h ) FIND_LIBRARY( GNUTLS_LIBRARIES gnutls) # Report results IF ( GNUTLS_LIBRARIES AND GNUTLS_INCLUDE_DIRS ) SET( GNUTLS_FOUND 1 ) IF ( NOT GNUTLS_FIND_QUIETLY ) MESSAGE( STATUS "Found gnutls: ${GNUTLS_LIBRARIES}" ) ENDIF ( NOT GNUTLS_FIND_QUIETLY ) ELSE ( GNUTLS_LIBRARIES AND GNUTLS_INCLUDE_DIRS ) IF ( GNUTLS_FIND_REQUIRED ) MESSAGE( SEND_ERROR "Could NOT find gnutls" ) ELSE ( GNUTLS_FIND_REQUIRED ) IF ( NOT GNUTLS_FIND_QUIETLY ) MESSAGE( STATUS "Could NOT find gnutls" ) ENDIF ( NOT GNUTLS_FIND_QUIETLY ) ENDIF ( GNUTLS_FIND_REQUIRED ) ENDIF ( GNUTLS_LIBRARIES AND GNUTLS_INCLUDE_DIRS ) ENDIF( NOT GNUTLS_FOUND AND NOT PKG_CONFIG_FOUND ) MARK_AS_ADVANCED( GNUTLS_LIBRARIES GNUTLS_INCLUDE_DIRS ) libsyncml-0.5.4/cmake/modules/FindLibDbusGlib.cmake100644 1750 1750 3727 11211710410 22107 0ustar00bellmichbellmich# - Try to find LIBDBUS GLIB Bindings # Find LIBDBUSGLIB headers, libraries and the answer to all questions. # # LIBDBUSGLIB_FOUND True if libdbus-glib got found # LIBDBUSGLIB_INCLUDE_DIRS Location of libdbus-glib headers # LIBDBUSGLIB_LIBRARIES List of libraries to use libdbus-glib # # Copyright (c) 2008 Bjoern Ricks # # Redistribution and use is allowed according to the terms of the New # BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # INCLUDE( FindPkgConfig ) IF ( LibDbusGlib_FIND_REQUIRED ) SET( _pkgconfig_REQUIRED "REQUIRED" ) ELSE( LibDbusGlib_FIND_REQUIRED ) SET( _pkgconfig_REQUIRED "" ) ENDIF ( LibDbusGlib_FIND_REQUIRED ) IF ( LIBDBUSGLIB_MIN_VERSION ) PKG_SEARCH_MODULE( LIBDBUSGLIB ${_pkgconfig_REQUIRED} dbus-glib-1>=${LIBDBUSGLIB_MIN_VERSION} ) ELSE ( LIBDBUSGLIB_MIN_VERSION ) PKG_SEARCH_MODULE( LIBDBUSGLIB ${_pkgconfig_REQUIRED} dbus-glib-1 ) ENDIF ( LIBDBUSGLIB_MIN_VERSION ) IF( NOT LIBDBUSGLIB_FOUND AND NOT PKG_CONFIG_FOUND ) FIND_PATH( LIBDBUSGLIB_INCLUDE_DIRS dbus/dbus-glib.h PATH_SUFFIXES dbus-1.0 dbus ) FIND_LIBRARY( LIBDBUSGLIB_LIBRARIES dbus-glib dbus-glib-1) # Report results IF ( LIBDBUSGLIB_LIBRARIES AND LIBDBUSGLIB_INCLUDE_DIRS ) SET( LIBDBUSGLIB_FOUND 1 ) IF ( NOT LIBDBUSGLIB_FIND_QUIETLY ) MESSAGE( STATUS "Found libdbus-glib: ${LIBDBUSGLIB_LIBRARIES}" ) ENDIF ( NOT LIBDBUSGLIB_FIND_QUIETLY ) ELSE ( LIBDBUSGLIB_LIBRARIES AND LIBDBUSGLIB_INCLUDE_DIRS ) IF ( LIBDBUSGLIB_FIND_REQUIRED ) MESSAGE( SEND_ERROR "Could NOT find libdbus-glib" ) ELSE ( LIBDBUSGLIB_FIND_REQUIRED ) IF ( NOT LIBDBUSGLIB_FIND_QUIETLY ) MESSAGE( STATUS "Could NOT find libdbus-glib" ) ENDIF ( NOT LIBDBUSGLIB_FIND_QUIETLY ) ENDIF ( LIBDBUSGLIB_FIND_REQUIRED ) ENDIF ( LIBDBUSGLIB_LIBRARIES AND LIBDBUSGLIB_INCLUDE_DIRS ) ENDIF( NOT LIBDBUSGLIB_FOUND AND NOT PKG_CONFIG_FOUND ) MARK_AS_ADVANCED( LIBDBUSGLIB_LIBRARIES LIBDBUSGLIB_INCLUDE_DIRS )libsyncml-0.5.4/cmake/modules/FindGMODULE2.cmake100644 1750 1750 3670 11211710410 21140 0ustar00bellmichbellmich# - Try to find GModule2 # Find GModule headers, libraries and the answer to all questions. # # GMODULE2_FOUND True if GMODULE2 got found # GMODULE2_INCLUDE_DIRS Location of GMODULE2 headers # GMODULE2_LIBRARIES List of libraries to use GMODULE2 # # Copyright (c) 2008 Bjoern Ricks # # Redistribution and use is allowed according to the terms of the New # BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # INCLUDE( FindPkgConfig ) IF ( GMODULE2_FIND_REQUIRED ) SET( _pkgconfig_REQUIRED "REQUIRED" ) ELSE( GMODULE2_FIND_REQUIRED ) SET( _pkgconfig_REQUIRED "" ) ENDIF ( GMODULE2_FIND_REQUIRED ) IF ( GMODULE2_MIN_VERSION ) PKG_SEARCH_MODULE( GMODULE2 ${_pkgconfig_REQUIRED} gmodule-2.0>=${GMODULE2_MIN_VERSION} ) ELSE ( GMODULE2_MIN_VERSION ) PKG_SEARCH_MODULE( GMODULE2 ${_pkgconfig_REQUIRED} gmodule-2.0 ) ENDIF ( GMODULE2_MIN_VERSION ) IF( NOT GMODULE2_FOUND AND NOT PKG_CONFIG_FOUND ) FIND_PATH( GMODULE2_INCLUDE_DIRS gmodule.h PATH_SUFFIXES glib-2.0 ) IF ( APPLE ) FIND_LIBRARY( GMODULE2_LIBRARIES glib ) ELSE ( APPLE ) FIND_LIBRARY( GMODULE2_LIBRARIES NAMES gmodule-2.0 gmodule ) ENDIF (APPLE) # Report results IF ( GMODULE2_LIBRARIES AND GMODULE2_INCLUDE_DIRS ) SET( GMODULE2_FOUND 1 ) IF ( NOT GMODULE2_FIND_QUIETLY ) MESSAGE( STATUS "Found GMODULE2: ${GMODULE2_LIBRARIES} ${GMODULE2_INCLUDE_DIRS}" ) ENDIF ( NOT GMODULE2_FIND_QUIETLY ) ELSE ( GMODULE2_LIBRARIES AND GMODULE2_INCLUDE_DIRS ) IF ( GMODULE2_FIND_REQUIRED ) MESSAGE( SEND_ERROR "Could NOT find GMODULE2" ) ELSE ( GMODULE2_FIND_REQUIRED ) IF ( NOT GMODULE2_FIND_QUIETLY ) MESSAGE( STATUS "Could NOT find GMODULE2" ) ENDIF ( NOT GMODULE2_FIND_QUIETLY ) ENDIF ( GMODULE2_FIND_REQUIRED ) ENDIF ( GMODULE2_LIBRARIES AND GMODULE2_INCLUDE_DIRS ) ENDIF( NOT GMODULE2_FOUND AND NOT PKG_CONFIG_FOUND ) MARK_AS_ADVANCED( GMODULE2_LIBRARIES GMODULE2_INCLUDE_DIRS )libsyncml-0.5.4/cmake/modules/FindEDataServer1.0.cmake100644 1750 1750 12437 11211710410 22367 0ustar00bellmichbellmich# - Try to find libedataserver1.0 components # Find libedataserver 1.0 headers, libraries and the answer to all questions. # # LIBEDATASERVER1.0_FOUND True if libedataserver1.0 got found # LIBEDATASERVER1.0_INCLUDE_DIRS Location of libedataserver1.0 headers # LIBEDATASERVER1.0_LIBRARIES List of libaries to use libedataserver1.0 # LIBEDATASERVER1.0_DEFINITIONS Definitions to compile libedataserver1.0 # # Copyright (c) 2007 Juha Tuomala # Copyright (c) 2007 Daniel Gollub # Copyright (c) 2007 Alban Browaeys # # Redistribution and use is allowed according to the terms of the New # BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # INCLUDE( FindPkgConfig ) # Take care about libedataserver-1.0.pc settings IF ( EDataServer1.0_FIND_REQUIRED ) SET( _pkgconfig_REQUIRED "REQUIRED" ) ELSE ( EDataServer1.0_FIND_REQUIRED ) SET( _pkgconfig_REQUIRED "" ) ENDIF ( EDataServer1.0_FIND_REQUIRED ) pkg_search_module( LIBEDATASERVER1.0 ${_pkgconfig_REQUIRED} libedataserver-1.0 ) # Look for libedataserver1.0 include dir and libraries w/o pkg-config. IF ( NOT LIBEDATASERVER1.0_FOUND AND NOT PKG_CONFIG_FOUND ) FIND_PATH( _libedataserver1.0_include_DIR libedataserver/e-account.h PATH_SUFFIXES evolution-data-server-1.12 evolution-data-server-1.10 evolution-data-server-1.8 evolution-data-server-1.6 evolution-data-server-1.4 evolution-data-server-1.0 PATHS /opt/local/include/ /sw/include/ /usr/local/include/ /usr/include/ ) FIND_LIBRARY( _libedataserver1.0_link_DIR edataserver-1.0 PATHS /opt/local/lib /sw/lib /usr/lib /usr/local/lib /usr/lib64 /usr/local/lib64 /opt/lib64 ) IF ( _libedataserver1.0_include_DIR AND _libedataserver1.0_link_DIR ) SET ( _libedataserver1.0_FOUND TRUE ) ENDIF ( _libedataserver1.0_include_DIR AND _libedataserver1.0_link_DIR ) IF ( _libedataserver1.0_FOUND ) SET ( LIBEDATASERVER1.0_INCLUDE_DIRS ${_libedataserver1.0_include_DIR} ) SET ( LIBEDATASERVER1.0_LIBRARIES ${_libedataserver1.0_link_DIR} ) ENDIF ( _libedataserver1.0_FOUND ) # Handle dependencies IF ( NOT GCONF2_FOUND ) FIND_PACKAGE ( GConf2 REQUIRED ) IF ( GCONF2_FOUND ) SET ( LIBEDATASERVER1.0_INCLUDE_DIRS ${LIBEDATASERVER1.0_INCLUDE_DIRS} ${GCONF2_INCLUDE_DIRS} ) SET ( LIBEDATASERVER1.0_LIBRARIES ${LIBEDATASERVER1.0_LIBRARIES} ${GCONF2_LIBRARIES} ) ENDIF ( GCONF2_FOUND ) ENDIF ( NOT GCONF2_FOUND ) IF ( NOT BONOBO2_FOUND ) SET ( BONOBO2_MIN_VERSION "2.4.2" ) FIND_PACKAGE ( BONOBO2 REQUIRED ) IF ( BONOBO2_FOUND ) SET ( LIBEDATASERVER1.0_INCLUDE_DIRS ${LIBEDATASERVER1.0_INCLUDE_DIRS} ${BONOBO2_INCLUDE_DIRS} ) SET ( LIBEDATASERVER1.0_LIBRARIES ${LIBEDATASERVER1.0_LIBRARIES} ${BONOBO2_LIBRARIES} ) ENDIF ( BONOBO2_FOUND ) ENDIF ( NOT BONOBO2_FOUND ) IF ( NOT ORBIT2_FOUND ) SET ( ORBIT2_MIN_VERSION "2.9.8" ) FIND_PACKAGE ( ORBit2 REQUIRED ) IF ( ORBIT2_FOUND ) SET ( LIBEDATASERVER1.0_INCLUDE_DIRS ${LIBEDATASERVER1.0_INCLUDE_DIRS} ${ORBIT2_INCLUDE_DIRS} ) SET ( LIBEDATASERVER1.0_LIBRARIES ${LIBEDATASERVER1.0_LIBRARIES} ${ORBIT2_LIBRARIES} ) ENDIF ( ORBIT2_FOUND ) ENDIF ( NOT ORBIT2_FOUND ) IF ( NOT LIBXML2_FOUND ) FIND_PACKAGE ( LibXml2 REQUIRED ) IF ( LIBXML2_FOUND ) SET ( LIBEDATASERVER1.0_INCLUDE_DIRS ${LIBEDATASERVER1.0_INCLUDE_DIRS} ${LIBXML2_INCLUDE_DIRS} ) SET ( LIBEDATASERVER1.0_LIBRARIES ${LIBEDATASERVER1.0_LIBRARIES} ${LIBXML2_LIBRARY} ) ENDIF ( LIBXML2_FOUND ) ENDIF ( NOT LIBXML2_FOUND ) IF ( NOT GLIB2_FOUND ) FIND_PACKAGE ( GLIB2 REQUIRED ) IF ( GLIB2_FOUND ) SET ( LIBEDATASERVER1.0_INCLUDE_DIRS ${LIBEDATASERVER1.0_INCLUDE_DIRS} ${GLIB2_INCLUDE_DIRS} ${GLIBCONFIG_INCLUDE_DIR} ) SET ( LIBEDATASERVER1.0_LIBRARIES ${LIBEDATASERVER1.0_LIBRARIES} ${GLIB2_LIBRARIES} ) ENDIF ( GLIB2_FOUND ) ENDIF ( NOT GLIB2_FOUND ) # Report results IF ( LIBEDATASERVER1.0_LIBRARIES AND LIBEDATASERVER1.0_INCLUDE_DIRS AND _libedataserver1.0_FOUND ) SET( LIBEDATASERVER1.0_FOUND 1 ) IF ( NOT LibEDataServer1.0_FIND_QUIETLY ) MESSAGE( STATUS "Found libedataserver-1.0: ${LIBEDATASERVER1.0_LIBRARIES}" ) ENDIF ( NOT LibEDataServer1.0_FIND_QUIETLY ) ELSE ( LIBEDATASERVER1.0_LIBRARIES AND LIBEDATASERVER1.0_INCLUDE_DIRS AND _libedataserver1.0_FOUND ) IF ( LibEDataServer1.0_FIND_REQUIRED ) MESSAGE( SEND_ERROR "Could NOT find libedataserver-1.0" ) ELSE ( LibEDataServer1.0_FIND_REQUIRED ) IF ( NOT LibEDataServer1.0_FIND_QUIETLY ) MESSAGE( STATUS "Could NOT find libedataserver-1.0" ) ENDIF ( NOT LibEDataServer1.0_FIND_QUIETLY ) ENDIF ( LibEDataServer1.0_FIND_REQUIRED ) ENDIF ( LIBEDATASERVER1.0_LIBRARIES AND LIBEDATASERVER1.0_INCLUDE_DIRS AND _libedataserver1.0_FOUND ) ENDIF ( NOT LIBEDATASERVER1.0_FOUND AND NOT PKG_CONFIG_FOUND ) # Hide advanced variables from CMake GUIs MARK_AS_ADVANCED( LIBEDATASERVER1.0_LIBRARIES LIBEDATASERVER1.0_INCLUDE_DIRS ) libsyncml-0.5.4/cmake/modules/FindECal1.0.cmake100644 1750 1750 10006 11211710410 21014 0ustar00bellmichbellmich# - Try to find libecal1.0 components # Find libecal 1.0 headers, libraries and the answer to all questions. # # LIBECAL1.0_FOUND True if libecal1.0 got found # LIBECAL1.0_INCLUDE_DIRS Location of libecal1.0 headers # LIBECAL1.0_LIBRARIES List of libaries to use libecal1.0 # LIBECAL1.0_DEFINITIONS Definitions to compile libecal1.0 # # Copyright (c) 2007 Juha Tuomala # Copyright (c) 2007 Daniel Gollub # Copyright (c) 2007 Alban Browaeys # # Redistribution and use is allowed according to the terms of the New # BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # INCLUDE( FindPkgConfig ) # Take care about libecal-1.0.pc settings IF ( ECal1.0_FIND_REQUIRED ) SET( _pkgconfig_REQUIRED "REQUIRED" ) ELSE ( ECal1.0_FIND_REQUIRED ) SET( _pkgconfig_REQUIRED "" ) ENDIF ( ECal1.0_FIND_REQUIRED ) pkg_search_module( LIBECAL1.0 ${_pkgconfig_REQUIRED} libecal-1.0 ) # Look for libecal1.0 include dir and libraries w/o pkg-config. IF ( NOT LIBECAL1.0_FOUND AND NOT PKG_CONFIG_FOUND ) FIND_PATH( _libecal1.0_include_DIR libecal/e-cal.h PATH_SUFFIXES evolution-data-server-1.12 evolution-data-server-1.10 evolution-data-server-1.8 evolution-data-server-1.6 evolution-data-server-1.4 evolution-data-server-1.0 PATHS /opt/local/include/ /sw/include/ /usr/local/include/ /usr/include/ ) FIND_LIBRARY( _libecal1.0_link_DIR ecal-1.0 PATHS /opt/local/lib /sw/lib /usr/lib /usr/local/lib /usr/lib64 /usr/local/lib64 /opt/lib64 ) IF ( _libecal1.0_include_DIR AND _libecal1.0_link_DIR ) SET ( _libecal1.0_FOUND TRUE ) ENDIF ( _libecal1.0_include_DIR AND _libecal1.0_link_DIR ) IF ( _libecal1.0_FOUND ) SET ( LIBECAL1.0_INCLUDE_DIRS ${_libecal1.0_include_DIR} ) SET ( LIBECAL1.0_LIBRARIES ${_libecal1.0_link_DIR} ) ENDIF ( _libecal1.0_FOUND ) # Handle dependencies IF ( NOT LIBEDATASERVER1.0_FOUND ) FIND_PACKAGE ( EDataServer1.0 REQUIRED ) IF ( LIBEDATASERVER1.0_FOUND ) SET ( LIBECAL1.0_INCLUDE_DIRS ${LIBECAL1.0_INCLUDE_DIRS} ${LIBEDATASERVER1.0_INCLUDE_DIRS} ) SET ( LIBECAL1.0_LIBRARIES ${LIBECAL1.0_LIBRARIES} ${LIBEDATASERVER1.0_LIBRARIES} ) ENDIF ( LIBEDATASERVER1.0_FOUND ) ENDIF ( NOT LIBEDATASERVER1.0_FOUND ) IF ( NOT LIBGNOME2_FOUND ) FIND_PACKAGE ( LibGnome2 REQUIRED ) IF ( LIBGNOME2_FOUND ) SET ( LIBECAL1.0_INCLUDE_DIRS ${LIBECAL1.0_INCLUDE_DIRS} ${LIBGNOME2_INCLUDE_DIRS} ) SET ( LIBECAL1.0_LIBRARIES ${LIBECAL1.0_LIBRARIES} ${LIBGNOME2_LIBRARIES} ) ENDIF ( LIBGNOME2_FOUND ) ENDIF ( NOT LIBGNOME2_FOUND ) IF ( NOT BONOBO2_FOUND ) FIND_PACKAGE ( BONOBO2 REQUIRED ) IF ( BONOBO2_FOUND ) SET ( LIBECAL1.0_INCLUDE_DIRS ${LIBECAL1.0_INCLUDE_DIRS} ${BONOBO2_INCLUDE_DIRS} ) SET ( LIBECAL1.0_LIBRARIES ${LIBECAL1.0_LIBRARIES} ${BONOBO2_LIBRARIES} ) ENDIF ( BONOBO2_FOUND ) ENDIF ( NOT BONOBO2_FOUND ) # Report results IF ( LIBECAL1.0_LIBRARIES AND LIBECAL1.0_INCLUDE_DIRS AND _libecal1.0_FOUND ) SET( LIBECAL1.0_FOUND 1 ) IF ( NOT ECal1.0_FIND_QUIETLY ) MESSAGE( STATUS "Found libecal-1.0: ${LIBECAL1.0_LIBRARIES}" ) ENDIF ( NOT ECal1.0_FIND_QUIETLY ) ELSE ( LIBECAL1.0_LIBRARIES AND LIBECAL1.0_INCLUDE_DIRS AND _libecal1.0_FOUND ) IF ( ECal1.0_FIND_REQUIRED ) MESSAGE( SEND_ERROR "Could NOT find libecal-1.0" ) ELSE ( ECal1.0_FIND_REQUIRED ) IF ( NOT ECal1.0_FIND_QUIETLY ) MESSAGE( STATUS "Could NOT find libecal-1.0" ) ENDIF ( NOT ECal1.0_FIND_QUIETLY ) ENDIF ( ECal1.0_FIND_REQUIRED ) ENDIF ( LIBECAL1.0_LIBRARIES AND LIBECAL1.0_INCLUDE_DIRS AND _libecal1.0_FOUND ) ENDIF ( NOT LIBECAL1.0_FOUND AND NOT PKG_CONFIG_FOUND ) # Hide advanced variables from CMake GUIs MARK_AS_ADVANCED( LIBECAL1.0_LIBRARIES LIBECAL1.0_INCLUDE_DIRS ) libsyncml-0.5.4/cmake/modules/FindEvolutionDataServer1.0.cmake100644 1750 1750 6426 11211710410 24150 0ustar00bellmichbellmich# - Try to find evolutiondataserver1.0 components # Find evolutiondataserver 1.0 headers, libraries and the answer to all questions. # # EVOLUTIONDATASERVER1.0_FOUND True if evolutiondataserver1.0 got found # EVOLUTIONDATASERVER1.0_INCLUDE_DIRS Location of evolutiondataserver1.0 headers # EVOLUTIONDATASERVER1.0_LIBRARIES List of libaries to use evolutiondataserver1.0 # EVOLUTIONDATASERVER1.0_DEFINITIONS Definitions to compile evolutiondataserver1.0 # # Copyright (c) 2007 Juha Tuomala # Copyright (c) 2007 Daniel Gollub # Copyright (c) 2007 Alban Browaeys # # Redistribution and use is allowed according to the terms of the New # BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # INCLUDE( FindPkgConfig ) # Take care about evolution-data-server-1.0.pc settings IF ( EvolutionDataServer1.0_FIND_REQUIRED ) SET( _pkgconfig_REQUIRED "REQUIRED" ) ELSE ( EvolutionDataServer1.0_FIND_REQUIRED ) SET( _pkgconfig_REQUIRED "" ) ENDIF ( EvolutionDataServer1.0_FIND_REQUIRED ) pkg_search_module( EVOLUTIONDATASERVER1.0 ${_pkgconfig_REQUIRED} evolution-data-server-1.0 ) # Look for evolutiondataserver1.0 include dir and libraries w/o pkg-config. IF ( NOT EVOLUTIONDATASERVER1.0_FOUND AND NOT PKG_CONFIG_FOUND ) # Handle dependencies IF ( NOT LIBGNOME2_FOUND ) FIND_PACKAGE ( LibGnome2 REQUIRED ) IF ( LIBGNOME2_FOUND ) SET ( EVOLUTIONDATASERVER1.0_INCLUDE_DIRS ${EVOLUTIONDATASERVER1.0_INCLUDE_DIRS} ${LIBGNOME2_INCLUDE_DIRS} ) SET ( EVOLUTIONDATASERVER1.0_LIBRARIES ${EVOLUTIONDATASERVER1.0_LIBRARIES} ${LIBGNOME2_LIBRARIES} ) ENDIF ( LIBGNOME2_FOUND ) ENDIF ( NOT LIBGNOME2_FOUND ) IF ( NOT BONOBO2_FOUND ) SET ( BONOBO2_MIN_VERSION "2.4.2" ) FIND_PACKAGE ( BONOBO2 REQUIRED ) IF ( BONOBO2_FOUND ) SET ( EVOLUTIONDATASERVER1.0_INCLUDE_DIRS ${EVOLUTIONDATASERVER1.0_INCLUDE_DIRS} ${BONOBO2_INCLUDE_DIRS} ) SET ( EVOLUTIONDATASERVER1.0_LIBRARIES ${EVOLUTIONDATASERVER1.0_LIBRARIES} ${BONOBO2_LIBRARIES} ) ENDIF ( BONOBO2_FOUND ) ENDIF ( NOT BONOBO2_FOUND ) # Report results IF ( EVOLUTIONDATASERVER1.0_LIBRARIES AND EVOLUTIONDATASERVER1.0_INCLUDE_DIRS ) SET( EVOLUTIONDATASERVER1.0_FOUND 1 ) IF ( NOT EvolutionDataServer1.0_FIND_QUIETLY ) MESSAGE( STATUS "Found evolutiondataserver-1.0: ${EVOLUTIONDATASERVER1.0_LIBRARIES}" ) ENDIF ( NOT EvolutionDataServer1.0_FIND_QUIETLY ) ELSE ( EVOLUTIONDATASERVER1.0_LIBRARIES AND EVOLUTIONDATASERVER1.0_INCLUDE_DIRS ) IF ( EvolutionDataServer1.0_FIND_REQUIRED ) MESSAGE( SEND_ERROR "Could NOT find evolutiondataserver-1.0" ) ELSE ( EvolutionDataServer1.0_FIND_REQUIRED ) IF ( NOT EvolutionDataServer1.0_FIND_QUIETLY ) MESSAGE( STATUS "Could NOT find evolutiondataserver-1.0" ) ENDIF ( NOT EvolutionDataServer1.0_FIND_QUIETLY ) ENDIF ( EvolutionDataServer1.0_FIND_REQUIRED ) ENDIF ( EVOLUTIONDATASERVER1.0_LIBRARIES AND EVOLUTIONDATASERVER1.0_INCLUDE_DIRS ) ENDIF ( NOT EVOLUTIONDATASERVER1.0_FOUND AND NOT PKG_CONFIG_FOUND ) # Hide advanced variables from CMake GUIs MARK_AS_ADVANCED( EVOLUTIONDATASERVER1.0_LIBRARIES EVOLUTIONDATASERVER1.0_INCLUDE_DIRS ) libsyncml-0.5.4/cmake/modules/FindECal1.2.cmake100644 1750 1750 10054 11211710410 21021 0ustar00bellmichbellmich# - Try to find libecal1.2 components # Find libecal 1.2 headers, libraries and the answer to all questions. # # LIBECAL1.2_FOUND True if libecal1.2 got found # LIBECAL1.2_INCLUDE_DIRS Location of libecal1.2 headers # LIBECAL1.2_LIBRARIES List of libaries to use libecal1.2 # LIBECAL1.2_DEFINITIONS Definitions to compile libecal1.2 # # Copyright (c) 2007 Juha Tuomala # Copyright (c) 2007 Daniel Gollub # Copyright (c) 2007 Alban Browaeys # # Redistribution and use is allowed according to the terms of the New # BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # INCLUDE( FindPkgConfig ) # Take care about libecal-1.2.pc settings IF ( ECal1.2_FIND_REQUIRED ) SET( _pkgconfig_REQUIRED "REQUIRED" ) ELSE ( ECal1.2_FIND_REQUIRED ) SET( _pkgconfig_REQUIRED "" ) ENDIF ( ECal1.2_FIND_REQUIRED ) pkg_search_module( LIBECAL1.2 ${_pkgconfig_REQUIRED} libecal-1.2 ) # Look for libecal1.2 include dir and libraries w/o pkg-config. IF ( NOT LIBECAL1.2_FOUND AND NOT PKG_CONFIG_FOUND ) FIND_PATH( _libecal1.2_include_DIR libecal/e-cal.h PATH_SUFFIXES evolution-data-server-1.12 evolution-data-server-1.10 evolution-data-server-1.8 evolution-data-server-1.6 evolution-data-server-1.4 evolution-data-server-1.2 PATHS /opt/local/include/ /sw/include/ /usr/local/include/ /usr/include/ ) FIND_LIBRARY( _libecal1.2_link_DIR ecal-1.2 PATHS /opt/local/lib /sw/lib /usr/lib /usr/local/lib /usr/lib64 /usr/local/lib64 /opt/lib64 ) IF ( _libecal1.2_include_DIR AND _libecal1.2_link_DIR ) SET ( _libecal1.2_FOUND TRUE ) ENDIF ( _libecal1.2_include_DIR AND _libecal1.2_link_DIR ) IF ( _libecal1.2_FOUND ) SET ( LIBECAL1.2_INCLUDE_DIRS ${_libecal1.2_include_DIR} ) SET ( LIBECAL1.2_LIBRARIES ${_libecal1.2_link_DIR} ) ENDIF ( _libecal1.2_FOUND ) # Handle dependencies IF ( NOT LIBEDATASERVER1.2_FOUND ) FIND_PACKAGE ( EDataServer1.2 REQUIRED ) IF ( LIBEDATASERVER1.2_FOUND ) SET ( LIBECAL1.2_INCLUDE_DIRS ${LIBECAL1.2_INCLUDE_DIRS} ${LIBEDATASERVER1.2_INCLUDE_DIRS} ) SET ( LIBECAL1.2_LIBRARIES ${LIBECAL1.2_LIBRARIES} ${LIBEDATASERVER1.2_LIBRARIES} ) ENDIF ( LIBEDATASERVER1.2_FOUND ) ENDIF ( NOT LIBEDATASERVER1.2_FOUND ) IF ( NOT LIBGNOME2_FOUND ) FIND_PACKAGE ( LibGnome2 REQUIRED ) IF ( LIBGNOME2_FOUND ) SET ( LIBECAL1.2_INCLUDE_DIRS ${LIBECAL1.2_INCLUDE_DIRS} ${LIBGNOME2_INCLUDE_DIRS} ) SET ( LIBECAL1.2_LIBRARIES ${LIBECAL1.2_LIBRARIES} ${LIBGNOME2_LIBRARIES} ) ENDIF ( LIBGNOME2_FOUND ) ENDIF ( NOT LIBGNOME2_FOUND ) IF ( NOT BONOBO2_FOUND ) SET ( BONOBO2_MIN_VERSION "2.4.2" ) FIND_PACKAGE ( BONOBO2 REQUIRED ) IF ( BONOBO2_FOUND ) SET ( LIBECAL1.2_INCLUDE_DIRS ${LIBECAL1.2_INCLUDE_DIRS} ${BONOBO2_INCLUDE_DIRS} ) SET ( LIBECAL1.2_LIBRARIES ${LIBECAL1.2_LIBRARIES} ${BONOBO2_LIBRARIES} ) ENDIF ( BONOBO2_FOUND ) ENDIF ( NOT BONOBO2_FOUND ) # Report results IF ( LIBECAL1.2_LIBRARIES AND LIBECAL1.2_INCLUDE_DIRS AND _libecal1.2_FOUND ) SET( LIBECAL1.2_FOUND 1 ) IF ( NOT ECal1.2_FIND_QUIETLY ) MESSAGE( STATUS "Found libecal-1.2: ${LIBECAL1.2_LIBRARIES}" ) ENDIF ( NOT ECal1.2_FIND_QUIETLY ) ELSE ( LIBECAL1.2_LIBRARIES AND LIBECAL1.2_INCLUDE_DIRS AND _libecal1.2_FOUND ) IF ( ECal1.2_FIND_REQUIRED ) MESSAGE( SEND_ERROR "Could NOT find libecal-1.2" ) ELSE ( ECal1.2_FIND_REQUIRED ) IF ( NOT ECal1.2_FIND_QUIETLY ) MESSAGE( STATUS "Could NOT find libecal-1.2" ) ENDIF ( NOT ECal1.2_FIND_QUIETLY ) ENDIF ( ECal1.2_FIND_REQUIRED ) ENDIF ( LIBECAL1.2_LIBRARIES AND LIBECAL1.2_INCLUDE_DIRS AND _libecal1.2_FOUND ) ENDIF ( NOT LIBECAL1.2_FOUND AND NOT PKG_CONFIG_FOUND ) # Hide advanced variables from CMake GUIs MARK_AS_ADVANCED( LIBECAL1.2_LIBRARIES LIBECAL1.2_INCLUDE_DIRS ) libsyncml-0.5.4/cmake/modules/FindSqlite3.cmake100644 1750 1750 5122 11211710410 21300 0ustar00bellmichbellmich# - Try to find sqlite3 # Find sqlite3 headers, libraries and the answer to all questions. # # SQLITE3_FOUND True if sqlite3 got found # SQLITE3_INCLUDEDIR Location of sqlite3 headers # SQLITE3_LIBRARIES List of libaries to use sqlite3 # SQLITE3_DEFINITIONS Definitions to compile sqlite3 # # Copyright (c) 2007 Juha Tuomala # Copyright (c) 2007 Daniel Gollub # Copyright (c) 2007 Alban Browaeys # # Redistribution and use is allowed according to the terms of the New # BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # INCLUDE( FindPkgConfig ) # Take care about sqlite3.pc settings IF ( Sqlite3_FIND_REQUIRED ) SET( _pkgconfig_REQUIRED "REQUIRED" ) ELSE ( Sqlite3_FIND_REQUIRED ) SET( _pkgconfig_REQUIRED "" ) ENDIF ( Sqlite3_FIND_REQUIRED ) IF ( SQLITE3_MIN_VERSION ) PKG_SEARCH_MODULE( SQLITE3 ${_pkgconfig_REQUIRED} sqlite3>=${SQLITE3_MIN_VERSION} ) ELSE ( SQLITE3_MIN_VERSION ) pkg_search_module( SQLITE3 ${_pkgconfig_REQUIRED} sqlite3 ) ENDIF ( SQLITE3_MIN_VERSION ) # Look for sqlite3 include dir and libraries w/o pkgconfig IF ( NOT SQLITE3_FOUND AND NOT PKG_CONFIG_FOUND ) FIND_PATH( _sqlite3_include_DIR sqlite3.h PATHS /opt/local/include/ /sw/include/ /usr/local/include/ /usr/include/ ) FIND_LIBRARY( _sqlite3_link_DIR sqlite3 PATHS /opt/local/lib /sw/lib /usr/lib /usr/local/lib /usr/lib64 /usr/local/lib64 /opt/lib64 ) IF ( _sqlite3_include_DIR AND _sqlite3_link_DIR ) SET ( _sqlite3_FOUND TRUE ) ENDIF ( _sqlite3_include_DIR AND _sqlite3_link_DIR ) IF ( _sqlite3_FOUND ) SET ( SQLITE3_INCLUDE_DIRS ${_sqlite3_include_DIR} ) SET ( SQLITE3_LIBRARIES ${_sqlite3_link_DIR} ) ENDIF ( _sqlite3_FOUND ) # Report results IF ( SQLITE3_LIBRARIES AND SQLITE3_INCLUDE_DIRS AND _sqlite3_FOUND ) SET( SQLITE3_FOUND 1 ) IF ( NOT Sqlite3_FIND_QUIETLY ) MESSAGE( STATUS "Found sqlite3: ${SQLITE3_LIBRARIES} ${SQLITE3_INCLUDE_DIRS}" ) ENDIF ( NOT Sqlite3_FIND_QUIETLY ) ELSE ( SQLITE3_LIBRARIES AND SQLITE3_INCLUDE_DIRS AND _sqlite3_FOUND ) IF ( Sqlite3_FIND_REQUIRED ) MESSAGE( SEND_ERROR "Could NOT find sqlite3" ) ELSE ( Sqlite3_FIND_REQUIRED ) IF ( NOT Sqlite3_FIND_QUIETLY ) MESSAGE( STATUS "Could NOT find sqlite3" ) ENDIF ( NOT Sqlite3_FIND_QUIETLY ) ENDIF ( Sqlite3_FIND_REQUIRED ) ENDIF ( SQLITE3_LIBRARIES AND SQLITE3_INCLUDE_DIRS AND _sqlite3_FOUND ) ENDIF ( NOT SQLITE3_FOUND AND NOT PKG_CONFIG_FOUND ) # Hide advanced variables from CMake GUIs MARK_AS_ADVANCED( SQLITE3_LIBRARIES SQLITE3_INCLUDE_DIRS ) libsyncml-0.5.4/cmake/modules/cmake_uninstall.cmake.in100644 1750 1750 1617 11211710410 22736 0ustar00bellmichbellmichIF(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") MESSAGE(FATAL_ERROR "Cannot find install manifest: \"@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt\"") ENDIF(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") FILE(READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" files) STRING(REGEX REPLACE "\n" ";" files "${files}") FOREACH(file ${files}) MESSAGE(STATUS "Uninstalling \"$ENV{DESTDIR}${file}\"") IF(EXISTS "$ENV{DESTDIR}${file}") EXEC_PROGRAM( "@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\"" OUTPUT_VARIABLE rm_out RETURN_VALUE rm_retval ) IF(NOT "${rm_retval}" STREQUAL 0) MESSAGE(FATAL_ERROR "Problem when removing \"$ENV{DESTDIR}${file}\"") ENDIF(NOT "${rm_retval}" STREQUAL 0) ELSE(EXISTS "$ENV{DESTDIR}${file}") MESSAGE(STATUS "File \"$ENV{DESTDIR}${file}\" does not exist.") ENDIF(EXISTS "$ENV{DESTDIR}${file}") ENDFOREACH(file) libsyncml-0.5.4/cmake/modules/FindGTK2.cmake100644 1750 1750 31471 11211710410 20511 0ustar00bellmichbellmich# - Try to find GTK2 # Once done this will define # # GTK2_FOUND - System has Boost # GTK2_INCLUDE_DIRS - GTK2 include directory # GTK2_LIBRARIES - Link these to use GTK2 # GTK2_LIBRARY_DIRS - The path to where the GTK2 library files are. # GTK2_DEFINITIONS - Compiler switches required for using GTK2 # # Copyright (c) 2007 Andreas Schneider # # Redistribution and use is allowed according to the terms of the New # BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # set(GTK2_DEBUG ON) macro(GTK2_DEBUG_MESSAGE _message) if (GTK2_DEBUG) message(STATUS "(DEBUG) ${_message}") endif (GTK2_DEBUG) endmacro(GTK2_DEBUG_MESSAGE _message) if (GTK2_LIBRARIES AND GTK2_INCLUDE_DIRS) # in cache already set(GTK2_FOUND TRUE) else (GTK2_LIBRARIES AND GTK2_INCLUDE_DIRS) if (UNIX) # use pkg-config to get the directories and then use these values # in the FIND_PATH() and FIND_LIBRARY() calls include(UsePkgConfig) pkgconfig(gtk+-2.0 _GTK2IncDir _GTK2LinkDir _GTK2LinkFlags _GTK2Cflags) find_path(GTK2_GTK_INCLUDE_DIR NAMES gtk/gtk.h PATHS $ENV{GTK2_HOME} ${_GTK2IncDir} /usr/include/gtk-2.0 /usr/local/include/gtk-2.0 /opt/include/gtk-2.0 /opt/gnome/include/gtk-2.0 /sw/include/gtk-2.0 ) gtk2_debug_message("GTK2_GTK_INCLUDE_DIR is ${GTK2_GTK_INCLUDE_DIR}") # Some Linux distributions (e.g. Red Hat) have glibconfig.h # and glib.h in different directories, so we need to look # for both. # - Atanas Georgiev pkgconfig(glib-2.0 _GLIB2IncDir _GLIB2LinkDir _GLIB2LinkFlags _GLIB2Cflags) pkgconfig(gmodule-2.0 _GMODULE2IncDir _GMODULE2LinkDir _GMODULE2LinkFlags _GMODULE2Cflags) find_path(GTK2_GLIBCONFIG_INCLUDE_DIR NAMES glibconfig.h PATHS ${_GLIB2IncDir} ${_GMODULE2IncDir} /opt/gnome/lib64/glib-2.0/include /opt/gnome/lib/glib-2.0/include /opt/lib/glib-2.0/include /usr/lib64/glib-2.0/include /usr/lib/glib-2.0/include /sw/lib/glib-2.0/include ) gtk2_debug_message("GTK2_GLIBCONFIG_INCLUDE_DIR is ${GTK2_GLIBCONFIG_INCLUDE_DIR}") find_path(GTK2_GLIB_INCLUDE_DIR NAMES glib.h PATHS ${_GLIB2IncDir} ${_GMODULE2IncDir} /opt/include/glib-2.0 /opt/gnome/include/glib-2.0 /usr/include/glib-2.0 /sw/include/glib-2.0 ) gtk2_debug_message("GTK2_GLIB_INCLUDE_DIR is ${GTK2_GLIB_INCLUDE_DIR}") pkgconfig(gdk-2.0 _GDK2IncDir _GDK2LinkDir _GDK2LinkFlags _GDK2Cflags) find_path(GTK2_GDK_INCLUDE_DIR NAMES gdkconfig.h PATHS ${_GDK2IncDir} /opt/gnome/lib/gtk-2.0/include /opt/gnome/lib64/gtk-2.0/include /opt/lib/gtk-2.0/include /usr/lib/gtk-2.0/include /usr/lib64/gtk-2.0/include /sw/lib/gtk-2.0/include ) gtk2_debug_message("GTK2_GDK_INCLUDE_DIR is ${GTK2_GDK_INCLUDE_DIR}") find_path(GTK2_GTKGL_INCLUDE_DIR NAMES gtkgl/gtkglarea.h PATHS ${_GLIB2IncDir} /usr/include /usr/local/include /usr/openwin/share/include /opt/gnome/include /opt/include /sw/include ) gtk2_debug_message("GTK2_GTKGL_INCLUDE_DIR is ${GTK2_GTKGL_INCLUDE_DIR}") pkgconfig(libglade-2.0 _GLADEIncDir _GLADELinkDir _GLADELinkFlags _GLADECflags) find_path(GTK2_GLADE_INCLUDE_DIR NAMES glade/glade.h PATHS ${_GLADEIncDir} /opt/gnome/include/libglade-2.0 /usr/include/libglade-2.0 /opt/include/libglade-2.0 /sw/include/libglade-2.0 ) gtk2_debug_message("GTK2_GLADE_INCLUDE_DIR is ${GTK2_GLADE_INCLUDE_DIR}") pkgconfig(pango _PANGOIncDir _PANGOLinkDir _PANGOLinkFlags _PANGOCflags) find_path(GTK2_PANGO_INCLUDE_DIR NAMES pango/pango.h PATHS ${_PANGOIncDir} /usr/include/pango-1.0 /opt/gnome/include/pango-1.0 /opt/include/pango-1.0 /sw/include/pango-1.0 ) gtk2_debug_message("GTK2_PANGO_INCLUDE_DIR is ${GTK2_PANGO_INCLUDE_DIR}") pkgconfig(cairo _CAIROIncDir _CAIROLinkDir _CAIROLinkFlags _CAIROCflags) find_path(GTK2_CAIRO_INCLUDE_DIR NAMES cairo.h PATHS ${_CAIROIncDir} /opt/gnome/include/cairo /usr/include /usr/include/cairo /opt/include /opt/include/cairo /sw/include /sw/include/cairo ) gtk2_debug_message("GTK2_CAIRO_INCLUDE_DIR is ${GTK2_CAIRO_INCLUDE_DIR}") pkgconfig(atk _ATKIncDir _ATKLinkDir _ATKLinkFlags _ATKCflags) find_path(GTK2_ATK_INCLUDE_DIR NAMES atk/atk.h PATHS ${_ATKIncDir} /opt/gnome/include/atk-1.0 /usr/include/atk-1.0 /opt/include/atk-1.0 /sw/include/atk-1.0 ) gtk2_debug_message("GTK2_ATK_INCLUDE_DIR is ${GTK2_ATK_INCLUDE_DIR}") find_library(GTK2_GTK_LIBRARY NAMES gtk-x11-2.0 PATHS ${_GTK2LinkDir} /usr/lib /usr/local/lib /usr/openwin/lib /usr/X11R6/lib /opt/gnome/lib /opt/lib /sw/lib ) gtk2_debug_message("GTK2_GTK_LIBRARY is ${GTK2_GTK_LIBRARY}") find_library(GTK2_GDK_LIBRARY NAMES gdk-x11-2.0 PATHS ${_GDK2LinkDir} /usr/lib /usr/local/lib /usr/openwin/lib /usr/X11R6/lib /opt/gnome/lib /opt/lib /sw/lib ) gtk2_debug_message("GTK2_GDK_LIBRARY is ${GTK2_GDK_LIBRARY}") find_library(GTK2_GDK_PIXBUF_LIBRARY NAMES gdk_pixbuf-2.0 PATHS ${_GDK2LinkDir} /usr/lib /usr/local/lib /usr/openwin/lib /usr/X11R6/lib /opt/gnome/lib /opt/lib /sw/lib ) gtk2_debug_message("GTK2_GDK_PIXBUF_LIBRARY is ${GTK2_GDK_PIXBUF_LIBRARY}") find_library(GTK2_GMODULE_LIBRARY NAMES gmodule-2.0 PATHS ${_GMODULE2LinkDir} /usr/lib /usr/local/lib /usr/openwin/lib /usr/X11R6/lib /opt/gnome/lib /opt/lib /sw/lib ) gtk2_debug_message("GTK2_GMODULE_LIBRARY is ${GTK2_GMODULE_LIBRARY}") find_library(GTK2_GTHREAD_LIBRARY NAMES gthread-2.0 PATHS ${_GTK2LinkDir} /usr/lib /usr/local/lib /usr/openwin/lib /usr/X11R6/lib /opt/gnome/lib /opt/lib /sw/lib ) gtk2_debug_message("GTK2_GTHREAD_LIBRARY is ${GTK2_GTHREAD_LIBRARY}") find_library(GTK2_GOBJECT_LIBRARY NAMES gobject-2.0 PATHS ${_GTK2LinkDir} /usr/lib /usr/local/lib /usr/openwin/lib /usr/X11R6/lib /opt/gnome/lib /opt/lib /sw/lib ) gtk2_debug_message("GTK2_GOBJECT_LIBRARY is ${GTK2_GOBJECT_LIBRARY}") find_library(GTK2_GLIB_LIBRARY NAMES glib-2.0 PATHS ${_GLIB2LinkDir} /usr/lib /usr/local/lib /usr/openwin/lib /usr/X11R6/lib /opt/gnome/lib /opt/lib /sw/lib ) gtk2_debug_message("GTK2_GLIB_LIBRARY is ${GTK2_GLIB_LIBRARY}") find_library(GTK2_GTKGL_LIBRARY NAMES gtkgl PATHS ${_GTK2LinkDir} /usr/lib /usr/local/lib /usr/openwin/lib /usr/X11R6/lib /opt/gnome/lib /opt/lib /sw/lib ) gtk2_debug_message("GTK2_GTKGL_LIBRARY is ${GTK2_GTKGL_LIBRARY}") find_library(GTK2_GLADE_LIBRARY NAMES glade-2.0 PATHS ${_GLADELinkDir} /usr/lib /usr/local/lib /usr/openwin/lib /usr/X11R6/lib /opt/gnome/lib /opt/lib /sw/lib ) gtk2_debug_message("GTK2_GLADE_LIBRARY is ${GTK2_GLADE_LIBRARY}") find_library(GTK2_PANGO_LIBRARY NAMES pango-1.0 PATHS ${_PANGOLinkDir} /usr/lib /usr/local/lib /usr/openwin/lib /usr/X11R6/lib /opt/gnome/lib /opt/lib /sw/lib ) gtk2_debug_message("GTK2_PANGO_LIBRARY is ${GTK2_PANGO_LIBRARY}") find_library(GTK2_CAIRO_LIBRARY NAMES pangocairo-1.0 PATHS ${_CAIROLinkDir} /usr/lib /usr/local/lib /usr/openwin/lib /usr/X11R6/lib /opt/gnome/lib /opt/lib /sw/lib ) gtk2_debug_message("GTK2_PANGO_LIBRARY is ${GTK2_CAIRO_LIBRARY}") find_library(GTK2_ATK_LIBRARY NAMES atk-1.0 PATHS ${_ATKinkDir} /usr/lib /usr/local/lib /usr/openwin/lib /usr/X11R6/lib /opt/gnome/lib /opt/lib /sw/lib ) gtk2_debug_message("GTK2_ATK_LIBRARY is ${GTK2_ATK_LIBRARY}") set(GTK2_INCLUDE_DIRS ${GTK2_GTK_INCLUDE_DIR} ${GTK2_GLIBCONFIG_INCLUDE_DIR} ${GTK2_GLIB_INCLUDE_DIR} ${GTK2_GDK_INCLUDE_DIR} ${GTK2_GLADE_INCLUDE_DIR} ${GTK2_PANGO_INCLUDE_DIR} ${GTK2_CAIRO_INCLUDE_DIR} ${GTK2_ATK_INCLUDE_DIR} ) if (GTK2_GTK_LIBRARY AND GTK2_GTK_INCLUDE_DIR) if (GTK2_GDK_LIBRARY AND GTK2_GDK_PIXBUF_LIBRARY AND GTK2_GDK_INCLUDE_DIR) if (GTK2_GMODULE_LIBRARY) if (GTK2_GTHREAD_LIBRARY) if (GTK2_GOBJECT_LIBRARY) if (GTK2_GLADE_LIBRARY AND GTK2_GLADE_INCLUDE_DIR) if (GTK2_PANGO_LIBRARY AND GTK2_PANGO_INCLUDE_DIR) if (GTK2_CAIRO_LIBRARY AND GTK2_CAIRO_INCLUDE_DIR) if (GTK2_ATK_LIBRARY AND GTK2_ATK_INCLUDE_DIR) # set GTK2 libraries set (GTK2_LIBRARIES ${GTK2_GTK_LIBRARY} ${GTK2_GDK_LIBRARY} ${GTK2_GDK_PIXBUF_LIBRARY} ${GTK2_GMODULE_LIBRARY} ${GTK2_GTHREAD_LIBRARY} ${GTK2_GOBJECT_LIBRARY} ${GTK2_GLADE_LIBRARY} ${GTK2_PANGO_LIBRARY} ${GTK2_CAIRO_LIBRARY} ${GTK2_ATK_LIBRARY} ) # check for gtkgl support if (GTK2_GTKGL_LIBRARY AND GTK2_GTKGL_INCLUDE_DIR) set(GTK2_GTKGL_FOUND TRUE) set(GTK2_INCLUDE_DIRS ${GTK2_INCLUDE_DIR} ${GTK2_GTKGL_INCLUDE_DIR} ) set(GTK2_LIBRARIES ${GTK2_LIBRARIES} ${GTK2_GTKGL_LIBRARY} ) endif (GTK2_GTKGL_LIBRARY AND GTK2_GTKGL_INCLUDE_DIR) else (GTK2_ATK_LIBRARY AND GTK2_ATK_INCLUDE_DIR) message(SEND_ERROR "Could not find ATK") endif (GTK2_ATK_LIBRARY AND GTK2_ATK_INCLUDE_DIR) else (GTK2_CAIRO_LIBRARY AND GTK2_CAIRO_INCLUDE_DIR) message(SEND_ERROR "Could not find CAIRO") endif (GTK2_CAIRO_LIBRARY AND GTK2_CAIRO_INCLUDE_DIR) else (GTK2_PANGO_LIBRARY AND GTK2_PANGO_INCLUDE_DIR) message(SEND_ERROR "Could not find PANGO") endif (GTK2_PANGO_LIBRARY AND GTK2_PANGO_INCLUDE_DIR) else (GTK2_GLADE_LIBRARY AND GTK2_GLADE_INCLUDE_DIR) message(SEND_ERROR "Could not find GLADE") endif (GTK2_GLADE_LIBRARY AND GTK2_GLADE_INCLUDE_DIR) else (GTK2_GOBJECT_LIBRARY) message(SEND_ERROR "Could not find GOBJECT") endif (GTK2_GOBJECT_LIBRARY) else (GTK2_GTHREAD_LIBRARY) message(SEND_ERROR "Could not find GTHREAD") endif (GTK2_GTHREAD_LIBRARY) else (GTK2_GMODULE_LIBRARY) message(SEND_ERROR "Could not find GMODULE") endif (GTK2_GMODULE_LIBRARY) else (GTK2_GDK_LIBRARY AND GTK2_GDK_PIXBUF_LIBRARY AND GTK2_GDK_INCLUDE_DIR) message(SEND_ERROR "Could not find GDK (GDK_PIXBUF)") endif (GTK2_GDK_LIBRARY AND GTK2_GDK_PIXBUF_LIBRARY AND GTK2_GDK_INCLUDE_DIR) else (GTK2_GTK_LIBRARY AND GTK2_GTK_INCLUDE_DIR) message(SEND_ERROR "Could not find GTK2-X11") endif (GTK2_GTK_LIBRARY AND GTK2_GTK_INCLUDE_DIR) if (GTK2_INCLUDE_DIRS AND GTK2_LIBRARIES) set(GTK2_FOUND TRUE) endif (GTK2_INCLUDE_DIRS AND GTK2_LIBRARIES) if (GTK2_FOUND) if (NOT GTK2_FIND_QUIETLY) message(STATUS "Found GTK2: ${GTK2_LIBRARIES}") endif (NOT GTK2_FIND_QUIETLY) else (GTK2_FOUND) if (GTK2_FIND_REQUIRED) message(FATAL_ERROR "Could not find GTK2") endif (GTK2_FIND_REQUIRED) endif (GTK2_FOUND) # show the GTK2_INCLUDE_DIRS and GTK2_LIBRARIES variables only in the advanced view mark_as_advanced(GTK2_INCLUDE_DIRS GTK2_LIBRARIES) endif (UNIX) endif (GTK2_LIBRARIES AND GTK2_INCLUDE_DIRS) libsyncml-0.5.4/cmake/modules/FindGNOKII.cmake100644 1750 1750 3542 11211710410 20740 0ustar00bellmichbellmich# - Try to find GNOKII # Find GNOKII headers, libraries and the answer to all questions. # # GNOKII_FOUND True if GNOKII got found # GNOKII_INCLUDE_DIRS Location of GNOKII headers # GNOKII_LIBRARIES List of libaries to use GNOKII # GNOKII_DEFINITIONS Definitions to compile GNOKII # # Copyright (c) 2007 Daniel Gollub # Copyright (c) 2008 Bjoern Ricks # # Redistribution and use is allowed according to the terms of the New # BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # INCLUDE( FindPkgConfig ) IF ( GNOKII_FIND_REQUIRED ) SET( _pkgconfig_REQUIRED "REQUIRED" ) ELSE( GNOKII_FIND_REQUIRED ) SET( _pkgconfig_REQUIRED "" ) ENDIF ( GNOKII_FIND_REQUIRED ) IF ( GNOKII_MIN_VERSION ) PKG_SEARCH_MODULE( GNOKII ${_pkgconfig_REQUIRED} gnokii>=${GNOKII_MIN_VERSION} ) ELSE ( GNOKII_MIN_VERSION ) PKG_SEARCH_MODULE( GNOKII ${_pkgconfig_REQUIRED} gnokii ) ENDIF ( GNOKII_MIN_VERSION ) IF( NOT GNOKII_FOUND AND NOT PKG_CONFIG_FOUND ) FIND_PATH( GNOKII_INCLUDE_DIRS gnokii.h ) FIND_LIBRARY( GNOKII_LIBRARIES gnokii) # Report results IF ( GNOKII_LIBRARIES AND GNOKII_INCLUDE_DIRS ) SET( GNOKII_FOUND 1 ) IF ( NOT GNOKII_FIND_QUIETLY ) MESSAGE( STATUS "Found GNOKII: ${GNOKII_LIBRARIES}" ) ENDIF ( NOT GNOKII_FIND_QUIETLY ) ELSE ( GNOKII_LIBRARIES AND GNOKII_INCLUDE_DIRS ) IF ( GNOKII_FIND_REQUIRED ) MESSAGE( SEND_ERROR "Could NOT find GNOKII" ) ELSE ( GNOKII_FIND_REQUIRED ) IF ( NOT GNOKII_FIND_QUIETLY ) MESSAGE( STATUS "Could NOT find GNOKII" ) ENDIF ( NOT GNOKII_FIND_QUIETLY ) ENDIF ( GNOKII_FIND_REQUIRED ) ENDIF ( GNOKII_LIBRARIES AND GNOKII_INCLUDE_DIRS ) ENDIF( NOT GNOKII_FOUND AND NOT PKG_CONFIG_FOUND ) # Hide advanced variables from CMake GUIs MARK_AS_ADVANCED( GNOKII_LIBRARIES GNOKII_INCLUDE_DIRS ) libsyncml-0.5.4/cmake/modules/FindPilotLink.cmake100644 1750 1750 3754 11211710410 21672 0ustar00bellmichbellmich# - Try to find PilotLink # Find PilotLink headers, libraries and the answer to all questions. # # PILOTLINK_FOUND True if PilotLink got found # PILOTLINK_INCLUDE_DIRS Location of PilotLink headers # PILOTLINK_LIBRARIES List of libaries to use PilotLink # PILOTLINK_DEFINITIONS Definitions to compile PilotLink # # Copyright (c) 2007 Daniel Gollub # Copyright (c) 2008 Bjoern Ricks # # Redistribution and use is allowed according to the terms of the New # BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # INCLUDE( FindPkgConfig ) IF ( PilotLink_FIND_REQUIRED ) SET( _pkgconfig_REQUIRED "REQUIRED" ) ELSE( PilotLink_FIND_REQUIRED ) SET( _pkgconfig_REQUIRED "" ) ENDIF ( PilotLink_FIND_REQUIRED ) IF ( PILOTLINK_MIN_VERSION ) PKG_SEARCH_MODULE( PILOTLINK ${_pkgconfig_REQUIRED} pilot-link>=${PILOTLINK_MIN_VERSION} ) ELSE ( PILOTLINK_MIN_VERSION ) PKG_SEARCH_MODULE( PILOTLINK ${_pkgconfig_REQUIRED} pilot-link ) ENDIF ( PILOTLINK_MIN_VERSION ) IF( NOT PILOTLINK_FOUND AND NOT PKG_CONFIG_FOUND ) FIND_PATH( PILOTLINK_INCLUDE_DIRS pilot-link ) FIND_LIBRARY( PILOTLINK_LIBRARIES pisock) # Report results IF ( PILOTLINK_LIBRARIES AND PILOTLINK_INCLUDE_DIRS ) SET( PILOTLINK_FOUND 1 ) IF ( NOT PilotLink_FIND_QUIETLY ) MESSAGE( STATUS "Found PilotLink: ${PILOTLINK_LIBRARIES}" ) ENDIF ( NOT PilotLink_FIND_QUIETLY ) ELSE ( PILOTLINK_LIBRARIES AND PILOTLINK_INCLUDE_DIRS ) IF ( PilotLink_FIND_REQUIRED ) MESSAGE( SEND_ERROR "Could NOT find PilotLink" ) ELSE ( PilotLink_FIND_REQUIRED ) IF ( NOT PilotLink_FIND_QUIETLY ) MESSAGE( STATUS "Could NOT find PilotLink" ) ENDIF ( NOT PilotLink_FIND_QUIETLY ) ENDIF ( PilotLink_FIND_REQUIRED ) ENDIF ( PILOTLINK_LIBRARIES AND PILOTLINK_INCLUDE_DIRS ) ENDIF( NOT PILOTLINK_FOUND AND NOT PKG_CONFIG_FOUND ) # Hide advanced variables from CMake GUIs MARK_AS_ADVANCED( PILOTLINK_LIBRARIES PILOTLINK_INCLUDE_DIRS ) libsyncml-0.5.4/cmake/modules/FindLibGcal.cmake100644 1750 1750 5202 11211710410 21250 0ustar00bellmichbellmich# - Try to find libgcal # Find libgcal headers, libraries and the answer to all questions. # # LIBGCAL_FOUND True if libgcal got found # LIBGCAL_INCLUDE_DIRS Location of libgcal headers # LIBGCAL_LIBRARIES List of libaries to use libgcal # LIBGCAL_DEFINITIONS Definitions to compile libgcal # # Copyright (c) 2006, Alexander Neundorf, # Copyright (c) 2007 Alban Browaeys # Copyright (c) 2008 Adenilson Cavalcanti # Adapted this to scan for libgcal # # Redistribution and use is allowed according to the terms of the New # BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # INCLUDE( FindPkgConfig ) # Take care about libgcal.pc settings IF ( Libgcal_FIND_REQUIRED ) SET( _pkgconfig_REQUIRED "REQUIRED" ) ELSE ( Libgcal_FIND_REQUIRED ) SET( _pkgconfig_REQUIRED "" ) ENDIF ( Libgcal_FIND_REQUIRED ) IF ( LIBGCAL_MIN_VERSION ) PKG_SEARCH_MODULE( LIBGCAL ${_pkgconfig_REQUIRED} libgcal>=${LIBGCAL_MIN_VERSION} ) ELSE ( LIBGCAL_MIN_VERSION ) pkg_search_module( LIBGCAL ${_pkgconfig_REQUIRED} libgcal ) ENDIF ( LIBGCAL_MIN_VERSION ) # Look for libgcal include dir and libraries w/o pkgconfig IF ( NOT LIBGCAL_FOUND AND NOT PKG_CONFIG_FOUND ) FIND_PATH( _libgcal_include_DIR gcal.h PATHS /opt/local/include/ /sw/include/ /usr/local/include/ /usr/include/ ) FIND_LIBRARY( _libgcal_link_DIR NAME libgcal PATHS /opt/local/lib /sw/lib /usr/lib /usr/local/lib /usr/lib64 /usr/local/lib64 /opt/lib64 ) IF ( _libgcal_include_DIR AND _libgcal_link_DIR ) SET ( _libgcal_FOUND TRUE ) ENDIF ( _libgcal_include_DIR AND _libgcal_link_DIR ) IF ( _libgcal_FOUND ) SET ( LIBGCAL_INCLUDE_DIRS ${_libgcal_include_DIR} ) SET ( LIBGCAL_LIBRARIES ${_libgcal_link_DIR} ) ENDIF ( _libgcal_FOUND ) # Report results IF ( LIBGCAL_LIBRARIES AND LIBGCAL_INCLUDE_DIRS AND _libgcal_FOUND ) SET( LIBGCAL_FOUND 1 ) IF ( NOT Libgcal_FIND_QUIETLY ) MESSAGE( STATUS "Found libgcal: ${LIBGCAL_LIBRARIES} ${LIBGCAL_INCLUDE_DIRS}" ) ENDIF ( NOT Libgcal_FIND_QUIETLY ) ELSE ( LIBGCAL_LIBRARIES AND LIBGCAL_INCLUDE_DIRS AND _libgcal_FOUND ) IF ( Libgcal_FIND_REQUIRED ) MESSAGE( SEND_ERROR "Could NOT find libgcal" ) ELSE ( Libgcal_FIND_REQUIRED ) IF ( NOT Libgcal_FIND_QUIETLY ) MESSAGE( STATUS "Could NOT find libgcal" ) ENDIF ( NOT Libgcal_FIND_QUIETLY ) ENDIF ( Libgcal_FIND_REQUIRED ) ENDIF ( LIBGCAL_LIBRARIES AND LIBGCAL_INCLUDE_DIRS AND _libgcal_FOUND ) ENDIF ( NOT LIBGCAL_FOUND AND NOT PKG_CONFIG_FOUND ) # Hide advanced variables from CMake GUIs MARK_AS_ADVANCED( LIBGCAL_LIBRARIES LIBGCAL_INCLUDE_DIRS ) libsyncml-0.5.4/cmake/modules/FindLibSyncMl.cmake100644 1750 1750 12131 11211710410 21626 0ustar00bellmichbellmich# - Try to find libsyncml # Find libsyncml headers, libraries and the answer to all questions. # # LIBSYNCML_FOUND True if libsyncml got found # LIBSYNCML_INCLUDE_DIRS Location of libsyncml headers # LIBSYNCML_LIBRARIES List of libaries to use libsyncml # # Copyright (c) 2007 Juha Tuomala # Copyright (c) 2007 Daniel Gollub # Copyright (c) 2007 Alban Browaeys # # Redistribution and use is allowed according to the terms of the New # BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # INCLUDE( FindPkgConfig ) # Take care about libsyncml-1.0.pc settings IF ( LibSyncMl_FIND_REQUIRED ) SET( _pkgconfig_REQUIRED "REQUIRED" ) ELSE ( LibSyncMl_FIND_REQUIRED ) SET( _pkgconfig_REQUIRED "" ) ENDIF ( LibSyncMl_FIND_REQUIRED ) IF ( LIBSYNCML_MIN_VERSION ) PKG_SEARCH_MODULE( LIBSYNCML ${_pkgconfig_REQUIRED} libsyncml-1.0>=${LIBSYNCML_MIN_VERSION} ) ELSE( LIBSYNCML_MIN_VERSION ) PKG_SEARCH_MODULE( LIBSYNCML ${_pkgconfig_REQUIRED} libsyncml-1.0 ) ENDIF ( LIBSYNCML_MIN_VERSION ) # Look for libsyncml include dir and libraries without pkg-config... IF ( NOT LIBSYNCML_FOUND AND NOT PKG_CONFIG_FOUND ) FIND_PATH( _libsyncml_include_DIR libsyncml/syncml.h PATH_SUFFIXES libsyncml-1.0 PATHS /opt/local/include/ /sw/include/ /usr/local/include/ /usr/include/ ) FIND_LIBRARY( _libsyncml_link_DIR syncml PATHS /opt/local/lib /sw/lib /usr/lib /usr/local/lib /usr/lib64 /usr/local/lib64 /opt/lib64 ) IF ( _libsyncml_include_DIR AND _libsyncml_link_DIR ) SET ( _libsyncml_FOUND TRUE ) ENDIF ( _libsyncml_include_DIR AND _libsyncml_link_DIR ) IF ( _libsyncml_FOUND ) SET ( LIBSYNCML_INCLUDE_DIRS ${_libsyncml_include_DIR} ) SET ( LIBSYNCML_LIBRARIES ${_libsyncml_link_DIR} ) ENDIF ( _libsyncml_FOUND ) # Handle dependencies IF( NOT LIBSOUP2_FOUND ) SET ( LIBSOUP2_MIN_VERSION "2.2.91" ) FIND_PACKAGE( LibSoup2 ) IF ( LIBSOUP2_FOUND ) SET ( LIBSYNCML_INCLUDE_DIRS ${LIBSYNCML_INCLUDE_DIRS} ${LIBSOUP2_INCLUDE_DIRS} ) SET ( LIBSYNCML_LIBRARIES ${LIBSYNCML_LIBRARIES} ${LIBSOUP2_LIBRARIES} ) ENDIF( LIBSOUP2_FOUND ) ENDIF( NOT LIBSOUP2_FOUND ) IF( NOT OPENOBEX_FOUND ) SET ( OPENOBEX_MIN_VERSION "1.1" ) FIND_PACKAGE( OpenObex ) IF ( OPENOBEX_FOUND ) SET ( LIBSYNCML_INCLUDE_DIRS ${LIBSYNCML_INCLUDE_DIRS} ${OPENOBEX_INCLUDE_DIRS} ) SET ( LIBSYNCML_LIBRARIES ${LIBSYNCML_LIBRARIES} ${OPENOBEX_LIBRARIES} ) ENDIF( OPENOBEX_FOUND ) ENDIF( NOT OPENOBEX_FOUND ) IF( NOT LIBWBXML2_FOUND ) FIND_PACKAGE( LibWbxml2 REQUIRED ) IF ( LIBWBXML2_FOUND ) SET ( LIBSYNCML_INCLUDE_DIRS ${LIBSYNCML_INCLUDE_DIRS} ${LIBWBXML2_INCLUDE_DIRS} ) SET ( LIBSYNCML_LIBRARIES ${LIBSYNCML_LIBRARIES} ${LIBWBXML2_LIBRARIES} ) ENDIF( LIBWBXML2_FOUND ) ENDIF( NOT LIBWBXML2_FOUND ) IF( NOT BLUEZ_FOUND ) FIND_PACKAGE( BlueZ ) IF ( BLUEZ_FOUND ) SET ( LIBSYNCML_INCLUDE_DIRS ${LIBSYNCML_INCLUDE_DIRS} ${BLUEZ_INCLUDE_DIRS} ) SET ( LIBSYNCML_LIBRARIES ${LIBSYNCML_LIBRARIES} ${BLUEZ_LIBRARIES} ) ENDIF( BLUEZ_FOUND ) ENDIF( NOT BLUEZ_FOUND ) IF( NOT LIBXML2_FOUND ) FIND_PACKAGE( LibXml2 REQUIRED ) IF ( LIBXML2_FOUND ) SET ( LIBSYNCML_INCLUDE_DIRS ${LIBSYNCML_INCLUDE_DIRS} ${LIBXML2_INCLUDE_DIRS} ) SET ( LIBSYNCML_LIBRARIES ${LIBSYNCML_LIBRARIES} ${LIBXML2_LIBRARIES} ) ENDIF( LIBXML2_FOUND ) ENDIF( NOT LIBXML2_FOUND ) IF ( NOT GLIB2_FOUND ) FIND_PACKAGE( GLIB2 REQUIRED) IF ( GOBJECT2_FOUND ) SET ( LIBSYNCML_INCLUDE_DIRS ${LIBSYNCML_INCLUDE_DIRS} ${GOBJECT2_INCLUDE_DIR} ) SET ( LIBSYNCML_LIBRARIES ${LIBSYNCML_LIBRARIES} ${GOBJECT2_LIBRARY} ) ENDIF ( GOBJECT2_FOUND ) IF ( GTHREAD2_FOUND ) SET ( LIBSYNCML_INCLUDE_DIRS ${LIBSYNCML_INCLUDE_DIRS} ${GTHREAD2_INCLUDE_DIR} ) SET ( LIBSYNCML_LIBRARIES ${LIBSYNCML_LIBRARIES} ${GTHREAD2_LIBRARY} ) ENDIF ( GTHREAD2_FOUND ) IF ( GLIB2_FOUND ) SET ( LIBSYNCML_INCLUDE_DIRS ${LIBSYNCML_INCLUDE_DIRS} ${GLIB2_INCLUDE_DIRS} ${GLIBCONFIG_INCLUDE_DIR} ) SET ( LIBSYNCML_LIBRARIES ${LIBSYNCML_LIBRARIES} ${GLIB2_LIBRARIES} ) ENDIF ( GLIB2_FOUND ) ENDIF ( NOT GLIB2_FOUND ) # Report results IF ( LIBSYNCML_LIBRARIES AND LIBSYNCML_INCLUDE_DIRS ) SET( LIBSYNCML_FOUND 1 ) IF ( NOT LibSyncMl_FIND_QUIETLY ) MESSAGE( STATUS "Found libsyncml: ${LIBSYNCML_LIBRARIES}" ) ENDIF ( NOT LibSyncMl_FIND_QUIETLY ) ELSE ( LIBSYNCML_LIBRARIES AND LIBSYNCML_INCLUDE_DIRS ) IF ( LibSyncMl_FIND_REQUIRED ) MESSAGE( SEND_ERROR "Could NOT find libsyncml" ) ELSE ( LibSyncMl_FIND_REQUIRED ) IF ( NOT LibSyncMl_FIND_QUIETLY ) MESSAGE( STATUS "Could NOT find libsyncml" ) ENDIF ( NOT LibSyncMl_FIND_QUIETLY ) ENDIF ( LibSyncMl_FIND_REQUIRED ) ENDIF ( LIBSYNCML_LIBRARIES AND LIBSYNCML_INCLUDE_DIRS ) ENDIF ( NOT LIBSYNCML_FOUND AND NOT PKG_CONFIG_FOUND ) # Hide advanced variables from CMake GUIs MARK_AS_ADVANCED( LIBSYNCML_LIBRARIES LIBSYNCML_INCLUDE_DIRS ) libsyncml-0.5.4/cmake/modules/FindEPackage.cmake100644 1750 1750 21475 11211710410 21445 0ustar00bellmichbellmich# - Try to find evolution-data-server components # Set evolution-data-server headers, libraries and the answer to all questions. # # EVOLUTIONDATASERVER_INCLUDE_DIRS Location of evolution-data-server headers # EVOLUTIONDATASERVER_LIBRARIES List of libraries to use evolution-data-server # EVOLUTIONDATASERVER_LIBRARY_DIRS Pathes of libraries to use evolution-data-server # EVOLUTIONDATASERVER_LDFLAGS List of link flags to use evolution-data-server # # LIBEBOOK_INCLUDE_DIRS Location of libebook headers # LIBEBOOK_LIBRARIES List of libraries to use libebook # LIBEBOOK_LIBRARY_DIRS Pathes of libraries to use libebook # LIBEBOOK_LDFLAGS List of link flags to use libebook # # LIBECAL_INCLUDE_DIRS Location of libecal headers # LIBECAL_LIBRARIES List of libraries to use libecal # LIBECAL_LIBRARY_DIRS Pathes of libraries to use libecal # LIBECAL_LDFLAGS List of link flags to use libecal # # LIBEDATABOOK_INCLUDE_DIRS Location of libedata-book headers # LIBEDATABOOK_LIBRARIES List of libraries to use libedata-book # LIBEDATABOOK_LIBRARY_DIRS Pathes of libraries to use libedata-book # LIBEDATABOOK_LDFLAGS List of link flags to use libedata-book # # LIBEDATACAL_INCLUDE_DIRS Location of libedata-cal headers # LIBEDATACAL_LIBRARIES List of libraries to use libedata-cal # LIBEDATACAL_LIBRARY_DIRS Pathes of libraries to use libedata-cal # LIBEDATACAL_LDFLAGS List of link flags to use libedata-cal # # LIBEDATASERVER_INCLUDE_DIRS Location of libedataserver headers # LIBEDATASERVER_LIBRARIES List of libraries to use libedataserver # LIBEDATASERVER_LIBRARY_DIRS Pathes of libraries to use libedataserver # LIBEDATASERVER_LDFLAGS List of link flags to use libedataserver # # Copyright (c) 2007 Alban Browaeys # # Redistribution and use is allowed according to the terms of the New # BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # FIND_PACKAGE ( EvolutionDataServer1.2 ) FIND_PACKAGE ( EBook1.2 ) FIND_PACKAGE ( ECal1.2 ) FIND_PACKAGE ( EDataBook1.2 ) FIND_PACKAGE ( EDataCal1.2 ) FIND_PACKAGE ( EDataServer1.2 ) IF ( EVOLUTIONDATASERVER1.2_LIBRARIES AND EVOLUTIONDATASERVER1.2_INCLUDE_DIRS ) IF ( LIBEBOOK1.2_LIBRARIES AND LIBEBOOK1.2_INCLUDE_DIRS ) IF ( LIBECAL1.2_LIBRARIES AND LIBECAL1.2_INCLUDE_DIRS ) IF ( LIBEDATABOOK1.2_LIBRARIES AND LIBEDATABOOK1.2_INCLUDE_DIRS ) IF ( LIBEDATACAL1.2_LIBRARIES AND LIBEDATACAL1.2_INCLUDE_DIRS ) IF ( LIBEDATASERVER1.2_LIBRARIES AND LIBEDATASERVER1.2_INCLUDE_DIRS ) SET( EDS1.2_FOUND 1 ) ELSE ( LIBEDATASERVER1.2_LIBRARIES AND LIBEDATASERVER1.2_INCLUDE_DIRS ) SET( EDS1.2_FOUND 0 ) ENDIF ( LIBEDATASERVER1.2_LIBRARIES AND LIBEDATASERVER1.2_INCLUDE_DIRS ) ELSE ( LIBEDATACAL1.2_LIBRARIES AND LIBEDATACAL1.2_INCLUDE_DIRS ) SET( EDS1.2_FOUND 0 ) ENDIF ( LIBEDATACAL1.2_LIBRARIES AND LIBEDATACAL1.2_INCLUDE_DIRS ) ELSE ( LIBEDATABOOK1.2_LIBRARIES AND LIBEDATABOOK1.2_INCLUDE_DIRS ) SET( EDS1.2_FOUND 0 ) ENDIF ( LIBEDATABOOK1.2_LIBRARIES AND LIBEDATABOOK1.2_INCLUDE_DIRS ) ELSE ( LIBECAL1.2_LIBRARIES AND LIBECAL1.2_INCLUDE_DIRS ) SET( EDS1.2_FOUND 0 ) ENDIF ( LIBECAL1.2_LIBRARIES AND LIBECAL1.2_INCLUDE_DIRS ) ELSE ( LIBEBOOK1.2_LIBRARIES AND LIBEBOOK1.2_INCLUDE_DIRS ) SET( EDS1.2_FOUND 0 ) ENDIF ( LIBEBOOK1.2_LIBRARIES AND LIBEBOOK1.2_INCLUDE_DIRS ) ELSE ( EVOLUTIONDATASERVER1.2_LIBRARIES AND EVOLUTIONDATASERVER1.2_INCLUDE_DIRS ) SET( EDS1.2_FOUND 0 ) ENDIF ( EVOLUTIONDATASERVER1.2_LIBRARIES AND EVOLUTIONDATASERVER1.2_INCLUDE_DIRS ) IF ( NOT EDS1.2_FOUND ) FIND_PACKAGE ( EvolutionDataServer1.0 ) FIND_PACKAGE ( EBook1.0 ) FIND_PACKAGE ( ECal1.0 ) FIND_PACKAGE ( EDataBook1.0 ) FIND_PACKAGE ( EDataCal1.0 ) FIND_PACKAGE ( EDataServer1.0 ) IF ( EVOLUTIONDATASERVER1.0_LIBRARIES AND EVOLUTIONDATASERVER1.0_INCLUDE_DIRS ) IF ( LIBEBOOK1.0_LIBRARIES AND LIBEBOOK1.0_INCLUDE_DIRS ) IF ( LIBECAL1.0_LIBRARIES AND LIBECAL1.0_INCLUDE_DIRS ) IF ( LIBEDATABOOK1.0_LIBRARIES AND LIBEDATABOOK1.0_INCLUDE_DIRS ) IF ( LIBEDATACAL1.0_LIBRARIES AND LIBEDATACAL1.0_INCLUDE_DIRS ) IF ( LIBEDATASERVER1.0_LIBRARIES AND LIBEDATASERVER1.0_INCLUDE_DIRS ) SET( EDS1.0_FOUND 1 ) ELSE ( LIBEDATASERVER1.0_LIBRARIES AND LIBEDATASERVER1.0_INCLUDE_DIRS ) SET( EDS1.0_FOUND 0 ) ENDIF ( LIBEDATASERVER1.0_LIBRARIES AND LIBEDATASERVER1.0_INCLUDE_DIRS ) ELSE ( LIBEDATACAL1.0_LIBRARIES AND LIBEDATACAL1.0_INCLUDE_DIRS ) SET( EDS1.0_FOUND 0 ) ENDIF ( LIBEDATACAL1.0_LIBRARIES AND LIBEDATACAL1.0_INCLUDE_DIRS ) ELSE ( LIBEDATABOOK1.0_LIBRARIES AND LIBEDATABOOK1.0_INCLUDE_DIRS ) SET( EDS1.0_FOUND 0 ) ENDIF ( LIBEDATABOOK1.0_LIBRARIES AND LIBEDATABOOK1.0_INCLUDE_DIRS ) ELSE ( LIBECAL1.0_LIBRARIES AND LIBECAL1.0_INCLUDE_DIRS ) SET( EDS1.0_FOUND 0 ) ENDIF ( LIBECAL1.0_LIBRARIES AND LIBECAL1.0_INCLUDE_DIRS ) ELSE ( LIBEBOOK1.0_LIBRARIES AND LIBEBOOK1.0_INCLUDE_DIRS ) SET( EDS1.0_FOUND 0 ) ENDIF ( LIBEBOOK1.0_LIBRARIES AND LIBEBOOK1.0_INCLUDE_DIRS ) ELSE ( EVOLUTIONDATASERVER1.0_LIBRARIES AND EVOLUTIONDATASERVER1.0_INCLUDE_DIRS ) SET( EDS1.0_FOUND 0 ) ENDIF ( EVOLUTIONDATASERVER1.0_LIBRARIES AND EVOLUTIONDATASERVER1.0_INCLUDE_DIRS ) ENDIF ( NOT EDS1.2_FOUND ) IF ( EDS1.2_FOUND ) MESSAGE( STATUS "Evolution Data Server 1.2 used." ) SET( EVOLUTIONDATASERVER_INCLUDE_DIRS ${EVOLUTIONDATASERVER1.2_INCLUDE_DIRS} ) SET( EVOLUTIONDATASERVER_LIBRARIES ${EVOLUTIONDATASERVER1.2_LIBRARIES} ) SET( EVOLUTIONDATASERVER_LIBRARY_DIRS ${EVOLUTIONDATASERVER1.2_LIBRARY_DIRS} ) SET( EVOLUTIONDATASERVER_LDFLAGS ${EVOLUTIONDATASERVER1.2_LDFLAGS} ) SET( LIBEBOOK_INCLUDE_DIRS ${LIBEBOOK1.2_INCLUDE_DIRS} ) SET( LIBEBOOK_LIBRARIES ${LIBEBOOK1.2_LIBRARIES} ) SET( LIBEBOOK_LIBRARY_DIRS ${LIBEBOOK1.2_LIBRARY_DIRS} ) SET( LIBEBOOK_LDFLAGS ${LIBEBOOK1.2_LDFLAGS} ) SET( LIBECAL_INCLUDE_DIRS ${LIBECAL1.2_INCLUDE_DIRS} ) SET( LIBECAL_LIBRARIES ${LIBECAL1.2_LIBRARIES} ) SET( LIBECAL_LIBRARY_DIRS ${LIBECAL1.2_LIBRARY_DIRS} ) SET( LIBECAL_LDFLAGS ${LIBECAL1.2_LDFLAGS} ) SET( LIBEDATABOOK_INCLUDE_DIRS ${LIBEDATABOOK1.2_INCLUDE_DIRS} ) SET( LIBEDATABOOK_LIBRARIES ${LIBEDATABOOK1.2_LIBRARIES} ) SET( LIBEDATABOOK_LIBRARY_DIRS ${LIBEDATABOOK1.2_LIBRARY_DIRS} ) SET( LIBEDATABOOK_LDFLAGS ${LIBEDATABOOK1.2_LDFLAGS} ) SET( LIBEDATACAL_INCLUDE_DIRS ${LIBEDATACAL1.2_INCLUDE_DIRS} ) SET( LIBEDATACAL_LIBRARIES ${LIBEDATACAL1.2_LIBRARIES} ) SET( LIBEDATACAL_LIBRARY_DIRS ${LIBEDATACAL1.2_LIBRARY_DIRS} ) SET( LIBEDATACAL_LDFLAGS ${LIBEDATACAL1.2_LDFLAGS} ) SET( LIBEDATASERVER_INCLUDE_DIRS ${LIBEDATASERVER1.2_INCLUDE_DIRS} ) SET( LIBEDATASERVER_LIBRARIES ${LIBEDATASERVER1.2_LIBRARIES} ) SET( LIBEDATASERVER_LIBRARY_DIRS ${LIBEDATASERVER1.2_LIBRARY_DIRS} ) SET( LIBEDATASERVER_LDFLAGS ${LIBEDATASERVER1.2_LDFLAGS} ) ELSE ( EDS1.2_FOUND ) IF ( EDS1.0_FOUND ) MESSAGE( STATUS "Evolution Data Server 1.0 used." ) SET( EVOLUTIONDATASERVER_INCLUDE_DIRS ${EVOLUTIONDATASERVER1.0_INCLUDE_DIRS} ) SET( EVOLUTIONDATASERVER_LIBRARIES ${EVOLUTIONDATASERVER1.2_LIBRARIES} ) SET( EVOLUTIONDATASERVER_LIBRARY_DIRS ${EVOLUTIONDATASERVER1.2_LIBRARY_DIRS} ) SET( EVOLUTIONDATASERVER_LDFLAGS ${EVOLUTIONDATASERVER1.2_LDFLAGS} ) SET( LIBEBOOK_INCLUDE_DIRS ${LIBEBOOK1.0_INCLUDE_DIRS} ) SET( LIBEBOOK_LIBRARIES ${LIBEBOOK1.0_LIBRARIES} ) SET( LIBEBOOK_LIBRARY_DIRS ${LIBEBOOK1.0_LIBRARY_DIRS} ) SET( LIBEBOOK_LDFLAGS ${LIBEBOOK1.0_LDFLAGS} ) SET( LIBECAL_INCLUDE_DIRS ${LIBECAL1.0_INCLUDE_DIRS} ) SET( LIBECAL_LIBRARIES ${LIBECAL1.0_LIBRARIES} ) SET( LIBECAL_LIBRARY_DIRS ${LIBECAL1.0_LIBRARY_DIRS} ) SET( LIBECAL_LDFLAGS ${LIBECAL1.0_LDFLAGS} ) SET( LIBEDATABOOK_INCLUDE_DIRS ${LIBEDATABOOK1.0_INCLUDE_DIRS} ) SET( LIBEDATABOOK_LIBRARIES ${LIBEDATABOOK1.0_LIBRARIES} ) SET( LIBEDATABOOK_LIBRARY_DIRS ${LIBEDATABOOK1.0_LIBRARY_DIRS} ) SET( LIBEDATABOOK_LDFLAGS ${LIBEDATABOOK1.0_LDFLAGS} ) SET( LIBEDATACAL_INCLUDE_DIRS ${LIBEDATACAL1.0_INCLUDE_DIRS} ) SET( LIBEDATACAL_LIBRARIES ${LIBEDATACAL1.0_LIBRARIES} ) SET( LIBEDATACAL_LIBRARY_DIRS ${LIBEDATACAL1.0_LIBRARY_DIRS} ) SET( LIBEDATACAL_LDFLAGS ${LIBEDATACAL1.0_LDFLAGS} ) SET( LIBEDATASERVER_INCLUDE_DIRS ${LIBEDATASERVER1.0_INCLUDE_DIRS} ) SET( LIBEDATASERVER_LIBRARIES ${LIBEDATASERVER1.0_LIBRARIES} ) SET( LIBEDATASERVER_LIBRARY_DIRS ${LIBEDATASERVER1.0_LIBRARY_DIRS} ) SET( LIBEDATASERVER_LDFLAGS ${LIBEDATASERVER1.0_LDFLAGS} ) ELSE ( EDS1.0_FOUND ) MESSAGE( FATAL_ERROR "Evolution Data Server not found." ) ENDIF ( EDS1.0_FOUND ) ENDIF ( EDS1.2_FOUND ) libsyncml-0.5.4/cmake/modules/FindEBook1.2.cmake100644 1750 1750 10162 11211710410 21214 0ustar00bellmichbellmich# - Try to find libebook1.2 components # Find libebook 1.2 headers, libraries and the answer to all questions. # # LIBEBOOK1.2_FOUND True if libebook1.2 got found # LIBEBOOK1.2_INCLUDE_DIRS Location of libebook1.2 headers # LIBEBOOK1.2_LIBRARIES List of libaries to use libebook1.2 # LIBEBOOK1.2_DEFINITIONS Definitions to compile libebook1.2 # # Copyright (c) 2007 Juha Tuomala # Copyright (c) 2007 Daniel Gollub # Copyright (c) 2007 Alban Browaeys # # Redistribution and use is allowed according to the terms of the New # BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # INCLUDE( FindPkgConfig ) # Take care about libebook-1.2.pc settings IF ( EBook1.2_FIND_REQUIRED ) SET( _pkgconfig_REQUIRED "REQUIRED" ) ELSE ( EBook1.2_FIND_REQUIRED ) SET( _pkgconfig_REQUIRED "" ) ENDIF ( EBook1.2_FIND_REQUIRED ) pkg_search_module( LIBEBOOK1.2 ${_pkgconfig_REQUIRED} libebook-1.2 ) # Look for libebook1.2 include dir and libraries w/o pkg-config. IF ( NOT LIBEBOOK1.2_FOUND AND NOT PKG_CONFIG_FOUND ) FIND_PATH( _libebook1.2_include_DIR libebook/e-book.h PATH_SUFFIXES evolution-data-server-1.12 evolution-data-server-1.10 evolution-data-server-1.8 evolution-data-server-1.6 evolution-data-server-1.4 evolution-data-server-1.2 PATHS /opt/local/include/ /sw/include/ /usr/local/include/ /usr/include/ ) FIND_LIBRARY( _libebook1.2_link_DIR ebook-1.2 PATHS /opt/local/lib /sw/lib /usr/lib /usr/local/lib /usr/lib64 /usr/local/lib64 /opt/lib64 ) IF ( _libebook1.2_include_DIR AND _libebook1.2_link_DIR ) SET ( _libebook1.2_FOUND TRUE ) ENDIF ( _libebook1.2_include_DIR AND _libebook1.2_link_DIR ) IF ( _libebook1.2_FOUND ) SET ( LIBEBOOK1.2_INCLUDE_DIRS ${_libebook1.2_include_DIR} ) SET ( LIBEBOOK1.2_LIBRARIES ${_libebook1.2_link_DIR} ) ENDIF ( _libebook1.2_FOUND ) # Handle dependencies IF ( NOT LIBEDATASERVER1.2_FOUND ) FIND_PACKAGE ( EDataServer1.2 REQUIRED ) IF ( LIBEDATASERVER1.2_FOUND ) SET ( LIBEBOOK1.2_INCLUDE_DIRS ${LIBEBOOK1.2_INCLUDE_DIRS} ${LIBEDATASERVER1.2_INCLUDE_DIRS} ) SET ( LIBEBOOK1.2_LIBRARIES ${LIBEBOOK1.2_LIBRARIES} ${LIBEDATASERVER1.2_LIBRARIES} ) ENDIF ( LIBEDATASERVER1.2_FOUND ) ENDIF ( NOT LIBEDATASERVER1.2_FOUND ) IF ( NOT LIBGNOME2_FOUND ) FIND_PACKAGE ( LibGnome2 REQUIRED ) IF ( LIBGNOME2_FOUND ) SET ( LIBEBOOK1.2_INCLUDE_DIRS ${LIBEBOOK1.2_INCLUDE_DIRS} ${LIBGNOME2_INCLUDE_DIRS} ) SET ( LIBEBOOK1.2_LIBRARIES ${LIBEBOOK1.2_LIBRARIES} ${LIBGNOME2_LIBRARIES} ) ENDIF ( LIBGNOME2_FOUND ) ENDIF ( NOT LIBGNOME2_FOUND ) IF ( NOT BONOBO2_FOUND ) SET ( BONOBO2_MIN_VERSION "2.4.2" ) FIND_PACKAGE ( BONOBO2 REQUIRED ) IF ( BONOBO2_FOUND ) SET ( LIBEBOOK1.2_INCLUDE_DIRS ${LIBEBOOK1.2_INCLUDE_DIRS} ${BONOBO2_INCLUDE_DIRS} ) SET ( LIBEBOOK1.2_LIBRARIES ${LIBEBOOK1.2_LIBRARIES} ${BONOBO2_LIBRARIES} ) ENDIF ( BONOBO2_FOUND ) ENDIF ( NOT BONOBO2_FOUND ) # Report results IF ( LIBEBOOK1.2_LIBRARIES AND LIBEBOOK1.2_INCLUDE_DIRS AND _libebook1.2_FOUND ) SET( LIBEBOOK1.2_FOUND 1 ) IF ( NOT EBook1.2_FIND_QUIETLY ) MESSAGE( STATUS "Found libebook-1.2: ${LIBEBOOK1.2_LIBRARIES}" ) ENDIF ( NOT EBook1.2_FIND_QUIETLY ) ELSE ( LIBEBOOK1.2_LIBRARIES AND LIBEBOOK1.2_INCLUDE_DIRS AND _libebook1.2_FOUND ) IF ( EBook1.2_FIND_REQUIRED ) MESSAGE( SEND_ERROR "Could NOT find libebook-1.2" ) ELSE ( EBook1.2_FIND_REQUIRED ) IF ( NOT EBook1.2_FIND_QUIETLY ) MESSAGE( STATUS "Could NOT find libebook-1.2" ) ENDIF ( NOT EBook1.2_FIND_QUIETLY ) ENDIF ( EBook1.2_FIND_REQUIRED ) ENDIF ( LIBEBOOK1.2_LIBRARIES AND LIBEBOOK1.2_INCLUDE_DIRS AND _libebook1.2_FOUND ) ENDIF ( NOT LIBEBOOK1.2_FOUND AND NOT PKG_CONFIG_FOUND ) # Hide advanced variables from CMake GUIs MARK_AS_ADVANCED( LIBEBOOK1.2_LIBRARIES LIBEBOOK1.2_INCLUDE_DIRS ) libsyncml-0.5.4/cmake/modules/FindLibGlade.cmake100644 1750 1750 4020 11211710410 21413 0ustar00bellmichbellmich# - Try to find LIBGLADE # Find LIBGLADE headers, libraries and the answer to all questions. # # LIBGLADE_FOUND True if LIBGLADE got found # LIBGLADE_INCLUDE_DIR Location of LIBGLADE headers # LIBGLADE_LIBRARIES List of libaries to use LIBGLADE # LIBGLADE_DEFINITIONS Definitions to compile LIBGLADE # # Copyright (c) 2007 Daniel Gollub # Copyright (c) 2008 Daniel Friedrich # Copyright (c) 2008 Bjoern Ricks # # Redistribution and use is allowed according to the terms of the New # BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # INCLUDE( FindPkgConfig ) IF ( LibGlade_FIND_REQUIRED ) SET( _pkgconfig_REQUIRED "REQUIRED" ) ELSE( LibGlade_FIND_REQUIRED ) SET( _pkgconfig_REQUIRED "" ) ENDIF ( LibGlade_FIND_REQUIRED ) IF ( LIBGLADE_MIN_VERSION ) PKG_SEARCH_MODULE( LIBGLADE ${_pkgconfig_REQUIRED} libglade-2.0>=${LIBGLADE_MIN_VERSION} ) ELSE ( LIBGLADE_MIN_VERSION ) PKG_SEARCH_MODULE( LIBGLADE ${_pkgconfig_REQUIRED} libglade-2.0 ) ENDIF ( LIBGLADE_MIN_VERSION ) IF( NOT LIBGLADE_FOUND AND NOT PKG_CONFIG_FOUND ) FIND_PATH(LIBGLADE_INCLUDE_DIRS glade/glade.h ) FIND_LIBRARY( LIBGLADE_LIBRARIES glade-2.0) # Report results IF ( LIBGLADE_LIBRARIES AND LIBGLADE_INCLUDE_DIRS ) SET( LIBGLADE_FOUND 1 ) IF ( NOT LIBGLADE_FIND_QUIETLY ) MESSAGE( STATUS "Found LIBGLADE: ${LIBGLADE_LIBRARIES}" ) ENDIF ( NOT LIBGLADE_FIND_QUIETLY ) ELSE ( LIBGLADE_LIBRARIES AND LIBGLADE_INCLUDE_DIRS ) IF ( LibGlade_FIND_REQUIRED ) MESSAGE( SEND_ERROR "Could NOT find LIBGLADE" ) ELSE ( LibGlade_FIND_REQUIRED ) IF ( NOT LIBGLADE_FIND_QUIETLY ) MESSAGE( STATUS "Could NOT find LIBGLADE" ) ENDIF ( NOT LIBGLADE_FIND_QUIETLY ) ENDIF ( LibGlade_FIND_REQUIRED ) ENDIF ( LIBGLADE_LIBRARIES AND LIBGLADE_INCLUDE_DIRS ) ENDIF( NOT LIBGLADE_FOUND AND NOT PKG_CONFIG_FOUND ) # Hide advanced variables from CMake GUIs MARK_AS_ADVANCED( LIBGLADE_LIBRARIES LIBGLADE_INCLUDE_DIRS ) libsyncml-0.5.4/cmake/modules/FindLibLdap.cmake100644 1750 1750 2477 11211710410 21275 0ustar00bellmichbellmich# Try and find libldap. # As soon as libldap has been found, the following variables will be defined: # # LIBLDAP_FOUND # LDAP_INCLUDE_DIR # LDAP_LIBRARY:FILEPATH # # # Copyright (c) 2009 Juergen Leising # # Redistribution and use is allowed according to the terms of the New # BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # MESSAGE(STATUS "checking for libldap...") FIND_PATH(LDAP_INCLUDE_DIR NAMES ldap.h PATHS /include /usr/include /usr/local/include /usr/share/include /opt/include DOC "Try and find the header file ldap.h") FIND_LIBRARY(LDAP_LIBRARY NAMES ldap PATHS /usr/lib /lib /usr/local/lib /usr/share/lib /opt/lib /opt/share/lib /var/lib DOC "Try and find libldap") IF (LDAP_INCLUDE_DIR AND LDAP_LIBRARY) SET( LIBLDAP_FOUND 1 ) get_filename_component(LDAP_LIBRARY_DIRS ${LDAP_LIBRARY} PATH) MESSAGE(STATUS " Found ${LDAP_LIBRARY}") ELSE (LDAP_INCLUDE_DIR AND LDAP_LIBRARY) IF ( LibLdap_FIND_REQUIRED ) MESSAGE( FATAL_ERROR " Could NOT find libldap. The ldap plugin needs this library.") ELSE ( LibLdap_FIND_REQUIRED ) MESSAGE( STATUS " Could NOT find libldap.") ENDIF ( LibLdap_FIND_REQUIRED ) ENDIF (LDAP_INCLUDE_DIR AND LDAP_LIBRARY) libsyncml-0.5.4/cmake/modules/FindLibDbus.cmake100644 1750 1750 3413 11211710410 21301 0ustar00bellmichbellmich# - Try to find LIBDBUS # Find LIBDBUS headers, libraries and the answer to all questions. # # LIBDBUS_FOUND True if libdbus got found # LIBDBUS_INCLUDE_DIRS Location of libdbus headers # LIBDBUS_LIBRARIES List of libraries to use libdbus # # Copyright (c) 2008 Bjoern Ricks # # Redistribution and use is allowed according to the terms of the New # BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # INCLUDE( FindPkgConfig ) IF ( LibDbus_FIND_REQUIRED ) SET( _pkgconfig_REQUIRED "REQUIRED" ) ELSE( LibDbus_FIND_REQUIRED ) SET( _pkgconfig_REQUIRED "" ) ENDIF ( LibDbus_FIND_REQUIRED ) IF ( LIBDBUS_MIN_VERSION ) PKG_SEARCH_MODULE( LIBDBUS ${_pkgconfig_REQUIRED} dbus-1>=${LIBDBUS_MIN_VERSION} ) ELSE ( LIBDBUS_MIN_VERSION ) PKG_SEARCH_MODULE( LIBDBUS ${_pkgconfig_REQUIRED} dbus-1 ) ENDIF ( LIBDBUS_MIN_VERSION ) IF( NOT LIBDBUS_FOUND AND NOT PKG_CONFIG_FOUND ) FIND_PATH( LIBDBUS_INCLUDE_DIRS dbus/dbus.h PATH_SUFFIXES dbus-1.0 dbus ) FIND_LIBRARY( LIBDBUS_LIBRARIES dbus dbus-1) # Report results IF ( LIBDBUS_LIBRARIES AND LIBDBUS_INCLUDE_DIRS ) SET( LIBDBUS_FOUND 1 ) IF ( NOT LIBDBUS_FIND_QUIETLY ) MESSAGE( STATUS "Found libdbus: ${LIBDBUS_LIBRARIES}" ) ENDIF ( NOT LIBDBUS_FIND_QUIETLY ) ELSE ( LIBDBUS_LIBRARIES AND LIBDBUS_INCLUDE_DIRS ) IF ( LIBDBUS_FIND_REQUIRED ) MESSAGE( SEND_ERROR "Could NOT find libdbus" ) ELSE ( LIBDBUS_FIND_REQUIRED ) IF ( NOT LIBDBUS_FIND_QUIETLY ) MESSAGE( STATUS "Could NOT find libdbus" ) ENDIF ( NOT LIBDBUS_FIND_QUIETLY ) ENDIF ( LIBDBUS_FIND_REQUIRED ) ENDIF ( LIBDBUS_LIBRARIES AND LIBDBUS_INCLUDE_DIRS ) ENDIF( NOT LIBDBUS_FOUND AND NOT PKG_CONFIG_FOUND ) MARK_AS_ADVANCED( LIBDBUS_LIBRARIES LIBDBUS_INCLUDE_DIRS )libsyncml-0.5.4/cmake/modules/FindLibSASL2.cmake100644 1750 1750 2543 11211710410 21233 0ustar00bellmichbellmich# Try and find libsasl2. # As soon as libsasl2 has been found, the following variables will be defined: # # LIBSASL2_FOUND # SASL2_INCLUDE_DIR # SASL2_LIBRARY:FILEPATH # # Copyright (c) 2009 Juergen Leising # # Redistribution and use is allowed according to the terms of the New # BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # MESSAGE(STATUS "checking for libsasl2...") FIND_PATH(SASL2_INCLUDE_DIR NAMES sasl/sasl.h PATHS /include /usr/include /usr/local/include /usr/share/include /opt/include DOC "Try and find the header file sasl/sasl.h") FIND_LIBRARY(SASL2_LIBRARY NAMES sasl2 PATHS /usr/lib /lib /usr/local/lib /usr/share/lib /opt/lib /opt/share/lib /var/lib DOC "Try and find libsasl2") IF (SASL2_INCLUDE_DIR AND SASL2_LIBRARY) SET (LIBSASL2_FOUND 1) get_filename_component(SASL2_LIBRARY_DIRS ${SASL2_LIBRARY} PATH) MESSAGE(STATUS " Found ${SASL2_LIBRARY}") ELSE (SASL2_INCLUDE_DIR AND SASL2_LIBRARY) IF ( LibSASL2_FIND_REQUIRED ) MESSAGE( FATAL_ERROR " Could NOT find libsasl2. The ldap plugin needs this library." ) ELSE ( LibSASL2_FIND_REQUIRED ) MESSAGE( STATUS " Could NOT find libsasl2.") ENDIF ( LibSASL2_FIND_REQUIRED ) ENDIF (SASL2_INCLUDE_DIR AND SASL2_LIBRARY) libsyncml-0.5.4/cmake/modules/FindSWIG.cmake100644 1750 1750 3602 11211710410 20526 0ustar00bellmichbellmich# - Find SWIG # This module finds an installed SWIG. It sets the following variables: # SWIG_FOUND - set to true if SWIG is found # SWIG_DIR - the directory where swig is installed # SWIG_EXECUTABLE - the path to the swig executable SET(SWIG_FOUND FOOBAR) FILE(GLOB_RECURSE SWIGSWG /usr/share/swig/swig.swg) FILE(GLOB_RECURSE SWIGCONFIG /usr/share/swig/SWIGConfig.cmake) FOREACH(_file ${SWIGCONFIG} ${SWIGSWG} ) GET_FILENAME_COMPONENT(SWIG_DIR ${_file} PATH) ENDFOREACH(_file) FIND_PATH(SWIG_DIR SWIGConfig.cmake /usr/share/swig1.3 /usr/lib/swig1.3 /usr/local/share/swig1.3) FIND_PATH(SWIG_DIR swig.swg /usr/share/swig1.3 /usr/lib/swig1.3 /usr/local/share/swig1.3) IF(EXISTS ${SWIG_DIR}) IF("x${SWIG_DIR}x" STREQUAL "x${CMAKE_ROOT}/Modulesx") MESSAGE("SWIG_DIR should not be modules subdirectory of CMake") ENDIF("x${SWIG_DIR}x" STREQUAL "x${CMAKE_ROOT}/Modulesx") IF(EXISTS ${SWIG_DIR}/SWIGConfig.cmake) INCLUDE(${SWIG_DIR}/SWIGConfig.cmake) SET(SWIG_FOUND 1) ELSE(EXISTS ${SWIG_DIR}/SWIGConfig.cmake) FIND_PROGRAM(SWIG_EXECUTABLE NAMES swig-1.3 swig PATHS ${SWIG_DIR} ${SWIG_DIR}/.. ${SWIG_DIR}/../../bin /usr/bin /usr/local/bin ) SET(SWIG_USE_FILE ${CMAKE_ROOT}/Modules/UseSWIG.cmake) ENDIF(EXISTS ${SWIG_DIR}/SWIGConfig.cmake) ENDIF(EXISTS ${SWIG_DIR}) IF("x${SWIG_FOUND}x" STREQUAL "xFOOBARx") SET(SWIG_FOUND 0) IF(EXISTS ${SWIG_DIR}) IF(EXISTS ${SWIG_USE_FILE}) IF(EXISTS ${SWIG_EXECUTABLE}) SET(SWIG_FOUND 1) MESSAGE(STATUS "Found SWIG: ${SWIG_EXECUTABLE}" ) ENDIF(EXISTS ${SWIG_EXECUTABLE}) ENDIF(EXISTS ${SWIG_USE_FILE}) ENDIF(EXISTS ${SWIG_DIR}) IF(NOT ${SWIG_FOUND}) IF(${SWIG_FIND_REQUIRED}) MESSAGE(FATAL_ERROR "SWIG was not found on the system. Please specify the location of SWIG.") ENDIF(${SWIG_FIND_REQUIRED}) ENDIF(NOT ${SWIG_FOUND}) ENDIF("x${SWIG_FOUND}x" STREQUAL "xFOOBARx") libsyncml-0.5.4/cmake/modules/FindThunderbirdXpcom.cmake100644 1750 1750 23717 11211710410 23267 0ustar00bellmichbellmich# ====================================================== # This file is part of the mozilla-sync plugin for OpenSync # See http://www.KaarPoSoft.dk/bluezync # $Id: FindThunderbirdXpcom.cmake 5617 2009-04-17 22:25:03Z henrik $ # ====================================================== # The purpose of this CMake file is to find Thunderbird and Sunbird files and versions. # It should work with Icedove and Iceowl as well # First we look for a Thunderbird package PKG_SEARCH_MODULE ( THUNDERBIRD_XPCOM thunderbird-xpcom icedove-xpcom ) IF ( THUNDERBIRD_XPCOM_FOUND ) # If we found the Thunderbird package, look for one of the includes, just to be sure FIND_PATH ( THUNDERBIRD_XPCOM_MAIN_INCLUDE_DIR mozilla-config.h PATHS ${THUNDERBIRD_XPCOM_INCLUDE_DIRS} ) IF( NOT THUNDERBIRD_XPCOM_MAIN_INCLUDE_DIR ) MESSAGE ( FATAL_ERROR "*** *** Found Thunderbird package, but not mozilla-config.h" ) ENDIF ( NOT THUNDERBIRD_XPCOM_MAIN_INCLUDE_DIR ) # We also need NSPR, so let's make sure it is there FIND_PATH ( NSPR_MAIN_INCLUDE_DIR nspr.h PATHS ${THUNDERBIRD_XPCOM_INCLUDE_DIRS} ) IF( NOT NSPR_MAIN_INCLUDE_DIR ) MESSAGE ( FATAL_ERROR "*** *** Found Thunderbird package, but not nspr.h" ) ENDIF ( NOT NSPR_MAIN_INCLUDE_DIR ) ELSE( THUNDERBIRD_XPCOM_FOUND ) # We did not find a Thunderbird package, so let us look for the files manually MESSAGE ( STATUS " did not find thunderbird package; now looking for thunderbird files" ) FIND_PATH (THUNDERBIRD_XPCOM_MAIN_INCLUDE_DIR mozilla-config.h PATH_SUFFIXES thunderbird icedove PATHS /opt/local/include/ /sw/include/ /usr/local/include/ /usr/include/ /usr/lib64/mozilla-thunderbird/include/ ) IF ( NOT THUNDERBIRD_XPCOM_MAIN_INCLUDE_DIR ) MESSAGE ( FATAL_ERROR "*** *** Did not find Thunderbird include directory with mozilla-config.h" ) ENDIF ( NOT THUNDERBIRD_XPCOM_MAIN_INCLUDE_DIR ) FIND_PATH ( NSPR_MAIN_INCLUDE_DIR nspr.h PATH_SUFFIXES nspr nspr4 PATHS /opt/local/include/ /sw/include/ /usr/local/include/ /usr/include/ ) IF( NOT NSPR_MAIN_INCLUDE_DIR ) MESSAGE ( FATAL_ERROR "*** *** Found Thunderbird include directory, but not nspr.h" ) ENDIF ( NOT NSPR_MAIN_INCLUDE_DIR ) # Usually all the libraries are in one directory, so let us try to find it FIND_LIBRARY ( _xpcom_lib NAMES xpcom libxpcom PATH_SUFFIXES thunderbird icedove PATHS /opt/local/lib /sw/lib /usr/lib /usr/local/lib /usr/lib64 /usr/local/lib64 /opt/lib64 ) IF ( WIN32 AND NOT _xpcom_lib ) GET_FILENAME_COMPONENT ( _tbdir "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\thunderbird.exe]" PATH CACHE) FIND_LIBRARY ( _xpcom_lib NAMES xpcom libxpcom PATHS "${_tbdir}" ) ENDIF ( WIN32 AND NOT _xpcom_lib ) IF ( NOT _xpcom_lib ) MESSAGE ( FATAL_ERROR "*** *** Found Thunderbird, but not the xpcom library" ) ENDIF ( NOT _xpcom_lib ) # We got the actual library, but we need the directory GET_FILENAME_COMPONENT ( THUNDERBIRD_XPCOM_LIBRARY_DIRS "${_xpcom_lib}" PATH ) # Usually the only library we need is the xpcom SET ( THUNDERBIRD_XPCOM_LIBRARIES "xpcom" ) IF ( WIN32 ) SET ( THUNDERBIRD_XPCOM_LIBRARIES "xpcom;xpcom_compat;xpcom_core;xpistub" ) ENDIF ( WIN32 ) # For Thunderbird 3.0 we need to link the glue library EXEC_PROGRAM ( thunderbird ARGS "--version" OUTPUT_VARIABLE THUNDERBIRD_XPCOM_VERSION RETURN_VALUE _THUNDERBIRD_XPCOM_VERSION_RET ) IF ( _THUNDERBIRD_XPCOM_VERSION_RET ) EXEC_PROGRAM ( icedove ARGS "--version" OUTPUT_VARIABLE THUNDERBIRD_XPCOM_VERSION RETURN_VALUE _THUNDERBIRD_XPCOM_VERSION_RET ) ENDIF ( _THUNDERBIRD_XPCOM_VERSION_RET ) IF ( WIN32 AND _THUNDERBIRD_XPCOM_VERSION_RET ) GET_FILENAME_COMPONENT ( _tb_exe "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\thunderbird.exe]" ABSOLUTE CACHE) EXEC_PROGRAM ( "${_tb_exe}" ARGS "--version" OUTPUT_VARIABLE THUNDERBIRD_XPCOM_VERSION RETURN_VALUE _THUNDERBIRD_XPCOM_VERSION_RET ) ENDIF ( WIN32 AND _THUNDERBIRD_XPCOM_VERSION_RET ) IF (_THUNDERBIRD_XPCOM_VERSION_RET ) MESSAGE ( FATAL_ERROR "*** *** Unable execute Thunderbird/Icedove to get its version" ) ENDIF ( _THUNDERBIRD_XPCOM_VERSION_RET ) STRING ( REGEX MATCH ".* ([0-9]\\.[0-9]).*" _THUNDERBIRD_XPCOM_VERSION_OK "${THUNDERBIRD_XPCOM_VERSION}" ) IF ( _THUNDERBIRD_XPCOM_VERSION_OK ) STRING (REGEX REPLACE ".* ([0-9]\\.[0-9]).*" "\\1" THUNDERBIRD_XPCOM_VERSION "${THUNDERBIRD_XPCOM_VERSION}" ) ENDIF ( _THUNDERBIRD_XPCOM_VERSION_OK ) ENDIF( THUNDERBIRD_XPCOM_FOUND ) STRING ( REGEX MATCH ".*([0-9]\\.[0-9]).*" _THUNDERBIRD_XPCOM_VERSION_OK "${THUNDERBIRD_XPCOM_VERSION}" ) IF ( _THUNDERBIRD_XPCOM_VERSION_OK ) # Thunderbird main version STRING (REGEX REPLACE "^([0-9]+)\\..*$" "\\1" THUNDERBIRD_VERSION_MAIN "${THUNDERBIRD_XPCOM_VERSION}" ) ELSE ( _THUNDERBIRD_XPCOM_VERSION_OK ) MESSAGE ( STATUS "Unable to interpret Thunderbird version [${THUNDERBIRD_XPCOM_VERSION}]; continuing anyway" ) ENDIF ( _THUNDERBIRD_XPCOM_VERSION_OK ) # Thunderbird 3 IF ( THUNDERBIRD_VERSION_MAIN STREQUAL "3" ) SET ( THUNDERBIRD_XPCOM_LIBRARIES "xpcomglue_s;xpcom" ) ENDIF ( THUNDERBIRD_VERSION_MAIN STREQUAL "3" ) # So, by now we should have the following variables set: MESSAGE ( STATUS " THUNDERBIRD_XPCOM_VERSION ${THUNDERBIRD_XPCOM_VERSION}" ) MESSAGE ( STATUS " THUNDERBIRD_VERSION_MAIN ${THUNDERBIRD_VERSION_MAIN}" ) MESSAGE ( STATUS " THUNDERBIRD_XPCOM_MAIN_INCLUDE_DIR ${THUNDERBIRD_XPCOM_MAIN_INCLUDE_DIR}" ) MESSAGE ( STATUS " NSPR_MAIN_INCLUDE_DIR ${NSPR_MAIN_INCLUDE_DIR}" ) MESSAGE ( STATUS " THUNDERBIRD_XPCOM_LIBRARY_DIRS ${THUNDERBIRD_XPCOM_LIBRARY_DIRS}" ) MESSAGE ( STATUS " THUNDERBIRD_XPCOM_LIBRARIES ${THUNDERBIRD_XPCOM_LIBRARIES}" ) # Those are the include directories we actually need SET ( XPCOM_INCLUDE_DIRS ${NSPR_MAIN_INCLUDE_DIR} ${THUNDERBIRD_XPCOM_MAIN_INCLUDE_DIR} ${THUNDERBIRD_XPCOM_MAIN_INCLUDE_DIR}/addrbook ${THUNDERBIRD_XPCOM_MAIN_INCLUDE_DIR}/extensions ${THUNDERBIRD_XPCOM_MAIN_INCLUDE_DIR}/rdf ${THUNDERBIRD_XPCOM_MAIN_INCLUDE_DIR}/string ${THUNDERBIRD_XPCOM_MAIN_INCLUDE_DIR}/xpcom_obsolete ${THUNDERBIRD_XPCOM_MAIN_INCLUDE_DIR}/xpcom ${THUNDERBIRD_XPCOM_MAIN_INCLUDE_DIR}/xulapp ) # ---------------------------------------- # Now look for a Subird package PKG_SEARCH_MODULE ( SUNBIRD sunbird-xpcom iceowl-xpcom ) IF ( SUNBIRD_FOUND ) # If we found the Thunderbird package, let us try to find the main include dir MESSAGE ( " SUNBIRD_INCLUDE_DIRS ${SUNBIRD_INCLUDE_DIRS}" ) # ---------- We just need the first directory, which should be the main directory # The rest will point to xpcom and friends; and we do not want that. # But, let's also handle the special case of only one direcory reported, just in case STRING ( REGEX MATCH ";" _SEVERAL_INCLUDE_DIRS "${SUNBIRD_INCLUDE_DIRS}" ) IF ( _SEVERAL_INCLUDE_DIRS ) MESSAGE ( "SEVERAL") STRING ( REGEX REPLACE "([^;]*);.*" "\\1" SUNBIRD_MAIN_INCLUDE_DIR "${SUNBIRD_INCLUDE_DIRS}" ) ELSE ( _SEVERAL_INCLUDE_DIRS ) SET ( SUNBIRD_MAIN_INCLUDE_DIR "${SUNBIRD_INCLUDE_DIRS}" ) ENDIF ( _SEVERAL_INCLUDE_DIRS ) ELSE( SUNBIRD_FOUND ) # We did not find a Sunbird package, so let us look for the files manually MESSAGE ( STATUS " did not find sunbird package; now looking for sunbird files" ) FIND_PATH ( SUNBIRD_MAIN_INCLUDE_DIR calbase/calIICSService.h PATH_SUFFIXES sunbird iceowl PATHS /opt/local/include/ /sw/include/ /usr/local/include/ /usr/include/ ) IF ( NOT SUNBIRD_MAIN_INCLUDE_DIR ) MESSAGE ( FATAL_ERROR "*** *** Did not find Sunbird include directory with mozilla-config.h" ) ENDIF ( NOT SUNBIRD_MAIN_INCLUDE_DIR ) # We need the Sunbird version number EXEC_PROGRAM ( sunbird ARGS "--version" OUTPUT_VARIABLE SUNBIRD_VERSION RETURN_VALUE _SUNBIRD_VERSION_RET ) IF ( _SUNBIRD_VERSION_RET ) EXEC_PROGRAM ( iceowl ARGS "--version" OUTPUT_VARIABLE SUNBIRD_VERSION RETURN_VALUE _SUNBIRD_VERSION_RET ) ENDIF ( _SUNBIRD_VERSION_RET ) IF ( WIN32 AND _SUNBIRD_VERSION_RET ) GET_FILENAME_COMPONENT ( _sb_exe "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\sunbird.exe]" ABSOLUTE CACHE) EXEC_PROGRAM ( "${_sb_exe}" ARGS "--version" OUTPUT_VARIABLE SUNBIRD_VERSION RETURN_VALUE _SUNBIRD_VERSION_RET ) ENDIF ( WIN32 AND _SUNBIRD_VERSION_RET ) IF ( _SUNBIRD_VERSION_RET ) MESSAGE ( FATAL_ERROR "*** *** Unable execute sunbird/iceowl to get its version" ) ENDIF ( _SUNBIRD_VERSION_RET ) STRING ( REGEX MATCH ".* ([0-9]\\.[0-9]).*" _SUNBIRD_VERSION_OK "${SUNBIRD_VERSION}" ) IF ( _SUNBIRD_VERSION_OK ) STRING (REGEX REPLACE ".* ([0-9]\\.[0-9]).*" "\\1" SUNBIRD_VERSION "${SUNBIRD_VERSION}" ) ENDIF ( _SUNBIRD_VERSION_OK ) ENDIF ( SUNBIRD_FOUND ) STRING ( REGEX MATCH ".*([0-9]\\.[0-9]).*" _SUNBIRD_VERSION_OK "${SUNBIRD_VERSION}" ) IF ( _SUNBIRD_VERSION_OK ) # Sunbird main version STRING (REGEX REPLACE "^([0-9]+)\\..*$" "\\1" SUNBIRD_VERSION_MAIN "${SUNBIRD_VERSION}" ) ELSE ( _SUNBIRD_VERSION_OK ) MESSAGE ( FATAL_ERROR "*** ***Unable to interpret Sunbird version [${_SUNBIRD_VERSION}]" ) ENDIF ( _SUNBIRD_VERSION_OK ) # ---------------------------------------- # So, by now we should have the following variables set: MESSAGE ( STATUS " SUNBIRD_MAIN_INCLUDE_DIR ${SUNBIRD_MAIN_INCLUDE_DIR}" ) MESSAGE ( STATUS " SUNBIRD_VERSION ${SUNBIRD_VERSION}" ) # Set the final output variables SET ( XPCOM_INCLUDE_DIRS "${XPCOM_INCLUDE_DIRS};${SUNBIRD_MAIN_INCLUDE_DIR}" ) SET ( XPCOM_LIBRARY_DIRS "${THUNDERBIRD_XPCOM_LIBRARY_DIRS}" ) SET ( XPCOM_LIBRARIES "${THUNDERBIRD_XPCOM_LIBRARIES}" ) # And here is what we found out: MESSAGE ( STATUS "Found xpcom (thunderbird and sunbird):" ) MESSAGE ( STATUS " THUNDERBIRD_XPCOM_VERSION=[${THUNDERBIRD_XPCOM_VERSION}]" ) MESSAGE ( STATUS " SUNBIRD_VERSION=[${SUNBIRD_VERSION}]" ) MESSAGE ( STATUS " THUNDERBIRD_VERSION_MAIN=[${THUNDERBIRD_VERSION_MAIN}]" ) MESSAGE ( STATUS " SUNBIRD_VERSION_MAIN=[${SUNBIRD_VERSION_MAIN}]" ) MESSAGE ( STATUS " XPCOM_INCLUDE_DIRS ${XPCOM_INCLUDE_DIRS}" ) MESSAGE ( STATUS " XPCOM_LIBRARY_DIRS ${XPCOM_LIBRARY_DIRS}" ) MESSAGE ( STATUS " XPCOM_LIBRARIES ${XPCOM_LIBRARIES}" ) MESSAGE ( STATUS " SUNBIRD_VERSION ${SUNBIRD_VERSION}" ) libsyncml-0.5.4/cmake/modules/Compiler.cmake100644 1750 1750 2045 11211710410 20726 0ustar00bellmichbellmich# Copyright (c) 2007 Daniel Gollub IF ( CMAKE_COMPILER_IS_GNUCC ) SET( SYMBOLS_VISIBILITY "-fvisibility=hidden" ) SET( CMAKE_C_FLAGS_HACKING "-O2 -fmessage-length=0 -Wall -Werror -D_FORTIFY_SOURCE=2 -fstack-protector -g" CACHE STRING "Developer C Compiler Flags" ) SET( CMAKE_CXX_FLAGS_HACKING "-O2 -fmessage-length=0 -Wall -Werror -D_FORTIFY_SOURCE=2 -fstack-protector -g" CACHE STRING "Developer C++ Compiler Flags" ) ENDIF ( CMAKE_COMPILER_IS_GNUCC ) IF (CMAKE_SYSTEM MATCHES "SunOS-5*.") SET( SYMBOLS_VISIBILITY "-xldscope=hidden" ) ENDIF (CMAKE_SYSTEM MATCHES "SunOS-5*.") IF ( SYMBOLS_VISIBILITY ) INCLUDE( CheckCCompilerFlag ) check_c_compiler_flag( ${SYMBOLS_VISIBILITY} COMPILER_SUPPORTS_VISIBILITY ) ENDIF ( SYMBOLS_VISIBILITY ) IF (NOT COMPILER_SUPPORTS_VISIBILITY) SET( SYMBOLS_VISIBILITY "" ) ENDIF (NOT COMPILER_SUPPORTS_VISIBILITY) IF ( MSVC ) # Some compiler options for MSVC to not print non-sense warnings. ADD_DEFINITIONS ( -D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE ) ENDIF ( MSVC ) libsyncml-0.5.4/cmake/modules/ShowStatus.cmake100644 1750 1750 1224 11211710410 21276 0ustar00bellmichbellmich# Shows status of a option variable # # usage: SHOW_STATUS( ) # # Copyright (C) 2007 Bjoern Ricks # # Redistribution and use is allowed according to the terms of the New # BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # MACRO( SHOW_STATUS _name _message ) IF( DEFINED ${_name} ) IF( ${ARGV2} ) MESSAGE( STATUS "${_message}\t\t${${_name}}\t(${${ARGV2}})" ) ELSE( ${ARGV2} ) MESSAGE( STATUS "${_message}\t\t${${_name}}" ) ENDIF( ${ARGV2} ) ELSE( DEFINED ${_name} ) MESSAGE( STATUS "${_message}\t\tOFF" ) ENDIF( DEFINED ${_name}) ENDMACRO( SHOW_STATUS ) libsyncml-0.5.4/cmake/modules/FindEDataBook1.0.cmake100644 1750 1750 11463 11211710410 22011 0ustar00bellmichbellmich# - Try to find libedatabook1.0 components # Find libedatabook 1.0 headers, libraries and the answer to all questions. # # LIBEDATABOOK1.0_FOUND True if libedatabook1.0 got found # LIBEDATABOOK1.0_INCLUDE_DIRS Location of libedatabook1.0 headers # LIBEDATABOOK1.0_LIBRARIES List of libaries to use libedatabook1.0 # LIBEDATABOOK1.0_DEFINITIONS Definitions to compile libedatabook1.0 # # Copyright (c) 2007 Juha Tuomala # Copyright (c) 2007 Daniel Gollub # Copyright (c) 2007 Alban Browaeys # # Redistribution and use is allowed according to the terms of the New # BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # INCLUDE( FindPkgConfig ) # Take care about libedata-book-1.0.pc settings IF ( EDataBook1.0_FIND_REQUIRED ) SET( _pkgconfig_REQUIRED "REQUIRED" ) ELSE ( EDataBook1.0_FIND_REQUIRED ) SET( _pkgconfig_REQUIRED "" ) ENDIF ( EDataBook1.0_FIND_REQUIRED ) pkg_search_module( LIBEDATABOOK1.0 ${_pkgconfig_REQUIRED} libedata-book-1.0 ) # Look for libedatabook1.0 include dir and libraries w/o pkg-config. IF ( NOT LIBEDATABOOK1.0_FOUND AND NOT PKG_CONFIG_FOUND ) FIND_PATH( _libedatabook1.0_include_DIR libedata-book/e-data-book.h PATH_SUFFIXES evolution-data-server-1.12 evolution-data-server-1.10 evolution-data-server-1.8 evolution-data-server-1.6 evolution-data-server-1.4 evolution-data-server-1.0 PATHS /opt/local/include/ /sw/include/ /usr/local/include/ /usr/include/ ) FIND_LIBRARY( _libedatabook1.0_link_DIR edata-book-1.0 PATHS /opt/local/lib /sw/lib /usr/lib /usr/local/lib /usr/lib64 /usr/local/lib64 /opt/lib64 ) IF ( _libedatabook1.0_include_DIR AND _libedatabook1.0_link_DIR ) SET ( _libedatabook1.0_FOUND TRUE ) ENDIF ( _libedatabook1.0_include_DIR AND _libedatabook1.0_link_DIR ) IF ( _libedatabook1.0_FOUND ) SET ( LIBEDATABOOK1.0_INCLUDE_DIRS ${_libedatabook1.0_include_DIR} ) SET ( LIBEDATABOOK1.0_LIBRARIES ${_libedatabook1.0_link_DIR} ) ENDIF ( _libedatabook1.0_FOUND ) # Handle dependencies IF ( NOT LIBEBOOK1.0_FOUND ) FIND_PACKAGE ( EBook1.0 REQUIRED ) IF ( LIBEBOOK1.0_FOUND ) SET ( LIBEDATABOOK1.0_INCLUDE_DIRS ${LIBEDATABOOK1.0_INCLUDE_DIRS} ${LIBEBOOK1.0_INCLUDE_DIRS} ) SET ( LIBEDATABOOK1.0_LIBRARIES ${LIBEDATABOOK1.0_LIBRARIES} ${LIBEBOOK1.0_LIBRARIES} ) ENDIF ( LIBEBOOK1.0_FOUND ) ENDIF ( NOT LIBEBOOK1.0_FOUND ) IF ( NOT LIBEDATASERVER1.0_FOUND ) FIND_PACKAGE ( EDataServer1.0 REQUIRED ) IF ( LIBEDATASERVER1.0_FOUND ) SET ( LIBEDATABOOK1.0_INCLUDE_DIRS ${LIBEDATABOOK1.0_INCLUDE_DIRS} ${LIBEDATASERVER1.0_INCLUDE_DIRS} ) SET ( LIBEDATABOOK1.0_LIBRARIES ${LIBEDATABOOK1.0_LIBRARIES} ${LIBEDATASERVER1.0_LIBRARIES} ) ENDIF ( LIBEDATASERVER1.0_FOUND ) ENDIF ( NOT LIBEDATASERVER1.0_FOUND ) IF ( NOT LIBGNOME2_FOUND ) FIND_PACKAGE ( LibGnome2 REQUIRED ) IF ( LIBGNOME2_FOUND ) SET ( LIBEDATABOOK1.0_INCLUDE_DIRS ${LIBEDATABOOK1.0_INCLUDE_DIRS} ${LIBGNOME2_INCLUDE_DIRS} ) SET ( LIBEDATABOOK1.0_LIBRARIES ${LIBEDATABOOK1.0_LIBRARIES} ${LIBGNOME2_LIBRARIES} ) ENDIF ( LIBGNOME2_FOUND ) ENDIF ( NOT LIBGNOME2_FOUND ) IF ( NOT BONOBO2_FOUND ) SET ( BONOBO2_MIN_VERSION "2.4.2" ) FIND_PACKAGE ( BONOBO2 REQUIRED ) IF ( BONOBO2_FOUND ) SET ( LIBEDATABOOK1.0_INCLUDE_DIRS ${LIBEDATABOOK1.0_INCLUDE_DIRS} ${BONOBO2_INCLUDE_DIRS} ) SET ( LIBEDATABOOK1.0_LIBRARIES ${LIBEDATABOOK1.0_LIBRARIES} ${BONOBO2_LIBRARIES} ) ENDIF ( BONOBO2_FOUND ) ENDIF ( NOT BONOBO2_FOUND ) # Report results IF ( LIBEDATABOOK1.0_LIBRARIES AND LIBEDATABOOK1.0_INCLUDE_DIRS AND _libedatabook1.0_FOUND ) SET( LIBEDATABOOK1.0_FOUND 1 ) IF ( NOT EDataBook1.0_FIND_QUIETLY ) MESSAGE( STATUS "Found libedatabook-1.0: ${LIBEDATABOOK1.0_LIBRARIES}" ) ENDIF ( NOT EDataBook1.0_FIND_QUIETLY ) ELSE ( LIBEDATABOOK1.0_LIBRARIES AND LIBEDATABOOK1.0_INCLUDE_DIRS AND _libedatabook1.0_FOUND ) IF ( EDataBook1.0_FIND_REQUIRED ) MESSAGE( SEND_ERROR "Could NOT find libedatabook-1.0" ) ELSE ( EDataBook1.0_FIND_REQUIRED ) IF ( NOT EDataBook1.0_FIND_QUIETLY ) MESSAGE( STATUS "Could NOT find libedatabook-1.0" ) ENDIF ( NOT EDataBook1.0_FIND_QUIETLY ) ENDIF ( EDataBook1.0_FIND_REQUIRED ) ENDIF ( LIBEDATABOOK1.0_LIBRARIES AND LIBEDATABOOK1.0_INCLUDE_DIRS AND _libedatabook1.0_FOUND ) ENDIF ( NOT LIBEDATABOOK1.0_FOUND AND NOT PKG_CONFIG_FOUND ) # Hide advanced variables from CMake GUIs MARK_AS_ADVANCED( LIBEDATABOOK1.0_LIBRARIES LIBEDATABOOK1.0_INCLUDE_DIRS ) libsyncml-0.5.4/cmake/modules/FindLibXml2.cmake100644 1750 1750 5232 11211710410 21227 0ustar00bellmichbellmich# - Try to find libxml2 # Find libxml2 headers, libraries and the answer to all questions. # # LIBXML2_FOUND True if libxml2 got found # LIBXML2_INCLUDE_DIRS Location of libxml2 headers # LIBXML2_LIBRARIES List of libraries to use libxml2 # LIBXML2_DEFINITIONS Definitions to compile libxml2 # # Copyright (c) 2006, Alexander Neundorf, # Copyright (c) 2007 Alban Browaeys # Copyright (c) 2008 Bjoern Ricks # # Redistribution and use is allowed according to the terms of the New # BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # INCLUDE( FindPkgConfig ) # Take care about libxml2.pc settings IF ( LibXml2_FIND_REQUIRED ) SET( _pkgconfig_REQUIRED "REQUIRED" ) ELSE ( LibXml2_FIND_REQUIRED ) SET( _pkgconfig_REQUIRED "" ) ENDIF ( LibXml2_FIND_REQUIRED ) IF ( LIBXML2_MIN_VERSION ) PKG_SEARCH_MODULE( LIBXML2 ${_pkgconfig_REQUIRED} libxml-2.0>=${LIBXML2_MIN_VERSION} ) ELSE ( LIBXML2_MIN_VERSION ) PKG_SEARCH_MODULE( LIBXML2 ${_pkgconfig_REQUIRED} libxml-2.0 ) ENDIF ( LIBXML2_MIN_VERSION ) # Look for libxml-2.0 include dir and libraries w/o pkgconfig IF ( NOT LIBXML2_FOUND AND NOT PKG_CONFIG_FOUND ) FIND_PATH( _libxml2_include_DIR libxml/xpath.h PATH_SUFFIXES libxml2 PATHS /opt/local/include/ /sw/include/ /usr/local/include/ /usr/include/ ) FIND_LIBRARY( _libxml2_link_DIR NAMES xml2 libxml2 libxml PATHS /opt/local/lib /sw/lib /usr/lib /usr/local/lib /usr/lib64 /usr/local/lib64 /opt/lib64 ) IF ( _libxml2_include_DIR AND _libxml2_link_DIR ) SET ( _libxml2_FOUND TRUE ) ENDIF ( _libxml2_include_DIR AND _libxml2_link_DIR ) IF ( _libxml2_FOUND ) SET ( LIBXML2_INCLUDE_DIRS ${_libxml2_include_DIR} ) SET ( LIBXML2_LIBRARIES ${_libxml2_link_DIR} ) ENDIF ( _libxml2_FOUND ) # Report results IF ( LIBXML2_LIBRARIES AND LIBXML2_INCLUDE_DIRS AND _libxml2_FOUND ) SET( LIBXML2_FOUND 1 ) IF ( NOT LibXml2_FIND_QUIETLY ) MESSAGE( STATUS "Found libxml2: ${LIBXML2_LIBRARIES} ${LIBXML2_INCLUDE_DIRS}" ) ENDIF ( NOT LibXml2_FIND_QUIETLY ) ELSE ( LIBXML2_LIBRARIES AND LIBXML2_INCLUDE_DIRS AND _libxml2_FOUND ) IF ( LibXml2_FIND_REQUIRED ) MESSAGE( SEND_ERROR "Could NOT find libxml2" ) ELSE ( LibXml2_FIND_REQUIRED ) IF ( NOT LibXml2_FIND_QUIETLY ) MESSAGE( STATUS "Could NOT find libxml2" ) ENDIF ( NOT LibXml2_FIND_QUIETLY ) ENDIF ( LibXml2_FIND_REQUIRED ) ENDIF ( LIBXML2_LIBRARIES AND LIBXML2_INCLUDE_DIRS AND _libxml2_FOUND ) ENDIF ( NOT LIBXML2_FOUND AND NOT PKG_CONFIG_FOUND ) # Hide advanced variables from CMake GUIs MARK_AS_ADVANCED( LIBXML2_LIBRARIES LIBXML2_INCLUDE_DIRS ) libsyncml-0.5.4/cmake/modules/FindEBook1.0.cmake100644 1750 1750 10114 11211710410 21207 0ustar00bellmichbellmich# - Try to find libebook1.0 components # Find libebook 1.0 headers, libraries and the answer to all questions. # # LIBEBOOK1.0_FOUND True if libebook1.0 got found # LIBEBOOK1.0_INCLUDE_DIRS Location of libebook1.0 headers # LIBEBOOK1.0_LIBRARIES List of libaries to use libebook1.0 # LIBEBOOK1.0_DEFINITIONS Definitions to compile libebook1.0 # # Copyright (c) 2007 Juha Tuomala # Copyright (c) 2007 Daniel Gollub # Copyright (c) 2007 Alban Browaeys # # Redistribution and use is allowed according to the terms of the New # BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # INCLUDE( FindPkgConfig ) # Take care about libebook-1.0.pc settings IF ( EBook1.0_FIND_REQUIRED ) SET( _pkgconfig_REQUIRED "REQUIRED" ) ELSE ( EBook1.0_FIND_REQUIRED ) SET( _pkgconfig_REQUIRED "" ) ENDIF ( EBook1.0_FIND_REQUIRED ) pkg_search_module( LIBEBOOK1.0 ${_pkgconfig_REQUIRED} libebook-1.0 ) # Look for libebook1.0 include dir and libraries w/o pkg-config. IF ( NOT LIBEBOOK1.0_FOUND AND NOT PKG_CONFIG_FOUND ) FIND_PATH( _libebook1.0_include_DIR libebook/e-book.h PATH_SUFFIXES evolution-data-server-1.12 evolution-data-server-1.10 evolution-data-server-1.8 evolution-data-server-1.6 evolution-data-server-1.4 evolution-data-server-1.0 PATHS /opt/local/include/ /sw/include/ /usr/local/include/ /usr/include/ ) FIND_LIBRARY( _libebook1.0_link_DIR ebook-1.0 PATHS /opt/local/lib /sw/lib /usr/lib /usr/local/lib /usr/lib64 /usr/local/lib64 /opt/lib64 ) IF ( _libebook1.0_include_DIR AND _libebook1.0_link_DIR ) SET ( _libebook1.0_FOUND TRUE ) ENDIF ( _libebook1.0_include_DIR AND _libebook1.0_link_DIR ) IF ( _libebook1.0_FOUND ) SET ( LIBEBOOK1.0_INCLUDE_DIRS ${_libebook1.0_include_DIR} ) SET ( LIBEBOOK1.0_LIBRARIES ${_libebook1.0_link_DIR} ) ENDIF ( _libebook1.0_FOUND ) # Handle dependencies IF ( NOT LIBEDATASERVER1.0_FOUND ) FIND_PACKAGE ( EDataServer1.0 REQUIRED ) IF ( LIBEDATASERVER1.0_FOUND ) SET ( LIBEBOOK1.0_INCLUDE_DIRS ${LIBEBOOK1.0_INCLUDE_DIRS} ${LIBEDATASERVER1.0_INCLUDE_DIRS} ) SET ( LIBEBOOK1.0_LIBRARIES ${LIBEBOOK1.0_LIBRARIES} ${LIBEDATASERVER1.0_LIBRARIES} ) ENDIF ( LIBEDATASERVER1.0_FOUND ) ENDIF ( NOT LIBEDATASERVER1.0_FOUND ) IF ( NOT LIBGNOME2_FOUND ) FIND_PACKAGE ( LibGnome2 REQUIRED ) IF ( LIBGNOME2_FOUND ) SET ( LIBEBOOK1.0_INCLUDE_DIRS ${LIBEBOOK1.0_INCLUDE_DIRS} ${LIBGNOME2_INCLUDE_DIRS} ) SET ( LIBEBOOK1.0_LIBRARIES ${LIBEBOOK1.0_LIBRARIES} ${LIBGNOME2_LIBRARIES} ) ENDIF ( LIBGNOME2_FOUND ) ENDIF ( NOT LIBGNOME2_FOUND ) IF ( NOT BONOBO2_FOUND ) FIND_PACKAGE ( BONOBO2 REQUIRED ) IF ( BONOBO2_FOUND ) SET ( LIBEBOOK1.0_INCLUDE_DIRS ${LIBEBOOK1.0_INCLUDE_DIRS} ${BONOBO2_INCLUDE_DIRS} ) SET ( LIBEBOOK1.0_LIBRARIES ${LIBEBOOK1.0_LIBRARIES} ${BONOBO2_LIBRARIES} ) ENDIF ( BONOBO2_FOUND ) ENDIF ( NOT BONOBO2_FOUND ) # Report results IF ( LIBEBOOK1.0_LIBRARIES AND LIBEBOOK1.0_INCLUDE_DIRS AND _libebook1.0_FOUND ) SET( LIBEBOOK1.0_FOUND 1 ) IF ( NOT EBook1.0_FIND_QUIETLY ) MESSAGE( STATUS "Found libebook-1.0: ${LIBEBOOK1.0_LIBRARIES}" ) ENDIF ( NOT EBook1.0_FIND_QUIETLY ) ELSE ( LIBEBOOK1.0_LIBRARIES AND LIBEBOOK1.0_INCLUDE_DIRS AND _libebook1.0_FOUND ) IF ( EBook1.0_FIND_REQUIRED ) MESSAGE( SEND_ERROR "Could NOT find libebook-1.0" ) ELSE ( EBook1.0_FIND_REQUIRED ) IF ( NOT EBook1.0_FIND_QUIETLY ) MESSAGE( STATUS "Could NOT find libebook-1.0" ) ENDIF ( NOT EBook1.0_FIND_QUIETLY ) ENDIF ( EBook1.0_FIND_REQUIRED ) ENDIF ( LIBEBOOK1.0_LIBRARIES AND LIBEBOOK1.0_INCLUDE_DIRS AND _libebook1.0_FOUND ) ENDIF ( NOT LIBEBOOK1.0_FOUND AND NOT PKG_CONFIG_FOUND ) # Hide advanced variables from CMake GUIs MARK_AS_ADVANCED( LIBEBOOK1.0_LIBRARIES LIBEBOOK1.0_INCLUDE_DIRS ) libsyncml-0.5.4/cmake/modules/FindLibSoup2.cmake100644 1750 1750 15507 11211710410 21443 0ustar00bellmichbellmich# - Try to find libsoup # Find libsoup headers, libraries and the answer to all questions. # # LIBSOUP2_FOUND True if libsoup2 got found # LIBSOUP2_INCLUDE_DIRS Location of libsoup2 headers # LIBSOUP2_LIBRARIES List of libaries to use libsoup2 # LIBSOUP2_LIBRARY_DIRS Location of libsoup2 library # # LIBSOUP22_FOUND True if libsoup2.2 got found # LIBSOUP22_INCLUDE_DIRS Location of libsoup2.2 headers # LIBSOUP22_LIBRARIES List of libaries to use libsoup2.2 # LIBSOUP22_LIBRARY_DIRS Location of libsoup2.2 library # # LIBSOUP24_FOUND True if libsoup2.4 got found # LIBSOUP24_INCLUDE_DIRS Location of libsoup2.4 headers # LIBSOUP24_LIBRARIES List of libaries to use libsoup2.4 # LIBSOUP24_LIBRARY_DIRS Location of libsoup2.4 library # # Set LIBSOUP2_MIN_VERSION to find libsoup2.2 or libsoup2.4 if only # one of both libraries is supported # # Don't use LIBSOUP2_MIN_VERSION if you want to support # libsoup2.2 and libsoup2.4. # Instead use LIBSPOUP22_MIN_VERSION and LIBSPOUP24_MIN_VERSION. # # Set LIBSPOUP22_MIN_VERSION to find libsoup2.2 which version is # greater than LIBSPOUP22_MIN_VERSION # # Set LIBSPOUP24_MIN_VERSION to find libsoup2.4 which version is # greater than LIBSPOUP24_MIN_VERSION # # WARNING: It is not possible to set LIBSPOUP22_MIN_VERSION # and support any version of libsoup2.4 at the same time. # In this situation you have to set LIBSPOUP24_MIN_VERSION also. # The same applies to LIBSPOUP24_MIN_VERSION and libsoup2.2. # # Copyright (c) 2007 Daniel Gollub # Copyright (c) 2008 Bjoern Ricks # # Redistribution and use is allowed according to the terms of the New # BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # INCLUDE( FindPkgConfig ) IF ( LibSoup2_FIND_REQUIRED ) SET( _pkgconfig_REQUIRED "REQUIRED" ) ELSE( LibSoup2_FIND_REQUIRED ) SET( _pkgconfig_REQUIRED "" ) ENDIF ( LibSoup2_FIND_REQUIRED ) IF ( LIBSOUP2_MIN_VERSION ) STRING(REGEX REPLACE "^(2)(\\.)([0-9]*)(\\.?)(.*)" "\\3" LIBSOUP2_VERSION_MINOR "${LIBSOUP2_MIN_VERSION}") IF ( LIBSOUP2_VERSION_MINOR EQUAL "2" ) SET( LIBSOUP22_MIN_VERSION "${LIBSOUP2_MIN_VERSION}" ) ELSE ( LIBSOUP2_VERSION_MINOR EQUAL "2" ) SET( LIBSOUP24_MIN_VERSION "${LIBSOUP2_MIN_VERSION}" ) ENDIF ( LIBSOUP2_VERSION_MINOR EQUAL "2" ) ENDIF ( LIBSOUP2_MIN_VERSION ) # try to find libsoup2.2>=LIBSOUP22_MIN_VERSION IF ( LIBSOUP22_MIN_VERSION ) PKG_SEARCH_MODULE( LIBSOUP22 libsoup-2.2>=${LIBSOUP22_MIN_VERSION} libsoup2>=${LIBSOUP22_MIN_VERSION} ) ENDIF ( LIBSOUP22_MIN_VERSION ) # try to find libsoup2.4>=LIBSOUP24_MIN_VERSION IF ( LIBSOUP24_MIN_VERSION ) PKG_SEARCH_MODULE( LIBSOUP24 libsoup-2.4>=${LIBSOUP24_MIN_VERSION} libsoup2>=${LIBSOUP24_MIN_VERSION} ) ENDIF ( LIBSOUP24_MIN_VERSION ) # try to find any version of libsoup2.4 if LIBSOUP22_MIN_VERSION is not set IF ( NOT LIBSOUP24_FOUND AND NOT LIBSOUP22_MIN_VERSION ) PKG_SEARCH_MODULE( LIBSOUP24 libsoup-2.4 libsoup2 ) ENDIF ( NOT LIBSOUP24_FOUND AND NOT LIBSOUP22_MIN_VERSION) # try to find any version of libsoup2.2 if LIBSOUP24_MIN_VERSION is not set IF ( NOT LIBSOUP22_FOUND AND NOT LIBSOUP24_MIN_VERSION ) PKG_SEARCH_MODULE( LIBSOUP22 libsoup-2.2 libsoup2 ) ENDIF ( NOT LIBSOUP22_FOUND AND NOT LIBSOUP24_MIN_VERSION) # set LIBSOUP2_ variables IF ( LIBSOUP24_FOUND ) # prefer libsoup2.4 to libsoup2.2 if both are found SET( LIBSOUP2_FOUND ${LIBSOUP24_FOUND} CACHE INTERNAL "" ) SET( LIBSOUP2_INCLUDE_DIRS ${LIBSOUP24_INCLUDE_DIRS} CACHE INTERNAL "" ) SET( LIBSOUP2_LIBRARIES ${LIBSOUP24_LIBRARIES} CACHE INTERNAL "" ) SET( LIBSOUP2_LIBRARY_DIRS ${LIBSOUP24_LIBRARY_DIRS} CACHE INTERNAL "" ) SET( LIBSOUP2_VERSION ${LIBSOUP24_VERSION} CACHE INTERNAL "" ) ELSEIF ( LIBSOUP22_FOUND ) SET( LIBSOUP2_FOUND ${LIBSOUP22_FOUND} CACHE INTERNAL "" ) SET( LIBSOUP2_INCLUDE_DIRS ${LIBSOUP22_INCLUDE_DIRS} CACHE INTERNAL "" ) SET( LIBSOUP2_LIBRARIES ${LIBSOUP22_LIBRARIES} CACHE INTERNAL "" ) SET( LIBSOUP2_LIBRARY_DIRS ${LIBSOUP22_LIBRARY_DIRS} CACHE INTERNAL "" ) SET( LIBSOUP2_VERSION ${LIBSOUP22_VERSION} CACHE INTERNAL "" ) ELSEIF( PKG_CONFIG_FOUND AND LibSoup2_FIND_REQUIRED ) # raise an error if both libs are not found # and FIND_PACKAGE( LibSoup2 REQUIRED ) was called MESSAGE( SEND_ERROR "package libsoup2 not found" ) ENDIF ( LIBSOUP24_FOUND ) IF( NOT LIBSOUP2_FOUND AND NOT PKG_CONFIG_FOUND ) # WARNING: # This case is executed if pkg-config isn't installed. # Currently in this case it is only checked if libsoup2.2 is available. # Therefore please don't use this cmake module without pkg-config! FIND_PATH( _libsoup2_include_DIR libsoup/soup.h PATH_SUFFIXES libsoup libsoup-2.2 ) FIND_LIBRARY( _libsoup2_LIBRARY soup-2.2) IF ( _libsoup2_include_DIR AND _libsoup2_LIBRARY ) SET ( _libsoup2_FOUND TRUE ) ENDIF ( _libsoup2_include_DIR AND _libsoup2_LIBRARY ) IF ( _libsoup2_FOUND ) SET ( LIBSOUP2_INCLUDE_DIRS ${_libsoup2_include_DIR} ) SET ( LIBSOUP2_LIBRARIES ${_libsoup2_LIBRARY} ) # find requited glib2 IF( NOT GLIB2_FOUND ) FIND_PACKAGE( GLIB2 REQUIRED ) IF ( GLIB2_FOUND ) SET ( LIBSOUP2_INCLUDE_DIRS ${LIBSOUP2_INCLUDE_DIRS} ${GLIB2_INCLUDE_DIRS} ) SET ( LIBSOUP2_LIBRARIES ${LIBSOUP2_LIBRARIES} ${GLIB2_LIBRARIES} ) ENDIF ( GLIB2_FOUND ) ENDIF( NOT GLIB2_FOUND ) # find required libxml2 IF( NOT LIBXML2_FOUND ) FIND_PACKAGE( LibXml2 REQUIRED ) IF ( LIBXML2_FOUND ) SET ( LIBSOUP2_INCLUDE_DIRS ${LIBSOUP2_INCLUDE_DIRS} ${LIBXML2_INCLUDE_DIRS} ) SET ( LIBSOUP2_LIBRARIES ${LIBSOUP2_LIBRARIES} ${LIBXML2_LIBRARIES} ) ENDIF( LIBXML2_FOUND ) ENDIF( NOT LIBXML2_FOUND ) # find required gnutls IF( NOT GNUTLS_FOUND ) FIND_PACKAGE( GNUTLS REQUIRED ) IF ( GNUTLS_FOUND ) SET ( LIBSOUP2_INCLUDE_DIRS ${LIBSOUP2_INCLUDE_DIRS} ${GNUTLS_INCLUDE_DIRS} ) SET ( LIBSOUP2_LIBRARIES ${LIBSOUP2_LIBRARIES} ${GNUTLS_LIBRARIES} ) ENDIF( GNUTLS_FOUND ) ENDIF( NOT GNUTLS_FOUND ) ENDIF ( _libsoup2_FOUND ) MARK_AS_ADVANCED( _libsoup2_include_DIR _libsoup2_LIBRARY ) # Report results IF ( LIBSOUP2_LIBRARIES AND LIBSOUP2_INCLUDE_DIRS AND _libsoup2_FOUND ) SET( LIBSOUP2_FOUND 1 ) IF ( NOT LibSoup2_FIND_QUIETLY ) MESSAGE( STATUS "Found libsoup2: ${_libsoup2_LIBRARY}" ) ENDIF ( NOT LibSoup2_FIND_QUIETLY ) ELSE ( LIBSOUP2_LIBRARIES AND LIBSOUP_INCLUDE_DIRS AND _libsoup2_FOUND ) IF ( LibSoup2_FIND_REQUIRED ) MESSAGE( SEND_ERROR "Could NOT find libsoup2" ) ELSE ( LibSoup2_FIND_REQUIRED ) IF ( NOT LibSoup2_FIND_QUIETLY ) MESSAGE( STATUS "Could NOT find libsoup2" ) ENDIF ( NOT LibSoup2_FIND_QUIETLY ) ENDIF ( LibSoup2_FIND_REQUIRED ) ENDIF ( LIBSOUP2_LIBRARIES AND LIBSOUP2_INCLUDE_DIRS AND _libsoup2_FOUND ) ENDIF( NOT LIBSOUP2_FOUND AND NOT PKG_CONFIG_FOUND ) # Hide advanced variables from CMake GUIs MARK_AS_ADVANCED( LIBSOUP2_LIBRARIES LIBSOUP2_INCLUDE_DIRS ) libsyncml-0.5.4/cmake/modules/FindBONOBO2.cmake100644 1750 1750 7700 11211710410 21020 0ustar00bellmichbellmich# - Try to find bonobo2 # Find bonobo2 headers, libraries and the answer to all questions. # # BONOBO2_FOUND True if bonobo2 got found # BONOBO2_INCLUDEDIR Location of bonobo2 headers # BONOBO2_LIBRARIES List of libaries to use bonobo2 # BONOBO2_DEFINITIONS Definitions to compile bonobo2 # # Copyright (c) 2007 Juha Tuomala # Copyright (c) 2007 Daniel Gollub # Copyright (c) 2007 Alban Browaeys # # Redistribution and use is allowed according to the terms of the New # BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # INCLUDE( FindPkgConfig ) # Take care about libbonobo-2.0.pc settings IF ( BONOBO2_FIND_REQUIRED ) SET( _pkgconfig_REQUIRED "REQUIRED" ) ELSE ( BONOBO2_FIND_REQUIRED ) SET( _pkgconfig_REQUIRED "" ) ENDIF ( BONOBO2_FIND_REQUIRED ) IF ( BONOBO2_MIN_VERSION ) pkg_search_module( BONOBO2 ${_pkgconfig_REQUIRED} libbonobo-2.0>=${BONOBO2_MIN_VERSION} ) ELSE ( BONOBO2_MIN_VERSION ) pkg_search_module( BONOBO2 ${_pkgconfig_REQUIRED} libbonobo-2.0 ) ENDIF ( BONOBO2_MIN_VERSION ) # Look for libbonobo2 include dir and libraries w/o pkgconfig IF ( NOT BONOBO2_FOUND AND NOT PKG_CONFIG_FOUND ) FIND_PATH( _bonobo2_include_DIR libbonobo.h PATH_SUFFIXES libbonobo-2.0 PATHS /opt/local/include/ /sw/include/ /usr/local/include/ /usr/include/ ) FIND_LIBRARY( _bonobo2_link_DIR bonobo-2 PATHS /opt/local/lib /sw/lib /usr/lib /usr/local/lib /usr/lib64 /usr/local/lib64 /opt/lib64 ) IF ( _bonobo2_include_DIR AND _bonobo2_link_DIR ) SET ( _bonobo2_FOUND TRUE ) ENDIF ( _bonobo2_include_DIR AND _bonobo2_link_DIR ) IF ( _bonobo2_FOUND ) SET ( BONOBO2_INCLUDE_DIRS ${_bonobo2_include_DIR} ) SET ( BONOBO2_LIBRARIES ${_bonobo2_link_DIR} ) ENDIF ( _bonobo2_FOUND ) # Handle dependencies IF ( NOT BONOBOACTIVATION2_FOUND ) FIND_PACKAGE( BONOBOACTIVATION2 REQUIRED) IF ( BONOBOACTIVATION2_FOUND ) SET ( BONOBO2_INCLUDE_DIRS ${BONOBO2_INCLUDE_DIRS} ${BONOBOACTIVATION2_INCLUDE_DIRS} ) SET ( BONOBO2_LIBRARIES ${BONOBO2_LIBRARIES} ${BONOBOACTIVATION2_LIBRARIES} ) ENDIF ( BONOBOACTIVATION2_FOUND ) ENDIF ( NOT BONOBOACTIVATION2_FOUND ) IF ( NOT ORBIT2_FOUND ) FIND_PACKAGE( ORBit2 REQUIRED) IF ( ORBIT2_FOUND ) SET ( BONOBO2_INCLUDE_DIRS ${BONOBO2_INCLUDE_DIRS} ${ORBIT2_INCLUDE_DIRS} ) SET ( BONOBO2_LIBRARIES ${BONOBO2_LIBRARIES} ${ORBIT2_LIBRARIES} ) ENDIF ( ORBIT2_FOUND ) ENDIF ( NOT ORBIT2_FOUND ) IF ( NOT GLIB2_FOUND ) FIND_PACKAGE( GLIB2 REQUIRED) IF ( GMODULE2_FOUND ) SET ( BONOBO2_INCLUDE_DIRS ${BONOBO2_INCLUDE_DIRS} ${GMODULE2_INCLUDE_DIR} ) SET ( BONOBO2_LIBRARIES ${BONOBO2_LIBRARIES} ${GMODULE2_LIBRARY} ) ENDIF ( GMODULE2_FOUND ) IF ( GLIB2_FOUND ) SET ( BONOBO2_INCLUDE_DIRS ${BONOBO2_INCLUDE_DIRS} ${GLIB2_INCLUDE_DIR} ${GLIBCONFIG_INCLUDE_DIR} ) SET ( BONOBO2_LIBRARIES ${BONOBO2_LIBRARIES} ${GLIB2_LIBRARY} ) ENDIF ( GLIB2_FOUND ) ENDIF ( NOT GLIB2_FOUND ) # Report results IF ( BONOBO2_LIBRARIES AND BONOBO2_INCLUDE_DIRS AND _bonobo2_FOUND ) SET( BONOBO2_FOUND 1 ) IF ( NOT BONOBO2_FIND_QUIETLY ) MESSAGE( STATUS "Found bonobo2: ${BONOBO2_LIBRARIES} ${BONOBO2_INCLUDE_DIRS}" ) ENDIF ( NOT BONOBO2_FIND_QUIETLY ) ELSE ( BONOBO2_LIBRARIES AND BONOBO2_INCLUDE_DIRS AND _bonobo2_FOUND ) IF ( BONOBO2_FIND_REQUIRED ) MESSAGE( SEND_ERROR "Could NOT find bonobo2" ) ELSE ( BONOBO2_FIND_REQUIRED ) IF ( NOT BONOBO2_FIND_QUIETLY ) MESSAGE( STATUS "Could NOT find bonobo2" ) ENDIF ( NOT BONOBO2_FIND_QUIETLY ) ENDIF ( BONOBO2_FIND_REQUIRED ) ENDIF ( BONOBO2_LIBRARIES AND BONOBO2_INCLUDE_DIRS AND _bonobo2_FOUND ) ENDIF ( NOT BONOBO2_FOUND AND NOT PKG_CONFIG_FOUND ) # Hide advanced variables from CMake GUIs MARK_AS_ADVANCED( BONOBO2_LIBRARIES BONOBO2_INCLUDE_DIRS ) libsyncml-0.5.4/cmake/modules/FindLibUuid.cmake100644 1750 1750 3344 11211710410 21315 0ustar00bellmichbellmich# - Try to find LIBUUID # Find LIBUUID headers, libraries and the answer to all questions. # # LIBUUID_FOUND True if libuuid got found # LIBUUID_INCLUDE_DIRS Location of libuuid headers # LIBUUID_LIBRARIES List of libraries to use libuuid # # Copyright (c) 2008 Bjoern Ricks # # Redistribution and use is allowed according to the terms of the New # BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # INCLUDE( FindPkgConfig ) IF ( LibUuid_FIND_REQUIRED ) SET( _pkgconfig_REQUIRED "REQUIRED" ) ELSE( LibUuid_FIND_REQUIRED ) SET( _pkgconfig_REQUIRED "" ) ENDIF ( LibUuid_FIND_REQUIRED ) IF ( LIBUUID_MIN_VERSION ) PKG_SEARCH_MODULE( LIBUUID ${_pkgconfig_REQUIRED} uuid>=${LIBUUID_MIN_VERSION} ) ELSE ( LIBUUID_MIN_VERSION ) PKG_SEARCH_MODULE( LIBUUID ${_pkgconfig_REQUIRED} uuid ) ENDIF ( LIBUUID_MIN_VERSION ) IF( NOT LIBUUID_FOUND AND NOT PKG_CONFIG_FOUND ) FIND_PATH( LIBUUID_INCLUDE_DIRS uuid/uuid.h ) FIND_LIBRARY( LIBUUID_LIBRARIES uuid) # Report results IF ( LIBUUID_LIBRARIES AND LIBUUID_INCLUDE_DIRS ) SET( LIBUUID_FOUND 1 ) IF ( NOT LIBUUID_FIND_QUIETLY ) MESSAGE( STATUS "Found libuuid: ${LIBUUID_LIBRARIES}" ) ENDIF ( NOT LIBUUID_FIND_QUIETLY ) ELSE ( LIBUUID_LIBRARIES AND LIBUUID_INCLUDE_DIRS ) IF ( LIBUUID_FIND_REQUIRED ) MESSAGE( SEND_ERROR "Could NOT find libuuid" ) ELSE ( LIBUUID_FIND_REQUIRED ) IF ( NOT LIBUUID_FIND_QUIETLY ) MESSAGE( STATUS "Could NOT find libuuid" ) ENDIF ( NOT LIBUUID_FIND_QUIETLY ) ENDIF ( LIBUUID_FIND_REQUIRED ) ENDIF ( LIBUUID_LIBRARIES AND LIBUUID_INCLUDE_DIRS ) ENDIF( NOT LIBUUID_FOUND AND NOT PKG_CONFIG_FOUND ) MARK_AS_ADVANCED( LIBUUID_LIBRARIES LIBUUID_INCLUDE_DIRS )libsyncml-0.5.4/cmake/modules/FindLibWbxml2.cmake100644 1750 1750 5537 11211710410 21570 0ustar00bellmichbellmich# - Try to find libwbxml # Find libwbxml headers, libraries and the answer to all questions. # # LIBWBXML2_FOUND True if libwbxml got found # LIBWBXML2_INCLUDE_DIRS Location of libwbxml headers # LIBWBXML2_LIBRARIES List of libaries to use libwbxml # # Copyright (c) 2007 Daniel Gollub # Copyright (c) 2007 Bjoern Ricks # # Redistribution and use is allowed according to the terms of the New # BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # INCLUDE( FindPkgConfig ) IF ( LibWbxml2_FIND_REQUIRED ) SET( _pkgconfig_REQUIRED "REQUIRED" ) ELSE( LibWbxml2_FIND_REQUIRED ) SET( _pkgconfig_REQUIRED "" ) ENDIF ( LibWbxml2_FIND_REQUIRED ) IF ( LIBWBXML2_MIN_VERSION ) PKG_SEARCH_MODULE( LIBWBXML2 libwbxml2>=${LIBWBXML2_MIN_VERSION} ${_pkgconfig_REQUIRED} ) ELSE ( LIBWBXML2_MIN_VERSION ) PKG_SEARCH_MODULE( LIBWBXML2 libwbxml2 ${_pkgconfig_REQUIRED} ) ENDIF ( LIBWBXML2_MIN_VERSION ) IF( NOT LIBWBXML2_FOUND AND NOT PKG_CONFIG_FOUND ) FIND_PATH( _libwbxml2_include_DIR wbxml.h PATHS /opt/local/include/ /sw/include/ /usr/local/include/ /usr/include/ ) FIND_LIBRARY( _libwbxml2_LIBRARY wbxml2 PATHS /opt/local/lib /sw/lib /usr/lib /usr/local/lib /usr/lib64 /usr/local/lib64 /opt/lib64 ) IF ( _libwbxml2_include_DIR AND _libwbxml2_LIBRARY ) SET ( _libwbxml2_FOUND TRUE ) ENDIF ( _libwbxml2_include_DIR AND _libwbxml2_LIBRARY ) IF ( _libwbxml2_FOUND ) SET ( LIBWBXML2_INCLUDE_DIRS ${_libwbxml2_include_DIR} ) SET ( LIBWBXML2_LIBRARIES ${_libwbxml2_LIBRARY} ) # find required libxml2 IF( NOT LIBXML2_FOUND ) FIND_PACKAGE( LibXml2 REQUIRED ) IF ( LIBXML2_FOUND ) SET ( LIBWBXML2_INCLUDE_DIRS ${LIBWBXML2_INCLUDE_DIRS} ${LIBXML2_INCLUDE_DIRS} ) SET ( LIBWBXML2_LIBRARIES ${LIBWBXML2_LIBRARIES} ${LIBXML2_LIBRARIES} ) ENDIF( LIBXML2_FOUND ) ENDIF( NOT LIBXML2_FOUND ) ENDIF( _libwbxml2_FOUND ) MARK_AS_ADVANCED( _libwbxml2_include_DIR _libwbxml2_LIBRARY ) # Report results IF ( LIBWBXML2_LIBRARIES AND LIBWBXML2_INCLUDE_DIRS AND _libwbxml2_FOUND ) SET( LIBWBXML_FOUND 1 ) IF ( NOT LibWbxml2_FIND_QUIETLY ) MESSAGE( STATUS "Found libwbxml2: ${_libwbxml2_LIBRARY}" ) ENDIF ( NOT LibWbxml2_FIND_QUIETLY ) ELSE ( LIBWBXML2_LIBRARIES AND LIBWBXML2_INCLUDE_DIRS AND _libwbxml2_FOUND ) IF ( LibWbxml2_FIND_REQUIRED ) MESSAGE( SEND_ERROR "Could NOT find libwbxml2" ) ELSE ( LibWbxml2_FIND_REQUIRED ) IF ( NOT LibWbxml2_FIND_QUIETLY ) MESSAGE( STATUS "Could NOT find libwbxml2" ) ENDIF ( NOT LibWbxml2_FIND_QUIETLY ) ENDIF ( LibWbxml2_FIND_REQUIRED ) ENDIF ( LIBWBXML2_LIBRARIES AND LIBWBXML2_INCLUDE_DIRS AND _libwbxml2_FOUND ) ENDIF( NOT LIBWBXML2_FOUND AND NOT PKG_CONFIG_FOUND ) # Hide advanced variables from CMake GUIs MARK_AS_ADVANCED( LIBWBXML2_LIBRARIES LIBWBXML2_INCLUDE_DIRS ) libsyncml-0.5.4/cmake/modules/FindPythonLibs.cmake100644 1750 1750 14542 11211710410 22075 0ustar00bellmichbellmich# - Find python libraries # This module finds if Python is installed and determines where the # include files and libraries are. It also determines what the name of # the library is. This code sets the following variables: # # PYTHON_LIBRARIES = path to the python library # PYTHON_INCLUDE_PATH = path to where Python.h is found # PYTHON_DEBUG_LIBRARIES = path to the debug library # PYTHON_VERSION = version of python library # # The user can set this variable to choose their preferred python # version to be found: # # PREFERRED_PYTHON_VERSION = preferred version of the python library INCLUDE(CMakeFindFrameworks) IF(WIN32) FIND_LIBRARY(PYTHON_DEBUG_LIBRARY NAMES python26_d python25_d python24_d python23_d python22_d python21_d python20_d python PATHS [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\2.6\\InstallPath]/libs/Debug [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\2.6\\InstallPath]/libs [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\2.5\\InstallPath]/libs/Debug [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\2.5\\InstallPath]/libs [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\2.4\\InstallPath]/libs/Debug [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\2.4\\InstallPath]/libs [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\2.3\\InstallPath]/libs/Debug [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\2.3\\InstallPath]/libs [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\2.2\\InstallPath]/libs/Debug [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\2.2\\InstallPath]/libs [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\2.1\\InstallPath]/libs/Debug [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\2.1\\InstallPath]/libs [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\2.0\\InstallPath]/libs/Debug [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\2.0\\InstallPath]/libs [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\1.6\\InstallPath]/libs/Debug [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\1.6\\InstallPath]/libs [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\1.5\\InstallPath]/libs/Debug [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\1.5\\InstallPath]/libs ) ENDIF(WIN32) FIND_LIBRARY(PYTHON_LIBRARY ${PREFERRED_PYTHON_VERSION} NAMES python26 python2.6 python25 python2.5 python24 python2.4 python23 python2.3 python22 python2.2 python21 python2.1 python20 python2.0 python16 python1.6 python15 python1.5 PATHS [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\2.6\\InstallPath]/libs [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\2.5\\InstallPath]/libs [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\2.4\\InstallPath]/libs [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\2.3\\InstallPath]/libs [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\2.2\\InstallPath]/libs [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\2.1\\InstallPath]/libs [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\2.0\\InstallPath]/libs [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\1.6\\InstallPath]/libs [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\1.5\\InstallPath]/libs PATH_SUFFIXES python2.6/config python2.5/config python2.4/config python2.3/config python2.2/config python2.1/config python2.0/config python1.6/config python1.5/config ) IF(PYTHON_LIBRARY) message(STATUS "Found Python: ${PYTHON_LIBRARY}") ENDIF(PYTHON_LIBRARY) # Search for the python framework on Apple. CMAKE_FIND_FRAMEWORKS(Python) SET(PYTHON_FRAMEWORK_INCLUDES) IF(Python_FRAMEWORKS) IF(NOT PYTHON_INCLUDE_PATH) FOREACH(version 2.6 2.5 2.4 2.3 2.2 2.1 2.0 1.6 1.5) FOREACH(dir ${Python_FRAMEWORKS}) SET(PYTHON_FRAMEWORK_INCLUDES ${PYTHON_FRAMEWORK_INCLUDES} ${dir}/Versions/${version}/include/python${version}) ENDFOREACH(dir) ENDFOREACH(version) ENDIF(NOT PYTHON_INCLUDE_PATH) ENDIF(Python_FRAMEWORKS) FIND_PATH(PYTHON_INCLUDE_PATH NAMES Python.h PATHS ${PYTHON_FRAMEWORK_INCLUDES} [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\2.6\\InstallPath]/include [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\2.5\\InstallPath]/include [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\2.4\\InstallPath]/include [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\2.3\\InstallPath]/include [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\2.2\\InstallPath]/include [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\2.1\\InstallPath]/include [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\2.0\\InstallPath]/include [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\1.6\\InstallPath]/include [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\1.5\\InstallPath]/include PATH_SUFFIXES ${PREFERRED_PYTHON_VERSION} python2.6 python2.5 python2.4 python2.3 python2.2 python2.1 python2.0 python1.6 python1.5 ) IF (WIN32) MARK_AS_ADVANCED( PYTHON_DEBUG_LIBRARY PYTHON_LIBRARY PYTHON_INCLUDE_PATH ) ENDIF(WIN32) FIND_PROGRAM( PYTHON_EXECUTABLE NAMES ${PREFERRED_PYTHON_VERSION} python ) IF ( PYTHON_EXECUTABLE ) EXEC_PROGRAM( ${PYTHON_EXECUTABLE} ARGS "-c \"import sys; print sys.version[:3]\"" OUTPUT_VARIABLE PYTHON_VERSION ) STRING( REGEX REPLACE "[\r\n]" " " PYTHON_VERSION "${PYTHON_VERSION}" ) ENDIF ( PYTHON_EXECUTABLE ) # Python Should be built and installed as a Framework on OSX IF(Python_FRAMEWORKS) # If a framework has been selected for the include path, # make sure "-framework" is used to link it. IF("${PYTHON_INCLUDE_PATH}" MATCHES "Python\\.framework") SET(PYTHON_LIBRARY "") SET(PYTHON_DEBUG_LIBRARY "") ENDIF("${PYTHON_INCLUDE_PATH}" MATCHES "Python\\.framework") IF(NOT PYTHON_LIBRARY) SET (PYTHON_LIBRARY "-framework Python" CACHE FILEPATH "Python Framework" FORCE) ENDIF(NOT PYTHON_LIBRARY) IF(NOT PYTHON_DEBUG_LIBRARY) SET (PYTHON_DEBUG_LIBRARY "-framework Python" CACHE FILEPATH "Python Framework" FORCE) ENDIF(NOT PYTHON_DEBUG_LIBRARY) ENDIF(Python_FRAMEWORKS) # We use PYTHON_LIBRARY and PYTHON_DEBUG_LIBRARY for the cache entries # because they are meant to specify the location of a single library. # We now set the variables listed by the documentation for this # module. SET(PYTHON_LIBRARIES "${PYTHON_LIBRARY}") SET(PYTHON_DEBUG_LIBRARIES "${PYTHON_DEBUG_LIBRARY}") libsyncml-0.5.4/cmake/modules/FindGOBJECT2.cmake100644 1750 1750 3500 11211710410 21111 0ustar00bellmichbellmich# - Try to find GObject2 # Find GObject2 headers, libraries and the answer to all questions. # # GOBJECT2_FOUND True if GOBJECT2 got found # GOBJECT2_INCLUDE_DIRS Location of GOBJECT2 headers # GOBJECT2_LIBRARIES List of libraries to use GOBJECT2 # # Copyright (c) 2008 Bjoern Ricks # # Redistribution and use is allowed according to the terms of the New # BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # INCLUDE( FindPkgConfig ) IF ( GOBJECT2_FIND_REQUIRED ) SET( _pkgconfig_REQUIRED "REQUIRED" ) ELSE( GOBJECT2_FIND_REQUIRED ) SET( _pkgconfig_REQUIRED "" ) ENDIF ( GOBJECT2_FIND_REQUIRED ) IF ( GOBJECT2_MIN_VERSION ) PKG_SEARCH_MODULE( GOBJECT2 ${_pkgconfig_REQUIRED} gobject-2.0>=${GOBJECT2_MIN_VERSION} ) ELSE ( GOBJECT2_MIN_VERSION ) PKG_SEARCH_MODULE( GOBJECT2 ${_pkgconfig_REQUIRED} gobject-2.0 ) ENDIF ( GOBJECT2_MIN_VERSION ) IF( NOT GOBJECT2_FOUND AND NOT PKG_CONFIG_FOUND ) FIND_PATH( GOBJECT2_INCLUDE_DIRS gobject/gobject.h PATH_SUFFIXES glib-2.0) FIND_LIBRARY( GOBJECT2_LIBRARIES gobject-2.0 ) # Report results IF ( GOBJECT2_LIBRARIES AND GOBJECT2_INCLUDE_DIRS ) SET( GOBJECT2_FOUND 1 ) IF ( NOT GOBJECT2_FIND_QUIETLY ) MESSAGE( STATUS "Found GOBJECT2: ${GOBJECT2_LIBRARIES}" ) ENDIF ( NOT GOBJECT2_FIND_QUIETLY ) ELSE ( GOBJECT2_LIBRARIES AND GOBJECT2_INCLUDE_DIRS ) IF ( GOBJECT2_FIND_REQUIRED ) MESSAGE( SEND_ERROR "Could NOT find GOBJECT2" ) ELSE ( GOBJECT2_FIND_REQUIRED ) IF ( NOT GOBJECT2_FIND_QUIETLY ) MESSAGE( STATUS "Could NOT find GOBJECT2" ) ENDIF ( NOT GOBJECT2_FIND_QUIETLY ) ENDIF ( GOBJECT2_FIND_REQUIRED ) ENDIF ( GOBJECT2_LIBRARIES AND GOBJECT2_INCLUDE_DIRS ) ENDIF( NOT GOBJECT2_FOUND AND NOT PKG_CONFIG_FOUND ) MARK_AS_ADVANCED( GOBJECT2_LIBRARIES GOBJECT2_INCLUDE_DIRS ) libsyncml-0.5.4/config.h.cmake100644 1750 1750 5161 11211710410 16121 0ustar00bellmichbellmich/* config.h.cmake */ /* Bluetooth Transport */ #cmakedefine ENABLE_BLUETOOTH /* Bluetooth SDP library - necessary for automatic channel discovery */ #cmakedefine ENABLE_BLUETOOTH_SDPLIB /* Http Transport */ #cmakedefine ENABLE_HTTP /* libsoup version in use */ #cmakedefine HAVE_LIBSOUP22_SOLARIS #cmakedefine HAVE_LIBSOUP22 #cmakedefine HAVE_LIBSOUP24 /* Obex Transport */ #cmakedefine ENABLE_OBEX /* Obex Transport via TCP */ /* TODO: Remove this on next OpenOBEX */ #cmakedefine ENABLE_OPENOBEX_TCP /* Tracing */ #cmakedefine ENABLE_TRACE /* Defined if the correct libwbxml2 version exists. */ #cmakedefine ENABLE_WBXML /* Define to 1 if you have the header file. */ #cmakedefine HAVE_DLFCN_H 1 /* Define to 1 if you have the header file. */ #cmakedefine HAVE_INTTYPES_H 1 /* Define to 1 if you have the header file. */ #cmakedefine HAVE_MEMORY_H 1 /* Define to 1 if you have the header file. */ #cmakedefine HAVE_STDINT_H 1 /* Define to 1 if you have the header file. */ #cmakedefine HAVE_STDLIB_H 1 /* Define to 1 if you have the header file. */ #cmakedefine HAVE_STRINGS_H 1 /* Define to 1 if you have the header file. */ #cmakedefine HAVE_STRING_H 1 /* Define to 1 if you have the header file. */ #cmakedefine HAVE_SYS_STAT_H 1 /* Define to 1 if you have the header file. */ #cmakedefine HAVE_SYS_TYPES_H 1 /* Define to 1 if the system has the type `uint16_t'. */ #cmakedefine HAVE_UINT16_T 1 /* Define to 1 if the system has the type `uint32_t'. */ #cmakedefine HAVE_UINT32_T 1 /* Define to 1 if the system has the type `uint8_t'. */ #cmakedefine HAVE_UINT8_T 1 /* Define to 1 if you have the header file. */ #cmakedefine HAVE_UNISTD_H 1 /* Name of package */ #cmakedefine PACKAGE "${PACKAGE}" /* Define to the address where bug reports for this package should be sent. */ #cmakedefine PACKAGE_BUGREPORT "${PACKAGE_BUGREPORT}" /* Define to the full name of this package. */ #cmakedefine PACKAGE_NAME "${PACKAGE_NAME}" /* Define to the full name and version of this package. */ #cmakedefine PACKAGE_STRING "${PACKAGE_STRING}" /* Define to the one symbol short name of this package. */ #cmakedefine PACKAGE_TARNAME "${PACKAGE_TARNAME}" /* Define to the version of this package. */ #cmakedefine PACKAGE_VERSION "${PACKAGE_VERSION}" /* Define to the SONAME libversion of this package. */ #cmakedefine PACKAGE_SONAME "${PACKAGE_SONAME}" /* Define to 1 if you have the ANSI C header files. */ /* #undef STDC_HEADERS 1 */ /* Version number of package */ #cmakedefine VERSION "${VERSION}" /* wbxml */ /* #undef WBXML_LIBS */ libsyncml-0.5.4/libsyncml-1.0.pc.cmake.in100644 1750 1750 456 11211710410 17706 0ustar00bellmichbellmichprefix=@CMAKE_INSTALL_PREFIX@ exec_prefix=@LIBSYNCML_EXEC_INSTALL_DIR@ libdir=@LIBSYNCML_LIBRARIES_DIR@ includedir=@LIBSYNCML_INCLUDE_DIR@ datadir=@LIBSYNCML_DATA_DIR@ Name: libsyncml Description: SyncML protocol library Version: @LIBSYNCML_VERSION@ Libs: -L${libdir} -lsyncml Cflags: -I${includedir} libsyncml-0.5.4/LICENSE100644 1750 1750 1676 11211710410 14440 0ustar00bellmichbellmichlibsyncml - A syncml protocol implementation COPYRIGT NOTICE: Please see the different files to find the different copyright statements. LICENSE NOTICE: You can find a full copy of the license in the file COPYING. LICENSE: This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA libsyncml-0.5.4/CODING100644 1750 1750 14412 11211710410 14331 0ustar00bellmichbellmichINTRODUCTION --------------------------------------------------------------------- Here will you find coding standards to the project. Requirements are listed in their respective files and can be considered an adendum to this document. CODING STYLE --------------------------------------------------------------------- See linux/Documentation/CodingStyle. Some highlights: - Outside of comments and documentation, never use spaces. Identation is done using tabs only. - Do not use tabs to align text documentation. Changing tab width should not interfere with the layout/alignment of code, only indentation. - functions are declared like this: char *function(const char *test) { } - if you use brackets INSIDE a function put them on the same line Wrong: if (condition) { do_something; } Right: if (condition) { do_something; } - Do not put actions in the same line of conditions: Wrong: if (condition) do_this; Right: if (condition) do_this; - Variables are always in lower case (like tmp_buf) - New defined types are capitalized (like OSyncEngine) - Never use typedefs just to hide pointers - External APIs, used for integration between components may look like this: osync_engine_init() - Always add the osync_ prefix to your functions - Do not return function calls, like "return do_something();", instead, use a auxiliar variable (rationale: easy trace). - When doing error checking, use goto to help creating a single return point. Do not abuse goto usage though... never goto up, never create more than one label and do not "gotoo far". CODE DOCUMENTATION --------------------------------------------------------------------- * Add FIXME, TODO and XXX comments appropriately. * Doxygen * Add simple READMEs and pictures as needed, but concentrate on doxygen. CODE INSTRUMENTATION ----------------------------------------------------------------- Always: * Use const; * Use static for internal functions; * Use safe glib functions where possible; * Check validity of all received parameters; * Use assert() while developing; * Do not use alloca() or other non-recommended functions; * Check for return errors even from malloc() and other standard system calls; Regularly: * Use valgrind to profile you application and find memleaks About header files: * Source code has to be split into modules, which are defined as a collection of implementation files (.c) with an interface exported through a header file (.h). * The inclusion (#include) of headers must reflect the dependencies between modules in the implementation. The most important implications from this statement are: . implementation files (.c) *must* include *all* headers it directly depends; . implementation files (.c) *must not* include headers it doesn't directly depend; . headers should include headers only when needing a definition or declaration; . headers should never include other headers just to create a "single point of inclusion". These rules may sound obvious, but they're actually hard to follow. COMMITS AND CHANGELOGS --------------------------------------------------------------------- Descriptive and small. General rules: - *Always* do a svn diff and a svn status before a commit and document the diff(s) in the changelogs; - What matters is not what but why; - Several commits are usually better than a big one; - Do not commit unrelated modifications at once unless they're really trivial; - Commit ASAP. BUILD-SYSTEM --------------------------------------------------------------------- Standard instructions: Code should compile with no warnings, using the following GCC options: -Wall -Werror Recomended but not mandatory (for now): -W -Wmissing-declarations -Wmissing-prototypes -Wredundant-decls -Wshadow -Wbad-function-cast -Wcast-qual -std=iso9899:1990 LOGS and TRACES --------------------------------------------------------------------- There are two types of logs that must be handled by almost all applications: * HIGH-LEVEL LOGS: these are standard, high-level logs usually enabled by default. Useful to advanced users, support-centers and alike. Should include basic information, including but not limited to: - start/end of application - errors - complex operations The requirements document specifies if logs are needed or not. * TRACES: traces are a particular kind of log used to debug the application. They're used mostly by black-box testers to submit failure reports. Traces should be enabled in a per-application basis using an envinronment variable or at compile time, to be yet defined. UNIT TESTS ----------------------------------------------------------------- * All code should be written together with unit-tests. The tool used to implement the tests is "check", available on http://check.sourceforge.net/. The build-system infra-structure provides a configure option to allow check usage. The tests must be implemented inside a sub-directory called test with the following modules: check_ --> the test-manager check_ --> implements tests for interfaces exported by unit check_<...> Just to remember, an unit, or module, is a collection of souce-code files (.c) with an interface exported through a header file (.h). All interfaces exported by units must be tested (that is, all non-static functions). The tests should implement at least the following test cases: - standard usage - upper and bottom limits of buffers and variables as needed - error conditions - critical paths Use incremental tests, that is, test functions before using them in other test-cases (for example, if you need to call function A to prepare the environment to test function B, test function A first). Try to write the test-case before the unit or function itself. If the test needs an external entity to work (for example, it needs a device connected on a specific port), put the test inside a condition for an environemnt variable and document it in a README file. libsyncml-0.5.4/misc/doxygen.css100644 1750 1750 15463 11211710410 16574 0ustar00bellmichbellmichBODY,H1,H2,H3,H4,H5,H6,P,CENTER,TD,TH,UL,DL,DIV { font-family: sans-serif; } BODY,TD { font-size: 90%; } H1 { text-align: center; font-size: 160%; } H2 { font-size: 120%; } H3 { font-size: 110%; } CAPTION { font-weight: bold } DIV.qindex { width: 100%; background-color: #eeeeff; border: 1px solid #b0b0b0; text-align: center; margin: 2px; padding: 2px; line-height: 140%; } DIV.nav { width: 100%; background-color: #eeeeff; border: 1px solid #b0b0b0; text-align: center; margin: 2px; padding: 2px; line-height: 140%; } A.qindex { text-decoration: none; font-weight: bold; color: #1A419D; } A.qindex:visited { text-decoration: none; font-weight: bold; color: #1A419D } A.qindex:hover { text-decoration: none; background-color: #ddddff; } A.qindexHL { text-decoration: none; font-weight: bold; background-color: #6666cc; color: #ffffff; border: 1px double #9295C2; } A.qindexHL:hover { text-decoration: none; background-color: #6666cc; color: #ffffff; } A.qindexHL:visited { text-decoration: none; background-color: #6666cc; color: #ffffff } A.el { text-decoration: none; font-weight: bold } A.elRef { font-weight: bold } A.code:link { text-decoration: none; font-weight: normal; color: #0000FF} A.code:visited { text-decoration: none; font-weight: normal; color: #0000FF} A.codeRef:link { font-weight: normal; color: #0000FF} A.codeRef:visited { font-weight: normal; color: #0000FF} A:hover { text-decoration: none; background-color: #f2f2ff } DL.el { margin-left: -1cm } .fragment { font-family: monospace } PRE.fragment { border: 1px solid #CCCCCC; background-color: #f5f5f5; margin-top: 4px; margin-bottom: 4px; margin-left: 2px; margin-right: 8px; padding-left: 6px; padding-right: 6px; padding-top: 4px; padding-bottom: 4px; } DIV.ah { background-color: black; font-weight: bold; color: #ffffff; margin-bottom: 3px; margin-top: 3px } TD.md { background-color: #F4F4FB; font-weight: bold; } TD.mdPrefix { background-color: #F4F4FB; color: #606060; font-size: 80%; } TD.mdname1 { background-color: #F4F4FB; font-weight: bold; color: #602020; } TD.mdname { background-color: #F4F4FB; font-weight: bold; color: #602020; width: 600px; } DIV.groupHeader { margin-left: 16px; margin-top: 12px; margin-bottom: 6px; font-weight: bold; } DIV.groupText { margin-left: 16px; font-style: italic; font-size: 90% } BODY { background: white; color: black; margin-right: 20px; margin-left: 20px; } TD.indexkey { background-color: #eeeeff; font-weight: bold; padding-right : 10px; padding-top : 2px; padding-left : 10px; padding-bottom : 2px; margin-left : 0px; margin-right : 0px; margin-top : 2px; margin-bottom : 2px; border: 1px solid #CCCCCC; } TD.indexvalue { background-color: #eeeeff; font-style: italic; padding-right : 10px; padding-top : 2px; padding-left : 10px; padding-bottom : 2px; margin-left : 0px; margin-right : 0px; margin-top : 2px; margin-bottom : 2px; border: 1px solid #CCCCCC; } TR.memlist { background-color: #f0f0f0; } P.formulaDsp { text-align: center; } IMG.formulaDsp { } IMG.formulaInl { vertical-align: middle; } SPAN.keyword { color: #008000 } SPAN.keywordtype { color: #604020 } SPAN.keywordflow { color: #e08000 } SPAN.comment { color: #800000 } SPAN.preprocessor { color: #806020 } SPAN.stringliteral { color: #002080 } SPAN.charliteral { color: #008080 } .mdTable { border: 1px solid #868686; background-color: #F4F4FB; width: 100%; } .mdRow { width: 100%; padding: 8px 10px; } .mdescLeft { padding: 0px 8px 4px 8px; font-size: 80%; font-style: italic; background-color: #FAFAFA; border-top: 1px none #E0E0E0; border-right: 1px none #E0E0E0; border-bottom: 1px none #E0E0E0; border-left: 1px none #E0E0E0; margin: 0px; } .mdescRight { padding: 0px 8px 4px 8px; font-size: 80%; font-style: italic; background-color: #FAFAFA; border-top: 1px none #E0E0E0; border-right: 1px none #E0E0E0; border-bottom: 1px none #E0E0E0; border-left: 1px none #E0E0E0; margin: 0px; } .memItemLeft { padding: 1px 0px 0px 8px; margin: 4px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-color: #E0E0E0; border-right-color: #E0E0E0; border-bottom-color: #E0E0E0; border-left-color: #E0E0E0; border-top-style: solid; border-right-style: none; border-bottom-style: none; border-left-style: none; background-color: #FAFAFA; font-size: 80%; } .memItemRight { padding: 1px 8px 0px 8px; margin: 4px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-color: #E0E0E0; border-right-color: #E0E0E0; border-bottom-color: #E0E0E0; border-left-color: #E0E0E0; border-top-style: solid; border-right-style: none; border-bottom-style: none; border-left-style: none; background-color: #FAFAFA; font-size: 80%; } .memTemplItemLeft { padding: 1px 0px 0px 8px; margin: 4px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-color: #E0E0E0; border-right-color: #E0E0E0; border-bottom-color: #E0E0E0; border-left-color: #E0E0E0; border-top-style: none; border-right-style: none; border-bottom-style: none; border-left-style: none; background-color: #FAFAFA; font-size: 80%; } .memTemplItemRight { padding: 1px 8px 0px 8px; margin: 4px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-color: #E0E0E0; border-right-color: #E0E0E0; border-bottom-color: #E0E0E0; border-left-color: #E0E0E0; border-top-style: none; border-right-style: none; border-bottom-style: none; border-left-style: none; background-color: #FAFAFA; font-size: 80%; } .memTemplParams { padding: 1px 0px 0px 8px; margin: 4px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-color: #E0E0E0; border-right-color: #E0E0E0; border-bottom-color: #E0E0E0; border-left-color: #E0E0E0; border-top-style: solid; border-right-style: none; border-bottom-style: none; border-left-style: none; color: #606060; background-color: #FAFAFA; font-size: 80%; } .search { color: #003399; font-weight: bold; } FORM.search { margin-bottom: 0px; margin-top: 0px; } INPUT.search { font-size: 75%; color: #000080; font-weight: normal; background-color: #eeeeff; } TD.tiny { font-size: 75%; } a { color: #252E78; } a:visited { color: #3D2185; } .dirtab { padding: 4px; border-collapse: collapse; border: 1px solid #b0b0b0; } TH.dirtab { background: #eeeeff; font-weight: bold; } HR { height: 1px; border: none; border-top: 1px solid black; } libsyncml-0.5.4/ChangeLog100644 1750 1750 26432 11211710410 15222 0ustar00bellmichbellmich2009-06-04 Michael Bell * Released 0.5.4 * All header files of the high level API are missing the extern "C" declarations for C++ (ticket #240). The patch was supplied by Sascha Peilicke. 2009-05-15 Michael Bell * Released 0.5.3 * Added a first implementation of the function smlDataSyncAbort. This function can be called if the synchronization must be abortedi (e.g. because of another external error like a full disk). * HTTP transport is now supported for old Solaris libsoup 2.2 packages * Added a missing SmlDevInf reference which causes a segmentation fault if a cached SmlDevInf object is used by OpenSync's SyncML plugin * Added support for the case that a client sends alert 200 and receives alert 200 but needs to update to a SLOW-SYNC alert 201 because of an internal problem like wrong anchors (NOTE: This code is untested because I failed to simulate this until now.) * Fixed bugs related to Funambol/ScheduleWorld: * Fixed wrong vCal 1.0 device information. If the default format of a datastore is iCal 2.0 then the content type for vCal 1.0 was wrong. Old (buggy): text/calendar 1.0 New (correct): text/x-vcalendar 1.0 * The Funambol server on scheduleworld.com returned error code 511. So the error code is supported now too. * The requested remote alert type is unknown and so let's signal this to the library user. * The getAlertTypeCallback should only be called once per data store. * Fixed return value of smlDataSyncClientSendAlert. If a slow-sync alert is initiated and the remote peer did not request it then the function must return false to trigger a status 508 (REFRESH_REQUIRED). If the requested alert type is not known then there is no need for a status and the function returns true. This can happen if the remote peer did not trigger the client via a SAN (e.g. OMA DS client over HTTP). * Added support for a separate mapping callback * Added better cleanup code for the transport layer in smlDataSyncObjectUnref * Fixed several comments * Added some trace statements * Several fixes for libsoup * Added tests to validate libsoup * Several fixes for the asynchronous http client * Added timeout to asynchronous http client session * Fixed client callback for libsoup 2.2 * Own thread and ctx for HTTP client * Added workaround for libsoup 2.2 http clients under Solaris (asynchronous http client support does not work under Solaris) * some cosmetical changes for http server code (traces, comments, assertions) * Added an internal function to run a function in a special thread. This feature is necessary because some libaries like libsoup are only designed for single-threaded applications. This means that every function must be called from the same thread. Otherwise there is no guarantee about the behaviour of the library. * libsoup_async respects now that SoupSessionAsync was designed for single-threaded applications. * Multi session fixes * Added multi session safe SAN callback * Fixed device information agent to be multi session safe. The old code only works if the manager manages exactly one session. If there is more than one session then the agent must take care about the different remote device capabilities. * Fixed remote device handling to be multi session safe. This is important if you ever implement long living processes or if you implement a client which wants to use its own session ID. * use new SAN callback which provides the session too which avoids race conditions (alternatively you can block the thread until the event SESSION_NEW will be dispatched) * Transport layer fixes: * Added code to test the transport layer context management * If a transport implementation has no public connect function then it cannot send a connect event. * smlTransportFinalize calls the finalize function of the transport implementations directly. The HTTP implementations depend on the correct thread because libsoup is single-threaded. This means that the worker thread must be available until all connections are closed (disconnected or finalized). Therefore the finalize function of a transport implementation must be called within the worker thread and the thread must be shut down after the finalize function was called. * Device Information fixes: * Added automatic localtime enforcement if the remote device sends a device information without UTC support * Ensure that the device information is always at the end of the message * If the alerts and the device information are in the same SyncML message then the alerts are dispatched faster. So it is necessary to check manually for an available remote device information. * Made smlQueueDetach of sml_queue.c thread safe * Made pendingMaps of objects/sml_ds_server.c thread safe * Added support for coverage analysis * Introduced internal mapping function. A change can now be freed after the status was received. * Fixed incorrect use of pthread_self (ticket #222). The patch was supplied by Henrik Kaare Poulsen. * Added missing @ONLY which reduces the memory usage from cmake (ticket #223). * Fixed wrong g_error usage (ticket #224). The patch was supplied by Henrik Kaare Poulsen. * Added default XML encoding explicitly because Sync4j requires it (ticket #225). * Abort more carefully (ticket #226 - does not affect 0.5.2 or earlier). * Added missing OBEX_TransportDisconnect in transport/obex_client.c (ticket #227). The original patch was supplied by Patrick Pfeifer. * Fixed some Windows/MinGW issues (ticket #228). The patch was supplied by Henrik Kaare Poulsen. * Fixed the target and source setting in change commands (ticket #229). * Google related fixes (ticket #230): * The HTTP client of DS API must support WBXML too. Google only supports WBXML today. (https://m.google.com/syncml is still a beta.) * Google has a wrong implementation of Alert Status. The Item Data is the Next Anchor. 5 2 3 Alert contacts contacts 200 * If an Item is deleted then it is not necessary to add a Data tag (ticket #232). The patch was supplied by Kwan hong Lee. * Sanitized UIDs (ticket #233). * Fixed DS API HTTP client inital allert which always sent a SLOW-SYNC alert (ticket #234). * Fixed skipping of Ext element (#235). The original patch was modified because the end of the new function could be reached without a return statement. The original patch was supplied by Kwan hong Lee. * Ticket #236 is a duplicate of ticket #232. * Fixed the handling of empty Data elements (ticket #237). The original patch was supplied by Kwan hong Lee. 2009-03-10 Michael Bell * Released 0.5.2 * Used SourceForge.net FRS for the first time * Discovered that xmlInitParser and especially xmlCleanupParser must be handled and called by the library user. * Added support for automatic Bluetooth channel detection * Added support for generic content-types * Added automatic base64 conversion for binary data types which are prefixed with application, audio, image, message and video (ticket #185) * Added IRDA support to OBEX client transport (ticket #212). The patch was supplied by Peter Collingbourne. * Added a test for the high level DS API * Added automatic UTF-16 to UTF-8 conversion for wrongly embedded SMS which is used bei Nokia S60 platform (ticket #217) * Added OMA DS 1.2 SAN support for content-types without an OMNA WSP number (ticket #217) * Added support for OMA DS 1.2 SAN without any data store. Mobiles which receive such a SAN should answer with alerts for all configured data stores. The problem is the term ''SHOULD''. Nokia S60 mobiles do not work this way for example. * Fixed string representation in OMA DS 1.2 SAN implementation (trailing NULL bytes must not be copied). Nokia S60 platform mobiles work now with OMA DS 1.2 over OBEX. * Fixed build environment to build correctly if OpenOBEX or libsoup are missing (ticket #211) * If a SAN is received then the remote location must be taken from the SAN alert. * DS API should only set configuration options if they are present. * Added support for receiving SANs to DS API * The target of an alert can now be different from the source in the DS API (e.g. source = Contacts, target = Addressbook). * syncml-ds-tool supports device faking. * Fixed wrong return value for vendor detection via AT commands (ticket #213). The patch was supplied by Frederic Brin. * Added Samsung SGH-F480 to the list of the supported models (ticket #214). The patch was supplied by Frederic Brin. * Added an assertion to smlDataSyncInit which checks for a non-NULL dsObject (ticket #215) * Fixed code to handle specific Samsung AT commands (ticket #216 - still open). A patch was supplied by Frederic Brin. * Added support for SourceParent and SourceTarget in XML parser and assembler (ticket #217 and #218) * Added support for SupportHierarchicalSync of OMA DS 1.2 DevInf (ticket #217 and #218) * Added some new content-types which were registered by OMA DS WG * Added support for authenticated OMA DS 1.2 SANs * If an enum type will be changed in the future then the order is critical. Hard coded values of the elements makes enums robust against re-ordering. * The HTTP client transport of the DS API does no longer instantiate a link object because the HTTP client transport does not support this. * If an error is dereferenced by smlErrorDeref then the caller can no longer access the object. (This makes sense because otherwise the caller should not dereference the object.) * smlTransportSetConfigOption traces no longer PASSWORD options. * If a link of a server is requested to be disconnected but it is already disconnected then this is sometimes no error when a very fast client disconnects before the server. * If the server closes the connection before the client can do this then the disconnect command of the client fails but the client is disconnected. * Fixed wrong interpretation of return value from smlTransportFinalize in data_sync.c * Fixed wrong handling of REPLACE command during SLOW SYNC * Fixed wrong context free of OBEX server transport finalize. * Fixed error handling and reference counting of smlCredNewAuth * Fixed again several memory leaks and removed all suppressions for libxml from valgrind.supp. * Added some code to handle the not thread safe check library libsyncml-0.5.4/tests/check_data_sync_api.c100644 1750 1750 31303 11211710410 20702 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2009 Michael Bell * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include "tests/support.h" #include #include #include #include #include #include // #include //#include //#include //#include GMutex *runMutex = NULL; int locks; GList *client_items; SmlDataSyncObject *client; SmlDataSyncObject *server; const char *client_source; const char *server_source; const char *transport; /* ************************************ */ /* *********** CALLBACKS ************** */ /* ************************************ */ SmlBool sendAllChanges( SmlDataSyncObject *dsObject, SmlError **error) { smlTrace(TRACE_ENTRY, "%s", __func__); if (dsObject == client) { GList *list = client_items; size_t count = 0; for (;list;list = list->next) { count++; const char *test_data = list->data; char *name = g_strdup_printf("%d", count); if (!smlDataSyncAddChange(client, client_source, SML_CHANGE_ADD, name , test_data, strlen(test_data), NULL, error)) { sml_fail_unless(FALSE, "%s", smlErrorPrint(error)); } smlSafeCFree(&name); } } smlTrace(TRACE_EXIT, "%s", __func__); return smlDataSyncSendChanges(dsObject, error); } static void recvEventCallback( SmlDataSyncObject *dsObject, SmlDataSyncEventType type, void *userdata, SmlError *error) { smlTrace(TRACE_ENTRY, "%s(%p, %i, %p, %p)", __func__, dsObject, type, userdata, error); SmlError *locerror = NULL; switch (type) { case SML_DATA_SYNC_EVENT_ERROR: if (dsObject == client) { sml_fail_unless(FALSE, "OMA DS client failed: %s", smlErrorPrint(&error)); } else { sml_fail_unless(FALSE, "OMA DS server failed: %s", smlErrorPrint(&error)); } break; case SML_DATA_SYNC_EVENT_CONNECT: /* g_message("Remote device was successfully connected."); */ break; case SML_DATA_SYNC_EVENT_DISCONNECT: /* g_message("Remote device was successfully disconnected."); */ break; case SML_DATA_SYNC_EVENT_FINISHED: /* g_message("SyncML session finished successfully."); */ if (g_atomic_int_dec_and_test(&locks)) g_mutex_unlock(runMutex); break; case SML_DATA_SYNC_EVENT_GOT_ALL_ALERTS: /* g_message("All alerts of the remote device were received."); */ if (dsObject == client) { if (!sendAllChanges(dsObject, &locerror)) goto error; } break; case SML_DATA_SYNC_EVENT_GOT_ALL_CHANGES: /* g_message("All changes of the remote device were received."); */ if (dsObject == server) { if (!sendAllChanges(dsObject, &locerror)) goto error; } /* the map of the client is send automatically */ break; case SML_DATA_SYNC_EVENT_GOT_ALL_MAPPINGS: if (dsObject == server) { /* g_message("All mappings of the remote device were received."); */ } else { g_error("Received a map but I'm a client!"); } break; default: g_error("Unknown event(%d).\n", type); break; } smlTrace(TRACE_EXIT, "%s", __func__); return; error: fprintf(stderr, "An error occured while handling events: %s\n", smlErrorPrint(&locerror)); smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(&locerror)); smlErrorDeref(&locerror); exit(3); } static SmlBool recvChangeCallback( SmlDataSyncObject *dsObject, const char *source, SmlChangeType type, const char *uid, char *data, unsigned int size, void *userdata, SmlError **error) { smlTrace(TRACE_ENTRY, "%s: %s ==> %s(%p, %d, %p, %d, %p, %p)", __func__, VA_STRING(source), VA_STRING(uid), dsObject, type, data, size, userdata, error); /* clients should never receive a change in this test */ if (dsObject == client) { sml_fail_unless(FALSE, "A change was received from the server."); } /* check the source */ if (strcmp(server_source, source)) { sml_fail_unless(FALSE, "The source %s is wrong.", server_source); } /* handle the item */ GList *list = client_items; size_t count = 0; for (; list; list = list->next) { count++; /* test the uid */ char *name = g_strdup_printf("%d", count); if (strcmp(name, uid)) { smlSafeCFree(&name); continue; } smlSafeCFree(&name); /* item with correct uid */ if (strcmp(list->data, data)) { sml_fail_unless(FALSE, "The data of the item %s was wrong(%s != %s).", uid, data, list->data); } } smlSafeCFree(&data); smlTrace(TRACE_EXIT, "%s - TRUE", __func__); return TRUE; } //static SmlAlertType recvAlertTypeCallback( // SmlDataSyncObject *dsObject, // const char *source, // SmlAlertType type, // void *userdata, // SmlError **error) //{ // smlTrace(TRACE_ENTRY, "%s - %s: %d", __func__, VA_STRING(source), type); // /* find the appropriate datasoure */ // SmlDsToolLocationType *datastore = NULL; // GList *o = datastores; // while (o) { // datastore = o->data; // if (!strcmp(datastore->source, source)) { // /* abort the scan */ // o = NULL; // } else { // datastore = NULL; // } // if (o) o = o->next; // } // if (!datastore) { // smlErrorSet(error, SML_ERROR_GENERIC, // "Cannot found datastore %s.", // source); // goto error; // } // smlTrace(TRACE_INTERNAL, "%s: datastores scanned", __func__); // // /* synchronize the alert type */ // if (type == SML_ALERT_SLOW_SYNC) // datastore->slow = TRUE; // if (datastore->slow) // type = SML_ALERT_SLOW_SYNC; // // smlTrace(TRACE_EXIT, "%s - slow == %d", __func__, datastore->slow); // return type; //error: // smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(error)); // return SML_ALERT_UNKNOWN; //} void init_testbed(const char *transport_type, const char *port) { /* general init */ setup_testbed(NULL); SmlError *error = NULL; client_items = NULL; #ifdef ENABLE_OPENOBEX_TCP transport = "OBEX"; #endif #ifdef ENABLE_HTTP transport = "HTTP"; #endif #ifdef ENABLE_OPENOBEX_TCP if (!strcasecmp(transport_type, "OBEX")) { transport = "OBEX"; } #endif #ifdef ENABLE_HTTP if (!strcasecmp(transport_type, "HTTP")) { transport = "HTTP"; } #endif if (!strcmp(transport, "HTTP")) { client = smlDataSyncNew(SML_SESSION_TYPE_CLIENT, SML_TRANSPORT_HTTP_CLIENT, &error); if (!client) goto error; server = smlDataSyncNew(SML_SESSION_TYPE_SERVER, SML_TRANSPORT_HTTP_SERVER, &error); if (!server) goto error; } else { client = smlDataSyncNew(SML_SESSION_TYPE_CLIENT, SML_TRANSPORT_OBEX_SERVER, &error); if (!client) goto error; server = smlDataSyncNew(SML_SESSION_TYPE_SERVER, SML_TRANSPORT_OBEX_CLIENT, &error); if (!server) goto error; } /* default configuration of callbacks */ smlDataSyncRegisterEventCallback(client, recvEventCallback, NULL); smlDataSyncRegisterEventCallback(server, recvEventCallback, NULL); // smlDataSyncRegisterGetAlertTypeCallback(client, recvAlertTypeCallback, NULL); // smlDataSyncRegisterGetAlertTypeCallback(server, recvAlertTypeCallback, NULL); smlDataSyncRegisterChangeCallback(client, recvChangeCallback, NULL); smlDataSyncRegisterChangeCallback(server, recvChangeCallback, NULL); // smlDataSyncRegisterChangeStatusCallback(dsObject, recvChangeStatusCallback); // smlDataSyncRegisterMappingCallback(dsObject, recvMappingCallback, NULL); /* configure transport */ if (!strcmp(transport, "HTTP")) { /* HTTP */ char *url = g_strdup_printf("http://127.0.0.1:%s", port); if (!smlDataSyncSetOption( client, SML_TRANSPORT_CONFIG_URL, url, &error)) goto error; smlSafeCFree(&url); } else { /* OBEX */ if (!smlDataSyncSetOption( client, SML_DATA_SYNC_CONFIG_CONNECTION_TYPE, SML_DATA_SYNC_CONFIG_CONNECTION_NET, &error)) goto error; if (!smlDataSyncSetOption( server, SML_DATA_SYNC_CONFIG_CONNECTION_TYPE, SML_DATA_SYNC_CONFIG_CONNECTION_NET, &error)) goto error; if (!smlDataSyncSetOption( server, SML_TRANSPORT_CONFIG_URL, "127.0.0.1", &error)) goto error; if (!smlDataSyncSetOption( client, SML_TRANSPORT_CONFIG_PORT, port, &error)) goto error; } if (!smlDataSyncSetOption( server, SML_TRANSPORT_CONFIG_PORT, port, &error)) goto error; return; error: sml_fail_unless(FALSE, "%s", smlErrorPrint(&error)); } void run_testbed() { SmlError *error = NULL; locks = 2; /* init the sync */ if (!strcmp(transport, "HTTP")) { if (!smlDataSyncInit(server, &error)) goto error; if (!smlDataSyncInit(client, &error)) goto error; if (!smlDataSyncRun(server, &error)) goto error; if (!smlDataSyncRun(client, &error)) goto error; } else { if (!smlDataSyncInit(client, &error)) goto error; if (!smlDataSyncInit(server, &error)) goto error; if (!smlDataSyncRun(client, &error)) goto error; /* The OBEX server needs some time to start. */ if (g_getenv("SYNCML_TRACE")) sleep(2); else sleep(5); if (!smlDataSyncRun(server, &error)) goto error; } runMutex = g_mutex_new(); g_mutex_lock(runMutex); g_mutex_lock(runMutex); g_mutex_unlock(runMutex); g_mutex_free(runMutex); runMutex = NULL; /* close the object */ smlDataSyncObjectUnref(&client); smlDataSyncObjectUnref(&server); g_list_free(client_items); return; error: sml_fail_unless(FALSE, "%s", smlErrorPrint(&error)); } START_TEST (ds_api_text_vcard_21) { SmlError *error = NULL; init_testbed("HTTP", "17001"); /* register datastore * the source must be identical because this is http */ client_source = "contacts"; server_source = "contacts"; if (!smlDataSyncAddDatastore( client, "text/x-vcard", NULL, client_source, &error)) goto error; if (!smlDataSyncAddDatastore( server, "text/x-vcard", NULL, server_source, &error)) goto error; /* configure test data */ client_items = g_list_append(client_items, (char *) "blabla"); run_testbed(); return; error: sml_fail_unless(FALSE, "%s", smlErrorPrint(&error)); } END_TEST START_TEST (ds_api_image_jpeg) { SmlError *error = NULL; init_testbed("OBEX", "17002"); /* register datastore * the source must be identical if this is http */ client_source = "dcim"; if (!strcmp(transport, "OBEX")) server_source = "photos"; else server_source = "dcim"; if (!smlDataSyncAddDatastore( client, "image/jpeg", NULL, client_source, &error)) goto error; if (!smlDataSyncAddDatastore( server, "image/jpeg", NULL, server_source, &error)) goto error; /* configure test data */ client_items = g_list_append(client_items, (char *) "this is an image"); run_testbed(); return; error: sml_fail_unless(FALSE, "%s", smlErrorPrint(&error)); } END_TEST START_TEST (ds_api_unknown_ct) { SmlError *error = NULL; init_testbed("HTTP", "17003"); /* register datastore * the source must be identical because this is http */ client_source = "data"; server_source = "data"; if (!smlDataSyncAddDatastore( client, "unknown/content-type", NULL, client_source, &error)) goto error; if (!smlDataSyncAddDatastore( server, "unknown/content-type", NULL, server_source, &error)) goto error; /* configure test data */ client_items = g_list_append(client_items, (char *) "this is some data"); run_testbed(); return; error: sml_fail_unless(FALSE, "%s", smlErrorPrint(&error)); } END_TEST START_TEST (ds_api_multi_text_vcard_21) { SmlError *error = NULL; init_testbed("HTTP", "17004"); /* register datastore * the source must be identical because this is http */ client_source = "contacts"; server_source = "contacts"; if (!smlDataSyncAddDatastore( client, "text/x-vcard", NULL, client_source, &error)) goto error; if (!smlDataSyncAddDatastore( server, "text/x-vcard", NULL, server_source, &error)) goto error; /* configure test data */ int max_items = 10000; int i; for(i = 0; i < max_items; i++) { client_items = g_list_append(client_items, (char *) "client data"); } run_testbed(); return; error: sml_fail_unless(FALSE, "%s", smlErrorPrint(&error)); } END_TEST @SML_TESTCASE_CODE@ libsyncml-0.5.4/tests/check_xml_assembler.c100644 1750 1750 155726 11211710410 21001 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2005 Armin Bauer * Copyright (C) 2008 Michael Bell * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include "tests/support.h" #include #include static SmlAssembler *start_assembler(SmlSession *session, unsigned int limit) { setup_testbed(NULL); SmlError *error = NULL; SmlAssembler *assm = smlAssemblerNew(SML_MIMETYPE_XML, limit, &error); sml_fail_unless(assm != NULL, NULL); sml_fail_unless(error == NULL, NULL); if (!smlAssemblerStart(assm, session, &error)) { sml_fail_unless(error != NULL, NULL); smlAssemblerFree(assm); return NULL; } return assm; } START_TEST (xml_assembler_message_empty) { SmlError *error = NULL; SmlLocation *loc = smlLocationNew("/test", NULL, &error); sml_fail_unless(loc != NULL, NULL); sml_fail_unless(error == NULL, NULL); /* The session type must be SML_SESSION_TYPE_CLIENT * because servers of SyncML 1.1 or higher must send MaxMsgSize. */ SmlSession *session = smlSessionNew(SML_SESSION_TYPE_CLIENT, SML_MIMETYPE_XML, SML_VERSION_12, SML_PROTOCOL_SYNCML, loc, loc, "1", 0, &error); smlLocationUnref(loc); SmlAssembler *assm = start_assembler(session, 0); sml_fail_unless(assm != NULL, NULL); char *data = NULL; unsigned int size = 0; sml_fail_unless(!smlAssemblerRun(assm, &data, &size, NULL, TRUE, &error), NULL); sml_fail_unless(error != NULL, NULL); smlErrorDeref(&error); sml_fail_unless(smlAssemblerFlush(assm) == 1, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(!smlAssemblerRun(assm, &data, &size, NULL, TRUE, &error), NULL); sml_fail_unless(error != NULL, NULL); smlErrorDeref(&error); smlAssemblerFree(assm); smlSessionUnref(session); } END_TEST START_TEST (xml_assembler_message_only_header) { SmlError *error = NULL; SmlLocation *loc = smlLocationNew("/test", NULL, &error); sml_fail_unless(loc != NULL, NULL); sml_fail_unless(error == NULL, NULL); /* The session type must be SML_SESSION_TYPE_CLIENT * because servers of SyncML 1.1 or higher must send MaxMsgSize. */ SmlSession *session = smlSessionNew(SML_SESSION_TYPE_CLIENT, SML_MIMETYPE_XML, SML_VERSION_12, SML_PROTOCOL_SYNCML, loc, loc, "1", 0, &error); smlLocationUnref(loc); SmlAssembler *assm = start_assembler(session, 0); sml_fail_unless(assm != NULL, NULL); sml_fail_unless(smlAssemblerAddHeader(assm, session, &error), NULL); sml_fail_unless(error == NULL, NULL); char *data = NULL; unsigned int size = 0; sml_fail_unless(!smlAssemblerRun(assm, &data, &size, NULL, TRUE, &error), NULL); sml_fail_unless(error != NULL, NULL); smlErrorDeref(&error); sml_fail_unless(smlAssemblerFlush(assm) == 1, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(!smlAssemblerRun(assm, &data, &size, NULL, TRUE, &error), NULL); sml_fail_unless(error != NULL, NULL); smlErrorDeref(&error); smlAssemblerFree(assm); smlSessionUnref(session); } END_TEST START_TEST (xml_assembler_message_status) { SmlError *error = NULL; SmlLocation *loc = smlLocationNew("/test", NULL, &error); sml_fail_unless(loc != NULL, NULL); sml_fail_unless(error == NULL, NULL); /* The session type must be SML_SESSION_TYPE_CLIENT * because servers of SyncML 1.1 or higher must send MaxMsgSize. */ SmlSession *session = smlSessionNew(SML_SESSION_TYPE_CLIENT, SML_MIMETYPE_XML, SML_VERSION_12, SML_PROTOCOL_SYNCML, loc, loc, "1", 0, &error); SmlAssembler *assm = start_assembler(session, 0); sml_fail_unless(assm != NULL, NULL); sml_fail_unless(smlAssemblerAddHeader(assm, session, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlAssemblerReserveStatus(assm, 1, 1, 1, &error), NULL); sml_fail_unless(error == NULL, NULL); SmlStatus *status = smlStatusNew(SML_NO_ERROR, 1, 1, loc, loc, SML_COMMAND_TYPE_SYNC, &error); sml_fail_unless(status != NULL, NULL); sml_fail_unless(error == NULL, NULL); smlLocationUnref(loc); sml_fail_unless(smlAssemblerAddStatus(assm, status, &error), NULL); sml_fail_unless(error == NULL, NULL); smlStatusUnref(status); char *data = NULL; unsigned int size = 0; sml_fail_unless(smlAssemblerRun(assm, &data, &size, NULL, TRUE, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(data != NULL, NULL); sml_fail_unless(size != 0, NULL); g_free(data); sml_fail_unless(smlAssemblerFlush(assm) == 1, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(!smlAssemblerRun(assm, &data, &size, NULL, TRUE, &error), NULL); sml_fail_unless(error != NULL, NULL); smlErrorDeref(&error); smlAssemblerFree(assm); smlSessionUnref(session); } END_TEST START_TEST (xml_assembler_message_cmd) { SmlError *error = NULL; SmlLocation *loc = smlLocationNew("/test", NULL, &error); sml_fail_unless(loc != NULL, NULL); sml_fail_unless(error == NULL, NULL); /* The session type must be SML_SESSION_TYPE_CLIENT * because servers of SyncML 1.1 or higher must send MaxMsgSize. */ SmlSession *session = smlSessionNew(SML_SESSION_TYPE_CLIENT, SML_MIMETYPE_XML, SML_VERSION_12, SML_PROTOCOL_SYNCML, loc, loc, "1", 0, &error); SmlAssembler *assm = start_assembler(session, 0); sml_fail_unless(assm != NULL, NULL); sml_fail_unless(smlAssemblerAddHeader(assm, session, &error), NULL); sml_fail_unless(error == NULL, NULL); SmlCommand *cmd = smlCommandNewAlert(SML_ALERT_TWO_WAY, loc, loc, "next", "last", NULL, &error); sml_fail_unless(cmd != NULL, NULL); sml_fail_unless(error == NULL, NULL); cmd->cmdID = 1; smlLocationUnref(loc); sml_fail_unless(smlAssemblerStartCommand(assm, NULL, cmd, &error), NULL); sml_fail_unless(error == NULL, NULL); smlCommandUnref(cmd); sml_fail_unless(smlAssemblerEndCommand(assm, NULL, &error), NULL); sml_fail_unless(error == NULL, NULL); char *data = NULL; unsigned int size = 0; sml_fail_unless(smlAssemblerRun(assm, &data, &size, NULL, TRUE, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(data != NULL, NULL); sml_fail_unless(size != 0, NULL); g_free(data); sml_fail_unless(smlAssemblerFlush(assm) == 1, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(!smlAssemblerRun(assm, &data, &size, NULL, TRUE, &error), NULL); sml_fail_unless(error != NULL, NULL); smlErrorDeref(&error); smlAssemblerFree(assm); smlSessionUnref(session); } END_TEST START_TEST (xml_assembler_message_subcmd) { SmlError *error = NULL; SmlLocation *loc = smlLocationNew("/test", NULL, &error); sml_fail_unless(loc != NULL, NULL); sml_fail_unless(error == NULL, NULL); /* The session type must be SML_SESSION_TYPE_CLIENT * because servers of SyncML 1.1 or higher must send MaxMsgSize. */ SmlSession *session = smlSessionNew(SML_SESSION_TYPE_CLIENT, SML_MIMETYPE_XML, SML_VERSION_12, SML_PROTOCOL_SYNCML, loc, loc, "1", 0, &error); SmlAssembler *assm = start_assembler(session, 0); sml_fail_unless(assm != NULL, NULL); sml_fail_unless(smlAssemblerAddHeader(assm, session, &error), NULL); sml_fail_unless(error == NULL, NULL); SmlCommand *cmd1 = smlCommandNewSync(loc, loc, 0, &error); sml_fail_unless(cmd1 != NULL, NULL); sml_fail_unless(error == NULL, NULL); cmd1->cmdID = 1; smlLocationUnref(loc); sml_fail_unless(smlAssemblerStartCommand(assm, NULL, cmd1, &error), NULL); sml_fail_unless(error == NULL, NULL); SmlCommand *cmd2 = smlCommandNewChange(SML_CHANGE_ADD, "uid", "data", 5, SML_ELEMENT_TEXT_VCARD, &error); sml_fail_unless(cmd2 != NULL, NULL); sml_fail_unless(error == NULL, NULL); cmd2->cmdID = 2; sml_fail_unless(smlAssemblerStartCommand(assm, cmd1, cmd2, &error), NULL); sml_fail_unless(error == NULL, NULL); smlCommandUnref(cmd2); sml_fail_unless(smlAssemblerEndCommand(assm, cmd1, &error), NULL); sml_fail_unless(error == NULL, NULL); smlCommandUnref(cmd1); sml_fail_unless(smlAssemblerEndCommand(assm, NULL, &error), NULL); sml_fail_unless(error == NULL, NULL); char *data = NULL; unsigned int size = 0; sml_fail_unless(smlAssemblerRun(assm, &data, &size, NULL, TRUE, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(data != NULL, NULL); sml_fail_unless(size != 0, NULL); g_free(data); sml_fail_unless(smlAssemblerFlush(assm) == 1, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(!smlAssemblerRun(assm, &data, &size, NULL, TRUE, &error), NULL); sml_fail_unless(error != NULL, NULL); smlErrorDeref(&error); smlAssemblerFree(assm); smlSessionUnref(session); } END_TEST START_TEST (xml_assembler_message_several_subcmd) { SmlError *error = NULL; SmlLocation *loc = smlLocationNew("/test", NULL, &error); sml_fail_unless(loc != NULL, NULL); sml_fail_unless(error == NULL, NULL); /* The session type must be SML_SESSION_TYPE_CLIENT * because servers of SyncML 1.1 or higher must send MaxMsgSize. */ SmlSession *session = smlSessionNew(SML_SESSION_TYPE_CLIENT, SML_MIMETYPE_XML, SML_VERSION_12, SML_PROTOCOL_SYNCML, loc, loc, "1", 0, &error); SmlAssembler *assm = start_assembler(session, 0); sml_fail_unless(assm != NULL, NULL); sml_fail_unless(smlAssemblerAddHeader(assm, session, &error), NULL); sml_fail_unless(error == NULL, NULL); SmlCommand *cmd1 = smlCommandNewSync(loc, loc, 0, &error); sml_fail_unless(cmd1 != NULL, NULL); sml_fail_unless(error == NULL, NULL); cmd1->cmdID = 1; sml_fail_unless(smlAssemblerStartCommand(assm, NULL, cmd1, &error), NULL); sml_fail_unless(error == NULL, NULL); SmlCommand *cmd2 = smlCommandNewChange(SML_CHANGE_ADD, "uid", "data", 5, SML_ELEMENT_TEXT_VCARD, &error); cmd2->cmdID = 2; sml_fail_unless(smlAssemblerStartCommand(assm, cmd1, cmd2, &error), NULL); sml_fail_unless(error == NULL, NULL); smlCommandUnref(cmd2); sml_fail_unless(smlAssemblerEndCommand(assm, cmd1, &error), NULL); sml_fail_unless(error == NULL, NULL); cmd2 = smlCommandNewChange(SML_CHANGE_ADD, "uid2", "data2", 5, SML_ELEMENT_TEXT_VCARD, &error); cmd2->cmdID = 3; sml_fail_unless(smlAssemblerStartCommand(assm, cmd1, cmd2, &error), NULL); sml_fail_unless(error == NULL, NULL); smlCommandUnref(cmd2); sml_fail_unless(smlAssemblerEndCommand(assm, cmd1, &error), NULL); sml_fail_unless(error == NULL, NULL); smlCommandUnref(cmd1); sml_fail_unless(smlAssemblerEndCommand(assm, NULL, &error), NULL); sml_fail_unless(error == NULL, NULL); cmd1 = smlCommandNewSync(loc, loc, 0, &error); sml_fail_unless(cmd1 != NULL, NULL); sml_fail_unless(error == NULL, NULL); cmd1->cmdID = 4; smlLocationUnref(loc); sml_fail_unless(smlAssemblerStartCommand(assm, NULL, cmd1, &error), NULL); sml_fail_unless(error == NULL, NULL); cmd2 = smlCommandNewChange(SML_CHANGE_ADD, "uid", "data", 5, SML_ELEMENT_TEXT_VCARD, &error); cmd2->cmdID = 5; sml_fail_unless(smlAssemblerStartCommand(assm, cmd1, cmd2, &error), NULL); sml_fail_unless(error == NULL, NULL); smlCommandUnref(cmd2); sml_fail_unless(smlAssemblerEndCommand(assm, cmd1, &error), NULL); sml_fail_unless(error == NULL, NULL); cmd2 = smlCommandNewChange(SML_CHANGE_ADD, "uid2", "data2", 5, SML_ELEMENT_TEXT_VCARD, &error); cmd2->cmdID = 6; sml_fail_unless(smlAssemblerStartCommand(assm, cmd1, cmd2, &error), NULL); sml_fail_unless(error == NULL, NULL); smlCommandUnref(cmd2); sml_fail_unless(smlAssemblerEndCommand(assm, cmd1, &error), NULL); sml_fail_unless(error == NULL, NULL); smlCommandUnref(cmd1); sml_fail_unless(smlAssemblerEndCommand(assm, NULL, &error), NULL); sml_fail_unless(error == NULL, NULL); char *data = NULL; unsigned int size = 0; sml_fail_unless(smlAssemblerRun(assm, &data, &size, NULL, TRUE, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(data != NULL, NULL); sml_fail_unless(size != 0, NULL); g_free(data); sml_fail_unless(smlAssemblerFlush(assm) == 1, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(!smlAssemblerRun(assm, &data, &size, NULL, TRUE, &error), NULL); sml_fail_unless(error != NULL, NULL); smlErrorDeref(&error); smlAssemblerFree(assm); smlSessionUnref(session); } END_TEST START_TEST (xml_assembler_message_flush_open) { SmlError *error = NULL; SmlLocation *loc = smlLocationNew("/test", NULL, &error); sml_fail_unless(loc != NULL, NULL); sml_fail_unless(error == NULL, NULL); /* The session type must be SML_SESSION_TYPE_CLIENT * because servers of SyncML 1.1 or higher must send MaxMsgSize. */ SmlSession *session = smlSessionNew(SML_SESSION_TYPE_CLIENT, SML_MIMETYPE_XML, SML_VERSION_12, SML_PROTOCOL_SYNCML, loc, loc, "1", 0, &error); SmlAssembler *assm = start_assembler(session, 0); sml_fail_unless(assm != NULL, NULL); sml_fail_unless(smlAssemblerAddHeader(assm, session, &error), NULL); sml_fail_unless(error == NULL, NULL); SmlCommand *cmd1 = smlCommandNewSync(loc, loc, 0, &error); sml_fail_unless(cmd1 != NULL, NULL); sml_fail_unless(error == NULL, NULL); cmd1->cmdID = 1; smlLocationUnref(loc); sml_fail_unless(smlAssemblerStartCommand(assm, NULL, cmd1, &error), NULL); sml_fail_unless(error == NULL, NULL); SmlCommand *cmd2 = smlCommandNewChange(SML_CHANGE_ADD, "uid", "data", 5, SML_ELEMENT_TEXT_VCARD, &error); cmd2->cmdID = 2; sml_fail_unless(smlAssemblerStartCommand(assm, cmd1, cmd2, &error), NULL); sml_fail_unless(error == NULL, NULL); smlCommandUnref(cmd2); sml_fail_unless(smlAssemblerEndCommand(assm, cmd1, &error), NULL); sml_fail_unless(error == NULL, NULL); char *data = NULL; unsigned int size = 0; sml_fail_unless(smlAssemblerRun(assm, &data, &size, NULL, FALSE, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(data != NULL, NULL); sml_fail_unless(size != 0, NULL); g_free(data); sml_fail_unless(smlAssemblerFlush(assm) == 1, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlAssemblerStartCommand(assm, NULL, cmd1, &error), NULL); sml_fail_unless(error == NULL, NULL); cmd2 = smlCommandNewChange(SML_CHANGE_ADD, "uid2", "data2", 5, SML_ELEMENT_TEXT_VCARD, &error); cmd2->cmdID = 3; sml_fail_unless(smlAssemblerStartCommand(assm, cmd1, cmd2, &error), NULL); sml_fail_unless(error == NULL, NULL); smlCommandUnref(cmd2); sml_fail_unless(smlAssemblerEndCommand(assm, cmd1, &error), NULL); sml_fail_unless(error == NULL, NULL); smlCommandUnref(cmd1); sml_fail_unless(smlAssemblerEndCommand(assm, NULL, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlAssemblerRun(assm, &data, &size, NULL, TRUE, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(data != NULL, NULL); sml_fail_unless(size != 0, NULL); g_free(data); sml_fail_unless(smlAssemblerFlush(assm) == 1, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(!smlAssemblerRun(assm, &data, &size, NULL, TRUE, &error), NULL); sml_fail_unless(error != NULL, NULL); smlErrorDeref(&error); smlAssemblerFree(assm); smlSessionUnref(session); } END_TEST /** - start sync1 * - add change to sync1 * - start sync2 * - add change to sync2 * - end sync1 * - add change to sync1 * - add change to sync2 * - end root (sync1) * - add change to sync2 * - end root (sync2) */ START_TEST (xml_assembler_out_of_order) { SmlError *error = NULL; SmlLocation *loc = smlLocationNew("/test", NULL, &error); sml_fail_unless(loc != NULL, NULL); sml_fail_unless(error == NULL, NULL); /* The session type must be SML_SESSION_TYPE_CLIENT * because servers of SyncML 1.1 or higher must send MaxMsgSize. */ SmlSession *session = smlSessionNew(SML_SESSION_TYPE_CLIENT, SML_MIMETYPE_XML, SML_VERSION_12, SML_PROTOCOL_SYNCML, loc, loc, "1", 0, &error); SmlAssembler *assm = start_assembler(session, 0); sml_fail_unless(assm != NULL, NULL); sml_fail_unless(smlAssemblerAddHeader(assm, session, &error), NULL); sml_fail_unless(error == NULL, NULL); SmlCommand *cmd1 = smlCommandNewSync(loc, loc, 0, &error); sml_fail_unless(cmd1 != NULL, NULL); sml_fail_unless(error == NULL, NULL); cmd1->cmdID = 1; sml_fail_unless(smlAssemblerStartCommand(assm, NULL, cmd1, &error), NULL); sml_fail_unless(error == NULL, NULL); SmlCommand *cmd2 = smlCommandNewChange(SML_CHANGE_ADD, "change1sync1", "data", 5, SML_ELEMENT_TEXT_VCARD, &error); cmd2->cmdID = 2; sml_fail_unless(smlAssemblerStartCommand(assm, cmd1, cmd2, &error), NULL); sml_fail_unless(error == NULL, NULL); smlCommandUnref(cmd2); sml_fail_unless(smlAssemblerEndCommand(assm, cmd1, &error), NULL); sml_fail_unless(error == NULL, NULL); SmlCommand *cmd3 = smlCommandNewSync(loc, loc, 0, &error); sml_fail_unless(cmd3 != NULL, NULL); sml_fail_unless(error == NULL, NULL); cmd3->cmdID = 4; smlLocationUnref(loc); sml_fail_unless(smlAssemblerStartCommand(assm, NULL, cmd3, &error), NULL); sml_fail_unless(error == NULL, NULL); cmd2 = smlCommandNewChange(SML_CHANGE_ADD, "change1sync2", "data", 5, SML_ELEMENT_TEXT_VCARD, &error); cmd2->cmdID = 5; sml_fail_unless(smlAssemblerStartCommand(assm, cmd3, cmd2, &error), NULL); sml_fail_unless(error == NULL, NULL); smlCommandUnref(cmd2); sml_fail_unless(smlAssemblerEndCommand(assm, cmd3, &error), NULL); sml_fail_unless(error == NULL, NULL); cmd2 = smlCommandNewChange(SML_CHANGE_ADD, "change2sync1", "data2", 5, SML_ELEMENT_TEXT_VCARD, &error); cmd2->cmdID = 3; sml_fail_unless(smlAssemblerStartCommand(assm, cmd1, cmd2, &error), NULL); sml_fail_unless(error == NULL, NULL); smlCommandUnref(cmd2); sml_fail_unless(smlAssemblerEndCommand(assm, cmd1, &error), NULL); sml_fail_unless(error == NULL, NULL); cmd2 = smlCommandNewChange(SML_CHANGE_ADD, "change2sync2", "data2", 5, SML_ELEMENT_TEXT_VCARD, &error); cmd2->cmdID = 6; sml_fail_unless(smlAssemblerStartCommand(assm, cmd3, cmd2, &error), NULL); sml_fail_unless(error == NULL, NULL); smlCommandUnref(cmd2); sml_fail_unless(smlAssemblerEndCommand(assm, cmd3, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlAssemblerEndCommand(assm, NULL, &error), NULL); sml_fail_unless(error == NULL, NULL); cmd2 = smlCommandNewChange(SML_CHANGE_ADD, "change3sync2", "data2", 5, SML_ELEMENT_TEXT_VCARD, &error); cmd2->cmdID = 7; sml_fail_unless(smlAssemblerStartCommand(assm, cmd3, cmd2, &error), NULL); sml_fail_unless(error == NULL, NULL); smlCommandUnref(cmd2); sml_fail_unless(smlAssemblerEndCommand(assm, cmd3, &error), NULL); sml_fail_unless(error == NULL, NULL); smlCommandUnref(cmd3); smlCommandUnref(cmd1); sml_fail_unless(smlAssemblerEndCommand(assm, NULL, &error), NULL); sml_fail_unless(error == NULL, NULL); char *data = NULL; unsigned int size = 0; sml_fail_unless(smlAssemblerRun(assm, &data, &size, NULL, TRUE, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(data != NULL, NULL); sml_fail_unless(size != 0, NULL); g_free(data); sml_fail_unless(smlAssemblerFlush(assm) == 1, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(!smlAssemblerRun(assm, &data, &size, NULL, TRUE, &error), NULL); sml_fail_unless(error != NULL, NULL); smlErrorDeref(&error); smlAssemblerFree(assm); smlSessionUnref(session); } END_TEST START_TEST (xml_assembler_limit1) { SmlError *error = NULL; SmlLocation *loc = smlLocationNew("/test", NULL, &error); sml_fail_unless(loc != NULL, NULL); sml_fail_unless(error == NULL, NULL); /* The session type must be SML_SESSION_TYPE_CLIENT * because servers of SyncML 1.1 or higher must send MaxMsgSize. */ SmlSession *session = smlSessionNew(SML_SESSION_TYPE_CLIENT, SML_MIMETYPE_XML, SML_VERSION_12, SML_PROTOCOL_SYNCML, loc, loc, "1", 0, &error); smlLocationUnref(loc); SmlAssembler *assm = start_assembler(session, 1); sml_fail_unless(assm != NULL, NULL); sml_fail_unless(!smlAssemblerAddHeader(assm, session, &error), NULL); sml_fail_unless(error != NULL, NULL); smlErrorDeref(&error); char *data = NULL; unsigned int size = 0; sml_fail_unless(!smlAssemblerRun(assm, &data, &size, NULL, TRUE, &error), NULL); sml_fail_unless(error != NULL, NULL); smlErrorDeref(&error); smlAssemblerFree(assm); smlSessionUnref(session); } END_TEST START_TEST (xml_assembler_limit2) { SmlError *error = NULL; SmlLocation *loc = smlLocationNew("/test", NULL, &error); sml_fail_unless(loc != NULL, NULL); sml_fail_unless(error == NULL, NULL); /* The session type must be SML_SESSION_TYPE_CLIENT * because servers of SyncML 1.1 or higher must send MaxMsgSize. */ SmlSession *session = smlSessionNew(SML_SESSION_TYPE_CLIENT, SML_MIMETYPE_XML, SML_VERSION_12, SML_PROTOCOL_SYNCML, loc, loc, "1", 0, &error); smlLocationUnref(loc); SmlAssembler *assm = start_assembler(session, 100); sml_fail_unless(assm != NULL, NULL); sml_fail_unless(!smlAssemblerAddHeader(assm, session, &error), NULL); sml_fail_unless(error != NULL, NULL); smlErrorDeref(&error); char *data = NULL; unsigned int size = 0; sml_fail_unless(!smlAssemblerRun(assm, &data, &size, NULL, TRUE, &error), NULL); sml_fail_unless(error != NULL, NULL); smlErrorDeref(&error); smlAssemblerFree(assm); smlSessionUnref(session); } END_TEST START_TEST (xml_assembler_limit3) { SmlError *error = NULL; SmlLocation *loc = smlLocationNew("/test", NULL, &error); sml_fail_unless(loc != NULL, NULL); sml_fail_unless(error == NULL, NULL); /* The session type must be SML_SESSION_TYPE_CLIENT * because servers of SyncML 1.1 or higher must send MaxMsgSize. */ SmlSession *session = smlSessionNew(SML_SESSION_TYPE_CLIENT, SML_MIMETYPE_XML, SML_VERSION_12, SML_PROTOCOL_SYNCML, loc, loc, "1", 0, &error); SmlAssembler *assm = start_assembler(session, 220); sml_fail_unless(assm != NULL, NULL); sml_fail_unless(smlAssemblerReserveStatus(assm, 1, 1, 1, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlAssemblerAddHeader(assm, session, &error), NULL); sml_fail_unless(error == NULL, NULL); SmlStatus *status = smlStatusNew(SML_NO_ERROR, 1, 1, loc, loc, SML_COMMAND_TYPE_SYNC, &error); sml_fail_unless(status != NULL, NULL); sml_fail_unless(error == NULL, NULL); smlLocationUnref(loc); sml_fail_unless(smlAssemblerAddStatus(assm, status, &error) == SML_ASSEMBLER_RESULT_MISMATCH, NULL); sml_fail_unless(error == NULL, NULL); smlStatusUnref(status); char *data = NULL; unsigned int size = 0; sml_fail_unless(!smlAssemblerRun(assm, &data, &size, NULL, TRUE, &error), NULL); sml_fail_unless(error != NULL, NULL); smlErrorDeref(&error); smlAssemblerFree(assm); smlSessionUnref(session); } END_TEST START_TEST (xml_assembler_limit4) { SmlError *error = NULL; SmlLocation *loc = smlLocationNew("/test", NULL, &error); sml_fail_unless(loc != NULL, NULL); sml_fail_unless(error == NULL, NULL); /* The session type must be SML_SESSION_TYPE_CLIENT * because servers of SyncML 1.1 or higher must send MaxMsgSize. */ SmlSession *session = smlSessionNew(SML_SESSION_TYPE_CLIENT, SML_MIMETYPE_XML, SML_VERSION_12, SML_PROTOCOL_SYNCML, loc, loc, "1", 0, &error); SmlAssembler *assm = start_assembler(session, 380); sml_fail_unless(assm != NULL, NULL); sml_fail_unless(smlAssemblerAddHeader(assm, session, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlAssemblerReserveStatus(assm, 1, 1, 1, &error), NULL); sml_fail_unless(error == NULL, NULL); SmlStatus *status = smlStatusNew(SML_NO_ERROR, 1, 1, loc, loc, SML_COMMAND_TYPE_SYNC, &error); sml_fail_unless(status != NULL, NULL); sml_fail_unless(error == NULL, NULL); smlLocationUnref(loc); sml_fail_unless(smlAssemblerAddStatus(assm, status, &error) == SML_ASSEMBLER_RESULT_OK, NULL); sml_fail_unless(error == NULL, NULL); smlStatusUnref(status); char *data = NULL; unsigned int size = 0; sml_fail_unless(smlAssemblerRun(assm, &data, &size, NULL, TRUE, &error), NULL); sml_fail_unless(error == NULL, NULL); g_free(data); smlAssemblerFree(assm); smlSessionUnref(session); } END_TEST START_TEST (xml_assembler_limit5) { SmlError *error = NULL; SmlLocation *loc = smlLocationNew("/test", NULL, &error); sml_fail_unless(loc != NULL, NULL); sml_fail_unless(error == NULL, NULL); /* The session type must be SML_SESSION_TYPE_CLIENT * because servers of SyncML 1.1 or higher must send MaxMsgSize. */ SmlSession *session = smlSessionNew(SML_SESSION_TYPE_CLIENT, SML_MIMETYPE_XML, SML_VERSION_12, SML_PROTOCOL_SYNCML, loc, loc, "1", 0, &error); SmlAssembler *assm = start_assembler(session, 500); sml_fail_unless(assm != NULL, NULL); sml_fail_unless(smlAssemblerAddHeader(assm, session, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlAssemblerReserveStatus(assm, 1, 1, 1, &error), NULL); sml_fail_unless(error == NULL, NULL); SmlStatus *status = smlStatusNew(SML_NO_ERROR, 1, 1, loc, loc, SML_COMMAND_TYPE_SYNC, &error); sml_fail_unless(status != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlAssemblerAddStatus(assm, status, &error) == SML_ASSEMBLER_RESULT_OK, NULL); sml_fail_unless(error == NULL, NULL); smlStatusUnref(status); SmlCommand *cmd = smlCommandNewAlert(SML_ALERT_TWO_WAY, loc, loc, "next", "last", NULL, &error); sml_fail_unless(cmd != NULL, NULL); sml_fail_unless(error == NULL, NULL); cmd->cmdID = 1; smlLocationUnref(loc); sml_fail_unless(smlAssemblerStartCommand(assm, NULL, cmd, &error) == SML_ASSEMBLER_RESULT_MISMATCH, NULL); sml_fail_unless(error == NULL, NULL); char *data = NULL; unsigned int size = 0; sml_fail_unless(smlAssemblerRun(assm, &data, &size, NULL, FALSE, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(data != NULL, NULL); sml_fail_unless(size != 0, NULL); g_free(data); sml_fail_unless(smlAssemblerFlush(assm) == 1, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlAssemblerStartCommand(assm, NULL, cmd, &error) == SML_ASSEMBLER_RESULT_OK, NULL); sml_fail_unless(error == NULL, NULL); smlCommandUnref(cmd); sml_fail_unless(smlAssemblerEndCommand(assm, NULL, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlAssemblerRun(assm, &data, &size, NULL, TRUE, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(data != NULL, NULL); sml_fail_unless(size != 0, NULL); g_free(data); smlAssemblerFree(assm); smlSessionUnref(session); } END_TEST START_TEST (xml_assembler_devinf) { SmlError *error = NULL; SmlLocation *loc = smlLocationNew("/test", NULL, &error); sml_fail_unless(loc != NULL, NULL); sml_fail_unless(error == NULL, NULL); /* The session type must be SML_SESSION_TYPE_CLIENT * because servers of SyncML 1.1 or higher must send MaxMsgSize. */ SmlSession *session = smlSessionNew(SML_SESSION_TYPE_CLIENT, SML_MIMETYPE_XML, SML_VERSION_12, SML_PROTOCOL_SYNCML, loc, loc, "1", 0, &error); SmlAssembler *assm = start_assembler(session, 0); sml_fail_unless(assm != NULL, NULL); sml_fail_unless(smlAssemblerReserveStatus(assm, 0, 1, 1, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlAssemblerAddHeader(assm, session, &error), NULL); sml_fail_unless(error == NULL, NULL); SmlStatus *status = smlStatusNew(SML_NO_ERROR, 0, 1, loc, loc, SML_COMMAND_TYPE_HEADER, &error); sml_fail_unless(status != NULL, NULL); sml_fail_unless(error == NULL, NULL); smlLocationUnref(loc); sml_fail_unless(smlAssemblerAddStatus(assm, status, &error) == SML_ASSEMBLER_RESULT_OK, NULL); sml_fail_unless(error == NULL, NULL); smlStatusUnref(status); SmlDevInf *devinf = smlDevInfNew("mydevice", SML_DEVINF_DEVTYPE_WORKSTATION, &error); sml_fail_unless(devinf != NULL, NULL); sml_fail_unless(error == NULL, NULL); SmlCommand *cmd = smlDevInfNewPut(devinf, SML_DEVINF_VERSION_11, &error); sml_fail_unless(cmd != NULL, NULL); sml_fail_unless(error == NULL, NULL); cmd->cmdID = 1; smlDevInfUnref(devinf); sml_fail_unless(smlAssemblerStartCommand(assm, NULL, cmd, &error) == SML_ASSEMBLER_RESULT_OK, NULL); sml_fail_unless(error == NULL, NULL); smlCommandUnref(cmd); sml_fail_unless(smlAssemblerEndCommand(assm, NULL, &error), NULL); sml_fail_unless(error == NULL, NULL); char *data = NULL; unsigned int size = 0; sml_fail_unless(smlAssemblerRun(assm, &data, &size, NULL, FALSE, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(data != NULL, NULL); sml_fail_unless(size != 0, NULL); g_free(data); sml_fail_unless(smlAssemblerFlush(assm) == 1, NULL); sml_fail_unless(error == NULL, NULL); smlAssemblerFree(assm); smlSessionUnref(session); } END_TEST START_TEST (xml_assembler_devinf12) { SmlError *error = NULL; SmlLocation *loc = smlLocationNew("/test", NULL, &error); sml_fail_unless(loc != NULL, NULL); sml_fail_unless(error == NULL, NULL); /* The session type must be SML_SESSION_TYPE_CLIENT * because servers of SyncML 1.1 or higher must send MaxMsgSize. */ SmlSession *session = smlSessionNew(SML_SESSION_TYPE_CLIENT, SML_MIMETYPE_XML, SML_VERSION_12, SML_PROTOCOL_SYNCML, loc, loc, "1", 0, &error); SmlAssembler *assm = start_assembler(session, 0); sml_fail_unless(assm != NULL, NULL); sml_fail_unless(smlAssemblerReserveStatus(assm, 0, 1, 1, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlAssemblerAddHeader(assm, session, &error), NULL); sml_fail_unless(error == NULL, NULL); SmlStatus *status = smlStatusNew(SML_NO_ERROR, 0, 1, loc, loc, SML_COMMAND_TYPE_HEADER, &error); sml_fail_unless(status != NULL, NULL); sml_fail_unless(error == NULL, NULL); smlLocationUnref(loc); sml_fail_unless(smlAssemblerAddStatus(assm, status, &error) == SML_ASSEMBLER_RESULT_OK, NULL); sml_fail_unless(error == NULL, NULL); smlStatusUnref(status); SmlDevInf *devinf = smlDevInfNew("mydevice", SML_DEVINF_DEVTYPE_WORKSTATION, &error); sml_fail_unless(devinf != NULL, NULL); sml_fail_unless(error == NULL, NULL); SmlCommand *cmd = smlDevInfNewPut(devinf, SML_DEVINF_VERSION_12, &error); sml_fail_unless(cmd != NULL, NULL); sml_fail_unless(error == NULL, NULL); cmd->cmdID = 1; smlDevInfUnref(devinf); sml_fail_unless(smlAssemblerStartCommand(assm, NULL, cmd, &error) == SML_ASSEMBLER_RESULT_OK, NULL); sml_fail_unless(error == NULL, NULL); smlCommandUnref(cmd); sml_fail_unless(smlAssemblerEndCommand(assm, NULL, &error), NULL); sml_fail_unless(error == NULL, NULL); char *data = NULL; unsigned int size = 0; sml_fail_unless(smlAssemblerRun(assm, &data, &size, NULL, FALSE, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(data != NULL, NULL); sml_fail_unless(size != 0, NULL); g_free(data); sml_fail_unless(smlAssemblerFlush(assm) == 1, NULL); sml_fail_unless(error == NULL, NULL); smlAssemblerFree(assm); smlSessionUnref(session); } END_TEST START_TEST (xml_assembler_order) { SmlError *error = NULL; SmlLocation *loc = smlLocationNew("/test", NULL, &error); sml_fail_unless(loc != NULL, NULL); sml_fail_unless(error == NULL, NULL); /* The session type must be SML_SESSION_TYPE_CLIENT * because servers of SyncML 1.1 or higher must send MaxMsgSize. */ SmlSession *session = smlSessionNew(SML_SESSION_TYPE_CLIENT, SML_MIMETYPE_XML, SML_VERSION_12, SML_PROTOCOL_SYNCML, loc, loc, "1", 0, &error); SmlAssembler *assm = start_assembler(session, 0); sml_fail_unless(assm != NULL, NULL); sml_fail_unless(smlAssemblerAddHeader(assm, session, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlAssemblerReserveStatus(assm, 0, 1, 1, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlAssemblerReserveStatus(assm, 1, 1, 2, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlAssemblerReserveStatus(assm, 2, 1, 3, &error), NULL); sml_fail_unless(error == NULL, NULL); SmlStatus *status = smlStatusNew(SML_NO_ERROR, 2, 1, loc, loc, SML_COMMAND_TYPE_PUT, &error); sml_fail_unless(status != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlAssemblerAddStatus(assm, status, &error) == SML_ASSEMBLER_RESULT_OK, NULL); sml_fail_unless(error == NULL, NULL); smlStatusUnref(status); status = smlStatusNew(SML_NO_ERROR, 1, 1, loc, loc, SML_COMMAND_TYPE_SYNC, &error); sml_fail_unless(status != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlAssemblerAddStatus(assm, status, &error) == SML_ASSEMBLER_RESULT_OK, NULL); sml_fail_unless(error == NULL, NULL); smlStatusUnref(status); status = smlStatusNew(SML_NO_ERROR, 0, 1, loc, loc, SML_COMMAND_TYPE_HEADER, &error); sml_fail_unless(status != NULL, NULL); sml_fail_unless(error == NULL, NULL); smlLocationUnref(loc); sml_fail_unless(smlAssemblerAddStatus(assm, status, &error) == SML_ASSEMBLER_RESULT_OK, NULL); sml_fail_unless(error == NULL, NULL); smlStatusUnref(status); char *data = NULL; unsigned int size = 0; sml_fail_unless(smlAssemblerRun(assm, &data, &size, NULL, FALSE, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(data != NULL, NULL); sml_fail_unless(size != 0, NULL); smlAssemblerFree(assm); smlSessionUnref(session); SmlParser *parser = start_parser(data, &error); sml_fail_unless(parser != NULL, "%s", smlErrorPrint(&error)); SmlHeader *header = NULL; SmlCred *cred = NULL; sml_fail_unless(smlParserGetHeader(parser, &header, &cred, &error), NULL); sml_fail_unless(header != NULL, NULL); sml_fail_unless(cred == NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(header->messageID == 1, NULL); smlHeaderFree(header); sml_fail_unless(smlParserGetStatus(parser, &status, &error), NULL); sml_fail_unless(status != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(status->type == SML_COMMAND_TYPE_HEADER, NULL); smlStatusUnref(status); sml_fail_unless(smlParserGetStatus(parser, &status, &error), NULL); sml_fail_unless(status != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(status->type == SML_COMMAND_TYPE_SYNC, NULL); smlStatusUnref(status); sml_fail_unless(smlParserGetStatus(parser, &status, &error), NULL); sml_fail_unless(status != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(status->type == SML_COMMAND_TYPE_PUT, NULL); smlStatusUnref(status); sml_fail_unless(smlParserGetStatus(parser, &status, &error), NULL); sml_fail_unless(status == NULL, NULL); sml_fail_unless(error == NULL, NULL); SmlBool final = TRUE; SmlBool end = TRUE; sml_fail_unless(smlParserEnd(parser, &final, &end, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(final == FALSE, NULL); sml_fail_unless(end == FALSE, NULL); smlParserFree(parser); g_free(data); } END_TEST /* - Reserve 3 statuses * - Add one status * - Should report missing statuses * - Run(final) -> error since statuses are missing * - Run(not final) & Flush -> data should have one status * - Should report missing statuses * - Add 2 remaining statuses * - Should not report missing statuses * - Run & Flush -> data should have the 2 remaining statuses */ START_TEST (xml_assembler_reuse) { SmlError *error = NULL; SmlLocation *loc = smlLocationNew("/test", NULL, &error); sml_fail_unless(loc != NULL, NULL); sml_fail_unless(error == NULL, NULL); /* The session type must be SML_SESSION_TYPE_CLIENT * because servers of SyncML 1.1 or higher must send MaxMsgSize. */ SmlSession *session = smlSessionNew(SML_SESSION_TYPE_CLIENT, SML_MIMETYPE_XML, SML_VERSION_12, SML_PROTOCOL_SYNCML, loc, loc, "1", 0, &error); SmlAssembler *assm = start_assembler(session, 0); sml_fail_unless(assm != NULL, NULL); sml_fail_unless(smlAssemblerAddHeader(assm, session, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlAssemblerIsStatusMissing(assm) == FALSE, NULL); sml_fail_unless(smlAssemblerReserveStatus(assm, 0, 1, 1, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlAssemblerReserveStatus(assm, 1, 1, 2, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlAssemblerReserveStatus(assm, 2, 1, 3, &error), NULL); sml_fail_unless(error == NULL, NULL); SmlStatus *status = smlStatusNew(SML_NO_ERROR, 0, 1, loc, loc, SML_COMMAND_TYPE_HEADER, &error); sml_fail_unless(status != NULL, NULL); sml_fail_unless(error == NULL, NULL); char *data = NULL; unsigned int size = 0; /* Must fail since nothing has been added at all */ sml_fail_unless(!smlAssemblerRun(assm, &data, &size, NULL, FALSE, &error), NULL); sml_fail_unless(error != NULL, NULL); sml_fail_unless(data == NULL, NULL); sml_fail_unless(size == 0, NULL); smlErrorDeref(&error); sml_fail_unless(smlAssemblerAddStatus(assm, status, &error) == SML_ASSEMBLER_RESULT_OK, NULL); sml_fail_unless(error == NULL, NULL); smlStatusUnref(status); sml_fail_unless(smlAssemblerIsStatusMissing(assm) == TRUE, NULL); /* Must fail since not all statuses have been added */ sml_fail_unless(!smlAssemblerRun(assm, &data, &size, NULL, TRUE, &error), NULL); sml_fail_unless(error != NULL, NULL); sml_fail_unless(data == NULL, NULL); sml_fail_unless(size == 0, NULL); smlErrorDeref(&error); /* Must work */ sml_fail_unless(smlAssemblerRun(assm, &data, &size, NULL, FALSE, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(data != NULL, NULL); sml_fail_unless(size != 0, NULL); sml_fail_unless(smlAssemblerFlush(assm) == 3, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlAssemblerAddHeader(assm, session, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlAssemblerIsStatusMissing(assm) == TRUE, NULL); SmlParser *parser = start_parser(data, &error); sml_fail_unless(parser != NULL, "%s", smlErrorPrint(&error)); SmlHeader *header = NULL; SmlCred *cred = NULL; sml_fail_unless(smlParserGetHeader(parser, &header, &cred, &error), NULL); sml_fail_unless(header != NULL, NULL); sml_fail_unless(cred == NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(header->messageID == 1, NULL); smlHeaderFree(header); sml_fail_unless(smlParserGetStatus(parser, &status, &error), NULL); sml_fail_unless(status != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(status->type == SML_COMMAND_TYPE_HEADER, NULL); smlStatusUnref(status); sml_fail_unless(smlParserGetStatus(parser, &status, &error), NULL); sml_fail_unless(status == NULL, NULL); sml_fail_unless(error == NULL, NULL); SmlBool final = TRUE; SmlBool end = TRUE; sml_fail_unless(smlParserEnd(parser, &final, &end, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(final == FALSE, NULL); sml_fail_unless(end == FALSE, NULL); smlParserFree(parser); g_free(data); status = smlStatusNew(SML_NO_ERROR, 1, 1, loc, loc, SML_COMMAND_TYPE_SYNC, &error); sml_fail_unless(status != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlAssemblerAddStatus(assm, status, &error) == SML_ASSEMBLER_RESULT_OK, NULL); sml_fail_unless(error == NULL, NULL); smlStatusUnref(status); status = smlStatusNew(SML_NO_ERROR, 2, 1, loc, loc, SML_COMMAND_TYPE_PUT, &error); sml_fail_unless(status != NULL, NULL); sml_fail_unless(error == NULL, NULL); smlLocationUnref(loc); sml_fail_unless(smlAssemblerAddStatus(assm, status, &error) == SML_ASSEMBLER_RESULT_OK, NULL); sml_fail_unless(error == NULL, NULL); smlStatusUnref(status); sml_fail_unless(smlAssemblerIsStatusMissing(assm) == FALSE, NULL); data = NULL; size = 0; sml_fail_unless(smlAssemblerRun(assm, &data, &size, NULL, TRUE, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(data != NULL, NULL); sml_fail_unless(size != 0, NULL); smlAssemblerFree(assm); smlSessionUnref(session); parser = start_parser(data, &error); sml_fail_unless(parser != NULL, "%s", smlErrorPrint(&error)); header = NULL; sml_fail_unless(smlParserGetHeader(parser, &header, &cred, &error), NULL); sml_fail_unless(header != NULL, NULL); sml_fail_unless(cred == NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(header->messageID == 1, NULL); smlHeaderFree(header); sml_fail_unless(smlParserGetStatus(parser, &status, &error), NULL); sml_fail_unless(status != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(status->type == SML_COMMAND_TYPE_SYNC, NULL); smlStatusUnref(status); sml_fail_unless(smlParserGetStatus(parser, &status, &error), NULL); sml_fail_unless(status != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(status->type == SML_COMMAND_TYPE_PUT, NULL); smlStatusUnref(status); sml_fail_unless(smlParserGetStatus(parser, &status, &error), NULL); sml_fail_unless(status == NULL, NULL); sml_fail_unless(error == NULL, NULL); final = TRUE; end = TRUE; sml_fail_unless(smlParserEnd(parser, &final, &end, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(final == TRUE, NULL); sml_fail_unless(end == TRUE, NULL); smlParserFree(parser); g_free(data); } END_TEST START_TEST (xml_assembler_leak) { SmlError *error = NULL; SmlLocation *loc = smlLocationNew("/test", NULL, &error); sml_fail_unless(loc != NULL, NULL); sml_fail_unless(error == NULL, NULL); /* The session type must be SML_SESSION_TYPE_CLIENT * because servers of SyncML 1.1 or higher must send MaxMsgSize. */ SmlSession *session = smlSessionNew(SML_SESSION_TYPE_CLIENT, SML_MIMETYPE_XML, SML_VERSION_12, SML_PROTOCOL_SYNCML, loc, loc, "1", 0, &error); SmlAssembler *assm = start_assembler(session, 0); sml_fail_unless(assm != NULL, NULL); sml_fail_unless(smlAssemblerAddHeader(assm, session, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlAssemblerReserveStatus(assm, 0, 1, 1, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlAssemblerReserveStatus(assm, 1, 1, 2, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlAssemblerReserveStatus(assm, 2, 1, 3, &error), NULL); sml_fail_unless(error == NULL, NULL); char *data = NULL; unsigned int size = 0; /* Must fail since nothing has been added at all */ sml_fail_unless(!smlAssemblerRun(assm, &data, &size, NULL, FALSE, &error), NULL); sml_fail_unless(error != NULL, NULL); sml_fail_unless(data == NULL, NULL); sml_fail_unless(size == 0, NULL); smlErrorDeref(&error); sml_fail_unless(smlAssemblerFlush(assm) == 4, NULL); sml_fail_unless(error == NULL, NULL); smlAssemblerFree(assm); assm = start_assembler(session, 0); sml_fail_unless(assm != NULL, NULL); sml_fail_unless(smlAssemblerAddHeader(assm, session, &error), NULL); sml_fail_unless(error == NULL, NULL); SmlStatus *status = smlStatusNew(SML_NO_ERROR, 0, 1, loc, loc, SML_COMMAND_TYPE_HEADER, &error); sml_fail_unless(status != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlAssemblerAddStatus(assm, status, &error) != SML_ASSEMBLER_RESULT_OK, NULL); sml_fail_unless(error != NULL, NULL); smlErrorDeref(&error); smlStatusUnref(status); /* Must fail since not all statuses have been added */ sml_fail_unless(!smlAssemblerRun(assm, &data, &size, NULL, TRUE, &error), NULL); sml_fail_unless(error != NULL, NULL); sml_fail_unless(data == NULL, NULL); sml_fail_unless(size == 0, NULL); smlErrorDeref(&error); sml_fail_unless(smlAssemblerFlush(assm) == 1, NULL); sml_fail_unless(error == NULL, NULL); smlAssemblerFree(assm); assm = start_assembler(session, 0); sml_fail_unless(assm != NULL, NULL); sml_fail_unless(smlAssemblerAddHeader(assm, session, &error), NULL); sml_fail_unless(error == NULL, NULL); SmlCommand *cmd2 = smlCommandNewChange(SML_CHANGE_ADD, "change1sync1", "data", 5, SML_ELEMENT_TEXT_VCARD, &error); cmd2->cmdID = 2; sml_fail_unless(smlAssemblerStartCommand(assm, NULL, cmd2, &error), NULL); sml_fail_unless(error == NULL, NULL); smlCommandUnref(cmd2); /* Must fail since not all statuses have been added */ sml_fail_unless(smlAssemblerRun(assm, &data, &size, NULL, TRUE, &error), NULL); sml_fail_unless(error== NULL, NULL); sml_fail_unless(data != NULL, NULL); sml_fail_unless(size != 0, NULL); g_free(data); sml_fail_unless(smlAssemblerFlush(assm) == 1, NULL); sml_fail_unless(error == NULL, NULL); smlLocationUnref(loc); smlAssemblerFree(assm); smlSessionUnref(session); } END_TEST START_TEST (xml_assembler_stress) { int num_cmd = 1000; int num_status = 1000; SmlError *error = NULL; SmlLocation *loc = smlLocationNew("/test", NULL, &error); sml_fail_unless(loc != NULL, NULL); sml_fail_unless(error == NULL, NULL); /* The session type must be SML_SESSION_TYPE_CLIENT * because servers of SyncML 1.1 or higher must send MaxMsgSize. */ SmlSession *session = smlSessionNew(SML_SESSION_TYPE_CLIENT, SML_MIMETYPE_XML, SML_VERSION_12, SML_PROTOCOL_SYNCML, loc, loc, "1", 0, &error); SmlAssembler *assm = start_assembler(session, 0); sml_fail_unless(assm != NULL, NULL); sml_fail_unless(smlAssemblerAddHeader(assm, session, &error), NULL); sml_fail_unless(error == NULL, NULL); int i = 0; for (i = 0; i < num_status; i++) { sml_fail_unless(smlAssemblerReserveStatus(assm, i + 1, 1, 1, &error), NULL); sml_fail_unless(error == NULL, NULL); SmlStatus *status = smlStatusNew(SML_NO_ERROR, i + 1, 1, loc, loc, SML_COMMAND_TYPE_SYNC, &error); sml_fail_unless(status != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlAssemblerAddStatus(assm, status, &error), NULL); sml_fail_unless(error == NULL, NULL); smlStatusUnref(status); } for (i = 0; i < num_cmd; i++) { SmlCommand *cmd1 = smlCommandNewSync(loc, loc, 0, &error); sml_fail_unless(cmd1 != NULL, NULL); sml_fail_unless(error == NULL, NULL); cmd1->cmdID = i + 1 + num_status; sml_fail_unless(smlAssemblerStartCommand(assm, NULL, cmd1, &error), NULL); sml_fail_unless(error == NULL, NULL); smlCommandUnref(cmd1); sml_fail_unless(smlAssemblerEndCommand(assm, NULL, &error), NULL); sml_fail_unless(error == NULL, NULL); } char *data = NULL; unsigned int size = 0; sml_fail_unless(smlAssemblerRun(assm, &data, &size, NULL, TRUE, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(data != NULL, NULL); sml_fail_unless(size != 0, NULL); g_free(data); sml_fail_unless(smlAssemblerFlush(assm) == 1, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(!smlAssemblerRun(assm, &data, &size, NULL, TRUE, &error), NULL); sml_fail_unless(error != NULL, NULL); smlErrorDeref(&error); smlLocationUnref(loc); smlAssemblerFree(assm); smlSessionUnref(session); } END_TEST START_TEST (xml_assembler_stress_limit) { int num_cmd = 1000; int num_status = 1000; int limit = 50000; SmlError *error = NULL; SmlLocation *loc = smlLocationNew("/test", NULL, &error); sml_fail_unless(loc != NULL, NULL); sml_fail_unless(error == NULL, NULL); /* The session type must be SML_SESSION_TYPE_CLIENT * because servers of SyncML 1.1 or higher must send MaxMsgSize. */ SmlSession *session = smlSessionNew(SML_SESSION_TYPE_CLIENT, SML_MIMETYPE_XML, SML_VERSION_12, SML_PROTOCOL_SYNCML, loc, loc, "1", 0, &error); SmlAssembler *assm = start_assembler(session, limit); sml_fail_unless(assm != NULL, NULL); sml_fail_unless(smlAssemblerAddHeader(assm, session, &error), NULL); sml_fail_unless(error == NULL, NULL); int i = 0; for (i = 0; i < num_status; i++) { sml_fail_unless(smlAssemblerReserveStatus(assm, i + 1, 1, 1, &error), NULL); sml_fail_unless(error == NULL, NULL); SmlStatus *status = smlStatusNew(SML_NO_ERROR, i + 1, 1, loc, loc, SML_COMMAND_TYPE_SYNC, &error); sml_fail_unless(status != NULL, NULL); sml_fail_unless(error == NULL, NULL); SmlAssemblerResult res = smlAssemblerAddStatus(assm, status, &error); if (res == SML_ASSEMBLER_RESULT_MISMATCH) { char *data = NULL; unsigned int size = 0; sml_fail_unless(smlAssemblerRun(assm, &data, &size, NULL, FALSE, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(data != NULL, NULL); sml_fail_unless(size != 0, NULL); g_free(data); smlAssemblerFlush(assm); sml_fail_unless(smlAssemblerAddStatus(assm, status, &error) == SML_ASSEMBLER_RESULT_OK, NULL); sml_fail_unless(error == NULL, NULL); } else if (res != SML_ASSEMBLER_RESULT_OK) { sml_fail_unless(FALSE, "%s", smlErrorPrint(&error)); } smlStatusUnref(status); } for (i = 0; i < num_cmd; i++) { SmlCommand *cmd1 = smlCommandNewSync(loc, loc, 0, &error); sml_fail_unless(cmd1 != NULL, NULL); sml_fail_unless(error == NULL, NULL); cmd1->cmdID = i + 1 + num_status; SmlAssemblerResult res = smlAssemblerStartCommand(assm, NULL, cmd1, &error); if (res == SML_ASSEMBLER_RESULT_MISMATCH) { char *data = NULL; unsigned int size = 0; sml_fail_unless(smlAssemblerRun(assm, &data, &size, NULL, FALSE, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(data != NULL, NULL); sml_fail_unless(size != 0, NULL); g_free(data); sml_fail_unless(smlAssemblerFlush(assm) == 1, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlAssemblerStartCommand(assm, NULL, cmd1, &error), NULL); sml_fail_unless(error == NULL, NULL); } else if (res != SML_ASSEMBLER_RESULT_OK) { sml_fail_unless(FALSE, "%s", smlErrorPrint(&error)); } smlCommandUnref(cmd1); sml_fail_unless(smlAssemblerEndCommand(assm, NULL, &error), NULL); sml_fail_unless(error == NULL, NULL); } char *data = NULL; unsigned int size = 0; sml_fail_unless(smlAssemblerRun(assm, &data, &size, NULL, TRUE, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(data != NULL, NULL); sml_fail_unless(size != 0, NULL); g_free(data); sml_fail_unless(smlAssemblerFlush(assm) == 1, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(!smlAssemblerRun(assm, &data, &size, NULL, TRUE, &error), NULL); sml_fail_unless(error != NULL, NULL); smlErrorDeref(&error); smlLocationUnref(loc); smlAssemblerFree(assm); smlSessionUnref(session); } END_TEST START_TEST (xml_assembler_stress_large_limit) { int num_cmd = 1000; int num_status = 1000; int limit = 500000000; SmlError *error = NULL; SmlLocation *loc = smlLocationNew("/test", NULL, &error); sml_fail_unless(loc != NULL, NULL); sml_fail_unless(error == NULL, NULL); /* The session type must be SML_SESSION_TYPE_CLIENT * because servers of SyncML 1.1 or higher must send MaxMsgSize. */ SmlSession *session = smlSessionNew(SML_SESSION_TYPE_CLIENT, SML_MIMETYPE_XML, SML_VERSION_12, SML_PROTOCOL_SYNCML, loc, loc, "1", 0, &error); SmlAssembler *assm = start_assembler(session, limit); sml_fail_unless(assm != NULL, NULL); sml_fail_unless(smlAssemblerAddHeader(assm, session, &error), NULL); sml_fail_unless(error == NULL, NULL); int i = 0; for (i = 0; i < num_status; i++) { sml_fail_unless(smlAssemblerReserveStatus(assm, i + 1, 1, 1, &error), NULL); sml_fail_unless(error == NULL, NULL); SmlStatus *status = smlStatusNew(SML_NO_ERROR, i + 1, 1, loc, loc, SML_COMMAND_TYPE_SYNC, &error); sml_fail_unless(status != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlAssemblerAddStatus(assm, status, &error) == SML_ASSEMBLER_RESULT_OK, NULL); sml_fail_unless(error == NULL, NULL); smlStatusUnref(status); } for (i = 0; i < num_cmd; i++) { SmlCommand *cmd1 = smlCommandNewSync(loc, loc, 0, &error); sml_fail_unless(cmd1 != NULL, NULL); sml_fail_unless(error == NULL, NULL); cmd1->cmdID = i + 1 + num_status; sml_fail_unless(smlAssemblerStartCommand(assm, NULL, cmd1, &error) == SML_ASSEMBLER_RESULT_OK, NULL); sml_fail_unless(error == NULL, NULL); smlCommandUnref(cmd1); sml_fail_unless(smlAssemblerEndCommand(assm, NULL, &error), NULL); sml_fail_unless(error == NULL, NULL); } char *data = NULL; unsigned int size = 0; sml_fail_unless(smlAssemblerRun(assm, &data, &size, NULL, TRUE, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(data != NULL, NULL); sml_fail_unless(size != 0, NULL); g_free(data); sml_fail_unless(smlAssemblerFlush(assm) == 1, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(!smlAssemblerRun(assm, &data, &size, NULL, TRUE, &error), NULL); sml_fail_unless(error != NULL, NULL); smlErrorDeref(&error); smlLocationUnref(loc); smlAssemblerFree(assm); smlSessionUnref(session); } END_TEST START_TEST (xml_assembler_large_obj) { int limit = 500000; SmlError *error = NULL; SmlLocation *loc = smlLocationNew("/test", NULL, &error); sml_fail_unless(loc != NULL, NULL); sml_fail_unless(error == NULL, NULL); /* The session type must be SML_SESSION_TYPE_CLIENT * because servers of SyncML 1.1 or higher must send MaxMsgSize. */ SmlSession *session = smlSessionNew(SML_SESSION_TYPE_CLIENT, SML_MIMETYPE_XML, SML_VERSION_12, SML_PROTOCOL_SYNCML, loc, loc, "1", 0, &error); SmlAssembler *assm = start_assembler(session, limit); sml_fail_unless(assm != NULL, NULL); sml_fail_unless(smlAssemblerAddHeader(assm, session, &error), NULL); sml_fail_unless(error == NULL, NULL); SmlCommand *cmd1 = smlCommandNewSync(loc, loc, 0, &error); sml_fail_unless(cmd1 != NULL, NULL); sml_fail_unless(error == NULL, NULL); cmd1->cmdID = 1; smlAssemblerStartCommand(assm, NULL, cmd1, &error); SmlCommand *cmd2 = smlCommandNewChange(SML_CHANGE_ADD, "uid", "data", 5, SML_ELEMENT_TEXT_VCARD, &error); sml_fail_unless(cmd2 != NULL, NULL); sml_fail_unless(error == NULL, NULL); cmd2->cmdID = 2; sml_fail_unless(smlAssemblerStartCommand(assm, cmd1, cmd2, &error), NULL); sml_fail_unless(error == NULL, NULL); smlCommandUnref(cmd2); sml_fail_unless(smlAssemblerEndCommand(assm, cmd1, &error), NULL); sml_fail_unless(error == NULL, NULL); cmd2 = smlCommandNewPartialChange(SML_CHANGE_ADD, "uid", "data", 200, 5, SML_ELEMENT_TEXT_VCARD, &error); sml_fail_unless(cmd2 != NULL, NULL); sml_fail_unless(error == NULL, NULL); cmd2->cmdID = 2; sml_fail_unless(smlAssemblerStartCommand(assm, cmd1, cmd2, &error), NULL); sml_fail_unless(error == NULL, NULL); smlCommandUnref(cmd2); sml_fail_unless(smlAssemblerEndCommand(assm, cmd1, &error), NULL); sml_fail_unless(error == NULL, NULL); cmd2 = smlCommandNewChange(SML_CHANGE_ADD, "uid", "data", 5, SML_ELEMENT_TEXT_VCARD, &error); sml_fail_unless(cmd2 != NULL, NULL); sml_fail_unless(error == NULL, NULL); cmd2->cmdID = 2; sml_fail_unless(!smlAssemblerStartCommand(assm, cmd1, cmd2, &error), NULL); sml_fail_unless(error != NULL, NULL); smlErrorDeref(&error); smlCommandUnref(cmd2); sml_fail_unless(smlAssemblerEndCommand(assm, cmd1, &error), NULL); sml_fail_unless(error == NULL, NULL); smlCommandUnref(cmd1); sml_fail_unless(smlAssemblerEndCommand(assm, NULL, &error), NULL); sml_fail_unless(error == NULL, NULL); char *data = NULL; unsigned int size = 0; sml_fail_unless(smlAssemblerRun(assm, &data, &size, NULL, TRUE, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(data != NULL, NULL); sml_fail_unless(size != 0, NULL); g_free(data); sml_fail_unless(smlAssemblerFlush(assm) == 1, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(!smlAssemblerRun(assm, &data, &size, NULL, TRUE, &error), NULL); sml_fail_unless(error != NULL, NULL); smlErrorDeref(&error); smlLocationUnref(loc); smlAssemblerFree(assm); smlSessionUnref(session); } END_TEST @SML_TESTCASE_CODE@ libsyncml-0.5.4/tests/mobiles/nokia_9500_vcard/sent-1.xml100644 1750 1750 13137 11211710410 23030 0ustar00bellmichbellmich 1.1SyncML/1.12232IMEI:123456789012345PC Suite10000 110SyncHdrPC SuiteIMEI:123456789012345200 213Alert./Contacts./C\System\Data\Contacts.cdb50820080905T111459Z 3201./C\System\Data\Contacts.cdb./Contacts20080905T112020Z 4application/vnd.syncml-devinf+xml./devinf111.1OpenSynclibsyncmlLinux2.6.25-2-6860.4.7PC Suiteserver./Contactstext/x-vcard2.1text/vcard3.0text/x-vcard2.1text/vcard3.0127text/x-vcardADRTYPEHOMEWORKPARCELPOSTALINTLDOMHOMEWORKPARCELPOSTALINTLDOMAGENTBDAYBEGINVCARDENDVCARDEMAILTYPEINTERNETINTERNETFNGEOKEYTYPEX509PGPX509PGPLABELTYPEHOMEWORKPARCELPOSTALINTLDOMHOMEWORKPARCELPOSTALINTLDOMLOGOTYPEJPEGJPEGMAILERNNOTEORGPHOTOTYPEJPEGJPEGREVROLESOUNDTYPEAIFFPCMWAVEAIFFPCMWAVETELTYPEWORKVOICEPREFPAGERMSGMODEMISDNHOMEFAXCELLCARBBSWORKVOICEPREFPAGERMSGMODEMISDNHOMEFAXCELLCARBBSTITLETZUIDURLTYPEWORKHOMEWORKHOMEVERSION2.1text/vcardBEGINVCARDENDVCARDVERSION3.0REVNTITLECATEGORIESCLASSORGEMAILURLTELTYPECELLHOMEWORKFAXMODEMVOICEADRTYPEHOMEWORKBDAYNOTEPHOTOTYPE 5application/vnd.syncml-devinf+xml./devinf11 libsyncml-0.5.4/tests/mobiles/nokia_9500_vcard/sent-2.wbxml100644 1750 1750 751 11211710410 23320 0ustar00bellmichbellmichŸSjmlq1.1rSyncML/1.1e223[3nWIMEI:123456789012345gWPC SuiteZL10000kiK1\2L0JSyncHdroPC SuitehIMEI:123456789012345O200iK7\2L5JResultsh./devinf11O200iK8\2L6JSynco./Contactsh./C\System\Data\Contacts.cdbO200iK9\2L7JAddh4O201iK10\2L8JAddh8O201iK11\2L9JAddh18O201jK12nW./C\System\Data\Contacts.cdbgW./ContactsZU1024000s0libsyncml-0.5.4/tests/mobiles/nokia_9500_vcard/sent-3.wbxml100644 1750 1750 253 11211710410 23316 0ustar00bellmichbellmichŸSjmlq1.1rSyncML/1.1e223[4nWIMEI:123456789012345gWPC SuiteZL10000kiK1\3L0JSyncHdroPC SuitehIMEI:123456789012345O200libsyncml-0.5.4/tests/mobiles/nokia_9500_vcard/received-0.xml100644 1750 1750 2034 11211710410 23616 0ustar00bellmichbellmich1.1SyncML/1.12231PC SuiteIMEI:12345678901234510000110SyncHdr/PC Suite200211Alert./Contacts2003200./Contacts./C\System\Data\Contacts.cdb20080905T091440Z20080905T111459Zlibsyncml-0.5.4/tests/mobiles/nokia_9500_vcard/received-2.xml100644 1750 1750 1516 11211710410 23624 0ustar00bellmichbellmich1.1SyncML/1.12233PC SuiteIMEI:12345678901234510000130SyncHdrIMEI:123456789012345PC Suite2002312Sync./C\System\Data\Contacts.cdb./Contacts200libsyncml-0.5.4/tests/mobiles/nokia_9500_vcard/received-2.wbxml100644 1750 1750 372 11211710410 24134 0ustar00bellmichbellmichŸSjmlqÃ1.1rà SyncML/1.1eÃ223[Ã3nWÃPC SuitegWÃIMEI:123456789012345ZLÃ10000kiKÃ1\Ã3LÃ0JÃSyncHdroÃIMEI:123456789012345hÃPC SuiteOÃ200iKÃ2\Ã3LÃ12JÃSyncoÃ./C\System\Data\Contacts.cdbhà ./ContactsOÃ200libsyncml-0.5.4/tests/mobiles/nokia_9500_vcard/received-1.wbxml100644 1750 1750 3357 11211710410 24161 0ustar00bellmichbellmichŸSjmlqÃ1.1rà SyncML/1.1eÃ223[Ã2nWÃPC SuitegWÃIMEI:123456789012345ZLÃ10000kiKÃ1\Ã2LÃ0JÃSyncHdroÃIMEI:123456789012345hÃPC SuiteOÃ200iKÃ2\Ã2LÃ3JÃAlertoÃ./C\System\Data\Contacts.cdbhà ./ContactsOÃ200TOEOÃ20080905T112020ZiKÃ3\Ã2LÃ4JÃPutOÃ200iKÃ4\Ã2LÃ5JÃGetOÃ200bKÃ5\Ã2LÃ5ZSÃ#application/vnd.syncml-devinf+wbxmlTgWà ./devinf11OÃ…zŸTjJeÃ1.1QÃNOKIAUÃ9500^à 05.22(01)IÃIMEI:123456789012345KÃphone(*)G]Ã./C\System\Data\Contacts.cdbRÃ8ZFà text/x-vcarddÃ2.1YFà text/vcarddÃ3.0bFà text/x-vcarddÃ2.1_`Ã1`Ã2`Ã3`Ã4`Ã5`Ã6`Ã7EFà text/x-vcardXÃBEGINcÃVCARDXÃENDcÃVCARDXÃVERSIONcÃ2.1XÃREVXÃNXÃADRWÃHOMEWÃWORKXÃTELWÃHOMEWÃWORKWÃCELLWÃPAGERWÃFAXWÃVOICEXÃFNXÃEMAILWÃINTERNETWÃHOMEWÃWORKXÃURLWÃHOMEWÃWORKXÃNOTEXÃTITLEXÃORGXÃPHOTOXÃBDAYFà text/vcardXÃBEGINcÃVCARDXÃENDcÃVCARDXÃVERSIONcÃ3.0XÃREVXÃNXÃADRWÃHOMEWÃWORKXÃTELWÃHOMEWÃWORKWÃCELLWÃPAGERWÃFAXWÃVOICEXÃFNXÃEMAILWÃINTERNETWÃHOMEWÃWORKXÃURLWÃHOMEWÃWORKXÃNOTEXÃTITLEXÃORGXÃPHOTOXÃBDAYjKÃ6nWà ./ContactsgWÃ./C\System\Data\Contacts.cdbZUÃ786432sÃ3EKÃ7ZSà text/x-vcardTgWÃ4OÃRBEGIN:VCARD VERSION:2.1 REV:20080616T114328Z N:testuser;Michael;;; END:VCARD EKÃ8ZSà text/x-vcardTgWÃ8OÃRBEGIN:VCARD VERSION:2.1 REV:20080619T073500Z N:Testnach;Testvor;;; END:VCARD EKÃ9ZSà text/x-vcardTgWÃ18OÃXBEGIN:VCARD VERSION:2.1 REV:20080905T070149Z N:Doe;Jon;Henry;Prof. Dr.-Ing.;add-on ORG:Company; TITLE:position BDAY:20080905 NOTE:some extra note like, he is a nice guy URL:http://www.some.domain END:VCARD libsyncml-0.5.4/tests/mobiles/nokia_9500_vcard/test.c100644 1750 1750 3426 11211710410 22302 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2008 Michael Bell * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ /** Test environment: * * Single address book sync: * syncml-ds-tool * -b 00:00:00:00:00:00 10 * --identifier "PC Suite" * --wbxml --dumpinfo * --slow-sync text/x-vcard ./Contacts * * Version: * syncml-ds-tool --version * 0.4.7 (Revision: 634) * */ /** Description of the mobile: * * Mobile: Nokia 9500 (Nokia Series 80) * FirmwareVersion: - * SoftwareVersion: 05.22(01) * HardwareVersion: - * */ #include "../test_mobile.c" SmlTransportType tspType = SML_TRANSPORT_OBEX_CLIENT; const char *obex_port = "10204"; const char *enableWbxml = "1"; const char *useTimestamp = "1"; const char *mobile_name = "Nokia 9500"; const char *maxMsgSize = "65535"; const char *maxObjSize = "1024000"; const char *identifier = "PC Suite"; const char *locList[] = {"./Contacts", SML_ELEMENT_TEXT_VCARD, NULL, NULL}; libsyncml-0.5.4/tests/mobiles/nokia_9500_vcard/sent-2.xml100644 1750 1750 3111 11211710410 23000 0ustar00bellmichbellmich 1.1SyncML/1.12233IMEI:123456789012345PC Suite10000 120SyncHdrPC SuiteIMEI:123456789012345200 725Results./devinf11200 826Sync./Contacts./C\System\Data\Contacts.cdb200 927Add4201 1028Add8201 1129Add18201 12./C\System\Data\Contacts.cdb./Contacts10240000 libsyncml-0.5.4/tests/mobiles/nokia_9500_vcard/sent-1.wbxml100644 1750 1750 3524 11211710410 23340 0ustar00bellmichbellmichŸSjmlq1.1rSyncML/1.1e223[2nWIMEI:123456789012345gWPC SuiteZL10000kiK1\1L0JSyncHdroPC SuitehIMEI:123456789012345O200iK2\1L3JAlerto./Contactsh./C\System\Data\Contacts.cdbO508TOEO20080905T111459ZFK3O201TnW./C\System\Data\Contacts.cdbgW./ContactsZEO20080905T112020Z_K4ZSapplication/vnd.syncml-devinf+wbxmlTgW./devinf11OÊMŸTjJe1.1QOpenSyncUlibsyncmlVLinuxO2.6.25-2-686^0.4.7IPC SuiteKserver(*)G]./ContactsZFtext/x-vcardd2.1YFtext/vcardd3.0bFtext/x-vcardd2.1aFtext/vcardd3.0_`1`2`7EFtext/x-vcardXADRWTYPEcHOMEcWORKcPARCELcPOSTALcINTLcDOMWHOMEWWORKWPARCELWPOSTALWINTLWDOMXAGENTXBDAYXBEGINcVCARDXENDcVCARDXEMAILWTYPEcINTERNETWINTERNETXFNXGEOXKEYWTYPEcX509cPGPWX509WPGPXLABELWTYPEcHOMEcWORKcPARCELcPOSTALcINTLcDOMWHOMEWWORKWPARCELWPOSTALWINTLWDOMXLOGOWTYPEcJPEGWJPEGXMAILERXNXNOTEXORGXPHOTOWTYPEcJPEGWJPEGXREVXROLEXSOUNDWTYPEcAIFFcPCMcWAVEWAIFFWPCMWWAVEXTELWTYPEcWORKcVOICEcPREFcPAGERcMSGcMODEMcISDNcHOMEcFAXcCELLcCARcBBSWWORKWVOICEWPREFWPAGERWMSGWMODEMWISDNWHOMEWFAXWCELLWCARWBBSXTITLEXTZXUIDXURLWTYPEcWORKcHOMEWWORKWHOMEXVERSIONc2.1Ftext/vcardXBEGINcVCARDXENDcVCARDXVERSIONc3.0XREVXNXTITLEXCATEGORIESXCLASSXORGXEMAILXURLXTELWTYPEcCELLcHOMEcWORKcFAXcMODEMcVOICEXADRWTYPEcHOMEcWORKXBDAYXNOTEXPHOTOWTYPESK5ZSapplication/vnd.syncml-devinf+wbxmlTnW./devinf11libsyncml-0.5.4/tests/mobiles/nokia_9500_vcard/received-0.wbxml100644 1750 1750 471 11211710410 24132 0ustar00bellmichbellmichŸSjmlqÃ1.1rà SyncML/1.1eÃ223[Ã1nWÃPC SuitegWÃIMEI:123456789012345ZLÃ10000kiKÃ1\Ã1LÃ0JÃSyncHdroÃ/hÃPC SuiteOÃ200iKÃ2\Ã1LÃ1JÃAlerthà ./ContactsOÃ200FKÃ3OÃ200TnWà ./ContactsgWÃ./C\System\Data\Contacts.cdbZEJÃ20080905T091440ZOÃ20080905T111459Zlibsyncml-0.5.4/tests/mobiles/nokia_9500_vcard/sent-0.xml100644 1750 1750 1220 11211710410 22775 0ustar00bellmichbellmich 1.1SyncML/1.129105858660856377871/PC Suite65535 1206./Contactstext/x-vcard libsyncml-0.5.4/tests/mobiles/nokia_9500_vcard/sent-0.wbxml100644 1750 1750 227 11211710410 23314 0ustar00bellmichbellmichŸSjmlq1.1rSyncML/1.1e2910585866085637787[1nW/gWPC SuiteZL65535kFK1O206TgW./ContactsZStext/x-vcardlibsyncml-0.5.4/tests/mobiles/nokia_9500_vcard/sent-3.xml100644 1750 1750 1240 11211710410 23002 0ustar00bellmichbellmich 1.1SyncML/1.12234IMEI:123456789012345PC Suite10000 130SyncHdrPC SuiteIMEI:123456789012345200 libsyncml-0.5.4/tests/mobiles/nokia_9500_vcard/received-1.xml100644 1750 1750 11302 11211710410 23635 0ustar00bellmichbellmich1.1SyncML/1.12232PC SuiteIMEI:12345678901234510000120SyncHdrIMEI:123456789012345PC Suite200223Alert./C\System\Data\Contacts.cdb./Contacts20020080905T112020Z324Put200425Get200525application/vnd.syncml-devinf+xml./devinf111.1NOKIA9500 05.22(01)IMEI:123456789012345phone./C\System\Data\Contacts.cdb8text/x-vcard2.1text/vcard3.0text/x-vcard2.11234567text/x-vcardBEGINVCARDENDVCARDVERSION2.1REVNADRHOMEWORKTELHOMEWORKCELLPAGERFAXVOICEFNEMAILINTERNETHOMEWORKURLHOMEWORKNOTETITLEORGPHOTOBDAYtext/vcardBEGINVCARDENDVCARDVERSION3.0REVNADRHOMEWORKTELHOMEWORKCELLPAGERFAXVOICEFNEMAILINTERNETHOMEWORKURLHOMEWORKNOTETITLEORGPHOTOBDAY6./Contacts./C\System\Data\Contacts.cdb78643237text/x-vcard48text/x-vcard89text/x-vcard18libsyncml-0.5.4/tests/mobiles/nokia_9500_vcard_vcal/sent-1.xml100644 1750 1750 21134 11211710410 24031 0ustar00bellmichbellmich 1.1SyncML/1.12242IMEI:123456789012345PC Suite10000 110SyncHdrPC SuiteIMEI:123456789012345200 214Alert./Calendar./C\System\Data\Calendar50820080905T111557Z 315Alert./Contacts./C\System\Data\Contacts.cdb50820080905T111557Z 4201./C\System\Data\Calendar./Calendar20080905T112118Z 5201./C\System\Data\Contacts.cdb./Contacts20080905T112118Z 6application/vnd.syncml-devinf+xml./devinf111.1OpenSynclibsyncmlLinux2.6.25-2-6860.4.7PC Suiteserver./Contactstext/x-vcard2.1text/vcard3.0text/x-vcard2.1text/vcard3.0127./Calendartext/x-vcalendar1.0text/calendar2.0text/x-vcalendar1.0text/calendar2.0127text/x-vcardADRTYPEHOMEWORKPARCELPOSTALINTLDOMHOMEWORKPARCELPOSTALINTLDOMAGENTBDAYBEGINVCARDENDVCARDEMAILTYPEINTERNETINTERNETFNGEOKEYTYPEX509PGPX509PGPLABELTYPEHOMEWORKPARCELPOSTALINTLDOMHOMEWORKPARCELPOSTALINTLDOMLOGOTYPEJPEGJPEGMAILERNNOTEORGPHOTOTYPEJPEGJPEGREVROLESOUNDTYPEAIFFPCMWAVEAIFFPCMWAVETELTYPEWORKVOICEPREFPAGERMSGMODEMISDNHOMEFAXCELLCARBBSWORKVOICEPREFPAGERMSGMODEMISDNHOMEFAXCELLCARBBSTITLETZUIDURLTYPEWORKHOMEWORKHOMEVERSION2.1text/vcardBEGINVCARDENDVCARDVERSION3.0REVNTITLECATEGORIESCLASSORGEMAILURLTELTYPECELLHOMEWORKFAXMODEMVOICEADRTYPEHOMEWORKBDAYNOTEPHOTOTYPEtext/x-vcalendarAALARMATTACHATTENDEEEXCEPTRSVPSTATUSROLEBEGINVCALENDARVEVENTVTODOCATEGORIESCOMPLETEDCLASSPUBLICPRIVATECONFIDENTIALDALARMDAYLIGHTDCREATEDDESCRIPTIONDTSTARTDTENDDUEENDVCALENDARVEVENTVTODOEXDATELAST-MODIFIEDLOCATIONPRIORITYRRULESTATUSSUMMARYUIDVERSION1.0text/calendarAALARMATTACHATTENDEERSVPPARTSTATROLEBEGINVCALENDARVEVENTVTODOCATEGORIESCOMPLETEDCLASSPUBLICPRIVATECONFIDENTIALDALARMDAYLIGHTDCREATEDDESCRIPTIONDTSTARTDTENDDUEENDVCALENDARVEVENTVTODOEXDATELAST-MODIFIEDLOCATIONPRIORITYRRULESTATUSSUMMARYUIDVERSION2.0 7application/vnd.syncml-devinf+xml./devinf11 libsyncml-0.5.4/tests/mobiles/nokia_9500_vcard_vcal/sent-2.wbxml100644 1750 1750 1320 11211710410 24336 0ustar00bellmichbellmichŸSjmlq1.1rSyncML/1.1e224[3nWIMEI:123456789012345gWPC SuiteZL10000kiK1\2L0JSyncHdroPC SuitehIMEI:123456789012345O200iK9\2L6JResultsh./devinf11O200iK10\2L7JSynco./Calendarh./C\System\Data\CalendarO200iK11\2L8JAddh4O201iK12\2L9JAddh5O201iK13\2L10JSynco./Contactsh./C\System\Data\Contacts.cdbO200iK14\2L11JAddh4O201iK15\2L12JAddh8O201iK16\2L13JAddh18O201jK17nW./C\System\Data\Contacts.cdbgW./ContactsZU1024000s0jK18nW./C\System\Data\CalendargW./CalendarZU1024000s0libsyncml-0.5.4/tests/mobiles/nokia_9500_vcard_vcal/sent-3.wbxml100644 1750 1750 253 11211710410 24323 0ustar00bellmichbellmichŸSjmlq1.1rSyncML/1.1e224[4nWIMEI:123456789012345gWPC SuiteZL10000kiK1\3L0JSyncHdroPC SuitehIMEI:123456789012345O200libsyncml-0.5.4/tests/mobiles/nokia_9500_vcard_vcal/received-0.xml100644 1750 1750 2662 11211710410 24632 0ustar00bellmichbellmich1.1SyncML/1.12241PC SuiteIMEI:12345678901234510000110SyncHdr/PC Suite200211Alert./Contacts200312Alert./Calendar2004200./Calendar./C\System\Data\Calendar20080818T133355Z20080905T111557Z5200./Contacts./C\System\Data\Contacts.cdb20080905T111459Z20080905T111557Zlibsyncml-0.5.4/tests/mobiles/nokia_9500_vcard_vcal/received-2.xml100644 1750 1750 2003 11211710410 24621 0ustar00bellmichbellmich1.1SyncML/1.12243PC SuiteIMEI:12345678901234510000130SyncHdrIMEI:123456789012345PC Suite2002317Sync./C\System\Data\Contacts.cdb./Contacts2003318Sync./C\System\Data\Calendar./Calendar200libsyncml-0.5.4/tests/mobiles/nokia_9500_vcard_vcal/received-2.wbxml100644 1750 1750 505 11211710410 25137 0ustar00bellmichbellmichŸSjmlqÃ1.1rà SyncML/1.1eÃ224[Ã3nWÃPC SuitegWÃIMEI:123456789012345ZLÃ10000kiKÃ1\Ã3LÃ0JÃSyncHdroÃIMEI:123456789012345hÃPC SuiteOÃ200iKÃ2\Ã3LÃ17JÃSyncoÃ./C\System\Data\Contacts.cdbhà ./ContactsOÃ200iKÃ3\Ã3LÃ18JÃSyncoÃ./C\System\Data\Calendarhà ./CalendarOÃ200libsyncml-0.5.4/tests/mobiles/nokia_9500_vcard_vcal/received-1.wbxml100644 1750 1750 7352 11211710410 25165 0ustar00bellmichbellmichŸSjmlqÃ1.1rà SyncML/1.1eÃ224[Ã2nWÃPC SuitegWÃIMEI:123456789012345ZLÃ10000kiKÃ1\Ã2LÃ0JÃSyncHdroÃIMEI:123456789012345hÃPC SuiteOÃ200iKÃ2\Ã2LÃ4JÃAlertoÃ./C\System\Data\Calendarhà ./CalendarOÃ200TOEOÃ20080905T112118ZiKÃ3\Ã2LÃ5JÃAlertoÃ./C\System\Data\Contacts.cdbhà ./ContactsOÃ200TOEOÃ20080905T112118ZiKÃ4\Ã2LÃ6JÃPutOÃ200iKÃ5\Ã2LÃ7JÃGetOÃ200bKÃ6\Ã2LÃ7ZSÃ#application/vnd.syncml-devinf+wbxmlTgWà ./devinf11OÃaŸTjJeÃ1.1QÃNOKIAUÃ9500^à 05.22(01)IÃIMEI:123456789012345KÃphone(*)G]Ã./C\System\Data\CalendarRÃ8ZFÃtext/x-vcalendardÃ1.0YFà text/calendardÃ2.0bFÃtext/x-vcalendardÃ1.0_`Ã1`Ã2`Ã3`Ã4`Ã5`Ã6`Ã7G]Ã./C\System\Data\Contacts.cdbRÃ8ZFà text/x-vcarddÃ2.1YFà text/vcarddÃ3.0bFà text/x-vcarddÃ2.1_`Ã1`Ã2`Ã3`Ã4`Ã5`Ã6`Ã7EFÃtext/x-vcalendarXÃBEGINcà VCALENDARcÃVEVENTcÃVTODOXÃENDcà VCALENDARcÃVEVENTcÃVTODOXÃVERSIONcÃ1.0XÃUIDXÃSUMMARYXà DESCRIPTIONXÃDTENDXÃDTSTARTXÃAALARMWÃTYPEXÃCLASScÃPUBLICcÃPRIVATEcà CONFIDENTIALXà COMPLETEDXÃLOCATIONXÃDCREATEDXà LAST-MODIFIEDXÃPRIORITYXÃSTATUSXÃRRULEXÃDUEXÃEXDATEXÃTZXÃDAYLIGHTXÃX-EPOCAGENDAENTRYTYPEXÃX-EPOCTODOLISTXÃX-NOKIA-RECURRENCE-IDFà text/calendarXÃBEGINcà VCALENDARcÃVEVENTcÃVTODOXÃENDcà VCALENDARcÃVEVENTcÃVTODOXÃVERSIONcÃ2.0XÃUIDXÃSUMMARYXà DESCRIPTIONXÃDTENDXÃDTSTARTXÃAALARMWÃTYPEXÃCLASScÃPUBLICcÃPRIVATEcà CONFIDENTIALXà COMPLETEDXÃLOCATIONXÃDCREATEDXà LAST-MODIFIEDXÃPRIORITYXÃSTATUSXÃRRULEXÃDUEXÃEXDATEXÃTZXÃDAYLIGHTXÃX-EPOCAGENDAENTRYTYPEXÃX-EPOCTODOLISTXÃX-NOKIA-RECURRENCE-IDFà text/x-vcardXÃBEGINcÃVCARDXÃENDcÃVCARDXÃVERSIONcÃ2.1XÃREVXÃNXÃADRWÃHOMEWÃWORKXÃTELWÃHOMEWÃWORKWÃCELLWÃPAGERWÃFAXWÃVOICEXÃFNXÃEMAILWÃINTERNETWÃHOMEWÃWORKXÃURLWÃHOMEWÃWORKXÃNOTEXÃTITLEXÃORGXÃPHOTOXÃBDAYFà text/vcardXÃBEGINcÃVCARDXÃENDcÃVCARDXÃVERSIONcÃ3.0XÃREVXÃNXÃADRWÃHOMEWÃWORKXÃTELWÃHOMEWÃWORKWÃCELLWÃPAGERWÃFAXWÃVOICEXÃFNXÃEMAILWÃINTERNETWÃHOMEWÃWORKXÃURLWÃHOMEWÃWORKXÃNOTEXÃTITLEXÃORGXÃPHOTOXÃBDAYjKÃ7nWà ./CalendargWÃ./C\System\Data\CalendarZUÃ786432sÃ2EKÃ8ZSÃtext/x-vcalendarTgWÃ4OÂZBEGIN:VCALENDAR VERSION:1.0 TZ:+01 DAYLIGHT:TRUE;+02;20080330T000000;20081026T000000;+01;+02 BEGIN:VEVENT UID:4 SUMMARY:elke Geburtstag DESCRIPTION:amazon DTSTART:20080620T170000Z DTEND:20080620T200000Z CLASS:PUBLIC DCREATED:20080620T000000Z LAST-MODIFIED:20080620T111800Z PRIORITY:0 STATUS:NEEDS ACTION END:VEVENT END:VCALENDAR EKÃ9ZSÃtext/x-vcalendarTgWÃ5OÃ%BEGIN:VCALENDAR VERSION:1.0 TZ:+01 DAYLIGHT:TRUE;+02;20080330T000000;20081026T000000;+01;+02 BEGIN:VEVENT UID:5 SUMMARY:test event DESCRIPTION:need to test OpenSync DTSTART:20080905T070000Z DTEND:20080905T080000Z CLASS:PUBLIC DCREATED:20080905T000000Z RRULE:D1 #0 AALARM;TYPE=X-EPOCSOUND:20080905T064500Z;;0;dummy LAST-MODIFIED:20080905T091500Z PRIORITY:0 STATUS:NEEDS ACTION END:VEVENT END:VCALENDAR jKÃ10nWà ./ContactsgWÃ./C\System\Data\Contacts.cdbZUÃ786432sÃ3EKÃ11ZSà text/x-vcardTgWÃ4OÃRBEGIN:VCARD VERSION:2.1 REV:20080616T114328Z N:testuser;Michael;;; END:VCARD EKÃ12ZSà text/x-vcardTgWÃ8OÃRBEGIN:VCARD VERSION:2.1 REV:20080619T073500Z N:Testnach;Testvor;;; END:VCARD EKÃ13ZSà text/x-vcardTgWÃ18OÃXBEGIN:VCARD VERSION:2.1 REV:20080905T070149Z N:Doe;Jon;Henry;Prof. Dr.-Ing.;add-on ORG:Company; TITLE:position BDAY:20080905 NOTE:some extra note like, he is a nice guy URL:http://www.some.domain END:VCARD libsyncml-0.5.4/tests/mobiles/nokia_9500_vcard_vcal/test.c100644 1750 1750 3606 11211710410 23307 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2008 Michael Bell * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ /** Test environment: * * Combined address book and calendar sync: * syncml-ds-tool * -b 00:00:00:00:00:00 10 * --identifier "PC Suite" * --wbxml --dumpinfo * --slow-sync text/x-vcard ./Contacts * --slow-sync text/x-vcalendar ./Calendar * * Version: * syncml-ds-tool --version * 0.4.7 (Revision: 634) * */ /** Description of the mobile: * * Mobile: Nokia 9500 (Nokia Series 80) * FirmwareVersion: - * SoftwareVersion: 05.22(01) * HardwareVersion: - * */ #include "../test_mobile.c" SmlTransportType tspType = SML_TRANSPORT_OBEX_CLIENT; const char *obex_port = "10205"; const char *enableWbxml = "1"; const char *useTimestamp = "1"; const char *mobile_name = "Nokia 9500"; const char *maxMsgSize = "65535"; const char *maxObjSize = "1024000"; const char *identifier = "PC Suite"; const char *locList[] = {"./Contacts", SML_ELEMENT_TEXT_VCARD, "./Calendar", SML_ELEMENT_TEXT_VCAL, NULL, NULL}; libsyncml-0.5.4/tests/mobiles/nokia_9500_vcard_vcal/sent-2.xml100644 1750 1750 4353 11211710410 24016 0ustar00bellmichbellmich 1.1SyncML/1.12243IMEI:123456789012345PC Suite10000 120SyncHdrPC SuiteIMEI:123456789012345200 926Results./devinf11200 1027Sync./Calendar./C\System\Data\Calendar200 1128Add4201 1229Add5201 13210Sync./Contacts./C\System\Data\Contacts.cdb200 14211Add4201 15212Add8201 16213Add18201 17./C\System\Data\Contacts.cdb./Contacts10240000 18./C\System\Data\Calendar./Calendar10240000 libsyncml-0.5.4/tests/mobiles/nokia_9500_vcard_vcal/sent-1.wbxml100644 1750 1750 5751 11211710410 24351 0ustar00bellmichbellmichŸSjmlq1.1rSyncML/1.1e224[2nWIMEI:123456789012345gWPC SuiteZL10000kiK1\1L0JSyncHdroPC SuitehIMEI:123456789012345O200iK2\1L4JAlerto./Calendarh./C\System\Data\CalendarO508TOEO20080905T111557ZiK3\1L5JAlerto./Contactsh./C\System\Data\Contacts.cdbO508TOEO20080905T111557ZFK4O201TnW./C\System\Data\CalendargW./CalendarZEO20080905T112118ZFK5O201TnW./C\System\Data\Contacts.cdbgW./ContactsZEO20080905T112118Z_K6ZSapplication/vnd.syncml-devinf+wbxmlTgW./devinf11OÃ’ŸTjJe1.1QOpenSyncUlibsyncmlVLinuxO2.6.25-2-686^0.4.7IPC SuiteKserver(*)G]./ContactsZFtext/x-vcardd2.1YFtext/vcardd3.0bFtext/x-vcardd2.1aFtext/vcardd3.0_`1`2`7G]./CalendarZFtext/x-vcalendard1.0YFtext/calendard2.0bFtext/x-vcalendard1.0aFtext/calendard2.0_`1`2`7EFtext/x-vcardXADRWTYPEcHOMEcWORKcPARCELcPOSTALcINTLcDOMWHOMEWWORKWPARCELWPOSTALWINTLWDOMXAGENTXBDAYXBEGINcVCARDXENDcVCARDXEMAILWTYPEcINTERNETWINTERNETXFNXGEOXKEYWTYPEcX509cPGPWX509WPGPXLABELWTYPEcHOMEcWORKcPARCELcPOSTALcINTLcDOMWHOMEWWORKWPARCELWPOSTALWINTLWDOMXLOGOWTYPEcJPEGWJPEGXMAILERXNXNOTEXORGXPHOTOWTYPEcJPEGWJPEGXREVXROLEXSOUNDWTYPEcAIFFcPCMcWAVEWAIFFWPCMWWAVEXTELWTYPEcWORKcVOICEcPREFcPAGERcMSGcMODEMcISDNcHOMEcFAXcCELLcCARcBBSWWORKWVOICEWPREFWPAGERWMSGWMODEMWISDNWHOMEWFAXWCELLWCARWBBSXTITLEXTZXUIDXURLWTYPEcWORKcHOMEWWORKWHOMEXVERSIONc2.1Ftext/vcardXBEGINcVCARDXENDcVCARDXVERSIONc3.0XREVXNXTITLEXCATEGORIESXCLASSXORGXEMAILXURLXTELWTYPEcCELLcHOMEcWORKcFAXcMODEMcVOICEXADRWTYPEcHOMEcWORKXBDAYXNOTEXPHOTOWTYPEFtext/x-vcalendarXAALARMXATTACHXATTENDEEWEXCEPTWRSVPWSTATUSWROLEXBEGINcVCALENDARcVEVENTcVTODOXCATEGORIESXCOMPLETEDXCLASScPUBLICcPRIVATEcCONFIDENTIALXDALARMXDAYLIGHTXDCREATEDXDESCRIPTIONXDTSTARTXDTENDXDUEXENDcVCALENDARcVEVENTcVTODOXEXDATEXLAST-MODIFIEDXLOCATIONXPRIORITYXRRULEXSTATUSXSUMMARYXUIDXVERSIONc1.0Ftext/calendarXAALARMXATTACHXATTENDEEWRSVPWPARTSTATWROLEXBEGINcVCALENDARcVEVENTcVTODOXCATEGORIESXCOMPLETEDXCLASScPUBLICcPRIVATEcCONFIDENTIALXDALARMXDAYLIGHTXDCREATEDXDESCRIPTIONXDTSTARTXDTENDXDUEXENDcVCALENDARcVEVENTcVTODOXEXDATEXLAST-MODIFIEDXLOCATIONXPRIORITYXRRULEXSTATUSXSUMMARYXUIDXVERSIONc2.0SK7ZSapplication/vnd.syncml-devinf+wbxmlTnW./devinf11libsyncml-0.5.4/tests/mobiles/nokia_9500_vcard_vcal/received-0.wbxml100644 1750 1750 726 11211710410 25142 0ustar00bellmichbellmichŸSjmlqÃ1.1rà SyncML/1.1eÃ224[Ã1nWÃPC SuitegWÃIMEI:123456789012345ZLÃ10000kiKÃ1\Ã1LÃ0JÃSyncHdroÃ/hÃPC SuiteOÃ200iKÃ2\Ã1LÃ1JÃAlerthà ./ContactsOÃ200iKÃ3\Ã1LÃ2JÃAlerthà ./CalendarOÃ200FKÃ4OÃ200TnWà ./CalendargWÃ./C\System\Data\CalendarZEJÃ20080818T133355ZOÃ20080905T111557ZFKÃ5OÃ200TnWà ./ContactsgWÃ./C\System\Data\Contacts.cdbZEJÃ20080905T111459ZOÃ20080905T111557Zlibsyncml-0.5.4/tests/mobiles/nokia_9500_vcard_vcal/sent-0.xml100644 1750 1750 1471 11211710410 24012 0ustar00bellmichbellmich 1.1SyncML/1.131737907276179373791/PC Suite65535 1206./Contactstext/x-vcard 2206./Calendartext/x-vcalendar libsyncml-0.5.4/tests/mobiles/nokia_9500_vcard_vcal/sent-0.wbxml100644 1750 1750 321 11211710410 24314 0ustar00bellmichbellmichŸSjmlq1.1rSyncML/1.1e3173790727617937379[1nW/gWPC SuiteZL65535kFK1O206TgW./ContactsZStext/x-vcardFK2O206TgW./CalendarZStext/x-vcalendarlibsyncml-0.5.4/tests/mobiles/nokia_9500_vcard_vcal/sent-3.xml100644 1750 1750 1240 11211710410 24007 0ustar00bellmichbellmich 1.1SyncML/1.12244IMEI:123456789012345PC Suite10000 130SyncHdrPC SuiteIMEI:123456789012345200 libsyncml-0.5.4/tests/mobiles/nokia_9500_vcard_vcal/received-1.xml100644 1750 1750 21304 11211710410 24645 0ustar00bellmichbellmich1.1SyncML/1.12242PC SuiteIMEI:12345678901234510000120SyncHdrIMEI:123456789012345PC Suite200224Alert./C\System\Data\Calendar./Calendar20020080905T112118Z325Alert./C\System\Data\Contacts.cdb./Contacts20020080905T112118Z426Put200527Get200627application/vnd.syncml-devinf+xml./devinf111.1NOKIA9500 05.22(01)IMEI:123456789012345phone./C\System\Data\Calendar8text/x-vcalendar1.0text/calendar2.0text/x-vcalendar1.01234567./C\System\Data\Contacts.cdb8text/x-vcard2.1text/vcard3.0text/x-vcard2.11234567text/x-vcalendarBEGINVCALENDARVEVENTVTODOENDVCALENDARVEVENTVTODOVERSION1.0UIDSUMMARYDESCRIPTIONDTENDDTSTARTAALARMTYPECLASSPUBLICPRIVATECONFIDENTIALCOMPLETEDLOCATIONDCREATEDLAST-MODIFIEDPRIORITYSTATUSRRULEDUEEXDATETZDAYLIGHTX-EPOCAGENDAENTRYTYPEX-EPOCTODOLISTX-NOKIA-RECURRENCE-IDtext/calendarBEGINVCALENDARVEVENTVTODOENDVCALENDARVEVENTVTODOVERSION2.0UIDSUMMARYDESCRIPTIONDTENDDTSTARTAALARMTYPECLASSPUBLICPRIVATECONFIDENTIALCOMPLETEDLOCATIONDCREATEDLAST-MODIFIEDPRIORITYSTATUSRRULEDUEEXDATETZDAYLIGHTX-EPOCAGENDAENTRYTYPEX-EPOCTODOLISTX-NOKIA-RECURRENCE-IDtext/x-vcardBEGINVCARDENDVCARDVERSION2.1REVNADRHOMEWORKTELHOMEWORKCELLPAGERFAXVOICEFNEMAILINTERNETHOMEWORKURLHOMEWORKNOTETITLEORGPHOTOBDAYtext/vcardBEGINVCARDENDVCARDVERSION3.0REVNADRHOMEWORKTELHOMEWORKCELLPAGERFAXVOICEFNEMAILINTERNETHOMEWORKURLHOMEWORKNOTETITLEORGPHOTOBDAY7./Calendar./C\System\Data\Calendar78643228text/x-vcalendar49text/x-vcalendar510./Contacts./C\System\Data\Contacts.cdb786432311text/x-vcard412text/x-vcard813text/x-vcard18libsyncml-0.5.4/tests/mobiles/test_mobile.c100644 1750 1750 4044 11211710410 20671 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2005 Armin Bauer * Copyright (C) 2008 Michael Bell * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include "../support.h" #include "obex_mobile_ds_client.c" /* #include "http_mobile_ds_client.c" */ #include "libsyncml_ds_server.c" extern SmlTransportType tspType; extern const char *mobile_name; char *testDirectory; /* ************************************ * *********** MOBILE TEST ************ * ************************************ */ START_TEST (obex_test_mobile) { obex_mobile_connect(); libsyncml_connect(); obex_mobile_disconnect(); libsyncml_disconnect(); } END_TEST Suite *obex_get_test_suite(void) { Suite *s = suite_create(mobile_name); create_case(s, mobile_name, obex_test_mobile); return s; } int main(int argc, char **argv) { configure_environment(); int nf; /* init test environment */ if (argc > 1) testDirectory = argv[1]; else testDirectory = argv[0]; /* init test suite */ Suite *s = NULL; switch(tspType) { case SML_TRANSPORT_OBEX_CLIENT: s = obex_get_test_suite(); break; default: return 1; break; } SRunner *sr; sr = srunner_create(s); srunner_run_all(sr, CK_VERBOSE); nf = srunner_ntests_failed(sr); srunner_free(sr); cleanup_environment(); return (nf == 0) ? 0 : 1; } libsyncml-0.5.4/tests/mobiles/libsyncml_ds_server.c100644 1750 1750 12420 11211710410 22450 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2005 Armin Bauer * Copyright (C) 2008 Michael Bell * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include "../support.h" /* ************************************ * *********** OMA DS SERVER ********** * ************************************ * (libsyncml customer) */ extern SmlTransportType tspType; extern const char *obex_port; extern const char *maxObjSize; extern const char *maxMsgSize; extern const char *enableWbxml; extern const char *useTimestamp; extern const char *identifier; extern const char *locList[]; #include #include #include static void _libsyncml_event_callback( SmlDataSyncObject *dsObject, SmlDataSyncEventType type, void *userdata, SmlError *error) { smlTrace(TRACE_ENTRY, "%s(%p, %i, %p, %p)", __func__, dsObject, type, userdata, error); switch (type) { case SML_DATA_SYNC_EVENT_ERROR: sml_fail_unless(FALSE, "%s", smlErrorPrint(&error)); smlAssert(FALSE); break; case SML_DATA_SYNC_EVENT_CONNECT: case SML_DATA_SYNC_EVENT_DISCONNECT: case SML_DATA_SYNC_EVENT_GOT_ALL_ALERTS: case SML_DATA_SYNC_EVENT_GOT_ALL_MAPPINGS: break; case SML_DATA_SYNC_EVENT_FINISHED: /* cleanup */ break; case SML_DATA_SYNC_EVENT_GOT_ALL_CHANGES: sml_fail_unless( smlDataSyncSendChanges(dsObject, &error), "%s", smlErrorPrint(&error)); break; default: sml_fail_unless(FALSE, "The unexpected data sync event %d was received.", type); break; } smlTrace(TRACE_EXIT, "%s", __func__); } static SmlBool _recv_change( SmlDataSyncObject *dsObject, const char *source, SmlChangeType type, const char *uid, char *data, unsigned int size, void *userdata, SmlError **error) { smlTrace(TRACE_INTERNAL, "%s: %s ==> %s (%p, %d, %p, %d, %p, %p)", __func__, VA_STRING(source), VA_STRING(uid), dsObject, type, data, size, userdata, error); smlSafeCFree(&data); return TRUE; } SmlDataSyncObject *dsObject = NULL; void libsyncml_connect() { SmlError *error = NULL; dsObject = smlDataSyncNew( SML_SESSION_TYPE_SERVER, tspType, &error); sml_fail_unless(dsObject != NULL, "%s", smlErrorPrint(&error)); switch(tspType) { case SML_TRANSPORT_OBEX_CLIENT: sml_fail_unless( smlDataSyncSetOption( dsObject, SML_DATA_SYNC_CONFIG_CONNECTION_TYPE, SML_DATA_SYNC_CONFIG_CONNECTION_NET, &error), "%s", smlErrorPrint(&error)); sml_fail_unless( smlDataSyncSetOption( dsObject, SML_TRANSPORT_CONFIG_PORT, obex_port, &error), "%s", smlErrorPrint(&error)); break; default: sml_fail_unless(FALSE, "The unsupported transport type %d was used for testing.", tspType); } sml_fail_unless( smlDataSyncSetOption( dsObject, SML_TRANSPORT_CONFIG_URL, "127.0.0.1", &error), "%s", smlErrorPrint(&error)); sml_fail_unless( smlDataSyncSetOption( dsObject, SML_DATA_SYNC_CONFIG_MAX_MSG_SIZE, maxMsgSize, &error), "%s", smlErrorPrint(&error)); sml_fail_unless( smlDataSyncSetOption( dsObject, SML_DATA_SYNC_CONFIG_MAX_OBJ_SIZE, maxObjSize, &error), "%s", smlErrorPrint(&error)); sml_fail_unless( smlDataSyncSetOption( dsObject, SML_DATA_SYNC_CONFIG_USE_WBXML, enableWbxml, &error), "%s", smlErrorPrint(&error)); sml_fail_unless( smlDataSyncSetOption( dsObject, SML_DATA_SYNC_CONFIG_IDENTIFIER, identifier, &error), "%s", smlErrorPrint(&error)); sml_fail_unless( smlDataSyncSetOption( dsObject, SML_DATA_SYNC_CONFIG_USE_TIMESTAMP_ANCHOR, useTimestamp, &error), "%s", smlErrorPrint(&error)); sml_fail_unless( smlDataSyncSetOption( dsObject, SML_DATA_SYNC_CONFIG_VERSION, "1.1", &error), "%s", smlErrorPrint(&error)); smlDataSyncRegisterEventCallback(dsObject, _libsyncml_event_callback, NULL); smlDataSyncRegisterChangeCallback(dsObject, _recv_change, NULL); int i = 0; for (i = 0; locList[2*i] != NULL; i++) { sml_fail_unless( smlDataSyncAddDatastore( dsObject, locList[2*i+1], /* content-type */ NULL, locList[2*i], /* source */ &error), "%s", smlErrorPrint(&error)); sml_fail_unless(error == NULL, NULL); } sml_fail_unless(smlDataSyncInit(dsObject, &error), "%s", smlErrorPrint(&error)); sml_fail_unless(error == NULL, "%s", smlErrorPrint(&error)); sml_fail_unless(smlDataSyncRun(dsObject, &error), "%s", smlErrorPrint(&error)); sml_fail_unless(error == NULL, "%s", smlErrorPrint(&error)); } void libsyncml_disconnect() { smlDataSyncObjectUnref(&dsObject); } libsyncml-0.5.4/tests/mobiles/nokia_e65_vcard/sent-1.xml100644 1750 1750 13115 11211710410 23026 0ustar00bellmichbellmich 1.1SyncML/1.162IMEI:123456789012345PC Suite65535 110SyncHdrPC SuiteIMEI:123456789012345200 213Alert./Contacts./C:Contacts.cdb50820080210T073528Z 3201./C:Contacts.cdbContacts20080903T075608Z 4application/vnd.syncml-devinf+xml./devinf111.1OpenSynclibsyncmlLinux2.6.25.14-108.fc9.x86_640.4.7PC SuiteserverContactstext/x-vcard2.1text/vcard3.0text/x-vcard2.1text/vcard3.0127text/x-vcardADRTYPEHOMEWORKPARCELPOSTALINTLDOMHOMEWORKPARCELPOSTALINTLDOMAGENTBDAYBEGINVCARDENDVCARDEMAILTYPEINTERNETINTERNETFNGEOKEYTYPEX509PGPX509PGPLABELTYPEHOMEWORKPARCELPOSTALINTLDOMHOMEWORKPARCELPOSTALINTLDOMLOGOTYPEJPEGJPEGMAILERNNOTEORGPHOTOTYPEJPEGJPEGREVROLESOUNDTYPEAIFFPCMWAVEAIFFPCMWAVETELTYPEWORKVOICEPREFPAGERMSGMODEMISDNHOMEFAXCELLCARBBSWORKVOICEPREFPAGERMSGMODEMISDNHOMEFAXCELLCARBBSTITLETZUIDURLTYPEWORKHOMEWORKHOMEVERSION2.1text/vcardBEGINVCARDENDVCARDVERSION3.0REVNTITLECATEGORIESCLASSORGEMAILURLTELTYPECELLHOMEWORKFAXMODEMVOICEADRTYPEHOMEWORKBDAYNOTEPHOTOTYPE 5application/vnd.syncml-devinf+xml./devinf11 libsyncml-0.5.4/tests/mobiles/nokia_e65_vcard/sent-2.wbxml100644 1750 1750 600 11211710410 23313 0ustar00bellmichbellmichŸSjmlq1.1rSyncML/1.1e6[3nWIMEI:123456789012345gWPC SuiteZL65535kiK1\2L0JSyncHdroPC SuitehIMEI:123456789012345O200iK7\2L5JResultsh./devinf11O200iK8\2L6JSynco./Contactsh./C:Contacts.cdbO200iK9\2L7JAddh1O201jK10nW./C:Contacts.cdbgWContactsZU65535s0libsyncml-0.5.4/tests/mobiles/nokia_e65_vcard/sent-3.wbxml100644 1750 1750 251 11211710410 23316 0ustar00bellmichbellmichŸSjmlq1.1rSyncML/1.1e6[4nWIMEI:123456789012345gWPC SuiteZL65535kiK1\3L0JSyncHdroPC SuitehIMEI:123456789012345O200libsyncml-0.5.4/tests/mobiles/nokia_e65_vcard/received-0.xml100644 1750 1750 2015 11211710410 23617 0ustar00bellmichbellmich1.1SyncML/1.161PC SuiteIMEI:12345678901234565535110SyncHdr/PC Suite200211AlertContacts2003200./Contacts./C:Contacts.cdb20080210T072716Z20080210T073528Z libsyncml-0.5.4/tests/mobiles/nokia_e65_vcard/received-2.xml100644 1750 1750 1477 11211710410 23634 0ustar00bellmichbellmich1.1SyncML/1.163PC SuiteIMEI:12345678901234565535130SyncHdrIMEI:123456789012345PC Suite2002310Sync./C:Contacts.cdbContacts200 libsyncml-0.5.4/tests/mobiles/nokia_e65_vcard/received-2.wbxml100644 1750 1750 352 11211710410 24134 0ustar00bellmichbellmichŸSjmlqÃ1.1rà SyncML/1.1eÃ6[Ã3nWÃPC SuitegWÃIMEI:123456789012345ZLÃ65535kiKÃ1\Ã3LÃ0JÃSyncHdroÃIMEI:123456789012345hÃPC SuiteOÃ200iKÃ2\Ã3LÃ10JÃSyncoÃ./C:Contacts.cdbhÃContactsOÃ200libsyncml-0.5.4/tests/mobiles/nokia_e65_vcard/received-1.wbxml100644 1750 1750 3530 11211710410 24154 0ustar00bellmichbellmichŸSjmlqÃ1.1rà SyncML/1.1eÃ6[Ã2nWÃPC SuitegWÃIMEI:123456789012345ZLÃ65535kiKÃ1\Ã2LÃ0JÃSyncHdroÃIMEI:123456789012345hÃPC SuiteOÃ200iKÃ2\Ã2LÃ3JÃAlertoÃ./C:Contacts.cdbhÃContactsOÃ200TOEOÃ20080903T075608ZiKÃ3\Ã2LÃ4JÃPutOÃ200iKÃ4\Ã2LÃ5JÃGetOÃ200bKÃ5\Ã2LÃ5ZSÃ#application/vnd.syncml-devinf+wbxmlTgWà ./devinf11OÉoŸTjJeÃ1.1QÃNOKIAUÃE65OÃ^à 1.0633.18.01PÃIÃIMEI:123456789012345KÃphone(*)G]Ã./C:Contacts.cdbLÃContactsRÃ8ZFà text/x-vcarddÃ2.1bFà text/x-vcarddÃ2.1_`Ã1`Ã2`Ã3`Ã4`Ã5`Ã6`Ã7EFà text/x-vcardXÃBEGINcÃVCARDLÃBeginXÃENDcÃVCARDLÃEndXÃVERSIONcÃ2.1LÃVersionXÃREVHÃ\Ã256LÃRevisionXÃNHÃ\Ã256LÃNameXÃADRHÃ\Ã256LÃAddressWÃHOMEHÃLà Home addressWÃWORKHÃLà Work addressXÃTELHÃ\Ã256LÃTelephone numberWÃHOMEHÃLÃHome telephoneWÃWORKHÃLÃWork telephoneWÃCELLHÃLÃCellular numberWÃPAGERHÃLà Pager numberWÃFAXHÃLà Fax numberWÃVIDEOHÃLà Video numberWÃPREFHÃLÃDefault numberXÃFNHÃ\Ã256LÃFullNameXÃEMAILHÃ\Ã256Là Email addressWÃHOMEHÃLà Home emailWÃWORKHÃLà Work emailXÃURLHÃ\Ã256Là URL addressWÃHOMEHÃLÃHome URLWÃWORKHÃLÃWork URLXÃNOTEHÃ\Ã256LÃNoteXÃTITLEHÃ\Ã256LÃTitleXÃORGHÃ\Ã256Là OrganisationXÃPHOTOHÃ\Ã256LÃPhotoXÃBDAYHÃ\Ã256LÃBirthdayXÃSOUNDHÃ\Ã256LÃSoundXÃX-WV-IDHÃ\Ã256LÃWireless Village IdXÃX-EPOCSECONDNAMEHÃ\Ã256LÃNicknameXÃX-SIPHÃ\Ã256Là SIP protocolWÃPOCHÃLÃPOCWÃSWISHÃLÃSWISWÃVOIPHÃLà Voice over IPjKÃ6nWà ./ContactsgWÃ./C:Contacts.cdbZUÃ102400sÃ1EKÃ7TgWÃ1ZSà text/x-vcardTÃ2.1OÃ[BEGIN:VCARD VERSION:2.1 REV:20080209T172846Z N:Doe;John;;; TEL;VOICE:12345 END:VCARD libsyncml-0.5.4/tests/mobiles/nokia_e65_vcard/test.c100644 1750 1750 3423 11211710410 22301 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2008 Michael Bell * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ /** Test environment: * * Single address book sync: * syncml-ds-tool * -b 00:00:00:00:00:00 10 * --identifier "PC Suite" * --wbxml --dumpinfo * --slow-sync text/x-vcard Contacts * * Version: * syncml-ds-tool --version * 0.4.7 (Revision: 614) * */ /** Description of the mobile: * * Mobile: Nokia E65 (Nokia Series 60) * FirmwareVersion: - * SoftwareVersion: 1.0633.18.01 * HardwareVersion: - * */ #include "../test_mobile.c" SmlTransportType tspType = SML_TRANSPORT_OBEX_CLIENT; const char *obex_port = "10206"; const char *enableWbxml = "1"; const char *useTimestamp = "1"; const char *mobile_name = "Nokia E65"; const char *maxMsgSize = "1024000"; const char *maxObjSize = "65535"; const char *identifier = "PC Suite"; const char *locList[] = {"Contacts", SML_ELEMENT_TEXT_VCARD, NULL, NULL}; libsyncml-0.5.4/tests/mobiles/nokia_e65_vcard/sent-2.xml100644 1750 1750 2460 11211710410 23010 0ustar00bellmichbellmich 1.1SyncML/1.163IMEI:123456789012345PC Suite65535 120SyncHdrPC SuiteIMEI:123456789012345200 725Results./devinf11200 826Sync./Contacts./C:Contacts.cdb200 927Add1201 10./C:Contacts.cdbContacts655350 libsyncml-0.5.4/tests/mobiles/nokia_e65_vcard/sent-1.wbxml100644 1750 1750 3502 11211710410 23336 0ustar00bellmichbellmichŸSjmlq1.1rSyncML/1.1e6[2nWIMEI:123456789012345gWPC SuiteZL65535kiK1\1L0JSyncHdroPC SuitehIMEI:123456789012345O200iK2\1L3JAlerto./Contactsh./C:Contacts.cdbO508TOEO20080210T073528ZFK3O201TnW./C:Contacts.cdbgWContactsZEO20080903T075608Z_K4ZSapplication/vnd.syncml-devinf+wbxmlTgW./devinf11OÊWŸTjJe1.1QOpenSyncUlibsyncmlVLinuxO2.6.25.14-108.fc9.x86_64^0.4.7IPC SuiteKserver(*)G]ContactsZFtext/x-vcardd2.1YFtext/vcardd3.0bFtext/x-vcardd2.1aFtext/vcardd3.0_`1`2`7EFtext/x-vcardXADRWTYPEcHOMEcWORKcPARCELcPOSTALcINTLcDOMWHOMEWWORKWPARCELWPOSTALWINTLWDOMXAGENTXBDAYXBEGINcVCARDXENDcVCARDXEMAILWTYPEcINTERNETWINTERNETXFNXGEOXKEYWTYPEcX509cPGPWX509WPGPXLABELWTYPEcHOMEcWORKcPARCELcPOSTALcINTLcDOMWHOMEWWORKWPARCELWPOSTALWINTLWDOMXLOGOWTYPEcJPEGWJPEGXMAILERXNXNOTEXORGXPHOTOWTYPEcJPEGWJPEGXREVXROLEXSOUNDWTYPEcAIFFcPCMcWAVEWAIFFWPCMWWAVEXTELWTYPEcWORKcVOICEcPREFcPAGERcMSGcMODEMcISDNcHOMEcFAXcCELLcCARcBBSWWORKWVOICEWPREFWPAGERWMSGWMODEMWISDNWHOMEWFAXWCELLWCARWBBSXTITLEXTZXUIDXURLWTYPEcWORKcHOMEWWORKWHOMEXVERSIONc2.1Ftext/vcardXBEGINcVCARDXENDcVCARDXVERSIONc3.0XREVXNXTITLEXCATEGORIESXCLASSXORGXEMAILXURLXTELWTYPEcCELLcHOMEcWORKcFAXcMODEMcVOICEXADRWTYPEcHOMEcWORKXBDAYXNOTEXPHOTOWTYPESK5ZSapplication/vnd.syncml-devinf+wbxmlTnW./devinf11libsyncml-0.5.4/tests/mobiles/nokia_e65_vcard/received-0.wbxml100644 1750 1750 451 11211710410 24132 0ustar00bellmichbellmichŸSjmlqÃ1.1rà SyncML/1.1eÃ6[Ã1nWÃPC SuitegWÃIMEI:123456789012345ZLÃ65535kiKÃ1\Ã1LÃ0JÃSyncHdroÃ/hÃPC SuiteOÃ200iKÃ2\Ã1LÃ1JÃAlerthÃContactsOÃ200FKÃ3OÃ200TnWà ./ContactsgWÃ./C:Contacts.cdbZEJÃ20080210T072716ZOÃ20080210T073528Zlibsyncml-0.5.4/tests/mobiles/nokia_e65_vcard/sent-0.xml100644 1750 1750 1221 11211710410 23000 0ustar00bellmichbellmich 1.1SyncML/1.1181148402400320025431/PC Suite1024000 1206Contactstext/x-vcard libsyncml-0.5.4/tests/mobiles/nokia_e65_vcard/sent-0.wbxml100644 1750 1750 230 11211710410 23310 0ustar00bellmichbellmichŸSjmlq1.1rSyncML/1.1e18114840240032002543[1nW/gWPC SuiteZL1024000kFK1O206TgWContactsZStext/x-vcardlibsyncml-0.5.4/tests/mobiles/nokia_e65_vcard/sent-3.xml100644 1750 1750 1236 11211710410 23011 0ustar00bellmichbellmich 1.1SyncML/1.164IMEI:123456789012345PC Suite65535 130SyncHdrPC SuiteIMEI:123456789012345200 libsyncml-0.5.4/tests/mobiles/nokia_e65_vcard/received-1.xml100644 1750 1750 12476 11211710410 23654 0ustar00bellmichbellmich1.1SyncML/1.162PC SuiteIMEI:12345678901234565535120SyncHdrIMEI:123456789012345PC Suite200223Alert./C:Contacts.cdbContacts20020080903T075608Z324Put200425Get200525application/vnd.syncml-devinf+xml./devinf111.1NOKIAE651.0633.18.01IMEI:123456789012345phone./C:Contacts.cdbContacts8text/x-vcard2.1text/x-vcard2.11234567text/x-vcardBEGINVCARDBeginENDVCARDEndVERSION2.1VersionREV256RevisionN256NameADR256AddressHOMEHome addressWORKWork addressTEL256Telephone numberHOMEHome telephoneWORKWork telephoneCELLCellular numberPAGERPager numberFAXFax numberVIDEOVideo numberPREFDefault numberFN256FullNameEMAIL256Email addressHOMEHome emailWORKWork emailURL256URL addressHOMEHome URLWORKWork URLNOTE256NoteTITLE256TitleORG256OrganisationPHOTO256PhotoBDAY256BirthdaySOUND256SoundX-WV-ID256Wireless Village IdX-EPOCSECONDNAME256NicknameX-SIP256SIP protocolPOCPOCSWISSWISVOIPVoice over IP6./Contacts./C:Contacts.cdb102400171text/x-vcard2.1 libsyncml-0.5.4/tests/mobiles/obex_mobile_ds_client.c100644 1750 1750 30531 11211710410 22713 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2005 Armin Bauer * Copyright (C) 2008 Michael Bell * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include "../support.h" /* ************************************ * *********** OBEX SERVER ************ * ************************************ * (mobile simulator) */ #include #include /* external configuration */ extern const char *obex_port; extern const char *enableWbxml; extern char *testDirectory; /* supported messages */ char *libsyncml_msg_notification_data; size_t libsyncml_msg_notification_size; char *mobile_msg_alert_data; size_t mobile_msg_alert_size; char *libsyncml_msg_alert_data; size_t libsyncml_msg_alert_size; char *mobile_msg_sync_data; size_t mobile_msg_sync_size; char *libsyncml_msg_sync_data; size_t libsyncml_msg_sync_size; char *mobile_msg_map_data; size_t mobile_msg_map_size; char *libsyncml_msg_end_data; size_t libsyncml_msg_end_size; /* mobile status variables */ typedef enum { TEST_MOBILE_STATE_UNKNOWN, TEST_MOBILE_STATE_CONNECTED, TEST_MOBILE_STATE_WAIT_FOR_NOTIFICATION, TEST_MOBILE_STATE_WAIT_FOR_ALERT, TEST_MOBILE_STATE_WAIT_FOR_SYNC, TEST_MOBILE_STATE_WAIT_FOR_END, TEST_MOBILE_STATE_FINISHED, TEST_MOBILE_STATE_DISCONNECTED, TEST_MOBILE_STATE_FAILED } SmlTestMobileStateType; SmlTestMobileStateType mobile_state = TEST_MOBILE_STATE_UNKNOWN; SmlTransport *mobile_tsp = NULL; void obex_mobile_send(SmlLink *link_, const char *data, unsigned int size) { SmlError *error = NULL; SmlMimeType mimetype = SML_MIMETYPE_XML; if (enableWbxml) mimetype = SML_MIMETYPE_WBXML; char *msg = smlTryMalloc0(size, &error); sml_fail_unless(msg != NULL, "%s", smlErrorPrint(&error)); memcpy(msg, data, size); SmlTransportData *tsp_data = smlTransportDataNew(msg, size, mimetype, TRUE, &error); sml_fail_unless(tsp_data != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlTransportSend(mobile_tsp, link_, tsp_data, &error), "%s", smlErrorPrint(&error)); sml_fail_unless(error == NULL, NULL); smlTransportDataDeref(tsp_data); } static char *_get_xml( const char *recv_data, size_t recv_size) { char *result = NULL; WBXMLConvWBXML2XMLParams params = {WBXML_ENCODER_XML_GEN_COMPACT, WBXML_LANG_UNKNOWN, 0, TRUE}; WBXMLError wberror; wberror = wbxml_conv_wbxml2xml((WB_UTINY*)recv_data, recv_size, (WB_UTINY**)&result, ¶ms); if (wberror != WBXML_OK) return NULL; else return result; } static char *replace_string( const char *expr, GRegexCompileFlags flags, char *original, const char* replacement) { smlTrace(TRACE_ENTRY, "%s(%s, %s)", __func__, VA_STRING(expr), VA_STRING(original)); GRegex *regex = NULL; GError *error = NULL; char *result = NULL; regex = g_regex_new(expr, flags, 0, &error); sml_fail_unless(regex != NULL, "Filter \"%s\" cannot be established.", expr); result = g_regex_replace_literal(regex, original, strlen(original), 0, replacement, 0, &error); sml_fail_unless(result != NULL, "Cannot filter \"%s\" from message.", expr); smlSafeCFree(&original); g_regex_unref(regex); return result; } static SmlBool equal_messages( const char *recv_data, size_t recv_size, const char *orig_data, size_t orig_size) { smlTrace(TRACE_ENTRY, "%s(%p, %d, %p, %d)", __func__, recv_data, recv_size, orig_data, orig_size); /* convert wbxml messages to xml */ /* WARNING: we cannot detect libwbxml problems by this way * * I (bellmich) tried to implement this in a native way * but this would nearly require a WBXML parser :( */ char *recv = _get_xml(recv_data, recv_size); char *orig = _get_xml(orig_data, orig_size); /* fix the content */ /* ignore SessionID */ recv = replace_string( "[0-9]+", 0, recv, "2346"); orig = replace_string( "[0-9]+", 0, orig, "2346"); /* ignore trailing whitespaces */ recv = replace_string( "[\\s\\n]*$", G_REGEX_DOLLAR_ENDONLY, recv, ""); orig = replace_string( "[\\s\\n]*$", G_REGEX_DOLLAR_ENDONLY, orig, ""); /* ignore newlines (not carriage return) */ recv = replace_string( ">\\n<", 0, recv, "><"); orig = replace_string( ">\\n<", 0, orig, "><"); /* ignore numbered next values */ recv = replace_string( "[0-9]+", 0, recv, "1357"); orig = replace_string( "[0-9]+", 0, orig, "1357"); /* ignore timestamp next values */ recv = replace_string( "[0-9]{8}T[0-9]{6}Z", 0, recv, "20080101T140000Z"); orig = replace_string( "[0-9]{8}T[0-9]{6}Z", 0, orig, "20080101T140000Z"); /* ignore FwV values */ recv = replace_string( "[^<]+", 0, recv, "2.6.25-2-686"); orig = replace_string( "[^<]+", 0, orig, "2.6.25-2-686"); /* ignore SwV values */ recv = replace_string( "[^<]+", 0, recv, "0.4.7"); orig = replace_string( "[^<]+", 0, orig, "0.4.7"); /* ignore OEM values */ recv = replace_string( "[^<]+", 0, recv, "Unix"); orig = replace_string( "[^<]+", 0, orig, "Unix"); /* compare strings */ SmlBool notEqual = strcmp(recv, orig); if (notEqual) { smlLog("original-%d.xml", orig, strlen(orig)); smlLog("validated-%d.xml", recv, strlen(recv)); } smlSafeCFree(&recv); smlSafeCFree(&orig); smlTrace(TRACE_EXIT, "%s - %d", __func__, (!notEqual)); return (!notEqual); } SmlBool _recv_server_event(SmlTransport *tsp, SmlLink *link_, SmlTransportEventType type, SmlTransportData *data, SmlError *error, void *userdata) { smlTrace(TRACE_ENTRY, "%s(%p, %p)", __func__, tsp, userdata); switch (type) { case SML_TRANSPORT_EVENT_DATA: if (mobile_state == TEST_MOBILE_STATE_WAIT_FOR_NOTIFICATION) { smlTrace(TRACE_INTERNAL, "%s: mobile received notification", __func__); if (!equal_messages( data->data, data->size, libsyncml_msg_notification_data, libsyncml_msg_notification_size)) { sml_fail_unless(FALSE, "wrong notification message"); } mobile_state = TEST_MOBILE_STATE_WAIT_FOR_ALERT; obex_mobile_send(link_, mobile_msg_alert_data, mobile_msg_alert_size); } else if (mobile_state == TEST_MOBILE_STATE_WAIT_FOR_ALERT) { smlTrace(TRACE_INTERNAL, "%s: mobile received alert", __func__); if (!equal_messages( data->data, data->size, libsyncml_msg_alert_data, libsyncml_msg_alert_size)) { sml_fail_unless(FALSE, "wrong alert message"); } mobile_state = TEST_MOBILE_STATE_WAIT_FOR_SYNC; obex_mobile_send(link_, mobile_msg_sync_data, mobile_msg_sync_size); } else if (mobile_state == TEST_MOBILE_STATE_WAIT_FOR_SYNC) { smlTrace(TRACE_INTERNAL, "%s: mobile received sync", __func__); if (!equal_messages( data->data, data->size, libsyncml_msg_sync_data, libsyncml_msg_sync_size)) { sml_fail_unless(FALSE, "wrong sync message"); } mobile_state = TEST_MOBILE_STATE_WAIT_FOR_END; obex_mobile_send(link_, mobile_msg_map_data, mobile_msg_map_size); } else if (mobile_state == TEST_MOBILE_STATE_WAIT_FOR_END) { smlTrace(TRACE_INTERNAL, "%s: mobile received end", __func__); if (!equal_messages( data->data, data->size, libsyncml_msg_end_data, libsyncml_msg_end_size)) { sml_fail_unless(FALSE, "wrong end message"); } mobile_state = TEST_MOBILE_STATE_FINISHED; /* The disconnect must be issued by obex client * but the mobile is the OBEX server. */ } else { sml_fail_unless(FALSE, "The unexpected mobile state %d is set.", mobile_state); } break; case SML_TRANSPORT_EVENT_CONNECT_DONE: mobile_state = TEST_MOBILE_STATE_CONNECTED; sml_fail_unless(libsyncml_msg_notification_data != NULL, "Missing notification message"); mobile_state = TEST_MOBILE_STATE_WAIT_FOR_NOTIFICATION; break; case SML_TRANSPORT_EVENT_DISCONNECT_DONE: mobile_state = TEST_MOBILE_STATE_DISCONNECTED; break; case SML_TRANSPORT_EVENT_ERROR: sml_fail_unless(FALSE, "%s", smlErrorPrint(&error)); break; default: sml_fail_unless(FALSE, "The unexpected transport event %d was received.", type); break; } smlTrace(TRACE_EXIT, "%s()", __func__); return TRUE; } void obex_mobile_connect() { char *filename = NULL; /* g_file_get_contents uses indirectly g_static_private_get * which can be used without g_thread_init * but g_thread_init avoids some memory leak warnings. */ if (!g_thread_supported ()) g_thread_init (NULL); /* load all the messages */ filename = g_strdup_printf("%s/sent-0.wbxml", testDirectory); sml_fail_unless( g_file_get_contents( filename, &libsyncml_msg_notification_data, &libsyncml_msg_notification_size, NULL), "Cannot load %s/sent-0.wbxml.", testDirectory); smlSafeCFree(&filename); filename = g_strdup_printf("%s/received-0.wbxml", testDirectory); sml_fail_unless( g_file_get_contents( filename, &mobile_msg_alert_data, &mobile_msg_alert_size, NULL), "Cannot load %s/received-0.wbxml.", testDirectory); smlSafeCFree(&filename); filename = g_strdup_printf("%s/sent-1.wbxml", testDirectory); sml_fail_unless( g_file_get_contents( filename, &libsyncml_msg_alert_data, &libsyncml_msg_alert_size, NULL), "Cannot load %s/sent-1.wbxml.", testDirectory); smlSafeCFree(&filename); filename = g_strdup_printf("%s/received-1.wbxml", testDirectory); sml_fail_unless( g_file_get_contents( filename, &mobile_msg_sync_data, &mobile_msg_sync_size, NULL), "Cannot load %s/received-1.wbxml.", testDirectory); smlSafeCFree(&filename); filename = g_strdup_printf("%s/sent-2.wbxml", testDirectory); sml_fail_unless( g_file_get_contents( filename, &libsyncml_msg_sync_data, &libsyncml_msg_sync_size, NULL), "Cannot load %s/sent-2.wbxml.", testDirectory); smlSafeCFree(&filename); filename = g_strdup_printf("%s/received-2.wbxml", testDirectory); sml_fail_unless( g_file_get_contents( filename, &mobile_msg_map_data, &mobile_msg_map_size, NULL), "Cannot load %s/received-2.wbxml.", testDirectory); smlSafeCFree(&filename); filename = g_strdup_printf("%s/sent-3.wbxml", testDirectory); sml_fail_unless( g_file_get_contents( filename, &libsyncml_msg_end_data, &libsyncml_msg_end_size, NULL), "Cannot load %s/sent-3.wbxml.", testDirectory); smlSafeCFree(&filename); /* init the mobiles SyncML stack */ SmlError *error = NULL; mobile_tsp = smlTransportNew(SML_TRANSPORT_OBEX_SERVER, &error); sml_fail_unless(smlTransportSetConnectionType(mobile_tsp, SML_TRANSPORT_CONNECTION_TYPE_NET, &error), NULL); sml_fail_unless(smlTransportSetConfigOption(mobile_tsp, SML_TRANSPORT_CONFIG_PORT, obex_port, &error), NULL); smlTransportSetEventCallback(mobile_tsp, _recv_server_event, GINT_TO_POINTER(1)); sml_fail_unless(smlTransportInitialize(mobile_tsp, &error), NULL); } void obex_mobile_disconnect() { smlTrace(TRACE_ENTRY, "%s", __func__); SmlError *error = NULL; while (mobile_state != TEST_MOBILE_STATE_DISCONNECTED) { usleep(100); } sml_fail_unless(smlTransportFinalize(mobile_tsp, &error), NULL); smlTransportFree(mobile_tsp); /* free configuration */ smlSafeCFree(&libsyncml_msg_notification_data); smlSafeCFree(&mobile_msg_alert_data); smlSafeCFree(&libsyncml_msg_alert_data); smlSafeCFree(&mobile_msg_sync_data); smlSafeCFree(&libsyncml_msg_sync_data); smlSafeCFree(&mobile_msg_map_data); smlSafeCFree(&libsyncml_msg_end_data); smlTrace(TRACE_EXIT, "%s", __func__); } libsyncml-0.5.4/tests/mobiles/nokia_6230_vcard/sent-1.xml100644 1750 1750 13056 11211710410 23025 0ustar00bellmichbellmich 1.1SyncML/1.1102IMEI:123456789012345PC Suite3584 110SyncHdrPC SuiteIMEI:123456789012345200 213AlertContacts/telecom/pb.vcf5081 3201/telecom/pb.vcfContacts20080904T151703Z 4application/vnd.syncml-devinf+xml./devinf111.1OpenSynclibsyncmlLinux2.6.25-2-6860.4.7PC SuiteserverContactstext/x-vcard2.1text/vcard3.0text/x-vcard2.1text/vcard3.0127text/x-vcardADRTYPEHOMEWORKPARCELPOSTALINTLDOMHOMEWORKPARCELPOSTALINTLDOMAGENTBDAYBEGINVCARDENDVCARDEMAILTYPEINTERNETINTERNETFNGEOKEYTYPEX509PGPX509PGPLABELTYPEHOMEWORKPARCELPOSTALINTLDOMHOMEWORKPARCELPOSTALINTLDOMLOGOTYPEJPEGJPEGMAILERNNOTEORGPHOTOTYPEJPEGJPEGREVROLESOUNDTYPEAIFFPCMWAVEAIFFPCMWAVETELTYPEWORKVOICEPREFPAGERMSGMODEMISDNHOMEFAXCELLCARBBSWORKVOICEPREFPAGERMSGMODEMISDNHOMEFAXCELLCARBBSTITLETZUIDURLTYPEWORKHOMEWORKHOMEVERSION2.1text/vcardBEGINVCARDENDVCARDVERSION3.0REVNTITLECATEGORIESCLASSORGEMAILURLTELTYPECELLHOMEWORKFAXMODEMVOICEADRTYPEHOMEWORKBDAYNOTEPHOTOTYPE 5application/vnd.syncml-devinf+xml./devinf11 libsyncml-0.5.4/tests/mobiles/nokia_6230_vcard/sent-2.wbxml100644 1750 1750 550 11211710410 23312 0ustar00bellmichbellmichŸSjmlq1.1rSyncML/1.1e10[3nWIMEI:123456789012345gWPC SuiteZL3584kiK1\2L0JSyncHdroPC SuitehIMEI:123456789012345O200iK7\2L5JResultsh./devinf11O200iK8\2L6JSyncoContactsh/telecom/pb.vcfO200iK9\2L7JAddh9O201jK10nW/telecom/pb.vcfgWContactslibsyncml-0.5.4/tests/mobiles/nokia_6230_vcard/sent-3.wbxml100644 1750 1750 251 11211710410 23311 0ustar00bellmichbellmichŸSjmlq1.1rSyncML/1.1e10[4nWIMEI:123456789012345gWPC SuiteZL3584kiK1\3L0JSyncHdroPC SuitehIMEI:123456789012345O200libsyncml-0.5.4/tests/mobiles/nokia_6230_vcard/received-0.xml100644 1750 1750 1777 11211710410 23630 0ustar00bellmichbellmich1.1SyncML/1.1101PC SuiteIMEI:1234567890123453584110SyncHdrIMEI:123456789012345PC Suite200211AlertContacts2003206Contacts/telecom/pb.vcf11 libsyncml-0.5.4/tests/mobiles/nokia_6230_vcard/received-2.xml100644 1750 1750 1376 11211710410 23625 0ustar00bellmichbellmich1.1SyncML/1.1103PC SuiteIMEI:123456789012345130SyncHdrIMEI:123456789012345PC Suite2002310Sync/telecom/pb.vcfContacts200 libsyncml-0.5.4/tests/mobiles/nokia_6230_vcard/received-2.wbxml100644 1750 1750 333 11211710410 24126 0ustar00bellmichbellmichŸSjmlq1.1rSyncML/1.1e10[3nWPC SuitegWIMEI:123456789012345kiK1\3L0JSyncHdroIMEI:123456789012345hPC SuiteO200iK2\3L10JSynco/telecom/pb.vcfhContactsO200libsyncml-0.5.4/tests/mobiles/nokia_6230_vcard/received-1.wbxml100644 1750 1750 3031 11211710410 24143 0ustar00bellmichbellmichŸSjmlq1.1rSyncML/1.1e10[2nWPC SuitegWIMEI:123456789012345kiK1\2L0JSyncHdroIMEI:123456789012345hPC SuiteO200iK2\2L3JAlerto/telecom/pb.vcfhContactsO200TOEO20080904T151703ZiK3\2L4JPuth./devinf11O200iK4\2L5JGeto./devinf11O200bK5\2L5o./devinf11TgW./devinf11ZSapplication/vnd.syncml-devinf+wbxmlOÇ-ŸTj~1.1Nokia 62300606V 05.50IMEI:123456789012345NokiaJeƒQƒiUƒOƒ?^ƒ?Pƒ*IƒTKphoneG]/telecom/pb.vcfR8ZFtext/x-vcardd2.1bFtext/x-vcardd2.1_`1`2`7G]/telecom/cal.vcsR8ZFtext/x-vcalendard1.0bFtext/x-vcalendard1.0_`1`2`7G]/telecom/note.txtR8ZFtext/plaindbFtext/plaind_`1`2`7EFtext/x-vcardXBEGINcVCARDXVERSIONc2.1XENDcVCARDXNXTELWPREFWWORKWHOMEWVOICEWFAXWCELLXNOTEXURLXEMAILXLABELEFtext/x-vcalendarXBEGINcVCALENDARcVEVENTcVTODOXVERSIONc1.0XENDcVCALENDARcVEVENTcVTODOXDTSTARTHdatetimeXDTENDHdatetimeXSUMMARYXDUEXAALARMHdatetimeXDALARMHdatetimeXRRULEXCATEGORIESXLOCATIONXSTATUSXPRIORITYXEXDATEEFtext/plainXHchr\3000jK6nWContactsgW/telecom/pb.vcfZMI99900H999EK7ZStext/x-vcardTgW9OÃJBEGIN:VCARD VERSION:2.1 N:Doe;John TEL;PREF;VOICE:55512345 END:VCARD libsyncml-0.5.4/tests/mobiles/nokia_6230_vcard/test.c100644 1750 1750 4310 11211710410 22270 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2008 Michael Bell * Copyright (C) 2008 Juha Tuomola * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ /** Test environment: * * Single address book sync: * syncml-ds-tool * -b 00:00:00:00:00:00 11 * --identifier "PC Suite" * --wbxml --dumpinfo * --slow-sync text/x-vcard Contacts * * Combined address book and calendar sync results in a crash of * the phone software but it restarts wihtout the PIN. * * Version: * syncml-ds-tool --version * 0.4.7 (Revision: 624) * */ /* Description of the mobile: * * Mobile: Nokia 6230 (without i - old Nokia Series 40) * FirmwareVersion: V 05.50 * SoftwareVersion: V 05.50 * HardwareVersion: 0606 * * (This is not the original firmware version * because original version does not support SyncML.) * * The mobile does not support: * * - UTC * - SupportLargeObjects * - SupportNumberOfChanges */ #include "../test_mobile.c" SmlTransportType tspType = SML_TRANSPORT_OBEX_CLIENT; const char *obex_port = "10202"; const char *enableWbxml = "1"; const char *useTimestamp = "1"; const char *mobile_name = "Nokia 6230 (without i)"; const char *maxMsgSize = "1024000"; const char *maxObjSize = "65535"; const char *identifier = "PC Suite"; const char *locList[] = {"Contacts", SML_ELEMENT_TEXT_VCARD, NULL, NULL}; libsyncml-0.5.4/tests/mobiles/nokia_6230_vcard/sent-2.xml100644 1750 1750 2307 11211710410 23003 0ustar00bellmichbellmich 1.1SyncML/1.1103IMEI:123456789012345PC Suite3584 120SyncHdrPC SuiteIMEI:123456789012345200 725Results./devinf11200 826SyncContacts/telecom/pb.vcf200 927Add9201 10/telecom/pb.vcfContacts libsyncml-0.5.4/tests/mobiles/nokia_6230_vcard/sent-1.wbxml100644 1750 1750 3443 11211710410 23335 0ustar00bellmichbellmichŸSjmlq1.1rSyncML/1.1e10[2nWIMEI:123456789012345gWPC SuiteZL3584kiK1\1L0JSyncHdroPC SuitehIMEI:123456789012345O200iK2\1L3JAlertoContactsh/telecom/pb.vcfO508TOEO1FK3O201TnW/telecom/pb.vcfgWContactsZEO20080904T151703Z_K4ZSapplication/vnd.syncml-devinf+wbxmlTgW./devinf11OÊKŸTjJe1.1QOpenSyncUlibsyncmlVLinuxO2.6.25-2-686^0.4.7IPC SuiteKserver(*)G]ContactsZFtext/x-vcardd2.1YFtext/vcardd3.0bFtext/x-vcardd2.1aFtext/vcardd3.0_`1`2`7EFtext/x-vcardXADRWTYPEcHOMEcWORKcPARCELcPOSTALcINTLcDOMWHOMEWWORKWPARCELWPOSTALWINTLWDOMXAGENTXBDAYXBEGINcVCARDXENDcVCARDXEMAILWTYPEcINTERNETWINTERNETXFNXGEOXKEYWTYPEcX509cPGPWX509WPGPXLABELWTYPEcHOMEcWORKcPARCELcPOSTALcINTLcDOMWHOMEWWORKWPARCELWPOSTALWINTLWDOMXLOGOWTYPEcJPEGWJPEGXMAILERXNXNOTEXORGXPHOTOWTYPEcJPEGWJPEGXREVXROLEXSOUNDWTYPEcAIFFcPCMcWAVEWAIFFWPCMWWAVEXTELWTYPEcWORKcVOICEcPREFcPAGERcMSGcMODEMcISDNcHOMEcFAXcCELLcCARcBBSWWORKWVOICEWPREFWPAGERWMSGWMODEMWISDNWHOMEWFAXWCELLWCARWBBSXTITLEXTZXUIDXURLWTYPEcWORKcHOMEWWORKWHOMEXVERSIONc2.1Ftext/vcardXBEGINcVCARDXENDcVCARDXVERSIONc3.0XREVXNXTITLEXCATEGORIESXCLASSXORGXEMAILXURLXTELWTYPEcCELLcHOMEcWORKcFAXcMODEMcVOICEXADRWTYPEcHOMEcWORKXBDAYXNOTEXPHOTOWTYPESK5ZSapplication/vnd.syncml-devinf+wbxmlTnW./devinf11libsyncml-0.5.4/tests/mobiles/nokia_6230_vcard/received-0.wbxml100644 1750 1750 433 11211710410 24125 0ustar00bellmichbellmichŸSjmlq1.1rSyncML/1.1e10[1nWPC SuitegWIMEI:123456789012345ZL3584kiK1\1L0JSyncHdroIMEI:123456789012345hPC SuiteO200iK2\1L1JAlerthContactsO200FK3O206TnWContactsgW/telecom/pb.vcfZEJ1O1libsyncml-0.5.4/tests/mobiles/nokia_6230_vcard/sent-0.xml100644 1750 1750 1221 11211710410 22773 0ustar00bellmichbellmich 1.1SyncML/1.1118658405867742381851/PC Suite1024000 1206Contactstext/x-vcard libsyncml-0.5.4/tests/mobiles/nokia_6230_vcard/sent-0.wbxml100644 1750 1750 230 11211710410 23303 0ustar00bellmichbellmichŸSjmlq1.1rSyncML/1.1e11865840586774238185[1nW/gWPC SuiteZL1024000kFK1O206TgWContactsZStext/x-vcardlibsyncml-0.5.4/tests/mobiles/nokia_6230_vcard/sent-3.xml100644 1750 1750 1236 11211710410 23004 0ustar00bellmichbellmich 1.1SyncML/1.1104IMEI:123456789012345PC Suite3584 130SyncHdrPC SuiteIMEI:123456789012345200 libsyncml-0.5.4/tests/mobiles/nokia_6230_vcard/received-1.xml100644 1750 1750 10263 11211710410 23637 0ustar00bellmichbellmich1.1SyncML/1.1102PC SuiteIMEI:123456789012345120SyncHdrIMEI:123456789012345PC Suite200223Alert/telecom/pb.vcfContacts20020080904T151703Z324Put./devinf11200425Get./devinf11200525./devinf11./devinf11application/vnd.syncml-devinf+xml1.1NokiaNokia 6230V 05.50V 05.500606IMEI:123456789012345phone/telecom/pb.vcf8text/x-vcard2.1text/x-vcard2.1127/telecom/cal.vcs8text/x-vcalendar1.0text/x-vcalendar1.0127/telecom/note.txt8text/plaintext/plain127text/x-vcardBEGINVCARDVERSION2.1ENDVCARDNTELPREFWORKHOMEVOICEFAXCELLNOTEURLEMAILLABELtext/x-vcalendarBEGINVCALENDARVEVENTVTODOVERSION1.0ENDVCALENDARVEVENTVTODODTSTARTdatetimeDTENDdatetimeSUMMARYDUEAALARMdatetimeDALARMdatetimeRRULECATEGORIESLOCATIONSTATUSPRIORITYEXDATEtext/plainchr30006Contacts/telecom/pb.vcf999009997text/x-vcard9 libsyncml-0.5.4/tests/mobiles/remove_IMEI.sh100644 1750 1750 175 11211710410 20634 0ustar00bellmichbellmich#!/bin/bash # for f in *xml do echo "processing File $f" sed -i -r -e "s/IMEI:[0-9]{15}/IMEI:123456789012345/g" $f done libsyncml-0.5.4/tests/mobiles/nokia_e65_vcard_vcal/sent-1.xml100644 1750 1750 21337 11211710410 24040 0ustar00bellmichbellmich 1.1SyncML/1.152IMEI:123456789012345PC Suite65535 110SyncHdrPC SuiteIMEI:123456789012345200 214Alert./Calendar./C:Calendar20020080210T072716Z 315Alert./Contacts./C:Contacts.cdb50820080210T072716Z 416Put./devinf11200 517Get./devinf11200 6201./C:CalendarCalendar20080903T074757Z 7201./C:Contacts.cdbContacts20080903T074757Z 817application/vnd.syncml-devinf+xml./devinf11./devinf111.1OpenSynclibsyncmlLinux2.6.25.14-108.fc9.x86_640.4.7PC SuiteserverContactstext/x-vcard2.1text/vcard3.0text/x-vcard2.1text/vcard3.0127Calendartext/x-vcalendar1.0text/calendar2.0text/x-vcalendar1.0text/calendar2.0127text/x-vcardADRTYPEHOMEWORKPARCELPOSTALINTLDOMHOMEWORKPARCELPOSTALINTLDOMAGENTBDAYBEGINVCARDENDVCARDEMAILTYPEINTERNETINTERNETFNGEOKEYTYPEX509PGPX509PGPLABELTYPEHOMEWORKPARCELPOSTALINTLDOMHOMEWORKPARCELPOSTALINTLDOMLOGOTYPEJPEGJPEGMAILERNNOTEORGPHOTOTYPEJPEGJPEGREVROLESOUNDTYPEAIFFPCMWAVEAIFFPCMWAVETELTYPEWORKVOICEPREFPAGERMSGMODEMISDNHOMEFAXCELLCARBBSWORKVOICEPREFPAGERMSGMODEMISDNHOMEFAXCELLCARBBSTITLETZUIDURLTYPEWORKHOMEWORKHOMEVERSION2.1text/vcardBEGINVCARDENDVCARDVERSION3.0REVNTITLECATEGORIESCLASSORGEMAILURLTELTYPECELLHOMEWORKFAXMODEMVOICEADRTYPEHOMEWORKBDAYNOTEPHOTOTYPEtext/x-vcalendarAALARMATTACHATTENDEEEXCEPTRSVPSTATUSROLEBEGINVCALENDARVEVENTVTODOCATEGORIESCOMPLETEDCLASSPUBLICPRIVATECONFIDENTIALDALARMDAYLIGHTDCREATEDDESCRIPTIONDTSTARTDTENDDUEENDVCALENDARVEVENTVTODOEXDATELAST-MODIFIEDLOCATIONPRIORITYRRULESTATUSSUMMARYUIDVERSION1.0text/calendarAALARMATTACHATTENDEERSVPPARTSTATROLEBEGINVCALENDARVEVENTVTODOCATEGORIESCOMPLETEDCLASSPUBLICPRIVATECONFIDENTIALDALARMDAYLIGHTDCREATEDDESCRIPTIONDTSTARTDTENDDUEENDVCALENDARVEVENTVTODOEXDATELAST-MODIFIEDLOCATIONPRIORITYRRULESTATUSSUMMARYUIDVERSION2.0 libsyncml-0.5.4/tests/mobiles/nokia_e65_vcard_vcal/sent-2.wbxml100644 1750 1750 761 11211710410 24330 0ustar00bellmichbellmichŸSjmlq1.1rSyncML/1.1e5[3nWIMEI:123456789012345gWPC SuiteZL65535kiK1\2L0JSyncHdroPC SuitehIMEI:123456789012345O200iK10\2L5JSynco./Calendarh./C:CalendarO200iK11\2L6JAddh2O201iK12\2L7JSynco./Contactsh./C:Contacts.cdbO200iK13\2L8JAddh1O201jK14nW./C:Contacts.cdbgWContactsZU65535s0jK15nW./C:CalendargWCalendarZU65535s0libsyncml-0.5.4/tests/mobiles/nokia_e65_vcard_vcal/sent-3.wbxml100644 1750 1750 251 11211710410 24323 0ustar00bellmichbellmichŸSjmlq1.1rSyncML/1.1e5[4nWIMEI:123456789012345gWPC SuiteZL65535kiK1\3L0JSyncHdroPC SuitehIMEI:123456789012345O200libsyncml-0.5.4/tests/mobiles/nokia_e65_vcard_vcal/received-0.xml100644 1750 1750 21473 11211710410 24655 0ustar00bellmichbellmich1.1SyncML/1.151PC SuiteIMEI:12345678901234565535110SyncHdr/PC Suite200211AlertContacts200312AlertCalendar2004201./Calendar./C:Calendar20080210T072716Z5200./Contacts./C:Contacts.cdb20080210T072026Z20080210T072716Z6application/vnd.syncml-devinf+xml./devinf111.1NOKIAE651.0633.18.01IMEI:123456789012345phone./C:CalendarCalendar8text/x-vcalendar1.0text/x-vcalendar1.01234567./C:Contacts.cdbContacts8text/x-vcard2.1text/x-vcard2.11234567text/x-vcalendarBEGINVCALENDARVEVENTVTODOBeginENDVCALENDARVEVENTVTODOEndVERSION1.0VersionUID256UidSUMMARY256SummaryDESCRIPTION256DescriptionDTSTART256DstartDTEND256DtendAALARM256AalarmCLASSPUBLICPRIVATECONFIDENTIALClassLOCATION256LocationLAST-MODIFIED256Last ModifiedPRIORITY256PrioritySTATUS256StatusRRULE256RruleCOMPLETED256CompletedDCREATED256DcreatedDUE256DueEXDATE256ExDateCATEGORIES256CategoriesSEQUENCE256SequenceTZ256TZDAYLIGHT256DaylightRDATE256RDateATTENDEE256AttendeeROLERoleSTATUSStatusX-CNX-CNX-ROLERoleX-SENTBYSent byX-RECURRENCE-ID256RecurrenceX-METHOD256MethodX-SYMBIAN-LUID256Local UIDX-SYMBIAN-DTSTAMP256Time stampX-EPOCAGENDAENTRYTYPE256X-Epoc Agenda Entry Typetext/x-vcardBEGINVCARDBeginENDVCARDEndVERSION2.1VersionREV256RevisionN256NameADR256AddressHOMEHome addressWORKWork addressTEL256Telephone numberHOMEHome telephoneWORKWork telephoneCELLCellular numberPAGERPager numberFAXFax numberVIDEOVideo numberPREFDefault numberFN256FullNameEMAIL256Email addressHOMEHome emailWORKWork emailURL256URL addressHOMEHome URLWORKWork URLNOTE256NoteTITLE256TitleORG256OrganisationPHOTO256PhotoBDAY256BirthdaySOUND256SoundX-WV-ID256Wireless Village IdX-EPOCSECONDNAME256NicknameX-SIP256SIP protocolPOCPOCSWISSWISVOIPVoice over IP7application/vnd.syncml-devinf+xml./devinf11 libsyncml-0.5.4/tests/mobiles/nokia_e65_vcard_vcal/received-2.xml100644 1750 1750 1746 11211710410 24640 0ustar00bellmichbellmich1.1SyncML/1.153PC SuiteIMEI:12345678901234565535130SyncHdrIMEI:123456789012345PC Suite2002314Sync./C:Contacts.cdbContacts2003315Sync./C:CalendarCalendar200 libsyncml-0.5.4/tests/mobiles/nokia_e65_vcard_vcal/received-2.wbxml100644 1750 1750 447 11211710410 25146 0ustar00bellmichbellmichŸSjmlqÃ1.1rà SyncML/1.1eÃ5[Ã3nWÃPC SuitegWÃIMEI:123456789012345ZLÃ65535kiKÃ1\Ã3LÃ0JÃSyncHdroÃIMEI:123456789012345hÃPC SuiteOÃ200iKÃ2\Ã3LÃ14JÃSyncoÃ./C:Contacts.cdbhÃContactsOÃ200iKÃ3\Ã3LÃ15JÃSyncoà ./C:CalendarhÃCalendarOÃ200libsyncml-0.5.4/tests/mobiles/nokia_e65_vcard_vcal/received-1.wbxml100644 1750 1750 1666 11211710410 25171 0ustar00bellmichbellmichŸSjmlqÃ1.1rà SyncML/1.1eÃ5[Ã2nWÃPC SuitegWÃIMEI:123456789012345ZLÃ65535kiKÃ1\Ã2LÃ0JÃSyncHdroÃIMEI:123456789012345hÃPC SuiteOÃ200iKÃ2\Ã2LÃ6JÃAlertoà ./C:CalendarhÃCalendarOÃ200TOEOÃ20080903T074757ZiKÃ3\Ã2LÃ7JÃAlertoÃ./C:Contacts.cdbhÃContactsOÃ200TOEOÃ20080903T074757ZiKÃ4\Ã2LÃ8JÃResultsOÃ200jKÃ5nWà ./CalendargWà ./C:CalendarZUÃ1048576sÃ1EKÃ6TgWÃ2ZSÃtext/x-vcalendarTÃ1.0OÃmBEGIN:VCALENDAR VERSION:1.0 BEGIN:VEVENT UID:6A80uF7y4EEVe62AEDCyD0 SUMMARY:Test1 DTSTART:20080209T060000Z DTEND:20080209T060000Z CLASS:PRIVATE LOCATION:Abc LAST-MODIFIED:20080209T172933Z PRIORITY:2 END:VEVENT END:VCALENDAR jKÃ7nWà ./ContactsgWÃ./C:Contacts.cdbZUÃ102400sÃ1EKÃ8TgWÃ1ZSà text/x-vcardTÃ2.1OÃ[BEGIN:VCARD VERSION:2.1 REV:20080209T172846Z N:Doe;John;;; TEL;VOICE:12345 END:VCARD libsyncml-0.5.4/tests/mobiles/nokia_e65_vcard_vcal/test.c100644 1750 1750 3624 11211710410 23311 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2008 Michael Bell * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ /** Test environment: * * Combined address book and calendar sync: * syncml-ds-tool * -b 00:00:00:00:00:00 10 * --identifier "PC Suite" * --wbxml --dumpinfo * --slow-sync text/x-vcard Contacts * --slow-sync text/x-vcalendar Calendar * * Version: * syncml-ds-tool --version * 0.4.7 (Revision: 614) * */ /** Description of the mobile: * * Mobile: Nokia E65 (Nokia Series 60) * FirmwareVersion: - * SoftwareVersion: 1.0633.18.01 * HardwareVersion: - * */ #include "../test_mobile.c" SmlTransportType tspType = SML_TRANSPORT_OBEX_CLIENT; const char *obex_port = "10207"; const char *enableWbxml = "1"; const char *useTimestamp = "1"; const char *mobile_name = "Nokia E65"; const char *maxMsgSize = "1024000"; const char *maxObjSize = "65535"; const char *identifier = "PC Suite"; const char *locList[] = {"Contacts", SML_ELEMENT_TEXT_VCARD, "Calendar", SML_ELEMENT_TEXT_VCAL, NULL, NULL}; libsyncml-0.5.4/tests/mobiles/nokia_e65_vcard_vcal/sent-2.xml100644 1750 1750 3254 11211710410 24017 0ustar00bellmichbellmich 1.1SyncML/1.153IMEI:123456789012345PC Suite65535 120SyncHdrPC SuiteIMEI:123456789012345200 1025Sync./Calendar./C:Calendar200 1126Add2201 1227Sync./Contacts./C:Contacts.cdb200 1328Add1201 14./C:Contacts.cdbContacts655350 15./C:CalendarCalendar655350 libsyncml-0.5.4/tests/mobiles/nokia_e65_vcard_vcal/sent-1.wbxml100644 1750 1750 5747 11211710410 24360 0ustar00bellmichbellmichŸSjmlq1.1rSyncML/1.1e5[2nWIMEI:123456789012345gWPC SuiteZL65535kiK1\1L0JSyncHdroPC SuitehIMEI:123456789012345O200iK2\1L4JAlerto./Calendarh./C:CalendarO200TOEO20080210T072716ZiK3\1L5JAlerto./Contactsh./C:Contacts.cdbO508TOEO20080210T072716ZiK4\1L6JPuth./devinf11O200iK5\1L7JGeto./devinf11O200FK6O201TnW./C:CalendargWCalendarZEO20080903T074757ZFK7O201TnW./C:Contacts.cdbgWContactsZEO20080903T074757ZbK8\1L7ZSapplication/vnd.syncml-devinf+wbxmlo./devinf11TgW./devinf11OÃ’'ŸTjJe1.1QOpenSyncUlibsyncmlVLinuxO2.6.25.14-108.fc9.x86_64^0.4.7IPC SuiteKserver(*)G]ContactsZFtext/x-vcardd2.1YFtext/vcardd3.0bFtext/x-vcardd2.1aFtext/vcardd3.0_`1`2`7G]CalendarZFtext/x-vcalendard1.0YFtext/calendard2.0bFtext/x-vcalendard1.0aFtext/calendard2.0_`1`2`7EFtext/x-vcardXADRWTYPEcHOMEcWORKcPARCELcPOSTALcINTLcDOMWHOMEWWORKWPARCELWPOSTALWINTLWDOMXAGENTXBDAYXBEGINcVCARDXENDcVCARDXEMAILWTYPEcINTERNETWINTERNETXFNXGEOXKEYWTYPEcX509cPGPWX509WPGPXLABELWTYPEcHOMEcWORKcPARCELcPOSTALcINTLcDOMWHOMEWWORKWPARCELWPOSTALWINTLWDOMXLOGOWTYPEcJPEGWJPEGXMAILERXNXNOTEXORGXPHOTOWTYPEcJPEGWJPEGXREVXROLEXSOUNDWTYPEcAIFFcPCMcWAVEWAIFFWPCMWWAVEXTELWTYPEcWORKcVOICEcPREFcPAGERcMSGcMODEMcISDNcHOMEcFAXcCELLcCARcBBSWWORKWVOICEWPREFWPAGERWMSGWMODEMWISDNWHOMEWFAXWCELLWCARWBBSXTITLEXTZXUIDXURLWTYPEcWORKcHOMEWWORKWHOMEXVERSIONc2.1Ftext/vcardXBEGINcVCARDXENDcVCARDXVERSIONc3.0XREVXNXTITLEXCATEGORIESXCLASSXORGXEMAILXURLXTELWTYPEcCELLcHOMEcWORKcFAXcMODEMcVOICEXADRWTYPEcHOMEcWORKXBDAYXNOTEXPHOTOWTYPEFtext/x-vcalendarXAALARMXATTACHXATTENDEEWEXCEPTWRSVPWSTATUSWROLEXBEGINcVCALENDARcVEVENTcVTODOXCATEGORIESXCOMPLETEDXCLASScPUBLICcPRIVATEcCONFIDENTIALXDALARMXDAYLIGHTXDCREATEDXDESCRIPTIONXDTSTARTXDTENDXDUEXENDcVCALENDARcVEVENTcVTODOXEXDATEXLAST-MODIFIEDXLOCATIONXPRIORITYXRRULEXSTATUSXSUMMARYXUIDXVERSIONc1.0Ftext/calendarXAALARMXATTACHXATTENDEEWRSVPWPARTSTATWROLEXBEGINcVCALENDARcVEVENTcVTODOXCATEGORIESXCOMPLETEDXCLASScPUBLICcPRIVATEcCONFIDENTIALXDALARMXDAYLIGHTXDCREATEDXDESCRIPTIONXDTSTARTXDTENDXDUEXENDcVCALENDARcVEVENTcVTODOXEXDATEXLAST-MODIFIEDXLOCATIONXPRIORITYXRRULEXSTATUSXSUMMARYXUIDXVERSIONc2.0libsyncml-0.5.4/tests/mobiles/nokia_e65_vcard_vcal/received-0.wbxml100644 1750 1750 6172 11211710410 25165 0ustar00bellmichbellmichŸSjmlqÃ1.1rà SyncML/1.1eÃ5[Ã1nWÃPC SuitegWÃIMEI:123456789012345ZLÃ65535kiKÃ1\Ã1LÃ0JÃSyncHdroÃ/hÃPC SuiteOÃ200iKÃ2\Ã1LÃ1JÃAlerthÃContactsOÃ200iKÃ3\Ã1LÃ2JÃAlerthÃCalendarOÃ200FKÃ4OÃ201TnWà ./CalendargWà ./C:CalendarZEJÃOÃ20080210T072716ZFKÃ5OÃ200TnWà ./ContactsgWÃ./C:Contacts.cdbZEJÃ20080210T072026ZOÃ20080210T072716Z_KÃ6ZSÃ#application/vnd.syncml-devinf+wbxmlTgWà ./devinf11OÔAŸTjJeÃ1.1QÃNOKIAUÃE65OÃ^à 1.0633.18.01PÃIÃIMEI:123456789012345KÃphone(*)G]à ./C:CalendarLÃCalendarRÃ8ZFÃtext/x-vcalendardÃ1.0bFÃtext/x-vcalendardÃ1.0_`Ã1`Ã2`Ã3`Ã4`Ã5`Ã6`Ã7G]Ã./C:Contacts.cdbLÃContactsRÃ8ZFà text/x-vcarddÃ2.1bFà text/x-vcarddÃ2.1_`Ã1`Ã2`Ã3`Ã4`Ã5`Ã6`Ã7EFÃtext/x-vcalendarXÃBEGINcà VCALENDARcÃVEVENTcÃVTODOLÃBeginXÃENDcà VCALENDARcÃVEVENTcÃVTODOLÃEndXÃVERSIONcÃ1.0LÃVersionXÃUIDHÃ\Ã256LÃUidXÃSUMMARYHÃ\Ã256LÃSummaryXà DESCRIPTIONHÃ\Ã256Là DescriptionXÃDTSTARTHÃ\Ã256LÃDstartXÃDTENDHÃ\Ã256LÃDtendXÃAALARMHÃ\Ã256LÃAalarmXÃCLASScÃPUBLICcÃPRIVATEcà CONFIDENTIALLÃClassXÃLOCATIONHÃ\Ã256LÃLocationXà LAST-MODIFIEDHÃ\Ã256Là Last ModifiedXÃPRIORITYHÃ\Ã256LÃPriorityXÃSTATUSHÃ\Ã256LÃStatusXÃRRULEHÃ\Ã256LÃRruleXà COMPLETEDHÃ\Ã256Là CompletedXÃDCREATEDHÃ\Ã256LÃDcreatedXÃDUEHÃ\Ã256LÃDueXÃEXDATEHÃ\Ã256LÃExDateXà CATEGORIESHÃ\Ã256Là CategoriesXÃSEQUENCEHÃ\Ã256LÃSequenceXÃTZHÃ\Ã256LÃTZXÃDAYLIGHTHÃ\Ã256LÃDaylightXÃRDATEHÃ\Ã256LÃRDateXÃATTENDEEHÃ\Ã256LÃAttendeeWÃROLEHÃLÃRoleWÃSTATUSHÃLÃStatusWÃX-CNHÃLÃX-CNWÃX-ROLEHÃLÃRoleWÃX-SENTBYHÃLÃSent byXÃX-RECURRENCE-IDHÃ\Ã256Là RecurrenceXÃX-METHODHÃ\Ã256LÃMethodXÃX-SYMBIAN-LUIDHÃ\Ã256Là Local UIDXÃX-SYMBIAN-DTSTAMPHÃ\Ã256Là Time stampXÃX-EPOCAGENDAENTRYTYPEHÃ\Ã256LÃX-Epoc Agenda Entry TypeFà text/x-vcardXÃBEGINcÃVCARDLÃBeginXÃENDcÃVCARDLÃEndXÃVERSIONcÃ2.1LÃVersionXÃREVHÃ\Ã256LÃRevisionXÃNHÃ\Ã256LÃNameXÃADRHÃ\Ã256LÃAddressWÃHOMEHÃLà Home addressWÃWORKHÃLà Work addressXÃTELHÃ\Ã256LÃTelephone numberWÃHOMEHÃLÃHome telephoneWÃWORKHÃLÃWork telephoneWÃCELLHÃLÃCellular numberWÃPAGERHÃLà Pager numberWÃFAXHÃLà Fax numberWÃVIDEOHÃLà Video numberWÃPREFHÃLÃDefault numberXÃFNHÃ\Ã256LÃFullNameXÃEMAILHÃ\Ã256Là Email addressWÃHOMEHÃLà Home emailWÃWORKHÃLà Work emailXÃURLHÃ\Ã256Là URL addressWÃHOMEHÃLÃHome URLWÃWORKHÃLÃWork URLXÃNOTEHÃ\Ã256LÃNoteXÃTITLEHÃ\Ã256LÃTitleXÃORGHÃ\Ã256Là OrganisationXÃPHOTOHÃ\Ã256LÃPhotoXÃBDAYHÃ\Ã256LÃBirthdayXÃSOUNDHÃ\Ã256LÃSoundXÃX-WV-IDHÃ\Ã256LÃWireless Village IdXÃX-EPOCSECONDNAMEHÃ\Ã256LÃNicknameXÃX-SIPHÃ\Ã256Là SIP protocolWÃPOCHÃLÃPOCWÃSWISHÃLÃSWISWÃVOIPHÃLà Voice over IPSKÃ7ZSÃ#application/vnd.syncml-devinf+wbxmlTnWà ./devinf11libsyncml-0.5.4/tests/mobiles/nokia_e65_vcard_vcal/sent-0.xml100644 1750 1750 1467 11211710410 24021 0ustar00bellmichbellmich 1.1SyncML/1.171803155899344065061/PC Suite1024000 1206Contactstext/x-vcard 2206Calendartext/x-vcalendar libsyncml-0.5.4/tests/mobiles/nokia_e65_vcard_vcal/sent-0.wbxml100644 1750 1750 317 11211710410 24323 0ustar00bellmichbellmichŸSjmlq1.1rSyncML/1.1e7180315589934406506[1nW/gWPC SuiteZL1024000kFK1O206TgWContactsZStext/x-vcardFK2O206TgWCalendarZStext/x-vcalendarlibsyncml-0.5.4/tests/mobiles/nokia_e65_vcard_vcal/sent-3.xml100644 1750 1750 1236 11211710410 24016 0ustar00bellmichbellmich 1.1SyncML/1.154IMEI:123456789012345PC Suite65535 130SyncHdrPC SuiteIMEI:123456789012345200 libsyncml-0.5.4/tests/mobiles/nokia_e65_vcard_vcal/received-1.xml100644 1750 1750 4631 11211710410 24633 0ustar00bellmichbellmich1.1SyncML/1.152PC SuiteIMEI:12345678901234565535120SyncHdrIMEI:123456789012345PC Suite200226Alert./C:CalendarCalendar20020080903T074757Z327Alert./C:Contacts.cdbContacts20020080903T074757Z428Results2005./Calendar./C:Calendar1048576162text/x-vcalendar1.07./Contacts./C:Contacts.cdb102400181text/x-vcard2.1 libsyncml-0.5.4/tests/mobiles/nokia_9500_vcal/sent-1.xml100644 1750 1750 10456 11211710410 22657 0ustar00bellmichbellmich 1.1SyncML/1.12252IMEI:123456789012345PC Suite10000 110SyncHdrPC SuiteIMEI:123456789012345200 213Alert./Calendar./C\System\Data\Calendar50820080905T111713Z 3201./C\System\Data\Calendar./Calendar20080905T112234Z 4application/vnd.syncml-devinf+xml./devinf111.1OpenSynclibsyncmlLinux2.6.25-2-6860.4.7PC Suiteserver./Calendartext/x-vcalendar1.0text/calendar2.0text/x-vcalendar1.0text/calendar2.0127text/x-vcalendarAALARMATTACHATTENDEEEXCEPTRSVPSTATUSROLEBEGINVCALENDARVEVENTVTODOCATEGORIESCOMPLETEDCLASSPUBLICPRIVATECONFIDENTIALDALARMDAYLIGHTDCREATEDDESCRIPTIONDTSTARTDTENDDUEENDVCALENDARVEVENTVTODOEXDATELAST-MODIFIEDLOCATIONPRIORITYRRULESTATUSSUMMARYUIDVERSION1.0text/calendarAALARMATTACHATTENDEERSVPPARTSTATROLEBEGINVCALENDARVEVENTVTODOCATEGORIESCOMPLETEDCLASSPUBLICPRIVATECONFIDENTIALDALARMDAYLIGHTDCREATEDDESCRIPTIONDTSTARTDTENDDUEENDVCALENDARVEVENTVTODOEXDATELAST-MODIFIEDLOCATIONPRIORITYRRULESTATUSSUMMARYUIDVERSION2.0 5application/vnd.syncml-devinf+xml./devinf11 libsyncml-0.5.4/tests/mobiles/nokia_9500_vcal/sent-2.wbxml100644 1750 1750 673 11211710410 23151 0ustar00bellmichbellmichŸSjmlq1.1rSyncML/1.1e225[3nWIMEI:123456789012345gWPC SuiteZL10000kiK1\2L0JSyncHdroPC SuitehIMEI:123456789012345O200iK7\2L5JResultsh./devinf11O200iK8\2L6JSynco./Calendarh./C\System\Data\CalendarO200iK9\2L7JAddh4O201iK10\2L8JAddh5O201jK11nW./C\System\Data\CalendargW./CalendarZU1024000s0libsyncml-0.5.4/tests/mobiles/nokia_9500_vcal/sent-3.wbxml100644 1750 1750 253 11211710410 23144 0ustar00bellmichbellmichŸSjmlq1.1rSyncML/1.1e225[4nWIMEI:123456789012345gWPC SuiteZL10000kiK1\3L0JSyncHdroPC SuitehIMEI:123456789012345O200libsyncml-0.5.4/tests/mobiles/nokia_9500_vcal/received-0.xml100644 1750 1750 2030 11211710410 23440 0ustar00bellmichbellmich1.1SyncML/1.12251PC SuiteIMEI:12345678901234510000110SyncHdr/PC Suite200211Alert./Calendar2003200./Calendar./C\System\Data\Calendar20080905T111557Z20080905T111713Zlibsyncml-0.5.4/tests/mobiles/nokia_9500_vcal/received-2.xml100644 1750 1750 1512 11211710410 23446 0ustar00bellmichbellmich1.1SyncML/1.12253PC SuiteIMEI:12345678901234510000130SyncHdrIMEI:123456789012345PC Suite2002311Sync./C\System\Data\Calendar./Calendar200libsyncml-0.5.4/tests/mobiles/nokia_9500_vcal/received-2.wbxml100644 1750 1750 366 11211710410 23765 0ustar00bellmichbellmichŸSjmlqÃ1.1rà SyncML/1.1eÃ225[Ã3nWÃPC SuitegWÃIMEI:123456789012345ZLÃ10000kiKÃ1\Ã3LÃ0JÃSyncHdroÃIMEI:123456789012345hÃPC SuiteOÃ200iKÃ2\Ã3LÃ11JÃSyncoÃ./C\System\Data\Calendarhà ./CalendarOÃ200libsyncml-0.5.4/tests/mobiles/nokia_9500_vcal/received-1.wbxml100644 1750 1750 4610 11211710410 24000 0ustar00bellmichbellmichŸSjmlqÃ1.1rà SyncML/1.1eÃ225[Ã2nWÃPC SuitegWÃIMEI:123456789012345ZLÃ10000kiKÃ1\Ã2LÃ0JÃSyncHdroÃIMEI:123456789012345hÃPC SuiteOÃ200iKÃ2\Ã2LÃ3JÃAlertoÃ./C\System\Data\Calendarhà ./CalendarOÃ200TOEOÃ20080905T112234ZiKÃ3\Ã2LÃ4JÃPutOÃ200iKÃ4\Ã2LÃ5JÃGetOÃ200bKÃ5\Ã2LÃ5ZSÃ#application/vnd.syncml-devinf+wbxmlTgWà ./devinf11OÈ:ŸTjJeÃ1.1QÃNOKIAUÃ9500^à 05.22(01)IÃIMEI:123456789012345KÃphone(*)G]Ã./C\System\Data\CalendarRÃ8ZFÃtext/x-vcalendardÃ1.0YFà text/calendardÃ2.0bFÃtext/x-vcalendardÃ1.0_`Ã1`Ã2`Ã3`Ã4`Ã5`Ã6`Ã7EFÃtext/x-vcalendarXÃBEGINcà VCALENDARcÃVEVENTcÃVTODOXÃENDcà VCALENDARcÃVEVENTcÃVTODOXÃVERSIONcÃ1.0XÃUIDXÃSUMMARYXà DESCRIPTIONXÃDTENDXÃDTSTARTXÃAALARMWÃTYPEXÃCLASScÃPUBLICcÃPRIVATEcà CONFIDENTIALXà COMPLETEDXÃLOCATIONXÃDCREATEDXà LAST-MODIFIEDXÃPRIORITYXÃSTATUSXÃRRULEXÃDUEXÃEXDATEXÃTZXÃDAYLIGHTXÃX-EPOCAGENDAENTRYTYPEXÃX-EPOCTODOLISTXÃX-NOKIA-RECURRENCE-IDFà text/calendarXÃBEGINcà VCALENDARcÃVEVENTcÃVTODOXÃENDcà VCALENDARcÃVEVENTcÃVTODOXÃVERSIONcÃ2.0XÃUIDXÃSUMMARYXà DESCRIPTIONXÃDTENDXÃDTSTARTXÃAALARMWÃTYPEXÃCLASScÃPUBLICcÃPRIVATEcà CONFIDENTIALXà COMPLETEDXÃLOCATIONXÃDCREATEDXà LAST-MODIFIEDXÃPRIORITYXÃSTATUSXÃRRULEXÃDUEXÃEXDATEXÃTZXÃDAYLIGHTXÃX-EPOCAGENDAENTRYTYPEXÃX-EPOCTODOLISTXÃX-NOKIA-RECURRENCE-IDjKÃ6nWà ./CalendargWÃ./C\System\Data\CalendarZUÃ786432sÃ2EKÃ7ZSÃtext/x-vcalendarTgWÃ4OÂZBEGIN:VCALENDAR VERSION:1.0 TZ:+01 DAYLIGHT:TRUE;+02;20080330T000000;20081026T000000;+01;+02 BEGIN:VEVENT UID:4 SUMMARY:elke Geburtstag DESCRIPTION:amazon DTSTART:20080620T170000Z DTEND:20080620T200000Z CLASS:PUBLIC DCREATED:20080620T000000Z LAST-MODIFIED:20080620T111800Z PRIORITY:0 STATUS:NEEDS ACTION END:VEVENT END:VCALENDAR EKÃ8ZSÃtext/x-vcalendarTgWÃ5OÃ%BEGIN:VCALENDAR VERSION:1.0 TZ:+01 DAYLIGHT:TRUE;+02;20080330T000000;20081026T000000;+01;+02 BEGIN:VEVENT UID:5 SUMMARY:test event DESCRIPTION:need to test OpenSync DTSTART:20080905T070000Z DTEND:20080905T080000Z CLASS:PUBLIC DCREATED:20080905T000000Z RRULE:D1 #0 AALARM;TYPE=X-EPOCSOUND:20080905T064500Z;;0;dummy LAST-MODIFIED:20080905T091700Z PRIORITY:0 STATUS:NEEDS ACTION END:VEVENT END:VCALENDAR libsyncml-0.5.4/tests/mobiles/nokia_9500_vcal/test.c100644 1750 1750 3425 11211710410 22127 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2008 Michael Bell * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ /** Test environment: * * Single calendar sync: * syncml-ds-tool * -b 00:00:00:00:00:00 10 * --identifier "PC Suite" * --wbxml --dumpinfo * --slow-sync text/x-vcalendar ./Calendar * * Version: * syncml-ds-tool --version * 0.4.7 (Revision: 634) * */ /** Description of the mobile: * * Mobile: Nokia 9500 (Nokia Series 80) * FirmwareVersion: - * SoftwareVersion: 05.22(01) * HardwareVersion: - * */ #include "../test_mobile.c" SmlTransportType tspType = SML_TRANSPORT_OBEX_CLIENT; const char *obex_port = "10203"; const char *enableWbxml = "1"; const char *useTimestamp = "1"; const char *mobile_name = "Nokia 9500"; const char *maxMsgSize = "65535"; const char *maxObjSize = "1024000"; const char *identifier = "PC Suite"; const char *locList[] = {"./Calendar", SML_ELEMENT_TEXT_VCAL, NULL, NULL}; libsyncml-0.5.4/tests/mobiles/nokia_9500_vcal/sent-2.xml100644 1750 1750 2703 11211710410 22634 0ustar00bellmichbellmich 1.1SyncML/1.12253IMEI:123456789012345PC Suite10000 120SyncHdrPC SuiteIMEI:123456789012345200 725Results./devinf11200 826Sync./Calendar./C\System\Data\Calendar200 927Add4201 1028Add5201 11./C\System\Data\Calendar./Calendar10240000 libsyncml-0.5.4/tests/mobiles/nokia_9500_vcal/sent-1.wbxml100644 1750 1750 3065 11211710410 23166 0ustar00bellmichbellmichŸSjmlq1.1rSyncML/1.1e225[2nWIMEI:123456789012345gWPC SuiteZL10000kiK1\1L0JSyncHdroPC SuitehIMEI:123456789012345O200iK2\1L3JAlerto./Calendarh./C\System\Data\CalendarO508TOEO20080905T111713ZFK3O201TnW./C\System\Data\CalendargW./CalendarZEO20080905T112234Z_K4ZSapplication/vnd.syncml-devinf+wbxmlTgW./devinf11OÈ6ŸTjJe1.1QOpenSyncUlibsyncmlVLinuxO2.6.25-2-686^0.4.7IPC SuiteKserver(*)G]./CalendarZFtext/x-vcalendard1.0YFtext/calendard2.0bFtext/x-vcalendard1.0aFtext/calendard2.0_`1`2`7EFtext/x-vcalendarXAALARMXATTACHXATTENDEEWEXCEPTWRSVPWSTATUSWROLEXBEGINcVCALENDARcVEVENTcVTODOXCATEGORIESXCOMPLETEDXCLASScPUBLICcPRIVATEcCONFIDENTIALXDALARMXDAYLIGHTXDCREATEDXDESCRIPTIONXDTSTARTXDTENDXDUEXENDcVCALENDARcVEVENTcVTODOXEXDATEXLAST-MODIFIEDXLOCATIONXPRIORITYXRRULEXSTATUSXSUMMARYXUIDXVERSIONc1.0Ftext/calendarXAALARMXATTACHXATTENDEEWRSVPWPARTSTATWROLEXBEGINcVCALENDARcVEVENTcVTODOXCATEGORIESXCOMPLETEDXCLASScPUBLICcPRIVATEcCONFIDENTIALXDALARMXDAYLIGHTXDCREATEDXDESCRIPTIONXDTSTARTXDTENDXDUEXENDcVCALENDARcVEVENTcVTODOXEXDATEXLAST-MODIFIEDXLOCATIONXPRIORITYXRRULEXSTATUSXSUMMARYXUIDXVERSIONc2.0SK5ZSapplication/vnd.syncml-devinf+wbxmlTnW./devinf11libsyncml-0.5.4/tests/mobiles/nokia_9500_vcal/received-0.wbxml100644 1750 1750 465 11211710410 23763 0ustar00bellmichbellmichŸSjmlqÃ1.1rà SyncML/1.1eÃ225[Ã1nWÃPC SuitegWÃIMEI:123456789012345ZLÃ10000kiKÃ1\Ã1LÃ0JÃSyncHdroÃ/hÃPC SuiteOÃ200iKÃ2\Ã1LÃ1JÃAlerthà ./CalendarOÃ200FKÃ3OÃ200TnWà ./CalendargWÃ./C\System\Data\CalendarZEJÃ20080905T111557ZOÃ20080905T111713Zlibsyncml-0.5.4/tests/mobiles/nokia_9500_vcal/sent-0.xml100644 1750 1750 1222 11211710410 22625 0ustar00bellmichbellmich 1.1SyncML/1.1866000443379172891/PC Suite65535 1206./Calendartext/x-vcalendar libsyncml-0.5.4/tests/mobiles/nokia_9500_vcal/sent-0.wbxml100644 1750 1750 231 11211710410 23135 0ustar00bellmichbellmichŸSjmlq1.1rSyncML/1.1e86600044337917289[1nW/gWPC SuiteZL65535kFK1O206TgW./CalendarZStext/x-vcalendarlibsyncml-0.5.4/tests/mobiles/nokia_9500_vcal/sent-3.xml100644 1750 1750 1240 11211710410 22630 0ustar00bellmichbellmich 1.1SyncML/1.12254IMEI:123456789012345PC Suite10000 130SyncHdrPC SuiteIMEI:123456789012345200 libsyncml-0.5.4/tests/mobiles/nokia_9500_vcal/received-1.xml100644 1750 1750 12440 11211710410 23467 0ustar00bellmichbellmich1.1SyncML/1.12252PC SuiteIMEI:12345678901234510000120SyncHdrIMEI:123456789012345PC Suite200223Alert./C\System\Data\Calendar./Calendar20020080905T112234Z324Put200425Get200525application/vnd.syncml-devinf+xml./devinf111.1NOKIA9500 05.22(01)IMEI:123456789012345phone./C\System\Data\Calendar8text/x-vcalendar1.0text/calendar2.0text/x-vcalendar1.01234567text/x-vcalendarBEGINVCALENDARVEVENTVTODOENDVCALENDARVEVENTVTODOVERSION1.0UIDSUMMARYDESCRIPTIONDTENDDTSTARTAALARMTYPECLASSPUBLICPRIVATECONFIDENTIALCOMPLETEDLOCATIONDCREATEDLAST-MODIFIEDPRIORITYSTATUSRRULEDUEEXDATETZDAYLIGHTX-EPOCAGENDAENTRYTYPEX-EPOCTODOLISTX-NOKIA-RECURRENCE-IDtext/calendarBEGINVCALENDARVEVENTVTODOENDVCALENDARVEVENTVTODOVERSION2.0UIDSUMMARYDESCRIPTIONDTENDDTSTARTAALARMTYPECLASSPUBLICPRIVATECONFIDENTIALCOMPLETEDLOCATIONDCREATEDLAST-MODIFIEDPRIORITYSTATUSRRULEDUEEXDATETZDAYLIGHTX-EPOCAGENDAENTRYTYPEX-EPOCTODOLISTX-NOKIA-RECURRENCE-ID6./Calendar./C\System\Data\Calendar78643227text/x-vcalendar48text/x-vcalendar5libsyncml-0.5.4/tests/mobiles/README100644 1750 1750 4772 11211710410 17107 0ustar00bellmichbellmichHow to create a new test? ========================= 1. Create a new directory like nokia_xyz/ 2. Copy test.c from another directory to this directory 3. Modify it accordingly (e.g. name and syncml-ds-tool config) 4. Sniff an appropriate communication from syncml-ds-tool WARNING: Do not use a mobile which is in practical use for this. WARNING: Why you MUST NOT do this? WARNING: First you can compromize real person with such sniffed WARNING: communication by publishing there contact data via WARNING: synchronized vCards. WARNING: Second you can forget to replace a real IMEI with a WARNING: dummy IMEI like IMEI:123456789012345. 5. Copy all (sent|received)-*.(xml|wbxml) file produced by SYNCML_LOG into the new directory. 6. Check the XML files if there is any private data inside. If you find any private data then stop here and remove the complete directory and start again. This is critical to protect your and your contacts privacy. 7. Replace your IMEI with IMEI:123456789012345 in all files. There are two ways how to do this: 7.1. Sed - the easy way sed -r -e "s/IMEI:[0-9]{15}/IMEI:123456789012345/g" \ < received-1.wbxml > rec1.wbxml The small script remove_IMEI.sh can do this job for you. You have to call it in the directory where all the XML and WBXML files are. 7.2. Manual - the hard way 7.2.1. Edit all XML files and replace all IMEI:[0-9]{15} with IMEI:123456789012345. Every IMEI is 15 characters long. We do not validate the IMEI. Only the length is important. 7.2.2. Edit all WBXML files and replace the IMEI. See above for an example. You can use hexedit for this. - khexedit *.wbxml - Edit --> Replace Search: Regular Text: IMEI:... Replace: Regular Text: IMEI:123456789012345 8. Run "grep IMEI:x" where x is the first digit of your IMEI. If grep finds a match then please remove all files and start from scratch. Privacy protection has priority. 9. Edit CMakeLists.txt in tests/ and add your new test. Please see other ADD_MOBILE_TEST entries for an example. That's it. If you have any further question then please contact us at opensync-devel@lists.sf.net or IRC channel #opensync. If you think this is too complicated then please send your dumps to us and we will do this for you. This is the most secure way because we check too that you don't try to publish your private data by accident. 2008-Sep-05 Michael Bell libsyncml-0.5.4/tests/mobiles/nokia_6230_vcal/sent-1.xml100644 1750 1750 2464 11211710410 22634 0ustar00bellmichbellmich 1.1SyncML/1.1112IMEI:123456789012345PC Suite3584 110SyncHdrPC SuiteIMEI:123456789012345200 213AlertCalendar/telecom/cal.vcs2000 314Put./devinf11200 4201/telecom/cal.vcsCalendar20080904T151720Z libsyncml-0.5.4/tests/mobiles/nokia_6230_vcal/sent-2.wbxml100644 1750 1750 473 11211710410 23144 0ustar00bellmichbellmichŸSjmlq1.1rSyncML/1.1e11[3nWIMEI:123456789012345gWPC SuiteZL3584kiK1\2L0JSyncHdroPC SuitehIMEI:123456789012345O200iK6\2L3JSyncoCalendarh/telecom/cal.vcsO200iK7\2L4JAddh3550O201jK8nW/telecom/cal.vcsgWCalendarlibsyncml-0.5.4/tests/mobiles/nokia_6230_vcal/sent-3.wbxml100644 1750 1750 251 11211710410 23137 0ustar00bellmichbellmichŸSjmlq1.1rSyncML/1.1e11[4nWIMEI:123456789012345gWPC SuiteZL3584kiK1\3L0JSyncHdroPC SuitehIMEI:123456789012345O200libsyncml-0.5.4/tests/mobiles/nokia_6230_vcal/received-0.xml100644 1750 1750 7105 11211710410 23445 0ustar00bellmichbellmich1.1SyncML/1.1111PC SuiteIMEI:1234567890123453584110SyncHdrIMEI:123456789012345PC Suite200211AlertCalendar2003201Calendar/telecom/cal.vcs004./devinf11application/vnd.syncml-devinf+xml1.1NokiaNokia 6230V 05.50V 05.500606IMEI:123456789012345phone/telecom/pb.vcf8text/x-vcard2.1text/x-vcard2.1127/telecom/cal.vcs8text/x-vcalendar1.0text/x-vcalendar1.0127/telecom/note.txt8text/plaintext/plain127text/x-vcardBEGINVCARDVERSION2.1ENDVCARDNTELPREFWORKHOMEVOICEFAXCELLNOTEURLEMAILLABELtext/x-vcalendarBEGINVCALENDARVEVENTVTODOVERSION1.0ENDVCALENDARVEVENTVTODODTSTARTdatetimeDTENDdatetimeSUMMARYDUEAALARMdatetimeDALARMdatetimeRRULECATEGORIESLOCATIONSTATUSPRIORITYEXDATEtext/plainchr3000 libsyncml-0.5.4/tests/mobiles/nokia_6230_vcal/received-2.xml100644 1750 1750 1376 11211710410 23453 0ustar00bellmichbellmich1.1SyncML/1.1113PC SuiteIMEI:123456789012345130SyncHdrIMEI:123456789012345PC Suite200238Sync/telecom/cal.vcsCalendar200 libsyncml-0.5.4/tests/mobiles/nokia_6230_vcal/received-2.wbxml100644 1750 1750 333 11211710410 23754 0ustar00bellmichbellmichŸSjmlq1.1rSyncML/1.1e11[3nWPC SuitegWIMEI:123456789012345kiK1\3L0JSyncHdroIMEI:123456789012345hPC SuiteO200iK2\3L8JSynco/telecom/cal.vcshCalendarO200libsyncml-0.5.4/tests/mobiles/nokia_6230_vcal/received-1.wbxml100644 1750 1750 1061 11211710410 23772 0ustar00bellmichbellmichŸSjmlq1.1rSyncML/1.1e11[2nWPC SuitegWIMEI:123456789012345kiK1\2L0JSyncHdroIMEI:123456789012345hPC SuiteO200iK2\2L4JAlerto/telecom/cal.vcshCalendarO200TOEO20080904T151720ZjK3nWCalendargW/telecom/cal.vcsZMI92900H929EK4ZStext/x-vcalendarTgW3550OÃBBEGIN:VCALENDAR VERSION:1.0 BEGIN:VEVENT DTSTART:20080617T090000 DTEND:20080617T100000 DALARM:20080617T090000 CATEGORIES:MEETING SUMMARY:Test LOCATION:Berlin END:VEVENT END:VCALENDAR libsyncml-0.5.4/tests/mobiles/nokia_6230_vcal/test.c100644 1750 1750 4313 11211710410 22121 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2008 Michael Bell * Copyright (C) 2008 Juha Tuomola * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ /** Test environment: * * Single address book sync: * syncml-ds-tool * -b 00:00:00:00:00:00 11 * --identifier "PC Suite" * --wbxml --dumpinfo * --slow-sync text/x-vcalendar Calendar * * Combined address book and calendar sync results in a crash of * the phone software but it restarts wihtout the PIN. * * Version: * syncml-ds-tool --version * 0.4.7 (Revision: 624) * */ /* Description of the mobile: * * Mobile: Nokia 6230 (without i - old Nokia Series 40) * FirmwareVersion: V 05.50 * SoftwareVersion: V 05.50 * HardwareVersion: 0606 * * (This is not the original firmware version * because original version does not support SyncML.) * * The mobile does not support: * * - UTC * - SupportLargeObjects * - SupportNumberOfChanges */ #include "../test_mobile.c" SmlTransportType tspType = SML_TRANSPORT_OBEX_CLIENT; const char *obex_port = "10201"; const char *enableWbxml = "1"; const char *useTimestamp = "1"; const char *mobile_name = "Nokia 6230 (without i)"; const char *maxMsgSize = "1024000"; const char *maxObjSize = "65535"; const char *identifier = "PC Suite"; const char *locList[] = {"Calendar", SML_ELEMENT_TEXT_VCAL, NULL, NULL}; libsyncml-0.5.4/tests/mobiles/nokia_6230_vcal/sent-2.xml100644 1750 1750 2102 11211710410 22622 0ustar00bellmichbellmich 1.1SyncML/1.1113IMEI:123456789012345PC Suite3584 120SyncHdrPC SuiteIMEI:123456789012345200 623SyncCalendar/telecom/cal.vcs200 724Add3550201 8/telecom/cal.vcsCalendar libsyncml-0.5.4/tests/mobiles/nokia_6230_vcal/sent-1.wbxml100644 1750 1750 566 11211710410 23146 0ustar00bellmichbellmichŸSjmlq1.1rSyncML/1.1e11[2nWIMEI:123456789012345gWPC SuiteZL3584kiK1\1L0JSyncHdroPC SuitehIMEI:123456789012345O200iK2\1L3JAlertoCalendarh/telecom/cal.vcsO200TOEO0iK3\1L4JPuth./devinf11O200FK4O201TnW/telecom/cal.vcsgWCalendarZEO20080904T151720Zlibsyncml-0.5.4/tests/mobiles/nokia_6230_vcal/received-0.wbxml100644 1750 1750 2424 11211710410 23775 0ustar00bellmichbellmichŸSjmlq1.1rSyncML/1.1e11[1nWPC SuitegWIMEI:123456789012345ZL3584kiK1\1L0JSyncHdroIMEI:123456789012345hPC SuiteO200iK2\1L1JAlerthCalendarO200FK3O201TnWCalendargW/telecom/cal.vcsZEJ0O0_K4TgW./devinf11ZSapplication/vnd.syncml-devinf+wbxmlOÇ-ŸTj~1.1Nokia 62300606V 05.50IMEI:123456789012345NokiaJeƒQƒiUƒOƒ?^ƒ?Pƒ*IƒTKphoneG]/telecom/pb.vcfR8ZFtext/x-vcardd2.1bFtext/x-vcardd2.1_`1`2`7G]/telecom/cal.vcsR8ZFtext/x-vcalendard1.0bFtext/x-vcalendard1.0_`1`2`7G]/telecom/note.txtR8ZFtext/plaindbFtext/plaind_`1`2`7EFtext/x-vcardXBEGINcVCARDXVERSIONc2.1XENDcVCARDXNXTELWPREFWWORKWHOMEWVOICEWFAXWCELLXNOTEXURLXEMAILXLABELEFtext/x-vcalendarXBEGINcVCALENDARcVEVENTcVTODOXVERSIONc1.0XENDcVCALENDARcVEVENTcVTODOXDTSTARTHdatetimeXDTENDHdatetimeXSUMMARYXDUEXAALARMHdatetimeXDALARMHdatetimeXRRULEXCATEGORIESXLOCATIONXSTATUSXPRIORITYXEXDATEEFtext/plainXHchr\3000libsyncml-0.5.4/tests/mobiles/nokia_6230_vcal/sent-0.xml100644 1750 1750 1224 11211710410 22624 0ustar00bellmichbellmich 1.1SyncML/1.160465570802663449271/PC Suite1024000 1206Calendartext/x-vcalendar libsyncml-0.5.4/tests/mobiles/nokia_6230_vcal/sent-0.wbxml100644 1750 1750 233 11211710410 23134 0ustar00bellmichbellmichŸSjmlq1.1rSyncML/1.1e6046557080266344927[1nW/gWPC SuiteZL1024000kFK1O206TgWCalendarZStext/x-vcalendarlibsyncml-0.5.4/tests/mobiles/nokia_6230_vcal/sent-3.xml100644 1750 1750 1236 11211710410 22632 0ustar00bellmichbellmich 1.1SyncML/1.1114IMEI:123456789012345PC Suite3584 130SyncHdrPC SuiteIMEI:123456789012345200 libsyncml-0.5.4/tests/mobiles/nokia_6230_vcal/received-1.xml100644 1750 1750 2632 11211710410 23446 0ustar00bellmichbellmich1.1SyncML/1.1112PC SuiteIMEI:123456789012345120SyncHdrIMEI:123456789012345PC Suite200224Alert/telecom/cal.vcsCalendar20020080904T151720Z3Calendar/telecom/cal.vcs929009294text/x-vcalendar3550 libsyncml-0.5.4/tests/check_error.c100644 1750 1750 10776 11211710410 17250 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2005 Armin Bauer * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include "tests/support.h" #include #include START_TEST (error_create) { setup_testbed(NULL); SmlError *error = NULL; smlErrorSet(&error, SML_ERROR_GENERIC, "test%i", 1); sml_fail_unless(error != NULL, NULL); sml_fail_unless(error->type == SML_ERROR_GENERIC, NULL); sml_fail_unless(!strcmp(error->message, "test1"), NULL); sml_fail_unless(smlErrorIsSet(&error), NULL); smlErrorDeref(&error); sml_fail_unless(error == NULL, NULL); } END_TEST START_TEST (error_create_null) { setup_testbed(NULL); smlErrorSet(NULL, SML_ERROR_GENERIC, "test%i", 1); } END_TEST START_TEST (error_free_null) { setup_testbed(NULL); smlErrorDeref(NULL); } END_TEST START_TEST (error_free_null2) { setup_testbed(NULL); SmlError *error = NULL; smlErrorDeref(&error); } END_TEST START_TEST (error_free) { setup_testbed(NULL); SmlError *error = NULL; smlErrorSet(&error, SML_ERROR_GENERIC, "test"); sml_fail_unless(error != NULL, NULL); smlErrorDeref(&error); sml_fail_unless(error == NULL, NULL); } END_TEST START_TEST (error_check_null) { setup_testbed(NULL); sml_fail_unless(smlErrorIsSet(NULL) == FALSE, NULL); } END_TEST START_TEST (error_check_null2) { setup_testbed(NULL); SmlError *error = NULL; sml_fail_unless(smlErrorIsSet(&error) == FALSE, NULL); } END_TEST START_TEST (error_check) { setup_testbed(NULL); SmlError *error = NULL; smlErrorSet(&error, SML_ERROR_GENERIC, "test"); sml_fail_unless(smlErrorIsSet(&error) == TRUE, NULL); smlErrorDeref(&error); } END_TEST START_TEST (error_check2) { setup_testbed(NULL); SmlError *error = NULL; smlErrorSet(&error, SML_NO_ERROR, NULL); sml_fail_unless(smlErrorIsSet(&error) == FALSE, NULL); } END_TEST START_TEST (error_update_null) { setup_testbed(NULL); smlErrorUpdate(NULL, NULL); } END_TEST START_TEST (error_update_null2) { setup_testbed(NULL); SmlError *error = NULL; smlErrorUpdate(&error, NULL); } END_TEST START_TEST (error_update) { setup_testbed(NULL); SmlError *error = NULL; smlErrorSet(&error, SML_ERROR_GENERIC, "test"); smlErrorUpdate(&error, "test2%i", 1); sml_fail_unless(!strcmp(error->message, "test21"), NULL); smlErrorDeref(&error); } END_TEST START_TEST (error_update2) { setup_testbed(NULL); SmlError *error = NULL; smlErrorSet(&error, SML_ERROR_GENERIC, "test"); smlErrorUpdate(&error, "test2%s", error->message); sml_fail_unless(!strcmp(error->message, "test2test"), "%s != test2test", error->message); smlErrorDeref(&error); } END_TEST START_TEST (error_set_null) { setup_testbed(NULL); smlErrorSet(NULL, SML_NO_ERROR, NULL); } END_TEST START_TEST (error_set_null2) { setup_testbed(NULL); SmlError *error = NULL; smlErrorUpdate(&error, NULL); } END_TEST START_TEST (error_duplicate_null) { setup_testbed(NULL); SmlError *error = NULL; smlErrorSet(&error, SML_ERROR_GENERIC, "asd"); smlErrorDuplicate(NULL, &error); smlErrorDeref(&error); } END_TEST START_TEST (error_class) { setup_testbed(NULL); sml_fail_unless(smlErrorGetClass(NULL) == SML_ERRORCLASS_SUCCESS, NULL); SmlError *error = NULL; sml_fail_unless(smlErrorGetClass(&error) == SML_ERRORCLASS_SUCCESS, NULL); smlErrorSet(&error, SML_NO_ERROR, "test%i", 1); sml_fail_unless(smlErrorGetClass(&error) == SML_ERRORCLASS_SUCCESS, NULL); smlErrorDeref(&error); smlErrorSet(&error, SML_ERROR_SEE_OTHER_RETRY, "test%i", 1); sml_fail_unless(smlErrorGetClass(&error) == SML_ERRORCLASS_RETRY, NULL); smlErrorDeref(&error); smlErrorSet(&error, SML_ERROR_GENERIC, "test%i", 1); sml_fail_unless(smlErrorGetClass(&error) == SML_ERRORCLASS_FATAL, NULL); smlErrorDeref(&error); sml_fail_unless(error == NULL, NULL); } END_TEST @SML_TESTCASE_CODE@ libsyncml-0.5.4/tests/check_obex.c100644 1750 1750 107170 11211710410 17067 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2005 Armin Bauer * Copyright (C) 2008 Michael Bell * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include "tests/support.h" #include #include START_TEST (obex_get_result_macro) { setup_testbed(NULL); errno = 0; sml_fail_unless(GET_OBEX_RESULT(0) == 0, "return: 0 => 0"); sml_fail_unless(errno == 0, "errno: 0 => 0"); sml_fail_unless(GET_OBEX_RESULT(1) == 1, "return: 1 => 1"); sml_fail_unless(errno == 0, "errno: 1 => 0"); sml_fail_unless(GET_OBEX_RESULT(-1) == -1, "return: -1 => -1"); sml_fail_unless(errno == 1, "errno(%d): -1 => 1", errno); sml_fail_unless(GET_OBEX_RESULT(-10) == -10, "return: -10 => -10"); sml_fail_unless(errno == 10, "errno: -10 => 10"); errno = 20 sml_fail_unless(GET_OBEX_RESULT(-1) == -20, "return: -1(20) => -20"); sml_fail_unless(errno == 20, "errno: -1(20) => 20"); errno = 0 sml_fail_unless(GET_OBEX_RESULT(0) == 0, "return: 0 => 0"); sml_fail_unless(errno == 0, "errno: 0 => 0"); } END_TEST START_TEST (obex_client_new) { setup_testbed(NULL); SmlError *error = NULL; SmlTransport *tsp = smlTransportNew(SML_TRANSPORT_OBEX_CLIENT, &error); sml_fail_unless(tsp != NULL, NULL); sml_fail_unless(error == NULL, "%s", smlErrorPrint(&error)); smlTransportFree(tsp); } END_TEST START_TEST (obex_client_init) { setup_testbed(NULL); SmlError *error = NULL; SmlTransport *tsp = smlTransportNew(SML_TRANSPORT_OBEX_CLIENT, &error); sml_fail_unless(tsp != NULL, NULL); sml_fail_unless(error == NULL, "%s", smlErrorPrint(&error)); sml_fail_unless(smlTransportSetConfigOption(tsp, "URL", "127.0.0.1", &error), NULL); sml_fail_unless(smlTransportSetConnectionType(tsp, SML_TRANSPORT_CONNECTION_TYPE_NET, &error), NULL); sml_fail_unless(smlTransportInitialize(tsp, &error), "%s", smlErrorPrint(&error)); sml_fail_unless(error == NULL, "%s", smlErrorPrint(&error)); sml_fail_unless(smlTransportFinalize(tsp, &error), NULL); sml_fail_unless(error == NULL, "%s", smlErrorPrint(&error)); smlTransportFree(tsp); } END_TEST START_TEST (obex_server_new) { setup_testbed(NULL); SmlError *error = NULL; SmlTransport *tsp = smlTransportNew(SML_TRANSPORT_OBEX_SERVER, &error); sml_fail_unless(tsp != NULL, NULL); sml_fail_unless(error == NULL, "%s", smlErrorPrint(&error)); smlTransportFree(tsp); } END_TEST int client_connect_done = 0; int client_disconnect_done = 0; int client_receives = 0; int client_errors = 0; SmlBool _recv_client_event(SmlTransport *tsp, SmlLink *link_, SmlTransportEventType type, SmlTransportData *data, SmlError *error, void *userdata) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %d)", __func__, tsp, link_, type); sml_fail_unless(GPOINTER_TO_INT(userdata) == 1, NULL); switch (type) { case SML_TRANSPORT_EVENT_CONNECT_DONE: g_atomic_int_inc(&client_connect_done); break; case SML_TRANSPORT_EVENT_DISCONNECT_DONE: g_atomic_int_inc(&client_disconnect_done); break; case SML_TRANSPORT_EVENT_DATA: sml_fail_unless(!strcmp(data->data, "answer"), NULL); sml_fail_unless(data->size == 7, NULL); sml_fail_unless(data->type == SML_MIMETYPE_XML, NULL); g_atomic_int_inc(&client_receives); break; case SML_TRANSPORT_EVENT_ERROR: sml_fail_unless(error != NULL, NULL); g_atomic_int_inc(&client_errors); break; default: sml_fail_unless(FALSE, "An unexpected transport event %d was received.", type); break; } smlTrace(TRACE_EXIT, "%s()", __func__); return TRUE; } int server_connect_done = 0; int server_disconnect_done = 0; int server_receives = 0; SmlBool _recv_server_event(SmlTransport *tsp, SmlLink *link_, SmlTransportEventType type, SmlTransportData *data, SmlError *error, void *userdata) { smlTrace(TRACE_ENTRY, "%s(%d, %p)", __func__, type, error); switch (type) { case SML_TRANSPORT_EVENT_DATA: g_atomic_int_inc(&server_receives); if (!strcmp(data->data, "test")) { sml_fail_unless(data->size == 5, NULL); sml_fail_unless(data->type == SML_MIMETYPE_XML, NULL); sml_fail_unless(link_ != NULL, NULL); if (GPOINTER_TO_INT(userdata) == 1) { data = smlTransportDataNew((char *)"answer", 7, SML_MIMETYPE_XML, FALSE, &error); sml_fail_unless(data != NULL, NULL); sml_fail_unless(error == NULL, "%s", smlErrorPrint(&error)); sml_fail_unless(smlTransportSend(tsp, link_, data, &error), "%s", smlErrorPrint(&error)); smlTransportDataDeref(data); } else if (GPOINTER_TO_INT(userdata) == 2) { SmlError *newerror = NULL; smlErrorSet(&newerror, SML_ERROR_GENERIC, "test"); smlTransportSetError(tsp, link_, &newerror); smlErrorDeref(&newerror); } else if (GPOINTER_TO_INT(userdata) == 3) { sml_fail_unless(smlTransportDisconnect(tsp, link_, &error), NULL); } else { sml_fail_unless(FALSE, "The userdata %d was not expected.", GPOINTER_TO_INT(userdata)); } } else if (!strcmp(data->data, "error")) { sml_fail_unless(data->size == 6, NULL); sml_fail_unless(data->type == SML_MIMETYPE_XML, NULL); sml_fail_unless(link_ != NULL, NULL); SmlError *newerror = NULL; smlErrorSet(&newerror, SML_ERROR_GENERIC, "test2"); smlTransportSetError(tsp, link_, &newerror); smlErrorDeref(&newerror); } else { sml_fail_unless(FALSE, "The received data was not expected (%s).", data->data); } break; case SML_TRANSPORT_EVENT_CONNECT_DONE: g_atomic_int_inc(&server_connect_done); if (GPOINTER_TO_INT(userdata) == 4) { smlTrace(TRACE_EXIT, "%s()", __func__); return FALSE; } break; case SML_TRANSPORT_EVENT_DISCONNECT_DONE: g_atomic_int_inc(&server_disconnect_done); break; case SML_TRANSPORT_EVENT_ERROR: sml_fail_unless(FALSE, "%s", smlErrorPrint(&error)); break; default: sml_fail_unless(FALSE, "An unexpected transport event %d was received.", type); break; } smlTrace(TRACE_EXIT, "%s()", __func__); return TRUE; } void reset_testbed() { client_connect_done = 0; client_disconnect_done = 0; client_receives = 0; client_errors = 0; server_connect_done = 0; server_disconnect_done = 0; server_receives = 0; /* server errors are always a failure */ setup_testbed(NULL); } START_TEST (obex_server_init) { setup_testbed(NULL); SmlError *error = NULL; SmlTransport *tsp = smlTransportNew(SML_TRANSPORT_OBEX_SERVER, &error); sml_fail_unless(tsp != NULL, NULL); sml_fail_unless(error == NULL, "%s", smlErrorPrint(&error)); sml_fail_unless(smlTransportSetConnectionType(tsp, SML_TRANSPORT_CONNECTION_TYPE_NET, &error), NULL); sml_fail_unless(error == NULL, "%s", smlErrorPrint(&error)); /* Don't use the default port 650 here because this is a reserved port in Unix. * Therefore the port is usually only allowed for the root user. */ sml_fail_unless(smlTransportSetConfigOption(tsp, "PORT", "10104", &error), NULL); smlTransportSetEventCallback(tsp, _recv_server_event, GINT_TO_POINTER(1)); sml_fail_unless(smlTransportInitialize(tsp, &error), "%s", smlErrorPrint(&error)); sml_fail_unless(error == NULL, "%s", smlErrorPrint(&error)); sml_fail_unless(smlTransportFinalize(tsp, &error), "%s", smlErrorPrint(&error)); sml_fail_unless(error == NULL, "%s", smlErrorPrint(&error)); smlTransportFree(tsp); } END_TEST START_TEST (obex_connect) { reset_testbed(); SmlError *error = NULL; SmlTransport *server = smlTransportNew(SML_TRANSPORT_OBEX_SERVER, &error); SmlTransport *client = smlTransportNew(SML_TRANSPORT_OBEX_CLIENT, &error); sml_fail_unless(smlTransportSetConfigOption(client, "URL", "127.0.0.1", &error), NULL); sml_fail_unless(smlTransportSetConfigOption(client, "PORT", "10105", &error), NULL); sml_fail_unless(smlTransportSetConnectionType(client, SML_TRANSPORT_CONNECTION_TYPE_NET, &error), NULL); sml_fail_unless(smlTransportSetConfigOption(server, "PORT", "10105", &error), NULL); sml_fail_unless(smlTransportSetConnectionType(server, SML_TRANSPORT_CONNECTION_TYPE_NET, &error), NULL); smlTransportSetEventCallback(client, _recv_client_event, GINT_TO_POINTER(1)); smlTransportSetEventCallback(server, _recv_server_event, GINT_TO_POINTER(1)); sml_fail_unless(smlTransportInitialize(client, &error), "%s", smlErrorPrint(&error)); sml_fail_unless(smlTransportInitialize(server, &error), "%s", smlErrorPrint(&error)); sml_fail_unless(error == NULL, "%s", smlErrorPrint(&error)); sml_fail_unless(smlTransportConnect(client, &error), NULL); sml_fail_unless(error == NULL, "%s", smlErrorPrint(&error)); while (client_connect_done < 1 || server_connect_done < 1) { usleep(50); }; sml_fail_unless(smlTransportDisconnect(client, NULL, &error), NULL); sml_fail_unless(error == NULL, "%s", smlErrorPrint(&error)); while (client_disconnect_done < 1 || server_disconnect_done < 1) { usleep(50); }; sml_fail_unless(client_receives == 0, NULL); sml_fail_unless(client_connect_done == 1, NULL); sml_fail_unless(client_disconnect_done == 1, NULL); sml_fail_unless(server_receives == 0, NULL); sml_fail_unless(server_connect_done == 1, NULL); sml_fail_unless(server_disconnect_done == 1, NULL); sml_fail_unless(smlTransportFinalize(server, &error), NULL); sml_fail_unless(smlTransportFinalize(client, &error), NULL); smlTransportFree(server); smlTransportFree(client); } END_TEST START_TEST (obex_send) { reset_testbed(); SmlError *error = NULL; SmlTransport *server = smlTransportNew(SML_TRANSPORT_OBEX_SERVER, &error); SmlTransport *client = smlTransportNew(SML_TRANSPORT_OBEX_CLIENT, &error); sml_fail_unless(smlTransportSetConfigOption(client, "URL", "127.0.0.1", &error), NULL); sml_fail_unless(smlTransportSetConfigOption(client, "PORT", "10106", &error), NULL); sml_fail_unless(smlTransportSetConnectionType(client, SML_TRANSPORT_CONNECTION_TYPE_NET, &error), NULL); sml_fail_unless(smlTransportSetConfigOption(server, "PORT", "10106", &error), NULL); sml_fail_unless(smlTransportSetConnectionType(server, SML_TRANSPORT_CONNECTION_TYPE_NET, &error), NULL); smlTransportSetEventCallback(client, _recv_client_event, GINT_TO_POINTER(1)); smlTransportSetEventCallback(server, _recv_server_event, GINT_TO_POINTER(3)); sml_fail_unless(smlTransportInitialize(client, &error), "%s", smlErrorPrint(&error)); sml_fail_unless(smlTransportInitialize(server, &error), "%s", smlErrorPrint(&error)); sml_fail_unless(error == NULL, "%s", smlErrorPrint(&error)); sml_fail_unless(smlTransportConnect(client, &error), NULL); sml_fail_unless(error == NULL, "%s", smlErrorPrint(&error)); while (client_connect_done < 1 || server_connect_done < 1) { usleep(50); }; SmlTransportData *data = smlTransportDataNew((char *)"test", 5, SML_MIMETYPE_XML, FALSE, &error); sml_fail_unless(data != NULL, NULL); sml_fail_unless(error == NULL, "%s", smlErrorPrint(&error)); sml_fail_unless(smlTransportSend(client, NULL, data, &error), "%s", smlErrorPrint(&error)); sml_fail_unless(error == NULL, "%s", smlErrorPrint(&error)); smlTransportDataDeref(data); while (server_receives < 1) { usleep(50); }; sml_fail_unless(smlTransportDisconnect(client, NULL, &error), NULL); sml_fail_unless(error == NULL, "%s", smlErrorPrint(&error)); while ((client_disconnect_done < 1 || server_disconnect_done < 1 ) && client_errors < 1) { usleep(50); }; sml_fail_unless(client_receives == 0, NULL); sml_fail_unless(server_receives == 1, NULL); sml_fail_unless(client_connect_done == 1, NULL); sml_fail_unless(server_connect_done == 1, NULL); /* If we stop the while loop like some lines before * then only client_disconnect_done or client_errors are * guaranteed to finish correctly. If this thread is fast * enough then the checks for equal (==2 && ==1) are reached * before the disconnects and error detection completed. * Such a behaviour would be a typical race condition. * The solution is to wait until there are enough disconnects * or more errors than expected. */ while ( (client_disconnect_done + client_errors) < 2 || server_disconnect_done < 1) { usleep(50); }; sml_fail_unless(client_disconnect_done == 1, NULL); sml_fail_unless(server_disconnect_done == 1, NULL); /* There must be an error but it depends on the speed of the * machine if two or one error are detected by the bluetooth * stack. */ sml_fail_unless(client_errors > 0, "There must be a client error."); sml_fail_unless(smlTransportFinalize(server, &error), NULL); sml_fail_unless(smlTransportFinalize(client, &error), NULL); smlTransportFree(server); smlTransportFree(client); } END_TEST START_TEST (obex_reply) { reset_testbed(); SmlError *error = NULL; SmlTransport *server = smlTransportNew(SML_TRANSPORT_OBEX_SERVER, &error); SmlTransport *client = smlTransportNew(SML_TRANSPORT_OBEX_CLIENT, &error); sml_fail_unless(smlTransportSetConfigOption(client, "URL", "127.0.0.1", &error), NULL); sml_fail_unless(smlTransportSetConfigOption(client, "PORT", "10107", &error), NULL); sml_fail_unless(smlTransportSetConnectionType(client, SML_TRANSPORT_CONNECTION_TYPE_NET, &error), NULL); sml_fail_unless(smlTransportSetConfigOption(server, "PORT", "10107", &error), NULL); sml_fail_unless(smlTransportSetConnectionType(server, SML_TRANSPORT_CONNECTION_TYPE_NET, &error), NULL); smlTransportSetEventCallback(client, _recv_client_event, GINT_TO_POINTER(1)); smlTransportSetEventCallback(server, _recv_server_event, GINT_TO_POINTER(1)); sml_fail_unless(smlTransportInitialize(client, &error), "%s", smlErrorPrint(&error)); sml_fail_unless(smlTransportInitialize(server, &error), "%s", smlErrorPrint(&error)); sml_fail_unless(error == NULL, "%s", smlErrorPrint(&error)); sml_fail_unless(smlTransportConnect(client, &error), NULL); sml_fail_unless(error == NULL, "%s", smlErrorPrint(&error)); while (client_connect_done < 1 || server_connect_done < 1) { usleep(50); }; SmlTransportData *data = smlTransportDataNew((char *)"test", 5, SML_MIMETYPE_XML, FALSE, &error); sml_fail_unless(data != NULL, NULL); sml_fail_unless(error == NULL, "%s", smlErrorPrint(&error)); sml_fail_unless(smlTransportSend(client, NULL, data, &error), "%s", smlErrorPrint(&error)); sml_fail_unless(error == NULL, "%s", smlErrorPrint(&error)); smlTransportDataDeref(data); sml_fail_unless(smlTransportDisconnect(client, NULL, &error), NULL); sml_fail_unless(error == NULL, "%s", smlErrorPrint(&error)); while (client_disconnect_done < 1 || server_disconnect_done < 1) { usleep(50); }; sml_fail_unless(client_receives == 1, NULL); sml_fail_unless(client_connect_done == 1, NULL); sml_fail_unless(client_disconnect_done == 1, NULL); sml_fail_unless(client_errors == 0, NULL); sml_fail_unless(server_receives == 1, NULL); sml_fail_unless(server_connect_done == 1, NULL); sml_fail_unless(server_disconnect_done == 1, NULL); sml_fail_unless(smlTransportFinalize(server, &error), NULL); sml_fail_unless(smlTransportFinalize(client, &error), NULL); smlTransportFree(server); smlTransportFree(client); } END_TEST START_TEST (obex_talk) { reset_testbed(); int num = 10; SmlError *error = NULL; SmlTransport *server = smlTransportNew(SML_TRANSPORT_OBEX_SERVER, &error); SmlTransport *client = smlTransportNew(SML_TRANSPORT_OBEX_CLIENT, &error); sml_fail_unless(smlTransportSetConfigOption(client, "URL", "127.0.0.1", &error), NULL); sml_fail_unless(smlTransportSetConfigOption(client, "PORT", "10108", &error), NULL); sml_fail_unless(smlTransportSetConnectionType(client, SML_TRANSPORT_CONNECTION_TYPE_NET, &error), NULL); sml_fail_unless(smlTransportSetConfigOption(server, "PORT", "10108", &error), NULL); sml_fail_unless(smlTransportSetConnectionType(server, SML_TRANSPORT_CONNECTION_TYPE_NET, &error), NULL); smlTransportSetEventCallback(client, _recv_client_event, GINT_TO_POINTER(1)); smlTransportSetEventCallback(server, _recv_server_event, GINT_TO_POINTER(1)); sml_fail_unless(smlTransportInitialize(client, &error), "%s", smlErrorPrint(&error)); sml_fail_unless(smlTransportInitialize(server, &error), "%s", smlErrorPrint(&error)); sml_fail_unless(error == NULL, "%s", smlErrorPrint(&error)); sml_fail_unless(smlTransportConnect(client, &error), NULL); sml_fail_unless(error == NULL, "%s", smlErrorPrint(&error)); while (client_connect_done < 1 || server_connect_done < 1) { usleep(50); }; SmlTransportData *data = NULL; int i; for (i = 0; i < num; i++) { data = smlTransportDataNew((char *)"test", 5, SML_MIMETYPE_XML, FALSE, &error); sml_fail_unless(data != NULL, NULL); sml_fail_unless(error == NULL, "%s", smlErrorPrint(&error)); sml_fail_unless(smlTransportSend(client, NULL, data, &error), "%s", smlErrorPrint(&error)); sml_fail_unless(error == NULL, "%s", smlErrorPrint(&error)); smlTransportDataDeref(data); while (1) { usleep(100); if (client_receives == i+1) break; } } sml_fail_unless(smlTransportDisconnect(client, NULL, &error), NULL); sml_fail_unless(error == NULL, "%s", smlErrorPrint(&error)); while (client_disconnect_done < 1 || server_disconnect_done < 1) { usleep(50); }; sml_fail_unless(client_receives == num, NULL); sml_fail_unless(client_connect_done == 1, NULL); sml_fail_unless(client_disconnect_done == 1, NULL); sml_fail_unless(client_errors == 0, NULL); sml_fail_unless(server_receives == num, NULL); sml_fail_unless(server_connect_done == 1, NULL); sml_fail_unless(server_disconnect_done == 1, NULL); sml_fail_unless(smlTransportFinalize(server, &error), NULL); sml_fail_unless(smlTransportFinalize(client, &error), NULL); smlTransportFree(server); smlTransportFree(client); } END_TEST START_TEST (obex_multi_connect) { reset_testbed(); SmlError *error = NULL; SmlTransport *server = smlTransportNew(SML_TRANSPORT_OBEX_SERVER, &error); SmlTransport *client1 = smlTransportNew(SML_TRANSPORT_OBEX_CLIENT, &error); SmlTransport *client2 = smlTransportNew(SML_TRANSPORT_OBEX_CLIENT, &error); SmlTransport *client3 = smlTransportNew(SML_TRANSPORT_OBEX_CLIENT, &error); sml_fail_unless(smlTransportSetConfigOption(client1, "URL", "127.0.0.1", &error), NULL); sml_fail_unless(smlTransportSetConfigOption(client1, "PORT", "10109", &error), NULL); sml_fail_unless(smlTransportSetConnectionType(client1, SML_TRANSPORT_CONNECTION_TYPE_NET, &error), NULL); sml_fail_unless(smlTransportSetConfigOption(client2, "URL", "127.0.0.1", &error), NULL); sml_fail_unless(smlTransportSetConfigOption(client2, "PORT", "10109", &error), NULL); sml_fail_unless(smlTransportSetConnectionType(client2, SML_TRANSPORT_CONNECTION_TYPE_NET, &error), NULL); sml_fail_unless(smlTransportSetConfigOption(client3, "URL", "127.0.0.1", &error), NULL); sml_fail_unless(smlTransportSetConfigOption(client3, "PORT", "10109", &error), NULL); sml_fail_unless(smlTransportSetConnectionType(client3, SML_TRANSPORT_CONNECTION_TYPE_NET, &error), NULL); sml_fail_unless(smlTransportSetConfigOption(server, "PORT", "10109", &error), NULL); sml_fail_unless(smlTransportSetConnectionType(server, SML_TRANSPORT_CONNECTION_TYPE_NET, &error), NULL); smlTransportSetEventCallback(client1, _recv_client_event, GINT_TO_POINTER(1)); smlTransportSetEventCallback(client2, _recv_client_event, GINT_TO_POINTER(1)); smlTransportSetEventCallback(client3, _recv_client_event, GINT_TO_POINTER(1)); smlTransportSetEventCallback(server, _recv_server_event, GINT_TO_POINTER(1)); sml_fail_unless(smlTransportInitialize(client1, &error), "%s", smlErrorPrint(&error)); sml_fail_unless(smlTransportInitialize(client2, &error), "%s", smlErrorPrint(&error)); sml_fail_unless(smlTransportInitialize(client3, &error), "%s", smlErrorPrint(&error)); sml_fail_unless(smlTransportInitialize(server, &error), "%s", smlErrorPrint(&error)); sml_fail_unless(error == NULL, "%s", smlErrorPrint(&error)); sml_fail_unless(smlTransportConnect(client1, &error), NULL); sml_fail_unless(smlTransportConnect(client2, &error), NULL); sml_fail_unless(smlTransportConnect(client3, &error), NULL); sml_fail_unless(error == NULL, "%s", smlErrorPrint(&error)); while (client_connect_done < 3 || server_connect_done < 3) { usleep(50); }; SmlTransportData *data = smlTransportDataNew((char *)"test", 5, SML_MIMETYPE_XML, FALSE, &error); sml_fail_unless(data != NULL, NULL); sml_fail_unless(error == NULL, "%s", smlErrorPrint(&error)); sml_fail_unless(smlTransportSend(client1, NULL, data, &error), "%s", smlErrorPrint(&error)); sml_fail_unless(error == NULL, "%s", smlErrorPrint(&error)); smlTransportDataDeref(data); data = smlTransportDataNew((char *)"test", 5, SML_MIMETYPE_XML, FALSE, &error); sml_fail_unless(data != NULL, NULL); sml_fail_unless(error == NULL, "%s", smlErrorPrint(&error)); sml_fail_unless(smlTransportSend(client2, NULL, data, &error), "%s", smlErrorPrint(&error)); sml_fail_unless(error == NULL, "%s", smlErrorPrint(&error)); smlTransportDataDeref(data); data = smlTransportDataNew((char *)"test", 5, SML_MIMETYPE_XML, FALSE, &error); sml_fail_unless(data != NULL, NULL); sml_fail_unless(error == NULL, "%s", smlErrorPrint(&error)); sml_fail_unless(smlTransportSend(client3, NULL, data, &error), "%s", smlErrorPrint(&error)); sml_fail_unless(error == NULL, "%s", smlErrorPrint(&error)); smlTransportDataDeref(data); sml_fail_unless(smlTransportDisconnect(client1, NULL, &error), NULL); sml_fail_unless(smlTransportDisconnect(client2, NULL, &error), NULL); sml_fail_unless(smlTransportDisconnect(client3, NULL, &error), NULL); sml_fail_unless(error == NULL, "%s", smlErrorPrint(&error)); while (client_disconnect_done < 3 || server_disconnect_done < 3) { usleep(50); }; sml_fail_unless(client_receives == 3, NULL); sml_fail_unless(client_connect_done == 3, NULL); sml_fail_unless(client_disconnect_done == 3, NULL); sml_fail_unless(client_errors == 0, NULL); sml_fail_unless(server_receives == 3, NULL); sml_fail_unless(server_connect_done == 3, NULL); sml_fail_unless(server_disconnect_done == 3, NULL); sml_fail_unless(smlTransportFinalize(server, &error), NULL); sml_fail_unless(smlTransportFinalize(client1, &error), NULL); sml_fail_unless(smlTransportFinalize(client2, &error), NULL); sml_fail_unless(smlTransportFinalize(client3, &error), NULL); smlTransportFree(server); smlTransportFree(client1); smlTransportFree(client2); smlTransportFree(client3); } END_TEST START_TEST (obex_multi_stress) { reset_testbed(); int num = 1000; SmlError *error = NULL; SmlTransport *server = smlTransportNew(SML_TRANSPORT_OBEX_SERVER, &error); SmlTransport *client1 = smlTransportNew(SML_TRANSPORT_OBEX_CLIENT, &error); SmlTransport *client2 = smlTransportNew(SML_TRANSPORT_OBEX_CLIENT, &error); SmlTransport *client3 = smlTransportNew(SML_TRANSPORT_OBEX_CLIENT, &error); sml_fail_unless(smlTransportSetConfigOption(client1, "URL", "127.0.0.1", &error), NULL); sml_fail_unless(smlTransportSetConfigOption(client1, "PORT", "10110", &error), NULL); sml_fail_unless(smlTransportSetConnectionType(client1, SML_TRANSPORT_CONNECTION_TYPE_NET, &error), NULL); sml_fail_unless(smlTransportSetConfigOption(client2, "URL", "127.0.0.1", &error), NULL); sml_fail_unless(smlTransportSetConfigOption(client2, "PORT", "10110", &error), NULL); sml_fail_unless(smlTransportSetConnectionType(client2, SML_TRANSPORT_CONNECTION_TYPE_NET, &error), NULL); sml_fail_unless(smlTransportSetConfigOption(client3, "URL", "127.0.0.1", &error), NULL); sml_fail_unless(smlTransportSetConfigOption(client3, "PORT", "10110", &error), NULL); sml_fail_unless(smlTransportSetConnectionType(client3, SML_TRANSPORT_CONNECTION_TYPE_NET, &error), NULL); sml_fail_unless(smlTransportSetConfigOption(server, "PORT", "10110", &error), NULL); sml_fail_unless(smlTransportSetConnectionType(server, SML_TRANSPORT_CONNECTION_TYPE_NET, &error), NULL); smlTransportSetEventCallback(client1, _recv_client_event, GINT_TO_POINTER(1)); smlTransportSetEventCallback(client2, _recv_client_event, GINT_TO_POINTER(1)); smlTransportSetEventCallback(client3, _recv_client_event, GINT_TO_POINTER(1)); smlTransportSetEventCallback(server, _recv_server_event, GINT_TO_POINTER(1)); /* Always start the server first. */ sml_fail_unless(error == NULL, "%s", smlErrorPrint(&error)); sml_fail_unless(smlTransportInitialize(server, &error), "%s", smlErrorPrint(&error)); sml_fail_unless(error == NULL, "%s", smlErrorPrint(&error)); sml_fail_unless(smlTransportInitialize(client1, &error), "%s", smlErrorPrint(&error)); sml_fail_unless(error == NULL, "%s", smlErrorPrint(&error)); sml_fail_unless(smlTransportInitialize(client2, &error), "%s", smlErrorPrint(&error)); sml_fail_unless(error == NULL, "%s", smlErrorPrint(&error)); sml_fail_unless(smlTransportInitialize(client3, &error), "%s", smlErrorPrint(&error)); sml_fail_unless(error == NULL, "%s", smlErrorPrint(&error)); sml_fail_unless(smlTransportConnect(client1, &error), NULL); sml_fail_unless(smlTransportConnect(client2, &error), NULL); sml_fail_unless(smlTransportConnect(client3, &error), NULL); sml_fail_unless(error == NULL, "%s", smlErrorPrint(&error)); while (client_connect_done < 3 || server_connect_done < 3) { usleep(50); }; SmlTransportData *data = NULL; int i; for (i = 0; i < num; i++) { data = smlTransportDataNew((char *)"test", 5, SML_MIMETYPE_XML, FALSE, &error); sml_fail_unless(data != NULL, NULL); sml_fail_unless(error == NULL, "%s", smlErrorPrint(&error)); sml_fail_unless(smlTransportSend(client1, NULL, data, &error), "%s", smlErrorPrint(&error)); sml_fail_unless(error == NULL, "%s", smlErrorPrint(&error)); smlTransportDataDeref(data); data = smlTransportDataNew((char *)"test", 5, SML_MIMETYPE_XML, FALSE, &error); sml_fail_unless(data != NULL, NULL); sml_fail_unless(error == NULL, "%s", smlErrorPrint(&error)); sml_fail_unless(smlTransportSend(client2, NULL, data, &error), "%s", smlErrorPrint(&error)); sml_fail_unless(error == NULL, "%s", smlErrorPrint(&error)); smlTransportDataDeref(data); data = smlTransportDataNew((char *)"test", 5, SML_MIMETYPE_XML, FALSE, &error); sml_fail_unless(data != NULL, NULL); sml_fail_unless(error == NULL, "%s", smlErrorPrint(&error)); sml_fail_unless(smlTransportSend(client3, NULL, data, &error), "%s", smlErrorPrint(&error)); sml_fail_unless(error == NULL, "%s", smlErrorPrint(&error)); smlTransportDataDeref(data); while (1) { usleep(1); if (client_receives == (i+1)*3) break; } } sml_fail_unless(smlTransportDisconnect(client1, NULL, &error), NULL); sml_fail_unless(smlTransportDisconnect(client2, NULL, &error), NULL); sml_fail_unless(smlTransportDisconnect(client3, NULL, &error), NULL); sml_fail_unless(error == NULL, "%s", smlErrorPrint(&error)); while (client_disconnect_done < 3 || server_disconnect_done < 3) { usleep(50); }; sml_fail_unless(client_receives == num * 3, NULL); sml_fail_unless(client_connect_done == 3, NULL); sml_fail_unless(client_disconnect_done == 3, NULL); sml_fail_unless(client_errors == 0, NULL); sml_fail_unless(server_receives == num * 3, NULL); sml_fail_unless(server_connect_done == 3, NULL); sml_fail_unless(server_disconnect_done == 3, NULL); sml_fail_unless(smlTransportFinalize(server, &error), NULL); sml_fail_unless(smlTransportFinalize(client1, &error), NULL); sml_fail_unless(smlTransportFinalize(client2, &error), NULL); sml_fail_unless(smlTransportFinalize(client3, &error), NULL); smlTransportFree(server); smlTransportFree(client1); smlTransportFree(client2); smlTransportFree(client3); } END_TEST START_TEST (obex_connect_error) { reset_testbed(); SmlError *error = NULL; SmlTransport *client = smlTransportNew(SML_TRANSPORT_OBEX_CLIENT, &error); sml_fail_unless(smlTransportSetConfigOption(client, "URL", "127.0.0.1", &error), NULL); sml_fail_unless(smlTransportSetConfigOption(client, "PORT", "10111", &error), NULL); sml_fail_unless(smlTransportSetConnectionType(client, SML_TRANSPORT_CONNECTION_TYPE_NET, &error), NULL); smlTransportSetEventCallback(client, _recv_client_event, GINT_TO_POINTER(1)); sml_fail_unless(smlTransportInitialize(client, &error), "%s", smlErrorPrint(&error)); sml_fail_unless(error == NULL, "%s", smlErrorPrint(&error)); sml_fail_unless(smlTransportConnect(client, &error), NULL); sml_fail_unless(error == NULL, "%s", smlErrorPrint(&error)); sleep(1); while (client_errors < 1) { usleep(50); }; sml_fail_unless(!smlTransportDisconnect(client, NULL, &error), NULL); sml_fail_unless(error != NULL, NULL); smlErrorDeref(&error); /* The client is stateful and so disconnect is false * because the client was never connected. */ sml_fail_unless(client_receives == 0, NULL); sml_fail_unless(server_receives == 0, NULL); sml_fail_unless(client_connect_done == 0, NULL); sml_fail_unless(client_disconnect_done == 0, NULL); sml_fail_unless(client_errors == 1, NULL); sml_fail_unless(smlTransportFinalize(client, &error), NULL); smlTransportFree(client); } END_TEST START_TEST (obex_reject) { reset_testbed(); SmlError *error = NULL; SmlTransport *server = smlTransportNew(SML_TRANSPORT_OBEX_SERVER, &error); SmlTransport *client = smlTransportNew(SML_TRANSPORT_OBEX_CLIENT, &error); sml_fail_unless(smlTransportSetConfigOption(client, "URL", "127.0.0.1", &error), NULL); sml_fail_unless(smlTransportSetConfigOption(client, "PORT", "10113", &error), NULL); sml_fail_unless(smlTransportSetConnectionType(client, SML_TRANSPORT_CONNECTION_TYPE_NET, &error), NULL); sml_fail_unless(smlTransportSetConfigOption(server, "PORT", "10113", &error), NULL); sml_fail_unless(smlTransportSetConnectionType(server, SML_TRANSPORT_CONNECTION_TYPE_NET, &error), NULL); smlTransportSetEventCallback(client, _recv_client_event, GINT_TO_POINTER(1)); smlTransportSetEventCallback(server, _recv_server_event, GINT_TO_POINTER(4)); sml_fail_unless(smlTransportInitialize(client, &error), "%s", smlErrorPrint(&error)); sml_fail_unless(smlTransportInitialize(server, &error), "%s", smlErrorPrint(&error)); sml_fail_unless(error == NULL, "%s", smlErrorPrint(&error)); sml_fail_unless(smlTransportConnect(client, &error), NULL); sml_fail_unless(error == NULL, "%s", smlErrorPrint(&error)); while (client_errors < 1 || server_connect_done < 1) { usleep(50); }; sml_fail_unless(!smlTransportDisconnect(client, NULL, &error), NULL); sml_fail_unless(error != NULL, NULL); smlErrorDeref(&error); while (server_disconnect_done < 1) { usleep(50); }; sml_fail_unless(client_receives == 0, NULL); sml_fail_unless(client_connect_done == 0, NULL); sml_fail_unless(client_disconnect_done == 0, NULL); sml_fail_unless(client_errors == 1, NULL); sml_fail_unless(server_receives == 0, NULL); sml_fail_unless(server_connect_done == 1, NULL); sml_fail_unless(server_disconnect_done == 1, NULL); sml_fail_unless(smlTransportFinalize(server, &error), NULL); sml_fail_unless(smlTransportFinalize(client, &error), NULL); smlTransportFree(server); smlTransportFree(client); } END_TEST START_TEST (obex_multi_partial_error) { reset_testbed(); SmlError *error = NULL; SmlTransport *server = smlTransportNew(SML_TRANSPORT_OBEX_SERVER, &error); SmlTransport *client1 = smlTransportNew(SML_TRANSPORT_OBEX_CLIENT, &error); SmlTransport *client2 = smlTransportNew(SML_TRANSPORT_OBEX_CLIENT, &error); SmlTransport *client3 = smlTransportNew(SML_TRANSPORT_OBEX_CLIENT, &error); sml_fail_unless(smlTransportSetConfigOption(client1, "URL", "127.0.0.1", &error), NULL); sml_fail_unless(smlTransportSetConfigOption(client1, "PORT", "10114", &error), NULL); sml_fail_unless(smlTransportSetConnectionType(client1, SML_TRANSPORT_CONNECTION_TYPE_NET, &error), NULL); sml_fail_unless(smlTransportSetConfigOption(client2, "URL", "127.0.0.1", &error), NULL); sml_fail_unless(smlTransportSetConfigOption(client2, "PORT", "10114", &error), NULL); sml_fail_unless(smlTransportSetConnectionType(client2, SML_TRANSPORT_CONNECTION_TYPE_NET, &error), NULL); sml_fail_unless(smlTransportSetConfigOption(client3, "URL", "127.0.0.1", &error), NULL); sml_fail_unless(smlTransportSetConfigOption(client3, "PORT", "10114", &error), NULL); sml_fail_unless(smlTransportSetConnectionType(client3, SML_TRANSPORT_CONNECTION_TYPE_NET, &error), NULL); sml_fail_unless(smlTransportSetConfigOption(server, "PORT", "10114", &error), NULL); sml_fail_unless(smlTransportSetConnectionType(server, SML_TRANSPORT_CONNECTION_TYPE_NET, &error), NULL); smlTransportSetEventCallback(client1, _recv_client_event, GINT_TO_POINTER(1)); smlTransportSetEventCallback(client2, _recv_client_event, GINT_TO_POINTER(1)); smlTransportSetEventCallback(client3, _recv_client_event, GINT_TO_POINTER(1)); smlTransportSetEventCallback(server, _recv_server_event, GINT_TO_POINTER(1)); sml_fail_unless(smlTransportInitialize(client1, &error), "%s", smlErrorPrint(&error)); sml_fail_unless(smlTransportInitialize(client2, &error), "%s", smlErrorPrint(&error)); sml_fail_unless(smlTransportInitialize(client3, &error), "%s", smlErrorPrint(&error)); sml_fail_unless(smlTransportInitialize(server, &error), "%s", smlErrorPrint(&error)); sml_fail_unless(error == NULL, "%s", smlErrorPrint(&error)); sml_fail_unless(smlTransportConnect(client1, &error), NULL); sml_fail_unless(smlTransportConnect(client2, &error), NULL); sml_fail_unless(smlTransportConnect(client3, &error), NULL); sml_fail_unless(error == NULL, "%s", smlErrorPrint(&error)); while (client_connect_done < 3 || server_connect_done < 3) { usleep(50); }; SmlTransportData *data = smlTransportDataNew((char *)"test", 5, SML_MIMETYPE_XML, FALSE, &error); sml_fail_unless(data != NULL, NULL); sml_fail_unless(error == NULL, "%s", smlErrorPrint(&error)); sml_fail_unless(smlTransportSend(client1, NULL, data, &error), "%s", smlErrorPrint(&error)); sml_fail_unless(error == NULL, "%s", smlErrorPrint(&error)); smlTransportDataDeref(data); data = smlTransportDataNew((char *)"error", 6, SML_MIMETYPE_XML, FALSE, &error); sml_fail_unless(data != NULL, NULL); sml_fail_unless(error == NULL, "%s", smlErrorPrint(&error)); sml_fail_unless(smlTransportSend(client2, NULL, data, &error), "%s", smlErrorPrint(&error)); sml_fail_unless(error == NULL, "%s", smlErrorPrint(&error)); smlTransportDataDeref(data); data = smlTransportDataNew((char *)"error", 6, SML_MIMETYPE_XML, FALSE, &error); sml_fail_unless(data != NULL, NULL); sml_fail_unless(error == NULL, "%s", smlErrorPrint(&error)); sml_fail_unless(smlTransportSend(client3, NULL, data, &error), "%s", smlErrorPrint(&error)); sml_fail_unless(error == NULL, "%s", smlErrorPrint(&error)); smlTransportDataDeref(data); sml_fail_unless(smlTransportDisconnect(client1, NULL, &error), NULL); sml_fail_unless(smlTransportDisconnect(client2, NULL, &error), NULL); sml_fail_unless(smlTransportDisconnect(client3, NULL, &error), NULL); sml_fail_unless(error == NULL, "%s", smlErrorPrint(&error)); while (client_disconnect_done < 3 || server_disconnect_done < 3) { usleep(50); }; sml_fail_unless(client_receives == 1, NULL); sml_fail_unless(client_connect_done == 3, NULL); sml_fail_unless(client_disconnect_done == 3, NULL); sml_fail_unless(client_errors == 2, NULL); sml_fail_unless(server_receives == 3, NULL); sml_fail_unless(server_connect_done == 3, NULL); sml_fail_unless(server_disconnect_done == 3, NULL); sml_fail_unless(smlTransportFinalize(server, &error), NULL); sml_fail_unless(smlTransportFinalize(client1, &error), NULL); sml_fail_unless(smlTransportFinalize(client2, &error), NULL); sml_fail_unless(smlTransportFinalize(client3, &error), NULL); smlTransportFree(server); smlTransportFree(client1); smlTransportFree(client2); smlTransportFree(client3); } END_TEST @SML_TESTCASE_CODE@ libsyncml-0.5.4/tests/check_san.c100644 1750 1750 46307 11211710410 16677 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2005 Armin Bauer * Copyright (C) 2008 Michael Bell * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include "tests/support.h" /* If the notification is a normal SyncML message then a manager is * required. The easiest way are two function which create and destroy * a default manager - only for testing. */ SmlTransport *_tsp = NULL; SmlManager* _start_manager() { unsigned int defaultMaxMsgSize = 10240; unsigned int defaultMaxObjSize = 1024000; SmlError *error = NULL; _tsp = smlTransportNew(SML_TRANSPORT_HTTP_SERVER, &error); sml_fail_unless(_tsp != NULL, "%s", smlErrorPrint(&error)); sml_fail_unless(error == NULL, "%s", smlErrorPrint(&error)); SmlManager *manager = smlManagerNew(_tsp, &error); sml_fail_unless(manager != NULL, "%s", smlErrorPrint(&error)); sml_fail_unless(error == NULL, "%s", smlErrorPrint(&error)); smlManagerSetLocalMaxMsgSize(manager, defaultMaxMsgSize); smlManagerSetLocalMaxObjSize(manager, defaultMaxObjSize); return manager; } void _stop_manager(SmlManager *manager) { smlManagerFree(manager); smlTransportFree(_tsp); } START_TEST (san_new) { setup_testbed(NULL); SmlError *error = NULL; SmlNotification *san = smlNotificationNew(SML_SAN_VERSION_12, SML_SAN_UIMODE_USER, SML_SAN_INITIATOR_USER, 0, "test", "/", SML_MIMETYPE_UNKNOWN, &error); sml_fail_unless(san != NULL, NULL); sml_fail_unless(error == NULL, NULL); smlNotificationFree(san); } END_TEST START_TEST (san_empty) { setup_testbed(NULL); SmlError *error = NULL; SmlNotification *san = smlNotificationNew(SML_SAN_VERSION_12, SML_SAN_UIMODE_UNSPECIFIED, SML_SAN_INITIATOR_USER, 0, "tttt", "/", SML_MIMETYPE_UNKNOWN, &error); sml_fail_unless(san != NULL, NULL); sml_fail_unless(error == NULL, NULL); unsigned char target[] = { /* old implementation without digest support 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //DIGEST */ 0x95, 0x5d, 0x6f, 0x61, 0xa4, 0x20, 0xb1, 0xa7, 0x46, 0x00, 0xc1, 0x12, 0x81, 0x06, 0x5e, 0x64, //DIGEST 0x03, 0x00, //version + ui + init + start of future 0x00, 0x00, 0x00, //Future 0x00, 0x00, //Session id 0x04, 0x74, 0x74, 0x74, 0x74, //server identifier 0x00}; // num syncs + future char *buffer = NULL; unsigned int size = 0; sml_fail_unless(smlNotificationAssemble(san, &buffer, &size, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(size == sizeof(target), NULL); sml_fail_unless(memcmp(target, buffer, size) == 0, NULL); g_free(buffer); smlNotificationFree(san); } END_TEST START_TEST (san_empty2) { setup_testbed(NULL); SmlError *error = NULL; SmlNotification *san = smlNotificationNew(SML_SAN_VERSION_12, SML_SAN_UIMODE_USER, SML_SAN_INITIATOR_SERVER, 65535, "ttttt", "/", SML_MIMETYPE_UNKNOWN, &error); sml_fail_unless(san != NULL, NULL); sml_fail_unless(error == NULL, NULL); unsigned char target[] = { /* old implementation without digest support 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //DIGEST */ 0x9e, 0x0d, 0x43, 0x31, 0x4f, 0x18, 0xb6, 0x96, 0x6d, 0x88, 0xf1, 0xa2, 0xdb, 0x00, 0x06, 0x15, //DIGEST 0x03, 0x38, //version + ui + init + start of future 0x00, 0x00, 0x00, //Future 0xFF, 0xFF, //Session id 0x05, 0x74, 0x74, 0x74, 0x74, 0x74, //server identifier 0x00}; // num syncs + future char *buffer = NULL; unsigned int size = 0; sml_fail_unless(smlNotificationAssemble(san, &buffer, &size, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(size == sizeof(target), NULL); sml_fail_unless(memcmp(target, buffer, size) == 0, NULL); g_free(buffer); smlNotificationFree(san); } END_TEST START_TEST (san_alert) { setup_testbed(NULL); SmlError *error = NULL; SmlNotification *san = smlNotificationNew(SML_SAN_VERSION_12, SML_SAN_UIMODE_USER, SML_SAN_INITIATOR_SERVER, 65535, "ttttt", "/", SML_MIMETYPE_UNKNOWN, &error); sml_fail_unless(san != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlNotificationNewAlert(san, SML_ALERT_TWO_WAY_BY_SERVER, SML_ELEMENT_TEXT_VCARD, "tttt", &error), NULL); sml_fail_unless(error == NULL, NULL); unsigned char target[] = { /* old implementation without digest support 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //DIGEST */ 0x7e, 0x39, 0x00, 0x91, 0x5e, 0x39, 0x3a, 0x69, 0xd2, 0x60, 0x18, 0x1f, 0x65, 0x65, 0x49, 0xe5, //DIGEST 0x03, 0x38, //version + ui + init + start of future 0x00, 0x00, 0x00, //Future 0xFF, 0xFF, //Session id 0x05, 0x74, 0x74, 0x74, 0x74, 0x74, //server identifier 0x10,// num syncs + future 0x60, //Sync type + future 0x00, 0x00, 0x07, //Content type 0x04, 0x74, 0x74, 0x74, 0x74}; //Server URI; char *buffer = NULL; unsigned int size = 0; sml_fail_unless(smlNotificationAssemble(san, &buffer, &size, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(size == sizeof(target), NULL); sml_fail_unless(memcmp(target, buffer, size) == 0, NULL); g_free(buffer); smlNotificationFree(san); } END_TEST START_TEST (san_alert2) { setup_testbed(NULL); SmlError *error = NULL; SmlNotification *san = smlNotificationNew(SML_SAN_VERSION_12, SML_SAN_UIMODE_USER, SML_SAN_INITIATOR_SERVER, 65535, "ttttt", "/", SML_MIMETYPE_UNKNOWN, &error); sml_fail_unless(san != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlNotificationNewAlert(san, SML_ALERT_TWO_WAY_BY_SERVER, SML_ELEMENT_TEXT_VCARD, "tttt", &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlNotificationNewAlert(san, SML_ALERT_REFRESH_FROM_SERVER_BY_SERVER, SML_ELEMENT_TEXT_VCARD, "tttt", &error), NULL); sml_fail_unless(error == NULL, NULL); unsigned char target[] = { /* old implementation without digest support 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //DIGEST */ 0x6d, 0x47, 0xd6, 0x78, 0xb2, 0xe0, 0xa3, 0x72, 0x75, 0x03, 0xcc, 0xae, 0xd0, 0x39, 0x3d, 0xea, //DIGEST 0x03, 0x38, //version + ui + init + start of future 0x00, 0x00, 0x00, //Future 0xFF, 0xFF, //Session id 0x05, 0x74, 0x74, 0x74, 0x74, 0x74, //server identifier 0x20,// num syncs + future 0x60, //Sync type + future 0x00, 0x00, 0x07, //Content type 0x04, 0x74, 0x74, 0x74, 0x74, //Server URI; 0xA0, //Sync type + future 0x00, 0x00, 0x07, //Content type 0x04, 0x74, 0x74, 0x74, 0x74}; //Server URI; char *buffer = NULL; unsigned int size = 0; sml_fail_unless(smlNotificationAssemble(san, &buffer, &size, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(size == sizeof(target), NULL); sml_fail_unless(memcmp(target, buffer, size) == 0, NULL); g_free(buffer); smlNotificationFree(san); } END_TEST START_TEST (san_alert_auth) { setup_testbed(NULL); SmlError *error = NULL; SmlNotification *san = smlNotificationNew(SML_SAN_VERSION_12, SML_SAN_UIMODE_USER, SML_SAN_INITIATOR_SERVER, 65535, "OpenSync", "/", SML_MIMETYPE_UNKNOWN, &error); sml_fail_unless(san != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlNotificationNewAlert(san, SML_ALERT_TWO_WAY_BY_SERVER, SML_ELEMENT_TEXT_VCARD, "contacts", &error), NULL); sml_fail_unless(error == NULL, NULL); SmlCred *cred = smlCredNewAuth( SML_AUTH_TYPE_MD5, "username", "password", &error); smlNotificationSetCred(san, cred); smlCredUnref(cred); unsigned char target[] = { 0x61, 0x59, 0x71, 0x16, 0x2e, 0x7d, 0x3e, 0x83, 0xa8, 0x23, 0x48, 0xa8, 0x5b, 0x21, 0x79, 0x49, //DIGEST 0x03, 0x38, //version + ui + init + start of future 0x00, 0x00, 0x00, //Future 0xFF, 0xFF, //Session id 0x08, 0x4f, 0x70, 0x65, 0x6e, 0x53, 0x79, 0x6e, 0x63, //server identifier 0x10,// num syncs + future 0x60, //Sync type + future 0x00, 0x00, 0x07, //Content type 0x08, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x63, 0x74, 0x73}; //Server URI; char *buffer = NULL; unsigned int size = 0; sml_fail_unless(smlNotificationAssemble(san, &buffer, &size, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(size == sizeof(target), NULL); sml_fail_unless(memcmp(target, buffer, size) == 0, NULL); g_free(buffer); smlNotificationFree(san); } END_TEST START_TEST (san_11_assemble_parse) { setup_testbed(NULL); SmlError *error = NULL; SmlNotification *san = smlNotificationNew(SML_SAN_VERSION_11, SML_SAN_UIMODE_USER, SML_SAN_INITIATOR_SERVER, 65535, "ttttt", "/", SML_MIMETYPE_XML, &error); sml_fail_unless(san != NULL, NULL); sml_fail_unless(error == NULL, NULL); SmlManager *manager = _start_manager(); smlNotificationSetManager(san, manager); sml_fail_unless(smlNotificationNewAlert(san, SML_ALERT_TWO_WAY_BY_SERVER, SML_ELEMENT_TEXT_VCARD, "tttt", &error), NULL); sml_fail_unless(error == NULL, NULL); char *buffer = NULL; unsigned int size = 0; sml_fail_unless(smlNotificationAssemble(san, &buffer, &size, &error), NULL); sml_fail_unless(error == NULL, NULL); smlNotificationFree(san); _stop_manager(manager); smlSafeCFree(&buffer); /* SyncML 1.1 SAN parsing is not supported today. * Such messages are assembled and parsed like * normal SyncML messages with the default XML * parser and assembler which is tested separately. */ //san = smlNotificationParse(buffer, size, &error); //sml_fail_unless(san != NULL, NULL); //sml_fail_unless(error == NULL, NULL); //g_free(buffer); //sml_fail_unless(smlNotificationGetVersion(san) == SML_SAN_VERSION_11, NULL); //sml_fail_unless(smlNotificationGetMode(san) == SML_SAN_UIMODE_USER, NULL); //sml_fail_unless(smlNotificationGetInitiator(san) == SML_SAN_INITIATOR_SERVER, NULL); //sml_fail_unless(smlNotificationGetSessionID(san) == 65535, NULL); //sml_fail_unless(!strcmp(smlNotificationGetIdentifier(san), "ttttt"), NULL); //sml_fail_unless(smlNotificationNumAlerts(san) == 1, NULL); //SmlSanAlert *alert = smlNotificationNthAlert(san, 0); //sml_fail_unless(alert != NULL, NULL); //sml_fail_unless(smlSanAlertGetType(alert) == SML_ALERT_TWO_WAY_BY_SERVER, NULL); //sml_fail_unless(!strcmp(smlSanAlertGetContentType(alert), SML_ELEMENT_TEXT_VCARD), NULL); //sml_fail_unless(!strcmp(smlSanAlertGetServerURI(alert), "tttt"), NULL); //smlNotificationFree(san); } END_TEST START_TEST (san_parse) { setup_testbed(NULL); unsigned char target[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //DIGEST 0x03, 0x38, //version + ui + init + start of future 0x00, 0x00, 0x00, //Future 0xFF, 0xFF, //Session id 0x06, 0x74, 0x74, 0x74, 0x74, 0x74, 0x00, //server identifier 0x20,// num syncs + future 0x60, //Sync type + future 0x00, 0x00, 0x07, //Content type 0x05, 0x74, 0x74, 0x74, 0x74, 0x00, //Server URI; 0xA0, //Sync type + future 0x00, 0x00, 0x07, //Content type 0x05, 0x74, 0x74, 0x74, 0x74, 0x00 }; //Server URI; SmlError *error = NULL; SmlNotification *san = smlNotificationParse((char *) target, sizeof(target), &error); sml_fail_unless(san != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlNotificationGetVersion(san) == SML_SAN_VERSION_12, NULL); sml_fail_unless(smlNotificationGetMode(san) == SML_SAN_UIMODE_USER, NULL); sml_fail_unless(smlNotificationGetInitiator(san) == SML_SAN_INITIATOR_SERVER, NULL); sml_fail_unless(smlNotificationGetSessionID(san) == 65535, NULL); sml_fail_unless(!strcmp(smlNotificationGetIdentifier(san), "ttttt"), NULL); sml_fail_unless(smlNotificationNumAlerts(san) == 2, NULL); SmlSanAlert *alert = smlNotificationNthAlert(san, 0); sml_fail_unless(alert != NULL, NULL); sml_fail_unless(smlSanAlertGetType(alert) == SML_ALERT_TWO_WAY_BY_SERVER, NULL); sml_fail_unless(!strcmp(smlSanAlertGetContentType(alert), SML_ELEMENT_TEXT_VCARD), NULL); sml_fail_unless(!strcmp(smlSanAlertGetServerURI(alert), "tttt"), NULL); alert = smlNotificationNthAlert(san, 1); sml_fail_unless(alert != NULL, NULL); sml_fail_unless(smlSanAlertGetType(alert) == SML_ALERT_REFRESH_FROM_SERVER_BY_SERVER, NULL); sml_fail_unless(!strcmp(smlSanAlertGetContentType(alert), SML_ELEMENT_TEXT_VCARD), NULL); sml_fail_unless(!strcmp(smlSanAlertGetServerURI(alert), "tttt"), NULL); smlNotificationFree(san); } END_TEST START_TEST (san_parse2) { setup_testbed(NULL); unsigned char target[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //DIGEST 0x03, 0x00, //version + ui + init + start of future 0x00, 0x00, 0x00, //Future 0x00, 0x00, //Session id 0x00, //server identifier 0x00}; //num syncs SmlError *error = NULL; SmlNotification *san = smlNotificationParse((char *) target, sizeof(target), &error); sml_fail_unless(san != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlNotificationGetVersion(san) == SML_SAN_VERSION_12, NULL); sml_fail_unless(smlNotificationGetMode(san) == SML_SAN_UIMODE_UNSPECIFIED, NULL); sml_fail_unless(smlNotificationGetInitiator(san) == SML_SAN_INITIATOR_USER, NULL); sml_fail_unless(smlNotificationGetSessionID(san) == 0, NULL); sml_fail_unless(smlNotificationGetIdentifier(san) == NULL, NULL); sml_fail_unless(smlNotificationNumAlerts(san) == 0, NULL); smlNotificationFree(san); } END_TEST START_TEST (san_parse_error) { setup_testbed(NULL); unsigned char target[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //DIGEST 0x03, 0x00, //version + ui + init + start of future 0x00, 0x00, 0x00, //Future 0x00, 0x00, //Session id 0x00}; //num syncs SmlError *error = NULL; SmlNotification *san = smlNotificationParse((char *) target, sizeof(target), &error); sml_fail_unless(san == NULL, NULL); sml_fail_unless(error != NULL, NULL); smlErrorDeref(&error); } END_TEST START_TEST (san_parse_error2) { setup_testbed(NULL); unsigned char target[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //DIGEST 0x03, 0x00, //version + ui + init + start of future 0x00, 0x00, 0x00, //Future 0x00, 0x00, //Session id 0x01, //server identifier 0x00}; //num syncs SmlError *error = NULL; SmlNotification *san = smlNotificationParse((char *) target, sizeof(target), &error); sml_fail_unless(san == NULL, NULL); sml_fail_unless(error != NULL, NULL); smlErrorDeref(&error); } END_TEST START_TEST (san_parse_error3) { setup_testbed(NULL); unsigned char target[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //DIGEST 0x03, 0x00, //version + ui + init + start of future 0x00, 0x00, 0x00, //Future 0x00, 0x00, //Session id 0x01, 0x00,//server identifier 0x10}; //num syncs SmlError *error = NULL; SmlNotification *san = smlNotificationParse((char *) target, sizeof(target), &error); sml_fail_unless(san == NULL, NULL); sml_fail_unless(error != NULL, NULL); smlErrorDeref(&error); } END_TEST START_TEST (san_parse_error4) { setup_testbed(NULL); char target[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //DIGEST 0x02, 0x00, //version + ui + init + start of future 0x00, 0x00, 0x00, //Future 0x00, 0x00, //Session id 0x01, 0x00,//server identifier 0x00}; //num syncs SmlError *error = NULL; SmlNotification *san = smlNotificationParse(target, sizeof(target), &error); sml_fail_unless(san == NULL, NULL); sml_fail_unless(error != NULL, NULL); smlErrorDeref(&error); } END_TEST START_TEST (san_parse_error5) { setup_testbed(NULL); unsigned char target[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //DIGEST 0x03, 0x38, //version + ui + init + start of future 0x00, 0x00, 0x00, //Future 0xFF, 0xFF, //Session id 0x06, 0x74, 0x74, 0x74, 0x74, 0x74, 0x00, //server identifier 0x10,// num syncs + future 0x50, //Sync type + future 0x00, 0x00, 0x07, //Content type 0x05, 0x74, 0x74, 0x74, 0x74, 0x00}; //Server URI; SmlError *error = NULL; SmlNotification *san = smlNotificationParse((char *) target, sizeof(target), &error); sml_fail_unless(san == NULL, NULL); sml_fail_unless(error != NULL, NULL); smlErrorDeref(&error); } END_TEST START_TEST (san_parse_error6) { setup_testbed(NULL); unsigned char target[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //DIGEST 0x03, 0x38, //version + ui + init + start of future 0x00, 0x00, 0x00, //Future 0xFF, 0xFF, //Session id 0x06, 0x74, 0x74, 0x74, 0x74, 0x74, 0x00, //server identifier 0x10,// num syncs + future 0x70, //Sync type + future 0x00, 0x00, 0x07, //Content type 0x01}; //Server URI; SmlError *error = NULL; SmlNotification *san = smlNotificationParse((char *) target, sizeof(target), &error); sml_fail_unless(san == NULL, NULL); sml_fail_unless(error != NULL, NULL); smlErrorDeref(&error); } END_TEST START_TEST (san_parse_error7) { setup_testbed(NULL); unsigned char target[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //DIGEST 0x03, 0x38, //version + ui + init + start of future 0x00, 0x00, 0x00, //Future 0xFF, 0xFF, //Session id 0x06, 0x74, 0x74, 0x74, 0x74, 0x74, 0x00, //server identifier 0x10,// num syncs + future 0x70, //Sync type + future 0x00, 0x00, 0x07, //Content type 0x01, 0x00, 0x00}; //Server URI; SmlError *error = NULL; SmlNotification *san = smlNotificationParse((char *) target, sizeof(target), &error); sml_fail_unless(san == NULL, NULL); sml_fail_unless(error != NULL, NULL); smlErrorDeref(&error); } END_TEST /*START_TEST (san_send) { setup_testbed(NULL); SmlError *error = NULL; SmlNotification *san = smlNotificationNew(SML_SAN_VERSION_12, SML_SAN_UIMODE_USER, SML_SAN_INITIATOR_SERVER, 65535, "ttttt", "/", &error); sml_fail_unless(san != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlNotificationNewAlert(san, SML_ALERT_TWO_WAY_BY_SERVER, SML_ELEMENT_TEXT_VCARD, "tttt", &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlNotificationNewAlert(san, SML_ALERT_REFRESH_FROM_SERVER_BY_SERVER, SML_ELEMENT_TEXT_VCARD, "ttttaaaa", &error), NULL); sml_fail_unless(error == NULL, NULL); char *buffer = NULL; unsigned int size = 0; sml_fail_unless(smlNotificationAssemble(san, &buffer, &size, &error), NULL); sml_fail_unless(error == NULL, NULL); SmlBool smlNotificationSend(SmlNotification *san, SmlTransport *tsp, SmlTransportSendCb callback, void *userdata, SmlError **error) sml_fail_unless(size == sizeof(target), NULL); sml_fail_unless(memcmp(target, buffer, size) == 0, NULL); g_free(buffer); smlNotificationFree(san); } END_TEST*/ @SML_TESTCASE_CODE@ libsyncml-0.5.4/tests/check_base64.c100644 1750 1750 13756 11211710410 17204 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2005 Armin Bauer * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include "tests/support.h" START_TEST (check_base64_decode_null) { SmlError *error = NULL; char *buffer = NULL; unsigned int buffersize = 0; sml_fail_unless(smlBase64Decode(NULL, &buffer, &buffersize, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(buffer == NULL, NULL); sml_fail_unless(buffersize == 0, NULL); } END_TEST START_TEST (check_base64_decode_null2) { SmlError *error = NULL; char *buffer = NULL; unsigned int buffersize = 0; sml_fail_unless(smlBase64Decode(NULL, &buffer, &buffersize, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(buffer == NULL, NULL); sml_fail_unless(buffersize == 0, NULL); } END_TEST START_TEST (check_base64_decode_test) { char *data = "dGVzdA=="; SmlError *error = NULL; char *buffer = NULL; unsigned int buffersize = 0; sml_fail_unless(smlBase64Decode(data, &buffer, &buffersize, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(!strcmp(buffer, "test"), NULL); sml_fail_unless(buffersize == 5, "The returned buffer hast not the correct length (%u instead of %u).", buffersize, 5); g_free(buffer); } END_TEST START_TEST (check_base64_decode_size) { char *data = "dGVzdA==/&%(§("; SmlError *error = NULL; char *buffer = NULL; unsigned int buffersize = 0; sml_fail_unless(smlBase64DecodeBinary(data, 8, &buffer, &buffersize, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(buffersize == 5, "The returned buffer size (%u) was not the expected buffer size (%u).", buffersize, 5); sml_fail_unless(!strncmp(buffer, "test", 4), NULL); g_free(buffer); } END_TEST START_TEST (check_base64_decode2) { char *data = "JlwiKKcpJD09YD9cJ1wnKy0tLiw7Pjw="; SmlError *error = NULL; char *buffer = NULL; unsigned int buffersize = 0; sml_fail_unless(smlBase64Decode(data, &buffer, &buffersize, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(!strncmp(buffer, "&\\\"(§)$==`?\\\'\\\'+--.,;><", 4), NULL); sml_fail_unless(buffersize == 24, NULL); g_free(buffer); } END_TEST START_TEST (check_base64_decode3) { char *data = "dGVzdDE="; SmlError *error = NULL; char *buffer = NULL; unsigned int buffersize = 0; sml_fail_unless(smlBase64Decode(data, &buffer, &buffersize, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(!strncmp(buffer, "test1", 4), NULL); sml_fail_unless(buffersize == 6, NULL); g_free(buffer); } END_TEST START_TEST (check_base64_decode4) { char *data = "dGVzdDEx"; SmlError *error = NULL; char *buffer = NULL; unsigned int buffersize = 0; sml_fail_unless(smlBase64Decode(data, &buffer, &buffersize, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(!strncmp(buffer, "test11", 4), NULL); sml_fail_unless(buffersize == 7, NULL); g_free(buffer); } END_TEST START_TEST (check_base64_invalid1) { char *data = "$%§$%&"; SmlError *error = NULL; char *buffer = NULL; unsigned int buffersize = 0; sml_fail_unless(!smlBase64Decode(data, &buffer, &buffersize, &error), NULL); sml_fail_unless(error != NULL, NULL); } END_TEST START_TEST (check_base64_empty) { char *data = ""; SmlError *error = NULL; char *buffer = (char *)1; unsigned int buffersize = 1; sml_fail_unless(smlBase64Decode(data, &buffer, &buffersize, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(buffer == NULL, NULL); sml_fail_unless(buffersize == 0, NULL); } END_TEST /* Too many "=" do not produce invalid base64 - see openssl base64. * So this is an invalid test. */ /* START_TEST (check_base64_invalid2) { char *data = "dGVz===="; SmlError *error = NULL; char *buffer = NULL; unsigned int buffersize = 0; sml_fail_unless(!smlBase64Decode(data, &buffer, &buffersize, &error), NULL); sml_fail_unless(error != NULL, NULL); } END_TEST */ START_TEST (check_base64_encode_null) { SmlError *error = NULL; char *buffer = (char *)1; sml_fail_unless(smlBase64Encode(NULL, &buffer, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(buffer == NULL, NULL); } END_TEST START_TEST (check_base64_encode_null2) { SmlError *error = NULL; char *buffer = (char *)1; sml_fail_unless(smlBase64EncodeBinary(NULL, 0, &buffer, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(buffer == NULL, NULL); } END_TEST START_TEST (check_base64_encode_test) { char *data = "test"; SmlError *error = NULL; char *buffer = NULL; sml_fail_unless(smlBase64Encode(data, &buffer, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(!strcmp(buffer, "dGVzdA=="), NULL); g_free(buffer); } END_TEST START_TEST (check_base64_encode_test2) { char *data = "test1"; SmlError *error = NULL; char *buffer = NULL; sml_fail_unless(smlBase64Encode(data, &buffer, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(!strcmp(buffer, "dGVzdDE="), NULL); g_free(buffer); } END_TEST START_TEST (check_base64_encode_test3) { char *data = "test11"; SmlError *error = NULL; char *buffer = NULL; sml_fail_unless(smlBase64Encode(data, &buffer, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(!strcmp(buffer, "dGVzdDEx"), NULL); g_free(buffer); } END_TEST @SML_TESTCASE_CODE@ libsyncml-0.5.4/tests/coverage.sh.cmake100755 1750 1750 3451 11211710410 17777 0ustar00bellmichbellmich#!/bin/sh echo -n "Checking Code Coverage of unit tests" DATE=$( date +%Y%m%d%H%M%S ) if [ -d .svn ]; then REV=`LANG=C svn info | grep Revision | cut -c 11-` echo " for SVN Revision: $REV" TITLE="libsyncml_SVN"$REV"_"$DATE else echo ":" TITLE="libsyncml_"$DATE fi echo $TITLE if ! [ -d ${CMAKE_BINARY_DIR}/coverage/html ]; then mkdir -p ${CMAKE_BINARY_DIR}/coverage/html fi ## compile tests RESULT=`find ${CMAKE_CURRENT_BINARY_DIR} -name "*.o" -print | wc -l` if [ "$RESULT" == "0" ]; then make fi ## create gcda files RESULT=`find ${CMAKE_CURRENT_BINARY_DIR} -name "*.gcda" -print | wc -l` if [ "$RESULT" == "0" ]; then ctest -R . fi ## analyze statistics lcov \ --test-name "$TITLE" \ --base-directory ${CMAKE_SOURCE_DIR} \ --directory ${CMAKE_BINARY_DIR} \ --quiet \ --capture \ --output-file ${CMAKE_BINARY_DIR}/coverage/$TITLE.info genhtml --legend -t "$TITLE" -o ${CMAKE_BINARY_DIR}/coverage/html/$TITLE ${CMAKE_BINARY_DIR}/coverage/$TITLE.info &> /dev/null cd ${CMAKE_BINARY_DIR}/coverage/html/ if [ -e LATEST ]; then rm -f LATEST; fi ln -s $TITLE LATEST cd ${CMAKE_BINARY_DIR} ## cleanup gcda files #lcov \ # --test-name "$TITLE" \ # --base-directory ${CMAKE_SOURCE_DIR} \ # --directory ${CMAKE_BINARY_DIR} \ # --quiet \ # --zerocounters \ # --output-file coverage/$TITLE.info echo -n "Code Coverage is: " grep " %" coverage/html/$TITLE/index.html | sed -e "s/^[^>]*>//g" -e "s/<[^>]*>//g" echo -n "" echo -e "\nTroubleshooting:\n If the Code Coverage number is quite low (less then 51%):" echo -e "\t-Did you run any unit tests before $0?" echo -e "\t-Did you build with enable_profiling=1?" echo -e "\t-Run ALL available unit tests!" echo -e "\t-Check if testcases in unit test are disabled!" echo -e "\t-Fix unit tests and their test cases!" echo -e "\t-Write new and more test cases!" exit 0 libsyncml-0.5.4/tests/check_xml_fix_broken_item_data.c100644 1750 1750 17047 11211710410 23132 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2005 Armin Bauer * Copyright (C) 2007-2008 Michael Bell * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include "tests/support.h" #include "libsyncml/parser/sml_xml_parse.c" START_TEST (xml_fix_broken_item_data_no_item) { const char *input_data = "askfdjasdkfjasd masldfjasldksdafsadada"; char *fixed_data = NULL; unsigned int fixed_size = 0; SmlError *error = NULL; sml_fail_unless( _smlXmlParserFixBrokenItemData( input_data, strlen(input_data), &fixed_data, &fixed_size, &error), "%s", smlErrorPrint(&error)); sml_fail_unless(error == NULL, "%s", smlErrorPrint(&error)); sml_fail_unless(fixed_size == strlen(input_data), "The data must not be fixed (size has changed)."); sml_fail_unless(strcmp(input_data, fixed_data) == 0, "The data must not be fixed."); g_free(fixed_data); } END_TEST START_TEST (xml_fix_broken_item_data_no_item_data) { const char *input_data = "askfdjasdkfjsdafsadada"; char *fixed_data = NULL; unsigned int fixed_size = 0; SmlError *error = NULL; sml_fail_unless( _smlXmlParserFixBrokenItemData( input_data, strlen(input_data), &fixed_data, &fixed_size, &error), "%s", smlErrorPrint(&error)); sml_fail_unless(error == NULL, "%s", smlErrorPrint(&error)); sml_fail_unless(fixed_size == strlen(input_data), "The data must not be fixed (size has changed)."); sml_fail_unless(strcmp(input_data, fixed_data) == 0, "The data must not be fixed."); g_free(fixed_data); } END_TEST START_TEST (xml_fix_broken_item_data_no_broken_item_data) { const char *input_data = "askfdjasdkfjadada"; char *fixed_data = NULL; unsigned int fixed_size = 0; SmlError *error = NULL; sml_fail_unless( _smlXmlParserFixBrokenItemData( input_data, strlen(input_data), &fixed_data, &fixed_size, &error), "%s", smlErrorPrint(&error)); sml_fail_unless(error == NULL, "%s", smlErrorPrint(&error)); sml_fail_unless(fixed_size == strlen(input_data), "The data must not be fixed (size has changed)."); sml_fail_unless(strcmp(input_data, fixed_data) == 0, "The data must not be fixed."); g_free(fixed_data); } END_TEST START_TEST (xml_fix_broken_item_data_one_broken_item_data) { const char *input_data = "askfdjasdkfjThis is binary data.adada"; const char *output_data = "askfdjasdkfjadada"; char *fixed_data = NULL; unsigned int fixed_size = 0; SmlError *error = NULL; sml_fail_unless( _smlXmlParserFixBrokenItemData( input_data, strlen(input_data), &fixed_data, &fixed_size, &error), "%s", smlErrorPrint(&error)); sml_fail_unless(error == NULL, "%s", smlErrorPrint(&error)); /* compare it and check the expected length */ sml_fail_unless(fixed_size != strlen(input_data), "The data must be fixed (size has not changed)."); sml_fail_unless(strcmp(input_data, fixed_data) != 0, "The data must be fixed."); sml_fail_unless(fixed_size == strlen(output_data), "The length of the fixed data is wrong."); sml_fail_unless(strcmp(output_data, fixed_data) == 0, "The fixed data is wrong.\nExpected: %s\nOutput: %s", output_data, fixed_data); g_free(fixed_data); } END_TEST START_TEST (xml_fix_broken_item_data_multi_broken_item_data) { const char *input_data = "askftest1" \ "adadtest2adada"; const char *output_data = "askf" \ "adadadada"; char *fixed_data = NULL; unsigned int fixed_size = 0; SmlError *error = NULL; sml_fail_unless( _smlXmlParserFixBrokenItemData( input_data, strlen(input_data), &fixed_data, &fixed_size, &error), "%s", smlErrorPrint(&error)); sml_fail_unless(error == NULL, "%s", smlErrorPrint(&error)); /* compare it and check the expected length */ sml_fail_unless(fixed_size != strlen(input_data), "The data must be fixed (size has not changed)."); sml_fail_unless(strcmp(input_data, fixed_data) != 0, "The data must be fixed."); sml_fail_unless(fixed_size == strlen(output_data), "The length of the fixed data is wrong."); sml_fail_unless(strcmp(output_data, fixed_data) == 0, "The fixed data is wrong.\nExpected: %s\nOutput: %s", output_data, fixed_data); g_free(fixed_data); } END_TEST START_TEST (xml_fix_broken_item_data_mixed_broken_item_data) { const char *input_data = "askftest1" \ "adadadada" \ "adadtest3adada" \ "adadadada" \ "adadtest5adada"; const char *output_data = "askf" \ "adadadada" \ "adadadada" \ "adadadada" \ "adadadada"; char *fixed_data = NULL; unsigned int fixed_size = 0; SmlError *error = NULL; sml_fail_unless( _smlXmlParserFixBrokenItemData( input_data, strlen(input_data), &fixed_data, &fixed_size, &error), "%s", smlErrorPrint(&error)); sml_fail_unless(error == NULL, "%s", smlErrorPrint(&error)); /* compare it and check the expected length */ sml_fail_unless(fixed_size != strlen(input_data), "The data must be fixed (size has not changed)."); sml_fail_unless(strcmp(input_data, fixed_data) != 0, "The data must be fixed."); sml_fail_unless(fixed_size == strlen(output_data), "The length of the fixed data is wrong."); sml_fail_unless(strcmp(output_data, fixed_data) == 0, "The fixed data is wrong.\nExpected: %s\nOutput: %s", output_data, fixed_data); g_free(fixed_data); } END_TEST START_TEST (xml_fix_broken_item_data_utf16_conversion) { SmlError *error = NULL; char *input_data = smlTryMalloc0(20, &error); sml_fail_unless(error == NULL, "%s", smlErrorPrint(&error)); input_data[0] = 65; /* A */ input_data[1] = 66; /* B */ input_data[3] = 67; /* C */ input_data[5] = 68; /* D */ input_data[6] = 69; /* E */ input_data[7] = 70; /* F*/ input_data[8] = 71; /* G */ input_data[10] = 72; /* H */ input_data[12] = 73; /* I */ input_data[13] = 74; /* J */ size_t length = 14; char *fixed_data = NULL; unsigned int fixed_size = 0; /* check UTF-16 conversion of_smlXmlParserFixBrokenItemData */ sml_fail_unless( _smlXmlParserFixBrokenItemData( input_data, length, &fixed_data, &fixed_size, &error), "%s", smlErrorPrint(&error)); sml_fail_unless(error == NULL, "%s", smlErrorPrint(&error)); sml_fail_unless(fixed_size == strlen("ABCDEFGHIJ"), "%d != %d", fixed_size, strlen("ABCDEFGHIJ")); sml_fail_unless(strcmp(fixed_data, "ABCDEFGHIJ") == 0, NULL); g_free(input_data); g_free(fixed_data); } END_TEST @SML_TESTCASE_CODE@ libsyncml-0.5.4/tests/check_libsoup.c100644 1750 1750 33316 11211710410 17567 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2009 Michael Bell * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include "tests/support.h" #include #include #include #include #include #include #include #ifdef HAVE_LIBSOUP22 #define soup_message_headers_get soup_message_get_header #define soup_message_headers_append soup_message_add_header #endif static int server_messages; static int server_connects; static int server_disconnects; static int server_errors; static int client_messages; static int client_connects; static int client_disconnects; static int client_errors; static void init_testbed() { setup_testbed(NULL); g_type_init(); server_messages = 0; server_errors = 0; client_messages = 0; client_connects = 0; client_disconnects = 0; client_errors = 0; } /* dummy callback for the transport queue */ void transport_dummy_callback(void *message, void *userdata) { /* this function should never be called */ smlTrace(TRACE_ERROR, "%s(%p, %p)", __func__, message, userdata); g_atomic_int_inc(&server_errors); } #ifdef HAVE_LIBSOUP22 static void server_callback( SoupServerContext *context, SoupMessage *msg, gpointer data) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, context, msg, data); #else static void server_callback( SoupServer *server, SoupMessage *msg, const char *path, GHashTable *query, SoupClientContext *client, gpointer data) { /* additional stuff is only traced to avoid warnings from gcc profiling */ smlTrace(TRACE_ENTRY, "%s(%p, %p, %s, %p, %p, %p)", __func__, server, msg, path, query, client, data); #endif smlAssert(msg); #ifdef HAVE_LIBSOUP22 const char *content = msg->request.body; size_t length = msg->request.length; #else smlAssert(msg->request_body); const char *content = msg->request_body->data; size_t length = msg->request_body->length; #endif if (length < strlen("test")) { g_atomic_int_inc(&server_errors); } else if (memcmp("test", content, 4) == 0) { g_atomic_int_inc(&server_messages); } else { g_atomic_int_inc(&server_errors); } /* prepare the response*/ soup_message_set_status (msg, SOUP_STATUS_OK); soup_message_set_response ( msg, SML_ELEMENT_XML, #ifdef HAVE_LIBSOUP22 SOUP_BUFFER_STATIC, #else SOUP_MEMORY_STATIC, #endif "answer", 6); smlTrace(TRACE_EXIT, "%s", __func__); } #ifdef HAVE_LIBSOUP22 static void client_callback(SoupMessage *msg, gpointer userdata) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, msg, userdata); #else static void client_callback( SoupSession *session, SoupMessage *msg, gpointer userdata) { /* session is only traced to avoid warnings from gcc profiling */ smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, session, msg, userdata); #endif g_atomic_int_inc(&client_messages); smlTrace(TRACE_EXIT, "%s", __func__); } GMainContext *server_ctx; SmlThread *server_thread; SmlQueue *queue; SoupServer *server; SmlLink *server_link; static void init_server(unsigned int port) { smlTrace(TRACE_ENTRY, "%s", __func__); SmlError *error = NULL; /* prepare asynchronous runtime environment */ server_ctx = g_main_context_new(); sml_fail_unless(server_ctx != NULL, NULL); server_thread = smlThreadNew(server_ctx, &error); sml_fail_unless(server_thread != NULL, "%s", smlErrorPrint(&error)); /* simulate the transport layer behaviour */ queue = smlQueueNew(&error); sml_fail_unless(queue != NULL, "%s", smlErrorPrint(&error)); smlQueueSetHandler(queue, (SmlQueueHandler)transport_dummy_callback, NULL); smlQueueAttach(queue, server_ctx); /* create async server */ server = soup_server_new ( SOUP_SERVER_PORT, port, SOUP_SERVER_ASYNC_CONTEXT, server_ctx, NULL); sml_fail_unless(server != NULL, NULL); #ifdef HAVE_LIBSOUP22 soup_server_add_handler( server, NULL, NULL, server_callback, NULL, NULL); #else soup_server_add_handler ( server, NULL, server_callback, NULL, NULL); #endif soup_server_run_async (server); /* start thread */ smlThreadStart(server_thread); smlTrace(TRACE_EXIT, "%s", __func__); } static void cleanup_server() { smlTrace(TRACE_ENTRY, "%s", __func__); /* wait until message was received by server */ int64_t sleep_max = 5000000000LL; int64_t sleep_interval = 50000000; int64_t sleep_total = 0; while (server_messages < 1 && server_errors < 1 && sleep_total < sleep_max) { sml_sleep(sleep_interval); sleep_total += sleep_interval; } /* check counter */ sml_fail_unless(sleep_total < sleep_max, "timeout detected"); sml_fail_unless(server_messages == 1, NULL); sml_fail_unless(server_errors == 0, NULL); /* cleanup */ smlThreadStop(server_thread); smlThreadFree(server_thread); g_main_context_unref(server_ctx); soup_server_quit(server); g_object_unref(server); smlQueueFree(queue); smlTrace(TRACE_EXIT, "%s", __func__); } SmlBool _recv_event( SmlTransport *tsp, SmlLink *link_, SmlTransportEventType type, SmlTransportData *data, SmlError *error, void *userdata) { smlTrace(TRACE_ENTRY, "%s(%d)", __func__, type); int source = GPOINTER_TO_INT(userdata); switch (type) { case SML_TRANSPORT_EVENT_CONNECT_DONE: if (source == 1) g_atomic_int_inc(&client_connects); else g_atomic_int_inc(&server_connects); break; case SML_TRANSPORT_EVENT_DISCONNECT_DONE: if (source == 1) g_atomic_int_inc(&client_disconnects); else g_atomic_int_inc(&server_disconnects); break; case SML_TRANSPORT_EVENT_DATA: sml_fail_unless(1 <= source && source <= 2, NULL); if (source == 1) { sml_fail_unless(!strcmp(data->data, "answer"), NULL); sml_fail_unless(data->size == 6, NULL); sml_fail_unless(data->type == SML_MIMETYPE_XML, NULL); g_atomic_int_inc(&client_messages); } else { if (link_) { server_link = link_; smlLinkRef(server_link); } sml_fail_unless(!strcmp(data->data, "test"), NULL); sml_fail_unless(data->size == 4, NULL); sml_fail_unless(data->type == SML_MIMETYPE_XML, NULL); g_atomic_int_inc(&server_messages); data = smlTransportDataNew( (char *)"answer", 6, SML_MIMETYPE_XML, FALSE, &error); sml_fail_unless(data != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlTransportSend(tsp, server_link, data, &error), NULL); sml_fail_unless(error == NULL, NULL); smlTransportDataDeref(data); } break; case SML_TRANSPORT_EVENT_ERROR: sml_fail_unless(error != NULL, NULL); if (source == 1) g_atomic_int_inc(&client_errors); else g_atomic_int_inc(&server_errors); break; default: sml_fail_unless(FALSE, "An unexpected transport event %d was received.", type); break; } smlTrace(TRACE_EXIT, "%s()", __func__); return TRUE; } static void run_transport_client(const char *url) { smlTrace(TRACE_ENTRY, "%s", __func__); SmlError *error = NULL; /* init client */ SmlTransport *client = smlTransportNew(SML_TRANSPORT_HTTP_CLIENT, &error); sml_fail_unless(smlTransportSetConfigOption(client, "URL", url, &error), NULL); smlTransportSetEventCallback(client, _recv_event, GINT_TO_POINTER(1)); sml_fail_unless(smlTransportInitialize(client, &error), "%s", smlErrorPrint(&error)); /* send test message */ SmlTransportData *data = smlTransportDataNew((char *)"test", 4, SML_MIMETYPE_XML, FALSE, &error); sml_fail_unless(data != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlTransportSend(client, NULL, data, &error), NULL); sml_fail_unless(error == NULL, NULL); smlTransportDataDeref(data); /* wait for client connect */ int64_t sleep_max = 5000000000LL; int64_t sleep_interval = 50000000; int64_t sleep_total = 0; while (client_connects < 1 && sleep_total < sleep_max) { sml_sleep(sleep_interval); sleep_total += sleep_interval; } sml_fail_unless(sleep_total < sleep_max, "client connect timed out"); /* cleanup client */ sml_fail_unless(smlTransportDisconnect(client, NULL, &error), "%s", smlErrorPrint(&error)); sleep_total = 0; while (client_disconnects < 1 && client_errors < 1 && sleep_total < sleep_max) { sml_sleep(sleep_interval); sleep_total += sleep_interval; } sml_fail_unless(client_errors == 0, NULL); sml_fail_unless(sleep_total < sleep_max, "client disconnect timed out"); sml_fail_unless(smlTransportFinalize(client, &error), NULL); smlTransportFree(client); /* verify results */ sml_fail_unless(client_errors == 0, NULL); // sml_fail_unless(client_messages != 0, NULL); smlTrace(TRACE_EXIT, "%s", __func__); } GMainContext *client_ctx; SoupSession *client_session; SmlBool init_soup_session(gpointer data, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p)", __func__, data, error); sml_fail_unless(data != NULL, NULL); SoupMessage *msg = data; client_session = soup_session_async_new_with_options( SOUP_SESSION_ASYNC_CONTEXT, client_ctx, SOUP_SESSION_TIMEOUT, 5, NULL); sml_fail_unless(client_session != NULL, NULL); soup_session_queue_message(client_session, msg, client_callback, NULL); return TRUE; } SmlBool cleanup_soup_session(gpointer data, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p)", __func__, data, error); smlTrace(TRACE_INTERNAL, "%s: aborting session", __func__); soup_session_abort(client_session); smlTrace(TRACE_INTERNAL, "%s: unref session", __func__); g_object_unref(client_session); smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; } START_TEST (libsoup_async) { smlTrace(TRACE_ENTRY, "%s", __func__); init_testbed(); SmlError *error = NULL; init_server(13001); /* prepare message */ SoupMessage *msg = soup_message_new (SOUP_METHOD_POST, "http://127.0.0.1:13001/"); soup_message_headers_append(msg->request_headers, "Accept", "text/plain"); soup_message_set_request (msg, "text/plain", #ifdef HAVE_LIBSOUP22 SOUP_BUFFER_SYSTEM_OWNED, #else SOUP_MEMORY_TAKE, #endif g_memdup("test", 4), 4); #ifdef HAVE_LIBSOUP22_SOLARIS /* create synchronous client */ SoupSession *session = soup_session_sync_new(); soup_session_send_message(session, msg); client_callback(msg, NULL); #else /* create asynchronous client */ client_ctx = g_main_context_new(); sml_fail_unless(client_ctx != NULL, NULL); SmlThread *client_thread = smlThreadNew(client_ctx, &error); sml_fail_unless(client_thread != NULL, "%s", smlErrorPrint(&error)); smlThreadStart(client_thread); sml_fail_unless(smlThreadCallFunction(client_thread, init_soup_session, msg, &error), "%s", smlErrorPrint(&error)); #endif /* test and cleanup server */ cleanup_server(); /* wait for client disconnect */ int64_t sleep_max = 5000000000LL; int64_t sleep_interval = 50000000; int64_t sleep_total = 0; while (client_messages < 1 && sleep_total < sleep_max) { sml_sleep(sleep_interval); sleep_total += sleep_interval; } sml_fail_unless(sleep_total < sleep_max, "client disconnect timed out"); #ifdef HAVE_LIBSOUP22_SOLARIS soup_session_abort(session); g_object_unref(session); #else /* cleanup session */ sml_fail_unless(smlThreadCallFunction(client_thread, cleanup_soup_session, NULL, &error), "%s", smlErrorPrint(&error)); /* The client thread must be stopped first * because libsoup is not thread safe. * If the client thread is still running * then the behaviour of the session is not predictable. */ smlTrace(TRACE_INTERNAL, "%s: cleanup client thread", __func__); smlThreadStop(client_thread); smlThreadFree(client_thread); smlTrace(TRACE_INTERNAL, "%s: cleanup client context", __func__); g_main_context_unref(client_ctx); #endif smlTrace(TRACE_EXIT, "%s", __func__); } END_TEST START_TEST (libsoup_http_client) { smlTrace(TRACE_ENTRY, "%s", __func__); init_testbed(); init_server(13002); run_transport_client("http://127.0.0.1:13002"); cleanup_server(); smlTrace(TRACE_EXIT, "%s", __func__); } END_TEST START_TEST (libsoup_http_server) { smlTrace(TRACE_ENTRY, "%s", __func__); init_testbed(); SmlError *error = NULL; /* init server transport */ SmlTransport *serverTsp = smlTransportNew(SML_TRANSPORT_HTTP_SERVER, &error); sml_fail_unless(serverTsp != NULL, "%s", smlErrorPrint(&error)); sml_fail_unless(smlTransportSetConfigOption(serverTsp, "PORT", "13003", &error), NULL); smlTransportSetEventCallback(serverTsp, _recv_event, GINT_TO_POINTER(2)); sml_fail_unless(smlTransportInitialize(serverTsp, &error), "%s", smlErrorPrint(&error)); /* client stuff */ run_transport_client("http://127.0.0.1:13003"); /* cleanup server transport */ sml_fail_unless(smlTransportDisconnect(serverTsp, server_link, &error), NULL); smlLinkDeref(server_link); int64_t sleep_max = 5000000000LL; int64_t sleep_interval = 50000000; int64_t sleep_total = 0; while (server_disconnects < 1 && server_errors < 1 && sleep_total < sleep_max) { sml_sleep(sleep_interval); sleep_total += sleep_interval; } sml_fail_unless(server_errors == 0, NULL); sml_fail_unless(sleep_total < sleep_max, "server disconnect timed out"); sml_fail_unless(smlTransportFinalize(serverTsp, &error), NULL); smlTransportFree(serverTsp); } END_TEST @SML_TESTCASE_CODE@ libsyncml-0.5.4/tests/check_wbxml_parser.c100644 1750 1750 63501 11211710410 20616 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2005 Armin Bauer * Copyright (C) 2008 Michael Bell * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include "tests/support.h" #ifdef ENABLE_WBXML #include #endif #include #include static SmlParser *start_wbxml_parser(const char *data) { setup_testbed(NULL); SmlError *error = NULL; SmlParser *parser = smlParserNew(SML_MIMETYPE_WBXML, 0, &error); sml_fail_unless(parser != NULL, NULL); sml_fail_unless(error == NULL, NULL); #ifdef ENABLE_WBXML char *buffer = NULL; unsigned int size = 0; sml_fail_unless(smlWbxmlConvertTo(NULL, data, &buffer, &size, &error), NULL); if (!smlParserStart(parser, buffer, size, &error)) { sml_fail_unless(error != NULL, NULL); smlErrorDeref(&error); /* the error is not used */ smlParserFree(parser); smlSafeCFree(&buffer); return NULL; } smlSafeCFree(&buffer); #endif return parser; } START_TEST (wbxml_parser_syncml_empty) { const char *data = ""; SmlParser *parser = start_wbxml_parser(data); sml_fail_unless(parser == NULL, NULL); } END_TEST START_TEST (wbxml_parser_no_syncbody) { const char *data = ""; SmlParser *parser = start_wbxml_parser(data); sml_fail_unless(parser != NULL, NULL); SmlError *error = NULL; SmlHeader *header = NULL; SmlCred *cred = NULL; sml_fail_unless(!smlParserGetHeader(parser, &header, &cred, &error), NULL); sml_fail_unless(header == NULL, NULL); sml_fail_unless(cred == NULL, NULL); sml_fail_unless(error != NULL, NULL); smlErrorDeref(&error); sml_fail_unless(!smlParserEnd(parser, NULL, NULL, &error), NULL); sml_fail_unless(error != NULL, NULL); smlErrorDeref(&error); smlParserFree(parser); } END_TEST START_TEST (wbxml_parser_no_synchdr) { const char *data = ""; SmlParser *parser = start_wbxml_parser(data); sml_fail_unless(parser == NULL, NULL); } END_TEST START_TEST (wbxml_parser_synchdr_empty) { const char *data = ""; SmlParser *parser = start_wbxml_parser(data); sml_fail_unless(parser != NULL, NULL); SmlError *error = NULL; SmlHeader *header = NULL; SmlCred *cred = NULL; sml_fail_unless(!smlParserGetHeader(parser, &header, &cred, &error), NULL); sml_fail_unless(header == NULL, NULL); sml_fail_unless(cred == NULL, NULL); sml_fail_unless(error != NULL, NULL); smlErrorDeref(&error); /* The empty SyncHdr is followed by an empty SyncHdr. * So the parser is at the correct position to finish successfully. */ sml_fail_unless(smlParserEnd(parser, NULL, NULL, &error), NULL); sml_fail_unless(error == NULL, NULL); smlParserFree(parser); } END_TEST START_TEST (wbxml_parser_synchdr_verproto) { const char *data = "SyncML/1.1"; SmlParser *parser = start_wbxml_parser(data); sml_fail_unless(parser != NULL, NULL); SmlError *error = NULL; SmlHeader *header = NULL; SmlCred *cred = NULL; sml_fail_unless(!smlParserGetHeader(parser, &header, &cred, &error), NULL); sml_fail_unless(header == NULL, NULL); sml_fail_unless(cred == NULL, NULL); sml_fail_unless(error != NULL, NULL); smlErrorDeref(&error); sml_fail_unless(!smlParserEnd(parser, NULL, NULL, &error), NULL); sml_fail_unless(error != NULL, NULL); smlErrorDeref(&error); smlParserFree(parser); } END_TEST START_TEST (wbxml_parser_synchdr_verdtd) { const char *data = "SyncML/1.11.1"; SmlParser *parser = start_wbxml_parser(data); sml_fail_unless(parser != NULL, NULL); SmlError *error = NULL; SmlHeader *header = NULL; SmlCred *cred = NULL; sml_fail_unless(!smlParserGetHeader(parser, &header, &cred, &error), NULL); sml_fail_unless(header == NULL, NULL); sml_fail_unless(cred == NULL, NULL); sml_fail_unless(error != NULL, NULL); smlErrorDeref(&error); sml_fail_unless(!smlParserEnd(parser, NULL, NULL, &error), NULL); sml_fail_unless(error != NULL, NULL); smlErrorDeref(&error); smlParserFree(parser); } END_TEST START_TEST (wbxml_parser_synchdr_msgid) { const char *data = "SyncML/1.11.11"; SmlParser *parser = start_wbxml_parser(data); sml_fail_unless(parser != NULL, NULL); SmlError *error = NULL; SmlHeader *header = NULL; SmlCred *cred = NULL; sml_fail_unless(!smlParserGetHeader(parser, &header, &cred, &error), NULL); sml_fail_unless(header == NULL, NULL); sml_fail_unless(cred == NULL, NULL); sml_fail_unless(error != NULL, NULL); smlErrorDeref(&error); sml_fail_unless(!smlParserEnd(parser, NULL, NULL, &error), NULL); sml_fail_unless(error != NULL, NULL); smlErrorDeref(&error); smlParserFree(parser); } END_TEST START_TEST (wbxml_parser_synchdr_sessionid) { const char *data = "SyncML/1.11.111"; SmlParser *parser = start_wbxml_parser(data); sml_fail_unless(parser != NULL, NULL); SmlError *error = NULL; SmlHeader *header = NULL; SmlCred *cred = NULL; sml_fail_unless(!smlParserGetHeader(parser, &header, &cred, &error), NULL); sml_fail_unless(header == NULL, NULL); sml_fail_unless(cred == NULL, NULL); sml_fail_unless(error != NULL, NULL); smlErrorDeref(&error); sml_fail_unless(!smlParserEnd(parser, NULL, NULL, &error), NULL); sml_fail_unless(error != NULL, NULL); smlErrorDeref(&error); smlParserFree(parser); } END_TEST START_TEST (wbxml_parser_synchdr_target) { const char *data = "SyncML/1.11.111test"; SmlParser *parser = start_wbxml_parser(data); sml_fail_unless(parser != NULL, NULL); SmlError *error = NULL; SmlHeader *header = NULL; SmlCred *cred = NULL; sml_fail_unless(!smlParserGetHeader(parser, &header, &cred, &error), NULL); sml_fail_unless(header == NULL, NULL); sml_fail_unless(cred == NULL, NULL); sml_fail_unless(error != NULL, NULL); smlErrorDeref(&error); sml_fail_unless(!smlParserEnd(parser, NULL, NULL, &error), NULL); sml_fail_unless(error != NULL, NULL); smlErrorDeref(&error); smlParserFree(parser); } END_TEST START_TEST (wbxml_parser_synchdr_source) { const char *data = "SyncML/1.11.111testtest"; SmlParser *parser = start_wbxml_parser(data); sml_fail_unless(parser != NULL, NULL); SmlError *error = NULL; SmlHeader *header = NULL; SmlCred *cred = NULL; sml_fail_unless(smlParserGetHeader(parser, &header, &cred, &error), NULL); sml_fail_unless(header != NULL, NULL); sml_fail_unless(cred == NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(header->messageID == 1, NULL); sml_fail_unless(header->target != NULL, NULL); sml_fail_unless(header->source != NULL, NULL); sml_fail_unless(header->protocol == SML_PROTOCOL_SYNCML, NULL); sml_fail_unless(header->version == SML_VERSION_11, NULL); sml_fail_unless(!strcmp(header->sessionID, "1"), NULL); smlHeaderFree(header); SmlStatus *status = NULL; sml_fail_unless(smlParserGetStatus(parser, &status, &error), NULL); sml_fail_unless(status == NULL, NULL); sml_fail_unless(error == NULL, NULL); SmlCommand *cmd = NULL; sml_fail_unless(smlParserGetCommand(parser, &cmd, &error), NULL); sml_fail_unless(cmd == NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlParserEnd(parser, NULL, NULL, &error), NULL); sml_fail_unless(error == NULL, NULL); smlParserFree(parser); } END_TEST START_TEST (wbxml_parser_synchdr_source2) { const char *data = "SyncML/1.11.11asdtesttest"; SmlParser *parser = start_wbxml_parser(data); sml_fail_unless(parser != NULL, NULL); SmlError *error = NULL; SmlHeader *header = NULL; SmlCred *cred = NULL; sml_fail_unless(smlParserGetHeader(parser, &header, &cred, &error), NULL); sml_fail_unless(header != NULL, NULL); sml_fail_unless(cred == NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(header->messageID == 1, NULL); sml_fail_unless(header->target != NULL, NULL); sml_fail_unless(header->source != NULL, NULL); sml_fail_unless(header->protocol == SML_PROTOCOL_SYNCML, NULL); sml_fail_unless(header->version == SML_VERSION_11, NULL); sml_fail_unless(!strcmp(header->sessionID, "asd"), NULL); smlHeaderFree(header); SmlStatus *status = NULL; sml_fail_unless(smlParserGetStatus(parser, &status, &error), NULL); sml_fail_unless(status == NULL, NULL); sml_fail_unless(error == NULL, NULL); SmlCommand *cmd = NULL; sml_fail_unless(smlParserGetCommand(parser, &cmd, &error), NULL); sml_fail_unless(cmd == NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlParserEnd(parser, NULL, NULL, &error), NULL); sml_fail_unless(error == NULL, NULL); smlParserFree(parser); } END_TEST START_TEST (wbxml_parser_synchdr_additional) { const char *data = "SyncML/1.11.111testtest"; SmlParser *parser = start_wbxml_parser(data); sml_fail_unless(parser != NULL, NULL); SmlError *error = NULL; SmlHeader *header = NULL; SmlCred *cred = NULL; sml_fail_unless(!smlParserGetHeader(parser, &header, &cred, &error), NULL); sml_fail_unless(header == NULL, NULL); sml_fail_unless(cred == NULL, NULL); sml_fail_unless(error != NULL, NULL); smlErrorDeref(&error); sml_fail_unless(!smlParserEnd(parser, NULL, NULL, &error), NULL); sml_fail_unless(error != NULL, NULL); smlErrorDeref(&error); smlParserFree(parser); } END_TEST START_TEST (wbxml_parser_status_empty) { const char *data = "SyncML/1.11.111testtest"; SmlParser *parser = start_wbxml_parser(data); sml_fail_unless(parser != NULL, NULL); SmlError *error = NULL; SmlHeader *header = NULL; SmlCred *cred = NULL; sml_fail_unless(smlParserGetHeader(parser, &header, &cred, &error), NULL); sml_fail_unless(header != NULL, NULL); sml_fail_unless(cred == NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(header->messageID == 1, NULL); smlHeaderFree(header); SmlStatus *status = NULL; sml_fail_unless(!smlParserGetStatus(parser, &status, &error), NULL); sml_fail_unless(status == NULL, NULL); sml_fail_unless(error != NULL, NULL); smlErrorDeref(&error); SmlCommand *cmd = NULL; sml_fail_unless(smlParserGetCommand(parser, &cmd, &error), NULL); sml_fail_unless(cmd == NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlParserEnd(parser, NULL, NULL, &error), NULL); sml_fail_unless(error == NULL, NULL); smlParserFree(parser); } END_TEST START_TEST (wbxml_parser_status_cmdid) { const char *data = "SyncML/1.11.111testtest1"; SmlParser *parser = start_wbxml_parser(data); sml_fail_unless(parser != NULL, NULL); SmlError *error = NULL; SmlHeader *header = NULL; SmlCred *cred = NULL; sml_fail_unless(smlParserGetHeader(parser, &header, &cred, &error), NULL); sml_fail_unless(header != NULL, NULL); sml_fail_unless(cred == NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(header->messageID == 1, NULL); smlHeaderFree(header); SmlStatus *status = NULL; sml_fail_unless(!smlParserGetStatus(parser, &status, &error), NULL); sml_fail_unless(status == NULL, NULL); sml_fail_unless(error != NULL, NULL); smlErrorDeref(&error); smlParserFree(parser); } END_TEST START_TEST (wbxml_parser_status_msgref) { const char *data = "SyncML/1.11.111testtest11"; SmlParser *parser = start_wbxml_parser(data); sml_fail_unless(parser != NULL, NULL); SmlError *error = NULL; SmlHeader *header = NULL; SmlCred *cred = NULL; sml_fail_unless(smlParserGetHeader(parser, &header, &cred, &error), NULL); sml_fail_unless(header != NULL, NULL); sml_fail_unless(cred == NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(header->messageID == 1, NULL); smlHeaderFree(header); SmlStatus *status = NULL; sml_fail_unless(!smlParserGetStatus(parser, &status, &error), NULL); sml_fail_unless(status == NULL, NULL); sml_fail_unless(error != NULL, NULL); smlErrorDeref(&error); smlParserFree(parser); } END_TEST START_TEST (wbxml_parser_status_cmdref) { const char *data = "SyncML/1.11.111testtest111"; SmlParser *parser = start_wbxml_parser(data); sml_fail_unless(parser != NULL, NULL); SmlError *error = NULL; SmlHeader *header = NULL; SmlCred *cred = NULL; sml_fail_unless(smlParserGetHeader(parser, &header, &cred, &error), NULL); sml_fail_unless(header != NULL, NULL); sml_fail_unless(cred == NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(header->messageID == 1, NULL); smlHeaderFree(header); SmlStatus *status = NULL; sml_fail_unless(!smlParserGetStatus(parser, &status, &error), NULL); sml_fail_unless(status == NULL, NULL); sml_fail_unless(error != NULL, NULL); smlErrorDeref(&error); smlParserFree(parser); } END_TEST START_TEST (wbxml_parser_status) { const char *data = "SyncML/1.11.111testtest110Sync"; SmlParser *parser = start_wbxml_parser(data); sml_fail_unless(parser != NULL, NULL); SmlError *error = NULL; SmlHeader *header = NULL; SmlCred *cred = NULL; sml_fail_unless(smlParserGetHeader(parser, &header, &cred, &error), NULL); sml_fail_unless(header != NULL, NULL); sml_fail_unless(cred == NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(header->messageID == 1, NULL); smlHeaderFree(header); SmlStatus *status = NULL; sml_fail_unless(smlParserGetStatus(parser, &status, &error), NULL); sml_fail_unless(status != NULL, NULL); sml_fail_unless(error == NULL, NULL); smlStatusUnref(status); sml_fail_unless(smlParserGetStatus(parser, &status, &error), NULL); sml_fail_unless(status == NULL, NULL); sml_fail_unless(error == NULL, NULL); SmlCommand *cmd = NULL; sml_fail_unless(smlParserGetCommand(parser, &cmd, &error), NULL); sml_fail_unless(cmd == NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlParserEnd(parser, NULL, NULL, &error), NULL); sml_fail_unless(error == NULL, NULL); smlParserFree(parser); } END_TEST START_TEST (wbxml_parser_status2) { const char *data = "SyncML/1.11.111testtest110Sync110Sync"; SmlParser *parser = start_wbxml_parser(data); sml_fail_unless(parser != NULL, NULL); SmlError *error = NULL; SmlHeader *header = NULL; SmlCred *cred = NULL; sml_fail_unless(smlParserGetHeader(parser, &header, &cred, &error), NULL); sml_fail_unless(header != NULL, NULL); sml_fail_unless(cred == NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(header->messageID == 1, NULL); smlHeaderFree(header); SmlStatus *status = NULL; sml_fail_unless(smlParserGetStatus(parser, &status, &error), NULL); sml_fail_unless(status != NULL, NULL); sml_fail_unless(error == NULL, NULL); smlStatusUnref(status); sml_fail_unless(smlParserGetStatus(parser, &status, &error), NULL); sml_fail_unless(status != NULL, NULL); sml_fail_unless(error == NULL, NULL); smlStatusUnref(status); sml_fail_unless(smlParserGetStatus(parser, &status, &error), NULL); sml_fail_unless(status == NULL, NULL); sml_fail_unless(error == NULL, NULL); SmlCommand *cmd = NULL; sml_fail_unless(smlParserGetCommand(parser, &cmd, &error), NULL); sml_fail_unless(cmd == NULL, NULL); sml_fail_unless(error == NULL, NULL); SmlBool final = TRUE; SmlBool end = TRUE; sml_fail_unless(smlParserEnd(parser, &final, &end, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(final == FALSE, NULL); sml_fail_unless(end == FALSE, NULL); smlParserFree(parser); } END_TEST START_TEST (wbxml_parser_final) { const char *data = "SyncML/1.11.111testtest110Sync110Sync"; SmlParser *parser = start_wbxml_parser(data); sml_fail_unless(parser != NULL, NULL); SmlError *error = NULL; SmlHeader *header = NULL; SmlCred *cred = NULL; sml_fail_unless(smlParserGetHeader(parser, &header, &cred, &error), NULL); sml_fail_unless(header != NULL, NULL); sml_fail_unless(cred == NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(header->messageID == 1, NULL); smlHeaderFree(header); SmlStatus *status = NULL; sml_fail_unless(smlParserGetStatus(parser, &status, &error), NULL); sml_fail_unless(status != NULL, NULL); sml_fail_unless(error == NULL, NULL); smlStatusUnref(status); sml_fail_unless(smlParserGetStatus(parser, &status, &error), NULL); sml_fail_unless(status != NULL, NULL); sml_fail_unless(error == NULL, NULL); smlStatusUnref(status); sml_fail_unless(smlParserGetStatus(parser, &status, &error), NULL); sml_fail_unless(status == NULL, NULL); sml_fail_unless(error == NULL, NULL); SmlCommand *cmd = NULL; sml_fail_unless(smlParserGetCommand(parser, &cmd, &error), NULL); sml_fail_unless(cmd == NULL, NULL); sml_fail_unless(error == NULL, NULL); SmlBool final = FALSE; SmlBool end = FALSE; sml_fail_unless(smlParserEnd(parser, &final, &end, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(final == TRUE, NULL); sml_fail_unless(end == TRUE, NULL); smlParserFree(parser); } END_TEST START_TEST (wbxml_parser_final2) { const char *data = "SyncML/1.11.111testtest110Sync110Sync"; SmlParser *parser = start_wbxml_parser(data); sml_fail_unless(parser != NULL, NULL); SmlError *error = NULL; SmlHeader *header = NULL; SmlCred *cred = NULL; sml_fail_unless(smlParserGetHeader(parser, &header, &cred, &error), NULL); sml_fail_unless(header != NULL, NULL); sml_fail_unless(cred == NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(header->messageID == 1, NULL); smlHeaderFree(header); SmlStatus *status = NULL; sml_fail_unless(smlParserGetStatus(parser, &status, &error), NULL); sml_fail_unless(status != NULL, NULL); sml_fail_unless(error == NULL, NULL); smlStatusUnref(status); sml_fail_unless(smlParserGetStatus(parser, &status, &error), NULL); sml_fail_unless(status != NULL, NULL); sml_fail_unless(error == NULL, NULL); smlStatusUnref(status); sml_fail_unless(smlParserGetStatus(parser, &status, &error), NULL); sml_fail_unless(status == NULL, NULL); sml_fail_unless(error == NULL, NULL); SmlCommand *cmd = NULL; sml_fail_unless(smlParserGetCommand(parser, &cmd, &error), NULL); sml_fail_unless(cmd == NULL, NULL); sml_fail_unless(error == NULL, NULL); SmlBool final = FALSE; SmlBool end = FALSE; sml_fail_unless(smlParserEnd(parser, &final, &end, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(final == TRUE, NULL); sml_fail_unless(end == TRUE, NULL); smlParserFree(parser); } END_TEST START_TEST (wbxml_parser_cmd) { const char *data = "SyncML/1.11.111testtest1/test/testNextlast200"; SmlParser *parser = start_wbxml_parser(data); sml_fail_unless(parser != NULL, NULL); SmlError *error = NULL; SmlHeader *header = NULL; SmlCred *cred = NULL; sml_fail_unless(smlParserGetHeader(parser, &header, &cred, &error), NULL); sml_fail_unless(header != NULL, NULL); sml_fail_unless(cred == NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(header->messageID == 1, NULL); smlHeaderFree(header); SmlStatus *status = NULL; sml_fail_unless(smlParserGetStatus(parser, &status, &error), NULL); sml_fail_unless(status == NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlParserGetStatus(parser, &status, &error), NULL); sml_fail_unless(status == NULL, NULL); sml_fail_unless(error == NULL, NULL); SmlCommand *cmd = NULL; sml_fail_unless(smlParserGetCommand(parser, &cmd, &error), NULL); sml_fail_unless(cmd != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(cmd->cmdID == 1, NULL); smlCommandUnref(cmd); sml_fail_unless(smlParserGetCommand(parser, &cmd, &error), NULL); sml_fail_unless(cmd == NULL, NULL); sml_fail_unless(error == NULL, NULL); SmlBool final = TRUE; SmlBool end = TRUE; sml_fail_unless(smlParserEnd(parser, &final, &end, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(final == FALSE, NULL); sml_fail_unless(end == FALSE, NULL); smlParserFree(parser); } END_TEST START_TEST (wbxml_parser_cmd_final) { const char *data = "SyncML/1.11.111testtest1/test/testNextlast200"; SmlParser *parser = start_wbxml_parser(data); sml_fail_unless(parser != NULL, NULL); SmlError *error = NULL; SmlHeader *header = NULL; SmlCred *cred = NULL; sml_fail_unless(smlParserGetHeader(parser, &header, &cred, &error), NULL); sml_fail_unless(header != NULL, NULL); sml_fail_unless(cred == NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(header->messageID == 1, NULL); smlHeaderFree(header); SmlStatus *status = NULL; sml_fail_unless(smlParserGetStatus(parser, &status, &error), NULL); sml_fail_unless(status == NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlParserGetStatus(parser, &status, &error), NULL); sml_fail_unless(status == NULL, NULL); sml_fail_unless(error == NULL, NULL); SmlCommand *cmd = NULL; sml_fail_unless(smlParserGetCommand(parser, &cmd, &error), NULL); sml_fail_unless(cmd != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(cmd->cmdID == 1, NULL); smlCommandUnref(cmd); sml_fail_unless(smlParserGetCommand(parser, &cmd, &error), NULL); sml_fail_unless(cmd == NULL, NULL); sml_fail_unless(error == NULL, NULL); SmlBool final = FALSE; SmlBool end = TRUE; sml_fail_unless(smlParserEnd(parser, &final, &end, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(final == TRUE, NULL); sml_fail_unless(end == FALSE, NULL); smlParserFree(parser); } END_TEST @SML_TESTCASE_CODE@ libsyncml-0.5.4/tests/check_session.c100644 1750 1750 273424 11211710410 17623 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2005 Armin Bauer * Copyright (C) 2008 Michael Bell * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include "tests/support.h" #include #include #include #include #include typedef struct SmlSessionThread { GMainContext *context; GSourceFuncs *functions; GSourceFuncs *data_functions; GSource *data_source; GSource *session_source; SmlThread *thread; SmlSession *session; SmlTransportData **data; } SmlSessionThread; gint current_msg_id = 1; gint current_cmd_id = 1; gint data_received = 0; int start_commands_received = 0; int end_commands_received = 0; int finals_received = 0; int end_received = 0; int errors_received = 0; int numflushes = 0; int num_changes = 0; SmlTransportData *to_session = NULL; SmlTransportData *to_session2 = NULL; gint numreplies = 0; GMutex *mutex = NULL; char *item_data = NULL; unsigned int item_size = 0; unsigned int defaultMaxMsgSize = 10240; unsigned int defaultMaxObjSize = 1024000; void init_testbed() { current_msg_id = 1; current_cmd_id = 1; data_received = 0; start_commands_received = 0; end_commands_received = 0; finals_received = 0; end_received = 0; errors_received = 0; numflushes = 0; num_changes = 0; to_session = NULL; to_session2 = NULL; numreplies = 0; mutex = NULL; item_data = NULL; item_size = 0; // if (!g_thread_supported ()) g_thread_init (NULL); // g_type_init(); setup_testbed(NULL); } void cleanup_testbed() { if (to_session) { smlTransportDataDeref(to_session); to_session = NULL; } if (to_session2) { smlTransportDataDeref(to_session2); to_session2 = NULL; } } gboolean _session_prepare(GSource *source, gint *timeout_) { smlTrace(TRACE_INTERNAL, "%s(%p, %p)", __func__, source, timeout_); *timeout_ = 1; return FALSE; } gboolean _session_check(GSource *source) { SmlSession *session = *((SmlSession **)(source + 1)); return smlSessionCheck(session); } gboolean _session_dispatch(GSource *source, GSourceFunc callback, gpointer user_data) { smlTrace(TRACE_INTERNAL, "%s(%p, %p, %p)", __func__, source, callback, user_data); SmlSession *session = user_data; while (smlSessionCheck(session)) smlSessionDispatch(session); return TRUE; } gboolean _data_prepare(GSource *source, gint *timeout_) { smlTrace(TRACE_INTERNAL, "%s(%p, %p)", __func__, source, timeout_); *timeout_ = 1; return FALSE; } gboolean _data_check(GSource *source) { SmlSessionThread *thread = *((SmlSessionThread **)(source + 1)); smlAssert(thread != NULL); smlAssert(thread->data != NULL); if (*(thread->data)) return TRUE; return FALSE; } gboolean _data_dispatch(GSource *source, GSourceFunc callback, gpointer user_data) { smlTrace(TRACE_INTERNAL, "%s(%p. %p, %p)", __func__, source, callback, user_data); SmlSessionThread *check = user_data; SmlError *error = NULL; smlAssert(check != NULL); smlAssert(check->data != NULL); if (*(check->data)) { if (mutex) g_mutex_lock(mutex); SmlTransportData *data = *(check->data); *(check->data) = NULL; smlTrace(TRACE_ENTRY, "%s(data: %p, real %p, size %i)", __func__, data, data->data, data->size); SmlParser *parser = smlParserNew(data->type, 0, &error); smlAssert(parser != NULL); smlAssert(smlParserStart(parser, data->data, data->size, &error)); SmlHeader *header = NULL; SmlCred *cred = NULL; smlAssert(smlParserGetHeader(parser, &header, &cred, &error)); smlAssert(header != NULL); //smlAssert(header->messageID == current_msg_id); smlAssert(smlSessionReceiveHeader(check->session, header, &error)); smlHeaderFree(header); SmlStatus *reply = smlStatusNew(SML_NO_ERROR, 0, check->session->lastReceivedMessageID, check->session->source, check->session->target, SML_COMMAND_TYPE_HEADER, &error); smlAssert(smlSessionSendReply(check->session, reply, &error)); smlAssert(error == NULL); check->session->established = TRUE; smlStatusUnref(reply); g_atomic_int_inc(¤t_msg_id); smlAssert(smlSessionReceiveBody(check->session, parser, &error)); smlParserFree(parser); smlTransportDataDeref(data); *(check->data) = NULL; /* cleanup transport data reference */ if (mutex) g_mutex_unlock(mutex); smlTrace(TRACE_EXIT, "%s", __func__); } return TRUE; } SmlSessionThread *smlSessionRunAsync(SmlSession *session, SmlTransportData **input) { smlTrace(TRACE_ENTRY, "%s(%p, %p)", __func__, session, input); SmlError *error = NULL; SmlSessionThread *thread = g_malloc0(sizeof(SmlSessionThread)); thread->context = g_main_context_new(); g_main_context_ref(thread->context); thread->functions = g_malloc0(sizeof(GSourceFuncs)); thread->functions->prepare = _session_prepare; thread->functions->check = _session_check; thread->functions->dispatch = _session_dispatch; thread->functions->finalize = NULL; thread->session_source = g_source_new(thread->functions, sizeof(GSource) + sizeof(SmlSession *)); SmlSession **sessionptr = (SmlSession **)(thread->session_source + 1); *sessionptr = session; g_source_set_callback(thread->session_source, NULL, session, NULL); g_source_attach(thread->session_source, thread->context); thread->data_functions = g_malloc0(sizeof(GSourceFuncs)); thread->data_functions->prepare = _data_prepare; thread->data_functions->check = _data_check; thread->data_functions->dispatch = _data_dispatch; thread->data_functions->finalize = NULL; thread->data = input; thread->session = session; thread->data_source = g_source_new(thread->data_functions, sizeof(GSource) + sizeof(SmlSession *)); SmlSessionThread **threadptr = (SmlSessionThread **)(thread->data_source + 1); *threadptr = thread; g_source_set_callback(thread->data_source, NULL, thread, NULL); g_source_attach(thread->data_source, thread->context); thread->thread = smlThreadNew(thread->context, &error); sml_fail_unless(thread->thread != NULL, NULL); smlThreadStart(thread->thread); smlTrace(TRACE_EXIT, "%s", __func__); return thread; } /** @brief Stops a asynchronously running transport * * @param tsp The transport * */ void smlSessionStop(SmlSessionThread *thread) { smlTrace(TRACE_ENTRY, "%s(%p)", __func__, thread); smlAssert(thread); smlThreadStop(thread->thread); smlThreadFree(thread->thread); g_source_destroy(thread->data_source); g_source_unref(thread->data_source); g_source_destroy(thread->session_source); g_source_unref(thread->session_source); g_free(thread->functions); g_free(thread->data_functions); g_main_context_unref(thread->context); g_main_context_unref(thread->context); g_free(thread); smlTrace(TRACE_EXIT, "%s", __func__); } /* If the notification is a normal SyncML message then a manager is * required. The easiest way are two function which create and destroy * a default manager - only for testing. */ SmlTransport *_tsp = NULL; SmlManager* _start_manager() { SmlError *error = NULL; _tsp = smlTransportNew(SML_TRANSPORT_HTTP_SERVER, &error); sml_fail_unless(_tsp != NULL, "%s", smlErrorPrint(&error)); sml_fail_unless(error == NULL, "%s", smlErrorPrint(&error)); SmlManager *manager = smlManagerNew(_tsp, &error); sml_fail_unless(manager != NULL, "%s", smlErrorPrint(&error)); sml_fail_unless(error == NULL, "%s", smlErrorPrint(&error)); smlManagerSetLocalMaxMsgSize(manager, defaultMaxMsgSize); smlManagerSetLocalMaxObjSize(manager, defaultMaxObjSize); return manager; } void _stop_manager(SmlManager *manager) { smlManagerFree(manager); smlTransportFree(_tsp); } START_TEST (session_new) { init_testbed(); SmlError *error = NULL; SmlLocation *loc = smlLocationNew("/test", NULL, &error); sml_fail_unless(loc != NULL, NULL); sml_fail_unless(error == NULL, NULL); SmlSession *session = smlSessionNew(SML_SESSION_TYPE_CLIENT, SML_MIMETYPE_XML, SML_VERSION_12, SML_PROTOCOL_SYNCML, loc, loc, "1", 0, &error); sml_fail_unless(session != NULL, NULL); sml_fail_unless(error == NULL, NULL); smlSessionUnref(session); smlLocationUnref(loc); cleanup_testbed(); } END_TEST START_TEST (session_send) { init_testbed(); SmlError *error = NULL; SmlLocation *loc = smlLocationNew("/test", NULL, &error); sml_fail_unless(loc != NULL, NULL); sml_fail_unless(error == NULL, NULL); SmlSession *session = smlSessionNew(SML_SESSION_TYPE_CLIENT, SML_MIMETYPE_XML, SML_VERSION_12, SML_PROTOCOL_SYNCML, loc, loc, "1", 0, &error); SmlCommand *cmd = smlCommandNewAlert(SML_ALERT_TWO_WAY, loc, loc, "last", "next", NULL, &error); sml_fail_unless(cmd != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlSessionSendCommand(session, cmd, NULL, NULL, NULL, &error), NULL); sml_fail_unless(error == NULL, NULL); smlCommandUnref(cmd); smlSessionUnref(session); smlLocationUnref(loc); cleanup_testbed(); } END_TEST static void _event_callback(SmlSession *session, SmlSessionEventType type, SmlCommand *command, SmlCommand *parent, SmlStatus *reply, SmlError *error, void *userdata) { smlTrace(TRACE_ENTRY, "%s: %d (%p)", __func__, type, parent); smlAssert(GPOINTER_TO_INT(userdata) <= 5); SmlError *locerror = NULL; switch (type) { case SML_SESSION_EVENT_HEADER_REPLY: // FIXME: Why should the msgRef be the current_msg_id minus 2? // FIXME: This is wrong even if you count all messages // FIXME: because it depends on the SyncML role (server or client). // smlAssert(reply->msgRef == g_atomic_int_get(¤t_msg_id) - 2); smlAssert(reply->cmdRef == 0); g_atomic_int_inc(¤t_cmd_id); break; case SML_SESSION_EVENT_CHILD_COMMAND: case SML_SESSION_EVENT_COMMAND_START: g_atomic_int_inc(&start_commands_received); g_atomic_int_inc(&num_changes); g_atomic_int_inc(¤t_cmd_id); if (GPOINTER_TO_INT(userdata) == 3 && command->type == SML_COMMAND_TYPE_ADD) { smlAssert(command->private.change.items); smlAssert(g_list_length(command->private.change.items)); SmlItem *item = g_list_nth_data(command->private.change.items, 0); smlAssert(item); smlAssert(smlItemCheck(item)); char *data = NULL; unsigned int size = 0; smlAssert(smlItemGetData(item, &data, &size, &locerror)); smlAssert(size == 8); smlAssert(!strncmp(data, "datadata", 8)); } if (GPOINTER_TO_INT(userdata) == 4 && command->type == SML_COMMAND_TYPE_ADD) { smlAssert(command->private.change.items); smlAssert(g_list_length(command->private.change.items)); SmlItem *item = g_list_nth_data(command->private.change.items, 0); smlAssert(item); smlAssert(smlItemCheck(item)); char *data = NULL; unsigned int size = 0; smlAssert(smlItemGetData(item, &data, &size, &locerror)); smlAssert(size == 20); smlAssert(!strncmp(data, "datadatadatadatatest", 20)); } if (GPOINTER_TO_INT(userdata) == 5 && command->type == SML_COMMAND_TYPE_ADD) { smlAssert(command->private.change.items); smlAssert(g_list_length(command->private.change.items)); SmlItem *item = g_list_nth_data(command->private.change.items, 0); smlAssert(item); smlAssert(smlItemCheck(item)); char *data = NULL; unsigned int size = 0; smlAssert(smlItemGetData(item, &data, &size, &locerror)); if (size != 4) { smlAssert(size == item_size); smlAssert(!strncmp(data, item_data, item_size)); } else { smlAssert(size == 4); smlAssert(!strncmp(data, "data", 4)); } } SmlStatus *status = smlCommandNewReply(command, SML_NO_ERROR, &locerror); smlAssert(status != NULL); smlAssert(locerror == NULL); smlAssert(smlSessionSendReply(session, status, &locerror)); smlAssert(locerror == NULL); smlStatusUnref(status); break; case SML_SESSION_EVENT_COMMAND_END: g_atomic_int_inc(&end_commands_received); break; case SML_SESSION_EVENT_FINAL: g_atomic_int_inc(&finals_received); current_cmd_id = 1; break; case SML_SESSION_EVENT_END: g_atomic_int_inc(&end_received); break; case SML_SESSION_EVENT_FLUSH: current_cmd_id = 1; g_atomic_int_inc(&numflushes); break; case SML_SESSION_EVENT_ERROR: smlAssert(error != NULL); if (GPOINTER_TO_INT(userdata) == 2) g_atomic_int_inc(&errors_received); else { sml_fail_unless(FALSE, "%s", smlErrorPrint(&error)); abort(); } break; case SML_MANAGER_SESSION_ESTABLISHED: case SML_SESSION_EVENT_RESPONSE_URI: // not used here break; } smlTrace(TRACE_EXIT, "%s", __func__); } void _status_reply(SmlSession *session, SmlStatus *status, void *userdata) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, session, status, userdata); smlAssert(session != NULL); smlAssert(status != NULL); //smlAssert(status->msgRef == current_msg_id - 1); if (GPOINTER_TO_INT(userdata) == 2) { smlAssert(smlStatusGetCode(status) >= 500); } else if (GPOINTER_TO_INT(userdata) == 1) { smlAssert(smlStatusGetClass(status) == SML_ERRORCLASS_SUCCESS); } else abort(); g_atomic_int_inc(¤t_cmd_id); g_atomic_int_inc(&numreplies); smlTrace(TRACE_EXIT, "%s", __func__); } void _status_reply_conc(SmlSession *session, SmlStatus *status, void *userdata) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, session, status, userdata); smlAssert(session != NULL); smlAssert(status != NULL); smlAssert(smlStatusGetClass(status) == SML_ERRORCLASS_SUCCESS); g_atomic_int_inc(¤t_cmd_id); g_atomic_int_inc(&numreplies); smlTrace(TRACE_EXIT, "%s", __func__); } static void _data_send_callback(SmlSession *session, SmlTransportData *data, void *userdata) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, session, data, userdata); smlTrace(TRACE_INTERNAL, "%s: setting data(data: %p, real %p, size %i)", __func__, data, data->data, data->size); SmlTransportData **dataptr = userdata; if (*dataptr != NULL) smlTransportDataDeref(*dataptr); smlTransportDataRef(data); *dataptr = data; g_atomic_int_inc(&data_received); smlTrace(TRACE_EXIT, "%s", __func__); } START_TEST (session_flush) { init_testbed(); SmlError *error = NULL; SmlLocation *loc = smlLocationNew("/test", NULL, &error); sml_fail_unless(loc != NULL, NULL); sml_fail_unless(error == NULL, NULL); SmlSession *session = smlSessionNew(SML_SESSION_TYPE_CLIENT, SML_MIMETYPE_XML, SML_VERSION_12, SML_PROTOCOL_SYNCML, loc, loc, "1", 0, &error); SmlSessionThread *thread1 = smlSessionRunAsync(session, &to_session); smlSessionSetDataCallback(session, _data_send_callback, &to_session2); smlSessionSetEventCallback(session, _event_callback, GINT_TO_POINTER(1)); SmlCommand *cmd = smlCommandNewAlert(SML_ALERT_TWO_WAY, loc, loc, "last", "next", NULL, &error); sml_fail_unless(cmd != NULL, NULL); sml_fail_unless(error == NULL, NULL); smlLocationUnref(loc); sml_fail_unless(smlSessionSendCommand(session, cmd, NULL, NULL, NULL, &error), NULL); sml_fail_unless(error == NULL, NULL); smlCommandUnref(cmd); sml_fail_unless(smlSessionFlush(session, FALSE, &error), NULL); sml_fail_unless(error == NULL, NULL); while (data_received != 1) { usleep(100); } smlSessionStop(thread1); smlSessionUnref(session); cleanup_testbed(); } END_TEST START_TEST (session_flush_final) { init_testbed(); SmlError *error = NULL; SmlLocation *loc = smlLocationNew("/test", NULL, &error); sml_fail_unless(loc != NULL, NULL); sml_fail_unless(error == NULL, NULL); SmlSession *session = smlSessionNew(SML_SESSION_TYPE_CLIENT, SML_MIMETYPE_XML, SML_VERSION_12, SML_PROTOCOL_SYNCML, loc, loc, "1", 0, &error); SmlSessionThread *thread1 = smlSessionRunAsync(session, &to_session); smlSessionSetDataCallback(session, _data_send_callback, &to_session2); smlSessionSetEventCallback(session, _event_callback, GINT_TO_POINTER(1)); SmlCommand *cmd = smlCommandNewAlert(SML_ALERT_TWO_WAY, loc, loc, "last", "next", NULL, &error); sml_fail_unless(cmd != NULL, NULL); sml_fail_unless(error == NULL, NULL); smlLocationUnref(loc); sml_fail_unless(smlSessionSendCommand(session, cmd, NULL, NULL, NULL, &error), NULL); sml_fail_unless(error == NULL, NULL); smlCommandUnref(cmd); sml_fail_unless(smlSessionFlush(session, TRUE, &error), NULL); sml_fail_unless(error == NULL, NULL); while (data_received != 1) { usleep(100); } smlSessionStop(thread1); smlSessionUnref(session); cleanup_testbed(); } END_TEST /* Check that event callbacks are working */ START_TEST (session_recv) { init_testbed(); SmlError *error = NULL; SmlLocation *loc = smlLocationNew("/test", NULL, &error); sml_fail_unless(loc != NULL, NULL); sml_fail_unless(error == NULL, NULL); const char *input = "SyncML/1.11.211/test/test1/test/testlastnext200"; SmlParser *parser = smlParserNew(SML_MIMETYPE_XML, 0, &error); sml_fail_unless(parser != NULL, NULL); sml_fail_unless(smlParserStart(parser, input, strlen(input), &error), NULL); SmlHeader *header = NULL; SmlCred *cred = NULL; sml_fail_unless(smlParserGetHeader(parser, &header, &cred, &error), NULL); sml_fail_unless(header != NULL, NULL); sml_fail_unless(cred == NULL, NULL); SmlSession *session = smlSessionNew(SML_SESSION_TYPE_SERVER, SML_MIMETYPE_XML, SML_VERSION_12, SML_PROTOCOL_SYNCML, loc, loc, "1", 0, &error); smlSessionSetLocalMaxMsgSize(session, defaultMaxMsgSize); smlSessionSetLocalMaxObjSize(session, defaultMaxObjSize); smlLocationUnref(loc); smlSessionSetEventCallback(session, _event_callback, GINT_TO_POINTER(1)); sml_fail_unless(smlSessionReceiveHeader(session, header, &error), NULL); SmlStatus *reply = smlStatusNew(SML_NO_ERROR, 0, 1, session->source, session->target, SML_COMMAND_TYPE_HEADER, &error); sml_fail_unless(smlSessionSendReply(session, reply, &error), NULL); smlStatusUnref(reply); session->established = TRUE; sml_fail_unless(smlSessionReceiveBody(session, parser, &error), NULL); smlParserFree(parser); smlHeaderFree(header); sml_fail_unless(start_commands_received == 1, NULL); sml_fail_unless(finals_received == 1, NULL); sml_fail_unless(end_received == 0, NULL); smlSessionUnref(session); cleanup_testbed(); } END_TEST /* Check that a session can parse the output of another session */ START_TEST (session_transmit) { init_testbed(); SmlError *error = NULL; SmlLocation *loc = smlLocationNew("/test", NULL, &error); sml_fail_unless(loc != NULL, NULL); sml_fail_unless(error == NULL, NULL); SmlSession *session = smlSessionNew(SML_SESSION_TYPE_CLIENT, SML_MIMETYPE_XML, SML_VERSION_12, SML_PROTOCOL_SYNCML, loc, loc, "1", 0, &error); SmlSessionThread *thread1 = smlSessionRunAsync(session, &to_session); smlSessionSetDataCallback(session, _data_send_callback, &to_session2); smlSessionSetEventCallback(session, _event_callback, GINT_TO_POINTER(1)); SmlCommand *cmd = smlCommandNewAlert(SML_ALERT_TWO_WAY, loc, loc, "last", "next", NULL, &error); sml_fail_unless(cmd != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlSessionSendCommand(session, cmd, NULL, NULL, NULL, &error), NULL); sml_fail_unless(error == NULL, NULL); smlCommandUnref(cmd); sml_fail_unless(smlSessionFlush(session, TRUE, &error), NULL); sml_fail_unless(error == NULL, NULL); while (data_received != 1) { usleep(100); } smlSessionStop(thread1); smlSessionUnref(session); session = NULL; SmlParser *parser = smlParserNew(to_session2->type, 0, &error); sml_fail_unless(parser != NULL, NULL); sml_fail_unless(smlParserStart(parser, to_session2->data, to_session2->size, &error), NULL); SmlHeader *header = NULL; SmlCred *cred = NULL; sml_fail_unless(smlParserGetHeader(parser, &header, &cred, &error), NULL); SmlSession *session2 = smlSessionNew(SML_SESSION_TYPE_SERVER, SML_MIMETYPE_XML, SML_VERSION_12, SML_PROTOCOL_SYNCML, loc, loc, "1", 0, &error); smlSessionSetLocalMaxMsgSize(session2, defaultMaxMsgSize); smlSessionSetLocalMaxObjSize(session2, defaultMaxObjSize); smlLocationUnref(loc); smlSessionSetDataCallback(session2, _data_send_callback, &to_session); smlSessionSetEventCallback(session2, _event_callback, GINT_TO_POINTER(1)); sml_fail_unless(smlSessionReceiveHeader(session2, header, &error), NULL); SmlStatus *reply = smlStatusNew(SML_NO_ERROR, 0, 1, session2->source, session2->target, SML_COMMAND_TYPE_HEADER, &error); sml_fail_unless(smlSessionSendReply(session2, reply, &error), NULL); smlStatusUnref(reply); session2->established = TRUE; sml_fail_unless(smlSessionReceiveBody(session2, parser, &error), NULL); smlHeaderFree(header); sml_fail_unless(start_commands_received == 1, NULL); sml_fail_unless(finals_received == 1, NULL); sml_fail_unless(end_received == 0, NULL); smlParserFree(parser); smlSessionUnref(session2); cleanup_testbed(); } END_TEST /* Check if statuses are working */ /* session --- Alert --> session2 * session2 --- Status ---> Session */ START_TEST (session_reply) { init_testbed(); SmlError *error = NULL; SmlLocation *loc = smlLocationNew("/test", NULL, &error); sml_fail_unless(loc != NULL, NULL); sml_fail_unless(error == NULL, NULL); SmlSession *session = smlSessionNew(SML_SESSION_TYPE_CLIENT, SML_MIMETYPE_XML, SML_VERSION_12, SML_PROTOCOL_SYNCML, loc, loc, "1", 0, &error); SmlSessionThread *thread1 = smlSessionRunAsync(session, &to_session); SmlSession *session2 = smlSessionNew(SML_SESSION_TYPE_SERVER, SML_MIMETYPE_XML, SML_VERSION_12, SML_PROTOCOL_SYNCML, loc, loc, "1", 0, &error); SmlSessionThread *thread2 = smlSessionRunAsync(session2, &to_session2); smlSessionSetLocalMaxMsgSize(session2, defaultMaxMsgSize); smlSessionSetLocalMaxObjSize(session2, defaultMaxObjSize); smlSessionSetEventCallback(session2, _event_callback, GINT_TO_POINTER(1)); smlSessionSetDataCallback(session2, _data_send_callback, &to_session); smlSessionSetEventCallback(session, _event_callback, GINT_TO_POINTER(1)); smlSessionSetDataCallback(session, _data_send_callback, &to_session2); SmlCommand *cmd = smlCommandNewAlert(SML_ALERT_TWO_WAY, loc, loc, "last", "next", NULL, &error); sml_fail_unless(cmd != NULL, NULL); sml_fail_unless(error == NULL, NULL); smlLocationUnref(loc); sml_fail_unless(smlSessionSendCommand(session, cmd, NULL, _status_reply, GINT_TO_POINTER(1), &error), NULL); sml_fail_unless(error == NULL, NULL); smlCommandUnref(cmd); sml_fail_unless(smlSessionFlush(session, TRUE, &error), NULL); sml_fail_unless(error == NULL, NULL); while (finals_received != 1) { usleep(100); } sml_fail_unless(data_received == 1, NULL); sml_fail_unless(numreplies == 0, NULL); sml_fail_unless(start_commands_received == 1, NULL); sml_fail_unless(finals_received == 1, NULL); sml_fail_unless(end_received == 0, NULL); sml_fail_unless(smlSessionFlush(session2, TRUE, &error), NULL); sml_fail_unless(error == NULL, NULL); /* do not test on final because this is a race condition */ while (end_received < 2) { usleep(100); } sml_fail_unless(data_received == 2, NULL); sml_fail_unless(numreplies == 1, NULL); sml_fail_unless(start_commands_received == 1, NULL); sml_fail_unless(finals_received == 2, NULL); sml_fail_unless(end_received == 2, NULL); smlSessionStop(thread1); smlSessionStop(thread2); smlSessionUnref(session2); smlSessionUnref(session); cleanup_testbed(); } END_TEST /* Check if sessions can talk to each other * session2 must reply with a empty message since * it is a server * * session --- Alert --> session2 * session2 --- Status, Alert ---> session * session --- Status ---> session2 * session2 --- ---> session */ START_TEST (session_talk) { init_testbed(); SmlError *error = NULL; SmlLocation *loc = smlLocationNew("/test", NULL, &error); sml_fail_unless(loc != NULL, NULL); sml_fail_unless(error == NULL, NULL); SmlSession *session = smlSessionNew(SML_SESSION_TYPE_CLIENT, SML_MIMETYPE_XML, SML_VERSION_12, SML_PROTOCOL_SYNCML, loc, loc, "1", 0, &error); SmlSessionThread *thread1 = smlSessionRunAsync(session, &to_session); SmlSession *session2 = smlSessionNew(SML_SESSION_TYPE_SERVER, SML_MIMETYPE_XML, SML_VERSION_12, SML_PROTOCOL_SYNCML, loc, loc, "1", 0, &error); SmlSessionThread *thread2 = smlSessionRunAsync(session2, &to_session2); smlSessionSetLocalMaxMsgSize(session2, defaultMaxMsgSize); smlSessionSetLocalMaxObjSize(session2, defaultMaxObjSize); smlSessionSetEventCallback(session2, _event_callback, GINT_TO_POINTER(1)); smlSessionSetDataCallback(session2, _data_send_callback, &to_session); smlSessionSetEventCallback(session, _event_callback, GINT_TO_POINTER(1)); smlSessionSetDataCallback(session, _data_send_callback, &to_session2); SmlCommand *cmd = smlCommandNewAlert(SML_ALERT_TWO_WAY, loc, loc, "last", "next", NULL, &error); sml_fail_unless(cmd != NULL, NULL); sml_fail_unless(error == NULL, NULL); smlLocationUnref(loc); sml_fail_unless(smlSessionSendCommand(session, cmd, NULL, _status_reply, GINT_TO_POINTER(1), &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlSessionFlush(session, TRUE, &error), NULL); sml_fail_unless(error == NULL, NULL); while (finals_received != 1) { usleep(100); } sml_fail_unless(data_received == 1, NULL); sml_fail_unless(numreplies == 0, NULL); sml_fail_unless(start_commands_received == 1, NULL); sml_fail_unless(finals_received == 1, NULL); sml_fail_unless(end_received == 0, NULL); sml_fail_unless(smlSessionSendCommand(session2, cmd, NULL, _status_reply, GINT_TO_POINTER(1), &error), NULL); sml_fail_unless(error == NULL, NULL); smlCommandUnref(cmd); sml_fail_unless(smlSessionFlush(session2, TRUE, &error), NULL); sml_fail_unless(error == NULL, NULL); while (finals_received != 2) { usleep(100); } sml_fail_unless(data_received == 2, NULL); sml_fail_unless(numreplies == 1, NULL); sml_fail_unless(start_commands_received == 2, NULL); sml_fail_unless(finals_received == 2, NULL); sml_fail_unless(end_received == 0, NULL); sml_fail_unless(smlSessionFlush(session, TRUE, &error), NULL); sml_fail_unless(error == NULL, NULL); while (finals_received != 4 || end_received != 2) { usleep(100); } sml_fail_unless(data_received == 4, NULL); sml_fail_unless(numreplies == 2, NULL); sml_fail_unless(start_commands_received == 2, NULL); sml_fail_unless(finals_received == 4, NULL); sml_fail_unless(end_received == 2, NULL); smlSessionStop(thread1); smlSessionStop(thread2); smlSessionUnref(session2); smlSessionUnref(session); cleanup_testbed(); } END_TEST /* Check if sessions can talk to each other * session2 must reply with a empty message since * it is a server * * session --- num * Alert --> session2 * session2 --- num * Status, num * Alert ---> session * session --- num * Status ---> session2 * session2 --- ---> session */ START_TEST (session_talk_alot) { init_testbed(); int num_commands = 1000; SmlError *error = NULL; SmlLocation *loc = smlLocationNew("/test", NULL, &error); sml_fail_unless(loc != NULL, NULL); sml_fail_unless(error == NULL, NULL); SmlSession *session = smlSessionNew(SML_SESSION_TYPE_CLIENT, SML_MIMETYPE_XML, SML_VERSION_12, SML_PROTOCOL_SYNCML, loc, loc, "1", 0, &error); SmlSessionThread *thread1 = smlSessionRunAsync(session, &to_session); SmlSession *session2 = smlSessionNew(SML_SESSION_TYPE_SERVER, SML_MIMETYPE_XML, SML_VERSION_12, SML_PROTOCOL_SYNCML, loc, loc, "1", 0, &error); SmlSessionThread *thread2 = smlSessionRunAsync(session2, &to_session2); /* The test is not designed for splitted packages or objects. */ smlSessionSetLocalMaxMsgSize(session2, defaultMaxObjSize); smlSessionSetLocalMaxObjSize(session2, defaultMaxObjSize); smlSessionSetEventCallback(session2, _event_callback, GINT_TO_POINTER(1)); smlSessionSetDataCallback(session2, _data_send_callback, &to_session); smlSessionSetEventCallback(session, _event_callback, GINT_TO_POINTER(1)); smlSessionSetDataCallback(session, _data_send_callback, &to_session2); SmlCommand *cmd = smlCommandNewAlert(SML_ALERT_TWO_WAY, loc, loc, "last", "next", NULL, &error); sml_fail_unless(cmd != NULL, NULL); sml_fail_unless(error == NULL, NULL); smlLocationUnref(loc); int i = 0; for (i = 0; i < num_commands; i++) { sml_fail_unless(smlSessionSendCommand(session, cmd, NULL, _status_reply, GINT_TO_POINTER(1), &error), NULL); sml_fail_unless(error == NULL, NULL); } sml_fail_unless(smlSessionFlush(session, TRUE, &error), NULL); sml_fail_unless(error == NULL, NULL); while (finals_received != 1) { usleep(100); } sml_fail_unless(data_received == 1, NULL); sml_fail_unless(numreplies == 0, NULL); sml_fail_unless(start_commands_received == num_commands, NULL); sml_fail_unless(finals_received == 1, NULL); sml_fail_unless(end_received == 0, NULL); for (i = 0; i < num_commands; i++) { sml_fail_unless(smlSessionSendCommand(session2, cmd, NULL, _status_reply, GINT_TO_POINTER(1), &error), NULL); sml_fail_unless(error == NULL, NULL); } smlCommandUnref(cmd); sml_fail_unless(smlSessionFlush(session2, TRUE, &error), NULL); sml_fail_unless(error == NULL, NULL); while (finals_received != 2) { usleep(100); } sml_fail_unless(data_received == 2, NULL); sml_fail_unless(numreplies == num_commands, NULL); sml_fail_unless(start_commands_received == 2 * num_commands, NULL); sml_fail_unless(finals_received == 2, NULL); sml_fail_unless(end_received == 0, NULL); sml_fail_unless(smlSessionFlush(session, TRUE, &error), NULL); sml_fail_unless(error == NULL, "%s", smlErrorPrint(&error)); /*while (finals_received != 3) { usleep(100); } sml_fail_unless(data_received == 3, NULL); sml_fail_unless(numreplies == 2 * num_commands, NULL); sml_fail_unless(start_commands_received == 2 * num_commands, NULL); sml_fail_unless(finals_received == 3, NULL); sml_fail_unless(end_received == 0, NULL); sml_fail_unless(smlSessionFlush(session2, TRUE, &error), NULL); sml_fail_unless(error == NULL, NULL);*/ while (finals_received != 4 || end_received != 2) { usleep(100); } sml_fail_unless(data_received == 4, NULL); sml_fail_unless(numreplies == 2 * num_commands, NULL); sml_fail_unless(start_commands_received == 2 * num_commands, NULL); sml_fail_unless(finals_received == 4, NULL); sml_fail_unless(end_received == 2, NULL); smlSessionStop(thread1); smlSessionStop(thread2); smlSessionUnref(session2); smlSessionUnref(session); cleanup_testbed(); } END_TEST /* Check if sessions can talk to each other * session2 must reply with a empty message since * it is a server * * session --- num * Alert --> session2 * session2 --- num * Status, num * Alert ---> session * session --- num * Status ---> session2 * session2 --- ---> session */ START_TEST (session_talk_alot_limit) { init_testbed(); int num_commands = 1000; int limit = 20000; mutex = g_mutex_new(); SmlError *error = NULL; SmlLocation *loc = smlLocationNew("/test", NULL, &error); sml_fail_unless(loc != NULL, NULL); sml_fail_unless(error == NULL, NULL); SmlSession *session = smlSessionNew(SML_SESSION_TYPE_CLIENT, SML_MIMETYPE_XML, SML_VERSION_12, SML_PROTOCOL_SYNCML, loc, loc, "1", 0, &error); SmlSessionThread *thread1 = smlSessionRunAsync(session, &to_session); SmlSession *session2 = smlSessionNew(SML_SESSION_TYPE_SERVER, SML_MIMETYPE_XML, SML_VERSION_12, SML_PROTOCOL_SYNCML, loc, loc, "1", 0, &error); SmlSessionThread *thread2 = smlSessionRunAsync(session2, &to_session2); smlSessionSetLocalMaxMsgSize(session, limit); smlSessionSetRemoteMaxMsgSize(session, limit); smlSessionSetLocalMaxMsgSize(session2, limit); smlSessionSetLocalMaxObjSize(session2, defaultMaxObjSize); smlSessionSetRemoteMaxMsgSize(session2, limit); smlSessionSetEventCallback(session2, _event_callback, GINT_TO_POINTER(1)); smlSessionSetDataCallback(session2, _data_send_callback, &to_session); smlSessionSetEventCallback(session, _event_callback, GINT_TO_POINTER(1)); smlSessionSetDataCallback(session, _data_send_callback, &to_session2); SmlCommand *cmd = smlCommandNewAlert(SML_ALERT_TWO_WAY, loc, loc, "last", "next", NULL, &error); sml_fail_unless(cmd != NULL, NULL); sml_fail_unless(error == NULL, NULL); smlLocationUnref(loc); int i = 0; for (i = 0; i < num_commands; i++) { sml_fail_unless(smlSessionSendCommand(session, cmd, NULL, _status_reply, GINT_TO_POINTER(1), &error), NULL); sml_fail_unless(error == NULL, NULL); } sml_fail_unless(smlSessionFlush(session, TRUE, &error), NULL); sml_fail_unless(error == NULL, NULL); while (finals_received != 1) { usleep(100); } sml_fail_unless(start_commands_received == num_commands, NULL); sml_fail_unless(finals_received == 1, NULL); sml_fail_unless(end_received == 0, NULL); for (i = 0; i < num_commands; i++) { sml_fail_unless(smlSessionSendCommand(session2, cmd, NULL, _status_reply, GINT_TO_POINTER(1), &error), NULL); sml_fail_unless(error == NULL, NULL); } smlCommandUnref(cmd); sml_fail_unless(smlSessionFlush(session2, TRUE, &error), NULL); sml_fail_unless(error == NULL, NULL); while (finals_received != 2) { usleep(100); } sml_fail_unless(start_commands_received == 2 * num_commands, NULL); sml_fail_unless(finals_received == 2, NULL); sml_fail_unless(end_received == 0, NULL); sml_fail_unless(smlSessionFlush(session, TRUE, &error), NULL); sml_fail_unless(error == NULL, NULL); /*while (finals_received != 3) { usleep(100); } sml_fail_unless(numreplies == 2 * num_commands, NULL); sml_fail_unless(start_commands_received == 2 * num_commands, NULL); sml_fail_unless(finals_received == 3, NULL); sml_fail_unless(end_received == 0, NULL); sml_fail_unless(smlSessionFlush(session2, TRUE, &error), NULL); sml_fail_unless(error == NULL, NULL);*/ while (finals_received != 4 || end_received != 2) { usleep(100); } sml_fail_unless(numreplies == 2 * num_commands, NULL); sml_fail_unless(start_commands_received == 2 * num_commands, NULL); sml_fail_unless(finals_received == 4, NULL); sml_fail_unless(end_received == 2, NULL); smlSessionStop(thread1); smlSessionStop(thread2); smlSessionUnref(session2); smlSessionUnref(session); g_mutex_free(mutex); cleanup_testbed(); } END_TEST /* Check if the session obeys remote message * limits. * * For this we setup a session with the remote limit set. The * expected behaviour is to see * - first the commands are added * - when the limit is reached, the data callback should be called * - more commands can be added * - as soon the session receives the reply from the remote side (a status in our case) * the session should call the data callback again * * Flushing while waiting for the remote reply should be ignored * * session -- x Alert (not final) --> session2 * session2 -- x Status (not final) --> session * session -- y Alert (final) --> session2 * session2 -- y Alert (final) --> session * */ START_TEST (session_limit_remote) { init_testbed(); int num_commands = 100; int limit = 5000; mutex = g_mutex_new(); SmlError *error = NULL; SmlLocation *loc = smlLocationNew("/test", NULL, &error); sml_fail_unless(loc != NULL, NULL); sml_fail_unless(error == NULL, NULL); SmlSession *session = smlSessionNew(SML_SESSION_TYPE_CLIENT, SML_MIMETYPE_XML, SML_VERSION_12, SML_PROTOCOL_SYNCML, loc, loc, "1", 0, &error); SmlSessionThread *thread1 = smlSessionRunAsync(session, &to_session); SmlSession *session2 = smlSessionNew(SML_SESSION_TYPE_SERVER, SML_MIMETYPE_XML, SML_VERSION_12, SML_PROTOCOL_SYNCML, loc, loc, "1", 0, &error); SmlSessionThread *thread2 = smlSessionRunAsync(session2, &to_session2); smlSessionSetLocalMaxMsgSize(session, limit); smlSessionSetRemoteMaxMsgSize(session, limit); smlSessionSetLocalMaxMsgSize(session2, defaultMaxMsgSize); smlSessionSetLocalMaxObjSize(session2, defaultMaxObjSize); smlSessionSetEventCallback(session2, _event_callback, GINT_TO_POINTER(1)); smlSessionSetDataCallback(session2, _data_send_callback, &to_session); smlSessionSetEventCallback(session, _event_callback, GINT_TO_POINTER(1)); smlSessionSetDataCallback(session, _data_send_callback, &to_session2); SmlCommand *cmd = smlCommandNewAlert(SML_ALERT_TWO_WAY, loc, loc, "last", "next", NULL, &error); sml_fail_unless(cmd != NULL, NULL); sml_fail_unless(error == NULL, NULL); smlLocationUnref(loc); int i = 0; for (i = 0; i < num_commands; i++) { sml_fail_unless(smlSessionSendCommand(session, cmd, NULL, _status_reply, GINT_TO_POINTER(1), &error), NULL); sml_fail_unless(error == NULL, NULL); } sml_fail_unless(smlSessionFlush(session, TRUE, &error), NULL); sml_fail_unless(error == NULL, NULL); while (finals_received < 1) { usleep(100); } sml_fail_unless(start_commands_received == num_commands, NULL); sml_fail_unless(finals_received == 1, NULL); sml_fail_unless(end_received == 0, NULL); int flush_before = numflushes; for (i = 0; i < num_commands; i++) { sml_fail_unless(smlSessionSendCommand(session2, cmd, NULL, _status_reply, GINT_TO_POINTER(1), &error), NULL); sml_fail_unless(error == NULL, NULL); } smlCommandUnref(cmd); sml_fail_unless(smlSessionFlush(session2, TRUE, &error), NULL); sml_fail_unless(error == NULL, NULL); while (finals_received < 2) { usleep(100); } // fprintf(stderr, "numflushes: %i, flush_before: %i\n", numflushes, flush_before); sml_fail_unless(numflushes - flush_before > 5, "numflushes: %i, flush_before: %i", numflushes, flush_before); sml_fail_unless(start_commands_received == 2 * num_commands, NULL); sml_fail_unless(finals_received == 2, NULL); sml_fail_unless(end_received == 0, NULL); sml_fail_unless(smlSessionFlush(session, TRUE, &error), NULL); sml_fail_unless(error == NULL, NULL); while (finals_received != 4 || end_received != 2) { usleep(100); } sml_fail_unless(numreplies == 2 * num_commands, NULL); sml_fail_unless(start_commands_received == 2 * num_commands, NULL); sml_fail_unless(finals_received == 4, NULL); sml_fail_unless(end_received == 2, NULL); smlSessionStop(thread1); smlSessionStop(thread2); smlSessionUnref(session2); smlSessionUnref(session); g_mutex_free(mutex); cleanup_testbed(); } END_TEST START_TEST (session_split_child) { init_testbed(); int num_commands = 100; int limit = 5000; mutex = g_mutex_new(); setup_testbed(NULL); SmlError *error = NULL; SmlLocation *loc = smlLocationNew("/test", NULL, &error); sml_fail_unless(loc != NULL, NULL); sml_fail_unless(error == NULL, NULL); SmlSession *session = smlSessionNew(SML_SESSION_TYPE_CLIENT, SML_MIMETYPE_XML, SML_VERSION_12, SML_PROTOCOL_SYNCML, loc, loc, "1", 0, &error); SmlSessionThread *thread1 = smlSessionRunAsync(session, &to_session); SmlSession *session2 = smlSessionNew(SML_SESSION_TYPE_SERVER, SML_MIMETYPE_XML, SML_VERSION_12, SML_PROTOCOL_SYNCML, loc, loc, "1", 0, &error); SmlSessionThread *thread2 = smlSessionRunAsync(session2, &to_session2); smlSessionSetLocalMaxMsgSize(session, limit); smlSessionSetRemoteMaxMsgSize(session, limit); smlSessionSetLocalMaxMsgSize(session2, limit); smlSessionSetRemoteMaxMsgSize(session2, limit); smlSessionSetLocalMaxObjSize(session2, defaultMaxObjSize); smlSessionSetEventCallback(session2, _event_callback, GINT_TO_POINTER(1)); smlSessionSetDataCallback(session2, _data_send_callback, &to_session); smlSessionSetEventCallback(session, _event_callback, GINT_TO_POINTER(1)); smlSessionSetDataCallback(session, _data_send_callback, &to_session2); SmlCommand *cmd1 = smlCommandNewSync(loc, loc, 0, &error); sml_fail_unless(cmd1 != NULL, NULL); sml_fail_unless(error == NULL, NULL); smlLocationUnref(loc); SmlCommand *cmd2 = smlCommandNewChange(SML_CHANGE_ADD, "uid", "data", 5, SML_ELEMENT_TEXT_VCARD, &error); sml_fail_unless(smlSessionStartCommand(session, cmd1, NULL, _status_reply, GINT_TO_POINTER(1), &error), NULL); sml_fail_unless(error == NULL, NULL); int i = 0; for (i = 0; i < num_commands; i++) { sml_fail_unless(smlSessionSendCommand(session, cmd2, NULL, _status_reply, GINT_TO_POINTER(1), &error), NULL); sml_fail_unless(error == NULL, NULL); } sml_fail_unless(smlSessionEndCommand(session, NULL, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlSessionFlush(session, TRUE, &error), NULL); sml_fail_unless(error == NULL, NULL); while (finals_received != 1) { usleep(100); } sml_fail_unless(start_commands_received == num_commands + 1, NULL); sml_fail_unless(finals_received == 1, NULL); sml_fail_unless(end_received == 0, NULL); sml_fail_unless(smlSessionStartCommand(session2, cmd1, NULL, _status_reply, GINT_TO_POINTER(1), &error), NULL); sml_fail_unless(error == NULL, NULL); for (i = 0; i < num_commands; i++) { sml_fail_unless(smlSessionSendCommand(session2, cmd2, NULL, _status_reply, GINT_TO_POINTER(1), &error), NULL); sml_fail_unless(error == NULL, NULL); } sml_fail_unless(smlSessionEndCommand(session2, NULL, &error), NULL); sml_fail_unless(error == NULL, NULL); smlCommandUnref(cmd1); smlCommandUnref(cmd2); sml_fail_unless(smlSessionFlush(session2, TRUE, &error), NULL); sml_fail_unless(error == NULL, NULL); while (finals_received != 2) { usleep(100); } sml_fail_unless(start_commands_received == 2 * (num_commands + 1), NULL); sml_fail_unless(finals_received == 2, NULL); sml_fail_unless(end_received == 0, NULL); sml_fail_unless(smlSessionFlush(session, TRUE, &error), NULL); sml_fail_unless(error == NULL, NULL); /*while (finals_received != 3) { usleep(100); } sml_fail_unless(numreplies == 2 * (num_commands + 1), NULL); sml_fail_unless(start_commands_received == 2 * (num_commands + 1), NULL); sml_fail_unless(finals_received == 3, NULL); sml_fail_unless(end_received == 0, NULL); sml_fail_unless(smlSessionFlush(session2, TRUE, &error), NULL); sml_fail_unless(error == NULL, NULL);*/ while (finals_received != 4 || end_received != 2) { usleep(100); } sml_fail_unless(numreplies == 2 * (num_commands + 1), NULL); sml_fail_unless(start_commands_received == 2 * (num_commands + 1), NULL); sml_fail_unless(finals_received == 4, NULL); sml_fail_unless(end_received == 2, NULL); smlSessionStop(thread1); smlSessionStop(thread2); smlSessionUnref(session2); smlSessionUnref(session); g_mutex_free(mutex); cleanup_testbed(); } END_TEST START_TEST (session_recv_large_obj) { init_testbed(); SmlError *error = NULL; SmlLocation *loc = smlLocationNew("/test", NULL, &error); sml_fail_unless(loc != NULL, NULL); sml_fail_unless(error == NULL, NULL); const char *input = "SyncML/1.11.111/vcards/vcards1/vcards/vcards12text/x-vcard8uid"; SmlParser *parser = smlParserNew(SML_MIMETYPE_XML, 0, &error); sml_fail_unless(parser != NULL, NULL); sml_fail_unless(smlParserStart(parser, input, strlen(input), &error), NULL); SmlHeader *header = NULL; SmlCred *cred = NULL; sml_fail_unless(smlParserGetHeader(parser, &header, &cred, &error), NULL); sml_fail_unless(header != NULL, NULL); sml_fail_unless(cred == NULL, NULL); SmlSession *session = smlSessionNew(SML_SESSION_TYPE_SERVER, SML_MIMETYPE_XML, SML_VERSION_11, SML_PROTOCOL_SYNCML, loc, loc, "1", 0, &error); smlSessionSetLocalMaxMsgSize(session, defaultMaxMsgSize); smlSessionSetLocalMaxObjSize(session, defaultMaxObjSize); smlLocationUnref(loc); smlSessionSetEventCallback(session, _event_callback, GINT_TO_POINTER(3)); smlSessionSetDataCallback(session, _data_send_callback, &to_session2); sml_fail_unless(smlSessionReceiveHeader(session, header, &error), NULL); SmlStatus *reply = smlStatusNew(SML_NO_ERROR, 0, 1, session->source, session->target, SML_COMMAND_TYPE_HEADER, &error); sml_fail_unless(smlSessionSendReply(session, reply, &error), NULL); smlStatusUnref(reply); session->established = TRUE; sml_fail_unless(smlSessionReceiveBody(session, parser, &error), NULL); smlParserFree(parser); smlHeaderFree(header); sml_fail_unless(start_commands_received == 1, NULL); sml_fail_unless(finals_received == 0, NULL); sml_fail_unless(end_received == 0, NULL); sml_fail_unless(to_session2 != NULL, NULL); smlTransportDataDeref(to_session2); to_session2 = NULL; const char *input2 = "SyncML/1.11.121/vcards/vcards1/vcards/vcards2text/x-vcarduid"; parser = smlParserNew(SML_MIMETYPE_XML, 0, &error); sml_fail_unless(parser != NULL, NULL); sml_fail_unless(smlParserStart(parser, input2, strlen(input2), &error), NULL); sml_fail_unless(smlParserGetHeader(parser, &header, &cred, &error), NULL); sml_fail_unless(header != NULL, NULL); sml_fail_unless(cred == NULL, NULL); sml_fail_unless(smlSessionReceiveHeader(session, header, &error), NULL); reply = smlStatusNew(SML_NO_ERROR, 0, 2, session->source, session->target, SML_COMMAND_TYPE_HEADER, &error); sml_fail_unless(smlSessionSendReply(session, reply, &error), NULL); smlStatusUnref(reply); session->established = TRUE; sml_fail_unless(smlSessionReceiveBody(session, parser, &error), NULL); smlParserFree(parser); smlHeaderFree(header); sml_fail_unless(start_commands_received == 3, NULL); sml_fail_unless(finals_received == 1, NULL); sml_fail_unless(end_received == 0, NULL); smlSessionUnref(session); cleanup_testbed(); } END_TEST START_TEST (session_recv_large_obj2) { init_testbed(); SmlError *error = NULL; SmlLocation *loc = smlLocationNew("/test", NULL, &error); sml_fail_unless(loc != NULL, NULL); sml_fail_unless(error == NULL, NULL); const char *input = "SyncML/1.11.111/vcards/vcards1/vcards/vcards12text/x-vcard20uid"; SmlParser *parser = smlParserNew(SML_MIMETYPE_XML, 0, &error); sml_fail_unless(parser != NULL, NULL); sml_fail_unless(smlParserStart(parser, input, strlen(input), &error), NULL); SmlHeader *header = NULL; SmlCred *cred = NULL; sml_fail_unless(smlParserGetHeader(parser, &header, &cred, &error), NULL); sml_fail_unless(header != NULL, NULL); sml_fail_unless(cred == NULL, NULL); SmlSession *session = smlSessionNew(SML_SESSION_TYPE_SERVER, SML_MIMETYPE_XML, SML_VERSION_11, SML_PROTOCOL_SYNCML, loc, loc, "1", 0, &error); smlSessionSetLocalMaxMsgSize(session, defaultMaxMsgSize); smlSessionSetLocalMaxObjSize(session, defaultMaxObjSize); smlSessionSetEventCallback(session, _event_callback, GINT_TO_POINTER(4)); smlSessionSetDataCallback(session, _data_send_callback, &to_session2); sml_fail_unless(smlSessionReceiveHeader(session, header, &error), NULL); SmlStatus *reply = smlStatusNew(SML_NO_ERROR, 0, 1, session->source, session->target, SML_COMMAND_TYPE_HEADER, &error); sml_fail_unless(smlSessionSendReply(session, reply, &error), NULL); smlStatusUnref(reply); session->established = TRUE; sml_fail_unless(smlSessionReceiveBody(session, parser, &error), NULL); smlParserFree(parser); smlHeaderFree(header); sml_fail_unless(start_commands_received == 1, NULL); sml_fail_unless(finals_received == 0, NULL); sml_fail_unless(end_received == 0, NULL); sml_fail_unless(to_session2 != NULL, NULL); smlTransportDataDeref(to_session2); to_session2 = NULL; const char *input2 = "SyncML/1.11.121/vcards/vcards1/vcards/vcards2text/x-vcarduid"; parser = smlParserNew(SML_MIMETYPE_XML, 0, &error); sml_fail_unless(parser != NULL, NULL); sml_fail_unless(smlParserStart(parser, input2, strlen(input2), &error), NULL); sml_fail_unless(smlParserGetHeader(parser, &header, &cred, &error), NULL); sml_fail_unless(header != NULL, NULL); sml_fail_unless(cred == NULL, NULL); sml_fail_unless(smlSessionReceiveHeader(session, header, &error), NULL); reply = smlStatusNew(SML_NO_ERROR, 0, 2, session->source, session->target, SML_COMMAND_TYPE_HEADER, &error); sml_fail_unless(smlSessionSendReply(session, reply, &error), NULL); smlStatusUnref(reply); session->established = TRUE; sml_fail_unless(smlSessionReceiveBody(session, parser, &error), NULL); smlParserFree(parser); smlHeaderFree(header); sml_fail_unless(start_commands_received == 2, NULL); sml_fail_unless(finals_received == 0, NULL); sml_fail_unless(end_received == 0, NULL); sml_fail_unless(to_session2 != NULL, NULL); smlTransportDataDeref(to_session2); to_session2 = NULL; input2 = "SyncML/1.11.131/vcards/vcards1/vcards/vcards2text/x-vcarduid"; parser = smlParserNew(SML_MIMETYPE_XML, 0, &error); sml_fail_unless(parser != NULL, NULL); sml_fail_unless(smlParserStart(parser, input2, strlen(input2), &error), NULL); sml_fail_unless(smlParserGetHeader(parser, &header, &cred, &error), NULL); sml_fail_unless(header != NULL, NULL); sml_fail_unless(cred == NULL, NULL); sml_fail_unless(smlSessionReceiveHeader(session, header, &error), NULL); reply = smlStatusNew(SML_NO_ERROR, 0, 3, session->source, session->target, SML_COMMAND_TYPE_HEADER, &error); sml_fail_unless(smlSessionSendReply(session, reply, &error), NULL); smlStatusUnref(reply); session->established = TRUE; sml_fail_unless(smlSessionReceiveBody(session, parser, &error), NULL); smlParserFree(parser); smlHeaderFree(header); sml_fail_unless(start_commands_received == 3, NULL); sml_fail_unless(finals_received == 0, NULL); sml_fail_unless(end_received == 0, NULL); sml_fail_unless(to_session2 != NULL, NULL); smlTransportDataDeref(to_session2); to_session2 = NULL; input2 = "SyncML/1.11.141/vcards/vcards1/vcards/vcards2text/x-vcarduid"; parser = smlParserNew(SML_MIMETYPE_XML, 0, &error); sml_fail_unless(parser != NULL, NULL); sml_fail_unless(smlParserStart(parser, input2, strlen(input2), &error), NULL); sml_fail_unless(smlParserGetHeader(parser, &header, &cred, &error), NULL); sml_fail_unless(header != NULL, NULL); sml_fail_unless(cred == NULL, NULL); sml_fail_unless(smlSessionReceiveHeader(session, header, &error), NULL); reply = smlStatusNew(SML_NO_ERROR, 0, 4, session->source, session->target, SML_COMMAND_TYPE_HEADER, &error); sml_fail_unless(smlSessionSendReply(session, reply, &error), NULL); smlStatusUnref(reply); session->established = TRUE; sml_fail_unless(smlSessionReceiveBody(session, parser, &error), NULL); SmlCommand *cmd = smlCommandNewAlert(SML_ALERT_TWO_WAY, loc, loc, "last", "next", NULL, &error); sml_fail_unless(cmd != NULL, NULL); sml_fail_unless(error == NULL, NULL); smlLocationUnref(loc); sml_fail_unless(smlSessionSendCommand(session, cmd, NULL, _status_reply, GINT_TO_POINTER(1), &error), NULL); sml_fail_unless(error == NULL, NULL); smlCommandUnref(cmd); smlSessionDispatch(session); smlSessionDispatch(session); sml_fail_unless(smlSessionFlush(session, TRUE, &error), NULL); smlSessionDispatch(session); smlParserFree(parser); smlHeaderFree(header); sml_fail_unless(start_commands_received == 5, NULL); sml_fail_unless(finals_received == 1, NULL); sml_fail_unless(end_received == 0, NULL); sml_fail_unless(to_session2 != NULL, NULL); smlTransportDataDeref(to_session2); to_session2 = NULL; /* libsyncml does not reset the CmdID during a session. * So the CmdID must be the total number of all send commands. */ input2 = "SyncML/1.11.151/vcards/vcards1416Alert200/vcards/vcards2/vcards/vcards3text/x-vcarduid"; parser = smlParserNew(SML_MIMETYPE_XML, 0, &error); sml_fail_unless(parser != NULL, NULL); sml_fail_unless(smlParserStart(parser, input2, strlen(input2), &error), NULL); sml_fail_unless(smlParserGetHeader(parser, &header, &cred, &error), NULL); sml_fail_unless(header != NULL, NULL); sml_fail_unless(cred == NULL, NULL); sml_fail_unless(smlSessionReceiveHeader(session, header, &error), NULL); reply = smlStatusNew(SML_NO_ERROR, 0, 5, session->source, session->target, SML_COMMAND_TYPE_HEADER, &error); sml_fail_unless(smlSessionSendReply(session, reply, &error), NULL); smlStatusUnref(reply); session->established = TRUE; sml_fail_unless(smlSessionReceiveBody(session, parser, &error), NULL); smlParserFree(parser); smlHeaderFree(header); sml_fail_unless(start_commands_received == 7, NULL); sml_fail_unless(finals_received == 2, NULL); sml_fail_unless(end_received == 0, NULL); smlSessionUnref(session); cleanup_testbed(); } END_TEST START_TEST (session_recv_wrong_order) { init_testbed(); SmlError *error = NULL; SmlLocation *loc = smlLocationNew("/test", NULL, &error); sml_fail_unless(loc != NULL, NULL); sml_fail_unless(error == NULL, NULL); const char *input = "SyncML/1.11.111/vcards/vcards1/vcards/vcards12text/x-vcard8uid3text/x-vcarduid"; SmlParser *parser = smlParserNew(SML_MIMETYPE_XML, 0, &error); sml_fail_unless(parser != NULL, NULL); sml_fail_unless(smlParserStart(parser, input, strlen(input), &error), NULL); SmlHeader *header = NULL; SmlCred *cred = NULL; sml_fail_unless(smlParserGetHeader(parser, &header, &cred, &error), NULL); sml_fail_unless(header != NULL, NULL); sml_fail_unless(cred == NULL, NULL); SmlSession *session = smlSessionNew(SML_SESSION_TYPE_SERVER, SML_MIMETYPE_XML, SML_VERSION_11, SML_PROTOCOL_SYNCML, loc, loc, "1", 0, &error); smlSessionSetLocalMaxMsgSize(session, defaultMaxMsgSize); smlSessionSetLocalMaxObjSize(session, defaultMaxObjSize); smlLocationUnref(loc); smlSessionSetEventCallback(session, _event_callback, GINT_TO_POINTER(2)); smlSessionSetDataCallback(session, _data_send_callback, &to_session2); sml_fail_unless(smlSessionReceiveHeader(session, header, &error), NULL); session->established = TRUE; sml_fail_unless(!smlSessionReceiveBody(session, parser, &error), NULL); sml_fail_unless(error != NULL, NULL); smlErrorDeref(&error); smlParserFree(parser); smlHeaderFree(header); sml_fail_unless(start_commands_received == 1, "%d != 1", start_commands_received); sml_fail_unless(finals_received == 0, NULL); sml_fail_unless(end_received == 0, NULL); smlSessionUnref(session); cleanup_testbed(); } END_TEST START_TEST (session_large_obj_10) { init_testbed(); SmlError *error = NULL; SmlLocation *loc = smlLocationNew("/test", NULL, &error); sml_fail_unless(loc != NULL, NULL); sml_fail_unless(error == NULL, NULL); const char *input = "SyncML/1.01.011/vcards/vcards1/vcards/vcards12text/x-vcard8uid"; SmlParser *parser = smlParserNew(SML_MIMETYPE_XML, 0, &error); sml_fail_unless(parser != NULL, NULL); sml_fail_unless(smlParserStart(parser, input, strlen(input), &error), NULL); SmlHeader *header = NULL; SmlCred *cred = NULL; sml_fail_unless(smlParserGetHeader(parser, &header, &cred, &error), NULL); sml_fail_unless(header != NULL, NULL); sml_fail_unless(cred == NULL, NULL); SmlSession *session = smlSessionNew(SML_SESSION_TYPE_SERVER, SML_MIMETYPE_XML, SML_VERSION_10, SML_PROTOCOL_SYNCML, loc, loc, "1", 0, &error); smlSessionSetLocalMaxMsgSize(session, defaultMaxMsgSize); smlSessionSetLocalMaxObjSize(session, defaultMaxObjSize); smlSessionSetEventCallback(session, _event_callback, GINT_TO_POINTER(2)); smlSessionSetDataCallback(session, _data_send_callback, &to_session2); sml_fail_unless(smlSessionReceiveHeader(session, header, &error), NULL); SmlStatus *reply = smlStatusNew(SML_NO_ERROR, 0, 1, session->source, session->target, SML_COMMAND_TYPE_HEADER, &error); sml_fail_unless(smlSessionSendReply(session, reply, &error), NULL); smlStatusUnref(reply); session->established = TRUE; sml_fail_unless(!smlSessionReceiveBody(session, parser, &error), NULL); sml_fail_unless(error != NULL, NULL); smlErrorDeref(&error); smlParserFree(parser); smlHeaderFree(header); sml_fail_unless(start_commands_received == 1, NULL); sml_fail_unless(finals_received == 0, NULL); sml_fail_unless(end_received == 0, NULL); smlSessionUnref(session); current_cmd_id = 1; input = "SyncML/1.11.111/vcards/vcards1/vcards/vcards12text/x-vcard8uid"; parser = smlParserNew(SML_MIMETYPE_XML, 0, &error); sml_fail_unless(parser != NULL, NULL); sml_fail_unless(smlParserStart(parser, input, strlen(input), &error), NULL); sml_fail_unless(smlParserGetHeader(parser, &header, &cred, &error), NULL); sml_fail_unless(header != NULL, NULL); sml_fail_unless(cred == NULL, NULL); session = smlSessionNew(SML_SESSION_TYPE_SERVER, SML_MIMETYPE_XML, SML_VERSION_11, SML_PROTOCOL_SYNCML, loc, loc, "1", 0, &error); smlSessionSetLocalMaxMsgSize(session, defaultMaxMsgSize); smlSessionSetLocalMaxObjSize(session, defaultMaxObjSize); smlLocationUnref(loc); smlSessionSetEventCallback(session, _event_callback, GINT_TO_POINTER(2)); smlSessionSetDataCallback(session, _data_send_callback, &to_session2); sml_fail_unless(smlSessionReceiveHeader(session, header, &error), NULL); reply = smlStatusNew(SML_NO_ERROR, 0, 1, session->source, session->target, SML_COMMAND_TYPE_HEADER, &error); sml_fail_unless(smlSessionSendReply(session, reply, &error), NULL); smlStatusUnref(reply); session->established = TRUE; sml_fail_unless(smlSessionReceiveBody(session, parser, &error), NULL); sml_fail_unless(error == NULL, NULL); smlParserFree(parser); smlHeaderFree(header); sml_fail_unless(start_commands_received == 2, NULL); sml_fail_unless(finals_received == 0, NULL); sml_fail_unless(end_received == 0, NULL); sml_fail_unless(to_session2 != NULL, NULL); smlTransportDataDeref(to_session2); to_session2 = NULL; smlSessionUnref(session); cleanup_testbed(); } END_TEST START_TEST (session_large_obj_open) { init_testbed(); SmlError *error = NULL; SmlLocation *loc = smlLocationNew("/test", NULL, &error); sml_fail_unless(loc != NULL, NULL); sml_fail_unless(error == NULL, NULL); const char *input = "SyncML/1.11.111/vcards/vcards1/vcards/vcards12text/x-vcard8uid"; SmlParser *parser = smlParserNew(SML_MIMETYPE_XML, 0, &error); sml_fail_unless(parser != NULL, NULL); sml_fail_unless(smlParserStart(parser, input, strlen(input), &error), NULL); SmlHeader *header = NULL; SmlCred *cred = NULL; sml_fail_unless(smlParserGetHeader(parser, &header, &cred, &error), NULL); sml_fail_unless(header != NULL, NULL); sml_fail_unless(cred == NULL, NULL); SmlSession *session = smlSessionNew(SML_SESSION_TYPE_SERVER, SML_MIMETYPE_XML, SML_VERSION_10, SML_PROTOCOL_SYNCML, loc, loc, "1", 0, &error); smlSessionSetLocalMaxMsgSize(session, defaultMaxMsgSize); smlSessionSetLocalMaxObjSize(session, defaultMaxObjSize); smlSessionSetEventCallback(session, _event_callback, GINT_TO_POINTER(2)); smlSessionSetDataCallback(session, _data_send_callback, &to_session2); sml_fail_unless(smlSessionReceiveHeader(session, header, &error), NULL); SmlStatus *reply = smlStatusNew(SML_NO_ERROR, 0, 1, session->source, session->target, SML_COMMAND_TYPE_HEADER, &error); sml_fail_unless(smlSessionSendReply(session, reply, &error), NULL); smlStatusUnref(reply); session->established = TRUE; sml_fail_unless(!smlSessionReceiveBody(session, parser, &error), NULL); sml_fail_unless(error != NULL, NULL); smlErrorDeref(&error); smlParserFree(parser); smlHeaderFree(header); /* Even if MoreData and Final is impossible in the same message * then this is no reason why the received final should not be * signaled. If the syntax of the message is wrong then only * the syntax handler (ReceiveBody) should fail. Any other * stuff is undefinite. */ sml_fail_unless(start_commands_received == 1, NULL); sml_fail_unless(finals_received == 1, NULL); sml_fail_unless(end_received == 0, NULL); smlLocationUnref(loc); smlSessionUnref(session); cleanup_testbed(); } END_TEST START_TEST (session_large_obj_no_size) { init_testbed(); SmlError *error = NULL; SmlLocation *loc = smlLocationNew("/test", NULL, &error); sml_fail_unless(loc != NULL, NULL); sml_fail_unless(error == NULL, NULL); const char *input = "SyncML/1.11.111/vcards/vcards1/vcards/vcards12text/x-vcarduid"; SmlParser *parser = smlParserNew(SML_MIMETYPE_XML, 0, &error); sml_fail_unless(parser != NULL, NULL); sml_fail_unless(smlParserStart(parser, input, strlen(input), &error), NULL); SmlHeader *header = NULL; SmlCred *cred = NULL; sml_fail_unless(smlParserGetHeader(parser, &header, &cred, &error), NULL); sml_fail_unless(header != NULL, NULL); sml_fail_unless(cred == NULL, NULL); SmlSession *session = smlSessionNew(SML_SESSION_TYPE_SERVER, SML_MIMETYPE_XML, SML_VERSION_11, SML_PROTOCOL_SYNCML, loc, loc, "1", 0, &error); smlSessionSetLocalMaxMsgSize(session, defaultMaxMsgSize); smlSessionSetLocalMaxObjSize(session, defaultMaxObjSize); smlSessionSetEventCallback(session, _event_callback, GINT_TO_POINTER(2)); smlSessionSetDataCallback(session, _data_send_callback, &to_session2); sml_fail_unless(smlSessionReceiveHeader(session, header, &error), NULL); SmlStatus *reply = smlStatusNew(SML_NO_ERROR, 0, 1, session->source, session->target, SML_COMMAND_TYPE_HEADER, &error); sml_fail_unless(smlSessionSendReply(session, reply, &error), NULL); smlStatusUnref(reply); session->established = TRUE; sml_fail_unless(!smlSessionReceiveBody(session, parser, &error), NULL); sml_fail_unless(error != NULL, NULL); smlErrorDeref(&error); smlParserFree(parser); smlHeaderFree(header); sml_fail_unless(start_commands_received == 1, NULL); sml_fail_unless(finals_received == 0, NULL); sml_fail_unless(end_received == 0, NULL); smlLocationUnref(loc); smlSessionUnref(session); cleanup_testbed(); } END_TEST START_TEST (session_large_obj_several_size) { init_testbed(); SmlError *error = NULL; SmlLocation *loc = smlLocationNew("/test", NULL, &error); sml_fail_unless(loc != NULL, NULL); sml_fail_unless(error == NULL, NULL); const char *input = "SyncML/1.11.111/vcards/vcards1/vcards/vcards12text/x-vcard8uid"; SmlParser *parser = smlParserNew(SML_MIMETYPE_XML, 0, &error); sml_fail_unless(parser != NULL, NULL); sml_fail_unless(smlParserStart(parser, input, strlen(input), &error), NULL); SmlHeader *header = NULL; SmlCred *cred = NULL; sml_fail_unless(smlParserGetHeader(parser, &header, &cred, &error), NULL); sml_fail_unless(header != NULL, NULL); sml_fail_unless(cred == NULL, NULL); SmlSession *session = smlSessionNew(SML_SESSION_TYPE_SERVER, SML_MIMETYPE_XML, SML_VERSION_11, SML_PROTOCOL_SYNCML, loc, loc, "1", 0, &error); smlSessionSetLocalMaxMsgSize(session, defaultMaxMsgSize); smlSessionSetLocalMaxObjSize(session, defaultMaxObjSize); smlLocationUnref(loc); smlSessionSetEventCallback(session, _event_callback, GINT_TO_POINTER(3)); smlSessionSetDataCallback(session, _data_send_callback, &to_session2); sml_fail_unless(smlSessionReceiveHeader(session, header, &error), NULL); SmlStatus *reply = smlStatusNew(SML_NO_ERROR, 0, 1, session->source, session->target, SML_COMMAND_TYPE_HEADER, &error); sml_fail_unless(smlSessionSendReply(session, reply, &error), NULL); smlStatusUnref(reply); session->established = TRUE; sml_fail_unless(smlSessionReceiveBody(session, parser, &error), NULL); smlParserFree(parser); smlHeaderFree(header); sml_fail_unless(start_commands_received == 1, NULL); sml_fail_unless(finals_received == 0, NULL); sml_fail_unless(end_received == 0, NULL); sml_fail_unless(to_session2 != NULL, NULL); smlTransportDataDeref(to_session2); to_session2 = NULL; const char *input2 = "SyncML/1.11.121/vcards/vcards1/vcards/vcards2text/x-vcard8uid"; parser = smlParserNew(SML_MIMETYPE_XML, 0, &error); sml_fail_unless(parser != NULL, NULL); sml_fail_unless(smlParserStart(parser, input2, strlen(input2), &error), NULL); sml_fail_unless(smlParserGetHeader(parser, &header, &cred, &error), NULL); sml_fail_unless(header != NULL, NULL); sml_fail_unless(cred == NULL, NULL); sml_fail_unless(smlSessionReceiveHeader(session, header, &error), NULL); reply = smlStatusNew(SML_NO_ERROR, 0, 1, session->source, session->target, SML_COMMAND_TYPE_HEADER, &error); sml_fail_unless(smlSessionSendReply(session, reply, &error), NULL); smlStatusUnref(reply); session->established = TRUE; sml_fail_unless(!smlSessionReceiveBody(session, parser, &error), NULL); sml_fail_unless(error != NULL, NULL); smlErrorDeref(&error); smlParserFree(parser); smlHeaderFree(header); sml_fail_unless(start_commands_received == 2, NULL); sml_fail_unless(finals_received == 0, NULL); sml_fail_unless(end_received == 0, NULL); smlSessionUnref(session); cleanup_testbed(); } END_TEST START_TEST (session_recv_large_wrong_size) { init_testbed(); SmlError *error = NULL; SmlLocation *loc = smlLocationNew("/test", NULL, &error); sml_fail_unless(loc != NULL, NULL); sml_fail_unless(error == NULL, NULL); const char *input = "SyncML/1.11.111/vcards/vcards1/vcards/vcards12text/x-vcard9uid"; SmlParser *parser = smlParserNew(SML_MIMETYPE_XML, 0, &error); sml_fail_unless(parser != NULL, NULL); sml_fail_unless(smlParserStart(parser, input, strlen(input), &error), NULL); SmlHeader *header = NULL; SmlCred *cred = NULL; sml_fail_unless(smlParserGetHeader(parser, &header, &cred, &error), NULL); sml_fail_unless(header != NULL, NULL); sml_fail_unless(cred == NULL, NULL); SmlSession *session = smlSessionNew(SML_SESSION_TYPE_SERVER, SML_MIMETYPE_XML, SML_VERSION_11, SML_PROTOCOL_SYNCML, loc, loc, "1", 0, &error); smlSessionSetLocalMaxMsgSize(session, defaultMaxMsgSize); smlSessionSetLocalMaxObjSize(session, defaultMaxObjSize); smlLocationUnref(loc); smlSessionSetEventCallback(session, _event_callback, GINT_TO_POINTER(3)); smlSessionSetDataCallback(session, _data_send_callback, &to_session2); sml_fail_unless(smlSessionReceiveHeader(session, header, &error), NULL); SmlStatus *reply = smlStatusNew(SML_NO_ERROR, 0, 1, session->source, session->target, SML_COMMAND_TYPE_HEADER, &error); sml_fail_unless(smlSessionSendReply(session, reply, &error), NULL); smlStatusUnref(reply); session->established = TRUE; sml_fail_unless(smlSessionReceiveBody(session, parser, &error), NULL); smlParserFree(parser); smlHeaderFree(header); sml_fail_unless(start_commands_received == 1, NULL); sml_fail_unless(finals_received == 0, NULL); sml_fail_unless(end_received == 0, NULL); sml_fail_unless(to_session2 != NULL, NULL); smlTransportDataDeref(to_session2); to_session2 = NULL; const char *input2 = "SyncML/1.11.121/vcards/vcards1/vcards/vcards2text/x-vcarduid"; parser = smlParserNew(SML_MIMETYPE_XML, 0, &error); sml_fail_unless(parser != NULL, NULL); sml_fail_unless(smlParserStart(parser, input2, strlen(input2), &error), NULL); sml_fail_unless(smlParserGetHeader(parser, &header, &cred, &error), NULL); sml_fail_unless(header != NULL, NULL); sml_fail_unless(cred == NULL, NULL); sml_fail_unless(smlSessionReceiveHeader(session, header, &error), NULL); reply = smlStatusNew(SML_NO_ERROR, 0, 1, session->source, session->target, SML_COMMAND_TYPE_HEADER, &error); sml_fail_unless(smlSessionSendReply(session, reply, &error), NULL); smlStatusUnref(reply); session->established = TRUE; sml_fail_unless(!smlSessionReceiveBody(session, parser, &error), NULL); sml_fail_unless(error != NULL, NULL); smlErrorDeref(&error); smlParserFree(parser); smlHeaderFree(header); sml_fail_unless(start_commands_received == 2, NULL); sml_fail_unless(finals_received == 0, NULL); sml_fail_unless(end_received == 0, NULL); smlSessionUnref(session); cleanup_testbed(); } END_TEST START_TEST (session_recv_large_wrong_size2) { init_testbed(); SmlError *error = NULL; SmlLocation *loc = smlLocationNew("/test", NULL, &error); sml_fail_unless(loc != NULL, NULL); sml_fail_unless(error == NULL, NULL); const char *input = "SyncML/1.11.111/vcards/vcards1/vcards/vcards12text/x-vcard7uid"; SmlParser *parser = smlParserNew(SML_MIMETYPE_XML, 0, &error); sml_fail_unless(parser != NULL, NULL); sml_fail_unless(smlParserStart(parser, input, strlen(input), &error), NULL); SmlHeader *header = NULL; SmlCred *cred = NULL; sml_fail_unless(smlParserGetHeader(parser, &header, &cred, &error), NULL); sml_fail_unless(header != NULL, NULL); sml_fail_unless(cred == NULL, NULL); SmlSession *session = smlSessionNew(SML_SESSION_TYPE_SERVER, SML_MIMETYPE_XML, SML_VERSION_11, SML_PROTOCOL_SYNCML, loc, loc, "1", 0, &error); smlSessionSetLocalMaxMsgSize(session, defaultMaxMsgSize); smlSessionSetLocalMaxObjSize(session, defaultMaxObjSize); smlLocationUnref(loc); smlSessionSetEventCallback(session, _event_callback, GINT_TO_POINTER(3)); smlSessionSetDataCallback(session, _data_send_callback, &to_session2); sml_fail_unless(smlSessionReceiveHeader(session, header, &error), NULL); SmlStatus *reply = smlStatusNew(SML_NO_ERROR, 0, 1, session->source, session->target, SML_COMMAND_TYPE_HEADER, &error); sml_fail_unless(smlSessionSendReply(session, reply, &error), NULL); smlStatusUnref(reply); session->established = TRUE; sml_fail_unless(smlSessionReceiveBody(session, parser, &error), NULL); smlParserFree(parser); smlHeaderFree(header); sml_fail_unless(start_commands_received == 1, NULL); sml_fail_unless(finals_received == 0, NULL); sml_fail_unless(end_received == 0, NULL); sml_fail_unless(to_session2 != NULL, NULL); smlTransportDataDeref(to_session2); to_session2 = NULL; const char *input2 = "SyncML/1.11.121/vcards/vcards1/vcards/vcards2text/x-vcarduid"; parser = smlParserNew(SML_MIMETYPE_XML, 0, &error); sml_fail_unless(parser != NULL, NULL); sml_fail_unless(smlParserStart(parser, input2, strlen(input2), &error), NULL); sml_fail_unless(smlParserGetHeader(parser, &header, &cred, &error), NULL); sml_fail_unless(header != NULL, NULL); sml_fail_unless(cred == NULL, NULL); sml_fail_unless(smlSessionReceiveHeader(session, header, &error), NULL); reply = smlStatusNew(SML_NO_ERROR, 0, 1, session->source, session->target, SML_COMMAND_TYPE_HEADER, &error); sml_fail_unless(smlSessionSendReply(session, reply, &error), NULL); smlStatusUnref(reply); session->established = TRUE; sml_fail_unless(!smlSessionReceiveBody(session, parser, &error), NULL); sml_fail_unless(error != NULL, NULL); smlErrorDeref(&error); smlParserFree(parser); smlHeaderFree(header); sml_fail_unless(start_commands_received == 2, NULL); sml_fail_unless(finals_received == 0, NULL); sml_fail_unless(end_received == 0, NULL); smlSessionUnref(session); cleanup_testbed(); } END_TEST START_TEST (session_send_large_obj) { init_testbed(); int limit = 1000; int objlength = 600; SmlError *error = NULL; SmlLocation *loc = smlLocationNew("/test", NULL, &error); sml_fail_unless(loc != NULL, NULL); sml_fail_unless(error == NULL, NULL); SmlSession *session = smlSessionNew(SML_SESSION_TYPE_CLIENT, SML_MIMETYPE_XML, SML_VERSION_12, SML_PROTOCOL_SYNCML, loc, loc, "1", 0, &error); SmlSessionThread *thread1 = smlSessionRunAsync(session, &to_session); SmlSession *session2 = smlSessionNew(SML_SESSION_TYPE_SERVER, SML_MIMETYPE_XML, SML_VERSION_12, SML_PROTOCOL_SYNCML, loc, loc, "1", 0, &error); SmlSessionThread *thread2 = smlSessionRunAsync(session2, &to_session2); smlSessionSetEventCallback(session2, _event_callback, GINT_TO_POINTER(5)); smlSessionSetDataCallback(session2, _data_send_callback, &to_session); smlSessionSetEventCallback(session, _event_callback, GINT_TO_POINTER(5)); smlSessionSetDataCallback(session, _data_send_callback, &to_session2); // smlSessionSetLocalMaxMsgSize(session, limit); smlSessionSetRemoteMaxMsgSize(session, limit); smlSessionSetRemoteMaxObjSize(session, defaultMaxObjSize); smlSessionSetLocalMaxMsgSize(session2, defaultMaxMsgSize); smlSessionSetLocalMaxObjSize(session2, defaultMaxObjSize); SmlCommand *cmd1 = smlCommandNewSync(loc, loc, 0, &error); sml_fail_unless(cmd1 != NULL, NULL); sml_fail_unless(error == NULL, NULL); smlLocationUnref(loc); sml_fail_unless(smlSessionStartCommand(session, cmd1, NULL, _status_reply, GINT_TO_POINTER(1), &error), NULL); sml_fail_unless(error == NULL, NULL); item_data = smlRandStr(objlength, TRUE); item_size = objlength; SmlCommand *cmd2 = smlCommandNewChange(SML_CHANGE_ADD, "uid", item_data, item_size, SML_ELEMENT_TEXT_VCARD, &error); sml_fail_unless(smlSessionSendCommand(session, cmd2, cmd1, _status_reply, GINT_TO_POINTER(1), &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlSessionEndCommand(session, cmd1, &error), NULL); sml_fail_unless(error == NULL, NULL); smlCommandUnref(cmd1); smlCommandUnref(cmd2); sml_fail_unless(smlSessionEndCommand(session, NULL, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlSessionFlush(session, TRUE, &error), NULL); sml_fail_unless(error == NULL, NULL); while (finals_received < 1) { usleep(100); } /* The data is additionally set to test the size of the * resulting message. So the variable name data_received * is not fully correct. */ sml_fail_unless(data_received >= 3, NULL); sml_fail_unless(numreplies == 1, NULL); /* 3x sync (in each of the three messages) and 1x add (large obj) */ sml_fail_unless(start_commands_received == 4, NULL); sml_fail_unless(finals_received == 1, NULL); sml_fail_unless(end_received == 0, NULL); g_free(item_data); smlSessionStop(thread1); smlSessionStop(thread2); smlSessionUnref(session2); smlSessionUnref(session); cleanup_testbed(); } END_TEST START_TEST (session_send_large_obj2) { init_testbed(); int limit = 1000; int objlength = 4000; SmlError *error = NULL; SmlLocation *loc = smlLocationNew("/test", NULL, &error); sml_fail_unless(loc != NULL, NULL); sml_fail_unless(error == NULL, NULL); SmlSession *session = smlSessionNew(SML_SESSION_TYPE_CLIENT, SML_MIMETYPE_XML, SML_VERSION_12, SML_PROTOCOL_SYNCML, loc, loc, "1", 0, &error); SmlSessionThread *thread1 = smlSessionRunAsync(session, &to_session); SmlSession *session2 = smlSessionNew(SML_SESSION_TYPE_SERVER, SML_MIMETYPE_XML, SML_VERSION_12, SML_PROTOCOL_SYNCML, loc, loc, "1", 0, &error); SmlSessionThread *thread2 = smlSessionRunAsync(session2, &to_session2); smlSessionSetEventCallback(session2, _event_callback, GINT_TO_POINTER(5)); smlSessionSetDataCallback(session2, _data_send_callback, &to_session); smlSessionSetEventCallback(session, _event_callback, GINT_TO_POINTER(5)); smlSessionSetDataCallback(session, _data_send_callback, &to_session2); smlSessionSetLocalMaxMsgSize(session, limit); smlSessionSetRemoteMaxMsgSize(session, limit); smlSessionSetLocalMaxMsgSize(session2, defaultMaxMsgSize); smlSessionSetLocalMaxObjSize(session2, defaultMaxObjSize); SmlCommand *cmd1 = smlCommandNewSync(loc, loc, 0, &error); sml_fail_unless(cmd1 != NULL, NULL); sml_fail_unless(error == NULL, NULL); smlLocationUnref(loc); sml_fail_unless(smlSessionStartCommand(session, cmd1, NULL, _status_reply, GINT_TO_POINTER(1), &error), NULL); sml_fail_unless(error == NULL, NULL); item_data = smlRandStr(objlength, TRUE); item_size = objlength; SmlCommand *cmd2 = smlCommandNewChange(SML_CHANGE_ADD, "uid", item_data, item_size, SML_ELEMENT_TEXT_VCARD, &error); sml_fail_unless(smlSessionSendCommand(session, cmd2, cmd1, _status_reply, GINT_TO_POINTER(1), &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlSessionEndCommand(session, cmd1, &error), NULL); sml_fail_unless(error == NULL, NULL); smlCommandUnref(cmd1); smlCommandUnref(cmd2); sml_fail_unless(smlSessionEndCommand(session, NULL, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlSessionFlush(session, TRUE, &error), NULL); sml_fail_unless(error == NULL, NULL); while (finals_received != 1) { usleep(100); } sml_fail_unless(finals_received == 1, NULL); sml_fail_unless(end_received == 0, NULL); g_free(item_data); smlSessionStop(thread1); smlSessionStop(thread2); smlSessionUnref(session2); smlSessionUnref(session); cleanup_testbed(); } END_TEST START_TEST (session_send_multi_large_obj) { init_testbed(); int limit = 1000; int objlength = 1500; int num_obj = 10; SmlError *error = NULL; SmlLocation *loc = smlLocationNew("/test", NULL, &error); sml_fail_unless(loc != NULL, NULL); sml_fail_unless(error == NULL, NULL); SmlSession *session = smlSessionNew(SML_SESSION_TYPE_CLIENT, SML_MIMETYPE_XML, SML_VERSION_12, SML_PROTOCOL_SYNCML, loc, loc, "1", 0, &error); SmlSessionThread *thread1 = smlSessionRunAsync(session, &to_session); SmlSession *session2 = smlSessionNew(SML_SESSION_TYPE_SERVER, SML_MIMETYPE_XML, SML_VERSION_12, SML_PROTOCOL_SYNCML, loc, loc, "1", 0, &error); SmlSessionThread *thread2 = smlSessionRunAsync(session2, &to_session2); smlSessionSetEventCallback(session2, _event_callback, GINT_TO_POINTER(5)); smlSessionSetDataCallback(session2, _data_send_callback, &to_session); smlSessionSetEventCallback(session, _event_callback, GINT_TO_POINTER(5)); smlSessionSetDataCallback(session, _data_send_callback, &to_session2); smlSessionSetLocalMaxMsgSize(session, limit); smlSessionSetRemoteMaxMsgSize(session, limit); smlSessionSetLocalMaxMsgSize(session2, defaultMaxMsgSize); smlSessionSetLocalMaxObjSize(session2, defaultMaxObjSize); SmlCommand *cmd1 = smlCommandNewSync(loc, loc, 0, &error); sml_fail_unless(cmd1 != NULL, NULL); sml_fail_unless(error == NULL, NULL); smlLocationUnref(loc); sml_fail_unless(smlSessionStartCommand(session, cmd1, NULL, _status_reply, GINT_TO_POINTER(1), &error), NULL); sml_fail_unless(error == NULL, NULL); item_data = smlRandStr(objlength, TRUE); item_size = objlength; SmlCommand *cmd2 = NULL; int i = 0; for (i = 0; i < num_obj; i++) { cmd2 = smlCommandNewChange(SML_CHANGE_ADD, "uid", item_data, item_size, SML_ELEMENT_TEXT_VCARD, &error); sml_fail_unless(smlSessionSendCommand(session, cmd2, cmd1, _status_reply, GINT_TO_POINTER(1), &error), NULL); sml_fail_unless(error == NULL, NULL); smlCommandUnref(cmd2); } smlCommandUnref(cmd1); sml_fail_unless(smlSessionEndCommand(session, NULL, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlSessionFlush(session, TRUE, &error), NULL); sml_fail_unless(error == NULL, NULL); while (finals_received < 1) { usleep(100); } sml_fail_unless(finals_received == 1, NULL); sml_fail_unless(end_received == 0, NULL); g_free(item_data); smlSessionStop(thread1); smlSessionStop(thread2); smlSessionUnref(session2); smlSessionUnref(session); cleanup_testbed(); } END_TEST START_TEST (session_send_multi_large_obj_alter) { init_testbed(); int limit = 1000; int objlength = 1500; int num_obj = 5; SmlError *error = NULL; SmlLocation *loc = smlLocationNew("/test", NULL, &error); sml_fail_unless(loc != NULL, NULL); sml_fail_unless(error == NULL, NULL); SmlSession *session = smlSessionNew(SML_SESSION_TYPE_CLIENT, SML_MIMETYPE_XML, SML_VERSION_12, SML_PROTOCOL_SYNCML, loc, loc, "1", 0, &error); SmlSessionThread *thread1 = smlSessionRunAsync(session, &to_session); SmlSession *session2 = smlSessionNew(SML_SESSION_TYPE_SERVER, SML_MIMETYPE_XML, SML_VERSION_12, SML_PROTOCOL_SYNCML, loc, loc, "1", 0, &error); SmlSessionThread *thread2 = smlSessionRunAsync(session2, &to_session2); smlSessionSetEventCallback(session2, _event_callback, GINT_TO_POINTER(5)); smlSessionSetDataCallback(session2, _data_send_callback, &to_session); smlSessionSetEventCallback(session, _event_callback, GINT_TO_POINTER(5)); smlSessionSetDataCallback(session, _data_send_callback, &to_session2); smlSessionSetLocalMaxMsgSize(session, limit); smlSessionSetRemoteMaxMsgSize(session, limit); smlSessionSetLocalMaxMsgSize(session2, defaultMaxMsgSize); smlSessionSetLocalMaxObjSize(session2, defaultMaxObjSize); SmlCommand *cmd1 = smlCommandNewSync(loc, loc, 0, &error); sml_fail_unless(cmd1 != NULL, NULL); sml_fail_unless(error == NULL, NULL); smlLocationUnref(loc); sml_fail_unless(smlSessionStartCommand(session, cmd1, NULL, _status_reply, GINT_TO_POINTER(1), &error), NULL); sml_fail_unless(error == NULL, NULL); item_data = smlRandStr(objlength, TRUE); item_size = objlength; SmlCommand *cmd2 = NULL; int i = 0; for (i = 0; i < num_obj; i++) { cmd2 = smlCommandNewChange(SML_CHANGE_ADD, "uid", item_data, item_size, SML_ELEMENT_TEXT_VCARD, &error); sml_fail_unless(smlSessionSendCommand(session, cmd2, cmd1, _status_reply, GINT_TO_POINTER(1), &error), NULL); sml_fail_unless(error == NULL, NULL); smlCommandUnref(cmd2); cmd2 = smlCommandNewChange(SML_CHANGE_ADD, "uid", "data", 4, SML_ELEMENT_TEXT_VCARD, &error); sml_fail_unless(smlSessionSendCommand(session, cmd2, cmd1, _status_reply, GINT_TO_POINTER(1), &error), NULL); sml_fail_unless(error == NULL, NULL); smlCommandUnref(cmd2); } smlCommandUnref(cmd1); sml_fail_unless(smlSessionEndCommand(session, NULL, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlSessionFlush(session, TRUE, &error), NULL); sml_fail_unless(error == NULL, NULL); while (finals_received < 1) { usleep(100); } sml_fail_unless(num_changes = num_obj * 2, NULL); sml_fail_unless(finals_received == 1, NULL); sml_fail_unless(end_received == 0, NULL); g_free(item_data); smlSessionStop(thread1); smlSessionStop(thread2); smlSessionUnref(session2); smlSessionUnref(session); cleanup_testbed(); } END_TEST START_TEST (session_san) { init_testbed(); SmlError *error = NULL; SmlLocation *loc = smlLocationNew("/test", NULL, &error); sml_fail_unless(loc != NULL, NULL); sml_fail_unless(error == NULL, NULL); SmlSession *session = smlSessionNew(SML_SESSION_TYPE_CLIENT, SML_MIMETYPE_XML, SML_VERSION_12, SML_PROTOCOL_SYNCML, loc, loc, "1", 0, &error); SmlSessionThread *thread1 = smlSessionRunAsync(session, &to_session); SmlSession *session2 = smlSessionNew(SML_SESSION_TYPE_SERVER, SML_MIMETYPE_XML, SML_VERSION_12, SML_PROTOCOL_SYNCML, loc, loc, "1", 0, &error); SmlSessionThread *thread2 = smlSessionRunAsync(session2, &to_session2); smlSessionSetLocalMaxMsgSize(session2, defaultMaxMsgSize); smlSessionSetLocalMaxObjSize(session2, defaultMaxObjSize); smlSessionSetEventCallback(session2, _event_callback, GINT_TO_POINTER(1)); smlSessionSetDataCallback(session2, _data_send_callback, &to_session); smlSessionSetEventCallback(session, _event_callback, GINT_TO_POINTER(1)); smlSessionSetDataCallback(session, _data_send_callback, &to_session2); SmlNotification *san = smlNotificationNew(SML_SAN_VERSION_11, SML_SAN_UIMODE_USER, SML_SAN_INITIATOR_SERVER, 65535, "test", "/", SML_MIMETYPE_XML, &error); sml_fail_unless(san != NULL, "%s", smlErrorPrint(&error)); sml_fail_unless(error == NULL, "%s", smlErrorPrint(&error)); SmlManager *manager = _start_manager(); smlNotificationSetManager(san, manager); sml_fail_unless(smlNotificationNewAlert(san, SML_ALERT_TWO_WAY_BY_SERVER, SML_ELEMENT_TEXT_VCARD, "tttt", &error), NULL); sml_fail_unless(error == NULL, NULL); char *buffer = NULL; unsigned int size = 0; sml_fail_unless(smlNotificationAssemble(san, &buffer, &size, &error), NULL); sml_fail_unless(error == NULL, NULL); smlNotificationFree(san); to_session = smlTransportDataNew(buffer, size, SML_MIMETYPE_XML, TRUE, &error); sml_fail_unless(to_session != NULL, NULL); sml_fail_unless(error == NULL, NULL); while (finals_received != 1) { usleep(100); } sml_fail_unless(data_received == 0, NULL); sml_fail_unless(numreplies == 0, NULL); sml_fail_unless(start_commands_received == 1, NULL); sml_fail_unless(finals_received == 1, NULL); sml_fail_unless(end_received == 0, NULL); SmlCommand *cmd = smlCommandNewAlert(SML_ALERT_TWO_WAY, loc, loc, "last", "next", NULL, &error); sml_fail_unless(cmd != NULL, NULL); sml_fail_unless(error == NULL, NULL); smlLocationUnref(loc); sml_fail_unless(smlSessionSendCommand(session, cmd, NULL, _status_reply, GINT_TO_POINTER(1), &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlSessionFlush(session, TRUE, &error), NULL); sml_fail_unless(error == NULL, NULL); while (finals_received != 2) { usleep(100); } sml_fail_unless(data_received == 1, NULL); sml_fail_unless(numreplies == 0, NULL); sml_fail_unless(start_commands_received == 2, NULL); sml_fail_unless(finals_received == 2, NULL); sml_fail_unless(end_received == 0, NULL); sml_fail_unless(smlSessionSendCommand(session2, cmd, NULL, _status_reply, GINT_TO_POINTER(1), &error), NULL); sml_fail_unless(error == NULL, NULL); smlCommandUnref(cmd); sml_fail_unless(smlSessionFlush(session2, TRUE, &error), NULL); sml_fail_unless(error == NULL, NULL); while (finals_received != 3) { usleep(100); } sml_fail_unless(data_received == 2, NULL); sml_fail_unless(numreplies == 1, NULL); sml_fail_unless(start_commands_received == 3, NULL); sml_fail_unless(finals_received == 3, NULL); sml_fail_unless(end_received == 0, NULL); sml_fail_unless(smlSessionFlush(session, TRUE, &error), NULL); sml_fail_unless(error == NULL, NULL); while (finals_received != 5 || end_received != 2) { usleep(100); } sml_fail_unless(data_received == 4, NULL); sml_fail_unless(numreplies == 2, NULL); sml_fail_unless(start_commands_received == 3, NULL); sml_fail_unless(finals_received == 5, NULL); sml_fail_unless(end_received == 2, NULL); smlSessionStop(thread1); smlSessionStop(thread2); smlSessionUnref(session2); smlSessionUnref(session); _stop_manager(manager); cleanup_testbed(); } END_TEST @SML_TESTCASE_CODE@ libsyncml-0.5.4/tests/check_ds.c100644 1750 1750 235166 11211710410 16547 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2005 Armin Bauer * Copyright (C) 2008 Michael Bell * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include "tests/support.h" #include #include #include #include #include #include typedef struct SmlSessionThread { GMainContext *context; GSourceFuncs *functions; GSourceFuncs *data_functions; GSource *data_source; GSource *session_source; SmlThread *thread; SmlSession *session; SmlTransportData **data; } SmlSessionThread; typedef struct _server_corr { SmlDsSession *dsession; SmlDsServer *server; SmlSessionThread *thread; } _server_corr; gint data_received = 0; int init_alerts_received = 0; int alerts_received = 0; int syncs_received = 0; int sync_ends_received = 0; int changes_received = 0; int replies_received = 0; int adds_received = 0; int add_replies_received = 0; int deletes_received = 0; int delete_replies_received = 0; int modifies_received = 0; int modify_replies_received = 0; int session_ends = 0; SmlTransportData *to_session = NULL; SmlTransportData *to_session2 = NULL; unsigned int defaultMaxMsgSize = 10240; unsigned int defaultMaxObjSize = 1024000; //SmlDsSession *serversession = NULL; gboolean _session_prepare(GSource *source, gint *timeout_) { smlTrace(TRACE_INTERNAL, "%s(%p, %p)", __func__, source, timeout_); *timeout_ = 1; return FALSE; } gboolean _session_check(GSource *source) { SmlSession *session = *((SmlSession **)(source + 1)); return smlSessionCheck(session); } gboolean _session_dispatch(GSource *source, GSourceFunc callback, gpointer user_data) { smlTrace(TRACE_INTERNAL, "%s(%p, %p)", __func__, source, callback); SmlSession *session = user_data; while (smlSessionCheck(session)) smlSessionDispatch(session); return TRUE; } gboolean _data_prepare(GSource *source, gint *timeout_) { smlTrace(TRACE_INTERNAL, "%s(%p, %p)", __func__, source, timeout_); *timeout_ = 1; return FALSE; } gboolean _data_check(GSource *source) { SmlSessionThread *thread = *((SmlSessionThread **)(source + 1)); smlAssert(thread != NULL); smlAssert(thread->data != NULL); if (*(thread->data)) return TRUE; return FALSE; } gboolean _data_dispatch(GSource *source, GSourceFunc callback, gpointer user_data) { smlTrace(TRACE_INTERNAL, "%s(%p, %p)", __func__, source, callback); SmlSessionThread *check = user_data; SmlError *error = NULL; smlAssert(check != NULL); smlAssert(check->data != NULL); if (*(check->data)) { SmlTransportData *data = *(check->data); *(check->data) = NULL; smlTrace(TRACE_ENTRY, "%s(data: %p, real %p, size %i)", __func__, data, data->data, data->size); SmlParser *parser = smlParserNew(data->type, 0, &error); smlAssert(parser != NULL); smlAssert(smlParserStart(parser, data->data, data->size, &error)); SmlHeader *header = NULL; SmlCred *cred = NULL; smlAssert(smlParserGetHeader(parser, &header, &cred, &error)); smlAssert(header != NULL); smlAssert(smlSessionReceiveHeader(check->session, header, &error)); smlHeaderFree(header); SmlStatus *reply = smlStatusNew(SML_NO_ERROR, 0, check->session->lastReceivedMessageID, check->session->source, check->session->target, SML_COMMAND_TYPE_HEADER, &error); smlAssert(smlSessionSendReply(check->session, reply, &error)); smlAssert(error == NULL); check->session->established = TRUE; smlStatusUnref(reply); smlAssert(smlSessionReceiveBody(check->session, parser, &error)); smlParserFree(parser); smlTransportDataDeref(data); smlTrace(TRACE_EXIT, "%s", __func__); } return TRUE; } SmlSessionThread *smlSessionRunAsync(SmlSession *session, SmlTransportData **input) { smlTrace(TRACE_ENTRY, "%s(%p, %p)", __func__, session, input); SmlError *error = NULL; SmlSessionThread *thread = g_malloc0(sizeof(SmlSessionThread)); thread->context = g_main_context_new(); g_main_context_ref(thread->context); thread->functions = g_malloc0(sizeof(GSourceFuncs)); thread->functions->prepare = _session_prepare; thread->functions->check = _session_check; thread->functions->dispatch = _session_dispatch; thread->functions->finalize = NULL; thread->session_source = g_source_new(thread->functions, sizeof(GSource) + sizeof(SmlSession *)); SmlSession **sessionptr = (SmlSession **)(thread->session_source + 1); *sessionptr = session; g_source_set_callback(thread->session_source, NULL, session, NULL); g_source_attach(thread->session_source, thread->context); thread->data_functions = g_malloc0(sizeof(GSourceFuncs)); thread->data_functions->prepare = _data_prepare; thread->data_functions->check = _data_check; thread->data_functions->dispatch = _data_dispatch; thread->data_functions->finalize = NULL; thread->data = input; thread->session = session; thread->data_source = g_source_new(thread->data_functions, sizeof(GSource) + sizeof(SmlSession *)); SmlSessionThread **threadptr = (SmlSessionThread **)(thread->data_source + 1); *threadptr = thread; g_source_set_callback(thread->data_source, NULL, thread, NULL); g_source_attach(thread->data_source, thread->context); thread->thread = smlThreadNew(thread->context, &error); sml_fail_unless(thread->thread != NULL, NULL); smlThreadStart(thread->thread); smlTrace(TRACE_EXIT, "%s", __func__); return thread; } /** @brief Stops a asynchronously running transport * * @param tsp The transport * */ void smlSessionStop(SmlSessionThread *thread) { smlTrace(TRACE_ENTRY, "%s(%p)", __func__, thread); smlAssert(thread); smlThreadStop(thread->thread); g_source_destroy(thread->data_source); g_source_destroy(thread->session_source); g_source_unref(thread->data_source); g_source_unref(thread->session_source); smlThreadFree(thread->thread); g_free(thread->functions); g_free(thread->data_functions); g_main_context_unref(thread->context); g_main_context_unref(thread->context); g_free(thread); smlTrace(TRACE_EXIT, "%s", __func__); } static void _recv_init_alert(SmlDsSession *dsession, void *userdata) { smlTrace(TRACE_ENTRY, "%s(%p, %p)", __func__, dsession, userdata); _server_corr *corr = userdata; corr->dsession = dsession; g_atomic_int_add(&init_alerts_received, 1); smlDsSessionRef(dsession); smlTrace(TRACE_EXIT, "%s", __func__); } static SmlBool _recv_alert(SmlDsSession *dsession, SmlAlertType type, const char *last, const char *next, void *userdata) { smlTrace(TRACE_ENTRY, "%s(%p, %i, %s, %s, %p)", __func__, dsession, type, VA_STRING(last), VA_STRING(next), userdata); sml_fail_unless(last != NULL, NULL); sml_fail_unless(next != NULL, NULL); g_atomic_int_add(&alerts_received, 1); smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; } static void _recv_sync(SmlDsSession *dsession, unsigned int numChanges, void *userdata) { smlTrace(TRACE_ENTRY, "%s(%p, %d, %p)", __func__,dsession, numChanges, userdata); g_atomic_int_add(&syncs_received, 1); smlTrace(TRACE_EXIT, "%s", __func__); } static SmlBool _recv_changes(SmlDsSession *dsession, SmlChangeType type, const char *uid, char *data, unsigned int size, const char *contenttype, void *userdata, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %i, %s, %s, %i, %s, %p, %p)", __func__, dsession, type, VA_STRING(uid), VA_STRING(data), size, VA_STRING(contenttype), userdata, error); if (type == SML_CHANGE_ADD) { g_atomic_int_add(&adds_received, 1); g_assert(!strcmp(uid, "uid")); g_assert(!strncmp(data, "data", size)); g_assert(size == 4); } else if (type == SML_CHANGE_REPLACE) { g_atomic_int_add(&modifies_received, 1); g_assert(!strcmp(uid, "uid")); g_assert(!strncmp(data, "newdata", size)); g_assert(size == 7); } else if (type == SML_CHANGE_DELETE) { g_atomic_int_add(&deletes_received, 1); g_assert(!strcmp(uid, "uid")); g_assert(!data); g_assert(size == 0); } else { sml_fail_unless(FALSE, "An unexpected SyncML change type %d was received.", type); } if (data) smlSafeCFree(&data); smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; } static void _alert_reply(SmlSession *dsession, SmlStatus *status, void *userdata) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, dsession, status, userdata); sml_fail_unless(status != NULL, NULL); if (GPOINTER_TO_INT(userdata) == 1) { sml_fail_unless(smlStatusGetClass(status) == SML_ERRORCLASS_SUCCESS, NULL); } else { sml_fail_unless(smlStatusGetClass(status) == SML_ERRORCLASS_FATAL, NULL); } g_atomic_int_add(&replies_received, 1); smlTrace(TRACE_EXIT, "%s", __func__); } static void _sync_reply(SmlSession *dsession, SmlStatus *status, void *userdata) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, dsession, status, userdata); sml_fail_unless(status != NULL, NULL); if (GPOINTER_TO_INT(userdata) == 1) { sml_fail_unless(smlStatusGetClass(status) == SML_ERRORCLASS_SUCCESS, NULL); } else { sml_fail_unless(smlStatusGetClass(status) == SML_ERRORCLASS_FATAL, NULL); } g_atomic_int_add(&replies_received, 1); smlTrace(TRACE_EXIT, "%s", __func__); } static void _add_reply(SmlDsSession *session, SmlStatus *status, const char *newuid, void *userdata) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %s, %p)", __func__, session, status, VA_STRING(newuid), userdata); sml_fail_unless(status != NULL, NULL); sml_fail_unless(smlStatusGetClass(status) == SML_ERRORCLASS_SUCCESS, NULL); sml_fail_unless(GPOINTER_TO_INT(userdata) == 1 || GPOINTER_TO_INT(userdata) == 2, NULL); if (GPOINTER_TO_INT(userdata) == 1) { sml_fail_unless(newuid != NULL, NULL); sml_fail_unless(!strcmp(newuid, "newuid"), NULL); } else { sml_fail_unless(newuid == NULL, NULL); } g_atomic_int_add(&add_replies_received, 1); smlTrace(TRACE_EXIT, "%s", __func__); } static void _modify_reply(SmlDsSession *session, SmlStatus *status, const char *newuid, void *userdata) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %s, %p)", __func__, session, status, VA_STRING(newuid), userdata); sml_fail_unless(status != NULL, NULL); sml_fail_unless(smlStatusGetClass(status) == SML_ERRORCLASS_SUCCESS, NULL); sml_fail_unless(GPOINTER_TO_INT(userdata) == 1, NULL); sml_fail_unless(newuid == NULL, NULL); g_atomic_int_add(&modify_replies_received, 1); smlTrace(TRACE_EXIT, "%s", __func__); } static void _delete_reply(SmlDsSession *session, SmlStatus *status, const char *newuid, void *userdata) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %s, %p)", __func__, session, status, VA_STRING(newuid), userdata); sml_fail_unless(status != NULL, NULL); sml_fail_unless(smlStatusGetClass(status) == SML_ERRORCLASS_SUCCESS, NULL); sml_fail_unless(GPOINTER_TO_INT(userdata) == 1, NULL); sml_fail_unless(newuid == NULL, NULL); g_atomic_int_add(&delete_replies_received, 1); smlTrace(TRACE_EXIT, "%s", __func__); } static void _map_reply(SmlSession *dsession, SmlStatus *status, void *userdata) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, dsession, status, userdata); sml_fail_unless(status != NULL, NULL); sml_fail_unless(smlStatusGetClass(status) == SML_ERRORCLASS_SUCCESS, NULL); g_atomic_int_add(&replies_received, 1); smlTrace(TRACE_EXIT, "%s", __func__); } START_TEST (datastore_server_new) { setup_testbed(NULL); SmlError *error = NULL; SmlLocation *loc = smlLocationNew("/vcards", NULL, &error); SmlDsServer *server = smlDsServerNew(SML_ELEMENT_TEXT_VCARD, loc, &error); sml_fail_unless(server != NULL, NULL); sml_fail_unless(error == NULL, NULL); smlLocationUnref(loc); smlDsServerFree(server); } END_TEST START_TEST (datastore_client_new) { setup_testbed(NULL); SmlError *error = NULL; SmlLocation *loc = smlLocationNew("/vcards", NULL, &error); SmlDsServer *server = smlDsClientNew(SML_ELEMENT_TEXT_VCARD, loc, loc, &error); sml_fail_unless(server != NULL, NULL); sml_fail_unless(error == NULL, NULL); smlLocationUnref(loc); smlDsServerFree(server); } END_TEST static void _event_callback(SmlSession *session, SmlSessionEventType type, SmlCommand *command, SmlCommand *parent, SmlStatus *reply, SmlError *error, void *userdata) { smlTrace(TRACE_ENTRY, "%s(%p, %p)", __func__, parent, reply); _server_corr *corr = userdata; switch (type) { case SML_SESSION_EVENT_ESTABLISHED: case SML_SESSION_EVENT_HEADER_REPLY: break; case SML_SESSION_EVENT_CHILD_COMMAND: case SML_SESSION_EVENT_COMMAND_START: switch (command->type) { case SML_COMMAND_TYPE_ALERT: if (!corr->dsession) corr->dsession = smlDsServerRecvAlert(corr->server, session, command); else smlDsSessionRecvAlert(session, command, corr->dsession); break; case SML_COMMAND_TYPE_SYNC: sml_fail_unless(corr->dsession != NULL, NULL); smlDsSessionRecvSync(session, command, corr->dsession); break; case SML_COMMAND_TYPE_ADD: case SML_COMMAND_TYPE_DELETE: case SML_COMMAND_TYPE_REPLACE: sml_fail_unless(corr->dsession != NULL, NULL); smlDsSessionRecvChange(session, command, corr->dsession); break; case SML_COMMAND_TYPE_MAP: sml_fail_unless(corr->dsession != NULL, NULL); smlDsSessionRecvMap(session, command, corr->dsession); break; default: sml_fail_unless(FALSE, "An unexpected command type %d was received.", command->type); break; } break; case SML_SESSION_EVENT_COMMAND_END: switch (command->type) { case SML_COMMAND_TYPE_SYNC: sml_fail_unless(corr->dsession != NULL, NULL); smlDsSessionRecvSync(session, command, corr->dsession); break; default: sml_fail_unless(FALSE, "An unexpected command type %d was received.", command->type); break; } break; case SML_SESSION_EVENT_FLUSH: case SML_SESSION_EVENT_FINAL: break; case SML_SESSION_EVENT_END: g_atomic_int_add(&session_ends, 1); break; case SML_SESSION_EVENT_ERROR: sml_fail_unless(FALSE, "%s", smlErrorPrint(&error)); break; default: sml_fail_unless(FALSE, "An unexpected session event %d was received.", type); break; } smlTrace(TRACE_EXIT, "%s", __func__); } static void _data_send_callback(SmlSession *session, SmlTransportData *data, void *userdata) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, session, data, userdata); smlTrace(TRACE_INTERNAL, "%s: setting data(data: %p, real %p, size %i)", __func__, data, data->data, data->size); smlTransportDataRef(data); SmlTransportData **dataptr = userdata; *dataptr = data; data_received++; smlTrace(TRACE_EXIT, "%s", __func__); } /* Send Alert -> C -- Put, Alert --> S -> init_alert, get_alert, recv_alert * end session -> S -- Status --> C -> manager event (Session End) */ START_TEST (datastore_send_alert) { /* General setup */ setup_testbed(NULL); SmlError *error = NULL; SmlLocation *loc = smlLocationNew("/vcards", NULL, &error); SmlDsServer *client = smlDsClientNew(SML_ELEMENT_TEXT_VCARD, loc, loc, &error); _server_corr *client_corr = g_malloc0(sizeof(_server_corr)); client_corr->server = client; SmlDsServer *server = smlDsServerNew(SML_ELEMENT_TEXT_VCARD, loc, &error); _server_corr *server_corr = g_malloc0(sizeof(_server_corr)); server_corr->server = server; smlDsServerSetConnectCallback(server, _recv_init_alert, server_corr); /* Start a new session from the client */ SmlSession *session = smlSessionNew(SML_SESSION_TYPE_CLIENT, SML_MIMETYPE_XML, SML_VERSION_12, SML_PROTOCOL_SYNCML, loc, loc, "1", 0, &error); client_corr->thread = smlSessionRunAsync(session, &to_session); SmlSession *session2 = smlSessionNew(SML_SESSION_TYPE_SERVER, SML_MIMETYPE_XML, SML_VERSION_12, SML_PROTOCOL_SYNCML, loc, loc, "1", 0, &error); server_corr->thread = smlSessionRunAsync(session2, &to_session2); smlSessionSetLocalMaxMsgSize(session2, defaultMaxMsgSize); smlSessionSetLocalMaxObjSize(session2, defaultMaxObjSize); smlLocationUnref(loc); smlSessionSetEventCallback(session, _event_callback, client_corr); smlSessionSetDataCallback(session, _data_send_callback, &to_session2); smlSessionSetEventCallback(session2, _event_callback, server_corr); smlSessionSetDataCallback(session2, _data_send_callback, &to_session); client_corr->dsession = smlDsServerSendAlert(client, session, SML_ALERT_TWO_WAY, "last", "next", _alert_reply, GINT_TO_POINTER(1), &error); sml_fail_unless(client_corr->dsession != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlSessionFlush(session, TRUE, &error), NULL); sml_fail_unless(error == NULL, NULL); while (init_alerts_received != 1) { usleep(500); } smlDsSessionGetAlert(server_corr->dsession, _recv_alert, GINT_TO_POINTER(1)); while (alerts_received != 1) { usleep(500); } sml_fail_unless(smlSessionEnd(session2, &error), NULL); sml_fail_unless(error == NULL, NULL); while (replies_received != 1) { usleep(500); } while (session_ends != 2) { usleep(500); } smlSessionStop(client_corr->thread); smlSessionStop(server_corr->thread); smlDsSessionUnref(client_corr->dsession); smlDsSessionUnref(server_corr->dsession); sml_fail_unless(data_received == 2, NULL); sml_fail_unless(init_alerts_received == 1, NULL); sml_fail_unless(alerts_received == 1, NULL); sml_fail_unless(syncs_received == 0, NULL); sml_fail_unless(changes_received == 0, NULL); sml_fail_unless(replies_received == 1, NULL); sml_fail_unless(session_ends == 2, NULL); g_free(client_corr); g_free(server_corr); smlSessionUnref(session); smlSessionUnref(session2); smlDsServerFree(server); smlDsServerFree(client); } END_TEST /* C -- Put, Alert --> S * S -- Status, Put, Alert --> C * C -- Status --> S * S -- Status --> C */ START_TEST (datastore_send_alert2) { data_received = 0; init_alerts_received = 0; alerts_received = 0; syncs_received = 0; sync_ends_received = 0; changes_received = 0; replies_received = 0; adds_received = 0; add_replies_received = 0; deletes_received = 0; delete_replies_received = 0; modifies_received = 0; modify_replies_received = 0; session_ends = 0; to_session = NULL; to_session2 = NULL; /* General setup */ setup_testbed(NULL); SmlError *error = NULL; SmlLocation *loc = smlLocationNew("/vcards", NULL, &error); SmlDsServer *client = smlDsClientNew(SML_ELEMENT_TEXT_VCARD, loc, loc, &error); _server_corr *client_corr = g_malloc0(sizeof(_server_corr)); client_corr->server = client; SmlDsServer *server = smlDsServerNew(SML_ELEMENT_TEXT_VCARD, loc, &error); _server_corr *server_corr = g_malloc0(sizeof(_server_corr)); server_corr->server = server; smlDsServerSetConnectCallback(server, _recv_init_alert, server_corr); /* Start a new session from the client */ SmlSession *session = smlSessionNew(SML_SESSION_TYPE_CLIENT, SML_MIMETYPE_XML, SML_VERSION_12, SML_PROTOCOL_SYNCML, loc, loc, "1", 0, &error); client_corr->thread = smlSessionRunAsync(session, &to_session); SmlSession *session2 = smlSessionNew(SML_SESSION_TYPE_SERVER, SML_MIMETYPE_XML, SML_VERSION_12, SML_PROTOCOL_SYNCML, loc, loc, "1", 0, &error); server_corr->thread = smlSessionRunAsync(session2, &to_session2); smlSessionSetLocalMaxMsgSize(session2, defaultMaxMsgSize); smlSessionSetLocalMaxObjSize(session2, defaultMaxObjSize); smlSessionSetEventCallback(session, _event_callback, client_corr); smlSessionSetDataCallback(session, _data_send_callback, &to_session2); smlSessionSetEventCallback(session2, _event_callback, server_corr); smlSessionSetDataCallback(session2, _data_send_callback, &to_session); client_corr->dsession = smlDsServerSendAlert(client, session, SML_ALERT_TWO_WAY, "last", "next", _alert_reply, GINT_TO_POINTER(1), &error); sml_fail_unless(client_corr->dsession != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlSessionFlush(session, TRUE, &error), NULL); sml_fail_unless(error == NULL, NULL); while (init_alerts_received != 1) { usleep(500); } smlDsSessionGetAlert(server_corr->dsession, _recv_alert, GINT_TO_POINTER(1)); smlDsSessionSendAlert(server_corr->dsession, SML_ALERT_TWO_WAY, "last", "next", _alert_reply, GINT_TO_POINTER(1), &error); smlLocationUnref(loc); while (alerts_received != 1) { usleep(500); } sml_fail_unless(smlSessionFlush(session2, TRUE, &error), NULL); sml_fail_unless(error == NULL, NULL); while (data_received != 2) { usleep(500); } smlDsSessionGetAlert(client_corr->dsession, _recv_alert, GINT_TO_POINTER(1)); while (alerts_received != 2) { smlDsSessionDispatch(client_corr->dsession); usleep(500); } sml_fail_unless(smlSessionEnd(session, &error), NULL); sml_fail_unless(error == NULL, NULL); while (session_ends != 2) { usleep(500); } smlSessionStop(client_corr->thread); smlSessionStop(server_corr->thread); smlDsSessionUnref(client_corr->dsession); smlDsSessionUnref(server_corr->dsession); sml_fail_unless(data_received == 4, NULL); sml_fail_unless(init_alerts_received == 1, NULL); sml_fail_unless(alerts_received == 2, NULL); sml_fail_unless(syncs_received == 0, NULL); sml_fail_unless(changes_received == 0, NULL); sml_fail_unless(replies_received == 2, NULL); sml_fail_unless(session_ends == 2, NULL); g_free(client_corr); g_free(server_corr); smlSessionUnref(session); smlSessionUnref(session2); smlDsServerFree(server); smlDsServerFree(client); } END_TEST /* C -- Put, Alert --> S * S -- Status, Put, Alert --> C * C -- Status, Sync --> S * S -- Status --> S */ START_TEST (datastore_send_empty_sync) { data_received = 0; init_alerts_received = 0; alerts_received = 0; syncs_received = 0; sync_ends_received = 0; changes_received = 0; replies_received = 0; adds_received = 0; add_replies_received = 0; deletes_received = 0; delete_replies_received = 0; modifies_received = 0; modify_replies_received = 0; session_ends = 0; to_session = NULL; to_session2 = NULL; /* General setup */ setup_testbed(NULL); SmlError *error = NULL; SmlLocation *loc = smlLocationNew("/vcards", NULL, &error); SmlDsServer *client = smlDsClientNew(SML_ELEMENT_TEXT_VCARD, loc, loc, &error); _server_corr *client_corr = g_malloc0(sizeof(_server_corr)); client_corr->server = client; SmlDsServer *server = smlDsServerNew(SML_ELEMENT_TEXT_VCARD, loc, &error); _server_corr *server_corr = g_malloc0(sizeof(_server_corr)); server_corr->server = server; smlDsServerSetConnectCallback(server, _recv_init_alert, server_corr); /* Start a new session from the client */ SmlSession *session = smlSessionNew(SML_SESSION_TYPE_CLIENT, SML_MIMETYPE_XML, SML_VERSION_12, SML_PROTOCOL_SYNCML, loc, loc, "1", 0, &error); client_corr->thread = smlSessionRunAsync(session, &to_session); SmlSession *session2 = smlSessionNew(SML_SESSION_TYPE_SERVER, SML_MIMETYPE_XML, SML_VERSION_12, SML_PROTOCOL_SYNCML, loc, loc, "1", 0, &error); server_corr->thread = smlSessionRunAsync(session2, &to_session2); smlSessionSetLocalMaxMsgSize(session2, defaultMaxMsgSize); smlSessionSetLocalMaxObjSize(session2, defaultMaxObjSize); smlSessionSetEventCallback(session, _event_callback, client_corr); smlSessionSetDataCallback(session, _data_send_callback, &to_session2); smlSessionSetEventCallback(session2, _event_callback, server_corr); smlSessionSetDataCallback(session2, _data_send_callback, &to_session); client_corr->dsession = smlDsServerSendAlert(client, session, SML_ALERT_TWO_WAY, "last", "next", _alert_reply, GINT_TO_POINTER(1), &error); sml_fail_unless(client_corr->dsession != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlSessionFlush(session, TRUE, &error), NULL); sml_fail_unless(error == NULL, NULL); while (init_alerts_received != 1) { usleep(500); } smlDsSessionGetAlert(server_corr->dsession, _recv_alert, GINT_TO_POINTER(1)); smlDsSessionSendAlert(server_corr->dsession, SML_ALERT_TWO_WAY, "last", "next", _alert_reply, GINT_TO_POINTER(1), &error); while (alerts_received != 1) { smlDsSessionDispatch(server_corr->dsession); usleep(500); } sml_fail_unless(smlSessionFlush(session2, TRUE, &error), NULL); sml_fail_unless(error == NULL, NULL); while (data_received != 2) { usleep(500); } smlDsSessionGetAlert(client_corr->dsession, _recv_alert, GINT_TO_POINTER(1)); while (alerts_received != 2) { smlDsSessionDispatch(client_corr->dsession); usleep(500); } smlDsSessionSendSync(client_corr->dsession, 0, _sync_reply, GINT_TO_POINTER(1), &error); smlDsSessionCloseSync(client_corr->dsession, &error); sml_fail_unless(smlSessionFlush(session, TRUE, &error), NULL); sml_fail_unless(error == NULL, NULL); while (data_received != 3) { usleep(500); } smlDsSessionGetSync(server_corr->dsession, _recv_sync, GINT_TO_POINTER(1)); while (syncs_received != 1) { smlDsSessionDispatch(server_corr->dsession); usleep(500); } sml_fail_unless(smlSessionEnd(session2, &error), NULL); sml_fail_unless(error == NULL, NULL); while (session_ends != 2) { usleep(500); } smlSessionStop(client_corr->thread); smlSessionStop(server_corr->thread); smlDsSessionUnref(client_corr->dsession); smlDsSessionUnref(server_corr->dsession); sml_fail_unless(data_received == 4, NULL); sml_fail_unless(init_alerts_received == 1, NULL); sml_fail_unless(alerts_received == 2, NULL); sml_fail_unless(syncs_received == 1, NULL); sml_fail_unless(changes_received == 0, NULL); sml_fail_unless(replies_received == 3, NULL); sml_fail_unless(session_ends == 2, NULL); g_free(client_corr); g_free(server_corr); smlSessionUnref(session); smlSessionUnref(session2); smlLocationUnref(loc); smlDsServerFree(server); smlDsServerFree(client); } END_TEST /* C -- Put, Alert --> S * S -- Status, Put, Alert --> C * C -- Status, Sync --> S * S -- Status, Sync --> S * C -- Status --> S * S -- Status --> C */ START_TEST (datastore_reply_empty_sync) { data_received = 0; init_alerts_received = 0; alerts_received = 0; syncs_received = 0; sync_ends_received = 0; changes_received = 0; replies_received = 0; adds_received = 0; add_replies_received = 0; deletes_received = 0; delete_replies_received = 0; modifies_received = 0; modify_replies_received = 0; session_ends = 0; to_session = NULL; to_session2 = NULL; /* General setup */ setup_testbed(NULL); SmlError *error = NULL; SmlLocation *loc = smlLocationNew("/vcards", NULL, &error); SmlDsServer *client = smlDsClientNew(SML_ELEMENT_TEXT_VCARD, loc, loc, &error); _server_corr *client_corr = g_malloc0(sizeof(_server_corr)); client_corr->server = client; SmlDsServer *server = smlDsServerNew(SML_ELEMENT_TEXT_VCARD, loc, &error); _server_corr *server_corr = g_malloc0(sizeof(_server_corr)); server_corr->server = server; smlDsServerSetConnectCallback(server, _recv_init_alert, server_corr); /* Start a new session from the client */ SmlSession *session = smlSessionNew(SML_SESSION_TYPE_CLIENT, SML_MIMETYPE_XML, SML_VERSION_12, SML_PROTOCOL_SYNCML, loc, loc, "1", 0, &error); client_corr->thread = smlSessionRunAsync(session, &to_session); SmlSession *session2 = smlSessionNew(SML_SESSION_TYPE_SERVER, SML_MIMETYPE_XML, SML_VERSION_12, SML_PROTOCOL_SYNCML, loc, loc, "1", 0, &error); server_corr->thread = smlSessionRunAsync(session2, &to_session2); smlSessionSetLocalMaxMsgSize(session2, defaultMaxMsgSize); smlSessionSetLocalMaxObjSize(session2, defaultMaxObjSize); smlSessionSetEventCallback(session, _event_callback, client_corr); smlSessionSetDataCallback(session, _data_send_callback, &to_session2); smlSessionSetEventCallback(session2, _event_callback, server_corr); smlSessionSetDataCallback(session2, _data_send_callback, &to_session); client_corr->dsession = smlDsServerSendAlert(client, session, SML_ALERT_TWO_WAY, "last", "next", _alert_reply, GINT_TO_POINTER(1), &error); sml_fail_unless(client_corr->dsession != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlSessionFlush(session, TRUE, &error), NULL); sml_fail_unless(error == NULL, NULL); while (init_alerts_received != 1) { usleep(500); } smlDsSessionGetAlert(server_corr->dsession, _recv_alert, GINT_TO_POINTER(1)); smlDsSessionSendAlert(server_corr->dsession, SML_ALERT_TWO_WAY, "last", "next", _alert_reply, GINT_TO_POINTER(1), &error); while (alerts_received != 1) { smlDsSessionDispatch(server_corr->dsession); usleep(500); } sml_fail_unless(smlSessionFlush(session2, TRUE, &error), NULL); sml_fail_unless(error == NULL, NULL); while (data_received != 2) { usleep(500); } smlDsSessionGetAlert(client_corr->dsession, _recv_alert, GINT_TO_POINTER(1)); while (alerts_received != 2) { smlDsSessionDispatch(client_corr->dsession); usleep(500); } smlDsSessionSendSync(client_corr->dsession, 0, _sync_reply, GINT_TO_POINTER(1), &error); smlDsSessionCloseSync(client_corr->dsession, &error); sml_fail_unless(smlSessionFlush(session, TRUE, &error), NULL); sml_fail_unless(error == NULL, NULL); while (data_received != 3) { usleep(500); } smlDsSessionGetSync(server_corr->dsession, _recv_sync, GINT_TO_POINTER(1)); while (syncs_received != 1) { smlDsSessionDispatch(server_corr->dsession); usleep(500); } smlDsSessionSendSync(server_corr->dsession, 0, _sync_reply, GINT_TO_POINTER(1), &error); smlDsSessionCloseSync(server_corr->dsession, &error); sml_fail_unless(smlSessionFlush(session2, TRUE, &error), NULL); sml_fail_unless(error == NULL, NULL); while (data_received != 4) { usleep(500); } smlDsSessionGetSync(client_corr->dsession, _recv_sync, GINT_TO_POINTER(1)); while (syncs_received != 2) { smlDsSessionDispatch(client_corr->dsession); usleep(500); } sml_fail_unless(smlSessionEnd(session, &error), NULL); sml_fail_unless(error == NULL, NULL); while (session_ends != 2) { usleep(500); } smlSessionStop(client_corr->thread); smlSessionStop(server_corr->thread); smlDsSessionUnref(client_corr->dsession); smlDsSessionUnref(server_corr->dsession); sml_fail_unless(data_received == 6, NULL); sml_fail_unless(init_alerts_received == 1, NULL); sml_fail_unless(alerts_received == 2, NULL); sml_fail_unless(syncs_received == 2, NULL); sml_fail_unless(changes_received == 0, NULL); sml_fail_unless(replies_received == 4, NULL); sml_fail_unless(session_ends == 2, NULL); g_free(client_corr); g_free(server_corr); smlSessionUnref(session); smlSessionUnref(session2); smlLocationUnref(loc); smlDsServerFree(server); smlDsServerFree(client); } END_TEST /* send alerts, send sync from server, send from client with one add */ /* Send no mapitems */ /* C -- Put, Alert --> S * S -- Status, Put, Alert --> C * C -- Status, Sync, Add --> S * S -- Status, Sync --> S * C -- Status --> S * S -- Status --> C */ START_TEST (datastore_add) { data_received = 0; init_alerts_received = 0; alerts_received = 0; syncs_received = 0; sync_ends_received = 0; changes_received = 0; replies_received = 0; adds_received = 0; add_replies_received = 0; deletes_received = 0; delete_replies_received = 0; modifies_received = 0; modify_replies_received = 0; session_ends = 0; to_session = NULL; to_session2 = NULL; /* General setup */ setup_testbed(NULL); SmlError *error = NULL; SmlLocation *loc = smlLocationNew("/vcards", NULL, &error); SmlDsServer *client = smlDsClientNew(SML_ELEMENT_TEXT_VCARD, loc, loc, &error); _server_corr *client_corr = g_malloc0(sizeof(_server_corr)); client_corr->server = client; SmlDsServer *server = smlDsServerNew(SML_ELEMENT_TEXT_VCARD, loc, &error); _server_corr *server_corr = g_malloc0(sizeof(_server_corr)); server_corr->server = server; smlDsServerSetConnectCallback(server, _recv_init_alert, server_corr); /* Start a new session from the client */ SmlSession *session = smlSessionNew(SML_SESSION_TYPE_CLIENT, SML_MIMETYPE_XML, SML_VERSION_12, SML_PROTOCOL_SYNCML, loc, loc, "1", 0, &error); client_corr->thread = smlSessionRunAsync(session, &to_session); SmlSession *session2 = smlSessionNew(SML_SESSION_TYPE_SERVER, SML_MIMETYPE_XML, SML_VERSION_12, SML_PROTOCOL_SYNCML, loc, loc, "1", 0, &error); server_corr->thread = smlSessionRunAsync(session2, &to_session2); smlSessionSetLocalMaxMsgSize(session2, defaultMaxMsgSize); smlSessionSetLocalMaxObjSize(session2, defaultMaxObjSize); smlSessionSetEventCallback(session, _event_callback, client_corr); smlSessionSetDataCallback(session, _data_send_callback, &to_session2); smlSessionSetEventCallback(session2, _event_callback, server_corr); smlSessionSetDataCallback(session2, _data_send_callback, &to_session); client_corr->dsession = smlDsServerSendAlert(client, session, SML_ALERT_TWO_WAY, "last", "next", _alert_reply, GINT_TO_POINTER(1), &error); sml_fail_unless(client_corr->dsession != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlSessionFlush(session, TRUE, &error), NULL); sml_fail_unless(error == NULL, NULL); while (init_alerts_received != 1) { usleep(500); } smlDsSessionGetAlert(server_corr->dsession, _recv_alert, GINT_TO_POINTER(1)); smlDsSessionSendAlert(server_corr->dsession, SML_ALERT_TWO_WAY, "last", "next", _alert_reply, GINT_TO_POINTER(1), &error); while (alerts_received != 1) { smlDsSessionDispatch(server_corr->dsession); usleep(500); } sml_fail_unless(smlSessionFlush(session2, TRUE, &error), NULL); sml_fail_unless(error == NULL, NULL); while (data_received != 2) { usleep(500); } smlDsSessionGetAlert(client_corr->dsession, _recv_alert, GINT_TO_POINTER(1)); while (alerts_received != 2) { smlDsSessionDispatch(client_corr->dsession); usleep(500); } smlDsSessionSendSync(client_corr->dsession, 0, _sync_reply, GINT_TO_POINTER(1), &error); sml_fail_unless(smlDsSessionQueueChange(client_corr->dsession, SML_CHANGE_ADD, "uid", "data", 4, SML_ELEMENT_TEXT_VCARD, _add_reply, GINT_TO_POINTER(2), &error), NULL); sml_fail_unless(error == NULL, NULL); smlDsSessionCloseSync(client_corr->dsession, &error); sml_fail_unless(smlSessionFlush(session, TRUE, &error), NULL); sml_fail_unless(error == NULL, NULL); while (data_received != 3) { usleep(500); } smlDsSessionGetSync(server_corr->dsession, _recv_sync, GINT_TO_POINTER(1)); smlDsSessionGetChanges(server_corr->dsession, _recv_changes, GINT_TO_POINTER(1)); while (syncs_received != 1 || adds_received != 1) { smlDsSessionDispatch(server_corr->dsession); usleep(500); } smlDsSessionSendSync(server_corr->dsession, 0, _sync_reply, GINT_TO_POINTER(1), &error); smlDsSessionCloseSync(server_corr->dsession, &error); sml_fail_unless(smlSessionFlush(session2, TRUE, &error), NULL); sml_fail_unless(error == NULL, NULL); while (data_received != 4) { usleep(500); } smlDsSessionGetSync(client_corr->dsession, _recv_sync, GINT_TO_POINTER(1)); while (syncs_received != 2) { smlDsSessionDispatch(client_corr->dsession); usleep(500); } sml_fail_unless(smlSessionEnd(session, &error), NULL); sml_fail_unless(error == NULL, NULL); while (session_ends != 2) { usleep(500); } smlSessionStop(client_corr->thread); smlSessionStop(server_corr->thread); smlDsSessionUnref(client_corr->dsession); smlDsSessionUnref(server_corr->dsession); sml_fail_unless(data_received == 6, NULL); sml_fail_unless(init_alerts_received == 1, NULL); sml_fail_unless(alerts_received == 2, NULL); sml_fail_unless(syncs_received == 2, NULL); sml_fail_unless(changes_received == 0, NULL); sml_fail_unless(replies_received == 4, NULL); sml_fail_unless(session_ends == 2, NULL); sml_fail_unless(adds_received == 1, NULL); sml_fail_unless(add_replies_received == 1, NULL); sml_fail_unless(deletes_received == 0, NULL); sml_fail_unless(delete_replies_received == 0, NULL); sml_fail_unless(modifies_received == 0, NULL); sml_fail_unless(modify_replies_received == 0, NULL); g_free(client_corr); g_free(server_corr); smlSessionUnref(session); smlSessionUnref(session2); smlLocationUnref(loc); smlDsServerFree(server); smlDsServerFree(client); } END_TEST /* send alerts, send sync from server, send from client with one add */ /* C -- Put, Alert --> S * S -- Status, Put, Alert --> C * C -- Status, Sync, Add --> S * S -- Status, Sync, Add --> S * C -- Status, Map --> S * S -- Status --> C */ START_TEST (datastore_add2) { data_received = 0; init_alerts_received = 0; alerts_received = 0; syncs_received = 0; sync_ends_received = 0; changes_received = 0; replies_received = 0; adds_received = 0; add_replies_received = 0; deletes_received = 0; delete_replies_received = 0; modifies_received = 0; modify_replies_received = 0; session_ends = 0; to_session = NULL; to_session2 = NULL; /* General setup */ setup_testbed(NULL); SmlError *error = NULL; SmlLocation *loc = smlLocationNew("/vcards", NULL, &error); SmlDsServer *client = smlDsClientNew(SML_ELEMENT_TEXT_VCARD, loc, loc, &error); _server_corr *client_corr = g_malloc0(sizeof(_server_corr)); client_corr->server = client; SmlDsServer *server = smlDsServerNew(SML_ELEMENT_TEXT_VCARD, loc, &error); _server_corr *server_corr = g_malloc0(sizeof(_server_corr)); server_corr->server = server; smlDsServerSetConnectCallback(server, _recv_init_alert, server_corr); /* Start a new session from the client */ SmlSession *session = smlSessionNew(SML_SESSION_TYPE_CLIENT, SML_MIMETYPE_XML, SML_VERSION_12, SML_PROTOCOL_SYNCML, loc, loc, "1", 0, &error); client_corr->thread = smlSessionRunAsync(session, &to_session); SmlSession *session2 = smlSessionNew(SML_SESSION_TYPE_SERVER, SML_MIMETYPE_XML, SML_VERSION_12, SML_PROTOCOL_SYNCML, loc, loc, "1", 0, &error); server_corr->thread = smlSessionRunAsync(session2, &to_session2); smlSessionSetLocalMaxMsgSize(session2, defaultMaxMsgSize); smlSessionSetLocalMaxObjSize(session2, defaultMaxObjSize); smlSessionSetEventCallback(session, _event_callback, client_corr); smlSessionSetDataCallback(session, _data_send_callback, &to_session2); smlSessionSetEventCallback(session2, _event_callback, server_corr); smlSessionSetDataCallback(session2, _data_send_callback, &to_session); client_corr->dsession = smlDsServerSendAlert(client, session, SML_ALERT_TWO_WAY, "last", "next", _alert_reply, GINT_TO_POINTER(1), &error); sml_fail_unless(client_corr->dsession != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlSessionFlush(session, TRUE, &error), NULL); sml_fail_unless(error == NULL, NULL); while (init_alerts_received != 1) { usleep(500); } smlDsSessionGetAlert(server_corr->dsession, _recv_alert, GINT_TO_POINTER(1)); smlDsSessionSendAlert(server_corr->dsession, SML_ALERT_TWO_WAY, "last", "next", _alert_reply, GINT_TO_POINTER(1), &error); while (alerts_received != 1) { smlDsSessionDispatch(server_corr->dsession); usleep(500); } sml_fail_unless(smlSessionFlush(session2, TRUE, &error), NULL); sml_fail_unless(error == NULL, NULL); while (data_received != 2) { usleep(500); } smlDsSessionGetAlert(client_corr->dsession, _recv_alert, GINT_TO_POINTER(1)); while (alerts_received != 2) { smlDsSessionDispatch(client_corr->dsession); usleep(500); } smlDsSessionSendSync(client_corr->dsession, 1, _sync_reply, GINT_TO_POINTER(1), &error); sml_fail_unless(smlDsSessionQueueChange(client_corr->dsession, SML_CHANGE_ADD, "uid", "data", 4, SML_ELEMENT_TEXT_VCARD, _add_reply, GINT_TO_POINTER(2), &error), NULL); sml_fail_unless(error == NULL, NULL); smlDsSessionCloseSync(client_corr->dsession, &error); sml_fail_unless(smlSessionFlush(session, TRUE, &error), NULL); sml_fail_unless(error == NULL, NULL); while (data_received != 3) { usleep(500); } smlDsSessionGetSync(server_corr->dsession, _recv_sync, GINT_TO_POINTER(1)); smlDsSessionGetChanges(server_corr->dsession, _recv_changes, GINT_TO_POINTER(1)); while (syncs_received != 1 || adds_received != 1) { smlDsSessionDispatch(server_corr->dsession); usleep(500); } smlDsSessionSendSync(server_corr->dsession, 1, _sync_reply, GINT_TO_POINTER(1), &error); sml_fail_unless(smlDsSessionQueueChange(server_corr->dsession, SML_CHANGE_ADD, "uid", "data", 4, SML_ELEMENT_TEXT_VCARD, _add_reply, GINT_TO_POINTER(1), &error), NULL); sml_fail_unless(error == NULL, NULL); smlDsSessionCloseSync(server_corr->dsession, &error); sml_fail_unless(smlSessionFlush(session2, TRUE, &error), NULL); sml_fail_unless(error == NULL, NULL); while (data_received != 4) { usleep(500); } smlDsSessionGetSync(client_corr->dsession, _recv_sync, GINT_TO_POINTER(1)); smlDsSessionGetChanges(client_corr->dsession, _recv_changes, GINT_TO_POINTER(1)); while (syncs_received != 2 || adds_received != 2) { smlDsSessionDispatch(client_corr->dsession); usleep(500); } smlDsSessionQueueMap(client_corr->dsession, "uid", "newuid", &error); smlDsSessionCloseMap(client_corr->dsession, _map_reply, GINT_TO_POINTER(1), &error); sml_fail_unless(smlSessionFlush(session, TRUE, &error), NULL); sml_fail_unless(error == NULL, NULL); while (data_received != 5 || add_replies_received != 2) { usleep(500); } sml_fail_unless(smlSessionEnd(session2, &error), NULL); sml_fail_unless(error == NULL, NULL); while (session_ends != 2) { usleep(500); } smlSessionStop(client_corr->thread); smlSessionStop(server_corr->thread); smlDsSessionUnref(client_corr->dsession); smlDsSessionUnref(server_corr->dsession); sml_fail_unless(data_received == 6, NULL); sml_fail_unless(init_alerts_received == 1, NULL); sml_fail_unless(alerts_received == 2, NULL); sml_fail_unless(syncs_received == 2, NULL); sml_fail_unless(changes_received == 0, NULL); sml_fail_unless(replies_received == 5, NULL); sml_fail_unless(session_ends == 2, NULL); sml_fail_unless(adds_received == 2, NULL); sml_fail_unless(add_replies_received == 2, NULL); sml_fail_unless(deletes_received == 0, NULL); sml_fail_unless(delete_replies_received == 0, NULL); sml_fail_unless(modifies_received == 0, NULL); sml_fail_unless(modify_replies_received == 0, NULL); g_free(client_corr); g_free(server_corr); smlSessionUnref(session); smlSessionUnref(session2); smlLocationUnref(loc); smlDsServerFree(server); smlDsServerFree(client); } END_TEST /* send alerts, send sync from server, send from client with one add */ /* C -- Put, Alert --> S * S -- Status, Put, Alert --> C * C -- Status, Sync, Delete --> S * S -- Status, Sync, Delete --> S * C -- Status --> S * S -- Status --> C */ START_TEST (datastore_delete) { data_received = 0; init_alerts_received = 0; alerts_received = 0; syncs_received = 0; sync_ends_received = 0; changes_received = 0; replies_received = 0; adds_received = 0; add_replies_received = 0; deletes_received = 0; delete_replies_received = 0; modifies_received = 0; modify_replies_received = 0; session_ends = 0; to_session = NULL; to_session2 = NULL; /* General setup */ setup_testbed(NULL); SmlError *error = NULL; SmlLocation *loc = smlLocationNew("/vcards", NULL, &error); SmlDsServer *client = smlDsClientNew(SML_ELEMENT_TEXT_VCARD, loc, loc, &error); _server_corr *client_corr = g_malloc0(sizeof(_server_corr)); client_corr->server = client; SmlDsServer *server = smlDsServerNew(SML_ELEMENT_TEXT_VCARD, loc, &error); _server_corr *server_corr = g_malloc0(sizeof(_server_corr)); server_corr->server = server; smlDsServerSetConnectCallback(server, _recv_init_alert, server_corr); /* Start a new session from the client */ SmlSession *session = smlSessionNew(SML_SESSION_TYPE_CLIENT, SML_MIMETYPE_XML, SML_VERSION_12, SML_PROTOCOL_SYNCML, loc, loc, "1", 0, &error); client_corr->thread = smlSessionRunAsync(session, &to_session); SmlSession *session2 = smlSessionNew(SML_SESSION_TYPE_SERVER, SML_MIMETYPE_XML, SML_VERSION_12, SML_PROTOCOL_SYNCML, loc, loc, "1", 0, &error); server_corr->thread = smlSessionRunAsync(session2, &to_session2); smlSessionSetLocalMaxMsgSize(session2, defaultMaxMsgSize); smlSessionSetLocalMaxObjSize(session2, defaultMaxObjSize); smlSessionSetEventCallback(session, _event_callback, client_corr); smlSessionSetDataCallback(session, _data_send_callback, &to_session2); smlSessionSetEventCallback(session2, _event_callback, server_corr); smlSessionSetDataCallback(session2, _data_send_callback, &to_session); client_corr->dsession = smlDsServerSendAlert(client, session, SML_ALERT_TWO_WAY, "last", "next", _alert_reply, GINT_TO_POINTER(1), &error); sml_fail_unless(client_corr->dsession != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlSessionFlush(session, TRUE, &error), NULL); sml_fail_unless(error == NULL, NULL); while (init_alerts_received != 1) { usleep(500); } smlDsSessionGetAlert(server_corr->dsession, _recv_alert, GINT_TO_POINTER(1)); smlDsSessionSendAlert(server_corr->dsession, SML_ALERT_TWO_WAY, "last", "next", _alert_reply, GINT_TO_POINTER(1), &error); while (alerts_received != 1) { smlDsSessionDispatch(server_corr->dsession); usleep(500); } sml_fail_unless(smlSessionFlush(session2, TRUE, &error), NULL); sml_fail_unless(error == NULL, NULL); while (data_received != 2) { usleep(500); } smlDsSessionGetAlert(client_corr->dsession, _recv_alert, GINT_TO_POINTER(1)); while (alerts_received != 2) { smlDsSessionDispatch(client_corr->dsession); usleep(500); } smlDsSessionSendSync(client_corr->dsession, 1, _sync_reply, GINT_TO_POINTER(1), &error); sml_fail_unless(smlDsSessionQueueChange(client_corr->dsession, SML_CHANGE_DELETE, "uid", NULL, 0, SML_ELEMENT_TEXT_VCARD, _delete_reply, GINT_TO_POINTER(1), &error), NULL); sml_fail_unless(error == NULL, NULL); smlDsSessionCloseSync(client_corr->dsession, &error); sml_fail_unless(smlSessionFlush(session, TRUE, &error), NULL); sml_fail_unless(error == NULL, NULL); while (data_received != 3) { usleep(500); } smlDsSessionGetSync(server_corr->dsession, _recv_sync, GINT_TO_POINTER(1)); smlDsSessionGetChanges(server_corr->dsession, _recv_changes, GINT_TO_POINTER(1)); while (syncs_received != 1 || deletes_received != 1) { smlDsSessionDispatch(server_corr->dsession); usleep(500); } smlDsSessionSendSync(server_corr->dsession, 1, _sync_reply, GINT_TO_POINTER(1), &error); sml_fail_unless(smlDsSessionQueueChange(server_corr->dsession, SML_CHANGE_DELETE, "uid", NULL, 0, SML_ELEMENT_TEXT_VCARD, _delete_reply, GINT_TO_POINTER(1), &error), NULL); sml_fail_unless(error == NULL, NULL); smlDsSessionCloseSync(server_corr->dsession, &error); sml_fail_unless(smlSessionFlush(session2, TRUE, &error), NULL); sml_fail_unless(error == NULL, NULL); while (data_received != 4) { usleep(500); } smlDsSessionGetSync(client_corr->dsession, _recv_sync, GINT_TO_POINTER(1)); smlDsSessionGetChanges(client_corr->dsession, _recv_changes, GINT_TO_POINTER(1)); while (syncs_received != 2 || deletes_received != 2) { smlDsSessionDispatch(client_corr->dsession); usleep(500); } sml_fail_unless(smlSessionFlush(session, TRUE, &error), NULL); sml_fail_unless(error == NULL, NULL); while (data_received != 6 || delete_replies_received != 2 || session_ends != 2) { usleep(500); } smlSessionStop(client_corr->thread); smlSessionStop(server_corr->thread); smlDsSessionUnref(client_corr->dsession); smlDsSessionUnref(server_corr->dsession); sml_fail_unless(data_received == 6, NULL); sml_fail_unless(init_alerts_received == 1, NULL); sml_fail_unless(alerts_received == 2, NULL); sml_fail_unless(syncs_received == 2, NULL); sml_fail_unless(changes_received == 0, NULL); sml_fail_unless(replies_received == 4, NULL); sml_fail_unless(session_ends == 2, NULL); sml_fail_unless(adds_received == 0, NULL); sml_fail_unless(add_replies_received == 0, NULL); sml_fail_unless(deletes_received == 2, NULL); sml_fail_unless(delete_replies_received == 2, NULL); sml_fail_unless(modifies_received == 0, NULL); sml_fail_unless(modify_replies_received == 0, NULL); g_free(client_corr); g_free(server_corr); smlSessionUnref(session); smlSessionUnref(session2); smlLocationUnref(loc); smlDsServerFree(server); smlDsServerFree(client); } END_TEST /* send alerts, send sync from client, send from server with one add */ /* Send map */ /* C -- Put, Alert --> S * S -- Status, Put, Alert --> C * C -- Status, Sync, Replace, Delete, Add --> S * S -- Status, Sync, Add, Replace, Delete --> S * C -- Status, Map --> S * S -- Status --> C */ START_TEST (datastore_map_full) { data_received = 0; init_alerts_received = 0; alerts_received = 0; syncs_received = 0; sync_ends_received = 0; changes_received = 0; replies_received = 0; adds_received = 0; add_replies_received = 0; deletes_received = 0; delete_replies_received = 0; modifies_received = 0; modify_replies_received = 0; session_ends = 0; to_session = NULL; to_session2 = NULL; /* General setup */ setup_testbed(NULL); SmlError *error = NULL; SmlLocation *loc = smlLocationNew("/vcards", NULL, &error); SmlDsServer *client = smlDsClientNew(SML_ELEMENT_TEXT_VCARD, loc, loc, &error); _server_corr *client_corr = g_malloc0(sizeof(_server_corr)); client_corr->server = client; SmlDsServer *server = smlDsServerNew(SML_ELEMENT_TEXT_VCARD, loc, &error); _server_corr *server_corr = g_malloc0(sizeof(_server_corr)); server_corr->server = server; smlDsServerSetConnectCallback(server, _recv_init_alert, server_corr); /* Start a new session from the client */ SmlSession *session = smlSessionNew(SML_SESSION_TYPE_CLIENT, SML_MIMETYPE_XML, SML_VERSION_12, SML_PROTOCOL_SYNCML, loc, loc, "1", 0, &error); client_corr->thread = smlSessionRunAsync(session, &to_session); SmlSession *session2 = smlSessionNew(SML_SESSION_TYPE_SERVER, SML_MIMETYPE_XML, SML_VERSION_12, SML_PROTOCOL_SYNCML, loc, loc, "1", 0, &error); server_corr->thread = smlSessionRunAsync(session2, &to_session2); smlSessionSetLocalMaxMsgSize(session2, defaultMaxMsgSize); smlSessionSetLocalMaxObjSize(session2, defaultMaxObjSize); smlSessionSetEventCallback(session, _event_callback, client_corr); smlSessionSetDataCallback(session, _data_send_callback, &to_session2); smlSessionSetEventCallback(session2, _event_callback, server_corr); smlSessionSetDataCallback(session2, _data_send_callback, &to_session); client_corr->dsession = smlDsServerSendAlert(client, session, SML_ALERT_TWO_WAY, "last", "next", _alert_reply, GINT_TO_POINTER(1), &error); sml_fail_unless(client_corr->dsession != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlSessionFlush(session, TRUE, &error), NULL); sml_fail_unless(error == NULL, NULL); while (init_alerts_received != 1) { usleep(500); } smlDsSessionGetAlert(server_corr->dsession, _recv_alert, GINT_TO_POINTER(1)); smlDsSessionSendAlert(server_corr->dsession, SML_ALERT_TWO_WAY, "last", "next", _alert_reply, GINT_TO_POINTER(1), &error); while (alerts_received != 1) { smlDsSessionDispatch(server_corr->dsession); usleep(500); } sml_fail_unless(smlSessionFlush(session2, TRUE, &error), NULL); sml_fail_unless(error == NULL, NULL); while (data_received != 2) { usleep(500); } smlDsSessionGetAlert(client_corr->dsession, _recv_alert, GINT_TO_POINTER(1)); while (alerts_received != 2) { smlDsSessionDispatch(client_corr->dsession); usleep(500); } smlDsSessionSendSync(client_corr->dsession, 0, _sync_reply, GINT_TO_POINTER(1), &error); sml_fail_unless(smlDsSessionQueueChange(client_corr->dsession, SML_CHANGE_REPLACE, "uid", "newdata", 7, SML_ELEMENT_TEXT_VCARD, _modify_reply, GINT_TO_POINTER(1), &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlDsSessionQueueChange(client_corr->dsession, SML_CHANGE_DELETE, "uid", NULL, 0, SML_ELEMENT_TEXT_VCARD, _delete_reply, GINT_TO_POINTER(1), &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlDsSessionQueueChange(client_corr->dsession, SML_CHANGE_ADD, "uid", "data", 4, SML_ELEMENT_TEXT_VCARD, _add_reply, GINT_TO_POINTER(2), &error), NULL); sml_fail_unless(error == NULL, NULL); smlDsSessionCloseSync(client_corr->dsession, &error); sml_fail_unless(smlSessionFlush(session, TRUE, &error), NULL); sml_fail_unless(error == NULL, NULL); while (data_received != 3) { usleep(500); } smlDsSessionGetSync(server_corr->dsession, _recv_sync, GINT_TO_POINTER(1)); smlDsSessionGetChanges(server_corr->dsession, _recv_changes, GINT_TO_POINTER(1)); while (syncs_received != 1 || adds_received != 1 || deletes_received != 1 || modifies_received != 1) { smlDsSessionDispatch(server_corr->dsession); usleep(500); } smlDsSessionSendSync(server_corr->dsession, 0, _sync_reply, GINT_TO_POINTER(1), &error); sml_fail_unless(smlDsSessionQueueChange(server_corr->dsession, SML_CHANGE_REPLACE, "uid", "newdata", 7, SML_ELEMENT_TEXT_VCARD, _modify_reply, GINT_TO_POINTER(1), &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlDsSessionQueueChange(server_corr->dsession, SML_CHANGE_ADD, "uid", "data", 4, SML_ELEMENT_TEXT_VCARD, _add_reply, GINT_TO_POINTER(1), &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlDsSessionQueueChange(server_corr->dsession, SML_CHANGE_DELETE, "uid", NULL, 0, SML_ELEMENT_TEXT_VCARD, _delete_reply, GINT_TO_POINTER(1), &error), NULL); sml_fail_unless(error == NULL, NULL); smlDsSessionCloseSync(server_corr->dsession, &error); sml_fail_unless(smlSessionFlush(session2, TRUE, &error), NULL); sml_fail_unless(error == NULL, NULL); while (data_received != 4) { usleep(500); } smlDsSessionGetSync(client_corr->dsession, _recv_sync, GINT_TO_POINTER(1)); smlDsSessionGetChanges(client_corr->dsession, _recv_changes, GINT_TO_POINTER(1)); while (syncs_received != 2 || adds_received != 2 || deletes_received != 2 || modifies_received != 2) { smlDsSessionDispatch(client_corr->dsession); usleep(500); } smlDsSessionQueueMap(client_corr->dsession, "uid", "newuid", &error); smlDsSessionCloseMap(client_corr->dsession, _map_reply, GINT_TO_POINTER(1), &error); sml_fail_unless(smlSessionFlush(session, TRUE, &error), NULL); sml_fail_unless(error == NULL, NULL); while (data_received != 5 || add_replies_received != 2) { usleep(500); } sml_fail_unless(smlSessionEnd(session2, &error), NULL); sml_fail_unless(error == NULL, NULL); while (session_ends != 2) { usleep(500); } smlSessionStop(client_corr->thread); smlSessionStop(server_corr->thread); smlDsSessionUnref(client_corr->dsession); smlDsSessionUnref(server_corr->dsession); sml_fail_unless(data_received == 6, NULL); sml_fail_unless(init_alerts_received == 1, NULL); sml_fail_unless(alerts_received == 2, NULL); sml_fail_unless(syncs_received == 2, NULL); sml_fail_unless(changes_received == 0, NULL); sml_fail_unless(replies_received == 5, NULL); sml_fail_unless(session_ends == 2, NULL); sml_fail_unless(adds_received == 2, NULL); sml_fail_unless(add_replies_received == 2, NULL); sml_fail_unless(deletes_received == 2, NULL); sml_fail_unless(delete_replies_received == 2, NULL); sml_fail_unless(modifies_received == 2, NULL); sml_fail_unless(modify_replies_received == 2, NULL); g_free(client_corr); g_free(server_corr); smlSessionUnref(session); smlSessionUnref(session2); smlLocationUnref(loc); smlDsServerFree(server); smlDsServerFree(client); } END_TEST /* C -- Put, Alert --> S * S -- Status, Put, Alert --> C * C -- Status, Sync, 500 * Add --> S * S -- Status, Sync, 500 * Add --> S * C -- Status, Map --> S * S -- Status --> C */ START_TEST (datastore_add_large) { data_received = 0; init_alerts_received = 0; alerts_received = 0; syncs_received = 0; sync_ends_received = 0; changes_received = 0; replies_received = 0; adds_received = 0; add_replies_received = 0; deletes_received = 0; delete_replies_received = 0; modifies_received = 0; modify_replies_received = 0; session_ends = 0; to_session = NULL; to_session2 = NULL; int num = 50; /* General setup */ setup_testbed(NULL); SmlError *error = NULL; SmlLocation *loc = smlLocationNew("/vcards", NULL, &error); SmlDsServer *client = smlDsClientNew(SML_ELEMENT_TEXT_VCARD, loc, loc, &error); _server_corr *client_corr = g_malloc0(sizeof(_server_corr)); client_corr->server = client; SmlDsServer *server = smlDsServerNew(SML_ELEMENT_TEXT_VCARD, loc, &error); _server_corr *server_corr = g_malloc0(sizeof(_server_corr)); server_corr->server = server; smlDsServerSetConnectCallback(server, _recv_init_alert, server_corr); /* Start a new session from the client */ SmlSession *session = smlSessionNew(SML_SESSION_TYPE_CLIENT, SML_MIMETYPE_XML, SML_VERSION_12, SML_PROTOCOL_SYNCML, loc, loc, "1", 0, &error); client_corr->thread = smlSessionRunAsync(session, &to_session); SmlSession *session2 = smlSessionNew(SML_SESSION_TYPE_SERVER, SML_MIMETYPE_XML, SML_VERSION_12, SML_PROTOCOL_SYNCML, loc, loc, "1", 0, &error); server_corr->thread = smlSessionRunAsync(session2, &to_session2); /* All stuff must be sent at once. */ smlSessionSetLocalMaxMsgSize(session2, defaultMaxObjSize); smlSessionSetLocalMaxObjSize(session2, defaultMaxObjSize); smlSessionSetEventCallback(session, _event_callback, client_corr); smlSessionSetDataCallback(session, _data_send_callback, &to_session2); smlSessionSetEventCallback(session2, _event_callback, server_corr); smlSessionSetDataCallback(session2, _data_send_callback, &to_session); client_corr->dsession = smlDsServerSendAlert(client, session, SML_ALERT_TWO_WAY, "last", "next", _alert_reply, GINT_TO_POINTER(1), &error); sml_fail_unless(client_corr->dsession != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlSessionFlush(session, TRUE, &error), NULL); sml_fail_unless(error == NULL, NULL); while (init_alerts_received != 1) { usleep(500); } smlDsSessionGetAlert(server_corr->dsession, _recv_alert, GINT_TO_POINTER(1)); smlDsSessionSendAlert(server_corr->dsession, SML_ALERT_TWO_WAY, "last", "next", _alert_reply, GINT_TO_POINTER(1), &error); while (alerts_received != 1) { smlDsSessionDispatch(server_corr->dsession); usleep(500); } sml_fail_unless(smlSessionFlush(session2, TRUE, &error), NULL); sml_fail_unless(error == NULL, NULL); while (data_received != 2) { usleep(500); } smlDsSessionGetAlert(client_corr->dsession, _recv_alert, GINT_TO_POINTER(1)); while (alerts_received != 2) { smlDsSessionDispatch(client_corr->dsession); usleep(500); } smlDsSessionSendSync(client_corr->dsession, 0, _sync_reply, GINT_TO_POINTER(1), &error); int i = 0; for (i = 0; i < num; i++) { sml_fail_unless(smlDsSessionQueueChange(client_corr->dsession, SML_CHANGE_ADD, "uid", "data", 4, SML_ELEMENT_TEXT_VCARD, _add_reply, GINT_TO_POINTER(2), &error), NULL); sml_fail_unless(error == NULL, NULL); } smlDsSessionCloseSync(client_corr->dsession, &error); sml_fail_unless(smlSessionFlush(session, TRUE, &error), NULL); sml_fail_unless(error == NULL, NULL); while (data_received != 3) { usleep(500); } smlDsSessionGetSync(server_corr->dsession, _recv_sync, GINT_TO_POINTER(1)); smlDsSessionGetChanges(server_corr->dsession, _recv_changes, GINT_TO_POINTER(1)); while (syncs_received != 1 || adds_received != num) { smlDsSessionDispatch(server_corr->dsession); usleep(500); } smlDsSessionSendSync(server_corr->dsession, 0, _sync_reply, GINT_TO_POINTER(1), &error); for (i = 0; i < num; i++) { sml_fail_unless(smlDsSessionQueueChange(server_corr->dsession, SML_CHANGE_ADD, "uid", "data", 4, SML_ELEMENT_TEXT_VCARD, _add_reply, GINT_TO_POINTER(1), &error), NULL); sml_fail_unless(error == NULL, NULL); } smlDsSessionCloseSync(server_corr->dsession, &error); sml_fail_unless(smlSessionFlush(session2, TRUE, &error), NULL); sml_fail_unless(error == NULL, NULL); while (data_received != 4) { usleep(500); } smlDsSessionGetSync(client_corr->dsession, _recv_sync, GINT_TO_POINTER(1)); smlDsSessionGetChanges(client_corr->dsession, _recv_changes, GINT_TO_POINTER(1)); while (syncs_received != 2 || adds_received != num * 2) { smlDsSessionDispatch(client_corr->dsession); usleep(500); } for (i = 0; i < num; i++) { smlDsSessionQueueMap(client_corr->dsession, "uid", "newuid", &error); } smlDsSessionCloseMap(client_corr->dsession, _map_reply, GINT_TO_POINTER(1), &error); sml_fail_unless(smlSessionFlush(session, TRUE, &error), NULL); sml_fail_unless(error == NULL, NULL); while (data_received != 5 || add_replies_received != num * 2) { usleep(500); } sml_fail_unless(smlSessionEnd(session2, &error), NULL); sml_fail_unless(error == NULL, NULL); while (session_ends != 2) { usleep(500); } smlSessionStop(client_corr->thread); smlSessionStop(server_corr->thread); smlDsSessionUnref(client_corr->dsession); smlDsSessionUnref(server_corr->dsession); sml_fail_unless(data_received == 6, NULL); sml_fail_unless(init_alerts_received == 1, NULL); sml_fail_unless(alerts_received == 2, NULL); sml_fail_unless(syncs_received == 2, NULL); sml_fail_unless(changes_received == 0, NULL); sml_fail_unless(replies_received == 5, NULL); sml_fail_unless(session_ends == 2, NULL); sml_fail_unless(adds_received == num * 2, NULL); sml_fail_unless(add_replies_received == num * 2, NULL); sml_fail_unless(deletes_received == 0, NULL); sml_fail_unless(delete_replies_received == 0, NULL); sml_fail_unless(modifies_received == 0, NULL); sml_fail_unless(modify_replies_received == 0, NULL); g_free(client_corr); g_free(server_corr); smlSessionUnref(session); smlSessionUnref(session2); smlLocationUnref(loc); smlDsServerFree(server); smlDsServerFree(client); } END_TEST /* C -- Put, Alert --> S * S -- Status, Put, Alert --> C * C -- Status, Sync, 500 * Add --> S * S -- Status, Sync, 500 * Add --> S * C -- Status, Map --> S * S -- Status --> C */ /* Limit the sending size of both sides */ START_TEST (datastore_limit) { data_received = 0; init_alerts_received = 0; alerts_received = 0; syncs_received = 0; sync_ends_received = 0; changes_received = 0; replies_received = 0; adds_received = 0; add_replies_received = 0; deletes_received = 0; delete_replies_received = 0; modifies_received = 0; modify_replies_received = 0; session_ends = 0; to_session = NULL; to_session2 = NULL; int num = 5; unsigned int limit = 1300; /* General setup */ setup_testbed(NULL); SmlError *error = NULL; SmlLocation *loc = smlLocationNew("/vcards", NULL, &error); SmlDsServer *client = smlDsClientNew(SML_ELEMENT_TEXT_VCARD, loc, loc, &error); _server_corr *client_corr = g_malloc0(sizeof(_server_corr)); client_corr->server = client; SmlDsServer *server = smlDsServerNew(SML_ELEMENT_TEXT_VCARD, loc, &error); _server_corr *server_corr = g_malloc0(sizeof(_server_corr)); server_corr->server = server; smlDsServerSetConnectCallback(server, _recv_init_alert, server_corr); /* Start a new session from the client */ SmlSession *session = smlSessionNew(SML_SESSION_TYPE_CLIENT, SML_MIMETYPE_XML, SML_VERSION_12, SML_PROTOCOL_SYNCML, loc, loc, "1", 0, &error); client_corr->thread = smlSessionRunAsync(session, &to_session); smlSessionSetRemoteMaxMsgSize(session, limit); SmlSession *session2 = smlSessionNew(SML_SESSION_TYPE_SERVER, SML_MIMETYPE_XML, SML_VERSION_12, SML_PROTOCOL_SYNCML, loc, loc, "1", 0, &error); server_corr->thread = smlSessionRunAsync(session2, &to_session2); smlSessionSetRemoteMaxMsgSize(session2, limit); smlSessionSetLocalMaxMsgSize(session2, defaultMaxMsgSize); smlSessionSetLocalMaxObjSize(session2, defaultMaxObjSize); smlSessionSetEventCallback(session, _event_callback, client_corr); smlSessionSetDataCallback(session, _data_send_callback, &to_session2); smlSessionSetEventCallback(session2, _event_callback, server_corr); smlSessionSetDataCallback(session2, _data_send_callback, &to_session); client_corr->dsession = smlDsServerSendAlert(client, session, SML_ALERT_TWO_WAY, "last", "next", _alert_reply, GINT_TO_POINTER(1), &error); sml_fail_unless(client_corr->dsession != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlSessionFlush(session, TRUE, &error), NULL); sml_fail_unless(error == NULL, NULL); while (init_alerts_received != 1) { usleep(500); } smlDsSessionGetAlert(server_corr->dsession, _recv_alert, GINT_TO_POINTER(1)); smlDsSessionSendAlert(server_corr->dsession, SML_ALERT_TWO_WAY, "last", "next", _alert_reply, GINT_TO_POINTER(1), &error); while (alerts_received != 1) { smlDsSessionDispatch(server_corr->dsession); usleep(500); } sml_fail_unless(smlSessionFlush(session2, TRUE, &error), NULL); sml_fail_unless(error == NULL, NULL); smlDsSessionGetAlert(client_corr->dsession, _recv_alert, GINT_TO_POINTER(1)); while (alerts_received != 2) { smlDsSessionDispatch(client_corr->dsession); usleep(500); } smlDsSessionSendSync(client_corr->dsession, 0, _sync_reply, GINT_TO_POINTER(1), &error); int i = 0; for (i = 0; i < num; i++) { sml_fail_unless(smlDsSessionQueueChange(client_corr->dsession, SML_CHANGE_ADD, "uid", "data", 4, SML_ELEMENT_TEXT_VCARD, _add_reply, GINT_TO_POINTER(2), &error), NULL); sml_fail_unless(error == NULL, NULL); } smlDsSessionCloseSync(client_corr->dsession, &error); sml_fail_unless(smlSessionFlush(session, TRUE, &error), NULL); sml_fail_unless(error == NULL, NULL); smlDsSessionGetSync(server_corr->dsession, _recv_sync, GINT_TO_POINTER(1)); smlDsSessionGetChanges(server_corr->dsession, _recv_changes, GINT_TO_POINTER(1)); while (syncs_received != 1 || adds_received != num) { smlDsSessionDispatch(server_corr->dsession); usleep(5000); } smlDsSessionSendSync(server_corr->dsession, 0, _sync_reply, GINT_TO_POINTER(1), &error); for (i = 0; i < num; i++) { sml_fail_unless(smlDsSessionQueueChange(server_corr->dsession, SML_CHANGE_ADD, "uid", "data", 4, SML_ELEMENT_TEXT_VCARD, _add_reply, GINT_TO_POINTER(1), &error), NULL); sml_fail_unless(error == NULL, NULL); } smlDsSessionCloseSync(server_corr->dsession, &error); sml_fail_unless(smlSessionFlush(session2, TRUE, &error), NULL); sml_fail_unless(error == NULL, NULL); smlDsSessionGetSync(client_corr->dsession, _recv_sync, GINT_TO_POINTER(1)); smlDsSessionGetChanges(client_corr->dsession, _recv_changes, GINT_TO_POINTER(1)); while (adds_received != num * 2) { smlDsSessionDispatch(client_corr->dsession); usleep(5000); } for (i = 0; i < num; i++) { smlDsSessionQueueMap(client_corr->dsession, "uid", "newuid", &error); } smlDsSessionCloseMap(client_corr->dsession, _map_reply, GINT_TO_POINTER(1), &error); sml_fail_unless(smlSessionFlush(session, TRUE, &error), NULL); sml_fail_unless(error == NULL, NULL); while (add_replies_received != num * 2) { usleep(500); } sml_fail_unless(smlSessionEnd(session2, &error), NULL); sml_fail_unless(error == NULL, NULL); while (session_ends != 2) { usleep(500); } smlLocationUnref(loc); smlSessionStop(client_corr->thread); smlSessionStop(server_corr->thread); smlDsSessionUnref(client_corr->dsession); smlDsSessionUnref(server_corr->dsession); //sml_fail_unless(data_received == 6, NULL); sml_fail_unless(init_alerts_received == 1, NULL); sml_fail_unless(alerts_received == 2, NULL); sml_fail_unless(syncs_received == 2, NULL); sml_fail_unless(changes_received == 0, NULL); sml_fail_unless(replies_received == 5, NULL); sml_fail_unless(session_ends == 2, NULL); sml_fail_unless(adds_received == num * 2, NULL); sml_fail_unless(add_replies_received == num * 2, NULL); sml_fail_unless(deletes_received == 0, NULL); sml_fail_unless(delete_replies_received == 0, NULL); sml_fail_unless(modifies_received == 0, NULL); sml_fail_unless(modify_replies_received == 0, NULL); g_free(client_corr); g_free(server_corr); smlSessionUnref(session); smlSessionUnref(session2); smlDsServerFree(server); smlDsServerFree(client); } END_TEST #if 0 /* C -- Put, Alert --> S * S -- Status, Put, Alert --> C * C -- Status, Sync, 500 * Add --> S * S -- Status, Sync, 500 * Add --> S * C -- Status, Map --> S * S -- Status --> C */ /* Limit the sending size of both sides */ START_TEST (datastore_multi_server) { data_received = 0; init_alerts_received = 0; alerts_received = 0; syncs_received = 0; sync_ends_received = 0; changes_received = 0; replies_received = 0; adds_received = 0; add_replies_received = 0; deletes_received = 0; delete_replies_received = 0; modifies_received = 0; modify_replies_received = 0; session_ends = 0; to_session = NULL; to_session2 = NULL; int num = 50; unsigned int limit = 2000; /* General setup */ setup_testbed(NULL); SmlError *error = NULL; SmlLocation *loc = smlLocationNew("test", NULL, &error); SmlLocation *loc1 = smlLocationNew("vcards", NULL, &error); SmlLocation *loc2 = smlLocationNew("vcals", NULL, &error); SmlLocation *loc3 = smlLocationNew("vnotes", NULL, &error); /* The ds clients */ SmlDsServer *client1 = smlDsClientNew(SML_ELEMENT_TEXT_VCARD, loc1, loc1, &error); _server_corr *client_corr1 = g_malloc0(sizeof(_server_corr)); client_corr1->server = client1; SmlDsServer *client2 = smlDsClientNew(SML_ELEMENT_TEXT_VCARD, loc2, loc2, &error); _server_corr *client_corr2 = g_malloc0(sizeof(_server_corr)); client_corr2->server = client2; SmlDsServer *client3 = smlDsClientNew(SML_ELEMENT_TEXT_VCARD, loc3, loc3, &error); _server_corr *client_corr3 = g_malloc0(sizeof(_server_corr)); client_corr3->server = client3; /* The ds servers */ SmlDsServer *server1 = smlDsServerNew(SML_ELEMENT_TEXT_VCARD, loc1, &error); _server_corr *server_corr1 = g_malloc0(sizeof(_server_corr)); server_corr1->server = server1; smlDsServerSetConnectCallback(server1, _recv_init_alert, server_corr1); SmlDsServer *server2 = smlDsServerNew(SML_ELEMENT_TEXT_VCARD, loc2, &error); _server_corr *server_corr2 = g_malloc0(sizeof(_server_corr)); server_corr2->server = server2; smlDsServerSetConnectCallback(server2, _recv_init_alert, server_corr2); SmlDsServer *server3 = smlDsServerNew(SML_ELEMENT_TEXT_VCARD, loc3, &error); _server_corr *server_corr3 = g_malloc0(sizeof(_server_corr)); server_corr3->server = server3; smlDsServerSetConnectCallback(server3, _recv_init_alert, server_corr3); /* Start a new session from the client */ SmlSession *session = smlSessionNew(SML_SESSION_TYPE_CLIENT, SML_MIMETYPE_XML, SML_VERSION_12, SML_PROTOCOL_SYNCML, loc, loc, "1", 0, &error); client_corr1->thread = smlSessionRunAsync(session, &to_session); smlSessionSetSendingMaxMsgSize(session, limit); SmlSession *session2 = smlSessionNew(SML_SESSION_TYPE_SERVER, SML_MIMETYPE_XML, SML_VERSION_12, SML_PROTOCOL_SYNCML, loc, loc, "1", 0, &error); server_corr->thread = smlSessionRunAsync(session2, &to_session2); smlSessionSetSendingMaxMsgSize(session2, limit); smlSessionSetEventCallback(session, _event_callback, client_corr); smlSessionSetDataCallback(session, _data_send_callback, &to_session2); smlSessionSetEventCallback(session2, _event_callback, server_corr); smlSessionSetDataCallback(session2, _data_send_callback, &to_session); client_corr->dsession = smlDsServerSendAlert(client, session, SML_ALERT_TWO_WAY, "last", "next", _alert_reply, GINT_TO_POINTER(1), &error); sml_fail_unless(client_corr->dsession != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlSessionFlush(session, TRUE, &error), NULL); sml_fail_unless(error == NULL, NULL); while (init_alerts_received != 1) { usleep(500); } smlDsSessionGetAlert(server_corr1->dsession, _recv_alert, GINT_TO_POINTER(1)); smlDsSessionSendAlert(server_corr1->dsession, SML_ALERT_TWO_WAY, "last", "next", _alert_reply, GINT_TO_POINTER(1), &error); smlDsSessionGetAlert(server_corr2->dsession, _recv_alert, GINT_TO_POINTER(1)); smlDsSessionSendAlert(server_corr2->dsession, SML_ALERT_TWO_WAY, "last", "next", _alert_reply, GINT_TO_POINTER(1), &error); smlDsSessionGetAlert(server_corr3->dsession, _recv_alert, GINT_TO_POINTER(1)); smlDsSessionSendAlert(server_corr4->dsession, SML_ALERT_TWO_WAY, "last", "next", _alert_reply, GINT_TO_POINTER(1), &error); while (alerts_received != 3) { smlDsSessionDispatch(server_corr1->dsession); smlDsSessionDispatch(server_corr2->dsession); smlDsSessionDispatch(server_corr3->dsession); usleep(500); } sml_fail_unless(smlSessionFlush(session2, TRUE, &error), NULL); sml_fail_unless(error == NULL, NULL); smlDsSessionGetAlert(client_corr1->dsession, _recv_alert, GINT_TO_POINTER(1)); smlDsSessionGetAlert(client_corr2->dsession, _recv_alert, GINT_TO_POINTER(1)); smlDsSessionGetAlert(client_corr3->dsession, _recv_alert, GINT_TO_POINTER(1)); while (alerts_received != 6) { smlDsSessionDispatch(client_corr1->dsession); smlDsSessionDispatch(client_corr2->dsession); smlDsSessionDispatch(client_corr3->dsession); usleep(500); } smlDsSessionSendSync(client_corr1->dsession, 0, _sync_reply, GINT_TO_POINTER(1), &error); int i = 0; for (i = 0; i < num; i++) { sml_fail_unless(smlDsSessionQueueChange(client_corr1->dsession, SML_CHANGE_ADD, "uid", "data", 4, SML_ELEMENT_TEXT_VCARD, _add_reply, GINT_TO_POINTER(2), &error), NULL); sml_fail_unless(error == NULL, NULL); } smlDsSessionCloseSync(client_corr1->dsession, &error); smlDsSessionSendSync(client_corr2->dsession, 0, _sync_reply, GINT_TO_POINTER(1), &error); for (i = 0; i < num; i++) { sml_fail_unless(smlDsSessionQueueChange(client_corr2->dsession, SML_CHANGE_ADD, "uid", "data", 4, SML_ELEMENT_TEXT_VCARD, _add_reply, GINT_TO_POINTER(2), &error), NULL); sml_fail_unless(error == NULL, NULL); } smlDsSessionCloseSync(client_corr2->dsession, &error); smlDsSessionSendSync(client_corr3->dsession, 0, _sync_reply, GINT_TO_POINTER(1), &error); for (i = 0; i < num; i++) { sml_fail_unless(smlDsSessionQueueChange(client_corr3->dsession, SML_CHANGE_ADD, "uid", "data", 4, SML_ELEMENT_TEXT_VCARD, _add_reply, GINT_TO_POINTER(2), &error), NULL); sml_fail_unless(error == NULL, NULL); } smlDsSessionCloseSync(client_corr3->dsession, &error); sml_fail_unless(smlSessionFlush(session, TRUE, &error), NULL); sml_fail_unless(error == NULL, NULL); smlDsSessionGetSync(server_corr1->dsession, _recv_sync, GINT_TO_POINTER(1)); smlDsSessionGetChanges(server_corr1->dsession, _recv_changes, GINT_TO_POINTER(1)); smlDsSessionGetSync(server_corr2->dsession, _recv_sync, GINT_TO_POINTER(1)); smlDsSessionGetChanges(server_corr2->dsession, _recv_changes, GINT_TO_POINTER(1)); smlDsSessionGetSync(server_corr3->dsession, _recv_sync, GINT_TO_POINTER(1)); smlDsSessionGetChanges(server_corr3->dsession, _recv_changes, GINT_TO_POINTER(1)); while (syncs_received != 3 || adds_received != num * 3) { smlDsSessionDispatch(server_corr1->dsession); smlDsSessionDispatch(server_corr2->dsession); smlDsSessionDispatch(server_corr3->dsession); usleep(5000); } smlDsSessionSendSync(server_corr1->dsession, 0, _sync_reply, GINT_TO_POINTER(1), &error); for (i = 0; i < num; i++) { sml_fail_unless(smlDsSessionQueueChange(server_corr1->dsession, SML_CHANGE_ADD, "uid", "data", 4, SML_ELEMENT_TEXT_VCARD, _add_reply, GINT_TO_POINTER(1), &error), NULL); sml_fail_unless(error == NULL, NULL); } smlDsSessionCloseSync(server_corr1->dsession, &error); smlDsSessionSendSync(server_corr2->dsession, 0, _sync_reply, GINT_TO_POINTER(1), &error); for (i = 0; i < num; i++) { sml_fail_unless(smlDsSessionQueueChange(server_corr2->dsession, SML_CHANGE_ADD, "uid", "data", 4, SML_ELEMENT_TEXT_VCARD, _add_reply, GINT_TO_POINTER(1), &error), NULL); sml_fail_unless(error == NULL, NULL); } smlDsSessionCloseSync(server_corr2->dsession, &error); smlDsSessionSendSync(server_corr3->dsession, 0, _sync_reply, GINT_TO_POINTER(1), &error); for (i = 0; i < num; i++) { sml_fail_unless(smlDsSessionQueueChange(server_corr3->dsession, SML_CHANGE_ADD, "uid", "data", 4, SML_ELEMENT_TEXT_VCARD, _add_reply, GINT_TO_POINTER(1), &error), NULL); sml_fail_unless(error == NULL, NULL); } smlDsSessionCloseSync(server_corr3->dsession, &error); sml_fail_unless(smlSessionFlush(session2, TRUE, &error), NULL); sml_fail_unless(error == NULL, NULL); smlDsSessionGetSync(client_corr1->dsession, _recv_sync, GINT_TO_POINTER(1)); smlDsSessionGetChanges(client_corr1->dsession, _recv_changes, GINT_TO_POINTER(1)); smlDsSessionGetSync(client_corr2->dsession, _recv_sync, GINT_TO_POINTER(1)); smlDsSessionGetChanges(client_corr2->dsession, _recv_changes, GINT_TO_POINTER(1)); smlDsSessionGetSync(client_corr3->dsession, _recv_sync, GINT_TO_POINTER(1)); smlDsSessionGetChanges(client_corr3->dsession, _recv_changes, GINT_TO_POINTER(1)); while (adds_received != num * 2 * 3) { smlDsSessionDispatch(client_corr1->dsession); smlDsSessionDispatch(client_corr2->dsession); smlDsSessionDispatch(client_corr3->dsession); usleep(5000); } for (i = 0; i < num; i++) { smlDsSessionQueueMap(client_corr1->dsession, "uid", "newuid", &error); } smlDsSessionCloseMap(client_corr1->dsession, _map_reply, GINT_TO_POINTER(1), &error); for (i = 0; i < num; i++) { smlDsSessionQueueMap(client_corr2->dsession, "uid", "newuid", &error); } smlDsSessionCloseMap(client_corr2->dsession, _map_reply, GINT_TO_POINTER(1), &error); for (i = 0; i < num; i++) { smlDsSessionQueueMap(client_corr3->dsession, "uid", "newuid", &error); } smlDsSessionCloseMap(client_corr3->dsession, _map_reply, GINT_TO_POINTER(1), &error); sml_fail_unless(smlSessionFlush(session, TRUE, &error), NULL); sml_fail_unless(error == NULL, NULL); while (add_replies_received != num * 2) { usleep(500); } sml_fail_unless(smlSessionEnd(session2, &error), NULL); sml_fail_unless(error == NULL, NULL); while (session_ends != 2) { usleep(500); } smlSessionStop(client_corr1->thread); smlSessionStop(client_corr2->thread); smlSessionStop(client_corr3->thread); smlSessionStop(server_corr1->thread); smlSessionStop(server_corr2->thread); smlSessionStop(server_corr3->thread); smlDsSessionUnref(client_corr1->dsession); smlDsSessionUnref(client_corr2->dsession); smlDsSessionUnref(client_corr3->dsession); smlDsSessionUnref(server_corr1->dsession); smlDsSessionUnref(server_corr2->dsession); smlDsSessionUnref(server_corr3->dsession); //sml_fail_unless(data_received == 6, NULL); sml_fail_unless(init_alerts_received == 1, NULL); sml_fail_unless(alerts_received == 6, NULL); sml_fail_unless(syncs_received == 6, NULL); sml_fail_unless(changes_received == 0, NULL); sml_fail_unless(replies_received == 15, NULL); sml_fail_unless(session_ends == 2, NULL); sml_fail_unless(adds_received == num * 2 * 3, NULL); sml_fail_unless(add_replies_received == num * 2 * 3, NULL); sml_fail_unless(deletes_received == 0, NULL); sml_fail_unless(delete_replies_received == 0, NULL); sml_fail_unless(modifies_received == 0, NULL); sml_fail_unless(modify_replies_received == 0, NULL); g_free(client_corr1); g_free(client_corr2); g_free(client_corr3); g_free(server_corr1); g_free(server_corr2); g_free(server_corr3); smlSessionUnref(session); smlSessionUnref(session2); smlDsServerFree(server1); smlDsServerFree(server2); smlDsServerFree(server3); smlDsServerFree(client1); smlDsServerFree(client2); smlDsServerFree(client3); } END_TEST #endif /* To test: * - Multiple ds servers * - error behavious * - Slow-sync overwrite * - Aborting * - lots of changes with limit * - large objs with both limits * - missing map * - size too small for one object * - SAN * - SAN 1.2 */ @SML_TESTCASE_CODE@ libsyncml-0.5.4/tests/check_sync.c100644 1750 1750 262227 11211710410 17113 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2005 Armin Bauer * Copyright (C) 2008 Michael Bell * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include "tests/support.h" #include #include #include #define NUM_SESSIONS 30 typedef struct managerTracker { SmlManager *manager; SmlSession *session; SmlDsSession *dssessions[NUM_SESSIONS]; SmlDsServer *ds[3]; } managerTracker; unsigned int init_alerts_received; unsigned int alerts_received; unsigned int syncs_received; unsigned int sans_received; unsigned int sync_ends_received; unsigned int changes_received; unsigned int replies_received; unsigned int adds_received; unsigned int add_replies_received; unsigned int deletes_received; unsigned int delete_replies_received; unsigned int modifies_received; unsigned int modify_replies_received; unsigned int session_ends; unsigned int transport_errors; unsigned int num_sessions; unsigned int num_finals; unsigned int num_end; int num_disconnects; unsigned int session_errors; /* This is a sync test only and not a test of large object support. * Therefore all commands must be put into one message. * This means one message per package. */ #define TEST_DEFAULT_MAX_MSG_SIZE 1024000 #define TEST_DEFAULT_MAX_OBJ_SIZE 1024000 unsigned int num_changes; SmlError *eventError; void reset_testbed() { init_alerts_received = 0; alerts_received = 0; syncs_received = 0; sans_received = 0; sync_ends_received = 0; changes_received = 0; replies_received = 0; adds_received = 0; add_replies_received = 0; deletes_received = 0; delete_replies_received = 0; modifies_received = 0; modify_replies_received = 0; session_ends = 0; transport_errors = 0; num_sessions = 0; num_finals = 0; num_end = 0; num_disconnects = 0; session_errors = 0; num_changes = 0; eventError = NULL; setup_testbed(NULL); } static void _manager_event(SmlManager *manager, SmlManagerEventType type, SmlSession *session, SmlError *error, void *userdata) { smlTrace(TRACE_ENTRY, "%s(%p, %i, %p, %p, %p)", __func__, manager, type, session, error, userdata); managerTracker *tracker = userdata; smlAssert(manager); smlAssert(userdata); switch (type) { case SML_MANAGER_SESSION_ESTABLISHED: case SML_MANAGER_SESSION_FLUSH: case SML_MANAGER_CONNECT_DONE: break; case SML_MANAGER_DISCONNECT_DONE: g_atomic_int_inc(&num_disconnects); break; case SML_MANAGER_TRANSPORT_ERROR: smlTrace(TRACE_INTERNAL, "%s - error: %s", __func__, smlErrorPrint(&error)); eventError = error; smlErrorRef(&eventError); transport_errors++; break; case SML_MANAGER_SESSION_NEW: smlAssert(session); tracker->session = session; num_sessions++; smlSessionRef(session); break; case SML_MANAGER_SESSION_FINAL: num_finals++; break; case SML_MANAGER_SESSION_END: num_end++; break; case SML_MANAGER_SESSION_ERROR: case SML_MANAGER_SESSION_WARNING: smlTrace(TRACE_INTERNAL, "%s - error: %s", __func__, smlErrorPrint(&error)); if (eventError) smlErrorDeref(&eventError); eventError = error; smlErrorRef(&eventError); session_errors++; break; default: sml_fail_unless(FALSE, "An unexpected manager event %d was received.", type); break; } smlTrace(TRACE_EXIT, "%s", __func__); } static void _recv_init_alert(SmlDsSession *dsession, void *userdata) { smlTrace(TRACE_ENTRY, "%s(%p, %p)", __func__, dsession, userdata); managerTracker *tracker = userdata; if (tracker->ds[0] == smlDsSessionGetServer(dsession)) tracker->dssessions[0] = dsession; else if (tracker->ds[1] == smlDsSessionGetServer(dsession)) tracker->dssessions[1] = dsession; else if (tracker->ds[2] == smlDsSessionGetServer(dsession)) tracker->dssessions[2] = dsession; smlDsSessionRef(dsession); init_alerts_received++; smlTrace(TRACE_EXIT, "%s", __func__); } static SmlBool _recv_alert(SmlDsSession *dsession, SmlAlertType type, const char *last, const char *next, void *userdata) { smlTrace(TRACE_ENTRY, "%s(%p, %i, %s, %s, %p)", __func__, dsession, type, VA_STRING(last), VA_STRING(next), userdata); sml_fail_unless(last != NULL, NULL); sml_fail_unless(next != NULL, NULL); alerts_received++; smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; } static void _alert_reply(SmlSession *dsession, SmlStatus *status, void *userdata) { smlTrace(TRACE_ENTRY, "%s(%p)", __func__, dsession); sml_fail_unless(status != NULL, NULL); if (GPOINTER_TO_INT(userdata) == 1) { sml_fail_unless(smlStatusGetClass(status) == SML_ERRORCLASS_SUCCESS, NULL); } else { sml_fail_unless(smlStatusGetClass(status) == SML_ERRORCLASS_FATAL, NULL); } replies_received++; smlTrace(TRACE_EXIT, "%s", __func__); } static void _sync_reply(SmlSession *dsession, SmlStatus *status, void *userdata) { smlTrace(TRACE_ENTRY, "%s(%p)", __func__, dsession); sml_fail_unless(status != NULL, NULL); if (GPOINTER_TO_INT(userdata) == 1) { sml_fail_unless(smlStatusGetClass(status) == SML_ERRORCLASS_SUCCESS, NULL); } else { sml_fail_unless(smlStatusGetClass(status) == SML_ERRORCLASS_FATAL, NULL); } replies_received++; smlTrace(TRACE_EXIT, "%s", __func__); } static void _add_reply(SmlDsSession *session, SmlStatus *status, const char *newuid, void *userdata) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %s, %p)", __func__, session, status, VA_STRING(newuid), userdata); sml_fail_unless(status != NULL, NULL); sml_fail_unless(smlStatusGetClass(status) == SML_ERRORCLASS_SUCCESS, NULL); sml_fail_unless(GPOINTER_TO_INT(userdata) == 1 || GPOINTER_TO_INT(userdata) == 2, NULL); if (GPOINTER_TO_INT(userdata) == 1) { sml_fail_unless(!strcmp(newuid, "newuid"), NULL); } else { sml_fail_unless(newuid == NULL, NULL); } add_replies_received++; smlTrace(TRACE_EXIT, "%s", __func__); } static void _modify_reply(SmlDsSession *session, SmlStatus *status, const char *newuid, void *userdata) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %s, %p)", __func__, session, status, VA_STRING(newuid), userdata); sml_fail_unless(status != NULL, NULL); sml_fail_unless(smlStatusGetClass(status) == SML_ERRORCLASS_SUCCESS, NULL); sml_fail_unless(GPOINTER_TO_INT(userdata) == 1, NULL); sml_fail_unless(newuid == NULL, NULL); modify_replies_received++; smlTrace(TRACE_EXIT, "%s", __func__); } static void _delete_reply(SmlDsSession *session, SmlStatus *status, const char *newuid, void *userdata) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %s, %p)", __func__, session, status, VA_STRING(newuid), userdata); sml_fail_unless(status != NULL, NULL); sml_fail_unless(smlStatusGetClass(status) == SML_ERRORCLASS_SUCCESS, NULL); sml_fail_unless(GPOINTER_TO_INT(userdata) == 1, NULL); sml_fail_unless(newuid == NULL, NULL); delete_replies_received++; smlTrace(TRACE_EXIT, "%s", __func__); } static void _map_reply(SmlSession *dsession, SmlStatus *status, void *userdata) { smlTrace(TRACE_ENTRY, "%s(%p, %p)", __func__, dsession, userdata); sml_fail_unless(status != NULL, NULL); sml_fail_unless(smlStatusGetClass(status) == SML_ERRORCLASS_SUCCESS, NULL); replies_received++; smlTrace(TRACE_EXIT, "%s", __func__); } static SmlErrorType _recv_san(SmlDsServer *server, SmlSession *session, SmlAlertType type, void *userdata) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p, %p)", __func__, server, session, type, userdata); sml_fail_unless(GPOINTER_TO_INT(userdata) == 1, NULL); sml_fail_unless(type == SML_ALERT_TWO_WAY_BY_SERVER, NULL); sans_received++; smlTrace(TRACE_EXIT, "%s", __func__); return SML_NO_ERROR; } static void _recv_sync(SmlDsSession *dsession, unsigned int numChanges, void *userdata) { smlTrace(TRACE_ENTRY, "%s(%p, %d, %p)", __func__, dsession, numChanges, userdata); sml_fail_unless(numChanges == num_changes, NULL); syncs_received++; smlTrace(TRACE_EXIT, "%s", __func__); } static SmlBool _recv_changes(SmlDsSession *dsession, SmlChangeType type, const char *uid, char *data, unsigned int size, const char *contenttype, void *userdata, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %i, %s, %s, %i, %s, %p, %p)", __func__, dsession, type, VA_STRING(uid), VA_STRING(data), size, VA_STRING(contenttype), userdata, error); if (type == SML_CHANGE_ADD) { adds_received++; sml_fail_unless(!strcmp(uid, "uid"), NULL); sml_fail_unless(!strncmp(data, "data", size), NULL); sml_fail_unless(size == 4, NULL); } else if (type == SML_CHANGE_REPLACE) { modifies_received++; sml_fail_unless(!strcmp(uid, "uid"), NULL); sml_fail_unless(!strncmp(data, "newdata", size), NULL); sml_fail_unless(size == 7, NULL); } else if (type == SML_CHANGE_DELETE) { deletes_received++; sml_fail_unless(!strcmp(uid, "uid"), NULL); sml_fail_unless(!data, NULL); sml_fail_unless(size == 0, NULL); } else { sml_fail_unless(FALSE, "The received SyncML change type %d is unsupported.", type); } if (data) smlSafeCFree(&data); smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; } START_TEST (sync_multi_start) { reset_testbed(); SmlError *error = NULL; SmlTransport *server = smlTransportNew(SML_TRANSPORT_HTTP_SERVER, &error); SmlTransport *client = smlTransportNew(SML_TRANSPORT_HTTP_CLIENT, &error); sml_fail_unless(smlTransportSetConfigOption(client, "URL", "http://127.0.0.1:12012", &error), NULL); sml_fail_unless(smlTransportSetConfigOption(server, "PORT", "12012", &error), NULL); managerTracker *clienttracker = g_malloc0(sizeof(managerTracker)); SmlManager *clientmanager = clienttracker->manager = smlManagerNew(client, &error); smlManagerSetEventCallback(clienttracker->manager, _manager_event, clienttracker); managerTracker *servertracker = g_malloc0(sizeof(managerTracker)); SmlManager *servermanager = servertracker->manager = smlManagerNew(server, &error); smlManagerSetEventCallback(servertracker->manager, _manager_event, servertracker); smlManagerSetLocalMaxMsgSize(servertracker->manager, TEST_DEFAULT_MAX_MSG_SIZE); smlManagerSetLocalMaxObjSize(servertracker->manager, TEST_DEFAULT_MAX_OBJ_SIZE); sml_fail_unless(error == NULL, "%s", smlErrorPrint(&error)); sml_fail_unless(smlTransportInitialize(client, &error), "%s", smlErrorPrint(&error)); sml_fail_unless(smlTransportInitialize(server, &error), "%s", smlErrorPrint(&error)); sml_fail_unless(smlManagerStart(clientmanager, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlManagerStart(servermanager, &error), NULL); sml_fail_unless(error == NULL, NULL); SmlLocation *loc = smlLocationNew("test", NULL, &error); sml_fail_unless(loc != NULL, NULL); sml_fail_unless(error == NULL, NULL); SmlLocation *loc1 = smlLocationNew("test1", NULL, &error); sml_fail_unless(loc1 != NULL, NULL); sml_fail_unless(error == NULL, NULL); SmlLocation *loc2 = smlLocationNew("test2", NULL, &error); sml_fail_unless(loc2 != NULL, NULL); sml_fail_unless(error == NULL, NULL); SmlLocation *loc3 = smlLocationNew("test3", NULL, &error); sml_fail_unless(loc3 != NULL, NULL); sml_fail_unless(error == NULL, NULL); clienttracker->ds[0] = smlDsClientNew(SML_ELEMENT_TEXT_VCARD, loc1, loc1, &error); clienttracker->ds[1] = smlDsClientNew(SML_ELEMENT_TEXT_VCAL, loc2, loc2, &error); clienttracker->ds[2] = smlDsClientNew(SML_ELEMENT_TEXT_PLAIN, loc3, loc3, &error); smlDsServerRegister(clienttracker->ds[0], clientmanager, &error); smlDsServerRegister(clienttracker->ds[1], clientmanager, &error); smlDsServerRegister(clienttracker->ds[2], clientmanager, &error); servertracker->ds[0] = smlDsServerNew(SML_ELEMENT_TEXT_VCARD, loc1, &error); servertracker->ds[1] = smlDsServerNew(SML_ELEMENT_TEXT_VCAL, loc2, &error); servertracker->ds[2] = smlDsServerNew(SML_ELEMENT_TEXT_PLAIN, loc3, &error); smlDsServerSetConnectCallback(servertracker->ds[0], _recv_init_alert, servertracker); smlDsServerSetConnectCallback(servertracker->ds[1], _recv_init_alert, servertracker); smlDsServerSetConnectCallback(servertracker->ds[2], _recv_init_alert, servertracker); smlDsServerRegister(servertracker->ds[0], servermanager, &error); smlDsServerRegister(servertracker->ds[1], servermanager, &error); smlDsServerRegister(servertracker->ds[2], servermanager, &error); smlLocationUnref(loc1); smlLocationUnref(loc2); smlLocationUnref(loc3); /* The authenticator */ /* The authenticator */ SmlAuthenticator *auth = smlAuthNew(&error); smlAuthSetEnable(auth, FALSE); smlAuthRegister(auth, clientmanager, &error); /* The authenticator */ SmlAuthenticator *auth2 = smlAuthNew(&error); smlAuthSetEnable(auth2, FALSE); smlAuthRegister(auth2, servermanager, &error); SmlSession *session = smlSessionNew(SML_SESSION_TYPE_CLIENT, SML_MIMETYPE_XML, SML_VERSION_12, SML_PROTOCOL_SYNCML, loc, loc, NULL, 0, &error); sml_fail_unless(smlManagerSessionAdd(clientmanager, session, NULL, &error), NULL); sml_fail_unless(error == NULL, NULL); smlLocationUnref(loc); clienttracker->dssessions[0] = smlDsServerSendAlert(clienttracker->ds[0], session, SML_ALERT_TWO_WAY, "last", "next", _alert_reply, GINT_TO_POINTER(1), &error); clienttracker->dssessions[1] = smlDsServerSendAlert(clienttracker->ds[1], session, SML_ALERT_TWO_WAY, "last", "next", _alert_reply, GINT_TO_POINTER(1), &error); clienttracker->dssessions[2] = smlDsServerSendAlert(clienttracker->ds[2], session, SML_ALERT_TWO_WAY, "last", "next", _alert_reply, GINT_TO_POINTER(1), &error); sml_fail_unless(smlSessionFlush(session, TRUE, &error), NULL); sml_fail_unless(error == NULL, NULL); while (init_alerts_received < 3 || num_sessions < 2) { smlManagerDispatch(servermanager); smlManagerDispatch(clientmanager); usleep(100); sml_fail_unless(eventError == NULL, "%s", smlErrorPrint(&eventError)); } smlDsSessionGetAlert(servertracker->dssessions[0], _recv_alert, GINT_TO_POINTER(1)); smlDsSessionGetAlert(servertracker->dssessions[1], _recv_alert, GINT_TO_POINTER(1)); smlDsSessionGetAlert(servertracker->dssessions[2], _recv_alert, GINT_TO_POINTER(1)); sml_fail_unless(servertracker->session != NULL, NULL); sml_fail_unless(smlSessionEnd(servertracker->session, &error), NULL); sml_fail_unless(error == NULL, NULL); smlSessionUnref(servertracker->session); /* unref for ref from callback */ smlSessionUnref(clienttracker->session); /* unref for ref from callback */ smlSessionUnref(clienttracker->session); /* unref for smlSessionNew */ while (num_end < 2 || replies_received < 3 || num_finals < 2) { smlManagerDispatch(servermanager); smlManagerDispatch(clientmanager); usleep(100); sml_fail_unless(eventError == NULL, "%s", smlErrorPrint(&eventError)); } sml_fail_unless(init_alerts_received == 3, NULL); sml_fail_unless(alerts_received == 3, NULL); sml_fail_unless(syncs_received == 0, NULL); sml_fail_unless(sync_ends_received == 0, NULL); sml_fail_unless(changes_received == 0, NULL); sml_fail_unless(replies_received == 3, NULL); sml_fail_unless(adds_received == 0, NULL); sml_fail_unless(add_replies_received == 0, NULL); sml_fail_unless(deletes_received == 0, NULL); sml_fail_unless(delete_replies_received == 0, NULL); sml_fail_unless(modifies_received == 0, NULL); sml_fail_unless(modify_replies_received == 0, NULL); sml_fail_unless(transport_errors == 0, NULL); sml_fail_unless(num_sessions == 2, NULL); sml_fail_unless(num_finals == 2, NULL); sml_fail_unless(num_end == 2, NULL); sml_fail_unless(session_errors == 0, NULL); smlDsSessionUnref(clienttracker->dssessions[0]); smlDsSessionUnref(clienttracker->dssessions[1]); smlDsSessionUnref(clienttracker->dssessions[2]); smlDsSessionUnref(servertracker->dssessions[0]); smlDsSessionUnref(servertracker->dssessions[1]); smlDsSessionUnref(servertracker->dssessions[2]); smlDsServerFree(clienttracker->ds[0]); smlDsServerFree(clienttracker->ds[1]); smlDsServerFree(clienttracker->ds[2]); smlDsServerFree(servertracker->ds[0]); smlDsServerFree(servertracker->ds[1]); smlDsServerFree(servertracker->ds[2]); g_free(clienttracker); g_free(servertracker); smlManagerStop(clientmanager); smlManagerStop(servermanager); while(num_disconnects < 2) { smlManagerDispatch(clientmanager); smlManagerDispatch(servermanager); } smlManagerFree(clientmanager); smlManagerFree(servermanager); smlAuthFree(auth); smlAuthFree(auth2); sml_fail_unless(smlTransportFinalize(server, &error), NULL); sml_fail_unless(smlTransportFinalize(client, &error), "%s", smlErrorPrint(&error)); smlTransportFree(server); smlTransportFree(client); } END_TEST /* client -- 3 * alert ---> server * server -- statuses, 3 * alert ---> client * client -- statuses, num * add, num * replace, num * delete ---> server * server -- statuses ---> client */ START_TEST (sync_multi_stress) { reset_testbed(); unsigned int num_items = 10; num_changes = 3 * num_items; SmlError *error = NULL; SmlTransport *server = smlTransportNew(SML_TRANSPORT_HTTP_SERVER, &error); SmlTransport *client = smlTransportNew(SML_TRANSPORT_HTTP_CLIENT, &error); sml_fail_unless(smlTransportSetConfigOption(client, "URL", "http://127.0.0.1:12013", &error), NULL); sml_fail_unless(smlTransportSetConfigOption(server, "PORT", "12013", &error), NULL); managerTracker *clienttracker = g_malloc0(sizeof(managerTracker)); SmlManager *clientmanager = clienttracker->manager = smlManagerNew(client, &error); smlManagerSetEventCallback(clienttracker->manager, _manager_event, clienttracker); managerTracker *servertracker = g_malloc0(sizeof(managerTracker)); SmlManager *servermanager = servertracker->manager = smlManagerNew(server, &error); smlManagerSetEventCallback(servertracker->manager, _manager_event, servertracker); smlManagerSetLocalMaxMsgSize(servertracker->manager, TEST_DEFAULT_MAX_MSG_SIZE); smlManagerSetLocalMaxObjSize(servertracker->manager, TEST_DEFAULT_MAX_OBJ_SIZE); sml_fail_unless(error == NULL, "%s", smlErrorPrint(&error)); sml_fail_unless(smlTransportInitialize(client, &error), "%s", smlErrorPrint(&error)); sml_fail_unless(smlTransportInitialize(server, &error), "%s", smlErrorPrint(&error)); sml_fail_unless(smlManagerStart(clientmanager, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlManagerStart(servermanager, &error), NULL); sml_fail_unless(error == NULL, NULL); SmlLocation *loc = smlLocationNew("test", NULL, &error); sml_fail_unless(loc != NULL, NULL); sml_fail_unless(error == NULL, NULL); SmlLocation *loc1 = smlLocationNew("test1", NULL, &error); sml_fail_unless(loc1 != NULL, NULL); sml_fail_unless(error == NULL, NULL); SmlLocation *loc2 = smlLocationNew("test2", NULL, &error); sml_fail_unless(loc2 != NULL, NULL); sml_fail_unless(error == NULL, NULL); SmlLocation *loc3 = smlLocationNew("test3", NULL, &error); sml_fail_unless(loc3 != NULL, NULL); sml_fail_unless(error == NULL, NULL); clienttracker->ds[0] = smlDsClientNew(SML_ELEMENT_TEXT_VCARD, loc1, loc1, &error); clienttracker->ds[1] = smlDsClientNew(SML_ELEMENT_TEXT_VCAL, loc2, loc2, &error); clienttracker->ds[2] = smlDsClientNew(SML_ELEMENT_TEXT_PLAIN, loc3, loc3, &error); smlDsServerRegister(clienttracker->ds[0], clientmanager, &error); smlDsServerRegister(clienttracker->ds[1], clientmanager, &error); smlDsServerRegister(clienttracker->ds[2], clientmanager, &error); servertracker->ds[0] = smlDsServerNew(SML_ELEMENT_TEXT_VCARD, loc1, &error); servertracker->ds[1] = smlDsServerNew(SML_ELEMENT_TEXT_VCAL, loc2, &error); servertracker->ds[2] = smlDsServerNew(SML_ELEMENT_TEXT_PLAIN, loc3, &error); smlDsServerSetConnectCallback(servertracker->ds[0], _recv_init_alert, servertracker); smlDsServerSetConnectCallback(servertracker->ds[1], _recv_init_alert, servertracker); smlDsServerSetConnectCallback(servertracker->ds[2], _recv_init_alert, servertracker); smlDsServerRegister(servertracker->ds[0], servermanager, &error); smlDsServerRegister(servertracker->ds[1], servermanager, &error); smlDsServerRegister(servertracker->ds[2], servermanager, &error); smlLocationUnref(loc1); smlLocationUnref(loc2); smlLocationUnref(loc3); /* The authenticator */ SmlAuthenticator *auth = smlAuthNew(&error); smlAuthSetEnable(auth, FALSE); smlAuthRegister(auth, clientmanager, &error); /* The authenticator */ SmlAuthenticator *auth2 = smlAuthNew(&error); smlAuthSetEnable(auth2, FALSE); smlAuthRegister(auth2, servermanager, &error); clienttracker->session = smlSessionNew(SML_SESSION_TYPE_CLIENT, SML_MIMETYPE_XML, SML_VERSION_12, SML_PROTOCOL_SYNCML, loc, loc, NULL, 0, &error); sml_fail_unless(smlManagerSessionAdd(clientmanager, clienttracker->session, NULL, &error), NULL); sml_fail_unless(error == NULL, NULL); smlLocationUnref(loc); clienttracker->dssessions[0] = smlDsServerSendAlert(clienttracker->ds[0], clienttracker->session, SML_ALERT_TWO_WAY, "last", "next", _alert_reply, GINT_TO_POINTER(1), &error); clienttracker->dssessions[1] = smlDsServerSendAlert(clienttracker->ds[1], clienttracker->session, SML_ALERT_TWO_WAY, "last", "next", _alert_reply, GINT_TO_POINTER(1), &error); clienttracker->dssessions[2] = smlDsServerSendAlert(clienttracker->ds[2], clienttracker->session, SML_ALERT_TWO_WAY, "last", "next", _alert_reply, GINT_TO_POINTER(1), &error); sml_fail_unless(smlSessionFlush(clienttracker->session, TRUE, &error), NULL); sml_fail_unless(error == NULL, NULL); while (init_alerts_received < 3 || num_sessions < 2) { smlManagerDispatch(servermanager); smlManagerDispatch(clientmanager); usleep(100); sml_fail_unless(eventError == NULL, "%s", smlErrorPrint(&eventError)); } smlDsSessionGetAlert(servertracker->dssessions[0], _recv_alert, GINT_TO_POINTER(1)); smlDsSessionGetAlert(servertracker->dssessions[1], _recv_alert, GINT_TO_POINTER(1)); smlDsSessionGetAlert(servertracker->dssessions[2], _recv_alert, GINT_TO_POINTER(1)); smlDsSessionSendAlert(servertracker->dssessions[0], SML_ALERT_TWO_WAY, "last", "next", _alert_reply, GINT_TO_POINTER(1), &error); smlDsSessionSendAlert(servertracker->dssessions[1], SML_ALERT_TWO_WAY, "last", "next", _alert_reply, GINT_TO_POINTER(1), &error); smlDsSessionSendAlert(servertracker->dssessions[2], SML_ALERT_TWO_WAY, "last", "next", _alert_reply, GINT_TO_POINTER(1), &error); sml_fail_unless(servertracker->session != NULL, NULL); sml_fail_unless(smlSessionFlush(servertracker->session, TRUE, &error), NULL); smlDsSessionGetAlert(clienttracker->dssessions[0], _recv_alert, GINT_TO_POINTER(1)); smlDsSessionGetAlert(clienttracker->dssessions[1], _recv_alert, GINT_TO_POINTER(1)); smlDsSessionGetAlert(clienttracker->dssessions[2], _recv_alert, GINT_TO_POINTER(1)); while (alerts_received < 6) { smlDsSessionDispatch(servertracker->dssessions[0]); smlDsSessionDispatch(servertracker->dssessions[1]); smlDsSessionDispatch(servertracker->dssessions[2]); smlDsSessionDispatch(clienttracker->dssessions[0]); smlDsSessionDispatch(clienttracker->dssessions[1]); smlDsSessionDispatch(clienttracker->dssessions[2]); smlManagerDispatch(servermanager); smlManagerDispatch(clientmanager); usleep(100); sml_fail_unless(eventError == NULL, "%s", smlErrorPrint(&eventError)); } const char *content_types[] = {SML_ELEMENT_TEXT_VCARD, SML_ELEMENT_TEXT_VCAL, SML_ELEMENT_TEXT_PLAIN}; int k = 0; for (k = 0; k < 3; k++) { smlDsSessionSendSync(clienttracker->dssessions[k], num_changes, _sync_reply, GINT_TO_POINTER(1), &error); unsigned int i = 0; for (i = 0; i < num_items; i++) { sml_fail_unless(smlDsSessionQueueChange(clienttracker->dssessions[k], SML_CHANGE_ADD, "uid", "data", 4, content_types[k], _add_reply, GINT_TO_POINTER(2), &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlDsSessionQueueChange(clienttracker->dssessions[k], SML_CHANGE_REPLACE, "uid", "newdata", 7, content_types[k], _modify_reply, GINT_TO_POINTER(1), &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlDsSessionQueueChange(clienttracker->dssessions[k], SML_CHANGE_DELETE, "uid", NULL, 0, content_types[k], _delete_reply, GINT_TO_POINTER(1), &error), NULL); sml_fail_unless(error == NULL, NULL); } smlDsSessionCloseSync(clienttracker->dssessions[k], &error); } sml_fail_unless(smlSessionFlush(clienttracker->session, TRUE, &error), NULL); smlDsSessionGetSync(servertracker->dssessions[0], _recv_sync, GINT_TO_POINTER(1)); smlDsSessionGetSync(servertracker->dssessions[1], _recv_sync, GINT_TO_POINTER(1)); smlDsSessionGetSync(servertracker->dssessions[2], _recv_sync, GINT_TO_POINTER(1)); smlDsSessionGetChanges(servertracker->dssessions[0], _recv_changes, GINT_TO_POINTER(1)); smlDsSessionGetChanges(servertracker->dssessions[1], _recv_changes, GINT_TO_POINTER(1)); smlDsSessionGetChanges(servertracker->dssessions[2], _recv_changes, GINT_TO_POINTER(1)); while (syncs_received < 3 || adds_received < num_items * 3 || deletes_received < num_items * 3 || modifies_received < num_items * 3) { smlDsSessionDispatch(servertracker->dssessions[0]); smlDsSessionDispatch(servertracker->dssessions[1]); smlDsSessionDispatch(servertracker->dssessions[2]); smlDsSessionDispatch(clienttracker->dssessions[0]); smlDsSessionDispatch(clienttracker->dssessions[1]); smlDsSessionDispatch(clienttracker->dssessions[2]); smlManagerDispatch(servermanager); smlManagerDispatch(clientmanager); usleep(100); sml_fail_unless(eventError == NULL, "%s", smlErrorPrint(&eventError)); } sml_fail_unless(servertracker->session != NULL, NULL); sml_fail_unless(smlSessionEnd(servertracker->session, &error), NULL); sml_fail_unless(error == NULL, NULL); smlSessionUnref(servertracker->session); /* unref for ref from callback */ smlSessionUnref(clienttracker->session); /* unref for ref from callback */ smlSessionUnref(clienttracker->session); /* unref for smlSessionNew */ while (num_end < 2 || replies_received < 9 || num_finals < 4) { smlManagerDispatch(servermanager); smlManagerDispatch(clientmanager); usleep(100); sml_fail_unless(eventError == NULL, "%s", smlErrorPrint(&eventError)); } sml_fail_unless(init_alerts_received == 3, NULL); sml_fail_unless(alerts_received == 6, NULL); sml_fail_unless(syncs_received == 3, NULL); sml_fail_unless(sync_ends_received == 0, NULL); sml_fail_unless(changes_received == 0, NULL); sml_fail_unless(replies_received == 9, NULL); sml_fail_unless(adds_received == num_items * 3, NULL); sml_fail_unless(add_replies_received == num_items * 3, NULL); sml_fail_unless(deletes_received == num_items * 3, NULL); sml_fail_unless(delete_replies_received == num_items * 3, NULL); sml_fail_unless(modifies_received == num_items * 3, NULL); sml_fail_unless(modify_replies_received == num_items * 3, NULL); sml_fail_unless(transport_errors == 0, NULL); sml_fail_unless(num_sessions == 2, NULL); sml_fail_unless(num_finals == 4, NULL); sml_fail_unless(num_end == 2, NULL); sml_fail_unless(session_errors == 0, NULL); smlDsSessionUnref(clienttracker->dssessions[0]); smlDsSessionUnref(clienttracker->dssessions[1]); smlDsSessionUnref(clienttracker->dssessions[2]); smlDsSessionUnref(servertracker->dssessions[0]); smlDsSessionUnref(servertracker->dssessions[1]); smlDsSessionUnref(servertracker->dssessions[2]); smlDsServerFree(clienttracker->ds[0]); smlDsServerFree(clienttracker->ds[1]); smlDsServerFree(clienttracker->ds[2]); smlDsServerFree(servertracker->ds[0]); smlDsServerFree(servertracker->ds[1]); smlDsServerFree(servertracker->ds[2]); smlAuthFree(auth); smlAuthFree(auth2); g_free(clienttracker); g_free(servertracker); smlManagerStop(clientmanager); smlManagerStop(servermanager); while(num_disconnects < 2) { smlManagerDispatch(clientmanager); smlManagerDispatch(servermanager); } smlManagerFree(clientmanager); smlManagerFree(servermanager); sml_fail_unless(smlTransportFinalize(server, &error), NULL); sml_fail_unless(smlTransportFinalize(client, &error), "%s", smlErrorPrint(&error)); smlTransportFree(server); smlTransportFree(client); } END_TEST /* client -- 3 * alert ---> server * server -- statuses, 3 * alert ---> client * client -- statuses, num * add, num * replace, num * delete ---> server * server -- statuses, num * add, num * replace, num * delete ---> client * client -- statuses, map ---> server * server -- statuses ---> client */ START_TEST (sync_multi_stress2) { reset_testbed(); unsigned int num_items = 100; num_changes = 3 * num_items; SmlError *error = NULL; SmlTransport *server = smlTransportNew(SML_TRANSPORT_HTTP_SERVER, &error); SmlTransport *client = smlTransportNew(SML_TRANSPORT_HTTP_CLIENT, &error); sml_fail_unless(smlTransportSetConfigOption(client, "URL", "http://127.0.0.1:12014", &error), NULL); sml_fail_unless(smlTransportSetConfigOption(server, "PORT", "12014", &error), NULL); managerTracker *clienttracker = g_malloc0(sizeof(managerTracker)); SmlManager *clientmanager = clienttracker->manager = smlManagerNew(client, &error); smlManagerSetEventCallback(clienttracker->manager, _manager_event, clienttracker); managerTracker *servertracker = g_malloc0(sizeof(managerTracker)); SmlManager *servermanager = servertracker->manager = smlManagerNew(server, &error); smlManagerSetEventCallback(servertracker->manager, _manager_event, servertracker); smlManagerSetLocalMaxMsgSize(servertracker->manager, TEST_DEFAULT_MAX_MSG_SIZE); smlManagerSetLocalMaxObjSize(servertracker->manager, TEST_DEFAULT_MAX_OBJ_SIZE); sml_fail_unless(error == NULL, "%s", smlErrorPrint(&error)); sml_fail_unless(smlTransportInitialize(client, &error), "%s", smlErrorPrint(&error)); sml_fail_unless(smlTransportInitialize(server, &error), "%s", smlErrorPrint(&error)); sml_fail_unless(smlManagerStart(clientmanager, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlManagerStart(servermanager, &error), NULL); sml_fail_unless(error == NULL, NULL); SmlLocation *loc = smlLocationNew("test", NULL, &error); sml_fail_unless(loc != NULL, NULL); sml_fail_unless(error == NULL, NULL); SmlLocation *loc1 = smlLocationNew("test1", NULL, &error); sml_fail_unless(loc1 != NULL, NULL); sml_fail_unless(error == NULL, NULL); SmlLocation *loc2 = smlLocationNew("test2", NULL, &error); sml_fail_unless(loc2 != NULL, NULL); sml_fail_unless(error == NULL, NULL); SmlLocation *loc3 = smlLocationNew("test3", NULL, &error); sml_fail_unless(loc3 != NULL, NULL); sml_fail_unless(error == NULL, NULL); clienttracker->ds[0] = smlDsClientNew(SML_ELEMENT_TEXT_VCARD, loc1, loc1, &error); clienttracker->ds[1] = smlDsClientNew(SML_ELEMENT_TEXT_VCAL, loc2, loc2, &error); clienttracker->ds[2] = smlDsClientNew(SML_ELEMENT_TEXT_PLAIN, loc3, loc3, &error); smlDsServerRegister(clienttracker->ds[0], clientmanager, &error); smlDsServerRegister(clienttracker->ds[1], clientmanager, &error); smlDsServerRegister(clienttracker->ds[2], clientmanager, &error); servertracker->ds[0] = smlDsServerNew(SML_ELEMENT_TEXT_VCARD, loc1, &error); servertracker->ds[1] = smlDsServerNew(SML_ELEMENT_TEXT_VCAL, loc2, &error); servertracker->ds[2] = smlDsServerNew(SML_ELEMENT_TEXT_PLAIN, loc3, &error); smlDsServerSetConnectCallback(servertracker->ds[0], _recv_init_alert, servertracker); smlDsServerSetConnectCallback(servertracker->ds[1], _recv_init_alert, servertracker); smlDsServerSetConnectCallback(servertracker->ds[2], _recv_init_alert, servertracker); smlDsServerRegister(servertracker->ds[0], servermanager, &error); smlDsServerRegister(servertracker->ds[1], servermanager, &error); smlDsServerRegister(servertracker->ds[2], servermanager, &error); smlLocationUnref(loc1); smlLocationUnref(loc2); smlLocationUnref(loc3); /* The authenticator */ SmlAuthenticator *auth = smlAuthNew(&error); smlAuthSetEnable(auth, FALSE); smlAuthRegister(auth, clientmanager, &error); /* The authenticator */ SmlAuthenticator *auth2 = smlAuthNew(&error); smlAuthSetEnable(auth2, FALSE); smlAuthRegister(auth2, servermanager, &error); clienttracker->session = smlSessionNew(SML_SESSION_TYPE_CLIENT, SML_MIMETYPE_XML, SML_VERSION_12, SML_PROTOCOL_SYNCML, loc, loc, NULL, 0, &error); sml_fail_unless(smlManagerSessionAdd(clientmanager, clienttracker->session, NULL, &error), NULL); sml_fail_unless(error == NULL, NULL); smlLocationUnref(loc); clienttracker->dssessions[0] = smlDsServerSendAlert(clienttracker->ds[0], clienttracker->session, SML_ALERT_TWO_WAY, "last", "next", _alert_reply, GINT_TO_POINTER(1), &error); clienttracker->dssessions[1] = smlDsServerSendAlert(clienttracker->ds[1], clienttracker->session, SML_ALERT_TWO_WAY, "last", "next", _alert_reply, GINT_TO_POINTER(1), &error); clienttracker->dssessions[2] = smlDsServerSendAlert(clienttracker->ds[2], clienttracker->session, SML_ALERT_TWO_WAY, "last", "next", _alert_reply, GINT_TO_POINTER(1), &error); sml_fail_unless(smlSessionFlush(clienttracker->session, TRUE, &error), NULL); sml_fail_unless(error == NULL, NULL); while (init_alerts_received < 3 || num_sessions < 2) { smlManagerDispatch(servermanager); smlManagerDispatch(clientmanager); usleep(100); sml_fail_unless(eventError == NULL, "%s", smlErrorPrint(&eventError)); } smlDsSessionGetAlert(servertracker->dssessions[0], _recv_alert, GINT_TO_POINTER(1)); smlDsSessionGetAlert(servertracker->dssessions[1], _recv_alert, GINT_TO_POINTER(1)); smlDsSessionGetAlert(servertracker->dssessions[2], _recv_alert, GINT_TO_POINTER(1)); smlDsSessionSendAlert(servertracker->dssessions[0], SML_ALERT_TWO_WAY, "last", "next", _alert_reply, GINT_TO_POINTER(1), &error); smlDsSessionSendAlert(servertracker->dssessions[1], SML_ALERT_TWO_WAY, "last", "next", _alert_reply, GINT_TO_POINTER(1), &error); smlDsSessionSendAlert(servertracker->dssessions[2], SML_ALERT_TWO_WAY, "last", "next", _alert_reply, GINT_TO_POINTER(1), &error); sml_fail_unless(servertracker->session != NULL, NULL); sml_fail_unless(smlSessionFlush(servertracker->session, TRUE, &error), NULL); smlDsSessionGetAlert(clienttracker->dssessions[0], _recv_alert, GINT_TO_POINTER(1)); smlDsSessionGetAlert(clienttracker->dssessions[1], _recv_alert, GINT_TO_POINTER(1)); smlDsSessionGetAlert(clienttracker->dssessions[2], _recv_alert, GINT_TO_POINTER(1)); while (alerts_received < 6) { smlDsSessionDispatch(servertracker->dssessions[0]); smlDsSessionDispatch(servertracker->dssessions[1]); smlDsSessionDispatch(servertracker->dssessions[2]); smlDsSessionDispatch(clienttracker->dssessions[0]); smlDsSessionDispatch(clienttracker->dssessions[1]); smlDsSessionDispatch(clienttracker->dssessions[2]); smlManagerDispatch(servermanager); smlManagerDispatch(clientmanager); usleep(100); sml_fail_unless(eventError == NULL, "%s", smlErrorPrint(&eventError)); } const char *content_types[] = {SML_ELEMENT_TEXT_VCARD, SML_ELEMENT_TEXT_VCAL, SML_ELEMENT_TEXT_PLAIN}; int k = 0; for (k = 0; k < 3; k++) { smlDsSessionSendSync(clienttracker->dssessions[k], num_changes, _sync_reply, GINT_TO_POINTER(1), &error); unsigned int i = 0; for (i = 0; i < num_items; i++) { sml_fail_unless(smlDsSessionQueueChange(clienttracker->dssessions[k], SML_CHANGE_ADD, "uid", "data", 4, content_types[k], _add_reply, GINT_TO_POINTER(2), &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlDsSessionQueueChange(clienttracker->dssessions[k], SML_CHANGE_REPLACE, "uid", "newdata", 7, content_types[k], _modify_reply, GINT_TO_POINTER(1), &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlDsSessionQueueChange(clienttracker->dssessions[k], SML_CHANGE_DELETE, "uid", NULL, 0, content_types[k], _delete_reply, GINT_TO_POINTER(1), &error), NULL); sml_fail_unless(error == NULL, NULL); } smlDsSessionCloseSync(clienttracker->dssessions[k], &error); } sml_fail_unless(smlSessionFlush(clienttracker->session, TRUE, &error), NULL); smlDsSessionGetSync(servertracker->dssessions[0], _recv_sync, GINT_TO_POINTER(1)); smlDsSessionGetSync(servertracker->dssessions[1], _recv_sync, GINT_TO_POINTER(1)); smlDsSessionGetSync(servertracker->dssessions[2], _recv_sync, GINT_TO_POINTER(1)); smlDsSessionGetChanges(servertracker->dssessions[0], _recv_changes, GINT_TO_POINTER(1)); smlDsSessionGetChanges(servertracker->dssessions[1], _recv_changes, GINT_TO_POINTER(1)); smlDsSessionGetChanges(servertracker->dssessions[2], _recv_changes, GINT_TO_POINTER(1)); while (syncs_received < 3 || adds_received < num_items * 3 || deletes_received < num_items * 3 || modifies_received < num_items * 3) { smlDsSessionDispatch(servertracker->dssessions[0]); smlDsSessionDispatch(servertracker->dssessions[1]); smlDsSessionDispatch(servertracker->dssessions[2]); smlDsSessionDispatch(clienttracker->dssessions[0]); smlDsSessionDispatch(clienttracker->dssessions[1]); smlDsSessionDispatch(clienttracker->dssessions[2]); smlManagerDispatch(servermanager); smlManagerDispatch(clientmanager); usleep(100); sml_fail_unless(eventError == NULL, "%s", smlErrorPrint(&eventError)); } for (k = 0; k < 3; k++) { smlDsSessionSendSync(servertracker->dssessions[k], num_changes, _sync_reply, GINT_TO_POINTER(1), &error); unsigned int i = 0; for (i = 0; i < num_items; i++) { sml_fail_unless(smlDsSessionQueueChange(servertracker->dssessions[k], SML_CHANGE_ADD, "uid", "data", 4, content_types[k], _add_reply, GINT_TO_POINTER(1), &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlDsSessionQueueChange(servertracker->dssessions[k], SML_CHANGE_REPLACE, "uid", "newdata", 7, content_types[k], _modify_reply, GINT_TO_POINTER(1), &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlDsSessionQueueChange(servertracker->dssessions[k], SML_CHANGE_DELETE, "uid", NULL, 0, content_types[k], _delete_reply, GINT_TO_POINTER(1), &error), NULL); sml_fail_unless(error == NULL, NULL); } smlDsSessionCloseSync(servertracker->dssessions[k], &error); } sml_fail_unless(smlSessionFlush(servertracker->session, TRUE, &error), NULL); smlDsSessionGetSync(clienttracker->dssessions[0], _recv_sync, GINT_TO_POINTER(1)); smlDsSessionGetSync(clienttracker->dssessions[1], _recv_sync, GINT_TO_POINTER(1)); smlDsSessionGetSync(clienttracker->dssessions[2], _recv_sync, GINT_TO_POINTER(1)); smlDsSessionGetChanges(clienttracker->dssessions[0], _recv_changes, GINT_TO_POINTER(1)); smlDsSessionGetChanges(clienttracker->dssessions[1], _recv_changes, GINT_TO_POINTER(1)); smlDsSessionGetChanges(clienttracker->dssessions[2], _recv_changes, GINT_TO_POINTER(1)); while (syncs_received < 6 || adds_received < num_items * 6 || deletes_received < num_items * 6 || modifies_received < num_items * 6) { smlDsSessionDispatch(servertracker->dssessions[0]); smlDsSessionDispatch(servertracker->dssessions[1]); smlDsSessionDispatch(servertracker->dssessions[2]); smlDsSessionDispatch(clienttracker->dssessions[0]); smlDsSessionDispatch(clienttracker->dssessions[1]); smlDsSessionDispatch(clienttracker->dssessions[2]); smlManagerDispatch(servermanager); smlManagerDispatch(clientmanager); usleep(100); sml_fail_unless(eventError == NULL, "%s", smlErrorPrint(&eventError)); } unsigned int i = 0; for (i = 0; i < num_items; i++) { sml_fail_unless(smlDsSessionQueueMap(clienttracker->dssessions[0], "uid", "newuid", &error), NULL); sml_fail_unless(smlDsSessionQueueMap(clienttracker->dssessions[1], "uid", "newuid", &error), NULL); sml_fail_unless(smlDsSessionQueueMap(clienttracker->dssessions[2], "uid", "newuid", &error), NULL); } smlDsSessionCloseMap(clienttracker->dssessions[0], _map_reply, GINT_TO_POINTER(1), &error); smlDsSessionCloseMap(clienttracker->dssessions[1], _map_reply, GINT_TO_POINTER(1), &error); smlDsSessionCloseMap(clienttracker->dssessions[2], _map_reply, GINT_TO_POINTER(1), &error); sml_fail_unless(smlSessionFlush(clienttracker->session, TRUE, &error), NULL); while (delete_replies_received < num_items * 6) { smlDsSessionDispatch(servertracker->dssessions[0]); smlDsSessionDispatch(servertracker->dssessions[1]); smlDsSessionDispatch(servertracker->dssessions[2]); smlDsSessionDispatch(clienttracker->dssessions[0]); smlDsSessionDispatch(clienttracker->dssessions[1]); smlDsSessionDispatch(clienttracker->dssessions[2]); smlManagerDispatch(servermanager); smlManagerDispatch(clientmanager); usleep(100); sml_fail_unless(eventError == NULL, "%s", smlErrorPrint(&eventError)); } sml_fail_unless(servertracker->session != NULL, NULL); sml_fail_unless(smlSessionEnd(servertracker->session, &error), NULL); sml_fail_unless(error == NULL, NULL); smlSessionUnref(servertracker->session); /* unref for event SESSION_NEW */ smlSessionUnref(clienttracker->session); /* unref for event SESSION_NEW */ smlSessionUnref(clienttracker->session); /* unref for smlSessionNew */ while (num_end < 2 || replies_received < 15 || num_finals < 6) { smlManagerDispatch(servermanager); smlManagerDispatch(clientmanager); usleep(100); sml_fail_unless(eventError == NULL, "%s", smlErrorPrint(&eventError)); } sml_fail_unless(init_alerts_received == 3, NULL); sml_fail_unless(alerts_received == 6, NULL); sml_fail_unless(syncs_received == 6, NULL); sml_fail_unless(sync_ends_received == 0, NULL); sml_fail_unless(changes_received == 0, NULL); sml_fail_unless(replies_received == 15, NULL); sml_fail_unless(adds_received == num_items * 6, NULL); sml_fail_unless(add_replies_received == num_items * 6, NULL); sml_fail_unless(deletes_received == num_items * 6, NULL); sml_fail_unless(delete_replies_received == num_items * 6, NULL); sml_fail_unless(modifies_received == num_items * 6, NULL); sml_fail_unless(modify_replies_received == num_items * 6, NULL); sml_fail_unless(transport_errors == 0, NULL); sml_fail_unless(num_sessions == 2, NULL); sml_fail_unless(num_finals == 6, NULL); sml_fail_unless(num_end == 2, NULL); sml_fail_unless(session_errors == 0, NULL); smlDsSessionUnref(clienttracker->dssessions[0]); smlDsSessionUnref(clienttracker->dssessions[1]); smlDsSessionUnref(clienttracker->dssessions[2]); smlDsSessionUnref(servertracker->dssessions[0]); smlDsSessionUnref(servertracker->dssessions[1]); smlDsSessionUnref(servertracker->dssessions[2]); smlDsServerFree(clienttracker->ds[0]); smlDsServerFree(clienttracker->ds[1]); smlDsServerFree(clienttracker->ds[2]); smlDsServerFree(servertracker->ds[0]); smlDsServerFree(servertracker->ds[1]); smlDsServerFree(servertracker->ds[2]); smlAuthFree(auth); smlAuthFree(auth2); g_free(clienttracker); g_free(servertracker); smlManagerStop(clientmanager); smlManagerStop(servermanager); while(num_disconnects < 2) { smlManagerDispatch(clientmanager); smlManagerDispatch(servermanager); } smlManagerFree(clientmanager); smlManagerFree(servermanager); sml_fail_unless(smlTransportFinalize(server, &error), NULL); sml_fail_unless(smlTransportFinalize(client, &error), "%s", smlErrorPrint(&error)); smlTransportFree(server); smlTransportFree(client); } END_TEST /* client -- 3 * alert ---> server * server -- statuses, 3 * alert ---> client * client -- statuses, num * add, num * replace, num * delete ---> server * server -- statuses ---> client */ START_TEST (sync_multi_conf_from_devinf) { reset_testbed(); unsigned int num_items = 100; num_changes = 3 * num_items; SmlError *error = NULL; SmlTransport *server = smlTransportNew(SML_TRANSPORT_HTTP_SERVER, &error); SmlTransport *client = smlTransportNew(SML_TRANSPORT_HTTP_CLIENT, &error); sml_fail_unless(smlTransportSetConfigOption(client, "URL", "http://127.0.0.1:12015", &error), NULL); sml_fail_unless(smlTransportSetConfigOption(server, "PORT", "12015", &error), NULL); managerTracker *clienttracker = g_malloc0(sizeof(managerTracker)); SmlManager *clientmanager = clienttracker->manager = smlManagerNew(client, &error); smlManagerSetEventCallback(clienttracker->manager, _manager_event, clienttracker); managerTracker *servertracker = g_malloc0(sizeof(managerTracker)); SmlManager *servermanager = servertracker->manager = smlManagerNew(server, &error); smlManagerSetEventCallback(servertracker->manager, _manager_event, servertracker); smlManagerSetLocalMaxMsgSize(servertracker->manager, TEST_DEFAULT_MAX_MSG_SIZE); smlManagerSetLocalMaxObjSize(servertracker->manager, TEST_DEFAULT_MAX_OBJ_SIZE); sml_fail_unless(error == NULL, "%s", smlErrorPrint(&error)); sml_fail_unless(smlTransportInitialize(client, &error), "%s", smlErrorPrint(&error)); sml_fail_unless(smlTransportInitialize(server, &error), "%s", smlErrorPrint(&error)); sml_fail_unless(smlManagerStart(clientmanager, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlManagerStart(servermanager, &error), NULL); sml_fail_unless(error == NULL, NULL); SmlLocation *loc = smlLocationNew("test", NULL, &error); sml_fail_unless(loc != NULL, NULL); sml_fail_unless(error == NULL, NULL); SmlLocation *loc1 = smlLocationNew("test1", NULL, &error); sml_fail_unless(loc1 != NULL, NULL); sml_fail_unless(error == NULL, NULL); SmlLocation *loc2 = smlLocationNew("test2", NULL, &error); sml_fail_unless(loc2 != NULL, NULL); sml_fail_unless(error == NULL, NULL); SmlLocation *loc3 = smlLocationNew("test3", NULL, &error); sml_fail_unless(loc3 != NULL, NULL); sml_fail_unless(error == NULL, NULL); clienttracker->ds[0] = smlDsClientNew(SML_ELEMENT_TEXT_VCARD, loc1, loc1, &error); clienttracker->ds[1] = smlDsClientNew(SML_ELEMENT_TEXT_VCAL, loc2, loc2, &error); clienttracker->ds[2] = smlDsClientNew(SML_ELEMENT_TEXT_PLAIN, loc3, loc3, &error); smlDsServerRegister(clienttracker->ds[0], clientmanager, &error); smlDsServerRegister(clienttracker->ds[1], clientmanager, &error); smlDsServerRegister(clienttracker->ds[2], clientmanager, &error); servertracker->ds[0] = smlDsServerNew(SML_ELEMENT_TEXT_VCARD, loc1, &error); servertracker->ds[1] = smlDsServerNew(SML_ELEMENT_TEXT_VCAL, loc2, &error); servertracker->ds[2] = smlDsServerNew(SML_ELEMENT_TEXT_PLAIN, loc3, &error); smlDsServerSetConnectCallback(servertracker->ds[0], _recv_init_alert, servertracker); smlDsServerSetConnectCallback(servertracker->ds[1], _recv_init_alert, servertracker); smlDsServerSetConnectCallback(servertracker->ds[2], _recv_init_alert, servertracker); smlDsServerRegister(servertracker->ds[0], servermanager, &error); smlDsServerRegister(servertracker->ds[1], servermanager, &error); smlDsServerRegister(servertracker->ds[2], servermanager, &error); /* The devinf obj */ SmlDevInf *devinf = smlDevInfNew("LibSyncmML", SML_DEVINF_DEVTYPE_WORKSTATION, &error); smlDevInfSetSupportsNumberOfChanges(devinf, TRUE); smlDevInfSetSupportsLargeObjs(devinf, FALSE); smlDevInfSetSupportsUTC(devinf, FALSE); SmlDevInfAgent *clientagent = smlDevInfAgentNew(devinf, &error); smlDevInfAgentRegister(clientagent, clientmanager, &error); /* And we also add the devinfo to the devinf agent */ SmlDevInfDataStore *datastore = smlDevInfDataStoreNew(smlLocationGetURI(loc1), &error); smlDevInfDataStoreSetRxPref(datastore, SML_ELEMENT_TEXT_VCARD, "2.1"); smlDevInfDataStoreSetTxPref(datastore, SML_ELEMENT_TEXT_VCARD, "2.1"); smlDevInfDataStoreSetSyncCap(datastore, SML_DEVINF_SYNCTYPE_TWO_WAY, TRUE); smlDevInfDataStoreSetSyncCap(datastore, SML_DEVINF_SYNCTYPE_SLOW_SYNC, TRUE); smlDevInfDataStoreSetSyncCap(datastore, SML_DEVINF_SYNCTYPE_SERVER_ALERTED_SYNC, TRUE); smlDevInfAddDataStore(devinf, datastore); datastore = smlDevInfDataStoreNew(smlLocationGetURI(loc2), &error); smlDevInfDataStoreSetRxPref(datastore, SML_ELEMENT_TEXT_VCAL, "2.0"); smlDevInfDataStoreSetTxPref(datastore, SML_ELEMENT_TEXT_VCAL, "2.0"); smlDevInfDataStoreSetSyncCap(datastore, SML_DEVINF_SYNCTYPE_TWO_WAY, TRUE); smlDevInfDataStoreSetSyncCap(datastore, SML_DEVINF_SYNCTYPE_SLOW_SYNC, TRUE); smlDevInfDataStoreSetSyncCap(datastore, SML_DEVINF_SYNCTYPE_SERVER_ALERTED_SYNC, TRUE); smlDevInfAddDataStore(devinf, datastore); datastore = smlDevInfDataStoreNew(smlLocationGetURI(loc3), &error); smlDevInfDataStoreSetRxPref(datastore, SML_ELEMENT_TEXT_PLAIN, "1.0"); smlDevInfDataStoreSetTxPref(datastore, SML_ELEMENT_TEXT_PLAIN, "1.0"); smlDevInfDataStoreSetSyncCap(datastore, SML_DEVINF_SYNCTYPE_TWO_WAY, TRUE); smlDevInfDataStoreSetSyncCap(datastore, SML_DEVINF_SYNCTYPE_SLOW_SYNC, TRUE); smlDevInfDataStoreSetSyncCap(datastore, SML_DEVINF_SYNCTYPE_SERVER_ALERTED_SYNC, TRUE); smlDevInfAddDataStore(devinf, datastore); devinf = smlDevInfNew("LibSyncmML", SML_DEVINF_DEVTYPE_SERVER, &error); smlDevInfSetSupportsNumberOfChanges(devinf, TRUE); smlDevInfSetSupportsLargeObjs(devinf, TRUE); smlDevInfSetSupportsUTC(devinf, FALSE); SmlDevInfAgent *serveragent = smlDevInfAgentNew(devinf, &error); smlDevInfAgentRegister(serveragent, servermanager, &error); datastore = smlDevInfDataStoreNew(smlLocationGetURI(loc1), &error); smlDevInfDataStoreSetRxPref(datastore, SML_ELEMENT_TEXT_VCARD, "2.1"); smlDevInfDataStoreSetTxPref(datastore, SML_ELEMENT_TEXT_VCARD, "2.1"); smlDevInfDataStoreSetSyncCap(datastore, SML_DEVINF_SYNCTYPE_TWO_WAY, TRUE); smlDevInfDataStoreSetSyncCap(datastore, SML_DEVINF_SYNCTYPE_SLOW_SYNC, TRUE); smlDevInfDataStoreSetSyncCap(datastore, SML_DEVINF_SYNCTYPE_SERVER_ALERTED_SYNC, TRUE); smlDevInfAddDataStore(devinf, datastore); datastore = smlDevInfDataStoreNew(smlLocationGetURI(loc2), &error); smlDevInfDataStoreSetRxPref(datastore, SML_ELEMENT_TEXT_VCAL, "2.0"); smlDevInfDataStoreSetTxPref(datastore, SML_ELEMENT_TEXT_VCAL, "2.0"); smlDevInfDataStoreSetSyncCap(datastore, SML_DEVINF_SYNCTYPE_TWO_WAY, TRUE); smlDevInfDataStoreSetSyncCap(datastore, SML_DEVINF_SYNCTYPE_SLOW_SYNC, TRUE); smlDevInfDataStoreSetSyncCap(datastore, SML_DEVINF_SYNCTYPE_SERVER_ALERTED_SYNC, TRUE); smlDevInfAddDataStore(devinf, datastore); datastore = smlDevInfDataStoreNew(smlLocationGetURI(loc3), &error); smlDevInfDataStoreSetRxPref(datastore, SML_ELEMENT_TEXT_PLAIN, "1.0"); smlDevInfDataStoreSetTxPref(datastore, SML_ELEMENT_TEXT_PLAIN, "1.0"); smlDevInfDataStoreSetSyncCap(datastore, SML_DEVINF_SYNCTYPE_TWO_WAY, TRUE); smlDevInfDataStoreSetSyncCap(datastore, SML_DEVINF_SYNCTYPE_SLOW_SYNC, TRUE); smlDevInfDataStoreSetSyncCap(datastore, SML_DEVINF_SYNCTYPE_SERVER_ALERTED_SYNC, TRUE); smlDevInfAddDataStore(devinf, datastore); smlLocationUnref(loc1); smlLocationUnref(loc2); smlLocationUnref(loc3); /* The authenticator */ SmlAuthenticator *auth = smlAuthNew(&error); smlAuthSetEnable(auth, FALSE); smlAuthRegister(auth, clientmanager, &error); /* The authenticator */ SmlAuthenticator *auth2 = smlAuthNew(&error); smlAuthSetEnable(auth2, FALSE); smlAuthRegister(auth2, servermanager, &error); clienttracker->session = smlSessionNew(SML_SESSION_TYPE_CLIENT, SML_MIMETYPE_XML, SML_VERSION_12, SML_PROTOCOL_SYNCML, loc, loc, NULL, 0, &error); smlSessionSetLocalMaxMsgSize(clienttracker->session, TEST_DEFAULT_MAX_MSG_SIZE); sml_fail_unless(smlSessionGetRemoteMaxObjSize(clienttracker->session) == 0, NULL); smlSessionSetLocalMaxObjSize(clienttracker->session, TEST_DEFAULT_MAX_OBJ_SIZE); sml_fail_unless(smlSessionGetLocalMaxObjSize(clienttracker->session) == TEST_DEFAULT_MAX_OBJ_SIZE, NULL); smlDevInfConfigureSession(devinf, clienttracker->session); sml_fail_unless(smlManagerSessionAdd(clientmanager, clienttracker->session, NULL, &error), NULL); sml_fail_unless(error == NULL, NULL); smlLocationUnref(loc); clienttracker->dssessions[0] = smlDsServerSendAlert(clienttracker->ds[0], clienttracker->session, SML_ALERT_TWO_WAY, "last", "next", _alert_reply, GINT_TO_POINTER(1), &error); clienttracker->dssessions[1] = smlDsServerSendAlert(clienttracker->ds[1], clienttracker->session, SML_ALERT_TWO_WAY, "last", "next", _alert_reply, GINT_TO_POINTER(1), &error); clienttracker->dssessions[2] = smlDsServerSendAlert(clienttracker->ds[2], clienttracker->session, SML_ALERT_TWO_WAY, "last", "next", _alert_reply, GINT_TO_POINTER(1), &error); sml_fail_unless(smlDevInfAgentSendDevInf(clientagent, clienttracker->session, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlSessionFlush(clienttracker->session, TRUE, &error), NULL); sml_fail_unless(error == NULL, NULL); while (init_alerts_received < 3 || num_sessions < 2) { smlManagerDispatch(servermanager); smlManagerDispatch(clientmanager); usleep(100); sml_fail_unless(eventError == NULL, "%s", smlErrorPrint(&eventError)); } sml_fail_unless(smlSessionGetRemoteMaxMsgSize(servertracker->session) == TEST_DEFAULT_MAX_MSG_SIZE, NULL); sml_fail_unless(smlSessionGetRemoteMaxObjSize(servertracker->session) == TEST_DEFAULT_MAX_OBJ_SIZE, "%u", smlSessionGetRemoteMaxObjSize(servertracker->session)); smlSessionSetLocalMaxMsgSize(servertracker->session, TEST_DEFAULT_MAX_MSG_SIZE); smlSessionSetLocalMaxObjSize(servertracker->session, TEST_DEFAULT_MAX_OBJ_SIZE); smlDsSessionGetAlert(servertracker->dssessions[0], _recv_alert, GINT_TO_POINTER(1)); smlDsSessionGetAlert(servertracker->dssessions[1], _recv_alert, GINT_TO_POINTER(1)); smlDsSessionGetAlert(servertracker->dssessions[2], _recv_alert, GINT_TO_POINTER(1)); while (alerts_received < 3 || !smlDevInfAgentGetSessionDevInf(serveragent, servertracker->session)) { smlDsSessionDispatch(servertracker->dssessions[0]); smlDsSessionDispatch(servertracker->dssessions[1]); smlDsSessionDispatch(servertracker->dssessions[2]); usleep(100); sml_fail_unless(eventError == NULL, "%s", smlErrorPrint(&eventError)); } SmlDevInf *recvClientDevInf = smlDevInfAgentGetSessionDevInf(serveragent, servertracker->session); sml_fail_unless(recvClientDevInf != NULL, NULL); sml_fail_unless(smlDevInfNumDataStores(recvClientDevInf) == 3, NULL); sml_fail_unless(smlDevInfSupportsNumberOfChanges(recvClientDevInf) == TRUE, NULL); sml_fail_unless(smlDevInfSupportsLargeObjs(recvClientDevInf) == FALSE, NULL); sml_fail_unless(smlDevInfSupportsUTC(recvClientDevInf) == FALSE, NULL); sml_fail_unless(smlDevInfAgentSendDevInf(serveragent, servertracker->session, &error), "%s", smlErrorPrint(&error)); sml_fail_unless(error == NULL, "%s", smlErrorPrint(&error)); smlDsSessionSendAlert(servertracker->dssessions[0], SML_ALERT_TWO_WAY, "last", "next", _alert_reply, GINT_TO_POINTER(1), &error); smlDsSessionSendAlert(servertracker->dssessions[1], SML_ALERT_TWO_WAY, "last", "next", _alert_reply, GINT_TO_POINTER(1), &error); smlDsSessionSendAlert(servertracker->dssessions[2], SML_ALERT_TWO_WAY, "last", "next", _alert_reply, GINT_TO_POINTER(1), &error); sml_fail_unless(servertracker->session != NULL, NULL); sml_fail_unless(smlSessionFlush(servertracker->session, TRUE, &error), NULL); smlDsSessionGetAlert(clienttracker->dssessions[0], _recv_alert, GINT_TO_POINTER(1)); smlDsSessionGetAlert(clienttracker->dssessions[1], _recv_alert, GINT_TO_POINTER(1)); smlDsSessionGetAlert(clienttracker->dssessions[2], _recv_alert, GINT_TO_POINTER(1)); while (alerts_received < 6) { smlDsSessionDispatch(servertracker->dssessions[0]); smlDsSessionDispatch(servertracker->dssessions[1]); smlDsSessionDispatch(servertracker->dssessions[2]); smlDsSessionDispatch(clienttracker->dssessions[0]); smlDsSessionDispatch(clienttracker->dssessions[1]); smlDsSessionDispatch(clienttracker->dssessions[2]); smlManagerDispatch(servermanager); smlManagerDispatch(clientmanager); usleep(100); sml_fail_unless(eventError == NULL, "%s", smlErrorPrint(&eventError)); } sml_fail_unless(smlSessionGetRemoteMaxMsgSize(clienttracker->session) == TEST_DEFAULT_MAX_MSG_SIZE, NULL); sml_fail_unless(smlSessionGetRemoteMaxObjSize(servertracker->session) == TEST_DEFAULT_MAX_OBJ_SIZE, NULL); SmlDevInf *recvServerDevInf = smlDevInfAgentGetSessionDevInf(clientagent, clienttracker->session); sml_fail_unless(recvServerDevInf != NULL, NULL); sml_fail_unless(smlDevInfNumDataStores(recvServerDevInf) == 3, NULL); sml_fail_unless(smlDevInfSupportsNumberOfChanges(recvServerDevInf) == TRUE, NULL); sml_fail_unless(smlDevInfSupportsLargeObjs(recvServerDevInf) == TRUE, NULL); sml_fail_unless(smlDevInfSupportsUTC(recvServerDevInf) == FALSE, NULL); const char *content_types[] = {SML_ELEMENT_TEXT_VCARD, SML_ELEMENT_TEXT_VCAL, SML_ELEMENT_TEXT_PLAIN}; int k = 0; for (k = 0; k < 3; k++) { smlDsSessionSendSync(clienttracker->dssessions[k], num_changes, _sync_reply, GINT_TO_POINTER(1), &error); unsigned int i = 0; for (i = 0; i < num_items; i++) { sml_fail_unless(smlDsSessionQueueChange(clienttracker->dssessions[k], SML_CHANGE_ADD, "uid", "data", 4, content_types[k], _add_reply, GINT_TO_POINTER(2), &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlDsSessionQueueChange(clienttracker->dssessions[k], SML_CHANGE_REPLACE, "uid", "newdata", 7, content_types[k], _modify_reply, GINT_TO_POINTER(1), &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlDsSessionQueueChange(clienttracker->dssessions[k], SML_CHANGE_DELETE, "uid", NULL, 0, content_types[k], _delete_reply, GINT_TO_POINTER(1), &error), NULL); sml_fail_unless(error == NULL, NULL); } smlDsSessionCloseSync(clienttracker->dssessions[k], &error); } sml_fail_unless(smlSessionFlush(clienttracker->session, TRUE, &error), NULL); smlDsSessionGetSync(servertracker->dssessions[0], _recv_sync, GINT_TO_POINTER(1)); smlDsSessionGetSync(servertracker->dssessions[1], _recv_sync, GINT_TO_POINTER(1)); smlDsSessionGetSync(servertracker->dssessions[2], _recv_sync, GINT_TO_POINTER(1)); smlDsSessionGetChanges(servertracker->dssessions[0], _recv_changes, GINT_TO_POINTER(1)); smlDsSessionGetChanges(servertracker->dssessions[1], _recv_changes, GINT_TO_POINTER(1)); smlDsSessionGetChanges(servertracker->dssessions[2], _recv_changes, GINT_TO_POINTER(1)); while (syncs_received < 3 || adds_received < num_items * 3 || deletes_received < num_items * 3 || modifies_received < num_items * 3) { smlDsSessionDispatch(servertracker->dssessions[0]); smlDsSessionDispatch(servertracker->dssessions[1]); smlDsSessionDispatch(servertracker->dssessions[2]); smlDsSessionDispatch(clienttracker->dssessions[0]); smlDsSessionDispatch(clienttracker->dssessions[1]); smlDsSessionDispatch(clienttracker->dssessions[2]); smlManagerDispatch(servermanager); smlManagerDispatch(clientmanager); usleep(100); sml_fail_unless(eventError == NULL, "%s", smlErrorPrint(&eventError)); } for (k = 0; k < 3; k++) { smlDsSessionSendSync(servertracker->dssessions[k], num_changes, _sync_reply, GINT_TO_POINTER(1), &error); unsigned int i = 0; for (i = 0; i < num_items; i++) { sml_fail_unless(smlDsSessionQueueChange(servertracker->dssessions[k], SML_CHANGE_ADD, "uid", "data", 4, content_types[k], _add_reply, GINT_TO_POINTER(1), &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlDsSessionQueueChange(servertracker->dssessions[k], SML_CHANGE_REPLACE, "uid", "newdata", 7, content_types[k], _modify_reply, GINT_TO_POINTER(1), &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlDsSessionQueueChange(servertracker->dssessions[k], SML_CHANGE_DELETE, "uid", NULL, 0, content_types[k], _delete_reply, GINT_TO_POINTER(1), &error), NULL); sml_fail_unless(error == NULL, NULL); } smlDsSessionCloseSync(servertracker->dssessions[k], &error); } sml_fail_unless(smlSessionFlush(servertracker->session, TRUE, &error), NULL); smlDsSessionGetSync(clienttracker->dssessions[0], _recv_sync, GINT_TO_POINTER(1)); smlDsSessionGetSync(clienttracker->dssessions[1], _recv_sync, GINT_TO_POINTER(1)); smlDsSessionGetSync(clienttracker->dssessions[2], _recv_sync, GINT_TO_POINTER(1)); smlDsSessionGetChanges(clienttracker->dssessions[0], _recv_changes, GINT_TO_POINTER(1)); smlDsSessionGetChanges(clienttracker->dssessions[1], _recv_changes, GINT_TO_POINTER(1)); smlDsSessionGetChanges(clienttracker->dssessions[2], _recv_changes, GINT_TO_POINTER(1)); while (syncs_received < 6 || adds_received < num_items * 6 || deletes_received < num_items * 6 || modifies_received < num_items * 6) { smlDsSessionDispatch(servertracker->dssessions[0]); smlDsSessionDispatch(servertracker->dssessions[1]); smlDsSessionDispatch(servertracker->dssessions[2]); smlDsSessionDispatch(clienttracker->dssessions[0]); smlDsSessionDispatch(clienttracker->dssessions[1]); smlDsSessionDispatch(clienttracker->dssessions[2]); smlManagerDispatch(servermanager); smlManagerDispatch(clientmanager); usleep(100); sml_fail_unless(eventError == NULL, "%s", smlErrorPrint(&eventError)); } unsigned int i = 0; for (i = 0; i < num_items; i++) { sml_fail_unless(smlDsSessionQueueMap(clienttracker->dssessions[0], "uid", "newuid", &error), NULL); sml_fail_unless(smlDsSessionQueueMap(clienttracker->dssessions[1], "uid", "newuid", &error), NULL); sml_fail_unless(smlDsSessionQueueMap(clienttracker->dssessions[2], "uid", "newuid", &error), NULL); } smlDsSessionCloseMap(clienttracker->dssessions[0], _map_reply, GINT_TO_POINTER(1), &error); smlDsSessionCloseMap(clienttracker->dssessions[1], _map_reply, GINT_TO_POINTER(1), &error); smlDsSessionCloseMap(clienttracker->dssessions[2], _map_reply, GINT_TO_POINTER(1), &error); sml_fail_unless(smlSessionFlush(clienttracker->session, TRUE, &error), NULL); while (delete_replies_received < num_items * 6) { smlDsSessionDispatch(servertracker->dssessions[0]); smlDsSessionDispatch(servertracker->dssessions[1]); smlDsSessionDispatch(servertracker->dssessions[2]); smlDsSessionDispatch(clienttracker->dssessions[0]); smlDsSessionDispatch(clienttracker->dssessions[1]); smlDsSessionDispatch(clienttracker->dssessions[2]); smlManagerDispatch(servermanager); smlManagerDispatch(clientmanager); usleep(100); sml_fail_unless(eventError == NULL, "%s", smlErrorPrint(&eventError)); } sml_fail_unless(smlSessionGetRemoteMaxMsgSize(servertracker->session) == TEST_DEFAULT_MAX_MSG_SIZE, NULL); sml_fail_unless(smlSessionGetRemoteMaxObjSize(servertracker->session) == TEST_DEFAULT_MAX_OBJ_SIZE, NULL); sml_fail_unless(smlSessionGetRemoteMaxMsgSize(clienttracker->session) == TEST_DEFAULT_MAX_MSG_SIZE, NULL); sml_fail_unless(smlSessionGetRemoteMaxObjSize(clienttracker->session) == TEST_DEFAULT_MAX_OBJ_SIZE, NULL); sml_fail_unless(servertracker->session != NULL, NULL); sml_fail_unless(smlSessionEnd(servertracker->session, &error), NULL); sml_fail_unless(error == NULL, NULL); smlSessionUnref(servertracker->session); /* unref from ref at callback */ smlSessionUnref(clienttracker->session); /* unref from ref at callback */ smlSessionUnref(clienttracker->session); /* unref from smlSessionNew */ while (num_end < 2 || replies_received < 15 || num_finals < 6) { smlManagerDispatch(servermanager); smlManagerDispatch(clientmanager); usleep(100); sml_fail_unless(eventError == NULL, "%s", smlErrorPrint(&eventError)); } sml_fail_unless(init_alerts_received == 3, NULL); sml_fail_unless(alerts_received == 6, NULL); sml_fail_unless(syncs_received == 6, NULL); sml_fail_unless(sync_ends_received == 0, NULL); sml_fail_unless(changes_received == 0, NULL); sml_fail_unless(replies_received == 15, NULL); sml_fail_unless(adds_received == num_items * 6, NULL); sml_fail_unless(add_replies_received == num_items * 6, NULL); sml_fail_unless(deletes_received == num_items * 6, NULL); sml_fail_unless(delete_replies_received == num_items * 6, NULL); sml_fail_unless(modifies_received == num_items * 6, NULL); sml_fail_unless(modify_replies_received == num_items * 6, NULL); sml_fail_unless(transport_errors == 0, NULL); sml_fail_unless(num_sessions == 2, NULL); sml_fail_unless(num_finals == 6, NULL); sml_fail_unless(num_end == 2, NULL); sml_fail_unless(session_errors == 0, NULL); smlDsSessionUnref(clienttracker->dssessions[0]); smlDsSessionUnref(clienttracker->dssessions[1]); smlDsSessionUnref(clienttracker->dssessions[2]); smlDsSessionUnref(servertracker->dssessions[0]); smlDsSessionUnref(servertracker->dssessions[1]); smlDsSessionUnref(servertracker->dssessions[2]); smlDsServerFree(clienttracker->ds[0]); smlDsServerFree(clienttracker->ds[1]); smlDsServerFree(clienttracker->ds[2]); smlDsServerFree(servertracker->ds[0]); smlDsServerFree(servertracker->ds[1]); smlDsServerFree(servertracker->ds[2]); smlAuthFree(auth); smlAuthFree(auth2); g_free(clienttracker); g_free(servertracker); smlManagerStop(clientmanager); smlManagerStop(servermanager); while(num_disconnects < 2) { smlManagerDispatch(clientmanager); smlManagerDispatch(servermanager); } smlManagerFree(clientmanager); smlManagerFree(servermanager); sml_fail_unless(smlTransportFinalize(server, &error), NULL); sml_fail_unless(smlTransportFinalize(client, &error), "%s", smlErrorPrint(&error)); smlTransportFree(server); smlTransportFree(client); smlDevInfAgentFree(clientagent); smlDevInfAgentFree(serveragent); } END_TEST #ifdef ENABLE_OBEX #ifdef ENABLE_OPENOBEX_TCP START_TEST (sync_send_san) { reset_testbed(); unsigned int num_items = 10; num_changes = 3 * num_items; SmlError *error = NULL; /* The OMA DS client is an OBEX server. */ SmlTransport *client = smlTransportNew(SML_TRANSPORT_OBEX_SERVER, &error); sml_fail_unless(smlTransportSetConnectionType(client, SML_TRANSPORT_CONNECTION_TYPE_NET, &error), NULL); sml_fail_unless(smlTransportSetConfigOption(client, "PORT", "12010", &error), "%s", smlErrorPrint(&error)); /* The OMA DS server is an OBEX client. */ SmlTransport *server = smlTransportNew(SML_TRANSPORT_OBEX_CLIENT, &error); sml_fail_unless(smlTransportSetConnectionType(server, SML_TRANSPORT_CONNECTION_TYPE_NET, &error), "%s", smlErrorPrint(&error)); sml_fail_unless(smlTransportSetConfigOption(server, "PORT", "12010", &error), "%s", smlErrorPrint(&error)); sml_fail_unless(smlTransportSetConfigOption(server, "URL", "127.0.0.1", &error), "%s", smlErrorPrint(&error)); managerTracker *clienttracker = g_malloc0(sizeof(managerTracker)); SmlManager *clientmanager = clienttracker->manager = smlManagerNew(client, &error); smlManagerSetEventCallback(clienttracker->manager, _manager_event, clienttracker); managerTracker *servertracker = g_malloc0(sizeof(managerTracker)); SmlManager *servermanager = servertracker->manager = smlManagerNew(server, &error); smlManagerSetEventCallback(servertracker->manager, _manager_event, servertracker); smlManagerSetLocalMaxMsgSize(servertracker->manager, TEST_DEFAULT_MAX_MSG_SIZE); smlManagerSetLocalMaxObjSize(servertracker->manager, TEST_DEFAULT_MAX_OBJ_SIZE); sml_fail_unless(smlManagerStart(clientmanager, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlManagerStart(servermanager, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlTransportInitialize(client, &error), "%s", smlErrorPrint(&error)); sml_fail_unless(smlTransportInitialize(server, &error), "%s", smlErrorPrint(&error)); SmlLocation *loc = smlLocationNew("test", NULL, &error); sml_fail_unless(loc != NULL, NULL); sml_fail_unless(error == NULL, NULL); SmlLocation *loc1 = smlLocationNew("test1", NULL, &error); sml_fail_unless(loc1 != NULL, NULL); sml_fail_unless(error == NULL, NULL); SmlLocation *loc2 = smlLocationNew("test2", NULL, &error); sml_fail_unless(loc2 != NULL, NULL); sml_fail_unless(error == NULL, NULL); SmlLocation *loc3 = smlLocationNew("test3", NULL, &error); sml_fail_unless(loc3 != NULL, NULL); sml_fail_unless(error == NULL, NULL); clienttracker->ds[0] = smlDsClientNew(SML_ELEMENT_TEXT_VCARD, loc1, loc1, &error); clienttracker->ds[1] = smlDsClientNew(SML_ELEMENT_TEXT_VCAL, loc2, loc2, &error); clienttracker->ds[2] = smlDsClientNew(SML_ELEMENT_TEXT_PLAIN, loc3, loc3, &error); smlDsServerSetSanSessionCallback(clienttracker->ds[0], _recv_san, GINT_TO_POINTER(1)); smlDsServerSetSanSessionCallback(clienttracker->ds[1], _recv_san, GINT_TO_POINTER(1)); smlDsServerSetSanSessionCallback(clienttracker->ds[2], _recv_san, GINT_TO_POINTER(1)); smlDsServerRegister(clienttracker->ds[0], clientmanager, &error); smlDsServerRegister(clienttracker->ds[1], clientmanager, &error); smlDsServerRegister(clienttracker->ds[2], clientmanager, &error); servertracker->ds[0] = smlDsServerNew(SML_ELEMENT_TEXT_VCARD, loc1, &error); servertracker->ds[1] = smlDsServerNew(SML_ELEMENT_TEXT_VCAL, loc2, &error); servertracker->ds[2] = smlDsServerNew(SML_ELEMENT_TEXT_PLAIN, loc3, &error); smlDsServerSetConnectCallback(servertracker->ds[0], _recv_init_alert, servertracker); smlDsServerSetConnectCallback(servertracker->ds[1], _recv_init_alert, servertracker); smlDsServerSetConnectCallback(servertracker->ds[2], _recv_init_alert, servertracker); smlDsServerRegister(servertracker->ds[0], servermanager, &error); smlDsServerRegister(servertracker->ds[1], servermanager, &error); smlDsServerRegister(servertracker->ds[2], servermanager, &error); smlLocationUnref(loc1); smlLocationUnref(loc2); smlLocationUnref(loc3); /* The authenticator */ SmlAuthenticator *auth = smlAuthNew(&error); smlAuthSetEnable(auth, FALSE); smlAuthRegister(auth, clientmanager, &error); /* The authenticator */ SmlAuthenticator *auth2 = smlAuthNew(&error); smlAuthSetEnable(auth2, FALSE); smlAuthRegister(auth2, servermanager, &error); sml_fail_unless(smlTransportConnect(server, &error), NULL); sml_fail_unless(error == NULL, NULL); SmlNotification *san = smlNotificationNew(SML_SAN_VERSION_11, SML_SAN_UIMODE_USER, SML_SAN_INITIATOR_SERVER, 65535, "test", "/", SML_MIMETYPE_XML, &error); sml_fail_unless(san != NULL, NULL); sml_fail_unless(error == NULL, NULL); smlNotificationSetManager(san, servermanager); sml_fail_unless(smlDsServerAddSan(servertracker->ds[0], san, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlDsServerAddSan(servertracker->ds[1], san, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlDsServerAddSan(servertracker->ds[2], san, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlNotificationSend(san, server, &error), NULL); sml_fail_unless(error == NULL, NULL); smlNotificationFree(san); while (sans_received < 3 || num_sessions < 2) { smlManagerDispatch(servermanager); smlManagerDispatch(clientmanager); usleep(100); sml_fail_unless(eventError == NULL, "%s", smlErrorPrint(&eventError)); } sml_fail_unless(clienttracker->session != NULL, NULL); smlLocationUnref(loc); clienttracker->dssessions[0] = smlDsServerSendAlert(clienttracker->ds[0], clienttracker->session, SML_ALERT_TWO_WAY, "last", "next", _alert_reply, GINT_TO_POINTER(1), &error); clienttracker->dssessions[1] = smlDsServerSendAlert(clienttracker->ds[1], clienttracker->session, SML_ALERT_TWO_WAY, "last", "next", _alert_reply, GINT_TO_POINTER(1), &error); clienttracker->dssessions[2] = smlDsServerSendAlert(clienttracker->ds[2], clienttracker->session, SML_ALERT_TWO_WAY, "last", "next", _alert_reply, GINT_TO_POINTER(1), &error); sml_fail_unless(smlSessionFlush(clienttracker->session, TRUE, &error), NULL); sml_fail_unless(error == NULL, NULL); while (init_alerts_received < 3 || num_sessions < 2) { smlManagerDispatch(servermanager); smlManagerDispatch(clientmanager); usleep(100); sml_fail_unless(eventError == NULL, "%s", smlErrorPrint(&eventError)); } smlDsSessionGetAlert(servertracker->dssessions[0], _recv_alert, GINT_TO_POINTER(1)); smlDsSessionGetAlert(servertracker->dssessions[1], _recv_alert, GINT_TO_POINTER(1)); smlDsSessionGetAlert(servertracker->dssessions[2], _recv_alert, GINT_TO_POINTER(1)); smlDsSessionSendAlert(servertracker->dssessions[0], SML_ALERT_TWO_WAY, "last", "next", _alert_reply, GINT_TO_POINTER(1), &error); smlDsSessionSendAlert(servertracker->dssessions[1], SML_ALERT_TWO_WAY, "last", "next", _alert_reply, GINT_TO_POINTER(1), &error); smlDsSessionSendAlert(servertracker->dssessions[2], SML_ALERT_TWO_WAY, "last", "next", _alert_reply, GINT_TO_POINTER(1), &error); sml_fail_unless(servertracker->session != NULL, NULL); sml_fail_unless(smlSessionFlush(servertracker->session, TRUE, &error), NULL); smlDsSessionGetAlert(clienttracker->dssessions[0], _recv_alert, GINT_TO_POINTER(1)); smlDsSessionGetAlert(clienttracker->dssessions[1], _recv_alert, GINT_TO_POINTER(1)); smlDsSessionGetAlert(clienttracker->dssessions[2], _recv_alert, GINT_TO_POINTER(1)); while (alerts_received < 6) { smlDsSessionDispatch(servertracker->dssessions[0]); smlDsSessionDispatch(servertracker->dssessions[1]); smlDsSessionDispatch(servertracker->dssessions[2]); smlDsSessionDispatch(clienttracker->dssessions[0]); smlDsSessionDispatch(clienttracker->dssessions[1]); smlDsSessionDispatch(clienttracker->dssessions[2]); smlManagerDispatch(servermanager); smlManagerDispatch(clientmanager); usleep(100); sml_fail_unless(eventError == NULL, "%s", smlErrorPrint(&eventError)); } const char *content_types[] = {SML_ELEMENT_TEXT_VCARD, SML_ELEMENT_TEXT_VCAL, SML_ELEMENT_TEXT_PLAIN}; int k = 0; for (k = 0; k < 3; k++) { smlDsSessionSendSync(clienttracker->dssessions[k], num_changes, _sync_reply, GINT_TO_POINTER(1), &error); unsigned int i = 0; for (i = 0; i < num_items; i++) { sml_fail_unless(smlDsSessionQueueChange(clienttracker->dssessions[k], SML_CHANGE_ADD, "uid", "data", 4, content_types[k], _add_reply, GINT_TO_POINTER(2), &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlDsSessionQueueChange(clienttracker->dssessions[k], SML_CHANGE_REPLACE, "uid", "newdata", 7, content_types[k], _modify_reply, GINT_TO_POINTER(1), &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlDsSessionQueueChange(clienttracker->dssessions[k], SML_CHANGE_DELETE, "uid", NULL, 0, content_types[k], _delete_reply, GINT_TO_POINTER(1), &error), NULL); sml_fail_unless(error == NULL, NULL); } smlDsSessionCloseSync(clienttracker->dssessions[k], &error); } sml_fail_unless(smlSessionFlush(clienttracker->session, TRUE, &error), NULL); smlDsSessionGetSync(servertracker->dssessions[0], _recv_sync, GINT_TO_POINTER(1)); smlDsSessionGetSync(servertracker->dssessions[1], _recv_sync, GINT_TO_POINTER(1)); smlDsSessionGetSync(servertracker->dssessions[2], _recv_sync, GINT_TO_POINTER(1)); smlDsSessionGetChanges(servertracker->dssessions[0], _recv_changes, GINT_TO_POINTER(1)); smlDsSessionGetChanges(servertracker->dssessions[1], _recv_changes, GINT_TO_POINTER(1)); smlDsSessionGetChanges(servertracker->dssessions[2], _recv_changes, GINT_TO_POINTER(1)); while (syncs_received < 3 || adds_received < num_items * 3 || deletes_received < num_items * 3 || modifies_received < num_items * 3) { smlDsSessionDispatch(servertracker->dssessions[0]); smlDsSessionDispatch(servertracker->dssessions[1]); smlDsSessionDispatch(servertracker->dssessions[2]); smlDsSessionDispatch(clienttracker->dssessions[0]); smlDsSessionDispatch(clienttracker->dssessions[1]); smlDsSessionDispatch(clienttracker->dssessions[2]); smlManagerDispatch(servermanager); smlManagerDispatch(clientmanager); usleep(100); sml_fail_unless(eventError == NULL, "%s", smlErrorPrint(&eventError)); } sml_fail_unless(servertracker->session != NULL, NULL); sml_fail_unless(smlSessionEnd(servertracker->session, &error), NULL); sml_fail_unless(error == NULL, NULL); smlSessionUnref(servertracker->session); smlSessionUnref(clienttracker->session); while (num_end < 2 || replies_received < 9 || num_finals < 5) { smlManagerDispatch(servermanager); smlManagerDispatch(clientmanager); usleep(100); sml_fail_unless(eventError == NULL, "%s", smlErrorPrint(&eventError)); } sml_fail_unless(init_alerts_received == 3, NULL); sml_fail_unless(alerts_received == 6, NULL); sml_fail_unless(syncs_received == 3, NULL); sml_fail_unless(sync_ends_received == 0, NULL); sml_fail_unless(changes_received == 0, NULL); sml_fail_unless(replies_received == 9, NULL); sml_fail_unless(adds_received == num_items * 3, NULL); sml_fail_unless(add_replies_received == num_items * 3, NULL); sml_fail_unless(deletes_received == num_items * 3, NULL); sml_fail_unless(delete_replies_received == num_items * 3, NULL); sml_fail_unless(modifies_received == num_items * 3, NULL); sml_fail_unless(modify_replies_received == num_items * 3, NULL); sml_fail_unless(transport_errors == 0, NULL); sml_fail_unless(num_sessions == 2, NULL); sml_fail_unless(num_finals == 5, NULL); sml_fail_unless(num_end == 2, NULL); sml_fail_unless(session_errors == 0, NULL); smlDsSessionUnref(clienttracker->dssessions[0]); smlDsSessionUnref(clienttracker->dssessions[1]); smlDsSessionUnref(clienttracker->dssessions[2]); smlDsSessionUnref(servertracker->dssessions[0]); smlDsSessionUnref(servertracker->dssessions[1]); smlDsSessionUnref(servertracker->dssessions[2]); smlDsServerFree(clienttracker->ds[0]); smlDsServerFree(clienttracker->ds[1]); smlDsServerFree(clienttracker->ds[2]); smlDsServerFree(servertracker->ds[0]); smlDsServerFree(servertracker->ds[1]); smlDsServerFree(servertracker->ds[2]); smlAuthFree(auth); smlAuthFree(auth2); g_free(clienttracker); g_free(servertracker); /* first we have to stop the OBEX client or we get errors */ smlManagerStop(servermanager); while(num_disconnects < 1) { smlManagerDispatch(servermanager); } smlManagerStop(clientmanager); while(num_disconnects < 2) { smlManagerDispatch(clientmanager); } smlManagerFree(clientmanager); smlManagerFree(servermanager); sml_fail_unless(smlTransportFinalize(server, &error), "%s", smlErrorPrint(&error)); sml_fail_unless(smlTransportFinalize(client, &error), NULL); smlTransportFree(server); smlTransportFree(client); } END_TEST #endif #endif #ifdef ENABLE_OBEX #ifdef ENABLE_OPENOBEX_TCP START_TEST (sync_send_san12) { reset_testbed(); unsigned int num_items = 10; num_changes = 3 * num_items; SmlError *error = NULL; SmlTransport *server = smlTransportNew(SML_TRANSPORT_OBEX_CLIENT, &error); SmlTransport *client = smlTransportNew(SML_TRANSPORT_OBEX_SERVER, &error); sml_fail_unless(smlTransportSetConfigOption(client, "PORT", "12011", &error), NULL); sml_fail_unless(smlTransportSetConnectionType(client, SML_TRANSPORT_CONNECTION_TYPE_NET, &error), NULL); sml_fail_unless(smlTransportSetConfigOption(server, "URL", "127.0.0.1", &error), NULL); sml_fail_unless(smlTransportSetConfigOption(server, "PORT", "12011", &error), NULL); sml_fail_unless(smlTransportSetConnectionType(server, SML_TRANSPORT_CONNECTION_TYPE_NET, &error), NULL); managerTracker *clienttracker = g_malloc0(sizeof(managerTracker)); SmlManager *clientmanager = clienttracker->manager = smlManagerNew(client, &error); smlManagerSetEventCallback(clienttracker->manager, _manager_event, clienttracker); managerTracker *servertracker = g_malloc0(sizeof(managerTracker)); SmlManager *servermanager = servertracker->manager = smlManagerNew(server, &error); smlManagerSetEventCallback(servertracker->manager, _manager_event, servertracker); smlManagerSetLocalMaxMsgSize(servertracker->manager, TEST_DEFAULT_MAX_MSG_SIZE); smlManagerSetLocalMaxObjSize(servertracker->manager, TEST_DEFAULT_MAX_OBJ_SIZE); sml_fail_unless(smlManagerStart(clientmanager, &error), "%s", smlErrorPrint(&error)); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlManagerStart(servermanager, &error), "%s", smlErrorPrint(&error)); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlTransportInitialize(client, &error), "%s", smlErrorPrint(&error)); sml_fail_unless(smlTransportInitialize(server, &error), "%s", smlErrorPrint(&error)); SmlLocation *loc1 = smlLocationNew("test1", NULL, &error); sml_fail_unless(loc1 != NULL, NULL); sml_fail_unless(error == NULL, NULL); SmlLocation *loc2 = smlLocationNew("test2", NULL, &error); sml_fail_unless(loc2 != NULL, NULL); sml_fail_unless(error == NULL, NULL); SmlLocation *loc3 = smlLocationNew("test3", NULL, &error); sml_fail_unless(loc3 != NULL, NULL); sml_fail_unless(error == NULL, NULL); clienttracker->ds[0] = smlDsClientNew(SML_ELEMENT_TEXT_VCARD, loc1, loc1, &error); clienttracker->ds[1] = smlDsClientNew(SML_ELEMENT_TEXT_VCAL, loc2, loc2, &error); clienttracker->ds[2] = smlDsClientNew(SML_ELEMENT_TEXT_PLAIN, loc3, loc3, &error); smlDsServerSetSanSessionCallback(clienttracker->ds[0], _recv_san, GINT_TO_POINTER(1)); smlDsServerSetSanSessionCallback(clienttracker->ds[1], _recv_san, GINT_TO_POINTER(1)); smlDsServerSetSanSessionCallback(clienttracker->ds[2], _recv_san, GINT_TO_POINTER(1)); smlDsServerRegister(clienttracker->ds[0], clientmanager, &error); smlDsServerRegister(clienttracker->ds[1], clientmanager, &error); smlDsServerRegister(clienttracker->ds[2], clientmanager, &error); servertracker->ds[0] = smlDsServerNew(SML_ELEMENT_TEXT_VCARD, loc1, &error); servertracker->ds[1] = smlDsServerNew(SML_ELEMENT_TEXT_VCAL, loc2, &error); servertracker->ds[2] = smlDsServerNew(SML_ELEMENT_TEXT_PLAIN, loc3, &error); smlDsServerSetConnectCallback(servertracker->ds[0], _recv_init_alert, servertracker); smlDsServerSetConnectCallback(servertracker->ds[1], _recv_init_alert, servertracker); smlDsServerSetConnectCallback(servertracker->ds[2], _recv_init_alert, servertracker); smlDsServerRegister(servertracker->ds[0], servermanager, &error); smlDsServerRegister(servertracker->ds[1], servermanager, &error); smlDsServerRegister(servertracker->ds[2], servermanager, &error); smlLocationUnref(loc1); smlLocationUnref(loc2); smlLocationUnref(loc3); /* The authenticator */ SmlAuthenticator *auth = smlAuthNew(&error); smlAuthSetEnable(auth, FALSE); smlAuthRegister(auth, clientmanager, &error); /* The authenticator */ SmlAuthenticator *auth2 = smlAuthNew(&error); smlAuthSetEnable(auth2, FALSE); smlAuthRegister(auth2, servermanager, &error); sml_fail_unless(smlTransportConnect(server, &error), NULL); sml_fail_unless(error == NULL, NULL); SmlNotification *san = smlNotificationNew(SML_SAN_VERSION_12, SML_SAN_UIMODE_USER, SML_SAN_INITIATOR_SERVER, 65535, "test", "/", SML_MIMETYPE_XML, &error); sml_fail_unless(san != NULL, NULL); sml_fail_unless(error == NULL, NULL); smlNotificationSetManager(san, servermanager); sml_fail_unless(smlDsServerAddSan(servertracker->ds[0], san, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlDsServerAddSan(servertracker->ds[1], san, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlDsServerAddSan(servertracker->ds[2], san, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlNotificationSend(san, server, &error), "%s", smlErrorPrint(&error)); sml_fail_unless(error == NULL, "%s", smlErrorPrint(&error)); smlNotificationFree(san); while (sans_received < 3 || num_sessions < 1) { smlManagerDispatch(servermanager); smlManagerDispatch(clientmanager); usleep(100); sml_fail_unless(eventError == NULL, "%s", smlErrorPrint(&eventError)); } sml_fail_unless(clienttracker->session != NULL, NULL); clienttracker->dssessions[0] = smlDsServerSendAlert(clienttracker->ds[0], clienttracker->session, SML_ALERT_TWO_WAY, "last", "next", _alert_reply, GINT_TO_POINTER(1), &error); clienttracker->dssessions[1] = smlDsServerSendAlert(clienttracker->ds[1], clienttracker->session, SML_ALERT_TWO_WAY, "last", "next", _alert_reply, GINT_TO_POINTER(1), &error); clienttracker->dssessions[2] = smlDsServerSendAlert(clienttracker->ds[2], clienttracker->session, SML_ALERT_TWO_WAY, "last", "next", _alert_reply, GINT_TO_POINTER(1), &error); sml_fail_unless(smlSessionFlush(clienttracker->session, TRUE, &error), NULL); sml_fail_unless(error == NULL, NULL); while (init_alerts_received < 3 || num_sessions < 2) { smlManagerDispatch(servermanager); smlManagerDispatch(clientmanager); usleep(100); sml_fail_unless(eventError == NULL, "%s", smlErrorPrint(&eventError)); } smlDsSessionGetAlert(servertracker->dssessions[0], _recv_alert, GINT_TO_POINTER(1)); smlDsSessionGetAlert(servertracker->dssessions[1], _recv_alert, GINT_TO_POINTER(1)); smlDsSessionGetAlert(servertracker->dssessions[2], _recv_alert, GINT_TO_POINTER(1)); smlDsSessionSendAlert(servertracker->dssessions[0], SML_ALERT_TWO_WAY, "last", "next", _alert_reply, GINT_TO_POINTER(1), &error); smlDsSessionSendAlert(servertracker->dssessions[1], SML_ALERT_TWO_WAY, "last", "next", _alert_reply, GINT_TO_POINTER(1), &error); smlDsSessionSendAlert(servertracker->dssessions[2], SML_ALERT_TWO_WAY, "last", "next", _alert_reply, GINT_TO_POINTER(1), &error); sml_fail_unless(servertracker->session != NULL, NULL); sml_fail_unless(smlSessionFlush(servertracker->session, TRUE, &error), NULL); smlDsSessionGetAlert(clienttracker->dssessions[0], _recv_alert, GINT_TO_POINTER(1)); smlDsSessionGetAlert(clienttracker->dssessions[1], _recv_alert, GINT_TO_POINTER(1)); smlDsSessionGetAlert(clienttracker->dssessions[2], _recv_alert, GINT_TO_POINTER(1)); while (alerts_received < 6) { smlDsSessionDispatch(servertracker->dssessions[0]); smlDsSessionDispatch(servertracker->dssessions[1]); smlDsSessionDispatch(servertracker->dssessions[2]); smlDsSessionDispatch(clienttracker->dssessions[0]); smlDsSessionDispatch(clienttracker->dssessions[1]); smlDsSessionDispatch(clienttracker->dssessions[2]); smlManagerDispatch(servermanager); smlManagerDispatch(clientmanager); usleep(100); sml_fail_unless(eventError == NULL, "%s", smlErrorPrint(&eventError)); } const char *content_types[] = {SML_ELEMENT_TEXT_VCARD, SML_ELEMENT_TEXT_VCAL, SML_ELEMENT_TEXT_PLAIN}; int k = 0; for (k = 0; k < 3; k++) { smlDsSessionSendSync(clienttracker->dssessions[k], num_changes, _sync_reply, GINT_TO_POINTER(1), &error); unsigned int i = 0; for (i = 0; i < num_items; i++) { sml_fail_unless(smlDsSessionQueueChange(clienttracker->dssessions[k], SML_CHANGE_ADD, "uid", "data", 4, content_types[k], _add_reply, GINT_TO_POINTER(2), &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlDsSessionQueueChange(clienttracker->dssessions[k], SML_CHANGE_REPLACE, "uid", "newdata", 7, content_types[k], _modify_reply, GINT_TO_POINTER(1), &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlDsSessionQueueChange(clienttracker->dssessions[k], SML_CHANGE_DELETE, "uid", NULL, 0, content_types[k], _delete_reply, GINT_TO_POINTER(1), &error), NULL); sml_fail_unless(error == NULL, NULL); } smlDsSessionCloseSync(clienttracker->dssessions[k], &error); } sml_fail_unless(smlSessionFlush(clienttracker->session, TRUE, &error), "%s", smlErrorPrint(&error)); smlDsSessionGetSync(servertracker->dssessions[0], _recv_sync, GINT_TO_POINTER(1)); smlDsSessionGetSync(servertracker->dssessions[1], _recv_sync, GINT_TO_POINTER(1)); smlDsSessionGetSync(servertracker->dssessions[2], _recv_sync, GINT_TO_POINTER(1)); smlDsSessionGetChanges(servertracker->dssessions[0], _recv_changes, GINT_TO_POINTER(1)); smlDsSessionGetChanges(servertracker->dssessions[1], _recv_changes, GINT_TO_POINTER(1)); smlDsSessionGetChanges(servertracker->dssessions[2], _recv_changes, GINT_TO_POINTER(1)); while (syncs_received < 3 || adds_received < num_items * 3 || deletes_received < num_items * 3 || modifies_received < num_items * 3) { smlDsSessionDispatch(servertracker->dssessions[0]); smlDsSessionDispatch(servertracker->dssessions[1]); smlDsSessionDispatch(servertracker->dssessions[2]); smlDsSessionDispatch(clienttracker->dssessions[0]); smlDsSessionDispatch(clienttracker->dssessions[1]); smlDsSessionDispatch(clienttracker->dssessions[2]); smlManagerDispatch(servermanager); smlManagerDispatch(clientmanager); usleep(100); sml_fail_unless(eventError == NULL, "%s", smlErrorPrint(&eventError)); } sml_fail_unless(servertracker->session != NULL, NULL); sml_fail_unless(smlSessionEnd(servertracker->session, &error), "%s", smlErrorPrint(&error)); sml_fail_unless(error == NULL, NULL); smlSessionUnref(servertracker->session); smlSessionUnref(clienttracker->session); while (num_end < 2 || replies_received < 9 || num_finals < 5) { smlManagerDispatch(servermanager); smlManagerDispatch(clientmanager); usleep(100); sml_fail_unless(eventError == NULL, "%s", smlErrorPrint(&eventError)); } sml_fail_unless(init_alerts_received == 3, NULL); sml_fail_unless(alerts_received == 6, NULL); sml_fail_unless(syncs_received == 3, NULL); sml_fail_unless(sync_ends_received == 0, NULL); sml_fail_unless(changes_received == 0, NULL); sml_fail_unless(replies_received == 9, NULL); sml_fail_unless(adds_received == num_items * 3, NULL); sml_fail_unless(add_replies_received == num_items * 3, NULL); sml_fail_unless(deletes_received == num_items * 3, NULL); sml_fail_unless(delete_replies_received == num_items * 3, NULL); sml_fail_unless(modifies_received == num_items * 3, NULL); sml_fail_unless(modify_replies_received == num_items * 3, NULL); sml_fail_unless(transport_errors == 0, NULL); sml_fail_unless(num_sessions == 2, NULL); sml_fail_unless(num_finals == 5, NULL); sml_fail_unless(num_end == 2, NULL); sml_fail_unless(session_errors == 0, NULL); smlDsSessionUnref(clienttracker->dssessions[0]); smlDsSessionUnref(clienttracker->dssessions[1]); smlDsSessionUnref(clienttracker->dssessions[2]); smlDsSessionUnref(servertracker->dssessions[0]); smlDsSessionUnref(servertracker->dssessions[1]); smlDsSessionUnref(servertracker->dssessions[2]); smlDsServerFree(clienttracker->ds[0]); smlDsServerFree(clienttracker->ds[1]); smlDsServerFree(clienttracker->ds[2]); smlDsServerFree(servertracker->ds[0]); smlDsServerFree(servertracker->ds[1]); smlDsServerFree(servertracker->ds[2]); smlAuthFree(auth); smlAuthFree(auth2); g_free(clienttracker); g_free(servertracker); /* first we have to stop the OBEX client or we get errors */ smlManagerStop(servermanager); while(num_disconnects < 1) { smlManagerDispatch(servermanager); } smlManagerStop(clientmanager); while(num_disconnects < 2) { smlManagerDispatch(clientmanager); } smlManagerFree(clientmanager); smlManagerFree(servermanager); sml_fail_unless(smlTransportFinalize(server, &error), "%s", smlErrorPrint(&error)); sml_fail_unless(smlTransportFinalize(client, &error), "%s", smlErrorPrint(&error)); smlTransportFree(server); smlTransportFree(client); } END_TEST #endif #endif @SML_TESTCASE_CODE@ libsyncml-0.5.4/tests/CMakeLists.txt100644 1750 1750 41357 11211710410 17355 0ustar00bellmichbellmichMACRO( ADD_MOBILE_TEST _testName ) if(COMMAND cmake_policy) cmake_policy(SET CMP0003 NEW) ## The macro ADD_CHECK_TEST creates false warning. cmake_policy(SET CMP0002 OLD) endif(COMMAND cmake_policy) ADD_EXECUTABLE( ${_testName} mobiles/${_testName}/test.c ) TARGET_LINK_LIBRARIES( ${_testName} ${ARGN} ) ADD_TEST( ${_testName} ${CMAKE_CURRENT_BINARY_DIR}/${_testName} ${CMAKE_CURRENT_SOURCE_DIR}/mobiles/${_testName} ) ENDMACRO( ADD_MOBILE_TEST ) ## start test MACRO( SML_START_TEST _testLabel _testName _testSource ) if(COMMAND cmake_policy) cmake_policy(SET CMP0003 NEW) ## The macro ADD_CHECK_TEST creates false warning. cmake_policy(SET CMP0002 OLD) endif(COMMAND cmake_policy) BUILD_CHECK_TEST( ${_testName} ${CMAKE_CURRENT_BINARY_DIR}/${_testSource} ${ARGN} ) SET( SML_TESTCASE_CODE "SML_TESTCASE_START(\"${_testLabel}\")\n" ) SET( SML_TESTCASE_NAME ${_testName} ) SET( SML_TESTCASE_SOURCE ${_testSource} ) ENDMACRO( SML_START_TEST ) ## add testcase to test MACRO( SML_ADD_TESTCASE _testcase ) SET( SML_TESTCASE_CODE "${SML_TESTCASE_CODE}SML_TESTCASE_ADD(${_testcase})\n" ) ADD_TEST( ${_testcase} ${CMAKE_CURRENT_BINARY_DIR}/${SML_TESTCASE_NAME} ${_testcase} ) ENDMACRO( SML_ADD_TESTCASE ) ## flush test to source file and build it MACRO( SML_END_TEST ) SET( SML_TESTCASE_CODE "${SML_TESTCASE_CODE}SML_TESTCASE_END\n\n" ) CONFIGURE_FILE( ${SML_TESTCASE_SOURCE} ${CMAKE_CURRENT_BINARY_DIR}/${SML_TESTCASE_SOURCE} @ONLY ) ENDMACRO( SML_END_TEST ) IF( ENABLE_UNIT_TEST ) LINK_DIRECTORIES( ${GLIB2_LIBRARY_DIRS} ${LIBXML2_LIBRARY_DIRS} ${OPENOBEX_LIBRARY_DIRS} ${LIBWBXML2_LIBRARY_DIRS} ${LIBSOUP2_LIBRARY_DIRS} ${BLUEZ_LIBRARY_DIRS} ${CHECK_LIBRARY_DIRS} ) if(COMMAND cmake_policy) cmake_policy(SET CMP0003 NEW) endif(COMMAND cmake_policy) # create support library ADD_LIBRARY( support STATIC support.c ) TARGET_LINK_LIBRARIES( support syncml ${CHECK_LIBRARIES} ) # include Testing Macro INCLUDE( Testing ) # include necessary headers INCLUDE_DIRECTORIES( ${CMAKE_SOURCE_DIR} ${CMAKE_BINARY_DIR} ${GLIB2_INCLUDE_DIRS} ${LIBXML2_INCLUDE_DIRS} ${LIBWBXML2_INCLUDE_DIRS} ${LIBSOUP2_INCLUDE_DIRS} ) # add tests SET( TEST_TARGET_LIBRARIES support ) ## error tests SML_START_TEST( "error" error check_error.c ${TEST_TARGET_LIBRARIES} ) SML_ADD_TESTCASE( error_create ) SML_ADD_TESTCASE( error_create_null ) SML_ADD_TESTCASE( error_free_null ) SML_ADD_TESTCASE( error_free_null2 ) SML_ADD_TESTCASE( error_free ) SML_ADD_TESTCASE( error_check_null ) SML_ADD_TESTCASE( error_check_null2 ) SML_ADD_TESTCASE( error_check ) SML_ADD_TESTCASE( error_check2 ) SML_ADD_TESTCASE( error_update_null ) SML_ADD_TESTCASE( error_update_null2 ) SML_ADD_TESTCASE( error_update ) SML_ADD_TESTCASE( error_update2 ) SML_ADD_TESTCASE( error_set_null ) SML_ADD_TESTCASE( error_set_null2 ) SML_ADD_TESTCASE( error_duplicate_null ) SML_ADD_TESTCASE( error_class ) SML_END_TEST() SML_START_TEST( "Elements" elements check_elements.c ${TEST_TARGET_LIBRARIES} ) SML_ADD_TESTCASE( location_new ) SML_ADD_TESTCASE( location_new2 ) SML_ADD_TESTCASE( location_new3 ) SML_ADD_TESTCASE( location_compare_rel ) SML_ADD_TESTCASE( location_compare_rel1 ) SML_ADD_TESTCASE( location_compare_rel2 ) SML_ADD_TESTCASE( location_compare_abs ) SML_ADD_TESTCASE( location_compare_abs2 ) SML_ADD_TESTCASE( location_compare_combined ) SML_ADD_TESTCASE( location_compare_combined2 ) SML_ADD_TESTCASE( location_compare_combined3 ) SML_ADD_TESTCASE( location_compare_combined4 ) SML_ADD_TESTCASE( location_compare_combined5 ) SML_ADD_TESTCASE( location_compare_combined6 ) SML_END_TEST() SML_START_TEST( "XML fix broken Item Data" xml-fix-broken-item-data check_xml_fix_broken_item_data.c ${TEST_TARGET_LIBRARIES} ) SML_ADD_TESTCASE( xml_fix_broken_item_data_no_item ) SML_ADD_TESTCASE( xml_fix_broken_item_data_no_item_data ) SML_ADD_TESTCASE( xml_fix_broken_item_data_no_broken_item_data ) SML_ADD_TESTCASE( xml_fix_broken_item_data_one_broken_item_data ) SML_ADD_TESTCASE( xml_fix_broken_item_data_multi_broken_item_data ) SML_ADD_TESTCASE( xml_fix_broken_item_data_mixed_broken_item_data ) SML_ADD_TESTCASE( xml_fix_broken_item_data_utf16_conversion ) SML_END_TEST() SML_START_TEST( "XML Parser" xmlparser check_xml_parser.c ${TEST_TARGET_LIBRARIES} ) SML_ADD_TESTCASE( xml_parser_empty ) SML_ADD_TESTCASE( xml_parser_syncml_empty ) SML_ADD_TESTCASE( xml_parser_syncml_wrong_case ) SML_ADD_TESTCASE( xml_parser_syncml_additional ) SML_ADD_TESTCASE( xml_parser_no_syncbody ) SML_ADD_TESTCASE( xml_parser_no_synchdr ) SML_ADD_TESTCASE( xml_parser_synchdr_empty ) SML_ADD_TESTCASE( xml_parser_synchdr_verproto ) SML_ADD_TESTCASE( xml_parser_synchdr_verdtd ) SML_ADD_TESTCASE( xml_parser_synchdr_msgid ) SML_ADD_TESTCASE( xml_parser_synchdr_sessionid ) SML_ADD_TESTCASE( xml_parser_synchdr_additional ) SML_ADD_TESTCASE( xml_parser_synchdr_target ) SML_ADD_TESTCASE( xml_parser_synchdr_source ) SML_ADD_TESTCASE( xml_parser_synchdr_source2 ) SML_ADD_TESTCASE( xml_parser_status_empty ) SML_ADD_TESTCASE( xml_parser_status_cmdid ) SML_ADD_TESTCASE( xml_parser_status_msgref ) SML_ADD_TESTCASE( xml_parser_status_cmdref ) SML_ADD_TESTCASE( xml_parser_status ) SML_ADD_TESTCASE( xml_parser_status2 ) SML_ADD_TESTCASE( xml_parser_status3 ) SML_ADD_TESTCASE( xml_parser_status_google ) SML_ADD_TESTCASE( xml_parser_final ) SML_ADD_TESTCASE( xml_parser_final2 ) SML_ADD_TESTCASE( xml_parser_cmd ) SML_ADD_TESTCASE( xml_parser_cmd_final ) SML_ADD_TESTCASE( xml_parser_sync_subcommand ) SML_ADD_TESTCASE( xml_parser_doctype ) SML_ADD_TESTCASE( xml_parser_emi ) SML_ADD_TESTCASE( xml_parser_large_obj ) SML_ADD_TESTCASE( xml_parser_large_obj2 ) SML_ADD_TESTCASE( xml_parser_large_obj_error ) SML_ADD_TESTCASE( xml_parser_large_obj_mangled ) SML_ADD_TESTCASE( xml_parser_devinf ) SML_ADD_TESTCASE( xml_parser_devinf_ctcap ) SML_ADD_TESTCASE( xml_parser_devinf12 ) SML_ADD_TESTCASE( xml_parser_devinf_ext ) SML_ADD_TESTCASE( xml_parser_empty_data_element ) SML_ADD_TESTCASE( xml_parser_msgref_zero ) SML_ADD_TESTCASE( xml_parser_ctcap_property_size ) SML_ADD_TESTCASE( xml_parser_ctcap11_size ) SML_ADD_TESTCASE( xml_parser_item_with_meta_in_status ) SML_ADD_TESTCASE( xml_parser_item_with_meta_and_long_empty_data_in_status ) SML_ADD_TESTCASE( xml_parser_item_with_meta_and_short_empty_data_in_status ) SML_END_TEST() SML_START_TEST( "XML Assembler" xmlassembler check_xml_assembler.c ${TEST_TARGET_LIBRARIES} ) SML_ADD_TESTCASE( xml_assembler_message_empty ) SML_ADD_TESTCASE( xml_assembler_message_only_header ) SML_ADD_TESTCASE( xml_assembler_message_status ) SML_ADD_TESTCASE( xml_assembler_message_cmd ) SML_ADD_TESTCASE( xml_assembler_message_subcmd ) SML_ADD_TESTCASE( xml_assembler_message_several_subcmd ) SML_ADD_TESTCASE( xml_assembler_message_flush_open ) SML_ADD_TESTCASE( xml_assembler_out_of_order ) SML_ADD_TESTCASE( xml_assembler_limit1 ) SML_ADD_TESTCASE( xml_assembler_limit2 ) SML_ADD_TESTCASE( xml_assembler_limit3 ) SML_ADD_TESTCASE( xml_assembler_limit4 ) SML_ADD_TESTCASE( xml_assembler_limit5 ) SML_ADD_TESTCASE( xml_assembler_devinf ) SML_ADD_TESTCASE( xml_assembler_devinf12 ) SML_ADD_TESTCASE( xml_assembler_order ) SML_ADD_TESTCASE( xml_assembler_reuse ) SML_ADD_TESTCASE( xml_assembler_leak ) SML_ADD_TESTCASE( xml_assembler_stress ) SML_ADD_TESTCASE( xml_assembler_stress_limit ) SML_ADD_TESTCASE( xml_assembler_stress_large_limit ) SML_ADD_TESTCASE( xml_assembler_large_obj ) SML_END_TEST() SML_START_TEST( "Session" session check_session.c ${TEST_TARGET_LIBRARIES} ) SML_ADD_TESTCASE( session_new ) SML_ADD_TESTCASE( session_send ) SML_ADD_TESTCASE( session_flush ) SML_ADD_TESTCASE( session_flush_final ) SML_ADD_TESTCASE( session_recv ) SML_ADD_TESTCASE( session_transmit ) SML_ADD_TESTCASE( session_reply ) SML_ADD_TESTCASE( session_talk ) SML_ADD_TESTCASE( session_talk_alot ) SML_ADD_TESTCASE( session_talk_alot_limit ) SML_ADD_TESTCASE( session_limit_remote ) SML_ADD_TESTCASE( session_split_child ) SML_ADD_TESTCASE( session_recv_large_obj ) SML_ADD_TESTCASE( session_recv_large_obj2 ) SML_ADD_TESTCASE( session_recv_wrong_order ) SML_ADD_TESTCASE( session_large_obj_10 ) SML_ADD_TESTCASE( session_large_obj_open ) SML_ADD_TESTCASE( session_large_obj_no_size ) SML_ADD_TESTCASE( session_large_obj_several_size ) SML_ADD_TESTCASE( session_recv_large_wrong_size ) SML_ADD_TESTCASE( session_recv_large_wrong_size2 ) SML_ADD_TESTCASE( session_send_large_obj ) SML_ADD_TESTCASE( session_send_large_obj2 ) SML_ADD_TESTCASE( session_send_multi_large_obj ) SML_ADD_TESTCASE( session_send_multi_large_obj_alter ) IF ( ENABLE_HTTP ) SML_ADD_TESTCASE( session_san ) ENDIF ( ENABLE_HTTP ) SML_END_TEST() SML_START_TEST( "MD5" md5 check_md5.c ${TEST_TARGET_LIBRARIES} ) SML_ADD_TESTCASE( md5_1 ) SML_ADD_TESTCASE( md5_2 ) SML_ADD_TESTCASE( md5_3 ) SML_ADD_TESTCASE( md5_4 ) SML_ADD_TESTCASE( md5_5 ) SML_ADD_TESTCASE( md5_6 ) SML_ADD_TESTCASE( md5_7 ) SML_END_TEST() SML_START_TEST( "DataStore" datastore check_ds.c ${TEST_TARGET_LIBRARIES} ) SML_ADD_TESTCASE( datastore_server_new ) SML_ADD_TESTCASE( datastore_client_new ) SML_ADD_TESTCASE( datastore_send_alert ) SML_ADD_TESTCASE( datastore_send_alert2 ) SML_ADD_TESTCASE( datastore_send_empty_sync ) SML_ADD_TESTCASE( datastore_reply_empty_sync ) SML_ADD_TESTCASE( datastore_add ) SML_ADD_TESTCASE( datastore_add2 ) SML_ADD_TESTCASE( datastore_delete ) SML_ADD_TESTCASE( datastore_map_full ) SML_ADD_TESTCASE( datastore_add_large ) SML_ADD_TESTCASE( datastore_limit ) SML_END_TEST() SML_START_TEST( "SAN" san check_san.c ${TEST_TARGET_LIBRARIES} ) SML_ADD_TESTCASE( san_new ) SML_ADD_TESTCASE( san_empty ) SML_ADD_TESTCASE( san_empty2 ) SML_ADD_TESTCASE( san_alert ) SML_ADD_TESTCASE( san_alert2 ) SML_ADD_TESTCASE( san_alert_auth ) SML_ADD_TESTCASE( san_parse ) SML_ADD_TESTCASE( san_parse2 ) IF ( ENABLE_HTTP ) SML_ADD_TESTCASE( san_11_assemble_parse ) ENDIF ( ENABLE_HTTP ) SML_ADD_TESTCASE( san_parse_error ) SML_ADD_TESTCASE( san_parse_error2 ) SML_ADD_TESTCASE( san_parse_error3 ) SML_ADD_TESTCASE( san_parse_error4 ) SML_ADD_TESTCASE( san_parse_error5 ) SML_ADD_TESTCASE( san_parse_error6 ) SML_ADD_TESTCASE( san_parse_error7 ) SML_END_TEST() SML_START_TEST( "DevInf" devinf check_devinf.c ${TEST_TARGET_LIBRARIES} ) IF( ENABLE_HTTP ) SML_ADD_TESTCASE( devinf_crash ) SML_ADD_TESTCASE( devinf_result ) ENDIF( ENABLE_HTTP ) SML_ADD_TESTCASE( devinf_max_size_element ) SML_END_TEST() SML_START_TEST( "Sync" sync check_sync.c ${TEST_TARGET_LIBRARIES} ) IF ( ENABLE_HTTP ) SML_ADD_TESTCASE( sync_multi_start ) SML_ADD_TESTCASE( sync_multi_stress ) SML_ADD_TESTCASE( sync_multi_stress2 ) SML_ADD_TESTCASE( sync_multi_conf_from_devinf ) ENDIF ( ENABLE_HTTP ) IF ( ENABLE_OBEX AND ENABLE_OPENOBEX_TCP ) SML_ADD_TESTCASE( sync_send_san ) SML_ADD_TESTCASE( sync_send_san12 ) ENDIF ( ENABLE_OBEX AND ENABLE_OPENOBEX_TCP ) SML_END_TEST() # dependent tests IF( ENABLE_OBEX AND ENABLE_OPENOBEX_TCP ) SML_START_TEST( "OBEX" obex check_obex.c ${TEST_TARGET_LIBRARIES} ) SML_ADD_TESTCASE( obex_get_result_macro ) SML_ADD_TESTCASE( obex_client_new ) SML_ADD_TESTCASE( obex_client_init ) SML_ADD_TESTCASE( obex_server_new ) SML_ADD_TESTCASE( obex_server_init ) SML_ADD_TESTCASE( obex_connect ) SML_ADD_TESTCASE( obex_send ) SML_ADD_TESTCASE( obex_reply ) SML_ADD_TESTCASE( obex_talk ) SML_ADD_TESTCASE( obex_multi_connect ) SML_ADD_TESTCASE( obex_multi_stress ) SML_ADD_TESTCASE( obex_connect_error ) SML_ADD_TESTCASE( obex_reject ) SML_ADD_TESTCASE( obex_multi_partial_error ) SML_END_TEST() ENDIF( ENABLE_OBEX AND ENABLE_OPENOBEX_TCP ) IF ( ENABLE_HTTP ) SML_START_TEST( "libsoup" libsoup check_libsoup.c ${TEST_TARGET_LIBRARIES} ) SML_ADD_TESTCASE( libsoup_async ) SML_ADD_TESTCASE( libsoup_http_client ) SML_ADD_TESTCASE( libsoup_http_server ) SML_END_TEST() SML_START_TEST( "HTTP" http check_http.c ${TEST_TARGET_LIBRARIES} ) SML_ADD_TESTCASE( http_client_new ) SML_ADD_TESTCASE( http_client_init ) # TODO: Review testcase. Obsolate? # SML_ADD_TESTCASE( http_client_wrong_port ) SML_ADD_TESTCASE( http_client_init_no_url ) SML_ADD_TESTCASE( http_server_new ) SML_ADD_TESTCASE( http_server_init ) SML_ADD_TESTCASE( http_server_wrong_port ) SML_ADD_TESTCASE( http_connect ) SML_ADD_TESTCASE( http_send ) SML_ADD_TESTCASE( http_receive ) SML_ADD_TESTCASE( http_reply ) SML_ADD_TESTCASE( http_talk ) SML_ADD_TESTCASE( http_connect_error ) SML_ADD_TESTCASE( http_reject ) SML_ADD_TESTCASE( http_multi_connect ) SML_ADD_TESTCASE( http_multi_partial_error ) SML_ADD_TESTCASE( http_multi_stress ) SML_END_TEST() SML_START_TEST( "Manager" manager check_manager.c ${TEST_TARGET_LIBRARIES} ) SML_ADD_TESTCASE( manager_new ) SML_ADD_TESTCASE( manager_run ) SML_ADD_TESTCASE( manager_receive ) SML_ADD_TESTCASE( manager_receive_session ) SML_ADD_TESTCASE( manager_end_session ) SML_ADD_TESTCASE( manager_register ) SML_ADD_TESTCASE( manager_start_session ) SML_END_TEST() ENDIF ( ENABLE_HTTP ) IF ( ENABLE_WBXML ) SML_START_TEST( "WBXML Parser" wbxmlparser check_wbxml_parser.c ${TEST_TARGET_LIBRARIES} ) SML_ADD_TESTCASE( wbxml_parser_syncml_empty ) SML_ADD_TESTCASE( wbxml_parser_no_syncbody ) SML_ADD_TESTCASE( wbxml_parser_no_synchdr ) SML_ADD_TESTCASE( wbxml_parser_synchdr_empty ) SML_ADD_TESTCASE( wbxml_parser_synchdr_verproto ) SML_ADD_TESTCASE( wbxml_parser_synchdr_verdtd ) SML_ADD_TESTCASE( wbxml_parser_synchdr_msgid ) SML_ADD_TESTCASE( wbxml_parser_synchdr_sessionid ) SML_ADD_TESTCASE( wbxml_parser_synchdr_additional ) SML_ADD_TESTCASE( wbxml_parser_synchdr_target ) SML_ADD_TESTCASE( wbxml_parser_synchdr_source ) SML_ADD_TESTCASE( wbxml_parser_synchdr_source2 ) SML_ADD_TESTCASE( wbxml_parser_status_empty ) SML_ADD_TESTCASE( wbxml_parser_status_cmdid ) SML_ADD_TESTCASE( wbxml_parser_status_msgref ) SML_ADD_TESTCASE( wbxml_parser_status_cmdref ) SML_ADD_TESTCASE( wbxml_parser_status ) SML_ADD_TESTCASE( wbxml_parser_status2 ) SML_ADD_TESTCASE( wbxml_parser_final ) SML_ADD_TESTCASE( wbxml_parser_final2 ) SML_ADD_TESTCASE( wbxml_parser_cmd ) SML_ADD_TESTCASE( wbxml_parser_cmd_final ) SML_END_TEST() SML_START_TEST( "WBXML Assembler" wbxmlassembler check_wbxml_assembler.c ${TEST_TARGET_LIBRARIES} ) SML_ADD_TESTCASE( wbxml_assembler_message_empty ) SML_ADD_TESTCASE( wbxml_assembler_message_only_header ) SML_ADD_TESTCASE( wbxml_assembler_message_status ) SML_ADD_TESTCASE( wbxml_assembler_message_cmd ) SML_ADD_TESTCASE( wbxml_assembler_message_subcmd ) SML_ADD_TESTCASE( wbxml_assembler_message_several_subcmd ) SML_ADD_TESTCASE( wbxml_assembler_message_flush_open ) SML_ADD_TESTCASE( wbxml_assembler_out_of_order ) SML_ADD_TESTCASE( wbxml_assembler_limit1 ) SML_ADD_TESTCASE( wbxml_assembler_limit2 ) SML_ADD_TESTCASE( wbxml_assembler_limit3 ) SML_ADD_TESTCASE( wbxml_assembler_limit4 ) SML_ADD_TESTCASE( wbxml_assembler_limit5 ) SML_ADD_TESTCASE( wbxml_assembler_complex1 ) SML_END_TEST() ENDIF( ENABLE_WBXML ) IF ( ENABLE_OBEX AND ENABLE_OPENOBEX_TCP AND ENABLE_WBXML AND ENABLE_GLIB2_GREGEX ) # mobile tests ADD_MOBILE_TEST( nokia_e65_vcard ${TEST_TARGET_LIBRARIES} ) ADD_MOBILE_TEST( nokia_e65_vcard_vcal ${TEST_TARGET_LIBRARIES} ) ADD_MOBILE_TEST( nokia_6230_vcard ${TEST_TARGET_LIBRARIES} ) ADD_MOBILE_TEST( nokia_6230_vcal ${TEST_TARGET_LIBRARIES} ) ADD_MOBILE_TEST( nokia_9500_vcard ${TEST_TARGET_LIBRARIES} ) ADD_MOBILE_TEST( nokia_9500_vcal ${TEST_TARGET_LIBRARIES} ) ADD_MOBILE_TEST( nokia_9500_vcard_vcal ${TEST_TARGET_LIBRARIES} ) ENDIF ( ENABLE_OBEX AND ENABLE_OPENOBEX_TCP AND ENABLE_WBXML AND ENABLE_GLIB2_GREGEX ) IF ( ENABLE_OPENOBEX_TCP OR ENABLE_HTTP ) SML_START_TEST( "OMA DS API" ds_api check_data_sync_api.c ${TEST_TARGET_LIBRARIES} ) SML_ADD_TESTCASE( ds_api_text_vcard_21 ) SML_ADD_TESTCASE( ds_api_image_jpeg ) SML_ADD_TESTCASE( ds_api_unknown_ct ) SML_ADD_TESTCASE( ds_api_multi_text_vcard_21 ) SML_END_TEST() ENDIF ( ENABLE_OPENOBEX_TCP OR ENABLE_HTTP ) # tests of deprecated stuff # such tests produce compiler warnings IF ( ENABLE_BASE64_TEST ) SML_START_TEST( "base64" base64 check_base64.c ${TEST_TARGET_LIBRARIES} ) SML_ADD_TESTCASE( base64_decode_null ) SML_ADD_TESTCASE( base64_decode_null2 ) SML_ADD_TESTCASE( base64_decode_test ) SML_ADD_TESTCASE( base64_decode_size ) SML_ADD_TESTCASE( base64_decode2 ) SML_ADD_TESTCASE( base64_decode3 ) SML_ADD_TESTCASE( base64_decode4 ) SML_ADD_TESTCASE( base64_invalid1 ) SML_ADD_TESTCASE( base64_empty ) # SML_ADD_TESTCASE( base64_invalid2 ) SML_ADD_TESTCASE( base64_encode_null ) SML_ADD_TESTCASE( base64_encode_null2 ) SML_ADD_TESTCASE( base64_encode_test ) SML_ADD_TESTCASE( base64_encode_test2 ) SML_ADD_TESTCASE( base64_encode_test3 ) SML_END_TEST() ENDIF ( ENABLE_BASE64_TEST ) ENDIF( ENABLE_UNIT_TEST ) CONFIGURE_FILE( "coverage.sh.cmake" "${CMAKE_BINARY_DIR}/coverage.sh") libsyncml-0.5.4/tests/check_elements.c100644 1750 1750 22161 11211710410 17722 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2005 Armin Bauer * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include "tests/support.h" #include START_TEST (location_new) { setup_testbed(NULL); SmlError *error = NULL; SmlLocation *location = smlLocationNew("uri", "name", &error); sml_fail_unless(location != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(!strcmp(smlLocationGetURI(location), "uri"), NULL); sml_fail_unless(!strcmp(smlLocationGetName(location), "name"), NULL); smlLocationUnref(location); } END_TEST START_TEST (location_new2) { setup_testbed(NULL); SmlError *error = NULL; SmlLocation *location = smlLocationNew("uri", NULL, &error); sml_fail_unless(location != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(!strcmp(smlLocationGetURI(location), "uri"), NULL); sml_fail_unless(smlLocationGetName(location) == NULL, NULL); smlLocationUnref(location); } END_TEST START_TEST (location_new3) { setup_testbed(NULL); SmlError *error = NULL; SmlLocation *location = smlLocationNew(NULL, NULL, &error); sml_fail_unless(location == NULL, NULL); sml_fail_unless(error != NULL, NULL); smlErrorDeref(&error); } END_TEST START_TEST (location_compare_rel) { setup_testbed(NULL); SmlError *error = NULL; SmlLocation *objloc = smlLocationNew("./test", NULL, &error); sml_fail_unless(objloc != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlLocationCompare(NULL, objloc, NULL, objloc), NULL); smlLocationUnref(objloc); } END_TEST START_TEST (location_compare_rel1) { setup_testbed(NULL); SmlError *error = NULL; SmlLocation *objloc = smlLocationNew("/test", NULL, &error); sml_fail_unless(objloc != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlLocationCompare(NULL, objloc, NULL, objloc), NULL); smlLocationUnref(objloc); } END_TEST START_TEST (location_compare_rel2) { setup_testbed(NULL); SmlError *error = NULL; SmlLocation *objloc = smlLocationNew("./test", NULL, &error); sml_fail_unless(objloc != NULL, NULL); sml_fail_unless(error == NULL, NULL); SmlLocation *objloc2 = smlLocationNew("./test2", NULL, &error); sml_fail_unless(objloc2 != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(!smlLocationCompare(NULL, objloc, NULL, objloc2), NULL); smlLocationUnref(objloc); smlLocationUnref(objloc2); } END_TEST START_TEST (location_compare_abs) { setup_testbed(NULL); SmlError *error = NULL; SmlLocation *objbase = smlLocationNew("/test", NULL, &error); sml_fail_unless(objbase != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlLocationCompare(objbase, NULL, objbase, NULL), NULL); smlLocationUnref(objbase); } END_TEST START_TEST (location_compare_abs2) { setup_testbed(NULL); SmlError *error = NULL; SmlLocation *objbase = smlLocationNew("/test", NULL, &error); sml_fail_unless(objbase != NULL, NULL); sml_fail_unless(error == NULL, NULL); SmlLocation *objbase2 = smlLocationNew("/test2", NULL, &error); sml_fail_unless(objbase2 != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlLocationCompare(objbase, NULL, objbase2, NULL), NULL); smlLocationUnref(objbase); smlLocationUnref(objbase2); } END_TEST START_TEST (location_compare_combined) { setup_testbed(NULL); SmlError *error = NULL; SmlLocation *objbase = smlLocationNew("/test", NULL, &error); sml_fail_unless(objbase != NULL, NULL); sml_fail_unless(error == NULL, NULL); SmlLocation *objloc = smlLocationNew("./test", NULL, &error); sml_fail_unless(objloc != NULL, NULL); sml_fail_unless(error == NULL, NULL); SmlLocation *objbase2 = smlLocationNew("/test", NULL, &error); sml_fail_unless(objbase2 != NULL, NULL); sml_fail_unless(error == NULL, NULL); SmlLocation *objloc2 = smlLocationNew("./test", NULL, &error); sml_fail_unless(objloc2 != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlLocationCompare(objbase, objloc, objbase2, objloc2), NULL); smlLocationUnref(objbase); smlLocationUnref(objloc); smlLocationUnref(objbase2); smlLocationUnref(objloc2); } END_TEST START_TEST (location_compare_combined2) { setup_testbed(NULL); SmlError *error = NULL; SmlLocation *objbase = smlLocationNew("/test", NULL, &error); sml_fail_unless(objbase != NULL, NULL); sml_fail_unless(error == NULL, NULL); SmlLocation *objloc = smlLocationNew("test", NULL, &error); sml_fail_unless(objloc != NULL, NULL); sml_fail_unless(error == NULL, NULL); SmlLocation *objbase2 = smlLocationNew("/test", NULL, &error); sml_fail_unless(objbase2 != NULL, NULL); sml_fail_unless(error == NULL, NULL); SmlLocation *objloc2 = smlLocationNew("./test", NULL, &error); sml_fail_unless(objloc2 != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlLocationCompare(objbase, objloc, objbase2, objloc2), NULL); smlLocationUnref(objbase); smlLocationUnref(objloc); smlLocationUnref(objbase2); smlLocationUnref(objloc2); } END_TEST START_TEST (location_compare_combined3) { setup_testbed(NULL); SmlError *error = NULL; SmlLocation *objbase = smlLocationNew("/test/asd", NULL, &error); sml_fail_unless(objbase != NULL, NULL); sml_fail_unless(error == NULL, NULL); SmlLocation *objloc = smlLocationNew("test/", NULL, &error); sml_fail_unless(objloc != NULL, NULL); sml_fail_unless(error == NULL, NULL); SmlLocation *objbase2 = smlLocationNew("/test/.//asd//", NULL, &error); sml_fail_unless(objbase2 != NULL, NULL); sml_fail_unless(error == NULL, NULL); SmlLocation *objloc2 = smlLocationNew("././test", NULL, &error); sml_fail_unless(objloc2 != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlLocationCompare(objbase, objloc, objbase2, objloc2), NULL); smlLocationUnref(objbase); smlLocationUnref(objloc); smlLocationUnref(objbase2); smlLocationUnref(objloc2); } END_TEST START_TEST (location_compare_combined4) { setup_testbed(NULL); SmlError *error = NULL; SmlLocation *objbase = smlLocationNew("/test/asd2", NULL, &error); sml_fail_unless(objbase != NULL, NULL); sml_fail_unless(error == NULL, NULL); SmlLocation *objloc = smlLocationNew("test", NULL, &error); sml_fail_unless(objloc != NULL, NULL); sml_fail_unless(error == NULL, NULL); SmlLocation *objbase2 = smlLocationNew("/test/.//asd//", NULL, &error); sml_fail_unless(objbase2 != NULL, NULL); sml_fail_unless(error == NULL, NULL); SmlLocation *objloc2 = smlLocationNew("././test", NULL, &error); sml_fail_unless(objloc2 != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(!smlLocationCompare(objbase, objloc, objbase2, objloc2), NULL); smlLocationUnref(objbase); smlLocationUnref(objloc); smlLocationUnref(objbase2); smlLocationUnref(objloc2); } END_TEST START_TEST (location_compare_combined5) { setup_testbed(NULL); SmlError *error = NULL; SmlLocation *objbase = smlLocationNew("/test/asd", NULL, &error); sml_fail_unless(objbase != NULL, NULL); sml_fail_unless(error == NULL, NULL); SmlLocation *objloc = smlLocationNew("tes3t", NULL, &error); sml_fail_unless(objloc != NULL, NULL); sml_fail_unless(error == NULL, NULL); SmlLocation *objbase2 = smlLocationNew("/test/.//asd//", NULL, &error); sml_fail_unless(objbase2 != NULL, NULL); sml_fail_unless(error == NULL, NULL); SmlLocation *objloc2 = smlLocationNew("././test", NULL, &error); sml_fail_unless(objloc2 != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(!smlLocationCompare(objbase, objloc, objbase2, objloc2), NULL); smlLocationUnref(objbase); smlLocationUnref(objloc); smlLocationUnref(objbase2); smlLocationUnref(objloc2); } END_TEST START_TEST (location_compare_combined6) { setup_testbed(NULL); SmlError *error = NULL; SmlLocation *objbase = smlLocationNew("/", NULL, &error); sml_fail_unless(objbase != NULL, NULL); sml_fail_unless(error == NULL, NULL); SmlLocation *objloc = smlLocationNew("", NULL, &error); sml_fail_unless(objloc != NULL, NULL); sml_fail_unless(error == NULL, NULL); SmlLocation *objbase2 = smlLocationNew(".//", NULL, &error); sml_fail_unless(objbase2 != NULL, NULL); sml_fail_unless(error == NULL, NULL); SmlLocation *objloc2 = smlLocationNew("///", NULL, &error); sml_fail_unless(objloc2 != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlLocationCompare(objbase, objloc, objbase2, objloc2), NULL); smlLocationUnref(objbase); smlLocationUnref(objloc); smlLocationUnref(objbase2); smlLocationUnref(objloc2); } END_TEST @SML_TESTCASE_CODE@ libsyncml-0.5.4/tests/check_http.c100644 1750 1750 100542 11211710410 17105 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2005 Armin Bauer * Copyright (C) 2008 Michael Bell * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include "tests/support.h" #include int client_connects; int client_disconnects; int client_receives; int client_errors; int server_connects; int server_disconnects; int server_receives; GList *links; void reset_testbed() { client_connects = 0; client_disconnects = 0; client_receives = 0; client_errors = 0; server_connects = 0; server_disconnects = 0; server_receives = 0; links = NULL; setup_testbed(NULL); } START_TEST (http_client_new) { reset_testbed(); SmlError *error = NULL; SmlTransport *tsp = smlTransportNew(SML_TRANSPORT_HTTP_CLIENT, &error); sml_fail_unless(tsp != NULL, NULL); sml_fail_unless(error == NULL, NULL); smlTransportFree(tsp); } END_TEST START_TEST (http_client_init) { reset_testbed(); SmlError *error = NULL; SmlTransport *tsp = smlTransportNew(SML_TRANSPORT_HTTP_CLIENT, &error); sml_fail_unless(tsp != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlTransportSetConfigOption(tsp, "URL", "http://libsyncml.opensyncml.org", &error), "%s", smlErrorPrint(&error)); sml_fail_unless(smlTransportInitialize(tsp, &error), "%s", smlErrorPrint(&error)); sml_fail_unless(error == NULL, "%s", smlErrorPrint(&error)); sml_fail_unless(smlTransportFinalize(tsp, &error), NULL); sml_fail_unless(error == NULL, NULL); smlTransportFree(tsp); } END_TEST /* TODO: Review if it's possible to fool libsoup with a wrong port. START_TEST (http_client_wrong_port) { reset_testbed(); SmlError *error = NULL; SmlTransport *tsp = smlTransportNew(SML_TRANSPORT_HTTP_CLIENT, &error); sml_fail_unless(tsp != NULL, NULL); sml_fail_unless(error == NULL, NULL); SmlTransportHttpClientConfig config; memset(&config, 0, sizeof(SmlTransportHttpClientConfig)); config.url = "http://libsyncml.opensync.org:-1/"; sml_fail_unless(!smlTransportInitialize(tsp, &config, &error), NULL); sml_fail_unless(error != NULL, NULL); smlErrorDeref(&error); smlTransportFree(tsp); } END_TEST */ START_TEST (http_client_init_no_url) { /* An HTTP client without an URL is an ERROR. */ reset_testbed(); SmlError *error = NULL; SmlTransport *tsp = smlTransportNew(SML_TRANSPORT_HTTP_CLIENT, &error); sml_fail_unless(tsp != NULL, NULL); sml_fail_unless(error == NULL, NULL); /* The port alone is a valid URL. */ sml_fail_unless(smlTransportSetConfigOption(tsp, "URL", "http://:80", &error), NULL); sml_fail_unless(error == NULL, NULL); /* The transport is not configured but libsoup can initialize a default client */ sml_fail_unless(smlTransportInitialize(tsp, &error), "%s", smlErrorPrint(&error)); sml_fail_unless(error == NULL, "%s", smlErrorPrint(&error)); sml_fail_unless(smlTransportFinalize(tsp, &error), "%s", smlErrorPrint(&error)); sml_fail_unless(error == NULL, "%s", smlErrorPrint(&error)); smlTransportFree(tsp); } END_TEST START_TEST (http_server_new) { reset_testbed(); SmlError *error = NULL; SmlTransport *tsp = smlTransportNew(SML_TRANSPORT_HTTP_SERVER, &error); sml_fail_unless(tsp != NULL, NULL); sml_fail_unless(error == NULL, NULL); smlTransportFree(tsp); } END_TEST SmlBool _recv_client_event(SmlTransport *tsp, SmlLink *link_, SmlTransportEventType type, SmlTransportData *data, SmlError *error, void *userdata) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %d)", __func__, tsp, link_, type); sml_fail_unless(GPOINTER_TO_INT(userdata) == 1, NULL); switch (type) { case SML_TRANSPORT_EVENT_CONNECT_DONE: g_atomic_int_inc(&client_connects); break; case SML_TRANSPORT_EVENT_DISCONNECT_DONE: g_atomic_int_inc(&client_disconnects); break; case SML_TRANSPORT_EVENT_DATA: sml_fail_unless(!strcmp(data->data, "answer"), NULL); sml_fail_unless(data->size == 7, NULL); sml_fail_unless(data->type == SML_MIMETYPE_WBXML, NULL); g_atomic_int_inc(&client_receives); break; case SML_TRANSPORT_EVENT_ERROR: sml_fail_unless(error != NULL, NULL); g_atomic_int_inc(&client_errors); break; default: sml_fail_unless(FALSE, "An unexpected transport event %d was received.", type); break; } smlTrace(TRACE_EXIT, "%s()", __func__); return TRUE; } SmlBool _recv_server_event(SmlTransport *tsp, SmlLink *link_, SmlTransportEventType type, SmlTransportData *data, SmlError *error, void *userdata) { smlTrace(TRACE_ENTRY, "%s(%p, %d, %p)", __func__, link_, type, error); SmlError *locerror = NULL; SmlLink *last = NULL; switch (type) { case SML_TRANSPORT_EVENT_CONNECT_DONE: g_atomic_int_inc(&server_connects); links = g_list_append(links, link_); smlLinkRef(link_); break; case SML_TRANSPORT_EVENT_DISCONNECT_DONE: /* only real connections must be managed */ last = g_list_nth_data(links, g_list_length(links)-1); sml_fail_unless(last == link_, "The disconnected links do not match."); links = g_list_remove(links, last); smlLinkDeref(last); g_atomic_int_inc(&server_disconnects); break; case SML_TRANSPORT_EVENT_DATA: g_atomic_int_inc(&server_receives); if (!strcmp(data->data, "test")) { sml_fail_unless(data->size == 5, NULL); sml_fail_unless(data->type == SML_MIMETYPE_XML, NULL); sml_fail_unless(link_ != NULL, NULL); if (GPOINTER_TO_INT(userdata) == 1) { data = smlTransportDataNew((char *)"answer", 7, SML_MIMETYPE_WBXML, FALSE, &locerror); sml_fail_unless(data != NULL, NULL); sml_fail_unless(locerror == NULL, "%s", smlErrorPrint(&locerror)); sml_fail_unless(smlTransportSend(tsp, link_, data, &locerror), "%s", smlErrorPrint(&locerror)); smlTransportDataDeref(data); } else if (GPOINTER_TO_INT(userdata) == 2) { SmlError *newerror = NULL; smlErrorSet(&newerror, SML_ERROR_GENERIC, "test"); smlTransportSetError(tsp, link_, &newerror); smlErrorDeref(&newerror); } else if (GPOINTER_TO_INT(userdata) == 3) { sml_fail_unless(smlTransportDisconnect(tsp, link_, &locerror), "%s", smlErrorPrint(&locerror)); } else { sml_fail_unless(FALSE, "Some unexpected userdata %i was detected.", GPOINTER_TO_INT(userdata)); } } else if (!strcmp(data->data, "error")) { sml_fail_unless(data->size == 6, NULL); sml_fail_unless(data->type == SML_MIMETYPE_XML, NULL); sml_fail_unless(link_ != NULL, NULL); SmlError *newerror = NULL; smlErrorSet(&newerror, SML_ERROR_GENERIC, "test2"); smlTransportSetError(tsp, link_, &newerror); smlErrorDeref(&newerror); } else { sml_fail_unless(FALSE, "The received data was not expected (%s).", data->data); } break; default: sml_fail_unless(FALSE, "An unexpected transport event %d was received.", type); break; } smlTrace(TRACE_EXIT, "%s()", __func__); return TRUE; } START_TEST (http_server_init) { reset_testbed(); SmlError *error = NULL; SmlTransport *tsp = smlTransportNew(SML_TRANSPORT_HTTP_SERVER, &error); sml_fail_unless(tsp != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlTransportSetConfigOption(tsp, "PORT", "32425", &error), NULL); sml_fail_unless(smlTransportSetConfigOption(tsp, "URL", "/test", &error), NULL); smlTransportSetEventCallback(tsp, _recv_server_event, GINT_TO_POINTER(1)); sml_fail_unless(smlTransportInitialize(tsp, &error), "%s", smlErrorPrint(&error)); sml_fail_unless(error == NULL, "%s", smlErrorPrint(&error)); sml_fail_unless(smlTransportFinalize(tsp, &error), NULL); sml_fail_unless(error == NULL, NULL); smlTransportFree(tsp); } END_TEST START_TEST (http_server_wrong_port) { reset_testbed(); SmlError *error = NULL; SmlTransport *tsp = smlTransportNew(SML_TRANSPORT_HTTP_SERVER, &error); sml_fail_unless(tsp != NULL, NULL); sml_fail_unless(error == NULL, NULL); /* -1 is an illegal port. */ sml_fail_unless(smlTransportSetConfigOption(tsp, "PORT", "-1", &error) == FALSE, NULL); sml_fail_unless(error != NULL, NULL); smlErrorDeref(&error); /* The default config of libsoup can be used to setup a valid transport. */ sml_fail_unless(smlTransportInitialize(tsp, &error), "%s", smlErrorPrint(&error)); sml_fail_unless(error == NULL, "%s", smlErrorPrint(&error)); sml_fail_unless(smlTransportFinalize(tsp, &error), NULL); sml_fail_unless(error == NULL, NULL); smlTransportFree(tsp); } END_TEST START_TEST (http_connect) { reset_testbed(); SmlError *error = NULL; SmlTransport *server = smlTransportNew(SML_TRANSPORT_HTTP_SERVER, &error); SmlTransport *client = smlTransportNew(SML_TRANSPORT_HTTP_CLIENT, &error); sml_fail_unless(smlTransportSetConfigOption(client, "URL", "http://127.0.0.1:10008", &error), NULL); sml_fail_unless(smlTransportSetConfigOption(server, "PORT", "10008", &error), NULL); smlTransportSetEventCallback(client, _recv_client_event, GINT_TO_POINTER(1)); smlTransportSetEventCallback(server, _recv_server_event, GINT_TO_POINTER(1)); sml_fail_unless(smlTransportInitialize(client, &error), "%s", smlErrorPrint(&error)); sml_fail_unless(smlTransportInitialize(server, &error), "%s", smlErrorPrint(&error)); sml_fail_unless(smlTransportConnect(client, &error), NULL); sml_fail_unless(error == NULL, NULL); while (client_connects == 0) { usleep(50); }; sml_fail_unless(client_connects == 1, NULL); sml_fail_unless(client_disconnects == 0, NULL); /* disconnect the client */ sml_fail_unless(smlTransportDisconnect(client, NULL, &error), "%s", smlErrorPrint(&error)); sml_fail_unless(error == NULL, NULL); while (client_disconnects == 0) { usleep(50); }; sml_fail_unless(client_connects == 1, NULL); sml_fail_unless(client_disconnects == 1, NULL); /* cleanup the transports */ sml_fail_unless(smlTransportFinalize(server, &error), NULL); sml_fail_unless(smlTransportFinalize(client, &error), NULL); smlTransportFree(server); smlTransportFree(client); } END_TEST START_TEST (http_send) { reset_testbed(); SmlError *error = NULL; SmlTransport *server = smlTransportNew(SML_TRANSPORT_HTTP_SERVER, &error); SmlTransport *client = smlTransportNew(SML_TRANSPORT_HTTP_CLIENT, &error); sml_fail_unless(smlTransportSetConfigOption(client, "URL", "http://127.0.0.1:10009", &error), NULL); sml_fail_unless(smlTransportSetConfigOption(server, "PORT", "10009", &error), NULL); smlTransportSetEventCallback(server, _recv_server_event, GINT_TO_POINTER(1)); smlTransportSetEventCallback(client, _recv_client_event, GINT_TO_POINTER(1)); sml_fail_unless(smlTransportInitialize(client, &error), "%s", smlErrorPrint(&error)); sml_fail_unless(smlTransportInitialize(server, &error), "%s", smlErrorPrint(&error)); SmlTransportData *data = smlTransportDataNew((char *)"test", 5, SML_MIMETYPE_XML, FALSE, &error); sml_fail_unless(data != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlTransportSend(client, NULL, data, &error), NULL); sml_fail_unless(error == NULL, NULL); smlTransportDataDeref(data); while(client_connects < 1) { usleep(50); } /* disconnect client */ sml_fail_unless(smlTransportDisconnect(client, NULL, &error), "%s", smlErrorPrint(&error)); while(client_disconnects < 1) { usleep(50); } /* disconnect server */ sml_fail_unless(smlTransportDisconnect(server, g_list_nth_data(links, 0), &error), NULL); while(server_disconnects < 1) { usleep(50); } /* cleanup transports */ sml_fail_unless(smlTransportFinalize(server, &error), NULL); sml_fail_unless(smlTransportFinalize(client, &error), NULL); smlTransportFree(server); smlTransportFree(client); } END_TEST START_TEST (http_receive) { reset_testbed(); SmlError *error = NULL; SmlTransport *server = smlTransportNew(SML_TRANSPORT_HTTP_SERVER, &error); SmlTransport *client = smlTransportNew(SML_TRANSPORT_HTTP_CLIENT, &error); sml_fail_unless(smlTransportSetConfigOption(client, "URL", "http://127.0.0.1:10010", &error), NULL); sml_fail_unless(smlTransportSetConfigOption(server, "PORT", "10010", &error), NULL); smlTransportSetEventCallback(server, _recv_server_event, GINT_TO_POINTER(3)); smlTransportSetEventCallback(client, _recv_client_event, GINT_TO_POINTER(1)); sml_fail_unless(smlTransportInitialize(client, &error), "%s", smlErrorPrint(&error)); sml_fail_unless(smlTransportInitialize(server, &error), "%s", smlErrorPrint(&error)); SmlTransportData *data = smlTransportDataNew((char *)"test", 5, SML_MIMETYPE_XML, FALSE, &error); sml_fail_unless(data != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlTransportSend(client, NULL, data, &error), NULL); sml_fail_unless(error == NULL, NULL); smlTransportDataDeref(data); while (server_receives < 1) { usleep(100); } sml_fail_unless(server_connects == 1, NULL); sml_fail_unless(server_receives == 1, NULL); /* the client must not be disconnected * because the server does not accept the connection */ while(server_disconnects < 1) { usleep(50); } /* cleanup transports */ sml_fail_unless(smlTransportFinalize(server, &error), NULL); sml_fail_unless(smlTransportFinalize(client, &error), NULL); smlTransportFree(server); smlTransportFree(client); } END_TEST START_TEST (http_reply) { reset_testbed(); SmlError *error = NULL; SmlTransport *server = smlTransportNew(SML_TRANSPORT_HTTP_SERVER, &error); SmlTransport *client = smlTransportNew(SML_TRANSPORT_HTTP_CLIENT, &error); sml_fail_unless(smlTransportSetConfigOption(client, "URL", "http://127.0.0.1:10011", &error), NULL); sml_fail_unless(smlTransportSetConfigOption(server, "PORT", "10011", &error), NULL); smlTransportSetEventCallback(client, _recv_client_event, GINT_TO_POINTER(1)); smlTransportSetEventCallback(server, _recv_server_event, GINT_TO_POINTER(1)); sml_fail_unless(smlTransportInitialize(client, &error), "%s", smlErrorPrint(&error)); sml_fail_unless(smlTransportInitialize(server, &error), "%s", smlErrorPrint(&error)); SmlTransportData *data = smlTransportDataNew((char *)"test", 5, SML_MIMETYPE_XML, FALSE, &error); sml_fail_unless(data != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlTransportSend(client, NULL, data, &error), NULL); sml_fail_unless(error == NULL, NULL); smlTransportDataDeref(data); while (client_receives < 1) { usleep(100); } sml_fail_unless(client_receives == 1, NULL); sml_fail_unless(server_receives == 1, NULL); /* disconnect client */ sml_fail_unless(smlTransportDisconnect(client, NULL, &error), "%s", smlErrorPrint(&error)); while(client_disconnects < 1) { usleep(50); } /* disconnect server */ sml_fail_unless(smlTransportDisconnect(server, g_list_nth_data(links, 0), &error), NULL); while(server_disconnects < 1) { usleep(50); } /* cleanup transports */ sml_fail_unless(smlTransportFinalize(server, &error), NULL); sml_fail_unless(smlTransportFinalize(client, &error), NULL); smlTransportFree(server); smlTransportFree(client); } END_TEST START_TEST (http_talk) { reset_testbed(); SmlError *error = NULL; SmlTransport *server = smlTransportNew(SML_TRANSPORT_HTTP_SERVER, &error); SmlTransport *client = smlTransportNew(SML_TRANSPORT_HTTP_CLIENT, &error); sml_fail_unless(smlTransportSetConfigOption(client, "URL", "http://127.0.0.1:10012", &error), NULL); sml_fail_unless(smlTransportSetConfigOption(server, "PORT", "10012", &error), NULL); smlTransportSetEventCallback(client, _recv_client_event, GINT_TO_POINTER(1)); smlTransportSetEventCallback(server, _recv_server_event, GINT_TO_POINTER(1)); sml_fail_unless(smlTransportInitialize(client, &error), "%s", smlErrorPrint(&error)); sml_fail_unless(smlTransportInitialize(server, &error), "%s", smlErrorPrint(&error)); SmlTransportData *data = NULL; int i; for (i = 0; i < 20; i++) { data = smlTransportDataNew((char *)"test", 5, SML_MIMETYPE_XML, FALSE, &error); sml_fail_unless(data != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlTransportSend(client, NULL, data, &error), NULL); sml_fail_unless(error == NULL, NULL); smlTransportDataDeref(data); while (1) { usleep(100); if (client_receives == i+1) break; } } sml_fail_unless(client_receives == 20, NULL); sml_fail_unless(server_receives == 20, NULL); /* disconnect client */ sml_fail_unless(smlTransportDisconnect(client, NULL, &error), "%s", smlErrorPrint(&error)); while(client_disconnects < 1) { usleep(50); } /* disconnect server */ for (i = 0; i < 20; i++) { /* start to disconnect from the end * to avoid conflicts with very fast SMP machines * which can process disconnects so fast * that the list will be cleaned up before * this for-loop ends */ smlTrace(TRACE_INTERNAL, "%s: Perparing next disconnect", __func__); sml_fail_unless(smlTransportDisconnect(server, g_list_nth_data(links, 19-i), &error), NULL); while(server_disconnects < i+1) { usleep(100); } } /* cleanup transports */ sml_fail_unless(smlTransportFinalize(server, &error), NULL); sml_fail_unless(smlTransportFinalize(client, &error), NULL); smlTransportFree(server); smlTransportFree(client); } END_TEST START_TEST (http_connect_error) { reset_testbed(); SmlError *error = NULL; SmlTransport *client = smlTransportNew(SML_TRANSPORT_HTTP_CLIENT, &error); sml_fail_unless(smlTransportSetConfigOption(client, "URL", "http://127.0.0.1:10013", &error), NULL); smlTransportSetEventCallback(client, _recv_client_event, GINT_TO_POINTER(1)); sml_fail_unless(smlTransportInitialize(client, &error), "%s", smlErrorPrint(&error)); SmlTransportData *data = smlTransportDataNew((char *)"test", 5, SML_MIMETYPE_XML, FALSE, &error); sml_fail_unless(data != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlTransportSend(client, NULL, data, &error), NULL); sml_fail_unless(error == NULL, NULL); smlTransportDataDeref(data); while (client_errors == 0) { usleep(100); }; sml_fail_unless(client_connects == 0, NULL); sml_fail_unless(client_disconnects == 0, NULL); sml_fail_unless(client_receives == 0, NULL); sml_fail_unless(client_errors == 1, NULL); sml_fail_unless(smlTransportFinalize(client, &error), NULL); smlTransportFree(client); } END_TEST START_TEST (http_reject) { reset_testbed(); SmlError *error = NULL; SmlTransport *server = smlTransportNew(SML_TRANSPORT_HTTP_SERVER, &error); SmlTransport *client = smlTransportNew(SML_TRANSPORT_HTTP_CLIENT, &error); sml_fail_unless(smlTransportSetConfigOption(client, "URL", "http://127.0.0.1:10014", &error), NULL); sml_fail_unless(smlTransportSetConfigOption(server, "PORT", "10014", &error), NULL); smlTransportSetEventCallback(client, _recv_client_event, GINT_TO_POINTER(1)); smlTransportSetEventCallback(server, _recv_server_event, GINT_TO_POINTER(2)); sml_fail_unless(smlTransportInitialize(client, &error), "%s", smlErrorPrint(&error)); sml_fail_unless(smlTransportInitialize(server, &error), "%s", smlErrorPrint(&error)); SmlTransportData *data = smlTransportDataNew((char *)"test", 5, SML_MIMETYPE_XML, FALSE, &error); sml_fail_unless(data != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlTransportSend(client, NULL, data, &error), NULL); sml_fail_unless(error == NULL, NULL); smlTransportDataDeref(data); while (server_receives == 0) { usleep(100); }; sml_fail_unless(server_receives == 1, NULL); while (client_errors == 0) { usleep(100); }; sml_fail_unless(smlTransportDisconnect(server, g_list_nth_data(links, 0), &error), NULL); while (server_disconnects == 0) { usleep(100); }; sml_fail_unless(client_connects == 0, NULL); sml_fail_unless(client_disconnects == 0, NULL); sml_fail_unless(client_receives == 0, NULL); sml_fail_unless(client_errors == 1, NULL); sml_fail_unless(server_disconnects == 1, NULL); sml_fail_unless(smlTransportFinalize(client, &error), NULL); sml_fail_unless(smlTransportFinalize(server, &error), "%s", smlErrorPrint(&error)); smlTransportFree(client); smlTransportFree(server); } END_TEST START_TEST (http_multi_connect) { reset_testbed(); SmlError *error = NULL; SmlTransport *server = smlTransportNew(SML_TRANSPORT_HTTP_SERVER, &error); SmlTransport *client1 = smlTransportNew(SML_TRANSPORT_HTTP_CLIENT, &error); SmlTransport *client2 = smlTransportNew(SML_TRANSPORT_HTTP_CLIENT, &error); SmlTransport *client3 = smlTransportNew(SML_TRANSPORT_HTTP_CLIENT, &error); sml_fail_unless(smlTransportSetConfigOption(client1, "URL", "http://127.0.0.1:10015", &error), NULL); sml_fail_unless(smlTransportSetConfigOption(client2, "URL", "http://127.0.0.1:10015", &error), NULL); sml_fail_unless(smlTransportSetConfigOption(client3, "URL", "http://127.0.0.1:10015", &error), NULL); sml_fail_unless(smlTransportSetConfigOption(server, "PORT", "10015", &error), NULL); smlTransportSetEventCallback(client1, _recv_client_event, GINT_TO_POINTER(1)); smlTransportSetEventCallback(client2, _recv_client_event, GINT_TO_POINTER(1)); smlTransportSetEventCallback(client3, _recv_client_event, GINT_TO_POINTER(1)); smlTransportSetEventCallback(server, _recv_server_event, GINT_TO_POINTER(1)); sml_fail_unless(smlTransportInitialize(client1, &error), "%s", smlErrorPrint(&error)); sml_fail_unless(smlTransportInitialize(client2, &error), "%s", smlErrorPrint(&error)); sml_fail_unless(smlTransportInitialize(client3, &error), "%s", smlErrorPrint(&error)); sml_fail_unless(smlTransportInitialize(server, &error), "%s", smlErrorPrint(&error)); SmlTransportData *data = smlTransportDataNew((char *)"test", 5, SML_MIMETYPE_XML, FALSE, &error); sml_fail_unless(data != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlTransportSend(client1, NULL, data, &error), NULL); sml_fail_unless(error == NULL, NULL); smlTransportDataDeref(data); /* It is necessary to perform the first request alone * because otherwise the test can fail on Solaris * because Solaris uses an outdated libsoup 2.2. */ while (client_receives != 1) { usleep(100); } data = smlTransportDataNew((char *)"test", 5, SML_MIMETYPE_XML, FALSE, &error); sml_fail_unless(data != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlTransportSend(client2, NULL, data, &error), NULL); sml_fail_unless(error == NULL, NULL); smlTransportDataDeref(data); data = smlTransportDataNew((char *)"test", 5, SML_MIMETYPE_XML, FALSE, &error); sml_fail_unless(data != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlTransportSend(client3, NULL, data, &error), NULL); sml_fail_unless(error == NULL, NULL); smlTransportDataDeref(data); while (client_receives != 3) { usleep(100); } sml_fail_unless(client_receives == 3, NULL); sml_fail_unless(server_receives == 3, NULL); sml_fail_unless(smlTransportDisconnect(client1, NULL, &error), "%s", smlErrorPrint(&error)); sml_fail_unless(smlTransportDisconnect(client2, NULL, &error), "%s", smlErrorPrint(&error)); sml_fail_unless(smlTransportDisconnect(client3, NULL, &error), "%s", smlErrorPrint(&error)); while (client_disconnects < 3) { usleep(100); }; int i; for (i = g_list_length(links); i > 0; i--) { /* start to disconnect from the end * to avoid conflicts with very fast SMP machines * which can process disconnects so fast * that the list will be cleaned up before * this for-loop ends */ sml_fail_unless(smlTransportDisconnect(server, g_list_nth_data(links, i-1), &error), "%s", smlErrorPrint(&error)); while (server_disconnects < 3 - i + 1) { usleep(100); } } sml_fail_unless(client_connects == 3, NULL); sml_fail_unless(server_connects == 3, NULL); sml_fail_unless(client_disconnects == 3, NULL); sml_fail_unless(server_disconnects == 3, NULL); sml_fail_unless(smlTransportFinalize(server, &error), NULL); sml_fail_unless(smlTransportFinalize(client1, &error), NULL); sml_fail_unless(smlTransportFinalize(client2, &error), NULL); sml_fail_unless(smlTransportFinalize(client3, &error), NULL); smlTransportFree(server); smlTransportFree(client1); smlTransportFree(client2); smlTransportFree(client3); } END_TEST START_TEST (http_multi_partial_error) { reset_testbed(); SmlError *error = NULL; SmlTransport *server = smlTransportNew(SML_TRANSPORT_HTTP_SERVER, &error); SmlTransport *client1 = smlTransportNew(SML_TRANSPORT_HTTP_CLIENT, &error); SmlTransport *client2 = smlTransportNew(SML_TRANSPORT_HTTP_CLIENT, &error); SmlTransport *client3 = smlTransportNew(SML_TRANSPORT_HTTP_CLIENT, &error); sml_fail_unless(smlTransportSetConfigOption(client1, "URL", "http://127.0.0.1:10016", &error), NULL); sml_fail_unless(smlTransportSetConfigOption(client2, "URL", "http://127.0.0.1:10016", &error), NULL); sml_fail_unless(smlTransportSetConfigOption(client3, "URL", "http://127.0.0.1:10016", &error), NULL); sml_fail_unless(smlTransportSetConfigOption(server, "PORT", "10016", &error), NULL); smlTransportSetEventCallback(client1, _recv_client_event, GINT_TO_POINTER(1)); smlTransportSetEventCallback(client2, _recv_client_event, GINT_TO_POINTER(1)); smlTransportSetEventCallback(client3, _recv_client_event, GINT_TO_POINTER(1)); smlTransportSetEventCallback(server, _recv_server_event, GINT_TO_POINTER(1)); sml_fail_unless(smlTransportInitialize(client1, &error), "%s", smlErrorPrint(&error)); sml_fail_unless(smlTransportInitialize(client2, &error), "%s", smlErrorPrint(&error)); sml_fail_unless(smlTransportInitialize(client3, &error), "%s", smlErrorPrint(&error)); sml_fail_unless(smlTransportInitialize(server, &error), "%s", smlErrorPrint(&error)); SmlTransportData *data = smlTransportDataNew((char *)"test", 5, SML_MIMETYPE_XML, FALSE, &error); sml_fail_unless(data != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlTransportSend(client1, NULL, data, &error), NULL); sml_fail_unless(error == NULL, NULL); smlTransportDataDeref(data); /* It is necessary to perform the working request first * because otherwise the test can fail on Solaris * because Solaris uses an outdated libsoup 2.2. */ while (client_receives != 1) { usleep(100); } data = smlTransportDataNew((char *)"error", 6, SML_MIMETYPE_XML, FALSE, &error); sml_fail_unless(data != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlTransportSend(client2, NULL, data, &error), NULL); sml_fail_unless(error == NULL, NULL); smlTransportDataDeref(data); data = smlTransportDataNew((char *)"error", 6, SML_MIMETYPE_XML, FALSE, &error); sml_fail_unless(data != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlTransportSend(client3, NULL, data, &error), NULL); sml_fail_unless(error == NULL, NULL); smlTransportDataDeref(data); while (client_receives != 1 || client_errors != 2) { usleep(100); } sml_fail_unless(client_receives == 1, NULL); sml_fail_unless(client_errors == 2, NULL); sml_fail_unless(server_receives == 3, NULL); sml_fail_unless(smlTransportDisconnect(client1, NULL, &error), "%s", smlErrorPrint(&error)); while (client_disconnects < 1) { usleep(100); } int i; for (i = g_list_length(links); i > 0; i--) { /* start to disconnect from the end * to avoid conflicts with very fast SMP machines * which can process disconnects so fast * that the list will be cleaned up before * this for-loop ends */ sml_fail_unless(smlTransportDisconnect(server, g_list_nth_data(links, i-1), &error), "%s", smlErrorPrint(&error)); while (server_disconnects < 3 - i + 1) { usleep(100); } } sml_fail_unless(client_connects == 1, NULL); sml_fail_unless(server_connects == 3, NULL); sml_fail_unless(client_disconnects == 1, NULL); sml_fail_unless(server_disconnects == 3, NULL); sml_fail_unless(smlTransportFinalize(server, &error), NULL); sml_fail_unless(smlTransportFinalize(client1, &error), NULL); sml_fail_unless(smlTransportFinalize(client2, &error), NULL); sml_fail_unless(smlTransportFinalize(client3, &error), NULL); smlTransportFree(server); smlTransportFree(client1); smlTransportFree(client2); smlTransportFree(client3); } END_TEST START_TEST (http_multi_stress) { reset_testbed(); int num = 1000; SmlError *error = NULL; SmlTransport *server = smlTransportNew(SML_TRANSPORT_HTTP_SERVER, &error); SmlTransport *client1 = smlTransportNew(SML_TRANSPORT_HTTP_CLIENT, &error); SmlTransport *client2 = smlTransportNew(SML_TRANSPORT_HTTP_CLIENT, &error); SmlTransport *client3 = smlTransportNew(SML_TRANSPORT_HTTP_CLIENT, &error); sml_fail_unless(smlTransportSetConfigOption(client1, "URL", "http://127.0.0.1:10017", &error), NULL); sml_fail_unless(smlTransportSetConfigOption(client2, "URL", "http://127.0.0.1:10017", &error), NULL); sml_fail_unless(smlTransportSetConfigOption(client3, "URL", "http://127.0.0.1:10017", &error), NULL); sml_fail_unless(smlTransportSetConfigOption(server, "PORT", "10017", &error), NULL); smlTransportSetEventCallback(client1, _recv_client_event, GINT_TO_POINTER(1)); smlTransportSetEventCallback(client2, _recv_client_event, GINT_TO_POINTER(1)); smlTransportSetEventCallback(client3, _recv_client_event, GINT_TO_POINTER(1)); smlTransportSetEventCallback(server, _recv_server_event, GINT_TO_POINTER(1)); sml_fail_unless(smlTransportInitialize(client1, &error), "%s", smlErrorPrint(&error)); sml_fail_unless(smlTransportInitialize(client2, &error), "%s", smlErrorPrint(&error)); sml_fail_unless(smlTransportInitialize(client3, &error), "%s", smlErrorPrint(&error)); sml_fail_unless(smlTransportInitialize(server, &error), "%s", smlErrorPrint(&error)); SmlTransportData *data = NULL; int i; for (i = 0; i < num; i++) { data = smlTransportDataNew((char *)"test", 5, SML_MIMETYPE_XML, FALSE, &error); sml_fail_unless(data != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlTransportSend(client1, NULL, data, &error), NULL); sml_fail_unless(error == NULL, NULL); smlTransportDataDeref(data); /* It is necessary to perform the first request alone * because otherwise the test can fail on Solaris * because Solaris uses an outdated libsoup 2.2. */ while (client_receives < 1) { usleep(10); } data = smlTransportDataNew((char *)"test", 5, SML_MIMETYPE_XML, FALSE, &error); sml_fail_unless(data != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlTransportSend(client2, NULL, data, &error), NULL); sml_fail_unless(error == NULL, NULL); smlTransportDataDeref(data); data = smlTransportDataNew((char *)"test", 5, SML_MIMETYPE_XML, FALSE, &error); sml_fail_unless(data != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlTransportSend(client3, NULL, data, &error), NULL); sml_fail_unless(error == NULL, NULL); smlTransportDataDeref(data); while (1) { usleep(1); if (client_receives == (i+1)*3) break; } } sml_fail_unless(client_receives == 3 * num, NULL); sml_fail_unless(server_receives == 3 * num, NULL); sml_fail_unless(smlTransportDisconnect(client1, NULL, &error), "%s", smlErrorPrint(&error)); sml_fail_unless(smlTransportDisconnect(client2, NULL, &error), "%s", smlErrorPrint(&error)); sml_fail_unless(smlTransportDisconnect(client3, NULL, &error), "%s", smlErrorPrint(&error)); for (i = g_list_length(links); i > 0; i--) { /* start to disconnect from the end * to avoid conflicts with very fast SMP machines * which can process disconnects so fast * that the list will be cleaned up before * this for-loop ends */ sml_fail_unless(smlTransportDisconnect(server, g_list_nth_data(links, i-1), &error), "%s", smlErrorPrint(&error)); while (server_disconnects < (3 * num - i + 1)) { usleep(100); } } sml_fail_unless(client_connects == 3, NULL); sml_fail_unless(server_connects == 3 * num, NULL); sml_fail_unless(client_disconnects == 3, NULL); sml_fail_unless(server_disconnects == 3 * num, NULL); sml_fail_unless(smlTransportFinalize(server, &error), NULL); sml_fail_unless(smlTransportFinalize(client1, &error), NULL); sml_fail_unless(smlTransportFinalize(client2, &error), NULL); sml_fail_unless(smlTransportFinalize(client3, &error), NULL); smlTransportFree(server); smlTransportFree(client1); smlTransportFree(client2); smlTransportFree(client3); } END_TEST @SML_TESTCASE_CODE@ libsyncml-0.5.4/tests/support.c100644 1750 1750 13711 11211710410 16466 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2005 Armin Bauer * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include "support.h" #include #include #ifndef THREAD_SAFE_CHECK GStaticMutex __libsyncml_check_mutex = G_STATIC_MUTEX_INIT; #endif /* FIXME: These settings should be controlled by the test environment. * FIXME: The hard coding of the environment creates an unreal test scenario. * FIXME: The build host environment must be changed appropriately. */ void configure_environment() { /* Several libraries do things which confuse debuggers and * memory checkers like Valgrind. Therefore it is often * possible to configure such libraries via environment * variables to use a more conventional behaviour. * * If the user already set an environment variable * then this variable is not touched. */ /* The glib uses some memory caching mechanisms for performance * enhancements which confuses memory checkers like Valgrind. * Therefore it is necessary to deactivate these mechanisms for * testing. */ if (!g_setenv("G_SLICE", "always-malloc", FALSE)) g_warning("G_SLICE is already set."); if (!g_setenv("G_DEBUG", "gc-friendly", FALSE)) g_warning("G_DEBUG is already set."); /* The check library usually forks test suites to safely survive * things like segmentation faults and to have a clean separated * address space for every test suite. This behaviour makes it * difficult for memory checks like Valgrind to detect real * problems correctly. Usually you get tons of false positives. * Therefore forking is disabled. */ if (!g_setenv("CK_FORK", "no", FALSE)) g_warning("CK_FORK is already set."); xmlInitParser(); } void cleanup_environment() { xmlCleanupParser(); } char *olddir = NULL; char *setup_testbed(char *fkt_name) { char *testbed = NULL; setuid(65534); if (!g_thread_supported ()) g_thread_init (NULL); #ifndef THREAD_SAFE_CHECK /* unlock static mutex lock if locked from earlier error */ g_static_mutex_trylock(&__libsyncml_check_mutex); g_static_mutex_unlock(&__libsyncml_check_mutex); #endif if (fkt_name) { testbed = g_strdup_printf("%s/testbed.XXXXXX", g_get_tmp_dir()); if (mkdtemp(testbed)) { sml_fail_unless(FALSE, "Cannot setup testbed at %s.", testbed); } char *command = NULL; if (fkt_name) { command = g_strdup_printf("cp -R %s%sdata/%s/* %s", g_getenv("srcdir") ? g_getenv("srcdir") : "", g_getenv("srcdir") ? "/" : "", fkt_name, testbed); if (system(command)) { sml_fail_unless(FALSE, "Cannot execute command \"%s\".", command); } g_free(command); } olddir = g_get_current_dir(); if (chdir(testbed)) { sml_fail_unless(FALSE, "Cannot change to testbed directory %s.", testbed); } smlTrace(TRACE_INTERNAL, "%s: Seting up %s at %s", __func__, VA_STRING(fkt_name), VA_STRING(testbed)); } //printf("."); //fflush(NULL); return testbed; } void destroy_testbed(char *path) { char *command = g_strdup_printf("rm -rf %s", path); if (olddir && chdir(olddir)) { sml_fail_unless(FALSE, "Cannot change to old directory \"%s\".", olddir); } if (system(command)) { sml_fail_unless(FALSE, "Cannot execute command \"%s\".", command); } g_free(command); smlTrace(TRACE_INTERNAL, "%s: Tearing down %s", __func__, VA_STRING(path)); g_free(path); } void create_case(Suite *s, const char *name, TFun function) { TCase *tc_new = tcase_create(name); tcase_set_timeout(tc_new, 60); tcase_add_test(tc_new, function); suite_add_tcase (s, tc_new); } SmlParser *start_parser(const char *data, SmlError **error) { CHECK_ERROR_REF setup_testbed(NULL); SmlParser *parser = smlParserNew(SML_MIMETYPE_XML, 0, error); sml_fail_unless(parser != NULL, "%s", smlErrorPrint(error)); sml_fail_unless(*error == NULL, "%s", smlErrorPrint(error)); if (!smlParserStart(parser, data, strlen(data), error)) { sml_fail_unless(*error != NULL, "The parser start failed but the error object was not set."); smlParserFree(parser); return NULL; } return parser; } int sml_sleep(int64_t nanoseconds) { long seconds = nanoseconds / 1000000000; nanoseconds = nanoseconds % 1000000000; struct timespec timestr; timestr.tv_sec = seconds; timestr.tv_nsec = nanoseconds; return nanosleep(×tr, NULL); } /* create test case stuff */ static void sml_testsuite_all(Suite *s, struct sml_testcase_s *tc) { unsigned int i; for (i=0; tc[i].name; i++) create_case(s, tc[i].name, tc[i].func); } static unsigned int sml_testsuite_selected( Suite *s, int argc, char **argv, struct sml_testcase_s *tc) { int i, j, n=0; /* Also argv[0]! for symlink-ed calls */ for (i=0; argc > i; i++) { for (j=0; tc[j].name; j++) { if (strcmp(g_basename(argv[i]), tc[j].name)) continue; create_case(s, tc[j].name, tc[j].func); n++; } } return n; } int sml_testsuite( int argc, char **argv, const char *unittest, struct sml_testcase_s *tc) { configure_environment(); int nf; Suite *s = suite_create(unittest); SRunner *sr; /* check_env(); */ if (!sml_testsuite_selected(s, argc, argv, tc)) sml_testsuite_all(s, tc); sr = srunner_create(s); srunner_run_all(sr, CK_VERBOSE); nf = srunner_ntests_failed(sr); srunner_free(sr); cleanup_environment(); return (nf == 0) ? EXIT_SUCCESS : EXIT_FAILURE; } libsyncml-0.5.4/tests/check_wbxml_assembler.c100644 1750 1750 73207 11211710410 21303 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2005 Armin Bauer * Copyright (C) 2008 Michael Bell * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include "tests/support.h" #include #include #include static SmlAssembler *start_assembler(SmlSession *session, unsigned int limit) { setup_testbed(NULL); SmlError *error = NULL; SmlAssembler *assm = smlAssemblerNew(SML_MIMETYPE_WBXML, limit, &error); sml_fail_unless(assm != NULL, NULL); sml_fail_unless(error == NULL, NULL); if (!smlAssemblerStart(assm, session, &error)) { sml_fail_unless(error != NULL, NULL); smlAssemblerFree(assm); return NULL; } return assm; } START_TEST (wbxml_assembler_message_empty) { SmlError *error = NULL; SmlLocation *loc = smlLocationNew("/test", NULL, &error); sml_fail_unless(loc != NULL, NULL); sml_fail_unless(error == NULL, NULL); /* The session type must be SML_SESSION_TYPE_CLIENT * because servers of SyncML 1.1 or higher must send MaxMsgSize. */ SmlSession *session = smlSessionNew(SML_SESSION_TYPE_CLIENT, SML_MIMETYPE_XML, SML_VERSION_12, SML_PROTOCOL_SYNCML, loc, loc, "1", 0, &error); smlLocationUnref(loc); SmlAssembler *assm = start_assembler(session, 0); sml_fail_unless(assm != NULL, NULL); char *data = NULL; unsigned int size = 0; sml_fail_unless(!smlAssemblerRun(assm, &data, &size, NULL, TRUE, &error), NULL); sml_fail_unless(error != NULL, NULL); smlErrorDeref(&error); sml_fail_unless(smlAssemblerFlush(assm) == 1, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(!smlAssemblerRun(assm, &data, &size, NULL, TRUE, &error), NULL); sml_fail_unless(error != NULL, NULL); smlErrorDeref(&error); smlAssemblerFree(assm); smlSessionUnref(session); } END_TEST START_TEST (wbxml_assembler_message_only_header) { SmlError *error = NULL; SmlLocation *loc = smlLocationNew("/test", NULL, &error); sml_fail_unless(loc != NULL, NULL); sml_fail_unless(error == NULL, NULL); /* The session type must be SML_SESSION_TYPE_CLIENT * because servers of SyncML 1.1 or higher must send MaxMsgSize. */ SmlSession *session = smlSessionNew(SML_SESSION_TYPE_CLIENT, SML_MIMETYPE_XML, SML_VERSION_12, SML_PROTOCOL_SYNCML, loc, loc, "1", 0, &error); smlLocationUnref(loc); SmlAssembler *assm = start_assembler(session, 0); sml_fail_unless(assm != NULL, NULL); sml_fail_unless(smlAssemblerAddHeader(assm, session, &error), NULL); sml_fail_unless(error == NULL, NULL); char *data = NULL; unsigned int size = 0; sml_fail_unless(!smlAssemblerRun(assm, &data, &size, NULL, TRUE, &error), NULL); sml_fail_unless(error != NULL, NULL); smlErrorDeref(&error); sml_fail_unless(smlAssemblerFlush(assm) == 1, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(!smlAssemblerRun(assm, &data, &size, NULL, TRUE, &error), NULL); sml_fail_unless(error != NULL, NULL); smlErrorDeref(&error); smlAssemblerFree(assm); smlSessionUnref(session); } END_TEST START_TEST (wbxml_assembler_message_status) { SmlError *error = NULL; SmlLocation *loc = smlLocationNew("/test", NULL, &error); sml_fail_unless(loc != NULL, NULL); sml_fail_unless(error == NULL, NULL); /* The session type must be SML_SESSION_TYPE_CLIENT * because servers of SyncML 1.1 or higher must send MaxMsgSize. */ SmlSession *session = smlSessionNew(SML_SESSION_TYPE_CLIENT, SML_MIMETYPE_XML, SML_VERSION_12, SML_PROTOCOL_SYNCML, loc, loc, "1", 0, &error); smlLocationUnref(loc); SmlAssembler *assm = start_assembler(session, 0); sml_fail_unless(assm != NULL, NULL); sml_fail_unless(smlAssemblerReserveStatus(assm, 1, 1, 1, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlAssemblerAddHeader(assm, session, &error), NULL); sml_fail_unless(error == NULL, NULL); SmlStatus *status = smlStatusNew(SML_NO_ERROR, 1, 1, loc, loc, SML_COMMAND_TYPE_SYNC, &error); sml_fail_unless(status != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlAssemblerAddStatus(assm, status, &error) == SML_ASSEMBLER_RESULT_OK, NULL); sml_fail_unless(error == NULL, NULL); smlStatusUnref(status); char *data = NULL; unsigned int size = 0; sml_fail_unless(smlAssemblerRun(assm, &data, &size, NULL, TRUE, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(data != NULL, NULL); sml_fail_unless(size != 0, NULL); smlSafeCFree(&data); sml_fail_unless(smlAssemblerFlush(assm) == 1, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(!smlAssemblerRun(assm, &data, &size, NULL, TRUE, &error), NULL); sml_fail_unless(error != NULL, NULL); smlErrorDeref(&error); smlAssemblerFree(assm); smlSessionUnref(session); } END_TEST START_TEST (wbxml_assembler_message_cmd) { SmlError *error = NULL; SmlLocation *loc = smlLocationNew("/test", NULL, &error); sml_fail_unless(loc != NULL, NULL); sml_fail_unless(error == NULL, NULL); /* The session type must be SML_SESSION_TYPE_CLIENT * because servers of SyncML 1.1 or higher must send MaxMsgSize. */ SmlSession *session = smlSessionNew(SML_SESSION_TYPE_CLIENT, SML_MIMETYPE_XML, SML_VERSION_12, SML_PROTOCOL_SYNCML, loc, loc, "1", 0, &error); SmlAssembler *assm = start_assembler(session, 0); sml_fail_unless(assm != NULL, NULL); sml_fail_unless(smlAssemblerAddHeader(assm, session, &error), NULL); sml_fail_unless(error == NULL, NULL); SmlCommand *cmd = smlCommandNewAlert(SML_ALERT_TWO_WAY, loc, loc, "next", "last", NULL, &error); sml_fail_unless(cmd != NULL, NULL); sml_fail_unless(error == NULL, NULL); cmd->cmdID = 1; smlLocationUnref(loc); sml_fail_unless(smlAssemblerStartCommand(assm, NULL, cmd, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlAssemblerEndCommand(assm, NULL, &error), NULL); sml_fail_unless(error == NULL, NULL); smlCommandUnref(cmd); char *data = NULL; unsigned int size = 0; sml_fail_unless(smlAssemblerRun(assm, &data, &size, NULL, TRUE, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(data != NULL, NULL); sml_fail_unless(size != 0, NULL); char *buffer = NULL; size_t buffer_size = 0; sml_fail_unless(smlWbxmlConvertFrom(NULL, data, size, &buffer, &buffer_size, &error), NULL); sml_fail_unless(buffer != NULL, NULL); sml_fail_unless(error == NULL, NULL); smlSafeCFree(&data); smlSafeCFree(&buffer); sml_fail_unless(smlAssemblerFlush(assm) == 1, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(!smlAssemblerRun(assm, &data, &size, NULL, TRUE, &error), NULL); sml_fail_unless(error != NULL, NULL); smlErrorDeref(&error); smlAssemblerFree(assm); smlSessionUnref(session); } END_TEST START_TEST (wbxml_assembler_message_subcmd) { SmlError *error = NULL; SmlLocation *loc = smlLocationNew("/test", NULL, &error); sml_fail_unless(loc != NULL, NULL); sml_fail_unless(error == NULL, NULL); /* The session type must be SML_SESSION_TYPE_CLIENT * because servers of SyncML 1.1 or higher must send MaxMsgSize. */ SmlSession *session = smlSessionNew(SML_SESSION_TYPE_CLIENT, SML_MIMETYPE_XML, SML_VERSION_12, SML_PROTOCOL_SYNCML, loc, loc, "1", 0, &error); SmlAssembler *assm = start_assembler(session, 0); sml_fail_unless(assm != NULL, NULL); sml_fail_unless(smlAssemblerAddHeader(assm, session, &error), NULL); sml_fail_unless(error == NULL, NULL); SmlCommand *cmd1 = smlCommandNewSync(loc, loc, 0, &error); sml_fail_unless(cmd1 != NULL, NULL); sml_fail_unless(error == NULL, NULL); cmd1->cmdID = 1; smlLocationUnref(loc); sml_fail_unless(smlAssemblerStartCommand(assm, NULL, cmd1, &error), NULL); sml_fail_unless(error == NULL, NULL); SmlCommand *cmd2 = smlCommandNewChange(SML_CHANGE_ADD, "uid", "data", 5, SML_ELEMENT_TEXT_VCARD, &error); sml_fail_unless(cmd2 != NULL, NULL); sml_fail_unless(error == NULL, NULL); cmd2->cmdID = 2; sml_fail_unless(smlAssemblerStartCommand(assm, cmd1, cmd2, &error), NULL); sml_fail_unless(error == NULL, NULL); smlCommandUnref(cmd2); sml_fail_unless(smlAssemblerEndCommand(assm, cmd1, &error), NULL); sml_fail_unless(error == NULL, NULL); smlCommandUnref(cmd1); sml_fail_unless(smlAssemblerEndCommand(assm, NULL, &error), NULL); sml_fail_unless(error == NULL, NULL); char *data = NULL; unsigned int size = 0; sml_fail_unless(smlAssemblerRun(assm, &data, &size, NULL, TRUE, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(data != NULL, NULL); sml_fail_unless(size != 0, NULL); smlSafeCFree(&data); sml_fail_unless(smlAssemblerFlush(assm) == 1, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(!smlAssemblerRun(assm, &data, &size, NULL, TRUE, &error), NULL); sml_fail_unless(error != NULL, NULL); smlErrorDeref(&error); smlAssemblerFree(assm); smlSessionUnref(session); } END_TEST START_TEST (wbxml_assembler_message_several_subcmd) { SmlError *error = NULL; SmlLocation *loc = smlLocationNew("/test", NULL, &error); sml_fail_unless(loc != NULL, NULL); sml_fail_unless(error == NULL, NULL); /* The session type must be SML_SESSION_TYPE_CLIENT * because servers of SyncML 1.1 or higher must send MaxMsgSize. */ SmlSession *session = smlSessionNew(SML_SESSION_TYPE_CLIENT, SML_MIMETYPE_XML, SML_VERSION_12, SML_PROTOCOL_SYNCML, loc, loc, "1", 0, &error); SmlAssembler *assm = start_assembler(session, 0); sml_fail_unless(assm != NULL, NULL); sml_fail_unless(smlAssemblerAddHeader(assm, session, &error), NULL); sml_fail_unless(error == NULL, NULL); SmlCommand *cmd1 = smlCommandNewSync(loc, loc, 0, &error); sml_fail_unless(cmd1 != NULL, NULL); sml_fail_unless(error == NULL, NULL); cmd1->cmdID = 1; sml_fail_unless(smlAssemblerStartCommand(assm, NULL, cmd1, &error), NULL); sml_fail_unless(error == NULL, NULL); SmlCommand *cmd2 = smlCommandNewChange(SML_CHANGE_ADD, "uid", "data", 5, SML_ELEMENT_TEXT_VCARD, &error); cmd2->cmdID = 2; sml_fail_unless(smlAssemblerStartCommand(assm, cmd1, cmd2, &error), NULL); sml_fail_unless(error == NULL, NULL); smlCommandUnref(cmd2); sml_fail_unless(smlAssemblerEndCommand(assm, cmd1, &error), NULL); sml_fail_unless(error == NULL, NULL); cmd2 = smlCommandNewChange(SML_CHANGE_ADD, "uid2", "data2", 5, SML_ELEMENT_TEXT_VCARD, &error); cmd2->cmdID = 3; sml_fail_unless(smlAssemblerStartCommand(assm, cmd1, cmd2, &error), NULL); sml_fail_unless(error == NULL, NULL); smlCommandUnref(cmd2); sml_fail_unless(smlAssemblerEndCommand(assm, cmd1, &error), NULL); sml_fail_unless(error == NULL, NULL); smlCommandUnref(cmd1); sml_fail_unless(smlAssemblerEndCommand(assm, NULL, &error), NULL); sml_fail_unless(error == NULL, NULL); cmd1 = smlCommandNewSync(loc, loc, 0, &error); sml_fail_unless(cmd1 != NULL, NULL); sml_fail_unless(error == NULL, NULL); cmd1->cmdID = 4; smlLocationUnref(loc); sml_fail_unless(smlAssemblerStartCommand(assm, NULL, cmd1, &error), NULL); sml_fail_unless(error == NULL, NULL); cmd2 = smlCommandNewChange(SML_CHANGE_ADD, "uid", "data", 5, SML_ELEMENT_TEXT_VCARD, &error); cmd2->cmdID = 5; sml_fail_unless(smlAssemblerStartCommand(assm, cmd1, cmd2, &error), NULL); sml_fail_unless(error == NULL, NULL); smlCommandUnref(cmd2); sml_fail_unless(smlAssemblerEndCommand(assm, cmd1, &error), NULL); sml_fail_unless(error == NULL, NULL); cmd2 = smlCommandNewChange(SML_CHANGE_ADD, "uid2", "data2", 5, SML_ELEMENT_TEXT_VCARD, &error); cmd2->cmdID = 6; sml_fail_unless(smlAssemblerStartCommand(assm, cmd1, cmd2, &error), NULL); sml_fail_unless(error == NULL, NULL); smlCommandUnref(cmd2); sml_fail_unless(smlAssemblerEndCommand(assm, cmd1, &error), NULL); sml_fail_unless(error == NULL, NULL); smlCommandUnref(cmd1); sml_fail_unless(smlAssemblerEndCommand(assm, NULL, &error), NULL); sml_fail_unless(error == NULL, NULL); char *data = NULL; unsigned int size = 0; sml_fail_unless(smlAssemblerRun(assm, &data, &size, NULL, TRUE, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(data != NULL, NULL); sml_fail_unless(size != 0, NULL); smlSafeCFree(&data); sml_fail_unless(smlAssemblerFlush(assm) == 1, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(!smlAssemblerRun(assm, &data, &size, NULL, TRUE, &error), NULL); sml_fail_unless(error != NULL, NULL); smlErrorDeref(&error); smlAssemblerFree(assm); smlSessionUnref(session); } END_TEST START_TEST (wbxml_assembler_message_flush_open) { SmlError *error = NULL; SmlLocation *loc = smlLocationNew("/test", NULL, &error); sml_fail_unless(loc != NULL, NULL); sml_fail_unless(error == NULL, NULL); /* The session type must be SML_SESSION_TYPE_CLIENT * because servers of SyncML 1.1 or higher must send MaxMsgSize. */ SmlSession *session = smlSessionNew(SML_SESSION_TYPE_CLIENT, SML_MIMETYPE_XML, SML_VERSION_12, SML_PROTOCOL_SYNCML, loc, loc, "1", 0, &error); SmlAssembler *assm = start_assembler(session, 0); sml_fail_unless(assm != NULL, NULL); sml_fail_unless(smlAssemblerAddHeader(assm, session, &error), NULL); sml_fail_unless(error == NULL, NULL); SmlCommand *cmd1 = smlCommandNewSync(loc, loc, 0, &error); sml_fail_unless(cmd1 != NULL, NULL); sml_fail_unless(error == NULL, NULL); cmd1->cmdID = 1; smlLocationUnref(loc); sml_fail_unless(smlAssemblerStartCommand(assm, NULL, cmd1, &error), NULL); sml_fail_unless(error == NULL, NULL); SmlCommand *cmd2 = smlCommandNewChange(SML_CHANGE_ADD, "uid", "data", 5, SML_ELEMENT_TEXT_VCARD, &error); cmd2->cmdID = 2; sml_fail_unless(smlAssemblerStartCommand(assm, cmd1, cmd2, &error), NULL); sml_fail_unless(error == NULL, NULL); smlCommandUnref(cmd2); sml_fail_unless(smlAssemblerEndCommand(assm, cmd1, &error), NULL); sml_fail_unless(error == NULL, NULL); char *data = NULL; unsigned int size = 0; sml_fail_unless(smlAssemblerRun(assm, &data, &size, NULL, FALSE, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(data != NULL, NULL); sml_fail_unless(size != 0, NULL); smlSafeCFree(&data); sml_fail_unless(smlAssemblerFlush(assm) == 1, NULL); sml_fail_unless(error == NULL, NULL); cmd2 = smlCommandNewChange(SML_CHANGE_ADD, "uid2", "data2", 5, SML_ELEMENT_TEXT_VCARD, &error); cmd2->cmdID = 3; sml_fail_unless(smlAssemblerStartCommand(assm, cmd1, cmd2, &error), NULL); sml_fail_unless(error == NULL, NULL); smlCommandUnref(cmd2); sml_fail_unless(smlAssemblerEndCommand(assm, cmd1, &error), NULL); sml_fail_unless(error == NULL, NULL); smlCommandUnref(cmd1); sml_fail_unless(smlAssemblerEndCommand(assm, NULL, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlAssemblerRun(assm, &data, &size, NULL, TRUE, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(data != NULL, NULL); sml_fail_unless(size != 0, NULL); smlSafeCFree(&data); sml_fail_unless(smlAssemblerFlush(assm) == 1, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(!smlAssemblerRun(assm, &data, &size, NULL, TRUE, &error), NULL); sml_fail_unless(error != NULL, NULL); smlErrorDeref(&error); smlAssemblerFree(assm); smlSessionUnref(session); } END_TEST START_TEST (wbxml_assembler_out_of_order) { SmlError *error = NULL; SmlLocation *loc = smlLocationNew("/test", NULL, &error); sml_fail_unless(loc != NULL, NULL); sml_fail_unless(error == NULL, NULL); /* The session type must be SML_SESSION_TYPE_CLIENT * because servers of SyncML 1.1 or higher must send MaxMsgSize. */ SmlSession *session = smlSessionNew(SML_SESSION_TYPE_CLIENT, SML_MIMETYPE_XML, SML_VERSION_12, SML_PROTOCOL_SYNCML, loc, loc, "1", 0, &error); SmlAssembler *assm = start_assembler(session, 0); sml_fail_unless(assm != NULL, NULL); sml_fail_unless(smlAssemblerAddHeader(assm, session, &error), NULL); sml_fail_unless(error == NULL, NULL); SmlCommand *cmd1 = smlCommandNewSync(loc, loc, 0, &error); sml_fail_unless(cmd1 != NULL, NULL); sml_fail_unless(error == NULL, NULL); cmd1->cmdID = 1; sml_fail_unless(smlAssemblerStartCommand(assm, NULL, cmd1, &error), NULL); sml_fail_unless(error == NULL, NULL); SmlCommand *cmd2 = smlCommandNewChange(SML_CHANGE_ADD, "uid", "data", 5, SML_ELEMENT_TEXT_VCARD, &error); cmd2->cmdID = 2; sml_fail_unless(smlAssemblerStartCommand(assm, cmd1, cmd2, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlAssemblerEndCommand(assm, cmd1, &error), NULL); sml_fail_unless(error == NULL, NULL); smlCommandUnref(cmd2); SmlCommand *cmd3 = smlCommandNewSync(loc, loc, 0, &error); sml_fail_unless(cmd3 != NULL, NULL); sml_fail_unless(error == NULL, NULL); cmd3->cmdID = 4; smlLocationUnref(loc); sml_fail_unless(smlAssemblerStartCommand(assm, NULL, cmd3, &error), NULL); sml_fail_unless(error == NULL, NULL); cmd2 = smlCommandNewChange(SML_CHANGE_ADD, "uid", "data", 5, SML_ELEMENT_TEXT_VCARD, &error); cmd2->cmdID = 5; sml_fail_unless(smlAssemblerStartCommand(assm, cmd3, cmd2, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlAssemblerEndCommand(assm, cmd3, &error), NULL); sml_fail_unless(error == NULL, NULL); smlCommandUnref(cmd2); cmd2 = smlCommandNewChange(SML_CHANGE_ADD, "uid2", "data2", 5, SML_ELEMENT_TEXT_VCARD, &error); cmd2->cmdID = 3; sml_fail_unless(smlAssemblerStartCommand(assm, cmd1, cmd2, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlAssemblerEndCommand(assm, cmd1, &error), NULL); sml_fail_unless(error == NULL, NULL); smlCommandUnref(cmd2); cmd2 = smlCommandNewChange(SML_CHANGE_ADD, "uid2", "data2", 5, SML_ELEMENT_TEXT_VCARD, &error); cmd2->cmdID = 6; sml_fail_unless(smlAssemblerStartCommand(assm, cmd3, cmd2, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlAssemblerEndCommand(assm, cmd3, &error), NULL); sml_fail_unless(error == NULL, NULL); smlCommandUnref(cmd2); sml_fail_unless(smlAssemblerEndCommand(assm, NULL, &error), NULL); sml_fail_unless(error == NULL, NULL); cmd2 = smlCommandNewChange(SML_CHANGE_ADD, "uid2", "data2", 5, SML_ELEMENT_TEXT_VCARD, &error); cmd2->cmdID = 7; sml_fail_unless(smlAssemblerStartCommand(assm, cmd3, cmd2, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlAssemblerEndCommand(assm, cmd3, &error), NULL); sml_fail_unless(error == NULL, NULL); smlCommandUnref(cmd2); sml_fail_unless(smlAssemblerEndCommand(assm, NULL, &error), NULL); sml_fail_unless(error == NULL, NULL); smlCommandUnref(cmd1); smlCommandUnref(cmd3); char *data = NULL; unsigned int size = 0; sml_fail_unless(smlAssemblerRun(assm, &data, &size, NULL, TRUE, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(data != NULL, NULL); sml_fail_unless(size != 0, NULL); smlSafeCFree(&data); sml_fail_unless(smlAssemblerFlush(assm) == 1, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(!smlAssemblerRun(assm, &data, &size, NULL, TRUE, &error), NULL); sml_fail_unless(error != NULL, NULL); smlErrorDeref(&error); smlAssemblerFree(assm); smlSessionUnref(session); } END_TEST START_TEST (wbxml_assembler_limit1) { SmlError *error = NULL; SmlLocation *loc = smlLocationNew("/test", NULL, &error); sml_fail_unless(loc != NULL, NULL); sml_fail_unless(error == NULL, NULL); /* The session type must be SML_SESSION_TYPE_CLIENT * because servers of SyncML 1.1 or higher must send MaxMsgSize. */ SmlSession *session = smlSessionNew(SML_SESSION_TYPE_CLIENT, SML_MIMETYPE_XML, SML_VERSION_12, SML_PROTOCOL_SYNCML, loc, loc, "1", 0, &error); SmlAssembler *assm = start_assembler(session, 1); sml_fail_unless(assm != NULL, NULL); sml_fail_unless(!smlAssemblerAddHeader(assm, session, &error), NULL); sml_fail_unless(error != NULL, NULL); smlErrorDeref(&error); char *data = NULL; unsigned int size = 0; sml_fail_unless(!smlAssemblerRun(assm, &data, &size, NULL, TRUE, &error), NULL); sml_fail_unless(error != NULL, NULL); smlErrorDeref(&error); smlAssemblerFree(assm); smlSessionUnref(session); } END_TEST START_TEST (wbxml_assembler_limit2) { SmlError *error = NULL; SmlLocation *loc = smlLocationNew("/test", NULL, &error); sml_fail_unless(loc != NULL, NULL); sml_fail_unless(error == NULL, NULL); /* The session type must be SML_SESSION_TYPE_CLIENT * because servers of SyncML 1.1 or higher must send MaxMsgSize. */ SmlSession *session = smlSessionNew(SML_SESSION_TYPE_CLIENT, SML_MIMETYPE_XML, SML_VERSION_12, SML_PROTOCOL_SYNCML, loc, loc, "1", 0, &error); SmlAssembler *assm = start_assembler(session, 50); sml_fail_unless(assm != NULL, NULL); sml_fail_unless(!smlAssemblerAddHeader(assm, session, &error), NULL); sml_fail_unless(error != NULL, NULL); smlErrorDeref(&error); char *data = NULL; unsigned int size = 0; sml_fail_unless(!smlAssemblerRun(assm, &data, &size, NULL, TRUE, &error), NULL); sml_fail_unless(error != NULL, NULL); smlErrorDeref(&error); smlAssemblerFree(assm); smlSessionUnref(session); } END_TEST START_TEST (wbxml_assembler_limit3) { SmlError *error = NULL; SmlLocation *loc = smlLocationNew("/test", NULL, &error); sml_fail_unless(loc != NULL, NULL); sml_fail_unless(error == NULL, NULL); /* The session type must be SML_SESSION_TYPE_CLIENT * because servers of SyncML 1.1 or higher must send MaxMsgSize. */ SmlSession *session = smlSessionNew(SML_SESSION_TYPE_CLIENT, SML_MIMETYPE_XML, SML_VERSION_12, SML_PROTOCOL_SYNCML, loc, loc, "1", 0, &error); SmlAssembler *assm = start_assembler(session, 100); sml_fail_unless(assm != NULL, NULL); sml_fail_unless(smlAssemblerReserveStatus(assm, 1, 1, 1, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlAssemblerAddHeader(assm, session, &error), NULL); sml_fail_unless(error == NULL, NULL); SmlStatus *status = smlStatusNew(SML_NO_ERROR, 1, 1, loc, loc, SML_COMMAND_TYPE_SYNC, &error); sml_fail_unless(status != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlAssemblerAddStatus(assm, status, &error) == SML_ASSEMBLER_RESULT_MISMATCH, NULL); sml_fail_unless(error == NULL, NULL); smlStatusUnref(status); char *data = NULL; unsigned int size = 0; sml_fail_unless(!smlAssemblerRun(assm, &data, &size, NULL, TRUE, &error), NULL); sml_fail_unless(error != NULL, NULL); smlErrorDeref(&error); smlAssemblerFree(assm); smlSessionUnref(session); } END_TEST START_TEST (wbxml_assembler_limit4) { SmlError *error = NULL; SmlLocation *loc = smlLocationNew("/test", NULL, &error); sml_fail_unless(loc != NULL, NULL); sml_fail_unless(error == NULL, NULL); /* The session type must be SML_SESSION_TYPE_CLIENT * because servers of SyncML 1.1 or higher must send MaxMsgSize. */ SmlSession *session = smlSessionNew(SML_SESSION_TYPE_CLIENT, SML_MIMETYPE_XML, SML_VERSION_12, SML_PROTOCOL_SYNCML, loc, loc, "1", 0, &error); SmlAssembler *assm = start_assembler(session, 380); sml_fail_unless(assm != NULL, NULL); sml_fail_unless(smlAssemblerReserveStatus(assm, 1, 1, 1, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlAssemblerAddHeader(assm, session, &error), NULL); sml_fail_unless(error == NULL, NULL); SmlStatus *status = smlStatusNew(SML_NO_ERROR, 1, 1, loc, loc, SML_COMMAND_TYPE_SYNC, &error); sml_fail_unless(status != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlAssemblerAddStatus(assm, status, &error) == SML_ASSEMBLER_RESULT_OK, NULL); sml_fail_unless(error == NULL, NULL); smlStatusUnref(status); char *data = NULL; unsigned int size = 0; sml_fail_unless(smlAssemblerRun(assm, &data, &size, NULL, TRUE, &error), NULL); sml_fail_unless(error == NULL, NULL); smlSafeCFree(&data); smlAssemblerFree(assm); smlSessionUnref(session); } END_TEST START_TEST (wbxml_assembler_limit5) { SmlError *error = NULL; SmlLocation *loc = smlLocationNew("/test", NULL, &error); sml_fail_unless(loc != NULL, NULL); sml_fail_unless(error == NULL, NULL); /* The session type must be SML_SESSION_TYPE_CLIENT * because servers of SyncML 1.1 or higher must send MaxMsgSize. */ SmlSession *session = smlSessionNew(SML_SESSION_TYPE_CLIENT, SML_MIMETYPE_XML, SML_VERSION_12, SML_PROTOCOL_SYNCML, loc, loc, "1", 0, &error); SmlAssembler *assm = start_assembler(session, 150); sml_fail_unless(assm != NULL, NULL); sml_fail_unless(smlAssemblerReserveStatus(assm, 1, 1, 1, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlAssemblerAddHeader(assm, session, &error), NULL); sml_fail_unless(error == NULL, NULL); SmlStatus *status = smlStatusNew(SML_NO_ERROR, 1, 1, loc, loc, SML_COMMAND_TYPE_SYNC, &error); sml_fail_unless(status != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlAssemblerAddStatus(assm, status, &error) == SML_ASSEMBLER_RESULT_OK, NULL); sml_fail_unless(error == NULL, NULL); smlStatusUnref(status); SmlCommand *cmd = smlCommandNewAlert(SML_ALERT_TWO_WAY, loc, loc, "next", "last", NULL, &error); sml_fail_unless(cmd != NULL, NULL); sml_fail_unless(error == NULL, NULL); cmd->cmdID = 1; smlLocationUnref(loc); sml_fail_unless(smlAssemblerStartCommand(assm, NULL, cmd, &error) == SML_ASSEMBLER_RESULT_MISMATCH, NULL); sml_fail_unless(error == NULL, NULL); char *data = NULL; unsigned int size = 0; sml_fail_unless(smlAssemblerRun(assm, &data, &size, NULL, FALSE, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(data != NULL, NULL); sml_fail_unless(size != 0, NULL); smlSafeCFree(&data); sml_fail_unless(smlAssemblerFlush(assm) == 1, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlAssemblerStartCommand(assm, NULL, cmd, &error) == SML_ASSEMBLER_RESULT_OK, NULL); sml_fail_unless(error == NULL, NULL); smlCommandUnref(cmd); sml_fail_unless(smlAssemblerEndCommand(assm, NULL, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlAssemblerRun(assm, &data, &size, NULL, TRUE, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(data != NULL, NULL); sml_fail_unless(size != 0, NULL); smlSafeCFree(&data); smlAssemblerFree(assm); smlSessionUnref(session); } END_TEST START_TEST (wbxml_assembler_complex1) { SmlError *error = NULL; SmlLocation *loc = smlLocationNew("/test", NULL, &error); sml_fail_unless(loc != NULL, NULL); sml_fail_unless(error == NULL, NULL); /* The session type must be SML_SESSION_TYPE_CLIENT * because servers of SyncML 1.1 or higher must send MaxMsgSize. */ SmlSession *session = smlSessionNew(SML_SESSION_TYPE_CLIENT, SML_MIMETYPE_XML, SML_VERSION_12, SML_PROTOCOL_SYNCML, loc, loc, "1", 0, &error); SmlAssembler *assm = start_assembler(session, 0); sml_fail_unless(assm != NULL, NULL); sml_fail_unless(smlAssemblerReserveStatus(assm, 1, 1, 1, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlAssemblerReserveStatus(assm, 2, 1, 2, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlAssemblerReserveStatus(assm, 3, 1, 3, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlAssemblerReserveStatus(assm, 4, 1, 4, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlAssemblerAddHeader(assm, session, &error), NULL); sml_fail_unless(error == NULL, NULL); SmlStatus *status = smlStatusNew(SML_NO_ERROR, 1, 1, loc, loc, SML_COMMAND_TYPE_SYNC, &error); sml_fail_unless(status != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlAssemblerAddStatus(assm, status, &error) == SML_ASSEMBLER_RESULT_OK, NULL); sml_fail_unless(error == NULL, NULL); smlStatusUnref(status); status = smlStatusNew(SML_NO_ERROR, 2, 1, loc, loc, SML_COMMAND_TYPE_SYNC, &error); sml_fail_unless(status != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlAssemblerAddStatus(assm, status, &error) == SML_ASSEMBLER_RESULT_OK, NULL); sml_fail_unless(error == NULL, NULL); smlStatusUnref(status); status = smlStatusNew(SML_NO_ERROR, 3, 1, loc, loc, SML_COMMAND_TYPE_SYNC, &error); sml_fail_unless(status != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlAssemblerAddStatus(assm, status, &error) == SML_ASSEMBLER_RESULT_OK, NULL); sml_fail_unless(error == NULL, NULL); smlStatusUnref(status); status = smlStatusNew(SML_NO_ERROR, 4, 1, loc, loc, SML_COMMAND_TYPE_SYNC, &error); sml_fail_unless(status != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlAssemblerAddStatus(assm, status, &error) == SML_ASSEMBLER_RESULT_OK, NULL); sml_fail_unless(error == NULL, NULL); smlStatusUnref(status); SmlCommand *cmd = smlCommandNewAlert(SML_ALERT_TWO_WAY, loc, loc, "next", "last", NULL, &error); sml_fail_unless(cmd != NULL, NULL); sml_fail_unless(error == NULL, NULL); cmd->cmdID = 5; smlLocationUnref(loc); sml_fail_unless(smlAssemblerStartCommand(assm, NULL, cmd, &error) == SML_ASSEMBLER_RESULT_OK, NULL); sml_fail_unless(error == NULL, NULL); smlCommandUnref(cmd); sml_fail_unless(smlAssemblerEndCommand(assm, NULL, &error), NULL); sml_fail_unless(error == NULL, NULL); char *data = NULL; unsigned int size = 0; sml_fail_unless(smlAssemblerRun(assm, &data, &size, NULL, FALSE, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(data != NULL, NULL); sml_fail_unless(size != 0, NULL); smlSafeCFree(&data); sml_fail_unless(smlAssemblerFlush(assm) == 1, NULL); sml_fail_unless(error == NULL, NULL); smlAssemblerFree(assm); smlSessionUnref(session); } END_TEST @SML_TESTCASE_CODE@ libsyncml-0.5.4/tests/check_md5.c100644 1750 1750 6510 11211710410 16553 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2005 Armin Bauer * Copyright (C) 2008 Michael Bell * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include "tests/support.h" START_TEST (md5_1) { const char *data = ""; unsigned char digest[16]; SmlError *error = NULL; smlMD5GetDigest(data, strlen(data), digest); char *md5 = smlMD5ToString(digest, &error); sml_fail_unless(!strcmp(md5, "d41d8cd98f00b204e9800998ecf8427e"), "%s", smlErrorPrint(&error)); smlSafeCFree(&md5); } END_TEST START_TEST (md5_2) { const char *data = "a"; unsigned char digest[16]; SmlError *error = NULL; smlMD5GetDigest(data, strlen(data), digest); char *md5 = smlMD5ToString(digest, &error); sml_fail_unless(!strcmp(md5, "0cc175b9c0f1b6a831c399e269772661"), "%s", smlErrorPrint(&error)); smlSafeCFree(&md5); } END_TEST START_TEST (md5_3) { const char *data = "abc"; unsigned char digest[16]; SmlError *error = NULL; smlMD5GetDigest(data, strlen(data), digest); char *md5 = smlMD5ToString(digest, &error); sml_fail_unless(!strcmp(md5, "900150983cd24fb0d6963f7d28e17f72"), "%s", smlErrorPrint(&error)); smlSafeCFree(&md5); } END_TEST START_TEST (md5_4) { const char *data = "message digest"; unsigned char digest[16]; SmlError *error = NULL; smlMD5GetDigest(data, strlen(data), digest); char *md5 = smlMD5ToString(digest, &error); sml_fail_unless(!strcmp(md5, "f96b697d7cb7938d525a2f31aaf161d0"), "%s", smlErrorPrint(&error)); smlSafeCFree(&md5); } END_TEST START_TEST (md5_5) { const char *data = "abcdefghijklmnopqrstuvwxyz"; unsigned char digest[16]; SmlError *error = NULL; smlMD5GetDigest(data, strlen(data), digest); char *md5 = smlMD5ToString(digest, &error); sml_fail_unless(!strcmp(md5, "c3fcd3d76192e4007dfb496cca67e13b"), "%s", smlErrorPrint(&error)); smlSafeCFree(&md5); } END_TEST START_TEST (md5_6) { const char *data = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; unsigned char digest[16]; SmlError *error = NULL; smlMD5GetDigest(data, strlen(data), digest); char *md5 = smlMD5ToString(digest, &error); sml_fail_unless(!strcmp(md5, "d174ab98d277d9f5a5611c2c9f419d9f"), "%s", smlErrorPrint(&error)); smlSafeCFree(&md5); } END_TEST START_TEST (md5_7) { const char *data = "12345678901234567890123456789012345678901234567890123456789012345678901234567890"; unsigned char digest[16]; SmlError *error = NULL; smlMD5GetDigest(data, strlen(data), digest); char *md5 = smlMD5ToString(digest, &error); sml_fail_unless(!strcmp(md5, "57edf4a22be3c955ac49da2e2107b67a"), "%s", smlErrorPrint(&error)); smlSafeCFree(&md5); } END_TEST @SML_TESTCASE_CODE@ libsyncml-0.5.4/tests/check_xml_parser.c100644 1750 1750 333316 11211710410 20311 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2005 Armin Bauer * Copyright (C) 2007-2008 Michael Bell * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include "tests/support.h" #include #include START_TEST (xml_parser_empty) { const char *data = " "; SmlError *error = NULL; SmlParser *parser = start_parser(data, &error); sml_fail_unless(parser == NULL, NULL); sml_fail_unless(error != NULL, NULL); smlErrorDeref(&error); } END_TEST START_TEST (xml_parser_syncml_empty) { const char *data = ""; SmlError *error = NULL; SmlParser *parser = start_parser(data, &error); sml_fail_unless(parser == NULL, NULL); sml_fail_unless(error != NULL, NULL); smlErrorDeref(&error); } END_TEST START_TEST (xml_parser_syncml_wrong_case) { const char *data = ""; SmlError *error = NULL; SmlParser *parser = start_parser(data, &error); sml_fail_unless(parser == NULL, NULL); sml_fail_unless(error != NULL, NULL); smlErrorDeref(&error); } END_TEST START_TEST (xml_parser_syncml_additional) { const char *data = ""; SmlError *error = NULL; SmlParser *parser = start_parser(data, &error); sml_fail_unless(parser == NULL, NULL); sml_fail_unless(error != NULL, NULL); smlErrorDeref(&error); } END_TEST START_TEST (xml_parser_no_syncbody) { const char *data = ""; SmlError *error = NULL; SmlParser *parser = start_parser(data, &error); sml_fail_unless(parser != NULL, "%s", smlErrorPrint(&error)); SmlHeader *header = NULL; SmlCred *cred = NULL; sml_fail_unless(!smlParserGetHeader(parser, &header, &cred, &error), NULL); sml_fail_unless(header == NULL, NULL); sml_fail_unless(error != NULL, NULL); smlErrorDeref(&error); sml_fail_unless(!smlParserEnd(parser, NULL, NULL, &error), NULL); sml_fail_unless(error != NULL, NULL); smlErrorDeref(&error); smlParserFree(parser); } END_TEST START_TEST (xml_parser_no_synchdr) { const char *data = ""; SmlError *error = NULL; SmlParser *parser = start_parser(data, &error); sml_fail_unless(parser == NULL, NULL); sml_fail_unless(error != NULL, NULL); smlErrorDeref(&error); } END_TEST START_TEST (xml_parser_synchdr_empty) { const char *data = ""; SmlError *error = NULL; SmlParser *parser = start_parser(data, &error); sml_fail_unless(parser != NULL, "%s", smlErrorPrint(&error)); SmlHeader *header = NULL; SmlCred *cred = NULL; sml_fail_unless(!smlParserGetHeader(parser, &header, &cred, &error), NULL); sml_fail_unless(header == NULL, NULL); sml_fail_unless(error != NULL, NULL); smlErrorDeref(&error); sml_fail_unless(!smlParserEnd(parser, NULL, NULL, &error), NULL); sml_fail_unless(error != NULL, NULL); smlErrorDeref(&error); smlParserFree(parser); } END_TEST START_TEST (xml_parser_synchdr_verproto) { const char *data = "SyncML/1.1"; SmlError *error = NULL; SmlParser *parser = start_parser(data, &error); sml_fail_unless(parser != NULL, "%s", smlErrorPrint(&error)); SmlHeader *header = NULL; SmlCred *cred = NULL; sml_fail_unless(!smlParserGetHeader(parser, &header, &cred, &error), NULL); sml_fail_unless(header == NULL, NULL); sml_fail_unless(error != NULL, NULL); smlErrorDeref(&error); sml_fail_unless(!smlParserEnd(parser, NULL, NULL, &error), NULL); sml_fail_unless(error != NULL, NULL); smlErrorDeref(&error); smlParserFree(parser); } END_TEST START_TEST (xml_parser_synchdr_verdtd) { const char *data = "SyncML/1.11.1"; SmlError *error = NULL; SmlParser *parser = start_parser(data, &error); sml_fail_unless(parser != NULL, "%s", smlErrorPrint(&error)); SmlHeader *header = NULL; SmlCred *cred = NULL; sml_fail_unless(!smlParserGetHeader(parser, &header, &cred, &error), NULL); sml_fail_unless(header == NULL, NULL); sml_fail_unless(error != NULL, NULL); smlErrorDeref(&error); sml_fail_unless(!smlParserEnd(parser, NULL, NULL, &error), NULL); sml_fail_unless(error != NULL, NULL); smlErrorDeref(&error); smlParserFree(parser); } END_TEST START_TEST (xml_parser_synchdr_msgid) { const char *data = "SyncML/1.11.11"; SmlError *error = NULL; SmlParser *parser = start_parser(data, &error); sml_fail_unless(parser != NULL, "%s", smlErrorPrint(&error)); SmlHeader *header = NULL; SmlCred *cred = NULL; sml_fail_unless(!smlParserGetHeader(parser, &header, &cred, &error), NULL); sml_fail_unless(header == NULL, NULL); sml_fail_unless(error != NULL, NULL); smlErrorDeref(&error); sml_fail_unless(!smlParserEnd(parser, NULL, NULL, &error), NULL); sml_fail_unless(error != NULL, NULL); smlErrorDeref(&error); smlParserFree(parser); } END_TEST START_TEST (xml_parser_synchdr_sessionid) { const char *data = "SyncML/1.11.111"; SmlError *error = NULL; SmlParser *parser = start_parser(data, &error); sml_fail_unless(parser != NULL, "%s", smlErrorPrint(&error)); SmlHeader *header = NULL; SmlCred *cred = NULL; sml_fail_unless(!smlParserGetHeader(parser, &header, &cred, &error), NULL); sml_fail_unless(header == NULL, NULL); sml_fail_unless(error != NULL, NULL); smlErrorDeref(&error); sml_fail_unless(!smlParserEnd(parser, NULL, NULL, &error), NULL); sml_fail_unless(error != NULL, NULL); smlErrorDeref(&error); smlParserFree(parser); } END_TEST START_TEST (xml_parser_synchdr_target) { const char *data = "SyncML/1.11.111test"; SmlError *error = NULL; SmlParser *parser = start_parser(data, &error); sml_fail_unless(parser != NULL, "%s", smlErrorPrint(&error)); SmlHeader *header = NULL; SmlCred *cred = NULL; sml_fail_unless(!smlParserGetHeader(parser, &header, &cred, &error), NULL); sml_fail_unless(header == NULL, NULL); sml_fail_unless(error != NULL, NULL); smlErrorDeref(&error); sml_fail_unless(!smlParserEnd(parser, NULL, NULL, &error), NULL); sml_fail_unless(error != NULL, NULL); smlErrorDeref(&error); smlParserFree(parser); } END_TEST START_TEST (xml_parser_synchdr_source) { const char *data = "SyncML/1.11.111testtest"; SmlError *error = NULL; SmlParser *parser = start_parser(data, &error); sml_fail_unless(parser != NULL, "%s", smlErrorPrint(&error)); SmlHeader *header = NULL; SmlCred *cred = NULL; sml_fail_unless(smlParserGetHeader(parser, &header, &cred, &error), NULL); sml_fail_unless(header != NULL, NULL); sml_fail_unless(cred == NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(header->messageID == 1, NULL); sml_fail_unless(header->target != NULL, NULL); sml_fail_unless(header->source != NULL, NULL); sml_fail_unless(header->protocol == SML_PROTOCOL_SYNCML, NULL); sml_fail_unless(header->version == SML_VERSION_11, NULL); sml_fail_unless(!strcmp(header->sessionID, "1"), NULL); smlHeaderFree(header); SmlStatus *status = NULL; sml_fail_unless(smlParserGetStatus(parser, &status, &error), NULL); sml_fail_unless(status == NULL, NULL); sml_fail_unless(error == NULL, NULL); SmlCommand *cmd = NULL; sml_fail_unless(smlParserGetCommand(parser, &cmd, &error), NULL); sml_fail_unless(cmd == NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlParserEnd(parser, NULL, NULL, &error), NULL); sml_fail_unless(error == NULL, NULL); smlParserFree(parser); } END_TEST START_TEST (xml_parser_synchdr_source2) { const char *data = "SyncML/1.11.11asdtesttest"; SmlError *error = NULL; SmlParser *parser = start_parser(data, &error); sml_fail_unless(parser != NULL, "%s", smlErrorPrint(&error)); SmlHeader *header = NULL; SmlCred *cred = NULL; sml_fail_unless(smlParserGetHeader(parser, &header, &cred, &error), NULL); sml_fail_unless(header != NULL, NULL); sml_fail_unless(cred == NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(header->messageID == 1, NULL); sml_fail_unless(header->target != NULL, NULL); sml_fail_unless(header->source != NULL, NULL); sml_fail_unless(header->protocol == SML_PROTOCOL_SYNCML, NULL); sml_fail_unless(header->version == SML_VERSION_11, NULL); sml_fail_unless(!strcmp(header->sessionID, "asd"), NULL); smlHeaderFree(header); SmlStatus *status = NULL; sml_fail_unless(smlParserGetStatus(parser, &status, &error), NULL); sml_fail_unless(status == NULL, NULL); sml_fail_unless(error == NULL, NULL); SmlCommand *cmd = NULL; sml_fail_unless(smlParserGetCommand(parser, &cmd, &error), NULL); sml_fail_unless(cmd == NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlParserEnd(parser, NULL, NULL, &error), NULL); sml_fail_unless(error == NULL, NULL); smlParserFree(parser); } END_TEST START_TEST (xml_parser_synchdr_additional) { const char *data = "SyncML/1.11.111testtest"; SmlError *error = NULL; SmlParser *parser = start_parser(data, &error); sml_fail_unless(parser != NULL, "%s", smlErrorPrint(&error)); SmlHeader *header = NULL; SmlCred *cred = NULL; sml_fail_unless(!smlParserGetHeader(parser, &header, &cred, &error), NULL); sml_fail_unless(header == NULL, NULL); sml_fail_unless(error != NULL, NULL); smlErrorDeref(&error); sml_fail_unless(!smlParserEnd(parser, NULL, NULL, &error), NULL); sml_fail_unless(error != NULL, NULL); smlErrorDeref(&error); smlParserFree(parser); } END_TEST START_TEST (xml_parser_status_empty) { const char *data = "SyncML/1.11.111testtest"; SmlError *error = NULL; SmlParser *parser = start_parser(data, &error); sml_fail_unless(parser != NULL, "%s", smlErrorPrint(&error)); SmlHeader *header = NULL; SmlCred *cred = NULL; sml_fail_unless(smlParserGetHeader(parser, &header, &cred, &error), NULL); sml_fail_unless(header != NULL, NULL); sml_fail_unless(cred == NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(header->messageID == 1, NULL); smlHeaderFree(header); SmlStatus *status = NULL; sml_fail_unless(!smlParserGetStatus(parser, &status, &error), NULL); sml_fail_unless(status == NULL, NULL); sml_fail_unless(error != NULL, NULL); smlErrorDeref(&error); SmlCommand *cmd = NULL; sml_fail_unless(smlParserGetCommand(parser, &cmd, &error), NULL); sml_fail_unless(cmd == NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlParserEnd(parser, NULL, NULL, &error), NULL); sml_fail_unless(error == NULL, NULL); smlParserFree(parser); } END_TEST START_TEST (xml_parser_status_cmdid) { const char *data = "SyncML/1.11.111testtest1"; SmlError *error = NULL; SmlParser *parser = start_parser(data, &error); sml_fail_unless(parser != NULL, "%s", smlErrorPrint(&error)); SmlHeader *header = NULL; SmlCred *cred = NULL; sml_fail_unless(smlParserGetHeader(parser, &header, &cred, &error), NULL); sml_fail_unless(header != NULL, NULL); sml_fail_unless(cred == NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(header->messageID == 1, NULL); smlHeaderFree(header); SmlStatus *status = NULL; sml_fail_unless(!smlParserGetStatus(parser, &status, &error), NULL); sml_fail_unless(status == NULL, NULL); sml_fail_unless(error != NULL, NULL); smlErrorDeref(&error); smlParserFree(parser); } END_TEST START_TEST (xml_parser_status_msgref) { const char *data = "SyncML/1.11.111testtest11"; SmlError *error = NULL; SmlParser *parser = start_parser(data, &error); sml_fail_unless(parser != NULL, "%s", smlErrorPrint(&error)); SmlHeader *header = NULL; SmlCred *cred = NULL; sml_fail_unless(smlParserGetHeader(parser, &header, &cred, &error), NULL); sml_fail_unless(header != NULL, NULL); sml_fail_unless(cred == NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(header->messageID == 1, NULL); smlHeaderFree(header); SmlStatus *status = NULL; sml_fail_unless(!smlParserGetStatus(parser, &status, &error), NULL); sml_fail_unless(status == NULL, NULL); sml_fail_unless(error != NULL, NULL); smlErrorDeref(&error); smlParserFree(parser); } END_TEST START_TEST (xml_parser_status_cmdref) { const char *data = "SyncML/1.11.111testtest111"; SmlError *error = NULL; SmlParser *parser = start_parser(data, &error); sml_fail_unless(parser != NULL, "%s", smlErrorPrint(&error)); SmlHeader *header = NULL; SmlCred *cred = NULL; sml_fail_unless(smlParserGetHeader(parser, &header, &cred, &error), NULL); sml_fail_unless(header != NULL, NULL); sml_fail_unless(cred == NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(header->messageID == 1, NULL); smlHeaderFree(header); SmlStatus *status = NULL; sml_fail_unless(!smlParserGetStatus(parser, &status, &error), NULL); sml_fail_unless(status == NULL, NULL); sml_fail_unless(error != NULL, NULL); smlErrorDeref(&error); smlParserFree(parser); } END_TEST START_TEST (xml_parser_status) { const char *data = "SyncML/1.11.111testtest110Sync"; SmlError *error = NULL; SmlParser *parser = start_parser(data, &error); sml_fail_unless(parser != NULL, "%s", smlErrorPrint(&error)); SmlHeader *header = NULL; SmlCred *cred = NULL; sml_fail_unless(smlParserGetHeader(parser, &header, &cred, &error), NULL); sml_fail_unless(header != NULL, NULL); sml_fail_unless(cred == NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(header->messageID == 1, NULL); smlHeaderFree(header); SmlStatus *status = NULL; sml_fail_unless(smlParserGetStatus(parser, &status, &error), NULL); sml_fail_unless(status != NULL, NULL); sml_fail_unless(error == NULL, NULL); smlStatusUnref(status); sml_fail_unless(smlParserGetStatus(parser, &status, &error), NULL); sml_fail_unless(status == NULL, NULL); sml_fail_unless(error == NULL, NULL); SmlCommand *cmd = NULL; sml_fail_unless(smlParserGetCommand(parser, &cmd, &error), NULL); sml_fail_unless(cmd == NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlParserEnd(parser, NULL, NULL, &error), NULL); sml_fail_unless(error == NULL, NULL); smlParserFree(parser); } END_TEST START_TEST (xml_parser_status2) { const char *data = "SyncML/1.11.111testtest110Sync110Sync"; SmlError *error = NULL; SmlParser *parser = start_parser(data, &error); sml_fail_unless(parser != NULL, "%s", smlErrorPrint(&error)); SmlHeader *header = NULL; SmlCred *cred = NULL; sml_fail_unless(smlParserGetHeader(parser, &header, &cred, &error), NULL); sml_fail_unless(header != NULL, NULL); sml_fail_unless(cred == NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(header->messageID == 1, NULL); smlHeaderFree(header); SmlStatus *status = NULL; sml_fail_unless(smlParserGetStatus(parser, &status, &error), NULL); sml_fail_unless(status != NULL, NULL); sml_fail_unless(error == NULL, NULL); smlStatusUnref(status); sml_fail_unless(smlParserGetStatus(parser, &status, &error), NULL); sml_fail_unless(status != NULL, NULL); sml_fail_unless(error == NULL, NULL); smlStatusUnref(status); sml_fail_unless(smlParserGetStatus(parser, &status, &error), NULL); sml_fail_unless(status == NULL, NULL); sml_fail_unless(error == NULL, NULL); SmlCommand *cmd = NULL; sml_fail_unless(smlParserGetCommand(parser, &cmd, &error), NULL); sml_fail_unless(cmd == NULL, NULL); sml_fail_unless(error == NULL, NULL); SmlBool final = TRUE; SmlBool end = TRUE; sml_fail_unless(smlParserEnd(parser, &final, &end, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(final == FALSE, NULL); sml_fail_unless(end == FALSE, NULL); smlParserFree(parser); } END_TEST START_TEST (xml_parser_status3) { const char *data = "SyncML/1.11.111testtest110Sync110Sync"; SmlError *error = NULL; SmlParser *parser = start_parser(data, &error); sml_fail_unless(parser != NULL, "%s", smlErrorPrint(&error)); SmlHeader *header = NULL; SmlCred *cred = NULL; sml_fail_unless(smlParserGetHeader(parser, &header, &cred, &error), NULL); sml_fail_unless(header != NULL, NULL); sml_fail_unless(cred == NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(header->messageID == 1, NULL); smlHeaderFree(header); SmlStatus *status = NULL; sml_fail_unless(smlParserGetStatus(parser, &status, &error), NULL); sml_fail_unless(status != NULL, NULL); sml_fail_unless(error == NULL, NULL); smlStatusUnref(status); sml_fail_unless(smlParserGetStatus(parser, &status, &error), NULL); sml_fail_unless(status != NULL, NULL); sml_fail_unless(error == NULL, NULL); smlStatusUnref(status); sml_fail_unless(smlParserGetStatus(parser, &status, &error), NULL); sml_fail_unless(status == NULL, NULL); sml_fail_unless(error == NULL, NULL); SmlCommand *cmd = NULL; sml_fail_unless(smlParserGetCommand(parser, &cmd, &error), NULL); sml_fail_unless(cmd == NULL, NULL); sml_fail_unless(error == NULL, NULL); SmlBool final = FALSE; SmlBool end = FALSE; sml_fail_unless(smlParserEnd(parser, &final, &end, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(final == TRUE, NULL); sml_fail_unless(end == TRUE, NULL); smlParserFree(parser); } END_TEST START_TEST (xml_parser_status_google) { const char *data = "SyncML/1.11.111testtest523Alertcontactscontacts200"; SmlError *error = NULL; SmlParser *parser = start_parser(data, &error); sml_fail_unless(parser != NULL, "%s", smlErrorPrint(&error)); SmlHeader *header = NULL; SmlCred *cred = NULL; sml_fail_unless(smlParserGetHeader(parser, &header, &cred, &error), NULL); sml_fail_unless(header != NULL, NULL); sml_fail_unless(cred == NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(header->messageID == 1, NULL); smlHeaderFree(header); SmlStatus *status = NULL; sml_fail_unless(smlParserGetStatus(parser, &status, &error), NULL); sml_fail_unless(status != NULL, NULL); sml_fail_unless(error == NULL, NULL); smlStatusUnref(status); sml_fail_unless(smlParserGetStatus(parser, &status, &error), NULL); sml_fail_unless(status == NULL, NULL); sml_fail_unless(error == NULL, NULL); SmlCommand *cmd = NULL; sml_fail_unless(smlParserGetCommand(parser, &cmd, &error), NULL); sml_fail_unless(cmd == NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlParserEnd(parser, NULL, NULL, &error), NULL); sml_fail_unless(error == NULL, NULL); smlParserFree(parser); } END_TEST START_TEST (xml_parser_final) { const char *data = "SyncML/1.11.111testtest110Sync110Sync"; SmlError *error = NULL; SmlParser *parser = start_parser(data, &error); sml_fail_unless(parser != NULL, "%s", smlErrorPrint(&error)); SmlHeader *header = NULL; SmlCred *cred = NULL; sml_fail_unless(smlParserGetHeader(parser, &header, &cred, &error), NULL); sml_fail_unless(header != NULL, NULL); sml_fail_unless(cred == NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(header->messageID == 1, NULL); smlHeaderFree(header); SmlStatus *status = NULL; sml_fail_unless(smlParserGetStatus(parser, &status, &error), NULL); sml_fail_unless(status != NULL, NULL); sml_fail_unless(error == NULL, NULL); smlStatusUnref(status); sml_fail_unless(smlParserGetStatus(parser, &status, &error), NULL); sml_fail_unless(status != NULL, NULL); sml_fail_unless(error == NULL, NULL); smlStatusUnref(status); sml_fail_unless(smlParserGetStatus(parser, &status, &error), NULL); sml_fail_unless(status == NULL, NULL); sml_fail_unless(error == NULL, NULL); SmlCommand *cmd = NULL; sml_fail_unless(smlParserGetCommand(parser, &cmd, &error), NULL); sml_fail_unless(cmd == NULL, NULL); sml_fail_unless(error == NULL, NULL); SmlBool final = FALSE; SmlBool end = FALSE; sml_fail_unless(smlParserEnd(parser, &final, &end, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(final == TRUE, NULL); sml_fail_unless(end == TRUE, NULL); smlParserFree(parser); } END_TEST START_TEST (xml_parser_final2) { const char *data = "SyncML/1.11.111testtest110Sync110Sync"; SmlError *error = NULL; SmlParser *parser = start_parser(data, &error); sml_fail_unless(parser != NULL, "%s", smlErrorPrint(&error)); SmlHeader *header = NULL; SmlCred *cred = NULL; sml_fail_unless(smlParserGetHeader(parser, &header, &cred, &error), NULL); sml_fail_unless(header != NULL, NULL); sml_fail_unless(cred == NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(header->messageID == 1, NULL); smlHeaderFree(header); SmlStatus *status = NULL; sml_fail_unless(smlParserGetStatus(parser, &status, &error), NULL); sml_fail_unless(status != NULL, NULL); sml_fail_unless(error == NULL, NULL); smlStatusUnref(status); sml_fail_unless(smlParserGetStatus(parser, &status, &error), NULL); sml_fail_unless(status != NULL, NULL); sml_fail_unless(error == NULL, NULL); smlStatusUnref(status); sml_fail_unless(smlParserGetStatus(parser, &status, &error), NULL); sml_fail_unless(status == NULL, NULL); sml_fail_unless(error == NULL, NULL); SmlCommand *cmd = NULL; sml_fail_unless(smlParserGetCommand(parser, &cmd, &error), NULL); sml_fail_unless(cmd == NULL, NULL); sml_fail_unless(error == NULL, NULL); SmlBool final = FALSE; SmlBool end = FALSE; sml_fail_unless(smlParserEnd(parser, &final, &end, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(final == TRUE, NULL); sml_fail_unless(end == TRUE, NULL); smlParserFree(parser); } END_TEST START_TEST (xml_parser_cmd) { const char *data = "SyncML/1.11.111testtest1/test/testNextlast200"; SmlError *error = NULL; SmlParser *parser = start_parser(data, &error); sml_fail_unless(parser != NULL, "%s", smlErrorPrint(&error)); SmlHeader *header = NULL; SmlCred *cred = NULL; sml_fail_unless(smlParserGetHeader(parser, &header, &cred, &error), NULL); sml_fail_unless(header != NULL, NULL); sml_fail_unless(cred == NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(header->messageID == 1, NULL); smlHeaderFree(header); SmlStatus *status = NULL; sml_fail_unless(smlParserGetStatus(parser, &status, &error), NULL); sml_fail_unless(status == NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlParserGetStatus(parser, &status, &error), NULL); sml_fail_unless(status == NULL, NULL); sml_fail_unless(error == NULL, NULL); SmlCommand *cmd = NULL; sml_fail_unless(smlParserGetCommand(parser, &cmd, &error), "%s", smlErrorPrint(&error)); sml_fail_unless(cmd != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(cmd->cmdID == 1, NULL); smlCommandUnref(cmd); sml_fail_unless(smlParserGetCommand(parser, &cmd, &error), NULL); sml_fail_unless(cmd == NULL, NULL); sml_fail_unless(error == NULL, NULL); SmlBool final = TRUE; SmlBool end = TRUE; sml_fail_unless(smlParserEnd(parser, &final, &end, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(final == FALSE, NULL); sml_fail_unless(end == FALSE, NULL); smlParserFree(parser); } END_TEST START_TEST (xml_parser_cmd_final) { const char *data = "SyncML/1.11.111testtest1/test/testNextlast200"; SmlError *error = NULL; SmlParser *parser = start_parser(data, &error); sml_fail_unless(parser != NULL, "%s", smlErrorPrint(&error)); SmlHeader *header = NULL; SmlCred *cred = NULL; sml_fail_unless(smlParserGetHeader(parser, &header, &cred, &error), NULL); sml_fail_unless(header != NULL, NULL); sml_fail_unless(cred == NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(header->messageID == 1, NULL); smlHeaderFree(header); SmlStatus *status = NULL; sml_fail_unless(smlParserGetStatus(parser, &status, &error), NULL); sml_fail_unless(status == NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlParserGetStatus(parser, &status, &error), NULL); sml_fail_unless(status == NULL, NULL); sml_fail_unless(error == NULL, NULL); SmlCommand *cmd = NULL; sml_fail_unless(smlParserGetCommand(parser, &cmd, &error), NULL); sml_fail_unless(cmd != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(cmd->cmdID == 1, NULL); smlCommandUnref(cmd); sml_fail_unless(smlParserGetCommand(parser, &cmd, &error), NULL); sml_fail_unless(cmd == NULL, NULL); sml_fail_unless(error == NULL, NULL); SmlBool final = FALSE; SmlBool end = TRUE; sml_fail_unless(smlParserEnd(parser, &final, &end, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(final == TRUE, NULL); sml_fail_unless(end == FALSE, NULL); smlParserFree(parser); } END_TEST START_TEST (xml_parser_sync_subcommand) { const char *data = "SyncML/1.11.211/vcards/vcards3/vcards/vcards14text/x-vcarduid"; SmlError *error = NULL; SmlParser *parser = start_parser(data, &error); sml_fail_unless(parser != NULL, "%s", smlErrorPrint(&error)); SmlHeader *header = NULL; SmlCred *cred = NULL; sml_fail_unless(smlParserGetHeader(parser, &header, &cred, &error), NULL); sml_fail_unless(header != NULL, NULL); sml_fail_unless(cred == NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(header->messageID == 1, NULL); smlHeaderFree(header); SmlStatus *status = NULL; sml_fail_unless(smlParserGetStatus(parser, &status, &error), NULL); sml_fail_unless(status == NULL, NULL); sml_fail_unless(error == NULL, NULL); SmlCommand *cmd = NULL; sml_fail_unless(smlParserGetCommand(parser, &cmd, &error) == SML_PARSER_RESULT_OPEN, NULL); sml_fail_unless(cmd != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(cmd->cmdID == 3, NULL); sml_fail_unless(cmd->type == SML_COMMAND_TYPE_SYNC, NULL); sml_fail_unless(cmd->private.sync.numChanged == 1, NULL); smlCommandUnref(cmd); sml_fail_unless(smlParserGetCommand(parser, &cmd, &error) == SML_PARSER_RESULT_NORMAL, NULL); sml_fail_unless(cmd != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(cmd->cmdID == 4, NULL); sml_fail_unless(cmd->type == SML_COMMAND_TYPE_ADD, NULL); sml_fail_unless(cmd->private.change.items != NULL, NULL); sml_fail_unless(cmd->private.change.type == SML_CHANGE_ADD, NULL); smlCommandUnref(cmd); sml_fail_unless(smlParserGetCommand(parser, &cmd, &error) == SML_PARSER_RESULT_CLOSE, NULL); sml_fail_unless(cmd == NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlParserGetCommand(parser, &cmd, &error) == SML_PARSER_RESULT_OTHER, NULL); sml_fail_unless(cmd == NULL, NULL); sml_fail_unless(error == NULL, NULL); SmlBool final = FALSE; SmlBool end = TRUE; sml_fail_unless(smlParserEnd(parser, &final, &end, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(final == TRUE, NULL); sml_fail_unless(end == FALSE, NULL); smlParserFree(parser); } END_TEST START_TEST (xml_parser_emi) { const char *data = "1.1SyncML/1.111opiumIMEI:xxxxxxxxxxxxxxx10000NokiaInq/1.11SyncHdr40321Alert50032Alert50043Alert500"; SmlError *error = NULL; SmlParser *parser = start_parser(data, &error); sml_fail_unless(parser != NULL, "%s", smlErrorPrint(&error)); SmlHeader *header = NULL; SmlCred *cred = NULL; sml_fail_unless(smlParserGetHeader(parser, &header, &cred, &error), NULL); sml_fail_unless(header != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(header->messageID == 1, NULL); smlHeaderFree(header); smlParserFree(parser); } END_TEST START_TEST (xml_parser_doctype) { const char *data = "\n\n\n\n\n1.1\n\n\nSyncML/1.1\n\n\n1125161435\n\n\n1\n\n\n\nhttp://test.com:7962/\n\n\n\n\n35686843434\n\n\nasd\n\n\n\n\n\nb64\n\n\nsyncml:auth-basic\n\n\n\nYXNkOmFzZA==\n\n\n\n\n3300\n\n\n\n\n\n\n1\n\n\n201\n\n\n\n\npeople\n\n\n\n\npeople\n\n\n\n\n\n\n\n1\n\n\n\n\n\n\n\n2\n\n\n\nwbxml\n\n\napplication/vnd.syncml-devinf+xml\n\n\n\n\n\n./devinf11\n\n\n\n\n\n1.1\n\n\nMotorola CE, Copyright 2004\n\n\nV3\n\n\nR374_G_0E.41.C3R_A\n\n\nSJUG0851CA\n\n\n3564564556453\n\n\nphone\n\n\n\npeople\n\n\n\ntext/x-vcard\n\n\n2.1\n\n\n\n\ntext/x-vcard\n\n\n2.1\n\n\n\n\n1\n\n\n2\n\n\n\n\n\ntext/x-vcard\n\n\nBEGIN\n\n\nVCARD\n\n\nEND\n\n\nVCARD\n\n\nVERSION\n\n\n2.1\n\n\nFN\n\n\nN\n\n\nTEL\n\n\nPREF\n\n\nWORK\n\n\nHOME\n\n\nCELL\n\n\nFAX\n\n\nPAGER\n\n\nEMAIL\n\n\nINTERNET\n\n\nCHARSET\n\n\n\n\n\n\n\n\n\n\n"; SmlError *error = NULL; SmlParser *parser = start_parser(data, &error); sml_fail_unless(parser != NULL, "%s", smlErrorPrint(&error)); SmlHeader *header = NULL; SmlCred *cred = NULL; sml_fail_unless(smlParserGetHeader(parser, &header, &cred, &error), NULL); sml_fail_unless(header != NULL, NULL); sml_fail_unless(cred != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(header->messageID == 1, NULL); smlHeaderFree(header); smlCredUnref(cred); SmlStatus *status = NULL; sml_fail_unless(smlParserGetStatus(parser, &status, &error), NULL); sml_fail_unless(status == NULL, NULL); sml_fail_unless(error == NULL, NULL); SmlCommand *cmd = NULL; sml_fail_unless(smlParserGetCommand(parser, &cmd, &error) == SML_PARSER_RESULT_NORMAL, NULL); sml_fail_unless(cmd != NULL, NULL); sml_fail_unless(error == NULL, NULL); smlCommandUnref(cmd); sml_fail_unless(smlParserGetCommand(parser, &cmd, &error) == SML_PARSER_RESULT_NORMAL, NULL); sml_fail_unless(cmd != NULL, NULL); sml_fail_unless(error == NULL, NULL); smlCommandUnref(cmd); sml_fail_unless(smlParserGetCommand(parser, &cmd, &error) == SML_PARSER_RESULT_OTHER, NULL); sml_fail_unless(cmd == NULL, NULL); sml_fail_unless(error == NULL, NULL); SmlBool final = FALSE; SmlBool end = TRUE; sml_fail_unless(smlParserEnd(parser, &final, &end, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(final == TRUE, NULL); sml_fail_unless(end == FALSE, NULL); smlParserFree(parser); } END_TEST START_TEST (xml_parser_large_obj) { const char *data = "SyncML/1.11.211/vcards/vcards3/vcards/vcards14text/x-vcard200uid"; SmlError *error = NULL; SmlParser *parser = start_parser(data, &error); sml_fail_unless(parser != NULL, "%s", smlErrorPrint(&error)); SmlHeader *header = NULL; SmlCred *cred = NULL; sml_fail_unless(smlParserGetHeader(parser, &header, &cred, &error), NULL); sml_fail_unless(header != NULL, NULL); sml_fail_unless(cred == NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(header->messageID == 1, NULL); smlHeaderFree(header); SmlStatus *status = NULL; sml_fail_unless(smlParserGetStatus(parser, &status, &error), NULL); sml_fail_unless(status == NULL, NULL); sml_fail_unless(error == NULL, NULL); SmlCommand *cmd = NULL; sml_fail_unless(smlParserGetCommand(parser, &cmd, &error) == SML_PARSER_RESULT_OPEN, NULL); sml_fail_unless(cmd != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(cmd->cmdID == 3, NULL); sml_fail_unless(cmd->type == SML_COMMAND_TYPE_SYNC, NULL); sml_fail_unless(cmd->private.sync.numChanged == 1, NULL); smlCommandUnref(cmd); sml_fail_unless(smlParserGetCommand(parser, &cmd, &error) == SML_PARSER_RESULT_NORMAL, NULL); sml_fail_unless(cmd != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(cmd->cmdID == 4, NULL); sml_fail_unless(cmd->type == SML_COMMAND_TYPE_ADD, NULL); sml_fail_unless(cmd->private.change.items != NULL, NULL); sml_fail_unless(cmd->private.change.type == SML_CHANGE_ADD, NULL); SmlItem *item = g_list_nth_data(cmd->private.change.items, 0); sml_fail_unless(item->moreData == TRUE, NULL); sml_fail_unless(cmd->size == 200, NULL); smlCommandUnref(cmd); sml_fail_unless(smlParserGetCommand(parser, &cmd, &error) == SML_PARSER_RESULT_CLOSE, NULL); sml_fail_unless(cmd == NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlParserGetCommand(parser, &cmd, &error) == SML_PARSER_RESULT_OTHER, NULL); sml_fail_unless(cmd == NULL, NULL); sml_fail_unless(error == NULL, NULL); SmlBool final = FALSE; SmlBool end = TRUE; sml_fail_unless(smlParserEnd(parser, &final, &end, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(final == TRUE, NULL); sml_fail_unless(end == FALSE, NULL); smlParserFree(parser); } END_TEST START_TEST (xml_parser_large_obj2) { const char *data = "SyncML/1.11.211/vcards/vcards3/vcards/vcards14text/x-vcard200uid"; SmlError *error = NULL; SmlParser *parser = start_parser(data, &error); sml_fail_unless(parser != NULL, "%s", smlErrorPrint(&error)); SmlHeader *header = NULL; SmlCred *cred = NULL; sml_fail_unless(smlParserGetHeader(parser, &header, &cred, &error), NULL); sml_fail_unless(header != NULL, NULL); sml_fail_unless(cred == NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(header->messageID == 1, NULL); smlHeaderFree(header); SmlStatus *status = NULL; sml_fail_unless(smlParserGetStatus(parser, &status, &error), NULL); sml_fail_unless(status == NULL, NULL); sml_fail_unless(error == NULL, NULL); SmlCommand *cmd = NULL; sml_fail_unless(smlParserGetCommand(parser, &cmd, &error) == SML_PARSER_RESULT_OPEN, NULL); sml_fail_unless(cmd != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(cmd->cmdID == 3, NULL); sml_fail_unless(cmd->type == SML_COMMAND_TYPE_SYNC, NULL); sml_fail_unless(cmd->private.sync.numChanged == 1, NULL); smlCommandUnref(cmd); sml_fail_unless(smlParserGetCommand(parser, &cmd, &error) == SML_PARSER_RESULT_NORMAL, NULL); sml_fail_unless(cmd != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(cmd->cmdID == 4, NULL); sml_fail_unless(cmd->type == SML_COMMAND_TYPE_ADD, NULL); sml_fail_unless(cmd->private.change.items != NULL, NULL); sml_fail_unless(cmd->private.change.type == SML_CHANGE_ADD, NULL); SmlItem *item = g_list_nth_data(cmd->private.change.items, 0); sml_fail_unless(item->moreData == TRUE, NULL); sml_fail_unless(cmd->size == 200, NULL); smlCommandUnref(cmd); sml_fail_unless(smlParserGetCommand(parser, &cmd, &error) == SML_PARSER_RESULT_CLOSE, NULL); sml_fail_unless(cmd == NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlParserGetCommand(parser, &cmd, &error) == SML_PARSER_RESULT_OTHER, NULL); sml_fail_unless(cmd == NULL, NULL); sml_fail_unless(error == NULL, NULL); SmlBool final = FALSE; SmlBool end = TRUE; sml_fail_unless(smlParserEnd(parser, &final, &end, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(final == TRUE, NULL); sml_fail_unless(end == FALSE, NULL); smlParserFree(parser); } END_TEST START_TEST (xml_parser_large_obj_error) { const char *data = "SyncML/1.11.211/vcards/vcards3/vcards/vcards14text/x-vcard200uid4text/x-vcard200uid"; SmlError *error = NULL; SmlParser *parser = start_parser(data, &error); sml_fail_unless(parser != NULL, "%s", smlErrorPrint(&error)); SmlHeader *header = NULL; SmlCred *cred = NULL; sml_fail_unless(smlParserGetHeader(parser, &header, &cred, &error), NULL); sml_fail_unless(header != NULL, NULL); sml_fail_unless(cred == NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(header->messageID == 1, NULL); smlHeaderFree(header); SmlStatus *status = NULL; sml_fail_unless(smlParserGetStatus(parser, &status, &error), NULL); sml_fail_unless(status == NULL, NULL); sml_fail_unless(error == NULL, NULL); SmlCommand *cmd = NULL; sml_fail_unless(smlParserGetCommand(parser, &cmd, &error) == SML_PARSER_RESULT_OPEN, NULL); sml_fail_unless(cmd != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(cmd->cmdID == 3, NULL); sml_fail_unless(cmd->type == SML_COMMAND_TYPE_SYNC, NULL); sml_fail_unless(cmd->private.sync.numChanged == 1, NULL); smlCommandUnref(cmd); sml_fail_unless(smlParserGetCommand(parser, &cmd, &error) == SML_PARSER_RESULT_NORMAL, NULL); sml_fail_unless(cmd != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(cmd->cmdID == 4, NULL); sml_fail_unless(cmd->type == SML_COMMAND_TYPE_ADD, NULL); sml_fail_unless(cmd->private.change.items != NULL, NULL); sml_fail_unless(cmd->private.change.type == SML_CHANGE_ADD, NULL); SmlItem *item = g_list_nth_data(cmd->private.change.items, 0); sml_fail_unless(item->moreData == TRUE, NULL); sml_fail_unless(cmd->size == 200, NULL); smlCommandUnref(cmd); sml_fail_unless(smlParserGetCommand(parser, &cmd, &error) == SML_PARSER_RESULT_ERROR, NULL); sml_fail_unless(cmd == NULL, NULL); sml_fail_unless(error != NULL, NULL); smlErrorDeref(&error); sml_fail_unless(smlParserGetCommand(parser, &cmd, &error) == SML_PARSER_RESULT_ERROR, NULL); sml_fail_unless(cmd == NULL, NULL); sml_fail_unless(error != NULL, NULL); smlErrorDeref(&error); SmlBool final = FALSE; SmlBool end = TRUE; sml_fail_unless(!smlParserEnd(parser, &final, &end, &error), NULL); sml_fail_unless(error != NULL, NULL); smlErrorDeref(&error); smlParserFree(parser); } END_TEST START_TEST (xml_parser_large_obj_mangled) { const char *data = "SyncML/1.11.211/vcards/vcards3/vcards/vcards14text/x-vcarduid10"; SmlError *error = NULL; SmlParser *parser = start_parser(data, &error); sml_fail_unless(parser != NULL, "%s", smlErrorPrint(&error)); SmlHeader *header = NULL; SmlCred *cred = NULL; sml_fail_unless(smlParserGetHeader(parser, &header, &cred, &error), NULL); sml_fail_unless(header != NULL, NULL); sml_fail_unless(cred == NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(header->messageID == 1, NULL); smlHeaderFree(header); SmlStatus *status = NULL; sml_fail_unless(smlParserGetStatus(parser, &status, &error), NULL); sml_fail_unless(status == NULL, NULL); sml_fail_unless(error == NULL, NULL); SmlCommand *cmd = NULL; sml_fail_unless(smlParserGetCommand(parser, &cmd, &error) == SML_PARSER_RESULT_OPEN, NULL); sml_fail_unless(cmd != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(cmd->cmdID == 3, NULL); sml_fail_unless(cmd->type == SML_COMMAND_TYPE_SYNC, NULL); sml_fail_unless(cmd->private.sync.numChanged == 1, NULL); smlCommandUnref(cmd); sml_fail_unless(smlParserGetCommand(parser, &cmd, &error) == SML_PARSER_RESULT_NORMAL, NULL); sml_fail_unless(cmd != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(cmd->cmdID == 4, NULL); sml_fail_unless(cmd->type == SML_COMMAND_TYPE_ADD, NULL); sml_fail_unless(cmd->private.change.items != NULL, NULL); sml_fail_unless(cmd->private.change.type == SML_CHANGE_ADD, NULL); SmlItem *item = g_list_nth_data(cmd->private.change.items, 0); sml_fail_unless(item->moreData == TRUE, NULL); sml_fail_unless(cmd->size == 10, NULL); char *data2 = NULL; unsigned int size = 0; sml_fail_unless(smlItemGetData(item, &data2, &size, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(!strcmp(data2, "data\r\n\r\nda"), NULL); smlCommandUnref(cmd); sml_fail_unless(smlParserGetCommand(parser, &cmd, &error) == SML_PARSER_RESULT_CLOSE, NULL); sml_fail_unless(cmd == NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlParserGetCommand(parser, &cmd, &error) == SML_PARSER_RESULT_OTHER, NULL); sml_fail_unless(cmd == NULL, NULL); sml_fail_unless(error == NULL, NULL); SmlBool final = FALSE; SmlBool end = TRUE; sml_fail_unless(smlParserEnd(parser, &final, &end, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(final == TRUE, NULL); sml_fail_unless(end == FALSE, NULL); smlParserFree(parser); } END_TEST START_TEST (xml_parser_devinf) { const char *data = "1.1SyncML/1.1211PC SuiteIMEI:XXXX100008application/vnd.syncml-devinf+xml./devinf111.1NOKIA66803.04.37IMEI:XXXXphone./C\\Systemata\\Calendar8text/x-vcalendar1.0text/calendar2.0text/x-vcalendar1.01234567./C\\System\\\\\\Data\\Contacts.cdb8text/x-vcard2.1text/vcard3.0text/x-vcard2.11234567./C\\System\\Data\\Notepad.dat8text/plain1.0text/plain1.0text/plain1.0text/plain1.01234567text/x-vcalendarBEGINVCALENDARVEVENTVTODOENDVCALENDARVEVENTVTODOVERSION1.0UIDSUMMARYDESCRIPTIONDTENDDTSTARTAALARMTYPECLASSPUBLICPRIVATECONFIDENTIALCOMPLETEDLOCATIONDCREATEDLAST-MODIFIEDPRIORITYSTATUSRRULEDUEEXDATEX-EPOCAGENDAENTRYTYPEtext/calendarBEGINVCALENDARVEVENTVTODOENDVCALENDARVEVENTVTODOVERSION2.0UIDSUMMARYDESCRIPTIONDTENDDTSTARTAALARMTYPECLASSPUBLICPRIVATECONFIDENTIALCOMPLETEDLOCATIONDCREATEDLAST-MODIFIEDPRIORITYSTATUSRRULEDUEEXDATEX-EPOCAGENDAENTRYTYPEtext/x-vcardBEGINVCARDENDVCARDVERSION2.1REVNADRHOMEWORKTELHOMEWORKCELLPAGERFAXVIDEOFNEMAILINTERNETHOMEWORKURLHOMEWORKNOTETITLEORGPHOTOBDAYSOUNDX-IRMC-Ntext/vcardBEGINVCARDENDVCARDVERSION3.0REVNADRHOMEWORKTELHOMEWORKCELLPAGERFAXVIDEOFNEMAILINTERNETHOMEWORKURLHOMEWORKNOTETITLEORGPHOTOBDAYSOUNDX-IRMC-Ntext/plain"; SmlError *error = NULL; SmlParser *parser = start_parser(data, &error); sml_fail_unless(parser != NULL, "%s", smlErrorPrint(&error)); SmlHeader *header = NULL; SmlCred *cred = NULL; sml_fail_unless(smlParserGetHeader(parser, &header, &cred, &error), NULL); sml_fail_unless(header != NULL, NULL); sml_fail_unless(cred == NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(header->messageID == 1, NULL); smlHeaderFree(header); SmlStatus *status = NULL; sml_fail_unless(smlParserGetStatus(parser, &status, &error), NULL); sml_fail_unless(status == NULL, NULL); sml_fail_unless(error == NULL, NULL); SmlCommand *cmd = NULL; sml_fail_unless(smlParserGetCommand(parser, &cmd, &error) == SML_PARSER_RESULT_NORMAL, NULL); sml_fail_unless(cmd != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(cmd->cmdID == 8, NULL); sml_fail_unless(cmd->type == SML_COMMAND_TYPE_PUT, NULL); sml_fail_unless(cmd->private.access.item != NULL, NULL); char *buffer = NULL; unsigned int size = 0; sml_fail_unless(smlItemGetData(cmd->private.access.item, &buffer, &size, &error), NULL); sml_fail_unless(error == NULL, NULL); SmlDevInf *devinf = smlDevInfParse(buffer, size, &error); sml_fail_unless(devinf != NULL, "%s", smlErrorPrint(&error)); sml_fail_unless(error == NULL, NULL); smlDevInfUnref(devinf); smlCommandUnref(cmd); sml_fail_unless(smlParserGetCommand(parser, &cmd, &error) == SML_PARSER_RESULT_OTHER, NULL); sml_fail_unless(cmd == NULL, NULL); sml_fail_unless(error == NULL, NULL); SmlBool final = FALSE; SmlBool end = TRUE; sml_fail_unless(smlParserEnd(parser, &final, &end, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(final == TRUE, NULL); sml_fail_unless(end == FALSE, NULL); smlParserFree(parser); } END_TEST START_TEST (xml_parser_devinf_ctcap) { const char *data = "1.2SyncML/1.211LibSyncML Test SuiteIMEI:xxxxxxxxxxxxxxx60001application/vnd.syncml-devinf+wbxml./devinf121.2SonyEricssonK850iR1CA029R7AR6AIMEI:xxxxxxxxxxxxxxxphoneContactsContacts64text/x-vcard2.1text/vcard3.0text/x-vcard2.1text/x-vcard2.1X-IRMC-LUID12GEOPHOTO10000ENCODINGBASE64BDAY8URL120TITLE30ORG30EMAIL3128TYPEWORKHOMEADR2125TYPEWORKHOMENOTE512TEL780TYPECELL;WORKCELL;HOMECELLHOMEFAXWORKN60VERSION2.1ENDVCARDBEGINVCARDtext/vcard3.0X-IRMC-LUID12GEOPHOTO10000ENCODINGBASE64BDAY8URL120TITLE30ORG30EMAIL3128TYPEWORKHOMEADR2125TYPEWORKHOMENOTE512TEL780TYPECELL;WORKCELL;HOMECELLHOMEFAXWORKN60VERSION3.0ENDVCARDBEGINVCARD500012467CalendarCalendar64text/x-vcalendar1.0text/x-vcalendar1.0text/x-vcalendar1.0X-IRMC-LUID12X-SONYERICSSON-DSTDAYLIGHTLAST-MODIFIEDEXDATERRULE50CLASSPUBLICCATEGORIESBIRTHDAYHOLIDAYVACATIONTRAVELPHONE CALLMISCELLANEOUSMEETINGAALARMDALARMDTENDDTSTARTDESCRIPTION512LOCATION50SUMMARY200VERSION1.0ENDVEVENTVCALENDARBEGINVEVENTVCALENDAR100012467TasksTasks64text/x-vcalendar1.0text/x-vcalendar1.0text/x-vcalendar1.0X-IRMC-LUID12X-SONYERICSSON-DSTDAYLIGHTLAST-MODIFIEDCLASSPUBLICCATEGORIESBIRTHDAYHOLIDAYVACATIONTRAVELPHONE CALLMISCELLANEOUSMEETINGSTATUSCOMPLETEDNEEDS ACTIONACCEPTEDPRIORITYDUECOMPLETEDAALARMDALARMDESCRIPTION512SUMMARY200VERSION1.0ENDVCALENDARVTODOBEGINVCALENDARVTODO25012467NotesNotes64text/plain1.0text/plain1.0text/plain1.0BODY2545012467BookmarksBookmarks64text/x-vbookmark1.0text/x-vbookmark1.0text/x-vbookmark1.0X-SONYERICSSON-ICON256ENCODINGBASE64X-IRMC-URLURL1024TITLE31BEGINVENVVBKMENDVENVVBKMVERSION1.012467"; SmlError *error = NULL; SmlParser *parser = start_parser(data, &error); sml_fail_unless(parser != NULL, "%s", smlErrorPrint(&error)); SmlHeader *header = NULL; SmlCred *cred = NULL; sml_fail_unless(smlParserGetHeader(parser, &header, &cred, &error), NULL); sml_fail_unless(header != NULL, NULL); sml_fail_unless(cred == NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(header->messageID == 1, NULL); smlHeaderFree(header); SmlStatus *status = NULL; sml_fail_unless(smlParserGetStatus(parser, &status, &error), NULL); sml_fail_unless(status == NULL, NULL); sml_fail_unless(error == NULL, NULL); SmlCommand *cmd = NULL; sml_fail_unless(smlParserGetCommand(parser, &cmd, &error) == SML_PARSER_RESULT_NORMAL, NULL); sml_fail_unless(cmd != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(cmd->cmdID == 1, NULL); sml_fail_unless(cmd->type == SML_COMMAND_TYPE_PUT, NULL); sml_fail_unless(cmd->private.access.item != NULL, NULL); char *buffer = NULL; unsigned int size = 0; sml_fail_unless(smlItemGetData(cmd->private.access.item, &buffer, &size, &error), NULL); sml_fail_unless(error == NULL, NULL); SmlDevInf *devinf = smlDevInfParse(buffer, size, &error); sml_fail_unless(devinf != NULL, NULL); sml_fail_unless(error == NULL, NULL); smlDevInfUnref(devinf); smlCommandUnref(cmd); SmlBool final = FALSE; SmlBool end = TRUE; sml_fail_unless(smlParserEnd(parser, &final, &end, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(final == TRUE, NULL); sml_fail_unless(end == FALSE, NULL); smlParserFree(parser); } END_TEST START_TEST (xml_parser_devinf12) { /* The following string has been sent by a SE P1i */ const char *data = "1.2SyncML/1.292841http://192.168.1.102:8080IMEI:xxxxxxxxxxxxxxx100001application/vnd.syncml-devinf+wbxml./devinf121.2Sony EricssonP1iSymbianUK0Z1.0.11.0IMEI:xxxxxxxxxxxxxxxsmartphoneC:CalendarAgendatext/x-vcalendar1.0text/x-vcalendar1.0text/x-vcalendar1.0text/x-vcalendar1.0text/x-vcalendar1.0AALARMtextATTACHtextATTENDEEtextEXPECTtextROLEtextRSVPtextSTATUStextBEGINtextVCALENDARVEVENTVTODOCATEGORIEStextCOMPLETEDtextCLASStextPUBLICPRIVATECONFIDENTIALDAYLIGHTtextDCREATEDtextDESCRIPTIONtextDTSTARTtextDTENDtextDUEtextENDtextVCALENDARVEVENTVTODOEXDATEtextLAST-MODIFIEDtextLOCATIONtextPRIORITYtextRRULEtextSTATUStextSUMMARYtextUIDtextVERSIONtext1.0X-EPOCALARMtextVALUEtextINLINEURLENCODINGtextBASE64X-CONTENTTYPEtextX-EPOCAGENDAENTRYTYPEtextAPPOINTMENTANNIVERSARYEVENTTODOREMINDER1235647"; SmlError *error = NULL; SmlParser *parser = start_parser(data, &error); sml_fail_unless(parser != NULL, "%s", smlErrorPrint(&error)); SmlHeader *header = NULL; SmlCred *cred = NULL; sml_fail_unless(smlParserGetHeader(parser, &header, &cred, &error), NULL); sml_fail_unless(header != NULL, NULL); sml_fail_unless(cred == NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(header->messageID == 1, NULL); smlHeaderFree(header); SmlStatus *status = NULL; sml_fail_unless(smlParserGetStatus(parser, &status, &error), NULL); sml_fail_unless(status == NULL, NULL); sml_fail_unless(error == NULL, NULL); SmlCommand *cmd = NULL; sml_fail_unless(smlParserGetCommand(parser, &cmd, &error) == SML_PARSER_RESULT_NORMAL, NULL); sml_fail_unless(cmd != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(cmd->cmdID == 1, NULL); sml_fail_unless(cmd->type == SML_COMMAND_TYPE_PUT, NULL); sml_fail_unless(cmd->private.access.item != NULL, NULL); char *buffer = NULL; unsigned int size = 0; sml_fail_unless(smlItemGetData(cmd->private.access.item, &buffer, &size, &error), NULL); sml_fail_unless(error == NULL, NULL); SmlDevInf *devinf = smlDevInfParse(buffer, size, &error); sml_fail_unless(devinf != NULL, NULL); sml_fail_unless(error == NULL, NULL); smlDevInfUnref(devinf); smlCommandUnref(cmd); sml_fail_unless(smlParserGetCommand(parser, &cmd, &error) == SML_PARSER_RESULT_OTHER, NULL); sml_fail_unless(cmd == NULL, NULL); sml_fail_unless(error == NULL, NULL); SmlBool final = FALSE; SmlBool end = TRUE; sml_fail_unless(smlParserEnd(parser, &final, &end, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(final == TRUE, NULL); sml_fail_unless(end == FALSE, NULL); smlParserFree(parser); } END_TEST START_TEST (xml_parser_devinf_ext) { /* The following test ensures that the parser tolerates Ext in DevInf * like this one from a ticket: * * X-funambol-smartslow * */ const char *data = "1.1SyncML/1.1211PC SuiteIMEI:XXXX100008application/vnd.syncml-devinf+xml./devinf111.1NOKIA66803.04.37IMEI:XXXXphone./C\\Systemata\\Calendar8text/x-vcalendar1.0text/calendar2.0text/x-vcalendar1.01234567./C\\System\\\\\\Data\\Contacts.cdb8text/x-vcard2.1text/vcard3.0text/x-vcard2.11234567./C\\System\\Data\\Notepad.dat8text/plain1.0text/plain1.0text/plain1.0text/plain1.01234567text/x-vcalendarBEGINVCALENDARVEVENTVTODOENDVCALENDARVEVENTVTODOVERSION1.0UIDSUMMARYDESCRIPTIONDTENDDTSTARTAALARMTYPECLASSPUBLICPRIVATECONFIDENTIALCOMPLETEDLOCATIONDCREATEDLAST-MODIFIEDPRIORITYSTATUSRRULEDUEEXDATEX-EPOCAGENDAENTRYTYPEtext/calendarBEGINVCALENDARVEVENTVTODOENDVCALENDARVEVENTVTODOVERSION2.0UIDSUMMARYDESCRIPTIONDTENDDTSTARTAALARMTYPECLASSPUBLICPRIVATECONFIDENTIALCOMPLETEDLOCATIONDCREATEDLAST-MODIFIEDPRIORITYSTATUSRRULEDUEEXDATEX-EPOCAGENDAENTRYTYPEtext/x-vcardBEGINVCARDENDVCARDVERSION2.1REVNADRHOMEWORKTELHOMEWORKCELLPAGERFAXVIDEOFNEMAILINTERNETHOMEWORKURLHOMEWORKNOTETITLEORGPHOTOBDAYSOUNDX-IRMC-Ntext/vcardBEGINVCARDENDVCARDVERSION3.0REVNADRHOMEWORKTELHOMEWORKCELLPAGERFAXVIDEOFNEMAILINTERNETHOMEWORKURLHOMEWORKNOTETITLEORGPHOTOBDAYSOUNDX-IRMC-Ntext/plain\n\n X-funambol-smartslow\n"; SmlError *error = NULL; SmlParser *parser = start_parser(data, &error); sml_fail_unless(parser != NULL, "%s", smlErrorPrint(&error)); SmlHeader *header = NULL; SmlCred *cred = NULL; sml_fail_unless(smlParserGetHeader(parser, &header, &cred, &error), NULL); sml_fail_unless(header != NULL, NULL); sml_fail_unless(cred == NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(header->messageID == 1, NULL); smlHeaderFree(header); SmlStatus *status = NULL; sml_fail_unless(smlParserGetStatus(parser, &status, &error), NULL); sml_fail_unless(status == NULL, NULL); sml_fail_unless(error == NULL, NULL); SmlCommand *cmd = NULL; sml_fail_unless(smlParserGetCommand(parser, &cmd, &error) == SML_PARSER_RESULT_NORMAL, NULL); sml_fail_unless(cmd != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(cmd->cmdID == 8, NULL); sml_fail_unless(cmd->type == SML_COMMAND_TYPE_PUT, NULL); sml_fail_unless(cmd->private.access.item != NULL, NULL); char *buffer = NULL; unsigned int size = 0; sml_fail_unless(smlItemGetData(cmd->private.access.item, &buffer, &size, &error), NULL); sml_fail_unless(error == NULL, NULL); SmlDevInf *devinf = smlDevInfParse(buffer, size, &error); sml_fail_unless(devinf != NULL, "%s", smlErrorPrint(&error)); sml_fail_unless(error == NULL, NULL); smlDevInfUnref(devinf); smlCommandUnref(cmd); sml_fail_unless(smlParserGetCommand(parser, &cmd, &error) == SML_PARSER_RESULT_OTHER, NULL); sml_fail_unless(cmd == NULL, NULL); sml_fail_unless(error == NULL, NULL); SmlBool final = FALSE; SmlBool end = TRUE; sml_fail_unless(smlParserEnd(parser, &final, &end, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(final == TRUE, NULL); sml_fail_unless(end == FALSE, NULL); smlParserFree(parser); } END_TEST START_TEST (xml_parser_empty_data_element) { const char *data = "SyncML/1.21.211testtest2./devinf12"; SmlError *error = NULL; SmlParser *parser = start_parser(data, &error); sml_fail_unless(parser != NULL, "%s", smlErrorPrint(&error)); SmlHeader *header = NULL; SmlCred *cred = NULL; sml_fail_unless(smlParserGetHeader(parser, &header, &cred, &error), NULL); sml_fail_unless(header != NULL, NULL); sml_fail_unless(cred == NULL, NULL); sml_fail_unless(error == NULL, NULL); smlHeaderFree(header); SmlStatus *status = NULL; sml_fail_unless(smlParserGetStatus(parser, &status, &error), NULL); sml_fail_unless(status == NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlParserGetStatus(parser, &status, &error), NULL); sml_fail_unless(status == NULL, NULL); sml_fail_unless(error == NULL, NULL); SmlCommand *cmd = NULL; sml_fail_unless(smlParserGetCommand(parser, &cmd, &error), NULL); sml_fail_unless(cmd != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(cmd->cmdID == 2, NULL); smlCommandUnref(cmd); sml_fail_unless(smlParserGetCommand(parser, &cmd, &error), NULL); sml_fail_unless(cmd == NULL, NULL); sml_fail_unless(error == NULL, NULL); SmlBool final = TRUE; SmlBool end = TRUE; sml_fail_unless(smlParserEnd(parser, &final, &end, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(final == FALSE, NULL); sml_fail_unless(end == FALSE, NULL); smlParserFree(parser); } END_TEST START_TEST (xml_parser_msgref_zero) { const char *data = "1.1SyncML/1.1161PC SuiteIMEI:XXXXXXXXXXXXXXX6000100SyncHdr/PC Suite513201Alert513302Alert513403Alert513" ; SmlError *error = NULL; SmlParser *parser = start_parser(data, &error); sml_fail_unless(parser != NULL, "%s", smlErrorPrint(&error)); SmlHeader *header = NULL; SmlCred *cred = NULL; sml_fail_unless(smlParserGetHeader(parser, &header, &cred, &error), NULL); sml_fail_unless(header != NULL, NULL); sml_fail_unless(cred == NULL, NULL); sml_fail_unless(error == NULL, NULL); smlHeaderFree(header); SmlStatus *status = NULL; sml_fail_unless(smlParserGetStatus(parser, &status, &error), NULL); sml_fail_unless(status != NULL, NULL); sml_fail_unless(status->msgRef == 0, NULL); sml_fail_unless(error == NULL, NULL); smlStatusUnref(status); sml_fail_unless(smlParserGetStatus(parser, &status, &error), NULL); sml_fail_unless(status != NULL, NULL); sml_fail_unless(status->msgRef == 0, NULL); sml_fail_unless(error == NULL, NULL); smlStatusUnref(status); sml_fail_unless(smlParserGetStatus(parser, &status, &error), NULL); sml_fail_unless(status != NULL, NULL); sml_fail_unless(status->msgRef == 0, NULL); sml_fail_unless(error == NULL, NULL); smlStatusUnref(status); sml_fail_unless(smlParserGetStatus(parser, &status, &error), NULL); sml_fail_unless(status != NULL, NULL); sml_fail_unless(status->msgRef == 0, NULL); sml_fail_unless(error == NULL, NULL); smlStatusUnref(status); SmlBool final = FALSE; SmlBool end = FALSE; sml_fail_unless(smlParserEnd(parser, &final, &end, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(final == TRUE, NULL); sml_fail_unless(end == TRUE, NULL); smlParserFree(parser); } END_TEST START_TEST (xml_parser_ctcap_property_size) { const char *data = "1.2SyncML/1.2421http://www.foo.barIMEI:XXXXXXXXXX60001application/vnd.syncml-devinf+wbxml./devinf121.2SonyEricssonW580iR6BC002R6AR5AIMEI:XXXXXXXXXXXXphoneContactsContacts64text/x-vcard2.1text/vcard3.0text/x-vcard2.1text/x-vcard2.1BDAYURL120TITLE15ORG30EMAIL350TYPEINTERNETADR2TYPEWORKHOMENOTE50TEL580TYPECELLHOMEFAXWORKN30VERSION2.1ENDVCARDBEGINVCARDtext/vcard3.0BDAYURL120TITLE15ORG30EMAIL350TYPEINTERNETADR2TYPEWORKHOMENOTE50TEL580TYPECELLHOMEFAXWORKN30VERSION3.0ENDVCARDBEGINVCARD100012467CalendarCalendar64text/x-vcalendar1.0text/x-vcalendar1.0text/x-vcalendar1.0LAST-MODIFIEDEXDATERRULE50CLASSPUBLICCATEGORIESVACATIONTRAVELPHONE CALLMISCELLANEOUSMEETINGAALARMDALARMDTENDDTSTARTDESCRIPTION128LOCATION50SUMMARY100VERSION1.0ENDVEVENTVCALENDARBEGINVEVENTVCALENDAR30012467TasksTasks64text/x-vcalendar1.0text/x-vcalendar1.0text/x-vcalendar1.0LAST-MODIFIEDCLASSPUBLICCATEGORIESVACATIONTRAVELPHONE CALLMISCELLANEOUSMEETINGSTATUSCOMPLETEDNEEDS ACTIONACCEPTEDPRIORITYDUECOMPLETEDAALARMDALARMDESCRIPTION128SUMMARY100VERSION1.0ENDVCALENDARVTODOBEGINVCALENDARVTODO8012467NotesNotes64text/plain1.0text/plain1.0text/plain1.0BODY2542512467BookmarksBookmarks64text/x-vbookmark1.0text/x-vbookmark1.0text/x-vbookmark1.0X-IRMC-URLURLTITLEBEGINVENVVBKMENDVENVVBKMVERSION1.0124672201contactsContacts016553565469465999"; ; SmlError *error = NULL; SmlParser *parser = start_parser(data, &error); sml_fail_unless(parser != NULL, "%s", smlErrorPrint(&error)); SmlHeader *header = NULL; SmlCred *cred = NULL; sml_fail_unless(smlParserGetHeader(parser, &header, &cred, &error), NULL); sml_fail_unless(header != NULL, NULL); sml_fail_unless(cred == NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(header->messageID == 1, NULL); smlHeaderFree(header); SmlStatus *status = NULL; sml_fail_unless(smlParserGetStatus(parser, &status, &error), NULL); sml_fail_unless(status == NULL, NULL); sml_fail_unless(error == NULL, NULL); SmlCommand *cmd = NULL; sml_fail_unless(smlParserGetCommand(parser, &cmd, &error) == SML_PARSER_RESULT_NORMAL, NULL); sml_fail_unless(cmd != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(cmd->cmdID == 1, NULL); sml_fail_unless(cmd->type == SML_COMMAND_TYPE_PUT, NULL); sml_fail_unless(cmd->private.access.item != NULL, NULL); char *buffer = NULL; unsigned int size = 0; sml_fail_unless(smlItemGetData(cmd->private.access.item, &buffer, &size, &error), NULL); sml_fail_unless(error == NULL, NULL); SmlDevInf *devinf = smlDevInfParse(buffer, size, &error); sml_fail_unless(devinf != NULL, NULL); sml_fail_unless(error == NULL, NULL); smlDevInfUnref(devinf); smlCommandUnref(cmd); sml_fail_unless(smlParserGetCommand(parser, &cmd, &error) == SML_PARSER_RESULT_NORMAL, NULL); sml_fail_unless(cmd != NULL, NULL); sml_fail_unless(error == NULL, NULL); smlCommandUnref(cmd); SmlBool final = FALSE; SmlBool end = TRUE; sml_fail_unless(smlParserEnd(parser, &final, &end, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(final == TRUE, NULL); sml_fail_unless(end == FALSE, NULL); smlParserFree(parser); } END_TEST START_TEST (xml_parser_ctcap11_size) { const char *data = "1.1SyncML/1.111PC SuiteIMEI:..............3584110SyncHdr/PC Suite200211AlertContacts2003application/vnd.syncml-devinf+xml./devinf111.1NokiaNokia 6300V 05.00\n27-04-07\nRM-217\n(c) N..V 05.00\n27-04-07\nRM-217\n(c) N..4001IMEI:..............phone/telecom/pb.vcf8text/x-vcard2.1text/x-vcard2.112467/telecom/cal.vcs8text/x-vcalendar1.0text/x-vcalendar1.012467/telecom/note.txt8text/plaintext/plain12467text/x-vcardBEGINVCARDVERSION2.1ENDVCARDNFNTELPREFWORKHOMEVOICEFAXCELLNOTEURLEMAILADRPHOTOBDAYTITLEORGX-NICKNAMEtext/x-vcalendarBEGINVCALENDARVEVENTVTODOVERSION1.0ENDVCALENDARVEVENTVTODODTSTARTDTENDSUMMARYDESCRIPTIONDUEAALARMDALARMRRULECATEGORIESSPECIAL OCCASIONMEETINGPHONE CALLMISCELLANEOUSREMINDERLOCATIONSTATUSNEEDS ACTIONCOMPLETEDPRIORITY123EXDATEtext/plainchr30004201Contacts/telecom/pb.vcf0297"; SmlError *error = NULL; SmlParser *parser = start_parser(data, &error); sml_fail_unless(parser != NULL, "%s", smlErrorPrint(&error)); SmlHeader *header = NULL; SmlCred *cred = NULL; sml_fail_unless(smlParserGetHeader(parser, &header, &cred, &error), NULL); sml_fail_unless(header != NULL, NULL); sml_fail_unless(cred == NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(header->messageID == 1, NULL); smlHeaderFree(header); SmlStatus *status = NULL; sml_fail_unless(smlParserGetStatus(parser, &status, &error), NULL); sml_fail_unless(status != NULL, NULL); sml_fail_unless(error == NULL, NULL); smlStatusUnref(status); sml_fail_unless(smlParserGetStatus(parser, &status, &error), NULL); sml_fail_unless(status != NULL, NULL); sml_fail_unless(error == NULL, NULL); smlStatusUnref(status); SmlCommand *cmd = NULL; sml_fail_unless(smlParserGetCommand(parser, &cmd, &error) == SML_PARSER_RESULT_NORMAL, NULL); sml_fail_unless(cmd != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(cmd->cmdID == 3, NULL); sml_fail_unless(cmd->type == SML_COMMAND_TYPE_PUT, NULL); sml_fail_unless(cmd->private.access.item != NULL, NULL); char *buffer = NULL; unsigned int size = 0; sml_fail_unless(smlItemGetData(cmd->private.access.item, &buffer, &size, &error), NULL); sml_fail_unless(error == NULL, NULL); SmlDevInf *devinf = smlDevInfParse(buffer, size, &error); sml_fail_unless(devinf != NULL, NULL); sml_fail_unless(error == NULL, NULL); smlDevInfUnref(devinf); smlCommandUnref(cmd); sml_fail_unless(smlParserGetCommand(parser, &cmd, &error) == SML_PARSER_RESULT_NORMAL, NULL); sml_fail_unless(cmd != NULL, NULL); sml_fail_unless(error == NULL, NULL); smlCommandUnref(cmd); SmlBool final = FALSE; SmlBool end = TRUE; sml_fail_unless(smlParserEnd(parser, &final, &end, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(final == TRUE, NULL); sml_fail_unless(end == FALSE, NULL); smlParserFree(parser); } END_TEST /* Funambol (e.g. scheduleworld.com) embeds Item in to Status * including the Meta element with MaxObjSize for example. */ START_TEST (xml_parser_item_with_meta_in_status) { const char *data = "" \ "1.1SyncML/1.1401424john.doe@example.com1234567http://sync.scheduleworld.com/funambol/ds/X4zeEsMHK05KPXYs3jD-MA==http://sync.scheduleworld.com/funambol/ds/X4zeEsMHK05KPXYs3jD-MA==" \ "" \ "" \ "140SyncHdr" \ "http://sync.scheduleworld.com/funambol/ds/X4zeEsMHK05KPXYs3jD-MA==" \ "jku@vili200" \ "" \ "" \ "2" \ "4" \ "10" \ "Alert" \ "200" \ "" \ "1024000" \ "" \ "" \ "" \ "" \ ""; /* check for valid document */ SmlError *error = NULL; SmlParser *parser = start_parser(data, &error); sml_fail_unless(parser != NULL, "%s", smlErrorPrint(&error)); /* parse header and first status */ SmlHeader *header = NULL; SmlCred *cred = NULL; sml_fail_unless(smlParserGetHeader(parser, &header, &cred, &error), NULL); sml_fail_unless(header != NULL, NULL); sml_fail_unless(cred == NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(header->messageID == 4, "The message ID must be 4."); smlHeaderFree(header); SmlStatus *status = NULL; sml_fail_unless(smlParserGetStatus(parser, &status, &error), NULL); sml_fail_unless(status != NULL, NULL); sml_fail_unless(error == NULL, NULL); smlStatusUnref(status); /* parse second status with item and meta info */ sml_fail_unless(smlParserGetStatus(parser, &status, &error), "%s", smlErrorPrint(&error)); sml_fail_unless(status != NULL, NULL); sml_fail_unless(error == NULL, NULL); smlStatusUnref(status); /* cleanup */ smlParserFree(parser); } END_TEST /* Funambol (e.g. scheduleworld.com) embeds Item in to Status * including the Meta element with MaxObjSize for example. * The Item element can include an empty Data element too. * If XML native communication is used then an empty Data * element usually looks like "". */ START_TEST (xml_parser_item_with_meta_and_long_empty_data_in_status) { const char *data = "" \ "1.1SyncML/1.1401424john.doe@example.com1234567http://sync.scheduleworld.com/funambol/ds/X4zeEsMHK05KPXYs3jD-MA==http://sync.scheduleworld.com/funambol/ds/X4zeEsMHK05KPXYs3jD-MA==" \ "" \ "" \ "140SyncHdr" \ "http://sync.scheduleworld.com/funambol/ds/X4zeEsMHK05KPXYs3jD-MA==" \ "jku@vili200" \ "" \ "" \ "2" \ "4" \ "10" \ "Alert" \ "200" \ "" \ "1024000" \ "" \ "" \ "" \ "" \ "" \ ""; /* check for valid document */ SmlError *error = NULL; SmlParser *parser = start_parser(data, &error); sml_fail_unless(parser != NULL, "%s", smlErrorPrint(&error)); /* parse header and first status */ SmlHeader *header = NULL; SmlCred *cred = NULL; sml_fail_unless(smlParserGetHeader(parser, &header, &cred, &error), NULL); sml_fail_unless(header != NULL, NULL); sml_fail_unless(cred == NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(header->messageID == 4, "The message ID must be 4."); smlHeaderFree(header); SmlStatus *status = NULL; sml_fail_unless(smlParserGetStatus(parser, &status, &error), NULL); sml_fail_unless(status != NULL, NULL); sml_fail_unless(error == NULL, NULL); smlStatusUnref(status); /* parse second status with item and meta info */ sml_fail_unless(smlParserGetStatus(parser, &status, &error), "%s", smlErrorPrint(&error)); sml_fail_unless(status != NULL, NULL); sml_fail_unless(error == NULL, NULL); smlStatusUnref(status); /* cleanup */ smlParserFree(parser); } END_TEST /* Funambol (e.g. scheduleworld.com) embeds Item in to Status * including the Meta element with MaxObjSize for example. * The Item element can include an empty Data element too. * If WBXML encoded communication is used then an empty Data * element usually looks like "". */ START_TEST (xml_parser_item_with_meta_and_short_empty_data_in_status) { const char *data = "" \ "1.1SyncML/1.1401424john.doe@example.com1234567http://sync.scheduleworld.com/funambol/ds/X4zeEsMHK05KPXYs3jD-MA==http://sync.scheduleworld.com/funambol/ds/X4zeEsMHK05KPXYs3jD-MA==" \ "" \ "" \ "140SyncHdr" \ "http://sync.scheduleworld.com/funambol/ds/X4zeEsMHK05KPXYs3jD-MA==" \ "jku@vili200" \ "" \ "" \ "2" \ "4" \ "10" \ "Alert" \ "200" \ "" \ "1024000" \ "" \ "" \ "" \ "" \ "" \ ""; /* check for valid document */ SmlError *error = NULL; SmlParser *parser = start_parser(data, &error); sml_fail_unless(parser != NULL, "%s", smlErrorPrint(&error)); /* parse header and first status */ SmlHeader *header = NULL; SmlCred *cred = NULL; sml_fail_unless(smlParserGetHeader(parser, &header, &cred, &error), NULL); sml_fail_unless(header != NULL, NULL); sml_fail_unless(cred == NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(header->messageID == 4, "The message ID must be 4."); smlHeaderFree(header); SmlStatus *status = NULL; sml_fail_unless(smlParserGetStatus(parser, &status, &error), NULL); sml_fail_unless(status != NULL, NULL); sml_fail_unless(error == NULL, NULL); smlStatusUnref(status); /* parse second status with item and meta info */ sml_fail_unless(smlParserGetStatus(parser, &status, &error), "%s", smlErrorPrint(&error)); sml_fail_unless(status != NULL, NULL); sml_fail_unless(error == NULL, NULL); smlStatusUnref(status); /* cleanup */ smlParserFree(parser); } END_TEST @SML_TESTCASE_CODE@ libsyncml-0.5.4/tests/check_devinf.c100644 1750 1750 43215 11211710410 17364 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2005 Armin Bauer * Copyright (C) 2008 Michael Bell * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include "tests/support.h" #include #include #define NUM_SESSIONS 30 typedef struct managerTracker { SmlManager *manager; SmlSession *session; } managerTracker; unsigned int transport_errors = 0; unsigned int num_sessions = 0; unsigned int num_finals = 0; unsigned int num_end = 0; unsigned int session_errors = 0; int num_disconnects = 0; unsigned int defaultMaxMsgSize = 10240; unsigned int defaultMaxObjSize = 1024000; static void _manager_event(SmlManager *manager, SmlManagerEventType type, SmlSession *session, SmlError *error, void *userdata) { smlTrace(TRACE_ENTRY, "%s(%p, %i, %p, %p, %p)", __func__, manager, type, session, error, userdata); managerTracker *tracker = userdata; smlAssert(manager); smlAssert(userdata); switch (type) { case SML_MANAGER_SESSION_FLUSH: break; case SML_MANAGER_CONNECT_DONE: case SML_MANAGER_SESSION_ESTABLISHED: break; case SML_MANAGER_DISCONNECT_DONE: num_disconnects++; break; case SML_MANAGER_TRANSPORT_ERROR: transport_errors++; break; case SML_MANAGER_SESSION_NEW: smlAssert(session); tracker->session = session; num_sessions++; smlSessionRef(session); break; case SML_MANAGER_SESSION_FINAL: num_finals++; break; case SML_MANAGER_SESSION_END: num_end++; break; case SML_MANAGER_SESSION_ERROR: case SML_MANAGER_SESSION_WARNING: session_errors++; break; } smlTrace(TRACE_EXIT, "%s", __func__); } START_TEST (devinf_crash) { transport_errors = 0; num_sessions = 0; num_finals = 0; num_end = 0; num_disconnects = 0; session_errors = 0; setup_testbed(NULL); SmlError *error = NULL; SmlTransport *server = smlTransportNew(SML_TRANSPORT_HTTP_SERVER, &error); SmlTransport *client = smlTransportNew(SML_TRANSPORT_HTTP_CLIENT, &error); sml_fail_unless(smlTransportSetConfigOption(client, "URL", "http://127.0.0.1:12030", &error), NULL); sml_fail_unless(smlTransportSetConfigOption(server, "PORT", "12030", &error), NULL); managerTracker *clienttracker = g_malloc0(sizeof(managerTracker)); SmlManager *clientmanager = clienttracker->manager = smlManagerNew(client, &error); smlManagerSetEventCallback(clienttracker->manager, _manager_event, clienttracker); managerTracker *servertracker = g_malloc0(sizeof(managerTracker)); SmlManager *servermanager = servertracker->manager = smlManagerNew(server, &error); smlManagerSetEventCallback(servertracker->manager, _manager_event, servertracker); smlManagerSetLocalMaxMsgSize(servermanager, defaultMaxMsgSize); smlManagerSetLocalMaxObjSize(servermanager, defaultMaxObjSize); sml_fail_unless(smlTransportInitialize(client, &error), "%s", smlErrorPrint(&error)); sml_fail_unless(smlTransportInitialize(server, &error), "%s", smlErrorPrint(&error)); sml_fail_unless(smlManagerStart(clientmanager, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlManagerStart(servermanager, &error), NULL); sml_fail_unless(error == NULL, NULL); SmlLocation *loc = smlLocationNew("test", NULL, &error); sml_fail_unless(loc != NULL, NULL); sml_fail_unless(error == NULL, NULL); /* The authenticator */ SmlAuthenticator *auth2 = smlAuthNew(&error); smlAuthSetEnable(auth2, FALSE); smlAuthRegister(auth2, servermanager, &error); /* The devinf obj for the server */ SmlDevInf *devinf = smlDevInfNew("LibSyncmML", SML_DEVINF_DEVTYPE_WORKSTATION, &error); smlDevInfSetSupportsLargeObjs(devinf, TRUE); SmlDevInfAgent *agent = smlDevInfAgentNew(devinf, &error); smlDevInfAgentRegister(agent, servermanager, &error); /* And we also add the devinfo to the devinf agent */ SmlDevInfDataStore *datastore = smlDevInfDataStoreNew(smlLocationGetURI(loc), &error); smlDevInfDataStoreSetRxPref(datastore, SML_ELEMENT_TEXT_VCARD, "2.1"); smlDevInfDataStoreSetTxPref(datastore, SML_ELEMENT_TEXT_VCARD, "2.1"); smlDevInfDataStoreSetSyncCap(datastore, SML_DEVINF_SYNCTYPE_TWO_WAY, TRUE); smlDevInfDataStoreSetSyncCap(datastore, SML_DEVINF_SYNCTYPE_SLOW_SYNC, TRUE); smlDevInfDataStoreSetSyncCap(datastore, SML_DEVINF_SYNCTYPE_SERVER_ALERTED_SYNC, TRUE); smlDevInfAddDataStore(devinf, datastore); smlLocationUnref(loc); const char *datastr = "1.1SyncML/1.1101PC SuiteIMEI:xxxxxxxxxxxxxxx10000110SyncHdr/PC Suite200211AlertContacts2003201./Contacts./C\\System\\Data\\Contacts.cdb20060317T083025Z4application/vnd.syncml-devinf+xml./devinf111.1NOKIA66802.04.15IMEI:xxxxxxxxxxxxxxxphone./C\\System\\Data\\Contacts.cdb8text/x-vcard2.1text/vcard3.0text/x-vcard2.11234567text/x-vcardBEGINVCARDENDVCARDVERSION2.1REVNADRHOMEWORKTELHOMEWORKCELLPAGERFAXVIDEOFNEMAILINTERNETHOMEWORKURLHOMEWORKNOTETITLEORGPHOTOBDAYSOUNDX-IRMC-Ntext/vcardBEGINVCARDENDVCARDVERSION3.0REVNADRHOMEWORKTELHOMEWORKCELLPAGERFAXVIDEOFNEMAILINTERNETHOMEWORKURLHOMEWORKNOTETITLEORGPHOTOBDAYSOUNDX-IRMC-N5application/vnd.syncml-devinf+xml./devinf11"; SmlTransportData *data = smlTransportDataNew((char *)datastr, strlen(datastr), SML_MIMETYPE_XML, FALSE, &error); sml_fail_unless(data != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlTransportSend(client, NULL, data, &error), NULL); sml_fail_unless(error == NULL, NULL); smlTransportDataDeref(data); while (num_finals != 1) { smlManagerDispatch(servermanager); usleep(100); } SmlDevInf *devinf2 = smlDevInfAgentGetSessionDevInf(agent, servertracker->session); sml_fail_unless(devinf2 != NULL, NULL); sml_fail_unless(transport_errors == 0, NULL); sml_fail_unless(num_sessions == 1, NULL); sml_fail_unless(num_finals == 1, NULL); sml_fail_unless(num_end == 0, NULL); sml_fail_unless(session_errors == 1, NULL); /* stop the server */ smlManagerStop(servermanager); while(num_disconnects < 1) { smlManagerDispatch(servermanager); } smlManagerFree(servermanager); smlAuthFree(auth2); /* stop the client */ smlManagerStop(clientmanager); smlManagerFree(clientmanager); /* The clienttracker session was referenced by the manager callback. */ smlSessionUnref(servertracker->session); smlSafeFree((gpointer *)&clienttracker); smlSafeFree((gpointer *)&servertracker); sml_fail_unless(smlTransportFinalize(server, &error), "%s", smlErrorPrint(&error)); sml_fail_unless(smlTransportFinalize(client, &error), "%s", smlErrorPrint(&error)); smlTransportFree(server); smlTransportFree(client); smlDevInfAgentFree(agent); } END_TEST /* client -- devinf get --> server * server -- result --> client * client -- status --> server * server -- status --> client */ START_TEST (devinf_result) { transport_errors = 0; num_sessions = 0; num_finals = 0; num_end = 0; num_disconnects = 0; session_errors = 0; setup_testbed(NULL); SmlError *error = NULL; SmlTransport *server = smlTransportNew(SML_TRANSPORT_HTTP_SERVER, &error); SmlTransport *client = smlTransportNew(SML_TRANSPORT_HTTP_CLIENT, &error); sml_fail_unless(smlTransportSetConfigOption(client, "URL", "http://127.0.0.1:12031", &error), NULL); sml_fail_unless(smlTransportSetConfigOption(server, "PORT", "12031", &error), NULL); managerTracker *clienttracker = g_malloc0(sizeof(managerTracker)); SmlManager *clientmanager = clienttracker->manager = smlManagerNew(client, &error); smlManagerSetEventCallback(clienttracker->manager, _manager_event, clienttracker); managerTracker *servertracker = g_malloc0(sizeof(managerTracker)); SmlManager *servermanager = servertracker->manager = smlManagerNew(server, &error); smlManagerSetEventCallback(servertracker->manager, _manager_event, servertracker); smlManagerSetLocalMaxMsgSize(servermanager, defaultMaxMsgSize); smlManagerSetLocalMaxObjSize(servermanager, defaultMaxObjSize); sml_fail_unless(smlTransportInitialize(client, &error), "%s", smlErrorPrint(&error)); sml_fail_unless(smlTransportInitialize(server, &error), "%s", smlErrorPrint(&error)); sml_fail_unless(smlManagerStart(clientmanager, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlManagerStart(servermanager, &error), NULL); sml_fail_unless(error == NULL, NULL); SmlLocation *loc = smlLocationNew("test", NULL, &error); sml_fail_unless(loc != NULL, NULL); sml_fail_unless(error == NULL, NULL); SmlLocation *loc1 = smlLocationNew("test", NULL, &error); sml_fail_unless(loc1 != NULL, NULL); sml_fail_unless(error == NULL, NULL); /* The devinf obj */ SmlDevInf *devinf = smlDevInfNew("LibSyncmML", SML_DEVINF_DEVTYPE_WORKSTATION, &error); SmlDevInfAgent *clientagent = smlDevInfAgentNew(devinf, &error); smlDevInfAgentRegister(clientagent, clientmanager, &error); /* And we also add the devinfo to the devinf agent */ SmlDevInfDataStore *datastore = smlDevInfDataStoreNew(smlLocationGetURI(loc1), &error); smlDevInfDataStoreSetRxPref(datastore, SML_ELEMENT_TEXT_VCARD, "2.1"); smlDevInfDataStoreSetTxPref(datastore, SML_ELEMENT_TEXT_VCARD, "2.1"); smlDevInfDataStoreSetSyncCap(datastore, SML_DEVINF_SYNCTYPE_TWO_WAY, TRUE); smlDevInfDataStoreSetSyncCap(datastore, SML_DEVINF_SYNCTYPE_SLOW_SYNC, TRUE); smlDevInfDataStoreSetSyncCap(datastore, SML_DEVINF_SYNCTYPE_SERVER_ALERTED_SYNC, TRUE); smlDevInfAddDataStore(devinf, datastore); devinf = smlDevInfNew("LibSyncmML", SML_DEVINF_DEVTYPE_SERVER, &error); smlDevInfSetSupportsLargeObjs(devinf, TRUE); SmlDevInfAgent *serveragent = smlDevInfAgentNew(devinf, &error); smlDevInfAgentRegister(serveragent, servermanager, &error); datastore = smlDevInfDataStoreNew(smlLocationGetURI(loc1), &error); smlDevInfDataStoreSetRxPref(datastore, SML_ELEMENT_TEXT_VCARD, "2.1"); smlDevInfDataStoreSetTxPref(datastore, SML_ELEMENT_TEXT_VCARD, "2.1"); smlDevInfDataStoreSetSyncCap(datastore, SML_DEVINF_SYNCTYPE_TWO_WAY, TRUE); smlDevInfDataStoreSetSyncCap(datastore, SML_DEVINF_SYNCTYPE_SLOW_SYNC, TRUE); smlDevInfDataStoreSetSyncCap(datastore, SML_DEVINF_SYNCTYPE_SERVER_ALERTED_SYNC, TRUE); smlDevInfAddDataStore(devinf, datastore); smlLocationUnref(loc1); /* The authenticator */ SmlAuthenticator *auth = smlAuthNew(&error); smlAuthSetEnable(auth, FALSE); smlAuthRegister(auth, clientmanager, &error); /* The authenticator */ SmlAuthenticator *auth2 = smlAuthNew(&error); smlAuthSetEnable(auth2, FALSE); smlAuthRegister(auth2, servermanager, &error); clienttracker->session = smlSessionNew(SML_SESSION_TYPE_CLIENT, SML_MIMETYPE_XML, SML_VERSION_11, SML_PROTOCOL_SYNCML, loc, loc, NULL, 0, &error); sml_fail_unless(smlManagerSessionAdd(clientmanager, clienttracker->session, NULL, &error), NULL); sml_fail_unless(error == NULL, NULL); smlLocationUnref(loc); sml_fail_unless(smlDevInfAgentRequestDevInf(clientagent, clienttracker->session, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlDevInfAgentSendDevInf(clientagent, clienttracker->session, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlSessionFlush(clienttracker->session, TRUE, &error), NULL); sml_fail_unless(error == NULL, NULL); while (num_sessions != 2 || !smlDevInfAgentGetSessionDevInf(serveragent, servertracker->session)) { smlManagerDispatch(servermanager); smlManagerDispatch(clientmanager); usleep(100); } SmlDevInf *recvClientDevInf = smlDevInfAgentGetSessionDevInf(serveragent, servertracker->session); sml_fail_unless(recvClientDevInf != NULL, NULL); sml_fail_unless(smlDevInfNumDataStores(recvClientDevInf) == 1, NULL); sml_fail_unless(servertracker->session != NULL, NULL); sml_fail_unless(smlSessionFlush(servertracker->session, TRUE, &error), NULL); while (!smlDevInfAgentGetSessionDevInf(clientagent, clienttracker->session)) { smlManagerDispatch(servermanager); smlManagerDispatch(clientmanager); usleep(100); } SmlDevInf *recvServerDevInf = smlDevInfAgentGetSessionDevInf(clientagent, clienttracker->session); sml_fail_unless(recvServerDevInf != NULL, NULL); sml_fail_unless(smlDevInfNumDataStores(recvServerDevInf) == 1, NULL); sml_fail_unless(servertracker->session != NULL, NULL); sml_fail_unless(smlSessionEnd(clienttracker->session, &error), NULL); sml_fail_unless(error == NULL, NULL); while (num_end != 2 || num_finals != 4) { smlManagerDispatch(servermanager); smlManagerDispatch(clientmanager); usleep(100); } /* The tracker sessions were referenced by the manager callback. * The clienttracker session is referenced twice because it * was created by the testcase itself. */ smlSessionUnref(servertracker->session); smlSessionUnref(clienttracker->session); smlSessionUnref(clienttracker->session); sml_fail_unless(num_sessions == 2, NULL); sml_fail_unless(num_finals == 4, NULL); sml_fail_unless(num_end == 2, NULL); sml_fail_unless(session_errors == 0, NULL); smlAuthFree(auth); smlAuthFree(auth2); smlSafeFree((gpointer *)&clienttracker); smlSafeFree((gpointer *)&servertracker); smlManagerStop(clientmanager); smlManagerStop(servermanager); while(num_disconnects < 2) { smlManagerDispatch(clientmanager); smlManagerDispatch(servermanager); } smlManagerFree(clientmanager); smlManagerFree(servermanager); sml_fail_unless(smlTransportFinalize(server, &error), "%s", smlErrorPrint(&error)); sml_fail_unless(smlTransportFinalize(client, &error), "%s", smlErrorPrint(&error)); smlTransportFree(server); smlTransportFree(client); smlDevInfAgentFree(clientagent); smlDevInfAgentFree(serveragent); } END_TEST /* SyncML 1.1 uses Size in CTCap Property. * SyncML 1.2 uses MaxSize in CTCap Property. * The CTCap parser must support both. */ START_TEST (devinf_max_size_element) { SmlError *error = NULL; SmlDevInfCTCapType type; /* SyncML 1.1 */ type = smlDevInfCTCapTypeFromString(SML_ELEMENT_SIZE, &error); sml_fail_unless(type == SML_DEVINF_CTCAP_SIZE, NULL); /* SyncML 1.1 and 1.2 */ type = smlDevInfCTCapTypeFromString(SML_ELEMENT_MAXSIZE, &error); sml_fail_unless(type == SML_DEVINF_CTCAP_MAXSIZE, NULL); } END_TEST @SML_TESTCASE_CODE@ libsyncml-0.5.4/tests/check_manager.c100644 1750 1750 55157 11211710410 17533 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2005 Armin Bauer * Copyright (C) 2008 Michael Bell * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include "tests/support.h" #include #define NUM_SESSIONS 30 unsigned int defaultMaxMsgSize = 10240; unsigned int defaultMaxObjSize = 1024000; typedef struct managerTracker { SmlManager *manager; SmlSession *sessions[NUM_SESSIONS]; int num_sessions; } managerTracker; START_TEST (manager_new) { setup_testbed(NULL); SmlError *error = NULL; SmlTransport *server = smlTransportNew(SML_TRANSPORT_HTTP_SERVER, &error); SmlManager *manager = smlManagerNew(server, &error); sml_fail_unless(manager != NULL, NULL); sml_fail_unless(error == NULL, NULL); smlManagerFree(manager); smlTransportFree(server); } END_TEST START_TEST (manager_run) { setup_testbed(NULL); SmlError *error = NULL; SmlTransport *server = smlTransportNew(SML_TRANSPORT_HTTP_SERVER, &error); SmlManager *manager = smlManagerNew(server, &error); sml_fail_unless(manager != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlManagerStart(manager, &error), NULL); sml_fail_unless(error == NULL, NULL); smlManagerStop(manager); smlManagerFree(manager); smlTransportFree(server); } END_TEST unsigned int transport_errors; unsigned int num_connects; unsigned int num_disconnects; unsigned int num_sessions; unsigned int num_finals; unsigned int num_end; unsigned int session_errors; unsigned int num_replies; unsigned int num_alerts; unsigned int num_syncs; unsigned int num_changes; void reset_testbed() { transport_errors = 0; num_connects = 0; num_disconnects = 0; num_sessions = 0; num_finals = 0; num_end = 0; session_errors = 0; num_replies = 0; num_alerts = 0; num_syncs = 0; num_changes = 0; setup_testbed(NULL); } static void _manager_event(SmlManager *manager, SmlManagerEventType type, SmlSession *session, SmlError *error, void *userdata) { smlTrace(TRACE_ENTRY, "%s(%p, %i, %p, %p, %p)", __func__, manager, type, session, error, userdata); managerTracker *tracker = userdata; smlAssert(manager); smlAssert(userdata); switch (type) { case SML_MANAGER_SESSION_FLUSH: break; case SML_MANAGER_CONNECT_DONE: num_connects++; break; case SML_MANAGER_SESSION_ESTABLISHED: break; case SML_MANAGER_DISCONNECT_DONE: num_disconnects++; break; case SML_MANAGER_TRANSPORT_ERROR: transport_errors++; break; case SML_MANAGER_SESSION_NEW: smlAssert(session); tracker->sessions[tracker->num_sessions] = session; tracker->num_sessions++; num_sessions++; smlSessionRef(session); break; case SML_MANAGER_SESSION_FINAL: num_finals++; break; case SML_MANAGER_SESSION_END: num_end++; break; case SML_MANAGER_SESSION_ERROR: case SML_MANAGER_SESSION_WARNING: session_errors++; break; } smlTrace(TRACE_EXIT, "%s", __func__); } static void _header_callback(SmlSession *session, SmlHeader *header, SmlCred *cred, void *userdata) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p, %p)", __func__, session, header, cred, userdata); smlAssert(session); SmlError *error = NULL; SmlStatus *reply = smlStatusNew(SML_AUTH_ACCEPTED, 0, session->lastReceivedMessageID, session->source, session->target, SML_COMMAND_TYPE_HEADER, &error); if (!reply) goto error; if (!smlSessionSendReply(session, reply, &error)) goto error; smlStatusUnref(reply); session->established = TRUE; smlTrace(TRACE_EXIT, "%s", __func__); return; error: smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(&error)); smlErrorDeref(&error); return; } START_TEST (manager_receive) { reset_testbed(); SmlError *error = NULL; SmlTransport *server = smlTransportNew(SML_TRANSPORT_HTTP_SERVER, &error); SmlTransport *client = smlTransportNew(SML_TRANSPORT_HTTP_CLIENT, &error); sml_fail_unless(smlTransportSetConfigOption(client, "URL", "http://127.0.0.1:12020", &error), NULL); sml_fail_unless(smlTransportSetConfigOption(server, "PORT", "12020", &error), NULL); managerTracker *clienttracker = g_malloc0(sizeof(managerTracker)); SmlManager *clientmanager = clienttracker->manager = smlManagerNew(client, &error); smlManagerSetEventCallback(clienttracker->manager, _manager_event, clienttracker); managerTracker *servertracker = g_malloc0(sizeof(managerTracker)); SmlManager *servermanager = servertracker->manager = smlManagerNew(server, &error); smlManagerSetEventCallback(servertracker->manager, _manager_event, servertracker); sml_fail_unless(smlTransportInitialize(client, &error), "%s", smlErrorPrint(&error)); sml_fail_unless(smlTransportInitialize(server, &error), "%s", smlErrorPrint(&error)); sml_fail_unless(smlManagerStart(clientmanager, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlManagerStart(servermanager, &error), NULL); sml_fail_unless(error == NULL, NULL); const char *datastr = ""; SmlTransportData *data = smlTransportDataNew((char *)datastr, strlen(datastr), SML_MIMETYPE_XML, FALSE, &error); sml_fail_unless(data != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlTransportSend(client, NULL, data, &error), NULL); sml_fail_unless(error == NULL, NULL); smlTransportDataDeref(data); while (session_errors < 1) { smlManagerDispatch(servermanager); smlManagerDispatch(clientmanager); usleep(100); } /* If the server disconnects actively without a response * then the service is unavailable. * The HTTP server transport sends status 503 in this case. * This is a transport error. * If the machine is fast enough or a SMP machine * then the transport error is signalled fast enough. */ sml_fail_unless(transport_errors <= 1, NULL); sml_fail_unless(num_sessions == 0, NULL); sml_fail_unless(num_finals == 0, NULL); sml_fail_unless(num_end == 0, NULL); sml_fail_unless(session_errors == 1, NULL); smlManagerStop(clientmanager); smlManagerStop(servermanager); smlManagerFree(clientmanager); smlManagerFree(servermanager); g_free(clienttracker); g_free(servertracker); sml_fail_unless(smlTransportFinalize(client, &error), NULL); sml_fail_unless(smlTransportFinalize(server, &error), "%s", smlErrorPrint(&error)); smlTransportFree(client); smlTransportFree(server); } END_TEST START_TEST (manager_receive_session) { reset_testbed(); SmlError *error = NULL; SmlTransport *server = smlTransportNew(SML_TRANSPORT_HTTP_SERVER, &error); SmlTransport *client = smlTransportNew(SML_TRANSPORT_HTTP_CLIENT, &error); sml_fail_unless(smlTransportSetConfigOption(client, "URL", "http://127.0.0.1:12001", &error), NULL); sml_fail_unless(smlTransportSetConfigOption(server, "PORT", "12001", &error), NULL); managerTracker *clienttracker = g_malloc0(sizeof(managerTracker)); SmlManager *clientmanager = clienttracker->manager = smlManagerNew(client, &error); smlManagerSetEventCallback(clienttracker->manager, _manager_event, clienttracker); managerTracker *servertracker = g_malloc0(sizeof(managerTracker)); SmlManager *servermanager = servertracker->manager = smlManagerNew(server, &error); smlManagerSetEventCallback(servertracker->manager, _manager_event, servertracker); smlManagerSetLocalMaxMsgSize(servertracker->manager, defaultMaxMsgSize); smlManagerSetLocalMaxObjSize(servertracker->manager, defaultMaxObjSize); smlManagerRegisterHeaderHandler(servermanager, _header_callback, NULL, NULL); sml_fail_unless(smlTransportInitialize(client, &error), "%s", smlErrorPrint(&error)); sml_fail_unless(smlTransportInitialize(server, &error), "%s", smlErrorPrint(&error)); sml_fail_unless(smlManagerStart(clientmanager, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlManagerStart(servermanager, &error), NULL); sml_fail_unless(error == NULL, NULL); const char *datastr = "SyncML/1.11.111testtest1/test/testNextlast200"; SmlTransportData *data = smlTransportDataNew((char *)datastr, strlen(datastr), SML_MIMETYPE_XML, FALSE, &error); sml_fail_unless(data != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlTransportSend(client, NULL, data, &error), NULL); sml_fail_unless(error == NULL, NULL); smlTransportDataDeref(data); /* The server detects that there is no matching datastore and * client receives an error from the server as the result. */ while (num_finals < 1 || session_errors < 1) { smlManagerDispatch(servermanager); smlManagerDispatch(clientmanager); usleep(100); } sml_fail_unless(transport_errors == 0, NULL); sml_fail_unless(num_sessions == 1, NULL); sml_fail_unless(num_finals == 1, NULL); sml_fail_unless(num_end == 0, NULL); sml_fail_unless(session_errors == 1, "session errors: %d", session_errors); sml_fail_unless(servertracker->sessions[0] != NULL, NULL); smlSessionUnref(servertracker->sessions[0]); g_free(clienttracker); g_free(servertracker); smlManagerStop(clientmanager); smlManagerStop(servermanager); smlManagerFree(clientmanager); smlManagerFree(servermanager); /* The session is not registered correctly at the client * because HTTP clients create their sessions always by * themselves and not via automatic registration at the * manager. Therefore the client transport must be * explicitely disconnected to avoid warnings from the * transport layer. */ // sml_fail_unless(smlTransportDisconnect(client, NULL, &error), NULL); sml_fail_unless(smlTransportFinalize(client, &error), NULL); sml_fail_unless(smlTransportFinalize(server, &error), NULL); smlTransportFree(server); smlTransportFree(client); } END_TEST START_TEST (manager_end_session) { reset_testbed(); SmlError *error = NULL; SmlTransport *server = smlTransportNew(SML_TRANSPORT_HTTP_SERVER, &error); SmlTransport *client = smlTransportNew(SML_TRANSPORT_HTTP_CLIENT, &error); sml_fail_unless(smlTransportSetConfigOption(client, "URL", "http://127.0.0.1:12002", &error), NULL); sml_fail_unless(smlTransportSetConfigOption(server, "PORT", "12002", &error), NULL); managerTracker *clienttracker = g_malloc0(sizeof(managerTracker)); SmlManager *clientmanager = clienttracker->manager = smlManagerNew(client, &error); smlManagerSetEventCallback(clienttracker->manager, _manager_event, clienttracker); managerTracker *servertracker = g_malloc0(sizeof(managerTracker)); SmlManager *servermanager = servertracker->manager = smlManagerNew(server, &error); smlManagerSetEventCallback(servertracker->manager, _manager_event, servertracker); smlManagerSetLocalMaxMsgSize(servertracker->manager, defaultMaxMsgSize); smlManagerSetLocalMaxObjSize(servertracker->manager, defaultMaxObjSize); smlManagerRegisterHeaderHandler(servermanager, _header_callback, NULL, NULL); sml_fail_unless(smlTransportInitialize(client, &error), "%s", smlErrorPrint(&error)); sml_fail_unless(smlTransportInitialize(server, &error), "%s", smlErrorPrint(&error)); sml_fail_unless(smlManagerStart(clientmanager, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlManagerStart(servermanager, &error), NULL); sml_fail_unless(error == NULL, NULL); /* the client send its data to the server */ const char *datastr = "SyncML/1.11.111testtest1/test/testtest1test2200"; SmlTransportData *data = smlTransportDataNew((char *)datastr, strlen(datastr), SML_MIMETYPE_XML, FALSE, &error); sml_fail_unless(data != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlTransportSend(client, NULL, data, &error), NULL); sml_fail_unless(error == NULL, NULL); smlTransportDataDeref(data); /* the server received the data and has no matching datastore */ while (num_connects < 1 || num_finals < 1 || session_errors < 1) { smlManagerDispatch(servermanager); usleep(100); } sml_fail_unless(transport_errors == 0, NULL); sml_fail_unless(num_sessions == 1, NULL); sml_fail_unless(num_finals == 1, NULL); sml_fail_unless(num_end == 0, NULL); sml_fail_unless(session_errors == 1, NULL); /* the server sends the answer */ sml_fail_unless(servertracker->sessions[0] != NULL, NULL); sml_fail_unless(smlSessionEnd(servertracker->sessions[0], &error), NULL); sml_fail_unless(error == NULL, NULL); smlSessionUnref(servertracker->sessions[0]); /* 1. the server sends the error message * 2. the server declares session end internally * 3. the server aborts the connection */ while (num_end < 1) { smlManagerDispatch(servermanager); usleep(100); } sml_fail_unless(TRUE, "server is passive now"); /* 1. the client receives the connect * 2. the client receives the error message * but the client has no appropriate session * * SO WHAT SHOULD HAPPEN !? * */ while (num_connects < 2 || session_errors < 2) { smlManagerDispatch(clientmanager); usleep(100); } sml_fail_unless(transport_errors == 0, NULL); sml_fail_unless(num_sessions == 1, NULL); sml_fail_unless(num_finals == 1, NULL); sml_fail_unless(num_end == 1, NULL); sml_fail_unless(session_errors == 2, "Session errors: %d", session_errors); sml_fail_unless(num_connects == 2, NULL); g_free(clienttracker); g_free(servertracker); sml_fail_unless(TRUE, "trackers freed"); /* first the client must be stopped */ /* The session is not registered correctly at the client * because HTTP clients create their sessions always by * themselves and not via automatic registration at the * manager. Therefore the client transport must be * explicitely disconnected to avoid warnings from the * transport layer. */ sml_fail_unless(smlTransportDisconnect(client, NULL, &error), NULL); while(num_disconnects < 1) { smlManagerDispatch(clientmanager); } smlManagerStop(clientmanager); smlManagerFree(clientmanager); sml_fail_unless(smlTransportFinalize(client, &error), NULL); smlTransportFree(client); /* second the server must be stopped */ smlManagerStop(servermanager); smlManagerFree(servermanager); sml_fail_unless(smlTransportFinalize(server, &error), NULL); smlTransportFree(server); } END_TEST static void _recv_alert(SmlSession *session, SmlCommand *cmd, void *userdata) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, session, cmd, userdata); SmlError *error = NULL; num_alerts++; SmlStatus *reply = smlCommandNewReply(cmd, SML_NO_ERROR, &error); if (!reply) goto error; if (!smlSessionSendReply(session, reply, &error)) { smlStatusUnref(reply); goto error; } smlStatusUnref(reply); smlTrace(TRACE_EXIT, "%s", __func__); return; error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(&error)); if (error) smlErrorDeref(&error); } static void _status_reply(SmlSession *session, SmlStatus *status, void *userdata) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, session, status, userdata); smlAssert(session != NULL); smlAssert(status != NULL); if (GPOINTER_TO_INT(userdata) == 2) { smlAssert(smlStatusGetCode(status) >= 500); } else if (GPOINTER_TO_INT(userdata) == 1) { smlAssert(smlStatusGetClass(status) == SML_ERRORCLASS_SUCCESS); } else abort(); num_replies++; smlTrace(TRACE_EXIT, "%s", __func__); } START_TEST (manager_start_session) { reset_testbed(); SmlError *error = NULL; SmlTransport *server = smlTransportNew(SML_TRANSPORT_HTTP_SERVER, &error); SmlTransport *client = smlTransportNew(SML_TRANSPORT_HTTP_CLIENT, &error); sml_fail_unless(smlTransportSetConfigOption(client, "URL", "http://127.0.0.1:12004", &error), NULL); sml_fail_unless(smlTransportSetConfigOption(server, "PORT", "12004", &error), NULL); managerTracker *clienttracker = g_malloc0(sizeof(managerTracker)); SmlManager *clientmanager = clienttracker->manager = smlManagerNew(client, &error); smlManagerSetEventCallback(clienttracker->manager, _manager_event, clienttracker); managerTracker *servertracker = g_malloc0(sizeof(managerTracker)); SmlManager *servermanager = servertracker->manager = smlManagerNew(server, &error); smlManagerSetEventCallback(servertracker->manager, _manager_event, servertracker); smlManagerSetLocalMaxMsgSize(servertracker->manager, defaultMaxMsgSize); smlManagerSetLocalMaxObjSize(servertracker->manager, defaultMaxObjSize); sml_fail_unless(smlTransportInitialize(client, &error), "%s", smlErrorPrint(&error)); sml_fail_unless(smlTransportInitialize(server, &error), "%s", smlErrorPrint(&error)); sml_fail_unless(smlManagerStart(clientmanager, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlManagerStart(servermanager, &error), NULL); sml_fail_unless(error == NULL, NULL); SmlLocation *loc = smlLocationNew("test", NULL, &error); sml_fail_unless(loc != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlManagerObjectRegister(servermanager, SML_COMMAND_TYPE_ALERT, NULL, loc, NULL, NULL, _recv_alert, NULL, NULL, &error), NULL); sml_fail_unless(error == NULL, NULL); smlManagerRegisterHeaderHandler(servermanager, _header_callback, NULL, NULL); SmlSession *session = smlSessionNew(SML_SESSION_TYPE_CLIENT, SML_MIMETYPE_XML, SML_VERSION_12, SML_PROTOCOL_SYNCML, loc, loc, NULL, 0, &error); sml_fail_unless(smlManagerSessionAdd(clientmanager, session, NULL, &error), NULL); sml_fail_unless(error == NULL, NULL); SmlCommand *cmd = smlCommandNewAlert(SML_ALERT_TWO_WAY, loc, loc, "last", "next", NULL, &error); sml_fail_unless(cmd != NULL, NULL); sml_fail_unless(error == NULL, NULL); smlLocationUnref(loc); sml_fail_unless(smlSessionSendCommand(session, cmd, NULL, _status_reply, GINT_TO_POINTER(1), &error), NULL); sml_fail_unless(error == NULL, NULL); smlCommandUnref(cmd); sml_fail_unless(smlSessionFlush(session, TRUE, &error), NULL); sml_fail_unless(error == NULL, NULL); /* unref session from smlSessionNew */ smlSessionUnref(session); session = NULL; while (num_finals < 1 || num_alerts < 1 || num_sessions < 2) { smlManagerDispatch(servermanager); smlManagerDispatch(clientmanager); usleep(100); } sml_fail_unless(transport_errors == 0, NULL); sml_fail_unless(num_sessions == 2, NULL); sml_fail_unless(num_finals == 1, NULL); sml_fail_unless(num_end == 0, NULL); sml_fail_unless(session_errors == 0, NULL); sml_fail_unless(servertracker->sessions[0] != NULL, NULL); sml_fail_unless(smlSessionEnd(servertracker->sessions[0], &error), NULL); sml_fail_unless(error == NULL, NULL); /* cleanup references on sessions because of SML_SESSION_NEW event */ smlSessionUnref(clienttracker->sessions[0]); smlSessionUnref(servertracker->sessions[0]); while (num_end != 2 || num_replies != 1 || num_finals != 2) { smlManagerDispatch(servermanager); smlManagerDispatch(clientmanager); usleep(100); } sml_fail_unless(transport_errors == 0, NULL); sml_fail_unless(num_sessions == 2, NULL); sml_fail_unless(num_finals == 2, NULL); sml_fail_unless(num_end == 2, NULL); sml_fail_unless(session_errors == 0, NULL); sml_fail_unless(num_replies == 1, NULL); sml_fail_unless(num_alerts == 1, NULL); sml_fail_unless(num_syncs == 0, NULL); sml_fail_unless(num_changes == 0, NULL); g_free(clienttracker); g_free(servertracker); smlManagerStop(clientmanager); smlManagerStop(servermanager); while(num_disconnects < 2) { smlManagerDispatch(clientmanager); smlManagerDispatch(servermanager); } smlManagerFree(clientmanager); smlManagerFree(servermanager); sml_fail_unless(smlTransportFinalize(server, &error), "%s", smlErrorPrint(&error)); sml_fail_unless(smlTransportFinalize(client, &error), "%s", smlErrorPrint(&error)); smlTransportFree(server); smlTransportFree(client); } END_TEST START_TEST (manager_register) { reset_testbed(); SmlError *error = NULL; SmlLocation *loc = smlLocationNew("test", NULL, &error); SmlTransport *server = smlTransportNew(SML_TRANSPORT_HTTP_SERVER, &error); SmlTransport *client = smlTransportNew(SML_TRANSPORT_HTTP_CLIENT, &error); sml_fail_unless(smlTransportSetConfigOption(client, "URL", "http://127.0.0.1:12005", &error), NULL); sml_fail_unless(smlTransportSetConfigOption(server, "PORT", "12005", &error), NULL); managerTracker *clienttracker = g_malloc0(sizeof(managerTracker)); SmlManager *clientmanager = clienttracker->manager = smlManagerNew(client, &error); smlManagerSetEventCallback(clienttracker->manager, _manager_event, clienttracker); managerTracker *servertracker = g_malloc0(sizeof(managerTracker)); SmlManager *servermanager = servertracker->manager = smlManagerNew(server, &error); smlManagerSetEventCallback(servertracker->manager, _manager_event, servertracker); sml_fail_unless(smlTransportInitialize(client, &error), "%s", smlErrorPrint(&error)); sml_fail_unless(smlTransportInitialize(server, &error), "%s", smlErrorPrint(&error)); sml_fail_unless(smlManagerStart(clientmanager, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlManagerStart(servermanager, &error), NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlManagerObjectRegister(clientmanager, SML_COMMAND_TYPE_ALERT, NULL, loc, NULL, NULL, _recv_alert, NULL, NULL, &error), NULL); sml_fail_unless(error == NULL, NULL); g_free(clienttracker); g_free(servertracker); smlManagerStop(clientmanager); smlManagerStop(servermanager); smlManagerFree(clientmanager); smlManagerFree(servermanager); sml_fail_unless(smlTransportFinalize(server, &error), NULL); sml_fail_unless(smlTransportFinalize(client, &error), NULL); smlLocationUnref(loc); smlTransportFree(server); smlTransportFree(client); } END_TEST @SML_TESTCASE_CODE@ libsyncml-0.5.4/tests/valgrind.supp100644 1750 1750 5056 11211710410 17310 0ustar00bellmichbellmich###################### ## libwbxml ## ###################### { libwbxml 0.10.0 memory leak at SyncML DevInf code Memcheck:Leak fun:malloc fun:wbxml_malloc fun:wbxml_buffer_create_real fun:wbxml_tree_clb_xml_end_element } ################## ## glib ## ################## # g_thread_init # Valgrind 3.4.0 or higher #{ # g_thread_init # Memcheck:Leak # fun:malloc # ... # fun:g_thread_init #} { g_thread_init - 1 Memcheck:Leak fun:malloc fun:g_malloc obj:* fun:g_thread_init_glib fun:g_thread_init } { g_thread_init - 2 Memcheck:Leak fun:realloc fun:g_realloc obj:* fun:g_array_set_size fun:g_static_private_set fun:g_get_language_names fun:g_thread_init } { g_thread_init - 3 Memcheck:Leak fun:calloc fun:g_malloc0 fun:g_thread_self fun:g_thread_init_glib fun:g_thread_init } # g_type_init # Valgrind 3.4.0 or higher #{ # g_type_init # Memcheck:Leak # fun:malloc # ... # fun:g_type_init #} { g_type_init - 1 Memcheck:Leak fun:calloc fun:g_malloc0 obj:* obj:* fun:g_type_init_with_debug_flags fun:g_type_init } { g_type_init - 2 Memcheck:Leak fun:malloc fun:realloc fun:g_realloc fun:g_quark_from_static_string fun:g_type_init_with_debug_flags fun:g_type_init } { g_type_init - 3 Memcheck:Leak fun:calloc fun:g_malloc0 obj:* obj:* fun:g_type_register_fundamental obj:* fun:g_type_init_with_debug_flags fun:g_type_init } { g_type_init - 4 Memcheck:Leak fun:malloc fun:realloc fun:g_realloc obj:* fun:g_type_init_with_debug_flags fun:g_type_init } { g_type_init - 5 Memcheck:Leak fun:malloc fun:realloc obj:* fun:g_type_register_static fun:g_param_type_register_static obj:* fun:g_type_init_with_debug_flags fun:g_type_init } { g_type_init - 6 Memcheck:Leak fun:malloc fun:realloc fun:g_realloc obj:* fun:g_type_register_fundamental obj:* fun:g_type_init_with_debug_flags fun:g_type_init } { g_type_init - 7 Memcheck:Leak fun:malloc fun:g_malloc fun:g_slice_alloc fun:g_hash_table_new_full fun:g_hash_table_new obj:* fun:g_type_init_with_debug_flags fun:g_type_init } { g_type_init - 8 Memcheck:Leak fun:malloc fun:realloc fun:g_realloc obj:* fun:g_type_register_static fun:g_param_type_register_static obj:* fun:g_type_init_with_debug_flags fun:g_type_init } libsyncml-0.5.4/tests/support.h100644 1750 1750 4742 11211710410 16457 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2005 Armin Bauer * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #ifndef _TESTS_SUPPORT_H #define _TESTS_SUPPORT_H #include #include #include void configure_environment(); void cleanup_environment(); char *setup_testbed(char *fkt_name); void destroy_testbed(char *path); void create_case(Suite *s, const char *name, TFun function); SmlParser *start_parser(const char *data, SmlError **error); int sml_sleep(int64_t nanoseconds); #ifdef THREAD_SAFE_CHECK #define sml_fail_unless(expr, ...);\ {\ int _result = expr;\ fail_unless(_result, ## __VA_ARGS__);\ if (!_result) smlAssertMsg(0, g_strdup_printf(__VA_ARGS__));\ } #else /* If check is earlier than 0.9.7 then it is not thread safe. */ extern GStaticMutex __libsyncml_check_mutex; #define sml_fail_unless(expr, ...);\ {\ int _result = expr;\ g_static_mutex_lock(&__libsyncml_check_mutex);\ fail_unless(_result, ## __VA_ARGS__);\ g_static_mutex_unlock(&__libsyncml_check_mutex);\ } /* disabled to avoid unwanted aborts * if (!_result) smlAssertMsg(0, g_strdup_printf(__VA_ARGS__));\ */ #endif /* THREAD_SAFE_CHECK */ /* setup test cases */ #define SML_TESTCASE_START(x) \ const char *_unittest = (#x); \ struct sml_testcase_s sml_testcase[] = { #define SML_TESTCASE_ADD(x) { (#x), x }, #define SML_TESTCASE_END \ { NULL, NULL } \ }; \ \ int main(int argc, char **argv) \ { \ return sml_testsuite(argc, argv, _unittest, sml_testcase); \ } struct sml_testcase_s { const char *name; void *func; }; int sml_testsuite( int argc, char **argv, const char *unittest, struct sml_testcase_s *tc); #endif // _TESTS_SUPPORT_H libsyncml-0.5.4/AUTHORS100644 1750 1750 1344 11211710410 14473 0ustar00bellmichbellmichHere you can see all the people who contributed code to this library. Armin Bauer Michael Bell Daniel Gollub If you contributed code and you don't see your name here but you would like to see it then you have two choices 1. If you have access to the source code repository then please add your name by yourself to the above list (in alphabetical order). 2. If you don't have access to the source code repository then please send an email to opensync-devel@lists.sf.net. We will add you to this list. NOTICE: This is not a replacement for your copyright notices. Please add always a copyright line at the top of each file in front of the license statement. libsyncml-0.5.4/INSTALL100644 1750 1750 1430 11211710410 14450 0ustar00bellmichbellmichInstallation ============ libsyncml is using as "build environment" CMake (http://www.cmake.org) Required packages: * glib2 - http://www.gtk.org * libxml2 - http://xmlsoft.org Optional but recommended: * wbxml2 - http://libwbxml.opensync.org * libsoup (for HTTP transport) - http://live.gnome.org/LibSoup * libopenobex (for OBEX transport) - http://www.bluez.org/openobex-14/ Optional: * libcheck (for Unittests) - http://check.sourceforge.net We only support/test "out of source builds", which means you have to create a separated build directory. Example: Use CMake build system =============================== mkdir build cd build cmake -DCMAKE_INSTALL_PREFIX=$prefix /path/to/libsyncml/source/ make make test (runs the testsuite if libcheck is installed) make install libsyncml-0.5.4/CMakeLists.txt100644 1750 1750 30602 11211710410 16202 0ustar00bellmichbellmichPROJECT( libsyncml C ) SET( LIBSYNCML_VERSION_MAJOR "0" ) SET( LIBSYNCML_VERSION_MINOR "5" ) SET( LIBSYNCML_VERSION_PATCH "4" ) SET( LIBSYNCML_VERSION "${LIBSYNCML_VERSION_MAJOR}.${LIBSYNCML_VERSION_MINOR}.${LIBSYNCML_VERSION_PATCH}" ) # The most recent interface number that this library implements. #UPDATE: If any interface have been added, removed or changed since #UPDATE: the last update increment CURRENT. SET( LIBSYNCML_LIBVERSION_CURRENT 6 ) # The implementation number of the CURRENT interface. # UPDATE: Increment only if the library code has changed at all, since # UPDATE: last release. # UPDATE: Set REVISION to 0 if any interface have been added, removed or # UPDATE: changed since the last update. SET( LIBSYNCML_LIBVERSION_REVISION 0 ) # The difference between the newest and the oldest interfaces. # UPDATE: If any interface have been added since the last public # UPDATE: release, then increment. # UPDATE: If any interface have been removed since the last release # UPDATE: reset to 0. SET( LIBSYNCML_LIBVERSION_AGE 4 ) # The range of implemention CURRENT - AGE is the SOVERSION MATH( EXPR LIBSYNCML_LIBVERSION_SOVERSION "${LIBSYNCML_LIBVERSION_CURRENT} - ${LIBSYNCML_LIBVERSION_AGE}" ) SET( LIBSYNCML_LIBVERSION_VERSION "${LIBSYNCML_LIBVERSION_SOVERSION}.${LIBSYNCML_LIBVERSION_AGE}.${LIBSYNCML_LIBVERSION_REVISION}" ) CMAKE_MINIMUM_REQUIRED(VERSION 2.4) # TODO: Move to external file/macro SET( CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/modules" ) SET( LIB_SUFFIX "" CACHE STRING "The library directory suffix. 32bit empty string, 64 for 64bit." ) SET( LIB_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX}" CACHE INTERNAL "libary location" ) SET( LIBDATA_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX}" CACHE PATH "library data location" ) SET( BIN_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/bin" CACHE INTERNAL "binary location" ) SET( SHARE_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/share" CACHE INTERNAL "data location" ) SET( INCLUDE_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/include" CACHE INTERNAL "headers location" ) SET( LIBEXEC_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/libexec" CACHE INTERNAL "libexec location" ) #MESSAGE(STATUS "CMAKE_MODULE_PATH: ${CMAKE_MODULE_PATH}" ) SET( LIBSYNCML_LIBRARIES_DIR "${LIB_INSTALL_DIR}" CACHE PATH "Syncml library location" ) SET( LIBSYNCML_INCLUDE_DIR "${INCLUDE_INSTALL_DIR}/libsyncml-1.0" CACHE PATH "Syncml headers location" ) SET( LIBSYNCML_BIN_DIR "${BIN_INSTALL_DIR}" CACHE PATH "Syncml binaries location" ) SET( LIBSYNCML_DATA_DIR "${CMAKE_INSTALL_PREFIX}/share" CACHE PATH "Syncml data location" ) SET( LIBSYNCML_EXEC_INSTALL_DIR "${BIN_INSTALL_DIR}" CACHE PATH "Syncml binary location" ) # find header files and type size INCLUDE( CheckTypeSize ) INCLUDE( CheckIncludeFiles ) INCLUDE( CheckFunctionExists ) INCLUDE( Documentation ) INCLUDE( AddDocumentation ) CHECK_INCLUDE_FILES( dlfcn.h HAVE_DLFCN_H ) CHECK_INCLUDE_FILES( inttypes.h HAVE_INTTYPES_H ) CHECK_INCLUDE_FILES( memory.h HAVE_MEMORY_H ) CHECK_INCLUDE_FILES( stdint.h HAVE_STDINT_H ) CHECK_INCLUDE_FILES( stdlib.h HAVE_STDLIB_H ) CHECK_INCLUDE_FILES( strings.h HAVE_STRINGS_H ) CHECK_INCLUDE_FILES( string.h HAVE_STRING_H ) CHECK_INCLUDE_FILES( sys/stat.h HAVE_SYS_STAT_H ) CHECK_INCLUDE_FILES( sys/types.h HAVE_SYS_TYPES_H ) CHECK_INCLUDE_FILES( unistd.h HAVE_UNISTD_H ) CHECK_TYPE_SIZE( uint16_t UINT16_T ) CHECK_TYPE_SIZE( uint32_t UINT32_T ) CHECK_TYPE_SIZE( uint8_t UINT8_T ) # ensure out od source build INCLUDE( MacroEnsureOutOfSourceBuild ) MACRO_ENSURE_OUT_OF_SOURCE_BUILD("${CMAKE_PROJECT_NAME} doesn't allow to build within the source directory. Please, create a seperate build directory and run 'cmake ${PROJECT_SOURCE_DIR} [options]'!") # find requirements SET ( GLIB2_MIN_VERSION "2.12" ) SET ( OPENOBEX_MIN_VERSION "1.1" ) # do not set LIBSOUP2_MIN_VERSION # if you set LIBSOUP2_MIN_VERSION then you cannot support 2.2 and 2.4 SET ( LIBSOUP22_MIN_VERSION "2.2.91" ) SET ( LIBSOUP24_MIN_VERSION "2.3.0.1" ) SET ( LIBWBXML2_MIN_VERSION "0.10.0" ) SET ( CHECK_MIN_VERSION "0.9.7" ) #SET ( BLUEZ_MIN_VERSION "3.19" ) ## avoid caching of CHECK_FOUND without CHECK_MIN_VERSION SET ( CHECK_FOUND OFF ) FIND_PACKAGE( GLIB2 REQUIRED ) FIND_PACKAGE( GTHREAD2 REQUIRED ) FIND_PACKAGE( GOBJECT2 REQUIRED ) FIND_PACKAGE( LibXml2 REQUIRED ) FIND_PACKAGE( OpenObex ) FIND_PACKAGE( LibSoup2 ) FIND_PACKAGE( LibWbxml2 ) FIND_PACKAGE( BlueZ ) FIND_PACKAGE( Check ) IF ( NOT GLIB2_FOUND ) SET ( FATAL_ERROR_GLIB2 "Cannot find correct glib version ${GLIB2_MIN_VERSION}." ) SET ( ENABLE_GLIB2_GREGEX ON ) ELSE ( NOT GLIB2_FOUND ) SET( CMAKE_REQUIRED_INCLUDES ${GLIB2_INCLUDE_DIRS} ) SET( CMAKE_REQUIRED_LIBRARIES ${GLIB2_LIBRARIES} ) CHECK_FUNCTION_EXISTS( g_regex_new GLIB2_HAVE_GREGEX ) IF ( GLIB2_HAVE_GREGEX ) SET ( ENABLE_GLIB2_GREGEX ON ) ELSE ( GLIB2_HAVE_GREGEX ) SET ( ENABLE_GLIB2_GREGEX OFF ) ENDIF ( GLIB2_HAVE_GREGEX ) ENDIF ( NOT GLIB2_FOUND ) IF(LIBWBXML2_FOUND) SET( ENABLE_WBXML ON) ENDIF(LIBWBXML2_FOUND) IF(LIBSOUP2_FOUND) OPTION( ENABLE_HTTP "enable http transports" ON ) IF (LIBSOUP24_FOUND) OPTION( HAVE_LIBSOUP24 "building with libsoup 2.4" ON ) OPTION( HAVE_LIBSOUP22 "building with libsoup 2.2" OFF ) OPTION( HAVE_LIBSOUP22_SOLARIS "enable Solaris libsoup workarounds" OFF ) ELSE (LIBSOUP24_FOUND) OPTION( HAVE_LIBSOUP24 "building with libsoup 2.4" OFF ) OPTION( HAVE_LIBSOUP22 "building with libsoup 2.2" ON ) IF( CMAKE_SYSTEM_NAME STREQUAL "SunOS" ) OPTION( HAVE_LIBSOUP22_SOLARIS "enable Solaris libsoup workarounds" ON ) ELSE( CMAKE_SYSTEM_NAME STREQUAL "SunOS" ) OPTION( HAVE_LIBSOUP22_SOLARIS "enable Solaris libsoup workarounds" OFF ) ENDIF( CMAKE_SYSTEM_NAME STREQUAL "SunOS" ) ENDIF (LIBSOUP24_FOUND) ELSE(LIBSOUP2_FOUND) OPTION( ENABLE_HTTP "enable http transports" OFF ) OPTION( HAVE_LIBSOUP22_SOLARIS "enable Solaris libsoup workarounds" OFF ) ENDIF(LIBSOUP2_FOUND) IF(OPENOBEX_FOUND) OPTION( ENABLE_OBEX "enable obex transports" ON ) IF(BLUEZ_FOUND) OPTION( ENABLE_BLUETOOTH "enable obex over bluetooth transports" ON ) SET( CMAKE_REQUIRED_FLAGS ${BLUEZ_CFLAGS} ) SET( CMAKE_REQUIRED_INCLUDES ${BLUEZ_INCLUDE_DIRS} ) SET( CMAKE_REQUIRED_LIBRARIES ${BLUEZ_LIBRARIES} ) CHECK_FUNCTION_EXISTS( sdp_service_search_attr_req BLUETOOTH_SDPLIB ) IF( BLUETOOTH_SDPLIB ) OPTION( ENABLE_BLUETOOTH_SDPLIB "enable bluetooth channel discovery" ON ) ENDIF( BLUETOOTH_SDPLIB ) ELSEIF(CMAKE_SYSTEM_NAME STREQUAL "FreeBSD") OPTION( ENABLE_BLUETOOTH "enable obex over bluetooth transports" ON ) LINK_LIBRARIES(bluetooth sdp) ELSE(BLUEZ_FOUND) OPTION( ENABLE_BLUETOOTH "enable obex over bluetooth transports" OFF ) ENDIF(BLUEZ_FOUND) IF( OPENOBEX_HAVE_TCPOBEX ) OPTION( ENABLE_OPENOBEX_TCP "enable obex over bluetooth transports" ON ) ELSE( OPENOBEX_HAVE_TCPOBEX ) OPTION( ENABLE_OPENOBEX_TCP "enable OBEX transport via TCP (requires OpenOBEX 1.3+SVN)" OFF ) ENDIF( OPENOBEX_HAVE_TCPOBEX ) ELSE(OPENOBEX_FOUND) OPTION( ENABLE_OBEX "enable obex transports" OFF ) OPTION( ENABLE_OPENOBEX_TCP "enable OBEX transport via TCP (requires OpenOBEX 1.3+SVN)" OFF ) OPTION( ENABLE_BLUETOOTH "enable obex over bluetooth transports" OFF ) OPTION( ENABLE_BLUETOOTH_SDPLIB "enable bluetooth channel discovery" OFF ) ENDIF(OPENOBEX_FOUND) IF( NOT LIBSOUP2_FOUND AND NOT OPENOBEX_FOUND ) SET ( FATAL_ERROR_TRANSPORT "Could not find libsoup2 nor OpenObex! Please install at least one of these libraries (e.g. libsoup2-dev package)." ) ENDIF( NOT LIBSOUP2_FOUND AND NOT OPENOBEX_FOUND ) OPTION( ENABLE_UNIT_TEST "enable unit tests" OFF ) OPTION( THREAD_SAFE_CHECK "check is thread safe" OFF ) IF(CHECK_FOUND) SET( THREAD_SAFE_CHECK ON ) ELSE(CHECK_FOUND) ## perhaps to small version ## these versions are not thread safe SET ( CHECK_MIN_VERSION "" ) FIND_PACKAGE( Check ) ENDIF(CHECK_FOUND) IF(CHECK_FOUND) SET( ENABLE_UNIT_TEST ON ) SET( MEMORYCHECK_SUPPRESSIONS_FILE "${CMAKE_SOURCE_DIR}/tests/valgrind.supp" CACHE FILEPATH "valgrind.supp" ) INCLUDE( Testing ) ENDIF(CHECK_FOUND) OPTION( ENABLE_TOOLS "enable building tools" ON ) OPTION( ENABLE_TRACE "enable tracing" ON ) OPTION( ENABLE_BASE64_TEST "enable deprecated base64 tests" OFF ) SET( PACKAGE "libsyncml" ) SET( PACKAGE_BUGREPORT " " ) SET( PACKAGE_NAME "libsyncml" ) SET( PACKAGE_TARNAME "${PACKAGE_NAME}" ) SET( PACKAGE_STRING "${PACKAGE_NAME} ${LIBSYNCML_VERSION}" ) SET( PACKAGE_VERSION "${LIBSYNCML_VERSION}" ) SET( PACKAGE_SONAME "${LIBSYNCML_LIBVERSION_VERSION}" ) SET( VERSION "${LIBSYNCML_VERSION}" ) CONFIGURE_FILE( "config.h.cmake" "${CMAKE_CURRENT_BINARY_DIR}/config.h") CONFIGURE_FILE( "libsyncml-1.0.pc.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/libsyncml-1.0.pc" @ONLY) # add uninstall target CONFIGURE_FILE( "${CMAKE_SOURCE_DIR}/cmake/modules/cmake_uninstall.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" IMMEDIATE @ONLY) ADD_CUSTOM_TARGET(uninstall "${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake") ADD_SUBDIRECTORY( libsyncml ) ADD_SUBDIRECTORY( tools ) ADD_SUBDIRECTORY( tests ) MARK_AS_ADVANCED( CLEAR BUILD_DOCUMENTATION ) IF ( BUILD_DOCUMENTATION ) IF ( DOXYGEN_DOT_EXECUTABLE ) SET( HAVE_DOT "YES" ) ENDIF ( DOXYGEN_DOT_EXECUTABLE ) # configure tools documentation CONFIGURE_FILE( "tools/Doxyfile.in" "${CMAKE_CURRENT_BINARY_DIR}/tools/Doxyfile" @ONLY) ADD_CUSTOM_TARGET( DoxygenDocTools ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/tools/Doxyfile ) # configure library documentation CONFIGURE_FILE( "libsyncml/Doxyfile.in" "${CMAKE_CURRENT_BINARY_DIR}/libsyncml/Doxyfile" @ONLY) ADD_CUSTOM_TARGET( DoxygenDocLibrary ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/libsyncml/Doxyfile ) # configure general doxygen target CONFIGURE_FILE( "misc/doxygen.css" "${CMAKE_CURRENT_BINARY_DIR}/misc/doxygen.css" @ONLY) # WARNING: Do not use DEPENDS of ADD_CUSTOM_TARGET here ADD_CUSTOM_TARGET( DoxygenDoc ) ADD_DEPENDENCIES( DoxygenDoc DoxygenDocLibrary DoxygenDocTools ) # install documentation ADD_DOCUMENTATION( HTML DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/docs/html/" ) ADD_DOCUMENTATION( MAN DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/docs/man/" ) ADD_DEPENDENCIES( syncml DoxygenDoc ) ENDIF ( BUILD_DOCUMENTATION ) # todo: add requires in pc file INSTALL( FILES "${CMAKE_CURRENT_BINARY_DIR}/libsyncml-1.0.pc" DESTINATION "${LIBDATA_INSTALL_DIR}/pkgconfig/" ) # status output INCLUDE( ShowStatus ) MESSAGE( STATUS "==================================================" ) MESSAGE( STATUS "Operating System ${CMAKE_SYSTEM_NAME}" ) IF( CMAKE_SYSTEM_NAME STREQUAL "SunOS" ) SHOW_STATUS( HAVE_LIBSOUP22_SOLARIS "libsoup 2.2 Solaris workaround" ) ENDIF( CMAKE_SYSTEM_NAME STREQUAL "SunOS" ) MESSAGE( STATUS "==================================================" ) SHOW_STATUS( ENABLE_TOOLS "building tools\t\t" ) SHOW_STATUS( ENABLE_TRACE "tracing tools\t\t" ) SHOW_STATUS( ENABLE_UNIT_TEST "unit tests\t\t\t" ) SHOW_STATUS( THREAD_SAFE_CHECK "check is thread safe\t\t" CHECK_VERSION ) SHOW_STATUS( ENABLE_WBXML "WAP Binary XML\t\t" LIBWBXML2_VERSION ) SHOW_STATUS( ENABLE_HTTP "http transports\t\t" LIBSOUP2_VERSION ) SHOW_STATUS( ENABLE_OBEX "obex transports\t\t" OPENOBEX_VERSION ) SHOW_STATUS( ENABLE_BLUETOOTH "obex over bluetooth transports" BLUEZ_VERSION ) SHOW_STATUS( ENABLE_BLUETOOTH_SDPLIB "bluetooth channel discovery\t" ) SHOW_STATUS( ENABLE_OPENOBEX_TCP "obex over tcp transports\t" ) SHOW_STATUS( ENABLE_BASE64_TEST "deprecated base64 tests\t" ) SHOW_STATUS( ENABLE_GLIB2_GREGEX "glib2 GRegex support\t\t" GLIB2_VERSION ) SHOW_STATUS( BUILD_DOCUMENTATION "documentation\t\t" ) # fatal error detection IF ( FATAL_ERROR_GLIB2 OR FATAL_ERROR_TRANSPORT ) MESSAGE( STATUS "==================================================" ) MESSAGE( STATUS "FATAL ERROR(S) DETECTED ... DETAILS FOLLOW:" ) MESSAGE( STATUS "==================================================" ) IF ( FATAL_ERROR_GLIB2 ) MESSAGE( STATUS "${FATAL_ERROR_GLIB2}" ) ENDIF ( FATAL_ERROR_GLIB2 ) IF ( FATAL_ERROR_TRANSPORT ) MESSAGE( STATUS "${FATAL_ERROR_TRANSPORT}" ) ENDIF ( FATAL_ERROR_TRANSPORT ) MESSAGE( STATUS "==================================================" ) ENDIF ( FATAL_ERROR_GLIB2 OR FATAL_ERROR_TRANSPORT ) ### CPack ######################################## IF( RELEASE_CANDIDATE ) SET( LIBSYNCML_VERSION "${LIBSYNCML_VERSION}-RC${RELEASE_CANDIDATE}" ) ENDIF( RELEASE_CANDIDATE ) SET( CPACK_GENERATOR "TGZ;TBZ2" ) # This line is need for a CMake (Version 2.4.7) Bug - Fixed in CVS SET( CPACK_SOURCE_GENERATOR "TGZ;TBZ2") SET( CPACK_SOURCE_PACKAGE_FILE_NAME "${PROJECT_NAME}-${LIBSYNCML_VERSION}" ) SET( CPACK_SET_DESTDIR ON ) INCLUDE( CPack ) libsyncml-0.5.4/CTestConfig.cmake100644 1750 1750 307 11211710410 16553 0ustar00bellmichbellmichset(CTEST_PROJECT_NAME "libsyncml") set(CTEST_DROP_METHOD "http") set(CTEST_DROP_SITE "opensync.org") set(CTEST_DROP_LOCATION "/testing/submit.php?project=libsyncml") set(CTEST_DROP_SITE_CDASH TRUE) libsyncml-0.5.4/RELEASE100644 1750 1750 4462 11211710410 14432 0ustar00bellmichbellmichMaking a release === To make a release of libsyncml, do the following: - check out a fresh copy from subversion - increment the version numbers in ./CMakeLists.txt: Package Version: LIBSYNCML_VERSION_MAJOR LIBSYNCML_VERSION_MINOR LIBSYNCML_VERSION_PATCH Library Version: LIBSYNCML_LIBVERSION_AGE * Increment if any interface changed since last release. LIBSYNCML_LIBVERSION_REVISION * Increment if any library code changed since last release. Set to 0 if any interface has been changed since last release. LIBSYNCML_LIBVERSION_AGE * Reset to 0 if any interface has been removed since last release. If any interface has been added incremnt. - Run "make Experimental" again several times to try to see race conditions. - Commit the increased version changes (and build fixes) - if someone else made changes and the commit fails, you have to "svn up" and run the tests again - please run "svn status" before you continue to be 100 percent sure that there is no forgotten commit and no unrevisioned file. - please run 'find . -name "svn-commit*.tmp" -print' to detect waste from failed commits. - once the commit succeeds, you have to create a new tag with "mkdir tags/libsyncml-$MAJOR.$MINOR.$PATCH", 'tar -C trunk --exclude="\.svn" -cf - . | tar -C tags/libsyncml-$MAJOR.$MINOR.$PATCH -xf -' "svn add tags/libsyncml-$MAJOR.$MINOR.$PATCH" and "svn commit tags/libsyncml-$MAJOR.$MINOR.$PATCH trunk" (NEVER use "svn cp" because you must replace the external entities of the trunk directory with hard copies of the actual state.) - create tarballs with "cmake $SOURCES; make package_source" (out of source build!) - write checksums with md5sum from the tarballs to a file with the same name like the tarballs without the tar and compression suffixes and plus a new suffix md5sum Example: md5sum libsyncml-$MAJOR.$MINOR.$PATCH.tar.* > libsyncml-$MAJOR.$MINOR.$PATCH.md5sum md5sum -c libsyncml-$MAJOR.$MINOR.$PATCH.md5sum - upload the tarballs and the checksum file to releases. make sure the version numbers are the same! - Annouce the release on the mailing list Tips: * make diff of the exported symbols "nm -g -P libsyncml.so" * read svn log * check trac tickets which are attached to the according milestone libsyncml-0.5.4/libsyncml/sml_error_internals.h100644 1750 1750 4126 11211710410 21654 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2005 Armin Bauer * Copyright (C) 2008 Michael Bell * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #ifndef _SML_ERROR_INTERNALS_H_ #define _SML_ERROR_INTERNALS_H_ #include "syncml_internals.h" /*! @brief Represent an error */ struct SmlError { /** The type of the error that occured */ SmlErrorType type; /** The message */ char *message; /** The printed message */ char *printMessage; /** The reference counter */ gint32 refCount; }; void smlErrorSetVargs(SmlError **error, SmlErrorType type, const char *format, va_list args); #define CHECK_ERROR_REF \ smlAssertMsg(error, SML_ASSERT_MSG_ERROR_MUST_NOT_BE_NULL); \ smlAssertMsg(*error == NULL, SML_ASSERT_MSG_ERROR_MUST_BE_EMPTY); /* Error messages for assertions */ #define SML_ASSERT_MSG_ERROR_MUST_NOT_BE_NULL "The error handling of the function must be used." #define SML_ASSERT_MSG_ERROR_MUST_BE_EMPTY "The error parameter is already filled (ignored error)." #define SML_ASSERT_MSG_ERROR_MUST_BE_AVAILABLE "If this function is used then there must be an error." #define SML_ASSERT_MSG_ERROR_MUST_BE_FILLED "If this function is used then the error message must be present." #define SML_ASSERT_MSG_SAN_PARSE_REQUIRES_MANAGER "If an OMA DS 1.2 SAN must be parsed then the manager must be present." #endif //_SML_ERROR_INTERNALS_H_ /*@}*/ libsyncml-0.5.4/libsyncml/sml_elements_internals.h100644 1750 1750 4463 11211710410 22343 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2005 Armin Bauer * Copyright (C) 2007-2009 Michael Bell * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ /** * @defgroup SmlElementsPrivate SyncML Elements Internals * @ingroup PrivateLowLevelAPI * @brief The private part * */ /*@{*/ #ifndef _SML_ELEMENTS_INTERNALS_H_ #define _SML_ELEMENTS_INTERNALS_H_ #include struct SmlAnchor { char *next; char *last; }; struct SmlLocation { gint refCount; char *locURI; char *locName; }; struct SmlItem { gint refCount; SmlLocation *source; SmlLocation *target; SmlLocation *sourceParent; SmlLocation *targetParent; SmlAnchor *anchor; xmlBuffer *buffer; unsigned int size; char *contenttype; SmlBool moreData; SmlBool disabled; /** If set to true, libsyncml will omit the cdata tags */ SmlBool raw; }; struct SmlMapItem { gint refCount; SmlLocation *source; SmlLocation *target; }; struct SmlHeader { char *sessionID; SmlProtocolVersion version; SmlProtocolType protocol; SmlLocation *source; SmlLocation *target; char *responseURI; SmlBool noResponse; unsigned int messageID; unsigned int maxmsgsize; unsigned int maxobjsize; char *emi; }; struct SmlCred { SmlFormatType format; SmlAuthType type; char *data; gint refCount; char *username; char *password; }; struct SmlChal { SmlFormatType format; SmlAuthType type; char *nonce_plain; unsigned int nonce_length; char *nonce_b64; gint refCount; }; void smlLocationSetURI(SmlLocation *loc, const char *uri); #endif //_SML_ELEMENTS_INTERNALS_H_ /*@}*/ libsyncml-0.5.4/libsyncml/sml_manager.h100644 1750 1750 7300 11211710410 20053 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2005 Armin Bauer * Copyright (C) 2007-2008 Michael Bell * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ /** * @defgroup SmlManager SyncML Manager * @ingroup PublicLowLevelAPI * @brief The public part * */ /*@{*/ #ifndef _SML_MANAGER_H #define _SML_MANAGER_H typedef enum { SML_MANAGER_CONNECT_DONE, SML_MANAGER_DISCONNECT_DONE, SML_MANAGER_TRANSPORT_ERROR, SML_MANAGER_SESSION_NEW, SML_MANAGER_SESSION_FINAL, SML_MANAGER_SESSION_END, SML_MANAGER_SESSION_FLUSH, SML_MANAGER_SESSION_WARNING, SML_MANAGER_SESSION_ERROR, SML_MANAGER_SESSION_ESTABLISHED, } SmlManagerEventType; typedef void (* SmlManagerEventCb) (SmlManager *manager, SmlManagerEventType type, SmlSession *session, SmlError *error, void *userdata); typedef void (* SmlCommandCb) (SmlSession *session, SmlCommand *cmd, void *userdata); typedef void (* SmlHeaderCb) (SmlSession *session, SmlHeader *header, SmlCred *cred, void *userdata); typedef void (* SmlStatusReplyCb) (SmlSession *session, SmlStatus *status, void *userdata); SmlManager *smlManagerNew(SmlTransport *tsp, SmlError **error); void smlManagerFree(SmlManager *manager); SmlBool smlManagerReceive(SmlManager *manager, SmlError **error); void smlManagerSetEventCallback(SmlManager *manager, SmlManagerEventCb callback, void *userdata); SmlSession *smlManagerSessionFind(SmlManager *manager, const char *sessionID); SmlBool smlManagerSessionAdd(SmlManager *manager, SmlSession *session, SmlLink *link, SmlError **error); void smlManagerSessionRemove(SmlManager *manager, SmlSession *session); SmlBool smlManagerObjectRegister(SmlManager *manager, SmlCommandType type, SmlSession *session, SmlLocation *location, SmlLocation *source, const char *contentType, SmlCommandCb callback, SmlCommandCb childCallback, void *userdata, SmlError **error); void smlManagerRegisterHeaderHandler(SmlManager *manager, SmlHeaderCb callback, SmlStatusReplyCb statuscb, void *userdata); void smlManagerObjectFree(SmlObject *object); SmlObject *smlManagerObjectFind(SmlManager *manager, SmlSession *session, SmlCommand *cmd); SmlBool smlManagerDispatchChildCommand(SmlManager *manager, SmlSession *session, SmlCommand *parent, SmlCommand *cmd, SmlError **error); SmlBool smlManagerDispatchHeader(SmlManager *manager, SmlSession *session, SmlHeader *header, SmlCred *cred, SmlError **error); SmlBool smlManagerDispatchCommand(SmlManager *manager, SmlSession *session, SmlCommand *cmd, SmlError **error); SmlBool smlManagerStart(SmlManager *manager, SmlError **error); void smlManagerStop(SmlManager *manager); void smlManagerRun(SmlManager *manager); void smlManagerQuit(SmlManager *manager); void smlManagerDispatch(SmlManager *manager); SmlBool smlManagerCheck(SmlManager *manager); void smlManagerSetLocalMaxMsgSize(SmlManager *manager, unsigned int size); void smlManagerSetLocalMaxObjSize(SmlManager *manager, unsigned int size); char *smlManagerGetNewSessionID(SmlManager *manager); #endif //_SML_MANAGER_H /*@}*/ libsyncml-0.5.4/libsyncml/Doxyfile.in100644 1750 1750 132165 11211710410 17600 0ustar00bellmichbellmich# Doxyfile 1.3.8 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project # # All text after a hash (#) is considered a comment and will be ignored # The format is: # TAG = value [value, ...] # For lists items can also be appended using: # TAG += value [value, ...] # Values that contain spaces should be placed between quotes (" ") #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- # The PROJECT_NAME tag is a single word (or a sequence of words surrounded # by quotes) that should identify the project. PROJECT_NAME = libsyncml # The PROJECT_NUMBER tag can be used to enter a project or revision number. # This could be handy for archiving the generated documentation or # if some version control system is used. PROJECT_NUMBER = @VERSION@ # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) # base path where the generated documentation will be put. # If a relative path is entered, it will be relative to the location # where doxygen was started. If left blank the current directory will be used. OUTPUT_DIRECTORY = docs # If the CREATE_SUBDIRS tag is set to YES, then doxygen will create # 4096 sub-directories (in 2 levels) under the output directory of each output # format and will distribute the generated files over these directories. # Enabling this option can be useful when feeding doxygen a huge amount of source # files, where putting all generated files in the same directory would otherwise # cause performance problems for the file system. CREATE_SUBDIRS = NO # The OUTPUT_LANGUAGE tag is used to specify the language in which all # documentation generated by doxygen is written. Doxygen will use this # information to generate all constant output in the proper language. # The default language is English, other supported languages are: # Brazilian, Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, # Dutch, Finnish, French, German, Greek, Hungarian, Italian, Japanese, # Japanese-en (Japanese with English messages), Korean, Korean-en, Norwegian, # Polish, Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish, # Swedish, and Ukrainian. OUTPUT_LANGUAGE = English # This tag can be used to specify the encoding used in the generated output. # The encoding is not always determined by the language that is chosen, # but also whether or not the output is meant for Windows or non-Windows users. # In case there is a difference, setting the USE_WINDOWS_ENCODING tag to YES # forces the Windows encoding (this is the default for the Windows binary), # whereas setting the tag to NO uses a Unix-style encoding (the default for # all platforms other than Windows). USE_WINDOWS_ENCODING = NO # If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will # include brief member descriptions after the members that are listed in # the file and class documentation (similar to JavaDoc). # Set to NO to disable this. BRIEF_MEMBER_DESC = YES # If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend # the brief description of a member or function before the detailed description. # Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the # brief descriptions will be completely suppressed. REPEAT_BRIEF = YES # This tag implements a quasi-intelligent brief description abbreviator # that is used to form the text in various listings. Each string # in this list, if found as the leading text of the brief description, will be # stripped from the text and the result after processing the whole list, is used # as the annotated text. Otherwise, the brief description is used as-is. If left # blank, the following values are used ("$name" is automatically replaced with the # name of the entity): "The $name class" "The $name widget" "The $name file" # "is" "provides" "specifies" "contains" "represents" "a" "an" "the" ABBREVIATE_BRIEF = # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then # Doxygen will generate a detailed section even if there is only a brief # description. ALWAYS_DETAILED_SEC = NO # If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all inherited # members of a class in the documentation of that class as if those members were # ordinary class members. Constructors, destructors and assignment operators of # the base classes will not be shown. INLINE_INHERITED_MEMB = YES # If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full # path before files name in the file list and in the header files. If set # to NO the shortest path that makes the file name unique will be used. FULL_PATH_NAMES = YES # If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag # can be used to strip a user-defined part of the path. Stripping is # only done if one of the specified strings matches the left-hand part of # the path. The tag can be used to show relative paths in the file list. # If left blank the directory from which doxygen is run is used as the # path to strip. STRIP_FROM_PATH = # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of # the path mentioned in the documentation of a class, which tells # the reader which header file to include in order to use a class. # If left blank only the name of the header file containing the class # definition is used. Otherwise one should specify the include paths that # are normally passed to the compiler using the -I flag. STRIP_FROM_INC_PATH = # If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter # (but less readable) file names. This can be useful is your file systems # doesn't support long names like on DOS, Mac, or CD-ROM. SHORT_NAMES = NO # If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen # will interpret the first line (until the first dot) of a JavaDoc-style # comment as the brief description. If set to NO, the JavaDoc # comments will behave just like the Qt-style comments (thus requiring an # explicit @brief command for a brief description. JAVADOC_AUTOBRIEF = NO # The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen # treat a multi-line C++ special comment block (i.e. a block of //! or /// # comments) as a brief description. This used to be the default behaviour. # The new default is to treat a multi-line C++ comment block as a detailed # description. Set this tag to YES if you prefer the old behaviour instead. MULTILINE_CPP_IS_BRIEF = NO # If the DETAILS_AT_TOP tag is set to YES then Doxygen # will output the detailed description near the top, like JavaDoc. # If set to NO, the detailed description appears after the member # documentation. DETAILS_AT_TOP = NO # If the INHERIT_DOCS tag is set to YES (the default) then an undocumented # member inherits the documentation from any documented member that it # re-implements. INHERIT_DOCS = YES # If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC # tag is set to YES, then doxygen will reuse the documentation of the first # member in the group (if any) for the other members of the group. By default # all members of a group must be documented explicitly. DISTRIBUTE_GROUP_DOC = NO # The TAB_SIZE tag can be used to set the number of spaces in a tab. # Doxygen uses this value to replace tabs by spaces in code fragments. TAB_SIZE = 8 # This tag can be used to specify a number of aliases that acts # as commands in the documentation. An alias has the form "name=value". # For example adding "sideeffect=\par Side Effects:\n" will allow you to # put the command \sideeffect (or @sideeffect) in the documentation, which # will result in a user-defined paragraph with heading "Side Effects:". # You can put \n's in the value part of an alias to insert newlines. ALIASES = # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources # only. Doxygen will then generate output that is more tailored for C. # For instance, some of the names that are used will be different. The list # of all members will be omitted, etc. OPTIMIZE_OUTPUT_FOR_C = YES # Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java sources # only. Doxygen will then generate output that is more tailored for Java. # For instance, namespaces will be presented as packages, qualified scopes # will look different, etc. OPTIMIZE_OUTPUT_JAVA = NO # Set the SUBGROUPING tag to YES (the default) to allow class member groups of # the same type (for instance a group of public functions) to be put as a # subgroup of that type (e.g. under the Public Functions section). Set it to # NO to prevent subgrouping. Alternatively, this can be done per class using # the \nosubgrouping command. SUBGROUPING = YES #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- # If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in # documentation are documented, even if no documentation was available. # Private class members and static file members will be hidden unless # the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES EXTRACT_ALL = NO # If the EXTRACT_PRIVATE tag is set to YES all private members of a class # will be included in the documentation. EXTRACT_PRIVATE = NO # If the EXTRACT_STATIC tag is set to YES all static members of a file # will be included in the documentation. EXTRACT_STATIC = NO # If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) # defined locally in source files will be included in the documentation. # If set to NO only classes defined in header files are included. EXTRACT_LOCAL_CLASSES = YES # This flag is only useful for Objective-C code. When set to YES local # methods, which are defined in the implementation section but not in # the interface are included in the documentation. # If set to NO (the default) only methods in the interface are included. EXTRACT_LOCAL_METHODS = NO # If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all # undocumented members of documented classes, files or namespaces. # If set to NO (the default) these members will be included in the # various overviews, but no documentation section is generated. # This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_MEMBERS = NO # If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all # undocumented classes that are normally visible in the class hierarchy. # If set to NO (the default) these classes will be included in the various # overviews. This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_CLASSES = NO # If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all # friend (class|struct|union) declarations. # If set to NO (the default) these declarations will be included in the # documentation. HIDE_FRIEND_COMPOUNDS = NO # If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any # documentation blocks found inside the body of a function. # If set to NO (the default) these blocks will be appended to the # function's detailed documentation block. HIDE_IN_BODY_DOCS = NO # The INTERNAL_DOCS tag determines if documentation # that is typed after a \internal command is included. If the tag is set # to NO (the default) then the documentation will be excluded. # Set it to YES to include the internal documentation. INTERNAL_DOCS = NO # If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate # file names in lower-case letters. If set to YES upper-case letters are also # allowed. This is useful if you have classes or files whose names only differ # in case and if your file system supports case sensitive file names. Windows # and Mac users are advised to set this option to NO. CASE_SENSE_NAMES = YES # If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen # will show members with their full class and namespace scopes in the # documentation. If set to YES the scope will be hidden. HIDE_SCOPE_NAMES = NO # If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen # will put a list of the files that are included by a file in the documentation # of that file. SHOW_INCLUDE_FILES = YES # If the INLINE_INFO tag is set to YES (the default) then a tag [inline] # is inserted in the documentation for inline members. INLINE_INFO = YES # If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen # will sort the (detailed) documentation of file and class members # alphabetically by member name. If set to NO the members will appear in # declaration order. SORT_MEMBER_DOCS = NO # If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the # brief documentation of file, namespace and class members alphabetically # by member name. If set to NO (the default) the members will appear in # declaration order. SORT_BRIEF_DOCS = NO # If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be # sorted by fully-qualified names, including namespaces. If set to # NO (the default), the class list will be sorted only by class name, # not including the namespace part. # Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. # Note: This option applies only to the class list, not to the # alphabetical list. SORT_BY_SCOPE_NAME = NO # The GENERATE_TODOLIST tag can be used to enable (YES) or # disable (NO) the todo list. This list is created by putting \todo # commands in the documentation. GENERATE_TODOLIST = YES # The GENERATE_TESTLIST tag can be used to enable (YES) or # disable (NO) the test list. This list is created by putting \test # commands in the documentation. GENERATE_TESTLIST = YES # The GENERATE_BUGLIST tag can be used to enable (YES) or # disable (NO) the bug list. This list is created by putting \bug # commands in the documentation. GENERATE_BUGLIST = YES # The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or # disable (NO) the deprecated list. This list is created by putting # \deprecated commands in the documentation. GENERATE_DEPRECATEDLIST = YES # The ENABLED_SECTIONS tag can be used to enable conditional # documentation sections, marked by \if sectionname ... \endif. ENABLED_SECTIONS = # The MAX_INITIALIZER_LINES tag determines the maximum number of lines # the initial value of a variable or define consists of for it to appear in # the documentation. If the initializer consists of more lines than specified # here it will be hidden. Use a value of 0 to hide initializers completely. # The appearance of the initializer of individual variables and defines in the # documentation can be controlled using \showinitializer or \hideinitializer # command in the documentation regardless of this setting. MAX_INITIALIZER_LINES = 30 # Set the SHOW_USED_FILES tag to NO to disable the list of files generated # at the bottom of the documentation of classes and structs. If set to YES the # list will mention the files that were used to generate the documentation. SHOW_USED_FILES = YES #--------------------------------------------------------------------------- # configuration options related to warning and progress messages #--------------------------------------------------------------------------- # The QUIET tag can be used to turn on/off the messages that are generated # by doxygen. Possible values are YES and NO. If left blank NO is used. QUIET = NO # The WARNINGS tag can be used to turn on/off the warning messages that are # generated by doxygen. Possible values are YES and NO. If left blank # NO is used. WARNINGS = YES # If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings # for undocumented members. If EXTRACT_ALL is set to YES then this flag will # automatically be disabled. WARN_IF_UNDOCUMENTED = YES # If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for # potential errors in the documentation, such as not documenting some # parameters in a documented function, or documenting parameters that # don't exist or using markup commands wrongly. WARN_IF_DOC_ERROR = YES # The WARN_FORMAT tag determines the format of the warning messages that # doxygen can produce. The string should contain the $file, $line, and $text # tags, which will be replaced by the file and line number from which the # warning originated and the warning text. WARN_FORMAT = "$file:$line: $text" # The WARN_LOGFILE tag can be used to specify a file to which warning # and error messages should be written. If left blank the output is written # to stderr. WARN_LOGFILE = #--------------------------------------------------------------------------- # configuration options related to the input files #--------------------------------------------------------------------------- # The INPUT tag can be used to specify the files and/or directories that contain # documented source files. You may enter file names like "myfile.cpp" or # directories like "/usr/src/myproject". Separate the files or directories # with spaces. INPUT = @CMAKE_SOURCE_DIR@/libsyncml # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank the following patterns are tested: # *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx *.hpp # *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm FILE_PATTERNS = *.c and *.h # The RECURSIVE tag can be used to turn specify whether or not subdirectories # should be searched for input files as well. Possible values are YES and NO. # If left blank NO is used. RECURSIVE = YES # The EXCLUDE tag can be used to specify files and/or directories that should # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. EXCLUDE = # The EXCLUDE_SYMLINKS tag can be used select whether or not files or directories # that are symbolic links (a Unix filesystem feature) are excluded from the input. EXCLUDE_SYMLINKS = NO # If the value of the INPUT tag contains directories, you can use the # EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude # certain files from those directories. EXCLUDE_PATTERNS = # The EXAMPLE_PATH tag can be used to specify one or more files or # directories that contain example code fragments that are included (see # the \include command). EXAMPLE_PATH = # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank all files are included. EXAMPLE_PATTERNS = # If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be # searched for input files to be used with the \include or \dontinclude # commands irrespective of the value of the RECURSIVE tag. # Possible values are YES and NO. If left blank NO is used. EXAMPLE_RECURSIVE = NO # The IMAGE_PATH tag can be used to specify one or more files or # directories that contain image that are included in the documentation (see # the \image command). IMAGE_PATH = # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program # by executing (via popen()) the command , where # is the value of the INPUT_FILTER tag, and is the name of an # input file. Doxygen will then use the output that the filter program writes # to standard output. If FILTER_PATTERNS is specified, this tag will be # ignored. INPUT_FILTER = # The FILTER_PATTERNS tag can be used to specify filters on a per file pattern # basis. Doxygen will compare the file name with each pattern and apply the # filter if there is a match. The filters are a list of the form: # pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further # info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER # is applied to all files. FILTER_PATTERNS = # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using # INPUT_FILTER) will be used to filter the input files when producing source # files to browse (i.e. when SOURCE_BROWSER is set to YES). FILTER_SOURCE_FILES = NO #--------------------------------------------------------------------------- # configuration options related to source browsing #--------------------------------------------------------------------------- # If the SOURCE_BROWSER tag is set to YES then a list of source files will # be generated. Documented entities will be cross-referenced with these sources. # Note: To get rid of all source code in the generated output, make sure also # VERBATIM_HEADERS is set to NO. SOURCE_BROWSER = YES # Setting the INLINE_SOURCES tag to YES will include the body # of functions and classes directly in the documentation. INLINE_SOURCES = NO # Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct # doxygen to hide any special comment blocks from generated source code # fragments. Normal C and C++ comments will always remain visible. STRIP_CODE_COMMENTS = YES # If the REFERENCED_BY_RELATION tag is set to YES (the default) # then for each documented function all documented # functions referencing it will be listed. REFERENCED_BY_RELATION = YES # If the REFERENCES_RELATION tag is set to YES (the default) # then for each documented function all documented entities # called/used by that function will be listed. REFERENCES_RELATION = NO # If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen # will generate a verbatim copy of the header file for each class for # which an include is specified. Set to NO to disable this. VERBATIM_HEADERS = YES #--------------------------------------------------------------------------- # configuration options related to the alphabetical class index #--------------------------------------------------------------------------- # If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index # of all compounds will be generated. Enable this if the project # contains a lot of classes, structs, unions or interfaces. ALPHABETICAL_INDEX = NO # If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then # the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns # in which this list will be split (can be a number in the range [1..20]) COLS_IN_ALPHA_INDEX = 5 # In case all classes in a project start with a common prefix, all # classes will be put under the same header in the alphabetical index. # The IGNORE_PREFIX tag can be used to specify one or more prefixes that # should be ignored while generating the index headers. IGNORE_PREFIX = #--------------------------------------------------------------------------- # configuration options related to the HTML output #--------------------------------------------------------------------------- # If the GENERATE_HTML tag is set to YES (the default) Doxygen will # generate HTML output. GENERATE_HTML = YES # The HTML_OUTPUT tag is used to specify where the HTML docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `html' will be used as the default path. HTML_OUTPUT = html # The HTML_FILE_EXTENSION tag can be used to specify the file extension for # each generated HTML page (for example: .htm,.php,.asp). If it is left blank # doxygen will generate files with .html extension. HTML_FILE_EXTENSION = .html # The HTML_HEADER tag can be used to specify a personal HTML header for # each generated HTML page. If it is left blank doxygen will generate a # standard header. HTML_HEADER = # The HTML_FOOTER tag can be used to specify a personal HTML footer for # each generated HTML page. If it is left blank doxygen will generate a # standard footer. HTML_FOOTER = # The HTML_STYLESHEET tag can be used to specify a user-defined cascading # style sheet that is used by each HTML page. It can be used to # fine-tune the look of the HTML output. If the tag is left blank doxygen # will generate a default style sheet. Note that doxygen will try to copy # the style sheet file to the HTML output directory, so don't put your own # stylesheet in the HTML output directory as well, or it will be erased! HTML_STYLESHEET = misc/doxygen.css # If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, # files or namespaces will be aligned in HTML using tables. If set to # NO a bullet list will be used. HTML_ALIGN_MEMBERS = YES # If the GENERATE_HTMLHELP tag is set to YES, additional index files # will be generated that can be used as input for tools like the # Microsoft HTML help workshop to generate a compressed HTML help file (.chm) # of the generated HTML documentation. GENERATE_HTMLHELP = NO # If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can # be used to specify the file name of the resulting .chm file. You # can add a path in front of the file if the result should not be # written to the html output directory. CHM_FILE = # If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can # be used to specify the location (absolute path including file name) of # the HTML help compiler (hhc.exe). If non-empty doxygen will try to run # the HTML help compiler on the generated index.hhp. HHC_LOCATION = # If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag # controls if a separate .chi index file is generated (YES) or that # it should be included in the master .chm file (NO). GENERATE_CHI = NO # If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag # controls whether a binary table of contents is generated (YES) or a # normal table of contents (NO) in the .chm file. BINARY_TOC = NO # The TOC_EXPAND flag can be set to YES to add extra items for group members # to the contents of the HTML help documentation and to the tree view. TOC_EXPAND = NO # The DISABLE_INDEX tag can be used to turn on/off the condensed index at # top of each HTML page. The value NO (the default) enables the index and # the value YES disables it. DISABLE_INDEX = NO # This tag can be used to set the number of enum values (range [1..20]) # that doxygen will group on one line in the generated HTML documentation. ENUM_VALUES_PER_LINE = 4 # If the GENERATE_TREEVIEW tag is set to YES, a side panel will be # generated containing a tree-like index structure (just like the one that # is generated for HTML Help). For this to work a browser that supports # JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, # Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are # probably better off using the HTML help feature. GENERATE_TREEVIEW = NO # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be # used to set the initial width (in pixels) of the frame in which the tree # is shown. TREEVIEW_WIDTH = 250 #--------------------------------------------------------------------------- # configuration options related to the LaTeX output #--------------------------------------------------------------------------- # If the GENERATE_LATEX tag is set to YES (the default) Doxygen will # generate Latex output. GENERATE_LATEX = NO # The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `latex' will be used as the default path. LATEX_OUTPUT = latex # The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be # invoked. If left blank `latex' will be used as the default command name. LATEX_CMD_NAME = latex # The MAKEINDEX_CMD_NAME tag can be used to specify the command name to # generate index for LaTeX. If left blank `makeindex' will be used as the # default command name. MAKEINDEX_CMD_NAME = makeindex # If the COMPACT_LATEX tag is set to YES Doxygen generates more compact # LaTeX documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_LATEX = NO # The PAPER_TYPE tag can be used to set the paper type that is used # by the printer. Possible values are: a4, a4wide, letter, legal and # executive. If left blank a4wide will be used. PAPER_TYPE = a4wide # The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX # packages that should be included in the LaTeX output. EXTRA_PACKAGES = # The LATEX_HEADER tag can be used to specify a personal LaTeX header for # the generated latex document. The header should contain everything until # the first chapter. If it is left blank doxygen will generate a # standard header. Notice: only use this tag if you know what you are doing! LATEX_HEADER = # If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated # is prepared for conversion to pdf (using ps2pdf). The pdf file will # contain links (just like the HTML output) instead of page references # This makes the output suitable for online browsing using a pdf viewer. PDF_HYPERLINKS = NO # If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of # plain latex in the generated Makefile. Set this option to YES to get a # higher quality PDF documentation. USE_PDFLATEX = NO # If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. # command to the generated LaTeX files. This will instruct LaTeX to keep # running if errors occur, instead of asking the user for help. # This option is also used when generating formulas in HTML. LATEX_BATCHMODE = NO # If LATEX_HIDE_INDICES is set to YES then doxygen will not # include the index chapters (such as File Index, Compound Index, etc.) # in the output. LATEX_HIDE_INDICES = NO #--------------------------------------------------------------------------- # configuration options related to the RTF output #--------------------------------------------------------------------------- # If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output # The RTF output is optimized for Word 97 and may not look very pretty with # other RTF readers or editors. GENERATE_RTF = NO # The RTF_OUTPUT tag is used to specify where the RTF docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `rtf' will be used as the default path. RTF_OUTPUT = rtf # If the COMPACT_RTF tag is set to YES Doxygen generates more compact # RTF documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_RTF = NO # If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated # will contain hyperlink fields. The RTF file will # contain links (just like the HTML output) instead of page references. # This makes the output suitable for online browsing using WORD or other # programs which support those fields. # Note: wordpad (write) and others do not support links. RTF_HYPERLINKS = NO # Load stylesheet definitions from file. Syntax is similar to doxygen's # config file, i.e. a series of assignments. You only have to provide # replacements, missing definitions are set to their default value. RTF_STYLESHEET_FILE = # Set optional variables used in the generation of an rtf document. # Syntax is similar to doxygen's config file. RTF_EXTENSIONS_FILE = #--------------------------------------------------------------------------- # configuration options related to the man page output #--------------------------------------------------------------------------- # If the GENERATE_MAN tag is set to YES (the default) Doxygen will # generate man pages GENERATE_MAN = NO # The MAN_OUTPUT tag is used to specify where the man pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `man' will be used as the default path. MAN_OUTPUT = man # The MAN_EXTENSION tag determines the extension that is added to # the generated man pages (default is the subroutine's section .3) MAN_EXTENSION = .3 # If the MAN_LINKS tag is set to YES and Doxygen generates man output, # then it will generate one additional man file for each entity # documented in the real man page(s). These additional files # only source the real man page, but without them the man command # would be unable to find the correct page. The default is NO. MAN_LINKS = NO #--------------------------------------------------------------------------- # configuration options related to the XML output #--------------------------------------------------------------------------- # If the GENERATE_XML tag is set to YES Doxygen will # generate an XML file that captures the structure of # the code including all documentation. GENERATE_XML = NO # The XML_OUTPUT tag is used to specify where the XML pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `xml' will be used as the default path. XML_OUTPUT = xml # The XML_SCHEMA tag can be used to specify an XML schema, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_SCHEMA = # The XML_DTD tag can be used to specify an XML DTD, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_DTD = # If the XML_PROGRAMLISTING tag is set to YES Doxygen will # dump the program listings (including syntax highlighting # and cross-referencing information) to the XML output. Note that # enabling this will significantly increase the size of the XML output. XML_PROGRAMLISTING = YES #--------------------------------------------------------------------------- # configuration options for the AutoGen Definitions output #--------------------------------------------------------------------------- # If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will # generate an AutoGen Definitions (see autogen.sf.net) file # that captures the structure of the code including all # documentation. Note that this feature is still experimental # and incomplete at the moment. GENERATE_AUTOGEN_DEF = NO #--------------------------------------------------------------------------- # configuration options related to the Perl module output #--------------------------------------------------------------------------- # If the GENERATE_PERLMOD tag is set to YES Doxygen will # generate a Perl module file that captures the structure of # the code including all documentation. Note that this # feature is still experimental and incomplete at the # moment. GENERATE_PERLMOD = NO # If the PERLMOD_LATEX tag is set to YES Doxygen will generate # the necessary Makefile rules, Perl scripts and LaTeX code to be able # to generate PDF and DVI output from the Perl module output. PERLMOD_LATEX = NO # If the PERLMOD_PRETTY tag is set to YES the Perl module output will be # nicely formatted so it can be parsed by a human reader. This is useful # if you want to understand what is going on. On the other hand, if this # tag is set to NO the size of the Perl module output will be much smaller # and Perl will parse it just the same. PERLMOD_PRETTY = YES # The names of the make variables in the generated doxyrules.make file # are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. # This is useful so different doxyrules.make files included by the same # Makefile don't overwrite each other's variables. PERLMOD_MAKEVAR_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the preprocessor #--------------------------------------------------------------------------- # If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will # evaluate all C-preprocessor directives found in the sources and include # files. ENABLE_PREPROCESSING = YES # If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro # names in the source code. If set to NO (the default) only conditional # compilation will be performed. Macro expansion can be done in a controlled # way by setting EXPAND_ONLY_PREDEF to YES. MACRO_EXPANSION = NO # If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES # then the macro expansion is limited to the macros specified with the # PREDEFINED and EXPAND_AS_PREDEFINED tags. EXPAND_ONLY_PREDEF = NO # If the SEARCH_INCLUDES tag is set to YES (the default) the includes files # in the INCLUDE_PATH (see below) will be search if a #include is found. SEARCH_INCLUDES = YES # The INCLUDE_PATH tag can be used to specify one or more directories that # contain include files that are not input files but should be processed by # the preprocessor. INCLUDE_PATH = # You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard # patterns (like *.h and *.hpp) to filter out the header-files in the # directories. If left blank, the patterns specified with FILE_PATTERNS will # be used. INCLUDE_FILE_PATTERNS = # The PREDEFINED tag can be used to specify one or more macro names that # are defined before the preprocessor is started (similar to the -D option of # gcc). The argument of the tag is a list of macros of the form: name # or name=definition (no spaces). If the definition and the = are # omitted =1 is assumed. PREDEFINED = DOXYGEN_SHOULD_SKIP_THIS # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then # this tag can be used to specify a list of macro names that should be expanded. # The macro definition that is found in the sources will be used. # Use the PREDEFINED tag if you want to use a different macro definition. EXPAND_AS_DEFINED = # If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then # doxygen's preprocessor will remove all function-like macros that are alone # on a line, have an all uppercase name, and do not end with a semicolon. Such # function macros are typically used for boiler-plate code, and will confuse the # parser if not removed. SKIP_FUNCTION_MACROS = YES #--------------------------------------------------------------------------- # Configuration::additions related to external references #--------------------------------------------------------------------------- # The TAGFILES option can be used to specify one or more tagfiles. # Optionally an initial location of the external documentation # can be added for each tagfile. The format of a tag file without # this location is as follows: # TAGFILES = file1 file2 ... # Adding location for the tag files is done as follows: # TAGFILES = file1=loc1 "file2 = loc2" ... # where "loc1" and "loc2" can be relative or absolute paths or # URLs. If a location is present for each tag, the installdox tool # does not have to be run to correct the links. # Note that each tag file must have a unique name # (where the name does NOT include the path) # If a tag file is not located in the directory in which doxygen # is run, you must also specify the path to the tagfile here. TAGFILES = # When a file name is specified after GENERATE_TAGFILE, doxygen will create # a tag file that is based on the input files it reads. GENERATE_TAGFILE = # If the ALLEXTERNALS tag is set to YES all external classes will be listed # in the class index. If set to NO only the inherited external classes # will be listed. ALLEXTERNALS = NO # If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed # in the modules index. If set to NO, only the current project's groups will # be listed. EXTERNAL_GROUPS = YES # The PERL_PATH should be the absolute path and name of the perl script # interpreter (i.e. the result of `which perl'). PERL_PATH = /usr/bin/perl #--------------------------------------------------------------------------- # Configuration options related to the dot tool #--------------------------------------------------------------------------- # If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will # generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base or # super classes. Setting the tag to NO turns the diagrams off. Note that this # option is superseded by the HAVE_DOT option below. This is only a fallback. It is # recommended to install and use dot, since it yields more powerful graphs. CLASS_DIAGRAMS = YES # If set to YES, the inheritance and collaboration graphs will hide # inheritance and usage relations if the target is undocumented # or is not a class. HIDE_UNDOC_RELATIONS = YES # If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is # available from the path. This tool is part of Graphviz, a graph visualization # toolkit from AT&T and Lucent Bell Labs. The other options in this section # have no effect if this option is set to NO (the default) HAVE_DOT = YES # If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect inheritance relations. Setting this tag to YES will force the # the CLASS_DIAGRAMS tag to NO. CLASS_GRAPH = YES # If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect implementation dependencies (inheritance, containment, and # class references variables) of the class with other documented classes. COLLABORATION_GRAPH = YES # If the UML_LOOK tag is set to YES doxygen will generate inheritance and # collaboration diagrams in a style similar to the OMG's Unified Modeling # Language. UML_LOOK = YES # If set to YES, the inheritance and collaboration graphs will show the # relations between templates and their instances. TEMPLATE_RELATIONS = NO # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT # tags are set to YES then doxygen will generate a graph for each documented # file showing the direct and indirect include dependencies of the file with # other documented files. INCLUDE_GRAPH = YES # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and # HAVE_DOT tags are set to YES then doxygen will generate a graph for each # documented header file showing the documented files that directly or # indirectly include this file. INCLUDED_BY_GRAPH = YES # If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will # generate a call dependency graph for every global function or class method. # Note that enabling this option will significantly increase the time of a run. # So in most cases it will be better to enable call graphs for selected # functions only using the \callgraph command. CALL_GRAPH = YES # If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen # will graphical hierarchy of all classes instead of a textual one. GRAPHICAL_HIERARCHY = YES # The DOT_IMAGE_FORMAT tag can be used to set the image format of the images # generated by dot. Possible values are png, jpg, or gif # If left blank png will be used. DOT_IMAGE_FORMAT = png # The tag DOT_PATH can be used to specify the path where the dot tool can be # found. If left blank, it is assumed the dot tool can be found on the path. DOT_PATH = # The DOTFILE_DIRS tag can be used to specify one or more directories that # contain dot files that are included in the documentation (see the # \dotfile command). DOTFILE_DIRS = # The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width # (in pixels) of the graphs generated by dot. If a graph becomes larger than # this value, doxygen will try to truncate the graph, so that it fits within # the specified constraint. Beware that most browsers cannot cope with very # large images. MAX_DOT_GRAPH_WIDTH = 1024 # The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height # (in pixels) of the graphs generated by dot. If a graph becomes larger than # this value, doxygen will try to truncate the graph, so that it fits within # the specified constraint. Beware that most browsers cannot cope with very # large images. MAX_DOT_GRAPH_HEIGHT = 1024 # The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the # graphs generated by dot. A depth value of 3 means that only nodes reachable # from the root by following a path via at most 3 edges will be shown. Nodes that # lay further from the root node will be omitted. Note that setting this option to # 1 or 2 may greatly reduce the computation time needed for large code bases. Also # note that a graph may be further truncated if the graph's image dimensions are # not sufficient to fit the graph (see MAX_DOT_GRAPH_WIDTH and MAX_DOT_GRAPH_HEIGHT). # If 0 is used for the depth value (the default), the graph is not depth-constrained. MAX_DOT_GRAPH_DEPTH = 0 # If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will # generate a legend page explaining the meaning of the various boxes and # arrows in the dot generated graphs. GENERATE_LEGEND = YES # If the DOT_CLEANUP tag is set to YES (the default) Doxygen will # remove the intermediate dot files that are used to generate # the various graphs. DOT_CLEANUP = YES #--------------------------------------------------------------------------- # Configuration::additions related to the search engine #--------------------------------------------------------------------------- # The SEARCHENGINE tag specifies whether or not a search engine should be # used. If set to NO the values of all tags below this one will be ignored. SEARCHENGINE = NO libsyncml-0.5.4/libsyncml/sml_transport_internals.h100644 1750 1750 11567 11211710410 22606 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2005 Armin Bauer * Copyright (C) 2007-2008 Michael Bell * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #ifndef _SML_TRANSPORT_INTERNALS_H_ #define _SML_TRANSPORT_INTERNALS_H_ #include "sml_queue_internals.h" typedef SmlBool (* SmlTransportSetConfigOptionFn) (SmlTransport *tsp, const char *name, const char *value, SmlError **error); typedef SmlBool (* SmlTransportSetConnectionTypeFn) (SmlTransport *tsp, SmlTransportConnectionType type, SmlError **error); typedef SmlBool (* SmlTransportInitializeFn) (SmlTransport *tsp, SmlError **error); /* This function is used for transport clients * to support redirects from the server. * Example: Funambol works with such redirects * because of Tomcat's session management. */ typedef SmlBool (* SmlTransportSetResponseUriFn) (SmlTransport *tsp, const char *uri, SmlError **error); /* This function is used to add some kind of session id * to the URL of the server. This is necessary to * avoid session hijacking. */ typedef char * (* SmlTransportGetResponseUriFn) (SmlLink *link, SmlSession *session, SmlError **error); typedef SmlBool (* SmlTransportFinalizeFn) (void *data, SmlError **error); typedef void (* SmlTransportConnectFn) (void *data); typedef void (* SmlTransportDisconnectFn) (void *data, void *link_data); typedef void (* SmlTransportSendFn) (void *userdata, void *link_data, SmlTransportData *data, SmlError *error); typedef struct SmlTransportFunctions { SmlTransportSetConfigOptionFn set_config_option; SmlTransportSetConnectionTypeFn set_connection_type; SmlTransportInitializeFn initialize; SmlTransportSetResponseUriFn set_response_uri; SmlTransportGetResponseUriFn get_response_uri; SmlTransportFinalizeFn finalize; SmlTransportConnectFn connect; SmlTransportDisconnectFn disconnect; SmlTransportSendFn send; } SmlTransportFunctions; typedef enum SmlTransportState { SML_TRANSPORT_UNINITIALIZED, SML_TRANSPORT_INITIALIZED, SML_TRANSPORT_CONNECTED, SML_TRANSPORT_ERROR } SmlTransportState; struct SmlTransport { GMainContext *context; SmlThread *thread; SmlTransportState state; SmlTransportType type; SmlTransportFunctions functions; void *transport_data; SmlQueue *command_queue; SmlTransportEventCb event_callback; void *event_callback_userdata; gint event_callback_ref_count; SmlError *cached_error; SmlBool connected; GHashTable *links; GMutex *links_mutex; unsigned int connections; GMutex *connections_mutex; }; struct SmlLink { SmlTransport *tsp; void *link_data; gint32 refCount; }; typedef enum SmlTransportCommandType { SML_TRANSPORT_CMD_SEND, SML_TRANSPORT_CMD_CONNECT, SML_TRANSPORT_CMD_DISCONNECT } SmlTransportCommandType; typedef struct SmlTransportCommand { SmlTransportCommandType type; SmlTransportData *data; const void *config; SmlLink *link; SmlError *error; } SmlTransportCommand; struct SmlTransportData { char *data; unsigned long size; SmlMimeType type; SmlBool ownsData; gint32 refCount; /** This field specifies if the data transported * here needs an reply from the other side. If it does not * need one, the transports might take special precautions */ SmlBool needsAnswer; /** This is only needed to switch the mime type when using the OBEX Transporting * and sending a SyncML 1.2 SAN package. The transport send() function for OBEX transport * make use of a PUT/GET command sequence. To avoid that GET command request with mimetype * SAN, we have to store the regular mimetype to continue the sync in this struct. * So the SyncML 1.2 notification looks like this: * PUT SML_MIMETYPE_SAN * -- wait for response -- * GET SML_MIMETYPE_XML / SML_MIMETYPE_WBXML (not SML_MIMETYPE_SAN!) * -- wait for resposne -- */ SmlMimeType type_get; }; void smlTransportWorkerHandler(void *message, void *userdata); SmlBool smlTransportReceiveEvent(SmlTransport *tsp, SmlLink *link, SmlTransportEventType type, SmlTransportData *data, SmlError *error); SmlBool smlTransportSetResponseURI(SmlTransport *tsp, const char *uri, SmlError **error); char *smlTransportGetResponseURI(SmlLink *link, SmlSession *session, SmlError **error); #endif //_SML_TRANSPORT_INTERNALS_H_ libsyncml-0.5.4/libsyncml/sml_base64.c100644 1750 1750 11143 11211710410 17540 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2005 Armin Bauer * Copyright (C) 2008 Michael Bell * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include "syncml.h" #include "sml_error.h" #include "sml_error_internals.h" #include "syncml_internals.h" static SmlBool _smlBase64DecodeBinary(const char *input, unsigned int size, char **output, unsigned int *outsize, SmlError **error); static SmlBool _smlBase64EncodeBinary(const char *input, unsigned int size, char **output, SmlError **error); /* FIXME: DEPRECATED*/ SmlBool smlBase64Decode(const char *input, char **output, unsigned int *outsize, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p, %p)", __func__, input, output, outsize, error); CHECK_ERROR_REF smlAssert(output); smlAssert(outsize); if (!input) { *output = NULL; *outsize = 0; goto out; } if (!_smlBase64DecodeBinary(input, strlen(input), output, outsize, error)) goto error; out: smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return FALSE; } /* FIXME: DEPRECATED*/ SmlBool smlBase64DecodeBinary(const char *input, unsigned int size, char **output, unsigned int *outsize, SmlError **error) { return _smlBase64DecodeBinary(input, size, output, outsize, error); } /* The only reason for this internal function is * to avoid compiler warnings during the normal build process * even if the whole base64 API is deprecated. */ static SmlBool _smlBase64DecodeBinary(const char *input, unsigned int size, char **output, unsigned int *outsize, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %i, %p, %p, %p)", __func__, input, size, output, outsize, error); CHECK_ERROR_REF if (!input || !size) { *output = NULL; *outsize = 0; goto out; } size_t length = 0; *output = (char *) g_base64_decode(input, &length); if (length < 1) { smlErrorSet(error, SML_ERROR_GENERIC, "Invalid base64 input"); goto error; } *outsize = length; /* This is some kind of special for libsyncml. * We have to add a padding NULL byte. */ char *result = smlTryMalloc0(*outsize + 1, error); if (result == NULL) goto error; memcpy(result, *output, *outsize); g_free(*output); *output = result; *outsize = *outsize + 1; out: smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error: *output = NULL; *outsize = 0; smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return FALSE; } /* FIXME: DEPRECATED*/ SmlBool smlBase64Encode(const char *input, char **output, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, input, output, error); CHECK_ERROR_REF smlAssert(output); if (!input) { *output = NULL; smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; } if (_smlBase64EncodeBinary(input, strlen(input), output, error)) { smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; } smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return FALSE; } /* FIXME: DEPRECATED*/ SmlBool smlBase64EncodeBinary(const char *input, unsigned int size, char **output, SmlError **error) { return _smlBase64EncodeBinary(input, size, output, error); } /* The only reason for this internal function is * to avoid compiler warnings during the normal build process * even if the whole base64 API is deprecated. */ static SmlBool _smlBase64EncodeBinary(const char *input, unsigned int size, char **output, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %i, %p, %p)", __func__, input, size, output, error); CHECK_ERROR_REF smlAssert(output); if (!input) { *output = NULL; goto out; } *output = g_base64_encode((const unsigned char *) input, size); if (!*output) { smlErrorSet(error, SML_ERROR_GENERIC, "Base64 encoding failed."); goto error; } out: smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return FALSE; } libsyncml-0.5.4/libsyncml/sml_parse.h100644 1750 1750 17345 11211710410 17605 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2005 Armin Bauer * Copyright (C) 2008 Michael Bell * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #ifndef _SML_PARSE_H_ #define _SML_PARSE_H_ typedef enum { SML_PARSER_RESULT_ERROR = 0, SML_PARSER_RESULT_OPEN = 1, SML_PARSER_RESULT_CLOSE = 2, SML_PARSER_RESULT_NORMAL = 3, SML_PARSER_RESULT_STATUS = 4, SML_PARSER_RESULT_OTHER = 5 } SmlParserResult; typedef void (* SmlParserFreeFunction) (void *userdata); typedef SmlBool (* SmlParserStartFunction) (void *userdata, const char *data, unsigned int size, SmlError **error); typedef SmlBool (* SmlParserEndFunction) (void *userdata, SmlBool *final, SmlBool *end, SmlError **error); typedef SmlBool (* SmlParserHeaderFunction) (void *userdata, SmlHeader **header, SmlCred **cred, SmlError **error); typedef SmlBool (* SmlParserStatusFunction) (void *userdata, SmlStatus **status, SmlError **error); typedef SmlParserResult (* SmlParserCommandFunction) (void *userdata, SmlCommand **cmd, SmlError **error); typedef struct SmlParserFunctions { SmlParserFreeFunction free; SmlParserStartFunction start; SmlParserEndFunction end; SmlParserHeaderFunction get_header; SmlParserStatusFunction get_status; SmlParserCommandFunction get_cmd; } SmlParserFunctions; typedef void (* SmlAssemblerFreeFunction) (void *userdata); typedef SmlBool (* SmlAssemblerStartFunction) (void *userdata, SmlSession *session, SmlError **error); typedef SmlBool (* SmlAssemblerEndFunction) (void *userdata, SmlError **error); typedef SmlBool (* SmlAssemblerRunFunction) (void *userdata, char **data, unsigned int *size, SmlBool *end, SmlBool final, unsigned int maxsize, SmlError **error); typedef unsigned int (* SmlAssemblerFlushFunction) (void *userdata); typedef SmlBool (* SmlAssemblerStatusFunction) (void *userdata, SmlStatus *status, SmlError **error); typedef SmlBool (* SmlAssemblerRemStatusFunction) (void *userdata, SmlError **error); typedef SmlBool (* SmlAssemblerReserveStatusFunction) (void *userdata, unsigned int cmdRef, unsigned int msgRef, unsigned int cmdID, SmlError **error); typedef SmlBool (* SmlAssemblerStatusMissingFunction) (void *userdata); typedef SmlBool (* SmlAssemblerStartCommandFunction) (void *userdata, unsigned int parentID, SmlCommand *cmd, SmlError **error); typedef SmlBool (* SmlAssemblerEndCommandFunction) (void *userdata, unsigned int parentID, SmlError **error); typedef SmlBool (* SmlAssemblerRemCommandFunction) (void *userdata, unsigned int parentID, SmlError **error); typedef SmlBool (* SmlAssemblerHeaderFunction) (void *userdata, SmlSession *session, SmlError **error); typedef unsigned int (* SmlAssemblerCheckFunction) (void *userdata, SmlBool headeronly, SmlError **error); typedef SmlBool (* SmlAssemblerNextCmdRefFunction) (void *userdata, unsigned int *cmdRef, unsigned int *msgRef); typedef void (* SmlAssemblerRestoreCommandsFunction) (void *userdata); typedef struct SmlAssemblerFunctions { SmlAssemblerFreeFunction free; SmlAssemblerStartFunction start; SmlAssemblerEndFunction end; SmlAssemblerRunFunction run; SmlAssemblerFlushFunction flush; SmlAssemblerStatusFunction add_status; SmlAssemblerRemStatusFunction rem_status; SmlAssemblerReserveStatusFunction reserve_status; SmlAssemblerStatusMissingFunction missing_status; SmlAssemblerStartCommandFunction start_cmd; SmlAssemblerEndCommandFunction end_cmd; SmlAssemblerRemCommandFunction rem_cmd; SmlAssemblerHeaderFunction add_header; SmlAssemblerCheckFunction check_size; SmlAssemblerNextCmdRefFunction next_cmdref; SmlAssemblerRestoreCommandsFunction restore_cmds; } SmlAssemblerFunctions; typedef enum { SML_ASSEMBLER_RESULT_ERROR = 0, SML_ASSEMBLER_RESULT_OK = 1, SML_ASSEMBLER_RESULT_MISMATCH =2 } SmlAssemblerResult; SmlParser *smlParserNew(SmlMimeType type, unsigned int limit, SmlError **error); void smlParserFree(SmlParser *parser); SmlBool smlParserStart(SmlParser *parser, const char *data, unsigned int size, SmlError **error); SmlBool smlParserGetHeader(SmlParser *parser, SmlHeader **header, SmlCred **cred, SmlError **error); SmlParserResult smlParserGetCommand(SmlParser *parser, SmlCommand **cmd, SmlError **error); SmlBool smlParserGetStatus(SmlParser *parser, SmlStatus **status, SmlError **error); SmlBool smlParserEnd(SmlParser *parser, SmlBool *final, SmlBool *end, SmlError **error); SmlAssembler *smlAssemblerNew(SmlMimeType type, unsigned int limit, SmlError **error); void smlAssemblerFree(SmlAssembler *assm); SmlBool smlAssemblerStart(SmlAssembler *assm, SmlSession *session, SmlError **error); unsigned int smlAssemblerFlush(SmlAssembler *assm); void smlAssemblerRestoreCommands(SmlAssembler *assm); SmlBool smlAssemblerRun(SmlAssembler *assm, char **data, unsigned int *size, SmlBool *end, SmlBool final, SmlError **error); SmlAssemblerResult smlAssemblerAddStatus(SmlAssembler *assm, SmlStatus *status, SmlError **error); SmlAssemblerResult smlAssemblerAddStatusFull(SmlAssembler *assm, SmlStatus *status, SmlBool force, SmlError **error); SmlAssemblerResult smlAssemblerReserveStatus(SmlAssembler *assm, unsigned int cmdRef, unsigned int msgRef, unsigned int cmdID, SmlError **error); SmlBool smlAssemblerAddHeader(SmlAssembler *assm, SmlSession *session, SmlError **error); SmlAssemblerResult smlAssemblerStartCommand(SmlAssembler *assm, SmlCommand *parent, SmlCommand *cmd, SmlError **error); SmlBool smlAssemblerEndCommand(SmlAssembler *assm, SmlCommand *parent, SmlError **error); unsigned int smlAssemblerCheckSize(SmlAssembler *assm, SmlBool headeronly, SmlError **error); void smlAssemblerSetOption(SmlAssembler *assm, const char *optionname, const char *value); const char *smlAssemblerGetOption(SmlAssembler *assm, const char *optionname); unsigned int smlAssemblerSetRemoteMaxMsgSize(SmlAssembler *assm, unsigned int limit); unsigned int smlAssemblerGetRemoteMaxMsgSize(SmlAssembler *assm); SmlBool smlAssemblerGetSpace(SmlAssembler *assm, int *space, SmlCommand *parent, SmlCommand *cmd, SmlError **error); unsigned int smlAssemblerGetRemoteMaxObjSize(SmlAssembler *assm); unsigned int smlAssemblerSetRemoteMaxObjSize(SmlAssembler *assm, unsigned int limit); SmlBool smlAssemblerIsEmpty(SmlAssembler *assm); SmlBool smlAssemblerIsStatusMissing(SmlAssembler *assm); SmlBool smlAssemblerGetNextCmdRef(SmlAssembler *assm, unsigned int *cmdRef, unsigned int *msgRef); /* expire date: 20090626 */ void smlAssemblerSetRequestedLimit(SmlAssembler *assm, unsigned int limit) LIBSYNCML_DEPRECATED; void smlAssemblerSetLimit(SmlAssembler *assm, unsigned int limit) LIBSYNCML_DEPRECATED; unsigned int smlAssemblerGetLimit(SmlAssembler *assm) LIBSYNCML_DEPRECATED; void smlAssemblerSetRequestedMaxObjSize(SmlAssembler *assm, int limit) LIBSYNCML_DEPRECATED; void smlAssemblerSetSendingMaxObjSize(SmlAssembler *assm, int limit) LIBSYNCML_DEPRECATED; int smlAssemblerGetSendingMaxObjSize(SmlAssembler *assm) LIBSYNCML_DEPRECATED; int smlAssemblerGetRequestedMaxObjSize(SmlAssembler *assm) LIBSYNCML_DEPRECATED; /* If you want to parse OMA DS 1.2 SANs then the manager is required. */ void smlParserSetManager(SmlParser *parser, SmlManager *manager); #endif //_SML_PARSE_H_ libsyncml-0.5.4/libsyncml/sml_queue_internals.h100644 1750 1750 5370 11211710410 21651 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2005 Armin Bauer * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ /** * @defgroup SmlQueuePrivate SyncML Queue Internals * @ingroup PrivateLowLevelAPI * @brief The private part * */ /*@{*/ #ifndef _SML_QUEUE_INTERNALS_H_ #define _SML_QUEUE_INTERNALS_H_ typedef void (*SmlQueueHandler)(void *message, void *userdata); /*! @brief Represents a Queue which can be used to receive messages */ typedef struct SmlQueue { /** The items of the queue **/ GList *head; GList *tail; GList *prio; /** The message handler for this queue **/ SmlQueueHandler handler; /** The user_data associated with this queue **/ void *userdata; /** The source associated with this queue */ GSource *source; /** The context in which this queue is dispatched */ GMainContext *context; GSourceFuncs *functions; GMutex *mutex; } SmlQueue; SmlQueue *smlQueueNew(SmlError **error); void smlQueueFree(SmlQueue *queue); void smlQueueFlush(SmlQueue *queue); void smlQueueSetHandler(SmlQueue *queue, SmlQueueHandler handler, void *userdata); void smlQueueSend(SmlQueue *queue, void *data); void smlQueueAttach(SmlQueue *queue, GMainContext *context); void smlQueueDetach(SmlQueue *queue); void smlQueueDispatch(SmlQueue *queue); void *smlQueueTryPop(SmlQueue *queue); SmlBool smlQueueCheck(SmlQueue *queue); void smlQueuePushHead(SmlQueue *queue, void *data); SmlBool smlQueueIsAttached(SmlQueue *queue); void smlQueueLock(SmlQueue *queue); void smlQueueUnlock(SmlQueue *queue); void *smlQueuePeek(SmlQueue *queue); GList *smlQueuePeekNext(SmlQueue *queue, GList *prev); void *smlQueueTryPopPrio(SmlQueue *queue); void smlQueuePushHeadPrio(SmlQueue *queue, void *data); void smlQueueSendPrio(SmlQueue *queue, void *data); SmlBool smlQueueCheckPrio(SmlQueue *queue); void smlQueueDispatchPrio(SmlQueue *queue); void *smlQueuePeekPrio(SmlQueue *queue); void smlQueuePrint(SmlQueue *queue); unsigned int smlQueueLength(SmlQueue *queue); unsigned int smlQueueLengthPrio(SmlQueue *queue); #endif //_SML_QUEUE_INTERNALS_H_ /*@}*/ libsyncml-0.5.4/libsyncml/transports/obex_client_vendor_internals.h100644 1750 1750 2051 11211710410 25732 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2008 Michael Bell * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #ifndef _OBEX_CLIENT_SAMSUNG_INTERNALS_H_ #define _OBEX_CLIENT_SAMSUNG_INTERNALS_H_ SmlBool smlTransportObexVendorSamsungInit(SmlTransportObexClientEnv *env); #endif //_OBEX_CLIENT_SAMSUNG_INTERNALS_H_ libsyncml-0.5.4/libsyncml/transports/obex_client_samsung.c100644 1750 1750 10765 11211710410 24061 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2008 Michael Bell * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include #include #include #include #include "obex_client_internals.h" SmlBool smlTransportObexVendorSamsungInit(SmlTransportObexClientEnv *env) { smlTrace(TRACE_EXIT, "%s(%p, %s)", __func__, VA_STRING(env->model)); /* Samsung uses several different ways of implementing SyncML. * Actually this is only one dialect. * If you need more then add model based detection via env->model. */ /* Notice - the information here are taken from * * www.traud.de/gsm/samsung.htm * * Many thanks for this nice work goes to Alexander Traud. */ if ( // PC Sync 2 !g_strcasecmp("SGH-Z500", env->model) || !g_strcasecmp("SGH-ZM60", env->model) || // PC Studio 3 !g_strcasecmp("SGH-D347", env->model) || !g_strcasecmp("SGH-D357", env->model) || !g_strcasecmp("SGH-D520", env->model) || !g_strcasecmp("SGH-D830", env->model) || !g_strcasecmp("SGH-D840", env->model) || !g_strcasecmp("SGH-E770", env->model) || !g_strcasecmp("SGH-E860", env->model) || !g_strcasecmp("SGH-E900", env->model) || !g_strcasecmp("SGH-F480", env->model) || !g_strcasecmp("SGH-S500i", env->model) || !g_strcasecmp("SGH-T609", env->model) || !g_strcasecmp("SGH-X800", env->model) || !g_strcasecmp("SGH-X810", env->model) || !g_strcasecmp("SGH-X820", env->model) || !g_strcasecmp("SGH-Z150", env->model) || !g_strcasecmp("SGH-Z310", env->model) || !g_strcasecmp("SGH-Z320i", env->model) || !g_strcasecmp("SGH-Z400", env->model) || !g_strcasecmp("SGH-Z510", env->model) || !g_strcasecmp("SGH-Z540", env->model) || !g_strcasecmp("SGH-Z560", env->model) || !g_strcasecmp("SGH-ZV30", env->model) ) { smlTrace(TRACE_INTERNAL, "%s: WebSync WiDESYNC III (Gumi, Suwon 3G)", __func__); smlTrace(TRACE_INTERNAL, "%s: %i datastores" , __func__, g_list_length(env->datastores)); /* Example: AT+SyncML=4061062063064 * 1. byte: number of datastores * 2.+3. byte: 200+number => 206 == TWO-WAY-SYNC-BY-SERVER * 4. byte: database * 1 contacts/addressbook * 2 events/calendar * 3 notes/memos * 4 todos/tasks * repeat with 2.+3. */ env->at_command = g_strdup_printf("AT+SyncML=%i", g_list_length(env->datastores)); unsigned int i; for(i = 0; i < g_list_length(env->datastores); i++) { char *tmp = g_strjoin("", env->at_command, "06", NULL); SmlTransportObexDatastoreType *type; type = g_list_nth_data(env->datastores, i); switch(*type) { case SML_TRANSPORT_OBEX_DATASTORE_CONTACT: env->at_command = g_strjoin ("", tmp, "1", NULL); break; case SML_TRANSPORT_OBEX_DATASTORE_EVENT: env->at_command = g_strjoin ("", tmp, "2", NULL); break; case SML_TRANSPORT_OBEX_DATASTORE_NOTE: env->at_command = g_strjoin ("", tmp, "3", NULL); break; case SML_TRANSPORT_OBEX_DATASTORE_TODO: env->at_command = g_strjoin ("", tmp, "4", NULL); break; default: smlSafeCFree(&tmp); g_warning("Unkown datastore type %d for Samsung mobiles.", *type); return FALSE; } smlSafeCFree(&tmp); } } else { g_warning("Unknown Samsung mobile device %s - using default AT command.", env->model); return TRUE; } /* add the CR */ char *tmp = g_strjoin("", env->at_command, "\r", NULL); smlSafeCFree(&(env->at_command)); env->at_command = tmp; tmp = NULL; smlTrace(TRACE_EXIT, "%s - %s", __func__, VA_STRING(env->at_command)); return TRUE; } libsyncml-0.5.4/libsyncml/transports/http_client.c100644 1750 1750 41506 11211710410 22343 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2005 Armin Bauer * Copyright (C) 2007-2009 Michael Bell * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include #include #include #include #include "http_client_internals.h" static void smlTransportHttpClientSend(void *userdata, void *link, SmlTransportData *data, SmlError *error); static void smlTransportHttpClientDisconnect(void *data, void *linkdata); static SmlBool smlTransportHttpClientFinalize(void *data, SmlError **error); #ifdef HAVE_LIBSOUP22 #define soup_message_headers_get soup_message_get_header #define soup_message_headers_append soup_message_add_header #endif #ifdef HAVE_LIBSOUP22 static void smlTransportHttpClientCallback(SoupMessage *msg, gpointer userdata) { smlTrace(TRACE_ENTRY, "%s(%p, %p)", __func__, msg, userdata); #else static void smlTransportHttpClientCallback(SoupSession *session, SoupMessage *msg, gpointer userdata) { /* session is only traced to avoid warnings from gcc profiling */ smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, session, msg, userdata); #endif SmlTransportHttpClientEnv *env = userdata; SmlError *error = NULL; /* handle potential session shutdown */ if (env->connectDone && msg->status_code == SOUP_STATUS_CANCELLED) { /* FIXME: This is clearly a disconnect. * FIXME: You must check if a disconnect is ongoing. */ smlTrace(TRACE_EXIT, "%s - ignoring due to shutdown", __func__); return; } /* handle a fresh connection */ if (!env->connectDone) { /* This is the first answer or any other event which is * detected after the first message was sent. * We have to check and signal if the connection is ok or not. */ if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) { smlErrorSet(&error, SML_ERROR_GENERIC, "Connection failed (%d) - %s", msg->status_code, msg->reason_phrase); goto error; } else { /* If a transport has no public connect function * then the connect event is sent by the * transport layer itself. */ smlTrace(TRACE_INTERNAL, "%s: Connect done", __func__); if (!env->tsp->connected) { /* If a user of the library know that connect * is not available then this is tolerated. */ smlTransportReceiveEvent( env->tsp, NULL, SML_TRANSPORT_EVENT_CONNECT_DONE, NULL, NULL); } } env->connectDone = TRUE; } smlTrace(TRACE_INTERNAL, "%s: Result: %d %s", __func__, msg->status_code, msg->reason_phrase); /* start http handling with some checks */ /* check the library status for errors */ if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) { smlErrorSet(&error, SML_ERROR_GENERIC, "Call not successfull: %d %s", msg->status_code, msg->reason_phrase); goto error; } /* check the header of the received message */ const char *header = soup_message_headers_get(msg->response_headers, "Content-Type"); smlTrace(TRACE_INTERNAL, "%s: content type ::= %s", __func__, header); SmlMimeType mimetype = SML_MIMETYPE_UNKNOWN; if (header && !g_strncasecmp(header, SML_ELEMENT_XML, strlen(SML_ELEMENT_XML))) mimetype = SML_MIMETYPE_XML; else if(header && !g_strncasecmp(header, SML_ELEMENT_WBXML, strlen(SML_ELEMENT_WBXML))) mimetype = SML_MIMETYPE_WBXML; else if(header && !g_strncasecmp(header, SML_ELEMENT_SAN, strlen(SML_ELEMENT_SAN))) mimetype = SML_MIMETYPE_SAN; else if (header) { smlErrorSet(&error, SML_ERROR_GENERIC, "Unknown mimetype"); goto error; } else { smlErrorSet(&error, SML_ERROR_GENERIC, "Faulty mimetype"); goto error; } /* prepare the received message */ char *data; gsize length; #ifdef HAVE_LIBSOUP22 length = msg->response.length; #else length = msg->response_body->length; #endif smlTrace(TRACE_INTERNAL, "%s: The message length is %i.", __func__, length); /* We need one byte more than the response length * because the data can be a native XML message. * If the data is a native XML message then it is * sometimes directly used as string. * * The string is automatically NULL terminated * because smlTryMalloc0 fills the new memory with NULLs. */ data = smlTryMalloc0(length + 1, &error); if (!data) goto error; #ifdef HAVE_LIBSOUP22 memcpy(data, msg->response.body, length); #else memcpy(data, msg->response_body->data, length); #endif SmlTransportData *tspdata = smlTransportDataNew(data, length, mimetype, TRUE, &error); data = NULL; if (!tspdata) goto error_free_data; /* signal the received message */ smlTransportReceiveEvent(env->tsp, NULL, SML_TRANSPORT_EVENT_DATA, tspdata, NULL); /* cleanup */ smlTransportDataDeref(tspdata); smlTrace(TRACE_EXIT, "%s", __func__); return; error_free_data: smlSafeCFree(&data); error: smlTransportReceiveEvent(env->tsp, NULL, SML_TRANSPORT_EVENT_ERROR, NULL, error); smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(&error)); smlErrorDeref(&error); } /* This is the authentication callback for libsoup. * If a SyncML server uses HTTP then the specification allows * standard HTTP authentication. This callback provides the * http library with the user and passphrase for the SyncML * account. Usually this is not required because the most * SyncML server manage the authentication via SyncHdr. */ #ifdef HAVE_LIBSOUP22 static void _authenticate (SoupSession *session, SoupMessage *msg, const char *auth_type, const char *auth_realm, char **username, char **password, gpointer data) { SmlTransportHttpClientEnv *env = data; smlTrace(TRACE_INTERNAL, "%s: authentication via auth_type %s", __func__, VA_STRING(auth_type)); *username = g_strdup(env->username); *password = g_strdup(env->password); } #else static void _authenticate (SoupSession *session, SoupMessage *msg, SoupAuth *auth, gboolean retrying, gpointer data) { smlTrace(TRACE_INTERNAL, "%s(%p, %p, %p, %d, %p)", __func__, session, msg, auth, retrying, data); SmlTransportHttpClientEnv *env = data; smlTrace(TRACE_INTERNAL, "%s: authentication via auth_type %s", __func__, VA_STRING(soup_auth_get_scheme_name(auth))); if (!retrying) soup_auth_authenticate(auth, env->username, env->password); } #endif static SmlBool smlTransportHttpClientSetConfigOption( SmlTransport *tsp, const char *name, const char *value, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %s, %s, %p)", __func__, tsp, VA_STRING(name), VA_STRING(value), error); CHECK_ERROR_REF smlAssert(tsp); smlAssert(tsp->transport_data); SmlTransportHttpClientEnv *env = tsp->transport_data; if (!strcmp(name, SML_TRANSPORT_CONFIG_URL)) { if (env->url) smlSafeCFree(&(env->url)); if (env->uri) soup_uri_free(env->uri); env->url = g_strdup(value); env->uri = soup_uri_new(env->url); if (env->uri == NULL) { smlErrorSet(error, SML_ERROR_INTERNAL_MISCONFIGURATION, "The configured url %s is wrong.", env->url); smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(error)); return FALSE; } smlTrace(TRACE_INTERNAL, "%s: URL %s detected", __func__, VA_STRING(env->url)); } else if (!strcmp(name, SML_TRANSPORT_CONFIG_PROXY)) { env->proxy = g_strdup(value); smlTrace(TRACE_INTERNAL, "%s: PROXY %s detected", __func__, VA_STRING(env->proxy)); } else if (!strcmp(name, SML_TRANSPORT_CONFIG_USERNAME)) { env->username = g_strdup(value); smlTrace(TRACE_INTERNAL, "%s: USERNAME %s detected", __func__, VA_STRING(env->username)); } else if (!strcmp(name, SML_TRANSPORT_CONFIG_PASSWORD)) { env->password = g_strdup(value); smlTrace(TRACE_INTERNAL, "%s: PASSWORD ******* detected", __func__); } else if (!strcmp(name, SML_TRANSPORT_CONFIG_SSL_CA_FILE)) { env->cafile = g_strdup(value); smlTrace(TRACE_INTERNAL, "%s: SSL_CA_FILE %s detected", __func__, VA_STRING(env->cafile)); } else { smlErrorSet(error, SML_ERROR_INTERNAL_MISCONFIGURATION, "Unknown parameter %s found.", name); smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(error)); return FALSE; } smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; } /* WARNING: Do not register this function as connect function. * This is only an internal connect function. */ static void smlTransportHttpClientConnect(void *data) { smlTrace(TRACE_ENTRY, "%s(%p)", __func__, data); smlAssert(data); SmlTransportHttpClientEnv *env = data; SmlError *error = NULL; if (!env->tsp->context) { smlErrorSet(&error, SML_ERROR_INTERNAL_MISCONFIGURATION, "HTTP client runs only in asynchronous mode. So the context must be set."); goto error; } env->connectDone = FALSE; env->disconnectDone = FALSE; if (env->proxy != NULL && strlen(env->proxy) > 0) { if (env->cafile != NULL && strlen(env->cafile)) { #ifdef HAVE_LIBSOUP22_SOLARIS env->session = soup_session_sync_new_with_options( #else env->session = soup_session_async_new_with_options( SOUP_SESSION_ASYNC_CONTEXT, env->tsp->context, #endif SOUP_SESSION_PROXY_URI, env->proxy, SOUP_SESSION_SSL_CA_FILE, env->cafile, NULL); /* FIXME: libsoup does not support CRLs * FIXME: CRL support is required for minimum security. * FIXME: http://bugzilla.gnome.org/show_bug.cgi?id=547881 */ } else { #ifdef HAVE_LIBSOUP22_SOLARIS env->session = soup_session_sync_new_with_options( #else env->session = soup_session_async_new_with_options( SOUP_SESSION_ASYNC_CONTEXT, env->tsp->context, #endif SOUP_SESSION_PROXY_URI, env->proxy, NULL); } } else { if (env->cafile != NULL && strlen(env->cafile)) { #ifdef HAVE_LIBSOUP22_SOLARIS env->session = soup_session_sync_new_with_options( #else env->session = soup_session_async_new_with_options( SOUP_SESSION_ASYNC_CONTEXT, env->tsp->context, #endif SOUP_SESSION_SSL_CA_FILE, env->cafile, NULL); } else { #ifdef HAVE_LIBSOUP22_SOLARIS env->session = soup_session_sync_new(); #else env->session = soup_session_async_new_with_options( SOUP_SESSION_ASYNC_CONTEXT, env->tsp->context, NULL); #endif } } if (!env->session) { smlErrorSet(&error, SML_ERROR_GENERIC, "Unable to create new session"); goto error; } /* add credentials to the environment and * enable authentication callback for http authentication */ if (env->username || env->password) { g_signal_connect (env->session, "authenticate", G_CALLBACK (_authenticate), env); } else { env->username = NULL; env->password = NULL; } smlTrace(TRACE_EXIT, "%s: %p", __func__, env); return; error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(&error)); smlTransportReceiveEvent(env->tsp, NULL, SML_TRANSPORT_EVENT_ERROR, NULL, error); } static SmlBool smlTransportHttpClientSetResponseURI( SmlTransport *tsp, const char *uri, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %s, %p)", __func__, tsp, VA_STRING(uri), error); CHECK_ERROR_REF smlAssert(tsp); smlAssert(tsp->transport_data); SmlTransportHttpClientEnv *env = tsp->transport_data; smlAssert(uri); if (env->url) smlSafeCFree(&(env->url)); if (env->uri) soup_uri_free(env->uri); env->url = g_strdup(uri); env->uri = soup_uri_new(env->url); if (env->uri == NULL) { smlErrorSet(error, SML_ERROR_INTERNAL_MISCONFIGURATION, "The specified url \"%s\" is wrong.", env->url); smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(error)); return FALSE; } smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; } static SmlBool smlTransportHttpClientCleanupSession( gpointer data, SmlError **error) { smlTrace(TRACE_ENTRY, "%s", __func__); CHECK_ERROR_REF smlAssert(data); SoupSession *session = data; soup_session_abort(session); g_object_unref(session); smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; } static SmlBool smlTransportHttpClientFinalize(void *data, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p)", __func__, data, error); CHECK_ERROR_REF smlAssert(data); SmlTransportHttpClientEnv *env = data; smlAssert(env->tsp); if (env->session) { if (!smlThreadCallFunction(env->tsp->thread, smlTransportHttpClientCleanupSession, env->session, error)) goto error; env->session = NULL; } if (env->uri) soup_uri_free(env->uri); if (env->url) smlSafeCFree(&(env->url)); if (env->proxy) smlSafeCFree(&(env->proxy)); smlSafeFree((gpointer *)&env); smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error: smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(error)); return FALSE; } static void smlTransportHttpClientSend(void *userdata, void *link_, SmlTransportData *data, SmlError *error) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p, %p)", __func__, userdata, link_, data, error); smlAssert(error || data); smlAssert(userdata); SmlTransportHttpClientEnv *env = userdata; smlAssert(env); smlAssert(env->uri); if (error) goto error; if (!env->connectDone) smlTransportHttpClientConnect(userdata); SoupMessage *msg = soup_message_new_from_uri(SOUP_METHOD_POST, env->uri); if (!msg) { smlErrorSet(&error, SML_ERROR_GENERIC, "unknown libsoup error during message_new"); goto error; } const char *content_type; switch (data->type) { case SML_MIMETYPE_XML: content_type = SML_ELEMENT_XML; break; case SML_MIMETYPE_WBXML: content_type = SML_ELEMENT_WBXML; break; case SML_MIMETYPE_SAN: content_type = SML_ELEMENT_SAN; break; default: smlErrorSet(&error, SML_ERROR_GENERIC, "Unknown Mimetype %d", data->type); goto error_free_message; } soup_message_headers_append(msg->request_headers, "Accept", content_type); soup_message_set_request (msg, content_type, #ifdef HAVE_LIBSOUP22 SOUP_BUFFER_SYSTEM_OWNED, #else SOUP_MEMORY_TAKE, #endif g_memdup(data->data, data->size), data->size); #ifdef HAVE_LIBSOUP22 smlTrace(TRACE_INTERNAL, "%s: data length: %i", __func__, msg->request.length); #else smlTrace(TRACE_INTERNAL, "%s: data length: %i", __func__, msg->request_body->length); #endif #ifdef HAVE_LIBSOUP22_SOLARIS soup_session_send_message(env->session, msg); smlTrace(TRACE_INTERNAL, "%s: sent message and starting callback", __func__); smlTransportHttpClientCallback(msg, userdata); g_object_unref(msg); /* synchronous mode !!! */ #else soup_session_queue_message(env->session, msg, smlTransportHttpClientCallback, userdata); #endif smlTrace(TRACE_EXIT, "%s", __func__); return; error_free_message: g_object_unref(msg); error: smlTransportReceiveEvent(env->tsp, NULL, SML_TRANSPORT_EVENT_ERROR, NULL, error); smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(&error)); smlErrorDeref(&error); } static void smlTransportHttpClientDisconnect(void *data, void *linkdata) { smlTrace(TRACE_ENTRY, "%s(%p, %p)", __func__, data, linkdata); smlAssert(data); SmlTransportHttpClientEnv *env = data; smlAssert(env); smlAssert(env->tsp); if (!env->connectDone && !env->session) { /* The client is not connected. */ env->disconnectDone = TRUE; smlTransportReceiveEvent(env->tsp, NULL, SML_TRANSPORT_EVENT_DISCONNECT_DONE, NULL, NULL); smlTrace(TRACE_EXIT, "%s - ignoring because never connected", __func__); return; } smlAssert(env->session); /* The only reason to implement a disconnect function is the fact * that some servers need a TCP/IP disconnect to cleanly finish * a SyncML session. * * Otherwise we are locked into an endless loop of Slow-Syncs. */ soup_session_abort(env->session); g_object_unref(env->session); env->session = NULL; /* Make a new disconnect object */ env->disconnectDone = FALSE; smlTransportReceiveEvent(env->tsp, NULL, SML_TRANSPORT_EVENT_DISCONNECT_DONE, NULL, NULL); smlTrace(TRACE_EXIT, "%s", __func__); } SmlBool smlTransportHttpClientNew(SmlTransport *tsp, SmlError **error) { CHECK_ERROR_REF smlAssert(tsp); #ifdef HAVE_LIBSOUP22_SOLARIS smlTrace(TRACE_INTERNAL, "%s: Enabled libsoup 2.2 Solaris workarounds", __func__); #endif tsp->functions.set_config_option = smlTransportHttpClientSetConfigOption; tsp->functions.set_response_uri = smlTransportHttpClientSetResponseURI; tsp->functions.disconnect = smlTransportHttpClientDisconnect; tsp->functions.finalize = smlTransportHttpClientFinalize; tsp->functions.send = smlTransportHttpClientSend; SmlTransportHttpClientEnv *env = smlTryMalloc0(sizeof(SmlTransportHttpClientEnv), error); if (!env) return FALSE; tsp->transport_data = env; env->tsp = tsp; return TRUE; } libsyncml-0.5.4/libsyncml/transports/obex.c100644 1750 1750 2474 11211710410 20744 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2008 Michael Bell * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include "obex_internals.h" #include /* The error code should be returned and errno is set. */ /* I want to define this as macro but I failed until now. */ int GET_OBEX_RESULT(int result) { /* no error */ if (result >= 0) return result; /* real error code is set in result */ if (result < -1) { errno = - result; return result; } /* result is -1 */ /* errno is set */ if (errno) return - errno; /* errno is not set */ errno = 1; return -1; } libsyncml-0.5.4/libsyncml/transports/obex_internals.h100644 1750 1750 2112 11211710410 23015 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2008 Michael Bell * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #ifndef _OBEX_INTERNALS_H_ #define _OBEX_INTERNALS_H_ /* The error code should be returned and errno is set. */ /* I want to define this as macro but I failed until now. */ int GET_OBEX_RESULT(int result); #endif //_OBEX_INTERNALS_H_ libsyncml-0.5.4/libsyncml/transports/http_server_internals.h100644 1750 1750 3355 11211710410 24437 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2005 Armin Bauer * Copyright (C) 2008 Michael Bell * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #ifndef _HTTP_SERVER_INTERNALS_H_ #define _HTTP_SERVER_INTERNALS_H_ #include #include #ifdef HAVE_LIBSOUP22 #include #else #include #endif typedef struct SmlTransportHttpServerEnv { #ifdef HAVE_LIBSOUP22 SoupUri *uri; #else SoupURI *uri; #endif SoupServer *server; SmlTransport *tsp; uint16_t port; char *url; char *ssl_cert; char *ssl_key; /* session protection via ResponseURI */ GHashTable *sessionToUri; GHashTable *uriToLink; } SmlTransportHttpServerEnv; typedef struct SmlLinkHttpServerEnv { SoupMessage *msg; SmlTransportHttpServerEnv *env; SmlSession *session; char *url; SmlLink *link; } SmlLinkHttpServerEnv; SmlBool smlTransportHttpServerNew(SmlTransport *tsp, SmlError **error); #endif //_HTTP_SERVER_INTERNALS_H_ libsyncml-0.5.4/libsyncml/transports/http_server.c100644 1750 1750 63477 11211710410 22406 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2005 Armin Bauer * Copyright (C) 2007-2009 Michael Bell * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include #include #include #include #include #include "http_server_internals.h" #ifdef HAVE_LIBSOUP22 static void smlTransportHttpServerCallback( SoupServerContext *context, SoupMessage *msg, gpointer data) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, context, msg, data); SmlMimeType mimetype = SML_MIMETYPE_UNKNOWN; smlAssert(data); SmlTransportHttpServerEnv *env = data; SmlLinkHttpServerEnv *linkenv = NULL; SmlLink *link_ = NULL; SmlError *error = NULL; char *path = soup_uri_to_string (soup_message_get_uri(msg), TRUE); smlTrace(TRACE_INTERNAL, "%s: %s %s HTTP/1.%d", __func__, VA_STRING(msg->method), VA_STRING(path), soup_message_get_http_version(msg)); if (g_strcasecmp(path, env->url)) { /* check that this is a registered session */ smlSafeCFree(&path); path = soup_uri_to_string (soup_message_get_uri(msg), FALSE); link_ = g_hash_table_lookup(env->uriToLink, path); if (!link_) { /* The URL was changed and there is no * key/value pair for this URL available. * * SECURITY: This is a potential attack. * FALSE POSITIVE: Session with a timeout. */ smlErrorSet(&error, SML_ERROR_INTERNAL_FILE_NOT_FOUND, "Not Found (%s).", path); soup_message_set_status(msg, SOUP_STATUS_NOT_FOUND); smlSafeCFree(&path); goto error; } smlLinkRef(link_); } smlSafeCFree(&path); if (soup_message_get_http_version(msg) != 1) { smlErrorSet(&error, SML_ERROR_NOT_IMPLEMENTED, "Wrong http version"); soup_message_set_status(msg, SOUP_STATUS_NOT_IMPLEMENTED); goto error; } if (soup_method_get_id(msg->method) != SOUP_METHOD_ID_POST) { smlErrorSet(&error, SML_ERROR_NOT_IMPLEMENTED, "Wrong method"); soup_message_set_status(msg, SOUP_STATUS_NOT_IMPLEMENTED); goto error; } const char *header = soup_message_get_header(msg->request_headers, "Content-Type"); if (header && !g_strncasecmp(header, SML_ELEMENT_XML, strlen(SML_ELEMENT_XML))) mimetype = SML_MIMETYPE_XML; else if(header && !g_strncasecmp(header, SML_ELEMENT_WBXML, strlen(SML_ELEMENT_WBXML))) mimetype = SML_MIMETYPE_WBXML; else if(header && !g_strncasecmp(header, SML_ELEMENT_SAN, strlen(SML_ELEMENT_SAN))) mimetype = SML_MIMETYPE_SAN; else if (header) { smlErrorSet(&error, SML_ERROR_GENERIC, "Unknown mimetype"); soup_message_set_status (msg, SOUP_STATUS_BAD_REQUEST); goto error; } else { smlErrorSet(&error, SML_ERROR_GENERIC, "Faulty mimetype"); soup_message_set_status (msg, SOUP_STATUS_BAD_REQUEST); goto error; } /* prepare link and linkenv */ if (!link_) { /* This is a potentially new session. * It is not possible to check this here. * smlTransportGetResponseURI must be used * to verify this. */ linkenv = smlTryMalloc0(sizeof(SmlLinkHttpServerEnv), &error); if (!linkenv) goto error; linkenv->env = env; link_ = smlLinkNew(env->tsp, linkenv, &error); if (!link_) goto error; linkenv->msg = msg; /* the link must be cached for disconnect signaling */ linkenv->link = link_; smlLinkRef(linkenv->link); /* We think positive here and signal connect. * the link is now complete, so send the connect event */ smlTransportReceiveEvent(env->tsp, link_, SML_TRANSPORT_EVENT_CONNECT_DONE, NULL, NULL); } else { linkenv = link_->link_data; if (linkenv->msg) smlTrace(TRACE_INTERNAL, "%s: WARNING: ResponseURI should not be in use - test mode.", __func__); linkenv->msg = msg; } smlTrace(TRACE_INTERNAL, "%s: The message length is %i.", __func__, msg->request.length); /* We need one byte more than the request length * because the data can be a native XML message. * If the data is a native XML message then it is * sometimes directly used as string. * * The string is automatically NULL terminated * because smlTryMalloc0 fills the new memory with NULLs. */ char *body = smlTryMalloc0(msg->request.length + 1, &error); if (!body) goto error; memcpy(body, msg->request.body, msg->request.length); SmlTransportData *tspdata = smlTransportDataNew(body, msg->request.length, mimetype, TRUE, &error); body = NULL; if (!tspdata) goto error_unref_msg; smlTransportReceiveEvent(env->tsp, link_, SML_TRANSPORT_EVENT_DATA, tspdata, NULL); smlLinkDeref(link_); smlTransportDataDeref(tspdata); soup_message_io_pause(msg); smlTrace(TRACE_EXIT, "%s", __func__); return; error_unref_msg: link_->link_data = NULL; smlLinkDeref(link_); linkenv->msg = NULL; smlSafeFree((gpointer *) &linkenv); error: soup_server_message_set_encoding (SOUP_SERVER_MESSAGE (msg), SOUP_TRANSFER_CONTENT_LENGTH); soup_message_io_unpause(msg); smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(&error)); smlErrorDeref(&error); } #else /* !HAVE_LIBSOUP22 == libsoup 2.4 */ static void smlTransportHttpServerCallback( SoupServer *server, SoupMessage *msg, const char *path, GHashTable *query, SoupClientContext *client, gpointer data) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %s, %p, %p, %p)", __func__, server, msg, VA_STRING(path), query, client, data); SmlMimeType mimetype = SML_MIMETYPE_UNKNOWN; smlAssert(data); SmlTransportHttpServerEnv *env = data; SmlLinkHttpServerEnv *linkenv = NULL; SmlLink *link_ = NULL; SmlError *error = NULL; smlTrace(TRACE_INTERNAL, "%s: %s %s HTTP/1.%d", __func__, VA_STRING(msg->method), VA_STRING(path), soup_message_get_http_version(msg)); if (msg->method != SOUP_METHOD_POST) { smlErrorSet(&error, SML_ERROR_NOT_IMPLEMENTED, "Wrong method"); soup_message_set_status(msg, SOUP_STATUS_NOT_IMPLEMENTED); goto error; } if (g_strcasecmp(path, env->url)) { /* check that this is a registered session */ char *fullpath = soup_uri_to_string (soup_message_get_uri(msg), FALSE); link_ = g_hash_table_lookup(env->uriToLink, fullpath); if (!link_) { /* The URL was changed and there is no * key/value pair for this URL available. * * SECURITY: This is a potential attack. * FALSE POSITIVE: Session with a timeout. */ smlErrorSet(&error, SML_ERROR_INTERNAL_FILE_NOT_FOUND, "Not Found (%s).", fullpath); soup_message_set_status(msg, SOUP_STATUS_NOT_FOUND); smlSafeCFree(&fullpath); goto error; } smlLinkRef(link_); smlSafeCFree(&fullpath); } const char *header = soup_message_headers_get(msg->request_headers, "Content-Type"); if (header && !g_strncasecmp(header, SML_ELEMENT_XML, strlen(SML_ELEMENT_XML))) mimetype = SML_MIMETYPE_XML; else if(header && !g_strncasecmp(header, SML_ELEMENT_WBXML, strlen(SML_ELEMENT_WBXML))) mimetype = SML_MIMETYPE_WBXML; else if(header && !g_strncasecmp(header, SML_ELEMENT_SAN, strlen(SML_ELEMENT_SAN))) mimetype = SML_MIMETYPE_SAN; else if (header) { smlErrorSet(&error, SML_ERROR_GENERIC, "Unknown mimetype"); soup_message_set_status (msg, SOUP_STATUS_BAD_REQUEST); goto error; } else { smlErrorSet(&error, SML_ERROR_GENERIC, "Faulty mimetype"); soup_message_set_status (msg, SOUP_STATUS_BAD_REQUEST); goto error; } /* prepare link and linkenv */ if (!link_) { /* This is a potentially new session. * It is not possible to check this here. * smlTransportGetResponseURI must be used * to verify this. */ linkenv = smlTryMalloc0(sizeof(SmlLinkHttpServerEnv), &error); if (!linkenv) goto error; linkenv->env = env; link_ = smlLinkNew(env->tsp, linkenv, &error); if (!link_) goto error; linkenv->msg = msg; /* the link must be cached for disconnect signaling */ linkenv->link = link_; smlLinkRef(linkenv->link); /* We think positive here and signal connect. * the link is now complete, so send the connect event */ smlTransportReceiveEvent(env->tsp, link_, SML_TRANSPORT_EVENT_CONNECT_DONE, NULL, NULL); } else { linkenv = link_->link_data; if (linkenv->msg) smlTrace(TRACE_INTERNAL, "%s: WARNING: ResponseURI should not be in use - test mode.", __func__); linkenv->msg = msg; } if (msg->request_body) { smlTrace(TRACE_INTERNAL, "%s: The message length is %i.", __func__, msg->request_body->length); } else { smlTrace(TRACE_INTERNAL, "%s: The message has no request body.", __func__); } /* We need one byte more than the request length * because the data can be a native XML message. * If the data is a native XML message then it is * sometimes directly used as string. * * The string is automatically NULL terminated * because smlTryMalloc0 fills the new memory with NULLs. */ char *body = smlTryMalloc0(msg->request_body->length + 1, &error); if (!body) goto error; memcpy(body, msg->request_body->data, msg->request_body->length); SmlTransportData *tspdata = smlTransportDataNew(body, msg->request_body->length, mimetype, TRUE, &error); body = NULL; if (!tspdata) goto error_unref_msg; smlTransportReceiveEvent(env->tsp, link_, SML_TRANSPORT_EVENT_DATA, tspdata, NULL); smlLinkDeref(link_); /* If we activate this function call then we get segfaults */ /* smlLinkDeref(link_); */ smlTransportDataDeref(tspdata); soup_server_pause_message(server, msg); smlTrace(TRACE_EXIT, "%s", __func__); return; error_unref_msg: smlLinkDeref(link_); error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(&error)); smlErrorDeref(&error); } #endif /* HAVE_LIBSOUP22 */ static SmlBool smlTransportHttpServerSetConfigOption( SmlTransport *tsp, const char *name, const char *value, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %s, %s, %p)", __func__, tsp, VA_STRING(name), VA_STRING(value), error); CHECK_ERROR_REF smlAssert(tsp); smlAssert(tsp->transport_data); SmlTransportHttpServerEnv *env = tsp->transport_data; if (!strcmp(name, SML_TRANSPORT_CONFIG_PORT)) { env->port = atoi(value); if (!(env->port > 0 && env->port < 65535)) { smlErrorSet(error, SML_ERROR_INTERNAL_MISCONFIGURATION, "specified port was wrong"); smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(error)); return FALSE; } smlTrace(TRACE_INTERNAL, "%s: Port %i detected", __func__, env->port); } else if (!strcmp(name, SML_TRANSPORT_CONFIG_URL)) { env->url = g_strdup(value); smlTrace(TRACE_INTERNAL, "%s: URL %s detected", __func__, VA_STRING(env->url)); } else if (!strcmp(name, SML_TRANSPORT_CONFIG_SSL_KEY)) { env->ssl_key = g_strdup(value); smlTrace(TRACE_INTERNAL, "%s: SSL key %s detected", __func__, VA_STRING(env->ssl_key)); } else if (!strcmp(name, SML_TRANSPORT_CONFIG_SSL_SERVER_CERT)) { env->ssl_cert = g_strdup(value); smlTrace(TRACE_INTERNAL, "%s: SSL server certificate %s detected", __func__, VA_STRING(env->ssl_cert)); } else { smlErrorSet(error, SML_ERROR_INTERNAL_MISCONFIGURATION, "Unknown parameter %s found.", name); smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(error)); return FALSE; } smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; } static SmlBool smlTransportHttpServerInit(SmlTransport *tsp, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p)", __func__, tsp, error); CHECK_ERROR_REF smlAssert(tsp); smlAssert(tsp->context); smlAssert(tsp->transport_data); SmlTransportHttpServerEnv *env = tsp->transport_data; if (!env->port) { smlErrorSet(error, SML_ERROR_INTERNAL_MISCONFIGURATION, "The HTTP server needs a port where it has to run."); goto error_free_env; } if (!env->url) { /* configure a default location */ env->url = g_strdup("/"); } smlTrace(TRACE_INTERNAL, "%s: config: port %i, url %s", __func__, env->port, VA_STRING(env->url)); smlTrace(TRACE_INTERNAL, "%s: http server uses context %p.", __func__, tsp->context); if(!env->ssl_key || !env->ssl_cert) { env->server = soup_server_new( SOUP_SERVER_ASYNC_CONTEXT, tsp->context, SOUP_SERVER_PORT, env->port, NULL); } else { env->server = soup_server_new( SOUP_SERVER_ASYNC_CONTEXT, tsp->context, SOUP_SERVER_PORT, env->port, SOUP_SERVER_SSL_CERT_FILE, env->ssl_cert, SOUP_SERVER_SSL_KEY_FILE, env->ssl_key, NULL); } if (!env->server) { smlErrorSet(error, SML_ERROR_INTERNAL_MISCONFIGURATION, "Unable to spawn server"); goto error_free_env; } #ifdef HAVE_LIBSOUP22 soup_server_add_handler(env->server, NULL, NULL, smlTransportHttpServerCallback, NULL, env); #else soup_server_add_handler(env->server, NULL, smlTransportHttpServerCallback, env, NULL); #endif soup_server_run_async(env->server); smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error_free_env: if (env->url) smlSafeCFree(&(env->url)); smlSafeFree((gpointer *)&env); // error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return FALSE; } static void smlTransportHttpServerDisconnect(void *data, void *linkdata) { smlTrace(TRACE_ENTRY, "%s(%p, %p)", __func__, data, linkdata); smlAssert(linkdata); SmlTransportHttpServerEnv *env = data; SmlLinkHttpServerEnv *linkenv = linkdata; /* remove session from sessionToUri */ smlTrace(TRACE_INTERNAL, "%s: remove link from session/uri cache", __func__); if (linkenv->session) { char *uri = g_hash_table_lookup(linkenv->env->sessionToUri, linkenv->session); g_hash_table_remove(linkenv->env->sessionToUri, linkenv->session); if (uri) smlSafeCFree(&uri); /* This is not a bug. We added two references to session * because the session is used in two locations. */ smlSessionUnref(linkenv->session); smlSessionUnref(linkenv->session); linkenv->session = NULL; } /* remove link from uriToLink */ SmlLink *link_ = NULL; smlTrace(TRACE_INTERNAL, "%s: remove link from uri/link cache", __func__); if (linkenv->url) { link_ = g_hash_table_lookup(linkenv->env->uriToLink, linkenv->url); g_hash_table_remove(linkenv->env->uriToLink, linkenv->url); smlLinkDeref(link_); smlSafeCFree(&(linkenv->url)); } /* save link for disconnect event */ link_ = linkenv->link; /* signal disconnect to socket and potential client */ if (linkenv->msg) { smlTrace(TRACE_INTERNAL, "%s: close open message/connection", __func__); soup_message_set_status (linkenv->msg, SOUP_STATUS_SERVICE_UNAVAILABLE); #ifdef HAVE_LIBSOUP22 //soup_server_message_set_encoding ( // SOUP_SERVER_MESSAGE (linkenv->msg), // SOUP_TRANSFER_CONTENT_LENGTH); soup_message_io_unpause(linkenv->msg); #else soup_server_unpause_message(linkenv->env->server, linkenv->msg); #endif linkenv->msg = NULL; } /* cleanup */ smlTrace(TRACE_INTERNAL, "%s: free memory", __func__); linkenv->env = NULL; link_->link_data = NULL; smlSafeFree((gpointer *)&linkenv); smlTrace(TRACE_INTERNAL, "%s: signal and unref link", __func__); smlTransportReceiveEvent(env->tsp, link_, SML_TRANSPORT_EVENT_DISCONNECT_DONE, NULL, NULL); smlLinkDeref(link_); smlTrace(TRACE_EXIT, "%s", __func__); } static void smlTransportHttpServerFreeResponseURI(gpointer key) { smlTrace(TRACE_ENTRY, "%s(%p)", __func__, key); smlSafeCFree((char **)&key); smlTrace(TRACE_EXIT, "%s", __func__); } static gboolean smlTransportHttpServerFreeUriToLink( gpointer key, gpointer value, gpointer user_data) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, key, value, user_data); // SmlTransportHttpServerEnv *env = user_data; char *uri = key; SmlLink *link_ = value; smlLinkDeref(link_); smlSafeCFree(&uri); smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; } static gboolean smlTransportHttpServerFreeSessionToUri( gpointer key, gpointer value, gpointer user_data) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, key, value, user_data); // SmlTransportHttpServerEnv *env = user_data; SmlSession *session = key; char *uri = value; smlSafeCFree(&uri); smlSessionUnref(session); smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; } static SmlBool smlTransportHttpServerCleanupSocket( gpointer data, SmlError **error) { smlTrace(TRACE_ENTRY, "%s", __func__); CHECK_ERROR_REF smlAssert(data); SoupServer *server = data; soup_server_quit(server); g_object_unref(server); smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; } static SmlBool smlTransportHttpServerFinalize(void *data, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p)", __func__, data, error); CHECK_ERROR_REF smlAssert(data); SmlTransportHttpServerEnv *env = data; smlAssert(env->tsp); if (env->server) { /* If there was no server init * then there is no server. * (e.g. failure after smlTransportHttpServerNew) */ if (!smlThreadCallFunction( env->tsp->thread, smlTransportHttpServerCleanupSocket, env->server, error)) goto error; env->server = NULL; } if (env->url) smlSafeCFree(&(env->url)); guint count = 0; guint removed = 0; /* cleanup hash table uriToLink */ count = g_hash_table_size(env->uriToLink); removed = g_hash_table_foreach_steal( env->uriToLink, smlTransportHttpServerFreeUriToLink, env); if (count != removed) { smlErrorSet(error, SML_ERROR_GENERIC, "The glib function g_hash_table_foreach_steal could " \ "not remove all key/value pairs from uriToLink (%u of %u).", removed, count); goto error; } else { g_hash_table_unref(env->uriToLink); env->uriToLink = NULL; } /* cleanup hash table sessionToUri */ count = g_hash_table_size(env->sessionToUri); removed = g_hash_table_foreach_steal( env->sessionToUri, smlTransportHttpServerFreeSessionToUri, env); if (count != removed) { smlErrorSet(error, SML_ERROR_GENERIC, "The glib function g_hash_table_foreach_steal could not " \ "remove all key/value pairs from sessionToUri. (%u of %u)", removed, count); goto error; } else { g_hash_table_unref(env->sessionToUri); env->sessionToUri = NULL; } smlSafeFree((gpointer *)&env); smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error: smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(error)); return FALSE; } static void smlTransportHttpServerSend(void *userdata, void *linkdata, SmlTransportData *data, SmlError *error) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p, %p)", __func__, userdata, linkdata, data, error); // smlAssert(userdata); smlAssert(linkdata); smlAssert(error || data); // SmlTransportHttpServerEnv *env = userdata; SmlLinkHttpServerEnv *linkenv = linkdata; smlAssert(linkenv->msg); SoupMessage *msg = linkenv->msg; linkenv->msg = NULL; if (error) goto error_free_message; soup_message_set_status (msg, SOUP_STATUS_OK); #ifdef HAVE_LIBSOUP22 soup_server_message_set_encoding (SOUP_SERVER_MESSAGE(msg), SOUP_TRANSFER_CONTENT_LENGTH); #endif const char *content_type; switch (data->type) { case SML_MIMETYPE_XML: content_type = SML_ELEMENT_XML; break; case SML_MIMETYPE_WBXML: content_type = SML_ELEMENT_WBXML; break; case SML_MIMETYPE_SAN: content_type = SML_ELEMENT_SAN; break; default: smlErrorSet(&error, SML_ERROR_GENERIC, "Unknown Mimetype"); goto error_free_message; } #ifdef HAVE_LIBSOUP22 // duplicate the data because sometimes data is freed to early char *soupcopy = (char *) smlTryMalloc0(data->size, &error); if (error) goto error_free_message; memcpy(soupcopy, data->data, data->size); soup_message_set_response (msg, content_type, SOUP_BUFFER_SYSTEM_OWNED, soupcopy, data->size); soup_message_io_unpause(msg); #else soup_message_set_response(msg, content_type, SOUP_MEMORY_COPY, data->data, data->size); soup_server_unpause_message(linkenv->env->server, msg); #endif smlTrace(TRACE_EXIT, "%s", __func__); return; error_free_message: if (smlErrorGetClass(&error) <= SML_ERRORCLASS_RETRY) soup_message_set_status_full(msg, SOUP_STATUS_BAD_REQUEST, smlErrorPrint(&error)); else soup_message_set_status_full(msg, SOUP_STATUS_INTERNAL_SERVER_ERROR, smlErrorPrint(&error)); #ifdef HAVE_LIBSOUP22 soup_server_message_set_encoding (SOUP_SERVER_MESSAGE (msg), SOUP_TRANSFER_CONTENT_LENGTH); soup_message_io_unpause(msg); #else soup_server_unpause_message(linkenv->env->server, msg); #endif smlErrorDeref(&error); smlTrace(TRACE_EXIT, "%s: Sent Error", __func__); return; } char * smlTransportHttpServerGetResponseURI(SmlLink *link_, SmlSession *session, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, link_, session, error); /* Do not change the assertion to simple return FALSE stuff * because to many developers incl. me ignore returned FALSE * if it is only configuration. */ CHECK_ERROR_REF smlAssert(link_); smlAssert(session); smlAssert(link_->link_data); SmlLinkHttpServerEnv *linkenv = link_->link_data; smlAssert(linkenv->env); SmlTransportHttpServerEnv *env = linkenv->env; char *responseURI = NULL; smlTrace(TRACE_INTERNAL, "%s: params checked", __func__); /* SECURITY NOTE * This is the function were we have to create and validate * the used URLs. If you are not sure about what you are doing * then do not touch the code and contact the developers. */ /* check the session */ if (!g_hash_table_lookup(env->sessionToUri, session)) { /* This is a potentially new session. * The URL must be the original URL. */ smlTrace(TRACE_INTERNAL, "%s: new session detected", __func__); char *soupURI = soup_uri_to_string (soup_message_get_uri(linkenv->msg), TRUE); if (strcmp(env->url, soupURI)) { /* SECURITY: This can be an attack. */ smlErrorSet(error, SML_ERROR_RETRY_LATER, "A new session with a configured HTTP session was detected."); smlSafeCFree(&soupURI); goto error; } smlSafeCFree(&soupURI); /* create new random response ID * * glib only supports 32 bit random numbers. * Therefore 4 random numbers are created * and a fixed length is used. * * Do not send the response ID as HTTP GET parameter * because this can cause conflicts * because SyncML requires HTTP POST and * libsoup 2.4 filters such parameters * from the path in the callback interface. */ soupURI = soup_uri_to_string (soup_message_get_uri(linkenv->msg), FALSE), responseURI = g_strdup_printf("%s0X%08X%08X%08X%08X", soupURI, g_random_int (), g_random_int (), g_random_int (), g_random_int ()); smlSafeCFree(&soupURI); /* map URI to link */ if (g_hash_table_lookup(env->uriToLink, responseURI)) { /* SECURITY: This can be an insecure random number generator. */ smlErrorSet(error, SML_ERROR_RETRY_LATER, "A fresh random session ID is already in use."); goto error; } smlLinkRef(link_); g_hash_table_insert(env->uriToLink, g_strdup(responseURI), link_); smlTrace(TRACE_INTERNAL, "%s: ResponseURI is %s.", __func__, VA_STRING(responseURI)); /* map session to URI */ g_hash_table_insert(env->sessionToUri, session, g_strdup(responseURI)); smlSessionRef(session); /* cache session and URI in linkenv - necessary for cleanup */ linkenv->session = session; smlSessionRef(session); linkenv->url = g_strdup(responseURI); } else { /* The session already exists. * The referenced URL must be checked against the cached URL. * The used URL must be checked against the cached URL too. */ smlTrace(TRACE_INTERNAL, "%s: cached session detected", __func__); char *soupURI = soup_uri_to_string (soup_message_get_uri(linkenv->msg), FALSE); const char *sessionURI = g_hash_table_lookup(env->sessionToUri, session); if (strcmp(soupURI, sessionURI)) { /* SECURITY: This is a potential attack. */ smlErrorSet(error, SML_ERROR_RETRY_LATER, "Another session (%s) re-used an already existing HTTP session (%s).", soupURI, sessionURI); smlSafeCFree(&soupURI); goto error; } SmlLink *cachedLink = g_hash_table_lookup(env->uriToLink, soupURI); if (!cachedLink) { /* SECURITY: This is an internal bug. */ smlErrorSet(error, SML_ERROR_GENERIC, "Cannot find link for used URL."); smlSafeCFree(&soupURI); goto error; } if (cachedLink != link_) { /* SECURITY: This is an internal bug. */ smlErrorSet(error, SML_ERROR_GENERIC, "The link objects mismatch."); smlSafeCFree(&soupURI); goto error; } if (strcmp(linkenv->url, soupURI)) { /* SECURITY: This can be an attack. */ smlErrorSet(error, SML_ERROR_GENERIC, "The URL of the link object is wrong."); smlSafeCFree(&soupURI); goto error; } responseURI = soupURI; } smlTrace(TRACE_EXIT, "%s - %s", __func__, VA_STRING(responseURI)); return responseURI; error: smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(error)); return NULL; } SmlBool smlTransportHttpServerNew(SmlTransport *tsp, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p)", __func__, tsp, error); CHECK_ERROR_REF smlAssert(tsp); tsp->functions.set_config_option = smlTransportHttpServerSetConfigOption; tsp->functions.initialize = smlTransportHttpServerInit; tsp->functions.finalize = smlTransportHttpServerFinalize; tsp->functions.send = smlTransportHttpServerSend; tsp->functions.get_response_uri = smlTransportHttpServerGetResponseURI; tsp->functions.disconnect = smlTransportHttpServerDisconnect; SmlTransportHttpServerEnv *env = smlTryMalloc0(sizeof(SmlTransportHttpServerEnv), error); if (!env) return FALSE; tsp->transport_data = env; env->tsp = tsp; env->sessionToUri = g_hash_table_new(g_direct_hash, g_direct_equal); env->uriToLink = g_hash_table_new_full(g_str_hash, g_str_equal, smlTransportHttpServerFreeResponseURI, NULL); smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; } libsyncml-0.5.4/libsyncml/transports/obex_client_internals.h100644 1750 1750 4074 11211710410 24364 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2005 Armin Bauer * Copyright (C) 2008 Michael Bell * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #ifndef _OBEX_CLIENT_INTERNALS_H_ #define _OBEX_CLIENT_INTERNALS_H_ #include "obex_bluetooth.h" #include #ifndef WIN32 #include #include #endif #define STREAM_CHUNK 4096 typedef enum { SML_OBEX_VENDOR_UNKNOWN = 0, SML_OBEX_VENDOR_SAMSUNG = 1, } SmlTransportObexVendorType; typedef enum { SML_TRANSPORT_OBEX_DATASTORE_UNKNOWN = 0, SML_TRANSPORT_OBEX_DATASTORE_CONTACT = 1, SML_TRANSPORT_OBEX_DATASTORE_EVENT = 2, SML_TRANSPORT_OBEX_DATASTORE_NOTE = 3, SML_TRANSPORT_OBEX_DATASTORE_TODO = 4, } SmlTransportObexDatastoreType; typedef struct SmlTransportObexClientEnv { SmlTransportConnectionType type; SmlTransport *tsp; obex_t *obexhandle; uint32_t connection_id; char *path; unsigned int port; char *irda_service; char *at_command; char *manufacturer; char *model; GList *datastores; int fd; int state; char *databuf; int *databuflen; int connected; #ifndef WIN32 struct termios oldtio; #endif SmlBool busy; SmlBool error; SmlMimeType mimetype; SmlBool isDisconnected; } SmlTransportObexClientEnv; SmlBool smlTransportObexClientNew(SmlTransport *tsp, SmlError **error); #endif //_OBEX_CLIENT_INTERNALS_H_ libsyncml-0.5.4/libsyncml/transports/obex_server_internals.h100644 1750 1750 3354 11211710410 24414 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2005 Armin Bauer * Copyright (C) 2008 Michael Bell * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #ifndef _OBEX_SERVER_INTERNALS_H_ #define _OBEX_SERVER_INTERNALS_H_ #include "obex_bluetooth.h" #include #define STREAM_CHUNK 4096 typedef struct SmlTransportObexServerEnv { SmlTransportConnectionType type; SmlTransport *tsp; char *path; uint16_t port; #ifdef ENABLE_BLUETOOTH bdaddr_t *bdaddr; #endif char *irda_service; obex_t *handle; GSource *source; GSourceFuncs *functions; uint32_t lastConId; } SmlTransportObexServerEnv; typedef struct SmlLinkObexServerEnv { SmlLink *link; SmlTransportObexServerEnv *env; uint32_t conid; obex_t *handle; uint8_t *stream_chunk; SmlBool destroy; SmlBool disconnect; GSource *source; SmlError *error; SmlTransportData *send_data; } SmlLinkObexServerEnv; SmlBool smlTransportObexServerNew(SmlTransport *tsp, SmlError **error); #endif //_OBEX_SERVER_INTERNALS_H_ libsyncml-0.5.4/libsyncml/transports/http_client_internals.h100644 1750 1750 3150 11211710410 24400 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2005 Armin Bauer * Copyright (C) 2007-2008 Michael Bell * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #ifndef _HTTP_CLIENT_INTERNALS_H_ #define _HTTP_CLIENT_INTERNALS_H_ #ifdef HAVE_LIBSOUP22_SOLARIS #include #else #include #endif #include #ifndef HAVE_LIBSOUP22 #include #endif typedef struct SmlTransportHttpClientEnv { #ifdef HAVE_LIBSOUP22 SoupUri *uri; #else SoupURI *uri; #endif SoupSession *session; SmlTransport *tsp; uint16_t port; char *url; char *proxy; char *username; char *password; char *cafile; SmlBool connectDone; SmlBool disconnectDone; } SmlTransportHttpClientEnv; SmlBool smlTransportHttpClientNew(SmlTransport *tsp, SmlError **error); #endif //_HTTP_CLIENT_INTERNALS_H_ libsyncml-0.5.4/libsyncml/transports/obex_bluetooth.h100644 1750 1750 2271 11211710410 23031 0ustar00bellmichbellmich/* * Copyright (C) 2008 Michael Bell * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #ifndef _OBEX_BLUETOOTH_H_ #define _OBEX_BLUETOOTH_H_ /* TODO: Avoid direct libbluetooth depency. This is only required for str2ba() */ #if defined(ENABLE_BLUETOOTH) && !defined(__FreeBSD__) #include #elif defined(ENABLE_BLUETOOTH) && defined(__FreeBSD__) #include #define BDADDR_ANY NG_HCI_BDADDR_ANY #endif #endif //_OBEX_BLUETOOTH_H_ libsyncml-0.5.4/libsyncml/transports/obex_client.c100644 1750 1750 126331 11211710410 22341 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2005 Armin Bauer * Copyright (C) 2007-2009 Michael Bell * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include #include #include #include #include "obex_internals.h" #include "obex_client_internals.h" #include "obex_client_vendor_internals.h" #ifdef ENABLE_BLUETOOTH_SDPLIB #include #include #endif #include #ifndef WIN32 #include #include #include #include #include #include #include #include #include #endif #include #include #include #include #include #include #ifndef WIN32 static SmlBool obex_cable_at( SmlTransportObexClientEnv *userdata, const char *cmd, char *rspbuf, int rspbuflen, int timeout, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %s, %p, %i, %i, %p)", __func__, userdata, VA_STRING(cmd), rspbuf, rspbuflen, timeout, error); CHECK_ERROR_REF fd_set ttyset; struct timeval tv; gint fd; SmlBool statusOnly = FALSE; char *answer = NULL; char *answer_end = NULL; int answer_size; char tmpbuf[100] = {0,}; int actual; int total = 0; int done = 0; if (!strncasecmp("ATZ", cmd, 3)) { smlTrace(TRACE_INTERNAL, "%s: detected standard ATZ command", __func__); statusOnly = TRUE; } if (!strncasecmp("AT+CPROT=0", cmd, 10)) { smlTrace(TRACE_INTERNAL, "%s: detected standard AT+CPROT=0 command", __func__); statusOnly = TRUE; } /* send AT command */ fd = userdata->fd; rspbuf[0] = 0; if(fd < 0) { smlErrorSet(error, SML_ERROR_GENERIC, "The file descriptor for the cable AT command is not legal (%d).", fd); goto error; } if(cmd != NULL) { // Write command gint cmdlen; cmdlen = strlen(cmd); if(write(fd, cmd, cmdlen) < cmdlen) { smlErrorSet(error, SML_ERROR_GENERIC, "The command cannot be written (completely) to the file descriptor."); goto error; } } /* read the answer * the default answer for AT commands is: \nresult\n\nOK\n */ while(!done) { FD_ZERO(&ttyset); FD_SET(fd, &ttyset); tv.tv_sec = timeout; tv.tv_usec = 0; if(select(fd+1, &ttyset, NULL, NULL, &tv)) { actual = read(fd, &tmpbuf[total], sizeof(tmpbuf) - total); if(actual < 0) { smlErrorSet(error, SML_ERROR_GENERIC, "read failed with return code %i.", actual); goto error; } total += actual; /* Answer didn't come within the length of the buffer. Cancel! */ if(total == sizeof(tmpbuf)) { smlErrorSet(error, SML_ERROR_NOT_IMPLEMENTED, "The size of the answer to the AT command %s was too large for the internal buffer.", VA_STRING(cmd)); goto error; } if( (answer = index(tmpbuf, '\n')) && /* \n infront of response */ (answer_end = index(answer+1, '\n')) /* \n at end of repsonse */ ) { /* check for an error */ if (!strncasecmp("ERROR", answer+1, 5)) { smlErrorSet(error, SML_ERROR_GENERIC, "The AT command %s failed.", VA_STRING(cmd)); goto error; } /* read the trailing \nOK\n if necessary */ if (statusOnly) { /* Found end of answer */ done = 1; } else { char *ok = NULL; char *ok_end = NULL; if ( (ok = index(answer_end+1, '\n')) && /* \n infront of ok */ (ok_end = index(ok+1, '\n')) /* \n at end of ok */ ) { /* Found end of answer */ done = 1; } } } } else { /* Anser didn't come in time. Cancel */ smlErrorSet(error, SML_ERROR_INTERNAL_IO_ERROR, "The read operation for the answer of the AT command was timed out."); goto error; } } smlTrace(TRACE_INTERNAL, "%s: answer: %s", __func__, VA_STRING(answer)); // Remove heading and trailing \r if((*answer_end == '\r') || (*answer_end == '\n')) answer_end--; if((*answer_end == '\r') || (*answer_end == '\n')) answer_end--; if((*answer == '\r') || (*answer == '\n')) answer++; if((*answer == '\r') || (*answer == '\n')) answer++; answer_size = (answer_end) - answer +1; smlTrace(TRACE_INTERNAL, "%s: answer size=%d", __func__, answer_size); if( (answer_size) >= rspbuflen ) { smlErrorSet(error, SML_ERROR_NOT_IMPLEMENTED, "The size of the answer to the AT command %s was too large.", VA_STRING(cmd)); goto error; } strncpy(rspbuf, answer, answer_size); rspbuf[answer_size] = 0; smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error: smlTrace(TRACE_EXIT, "%s - %s", __func__, smlErrorPrint(error)); return FALSE; } static int smlTransportObexClientCableDisconnect(obex_t *handle, gpointer ud) { smlTrace(TRACE_INTERNAL, "%s(%p, %p)", __func__, handle, ud); SmlTransportObexClientEnv *userdata = (SmlTransportObexClientEnv *) ud; if (userdata->fd >= 0) { // Send a break to get out of OBEX-mode #ifdef TCSBRKP if(ioctl(userdata->fd, TCSBRKP, 0) < 0) { #elif defined(TCSBRK) if(ioctl(userdata->fd, TCSBRK, 0) < 0) { #else if(tcsendbreak(userdata->fd, 0) < 0) { #endif /* TCSBRKP */ smlTrace(TRACE_INTERNAL, "%s: Unable to send break!", __func__); } tcsetattr(userdata->fd, TCSANOW, &userdata->oldtio); close(userdata->fd); } return 0; } SmlTransportObexVendorType smlTransportObexClientGetVendor(const char *manufacturer) { smlTrace(TRACE_ENTRY, "%s(%s)", __func__, VA_STRING(manufacturer)); smlAssert(manufacturer); SmlTransportObexVendorType vendor = SML_OBEX_VENDOR_UNKNOWN; char *big = g_ascii_strup(manufacturer, -1); if (strstr(big, "SAMSUNG") != NULL) { smlTrace(TRACE_INTERNAL, "%s - Samsung found.", __func__); vendor = SML_OBEX_VENDOR_SAMSUNG; } smlSafeCFree(&big); smlTrace(TRACE_EXIT, "%s - %d", __func__, vendor); return vendor; } static int smlTransportObexClientCableConnect(obex_t *handle, gpointer ud) { smlTrace(TRACE_ENTRY, "%s", __func__); SmlError *error = NULL; SmlTransportObexClientEnv *userdata = (SmlTransportObexClientEnv *) ud; struct termios newtio; char rspbuf[201]; rspbuf[sizeof(rspbuf)-1] = 0; /* sanitize for %s in printf format */ userdata->fd = open(userdata->path, O_RDWR|O_NONBLOCK|O_NOCTTY); if (userdata->fd < 0) { smlErrorSet(&error, SML_ERROR_INTERNAL_IO_ERROR, "A valid file descriptor must be non-negative."); goto error; } tcgetattr(userdata->fd, &userdata->oldtio); bzero(&newtio, sizeof(struct termios)); newtio.c_cflag = B115200 | CLOCAL | CS8 | CREAD | CRTSCTS; newtio.c_cc[VMIN] = 1; newtio.c_cc[VTIME] = 0; newtio.c_iflag = IGNPAR; newtio.c_oflag = 0; tcflush(userdata->fd, TCIFLUSH); tcsetattr(userdata->fd, TCSANOW, &newtio); /* init the communication line */ if (!obex_cable_at(userdata, "ATZ\r", rspbuf, sizeof(rspbuf) - 1, 1, &error)) goto error; if (strcasecmp("OK", rspbuf)) { smlErrorSet(&error, SML_ERROR_GENERIC, "The ATZ command was answered with %s.", rspbuf); goto error; } if (!userdata->at_command && !userdata->manufacturer) { /* get the manufacturer */ if (!obex_cable_at(userdata, "AT+CGMI\r", rspbuf, sizeof(rspbuf), 1, &error)) { smlTrace(TRACE_ERROR, "%s: Comm-error sending AT+CGMI\\r", __func__); goto error; } userdata->manufacturer = g_strdup(rspbuf); smlTrace(TRACE_ERROR, "%s: manufacturer %s", __func__, VA_STRING(userdata->manufacturer)); } if (!userdata->at_command && !userdata->model) { /* get the model */ if (!obex_cable_at(userdata, "AT+CGMM\r", rspbuf, sizeof(rspbuf), 1, &error)) { smlTrace(TRACE_ERROR, "%s: Comm-error sending AT+CGMM\\r", __func__); goto error; } userdata->model = g_strdup(rspbuf); smlTrace(TRACE_ERROR, "%s: model %s", __func__, VA_STRING(userdata->model)); } if (!userdata->at_command) { /* start vendor specific handling */ SmlTransportObexVendorType vendor = SML_OBEX_VENDOR_UNKNOWN; if (userdata->manufacturer) { smlTrace(TRACE_INTERNAL, "%s: Try to find an appropriate AT command", __func__); vendor = smlTransportObexClientGetVendor(userdata->manufacturer); } if (vendor) { switch(vendor) { case SML_OBEX_VENDOR_SAMSUNG: smlTrace(TRACE_INTERNAL, "%s: Samsung detected", __func__); if (!smlTransportObexVendorSamsungInit(userdata)) { smlErrorSet(&error, SML_ERROR_GENERIC, "The intialization for Samsung failed."); goto error; } break; default: smlTrace(TRACE_ERROR, "%s: Ups, vendor defined but not handled.", __func__); break; } } } if (!userdata->at_command) { /* setup default */ smlTrace(TRACE_INTERNAL, "%s: Setting up default AT command AT+CPROT=0\\r", __func__); userdata->at_command = g_strdup("AT+CPROT=0\r"); } /* start the synchronization */ if (!obex_cable_at(userdata, userdata->at_command, rspbuf, sizeof(rspbuf) - 1, 1, &error)) goto error; if (strcasecmp("CONNECT", rspbuf)) { smlErrorSet(&error, SML_ERROR_GENERIC, "The command AT+CPROT=0 failed with answer %s.", rspbuf); goto error; } // fcntl(userdata->fd, F_SETFL, O_NONBLOCK); return 0; error: perror(smlErrorPrint(&error)); smlTransportObexClientCableDisconnect(handle, userdata); smlTrace(TRACE_ERROR, "%s - %s", __func__, smlErrorPrint(&error)); smlErrorDeref(&error); return -1; } static int smlTransportObexClientCableWrite(obex_t *handle, gpointer ud, guint8 *buf, int buflen) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p, %i)", __func__, handle, ud, buf, buflen); SmlTransportObexClientEnv *userdata = (SmlTransportObexClientEnv *) ud; int written = 0; int ret = 0; while (ret >= 0 && written < buflen) { ret = write(userdata->fd, buf + written, buflen - written); if (ret >= 0) written += ret; } smlTrace(TRACE_EXIT, "%s: %i", __func__, written); return written; } gint obex_cable_handleinput(obex_t *handle, gpointer ud, gint timeout) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %i)", __func__, handle, ud, timeout); struct timeval to; fd_set readfds; char buf[512]; SmlTransportObexClientEnv *userdata; int ret = 0; int actual = 0; userdata = (SmlTransportObexClientEnv*) ud; FD_ZERO(&readfds); FD_SET(userdata->fd, &readfds); to.tv_sec = timeout; to.tv_usec = 0; smlTrace(TRACE_INTERNAL, "%s - %i", __func__, __LINE__); ret = select(userdata->fd + 1, &readfds, NULL, NULL, &to); if (ret < 1) goto error; smlTrace(TRACE_INTERNAL, "%s - %i", __func__, __LINE__); if ((actual = read(userdata->fd, buf, sizeof(buf))) <= 0) goto end; smlTrace(TRACE_INTERNAL, "%s - %i", __func__, __LINE__); OBEX_CustomDataFeed(handle, (unsigned char *) buf, actual); end: smlTrace(TRACE_EXIT, "%s(%p, %p, %i)", __func__, handle, ud, timeout); return actual; error: smlTrace(TRACE_EXIT_ERROR, "%s: %i", __func__, ret); return ret; } #endif static void smlTransportObexClientEvent(obex_t *handle, obex_object_t *object, int mode, int event, int obex_cmd, int obex_rsp) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %i, %i, %i, %i)", __func__, handle, object, mode, event, obex_cmd, obex_rsp); SmlTransportObexClientEnv *env = OBEX_GetUserData(handle); SmlError *error = NULL; switch (event) { case OBEX_EV_PROGRESS: smlTrace(TRACE_INTERNAL, "%s: Progress", __func__); break; case OBEX_EV_REQDONE: smlTrace(TRACE_INTERNAL, "%s: Request Done", __func__); env->busy = FALSE; if (obex_rsp != OBEX_RSP_SUCCESS) { switch(obex_cmd) { case OBEX_CMD_CONNECT: smlErrorSet(&error, SML_ERROR_INTERNAL_MISCONFIGURATION, "The OBEX client cannot connect to the configured device or resource (%s - 0x%x).", OBEX_ResponseToString(obex_rsp), obex_rsp); break; default: smlErrorSet(&error, SML_ERROR_INTERNAL_IO_ERROR, "%s (0x%x)", OBEX_ResponseToString(obex_rsp), obex_rsp); break; } goto error; } /* Get the connection id if we connected */ switch (obex_cmd) { case OBEX_CMD_CONNECT:; uint8_t headertype = 0; obex_headerdata_t header; uint32_t len; char *who = NULL; while (OBEX_ObjectGetNextHeader(env->obexhandle, object, &headertype, &header, &len)) { smlTrace(TRACE_INTERNAL, "%s: Next header %i, %d, %p", __func__, headertype, header.bq4, header.bs); switch (headertype) { case OBEX_HDR_CONNECTION: smlTrace(TRACE_INTERNAL, "%s: Found connection number: %d", __func__, header.bq4); env->connection_id = header.bq4; break; case OBEX_HDR_WHO: who = g_strndup((char *)header.bs, len); smlTrace(TRACE_INTERNAL, "%s: Found who: %s", __func__, VA_STRING(who)); break; default: smlTrace(TRACE_INTERNAL, "%s: Unknown header", __func__); } } if (!env->connection_id) { smlErrorSet(&error, SML_ERROR_GENERIC, "Missing connection id"); smlSafeCFree(&who); goto error; } smlTrace(TRACE_INTERNAL, "%s: Got who: %s", __func__, VA_STRING(who)); if (!who || strcmp(who, "SYNCML-SYNC")) { smlErrorSet(&error, SML_ERROR_GENERIC, "Missing or wrong who response"); smlSafeCFree(&who); goto error; } smlSafeCFree(&who); smlTransportReceiveEvent(env->tsp, NULL, SML_TRANSPORT_EVENT_CONNECT_DONE, NULL, NULL); break; case OBEX_CMD_DISCONNECT:; if (!env->isDisconnected) { env->busy = FALSE; env->isDisconnected = TRUE; OBEX_TransportDisconnect(env->obexhandle); smlTransportReceiveEvent(env->tsp, NULL, SML_TRANSPORT_EVENT_DISCONNECT_DONE, NULL, NULL); } break; case OBEX_CMD_GET:; smlTrace(TRACE_INTERNAL, "%s: Got GET command done", __func__); uint32_t length = 0; char *body = NULL; while (OBEX_ObjectGetNextHeader(handle, object, &headertype, &header, &len)) { smlTrace(TRACE_INTERNAL, "%s: Next header %i, %d, %p, len %i", __func__, headertype, header.bq4, header.bs, len); switch (headertype) { case OBEX_HDR_LENGTH: smlTrace(TRACE_INTERNAL, "%s: Found length: %d", __func__, header.bq4); length = header.bq4; break; case OBEX_HDR_BODY: if (!length) { smlTrace(TRACE_INTERNAL, "%s: Length not given. Calculating it to: %i", __func__, len); length = len; } if (!length) { smlErrorSet(&error, SML_ERROR_GENERIC, "Got zero length!"); goto error; } /* We need one byte more than the response length * because the data can be a native XML message. * If the data is a native XML message then it is * sometimes directly used as string. * * The string is automatically NULL terminated * because smlTryMalloc0 fills the new memory with NULLs. */ body = smlTryMalloc0(length + 1, &error); if (!body) goto error; memcpy(body, header.bs, length); break; default: smlTrace(TRACE_INTERNAL, "%s: Unknown header", __func__); } } if (!length) { smlErrorSet(&error, SML_ERROR_GENERIC, "Missing length"); goto error; } if (!body) { smlErrorSet(&error, SML_ERROR_GENERIC, "Missing body"); goto error; } SmlTransportData *tspdata = smlTransportDataNew(body, length, env->mimetype, TRUE, &error); if (!tspdata) goto error; smlTransportReceiveEvent(env->tsp, NULL, SML_TRANSPORT_EVENT_DATA, tspdata, NULL); smlTransportDataDeref(tspdata); break; } break; case OBEX_EV_LINKERR: if (obex_rsp == 0) { /* This is a disconnect. */ if (!env->isDisconnected) { env->busy = FALSE; env->isDisconnected = TRUE; OBEX_TransportDisconnect(env->obexhandle); smlTransportReceiveEvent(env->tsp, NULL, SML_TRANSPORT_EVENT_DISCONNECT_DONE, NULL, NULL); } } else { /* This is a normal error. */ smlErrorSet(&error, SML_ERROR_GENERIC, "Link Error: %s - 0x%x", OBEX_ResponseToString(obex_rsp), obex_rsp); smlTrace(TRACE_INTERNAL, "%s - %s", __func__, smlErrorPrint(&error)); goto error; } break; case OBEX_EV_STREAMEMPTY: smlTrace(TRACE_INTERNAL, "%s: Empty Stream", __func__); break; } smlTrace(TRACE_EXIT, "%s", __func__); return; error: smlTransportReceiveEvent(env->tsp, NULL, SML_TRANSPORT_EVENT_ERROR, NULL, error); smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(&error)); smlErrorDeref(&error); env->busy = FALSE; env->error = TRUE; return; } static SmlBool smlTransportObexClientSetConfigOption( SmlTransport *tsp, const char *name, const char *value, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %s, %s, %p)", __func__, tsp, VA_STRING(name), VA_STRING(value), error); CHECK_ERROR_REF smlAssert(tsp); smlAssert(tsp->transport_data); smlAssert(name); /* should be checked by smlTransportSetConfigOption */ SmlTransportObexClientEnv *env = tsp->transport_data; /* This transport does not accept NULL as value. */ if (!value) { smlErrorSet(error, SML_ERROR_INTERNAL_MISCONFIGURATION, "The configuration option %s requires a value.", name); goto error; } if (!strcmp(name, SML_TRANSPORT_CONFIG_BLUETOOTH_CHANNEL)) { env->port = atoi(value); smlTrace(TRACE_INTERNAL, "%s: Bluetooth channel %i detected", __func__, env->port); } else if (!strcmp(name, SML_TRANSPORT_CONFIG_BLUETOOTH_ADDRESS)) { /* This is the MAC of the remote device. */ env->path = g_strdup(value); smlTrace(TRACE_INTERNAL, "%s: Bluetooth MAC %s detected", __func__, VA_STRING(env->path)); } else if (!strcmp(name, SML_TRANSPORT_CONFIG_PORT)) { if (env->type == SML_TRANSPORT_CONNECTION_TYPE_BLUETOOTH) g_warning("Please use %s instead of %s.", SML_TRANSPORT_CONFIG_BLUETOOTH_CHANNEL, SML_TRANSPORT_CONFIG_PORT); env->port = atoi(value); smlTrace(TRACE_INTERNAL, "%s: Port or Bluetooth channel %i detected", __func__, env->port); } else if (!strcmp(name, SML_TRANSPORT_CONFIG_URL)) { if (env->type == SML_TRANSPORT_CONNECTION_TYPE_BLUETOOTH) g_warning("Please use %s instead of %s.", SML_TRANSPORT_CONFIG_BLUETOOTH_ADDRESS, SML_TRANSPORT_CONFIG_URL); env->path = g_strdup(value); smlTrace(TRACE_INTERNAL, "%s: URL or Bluetooth MAC %s detected", __func__, VA_STRING(env->path)); } else if (!strcmp(name, SML_TRANSPORT_CONFIG_IRDA_SERVICE)) { if (env->irda_service) smlSafeCFree(&(env->irda_service)); env->irda_service = g_strdup(value); smlTrace(TRACE_INTERNAL, "%s: IrDA service %s detected", __func__, VA_STRING(env->irda_service)); } else if (!strcmp(name, SML_TRANSPORT_CONFIG_AT_COMMAND)) { if (env->at_command) smlSafeCFree(&(env->at_command)); env->at_command = g_strdup(value); smlTrace(TRACE_INTERNAL, "%s: AT command %s detected", __func__, VA_STRING(env->at_command)); } else if (!strcmp(name, SML_TRANSPORT_CONFIG_AT_MANUFACTURER)) { if (env->manufacturer) smlSafeCFree(&(env->manufacturer)); env->manufacturer = g_strdup(value); smlTrace(TRACE_INTERNAL, "%s: AT manufacturer %s detected", __func__, VA_STRING(env->manufacturer)); } else if (!strcmp(name, SML_TRANSPORT_CONFIG_AT_MODEL)) { if (env->model) smlSafeCFree(&(env->model)); env->model = g_strdup(value); smlTrace(TRACE_INTERNAL, "%s: AT model %s detected", __func__, VA_STRING(env->model)); } else if (!strcmp(name, SML_TRANSPORT_CONFIG_DATASTORE)) { /* This is needed for vendors which signal the datastore with AT commands. */ SmlTransportObexDatastoreType datastore = SML_TRANSPORT_OBEX_DATASTORE_UNKNOWN; if (!strcasecmp(SML_TRANSPORT_CONFIG_DATASTORE_EVENT, value)) datastore = SML_TRANSPORT_OBEX_DATASTORE_EVENT; if (!strcasecmp(SML_TRANSPORT_CONFIG_DATASTORE_TODO, value)) datastore = SML_TRANSPORT_OBEX_DATASTORE_TODO; if (!strcasecmp(SML_TRANSPORT_CONFIG_DATASTORE_CONTACT, value)) datastore = SML_TRANSPORT_OBEX_DATASTORE_CONTACT; if (!strcasecmp(SML_TRANSPORT_CONFIG_DATASTORE_NOTE, value)) datastore = SML_TRANSPORT_OBEX_DATASTORE_NOTE; if (!datastore) { smlErrorSet(error, SML_ERROR_INTERNAL_MISCONFIGURATION, "Unknown datastore %s found.", value); goto error; } SmlTransportObexDatastoreType *type = smlTryMalloc0(sizeof(SmlTransportObexDatastoreType), error); if (!type) goto error; *type = datastore; env->datastores = g_list_append(env->datastores, type); smlTrace(TRACE_INTERNAL, "%s: Datastore %i detected", __func__, datastore); } else { smlErrorSet(error, SML_ERROR_INTERNAL_MISCONFIGURATION, "Unknown parameter %s found.", name); goto error; } smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error: smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(error)); return FALSE; } static SmlBool smlTransportObexClientSetConnectionType( SmlTransport *tsp, SmlTransportConnectionType type, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %i, %p)", __func__, tsp, type, error); CHECK_ERROR_REF smlAssert(tsp); smlAssert(tsp->transport_data); SmlTransportObexClientEnv *env = tsp->transport_data; env->type = type; switch (env->type) { case SML_TRANSPORT_CONNECTION_TYPE_NET: env->obexhandle = OBEX_Init(OBEX_TRANS_FD, smlTransportObexClientEvent, 0); break; case SML_TRANSPORT_CONNECTION_TYPE_IRDA: env->obexhandle = OBEX_Init(OBEX_TRANS_IRDA, smlTransportObexClientEvent, 0); break; case SML_TRANSPORT_CONNECTION_TYPE_BLUETOOTH: env->obexhandle = OBEX_Init(OBEX_TRANS_BLUETOOTH, smlTransportObexClientEvent, 0); break; case SML_TRANSPORT_CONNECTION_TYPE_SERIAL: env->obexhandle = OBEX_Init(OBEX_TRANS_CUST, smlTransportObexClientEvent, 0); break; case SML_TRANSPORT_CONNECTION_TYPE_USB: env->obexhandle = OBEX_Init(OBEX_TRANS_USB, smlTransportObexClientEvent, 0); break; default: smlErrorSet(error, SML_ERROR_GENERIC, "Unknown obex type"); smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(error)); return FALSE; } if (!env->obexhandle) { smlErrorSet(error, SML_ERROR_GENERIC, "Unable to open connection"); smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(error)); return FALSE; } #ifndef WIN32 if (env->type == SML_TRANSPORT_CONNECTION_TYPE_SERIAL) { obex_ctrans_t cabletrans = { smlTransportObexClientCableConnect, smlTransportObexClientCableDisconnect, NULL, smlTransportObexClientCableWrite, obex_cable_handleinput, env}; OBEX_RegisterCTransport(env->obexhandle, &cabletrans); } #endif smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; } static SmlBool smlTransportObexClientInit(SmlTransport *tsp, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p)", __func__, tsp, error); CHECK_ERROR_REF smlAssert(tsp); smlAssert(tsp->transport_data); SmlTransportObexClientEnv *env = tsp->transport_data; OBEX_SetUserData(env->obexhandle, env); switch (env->type) { case SML_TRANSPORT_CONNECTION_TYPE_NET: if (!env->path) { smlErrorSet(error, SML_ERROR_GENERIC, "The hostname or address is missing."); goto error; } break; case SML_TRANSPORT_CONNECTION_TYPE_BLUETOOTH: if (!env->path) { smlErrorSet(error, SML_ERROR_GENERIC, "The bluetooth address is missing."); goto error; } #ifndef ENABLE_BLUETOOTH_SDPLIB if (!env->port) { smlErrorSet(error, SML_ERROR_GENERIC, "The bluetooth channel is missing."); goto error; } #endif break; default: /* nothing to check here */ break; } smlTrace(TRACE_EXIT, "%s - TRUE", __func__); return TRUE; error: OBEX_Cleanup(env->obexhandle); if (env->path) smlSafeCFree(&(env->path)); if (env->at_command) smlSafeCFree(&(env->at_command)); if (env->manufacturer) smlSafeCFree(&(env->manufacturer)); if (env->model) smlSafeCFree(&(env->model)); smlSafeFree((gpointer *)&env); smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(error)); return FALSE; } static SmlBool smlTransportObexClientFinalize(void *data, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p)", __func__, data, error); CHECK_ERROR_REF smlAssert(data); SmlTransportObexClientEnv *env = data; smlAssert(env->tsp); if (env->path) smlSafeCFree(&(env->path)); OBEX_Cleanup(env->obexhandle); if (env->irda_service) smlSafeCFree(&(env->irda_service)); if (env->at_command) smlSafeCFree(&(env->at_command)); if (env->manufacturer) smlSafeCFree(&(env->manufacturer)); if (env->model) smlSafeCFree(&(env->model)); while (env->datastores) { SmlTransportObexDatastoreType *type = env->datastores->data; env->datastores = g_list_remove(env->datastores, type); smlSafeFree((gpointer *) &type); } smlSafeFree((gpointer *)&env); smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; } static void smlTransportObexClientConnect(void *data) { smlTrace(TRACE_ENTRY, "%s(%p)", __func__, data); smlAssert(data); SmlTransportObexClientEnv *env = data; int fd = 0; SmlError *error = NULL; unsigned int obex_intf_cnt; obex_interface_t *obex_intf; env->isDisconnected = FALSE; if (env->type == SML_TRANSPORT_CONNECTION_TYPE_NET) { smlTrace(TRACE_INTERNAL, "%s: connecting to inet address %s:%d", __func__, VA_STRING(env->path), env->port); struct sockaddr_in addr; memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_port = htons(env->port); struct hostent *hostinfo = gethostbyname (env->path); if (!hostinfo) { smlErrorSet(&error, SML_ERROR_GENERIC, "Unknown host %s", env->path); goto error; } addr.sin_addr = *(struct in_addr *) hostinfo->h_addr_list[0]; fd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); if (fd < 0) { smlErrorSet(&error, SML_ERROR_GENERIC, "Cannot create socket: %s", strerror(errno)); goto error; } smlTrace(TRACE_INTERNAL, "%s: socket %i", __func__, fd); char *addrstr = inet_ntoa(addr.sin_addr); smlTrace(TRACE_INTERNAL, "%s: peer addr = %d %s %i", __func__, hostinfo->h_addr_list[0], VA_STRING(addrstr), env->port); if (connect(fd, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)) < 0) { smlErrorSet(&error, SML_ERROR_GENERIC, "Cannot connect socket: %s", strerror(errno)); goto error_close; } smlTrace(TRACE_INTERNAL, "%s: connect done", __func__); } else if (env->type == SML_TRANSPORT_CONNECTION_TYPE_USB) { smlTrace(TRACE_INTERNAL, "%s: connecting to usb interface %i", __func__, env->port); obex_intf_cnt = OBEX_FindInterfaces(env->obexhandle, &obex_intf); smlTrace(TRACE_INTERNAL, "%s: found %i interfaces", __func__, obex_intf_cnt); if (obex_intf_cnt <= 0) { smlErrorSet(&error, SML_ERROR_GENERIC, "There are no valid USB interfaces."); goto error; } else if (env->port >= obex_intf_cnt) { smlErrorSet(&error, SML_ERROR_GENERIC, "Unable to find the USB interface number %i", env->port); goto error; } else { if (GET_OBEX_RESULT(OBEX_InterfaceConnect(env->obexhandle, &obex_intf[env->port])) < 0) { smlErrorSet(&error, SML_ERROR_GENERIC, "The interface cannot be connected. %s (%i).", strerror(errno), errno); goto error; } } smlTrace(TRACE_INTERNAL, "%s: usb connect done", __func__); } else if (env->type == SML_TRANSPORT_CONNECTION_TYPE_BLUETOOTH) { #ifdef ENABLE_BLUETOOTH smlTrace(TRACE_INTERNAL, "%s: connecting to bluetooth device %s channel %i", __func__, VA_STRING(env->path), env->port); uint8_t channel = env->port; bdaddr_t bdaddr; str2ba(env->path, &bdaddr); #ifdef ENABLE_BLUETOOTH_SDPLIB if (channel == 0) { /* FIXME: Is this code really memory leak free !? */ sdp_session_t *sdp_session = sdp_connect(BDADDR_ANY, &bdaddr, SDP_RETRY_IF_BUSY); if (!sdp_session) { smlErrorSet(&error, SML_ERROR_GENERIC, "The Bluetooth connect to search for the channel failed."); goto error; } unsigned char syncml_client_uuid[] = { 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x02, 0xEE, 0x00, 0x00, 0x02}; uuid_t uuid; uint32_t range = SDP_ATTR_PROTO_DESC_LIST; sdp_uuid128_create(&uuid, syncml_client_uuid); sdp_list_t *attribute = sdp_list_append(0, &range); sdp_list_t *class = sdp_list_append(0, &uuid); sdp_list_t *list; if (sdp_service_search_attr_req(sdp_session, class, SDP_ATTR_REQ_INDIVIDUAL, attribute, &list) < 0) { sdp_close(sdp_session); sdp_list_free(attribute, 0); sdp_list_free(class, 0); smlErrorSet( &error, SML_ERROR_GENERIC, "The service search on the Bluetooth device failed."); goto error; } sdp_list_free(attribute, 0); sdp_list_free(class, 0); sdp_list_t *iterator; for(iterator = list; iterator; iterator = iterator->next) { sdp_record_t *item = (sdp_record_t *) iterator->data; sdp_list_t *protos = NULL; sdp_get_access_protos(item, &protos); if(protos) { channel = sdp_get_proto_port(protos, RFCOMM_UUID); } sdp_record_free(item); } sdp_list_free(list, 0); sdp_close(sdp_session); sleep(1); smlTrace(TRACE_INTERNAL, "%s: SDP SyncML channel for %s: %d", __func__, env->path, channel); } #endif if (GET_OBEX_RESULT(BtOBEX_TransportConnect(env->obexhandle, BDADDR_ANY, &bdaddr, channel)) < 0) { smlErrorSet(&error, SML_ERROR_GENERIC, "The Bluetooth connect failed. %s (%i).", strerror(errno), errno); goto error; } smlTrace(TRACE_INTERNAL, "%s: bluetooth connect done", __func__); #else smlErrorSet(&error, SML_ERROR_GENERIC, "Bluetooth not enabled"); goto error; #endif } else if (env->type == SML_TRANSPORT_CONNECTION_TYPE_IRDA) { smlTrace(TRACE_INTERNAL, "%s: connecting to IrDA service %s", __func__, env->irda_service ? env->irda_service : "OBEX"); if (GET_OBEX_RESULT(IrOBEX_TransportConnect(env->obexhandle, env->irda_service)) < 0) { smlErrorSet(&error, SML_ERROR_GENERIC, "The IrDA connect failed. %s (%i).", strerror(errno), errno); goto error; } smlTrace(TRACE_INTERNAL, "%s: IrDA connect done", __func__); } else { #ifndef WIN32 struct termios tio; memset(&tio, 0, sizeof(tio)); /* Open the file descriptor */ fd = open(env->path, O_RDWR | O_NOCTTY); if (fd == -1) { smlErrorSet(&error, SML_ERROR_GENERIC, "Unable to open %s: %s", env->path, strerror(errno)); goto error; } /* Lock it*/ if (lockf(fd, F_TLOCK, 0)) { smlErrorSet(&error, SML_ERROR_GENERIC, "Unable to lock %s: %s", env->path, strerror(errno)); goto error_close; } if (tcgetattr(fd, &tio)) { smlErrorSet(&error, SML_ERROR_GENERIC, "Unable to get attr from %s", env->path); goto error_unlock; } /* Make the transmission raw (8 bit clean, no echo etc) */ /* Set the speed to a higher value (9600 would be default) */ #if defined(sun) && defined(__SVR4) tio.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON); tio.c_oflag &= ~OPOST; tio.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN); tio.c_cflag &= ~(CSIZE|PARENB); tio.c_cflag |= CS8; #else cfmakeraw(&tio); #endif cfsetispeed(&tio, B115200); cfsetospeed(&tio, B115200); if (tcsetattr(fd, TCSANOW, &tio)) { smlErrorSet(&error, SML_ERROR_GENERIC, "Unable to set attr from %s", env->path); goto error_unlock; } tcflush(fd, TCIFLUSH); #endif } if (env->type != SML_TRANSPORT_CONNECTION_TYPE_USB && env->type != SML_TRANSPORT_CONNECTION_TYPE_BLUETOOTH && env->type != SML_TRANSPORT_CONNECTION_TYPE_IRDA) { /* Start the obex transport */ if (GET_OBEX_RESULT(FdOBEX_TransportSetup(env->obexhandle, fd, fd, 4096)) < 0) { smlErrorSet(&error, SML_ERROR_GENERIC, "The OBEX transport setup failed. %s (%i).", strerror(errno), errno); goto error_unlock; } } /* Make a new connect object */ obex_object_t *obj = OBEX_ObjectNew(env->obexhandle, OBEX_CMD_CONNECT); if (!obj) { smlErrorSet(&error, SML_ERROR_GENERIC, "Unable to create new connect object"); goto error_transport_close; } /* Now add the header for the sync target */ obex_headerdata_t header; header.bs = (unsigned char *)"SYNCML-SYNC"; OBEX_ObjectAddHeader(env->obexhandle, obj, OBEX_HDR_TARGET, header, strlen((char *)header.bs), OBEX_FL_FIT_ONE_PACKET); env->busy = TRUE; /* Now we need to send the request */ if (GET_OBEX_RESULT(OBEX_Request(env->obexhandle, obj)) < 0) { smlErrorSet(&error, SML_ERROR_GENERIC, "The OBEX request failed. %s (%i).", strerror(errno), errno); goto error_free_obj; } if (env->error) { smlTrace(TRACE_EXIT, "%s: Unable to send connect request. Bailing out", __func__); return; } /* Lets see if it was successfull */ while (env->busy) { int result = OBEX_HandleInput(env->obexhandle, 20); if (result < 0) { smlErrorSet(&error, SML_ERROR_GENERIC, "The connect request was not successful (%i).", result); goto error; } else if (result == 0) { smlErrorSet(&error, SML_ERROR_GENERIC, "The connect request was timed out."); goto error; } } smlTrace(TRACE_EXIT, "%s", __func__); return; error_free_obj: OBEX_ObjectDelete(env->obexhandle, obj); error_transport_close: OBEX_Cleanup(env->obexhandle); error_unlock: #ifndef WIN32 if (!lockf(fd, F_ULOCK, 0)) smlTrace(TRACE_ERROR, "%s: error_unlock failed.", __func__); #endif error_close: close(fd); error: smlTransportReceiveEvent(env->tsp, NULL, SML_TRANSPORT_EVENT_ERROR, NULL, error); smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(&error)); smlErrorDeref(&error); } static void smlTransportObexClientDisconnect(void *data, void *linkdata) { smlTrace(TRACE_ENTRY, "%s(%p, %p)", __func__, data, linkdata); smlAssert(data); SmlTransportObexClientEnv *env = data; SmlError *error = NULL; if (env->isDisconnected) { /* This is a bug. If the transport is disconnected * then there is no reason for a second disconnect. * Nevertheless this mistake should not be fatal. */ smlTrace(TRACE_EXIT_ERROR, "%s - disconnect called on already disconnected transport", __func__); g_warning("%s called on disconnected OBEX connection.", __func__); return; } env->error = FALSE; /* Make a new disconnect object */ obex_object_t *obj = OBEX_ObjectNew(env->obexhandle, OBEX_CMD_DISCONNECT); if (!obj) { smlErrorSet(&error, SML_ERROR_GENERIC, "Unable to create new disconnect object"); goto error; } /* Add the connection id */ obex_headerdata_t header; header.bq4 = env->connection_id; OBEX_ObjectAddHeader(env->obexhandle, obj, OBEX_HDR_CONNECTION, header, sizeof(env->connection_id), OBEX_FL_FIT_ONE_PACKET); env->busy = TRUE; /* Now we need to send the request */ if (GET_OBEX_RESULT(OBEX_Request(env->obexhandle, obj)) < 0) { smlErrorSet(&error, SML_ERROR_GENERIC, "The OBEX request cannot be sent. %s (%i).", strerror(errno), errno); goto error_free_obj; } if (env->error) { smlErrorSet(&error, SML_ERROR_GENERIC, "Unable to send disconnect request. Bailing out"); goto error; } /* Lets see if it was successfull. We wait a certain period of * time (3 sec) for the answer to the disconnect. If we dont receive * the answer we just disconnect anyways. Some phones never answer * with a A0 (success) to the disconnect request, so we must have * a timeout here */ int maxLoop = 3; int i = 0; while (env->busy) { smlTrace(TRACE_INTERNAL, "%s: Disconnect loop %i", __func__, i); int result = OBEX_HandleInput(env->obexhandle, 1); /* timeout and success are not relevant */ if (result < 0) { smlErrorSet(&error, SML_ERROR_GENERIC, "The disconnect request was not accepted (%i).", result); goto error; } else if (result == 0 && !env->busy && !env->isDisconnected) { smlErrorSet(&error, SML_ERROR_GENERIC, "The disconnect request was timed out."); goto error; } if (i == maxLoop) { smlTrace(TRACE_INTERNAL, "%s: Did not receive a response to our disconnect", __func__); break; } i++; } /* Note: The disconnect is signaled by OBEX_EV_LINKERR or OBEX_CMD_DISCONNECT. * We only signal disconnect here if a phone does not answer. */ if (!env->isDisconnected) { env->busy = FALSE; env->isDisconnected = TRUE; OBEX_TransportDisconnect(env->obexhandle); smlTransportReceiveEvent(env->tsp, NULL, SML_TRANSPORT_EVENT_DISCONNECT_DONE, NULL, NULL); } smlTrace(TRACE_EXIT, "%s", __func__); return; error_free_obj: OBEX_ObjectDelete(env->obexhandle, obj); error: smlTransportReceiveEvent(env->tsp, NULL, SML_TRANSPORT_EVENT_ERROR, NULL, error); smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(&error)); smlErrorDeref(&error); } static void smlTransportObexClientSend(void *userdata, void *link_, SmlTransportData *data, SmlError *error) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p, %p)", __func__, userdata, link_, data, error); smlAssert(error || data); smlAssert(userdata); SmlTransportObexClientEnv *env = userdata; smlAssert(env); if (error) goto error; env->error = FALSE; env->mimetype = data->type; /* Make a new put command */ obex_object_t *obj = OBEX_ObjectNew(env->obexhandle, OBEX_CMD_PUT); if (!obj) { smlErrorSet(&error, SML_ERROR_GENERIC, "Unable to create new put object"); goto error; } /* Now add the header for the put target */ obex_headerdata_t header; smlTrace(TRACE_INTERNAL, "%s: Adding connection id %i", __func__, env->connection_id); /* Add the connection id */ header.bq4 = env->connection_id; OBEX_ObjectAddHeader(env->obexhandle, obj, OBEX_HDR_CONNECTION, header, sizeof(env->connection_id), OBEX_FL_FIT_ONE_PACKET); const char *target = NULL; switch (data->type) { case SML_MIMETYPE_WBXML: target = SML_ELEMENT_WBXML; break; case SML_MIMETYPE_XML: target = SML_ELEMENT_XML; break; case SML_MIMETYPE_SAN: target = SML_ELEMENT_SAN; break; default: smlErrorSet(&error, SML_ERROR_GENERIC, "Unknown mime type"); goto error_free_obj; } smlTrace(TRACE_INTERNAL, "%s: Target %s", __func__, VA_STRING(target)); /* Now convert to unicode. It requires 2 bytes per char + end*/ /*unsigned char *unicode = g_malloc0(2 * strlen(target) + 2); unsigned int unicodesize = OBEX_CharToUnicode(unicode, (const unsigned char *)target, 2 * strlen(target) + 2); if (unicodesize == -1) { smlErrorSet(&error, SML_ERROR_GENERIC, "unable to convert to unicode"); goto error_free_obj; }*/ /* Now add the target mime type */ /*header.bs = (unsigned char *)unicode; OBEX_ObjectAddHeader(env->obexhandle, obj, OBEX_HDR_TYPE, header, unicodesize, 0);*/ header.bs = (unsigned char *)target; OBEX_ObjectAddHeader(env->obexhandle, obj, OBEX_HDR_TYPE, header, strlen(target) + 1, 0); /* Now the data and size */ header.bq4 = (uint32_t)data->size; OBEX_ObjectAddHeader(env->obexhandle, obj, OBEX_HDR_LENGTH, header, sizeof(uint32_t), 0); header.bs = (unsigned char *)data->data; OBEX_ObjectAddHeader(env->obexhandle, obj, OBEX_HDR_BODY, header, data->size, 0); env->busy = TRUE; /* Now we need to send the request */ if (GET_OBEX_RESULT(OBEX_Request(env->obexhandle, obj)) < 0) { smlErrorSet(&error, SML_ERROR_GENERIC, "The OBEX request cannot be sent. %s (%i).", strerror(errno), errno); goto error_free_obj; } /* Lets see if it was successfull */ while (env->busy) { int result = OBEX_HandleInput(env->obexhandle, 20); if (result < 0) { smlErrorSet(&error, SML_ERROR_GENERIC, "The request was not successful (%d).", result); goto error; } else if (result == 0 && !env->busy) { smlErrorSet(&error, SML_ERROR_GENERIC, "The request was timed out."); goto error; } } if (env->error) { smlErrorSet(&error, SML_ERROR_GENERIC, "Unable to send put request. Bailing out"); goto error; } smlTrace(TRACE_INTERNAL, "%s: Done sending the put request", __func__); if (!data->needsAnswer) { smlTrace(TRACE_EXIT, "%s: No answer is needed", __func__); return; } /* Make a new get command */ obj = OBEX_ObjectNew(env->obexhandle, OBEX_CMD_GET); if (!obj) { smlErrorSet(&error, SML_ERROR_GENERIC, "Unable to create new get object"); goto error; } /* Now add the header for the get target */ smlTrace(TRACE_INTERNAL, "%s: Adding connection id %i", __func__, env->connection_id); /* Add the connection id */ header.bq4 = env->connection_id; OBEX_ObjectAddHeader(env->obexhandle, obj, OBEX_HDR_CONNECTION, header, sizeof(env->connection_id), OBEX_FL_FIT_ONE_PACKET); /* If smlTransportData.get_type is set, switch the mimetype for the GET command. This is needed for SyncML 1.2 SAN notificion: If this obex send sequence sends SyncML 1.2 SAN notification, switch the mimetype back to regular mimetype (not the SAN mimetype). The mimtype for the regular sync got stored in smlTransportData.type_get */ if (data->type_get != SML_MIMETYPE_UNKNOWN) { switch (data->type_get) { case SML_MIMETYPE_WBXML: target = SML_ELEMENT_WBXML; break; case SML_MIMETYPE_XML: target = SML_ELEMENT_XML; break; case SML_MIMETYPE_SAN: target = SML_ELEMENT_SAN; break; default: smlErrorSet(&error, SML_ERROR_GENERIC, "Unknown mime type"); goto error_free_obj; } /* After this point, the entire conversion will be XML or WBXML. No more SAN mimetype. */ env->mimetype = data->type_get; smlTrace(TRACE_INTERNAL, "%s: Switch to new target: %s", __func__, VA_STRING(target)); } /* Now add the target mime type */ //header.bs = (unsigned char *)unicode; //OBEX_ObjectAddHeader(env->obexhandle, obj, OBEX_HDR_TYPE, header, unicodesize, 0); header.bs = (unsigned char *)target; OBEX_ObjectAddHeader(env->obexhandle, obj, OBEX_HDR_TYPE, header, strlen(target) + 1, 0); env->busy = TRUE; /* Now we need to send the request */ if (GET_OBEX_RESULT(OBEX_Request(env->obexhandle, obj)) < 0) { smlErrorSet(&error, SML_ERROR_GENERIC, "The OBEX request cannot be sent. %s (%i).", strerror(errno), errno); goto error_free_obj; } /* Lets see if it was successfull */ smlTrace(TRACE_INTERNAL, "%s: Wait for the answer ...", __func__); while (env->busy) { int result = OBEX_HandleInput(env->obexhandle, 20); if (result < 0) { smlErrorSet(&error, SML_ERROR_GENERIC, "The answer was not received successfully (%i).", result); goto error; } else if (result == 0 && !env->busy) { smlErrorSet(&error, SML_ERROR_GENERIC, "The answer was timed out."); goto error; } } smlTrace(TRACE_EXIT, "%s", __func__); return; error_free_obj: OBEX_ObjectDelete(env->obexhandle, obj); error: smlTransportReceiveEvent(env->tsp, NULL, SML_TRANSPORT_EVENT_ERROR, NULL, error); smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(&error)); return; } SmlBool smlTransportObexClientNew(SmlTransport *tsp, SmlError **error) { CHECK_ERROR_REF smlAssert(tsp); tsp->functions.set_config_option = smlTransportObexClientSetConfigOption; tsp->functions.set_connection_type = smlTransportObexClientSetConnectionType; tsp->functions.initialize = smlTransportObexClientInit; tsp->functions.finalize = smlTransportObexClientFinalize; tsp->functions.connect = smlTransportObexClientConnect; tsp->functions.disconnect = smlTransportObexClientDisconnect; tsp->functions.send = smlTransportObexClientSend; SmlTransportObexClientEnv *env = smlTryMalloc0(sizeof(SmlTransportObexClientEnv), error); if (!env) return FALSE; tsp->transport_data = env; env->tsp = tsp; return TRUE; } libsyncml-0.5.4/libsyncml/transports/obex_server.c100644 1750 1750 65763 11211710410 22364 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2005 Armin Bauer * Copyright (C) 2008-2009 Michael Bell * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include #include #include #include #include "obex_internals.h" #include "obex_server_internals.h" #ifndef WIN32 #include #include #include #include #include #include #include #include #endif static gboolean _dispatch_obex(gpointer data) { SmlLinkObexServerEnv *linkenv = data; int result = OBEX_HandleInput(linkenv->handle, 0); if (result < 0) { SmlError *error = NULL; smlErrorSet(&error, SML_ERROR_GENERIC, "The handling of the obex input failed (%i).", result); smlTransportReceiveEvent(linkenv->env->tsp, linkenv->link, SML_TRANSPORT_EVENT_ERROR, NULL, error); smlTrace(TRACE_ERROR, "%s: %s", __func__, smlErrorPrint(&error)); smlErrorDeref(&error); return FALSE; } if (linkenv->disconnect) { smlTrace(TRACE_INTERNAL, "%s: disconnecting link", __func__); OBEX_TransportDisconnect(linkenv->handle); // close(linkenv->fd); linkenv->destroy = TRUE; } if (linkenv->destroy) { smlTrace(TRACE_INTERNAL, "%s: Destroying link %p %p", __func__, linkenv, linkenv->link); /* preserve the link and the transport for the disconnect event */ SmlTransport *tsp = linkenv->env->tsp; SmlLink *link_ = linkenv->link; smlLinkRef(link_); /* the environment must be cleaned up before the event is sent */ smlLinkDeref(linkenv->link); g_source_unref(linkenv->source); OBEX_Cleanup(linkenv->handle); if (tsp->context) g_main_context_unref(tsp->context); smlSafeFree((gpointer *)&linkenv); link_->link_data = NULL; /* send the event */ smlTransportReceiveEvent(tsp, link_, SML_TRANSPORT_EVENT_DISCONNECT_DONE, NULL, NULL); smlLinkDeref(link_); return FALSE; } return TRUE; } static void _smlTransportObexServerLinkEvent(obex_t *handle, obex_object_t *object, int mode, int event, int obex_cmd, int obex_rsp) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %i, %i, %i, %i)", __func__, handle, object, mode, event, obex_cmd, obex_rsp); SmlLinkObexServerEnv *linkenv = OBEX_GetUserData(handle); SmlError *error = NULL; obex_headerdata_t header; uint8_t headertype = 0; uint32_t len = 0; uint32_t conid = 0; SmlMimeType mimetype = SML_MIMETYPE_UNKNOWN; if (linkenv->disconnect) { OBEX_ObjectSetRsp(object, OBEX_RSP_FORBIDDEN, OBEX_RSP_FORBIDDEN); smlTrace(TRACE_EXIT, "%s: This link was disconnected", __func__); return; } switch (event) { case OBEX_EV_PROGRESS: smlTrace(TRACE_INTERNAL, "%s: Progress", __func__); break; case OBEX_EV_REQDONE: smlTrace(TRACE_INTERNAL, "%s: Done", __func__); if (obex_cmd == OBEX_CMD_DISCONNECT) { linkenv->destroy = TRUE; } break; case OBEX_EV_REQHINT: smlTrace(TRACE_INTERNAL, "%s: Hint", __func__); /* Comes BEFORE the lib parses anything. */ switch (obex_cmd) { case OBEX_CMD_GET: /* At this point we received a get request. If we dont have any data * to send yet, we iterate the main context until the data arrived. */ while (!linkenv->send_data && !linkenv->disconnect && !linkenv->error) { if (!g_main_context_pending(linkenv->env->tsp->context)) { usleep(100); continue; } smlTrace(TRACE_INTERNAL, "%s: Dispatching command queue since we dont have data to send", __func__); g_main_context_iteration(linkenv->env->tsp->context, TRUE); } /* We received a disconnect event so we reply with an error */ if (linkenv->disconnect) { OBEX_ObjectSetRsp(object, OBEX_RSP_FORBIDDEN, OBEX_RSP_FORBIDDEN); smlTrace(TRACE_INTERNAL, "%s: Get was aborted", __func__); break; } case OBEX_CMD_PUT: case OBEX_CMD_CONNECT: case OBEX_CMD_DISCONNECT: OBEX_ObjectSetRsp(object, OBEX_RSP_CONTINUE, OBEX_RSP_SUCCESS); break; default: OBEX_ObjectSetRsp(object, OBEX_RSP_NOT_IMPLEMENTED, OBEX_RSP_NOT_IMPLEMENTED); break; } break; case OBEX_EV_REQ: switch (obex_cmd) { case OBEX_CMD_SETPATH: smlTrace(TRACE_INTERNAL, "%s: Got SETPATH command", __func__); OBEX_ObjectSetRsp(object, OBEX_RSP_CONTINUE, OBEX_RSP_SUCCESS); break; case OBEX_CMD_PUT:; smlTrace(TRACE_INTERNAL, "%s: Got PUT command", __func__); uint32_t length = 0; char *body = NULL; while (OBEX_ObjectGetNextHeader(handle, object, &headertype, &header, &len)) { smlTrace(TRACE_INTERNAL, "%s: Next header %i, %d, %p", __func__, headertype, header.bq4, header.bs); switch (headertype) { case OBEX_HDR_CONNECTION: smlTrace(TRACE_INTERNAL, "%s: Found connection number: %d", __func__, header.bq4); conid = header.bq4; break; case OBEX_HDR_TYPE:; char *mimetypestr = g_strndup((char *)header.bs, len); /*char *mimetypestr = g_malloc0(len);// / 2 + 1); if (OBEX_UnicodeToChar((unsigned char *)mimetypestr, header.bs, len / 2 + 1) == -1) { smlSafeCFree(&mimetypestr); smlErrorSet(&error, SML_ERROR_GENERIC, "unable to convert from unicode"); goto error; }*/ smlTrace(TRACE_INTERNAL, "%s: Found type: %s", __func__, VA_STRING(mimetypestr)); if (!strcmp(mimetypestr, SML_ELEMENT_WBXML)) { mimetype = SML_MIMETYPE_WBXML; } else if (!strcmp(mimetypestr, SML_ELEMENT_XML)) { mimetype = SML_MIMETYPE_XML; } else if (!strcmp(mimetypestr, SML_ELEMENT_SAN)) { mimetype = SML_MIMETYPE_SAN; } else { smlSafeCFree(&mimetypestr); smlErrorSet(&error, SML_ERROR_GENERIC, "Unknown mime type"); goto error; } smlSafeCFree(&mimetypestr); break; case OBEX_HDR_LENGTH: smlTrace(TRACE_INTERNAL, "%s: Found length: %d", __func__, header.bq4); length = header.bq4; break; case OBEX_HDR_BODY: if (!length) { smlErrorSet(&error, SML_ERROR_GENERIC, "Length must come before the body"); goto error; } /* We need one byte more than the response length * because the data can be a native XML message. * If the data is a native XML message then it is * sometimes directly used as string. * * The string is automatically NULL terminated * because smlTryMalloc0 fills the new memory with NULLs. */ body = smlTryMalloc0(length + 1, &error); if (!body) goto error; memcpy(body, header.bs, length); break; default: smlTrace(TRACE_INTERNAL, "%s: Unknown header", __func__); } } if (!conid) { smlErrorSet(&error, SML_ERROR_GENERIC, "Missing connection id"); goto error; } if (conid != linkenv->conid) { smlErrorSet(&error, SML_ERROR_GENERIC, "Wrong connection id"); goto error; } if (mimetype == SML_MIMETYPE_UNKNOWN) { smlErrorSet(&error, SML_ERROR_GENERIC, "Missing mime type"); goto error; } if (!length) { smlErrorSet(&error, SML_ERROR_GENERIC, "Missing length"); goto error; } if (!body) { smlErrorSet(&error, SML_ERROR_GENERIC, "Missing body"); goto error; } SmlTransportData *tspdata = smlTransportDataNew(body, length, mimetype, TRUE, &error); if (!tspdata) goto error; if (smlTransportReceiveEvent(linkenv->env->tsp, linkenv->link, SML_TRANSPORT_EVENT_DATA, tspdata, NULL)) OBEX_ObjectSetRsp(object, OBEX_RSP_CONTINUE, OBEX_RSP_SUCCESS); else OBEX_ObjectSetRsp(object, OBEX_RSP_FORBIDDEN, OBEX_RSP_FORBIDDEN); smlTransportDataDeref(tspdata); break; case OBEX_CMD_GET:; smlTrace(TRACE_INTERNAL, "%s: Got GET command", __func__); while (OBEX_ObjectGetNextHeader(handle, object, &headertype, &header, &len)) { smlTrace(TRACE_INTERNAL, "%s: Next header %i, %d, %p", __func__, headertype, header.bq4, header.bs); switch (headertype) { case OBEX_HDR_CONNECTION: smlTrace(TRACE_INTERNAL, "%s: Found connection number: %d", __func__, header.bq4); conid = header.bq4; break; case OBEX_HDR_TYPE:; char *mimetypestr = g_strndup((char *)header.bs, len); /*char *mimetypestr = g_malloc0(len / 2 + 1); if (OBEX_UnicodeToChar((unsigned char *)mimetypestr, header.bs, len / 2 + 1) == -1) { smlSafeCFree(&mimetypestr); smlErrorSet(&error, SML_ERROR_GENERIC, "unable to convert from unicode"); goto error; }*/ smlTrace(TRACE_INTERNAL, "%s: Found type: %s", __func__, VA_STRING(mimetypestr)); if (!strcmp(mimetypestr, SML_ELEMENT_WBXML)) { mimetype = SML_MIMETYPE_WBXML; } else if (!strcmp(mimetypestr, SML_ELEMENT_XML)) { mimetype = SML_MIMETYPE_XML; } else if (!strcmp(mimetypestr, SML_ELEMENT_SAN)) { mimetype = SML_MIMETYPE_SAN; } else { smlSafeCFree(&mimetypestr); smlErrorSet(&error, SML_ERROR_GENERIC, "Unknown mime type"); goto error; } smlSafeCFree(&mimetypestr); break; default: smlTrace(TRACE_INTERNAL, "%s: Unknown header", __func__); } } if (!conid) { smlErrorSet(&error, SML_ERROR_GENERIC, "Missing connection id"); goto error; } if (conid != linkenv->conid) { smlErrorSet(&error, SML_ERROR_GENERIC, "Wrong connection id"); goto error; } if (mimetype == SML_MIMETYPE_UNKNOWN) { smlErrorSet(&error, SML_ERROR_GENERIC, "Missing mime type"); goto error; } if (linkenv->error) { if (smlErrorGetClass(&(linkenv->error)) <= SML_ERRORCLASS_RETRY) OBEX_ObjectSetRsp(object, OBEX_RSP_FORBIDDEN, OBEX_RSP_FORBIDDEN); else OBEX_ObjectSetRsp(object, OBEX_RSP_FORBIDDEN, OBEX_RSP_FORBIDDEN); smlErrorDeref(&(linkenv->error)); linkenv->error = NULL; smlTrace(TRACE_INTERNAL, "%s: Sent error in response to get", __func__); break; } if (!linkenv->send_data) { smlErrorSet(&error, SML_ERROR_GENERIC, "No data to send"); goto error; } if (mimetype != linkenv->send_data->type) { smlErrorSet(&error, SML_ERROR_GENERIC, "Wrong mimetype %d requested. %d was expected.", mimetype, linkenv->send_data->type); goto error; } /* Now the data and size */ header.bq4 = (uint32_t)linkenv->send_data->size; OBEX_ObjectAddHeader(handle, object, OBEX_HDR_LENGTH, header, sizeof(uint32_t), 0); header.bs = (unsigned char *)linkenv->send_data->data; OBEX_ObjectAddHeader(handle, object, OBEX_HDR_BODY, header, linkenv->send_data->size, 0); smlTransportDataDeref(linkenv->send_data); linkenv->send_data = NULL; OBEX_ObjectSetRsp(object, OBEX_RSP_CONTINUE, OBEX_RSP_SUCCESS); break; case OBEX_CMD_CONNECT:; smlTrace(TRACE_INTERNAL, "%s: Got CONNECT command", __func__); char *target = NULL; while (OBEX_ObjectGetNextHeader(handle, object, &headertype, &header, &len)) { smlTrace(TRACE_INTERNAL, "%s: Next header %i, %d, %p", __func__, headertype, header.bq4, header.bs); switch (headertype) { case OBEX_HDR_TARGET: target = g_strndup((char *)header.bs, len); smlTrace(TRACE_INTERNAL, "%s: Found target: %s", __func__, VA_STRING(target)); break; default: smlTrace(TRACE_INTERNAL, "%s: Unknown header", __func__); } } if (!target || strcmp(target, "SYNCML-SYNC")) { smlSafeCFree(&target); smlErrorSet(&error, SML_ERROR_GENERIC, "Missing target"); goto error; } smlSafeCFree(&target); header.bq4 = linkenv->conid; OBEX_ObjectAddHeader(handle, object, OBEX_HDR_CONNECTION, header, sizeof(linkenv->conid), OBEX_FL_FIT_ONE_PACKET); header.bs = (unsigned char *)"SYNCML-SYNC"; OBEX_ObjectAddHeader(handle, object, OBEX_HDR_WHO, header, strlen((char *)header.bs), OBEX_FL_FIT_ONE_PACKET); linkenv->link = smlLinkNew(linkenv->env->tsp, linkenv, &error); if (!linkenv->link) goto error; if (smlTransportReceiveEvent(linkenv->env->tsp, linkenv->link, SML_TRANSPORT_EVENT_CONNECT_DONE, NULL, NULL)) OBEX_ObjectSetRsp(object, OBEX_RSP_CONTINUE, OBEX_RSP_SUCCESS); else { OBEX_ObjectSetRsp(object, OBEX_RSP_FORBIDDEN, OBEX_RSP_FORBIDDEN); linkenv->disconnect = TRUE; } break; case OBEX_CMD_DISCONNECT: smlTrace(TRACE_INTERNAL, "%s: Got DISCONNECT command", __func__); OBEX_ObjectSetRsp(object, OBEX_RSP_SUCCESS, OBEX_RSP_SUCCESS); break; default: smlTrace(TRACE_INTERNAL, "%s: Denied %02x request", __func__, obex_cmd); OBEX_ObjectSetRsp(object, OBEX_RSP_NOT_IMPLEMENTED, OBEX_RSP_NOT_IMPLEMENTED); break; } break; case OBEX_EV_LINKERR: smlTrace(TRACE_INTERNAL, "%s: Link broken (this does not have to be an error)!", __func__); break; default: smlTrace(TRACE_INTERNAL, "%s: Unknown event!", __func__); break; } smlTrace(TRACE_EXIT, "%s", __func__); return; error: OBEX_ObjectSetRsp(object, OBEX_RSP_BAD_REQUEST, OBEX_RSP_BAD_REQUEST); smlErrorRef(&error); smlTransportReceiveEvent(linkenv->env->tsp, linkenv->link, SML_TRANSPORT_EVENT_ERROR, NULL, error); smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(&error)); smlErrorDeref(&error); } static void _smlTransportObexServerMainEvent(obex_t *handle, obex_object_t *object, int mode, int event, int obex_cmd, int obex_rsp) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %i, %i, %i, %i)", __func__, handle, object, mode, event, obex_cmd, obex_rsp); SmlTransportObexServerEnv *env = OBEX_GetUserData(handle); SmlError *error = NULL; SmlLinkObexServerEnv *linkenv = NULL; switch (event) { case OBEX_EV_ACCEPTHINT: /* This event means that there is a new connection. */ /* Create the env that handles this link */ linkenv = smlTryMalloc0(sizeof(SmlLinkObexServerEnv), &error); if (!linkenv) goto error; linkenv->env = env; linkenv->handle = OBEX_ServerAccept(env->handle, _smlTransportObexServerLinkEvent, linkenv); if (!linkenv->handle) { smlErrorSet(&error, SML_ERROR_GENERIC, "OBEX_ServerAccept failed."); smlSafeFree((gpointer *)&linkenv); goto error; } smlTrace(TRACE_INTERNAL, "%s: New obex_t * handle %p", __func__, linkenv->handle); /* Now we create a source that watches the new obex connection */ linkenv->source = g_idle_source_new(); g_source_set_callback(linkenv->source, _dispatch_obex, linkenv, NULL); g_source_attach(linkenv->source, env->tsp->context); if (env->tsp->context) g_main_context_ref(env->tsp->context); /* We first have to add the connection id which we generate for this transport */ env->lastConId++; linkenv->conid = env->lastConId; // the user data was already ste accept // OBEX_SetUserData(linkenv->handle, linkenv); break; default: smlErrorSet(&error, SML_ERROR_GENERIC, "Unknown OBEX event %d.", event); goto error; break; } smlTrace(TRACE_EXIT, "%s", __func__); return; error: OBEX_ObjectSetRsp(object, OBEX_RSP_BAD_REQUEST, OBEX_RSP_BAD_REQUEST); smlErrorRef(&error); smlTransportReceiveEvent(env->tsp, NULL, SML_TRANSPORT_EVENT_ERROR, NULL, error); smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(&error)); smlErrorDeref(&error); } /* These function supervise the file descriptor where we are listening for incoming * connections */ static gboolean _fd_prepare(GSource *source, gint *timeout_) { smlTrace(TRACE_INTERNAL, "%s(%p, %p)", __func__, source, timeout_); /* There is no need to dispatch this too fast since * it does not influence the transmission of data, only * the connection */ *timeout_ = 50; return FALSE; } static gboolean _fd_check(GSource *source) { SmlTransportObexServerEnv *env = *((SmlTransportObexServerEnv **)(source + 1)); fd_set rfds; FD_ZERO(&rfds); int fd = OBEX_GetFD(env->handle); FD_SET(fd, &rfds); struct timeval tv; tv.tv_sec = 0; tv.tv_usec = 1; int retval = select(fd + 1, &rfds, NULL, NULL, &tv); if (retval == -1) smlTrace(TRACE_ERROR, "%s: Unable to select()", __func__); else if (retval) return TRUE; return FALSE; } static gboolean _fd_dispatch(GSource *source, GSourceFunc callback, gpointer user_data) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, source, callback, user_data); SmlTransportObexServerEnv *env = user_data; SmlError *error = NULL; /* this is a non-locking function */ int result = OBEX_HandleInput(env->handle, 0); if (result < 0) { smlErrorSet(&error, SML_ERROR_GENERIC, "OBEX_HandleInput on main handle returned %d.", result); goto error; } if (result == 0) { smlErrorSet(&error, SML_ERROR_GENERIC, "OBEX_HandleInput on main handle get a timeout."); goto error; } smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error: smlTransportReceiveEvent(env->tsp, NULL, SML_TRANSPORT_EVENT_ERROR, NULL, error); smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(&error)); return FALSE; } static SmlBool smlTransportObexServerSetConfigOption( SmlTransport *tsp, const char *name, const char *value, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %s, %s, %p)", __func__, tsp, VA_STRING(name), VA_STRING(value), error); CHECK_ERROR_REF smlAssert(tsp); smlAssert(tsp->transport_data); SmlTransportObexServerEnv *env = tsp->transport_data; if (!strcmp(name, SML_TRANSPORT_CONFIG_PORT)) { env->port = atoi(value); smlTrace(TRACE_INTERNAL, "%s: Port %i detected", __func__, env->port); } else if (!strcmp(name, SML_TRANSPORT_CONFIG_BLUETOOTH_ADDRESS)) { #ifdef ENABLE_BLUETOOTH int code = str2ba(value, env->bdaddr); if (code != 0) { smlErrorSet(error, SML_ERROR_INTERNAL_MISCONFIGURATION, "Bluetooth MAC cannot be interpreted (%d).", code); goto error; } smlTrace(TRACE_INTERNAL, "%s: Bluetooth MAC %s detected", __func__, VA_STRING(value)); #else smlErrorSet(error, SML_ERROR_GENERIC, "Bluetooth not enabled"); goto error; #endif } else if (!strcmp(name, SML_TRANSPORT_CONFIG_BLUETOOTH_CHANNEL)) { env->port = atoi(value); smlTrace(TRACE_INTERNAL, "%s: Bluetooth channel %i detected", __func__, env->port); } else if (!strcmp(name, SML_TRANSPORT_CONFIG_IRDA_SERVICE)) { env->irda_service = g_strdup(value); smlTrace(TRACE_INTERNAL, "%s: IRDA service %s detected", __func__, VA_STRING(env->irda_service)); } else { smlErrorSet(error, SML_ERROR_INTERNAL_MISCONFIGURATION, "Unknown parameter %s found.", name); goto error; } smlTrace(TRACE_EXIT, "%s - TRUE", __func__); return TRUE; error: smlTrace(TRACE_EXIT, "%s - %s", __func__, smlErrorPrint(error)); return FALSE; } static SmlBool smlTransportObexServerSetConnectionType( SmlTransport *tsp, SmlTransportConnectionType type, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %i, %p)", __func__, tsp, type, error); CHECK_ERROR_REF smlAssert(tsp); smlAssert(tsp->transport_data); SmlTransportObexServerEnv *env = tsp->transport_data; env->type = type; smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; } static SmlBool smlTransportObexServerInit(SmlTransport *tsp, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p)", __func__, tsp, error); CHECK_ERROR_REF smlAssert(tsp); smlAssert(tsp->transport_data); SmlTransportObexServerEnv *env = tsp->transport_data; smlAssert(env->handle == NULL); switch (env->type) { #ifdef ENABLE_OPENOBEX_TCP case SML_TRANSPORT_CONNECTION_TYPE_NET:; /* init object */ env->handle = OBEX_Init(OBEX_TRANS_INET, _smlTransportObexServerMainEvent, OBEX_FL_KEEPSERVER); if (!env->handle) { smlErrorSet(error, SML_ERROR_GENERIC, "Unable to create OBEX IRDA transport."); goto error; } OBEX_SetUserData(env->handle, env); /* prepare IP address etc. */ if (!env->port) g_warning("Using default INET port."); size_t size = sizeof(struct sockaddr_in); struct sockaddr_in *addr = smlTryMalloc0(size, error); if (!addr) goto error; addr->sin_family = PF_INET; addr->sin_port = htons(env->port); addr->sin_addr.s_addr = INADDR_ANY; /* register server */ if (GET_OBEX_RESULT(TcpOBEX_ServerRegister(env->handle, (struct sockaddr *) addr, size)) < 0) { smlErrorSet(error, SML_ERROR_GENERIC, "Unable to register INET OBEX server. %s (%i).", strerror(errno), errno); smlSafeFree((gpointer *)&addr); goto error; } smlSafeFree((gpointer *)&addr); break; #endif /* ENABLE_OPENOBEX_TCP */ case SML_TRANSPORT_CONNECTION_TYPE_SERIAL: /* init object */ env->handle = OBEX_Init(OBEX_TRANS_IRDA, _smlTransportObexServerMainEvent, OBEX_FL_KEEPSERVER); if (!env->handle) { smlErrorSet(error, SML_ERROR_GENERIC, "Unable to create OBEX IRDA transport."); goto error; } OBEX_SetUserData(env->handle, env); /* register server */ if (GET_OBEX_RESULT(IrOBEX_ServerRegister(env->handle, env->irda_service))) { smlErrorSet(error, SML_ERROR_GENERIC, "Unable to register IRDA OBEX server. %s (%i).", strerror(errno), errno); goto error; } break; case SML_TRANSPORT_CONNECTION_TYPE_BLUETOOTH: #ifdef ENABLE_BLUETOOTH /* init object */ env->handle = OBEX_Init(OBEX_TRANS_BLUETOOTH, _smlTransportObexServerMainEvent, OBEX_FL_KEEPSERVER); if (!env->handle) { smlErrorSet(error, SML_ERROR_GENERIC, "Unable to create OBEX Bluetooth transport."); goto error; } OBEX_SetUserData(env->handle, env); /* register server */ if (GET_OBEX_RESULT(BtOBEX_ServerRegister(env->handle, env->bdaddr, env->port)) < 0) { smlErrorSet(error, SML_ERROR_GENERIC, "Unable to register Bluetooth OBEX server. %s (%i).", strerror(errno), errno); goto error; } #else smlErrorSet(error, SML_ERROR_GENERIC, "Bluetooth not enabled"); goto error; #endif break; default: smlErrorSet(error, SML_ERROR_GENERIC, "Unknown obex type"); goto error; } smlTrace(TRACE_INTERNAL, "%s: server registered successfully", __func__); /* Now we create a source that watches for incoming connection requests */ env->functions = smlTryMalloc0(sizeof(GSourceFuncs), error); if (!env->functions) goto error; env->functions->prepare = _fd_prepare; env->functions->check = _fd_check; env->functions->dispatch = _fd_dispatch; env->functions->finalize = NULL; env->source = g_source_new(env->functions, sizeof(GSource) + sizeof(SmlTransportObexServerEnv *)); SmlTransportObexServerEnv **envptr = (SmlTransportObexServerEnv **)(env->source + 1); *envptr = env; g_source_set_callback(env->source, NULL, env, NULL); g_source_attach(env->source, tsp->context); if (tsp->context) g_main_context_ref(tsp->context); smlTrace(TRACE_EXIT, "%s: %p", __func__, env); return TRUE; error: if (env->handle) { OBEX_Cleanup(env->handle); env->handle = NULL; } if (env) smlSafeFree((gpointer *)&env); smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(error)); return FALSE; } static SmlBool smlTransportObexServerFinalize(void *data, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p)", __func__, data, error); CHECK_ERROR_REF smlAssert(data); SmlTransportObexServerEnv *env = data; smlAssert(env->tsp); if (env->handle) OBEX_Cleanup(env->handle); /* detach source */ if (env->source) { g_source_destroy(env->source); g_source_unref(env->source); } /* free context */ if (env->tsp->context) g_main_context_unref(env->tsp->context); /* free functions */ if (env->functions) smlSafeFree((gpointer *)&(env->functions)); if (env->irda_service) smlSafeCFree(&(env->irda_service)); smlSafeFree((gpointer *)&env); smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; } static void smlTransportObexServerSend(void *userdata, void *linkdata, SmlTransportData *data, SmlError *error) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p, %p)", __func__, userdata, linkdata, data, error); smlAssert(data || error); smlAssert(userdata); // Unused: SmlTransportObexServerEnv *env = userdata; SmlLinkObexServerEnv *linkenv = linkdata; smlAssert(linkenv); SmlError *local_error = NULL; if (linkdata == NULL) { /* send is called before connect succeeded or * the user of the library ignored the link */ smlErrorSet(&local_error, SML_ERROR_GENERIC, "The OBEX server tries to send before a connection with a client was established or the link was ignored."); goto error; } if (error) { smlAssert(!data); linkenv->error = error; smlTrace(TRACE_EXIT, "%s: Error set", __func__); return; } if (linkenv->send_data) { smlErrorSet(&local_error, SML_ERROR_GENERIC, "We already have waiting data"); goto error; } linkenv->send_data = data; smlTransportDataRef(linkenv->send_data); smlTrace(TRACE_EXIT, "%s", __func__); return; error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(&local_error)); smlTransportReceiveEvent(linkenv->env->tsp, linkenv->link, SML_TRANSPORT_EVENT_ERROR, NULL, local_error); smlErrorDeref(&local_error); return; } static void smlTransportObexServerDisconnect(void *data, void *linkdata) { smlTrace(TRACE_ENTRY, "%s(%p, %p)", __func__, data, linkdata); smlAssert(data); /* The OBEX client usually performs the disconnect. * If the server disconnects first then the client * interprets this as an error. So if we want to * abort a connection then this is the correct way. */ if (linkdata) { SmlLinkObexServerEnv *linkenv = linkdata; linkenv->disconnect = TRUE; smlTrace(TRACE_ERROR, "%s - explicit disconnect by OBEX server", __func__); } smlTrace(TRACE_EXIT, "%s", __func__); return; } SmlBool smlTransportObexServerNew(SmlTransport *tsp, SmlError **error) { CHECK_ERROR_REF smlAssert(tsp); tsp->functions.set_config_option = smlTransportObexServerSetConfigOption; tsp->functions.set_connection_type = smlTransportObexServerSetConnectionType; tsp->functions.initialize = smlTransportObexServerInit; tsp->functions.finalize = smlTransportObexServerFinalize; tsp->functions.send = smlTransportObexServerSend; tsp->functions.disconnect = smlTransportObexServerDisconnect; SmlTransportObexServerEnv *env = smlTryMalloc0(sizeof(SmlTransportObexServerEnv), error); if (!env) return FALSE; tsp->transport_data = env; env->tsp = tsp; env->lastConId = 0; env->port = 0; return TRUE; } libsyncml-0.5.4/libsyncml/sml_parse_internals.h100644 1750 1750 2526 11211710410 21637 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2005 Armin Bauer * Copyright (C) 2008 Michael Bell * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #ifndef _SML_PARSE_INTERNALS_H_ #define _SML_PARSE_INTERNALS_H_ struct SmlParser { SmlParserFunctions functions; void *parser_userdata; SmlMimeType type; unsigned int limit; SmlManager *manager; }; struct SmlAssembler { SmlAssemblerFunctions functions; void *assm_userdata; SmlMimeType type; GHashTable *options; SmlBool empty; unsigned int remoteMaxMsgSize; unsigned int remoteMaxObjSize; }; #endif //_SML_PARSE_INTERNALS_H_ libsyncml-0.5.4/libsyncml/sml_md5.c100644 1750 1750 20006 11211710410 17137 0ustar00bellmichbellmich/* parts of this file are : * Written March 1993 by Branko Lankester * Modified June 1993 by Colin Plumb for altered md5.c. * Modified October 1995 by Erik Troan for RPM * Modified again 2005 by Armin Bauer * This code is in the public domain * */ #include "syncml.h" #include "syncml_internals.h" #include "sml_error_internals.h" #include #include #include "sml_md5.h" #include typedef struct SmlMD5Context { uint32_t buf[4]; uint32_t bits[2]; unsigned char in[64]; int doByteReverse; } SmlMD5Context; void smlMD5Init(SmlMD5Context *ctx); void smlMD5Update(SmlMD5Context *ctx, const char *buf, uint32_t len); void smlMD5Final (SmlMD5Context *ctx, unsigned char digest[16]); static void smlMD5Transform(uint32_t buf[4], const uint32_t in[16]); static gint _ie = 0x44332211; static union _endian { gint i; gchar b[4]; } *_endian = (union _endian *)&_ie; #define IS_BIG_ENDIAN() (_endian->b[0] == '\x44') #define IS_LITTLE_ENDIAN() (_endian->b[0] == '\x11') /* The four core functions - F1 is optimized somewhat */ /* #define F1(x, y, z) (x & y | ~x & z) */ #define F1(x, y, z) (z ^ (x & (y ^ z))) #define F2(x, y, z) F1(z, x, y) #define F3(x, y, z) (x ^ y ^ z) #define F4(x, y, z) (y ^ (x | ~z)) /* This is the central step in the MD5 algorithm. */ #define MD5STEP(f, w, x, y, z, data, s) ( w += f(x, y, z) + data, w = w<>(32-s), w += x ) /* * Note: this code is harmless on little-endian machines. */ static void _byte_reverse (guchar *buf, guint32 longs) { guint32 t; do { t = (guint32) ((guint32) buf[3] << 8 | buf[2]) << 16 | ((guint32) buf[1] << 8 | buf[0]); *(guint32 *) buf = t; buf += 4; } while (--longs); } void smlMD5Init(SmlMD5Context *ctx) { ctx->buf[0] = 0x67452301; ctx->buf[1] = 0xefcdab89; ctx->buf[2] = 0x98badcfe; ctx->buf[3] = 0x10325476; ctx->bits[0] = 0; ctx->bits[1] = 0; if (IS_BIG_ENDIAN()) ctx->doByteReverse = 1; else ctx->doByteReverse = 0; } void smlMD5Update(SmlMD5Context *ctx, const char *buf, uint32_t len) { guint32 t; /* Update bitcount */ t = ctx->bits[0]; if ((ctx->bits[0] = t + ((guint32) len << 3)) < t) ctx->bits[1]++; /* Carry from low to high */ ctx->bits[1] += len >> 29; t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */ /* Handle any leading odd-sized chunks */ if (t) { guchar *p = (guchar *) ctx->in + t; t = 64 - t; if (len < t) { memcpy (p, buf, len); return; } memcpy (p, buf, t); if (ctx->doByteReverse) _byte_reverse (ctx->in, 16); smlMD5Transform (ctx->buf, (guint32 *) ctx->in); buf += t; len -= t; } /* Process data in 64-byte chunks */ while (len >= 64) { memcpy (ctx->in, buf, 64); if (ctx->doByteReverse) _byte_reverse (ctx->in, 16); smlMD5Transform (ctx->buf, (guint32 *) ctx->in); buf += 64; len -= 64; } /* Handle any remaining bytes of data. */ memcpy (ctx->in, buf, len); } void smlMD5Final (SmlMD5Context *ctx, unsigned char digest[16]) { guint32 count; guchar *p; /* Compute number of bytes mod 64 */ count = (ctx->bits[0] >> 3) & 0x3F; /* Set the first char of padding to 0x80. This is safe since there is always at least one byte free */ p = ctx->in + count; *p++ = 0x80; /* Bytes of padding needed to make 64 bytes */ count = 64 - 1 - count; /* Pad out to 56 mod 64 */ if (count < 8) { /* Two lots of padding: Pad the first block to 64 bytes */ memset (p, 0, count); if (ctx->doByteReverse) _byte_reverse (ctx->in, 16); smlMD5Transform (ctx->buf, (guint32 *) ctx->in); /* Now fill the next block with 56 bytes */ memset (ctx->in, 0, 56); } else { /* Pad block to 56 bytes */ memset (p, 0, count - 8); } if (ctx->doByteReverse) _byte_reverse (ctx->in, 14); /* Append length in bits and transform */ ((guint32 *) ctx->in)[14] = ctx->bits[0]; ((guint32 *) ctx->in)[15] = ctx->bits[1]; smlMD5Transform (ctx->buf, (guint32 *) ctx->in); if (ctx->doByteReverse) _byte_reverse ((guchar *) ctx->buf, 4); memcpy (digest, ctx->buf, 16); } static void smlMD5Transform(uint32_t buf[4], const uint32_t in[16]) { register guint32 a, b, c, d; a = buf[0]; b = buf[1]; c = buf[2]; d = buf[3]; MD5STEP (F1, a, b, c, d, in[0] + 0xd76aa478, 7); MD5STEP (F1, d, a, b, c, in[1] + 0xe8c7b756, 12); MD5STEP (F1, c, d, a, b, in[2] + 0x242070db, 17); MD5STEP (F1, b, c, d, a, in[3] + 0xc1bdceee, 22); MD5STEP (F1, a, b, c, d, in[4] + 0xf57c0faf, 7); MD5STEP (F1, d, a, b, c, in[5] + 0x4787c62a, 12); MD5STEP (F1, c, d, a, b, in[6] + 0xa8304613, 17); MD5STEP (F1, b, c, d, a, in[7] + 0xfd469501, 22); MD5STEP (F1, a, b, c, d, in[8] + 0x698098d8, 7); MD5STEP (F1, d, a, b, c, in[9] + 0x8b44f7af, 12); MD5STEP (F1, c, d, a, b, in[10] + 0xffff5bb1, 17); MD5STEP (F1, b, c, d, a, in[11] + 0x895cd7be, 22); MD5STEP (F1, a, b, c, d, in[12] + 0x6b901122, 7); MD5STEP (F1, d, a, b, c, in[13] + 0xfd987193, 12); MD5STEP (F1, c, d, a, b, in[14] + 0xa679438e, 17); MD5STEP (F1, b, c, d, a, in[15] + 0x49b40821, 22); MD5STEP (F2, a, b, c, d, in[1] + 0xf61e2562, 5); MD5STEP (F2, d, a, b, c, in[6] + 0xc040b340, 9); MD5STEP (F2, c, d, a, b, in[11] + 0x265e5a51, 14); MD5STEP (F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20); MD5STEP (F2, a, b, c, d, in[5] + 0xd62f105d, 5); MD5STEP (F2, d, a, b, c, in[10] + 0x02441453, 9); MD5STEP (F2, c, d, a, b, in[15] + 0xd8a1e681, 14); MD5STEP (F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20); MD5STEP (F2, a, b, c, d, in[9] + 0x21e1cde6, 5); MD5STEP (F2, d, a, b, c, in[14] + 0xc33707d6, 9); MD5STEP (F2, c, d, a, b, in[3] + 0xf4d50d87, 14); MD5STEP (F2, b, c, d, a, in[8] + 0x455a14ed, 20); MD5STEP (F2, a, b, c, d, in[13] + 0xa9e3e905, 5); MD5STEP (F2, d, a, b, c, in[2] + 0xfcefa3f8, 9); MD5STEP (F2, c, d, a, b, in[7] + 0x676f02d9, 14); MD5STEP (F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20); MD5STEP (F3, a, b, c, d, in[5] + 0xfffa3942, 4); MD5STEP (F3, d, a, b, c, in[8] + 0x8771f681, 11); MD5STEP (F3, c, d, a, b, in[11] + 0x6d9d6122, 16); MD5STEP (F3, b, c, d, a, in[14] + 0xfde5380c, 23); MD5STEP (F3, a, b, c, d, in[1] + 0xa4beea44, 4); MD5STEP (F3, d, a, b, c, in[4] + 0x4bdecfa9, 11); MD5STEP (F3, c, d, a, b, in[7] + 0xf6bb4b60, 16); MD5STEP (F3, b, c, d, a, in[10] + 0xbebfbc70, 23); MD5STEP (F3, a, b, c, d, in[13] + 0x289b7ec6, 4); MD5STEP (F3, d, a, b, c, in[0] + 0xeaa127fa, 11); MD5STEP (F3, c, d, a, b, in[3] + 0xd4ef3085, 16); MD5STEP (F3, b, c, d, a, in[6] + 0x04881d05, 23); MD5STEP (F3, a, b, c, d, in[9] + 0xd9d4d039, 4); MD5STEP (F3, d, a, b, c, in[12] + 0xe6db99e5, 11); MD5STEP (F3, c, d, a, b, in[15] + 0x1fa27cf8, 16); MD5STEP (F3, b, c, d, a, in[2] + 0xc4ac5665, 23); MD5STEP (F4, a, b, c, d, in[0] + 0xf4292244, 6); MD5STEP (F4, d, a, b, c, in[7] + 0x432aff97, 10); MD5STEP (F4, c, d, a, b, in[14] + 0xab9423a7, 15); MD5STEP (F4, b, c, d, a, in[5] + 0xfc93a039, 21); MD5STEP (F4, a, b, c, d, in[12] + 0x655b59c3, 6); MD5STEP (F4, d, a, b, c, in[3] + 0x8f0ccc92, 10); MD5STEP (F4, c, d, a, b, in[10] + 0xffeff47d, 15); MD5STEP (F4, b, c, d, a, in[1] + 0x85845dd1, 21); MD5STEP (F4, a, b, c, d, in[8] + 0x6fa87e4f, 6); MD5STEP (F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10); MD5STEP (F4, c, d, a, b, in[6] + 0xa3014314, 15); MD5STEP (F4, b, c, d, a, in[13] + 0x4e0811a1, 21); MD5STEP (F4, a, b, c, d, in[4] + 0xf7537e82, 6); MD5STEP (F4, d, a, b, c, in[11] + 0xbd3af235, 10); MD5STEP (F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15); MD5STEP (F4, b, c, d, a, in[9] + 0xeb86d391, 21); buf[0] += a; buf[1] += b; buf[2] += c; buf[3] += d; } void smlMD5GetDigest (const char *buffer, int buffer_size, unsigned char digest[16]) { SmlMD5Context ctx; smlMD5Init (&ctx); smlMD5Update (&ctx, buffer, buffer_size); smlMD5Final (&ctx, digest); } char *smlMD5ToString(unsigned char digest[16], SmlError **error) { CHECK_ERROR_REF char *string = smlTryMalloc0(33, error); if (!string) return NULL; snprintf(string, 33, "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", digest[0], digest[1], digest[2], digest[3], digest[4], digest[5], digest[6], digest[7], digest[8], digest[9], digest[10], digest[11], digest[12], digest[13], digest[14], digest[15]); return string; } /*@}*/ libsyncml-0.5.4/libsyncml/sml_notification.h100644 1750 1750 6053 11211710410 21133 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2005 Armin Bauer * Copyright (C) 2007 Michael Bell * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ /** * @defgroup SmlNotification SyncML Notifications * @ingroup PublicLowLevelAPI * @brief The public part * */ /*@{*/ #ifndef _SML_NOTIFICATION_H_ #define _SML_NOTIFICATION_H_ typedef enum { SML_SAN_VERSION_UNKNOWN = 0, SML_SAN_VERSION_10 = 1, SML_SAN_VERSION_11 = 2, SML_SAN_VERSION_12 = 3 } SmlNotificationVersion; typedef enum { SML_SAN_UIMODE_UNSPECIFIED = 0, SML_SAN_UIMODE_BACKGROUND = 1, SML_SAN_UIMODE_INFORMATIVE = 2, SML_SAN_UIMODE_USER = 3 } SmlNotificationUIMode; typedef enum { SML_SAN_INITIATOR_USER = 0, SML_SAN_INITIATOR_SERVER = 1 } SmlNotificationInitiator; SmlNotification *smlNotificationNew(SmlNotificationVersion version, SmlNotificationUIMode mode, SmlNotificationInitiator init, unsigned int sessionID, const char *identifier, const char *target, SmlMimeType type, SmlError **error); void smlNotificationSetCred(SmlNotification *san, SmlCred *cred); void smlNotificationSetManager(SmlNotification *san, SmlManager *manager); void smlNotificationFree(SmlNotification *san); SmlNotification *smlNotificationParse(const char *data, unsigned int size, SmlError **error); SmlBool smlNotificationAssemble(SmlNotification *san, char **data, unsigned int *size, SmlError **error); SmlBool smlNotificationSend(SmlNotification *san, SmlTransport *tsp, SmlError **error); SmlBool smlNotificationNewAlert(SmlNotification *san, SmlAlertType type, const char *contenttype, const char *serverURI, SmlError **error); void smlNotificationFreeAlert(SmlSanAlert *alert); SmlNotificationVersion smlNotificationGetVersion(SmlNotification *san); SmlNotificationUIMode smlNotificationGetMode(SmlNotification *san); SmlNotificationInitiator smlNotificationGetInitiator(SmlNotification *san); unsigned int smlNotificationGetSessionID(SmlNotification *san); const char *smlNotificationGetIdentifier(SmlNotification *san); unsigned int smlNotificationNumAlerts(SmlNotification *san); SmlSanAlert *smlNotificationNthAlert(SmlNotification *san, unsigned int nth); SmlAlertType smlSanAlertGetType(SmlSanAlert *alert); const char *smlSanAlertGetContentType(SmlSanAlert *alert); const char *smlSanAlertGetServerURI(SmlSanAlert *alert); #endif //_SML_NOTIFICATION_H_ /*@{*/ libsyncml-0.5.4/libsyncml/sml_transport.h100644 1750 1750 7015 11211710410 20500 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2005 Armin Bauer * Copyright (C) 2008 Michael Bell * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #ifndef _SML_TRANSPORT_H_ #define _SML_TRANSPORT_H_ typedef enum SmlTransportEventType { SML_TRANSPORT_EVENT_CONNECT_DONE, SML_TRANSPORT_EVENT_DISCONNECT_DONE, SML_TRANSPORT_EVENT_ERROR, SML_TRANSPORT_EVENT_DATA } SmlTransportEventType; typedef enum { SML_TRANSPORT_CONNECTION_TYPE_UNKNOWN = 0, SML_TRANSPORT_CONNECTION_TYPE_SERIAL = 1, SML_TRANSPORT_CONNECTION_TYPE_BLUETOOTH = 2, SML_TRANSPORT_CONNECTION_TYPE_IRDA = 3, SML_TRANSPORT_CONNECTION_TYPE_NET = 4, SML_TRANSPORT_CONNECTION_TYPE_USB = 5 } SmlTransportConnectionType; typedef SmlBool (* SmlTransportEventCb) (SmlTransport *tsp, SmlLink *link, SmlTransportEventType type, SmlTransportData *data, SmlError *error, void *userdata); SmlTransport *smlTransportNew(SmlTransportType type, SmlError **error); void smlTransportFree(SmlTransport *tsp); SmlBool smlTransportSetConfigOption(SmlTransport *tsp, const char *name, const char *value, SmlError **error); SmlBool smlTransportSetConnectionType(SmlTransport *tsp, SmlTransportConnectionType type, SmlError **error); SmlBool smlTransportInitialize(SmlTransport *tsp, SmlError **error); void smlTransportSetEventCallback(SmlTransport *tsp, SmlTransportEventCb callback, void *userdata); SmlBool smlTransportFinalize(SmlTransport *tsp, SmlError **error); SmlBool smlTransportConnect(SmlTransport *tsp, SmlError **error); SmlBool smlTransportDisconnect(SmlTransport *tsp, SmlLink *link, SmlError **error); SmlBool smlTransportSend(SmlTransport *tsp, SmlLink *link, SmlTransportData *data, SmlError **error); SmlTransportData *smlTransportDataNew(char *data, unsigned long size, SmlMimeType mimetype, SmlBool ownsData, SmlError **error); SmlTransportData *smlTransportDataRef(SmlTransportData *data); void smlTransportDataDeref(SmlTransportData *data); SmlLink *smlLinkNew(SmlTransport *tsp, void *link_data, SmlError **error); SmlLink *smlLinkRef(SmlLink *link); void smlLinkDeref(SmlLink *link); void smlTransportSetError(SmlTransport *tsp, SmlLink *link, SmlError **error); SmlTransportType smlTransportGetType(SmlTransport *tsp); SmlTransport *smlManagerGetTransport(SmlManager *manager); /* This function will only be removed from the header. */ SmlBool smlTransportRunAsync(SmlTransport *tsp, SmlError **error) LIBSYNCML_DEPRECATED; /* expire date: 20090728 */ void smlTransportStop(SmlTransport *tsp) LIBSYNCML_DEPRECATED; /* expire date: 20090815 */ /* The function always returns NULL. * The function is not removed to protect the intergrity of the library. * Actually no user of this function is known. */ SmlLink *smlLinkFind(SmlTransport *tsp, void *link_data) LIBSYNCML_DEPRECATED; /* expire data: 20091223 */ #endif //_SML_TRANSPORT_H_ libsyncml-0.5.4/libsyncml/sml_notification_internals.h100644 1750 1750 3364 11211710410 23214 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2005 Armin Bauer * Copyright (C) 2007-2008 Michael Bell * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ /** * @defgroup SmlNotificationPrivate SyncML Notifications Internals * @ingroup PrivateLowLevelAPI * @brief The private part * */ /*@{*/ #ifndef _SML_NOTIFICATION_INTERNALS_H_ #define _SML_NOTIFICATION_INTERNALS_H_ struct SmlNotification { SmlNotificationVersion version; SmlNotificationUIMode mode; SmlNotificationInitiator init; unsigned int sessionID; char *identifier; SmlLocation *target; GList *alerts; SmlMimeType type; SmlCred *cred; SmlSessionType sessionType; SmlManager *manager; unsigned int localMaxMsgSize; unsigned int localMaxObjSize; }; struct SmlSanAlert { SmlAlertType type; char *contenttype; char *serverURI; }; SmlBool smlNotificationAssemble11( SmlNotification *san, char **data, unsigned int *size, SmlProtocolVersion version, SmlError **error); #endif //_SML_NOTIFICATION_INTERNALS_H_ /*@{*/ libsyncml-0.5.4/libsyncml/sml_manager_internals.h100644 1750 1750 4405 11211710410 22135 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2005 Armin Bauer * Copyright (C) 2008 Michael Bell * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ /** * @defgroup SmlManagerPrivate SyncML Manager Internals * @ingroup PrivateLowLevelAPI * @brief The private part * */ /*@{*/ #ifndef _SML_MANAGER_INTERNALS_H #define _SML_MANAGER_INTERNALS_H #include "sml_queue_internals.h" struct SmlManager { SmlTransport *transport; GList *sessions; SmlManagerEventCb eventCallback; void *eventCallbackUserdata; SmlHeaderCb headerCallback; SmlStatusReplyCb headerStatusCallback; void *headerCallbackUserdata; GList *objects; GSourceFuncs *functions; SmlThread *thread; GMainContext *context; GSource *source; GCond *running; GMutex *running_mutex; SmlQueue *userEventQueue; unsigned int localMaxMsgSize; unsigned int localMaxObjSize; }; typedef struct SmlManagerEvent { SmlManagerEventType type; SmlSession *session; SmlCommand *command; SmlCommand *parent; SmlError *error; } SmlManagerEvent; struct SmlObject { SmlCommandType type; SmlLocation *location; SmlLocation *source; SmlCommandCb commandCallback; SmlCommandCb childCallback; void *commandCallbackUserdata; char *contentType; }; void smlManagerSessionFinalLockRef(SmlManager *manager, SmlSession *session); void smlManagerSessionFinalLockUnref(SmlManager *manager, SmlSession *session); SmlLink *smlManagerSessionGetLink( SmlManager *manager, SmlSession *session, SmlError **error); #endif //_SML_MANAGER_INTERNALS_H /*@}*/ libsyncml-0.5.4/libsyncml/sml_command_internals.h100644 1750 1750 5655 11211710410 22151 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2005 Armin Bauer * Copyright (C) 2008 Michael Bell * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ /** * @defgroup SmlCommandPrivate SyncML Command Internals * @ingroup PrivateLowLevelAPI * @brief The private part * */ /*@{*/ #ifndef _SML_COMMAND_INTERNALS_H_ #define _SML_COMMAND_INTERNALS_H_ typedef struct SmlCommandAlertPrivate { SmlAlertType type; SmlAnchor *anchor; char *contentType; int maxObjSize; } SmlCommandAlertPrivate; typedef struct SmlCommandSyncPrivate { unsigned int numChanged; int maxObjSize; SmlBool hasNumChanged; } SmlCommandSyncPrivate; typedef struct SmlCommandAccessPrivate { char *type; SmlItem *item; } SmlCommandAccessPrivate; typedef struct SmlCommandChangePrivate { GList *items; SmlChangeType type; } SmlCommandChangePrivate; typedef struct SmlCommandMapPrivate { GList *items; } SmlCommandMapPrivate; typedef struct SmlCommandResultsPrivate { SmlStatus *status; } SmlCommandResultsPrivate; typedef union SmlCommandPrivate { SmlCommandAlertPrivate alert; SmlCommandSyncPrivate sync; SmlCommandAccessPrivate access; SmlCommandChangePrivate change; SmlCommandMapPrivate map; SmlCommandResultsPrivate results; } SmlCommandPrivate; struct SmlCommand { gint refCount; SmlCommandType type; unsigned int cmdID; unsigned int msgID; SmlCommandPrivate private; SmlLocation *source; SmlLocation *target; SmlPendingStatus *pendingReply; GList *children; SmlCommand *parent; SmlBool noResp; unsigned int size; /** True if the command has already seen a mismatch * in size. If a second mismatch happens, the command is * simply too large */ SmlBool pushedBack; }; struct SmlStatus { gint refCount; unsigned int msgRef; unsigned int cmdRef; SmlCommandType type; char *data; SmlAnchor *anchor; SmlLocation *sourceRef; SmlLocation *targetRef; SmlCred *cred; SmlChal *chal; SmlItem *item; SmlCommand *result; }; SmlCommandType smlCommandTypeFromString(const char *name, SmlError **error); const char *smlCommandTypeToString(SmlCommandType type, SmlError **error); SmlAlertType smlAlertTypeConvert(unsigned int id, SmlError **error); #endif //_SML_COMMAND_INTERNALS_H_ /*@}*/ libsyncml-0.5.4/libsyncml/sml_session.h100644 1750 1750 13354 11211710410 20152 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2005 Armin Bauer * Copyright (C) 2007-2008 Michael Bell * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #ifndef _SML_SESSION_H_ #define _SML_SESSION_H_ typedef enum SmlSessionType { SML_SESSION_TYPE_SERVER, SML_SESSION_TYPE_CLIENT } SmlSessionType; typedef enum SmlSessionEventType { SML_SESSION_EVENT_ERROR, SML_SESSION_EVENT_COMMAND_START, SML_SESSION_EVENT_CHILD_COMMAND, SML_SESSION_EVENT_HEADER_REPLY, SML_SESSION_EVENT_FINAL, SML_SESSION_EVENT_END, SML_SESSION_EVENT_FLUSH, SML_SESSION_EVENT_COMMAND_END, SML_SESSION_EVENT_RESPONSE_URI, SML_SESSION_EVENT_ESTABLISHED, } SmlSessionEventType; typedef void (* SmlSessionEventCallback) (SmlSession *session, SmlSessionEventType type, SmlCommand *command, SmlCommand *parent, SmlStatus *reply, SmlError *error, void *userdata); typedef void (* SmlSessionDataCallback) (SmlSession *session, SmlTransportData *data, void *userdata); /* Session Management */ SmlSession *smlSessionNew(SmlSessionType sessionType, SmlMimeType mimetype, SmlProtocolVersion version, SmlProtocolType protocol, SmlLocation *target, SmlLocation *source, const char *sessionID, unsigned int messageID, SmlError **error); SmlSession *smlSessionRef(SmlSession *session); void smlSessionUnref(SmlSession *session); void smlSessionSetEventCallback(SmlSession *session, SmlSessionEventCallback callback, void *userdata); void smlSessionSetDataCallback(SmlSession *session, SmlSessionDataCallback callback, void *userdata); /* Session Control */ SmlBool smlSessionFlush(SmlSession *session, SmlBool final, SmlError **error); SmlBool smlSessionEnd(SmlSession *session, SmlError **error); void smlSessionUseStringTable(SmlSession *session, SmlBool useStringtable); void smlSessionUseOnlyReplace(SmlSession *session, SmlBool onlyReplace); void smlSessionUseNumberOfChanges(SmlSession *session, SmlBool support); void smlSessionUseLargeObjects(SmlSession *session, SmlBool support); void smlSessionSetRemoteMaxMsgSize(SmlSession *session, unsigned int size); void smlSessionSetLocalMaxMsgSize(SmlSession *session, unsigned int size); unsigned int smlSessionGetRemoteMaxMsgSize(SmlSession *session); unsigned int smlSessionGetLocalMaxMsgSize(SmlSession *session); void smlSessionSetLocalMaxObjSize(SmlSession *session, unsigned int limit); void smlSessionSetRemoteMaxObjSize(SmlSession *session, unsigned int limit); unsigned int smlSessionGetLocalMaxObjSize(SmlSession *session); unsigned int smlSessionGetRemoteMaxObjSize(SmlSession *session); const char *smlSessionGetSessionID(SmlSession *session); void smlSessionSetSessionID(SmlSession *session, const char *sessionID); SmlProtocolVersion smlSessionGetVersion(SmlSession *session); void smlSessionDispatchEvent(SmlSession *session, SmlSessionEventType type, SmlCommand *cmd, SmlCommand *parent, SmlStatus *headerreply, SmlError *error); SmlLocation *smlSessionGetSource(SmlSession *session); SmlLocation *smlSessionGetTarget(SmlSession *session); /* This function MUST NOT be used for servers. * This function is only used to set the credentials for a client. */ void smlSessionRegisterCred(SmlSession *session, SmlCred *cred); /* Session Data input */ SmlBool smlSessionReceiveHeader(SmlSession *session, SmlHeader *header, SmlError **error); SmlBool smlSessionReceiveBody(SmlSession *session, SmlParser *parser, SmlError **error); /* Session Command input */ SmlBool smlSessionSendCommand(SmlSession *session, SmlCommand *cmd, SmlCommand *parent, SmlStatusReplyCb callback, void *userdata, SmlError **error); SmlBool smlSessionStartCommand(SmlSession *session, SmlCommand *cmd, SmlCommand *parent, SmlStatusReplyCb callback, void *userdata, SmlError **error); SmlBool smlSessionEndCommand(SmlSession *session, SmlCommand *parent, SmlError **error); SmlBool smlSessionSendReply(SmlSession *session, SmlStatus *status, SmlError **error); SmlBool smlSessionCheck(SmlSession *session); void smlSessionDispatch(SmlSession *session); /* expire date: 20090120 */ void smlSessionSetSendingLimit(SmlSession *session, unsigned int limit) LIBSYNCML_DEPRECATED; void smlSessionSetReceivingLimit(SmlSession *session, unsigned int limit) LIBSYNCML_DEPRECATED; unsigned int smlSessionGetSendingLimit(SmlSession *session) LIBSYNCML_DEPRECATED; /* expire date: 20090626 */ void smlSessionSetSendingMaxMsgSize(SmlSession *session, unsigned int size) LIBSYNCML_DEPRECATED; void smlSessionSetReceivingMaxMsgSize(SmlSession *session, unsigned int size) LIBSYNCML_DEPRECATED; unsigned int smlSessionGetSendingMaxMsgSize(SmlSession *session) LIBSYNCML_DEPRECATED; /* expire date: 20090626 */ void smlSessionSetSendingMaxObjSize(SmlSession *session, int limit) LIBSYNCML_DEPRECATED; void smlSessionSetRequestedMaxObjSize(SmlSession *session, int limit) LIBSYNCML_DEPRECATED; int smlSessionGetSendingMaxObjSize(SmlSession *session) LIBSYNCML_DEPRECATED; void smlSessionSetReceivingMaxObjSize(SmlSession *session, unsigned int limit) LIBSYNCML_DEPRECATED; unsigned int smlSessionGetReceivingMaxObjSize(SmlSession *session) LIBSYNCML_DEPRECATED; #endif //_SML_SESSION_H_ libsyncml-0.5.4/libsyncml/sml_devinf.c100644 1750 1750 123163 11211710410 17755 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2005 Armin Bauer * Copyright (C) 2007-2008 Michael Bell * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include "syncml.h" #include "syncml_internals.h" #include "sml_devinf_internals.h" #include "sml_command_internals.h" #include "sml_elements_internals.h" #include "sml_parse_internals.h" #include "parser/sml_xml_assm.h" #include "parser/sml_xml_parse.h" #include "sml_error_internals.h" SmlDevInfDevTyp smlDevInfDevTypeFromString(const char *name, SmlError **error) { CHECK_ERROR_REF if (!strcmp(name, SML_ELEMENT_DEVTYP_PAGER)) { return SML_DEVINF_DEVTYPE_PAGER; } else if (!strcmp(name, SML_ELEMENT_DEVTYP_HANDHELD)) { return SML_DEVINF_DEVTYPE_HANDHELD; } else if (!strcmp(name, SML_ELEMENT_DEVTYP_PDA)) { return SML_DEVINF_DEVTYPE_PDA; } else if (!strcmp(name, SML_ELEMENT_DEVTYP_PHONE)) { return SML_DEVINF_DEVTYPE_PHONE; } else if (!strcmp(name, SML_ELEMENT_DEVTYP_SMARTPHONE)) { return SML_DEVINF_DEVTYPE_SMARTPHONE; } else if (!strcmp(name, SML_ELEMENT_DEVTYP_SERVER)) { return SML_DEVINF_DEVTYPE_SERVER; } else if (!strcmp(name, SML_ELEMENT_DEVTYP_WORKSTATION)) { return SML_DEVINF_DEVTYPE_WORKSTATION; } smlErrorSet(error, SML_ERROR_GENERIC, "Unknown devinf type name \"%s\"", name); return SML_DEVINF_DEVTYPE_UNKNOWN; } const char *smlDevInfDevTypeToString(SmlDevInfDevTyp type, SmlError **error) { CHECK_ERROR_REF switch (type) { case SML_DEVINF_DEVTYPE_PAGER: return SML_ELEMENT_DEVTYP_PAGER; case SML_DEVINF_DEVTYPE_HANDHELD: return SML_ELEMENT_DEVTYP_HANDHELD; case SML_DEVINF_DEVTYPE_PDA: return SML_ELEMENT_DEVTYP_PDA; case SML_DEVINF_DEVTYPE_PHONE: return SML_ELEMENT_DEVTYP_PHONE; case SML_DEVINF_DEVTYPE_SMARTPHONE: return SML_ELEMENT_DEVTYP_SMARTPHONE; case SML_DEVINF_DEVTYPE_SERVER: return SML_ELEMENT_DEVTYP_SERVER; case SML_DEVINF_DEVTYPE_WORKSTATION: return SML_ELEMENT_DEVTYP_WORKSTATION; case SML_DEVINF_DEVTYPE_UNKNOWN: smlErrorSet(error, SML_ERROR_GENERIC, "Unknown devinf type \"%i\"", type); /* fall through! */ } return NULL; } SmlDevInf *smlDevInfNew(const char *devid, SmlDevInfDevTyp devtyp, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%s, %i, %p)", __func__, VA_STRING(devid), devtyp, error); CHECK_ERROR_REF smlAssert(devid); SmlDevInf *devinf = smlTryMalloc0(sizeof(SmlDevInf), error); if (!devinf) goto error; devinf->devid = g_strdup(devid); devinf->devtyp = devtyp; devinf->refCount = 1; smlTrace(TRACE_EXIT, "%s: %p", __func__, devinf); return devinf; error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return NULL; } SmlDevInf *smlDevInfRef(SmlDevInf *devinf) { smlTrace(TRACE_ENTRY, "%s(%p)", __func__, devinf); smlAssert(devinf); g_atomic_int_inc(&(devinf->refCount)); smlTrace(TRACE_EXIT, "%s: New refcount: %i", __func__, devinf->refCount); return devinf; } void smlDevInfUnref(SmlDevInf *devinf) { smlTrace(TRACE_ENTRY, "%s(%p)", __func__, devinf); smlAssert(devinf); if (g_atomic_int_dec_and_test(&(devinf->refCount))) { smlTrace(TRACE_INTERNAL, "%s: Refcount == 0!", __func__); if (devinf->manufacturer) smlSafeCFree(&(devinf->manufacturer)); if (devinf->model) smlSafeCFree(&(devinf->model)); if (devinf->oem) smlSafeCFree(&(devinf->oem)); if (devinf->softwareVersion) smlSafeCFree(&(devinf->softwareVersion)); if (devinf->hardwareVersion) smlSafeCFree(&(devinf->hardwareVersion)); if (devinf->firmwareVersion) smlSafeCFree(&(devinf->firmwareVersion)); if (devinf->devid) smlSafeCFree(&(devinf->devid)); while (devinf->datastores) { SmlDevInfDataStore *store = devinf->datastores->data; devinf->datastores = g_list_remove(devinf->datastores, store); smlDevInfDataStoreUnref(store); } while (devinf->ctcaps) { SmlDevInfCTCap *ctcap = devinf->ctcaps->data; devinf->ctcaps = g_list_remove(devinf->ctcaps, ctcap); smlSafeCFree(&(ctcap->ct->cttype)); if (ctcap->ct->verct) smlSafeCFree(&(ctcap->ct->verct)); smlSafeFree((gpointer *)&(ctcap->ct)); while (ctcap->properties) { SmlDevInfProperty *prop = ctcap->properties->data; ctcap->properties = g_list_remove(ctcap->properties, prop); smlSafeCFree(&(prop->propName)); if (prop->dataType) smlSafeCFree(&(prop->dataType)); if (prop->displayName) smlSafeCFree(&(prop->displayName)); /* if lists are removed * then the data must be removed separately */ while (prop->valEnums) { char *valEnum = prop->valEnums->data; prop->valEnums = g_list_remove(prop->valEnums, valEnum); smlSafeCFree(&valEnum); } while (prop->propParams) { SmlDevInfPropParam *param = prop->propParams->data; prop->propParams = g_list_remove(prop->propParams, param); smlSafeCFree(&(param->paramName)); if (param->dataType) smlSafeCFree(&(param->dataType)); if (param->displayName) smlSafeCFree(&(param->displayName)); /* if lists are removed * then the data must be removed separately */ while (param->valEnums) { char *valEnum = param->valEnums->data; param->valEnums = g_list_remove(param->valEnums, valEnum); smlSafeCFree(&valEnum); } /* free PropParam itself */ smlSafeFree((gpointer *) ¶m); } /* free Property itself */ smlSafeFree((gpointer *) &prop); } /* don't use ctcap here because the list must be cleaned up */ smlSafeFree((gpointer *)&ctcap); } smlSafeFree((gpointer *)&devinf); } smlTrace(TRACE_EXIT, "%s", __func__); } const char *smlDevInfGetManufacturer(SmlDevInf *devinf) { return devinf->manufacturer; } void smlDevInfSetManufacturer(SmlDevInf *devinf, const char *man) { if (devinf->manufacturer) smlSafeCFree(&(devinf->manufacturer)); devinf->manufacturer = g_strdup(man); } const char *smlDevInfGetModel(SmlDevInf *devinf) { return devinf->model; } void smlDevInfSetModel(SmlDevInf *devinf, const char *model) { if (devinf->model) smlSafeCFree(&(devinf->model)); devinf->model = g_strdup(model); } const char *smlDevInfGetOEM(SmlDevInf *devinf) { return devinf->oem; } void smlDevInfSetOEM(SmlDevInf *devinf, const char *oem) { if (devinf->oem) smlSafeCFree(&(devinf->oem)); devinf->oem = g_strdup(oem); } const char *smlDevInfGetFirmwareVersion(SmlDevInf *devinf) { return devinf->firmwareVersion; } void smlDevInfSetFirmwareVersion(SmlDevInf *devinf, const char *firmwareVersion) { if (devinf->firmwareVersion) smlSafeCFree(&(devinf->firmwareVersion)); devinf->firmwareVersion = g_strdup(firmwareVersion); } const char *smlDevInfGetSoftwareVersion(SmlDevInf *devinf) { return devinf->softwareVersion; } void smlDevInfSetSoftwareVersion(SmlDevInf *devinf, const char *softwareVersion) { if (devinf->softwareVersion) smlSafeCFree(&(devinf->softwareVersion)); devinf->softwareVersion = g_strdup(softwareVersion); } const char *smlDevInfGetHardwareVersion(SmlDevInf *devinf) { return devinf->hardwareVersion; } void smlDevInfSetHardwareVersion(SmlDevInf *devinf, const char *hardwareVersion) { if (devinf->hardwareVersion) smlSafeCFree(&(devinf->hardwareVersion)); devinf->hardwareVersion = g_strdup(hardwareVersion); } const char *smlDevInfGetDeviceID(SmlDevInf *devinf) { return devinf->devid; } void smlDevInfSetDeviceID(SmlDevInf *devinf, const char *devid) { if (devinf->devid) smlSafeCFree(&(devinf->devid)); devinf->devid = g_strdup(devid); } SmlDevInfDevTyp smlDevInfGetDeviceType(SmlDevInf *devinf) { return devinf->devtyp; } void smlDevInfSetDeviceType(SmlDevInf *devinf, SmlDevInfDevTyp devtyp) { devinf->devtyp = devtyp; } SmlBool smlDevInfSupportsUTC(SmlDevInf *devinf) { return devinf->supportsUTC; } void smlDevInfSetSupportsUTC(SmlDevInf *devinf, SmlBool supports) { devinf->supportsUTC = supports; } SmlBool smlDevInfSupportsLargeObjs(SmlDevInf *devinf) { return devinf->supportsLargeObjs; } void smlDevInfSetSupportsLargeObjs(SmlDevInf *devinf, SmlBool supports) { devinf->supportsLargeObjs = supports; } SmlBool smlDevInfSupportsNumberOfChanges(SmlDevInf *devinf) { return devinf->supportsNumberOfChanges; } void smlDevInfSetSupportsNumberOfChanges(SmlDevInf *devinf, SmlBool supports) { devinf->supportsNumberOfChanges = supports; } void smlDevInfAddDataStore(SmlDevInf *devinf, SmlDevInfDataStore *datastore) { smlTrace(TRACE_ENTRY, "%s(%p, %p)", __func__, devinf, datastore); smlAssert(devinf); smlAssert(datastore); devinf->datastores = g_list_append(devinf->datastores, datastore); smlTrace(TRACE_EXIT, "%s", __func__); } unsigned int smlDevInfNumDataStores(SmlDevInf *devinf) { smlAssert(devinf); return g_list_length(devinf->datastores); } const SmlDevInfDataStore *smlDevInfGetNthDataStore(const SmlDevInf *devinf, unsigned int nth) { smlAssert(devinf); return g_list_nth_data(devinf->datastores, nth); } SmlDevInfDataStore *smlDevInfDataStoreNew(const char *sourceRef, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p)", __func__, sourceRef, error); CHECK_ERROR_REF SmlDevInfDataStore *datastore = smlTryMalloc0(sizeof(SmlDevInfDataStore), error); if (!datastore) goto error; datastore->sourceref = g_strdup(sourceRef); datastore->refCount = 1; smlTrace(TRACE_EXIT, "%s: %p", __func__, datastore); return datastore; error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return NULL; } SmlDevInfDataStore *smlDevInfDataStoreRef(SmlDevInfDataStore *datastore) { smlTrace(TRACE_ENTRY, "%s(%p)", __func__, datastore); smlAssert(datastore); g_atomic_int_inc(&(datastore->refCount)); smlTrace(TRACE_EXIT, "%s: New refcount: %i", __func__, datastore->refCount); return datastore; } void smlDevInfDataStoreUnref(SmlDevInfDataStore *datastore) { smlTrace(TRACE_ENTRY, "%s(%p)", __func__, datastore); smlAssert(datastore); if (g_atomic_int_dec_and_test(&(datastore->refCount))) { smlTrace(TRACE_INTERNAL, "%s: Refcount == 0!", __func__); smlSafeCFree(&(datastore->sourceref)); if (datastore->displayname) smlSafeCFree(&(datastore->displayname)); smlSafeCFree(&(datastore->rxPrefContentType)); smlSafeCFree(&(datastore->rxPrefVersion)); GList *d = NULL; for (d = datastore->rx; d; d = d->next) { SmlDevInfContentType *ct = d->data; smlDevInfFreeContentType(ct); } g_list_free(datastore->rx); smlSafeCFree(&(datastore->txPrefContentType)); smlSafeCFree(&(datastore->txPrefVersion)); for (d = datastore->tx; d; d = d->next) { SmlDevInfContentType *ct = d->data; smlDevInfFreeContentType(ct); } g_list_free(datastore->tx); smlSafeFree((gpointer *)&datastore); } smlTrace(TRACE_EXIT, "%s", __func__); } const char *smlDevInfDataStoreGetSourceRef(const SmlDevInfDataStore *datastore) { return datastore->sourceref; } void smlDevInfDataStoreSetSourceRef(SmlDevInfDataStore *datastore, const char *sourceref) { if (datastore->sourceref) smlSafeCFree(&(datastore->sourceref)); datastore->sourceref = g_strdup(sourceref); } const char *smlDevInfDataStoreGetDisplayName(const SmlDevInfDataStore *datastore) { return datastore->displayname; } void smlDevInfDataStoreSetDisplayName(SmlDevInfDataStore *datastore, const char *displayName) { if (datastore->displayname) smlSafeCFree(&(datastore->displayname)); datastore->displayname = g_strdup(displayName); } unsigned int smlDevInfGetMaxGUIDSize(const SmlDevInfDataStore *datastore) { return datastore->maxGUIDSize; } void smlDevInfSetMaxGUIDSize(SmlDevInfDataStore *datastore, unsigned int max) { datastore->maxGUIDSize = max; } void smlDevInfDataStoreSetRxPref(SmlDevInfDataStore *datastore, const char *contenttype, const char *version) { if (datastore->rxPrefContentType) smlSafeCFree(&(datastore->rxPrefContentType)); datastore->rxPrefContentType = g_strdup(contenttype); if (datastore->rxPrefVersion) smlSafeCFree(&(datastore->rxPrefVersion)); datastore->rxPrefVersion = g_strdup(version); } SmlBool smlDevInfDataStoreGetRxPref(const SmlDevInfDataStore *datastore, char **contenttype, char **version) { if (!datastore->rxPrefContentType) return FALSE; *contenttype = datastore->rxPrefContentType; *version = datastore->rxPrefVersion; return TRUE; } /* FIXME: DEPRECATED*/ void smlDevInfDataStoreSetRx(SmlDevInfDataStore *datastore, const char *contenttype, const char *version) { SmlError *error = NULL; SmlDevInfContentType *ct = smlDevInfNewContentType(contenttype, version, &error); if (!ct) { smlTrace(TRACE_ERROR, "%s - %s", __func__, smlErrorPrint(&error)); smlErrorDeref(&error); return; } smlDevInfDataStoreAddRx(datastore, ct); } /* FIXME: DEPRECATED*/ SmlBool smlDevInfDataStoreGetRx(const SmlDevInfDataStore *datastore, char **contenttype, char **version) { const SmlDevInfContentType *ct = smlDevInfDataStoreGetNthRx(datastore, 0); if (!ct) return FALSE; *contenttype = smlDevInfContentTypeGetCTType(ct); *version = smlDevInfContentTypeGetVerCT(ct); return TRUE; } void smlDevInfDataStoreAddRx(SmlDevInfDataStore *datastore, SmlDevInfContentType *ct) { smlAssert(datastore); datastore->rx = g_list_append(datastore->rx, ct); } unsigned int smlDevInfDataStoreNumRx(const SmlDevInfDataStore *datastore) { return g_list_length(datastore->rx); } const SmlDevInfContentType *smlDevInfDataStoreGetNthRx( const SmlDevInfDataStore *datastore, unsigned int n) { return g_list_nth_data(datastore->rx, n); } void smlDevInfDataStoreSetTxPref(SmlDevInfDataStore *datastore, const char *contenttype, const char *version) { if (datastore->txPrefContentType) smlSafeCFree(&(datastore->txPrefContentType)); datastore->txPrefContentType = g_strdup(contenttype); if (datastore->txPrefVersion) smlSafeCFree(&(datastore->txPrefVersion)); datastore->txPrefVersion = g_strdup(version); } SmlBool smlDevInfDataStoreGetTxPref(const SmlDevInfDataStore *datastore, char **contenttype, char **version) { if (!datastore->txPrefContentType) return FALSE; *contenttype = datastore->txPrefContentType; *version = datastore->txPrefVersion; return TRUE; } /* FIXME: DEPRECATED*/ void smlDevInfDataStoreSetTx(SmlDevInfDataStore *datastore, const char *contenttype, const char *version) { SmlError *error = NULL; SmlDevInfContentType *ct = smlDevInfNewContentType(contenttype, version, &error); if (!ct) { smlTrace(TRACE_ERROR, "%s - %s", __func__, smlErrorPrint(&error)); smlErrorDeref(&error); return; } smlDevInfDataStoreAddTx(datastore, ct); } /* FIXME: DEPRECATED*/ SmlBool smlDevInfDataStoreGetTx(const SmlDevInfDataStore *datastore, char **contenttype, char **version) { const SmlDevInfContentType *ct = smlDevInfDataStoreGetNthRx(datastore, 0); if (!ct) return FALSE; *contenttype = smlDevInfContentTypeGetCTType(ct); *version = smlDevInfContentTypeGetVerCT(ct); return TRUE; } void smlDevInfDataStoreAddTx(SmlDevInfDataStore *datastore, SmlDevInfContentType *ct) { smlAssert(datastore); datastore->tx = g_list_append(datastore->tx, ct); } unsigned int smlDevInfDataStoreNumTx(const SmlDevInfDataStore *datastore) { return g_list_length(datastore->tx); } const SmlDevInfContentType *smlDevInfDataStoreGetNthTx( const SmlDevInfDataStore *datastore, unsigned int n) { return g_list_nth_data(datastore->tx, n); } void smlDevInfDataStoreSetMemory(SmlDevInfDataStore *datastore, SmlBool shared, unsigned int maxid, unsigned int maxmem) { datastore->sharedMem = shared; datastore->maxid = maxid; datastore->maxmem = maxmem; } void smlDevInfDataStoreGetMemory(const SmlDevInfDataStore *datastore, SmlBool *shared, unsigned int *maxid, unsigned int *maxmem) { if (shared) *shared = datastore->sharedMem; if (maxid) *maxid = datastore->maxid; if (maxmem) *maxmem = datastore->maxmem; } void smlDevInfDataStoreSetSyncCap(SmlDevInfDataStore *datastore, SmlDevInfSyncCap cap, SmlBool supported) { if (supported) datastore->synccap = datastore->synccap | cap; else datastore->synccap = datastore->synccap & ~cap; } SmlBool smlDevInfDataStoreGetSyncCap(const SmlDevInfDataStore *datastore, SmlDevInfSyncCap cap) { return datastore->synccap & cap ? TRUE : FALSE; } void smlDevInfConfigureSession(SmlDevInf *devinf, SmlSession *session) { smlTrace(TRACE_ENTRY, "%s(%p, %p)", __func__, devinf, session); smlAssert(devinf); smlAssert(session); if (!devinf->supportsNumberOfChanges) smlSessionUseNumberOfChanges(session, FALSE); if (!devinf->supportsLargeObjs) smlSessionUseLargeObjects(session, FALSE); smlTrace(TRACE_EXIT, "%s", __func__); } SmlBool smlDevInfAssemble(SmlDevInf *devinf, char **data, unsigned int *size, SmlError **error) { CHECK_ERROR_REF return smlXmlDevInfAssemble(devinf, devinf->version, data, size, error); } SmlCommand *smlDevInfNewResult(SmlCommand *cmd, SmlDevInf *devinf, SmlDevInfVersion version, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %i, %p, %p)", __func__, cmd, devinf, version, error); CHECK_ERROR_REF smlAssert(cmd); SmlLocation *source = NULL; char *data = NULL; unsigned int size = 0; if (!smlXmlDevInfAssemble(devinf, version, &data, &size, error)) goto error; if (version == SML_DEVINF_VERSION_10) source = smlLocationNew("./devinf10", NULL, error); else if (version == SML_DEVINF_VERSION_12) source = smlLocationNew("./devinf12", NULL, error); else source = smlLocationNew("./devinf11", NULL, error); if (!source) goto error_free_data; SmlCommand *result = smlCommandNewResult(cmd, source, data, size, SML_ELEMENT_DEVINF_XML, error); if (!result) { smlLocationUnref(source); goto error_free_data; } /* Since the devinf is xml, we want to send it "raw" (without cdata) */ result->private.results.status->item->raw = TRUE; smlLocationUnref(source); smlTrace(TRACE_EXIT, "%s: %p", __func__, result); return result; error_free_data: smlSafeCFree(&data); error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return NULL; } SmlCommand *smlDevInfNewPut(SmlDevInf *devinf, SmlDevInfVersion version, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %i, %p)", __func__, devinf, version, error); CHECK_ERROR_REF smlAssert(devinf); SmlLocation *source = NULL; // update version if (devinf->version == SML_DEVINF_VERSION_UNKNOWN) devinf->version = version; if (version == SML_DEVINF_VERSION_10) source = smlLocationNew("./devinf10", NULL, error); else if (version == SML_DEVINF_VERSION_12) source = smlLocationNew("./devinf12", NULL, error); else source = smlLocationNew("./devinf11", NULL, error); if (!source) goto error; SmlCommand *cmd = smlCommandNewPut(NULL, source, NULL, 0, SML_ELEMENT_DEVINF_XML, error); if (!cmd) goto error_free_source; smlLocationUnref(source); char *data = NULL; unsigned int size = 0; if (!smlXmlDevInfAssemble(devinf, version, &data, &size, error)) goto error_free_cmd; if (!smlItemAddData(cmd->private.access.item, data, size, error)) { smlSafeCFree(&data); goto error_free_cmd; } smlSafeCFree(&data); smlItemSetRaw(cmd->private.access.item, TRUE); smlTrace(TRACE_EXIT, "%s: %p", __func__, cmd); return cmd; error_free_cmd: smlCommandUnref(cmd); error_free_source: smlLocationUnref(source); error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return NULL; } SmlCommand *smlDevInfNewGet(SmlDevInfVersion version, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%i, %p)", __func__, version, error); CHECK_ERROR_REF SmlLocation *target = NULL; if (version == SML_DEVINF_VERSION_10) target = smlLocationNew("./devinf10", NULL, error); else if (version == SML_DEVINF_VERSION_12) target = smlLocationNew("./devinf12", NULL, error); else target = smlLocationNew("./devinf11", NULL, error); if (!target) goto error; SmlCommand *cmd = smlCommandNewGet(target, SML_ELEMENT_DEVINF_XML, error); if (!cmd) goto error_free_target; smlLocationUnref(target); smlTrace(TRACE_EXIT, "%s: %p", __func__, cmd); return cmd; error_free_target: smlLocationUnref(target); error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return NULL; } SmlDevInf *smlDevInfParse(const char *data, unsigned int length, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %i, %p)", __func__, data, length, error); CHECK_ERROR_REF smlAssert(data); smlAssert(length); SmlDevInf *devinf = smlXmlDevInfParse(data, length, error); if (!devinf) goto error; smlTrace(TRACE_EXIT, "%s", __func__); return devinf; error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return NULL; } SmlDevInf *smlDevInfFromResult(SmlCommand *result, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p)", __func__, result, error); CHECK_ERROR_REF smlAssert(result); if (result->type != SML_COMMAND_TYPE_RESULTS) { smlErrorSet(error, SML_ERROR_GENERIC, "devinf command was not a result"); goto error; } SmlItem *item = result->private.results.status->item; if (!item) { smlErrorSet(error, SML_ERROR_GENERIC, "devinf result did not have a item"); goto error; } char *data = NULL; unsigned int size = 0; if (!smlItemGetData(item, &data, &size, error)) goto error; SmlDevInf *devinf = smlDevInfParse(data, size, error); if (!devinf) goto error; smlTrace(TRACE_EXIT, "%s", __func__); return devinf; error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return NULL; } SmlDevInfCTCapType smlDevInfCTCapTypeFromString(const char *name, SmlError **error) { CHECK_ERROR_REF if (!strcmp(name, SML_ELEMENT_CTTYPE)) { return SML_DEVINF_CTCAP_CTTYPE; } else if (!strcmp(name, SML_ELEMENT_PROPNAME)) { return SML_DEVINF_CTCAP_PROPNAME; } else if (!strcmp(name, SML_ELEMENT_VALENUM)) { return SML_DEVINF_CTCAP_VALENUM; } else if (!strcmp(name, SML_ELEMENT_DATATYPE)) { return SML_DEVINF_CTCAP_DATATYPE; } else if (!strcmp(name, SML_ELEMENT_SIZE)) { return SML_DEVINF_CTCAP_SIZE; } else if (!strcmp(name, SML_ELEMENT_DISPLAYNAME)) { return SML_DEVINF_CTCAP_DISPLAYNAME; } else if (!strcmp(name, SML_ELEMENT_PARAMNAME)) { return SML_DEVINF_CTCAP_PARAMNAME; } else if (!strcmp(name, SML_ELEMENT_VERCT)) { return SML_DEVINF_CTCAP_VERCT; } else if (!strcmp(name, SML_ELEMENT_PROPERTY)) { return SML_DEVINF_CTCAP_PROPERTY; } else if (!strcmp(name, SML_ELEMENT_PROPPARAM)) { return SML_DEVINF_CTCAP_PROPPARAM; } else if (!strcmp(name, SML_ELEMENT_NOTRUNCATE)) { return SML_DEVINF_CTCAP_NOTRUNCATE; } else if (!strcmp(name, SML_ELEMENT_MAXOCCUR)) { return SML_DEVINF_CTCAP_MAXOCCUR; } else if (!strcmp(name, SML_ELEMENT_MAXSIZE)) { return SML_DEVINF_CTCAP_MAXSIZE; } smlErrorSet(error, SML_ERROR_GENERIC, "Unknown ctcap type name \"%s\"", name); smlTrace(TRACE_ERROR, "%s - %s", __func__, smlErrorPrint(error)); return SML_DEVINF_CTCAP_UNKNOWN; } const char *smlDevInfCTCapTypeToString(SmlDevInfCTCapType type, SmlError **error) { CHECK_ERROR_REF switch (type) { case SML_DEVINF_CTCAP_CTTYPE: return SML_ELEMENT_CTTYPE; case SML_DEVINF_CTCAP_PROPNAME: return SML_ELEMENT_PROPNAME; case SML_DEVINF_CTCAP_VALENUM: return SML_ELEMENT_VALENUM; case SML_DEVINF_CTCAP_DATATYPE: return SML_ELEMENT_DATATYPE; case SML_DEVINF_CTCAP_SIZE: return SML_ELEMENT_SIZE; case SML_DEVINF_CTCAP_DISPLAYNAME: return SML_ELEMENT_DISPLAYNAME; case SML_DEVINF_CTCAP_PARAMNAME: return SML_ELEMENT_PARAMNAME; case SML_DEVINF_CTCAP_NOTRUNCATE: return SML_ELEMENT_NOTRUNCATE; case SML_DEVINF_CTCAP_MAXOCCUR: return SML_ELEMENT_MAXOCCUR; case SML_DEVINF_CTCAP_VERCT: return SML_ELEMENT_VERCT; case SML_DEVINF_CTCAP_PROPERTY: return SML_ELEMENT_PROPERTY; case SML_DEVINF_CTCAP_PROPPARAM: return SML_ELEMENT_PROPPARAM; case SML_DEVINF_CTCAP_MAXSIZE: return SML_ELEMENT_MAXSIZE; case SML_DEVINF_CTCAP_UNKNOWN: smlErrorSet(error, SML_ERROR_GENERIC, "Unknown ctcap type \"%i\"", type); /* fall through! */ } return NULL; } /* PropParam stuff */ SmlDevInfPropParam *smlDevInfNewPropParam(SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p)", __func__, error); CHECK_ERROR_REF SmlDevInfPropParam *param = smlTryMalloc0(sizeof(SmlDevInfPropParam), error); if (!param) { smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return NULL; } param->paramName = NULL; param->dataType = NULL; param->displayName = NULL; param->valEnums = NULL; smlTrace(TRACE_EXIT, "%s", __func__); return param; } void smlDevInfPropParamSetParamName( SmlDevInfPropParam *propParam, const char *paramName) { smlTrace(TRACE_ENTRY, "%s(%p, %s)", __func__, propParam, VA_STRING(paramName)); smlAssert(propParam); smlAssert(paramName); if (propParam->paramName != NULL) smlSafeCFree(&(propParam->paramName)); propParam->paramName = g_strdup(paramName); smlTrace(TRACE_EXIT, "%s", __func__); } void smlDevInfPropParamSetDataType( SmlDevInfPropParam *propParam, const char *dataType) { smlTrace(TRACE_ENTRY, "%s(%p, %s)", __func__, propParam, VA_STRING(dataType)); smlAssert(propParam); smlAssert(dataType); if (propParam->dataType != NULL) smlSafeCFree(&(propParam->dataType)); propParam->dataType = g_strdup(dataType); smlTrace(TRACE_EXIT, "%s", __func__); } void smlDevInfPropParamSetDisplayName( SmlDevInfPropParam *propParam, const char *displayName) { smlTrace(TRACE_ENTRY, "%s(%p, %s)", __func__, propParam, VA_STRING(displayName)); smlAssert(propParam); smlAssert(displayName); if (propParam->displayName != NULL) smlSafeCFree(&(propParam->displayName)); propParam->displayName = g_strdup(displayName); smlTrace(TRACE_EXIT, "%s", __func__); } void smlDevInfPropParamAddValEnum( SmlDevInfPropParam *propParam, const char *valEnum) { smlTrace(TRACE_ENTRY, "%s(%p, %s)", __func__, propParam, VA_STRING(valEnum)); smlAssert(propParam); smlAssert(valEnum); propParam->valEnums = g_list_append(propParam->valEnums, g_strdup(valEnum)); smlTrace(TRACE_EXIT, "%s", __func__); } char *smlDevInfPropParamGetParamName(const SmlDevInfPropParam *propParam) { smlTrace(TRACE_ENTRY, "%s(%p)", __func__, propParam); smlAssert(propParam); char *result = g_strdup(propParam->paramName); smlTrace(TRACE_EXIT, "%s - %s", __func__, VA_STRING(result)); return result; } char *smlDevInfPropParamGetDataType(const SmlDevInfPropParam *propParam) { smlTrace(TRACE_ENTRY, "%s(%p)", __func__, propParam); smlAssert(propParam); char *result = g_strdup(propParam->dataType); smlTrace(TRACE_EXIT, "%s - %s", __func__, VA_STRING(result)); return result; } char *smlDevInfPropParamGetDisplayName(const SmlDevInfPropParam *propParam) { smlTrace(TRACE_ENTRY, "%s(%p)", __func__, propParam); smlAssert(propParam); char *result = g_strdup(propParam->displayName); smlTrace(TRACE_EXIT, "%s - %s", __func__, VA_STRING(result)); return result; } unsigned int smlDevInfPropParamNumValEnums(const SmlDevInfPropParam *propParam) { smlTrace(TRACE_ENTRY, "%s(%p)", __func__, propParam); smlAssert(propParam); unsigned int num = g_list_length(propParam->valEnums); smlTrace(TRACE_EXIT, "%s - %d", __func__, num); return num; } char *smlDevInfPropParamGetNthValEnum( const SmlDevInfPropParam *propParam, unsigned int n) { smlTrace(TRACE_ENTRY, "%s(%p, %d)", __func__, propParam, n); smlAssert(propParam); char *result = g_strdup(g_list_nth_data(propParam->valEnums, n)); smlTrace(TRACE_EXIT, "%s - %s", __func__, VA_STRING(result)); return result; } /* Property stuff */ SmlDevInfProperty *smlDevInfNewProperty(SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p)", __func__, error); CHECK_ERROR_REF SmlDevInfProperty *property = smlTryMalloc0(sizeof(SmlDevInfProperty), error); if (!property) { smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return NULL; } property->propName = NULL; property->dataType = NULL; property->maxOccur = 0; property->maxSize = 0; property->noTruncate = FALSE; property->displayName = NULL; property->valEnums = NULL; property->propParams = NULL; smlTrace(TRACE_EXIT, "%s", __func__); return property; } void smlDevInfPropertySetPropName( SmlDevInfProperty *property, const char *propName) { smlTrace(TRACE_ENTRY, "%s(%p, %s)", __func__, property, VA_STRING(propName)); smlAssert(property); smlAssert(propName); if (property->propName != NULL) smlSafeCFree(&(property->propName)); property->propName = g_strdup(propName); smlTrace(TRACE_EXIT, "%s", __func__); } void smlDevInfPropertySetDataType( SmlDevInfProperty *property, const char *dataType) { smlTrace(TRACE_ENTRY, "%s(%p, %s)", __func__, property, VA_STRING(dataType)); smlAssert(property); smlAssert(dataType); if (property->dataType != NULL) smlSafeCFree(&(property->dataType)); property->dataType = g_strdup(dataType); smlTrace(TRACE_EXIT, "%s", __func__); } void smlDevInfPropertySetMaxOccur( SmlDevInfProperty *property, unsigned int maxOccur) { smlTrace(TRACE_ENTRY, "%s(%p, %d)", __func__, property, maxOccur); smlAssert(property); property->maxOccur = maxOccur; smlTrace(TRACE_EXIT, "%s", __func__); } void smlDevInfPropertySetMaxSize( SmlDevInfProperty *property, unsigned int maxSize) { smlTrace(TRACE_ENTRY, "%s(%p, %d)", __func__, property, maxSize); smlAssert(property); property->maxSize = maxSize; smlTrace(TRACE_EXIT, "%s", __func__); } void smlDevInfPropertySetPropSize( SmlDevInfProperty *property, unsigned int propSize) { smlTrace(TRACE_ENTRY, "%s(%p, %d)", __func__, property, propSize); smlAssert(property); property->propSize = propSize; smlTrace(TRACE_EXIT, "%s", __func__); } void smlDevInfPropertySetNoTruncate( SmlDevInfProperty *property) { smlTrace(TRACE_ENTRY, "%s(%p)", __func__, property); smlAssert(property); property->noTruncate = TRUE; smlTrace(TRACE_EXIT, "%s", __func__); } void smlDevInfPropertySetDisplayName( SmlDevInfProperty *property, const char *displayName) { smlTrace(TRACE_ENTRY, "%s(%p, %s)", __func__, property, VA_STRING(displayName)); smlAssert(property); smlAssert(displayName); if (property->displayName != NULL) smlSafeCFree(&(property->displayName)); property->displayName = g_strdup(displayName); smlTrace(TRACE_EXIT, "%s", __func__); } void smlDevInfPropertyAddValEnum( SmlDevInfProperty *property, const char *valEnum) { smlTrace(TRACE_ENTRY, "%s(%p, %s)", __func__, property, VA_STRING(valEnum)); smlAssert(property); smlAssert(valEnum); property->valEnums = g_list_append(property->valEnums, g_strdup(valEnum)); smlTrace(TRACE_EXIT, "%s", __func__); } void smlDevInfPropertyAddPropParam( SmlDevInfProperty *property, SmlDevInfPropParam *propParam) { smlTrace(TRACE_ENTRY, "%s(%p, %p)", __func__, property, propParam); smlAssert(property); smlAssert(propParam); property->propParams = g_list_append(property->propParams, propParam); smlTrace(TRACE_EXIT, "%s", __func__); } char *smlDevInfPropertyGetPropName(const SmlDevInfProperty *property) { smlTrace(TRACE_ENTRY, "%s(%p)", __func__, property); smlAssert(property); char *result = g_strdup(property->propName); smlTrace(TRACE_EXIT, "%s - %s", __func__, VA_STRING(result)); return result; } char *smlDevInfPropertyGetDataType(const SmlDevInfProperty *property) { smlTrace(TRACE_ENTRY, "%s(%p)", __func__, property); smlAssert(property); char *result = g_strdup(property->dataType); smlTrace(TRACE_EXIT, "%s - %s", __func__, VA_STRING(result)); return result; } unsigned int smlDevInfPropertyGetMaxOccur(const SmlDevInfProperty *property) { smlTrace(TRACE_ENTRY, "%s(%p)", __func__, property); smlAssert(property); smlTrace(TRACE_EXIT, "%s - %d", __func__, property->maxOccur); return property->maxOccur; } unsigned int smlDevInfPropertyGetMaxSize(const SmlDevInfProperty *property) { smlTrace(TRACE_ENTRY, "%s(%p)", __func__, property); smlAssert(property); smlTrace(TRACE_EXIT, "%s - %d", __func__, property->maxSize); return property->maxSize; } SmlBool smlDevInfPropertyGetNoTruncate(const SmlDevInfProperty *property) { smlTrace(TRACE_ENTRY, "%s(%p)", __func__, property); smlAssert(property); smlTrace(TRACE_EXIT, "%s - %d", __func__, property->noTruncate); return property->noTruncate; } char *smlDevInfPropertyGetDisplayName(const SmlDevInfProperty *property) { smlTrace(TRACE_ENTRY, "%s(%p)", __func__, property); smlAssert(property); char *result = g_strdup(property->displayName); smlTrace(TRACE_EXIT, "%s - %s", __func__, VA_STRING(result)); return result; } unsigned int smlDevInfPropertyNumValEnums(const SmlDevInfProperty *property) { smlTrace(TRACE_ENTRY, "%s(%p)", __func__, property); smlAssert(property); unsigned int num = g_list_length(property->valEnums); smlTrace(TRACE_EXIT, "%s - %d", __func__, num); return num; } char *smlDevInfPropertyGetNthValEnum( const SmlDevInfProperty *property, unsigned int n) { smlTrace(TRACE_ENTRY, "%s(%p, %d)", __func__, property, n); smlAssert(property); char *result = g_strdup(g_list_nth_data(property->valEnums, n)); smlTrace(TRACE_EXIT, "%s - %s", __func__, VA_STRING(result)); return result; } unsigned int smlDevInfPropertyNumPropParams(const SmlDevInfProperty *property) { smlTrace(TRACE_ENTRY, "%s(%p)", __func__, property); smlAssert(property); unsigned int num = g_list_length(property->propParams); smlTrace(TRACE_EXIT, "%s - %d", __func__, num); return num; } const SmlDevInfPropParam *smlDevInfPropertyGetNthPropParam( const SmlDevInfProperty *property, unsigned int n) { smlTrace(TRACE_ENTRY, "%s(%p, %d)", __func__, property, n); smlAssert(property); SmlDevInfPropParam *param = g_list_nth_data(property->propParams, n); smlTrace(TRACE_EXIT, "%s - %p", __func__, param); return param; } /* CTCap stuff */ SmlDevInfContentType *smlDevInfNewContentType( const char *cttype, const char *verct, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p)", __func__, error); CHECK_ERROR_REF SmlDevInfContentType *ct = smlTryMalloc0(sizeof(SmlDevInfContentType), error); if (!ct) { smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return NULL; } if (cttype != NULL) ct->cttype = g_strdup(cttype); else ct->cttype = NULL; if (verct != NULL) ct->verct = g_strdup(verct); else ct->verct = NULL; smlTrace(TRACE_EXIT, "%s", __func__); return ct; } char *smlDevInfContentTypeGetCTType(const SmlDevInfContentType *ct) { return g_strdup(ct->cttype); } char *smlDevInfContentTypeGetVerCT(const SmlDevInfContentType *ct) { return g_strdup(ct->verct); } void smlDevInfFreeContentType(SmlDevInfContentType *ct) { smlTrace(TRACE_ENTRY, "%s", __func__); smlAssert(ct); if (ct->cttype != NULL) smlSafeCFree(&(ct->cttype)); if (ct->verct != NULL) smlSafeCFree(&(ct->verct)); smlSafeFree((gpointer *)&ct); smlTrace(TRACE_EXIT, "%s", __func__); } SmlDevInfCTCap *smlDevInfNewCTCap(SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p)", __func__, error); CHECK_ERROR_REF SmlDevInfCTCap *ctcap = smlTryMalloc0(sizeof(SmlDevInfCTCap), error); if (!ctcap) { smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return NULL; } ctcap->ct = smlDevInfNewContentType(NULL, NULL, error); if (!ctcap->ct) { smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); smlSafeFree((gpointer *)&ctcap); return NULL; } ctcap->properties = NULL; smlTrace(TRACE_EXIT, "%s", __func__); return ctcap; } void smlDevInfCTCapSetCTType( SmlDevInfCTCap *ctcap, const char *cttype) { smlTrace(TRACE_ENTRY, "%s(%p, %s)", __func__, ctcap, VA_STRING(cttype)); smlAssert(ctcap); smlAssert(cttype); ctcap->ct->cttype = g_strdup(cttype); smlTrace(TRACE_EXIT, "%s", __func__); } void smlDevInfCTCapSetVerCT( SmlDevInfCTCap *ctcap, const char *verct) { smlTrace(TRACE_ENTRY, "%s(%p, %s)", __func__, ctcap, VA_STRING(verct)); smlAssert(ctcap); smlAssert(verct); ctcap->ct->verct = g_strdup(verct); smlTrace(TRACE_EXIT, "%s", __func__); } char *smlDevInfCTCapGetCTType(const SmlDevInfCTCap *ctcap) { smlTrace(TRACE_ENTRY, "%s(%p)", __func__, ctcap); smlAssert(ctcap); char *cttype; cttype = g_strdup(ctcap->ct->cttype); smlTrace(TRACE_EXIT, "%s - %s", __func__, VA_STRING(cttype)); return cttype; } char *smlDevInfCTCapGetVerCT(const SmlDevInfCTCap *ctcap) { smlTrace(TRACE_ENTRY, "%s(%p)", __func__, ctcap); smlAssert(ctcap); char *verct; verct = g_strdup(ctcap->ct->verct); smlTrace(TRACE_EXIT, "%s - %s", __func__, VA_STRING(verct)); return verct; } void smlDevInfCTCapAddProperty( SmlDevInfCTCap *ctcap, SmlDevInfProperty *property) { smlTrace(TRACE_ENTRY, "%s(%p, %p)", __func__, ctcap, property); smlAssert(ctcap); smlAssert(property); ctcap->properties = g_list_append(ctcap->properties, property); smlTrace(TRACE_EXIT, "%s", __func__); } void smlDevInfAppendCTCap(SmlDevInf *devinf, SmlDevInfCTCap *ctcap) { smlTrace(TRACE_ENTRY, "%s(%p, %p)", __func__, devinf, ctcap); smlAssert(devinf); smlAssert(ctcap); devinf->ctcaps = g_list_append(devinf->ctcaps, ctcap); smlTrace(TRACE_EXIT, "%s", __func__); } /* FIXME: DEPRECATED*/ void smlDevInfAddCTCap(SmlDevInf *devinf, SmlDevInfCTCapType type, const char *value) { SmlDevInfCTCap *ctcap = smlDevInfNewCTCap(NULL); smlDevInfCTCapSetCTType(ctcap, smlDevInfCTCapTypeToString(type, NULL)); smlDevInfCTCapSetVerCT(ctcap, value); smlDevInfAppendCTCap(devinf, ctcap); } /* FIXME: DEPRECATED*/ SmlDevInfCTCapType smlDevInfGetNthCTCapType(SmlDevInf *devinf, unsigned int nth) { const SmlDevInfCTCap *ctcap = smlDevInfGetNthCTCap(devinf, nth); char *type = smlDevInfCTCapGetCTType(ctcap); SmlError *error = NULL; SmlDevInfCTCapType cttype = smlDevInfCTCapTypeFromString(type, &error); smlSafeCFree(&type); return cttype; } /* FIXME: DEPRECATED*/ const char *smlDevInfGetNthCTCapValue(SmlDevInf *devinf, unsigned int nth) { const SmlDevInfCTCap *ctcap = smlDevInfGetNthCTCap(devinf, nth); return smlDevInfCTCapGetVerCT(ctcap); } const SmlDevInfCTCap *smlDevInfGetCTCap( const SmlDevInf *devinf, SmlDevInfContentType *ct) { smlTrace(TRACE_ENTRY, "%s(%p, %p)", __func__, devinf, ct); smlAssert(devinf); smlAssert(ct); smlAssert(ct->cttype); smlAssert(ct->verct); GList *h; for (h = devinf->ctcaps; h; h = h->next) { SmlDevInfCTCap *ctcap = h->data; // check that CTType matches if (!strcmp(ct->cttype, ctcap->ct->cttype) && !strcmp(ct->verct, ctcap->ct->verct)) { smlTrace(TRACE_EXIT, "%s - succeeded", __func__); return ctcap; } } smlTrace(TRACE_EXIT, "%s - nothing found", __func__); return NULL; } unsigned int smlDevInfNumCTCaps(const SmlDevInf *devinf) { smlTrace(TRACE_ENTRY, "%s(%p)", __func__, devinf); smlAssert(devinf); unsigned int num = g_list_length(devinf->ctcaps); smlTrace(TRACE_EXIT, "%s - %d", __func__, num); return num; } const SmlDevInfCTCap *smlDevInfGetNthCTCap( const SmlDevInf *devinf, unsigned int n) { smlTrace(TRACE_ENTRY, "%s(%p, %d)", __func__, devinf, n); smlAssert(devinf); SmlDevInfCTCap *ctcap = g_list_nth_data(devinf->ctcaps, n); smlTrace(TRACE_EXIT, "%s - %p", __func__, ctcap); return ctcap; } unsigned int smlDevInfCTCapNumProperties(const SmlDevInfCTCap *ctcap) { smlTrace(TRACE_ENTRY, "%s(%p)", __func__, ctcap); smlAssert(ctcap); unsigned int num = g_list_length(ctcap->properties); smlTrace(TRACE_EXIT, "%s - %d", __func__, num); return num; } const SmlDevInfProperty *smlDevInfCTCapGetNthProperty( const SmlDevInfCTCap *ctcap, unsigned int n) { smlTrace(TRACE_ENTRY, "%s(%p, %d)", __func__, ctcap, n); smlAssert(ctcap); SmlDevInfProperty *property = g_list_nth_data(ctcap->properties, n); smlTrace(TRACE_EXIT, "%s - %p", __func__, property); return property; } SmlDevInfSyncCap smlDevInfSyncCapConvert(unsigned int id, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%u, %p)", __func__, id, error); CHECK_ERROR_REF SmlDevInfSyncCap result = SML_DEVINF_SYNCTYPE_UNKNOWN; switch (id) { case SML_DEVINF_SYNCTYPE_TWO_WAY: result = SML_DEVINF_SYNCTYPE_TWO_WAY; break; case SML_DEVINF_SYNCTYPE_SLOW_SYNC: result = SML_DEVINF_SYNCTYPE_SLOW_SYNC; break; case SML_DEVINF_SYNCTYPE_ONE_WAY_FROM_CLIENT: result = SML_DEVINF_SYNCTYPE_ONE_WAY_FROM_CLIENT; break; case SML_DEVINF_SYNCTYPE_REFRESH_FROM_CLIENT: result = SML_DEVINF_SYNCTYPE_REFRESH_FROM_CLIENT; break; case SML_DEVINF_SYNCTYPE_ONE_WAY_FROM_SERVER: result = SML_DEVINF_SYNCTYPE_ONE_WAY_FROM_SERVER; break; case SML_DEVINF_SYNCTYPE_REFRESH_FROM_SERVER: result = SML_DEVINF_SYNCTYPE_REFRESH_FROM_SERVER; break; case SML_DEVINF_SYNCTYPE_SERVER_ALERTED_SYNC: result = SML_DEVINF_SYNCTYPE_SERVER_ALERTED_SYNC; break; default: smlErrorSet(error, SML_ERROR_GENERIC, "The synchronization type %u is unknwon.", id); smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(error)); return SML_DEVINF_SYNCTYPE_UNKNOWN; break; } smlTrace(TRACE_EXIT, "%s - %u", __func__, result); return result; } libsyncml-0.5.4/libsyncml/sml_error.h100644 1750 1750 10104 11211710410 17606 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2005 Armin Bauer * Copyright (C) 2007-2008 Michael Bell * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #ifndef _SML_ERROR_H_ #define _SML_ERROR_H_ typedef enum { SML_ERRORCLASS_UNKNOWN = 0, SML_ERRORCLASS_SUCCESS = 2, SML_ERRORCLASS_RETRY = 3, SML_ERRORCLASS_FATAL = 5 } SmlErrorClass; /*! @ingroup smlErrorAPI * @brief Defines the possible error types */ typedef enum { SML_ERROR_UNKNOWN = 0, /* Informational */ SML_IN_PROGRESS = 101, /* OK code */ /** No error */ SML_NO_ERROR = 200, /** Requested item was added */ SML_ITEM_ADDED = 201, /** Accepted for processing */ SML_PROCESSING_ACCEPTED = 202, /** Non-authoritative response */ SML_NON_AUTHORITATIVE = 203, /** No content */ SML_NO_CONTENT = 204, /** Reset content */ SML_RESET_CONTENT = 205, /** Partial content */ SML_PARTIAL_CONTENT = 206, /** Conflict resolved with merge */ SML_CONFLICT_MERGE = 207, /** Conflict resolved with client win */ SML_CONFLICT_CLIENT_WIN = 208, /** Conflict resolved with duplicate */ SML_CONFLICT_DUPLICATE = 209, /** Deleted without archiving */ SML_DELETE_NO_ARCHIVE = 210, /** Item not deleted (not found) */ SML_DELETE_NOT_FOUND = 211, /** Authentication accepted */ SML_AUTH_ACCEPTED = 212, /** Chunked item accepted */ SML_CHUNK_ACCEPTED = 213, /** Operation cancelled */ SML_OPERATION_CANCELLED = 214, /** Not executed */ SML_NOT_EXECUTED = 215, /** Atomic rollback ok */ SML_ATOMIC_ROLLBACK_OK = 216, /* Retry error */ SML_ERROR_MULTIPLE_CHOICES = 300, SML_ERROR_MOVED_PERMANENTLY = 301, SML_ERROR_FOUND_RETRY = 302, SML_ERROR_SEE_OTHER_RETRY = 303, SML_ERROR_NOT_MODIFIED = 304, SML_ERROR_USE_PROXY = 305, /* Errors */ SML_ERROR_BAD_REQUEST = 400, // Bad Request SML_ERROR_AUTH_REJECTED = 401, // Unauthorized, Invalid Credentials SML_ERROR_PAYMENT_NEEDED =402, // Payment need SML_ERROR_FORBIDDEN = 403, // Forbidden SML_ERROR_NOT_FOUND = 404, // Not found SML_ERROR_COMMAND_NOT_ALLOWED = 405, // Command not allowed SML_ERROR_UNSUPPORTED_FEATURE = 406, // Optional feature unsupported SML_ERROR_AUTH_REQUIRED = 407, // Authentication required, Missing Credentials SML_ERROR_RETRY_LATER = 417, // Retry later SML_ERROR_ALREADY_EXISTS = 418, // Put or Add failed because item already exists SML_ERROR_SIZE_MISMATCH = 424, // Size mismatch /* Standard errors */ SML_ERROR_GENERIC = 500, SML_ERROR_NOT_IMPLEMENTED = 501, SML_ERROR_SERVICE_UNAVAILABLE = 503, SML_ERROR_REQUIRE_REFRESH = 508, SML_ERROR_SERVER_FAILURE = 511, /* Internal errors - never ever send this via SyncML */ SML_ERROR_INTERNAL_IO_ERROR = 1501, SML_ERROR_INTERNAL_TIMEOUT = 1503, SML_ERROR_INTERNAL_FILE_NOT_FOUND = 1505, SML_ERROR_INTERNAL_MISCONFIGURATION = 1506, SML_ERROR_INTERNAL_NO_MEMORY = 1512 } SmlErrorType; SmlError **smlErrorRef(SmlError **error); void smlErrorDeref(SmlError **error); SmlBool smlErrorIsSet(SmlError **error); void smlErrorSet(SmlError **error, SmlErrorType type, const char *format, ...); void smlErrorUpdate(SmlError **error, const char *format, ...); void smlErrorDuplicate(SmlError **target, SmlError **source); const char *smlErrorPrint(SmlError **error); SmlErrorType smlErrorGetType(SmlError **error); void smlErrorSetType(SmlError **error, SmlErrorType type); SmlErrorClass smlErrorGetClass(SmlError **error); #endif //_SML_ERROR_H_ libsyncml-0.5.4/libsyncml/syncml.h100644 1750 1750 7356 11211710410 17106 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2005 Armin Bauer * Copyright (C) 2007 Michael Bell * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ /** * @defgroup PublicAPI libsyncml API * @ingroup PublicAPI * @brief The public part * */ /** * @defgroup PublicObjectAPI libsyncml Object API * @ingroup PublicAPI * @brief The public part * */ /** * @defgroup PublicLowLevelAPI Low Level API * @ingroup PublicAPI * @brief The public part * */ /*@{*/ #ifndef _SYNCML_H #define _SYNCML_H #include #include #ifdef __cplusplus extern "C" { #endif /************************************************************** * Defines *************************************************************/ #ifndef TRUE #define TRUE 1 #endif #ifndef FALSE #define FALSE 0 #endif /************************************************************** * Structs *************************************************************/ typedef struct SmlError SmlError; typedef struct SmlTransport SmlTransport; typedef struct SmlParser SmlParser; typedef struct SmlAssembler SmlAssembler; typedef struct SmlCommand SmlCommand; typedef struct SmlLocation SmlLocation; typedef struct SmlStatus SmlStatus; typedef struct SmlSession SmlSession; typedef struct SmlAnchor SmlAnchor; typedef struct SmlPendingStatus SmlPendingStatus; typedef struct SmlItem SmlItem; typedef struct SmlDevInf SmlDevInf; typedef struct SmlDevInfDataStore SmlDevInfDataStore; typedef struct SmlDevInfContentType SmlDevInfContentType; typedef struct SmlDevInfCTCap SmlDevInfCTCap; typedef struct SmlDevInfProperty SmlDevInfProperty; typedef struct SmlDevInfPropParam SmlDevInfPropParam; typedef struct SmlNotification SmlNotification; typedef struct SmlSanAlert SmlSanAlert; typedef struct SmlMapItem SmlMapItem; typedef struct SmlCred SmlCred; typedef struct SmlChal SmlChal; typedef struct SmlHeader SmlHeader; typedef struct SmlTransportData SmlTransportData; typedef struct SmlObject SmlObject; typedef struct SmlManager SmlManager; typedef struct SmlLink SmlLink; typedef int SmlBool; #include #include #include #include #include #include #include #include #include #include #include const char *smlGetLibraryVersion(); const char *smlGetLibrarySoName(); #ifdef __cplusplus } #endif #endif /*@}*/ /** @mainpage * * This library implements the following protocols: * * - SyncML 1.0 Data Synchronization Protocol * - SyncML 1.1 Data Synchronization Protocol * - OMA DS 1.1 * - OMA DS 1.2 * * The following transports are supported: * * - HTTP client * - HTTP server * - OBEX client * - OBEX server * * SANs for HTTP clients are not supported because HTTP OTA requires * direct GSM network access. * * XML and WBXML are both supported. */ libsyncml-0.5.4/libsyncml/sml_parse.c100644 1750 1750 74110 11211710410 17571 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2005 Armin Bauer * Copyright (C) 2008 Michael Bell * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include "syncml.h" #include "syncml_internals.h" #include "sml_error_internals.h" #include "sml_parse_internals.h" #include "sml_command_internals.h" #include "sml_elements_internals.h" #include "sml_notification_internals.h" #include "parser/sml_xml_assm.h" #include "parser/sml_xml_parse.h" #include "parser/sml_wbxml.h" /** * @defgroup SmlParser SyncML Parser * @ingroup PublicLowLevelAPI * @brief Interfaces to parse syncml messages * */ /*@{*/ /** @brief Creates a new parser * * @param type The type of the parser * @param error A pointer to an error struct * @return The new parser or NULL in the case of an error * */ SmlParser *smlParserNew(SmlMimeType type, unsigned int limit, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%i, %i, %p)", __func__, type, limit, error); CHECK_ERROR_REF SmlParser *parser = smlTryMalloc0(sizeof(SmlParser), error); if (!parser) goto error; parser->type = type; parser->limit = limit; switch (type) { case SML_MIMETYPE_XML: if (!(parser->parser_userdata = smlXmlParserNew(&(parser->functions), error))) goto error_free_parser; break; case SML_MIMETYPE_SAN: /* SANs will be converted to normal SyncML 1.1 notifications */ if (!(parser->parser_userdata = smlXmlParserNew(&(parser->functions), error))) goto error_free_parser; break; case SML_MIMETYPE_WBXML: #ifdef ENABLE_WBXML if (!(parser->parser_userdata = smlWbxmlParserNew(&(parser->functions), error))) goto error_free_parser; break; #else smlErrorSet(error, SML_ERROR_GENERIC, "Wbxml not enabled in this build"); goto error_free_parser; #endif default: smlErrorSet(error, SML_ERROR_GENERIC, "Unknown parser type"); goto error_free_parser; } smlTrace(TRACE_EXIT, "%s: %p", __func__, parser); return parser; error_free_parser: smlSafeFree((gpointer *)&parser); error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return NULL; } void smlParserSetManager(SmlParser *parser, SmlManager *manager) { smlAssert(parser); smlAssert(manager); parser->manager = manager; } /** @brief Frees a parser * * @param parser The parser to free * */ void smlParserFree(SmlParser *parser) { smlTrace(TRACE_ENTRY, "%s(%p)", __func__, parser); smlAssert(parser); if (parser->functions.free) parser->functions.free(parser->parser_userdata); smlSafeFree((gpointer *)&parser); smlTrace(TRACE_EXIT, "%s", __func__); } /** @brief Starts the parser on a given data buffer * * This function will parse the data up to the SyncHdr tag * * @param parser The parser * @param data The data that should be parsed * @param size The size of the data * @param error A pointer to an error struct * @returns TRUE if the parser started successfully, FALSE otherwise * */ SmlBool smlParserStart(SmlParser *parser, const char *data, unsigned int size, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %i, %p)", __func__, parser, data, size, error); CHECK_ERROR_REF smlAssert(parser); smlAssert(data); smlAssert(size); smlAssert(parser->functions.start); smlAssertMsg(parser->type != SML_MIMETYPE_SAN || parser->manager, SML_ASSERT_MSG_SAN_PARSE_REQUIRES_MANAGER); if (parser->limit && size > parser->limit) { smlErrorSet(error, SML_ERROR_GENERIC, "Input data too large"); goto error; } if (parser->type == SML_MIMETYPE_SAN) { /* convert OMA DS 1.2 SAN into an SyncML 1.1 notification */ smlTrace(TRACE_INTERNAL, "%s - detected an OMA DS 1.2 SAN", __func__); /* parse the SAN */ SmlNotification *san = smlNotificationParse(data, size, error); if (!san) goto error; /* fix 1.2 SAN for use with SyncML 1.1 */ smlNotificationSetManager(san, parser->manager); san->type = SML_MIMETYPE_XML; san->sessionType = SML_SESSION_TYPE_CLIENT; san->target = smlLocationNew("/", NULL, error); if (!san->target) goto error; /* assemble a SyncML 1.1 notification */ char *xmlData = NULL; unsigned int xmlSize = 0; if (!smlNotificationAssemble11(san, &xmlData, &xmlSize, SML_VERSION_12, error)) { smlNotificationFree(san); goto error; } smlTrace(TRACE_INTERNAL, "%s - converted OMA DS 1.2 SAN to SyncML 1.1 server alerted sync - %s", __func__, VA_STRING(xmlData)); /* cleanup notification */ smlNotificationFree(san); san = NULL; /* run the parser on the converted SAN */ if (!parser->functions.start(parser->parser_userdata, xmlData, xmlSize, error)) { smlSafeCFree(&xmlData); goto error; } smlSafeCFree(&xmlData); } else { /* run the parser directly on the data */ if (!parser->functions.start(parser->parser_userdata, data, size, error)) goto error; } smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return FALSE; } /** @brief Parses the SyncHdr * * This function will parse the data inside the SyncHdr Tag. Possible * error case are: * * - No header was found * - The header is missing necessary information * - OOM * * @param parser The parser * @param header The return location of the header * @param error A pointer to an error struct * @returns TRUE if the parser retrieved the header successfully, FALSE otherwise * */ SmlBool smlParserGetHeader(SmlParser *parser, SmlHeader **header, SmlCred **cred, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, parser, header, cred, error); CHECK_ERROR_REF smlAssert(parser); smlAssert(header); smlAssert(cred); smlAssert(parser->functions.get_header); if (!parser->functions.get_header(parser->parser_userdata, header, cred, error)) goto error; smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return FALSE; } /** @brief Parses the next command * * This function will parse the next command found in the syncbody. Note that if you * call this function too early (before the synchdr is parsed this function will return an * error.) The correct order is: getHeader, getStatus until NULL, then getCommand * until NULL and then End to end parsing. * * @param parser The parser * @param cmd The return location of the command * @param error A pointer to an error struct * @returns TRUE if the parser retrieved the next command successfully or there were no more * commands available (in which case *cmd is NULL). FALSE in the case of an error * */ SmlParserResult smlParserGetCommand(SmlParser *parser, SmlCommand **cmd, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, parser, cmd, error); CHECK_ERROR_REF smlAssert(parser); smlAssert(cmd); smlAssert(parser->functions.get_cmd); SmlParserResult result = SML_PARSER_RESULT_ERROR; if (!(result = parser->functions.get_cmd(parser->parser_userdata, cmd, error))) goto error; smlTrace(TRACE_EXIT, "%s: %i", __func__, result); return result; error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return SML_PARSER_RESULT_ERROR; } /** @brief Parses the next status * * This function will parse the next status found in the syncbody. Note that if you * call this function too early (before the synchdr is parsed this function will return an * error.) The correct order is: getHeader, getStatus until NULL, then getCommand * until NULL and then End to end parsing. * * @param parser The parser * @param status The return location of the status * @param error A pointer to an error struct * @returns TRUE if the parser retrieved the next status successfully or there were no more * statuses available (in which case *status is NULL). FALSE in the case of an error * */ SmlBool smlParserGetStatus(SmlParser *parser, SmlStatus **status, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, parser, status, error); CHECK_ERROR_REF smlAssert(parser); smlAssert(status); smlAssert(parser->functions.get_status); if (!parser->functions.get_status(parser->parser_userdata, status, error)) goto error; smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return FALSE; } /** @brief Ends the parsing * * This function will check that all needed closing tags are in place * * @param parser The parser * @param final Return location to see if this was the final message * @param end Return location to see if this message was a end message (only statuses) * @param error A pointer to an error struct * @returns TRUE if the parser ended successfully, FALSE otherwise * */ SmlBool smlParserEnd(SmlParser *parser, SmlBool *final, SmlBool *end, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p, %p)", __func__, parser, final, end, error); CHECK_ERROR_REF smlAssert(parser); smlAssert(parser->functions.end); if (!parser->functions.end(parser->parser_userdata, final, end, error)) goto error; smlTrace(TRACE_INTERNAL, "%s: Final %i, End %i", __func__, final ? *final : -1, end ? *end : -1); smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return FALSE; } /*@}*/ /** * @defgroup SmlAssembler SyncML Assembler * @ingroup PublicLowLevelAPI * @brief Interfaces to assemble syncml messages * */ /*@{*/ /** @brief Creates a new assembler * * @param type The type of the assembler * @param limit The maximum size that can be assembled * @param error A pointer to an error struct * @return The new assembler or NULL in the case of an error * */ SmlAssembler *smlAssemblerNew(SmlMimeType type, unsigned int limit, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%i, %i, %p)", __func__, type, limit, error); CHECK_ERROR_REF SmlAssembler *assm = smlTryMalloc0(sizeof(SmlAssembler), error); if (!assm) goto error; assm->type = type; assm->remoteMaxMsgSize = limit; assm->empty = TRUE; assm->remoteMaxObjSize = 0; switch (type) { case SML_MIMETYPE_XML: if (!(assm->assm_userdata = smlXmlAssemblerNew(assm, &(assm->functions), error))) goto error_free_assm; break; case SML_MIMETYPE_WBXML: #ifdef ENABLE_WBXML if (!(assm->assm_userdata = smlWbxmlAssemblerNew(assm, &(assm->functions), error))) goto error_free_assm; break; #else smlErrorSet(error, SML_ERROR_GENERIC, "Wbxml not enabled in this build"); goto error_free_assm; #endif default: smlErrorSet(error, SML_ERROR_GENERIC, "Unknown assembler type"); goto error_free_assm; } assm->options = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); smlTrace(TRACE_EXIT, "%s: %p", __func__, assm); return assm; error_free_assm: smlSafeFree((gpointer *)&assm); error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return NULL; } /** @brief Frees a assembler * * @param assm The assembler to free * */ void smlAssemblerFree(SmlAssembler *assm) { smlTrace(TRACE_ENTRY, "%s(%p)", __func__, assm); smlAssert(assm); if (assm->functions.free) assm->functions.free(assm->assm_userdata); g_hash_table_destroy(assm->options); smlSafeFree((gpointer *)&assm); smlTrace(TRACE_EXIT, "%s", __func__); } /** @brief Starts a new message * * Note that the size already includes what will be needed to close the opened tags * (like SyncML) and already includes the remaining needed tags (like Final) * * @param assm The assembler * @param session The session for which to start a message * @param error A pointer to an error struct * @returns TRUE if the package container was assembled successfully, FALSE otherwise * */ SmlBool smlAssemblerStart(SmlAssembler *assm, SmlSession *session, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, assm, session, error); CHECK_ERROR_REF smlAssert(assm); smlAssert(session); smlAssert(assm->functions.start); if (!assm->functions.start(assm->assm_userdata, session, error)) goto error; smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return FALSE; } /** @brief Assembles the complete message and returns the result * * @param assm The assembler * @param data Place that will receive the data * @param size Place that will receive the size * @param error A pointer to an error struct * @returns TRUE if the package container was assembled successfully, FALSE otherwise * */ SmlBool smlAssemblerRun(SmlAssembler *assm, char **data, unsigned int *size, SmlBool *end, SmlBool final, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p, %p, %i, %p)", __func__, assm, data, size, end, final, error); CHECK_ERROR_REF smlAssert(assm); smlAssert(data); smlAssert(size); smlAssert(assm->functions.run); if (!assm->functions.run(assm->assm_userdata, data, size, end, final, smlAssemblerGetRemoteMaxMsgSize(assm), error)) goto error; smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return FALSE; } /** @brief Assembles the complete message and returns the result * * @param assm The assembler * @param data Place that will receive the data * @param size Place that will receive the size * @param error A pointer to an error struct * @returns TRUE if the package container was assembled successfully, FALSE otherwise * */ unsigned int smlAssemblerCheckSize(SmlAssembler *assm, SmlBool headeronly, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %i, %p)", __func__, assm, headeronly, error); CHECK_ERROR_REF smlAssert(assm); smlAssert(assm->functions.check_size); unsigned int size = 0; if (!(size = assm->functions.check_size(assm->assm_userdata, headeronly, error))) goto error; smlTrace(TRACE_EXIT, "%s: %i", __func__, size); return size; error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return 0; } /** @brief Flushes the already parsed commands * * This command can be used to flush the already parsed commands. You can use * this to flush the assembler after you pull part of the data using smlAssemblerRun() * * @param assm The assembler * @param error A pointer to an error struct * @returns TRUE if the flushing was successful, FALSE otherwise * */ unsigned int smlAssemblerFlush(SmlAssembler *assm) { smlTrace(TRACE_ENTRY, "%s(%p)", __func__, assm); smlAssert(assm); smlAssert(assm->functions.flush); unsigned int ret = assm->functions.flush(assm->assm_userdata); assm->empty = TRUE; smlTrace(TRACE_EXIT, "%s: %i", __func__, ret); return ret; } void smlAssemblerRestoreCommands(SmlAssembler *assm) { smlTrace(TRACE_ENTRY, "%s(%p)", __func__, assm); smlAssert(assm); smlAssert(assm->functions.restore_cmds); assm->functions.restore_cmds(assm->assm_userdata); assm->empty = FALSE; smlTrace(TRACE_EXIT, "%s", __func__); } /** @brief Gets the available space in the assembler * * This command tries to add the given command to the assembler without the * item data. Then it returns how big the item data could be without violating * the limits. If there is not limit set, -1 is returned. This command only * makes sense for change commands */ SmlBool smlAssemblerGetSpace(SmlAssembler *assm, int *space, SmlCommand *parent, SmlCommand *cmd, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p, %p, %p)", __func__, assm, space, parent, cmd, error); CHECK_ERROR_REF smlAssert(assm); smlAssert(space); smlAssert(cmd); smlAssert(assm->functions.start_cmd); smlAssert(assm->functions.rem_cmd); smlAssert(cmd->type == SML_COMMAND_TYPE_ADD || cmd->type == SML_COMMAND_TYPE_REPLACE); unsigned int parentID = 0; int limit = smlAssemblerGetRemoteMaxMsgSize(assm); if (!limit) { *space = -1; smlTrace(TRACE_EXIT, "%s: No limit", __func__); return TRUE; } /* Add the command */ if (parent) { if (!parent->cmdID) { smlErrorSet(error, SML_ERROR_GENERIC, "Parent has to be added before"); goto error; } parentID = parent->cmdID; } /* disable the items */ if (cmd->private.change.items) { guint i; for (i=0; i < g_list_length(cmd->private.change.items); i++) { SmlItem *item = g_list_nth_data(cmd->private.change.items, i); item->disabled = TRUE; } } SmlBool noCmdID = FALSE; if (!cmd->cmdID) { noCmdID = TRUE; /* FIXME: This code does not support more * FIXME: than 99.999 commands in one session. */ cmd->cmdID = 10000; } if (!assm->functions.start_cmd(assm->assm_userdata, parentID, cmd, error)) goto error_enable_item; /* Now check the size */ int size = 0; if (!(size = smlAssemblerCheckSize(assm, FALSE, error))) goto error_remove; if (limit <= size) *space = 0; else *space = limit - size - 10; /* Remove the command again */ if (!assm->functions.rem_cmd(assm->assm_userdata, parentID, error)) goto error_remove; /* enable the items again */ if (cmd->private.change.items) { guint i; for (i=0; i < g_list_length(cmd->private.change.items); i++) { SmlItem *item = g_list_nth_data(cmd->private.change.items, i); item->disabled = FALSE; } } if (noCmdID) cmd->cmdID = 0; smlTrace(TRACE_EXIT, "%s: %i", __func__, *space); return TRUE; error_remove: assm->functions.rem_cmd(assm->assm_userdata, parentID, NULL); error_enable_item: if (cmd->private.change.items) { guint i; for (i=0; i < g_list_length(cmd->private.change.items); i++) { SmlItem *item = g_list_nth_data(cmd->private.change.items, i); item->disabled = FALSE; } } if (noCmdID) cmd->cmdID = 0; error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return FALSE; } /** @brief Starts a parent command * * This command starts a parent command. All commands added after this one will be added * as subcommands. This functions also take care if the parent command would spawn 2 messages. * This function can nest. * * @param assm The assembler * @param parent The parent to the command to add. NULL if none * @param cmd The command to add * @param error A pointer to an error struct * @returns SML_ASSEMBLER_RESULT_OK if the command was added ok, SML_ASSEMBLER_RESULT_MISMATCH * if the parent command did not fit, SML_ASSEMBLER_RESULT_ERROR if some error occured. * */ SmlAssemblerResult smlAssemblerStartCommand(SmlAssembler *assm, SmlCommand *parent, SmlCommand *cmd, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p, %p)", __func__, assm, parent, cmd, error); CHECK_ERROR_REF smlAssert(assm); smlAssert(cmd); smlAssert(assm->functions.start_cmd); smlAssert(assm->functions.rem_cmd); unsigned int parentID = 0; /* Add the command */ if (parent) { if (!parent->cmdID) { smlErrorSet(error, SML_ERROR_GENERIC, "Parent has to be added before"); goto error; } parentID = parent->cmdID; } if (!assm->functions.start_cmd(assm->assm_userdata, parentID, cmd, error)) goto error; /* Lets see if the new buffer is small enough */ int limit = smlAssemblerGetRemoteMaxMsgSize(assm); if (limit) { /* Now check the size */ int size = 0; if (!(size = smlAssemblerCheckSize(assm, FALSE, error))) goto error; if (size > limit) { /* The status does not fit. Remove it again */ if (!assm->functions.rem_cmd(assm->assm_userdata, parentID, error)) goto error; smlTrace(TRACE_EXIT, "%s: Mismatch", __func__); return SML_ASSEMBLER_RESULT_MISMATCH; } smlTrace(TRACE_INTERNAL, "%s: size %i, limit %i", __func__, size, limit); } if (cmd->cmdID) assm->empty = FALSE; smlTrace(TRACE_EXIT, "%s", __func__); return SML_ASSEMBLER_RESULT_OK; error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return SML_ASSEMBLER_RESULT_ERROR; } /** @brief Ends a parent command * * Ends the last previously started parent command. All commands added afterwards wont be * subcommands any more. * * @param assm The assembler * @param parent The parent of the child to end. NULL if none * @param error A pointer to an error struct * @returns TRUE if the command was added successfully, FALSE otherwise * */ SmlBool smlAssemblerEndCommand(SmlAssembler *assm, SmlCommand *parent, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, assm, parent, error); CHECK_ERROR_REF smlAssert(assm); smlAssert(assm->functions.end_cmd); unsigned int parentID = 0; /* Add the command */ if (parent) { if (!parent->cmdID) { smlErrorSet(error, SML_ERROR_GENERIC, "Parent has to be added before"); goto error; } parentID = parent->cmdID; } /* End the command */ if (!assm->functions.end_cmd(assm->assm_userdata, parentID, error)) goto error; smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return FALSE; } /** @brief Assembles the header * * This command adds the header to the assembler. * * @param assm The assembler * @param session The session header to add * @param error A pointer to an error struct * @returns TRUE if the header was added ok, FALSE if some error occured. * */ SmlBool smlAssemblerAddHeader(SmlAssembler *assm, SmlSession *session, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, assm, session, error); CHECK_ERROR_REF smlAssert(assm); smlAssert(session); smlAssert(assm->functions.add_header); /* Add the command */ if (!assm->functions.add_header(assm->assm_userdata, session, error)) goto error; /* Now check the size */ unsigned int size = 0; if (!(size = smlAssemblerCheckSize(assm, TRUE, error))) goto error; /* Lets see if the new buffer is small enough */ if (smlAssemblerGetRemoteMaxMsgSize(assm) && size > smlAssemblerGetRemoteMaxMsgSize(assm)) { smlErrorSet(error, SML_ERROR_GENERIC, "Limit to small. Unable to fit a the header"); goto error; } smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return FALSE; } /** @brief Reserves a place for a status with this assembler * * This command reserves a place for a status. Call this function to make sure that * the statuses are added in the correct order. You dont have to reserve for cmdRef=0 * . This one is always reserved * * @param assm The assembler * @param cmdRef The cmdRef of the status to reserve * @param cmdID The cmdID for this status * @param error A pointer to an error struct * @returns TRUE if successful, FALSE otherwise * */ SmlAssemblerResult smlAssemblerReserveStatus(SmlAssembler *assm, unsigned int cmdRef, unsigned int msgRef, unsigned int cmdID, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %i, %i, %i, %p)", __func__, assm, cmdRef, msgRef, cmdID, error); CHECK_ERROR_REF smlAssert(assm); smlAssert(assm->functions.reserve_status); /* Reserve the status */ if (!assm->functions.reserve_status(assm->assm_userdata, cmdRef, msgRef, cmdID, error)) goto error; smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return FALSE; } /** @brief Assembles a status * * This command adds a status to the assembler. The complete package is assembled * afterwards to see if the status fits inside the current message. If the status * does not fit, SML_ASSEMBLER_RESULT_MISMATCH is returned * * @param assm The assembler * @param status The command to add * @param force If set to TRUE, libsyncml will ignore if the outgoing limit has been reached * @param error A pointer to an error struct * @returns SML_ASSEMBLER_RESULT_OK if the status was added ok, SML_ASSEMBLER_RESULT_MISMATCH * if the status did not fit, SML_ASSEMBLER_RESULT_ERROR if some error occured. * */ SmlAssemblerResult smlAssemblerAddStatusFull(SmlAssembler *assm, SmlStatus *status, SmlBool force, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %i, %p)", __func__, assm, status, force, error); CHECK_ERROR_REF smlAssert(assm); smlAssert(status); smlAssert(assm->functions.add_status); smlAssert(assm->functions.rem_status); /* Add the status */ if (!assm->functions.add_status(assm->assm_userdata, status, error)) goto error; if (!force) { /* Lets see if the new buffer is small enough */ int limit = smlAssemblerGetRemoteMaxMsgSize(assm); if (limit) { /* Now check the size */ int size = 0; if (!(size = smlAssemblerCheckSize(assm, FALSE, error))) goto error; if (size > limit) { /* The status does not fit. Remove it again */ if (!assm->functions.rem_status(assm->assm_userdata, error)) goto error; smlTrace(TRACE_EXIT, "%s: Mismatch", __func__); return SML_ASSEMBLER_RESULT_MISMATCH; } } } /*if (status->cmdRef != 0) assm->empty = FALSE;*/ smlTrace(TRACE_EXIT, "%s", __func__); return SML_ASSEMBLER_RESULT_OK; error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return SML_ASSEMBLER_RESULT_ERROR; } SmlAssemblerResult smlAssemblerAddStatus(SmlAssembler *assm, SmlStatus *status, SmlError **error) { CHECK_ERROR_REF return smlAssemblerAddStatusFull(assm, status, FALSE, error); } /** @brief Sets a option on the assembler * * @param assm The assembler * @param optionname The name of the option to set * @param value The new value * */ void smlAssemblerSetOption(SmlAssembler *assm, const char *optionname, const char *value) { smlTrace(TRACE_ENTRY, "%s(%p, %s, %s)", __func__, assm, VA_STRING(optionname), VA_STRING(value)); smlAssert(assm); smlAssert(optionname); g_hash_table_replace(assm->options, g_strdup(optionname), g_strdup(value)); smlTrace(TRACE_EXIT, "%s", __func__); } /** @brief Gets a option from the assembler * * @param assm The assembler * @param optionname The name of the option to get * @returns The value * */ const char *smlAssemblerGetOption(SmlAssembler *assm, const char *optionname) { smlTrace(TRACE_ENTRY, "%s(%p, %s)", __func__, assm, VA_STRING(optionname)); smlAssert(assm); smlAssert(optionname); const char *ret = g_hash_table_lookup(assm->options, optionname); smlTrace(TRACE_EXIT, "%s: %s", __func__, VA_STRING(ret)); return ret; } /* FIXME: DEPRECATED */ unsigned int smlAssemblerGetLimit(SmlAssembler *assm) { return smlAssemblerGetRemoteMaxMsgSize(assm); } unsigned int smlAssemblerGetRemoteMaxMsgSize(SmlAssembler *assm) { smlTrace(TRACE_ENTRY, "%s(%p)", __func__, assm); smlAssert(assm); smlTrace(TRACE_EXIT, "%s: %i", __func__, assm->remoteMaxMsgSize); return assm->remoteMaxMsgSize; } /* FIXME: DEPRECATED */ void smlAssemblerSetRequestedLimit(SmlAssembler *assm, unsigned int limit) { smlAssemblerSetRemoteMaxMsgSize(assm, limit); } /* FIXME: DEPRECATED */ void smlAssemblerSetLimit(SmlAssembler *assm, unsigned int limit) { smlAssemblerSetRemoteMaxMsgSize(assm, limit); } unsigned int smlAssemblerSetRemoteMaxMsgSize(SmlAssembler *assm, unsigned int limit) { smlTrace(TRACE_ENTRY, "%s(%p, %i)", __func__, assm, limit); smlAssert(assm); if (limit == 0) { /* Reset MaxMsgSize to unused state */ assm->remoteMaxMsgSize = limit; } else { if (limit < assm->remoteMaxMsgSize || assm->remoteMaxMsgSize == 0) { /* There is a real new limit. */ assm->remoteMaxMsgSize = limit; } else { smlTrace(TRACE_INTERNAL, "%s: using old limit (%d) because of large new limit (%d).", __func__, assm->remoteMaxMsgSize, limit); } } smlTrace(TRACE_EXIT, "%s - %d", __func__, assm->remoteMaxMsgSize); return assm->remoteMaxMsgSize; } /* FIXME: DEPRECATED */ int smlAssemblerGetSendingMaxObjSize(SmlAssembler *assm) { return smlAssemblerGetRemoteMaxObjSize(assm); } /* FIXME: DEPRECATED */ int smlAssemblerGetRequestedMaxObjSize(SmlAssembler *assm) { return smlAssemblerGetRemoteMaxObjSize(assm); } unsigned int smlAssemblerGetRemoteMaxObjSize(SmlAssembler *assm) { smlTrace(TRACE_ENTRY, "%s(%p)", __func__, assm); smlAssert(assm); smlTrace(TRACE_EXIT, "%s: %i", __func__, assm->remoteMaxObjSize); return assm->remoteMaxObjSize; } /* FIXME: DEPRECATED */ void smlAssemblerSetRequestedMaxObjSize(SmlAssembler *assm, int limit) { smlAssemblerSetRemoteMaxObjSize(assm, limit); } /* FIXME: DEPRECATED */ void smlAssemblerSetSendingMaxObjSize(SmlAssembler *assm, int limit) { smlAssemblerSetRemoteMaxObjSize(assm, limit); } unsigned int smlAssemblerSetRemoteMaxObjSize(SmlAssembler *assm, unsigned int limit) { smlTrace(TRACE_ENTRY, "%s(%p, %i)", __func__, assm, limit); smlAssert(assm); if (limit == 0) { /* Reset MaxObjSize to unused state */ assm->remoteMaxObjSize = limit; } else { if (limit < assm->remoteMaxObjSize || assm->remoteMaxObjSize == 0) { /* There is a real new limit. */ assm->remoteMaxObjSize = limit; } else { smlTrace(TRACE_INTERNAL, "%s: using old limit (%d) because of large new limit (%d).", __func__, assm->remoteMaxObjSize, limit); } } smlTrace(TRACE_EXIT, "%s - %d", __func__, assm->remoteMaxObjSize); return assm->remoteMaxObjSize; } SmlBool smlAssemblerIsEmpty(SmlAssembler *assm) { smlTrace(TRACE_ENTRY, "%s(%p)", __func__, assm); smlAssert(assm); SmlBool ret = assm->empty; smlTrace(TRACE_EXIT, "%s: %i", __func__, ret); return ret; } /** @brief Checks if there are reserved statuses missing * * @param assm The assembler to check * @returns TRUE if statuses are missing, FALSE if all statuses had been added */ SmlBool smlAssemblerIsStatusMissing(SmlAssembler *assm) { smlAssert(assm); smlAssert(assm->functions.missing_status); SmlBool ret = assm->functions.missing_status(assm->assm_userdata); return ret; } SmlBool smlAssemblerGetNextCmdRef(SmlAssembler *assm, unsigned int *cmdRef, unsigned int *msgRef) { smlAssert(assm); smlAssert(cmdRef); smlAssert(msgRef); smlAssert(assm->functions.next_cmdref); return assm->functions.next_cmdref(assm->assm_userdata, cmdRef, msgRef); } /*@}*/ libsyncml-0.5.4/libsyncml/data_sync_api/data_sync_callbacks.c100644 1750 1750 56256 11211710410 24361 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2008-2009 Michael Bell * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include "data_sync_callbacks.h" #include "libsyncml/syncml_internals.h" #include "libsyncml/sml_support.h" #include "libsyncml/sml_error_internals.h" #include #include #include "defines.h" #include "data_sync_devinf.h" #include "libsyncml/objects/sml_ds_server_internals.h" #include "libsyncml/sml_manager_internals.h" //#include "syncml_common.h" //#include "syncml_callbacks.h" //#include "syncml_vformat.h" //#include "syncml_devinf.h" //#include "syncml_ds_client.h" //#include "syncml_ds_server.h" /* **************************************** */ /* ***** Management Callbacks ***** */ /* **************************************** */ void smlDataSyncEventCallback( SmlManager *manager, SmlManagerEventType type, SmlSession *session, SmlError *error, void *userdata) { smlTrace(TRACE_ENTRY, "%s(%p, %i, %p, %p, %p)", __func__, manager, type, session, error, userdata); SmlDataSyncObject *dsObject = userdata; smlAssert(dsObject); GList *o = NULL; /* FIXME: Is this lock really needed? */ /* FIXME: Who is allowed to call smlManagerDispatch? */ /* FIXME: The SmlManager must be synchronized and not the callback. */ g_mutex_lock(dsObject->managerMutex); switch (type) { case SML_MANAGER_SESSION_FLUSH: case SML_MANAGER_CONNECT_DONE: smlTrace(TRACE_INTERNAL, "%s: ignored event %d ", __func__, type); dsObject->internalState = SML_DATA_SYNC_STATE_CONNECTED; break; case SML_MANAGER_SESSION_ESTABLISHED: smlTrace(TRACE_INTERNAL, "%s: session established", __func__); dsObject->internalState = SML_DATA_SYNC_STATE_SESSION_READY; smlDataSyncSendEvent( dsObject, SML_DATA_SYNC_EVENT_CONNECT, dsObject->eventUserdata, NULL); break; case SML_MANAGER_DISCONNECT_DONE: smlTrace(TRACE_INTERNAL, "%s: connection with device has ended", __func__); /* If the transport was never connected * then it is useless to handle the disconnect * event. */ if (dsObject->internalState < SML_DATA_SYNC_STATE_CONNECTED) { smlTrace(TRACE_INTERNAL, "%s: ignored disconnect because never connected", __func__); break; } /* anchor caching is optional */ if (dsObject->setAnchorCallback) { o = dsObject->datastores; for (; o; o = o->next) { SmlDataSyncDatastore *datastore = o->data; /* write new sync anchors */ char *anchor = g_strdup_printf( "localanchor%s", smlDsSessionGetLocation(datastore->session)); if (!dsObject->setAnchorCallback( dsObject, anchor, datastore->localNext, dsObject->setAnchorUserdata, &error)) goto error; anchor = g_strdup_printf( "remoteanchor%s", smlDsSessionGetLocation(datastore->session)); if (!dsObject->setAnchorCallback( dsObject, anchor, datastore->remoteNext, dsObject->setAnchorUserdata, &error)) goto error; } } dsObject->internalState = SML_DATA_SYNC_STATE_DISCONNECTED; smlDataSyncSendEvent( dsObject, SML_DATA_SYNC_EVENT_DISCONNECT, dsObject->eventUserdata, NULL); smlDataSyncSendEvent( dsObject, SML_DATA_SYNC_EVENT_FINISHED, dsObject->eventUserdata, NULL); break; case SML_MANAGER_TRANSPORT_ERROR: smlTrace(TRACE_INTERNAL, "There was an error in the transport: %s", smlErrorPrint(&error)); if (SML_DATA_SYNC_STATE_CONNECTED <= dsObject->internalState && dsObject->internalState < SML_DATA_SYNC_STATE_DISCONNECTED) { if (dsObject->internalState < SML_DATA_SYNC_STATE_DISCONNECT_IN_PROGRESS) { dsObject->internalState = SML_DATA_SYNC_STATE_DISCONNECT_IN_PROGRESS; SmlError *locerror = NULL; SmlLink *link_ = smlManagerSessionGetLink( dsObject->manager, dsObject->session, &locerror); if (link_ || !locerror) smlTransportDisconnect( dsObject->tsp, link_, &locerror); if (link_) smlLinkDeref(link_); /* error is already tracked. * So locerror can be ignored. */ if (locerror) smlErrorDeref(&locerror); /* It is not a good idea to wait for the * disconnect here. First this is an * asynchronous software so it is always * bad if the software blocks. Second it * is dangerous to call smlManagerDispatch * here because an error during these * dispatch activities can lead to another * error which overwrites the original * error. * * Deadlock must be handled in another way. * The SyncML protocol is usually already * broken if this happens (TRANSPORT_ERROR). * * So yes, it is important to disconnect * and no, it must not run dispatch. */ } else { /* disconnect failed */ dsObject->internalState = SML_DATA_SYNC_STATE_DISCONNECTED; } } goto error; break; case SML_MANAGER_SESSION_NEW: smlTrace(TRACE_INTERNAL, "%s: Just received a new session with ID %s", __func__, VA_STRING(smlSessionGetSessionID(session))); if (dsObject->session) { smlTrace(TRACE_INTERNAL, "%s: WARNING: There was an old session %s in the environment.", __func__, VA_STRING(smlSessionGetSessionID(dsObject->session))); smlSessionUnref(dsObject->session); dsObject->session = NULL; } smlSessionUseStringTable(session, dsObject->useStringTable); smlSessionUseOnlyReplace(session, dsObject->onlyReplace); smlSessionUseNumberOfChanges(session, dsObject->useNumberOfChanges); smlTrace(TRACE_INTERNAL, "%s: maxObjSize %d", __func__, dsObject->maxObjSize); dsObject->session = session; smlSessionRef(session); /* authentication management for OMA DS clients*/ if (dsObject->dsType == SML_SESSION_TYPE_CLIENT && (dsObject->username || dsObject->password)) { /* prepare credential */ SmlCred *cred = smlCredNewAuth(dsObject->authType, dsObject->username, dsObject->password, &error); if (!cred) goto error; smlSessionRegisterCred(dsObject->session, cred); smlTrace(TRACE_INTERNAL, "%s: credential initialized", __func__); } break; case SML_MANAGER_SESSION_FINAL: smlTrace(TRACE_INTERNAL, "%s: Session %s reported final", __func__, VA_STRING(smlSessionGetSessionID(session))); /* determine which package was received */ if (dsObject->dsType == SML_SESSION_TYPE_CLIENT) { /* only devinf receiving is not supported */ if (dsObject->actualPackage < SML_PACKAGE_1) dsObject->actualPackage = SML_PACKAGE_1; else dsObject->actualPackage += 2; } else { // SML_SESSION_TYPE_SERVER /* only devinf receiving is not supported */ if (dsObject->actualPackage < SML_PACKAGE_2) dsObject->actualPackage = SML_PACKAGE_2; else dsObject->actualPackage += 2; } smlTrace(TRACE_INTERNAL, "%s: package == %d", __func__, dsObject->actualPackage); /* start callbacks etc. according to state */ switch(dsObject->actualPackage) { case SML_PACKAGE_1: /* SAN received by client */ /* This is the best position to check for * the availability of the remote device * information. If it is not present then * the own device information is send and * the remote ones is requested. */ if (!smlDataSyncManageDevInf(dsObject, TRUE, &error)) goto error; if (!smlSessionFlush(dsObject->session, TRUE, &error)) goto error; break; case SML_PACKAGE_2: /* alerts received by server */ /* This is the best position to check for * the availability of the remote device * information. If it is not present then * the own device information is send and * the remote ones is requested. */ if (!smlDataSyncManageDevInf(dsObject, TRUE, &error)) goto error; if (!smlSessionFlush(dsObject->session, TRUE, &error)) goto error; smlDataSyncSendEvent( dsObject, SML_DATA_SYNC_EVENT_GOT_ALL_ALERTS, dsObject->eventUserdata, NULL); break; case SML_PACKAGE_3: /* alerts received by client */ smlDataSyncSendEvent( dsObject, SML_DATA_SYNC_EVENT_GOT_ALL_ALERTS, dsObject->eventUserdata, NULL); break; case SML_PACKAGE_4: /* syncs received by server */ smlDataSyncSendEvent( dsObject, SML_DATA_SYNC_EVENT_GOT_ALL_CHANGES, dsObject->eventUserdata, NULL); break; case SML_PACKAGE_5: /* syncs received by client */ if (!smlDataSyncSendMap(dsObject, &error)) goto error; if (!smlSessionFlush(dsObject->session, TRUE, &error)) goto error; smlDataSyncSendEvent( dsObject, SML_DATA_SYNC_EVENT_GOT_ALL_CHANGES, dsObject->eventUserdata, NULL); break; case SML_PACKAGE_6: /* map received by server */ if (!smlSessionFlush(dsObject->session, TRUE, &error)) goto error; break; case SML_PACKAGE_END: /* end received by client */ /* everything done */ /* auto disconnect by library */ break; default: smlErrorSet(&error, SML_ERROR_NOT_IMPLEMENTED, "The package %d is actually not supported.", dsObject->actualPackage); goto error; } break; case SML_MANAGER_SESSION_END: smlTrace(TRACE_INTERNAL, "%s: Session %s has ended", __func__, VA_STRING(smlSessionGetSessionID(session))); SmlLink *link_ = smlManagerSessionGetLink( dsObject->manager, dsObject->session, &error); if (!link_ && error) goto error; /* OBEX is a stateful protocol and the client should * init the disconnect. The problem is what happens * when the client hangs? * * if (dsObject->tspType != SML_TRANSPORT_OBEX_SERVER && * !smlTransportDisconnect(dsObject->tsp, link, &error)) */ if (!smlTransportDisconnect(dsObject->tsp, link_, &error)) { if (link_) smlLinkDeref(link_); goto error; } if (link_) smlLinkDeref(link_); break; case SML_MANAGER_SESSION_ERROR: if (session) smlTrace(TRACE_INTERNAL, "There was an error in the session %s: %s", VA_STRING(smlSessionGetSessionID(session)), smlErrorPrint(&error)); else smlTrace(TRACE_INTERNAL, "There was a general error in the manager. %s", smlErrorPrint(&error)); goto error; break; case SML_MANAGER_SESSION_WARNING: g_warning("WARNING: %s\n", smlErrorPrint(&error)); break; default: g_warning("%s: Unknown event received: %d.", __func__, type); break; } g_mutex_unlock(dsObject->managerMutex); smlTrace(TRACE_EXIT, "%s", __func__); return; error: g_mutex_unlock(dsObject->managerMutex); smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(&error)); smlDataSyncSendEvent( dsObject, SML_DATA_SYNC_EVENT_ERROR, dsObject->eventUserdata, error); } /* *************************************** */ /* ***** DsSession Callbacks ***** */ /* *************************************** */ void smlDataSyncDatastoreConnectCallback( SmlDsSession *dsession, void *userdata) { smlTrace(TRACE_ENTRY, "%s(%p, %p)", __func__, dsession, userdata); smlAssert(dsession); smlAssert(userdata); SmlDataSyncDatastore *datastore = userdata; SmlDataSyncObject *dsObject = datastore->dsObject; /* The session is required here. So if the session is missing * then the function has to block here. This is no real problem * because the SESSION_EVENT_NEW must already be in the queue of * the manager object. */ while (!dsObject->session) { smlManagerDispatch(dsObject->manager); } /* set callbacks if the DsSession was not ready before */ if (!datastore->session || datastore->session != dsession) { smlTrace(TRACE_INTERNAL, "%s: should be an OMA DS server", __func__); smlAssert(dsObject->funcDatastoreAlert); datastore->session = dsession; smlDsSessionGetAlert(datastore->session, dsObject->funcDatastoreAlert, datastore); if (dsObject->changeCallback) { smlDsSessionGetSync(datastore->session, smlDataSyncSyncCallback, datastore); smlDsSessionGetChanges(datastore->session, smlDataSyncChangeCallback, datastore); smlDsSessionGetMapping(datastore->session, smlDataSyncMappingCallback, datastore); } smlDsSessionRef(dsession); } smlTrace(TRACE_EXIT, "%s", __func__); return; #if 0 /* UNUSED */ error: smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(&error)); smlDataSyncSendEvent( dsObject, SML_DATA_SYNC_EVENT_ERROR, dsObject->eventUserdata, error); #endif /* UNUSED */ } /* *********************************** */ /* ***** Alert Callbacks ***** */ /* *********************************** */ void smlDataSyncAlertStatusCallback( SmlSession *session, SmlStatus *status, void *userdata) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, session, status, userdata); SmlDataSyncDatastore *datastore = userdata; /* If we talk as an OMA DS client with server like an OCS * then it can happen that this server denies the alert * because of an internal problem. * Example OCS: If there is an error inside of an SyncML session * then you must wait a configured time before you * can again sucessfully connect this server. * Typically the server responds with error 503. */ unsigned int code = smlStatusGetCode(status); if (code >= 300 && code != SML_ERROR_REQUIRE_REFRESH) { /* This is an error. */ SmlError *error = NULL; smlErrorSet(&error, SML_ERROR_GENERIC, "The alert response signals an error - %d.", code); smlErrorRef(&error); smlDataSyncSendEvent( datastore->dsObject, SML_DATA_SYNC_EVENT_ERROR, datastore->dsObject->eventUserdata, error); smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(&error)); smlErrorDeref(&error); } else { smlTrace(TRACE_EXIT, "%s", __func__); } } /* ********************************** */ /* ***** Sync Callbacks ***** */ /* ********************************** */ void smlDataSyncSyncCallback( SmlDsSession *dsession, unsigned int numchanges, void *userdata) { smlTrace(TRACE_ENTRY, "%s(%p, %i, %p)", __func__, dsession, numchanges, userdata); SmlDataSyncDatastore *datastore = userdata; SmlError *error = NULL; /* If the device information was not sent together with the * alerts and it was not cached then the device information * can be received together with the sync command(s). * This can happen with OMA DS clients and servers. */ if (!smlDataSyncManageDevInf(datastore->dsObject, FALSE, &error)) goto error; smlTrace(TRACE_EXIT, "%s", __func__); return; error: smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(&error)); smlDataSyncSendEvent( datastore->dsObject, SML_DATA_SYNC_EVENT_ERROR, datastore->dsObject->eventUserdata, error); } void smlDataSyncSyncStatusCallback( SmlSession *session, SmlStatus *status, void *userdata) { smlTrace(TRACE_ENTRY, "%s(%p, %p)", __func__, session, status, userdata); SmlDataSyncDatastore *datastore = userdata; if (smlStatusGetClass(status) != SML_ERRORCLASS_SUCCESS) { // inform user smlTrace(TRACE_INTERNAL, "%s: The synchronisation request failed.", __func__); smlTrace(TRACE_INTERNAL, "%s: Location => %s", __func__, VA_STRING(datastore->dsObject->url)); smlTrace(TRACE_INTERNAL, "%s: Database => %s", __func__, VA_STRING(datastore->sourceUri)); smlTrace(TRACE_INTERNAL, "%s: Error => %d", __func__, smlStatusGetCode(status)); if (smlStatusGetCode(status) == SML_ERROR_SERVICE_UNAVAILABLE && (strstr(datastore->dsObject->url, "ocst") || strstr(datastore->dsObject->url, "ocas"))) { /* this is a potential Oracle Collaboration Suite */ /* typical errorcode from OCS if there is something wrong */ smlTrace(TRACE_INTERNAL, "%s: Oracle Collaboration Suite detected.", __func__); smlTrace(TRACE_INTERNAL, "%s: Typical undefined error from OCS (503 - SyncML timeout error).", __func__); smlTrace(TRACE_INTERNAL, "%s: Please wait 5 minutes before retry - default session timeout.", __func__); } // stop session // FIXME: this is not available in a clean way today // FIXME: we need a session state // FIXME: osync must be signalled // FIXME: we need a mutex lock on database->env // smlSessionEnd(database->env->session, NULL); // printf(" Session finished.\n"); // smlManagerSessionRemove(database->env->manager, database->env->session); // smlManagerStop(database->env->manager); // smlManagerQuit(database->env->manager); // printf(" Manager finished.\n"); SmlError *error = NULL; smlErrorSet(&error, smlStatusGetCode(status), "Sync failed with error %d.", smlStatusGetCode(status)); smlErrorRef(&error); smlDataSyncSendEvent( datastore->dsObject, SML_DATA_SYNC_EVENT_ERROR, datastore->dsObject->eventUserdata, error); smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(&error)); smlErrorDeref(&error); } else { smlTrace(TRACE_EXIT, "%s", __func__); } } /* ************************************ */ /* ***** Change Callbacks ***** */ /* ************************************ */ SmlBool smlDataSyncChangeCallback( SmlDsSession *dsession, SmlChangeType type, const char *uid, char *data, unsigned int size, const char *contenttype, void *userdata, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %i, %s, %p, %i, %s, %p, %p)", __func__, dsession, type, VA_STRING(uid), data, size, VA_STRING(contenttype), userdata, error); CHECK_ERROR_REF SmlDataSyncDatastore *datastore = userdata; smlAssert(type); smlAssert(datastore); smlAssert(datastore->dsObject); smlAssert(datastore->dsObject->changeCallback); /* some mobiles sends replace commands during slow-sync */ if (datastore->alertType == SML_ALERT_SLOW_SYNC && type == SML_CHANGE_REPLACE) type = SML_CHANGE_ADD; /* decode base64 data if necessary */ size_t appClassLength = ((size_t) index(datastore->contentType, '/')) - ((size_t) datastore->contentType); if ( ( strstr(datastore->contentType, SML_CONTENT_TYPE_APPLICATION) == datastore->contentType && appClassLength == strlen(SML_CONTENT_TYPE_APPLICATION) ) || ( strstr(datastore->contentType, SML_CONTENT_TYPE_AUDIO) == datastore->contentType && appClassLength == strlen(SML_CONTENT_TYPE_AUDIO) ) || ( strstr(datastore->contentType, SML_CONTENT_TYPE_IMAGE) == datastore->contentType && appClassLength == strlen(SML_CONTENT_TYPE_IMAGE) ) || ( strstr(datastore->contentType, SML_CONTENT_TYPE_MESSAGE) == datastore->contentType && appClassLength == strlen(SML_CONTENT_TYPE_MESSAGE) ) || ( strstr(datastore->contentType, SML_CONTENT_TYPE_VIDEO) == datastore->contentType && appClassLength == strlen(SML_CONTENT_TYPE_AUDIO) ) ) { /* binary data must be base64 encoded */ char *b64data = data; size_t length = 0; data = (char *) g_base64_decode(b64data, &length); size = length; smlSafeCFree(&b64data); if (!data) { smlErrorSet(error, SML_ERROR_GENERIC, "The base 64 decoding of glib failed."); goto error; } } /* perform callback */ if (!datastore->dsObject->changeCallback( datastore->dsObject, datastore->sourceUri, type, uid, data, size, datastore->dsObject->changeUserdata, error)) goto error; /* if this is a client then the callback should add a mapping */ smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error: smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(error)); return FALSE; } void smlDataSyncChangeStatusCallback( SmlDsSession *dsession, SmlStatus *status, const char *newuid, void *userdata) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %s, %p)", __func__, dsession, status, VA_STRING(newuid), userdata); SmlError *error = NULL; smlAssert(userdata); SmlDataSyncChange *change = userdata; SmlDataSyncDatastore *datastore = change->datastore; SmlDataSyncObject *dsObject = datastore->dsObject; smlAssert(dsObject); if (dsObject->changeStatusCallback && !dsObject->changeStatusCallback( dsObject, smlStatusGetCode(status), newuid, change->userdata, &error)) goto error; smlTrace(TRACE_EXIT, "%s", __func__); return; error: smlErrorRef(&error); smlDataSyncSendEvent( dsObject, SML_DATA_SYNC_EVENT_ERROR, dsObject->eventUserdata, error); smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(&error)); smlErrorDeref(&error); } void smlDataSyncMappingCallback( SmlDsSession *dsession, SmlLocation *orig, SmlLocation *newuid, void *userdata) { smlTrace(TRACE_ENTRY, "%s(%p, %s, %s, %p)", __func__, dsession, VA_STRING(smlLocationGetURI(orig)), VA_STRING(smlLocationGetURI(newuid)), userdata); SmlError *error = NULL; SmlDataSyncDatastore *datastore = userdata; smlAssert(datastore); smlAssert(datastore->dsObject); smlAssert(datastore->dsObject->mappingCallback); /* perform callback */ if (!datastore->dsObject->mappingCallback( datastore->dsObject, datastore->sourceUri, smlLocationGetURI(orig), smlLocationGetURI(newuid), datastore->dsObject->mappingUserdata, &error)) goto error; smlTrace(TRACE_EXIT, "%s", __func__); return; error: smlErrorRef(&error); smlDataSyncSendEvent( datastore->dsObject, SML_DATA_SYNC_EVENT_ERROR, datastore->dsObject->eventUserdata, error); smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(&error)); smlErrorDeref(&error); } /* ********************************* */ /* ***** Map Callbacks ***** */ /* ********************************* */ void smlDataSyncMapStatusCallback( SmlSession *session, SmlStatus *status, void *userdata) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, session, status, userdata); if (smlStatusGetClass(status) != SML_ERRORCLASS_SUCCESS) { SmlDataSyncDatastore *datastore = userdata; SmlError *error = NULL; smlErrorSet(&error, smlStatusGetCode(status), "Map of datastore %s was rejected with error code %d", datastore->sourceUri, smlStatusGetCode(status)); smlDataSyncSendEvent( datastore->dsObject, SML_DATA_SYNC_EVENT_ERROR, datastore->dsObject->eventUserdata, error); } smlTrace(TRACE_EXIT, "%s", __func__); } /* ******************************************* */ /* ***** Authentication Callback ***** */ /* ******************************************* */ SmlBool smlDataSyncVerifyUserCallback( SmlChal *chal, SmlCred *cred, const char *username, void *userdata, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %s, %p)", __func__, chal, cred, VA_STRING(username), userdata); CHECK_ERROR_REF SmlDataSyncObject *dsObject = userdata; /* We have only one user and not a whole user database. */ smlTrace(TRACE_EXIT, "%s", __func__); return smlAuthVerify(chal, cred, dsObject->username, dsObject->password, error); } libsyncml-0.5.4/libsyncml/data_sync_api/data_sync_loop.h100644 1750 1750 2143 11211710410 23362 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2008 Michael Bell * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #ifndef _SML_DATA_SYNC_LOOP_H_ #define _SML_DATA_SYNC_LOOP_H_ #include "data_sync.h" SmlBool smlDataSyncLoopStart( SmlDataSyncObject *dsObject, SmlError **error); void smlDataSyncLoopStop(SmlDataSyncObject *dsObject); #endif /* _SML_DATA_SYNC_LOOP_H_ */ libsyncml-0.5.4/libsyncml/data_sync_api/transport_http_client.c100644 1750 1750 11502 11211710410 25027 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2008-2009 Michael Bell * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include "transport.h" #include "libsyncml/sml_error_internals.h" #include "libsyncml/sml_support.h" #include "data_sync_client.h" #include "data_sync_devinf.h" SmlBool smlDataSyncTransportHttpClientInit( SmlDataSyncObject *dsObject, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p)", __func__, dsObject, error); CHECK_ERROR_REF if (dsObject->url != NULL && !smlTransportSetConfigOption( dsObject->tsp, SML_TRANSPORT_CONFIG_URL, dsObject->url, error)) goto error; if (dsObject->username != NULL && !smlTransportSetConfigOption( dsObject->tsp, SML_TRANSPORT_CONFIG_USERNAME, dsObject->username, error)) goto error; if (dsObject->password != NULL && !smlTransportSetConfigOption( dsObject->tsp, SML_TRANSPORT_CONFIG_PASSWORD, dsObject->password, error)) goto error; smlTrace(TRACE_EXIT, "%s - TRUE", __func__); return TRUE; error: smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(error)); return FALSE; } static SmlBool smlDataSyncTransportHttpClientInitNewSession (SmlDataSyncObject *dsObject, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p)", __func__, dsObject, error); smlAssert(dsObject->url); smlAssert(dsObject->identifier); smlAssert(dsObject->tsp); smlAssert(dsObject->manager); smlAssert(dsObject->agent); SmlLocation *target = NULL; SmlLocation *source = NULL; /* If there is an old session then this is a bug. * the high level API only support one session per * OMA DS object. */ if (dsObject->session) { smlErrorSet(error, SML_ERROR_GENERIC, "Only one SyncML session is allowed per SmlDataSyncObject instance."); goto error; } /* create session */ target = smlLocationNew(dsObject->target, NULL, error); if (!target) goto error; source = smlLocationNew(dsObject->identifier, NULL, error); if (!source) goto error; char *sessionString = smlManagerGetNewSessionID(dsObject->manager); dsObject->session = smlSessionNew(SML_SESSION_TYPE_CLIENT, dsObject->useWbxml?SML_MIMETYPE_WBXML:SML_MIMETYPE_XML, dsObject->version, SML_PROTOCOL_SYNCML, target, source, sessionString, 0, error); smlSafeCFree(&sessionString); if (!dsObject->session) goto error; smlLocationUnref(target); target = NULL; smlLocationUnref(source); source = NULL; /* register all the add-ons */ if (!smlManagerSessionAdd(dsObject->manager, dsObject->session, NULL, error)) goto error; if (!smlDevInfAgentRegisterSession(dsObject->agent, dsObject->manager, dsObject->session, error)) goto error; smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error: if (target) { smlLocationUnref(target); target = NULL; } if (source) { smlLocationUnref(source); source = NULL; } smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(error)); return FALSE; } SmlBool smlDataSyncTransportHttpClientConnect(SmlDataSyncObject *dsObject, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p)", __func__, dsObject, error); CHECK_ERROR_REF /* init new session */ if (!smlDataSyncTransportHttpClientInitNewSession(dsObject, error)) goto error; /* send the device information */ if (!smlDataSyncManageDevInf(dsObject, TRUE, error)) goto error; smlTrace(TRACE_INTERNAL, "%s: sent devinf", __func__); /* prepare correct alert type */ GList *o = dsObject->datastores; for (; o; o = o->next) { SmlDataSyncDatastore *datastore = o->data; if (!smlDataSyncClientSendAlert(datastore, SML_ALERT_UNKNOWN, error)) goto error; } smlTrace(TRACE_INTERNAL, "%s: all datastores created their alerts", __func__); /* If no SAN and no server alerted sync is used * then we must set the actual package to 1. * Otherwise the state management thinks the first * received final is part of a SAN package. */ dsObject->actualPackage = SML_PACKAGE_1; /* flush package 1 */ if (!smlSessionFlush(dsObject->session, TRUE, error)) goto error; smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error: smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(error)); return FALSE; } libsyncml-0.5.4/libsyncml/data_sync_api/data_sync_devinf.h100644 1750 1750 3034 11211710410 23664 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2008 Michael Bell * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #ifndef _SML_DATA_SYNC_DEVINF_H #define _SML_DATA_SYNC_DEVINF_H #include "data_sync.h" SmlBool smlDataSyncDevInfAddDatastore( SmlDevInf *devinf, SmlDataSyncDatastore *datastore, SmlError **error); SmlBool smlDataSyncDevInfStore( SmlDevInf *devinf, const char *filename, SmlError **error); SmlBool smlDataSyncDevInfLoadRemote( SmlDataSyncObject *dsObject, SmlBool sendGet, SmlError **error); char *smlDataSyncDevInfGetIdentifier(); SmlBool smlDataSyncDevInfInit( SmlDataSyncObject *dsObject, SmlDevInfDevTyp type, SmlError **error); SmlBool smlDataSyncManageDevInf( SmlDataSyncObject *dsObject, SmlBool sendGet, SmlError **error); #endif //_SML_DATA_SYNC_DEVINF_H libsyncml-0.5.4/libsyncml/data_sync_api/data_sync_server.c100644 1750 1750 21111 11211710410 23726 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2008-2009 Michael Bell * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include "data_sync_server.h" #include "data_sync_common.h" #include "libsyncml/sml_error_internals.h" #include "data_sync_callbacks.h" #include "libsyncml/objects/sml_ds_server.h" #include "data_sync_devinf.h" #include "libsyncml/sml_support.h" static SmlBool smlDataSyncServerAlertCallback( SmlDsSession *dsession, SmlAlertType recvType, const char *last, const char *next, void *userdata) { smlTrace(TRACE_ENTRY, "%s(%p, %i, %s, %s, %p)", __func__, dsession, recvType, VA_STRING(last), VA_STRING(next), userdata); SmlDataSyncDatastore *datastore = userdata; SmlDataSyncObject *dsObject = datastore->dsObject; SmlBool ret = TRUE; SmlError *error = NULL; SmlAlertType sentType = recvType; /* libsyncml only supports SML_ALERT_TWO_WAY and SML_ALERT_SLOW_SYNC * but some old phones reply on a SAN alert 206 with a slow sync 201 * alert or a SAN alert 206 (insteed of a normal two way alert 200). * Therefore it is necessary to check for TWO_WAY and TWO_WAY_BY_SERVER. */ if (recvType != SML_ALERT_TWO_WAY && recvType != SML_ALERT_SLOW_SYNC && recvType != SML_ALERT_TWO_WAY_BY_SERVER) { smlErrorSet(&error, SML_ERROR_NOT_IMPLEMENTED, "Unsupported alert type %d.", recvType); goto error; } char *remote_key = g_strdup_printf("remoteanchor%s", smlDsSessionGetLocation(dsession)); datastore->remoteNext = g_strdup(next); /* We return FALSE if we need a special return code as answer: * SML_ERROR_REQUIRE_REFRESH 508 * This return code enforces a SLOW-SYNC. */ if (recvType == SML_ALERT_TWO_WAY || recvType == SML_ALERT_TWO_WAY_BY_SERVER) { if (!last) { smlTrace(TRACE_INTERNAL, "%s: TWO-WAY-SYNC but last is missing", __func__); sentType = SML_ALERT_SLOW_SYNC; ret = FALSE; } else { char *cached = NULL; if (dsObject->getAnchorCallback) cached = dsObject->getAnchorCallback( dsObject, remote_key, dsObject->getAnchorUserdata, &error); if (!cached && error) goto error; if (!cached || strcmp(cached, last)) { smlTrace(TRACE_INTERNAL, "%s: TWO-WAY-SYNC but received LAST(%s) and cached LAST (%s) mismatch", __func__, VA_STRING(last), VA_STRING(cached)); if (cached) smlSafeCFree(&cached); sentType = SML_ALERT_SLOW_SYNC; ret = FALSE; } } } if (dsObject->getAlertTypeCallback) { SmlAlertType alertType; alertType = dsObject->getAlertTypeCallback( dsObject, datastore->sourceUri, sentType, dsObject->getAlertTypeUserdata, &error); if (alertType == SML_ALERT_UNKNOWN || error) goto error; if (alertType == SML_ALERT_SLOW_SYNC && alertType != recvType) ret = FALSE; /* REQUIRE REFRESH */ sentType = alertType; } smlSafeCFree(&remote_key); /* If the getAnchorCallback and the getAlertTypeCallback * return inconsistent data then this must be detected here. * Inconsistent means that for example status 508 and alert * type 200 are used together which is illegal. */ if ( ( /* alert 200 => alert 200 + status 508 */ recvType != SML_ALERT_SLOW_SYNC && sentType != SML_ALERT_SLOW_SYNC && ret == FALSE ) || ( /* alert 200 => alert 201 + status 200 */ recvType != SML_ALERT_SLOW_SYNC && sentType == SML_ALERT_SLOW_SYNC && ret != FALSE ) || ( /* alert 201 => alert 200 */ recvType == SML_ALERT_SLOW_SYNC && sentType != SML_ALERT_SLOW_SYNC ) || ( /* alert 201 => alert 201 + status 508 */ recvType == SML_ALERT_SLOW_SYNC && sentType == SML_ALERT_SLOW_SYNC && ret == FALSE ) ) { if (ret) { smlErrorSet(&error, SML_ERROR_GENERIC, "The library user tries to respond an alert %d " \ "with an alert %d and status 200 which is illegal.", recvType, sentType); } else { smlErrorSet(&error, SML_ERROR_GENERIC, "The library user tries to respond an alert %d " \ "with an alert %d and status 508 which is illegal.", recvType, sentType); } goto error; } /* generate new timestamp for local anchors */ char *local_key = g_strdup_printf("localanchor%s", smlDsSessionGetLocation(dsession)); char *local_last = NULL; if (dsObject->getAnchorCallback) local_last = dsObject->getAnchorCallback( dsObject, local_key, dsObject->getAnchorUserdata, &error); if (!local_last && error) goto error; if (datastore->localNext) smlSafeCFree(&(datastore->localNext)); if (local_last == NULL || strlen(local_last) == 0) { /* this is the first sync * let's respect the remote's anchor style */ if (smlDataSyncIsTimestamp(next, dsObject->useTimestampAnchor) != dsObject->useTimestampAnchor) { /* Many users are confused by warnings which can be ignored. * Therefore the issue is only traced. */ smlTrace(TRACE_INTERNAL, "%s: libsyncml uses different timestamp anchor modes.", __func__); } } datastore->localNext = smlDataSyncGetNextAnchor(datastore, local_last, &error); if (!datastore->localNext) goto error; /* send alert */ if (!smlDsSessionSendAlert( dsession, sentType, local_last, datastore->localNext, smlDataSyncAlertStatusCallback, datastore, &error)) goto error; /* free local anchor stuff */ smlSafeCFree(&local_key); if (local_last) smlSafeCFree(&local_last); smlTrace(TRACE_EXIT, "%s: %i", __func__, ret); return ret; error: smlErrorRef(&error); smlDataSyncSendEvent( dsObject, SML_DATA_SYNC_EVENT_ERROR, dsObject->eventUserdata, error); smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(&error)); smlErrorDeref(&error); return FALSE; } SmlBool smlDataSyncServerInit(SmlDataSyncObject *dsObject, SmlError **error) { CHECK_ERROR_REF /* The manager responsible for handling the other objects */ dsObject->manager = smlManagerNew(dsObject->tsp, error); if (!dsObject->manager) goto error; smlManagerSetEventCallback(dsObject->manager, smlDataSyncEventCallback, dsObject); smlManagerSetLocalMaxMsgSize(dsObject->manager, dsObject->maxMsgSize); smlManagerSetLocalMaxObjSize(dsObject->manager, dsObject->maxObjSize); /* set server specific callbacks */ dsObject->funcDatastoreAlert = smlDataSyncServerAlertCallback; /* The authenticator */ dsObject->auth = smlAuthNew(error); if (!dsObject->auth) goto error; smlAuthSetVerifyCallback(dsObject->auth, smlDataSyncVerifyUserCallback, dsObject); if (!dsObject->username) { smlAuthSetEnable(dsObject->auth, FALSE); } else { smlAuthSetEnable(dsObject->auth, TRUE); smlAuthSetType(dsObject->auth, dsObject->authType); } if (!smlAuthRegister(dsObject->auth, dsObject->manager, error)) goto error; /* prepare device info */ if (!smlDataSyncDevInfInit(dsObject, SML_DEVINF_DEVTYPE_SERVER, error)) goto error; /* prepare datastore server */ GList *o = dsObject->datastores; for (; o; o = o->next) { SmlDataSyncDatastore *datastore = o->data; /* We now create the ds server hat the given location */ SmlLocation *loc = smlLocationNew(datastore->sourceUri, NULL, error); if (!loc) goto error; datastore->server = smlDsServerNew(datastore->contentType, loc, error); if (!datastore->server) { smlLocationUnref(loc); goto error; } smlLocationUnref(loc); if (!smlDsServerRegister(datastore->server, dsObject->manager, error)) goto error; smlDsServerSetConnectCallback( datastore->server, smlDataSyncDatastoreConnectCallback, datastore); /* And we also add the devinfo to the devinf agent */ if (!smlDataSyncDevInfAddDatastore(dsObject->localDevInf, datastore, error)) goto error; } /* Run the manager */ if (!smlManagerStart(dsObject->manager, error)) goto error; /* Initialize the Transport */ if (!smlTransportInitialize(dsObject->tsp, error)) goto error; smlTrace(TRACE_EXIT, "%s - TRUE", __func__); return TRUE; error: smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(error)); return FALSE; } libsyncml-0.5.4/libsyncml/data_sync_api/data_sync_common.h100644 1750 1750 2232 11211710410 23700 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2008 Michael Bell * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #ifndef _SML_DATA_SYNC_COMMON_H_ #define _SML_DATA_SYNC_COMMON_H_ #include "data_sync.h" SmlBool smlDataSyncIsTimestamp(const char *anchor, SmlBool timestampDefault); char *smlDataSyncGetNextAnchor( SmlDataSyncDatastore *datastore, const char *last, SmlError **error); #endif /* _SML_DATA_SYNC_COMMON_H_ */ libsyncml-0.5.4/libsyncml/data_sync_api/transport.h100644 1750 1750 3014 11211710410 22416 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2008 Michael Bell * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #ifndef _SML_DATA_SYNC_TRANSPORT_H_ #define _SML_DATA_SYNC_TRANSPORT_H_ #include "data_sync.h" /* OBEX client */ SmlBool smlDataSyncTransportObexClientInit( SmlDataSyncObject *dsObject, SmlError **error); SmlBool smlDataSyncTransportObexClientConnect( SmlDataSyncObject *dsObject, SmlError **error); /* HTTP client */ SmlBool smlDataSyncTransportHttpClientInit( SmlDataSyncObject *dsObject, SmlError **error); SmlBool smlDataSyncTransportHttpClientConnect( SmlDataSyncObject *dsObject, SmlError **error); /* HTTP server */ SmlBool smlDataSyncTransportHttpServerInit( SmlDataSyncObject *dsObject, SmlError **error); #endif /* _SML_DATA_SYNC_TRANSPORT_H_ */ libsyncml-0.5.4/libsyncml/data_sync_api/defines.h100644 1750 1750 7544 11211710410 22013 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2008-2009 Michael Bell * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ /** * @defgroup PublicHighLevelDefines High Level Defines * @ingroup PublicHighLevelAPI * @brief The defines of the high level data synchronization API. * * The defines can be splitted in two types of definitions - * default limits and configuration options. * * The default limits are used to configure the API * but they are defined in a public header file to * grant access of external applications to the used * limits of the library. * * The configuration options are defined to avoid typos and * guarantee via compile errors that typos in the source * code of a library user cause no runtime problems. * * Additionally it is possible to extend the number of supported * options without changing the major version of the library. */ /*@{*/ #ifndef _SML_DATA_SYNC_API_CONFIG_H_ #define _SML_DATA_SYNC_API_CONFIG_H_ #ifdef __cplusplus extern "C" { #endif #include /* SyncML default limitations */ #define SML_DEFAULT_MAX_MSG_SIZE 65535 #define SML_DEFAULT_MAX_OBJ_SIZE 1024000 /* Data Synchronization config API defines */ #define SML_DATA_SYNC_CONFIG_CONNECTION_TYPE "CONNECTION_TYPE" #define SML_DATA_SYNC_CONFIG_CONNECTION_SERIAL "SERIAL" #define SML_DATA_SYNC_CONFIG_CONNECTION_BLUETOOTH "BLUETOOTH" #define SML_DATA_SYNC_CONFIG_CONNECTION_IRDA "IRDA" #define SML_DATA_SYNC_CONFIG_CONNECTION_NET "NET" #define SML_DATA_SYNC_CONFIG_CONNECTION_USB "USB" #define SML_DATA_SYNC_CONFIG_AUTH_USERNAME SML_TRANSPORT_CONFIG_USERNAME #define SML_DATA_SYNC_CONFIG_AUTH_PASSWORD SML_TRANSPORT_CONFIG_PASSWORD #define SML_DATA_SYNC_CONFIG_AUTH_TYPE "AUTH_TYPE" #define SML_DATA_SYNC_CONFIG_AUTH_BASIC "AUTH_BASIC" #define SML_DATA_SYNC_CONFIG_AUTH_NONE "AUTH_NONE" #define SML_DATA_SYNC_CONFIG_AUTH_MD5 "AUTH_MD5" #define SML_DATA_SYNC_CONFIG_VERSION "VERSION" #define SML_DATA_SYNC_CONFIG_IDENTIFIER "IDENTIFIER" #define SML_DATA_SYNC_CONFIG_TARGET "TARGET" #define SML_DATA_SYNC_CONFIG_USE_WBXML "USE_WBXML" #define SML_DATA_SYNC_CONFIG_USE_STRING_TABLE "USE_STRING_TABLE" #define SML_DATA_SYNC_CONFIG_USE_TIMESTAMP_ANCHOR "USE_TIMESTAMP_ANCHOR" #define SML_DATA_SYNC_CONFIG_USE_NUMBER_OF_CHANGES "USE_NUMBER_OF_CHANGES" #define SML_DATA_SYNC_CONFIG_USE_LOCALTIME "USE_LOCALTIME" #define SML_DATA_SYNC_CONFIG_ONLY_REPLACE "ONLY_REPLACE" #define SML_DATA_SYNC_CONFIG_MAX_MSG_SIZE "MAX_MSG_SIZE" #define SML_DATA_SYNC_CONFIG_MAX_OBJ_SIZE "MAX_OBJ_SIZE" #define SML_DATA_SYNC_CONFIG_FAKE_DEVICE "FAKE_DEVICE" #define SML_DATA_SYNC_CONFIG_FAKE_MANUFACTURER "FAKE_MANUFACTURER" #define SML_DATA_SYNC_CONFIG_FAKE_MODEL "FAKE_MODEL" #define SML_DATA_SYNC_CONFIG_FAKE_SOFTWARE_VERSION "FAKE_SOFTWARE_VERSION" #define SML_CONTENT_TYPE_APPLICATION "application" #define SML_CONTENT_TYPE_AUDIO "audio" #define SML_CONTENT_TYPE_IMAGE "image" #define SML_CONTENT_TYPE_MESSAGE "message" #define SML_CONTENT_TYPE_VIDEO "video" #ifdef __cplusplus } #endif #endif /* _SML_DATA_SYNC_API_CONFIG_H_ */ /*@}*/ libsyncml-0.5.4/libsyncml/data_sync_api/data_sync_client.h100644 1750 1750 2244 11211710410 23671 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2008 Michael Bell * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #ifndef _SML_DATA_SYNC_CLIENT_H_ #define _SML_DATA_SYNC_CLIENT_H_ #include "data_sync.h" SmlBool smlDataSyncClientInit( SmlDataSyncObject *dsObject, SmlError **error); SmlBool smlDataSyncClientSendAlert( SmlDataSyncDatastore *datastore, SmlAlertType type, SmlError **error); #endif /* _SML_DATA_SYNC_SERVER_H_ */ libsyncml-0.5.4/libsyncml/data_sync_api/data_sync.c100644 1750 1750 67164 11211710410 22362 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2008-2009 Michael Bell * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include "../syncml.h" #include "../syncml_internals.h" #include "../sml_error_internals.h" #include #include #include /* required because of function index */ #include #include "data_sync.h" #include "data_sync_client.h" #include "data_sync_server.h" #include "data_sync_callbacks.h" #include "data_sync_callbacks.h" #include "data_sync_devinf.h" #include "data_sync_loop.h" #include "transport.h" #include "libsyncml/objects/sml_ds_server_internals.h" /* ********************************* */ /* object creation and configuration */ /* ********************************* */ SmlDataSyncObject *smlDataSyncNew( SmlSessionType dsType, SmlTransportType tspType, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%d, %d, %p)", __func__, dsType, tspType, error); CHECK_ERROR_REF smlTrace(TRACE_INTERNAL, "%s: libsyncml version: %s", __func__, VERSION); SmlDataSyncObject *dsObject = smlTryMalloc0(sizeof(SmlDataSyncObject), error); if (!dsObject) goto error; smlDataSyncObjectRef(dsObject); dsObject->dsType = dsType; dsObject->tspType = tspType; dsObject->version = SML_VERSION_11; dsObject->internalState = SML_DATA_SYNC_STATE_NEW; dsObject->useNumberOfChanges = TRUE; dsObject->useTimestampAnchor = TRUE; dsObject->maxObjSize = SML_DEFAULT_MAX_OBJ_SIZE; dsObject->maxMsgSize = SML_DEFAULT_MAX_MSG_SIZE; dsObject->tsp = smlTransportNew(tspType, error); if (!dsObject->tsp) goto error; switch(tspType) { case SML_TRANSPORT_OBEX_CLIENT: dsObject->funcTspInit = smlDataSyncTransportObexClientInit; dsObject->funcTspConnect = smlDataSyncTransportObexClientConnect; break; case SML_TRANSPORT_OBEX_SERVER: dsObject->funcTspInit = NULL; dsObject->funcTspConnect = NULL; break; case SML_TRANSPORT_HTTP_SERVER: dsObject->funcTspInit = smlDataSyncTransportHttpServerInit; dsObject->funcTspConnect = NULL; break; case SML_TRANSPORT_HTTP_CLIENT: dsObject->funcTspInit = smlDataSyncTransportHttpClientInit; dsObject->funcTspConnect = smlDataSyncTransportHttpClientConnect; break; default: smlErrorSet(error, SML_ERROR_INTERNAL_MISCONFIGURATION, "Unknown transport type %d used in __func__.", tspType, __func__); goto error; break; } switch(dsType) { case SML_SESSION_TYPE_SERVER: dsObject->funcDsInit = smlDataSyncServerInit; dsObject->funcDsConnect = NULL; break; case SML_SESSION_TYPE_CLIENT: dsObject->funcDsInit = smlDataSyncClientInit; dsObject->funcDsConnect = NULL; break; default: smlErrorSet(error, SML_ERROR_INTERNAL_MISCONFIGURATION, "Unknown data sync type %d used in %s.", dsType, __func__); goto error; break; } smlTrace(TRACE_EXIT, "%s - %p", __func__, dsObject); return dsObject; error: if (dsObject) { if (dsObject->tsp) smlTransportFree(dsObject->tsp); smlDataSyncObjectUnref(&dsObject); } smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(error)); return NULL; } void smlDataSyncObjectRef(SmlDataSyncObject *dsObject) { g_atomic_int_inc(&(dsObject->refCount)); } SmlBool smlDataSyncSetOption( SmlDataSyncObject *dsObject, const char *name, const char *value, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %s, %s, %p)", __func__, dsObject, VA_STRING(name), VA_STRING(value), error); CHECK_ERROR_REF if (!strcmp(SML_DATA_SYNC_CONFIG_CONNECTION_TYPE, name)) { if (!strcmp(SML_DATA_SYNC_CONFIG_CONNECTION_SERIAL, value)) dsObject->conType = SML_TRANSPORT_CONNECTION_TYPE_SERIAL; if (!strcmp(SML_DATA_SYNC_CONFIG_CONNECTION_BLUETOOTH, value)) dsObject->conType = SML_TRANSPORT_CONNECTION_TYPE_BLUETOOTH; if (!strcmp(SML_DATA_SYNC_CONFIG_CONNECTION_IRDA, value)) dsObject->conType = SML_TRANSPORT_CONNECTION_TYPE_IRDA; if (!strcmp(SML_DATA_SYNC_CONFIG_CONNECTION_NET, value)) dsObject->conType = SML_TRANSPORT_CONNECTION_TYPE_NET; if (!strcmp(SML_DATA_SYNC_CONFIG_CONNECTION_USB, value)) dsObject->conType = SML_TRANSPORT_CONNECTION_TYPE_USB; if (!smlTransportSetConnectionType(dsObject->tsp, dsObject->conType, error)) goto error; } else if (!strcmp(SML_DATA_SYNC_CONFIG_VERSION, name)) { dsObject->version = SML_VERSION_UNKNOWN; if (!strcmp("1.0", value)) dsObject->version = SML_VERSION_10; if (!strcmp("1.1", value)) dsObject->version = SML_VERSION_11; if (!strcmp("1.2", value)) dsObject->version = SML_VERSION_12; if (dsObject->version == SML_VERSION_UNKNOWN) { smlErrorSet(error, SML_ERROR_INTERNAL_MISCONFIGURATION, "Unknown SyncML version %s.", value); goto error; } } else if (!strcmp(SML_DATA_SYNC_CONFIG_AUTH_TYPE, name)) { if (!strcmp(value, SML_DATA_SYNC_CONFIG_AUTH_BASIC)) { dsObject->authType = SML_AUTH_TYPE_BASIC; } else if (!strcmp(value, SML_DATA_SYNC_CONFIG_AUTH_MD5)) { dsObject->authType = SML_AUTH_TYPE_MD5; } else if (!strcmp(value, SML_DATA_SYNC_CONFIG_AUTH_NONE)) { dsObject->authType = SML_AUTH_TYPE_UNKNOWN; } else { // this is an illegal keyword smlErrorSet(error, SML_ERROR_INTERNAL_MISCONFIGURATION, "Unknown authentication type %s.", value); goto error; } } else if (!strcmp(SML_TRANSPORT_CONFIG_URL, name)) { dsObject->url = g_strdup(value); /* If the Target is not set explicitly * then the URL is used as the Target in the session header. * This is only relevant for HTTP clients today. */ if (!dsObject->target) dsObject->target = g_strdup(value); } else if (!strcmp(SML_DATA_SYNC_CONFIG_TARGET, name)) { if (dsObject->target) smlSafeCFree(&(dsObject->target)); dsObject->target = g_strdup(value); } else if (!strcmp(SML_DATA_SYNC_CONFIG_IDENTIFIER, name)) { if (dsObject->identifier) smlSafeCFree(&(dsObject->identifier)); if (value && strlen(value)) { dsObject->identifier = g_strdup(value); } else { smlTrace(TRACE_INTERNAL, "%s: set identifier to NULL", __func__); } } else if (!strcmp(SML_DATA_SYNC_CONFIG_AUTH_USERNAME, name)) { dsObject->username = g_strdup(value); } else if (!strcmp(SML_DATA_SYNC_CONFIG_AUTH_PASSWORD, name)) { dsObject->password = g_strdup(value); } else if (!strcmp(SML_DATA_SYNC_CONFIG_USE_WBXML, name)) { dsObject->useWbxml = atoi(value); } else if (!strcmp(SML_DATA_SYNC_CONFIG_USE_STRING_TABLE, name)) { dsObject->useStringTable = atoi(value); } else if (!strcmp(SML_DATA_SYNC_CONFIG_USE_TIMESTAMP_ANCHOR, name)) { dsObject->useTimestampAnchor = atoi(value); } else if (!strcmp(SML_DATA_SYNC_CONFIG_USE_NUMBER_OF_CHANGES, name)) { dsObject->useNumberOfChanges = atoi(value); } else if (!strcmp(SML_DATA_SYNC_CONFIG_USE_LOCALTIME, name)) { dsObject->onlyLocaltime = atoi(value); } else if (!strcmp(SML_DATA_SYNC_CONFIG_ONLY_REPLACE, name)) { dsObject->onlyReplace = atoi(value); } else if (!strcmp(SML_DATA_SYNC_CONFIG_MAX_OBJ_SIZE, name)) { dsObject->maxObjSize = atoi(value); } else if (!strcmp(SML_DATA_SYNC_CONFIG_MAX_MSG_SIZE, name)) { dsObject->maxMsgSize = atoi(value); } else if (!strcmp(SML_DATA_SYNC_CONFIG_FAKE_DEVICE, name)) { dsObject->fakeDevice = g_strdup(value); } else if (!strcmp(SML_DATA_SYNC_CONFIG_FAKE_MANUFACTURER, name)) { dsObject->fakeManufacturer = g_strdup(value); } else if (!strcmp(SML_DATA_SYNC_CONFIG_FAKE_MODEL, name)) { dsObject->fakeModel = g_strdup(value); } else if (!strcmp(SML_DATA_SYNC_CONFIG_FAKE_SOFTWARE_VERSION, name)) { dsObject->fakeSoftwareVersion = g_strdup(value); } else { if (!smlTransportSetConfigOption(dsObject->tsp, name, value, error)) goto error; } // the default is syncml:auth-basic if ((dsObject->username || dsObject->password) && dsObject->authType == SML_AUTH_TYPE_UNKNOWN) { smlTrace(TRACE_INTERNAL, "%s: authType is set to default (syncml:auth-basic)", __func__); dsObject->authType = SML_AUTH_TYPE_BASIC; } smlTrace(TRACE_EXIT, "%s - TRUE", __func__); return TRUE; error: smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(error)); return FALSE; } SmlBool smlDataSyncAddDatastore(SmlDataSyncObject *dsObject, const char *contentType, const char *target, const char *source, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %s, %s, %s, %p)", __func__, dsObject, VA_STRING(contentType), VA_STRING(target), VA_STRING(source), error); CHECK_ERROR_REF char *lcCT = NULL; char *lcSource = NULL; SmlDataSyncDatastore *datastore = smlTryMalloc0(sizeof(SmlDataSyncDatastore), error); if (!datastore) goto error; datastore->dsObject = dsObject; datastore->syncChanges = NULL; datastore->syncContexts = NULL; datastore->sourceUri = g_strdup(source); datastore->targetUri = g_strdup(target); datastore->contentType = g_strdup(contentType); dsObject->datastores = g_list_append(dsObject->datastores, datastore); /* especially Samsung devices need the datastores during connect */ if (dsObject->tspType == SML_TRANSPORT_OBEX_CLIENT) { lcCT = g_ascii_strdown(contentType, strlen(contentType)); lcSource = g_utf8_strdown(source, strlen(source)); if (strstr(lcCT, "vcard") && !smlTransportSetConfigOption( dsObject->tsp, SML_TRANSPORT_CONFIG_DATASTORE, SML_TRANSPORT_CONFIG_DATASTORE_CONTACT, error)) { goto error; } if (strstr(lcCT, "calendar") && ( strstr(lcSource, "cal") || strstr(lcSource, "event") )&& !smlTransportSetConfigOption( dsObject->tsp, SML_TRANSPORT_CONFIG_DATASTORE, SML_TRANSPORT_CONFIG_DATASTORE_EVENT, error)) { goto error; } if (strstr(lcCT, "calendar") && strstr(lcSource, "todo") && !smlTransportSetConfigOption( dsObject->tsp, SML_TRANSPORT_CONFIG_DATASTORE, SML_TRANSPORT_CONFIG_DATASTORE_TODO, error)) { goto error; } if (strstr(lcCT, "text/plain") && !smlTransportSetConfigOption( dsObject->tsp, SML_TRANSPORT_CONFIG_DATASTORE, SML_TRANSPORT_CONFIG_DATASTORE_NOTE, error)) { goto error; } smlSafeCFree(&lcCT); smlSafeCFree(&lcSource); } smlTrace(TRACE_EXIT, "%s - TRUE", __func__); return TRUE; error: if (datastore) smlSafeFree((gpointer *)&datastore); if (lcCT) smlSafeCFree(&lcCT); if (lcSource) smlSafeCFree(&lcSource); smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(error)); return FALSE; } static SmlDataSyncDatastore *smlDataSyncGetDatastoreFromSource( SmlDataSyncObject *dsObject, const char *source, SmlError **error) { CHECK_ERROR_REF smlAssert(dsObject); smlAssert(source); GList *o = dsObject->datastores; for (; o; o = o->next) { SmlDataSyncDatastore *datastore = o->data; if (!strcmp(datastore->sourceUri, source)) return datastore; } smlErrorSet(error, SML_ERROR_INTERNAL_MISCONFIGURATION, "Cannot find datastore for source name %s.", source); return NULL; } /* ***************************** */ /* register callbacks */ /* ***************************** */ void smlDataSyncRegisterEventCallback( SmlDataSyncObject *dsObject, SmlDataSyncEventCallback callback, void *userdata) { smlTrace(TRACE_ENTRY, "%s", __func__); smlAssert(dsObject); smlAssert(callback); dsObject->eventCallback = callback; dsObject->eventUserdata = userdata; smlTrace(TRACE_EXIT, "%s", __func__); } void smlDataSyncRegisterGetAlertTypeCallback( SmlDataSyncObject *dsObject, SmlDataSyncGetAlertTypeCallback callback, void *userdata) { smlTrace(TRACE_ENTRY, "%s", __func__); smlAssert(dsObject); smlAssert(callback); dsObject->getAlertTypeCallback = callback; dsObject->getAlertTypeUserdata = userdata; smlTrace(TRACE_EXIT, "%s", __func__); } void smlDataSyncRegisterChangeCallback( SmlDataSyncObject *dsObject, SmlDataSyncChangeCallback callback, void *userdata) { smlTrace(TRACE_ENTRY, "%s", __func__); smlAssert(dsObject); smlAssert(callback); dsObject->changeCallback = callback; dsObject->changeUserdata = userdata; GList *o = dsObject->datastores; for (;o;o = o->next) { SmlDataSyncDatastore *datastore = o->data; if (datastore->session) { smlDsSessionGetSync(datastore->session, smlDataSyncSyncCallback, datastore); smlDsSessionGetChanges(datastore->session, smlDataSyncChangeCallback, datastore); } } smlTrace(TRACE_EXIT, "%s", __func__); } void smlDataSyncRegisterChangeStatusCallback( SmlDataSyncObject *dsObject, SmlDataSyncChangeStatusCallback callback) { smlTrace(TRACE_ENTRY, "%s", __func__); smlAssert(dsObject); smlAssert(callback); dsObject->changeStatusCallback = callback; /* the userdata is set by the AddChange function */ smlTrace(TRACE_EXIT, "%s", __func__); } void smlDataSyncRegisterMapCallback( SmlDataSyncObject *dsObject, SmlDataSyncMappingCallback callback, void *userdata) { smlTrace(TRACE_ENTRY, "%s", __func__); smlAssert(dsObject); smlAssert(callback); dsObject->mappingCallback = callback; dsObject->mappingUserdata = userdata; GList *o = dsObject->datastores; for (;o;o = o->next) { SmlDataSyncDatastore *datastore = o->data; if (datastore->session) { smlDsSessionGetMapping(datastore->session, smlDataSyncMappingCallback, datastore); } } smlTrace(TRACE_EXIT, "%s", __func__); } void smlDataSyncRegisterGetAnchorCallback( SmlDataSyncObject *dsObject, SmlDataSyncGetAnchorCallback callback, void *userdata) { smlTrace(TRACE_ENTRY, "%s", __func__); smlAssert(dsObject); smlAssert(callback); dsObject->getAnchorCallback = callback; dsObject->getAnchorUserdata = userdata; smlTrace(TRACE_EXIT, "%s", __func__); } void smlDataSyncRegisterSetAnchorCallback( SmlDataSyncObject *dsObject, SmlDataSyncSetAnchorCallback callback, void *userdata) { smlTrace(TRACE_ENTRY, "%s", __func__); smlAssert(dsObject); smlAssert(callback); dsObject->setAnchorCallback = callback; dsObject->setAnchorUserdata = userdata; smlTrace(TRACE_EXIT, "%s", __func__); } void smlDataSyncRegisterWriteDevInfCallback( SmlDataSyncObject *dsObject, SmlDataSyncWriteDevInfCallback callback, void *userdata) { smlTrace(TRACE_ENTRY, "%s", __func__); smlAssert(dsObject); smlAssert(callback); dsObject->writeDevInfCallback = callback; dsObject->writeDevInfUserdata = userdata; smlTrace(TRACE_EXIT, "%s", __func__); } void smlDataSyncRegisterReadDevInfCallback( SmlDataSyncObject *dsObject, SmlDataSyncReadDevInfCallback callback, void *userdata) { smlTrace(TRACE_ENTRY, "%s", __func__); smlAssert(dsObject); smlAssert(callback); dsObject->readDevInfCallback = callback; dsObject->readDevInfUserdata = userdata; smlTrace(TRACE_EXIT, "%s", __func__); } void smlDataSyncRegisterHandleRemoteDevInfCallback( SmlDataSyncObject *dsObject, SmlDataSyncHandleRemoteDevInfCallback callback, void *userdata) { smlTrace(TRACE_ENTRY, "%s", __func__); smlAssert(dsObject); smlAssert(callback); dsObject->handleRemoteDevInfCallback = callback; dsObject->handleRemoteDevInfUserdata = userdata; smlTrace(TRACE_EXIT, "%s", __func__); } /* ***************************** */ /* init session */ /* ***************************** */ SmlBool smlDataSyncInit(SmlDataSyncObject *dsObject, SmlError **error) { smlTrace(TRACE_ENTRY, "%s", __func__); CHECK_ERROR_REF smlAssert(dsObject); if (!dsObject->identifier) dsObject->identifier = smlDataSyncDevInfGetIdentifier(); dsObject->managerMutex = g_mutex_new(); if (dsObject->funcTspInit && !dsObject->funcTspInit(dsObject, error)) goto error; if (!dsObject->funcDsInit(dsObject, error)) goto error; dsObject->internalState = SML_DATA_SYNC_STATE_INITIALIZED; smlTrace(TRACE_EXIT, "%s - TRUE", __func__); return TRUE; error: smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(error)); return FALSE; } SmlBool smlDataSyncRun(SmlDataSyncObject *dsObject, SmlError **error) { smlTrace(TRACE_ENTRY, "%s", __func__); CHECK_ERROR_REF /* If a server was initialized then you cannot do more * than waiting for the remote client. */ if (dsObject->funcTspConnect && !dsObject->funcTspConnect(dsObject, error)) goto error; if (dsObject->funcDsConnect && !dsObject->funcDsConnect(dsObject, error)) goto error; if (!smlDataSyncLoopStart(dsObject, error)) goto error; smlTrace(TRACE_EXIT, "%s - TRUE", __func__); return TRUE; error: smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(error)); return FALSE; } /* synchronize */ SmlBool smlDataSyncAddChange( SmlDataSyncObject *dsObject, const char *source, SmlChangeType type, const char *name, const char *data, unsigned int size, void *userdata, /* for SmlDataSyncChangeStatusCallback */ SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%s)", __func__, VA_STRING(source)); /* check params */ CHECK_ERROR_REF smlAssert(dsObject); smlAssert(source); smlAssert(type); /* create a new change */ SmlDataSyncChange *change = smlTryMalloc0(sizeof(SmlDataSyncChange), error); if (!change) goto error; /* fill the new change */ change->type = type; change->name = g_strdup(name); change->userdata = userdata; /* determine the datastore */ change->datastore = smlDataSyncGetDatastoreFromSource(dsObject, source, error); if (!change->datastore) goto error; SmlDataSyncDatastore *datastore = change->datastore; /* copy data */ if (data) { smlAssert(datastore->contentType); smlAssert(index(datastore->contentType, '/')); size_t appClassLength = ((size_t) index(datastore->contentType, '/')) - ((size_t) datastore->contentType); if ( ( strstr(datastore->contentType, SML_CONTENT_TYPE_APPLICATION) == datastore->contentType && appClassLength == strlen(SML_CONTENT_TYPE_APPLICATION) ) || ( strstr(datastore->contentType, SML_CONTENT_TYPE_AUDIO) == datastore->contentType && appClassLength == strlen(SML_CONTENT_TYPE_AUDIO) ) || ( strstr(datastore->contentType, SML_CONTENT_TYPE_IMAGE) == datastore->contentType && appClassLength == strlen(SML_CONTENT_TYPE_IMAGE) ) || ( strstr(datastore->contentType, SML_CONTENT_TYPE_MESSAGE) == datastore->contentType && appClassLength == strlen(SML_CONTENT_TYPE_MESSAGE) ) || ( strstr(datastore->contentType, SML_CONTENT_TYPE_VIDEO) == datastore->contentType && appClassLength == strlen(SML_CONTENT_TYPE_AUDIO) ) ) { /* binary data must be base64 encoded */ change->data = g_base64_encode((const unsigned char *) data, size); if (!change->data) { smlErrorSet(error, SML_ERROR_GENERIC, "The base 64 encoding of glib failed."); goto error; } change->size = strlen(change->data); } else { change->data = smlTryMalloc0(size+1, error); if (!change->data) goto error; memcpy(change->data, data, size); change->size = size; } } else { change->data = NULL; change->size = 0; } /* append change to datastore */ datastore->changes = g_list_append(datastore->changes, change); smlTrace(TRACE_EXIT, "%s - TRUE", __func__); return TRUE; error: smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(error)); return FALSE; } SmlBool smlDataSyncSendChanges(SmlDataSyncObject *dsObject, SmlError **error) { /* This means that all alerts were received * and all changes were added. * So let us flush the session. */ smlTrace(TRACE_ENTRY, "%s", __func__); CHECK_ERROR_REF /* Verify that the library is in the correct state */ if (dsObject->internalState >= SML_DATA_SYNC_STATE_SENT_CHANGES) { smlErrorSet(error, SML_ERROR_GENERIC, "The function %s is called to late or more than once.", __func__); goto error; } else { dsObject->internalState = SML_DATA_SYNC_STATE_SENT_CHANGES; } if (dsObject->dsType == SML_SESSION_TYPE_SERVER && dsObject->actualPackage != SML_PACKAGE_4) { smlErrorSet(error, SML_ERROR_GENERIC, "This is not the server's sync package (%d).", dsObject->actualPackage); goto error; } if (dsObject->dsType == SML_SESSION_TYPE_CLIENT && dsObject->actualPackage != SML_PACKAGE_3) { smlErrorSet(error, SML_ERROR_GENERIC, "This is not the client's sync package (%d).", dsObject->actualPackage); goto error; } /* iterate over all datastores */ GList *o = dsObject->datastores; for (; o; o = o->next) { SmlDataSyncDatastore *datastore = o->data; smlAssert(datastore); int num = g_list_length(datastore->changes); if (!smlDsSessionSendSync( datastore->session, num, smlDataSyncSyncStatusCallback, datastore, error)) goto error; int i = 0; for (i = 0; i < num; i++) { SmlDataSyncChange *change = g_list_nth_data(datastore->changes, i); if (!smlDsSessionQueueChange( datastore->session, change->type, change->name, change->data, change->size, datastore->contentType, smlDataSyncChangeStatusCallback, change, error)) goto error; } if (!smlDsSessionCloseSync(datastore->session, error)) goto error; } /* Send the next package */ if (!smlSessionFlush(dsObject->session, TRUE, error)) goto error; smlTrace(TRACE_EXIT, "%s - TRUE", __func__); return TRUE; error: smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(error)); return FALSE; } SmlBool smlDataSyncAddMapping( SmlDataSyncObject *dsObject, const char *source, const char *remoteID, const char *localID, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%s)", __func__, VA_STRING(source)); /* check params */ CHECK_ERROR_REF smlAssert(dsObject); smlAssert(source); smlAssert(remoteID); smlAssert(localID); /* A map can only be created if a sync from a server was * received. So it makes no sense to cache the mapping. * Therefore the map will be set immediately. */ SmlDataSyncDatastore *datastore = NULL; datastore = smlDataSyncGetDatastoreFromSource(dsObject, source, error); if (!datastore) goto error; if (!smlDsSessionQueueMap(datastore->session, remoteID, localID, error)) goto error; smlTrace(TRACE_EXIT, "%s - TRUE", __func__); return TRUE; error: smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(error)); return FALSE; } SmlBool smlDataSyncSendMap(SmlDataSyncObject *dsObject, SmlError **error) { smlTrace(TRACE_ENTRY, "%s", __func__); CHECK_ERROR_REF smlAssert(dsObject); /* Verify that the library is in the correct state */ if (dsObject->dsType == SML_SESSION_TYPE_SERVER) { smlErrorSet(error, SML_ERROR_GENERIC, "An OMA DS server never sends a map."); goto error; } if (dsObject->dsType == SML_SESSION_TYPE_CLIENT && dsObject->actualPackage != SML_PACKAGE_5) { smlErrorSet(error, SML_ERROR_GENERIC, "Missing server's sync package."); goto error; } /* iterate over all datastores */ GList *o = dsObject->datastores; for (; o; o = o->next) { SmlDataSyncDatastore *datastore = o->data; smlAssert(datastore); /* FIXME: today we ignore the answer */ if (!smlDsSessionCloseMap(datastore->session, smlDataSyncMapStatusCallback, datastore, error)) goto error; } smlTrace(TRACE_EXIT, "%s - TRUE", __func__); return TRUE; error: smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(error)); return FALSE; } const SmlLocation *smlDataSyncGetTarget( SmlDataSyncObject *dsObject, SmlError **error) { smlTrace(TRACE_INTERNAL, "%s(%p, %p)", __func__, dsObject, error); smlAssert(dsObject); return smlSessionGetTarget(dsObject->session); } /* close session */ void smlDataSyncObjectUnref(SmlDataSyncObject **dsObject) { if (g_atomic_int_dec_and_test(&((*dsObject)->refCount))) { /* stop the dispatcher loop */ if ((*dsObject)->thread) smlDataSyncLoopStop((*dsObject)); /* stop and free manager */ if ((*dsObject)->manager) { smlManagerStop((*dsObject)->manager); smlManagerFree((*dsObject)->manager); } if ((*dsObject)->managerMutex) g_mutex_free((*dsObject)->managerMutex); /* cleanup transport */ if ((*dsObject)->tsp) { SmlError *error = NULL; if ((*dsObject)->dsType == SML_SESSION_TYPE_CLIENT && SML_DATA_SYNC_STATE_CONNECTED >= (*dsObject)->internalState && (*dsObject)->internalState <= SML_DATA_SYNC_STATE_DISCONNECTED && !smlTransportDisconnect((*dsObject)->tsp, NULL, &error)) { /* just ignore the error */ smlTrace(TRACE_ERROR, "%s: %s", __func__, smlErrorPrint(&error)); smlErrorDeref(&error); } /* FIXME: we have to wait here for the disconnect ... */ if ((*dsObject)->internalState >= SML_DATA_SYNC_STATE_INITIALIZED && !smlTransportFinalize((*dsObject)->tsp, &error)) { smlTrace(TRACE_ERROR, "%s: %s", __func__, smlErrorPrint(&error)); smlErrorDeref(&error); } smlTransportFree((*dsObject)->tsp); } /* cleanup configuration */ if ((*dsObject)->url) smlSafeCFree(&((*dsObject)->url)); if ((*dsObject)->target) smlSafeCFree(&((*dsObject)->target)); if ((*dsObject)->identifier) smlSafeCFree(&((*dsObject)->identifier)); if ((*dsObject)->username) smlSafeCFree(&((*dsObject)->username)); if ((*dsObject)->password) smlSafeCFree(&((*dsObject)->password)); if ((*dsObject)->fakeDevice) smlSafeCFree(&((*dsObject)->fakeDevice)); if ((*dsObject)->fakeManufacturer) smlSafeCFree(&((*dsObject)->fakeManufacturer)); if ((*dsObject)->fakeModel) smlSafeCFree(&((*dsObject)->fakeModel)); if ((*dsObject)->fakeSoftwareVersion) smlSafeCFree(&((*dsObject)->fakeSoftwareVersion)); /* cleanup datastores */ while((*dsObject)->datastores) { SmlDataSyncDatastore *datastore = (*dsObject)->datastores->data; (*dsObject)->datastores = g_list_remove( (*dsObject)->datastores, datastore); if (datastore->sourceUri) smlSafeCFree(&(datastore->sourceUri)); if (datastore->targetUri) smlSafeCFree(&(datastore->targetUri)); if (datastore->contentType) smlSafeCFree(&(datastore->contentType)); if (datastore->remoteNext) smlSafeCFree(&(datastore->remoteNext)); if (datastore->localNext) smlSafeCFree(&(datastore->localNext)); if (datastore->session) smlDsSessionUnref(datastore->session); if (datastore->server) smlDsServerFree(datastore->server); while(datastore->changes) { SmlDataSyncChange *change = datastore->changes->data; datastore->changes = g_list_remove( datastore->changes, change); if (change->name) smlSafeCFree(&(change->name)); if (change->data) smlSafeCFree(&(change->data)); smlSafeFree((gpointer *)&change); } smlSafeFree((gpointer *)&datastore); } /* cleanup authentication */ if ((*dsObject)->auth) smlAuthFree((*dsObject)->auth); /* cleanup session */ if ((*dsObject)->session) smlSessionUnref((*dsObject)->session); /* cleanup device information */ if ((*dsObject)->localDevInf) smlDevInfUnref((*dsObject)->localDevInf); if ((*dsObject)->remoteDevInf) smlDevInfUnref((*dsObject)->remoteDevInf); if ((*dsObject)->agent) smlDevInfAgentFree((*dsObject)->agent); smlSafeFree((gpointer *) dsObject); } } /* internal functions */ void smlDataSyncSendEvent( SmlDataSyncObject *dsObject, SmlDataSyncEventType type, void *userdata, SmlError *error) { /* this functionworks synchronous today */ smlAssert(dsObject); smlAssert(dsObject->eventCallback); dsObject->eventCallback(dsObject, type, userdata, error); } libsyncml-0.5.4/libsyncml/data_sync_api/data_sync_devinf.c100644 1750 1750 63632 11211710410 23711 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2008-2009 Michael Bell * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include "data_sync_devinf.h" #include "libsyncml/syncml_internals.h" #include "libsyncml/sml_error_internals.h" static SmlDevInfProperty *_add_ctcap_property_by_name( SmlDevInfCTCap *ctcap, const char *name, SmlError **error) { smlTrace(TRACE_ENTRY, "%s (%s)", __func__, VA_STRING(name)); CHECK_ERROR_REF smlAssert(ctcap); smlAssert(name); SmlDevInfProperty *prop = smlDevInfNewProperty(error); if (!prop) goto error; smlDevInfPropertySetPropName(prop, name); smlDevInfCTCapAddProperty(ctcap, prop); smlTrace(TRACE_EXIT, "%s", __func__); return prop; error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return NULL; } static SmlDevInfProperty *_add_ctcap_property_by_name_value( SmlDevInfCTCap *ctcap, const char*name, const char *value, SmlError **error) { smlTrace(TRACE_ENTRY, "%s (%s ::= %s)", __func__, VA_STRING(name), VA_STRING(value)); CHECK_ERROR_REF smlAssert(ctcap); smlAssert(name); smlAssert(value); SmlDevInfProperty *prop = _add_ctcap_property_by_name(ctcap, name, error); if (!prop) goto error; smlDevInfPropertyAddValEnum(prop, value); smlTrace(TRACE_EXIT, "%s", __func__); return prop; error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return NULL; } static SmlDevInfPropParam *_add_property_param( SmlDevInfProperty *prop, const char *name, SmlError **error) { smlTrace(TRACE_ENTRY, "%s (%s)", __func__, VA_STRING(name)); CHECK_ERROR_REF smlAssert(prop); smlAssert(name); SmlDevInfPropParam *param = smlDevInfNewPropParam(error); if (!param) goto error; smlDevInfPropParamSetParamName(param, name); smlDevInfPropertyAddPropParam(prop, param); smlTrace(TRACE_EXIT, "%s", __func__); return param; error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return NULL; } #define _ADD_PROPERTY_PARAM(text) \ param = _add_property_param(prop, text, error); \ if (!param) \ goto error; #define _ADD_CTCAP_PROPERTY_BY_NAME(text) \ prop = _add_ctcap_property_by_name(ctcap, text, error); \ if (!prop) \ goto error; #define _ADD_CTCAP_PROPERTY_BY_NAME_VALUE(name,value) \ if (!_add_ctcap_property_by_name_value(ctcap, name, value, error)) \ goto error; static SmlBool add_devinf_ctcap( SmlDevInf *devinf, const char* cttype, const char *verct, SmlError **error) { smlTrace(TRACE_ENTRY, "%s (%s %s)", __func__, VA_STRING(cttype), VA_STRING(verct)); CHECK_ERROR_REF smlAssert(devinf); smlAssert(cttype); smlAssert(verct); // first we check for an already configure CTCap SmlDevInfContentType *ct = smlDevInfNewContentType(cttype, verct, error); if (!ct) goto error; if (smlDevInfGetCTCap(devinf, ct) != NULL) { smlDevInfFreeContentType(ct); smlTrace(TRACE_EXIT, "%s - content type already present in devinf", __func__); return TRUE; } else { smlDevInfFreeContentType(ct); smlTrace(TRACE_INTERNAL, "%s: new content type detected", __func__); } SmlDevInfCTCap *ctcap; SmlDevInfProperty *prop; SmlDevInfPropParam *param; if (!strcmp(cttype, SML_ELEMENT_TEXT_VCARD) && !strcmp(verct, "2.1")) { smlTrace(TRACE_INTERNAL, "%s: vCard 2.1 detected", __func__); ctcap = smlDevInfNewCTCap(error); if (!ctcap) goto error; smlDevInfCTCapSetCTType(ctcap, SML_ELEMENT_TEXT_VCARD); smlDevInfCTCapSetVerCT(ctcap, "2.1"); _ADD_CTCAP_PROPERTY_BY_NAME("ADR") _ADD_PROPERTY_PARAM("TYPE") smlDevInfPropParamAddValEnum(param, "HOME"); smlDevInfPropParamAddValEnum(param, "WORK"); smlDevInfPropParamAddValEnum(param, "PARCEL"); smlDevInfPropParamAddValEnum(param, "POSTAL"); smlDevInfPropParamAddValEnum(param, "INTL"); smlDevInfPropParamAddValEnum(param, "DOM"); _ADD_PROPERTY_PARAM("HOME"); _ADD_PROPERTY_PARAM("WORK"); _ADD_PROPERTY_PARAM("PARCEL"); _ADD_PROPERTY_PARAM("POSTAL"); _ADD_PROPERTY_PARAM("INTL"); _ADD_PROPERTY_PARAM("DOM"); _ADD_CTCAP_PROPERTY_BY_NAME("AGENT") _ADD_CTCAP_PROPERTY_BY_NAME("BDAY") _ADD_CTCAP_PROPERTY_BY_NAME_VALUE("BEGIN","VCARD") _ADD_CTCAP_PROPERTY_BY_NAME_VALUE("END","VCARD") _ADD_CTCAP_PROPERTY_BY_NAME("EMAIL") _ADD_PROPERTY_PARAM("TYPE") smlDevInfPropParamAddValEnum(param, "INTERNET"); _ADD_PROPERTY_PARAM("INTERNET"); _ADD_CTCAP_PROPERTY_BY_NAME("FN") _ADD_CTCAP_PROPERTY_BY_NAME("GEO") _ADD_CTCAP_PROPERTY_BY_NAME("KEY") _ADD_PROPERTY_PARAM("TYPE") smlDevInfPropParamAddValEnum(param, "X509"); smlDevInfPropParamAddValEnum(param, "PGP"); _ADD_PROPERTY_PARAM("X509"); _ADD_PROPERTY_PARAM("PGP"); _ADD_CTCAP_PROPERTY_BY_NAME("LABEL") _ADD_PROPERTY_PARAM("TYPE") smlDevInfPropParamAddValEnum(param, "HOME"); smlDevInfPropParamAddValEnum(param, "WORK"); smlDevInfPropParamAddValEnum(param, "PARCEL"); smlDevInfPropParamAddValEnum(param, "POSTAL"); smlDevInfPropParamAddValEnum(param, "INTL"); smlDevInfPropParamAddValEnum(param, "DOM"); _ADD_PROPERTY_PARAM("HOME"); _ADD_PROPERTY_PARAM("WORK"); _ADD_PROPERTY_PARAM("PARCEL"); _ADD_PROPERTY_PARAM("POSTAL"); _ADD_PROPERTY_PARAM("INTL"); _ADD_PROPERTY_PARAM("DOM"); _ADD_CTCAP_PROPERTY_BY_NAME("LOGO") _ADD_PROPERTY_PARAM("TYPE") smlDevInfPropParamAddValEnum(param, "JPEG"); _ADD_PROPERTY_PARAM("JPEG"); _ADD_CTCAP_PROPERTY_BY_NAME("MAILER") _ADD_CTCAP_PROPERTY_BY_NAME("N") _ADD_CTCAP_PROPERTY_BY_NAME("NOTE") _ADD_CTCAP_PROPERTY_BY_NAME("ORG") _ADD_CTCAP_PROPERTY_BY_NAME("PHOTO") _ADD_PROPERTY_PARAM("TYPE") smlDevInfPropParamAddValEnum(param, "JPEG"); _ADD_PROPERTY_PARAM("JPEG"); _ADD_CTCAP_PROPERTY_BY_NAME("REV") _ADD_CTCAP_PROPERTY_BY_NAME("ROLE") _ADD_CTCAP_PROPERTY_BY_NAME("SOUND") _ADD_PROPERTY_PARAM("TYPE") smlDevInfPropParamAddValEnum(param, "AIFF"); smlDevInfPropParamAddValEnum(param, "PCM"); smlDevInfPropParamAddValEnum(param, "WAVE"); _ADD_PROPERTY_PARAM("AIFF"); _ADD_PROPERTY_PARAM("PCM"); _ADD_PROPERTY_PARAM("WAVE"); _ADD_CTCAP_PROPERTY_BY_NAME("TEL") _ADD_PROPERTY_PARAM("TYPE") smlDevInfPropParamAddValEnum(param, "WORK"); smlDevInfPropParamAddValEnum(param, "VOICE"); smlDevInfPropParamAddValEnum(param, "PREF"); smlDevInfPropParamAddValEnum(param, "PAGER"); smlDevInfPropParamAddValEnum(param, "MSG"); smlDevInfPropParamAddValEnum(param, "MODEM"); smlDevInfPropParamAddValEnum(param, "ISDN"); smlDevInfPropParamAddValEnum(param, "HOME"); smlDevInfPropParamAddValEnum(param, "FAX"); smlDevInfPropParamAddValEnum(param, "CELL"); smlDevInfPropParamAddValEnum(param, "CAR"); smlDevInfPropParamAddValEnum(param, "BBS"); _ADD_PROPERTY_PARAM("WORK"); _ADD_PROPERTY_PARAM("VOICE"); _ADD_PROPERTY_PARAM("PREF"); _ADD_PROPERTY_PARAM("PAGER"); _ADD_PROPERTY_PARAM("MSG"); _ADD_PROPERTY_PARAM("MODEM"); _ADD_PROPERTY_PARAM("ISDN"); _ADD_PROPERTY_PARAM("HOME"); _ADD_PROPERTY_PARAM("FAX"); _ADD_PROPERTY_PARAM("CELL"); _ADD_PROPERTY_PARAM("CAR"); _ADD_PROPERTY_PARAM("BBS"); _ADD_CTCAP_PROPERTY_BY_NAME("TITLE") _ADD_CTCAP_PROPERTY_BY_NAME("TZ") _ADD_CTCAP_PROPERTY_BY_NAME("UID") _ADD_CTCAP_PROPERTY_BY_NAME("URL") _ADD_PROPERTY_PARAM("TYPE") smlDevInfPropParamAddValEnum(param, "WORK"); smlDevInfPropParamAddValEnum(param, "HOME"); _ADD_PROPERTY_PARAM("WORK"); _ADD_PROPERTY_PARAM("HOME"); _ADD_CTCAP_PROPERTY_BY_NAME_VALUE("VERSION", "2.1") smlDevInfAppendCTCap(devinf, ctcap); } else if (!strcmp(cttype, SML_ELEMENT_TEXT_VCARD_30) && !strcmp(verct, "3.0")) { // FIXME: this is no vCard 3.0 spec // FIXME: this is in terms of vCard 3.0 a bug smlTrace(TRACE_INTERNAL, "%s: vCard 3.0 detected", __func__); ctcap = smlDevInfNewCTCap(error); if (!ctcap) goto error; smlDevInfCTCapSetCTType(ctcap, SML_ELEMENT_TEXT_VCARD_30); smlDevInfCTCapSetVerCT(ctcap, "3.0"); _ADD_CTCAP_PROPERTY_BY_NAME_VALUE("BEGIN", "VCARD") _ADD_CTCAP_PROPERTY_BY_NAME_VALUE("END", "VCARD") _ADD_CTCAP_PROPERTY_BY_NAME_VALUE("VERSION", "3.0") _ADD_CTCAP_PROPERTY_BY_NAME("REV") _ADD_CTCAP_PROPERTY_BY_NAME("N") _ADD_CTCAP_PROPERTY_BY_NAME("TITLE") _ADD_CTCAP_PROPERTY_BY_NAME("CATEGORIES") _ADD_CTCAP_PROPERTY_BY_NAME("CLASS") _ADD_CTCAP_PROPERTY_BY_NAME("ORG") _ADD_CTCAP_PROPERTY_BY_NAME("EMAIL") _ADD_CTCAP_PROPERTY_BY_NAME("URL") _ADD_CTCAP_PROPERTY_BY_NAME("TEL") _ADD_PROPERTY_PARAM("TYPE") smlDevInfPropParamAddValEnum(param, "CELL"); smlDevInfPropParamAddValEnum(param, "HOME"); smlDevInfPropParamAddValEnum(param, "WORK"); smlDevInfPropParamAddValEnum(param, "FAX"); smlDevInfPropParamAddValEnum(param, "MODEM"); smlDevInfPropParamAddValEnum(param, "VOICE"); _ADD_CTCAP_PROPERTY_BY_NAME("ADR") _ADD_PROPERTY_PARAM("TYPE") smlDevInfPropParamAddValEnum(param, "HOME"); smlDevInfPropParamAddValEnum(param, "WORK"); _ADD_CTCAP_PROPERTY_BY_NAME("BDAY") _ADD_CTCAP_PROPERTY_BY_NAME("NOTE") _ADD_CTCAP_PROPERTY_BY_NAME("PHOTO") _ADD_PROPERTY_PARAM("TYPE") smlDevInfAppendCTCap(devinf, ctcap); } /* Oracle collaboration Suite uses the content type to distinguish */ /* the versions of vCalendar (and iCalendar) */ /* text/x-vcalendar --> VERSION 1.0 (vCalendar) */ /* text/calendar --> VERSION 2.0 (iCalendar) */ /* So be VERY VERY CAREFUL if you change something here. */ else if (!strcmp(cttype, SML_ELEMENT_TEXT_VCAL) && !strcmp(verct, "1.0")) { smlTrace(TRACE_INTERNAL, "%s: vCalendar 1.0 detected", __func__); ctcap = smlDevInfNewCTCap(error); if (!ctcap) goto error; smlDevInfCTCapSetCTType(ctcap, SML_ELEMENT_TEXT_VCAL); smlDevInfCTCapSetVerCT(ctcap, "1.0"); _ADD_CTCAP_PROPERTY_BY_NAME("AALARM") _ADD_CTCAP_PROPERTY_BY_NAME("ATTACH") _ADD_CTCAP_PROPERTY_BY_NAME("ATTENDEE") _ADD_PROPERTY_PARAM("EXCEPT") _ADD_PROPERTY_PARAM("RSVP") _ADD_PROPERTY_PARAM("STATUS") _ADD_PROPERTY_PARAM("ROLE") _ADD_CTCAP_PROPERTY_BY_NAME("BEGIN") smlDevInfPropertyAddValEnum(prop, "VCALENDAR"); smlDevInfPropertyAddValEnum(prop, "VEVENT"); smlDevInfPropertyAddValEnum(prop, "VTODO"); _ADD_CTCAP_PROPERTY_BY_NAME("CATEGORIES") _ADD_CTCAP_PROPERTY_BY_NAME("COMPLETED") _ADD_CTCAP_PROPERTY_BY_NAME("CLASS") smlDevInfPropertyAddValEnum(prop, "PUBLIC"); smlDevInfPropertyAddValEnum(prop, "PRIVATE"); smlDevInfPropertyAddValEnum(prop, "CONFIDENTIAL"); _ADD_CTCAP_PROPERTY_BY_NAME("DALARM") _ADD_CTCAP_PROPERTY_BY_NAME("DAYLIGHT") _ADD_CTCAP_PROPERTY_BY_NAME("DCREATED") _ADD_CTCAP_PROPERTY_BY_NAME("DESCRIPTION") _ADD_CTCAP_PROPERTY_BY_NAME("DTSTART") _ADD_CTCAP_PROPERTY_BY_NAME("DTEND") _ADD_CTCAP_PROPERTY_BY_NAME("DUE") _ADD_CTCAP_PROPERTY_BY_NAME("END") smlDevInfPropertyAddValEnum(prop, "VCALENDAR"); smlDevInfPropertyAddValEnum(prop, "VEVENT"); smlDevInfPropertyAddValEnum(prop, "VTODO"); _ADD_CTCAP_PROPERTY_BY_NAME("EXDATE") _ADD_CTCAP_PROPERTY_BY_NAME("LAST-MODIFIED") _ADD_CTCAP_PROPERTY_BY_NAME("LOCATION") _ADD_CTCAP_PROPERTY_BY_NAME("PRIORITY") _ADD_CTCAP_PROPERTY_BY_NAME("RRULE") _ADD_CTCAP_PROPERTY_BY_NAME("STATUS") _ADD_CTCAP_PROPERTY_BY_NAME("SUMMARY") _ADD_CTCAP_PROPERTY_BY_NAME("UID") _ADD_CTCAP_PROPERTY_BY_NAME_VALUE("VERSION", "1.0") smlDevInfAppendCTCap(devinf, ctcap); } else if (!strcmp(cttype, SML_ELEMENT_TEXT_ICAL) && !strcmp(verct, "2.0")) { // FIXME: this is no iCal spec !!! // FIXME: this is nearly a direct copy&paste from vCal // FIXME: this is a bug in terms of iCal smlTrace(TRACE_INTERNAL, "%s: iCalendar (vCalendar 2.0) detected", __func__); ctcap = smlDevInfNewCTCap(error); if (!ctcap) goto error; smlDevInfCTCapSetCTType(ctcap, SML_ELEMENT_TEXT_ICAL); smlDevInfCTCapSetVerCT(ctcap, "2.0"); _ADD_CTCAP_PROPERTY_BY_NAME("AALARM") _ADD_CTCAP_PROPERTY_BY_NAME("ATTACH") _ADD_CTCAP_PROPERTY_BY_NAME("ATTENDEE") _ADD_PROPERTY_PARAM("RSVP") _ADD_PROPERTY_PARAM("PARTSTAT") _ADD_PROPERTY_PARAM("ROLE") _ADD_CTCAP_PROPERTY_BY_NAME("BEGIN") smlDevInfPropertyAddValEnum(prop, "VCALENDAR"); smlDevInfPropertyAddValEnum(prop, "VEVENT"); smlDevInfPropertyAddValEnum(prop, "VTODO"); _ADD_CTCAP_PROPERTY_BY_NAME("CATEGORIES") _ADD_CTCAP_PROPERTY_BY_NAME("COMPLETED") _ADD_CTCAP_PROPERTY_BY_NAME("CLASS") smlDevInfPropertyAddValEnum(prop, "PUBLIC"); smlDevInfPropertyAddValEnum(prop, "PRIVATE"); smlDevInfPropertyAddValEnum(prop, "CONFIDENTIAL"); _ADD_CTCAP_PROPERTY_BY_NAME("DALARM") _ADD_CTCAP_PROPERTY_BY_NAME("DAYLIGHT") _ADD_CTCAP_PROPERTY_BY_NAME("DCREATED") _ADD_CTCAP_PROPERTY_BY_NAME("DESCRIPTION") _ADD_CTCAP_PROPERTY_BY_NAME("DTSTART") _ADD_CTCAP_PROPERTY_BY_NAME("DTEND") _ADD_CTCAP_PROPERTY_BY_NAME("DUE") _ADD_CTCAP_PROPERTY_BY_NAME("END") smlDevInfPropertyAddValEnum(prop, "VCALENDAR"); smlDevInfPropertyAddValEnum(prop, "VEVENT"); smlDevInfPropertyAddValEnum(prop, "VTODO"); _ADD_CTCAP_PROPERTY_BY_NAME("EXDATE") _ADD_CTCAP_PROPERTY_BY_NAME("LAST-MODIFIED") _ADD_CTCAP_PROPERTY_BY_NAME("LOCATION") _ADD_CTCAP_PROPERTY_BY_NAME("PRIORITY") _ADD_CTCAP_PROPERTY_BY_NAME("RRULE") _ADD_CTCAP_PROPERTY_BY_NAME("STATUS") _ADD_CTCAP_PROPERTY_BY_NAME("SUMMARY") _ADD_CTCAP_PROPERTY_BY_NAME("UID") _ADD_CTCAP_PROPERTY_BY_NAME_VALUE("VERSION", "2.0") smlDevInfAppendCTCap(devinf, ctcap); } else { /* trace the missing stuff and create a minimal CTCap */ smlTrace(TRACE_INTERNAL, "%s: unknown content type - %s %s", __func__, VA_STRING(cttype), VA_STRING(verct)); ctcap = smlDevInfNewCTCap(error); if (!ctcap) goto error; smlDevInfCTCapSetCTType(ctcap, cttype); smlDevInfCTCapSetVerCT(ctcap, verct); smlDevInfAppendCTCap(devinf, ctcap); } smlTrace(TRACE_EXIT, "%s - content type newly added to devinf", __func__); return TRUE; error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return FALSE; } static void _update_session_config_from_devinf(SmlDataSyncObject *dsObject) { smlTrace(TRACE_ENTRY, "%s called", __func__); SmlDevInf *devinf = dsObject->remoteDevInf; SmlSession *session = dsObject->session; // direct session config smlSessionUseNumberOfChanges(session, smlDevInfSupportsNumberOfChanges(devinf)); smlSessionUseLargeObjects(session, smlDevInfSupportsLargeObjs(devinf)); // local device information if (smlDevInfSupportsUTC(devinf)) dsObject->onlyLocaltime = FALSE; else dsObject->onlyLocaltime = TRUE; smlTrace(TRACE_EXIT, "%s succeeded", __func__); } /* here start the internal API functions */ SmlBool smlDataSyncDevInfAddDatastore( SmlDevInf *devinf, SmlDataSyncDatastore *datastore, SmlError **error) { smlTrace(TRACE_ENTRY, "%s (%p, %p)", __func__, devinf, datastore); CHECK_ERROR_REF smlAssert(datastore); smlAssert(datastore->contentType); smlAssert(datastore->sourceUri); SmlDevInfDataStore *ds = smlDevInfDataStoreNew(datastore->sourceUri, error); if (!ds) goto error; const char *ct = datastore->contentType; SmlDevInfContentType *ctype; if (!strcmp(ct, SML_ELEMENT_TEXT_VCARD)) { // we prefer actually vCard 2.1 // because the most cellphones support it ctype = smlDevInfNewContentType(SML_ELEMENT_TEXT_VCARD_30, "3.0", error); if (!ctype) goto error; smlDevInfDataStoreAddRx(ds, ctype); ctype = smlDevInfNewContentType(SML_ELEMENT_TEXT_VCARD_30, "3.0", error); if (!ctype) goto error; smlDevInfDataStoreAddTx(ds, ctype); smlDevInfDataStoreSetRxPref(ds, SML_ELEMENT_TEXT_VCARD, "2.1"); smlDevInfDataStoreSetTxPref(ds, SML_ELEMENT_TEXT_VCARD, "2.1"); if (!add_devinf_ctcap(devinf, SML_ELEMENT_TEXT_VCARD, "2.1", error)) goto error; if (!add_devinf_ctcap(devinf, SML_ELEMENT_TEXT_VCARD_30, "3.0", error)) goto error; } else if (!strcmp(ct, SML_ELEMENT_TEXT_VCARD_30)) { ctype = smlDevInfNewContentType(SML_ELEMENT_TEXT_VCARD_30, "2.1", error); if (!ctype) goto error; smlDevInfDataStoreAddRx(ds, ctype); ctype = smlDevInfNewContentType(SML_ELEMENT_TEXT_VCARD_30, "2.1", error); if (!ctype) goto error; smlDevInfDataStoreAddTx(ds, ctype); smlDevInfDataStoreSetRxPref(ds, SML_ELEMENT_TEXT_VCARD_30, "3.0"); smlDevInfDataStoreSetTxPref(ds, SML_ELEMENT_TEXT_VCARD_30, "3.0"); if (!add_devinf_ctcap(devinf, SML_ELEMENT_TEXT_VCARD, "2.1", error)) goto error; if (!add_devinf_ctcap(devinf, SML_ELEMENT_TEXT_VCARD_30, "3.0", error)) goto error; } else if (!strcmp(ct, SML_ELEMENT_TEXT_VCAL)) { ctype = smlDevInfNewContentType(SML_ELEMENT_TEXT_ICAL, "2.0", error); if (!ctype) goto error; smlDevInfDataStoreAddRx(ds, ctype); ctype = smlDevInfNewContentType(SML_ELEMENT_TEXT_ICAL, "2.0", error); if (!ctype) goto error; smlDevInfDataStoreAddTx(ds, ctype); smlDevInfDataStoreSetRxPref(ds, SML_ELEMENT_TEXT_VCAL, "1.0"); smlDevInfDataStoreSetTxPref(ds, SML_ELEMENT_TEXT_VCAL, "1.0"); if (!add_devinf_ctcap(devinf, SML_ELEMENT_TEXT_VCAL, "1.0", error)) goto error; if (!add_devinf_ctcap(devinf, SML_ELEMENT_TEXT_ICAL, "2.0", error)) goto error; } else if (!strcmp(ct, SML_ELEMENT_TEXT_ICAL)) { ctype = smlDevInfNewContentType(SML_ELEMENT_TEXT_VCAL, "1.0", error); if (!ctype) goto error; smlDevInfDataStoreAddRx(ds, ctype); ctype = smlDevInfNewContentType(SML_ELEMENT_TEXT_VCAL, "1.0", error); if (!ctype) goto error; smlDevInfDataStoreAddTx(ds, ctype); smlDevInfDataStoreSetRxPref(ds, SML_ELEMENT_TEXT_ICAL, "2.0"); smlDevInfDataStoreSetTxPref(ds, SML_ELEMENT_TEXT_ICAL, "2.0"); if (!add_devinf_ctcap(devinf, SML_ELEMENT_TEXT_VCAL, "1.0", error)) goto error; if (!add_devinf_ctcap(devinf, SML_ELEMENT_TEXT_ICAL, "2.0", error)) goto error; } else if (!strcmp(ct, SML_ELEMENT_TEXT_PLAIN)) { smlDevInfDataStoreSetRxPref(ds, SML_ELEMENT_TEXT_PLAIN, "1.0"); smlDevInfDataStoreSetTxPref(ds, SML_ELEMENT_TEXT_PLAIN, "1.0"); if (!add_devinf_ctcap(devinf, SML_ELEMENT_TEXT_PLAIN, "1.0", error)) goto error; } else { smlTrace(TRACE_INTERNAL, "%s - unknown content type detected (%s)", __func__, VA_STRING(ct)); smlDevInfDataStoreSetRxPref(ds, ct, "1.0"); smlDevInfDataStoreSetTxPref(ds, ct, "1.0"); if (!add_devinf_ctcap(devinf, ct, "1.0", error)) goto error; } // configure supported sync modes smlDevInfDataStoreSetSyncCap(ds, SML_DEVINF_SYNCTYPE_TWO_WAY, TRUE); smlDevInfDataStoreSetSyncCap(ds, SML_DEVINF_SYNCTYPE_SLOW_SYNC, TRUE); // server alerted sync means that the client has to interpret alerts !!! // FIXME: we receive alerts but we do nothing with it if (smlDsServerGetServerType(datastore->server) == SML_DS_CLIENT) // smlDevInfDataStoreSetSyncCap(ds, SML_DEVINF_SYNCTYPE_ONE_WAY_FROM_CLIENT, TRUE); smlTrace(TRACE_INTERNAL, "%s: SyncML clients only support SLOW and TWO WAY SYNC", __func__); else smlDevInfDataStoreSetSyncCap(ds, SML_DEVINF_SYNCTYPE_SERVER_ALERTED_SYNC, TRUE); smlDevInfAddDataStore(devinf, ds); smlTrace(TRACE_EXIT, "%s - content type newly added to devinf", __func__); return TRUE; error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return FALSE; } SmlBool smlDataSyncDevInfLoadRemote( SmlDataSyncObject *dsObject, SmlBool sendGet, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %i, %p)", __func__, dsObject, sendGet, error); CHECK_ERROR_REF smlAssert(dsObject); smlAssertMsg(dsObject->session, "an active session is needed to have a remote device"); /* if there is already a remote device information * then cleanup the reference. */ if (dsObject->remoteDevInf) smlDevInfUnref(dsObject->remoteDevInf); dsObject->remoteDevInf = smlDevInfAgentGetSessionDevInf(dsObject->agent, dsObject->session); if (dsObject->remoteDevInf) { smlTrace(TRACE_INTERNAL, "%s: The remote DevInf was received.", __func__); smlDevInfRef(dsObject->remoteDevInf); _update_session_config_from_devinf(dsObject); /* DevInf caching is optional */ if (dsObject->writeDevInfCallback) { smlTrace(TRACE_EXIT, "%s - calling writeDevInfCallback", __func__); return dsObject->writeDevInfCallback( dsObject, dsObject->remoteDevInf, dsObject->writeDevInfUserdata, error); } else { smlTrace(TRACE_EXIT, "%s - remote DevInf available", __func__); return TRUE; } } else { smlTrace(TRACE_INTERNAL, "%s: The remote DevInf was not received.", __func__); /* DevInf caching is optional */ if (dsObject->readDevInfCallback) { smlTrace(TRACE_INTERNAL, "%s: calling read DevInf callback", __func__); SmlDevInf *devinf = dsObject->readDevInfCallback( dsObject, smlLocationGetURI(smlSessionGetTarget(dsObject->session)), dsObject->readDevInfUserdata, error); if (!devinf && *error) goto error; if (devinf) { if (!smlDevInfAgentSetSessionDevInf( dsObject->agent, dsObject->session, devinf, error)) { goto error; } dsObject->remoteDevInf = smlDevInfAgentGetSessionDevInf( dsObject->agent, dsObject->session); /* smlDevInfAgentSetDevInf consumes the DevInf object. * So the reference counter must be incremented for * remoteDevInf. */ smlDevInfRef(dsObject->remoteDevInf); _update_session_config_from_devinf(dsObject); smlTrace(TRACE_EXIT, "%s - cached DevInf", __func__); return TRUE; } } if (sendGet) { /* the local device information is only send for fairness ;) */ smlDevInfAgentSendDevInf( dsObject->agent, dsObject->session, error); smlDevInfAgentRequestDevInf( dsObject->agent, dsObject->session, error); } smlTrace(TRACE_EXIT, "%s - no remote DevInf available at all", __func__); return FALSE; } error: smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(error)); return FALSE; } char *smlDataSyncDevInfGetIdentifier() { smlTrace(TRACE_ENTRY, "%s", __func__); const char *user = g_get_user_name(); const char *host = g_get_host_name(); char *id = g_strjoin("@", user, host, NULL); smlTrace(TRACE_EXIT, "%s - %s", __func__, VA_STRING(id)); return id; // smlTrace(TRACE_INTERNAL, "%s - %s", __func__, VA_STRING(id)); // char *b64 = g_base64_encode(id, strlen(id)); // smlSafeCFree(&id); // smlTrace(TRACE_EXIT, "%s - %s", __func__, VA_STRING(b64)); // return b64; } SmlBool smlDataSyncDevInfInit( SmlDataSyncObject *dsObject, SmlDevInfDevTyp type, SmlError **error) { CHECK_ERROR_REF SmlDevInf *devinf = NULL; /* fix missing identifier */ if (!dsObject->identifier) dsObject->identifier = smlDataSyncDevInfGetIdentifier(); if (dsObject->fakeDevice) { smlTrace(TRACE_INTERNAL, "%s: faking devinf", __func__); devinf = smlDevInfNew(dsObject->identifier, SML_DEVINF_DEVTYPE_SMARTPHONE, error); if (!devinf) goto error; smlDevInfSetManufacturer(devinf, dsObject->fakeManufacturer); smlDevInfSetModel(devinf, dsObject->fakeModel); smlDevInfSetSoftwareVersion(devinf, dsObject->fakeSoftwareVersion); } else { smlTrace(TRACE_INTERNAL, "%s: not faking devinf", __func__); devinf = smlDevInfNew(dsObject->identifier, type, error); if (!devinf) goto error; smlDevInfSetSoftwareVersion(devinf, dsObject->fakeSoftwareVersion); } smlDevInfSetSupportsNumberOfChanges(devinf, TRUE); smlDevInfSetSupportsLargeObjs(devinf, TRUE); if (!dsObject->onlyLocaltime) smlDevInfSetSupportsUTC(devinf, TRUE); smlAssert(dsObject->maxMsgSize); smlAssert(dsObject->maxObjSize); dsObject->localDevInf = devinf; dsObject->agent = smlDevInfAgentNew(dsObject->localDevInf, error); if (!dsObject->agent) goto error; smlDevInfRef(dsObject->localDevInf); /* the agent consumes the object */ if (!smlDevInfAgentRegister(dsObject->agent, dsObject->manager, error)) goto error; return TRUE; error: if (devinf) smlDevInfUnref(devinf); if (dsObject->agent) smlDevInfAgentFree(dsObject->agent); dsObject->localDevInf = NULL; dsObject->agent = NULL; return FALSE; } SmlBool smlDataSyncManageDevInf( SmlDataSyncObject *dsObject, SmlBool sendGet, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %i, %p)", __func__, dsObject, sendGet, error); CHECK_ERROR_REF smlAssertMsg(dsObject->session, "an active session is needed to manage device informations"); /* If the callback is available * then we dump the local device information first. */ if (dsObject->writeDevInfCallback) { /* store device info */ smlTrace(TRACE_INTERNAL, "%s: calling write DevInf callback", __func__); if (!dsObject->writeDevInfCallback( dsObject, dsObject->localDevInf, dsObject->writeDevInfUserdata, error)) goto error; } /* handle remote device information */ if (smlDataSyncDevInfLoadRemote(dsObject, sendGet, error) && dsObject->remoteDevInf && dsObject->handleRemoteDevInfCallback && !dsObject->handleRemoteDevInfCallback( dsObject, dsObject->remoteDevInf, dsObject->handleRemoteDevInfUserdata, error)) { /* the remote device information * and the callback are available * but the callback failed. */ goto error; } else { /* check if there was an error during DevInfLoadRemote * or dsObject->handleRemoteDevInfCallback */ if (*error != NULL) goto error; /* if the remote peer does not support UTC * then dsObject must be configured properly */ if (dsObject->remoteDevInf && !smlDevInfSupportsUTC(dsObject->remoteDevInf)) { smlTrace(TRACE_INTERNAL, "%s: enforcing localtime because of remote DevInf", __func__); dsObject->onlyLocaltime = TRUE; } } smlTrace(TRACE_EXIT, "%s - TRUE", __func__); return TRUE; error: smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(error)); return FALSE; } libsyncml-0.5.4/libsyncml/data_sync_api/data_sync.h100644 1750 1750 14050 11211710410 22351 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2008-2009 Michael Bell * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #ifndef _SML_DATA_SYNC_INTERNALS_H_ #define _SML_DATA_SYNC_INTERNALS_H_ #include #include #include #include #include #include #include #include #include #include /* typedef for internal function pointers */ typedef SmlBool (* SmlFunctionDataSyncInit) ( SmlDataSyncObject *dsObject, SmlError **error); typedef SmlBool (* SmlFunctionDataSyncConnect) ( SmlDataSyncObject *dsObject, SmlError **error); typedef SmlBool (* SmlFunctionTransportInit) ( SmlDataSyncObject *dsObject, SmlError **error); typedef SmlBool (* SmlFunctionTransportConnect) ( SmlDataSyncObject *dsObject, SmlError **error); /*! @brief This is the internal representation of the OMA DS packages. * OMA DS specifications define packages which can consist * of several messages. Each package represents a state. * The packages 1 to 6 are defined in the standards. * The package 0 is the usual SAN package like known from * OMA DS 1.2. The other states are used if someone * sends a message which has not directly to do with * the synchronization and the message is not part of * package 1 to 6. * * */ typedef enum { SML_PACKAGE_RECEIVED_UNKNOWN = -3, SML_PACKAGE_RECEIVED_DEVINF_REQUEST = -2, /* only DevInf was requested */ SML_PACKAGE_RECEIVED_DEVINF = -1, /* only DevInf was received */ SML_PACKAGE_0 = 0, /* SAN */ SML_PACKAGE_1 = 1, /* alerts from client */ SML_PACKAGE_2 = 2, /* alerts from server */ SML_PACKAGE_3 = 3, /* sync from client */ SML_PACKAGE_4 = 4, /* sync from server */ SML_PACKAGE_5 = 5, /* map from client */ SML_PACKAGE_6 = 6, /* end from server */ SML_PACKAGE_END = 7, /* client after end received from server */ } SmlDataSyncPackageType; typedef enum { SML_DATA_SYNC_STATE_UNKNOWN = 0, SML_DATA_SYNC_STATE_NEW = 1, SML_DATA_SYNC_STATE_INITIALIZED = 2, SML_DATA_SYNC_STATE_CONNECTED = 3, SML_DATA_SYNC_STATE_SESSION_READY = 4, SML_DATA_SYNC_STATE_SENT_CHANGES = 5, SML_DATA_SYNC_STATE_DISCONNECT_IN_PROGRESS = 6, SML_DATA_SYNC_STATE_DISCONNECTED = 7, } SmlDataSyncInternalStateType; /* typedefs for internal objects */ /*! @brief This object represents an OMA DS datastore. */ typedef struct SmlDataSyncDatastore { SmlDataSyncObject *dsObject; void *syncChanges; void *syncContexts; char *sourceUri; char *targetUri; char *contentType; SmlDsServer *server; SmlDsSession *session; char *localNext; char *remoteNext; SmlAlertType alertType; GList *changes; } SmlDataSyncDatastore; /*! @brief This is the central synchronization object. */ struct SmlDataSyncObject { SmlSessionType dsType; SmlTransportType tspType; SmlTransportConnectionType conType; SmlManager *manager; SmlTransport *tsp; SmlAuthenticator *auth; SmlDevInf *localDevInf; SmlDevInf *remoteDevInf; SmlDevInfAgent *agent; SmlSession *session; GMutex *managerMutex; /* loop management */ GSourceFuncs *functions; SmlThread *thread; GMainContext *context; GSource *source; /* config data */ GList *datastores; SmlBool useNumberOfChanges; SmlBool useTimestampAnchor; SmlBool onlyLocaltime; SmlBool onlyReplace; SmlBool useStringTable; SmlBool useWbxml; unsigned int maxObjSize; unsigned int maxMsgSize; char *identifier; SmlAuthType authType; char *username; char *password; char *url; char *target; SmlProtocolVersion version; char *fakeDevice; char *fakeManufacturer; char *fakeModel; char *fakeSoftwareVersion; /* states */ SmlDataSyncInternalStateType internalState; int refCount; SmlDataSyncPackageType actualPackage; /* callbacks */ SmlDataSyncEventCallback eventCallback; void *eventUserdata; SmlDataSyncGetAlertTypeCallback getAlertTypeCallback; void *getAlertTypeUserdata; SmlDataSyncChangeCallback changeCallback; void *changeUserdata; SmlDataSyncChangeStatusCallback changeStatusCallback; SmlDataSyncMappingCallback mappingCallback; void *mappingUserdata; SmlDataSyncGetAnchorCallback getAnchorCallback; void *getAnchorUserdata; SmlDataSyncSetAnchorCallback setAnchorCallback; void *setAnchorUserdata; SmlDataSyncWriteDevInfCallback writeDevInfCallback; void *writeDevInfUserdata; SmlDataSyncReadDevInfCallback readDevInfCallback; void *readDevInfUserdata; SmlDataSyncHandleRemoteDevInfCallback handleRemoteDevInfCallback; void *handleRemoteDevInfUserdata; /* internal function pointers */ SmlFunctionDataSyncInit funcDsInit; SmlFunctionDataSyncInit funcDsConnect; SmlFunctionTransportInit funcTspInit; SmlFunctionTransportConnect funcTspConnect; SmlDsSessionAlertCb funcDatastoreAlert; }; /*! @brief This internal structure represents exactly one change. */ typedef struct SmlDataSyncChange { SmlDataSyncDatastore *datastore; SmlChangeType type; char *name; char *data; unsigned int size; void *userdata; } SmlDataSyncChange; void smlDataSyncSendEvent( SmlDataSyncObject *dsObject, SmlDataSyncEventType type, void *userdata, SmlError *error); SmlBool smlDataSyncSendMap( SmlDataSyncObject *dsObject, SmlError **error); #endif /* _SML_DATA_SYNC_INTERNALS_H_ */ libsyncml-0.5.4/libsyncml/data_sync_api/data_sync_abort.c100644 1750 1750 5042 11211710410 23514 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2009 Michael Bell * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include "../syncml.h" #include "../syncml_internals.h" #include "../sml_error_internals.h" #include #include #include #include "data_sync.h" /** * This code is put into a separate source code file * because potentially all internal tricks and hacks * are used to abort the OMA DS session most carefully * ... at minimum in the future ... */ #include "../sml_session_internals.h" #include "../sml_manager_internals.h" SmlBool smlDataSyncAbort( SmlDataSyncObject *dsObject, SmlError **error) { smlTrace(TRACE_ENTRY, "%s", __func__); /* determine the state of the session */ if (!dsObject->session->sending && !dsObject->session->waiting) { /* send abort command */ smlTrace(TRACE_INTERNAL, "%s: A careful abort is possible.", __func__); /* FIXME: Send a default abort command. */ /* FIXME: Is it necessary or recommended to abort every datastore. */ goto WORKAROUND; } else { /* stop transport */ WORKAROUND: smlTrace(TRACE_INTERNAL, "%s: A hard abort is required.", __func__); if (SML_DATA_SYNC_STATE_CONNECTED <= dsObject->internalState && dsObject->internalState < SML_DATA_SYNC_STATE_DISCONNECT_IN_PROGRESS) { dsObject->internalState = SML_DATA_SYNC_STATE_DISCONNECT_IN_PROGRESS; SmlLink *link_ = smlManagerSessionGetLink( dsObject->manager, dsObject->session, error); if (!link_ && *error) goto error; if (!smlTransportDisconnect(dsObject->tsp, link_, error)) goto error; } } smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error: smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(error)); return FALSE; } libsyncml-0.5.4/libsyncml/data_sync_api/data_sync_loop.c100644 1750 1750 7247 11211710410 23367 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2008 Michael Bell * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include "../syncml.h" #include "../syncml_internals.h" #include "data_sync_devinf.h" #include "libsyncml/sml_error_internals.h" static gboolean _prepare(GSource *source, gint *timeout_) { smlTrace(TRACE_INTERNAL, "%s(%p, %p)", __func__, source, timeout_); *timeout_ = 50; return FALSE; } static gboolean _check(GSource *source) { SmlDataSyncObject *dsObject = *((SmlDataSyncObject **)(source + 1)); GList *o = dsObject->datastores; for (; o; o = o->next) { SmlDataSyncDatastore *datastore = o->data; if (datastore->session && smlDsSessionCheck(datastore->session)) return TRUE; } return smlManagerCheck(dsObject->manager); } static gboolean _dispatch(GSource *source, GSourceFunc callback, gpointer user_data) { smlTrace(TRACE_INTERNAL, "%s(%p, %p, %p)", __func__, source, callback, user_data); SmlDataSyncObject *dsObject = user_data; GList *o = dsObject->datastores; for (; o; o = o->next) { SmlDataSyncDatastore *datastore = o->data; if (datastore->session) smlDsSessionDispatch(datastore->session); } smlManagerDispatch(dsObject->manager); return TRUE; } SmlBool smlDataSyncLoopStart(SmlDataSyncObject *dsObject, SmlError **error) { smlTrace(TRACE_ENTRY, "%s", __func__); CHECK_ERROR_REF /* prepare function */ dsObject->functions = smlTryMalloc0(sizeof(GSourceFuncs), error); if (!dsObject->functions) goto error; dsObject->functions->prepare = _prepare; dsObject->functions->check = _check; dsObject->functions->dispatch = _dispatch; dsObject->functions->finalize = NULL; /* prepare context and thread */ dsObject->context = g_main_context_new(); if (!dsObject->context) goto error; dsObject->thread = smlThreadNew(dsObject->context, error); if (!dsObject->thread) goto error; smlThreadStart(dsObject->thread); /* prepare source for thread's main loop */ dsObject->source = g_source_new(dsObject->functions, sizeof(GSource) + sizeof(SmlDataSyncObject *)); SmlDataSyncObject **ptr = (SmlDataSyncObject **)(dsObject->source + 1); *ptr = dsObject; g_source_set_callback(dsObject->source, NULL, dsObject, NULL); g_source_attach(dsObject->source, dsObject->context); g_main_context_ref(dsObject->context); smlTrace(TRACE_EXIT, "%s - TRUE", __func__); return TRUE; error: smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(error)); return FALSE; } void smlDataSyncLoopStop(SmlDataSyncObject *dsObject) { smlTrace(TRACE_ENTRY, "%s", __func__); /* stop thread */ smlThreadStop(dsObject->thread); smlThreadFree(dsObject->thread); dsObject->thread = NULL; /* detach source */ g_source_unref(dsObject->source); dsObject->source = NULL; /* free context */ g_main_context_unref(dsObject->context); dsObject->context = NULL; /* free functions */ smlSafeFree((gpointer *)&(dsObject->functions)); dsObject->functions = NULL; smlTrace(TRACE_EXIT, "%s - TRUE", __func__); } libsyncml-0.5.4/libsyncml/data_sync_api/transport_obex_client.c100644 1750 1750 6275 11211710410 25000 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2008-2009 Michael Bell * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include "transport.h" #include "libsyncml/sml_error_internals.h" #include "libsyncml/sml_support.h" SmlBool smlDataSyncTransportObexClientInit( SmlDataSyncObject *dsObject, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p)", __func__, dsObject, error); CHECK_ERROR_REF if (dsObject->url && !smlTransportSetConfigOption( dsObject->tsp, SML_TRANSPORT_CONFIG_URL, dsObject->url, error)) goto error; smlTrace(TRACE_EXIT, "%s - TRUE", __func__); return TRUE; error: smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(error)); return FALSE; } SmlBool smlDataSyncTransportObexClientConnect(SmlDataSyncObject *dsObject, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p)", __func__, dsObject, error); CHECK_ERROR_REF /* Connect transport layer */ if (!smlTransportConnect(dsObject->tsp, error)) goto error; /* Create a SAN */ SmlNotificationVersion sanVersion = SML_SAN_VERSION_UNKNOWN; switch(dsObject->version) { case SML_VERSION_10: sanVersion = SML_SAN_VERSION_10; break; case SML_VERSION_11: sanVersion = SML_SAN_VERSION_11; break; case SML_VERSION_12: sanVersion = SML_SAN_VERSION_12; break; case SML_VERSION_UNKNOWN: smlErrorSet(error, SML_ERROR_GENERIC, "Unknown SyncML SAN Version."); goto error; break; } SmlNotification *san = smlNotificationNew( sanVersion, SML_SAN_UIMODE_UNSPECIFIED, SML_SAN_INITIATOR_USER, 1, dsObject->identifier, "/", dsObject->useWbxml ? SML_MIMETYPE_WBXML : SML_MIMETYPE_XML, error); if (!san) goto error; smlNotificationSetManager(san, dsObject->manager); /* init digest - SAN uses always MD5 */ if (dsObject->username != NULL && strlen(dsObject->username)) { SmlCred *cred = smlCredNewAuth( SML_AUTH_TYPE_MD5, dsObject->username, dsObject->password, error); if (!cred) goto error; smlNotificationSetCred(san, cred); smlCredUnref(cred); cred = NULL; } GList *o = dsObject->datastores; for (; o; o = o->next) { SmlDataSyncDatastore *datastore = o->data; if (!smlDsServerAddSan(datastore->server, san, error)) goto error; } if (!smlNotificationSend(san, dsObject->tsp, error)) goto error; smlNotificationFree(san); san = NULL; smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error: smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(error)); return FALSE; } libsyncml-0.5.4/libsyncml/data_sync_api/standard.h100644 1750 1750 7646 11211710410 22201 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2008-2009 Michael Bell * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ /** * @defgroup PublicHighLevelAPI High Level API * @ingroup PublicAPI * @brief The public part */ /** * @defgroup PublicHighLevelStandard High Level Standard Functions * @ingroup PublicHighLevelAPI * @brief The public part */ /*@{*/ #ifndef _SML_DATA_SYNC_API_STANDARD_H_ #define _SML_DATA_SYNC_API_STANDARD_H_ #include #ifdef __cplusplus extern "C" { #endif /*! @brief These are all possible events which the high level API sends. */ typedef enum SmlDataSyncEventType { SML_DATA_SYNC_EVENT_ERROR = 0, SML_DATA_SYNC_EVENT_CONNECT = 1, SML_DATA_SYNC_EVENT_GOT_ALL_ALERTS = 2, SML_DATA_SYNC_EVENT_GOT_ALL_CHANGES = 3, SML_DATA_SYNC_EVENT_GOT_ALL_MAPPINGS = 4, SML_DATA_SYNC_EVENT_DISCONNECT = 5, SML_DATA_SYNC_EVENT_FINISHED = 6, } SmlDataSyncEventType; typedef struct SmlDataSyncObject SmlDataSyncObject; /* object creation and configuration */ SmlDataSyncObject *smlDataSyncNew( SmlSessionType dsType, SmlTransportType tspType, SmlError **error); void smlDataSyncObjectRef(SmlDataSyncObject *dsObject); SmlBool smlDataSyncSetOption( SmlDataSyncObject *dsObject, const char *name, const char *value, SmlError **error); SmlBool smlDataSyncAddDatastore(SmlDataSyncObject *dsObject, const char *contentType, const char *target, const char *source, SmlError **error); /* init session */ SmlBool smlDataSyncInit(SmlDataSyncObject *dsObject, SmlError **error); SmlBool smlDataSyncRun(SmlDataSyncObject *dsObject, SmlError **error); /* synchronize */ SmlBool smlDataSyncAddChange( SmlDataSyncObject *dsObject, const char *source, SmlChangeType type, const char *name, const char *data, unsigned int size, void *userdata, /* for SmlDataSyncChangeStatusCallback */ SmlError **error); SmlBool smlDataSyncSendChanges(SmlDataSyncObject *dsObject, SmlError **error); SmlBool smlDataSyncAddMapping( SmlDataSyncObject *dsObject, const char *source, const char *remoteID, const char *localID, SmlError **error); /** * Aborts the data synchronization in every state of the API. * The only possible function call after this function is * smlDataSyncObjectUnref. If you called this function then * you can still wait for SML_DATA_SYNC_EVENT_ERROR or * SML_DATA_SYNC_EVENT_FINISHED before you start to cleanup * with smlDataSyncObjectUnref. * * @param dsObject The data sync object * @param error The error condition * * @return TRUE on success. False on failure. */ SmlBool smlDataSyncAbort( SmlDataSyncObject *dsObject, SmlError **error); /** * Returns the identity of the remote sync peer. This is the * tag. The returned reference is not owned * by the caller and must NOT be freed or unrefed by the caller. * * @param dsObject The data sync object * @param error The error condition * @return The identity of the remote peer */ const SmlLocation *smlDataSyncGetTarget( SmlDataSyncObject *dsObject, SmlError **error); /* close session */ void smlDataSyncObjectUnref(SmlDataSyncObject **dsObject); #ifdef __cplusplus } #endif #endif /* _SML_DATA_SYNC_API_STANDARD_H_ */ /*@}*/ libsyncml-0.5.4/libsyncml/data_sync_api/data_sync_client.c100644 1750 1750 26253 11211710410 23712 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2008-2009 Michael Bell * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include "data_sync_server.h" #include "data_sync_common.h" #include "libsyncml/sml_error_internals.h" #include "data_sync_callbacks.h" #include "libsyncml/objects/sml_ds_server.h" #include "data_sync_devinf.h" #include "libsyncml/sml_support.h" static SmlBool smlDataSyncClientAlertCallback( SmlDsSession *dsession, SmlAlertType type, const char *last, const char *next, void *userdata) { smlTrace(TRACE_ENTRY, "%s(%p, %i, %s, %s, %p)", __func__, dsession, type, VA_STRING(last), VA_STRING(next), userdata); SmlDataSyncDatastore *datastore = userdata; SmlDataSyncObject *dsObject = datastore->dsObject; SmlBool ret = TRUE; SmlError *error = NULL; /* libsyncml only supports SML_ALERT_TWO_WAY and SML_ALERT_SLOW_SYNC * but some old phones reply on a SAN alert 206 with a slow sync 201 * alert or a SAN alert 206 (insteed of a normal two way alert 200). * Therefore it is necessary to check for TWO_WAY and TWO_WAY_BY_SERVER. */ if (type != SML_ALERT_TWO_WAY && type != SML_ALERT_SLOW_SYNC && type != SML_ALERT_TWO_WAY_BY_SERVER) { smlErrorSet(&error, SML_ERROR_NOT_IMPLEMENTED, "Unsupported alert type %d.", type); goto error; } char *remote_key = g_strdup_printf("remoteanchor%s", smlDsSessionGetLocation(dsession)); datastore->remoteNext = g_strdup(next); /* We return FALSE if we need a special return code as answer: * SML_ERROR_REQUIRE_REFRESH 508 * This return code enforces a SLOW-SYNC. */ if (type == SML_ALERT_TWO_WAY || type == SML_ALERT_TWO_WAY_BY_SERVER) { if (!last) { smlTrace(TRACE_INTERNAL, "%s: TWO-WAY-SYNC is requested but there is no LAST anchor.", __func__); type = SML_ALERT_SLOW_SYNC; ret = FALSE; } else { char *cached = NULL; if (dsObject->getAnchorCallback) cached = dsObject->getAnchorCallback( dsObject, remote_key, dsObject->getAnchorUserdata, &error); if (!cached && error) goto error; if (!cached || strcmp(cached, last)) { smlTrace(TRACE_INTERNAL, "%s: TWO-WAY-SYNC is requested but the cached LAST anchor (%s) does not match the presented LAST anchor from the remote peer (%s).", __func__, last, cached); if (cached) smlSafeCFree(&cached); type = SML_ALERT_SLOW_SYNC; ret = FALSE; } } } if (dsObject->getAlertTypeCallback) { SmlAlertType h = dsObject->getAlertTypeCallback( dsObject, datastore->sourceUri, type, dsObject->getAlertTypeUserdata, &error); if (h == SML_ALERT_UNKNOWN || error) goto error; /* There is only one situation where the callback can return * something different than type. If the client requested an * alert type 200, the server requested an alert type 200 too * and after this there is a problem detected on the client * then the returned type can be 201 SLOW-SYNC. * * If this happens then a new alert 201 and a status 508 must * be send. */ if (h != type) { if (h != SML_ALERT_SLOW_SYNC) { smlErrorSet(&error, SML_ERROR_GENERIC, "It is not possible to change the alert type after an OMA DS client received the alerts from the OMA DS server."); goto error; } else { /* send alert 201 */ SmlLocation *source = NULL; source = smlLocationNew(datastore->sourceUri, NULL, &error); if (!source) goto error; SmlCommand *alert = NULL; alert = smlCommandNewAlert( SML_ALERT_SLOW_SYNC, smlDsSessionGetTarget(datastore->session), source, NULL, datastore->localNext, NULL, &error); if (!alert) { smlLocationUnref(source); goto error; } smlLocationUnref(source); if (!smlSessionSendCommand(dsObject->session, alert, NULL, NULL, NULL, &error)) { smlCommandUnref(alert); goto error; } smlCommandUnref(alert); /* send status 508 */ ret = FALSE; } } } smlSafeCFree(&remote_key); smlTrace(TRACE_EXIT, "%s: %i", __func__, ret); return ret; error: smlErrorRef(&error); smlDataSyncSendEvent( dsObject, SML_DATA_SYNC_EVENT_ERROR, dsObject->eventUserdata, error); smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(&error)); smlErrorDeref(&error); return FALSE; } SmlBool smlDataSyncClientSendAlert( SmlDataSyncDatastore *datastore, SmlAlertType type, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %d, %p)", __func__, datastore, type, error); CHECK_ERROR_REF SmlDataSyncObject *dsObject = datastore->dsObject; /* initialize the last anchor */ SmlAlertType alertType = type; char *local_last = NULL; // perhaps NULL is better if (dsObject->getAlertTypeCallback) { alertType = dsObject->getAlertTypeCallback( dsObject, datastore->sourceUri, type, dsObject->getAlertTypeUserdata, error); if (*error) goto error; } if (alertType == SML_ALERT_UNKNOWN) { smlTrace(TRACE_INTERNAL, "%s: no alert type => slow-sync", __func__); alertType = SML_ALERT_SLOW_SYNC; } if (alertType != SML_ALERT_SLOW_SYNC) { /* this must be a two-way-sync */ alertType = SML_ALERT_TWO_WAY; char *local_key = g_strdup_printf("localanchor%s", smlDsServerGetLocation(datastore->server)); if (dsObject->getAnchorCallback) local_last = dsObject->getAnchorCallback( dsObject, local_key, dsObject->getAnchorUserdata, error); smlSafeCFree(&local_key); } /* initialize the next anchor */ if (datastore->localNext) smlSafeCFree(&(datastore->localNext)); datastore->localNext = smlDataSyncGetNextAnchor(datastore, local_last, error); /* The session is required here. So if the session is missing * then the function has to block here. This is no real problem * because the SESSION_EVENT_NEW must already be in the queue of * the manager object. */ while (!dsObject->session) { smlManagerDispatch(dsObject->manager); } /* The OMA DS client starts the synchronization so there should be no * DsSession (datastore session) present. */ datastore->session = smlDsServerSendAlert( datastore->server, dsObject->session, alertType, local_last, datastore->localNext, smlDataSyncAlertStatusCallback, datastore, error); if (local_last) smlSafeCFree(&local_last); if (!datastore->session) goto error; /* Only the alert callback is registered here because the changes should * be managed after the function ds_client_get_changeinfo was called. */ smlDsSessionGetAlert(datastore->session, smlDataSyncClientAlertCallback, datastore); if (dsObject->changeCallback) { smlDsSessionGetSync(datastore->session, smlDataSyncSyncCallback, datastore); smlDsSessionGetChanges(datastore->session, smlDataSyncChangeCallback, datastore); } /* If a slow-sync alert is initiated and the remote peer * did not request it then the function must return false * to trigger a status 508 (REFRESH_REQUIRED). * If the requested alert type is not known then there * is no need for a status and the function returns true. * This can happen if the remote peer did not trigger * the client via a SAN (e.g. OMA DS client over HTTP). */ SmlBool ret = TRUE; if (alertType == SML_ALERT_SLOW_SYNC && alertType != type && type != SML_ALERT_UNKNOWN) { ret = FALSE; } smlTrace(TRACE_EXIT, "%s: %i", __func__, ret); return ret; error: smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(error)); return FALSE; } static SmlErrorType smlDataSyncSanCallback( SmlDsServer *server, SmlSession *session, SmlAlertType type, void *userdata) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %d, %p)", __func__, server, session, type, userdata); SmlDataSyncDatastore *datastore = userdata; SmlDataSyncObject *dsObject = datastore->dsObject; SmlError *error = NULL; SmlErrorType ret = SML_NO_ERROR; /* soemtimes the event manager thread is too slow */ if (!dsObject->session) { dsObject->session = session; smlSessionRef(session); } if (!smlDataSyncClientSendAlert(datastore, type, &error)) { if (!error) ret = SML_ERROR_REQUIRE_REFRESH; else goto error; } smlTrace(TRACE_EXIT, "%s: %i", __func__, ret); return ret; error: smlErrorRef(&error); smlDataSyncSendEvent( dsObject, SML_DATA_SYNC_EVENT_ERROR, dsObject->eventUserdata, error); smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(&error)); smlErrorDeref(&error); return SML_ERROR_GENERIC; } SmlBool smlDataSyncClientInit(SmlDataSyncObject *dsObject, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p)", __func__, dsObject, error); CHECK_ERROR_REF /* The manager responsible for handling the other objects */ dsObject->manager = smlManagerNew(dsObject->tsp, error); if (!dsObject->manager) goto error; smlManagerSetEventCallback(dsObject->manager, smlDataSyncEventCallback, dsObject); smlManagerSetLocalMaxMsgSize(dsObject->manager, dsObject->maxMsgSize); smlManagerSetLocalMaxObjSize(dsObject->manager, dsObject->maxObjSize); /* set server specific callbacks */ dsObject->funcDatastoreAlert = smlDataSyncClientAlertCallback; /* prepare device info */ if (!smlDataSyncDevInfInit(dsObject, SML_DEVINF_DEVTYPE_WORKSTATION, error)) goto error; /* prepare datastore server */ GList *o = dsObject->datastores; for (; o; o = o->next) { SmlDataSyncDatastore *datastore = o->data; smlTrace(TRACE_INTERNAL, "preparing DsServer (datastore) %s", datastore->sourceUri); /* We now create the ds server at the given location. */ SmlLocation *loc = smlLocationNew(datastore->sourceUri, NULL, error); if (!loc) goto error; datastore->server = smlDsClientNew(datastore->contentType, loc, loc, error); smlLocationUnref(loc); if (!datastore->server) goto error; if (!smlDsServerRegister(datastore->server, dsObject->manager, error)) goto error; /* this is a client and not a server * but the callback initializes only database->session (DsSession) */ smlDsServerSetConnectCallback( datastore->server, smlDataSyncDatastoreConnectCallback, datastore); smlDsServerSetSanSessionCallback( datastore->server, smlDataSyncSanCallback, datastore); /* And we also add the devinfo to the devinf agent */ if (!smlDataSyncDevInfAddDatastore(dsObject->localDevInf, datastore, error)) goto error; } /* Run the manager */ if (!smlManagerStart(dsObject->manager, error)) goto error; /* Initialize the Transport */ if (!smlTransportInitialize(dsObject->tsp, error)) goto error; smlTrace(TRACE_EXIT, "%s - TRUE", __func__); return TRUE; error: smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(error)); return FALSE; } libsyncml-0.5.4/libsyncml/data_sync_api/data_sync_callbacks.h100644 1750 1750 6470 11211710410 24337 0ustar00bellmichbellmich/* * syncml plugin - A syncml plugin for OpenSync * Copyright (C) 2008 Michael Bell * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #ifndef _SML_DATA_SYNC_CALLBACKS_H #define _SML_DATA_SYNC_CALLBACKS_H #include "data_sync.h" /* **************************************** */ /* ***** Management Callbacks ***** */ /* **************************************** */ void smlDataSyncEventCallback( SmlManager *manager, SmlManagerEventType type, SmlSession *session, SmlError *error, void *userdata); /* *************************************** */ /* ***** DsSession Callbacks ***** */ /* *************************************** */ void smlDataSyncDatastoreConnectCallback( SmlDsSession *dsession, void *userdata); /* *********************************** */ /* ***** Alert Callbacks ***** */ /* *********************************** */ /* The real alert callbacks are specific for DS clients and servers. * So please check data_sync_client.h and data_sync_server.h for more details. */ void smlDataSyncAlertStatusCallback( SmlSession *session, SmlStatus *status, void *userdata); /* ********************************** */ /* ***** Sync Callbacks ***** */ /* ********************************** */ void smlDataSyncSyncCallback( SmlDsSession *dsession, unsigned int numchanges, void *userdata); void smlDataSyncSyncStatusCallback( SmlSession *session, SmlStatus *status, void *userdata); /* ************************************ */ /* ***** Change Callbacks ***** */ /* ************************************ */ SmlBool smlDataSyncChangeCallback( SmlDsSession *dsession, SmlChangeType type, const char *uid, char *data, unsigned int size, const char *contenttype, void *userdata, SmlError **smlerror); void smlDataSyncChangeStatusCallback( SmlDsSession *dsession, SmlStatus *status, const char *newuid, void *userdata); void smlDataSyncMappingCallback( SmlDsSession *dsession, SmlLocation *orig, SmlLocation *newuid, void *userdata); /* ********************************* */ /* ***** Map Callbacks ***** */ /* ********************************* */ void smlDataSyncMapStatusCallback( SmlSession *session, SmlStatus *status, void *userdata); /* ******************************************* */ /* ***** Authentication Callback ***** */ /* ******************************************* */ SmlBool smlDataSyncVerifyUserCallback( SmlChal *chal, SmlCred *cred, const char *username, void *userdata, SmlError **error); #endif /* _SML_DATA_SYNC_CALLBACKS_H */ libsyncml-0.5.4/libsyncml/data_sync_api/callbacks.h100644 1750 1750 10637 11211710410 22332 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2008 Michael Bell * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ /** * @defgroup PublicHighLevelCallbacks High Level Callbacks * @ingroup PublicHighLevelAPI * @brief The public part */ /*@{*/ #ifndef _SML_DATA_SYNC_API_CALLBACKS_H_ #define _SML_DATA_SYNC_API_CALLBACKS_H_ #include #ifdef __cplusplus extern "C" { #endif /* required callbacks - the event handler */ typedef void (* SmlDataSyncEventCallback) ( SmlDataSyncObject *dsObject, SmlDataSyncEventType type, void *userdata, SmlError *error); typedef SmlAlertType (* SmlDataSyncGetAlertTypeCallback) ( SmlDataSyncObject *dsObject, const char *source, SmlAlertType type, void *userdata, SmlError **error); typedef SmlBool (* SmlDataSyncChangeCallback) ( SmlDataSyncObject *dsObject, const char *source, SmlChangeType type, const char *uid, char *data, unsigned int size, void *userdata, SmlError **error); /* FIXME: newuid must be removed before next API break */ /* FIXME: DEPRECATED */ typedef SmlBool (* SmlDataSyncChangeStatusCallback) ( SmlDataSyncObject *dsObject, unsigned int code, const char *newuid, void *userdata, SmlError **error); typedef SmlBool (* SmlDataSyncMappingCallback) ( SmlDataSyncObject *dsObject, const char *source, const char *orig, const char *newuid, void *userdata, SmlError **error); typedef char *(* SmlDataSyncGetAnchorCallback) ( SmlDataSyncObject *dsObject, const char *name, void *userdata, SmlError **error); typedef SmlBool (* SmlDataSyncSetAnchorCallback) ( SmlDataSyncObject *dsObject, const char *name, const char *value, void *userdata, SmlError **error); typedef SmlBool (* SmlDataSyncWriteDevInfCallback) ( SmlDataSyncObject *dsObject, SmlDevInf *devinf, void *userdata, SmlError **error); typedef SmlDevInf *(* SmlDataSyncReadDevInfCallback) ( SmlDataSyncObject *dsObject, const char *devid, void *userdata, SmlError **error); typedef SmlBool (* SmlDataSyncHandleRemoteDevInfCallback) ( SmlDataSyncObject *dsObject, SmlDevInf *devinf, void *userdata, SmlError **error); /* functions to register the callbacks */ void smlDataSyncRegisterEventCallback( SmlDataSyncObject *dsObject, SmlDataSyncEventCallback callback, void *userdata); void smlDataSyncRegisterGetAlertTypeCallback( SmlDataSyncObject *dsObject, SmlDataSyncGetAlertTypeCallback callback, void *userdata); void smlDataSyncRegisterChangeCallback( SmlDataSyncObject *dsObject, SmlDataSyncChangeCallback callback, void *userdata); void smlDataSyncRegisterMappingCallback( SmlDataSyncObject *dsObject, SmlDataSyncMappingCallback callback, void *userdata); void smlDataSyncRegisterGetAnchorCallback( SmlDataSyncObject *dsObject, SmlDataSyncGetAnchorCallback callback, void *userdata); void smlDataSyncRegisterSetAnchorCallback( SmlDataSyncObject *dsObject, SmlDataSyncSetAnchorCallback callback, void *userdata); void smlDataSyncRegisterWriteDevInfCallback( SmlDataSyncObject *dsObject, SmlDataSyncWriteDevInfCallback callback, void *userdata); void smlDataSyncRegisterReadDevInfCallback( SmlDataSyncObject *dsObject, SmlDataSyncReadDevInfCallback callback, void *userdata); void smlDataSyncRegisterHandleRemoteDevInfCallback( SmlDataSyncObject *dsObject, SmlDataSyncHandleRemoteDevInfCallback callback, void *userdata); /* ChangeStatus uses the userdata from AddChange */ void smlDataSyncRegisterChangeStatusCallback( SmlDataSyncObject *dsObject, SmlDataSyncChangeStatusCallback callback); #ifdef __cplusplus } #endif #endif /* _SML_DATA_SYNC_API_CALLBACKS_H_ */ /*@}*/ libsyncml-0.5.4/libsyncml/data_sync_api/data_sync_server.h100644 1750 1750 2062 11211710410 23717 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2008 Michael Bell * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #ifndef _SML_DATA_SYNC_SERVER_H_ #define _SML_DATA_SYNC_SERVER_H_ #include "data_sync.h" SmlBool smlDataSyncServerInit( SmlDataSyncObject *dsObject, SmlError **error); #endif /* _SML_DATA_SYNC_SERVER_H_ */ libsyncml-0.5.4/libsyncml/data_sync_api/transport_http_server.c100644 1750 1750 2664 11211710410 25050 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2008-2009 Michael Bell * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include "transport.h" #include "libsyncml/sml_error_internals.h" #include "libsyncml/sml_support.h" SmlBool smlDataSyncTransportHttpServerInit( SmlDataSyncObject *dsObject, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p)", __func__, dsObject, error); CHECK_ERROR_REF if (dsObject->url != NULL && !smlTransportSetConfigOption( dsObject->tsp, SML_TRANSPORT_CONFIG_URL, dsObject->url, error)) goto error; smlTrace(TRACE_EXIT, "%s - TRUE", __func__); return TRUE; error: smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(error)); return FALSE; } libsyncml-0.5.4/libsyncml/data_sync_api/data_sync_common.c100644 1750 1750 6350 11211710410 23700 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2008 Michael Bell * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include "data_sync_common.h" #include "libsyncml/syncml_internals.h" #include "libsyncml/sml_error_internals.h" #include "data_sync_devinf.h" SmlBool smlDataSyncIsTimestamp(const char *anchor, SmlBool timestampDefault) { smlTrace(TRACE_ENTRY, "%s(%s, %d)", __func__, VA_STRING(anchor), timestampDefault); if (anchor == NULL || strlen(anchor) < 1) { /* there is no anchor, so the default is sent */ smlTrace(TRACE_EXIT, "%s - default", __func__); return timestampDefault; } else { /* last is set in the anchor database */ if (strstr(anchor, "Z")) { /* anchor is a timestamp */ smlTrace(TRACE_EXIT, "%s - TRUE", __func__); return TRUE; } else { /* last is a number */ smlTrace(TRACE_EXIT, "%s - FALSE", __func__); return FALSE; } } } char *smlDataSyncGetNextAnchor( SmlDataSyncDatastore *datastore, const char *last, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%s)", __func__, VA_STRING(last)); CHECK_ERROR_REF SmlBool use_timestamp = TRUE; char *next = NULL; use_timestamp = smlDataSyncIsTimestamp(last, datastore->dsObject->useTimestampAnchor); smlTrace(TRACE_INTERNAL, "%s: use timestamp is %d", __func__, use_timestamp); if (use_timestamp) { /* It is necessary to be sure that the remote device supports UTC. */ smlTrace(TRACE_INTERNAL, "%s: session %p, localtime %d, remoteDevInf %p", __func__, datastore->dsObject->session, datastore->dsObject->onlyLocaltime, datastore->dsObject->remoteDevInf); if (datastore->dsObject->session && !datastore->dsObject->onlyLocaltime && !datastore->dsObject->remoteDevInf && !smlDataSyncManageDevInf(datastore->dsObject, FALSE, error)) { goto error; } next = smlTryMalloc0(sizeof(char)*17, error); if (!next) goto error; time_t htime = time(NULL); if (datastore->dsObject->onlyLocaltime) { smlTrace(TRACE_INTERNAL, "%s: use localtime", __func__); strftime(next, 17, "%Y%m%dT%H%M%SZ", localtime(&htime)); } else { smlTrace(TRACE_INTERNAL, "%s: use UTC", __func__); strftime(next, 17, "%Y%m%dT%H%M%SZ", gmtime(&htime)); } } else { if (last == NULL) { next = g_strdup("1"); } else { unsigned long count = strtoul(last, NULL, 10); count++; next = g_strdup_printf("%lu", count); } } smlTrace(TRACE_EXIT, "%s(%s)", __func__, VA_STRING(next)); return next; error: smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(error)); return NULL; } libsyncml-0.5.4/libsyncml/sml_md5.h100644 1750 1750 2250 11211710410 17125 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2005 Armin Bauer * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ /** * @defgroup SmlMD5 SyncML MD5 * @ingroup PublicLowLevelAPI * @brief The public part * */ /*@{*/ #ifndef _SML_MD5_H_ #define _SML_MD5_H_ void smlMD5GetDigest (const char *buffer, int buffer_size, unsigned char digest[16]); char *smlMD5ToString(unsigned char digest[16], SmlError **error); #endif //_SML_BASE64_H_ /*@}*/ libsyncml-0.5.4/libsyncml/sml_devinf.h100644 1750 1750 25521 11211710410 17741 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2005 Armin Bauer * Copyright (C) 2007-2008 Michael Bell * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ /** * @defgroup SmlDevInf SyncML Device Information * @ingroup PublicLowLevelAPI * @brief The public part * */ /*@{*/ #ifndef _SML_DEVINF_H_ #define _SML_DEVINF_H_ SmlDevInfDevTyp smlDevInfDevTypeFromString(const char *name, SmlError **error); const char *smlDevInfDevTypeToString(SmlDevInfDevTyp type, SmlError **error); SmlDevInf *smlDevInfNew(const char *devid, SmlDevInfDevTyp devtyp, SmlError **error); SmlDevInf *smlDevInfRef(SmlDevInf *devinf); void smlDevInfUnref(SmlDevInf *devinf); const char *smlDevInfGetManufacturer(SmlDevInf *devinf); void smlDevInfSetManufacturer(SmlDevInf *devinf, const char *man); const char *smlDevInfGetModel(SmlDevInf *devinf); void smlDevInfSetModel(SmlDevInf *devinf, const char *model); const char *smlDevInfGetOEM(SmlDevInf *devinf); void smlDevInfSetOEM(SmlDevInf *devinf, const char *oem); const char *smlDevInfGetFirmwareVersion(SmlDevInf *devinf); void smlDevInfSetFirmwareVersion(SmlDevInf *devinf, const char *firmwareVersion); const char *smlDevInfGetSoftwareVersion(SmlDevInf *devinf); void smlDevInfSetSoftwareVersion(SmlDevInf *devinf, const char *softwareVersion); const char *smlDevInfGetHardwareVersion(SmlDevInf *devinf); void smlDevInfSetHardwareVersion(SmlDevInf *devinf, const char *hardwareVersion); const char *smlDevInfGetDeviceID(SmlDevInf *devinf); void smlDevInfSetDeviceID(SmlDevInf *devinf, const char *devid); SmlDevInfDevTyp smlDevInfGetDeviceType(SmlDevInf *devinf); void smlDevInfSetDeviceType(SmlDevInf *devinf, SmlDevInfDevTyp devtyp); SmlBool smlDevInfSupportsUTC(SmlDevInf *devinf); void smlDevInfSetSupportsUTC(SmlDevInf *devinf, SmlBool supports); SmlBool smlDevInfSupportsLargeObjs(SmlDevInf *devinf); void smlDevInfSetSupportsLargeObjs(SmlDevInf *devinf, SmlBool supports); SmlBool smlDevInfSupportsNumberOfChanges(SmlDevInf *devinf); void smlDevInfSetSupportsNumberOfChanges(SmlDevInf *devinf, SmlBool supports); void smlDevInfAddDataStore(SmlDevInf *devinf, SmlDevInfDataStore *datastore); unsigned int smlDevInfNumDataStores(SmlDevInf *devinf); const SmlDevInfDataStore *smlDevInfGetNthDataStore(const SmlDevInf *devinf, unsigned int nth); SmlDevInfDataStore *smlDevInfDataStoreNew(const char *sourceRef, SmlError **error); SmlDevInfDataStore *smlDevInfDataStoreRef(SmlDevInfDataStore *datastore); void smlDevInfDataStoreUnref(SmlDevInfDataStore *datastore); const char *smlDevInfDataStoreGetSourceRef(const SmlDevInfDataStore *datastore); void smlDevInfDataStoreSetSourceRef(SmlDevInfDataStore *datastore, const char *sourceref); const char *smlDevInfDataStoreGetDisplayName(const SmlDevInfDataStore *datastore); void smlDevInfDataStoreSetDisplayName(SmlDevInfDataStore *datastore, const char *displayName); unsigned int smlDevInfGetMaxGUIDSize(const SmlDevInfDataStore *datastore); void smlDevInfSetMaxGUIDSize(SmlDevInfDataStore *datastore, unsigned int max); void smlDevInfDataStoreSetRxPref(SmlDevInfDataStore *datastore, const char *contenttype, const char *version); SmlBool smlDevInfDataStoreGetRxPref(const SmlDevInfDataStore *datastore, char **contenttype, char **version); void smlDevInfDataStoreAddRx(SmlDevInfDataStore *datastore, SmlDevInfContentType *ct); unsigned int smlDevInfDataStoreNumRx(const SmlDevInfDataStore *datastore); const SmlDevInfContentType *smlDevInfDataStoreGetNthRx(const SmlDevInfDataStore *datastore, unsigned int n); void smlDevInfDataStoreSetTxPref(SmlDevInfDataStore *datastore, const char *contenttype, const char *version); SmlBool smlDevInfDataStoreGetTxPref(const SmlDevInfDataStore *datastore, char **contenttype, char **version); void smlDevInfDataStoreAddTx(SmlDevInfDataStore *datastore, SmlDevInfContentType *ct); unsigned int smlDevInfDataStoreNumTx(const SmlDevInfDataStore *datastore); const SmlDevInfContentType *smlDevInfDataStoreGetNthTx(const SmlDevInfDataStore *datastore, unsigned int n); void smlDevInfDataStoreSetMemory(SmlDevInfDataStore *datastore, SmlBool shared, unsigned int maxid, unsigned int maxmem); void smlDevInfDataStoreGetMemory(const SmlDevInfDataStore *datastore, SmlBool *shared, unsigned int *maxid, unsigned int *maxmem); void smlDevInfDataStoreSetSyncCap(SmlDevInfDataStore *datastore, SmlDevInfSyncCap cap, SmlBool supported); SmlBool smlDevInfDataStoreGetSyncCap(const SmlDevInfDataStore *datastore, SmlDevInfSyncCap cap); SmlBool smlDevInfAssemble(SmlDevInf *devinf, char **data, unsigned int *size, SmlError **error); SmlCommand *smlDevInfNewResult(SmlCommand *cmd, SmlDevInf *devinf, SmlDevInfVersion version, SmlError **error); SmlCommand *smlDevInfNewPut(SmlDevInf *devinf, SmlDevInfVersion version, SmlError **error); SmlCommand *smlDevInfNewGet(SmlDevInfVersion version, SmlError **error); void smlDevInfConfigureSession(SmlDevInf *devinf, SmlSession *session); SmlDevInf *smlDevInfParse(const char *data, unsigned int length, SmlError **error); SmlDevInf *smlDevInfFromResult(SmlCommand *result, SmlError **error); SmlDevInfCTCapType smlDevInfCTCapTypeFromString(const char *name, SmlError **error); const char *smlDevInfCTCapTypeToString(SmlDevInfCTCapType type, SmlError **error); /* this interface enforce the logical structure behind the devinf spec */ /* so we can generate SyncML 1.0, 1.1 and 1.2 devinf from this structure */ /* the CTCap will be assigned to a datastore if CTType and VerCT match */ /* PropParam stuff */ SmlDevInfPropParam *smlDevInfNewPropParam(SmlError **error); void smlDevInfPropParamSetParamName( // REQUIRED SmlDevInfPropParam *propParam, const char *paramName); void smlDevInfPropParamSetDataType( SmlDevInfPropParam *propParam, const char *dataType); void smlDevInfPropParamSetDisplayName( SmlDevInfPropParam *propParam, const char *displayName); void smlDevInfPropParamAddValEnum( SmlDevInfPropParam *propParam, const char *valEnum); char *smlDevInfPropParamGetParamName(const SmlDevInfPropParam *propParam); char *smlDevInfPropParamGetDataType(const SmlDevInfPropParam *propParam); char *smlDevInfPropParamGetDisplayName(const SmlDevInfPropParam *propParam); unsigned int smlDevInfPropParamNumValEnums(const SmlDevInfPropParam *propParam); char *smlDevInfPropParamGetNthValEnum( const SmlDevInfPropParam *propParam, unsigned int n); /* Property stuff */ SmlDevInfProperty *smlDevInfNewProperty(SmlError **error); void smlDevInfPropertySetPropName( // REQUIRED SmlDevInfProperty *property, const char *propName); void smlDevInfPropertySetPropSize( SmlDevInfProperty *property, unsigned int propSize); void smlDevInfPropertySetDataType( SmlDevInfProperty *property, const char *dataType); void smlDevInfPropertySetMaxOccur( SmlDevInfProperty *property, unsigned int maxOccur); void smlDevInfPropertySetMaxSize( SmlDevInfProperty *property, unsigned int maxSize); void smlDevInfPropertySetNoTruncate( SmlDevInfProperty *property); void smlDevInfPropertySetDisplayName( SmlDevInfProperty *property, const char *displayName); void smlDevInfPropertyAddValEnum( SmlDevInfProperty *property, const char *valEnum); void smlDevInfPropertyAddPropParam( SmlDevInfProperty *property, SmlDevInfPropParam *propParam); char *smlDevInfPropertyGetPropName(const SmlDevInfProperty *property); char *smlDevInfPropertyGetDataType(const SmlDevInfProperty *property); unsigned int smlDevInfPropertyGetMaxOccur(const SmlDevInfProperty *property); unsigned int smlDevInfPropertyGetMaxSize(const SmlDevInfProperty *property); SmlBool smlDevInfPropertyGetNoTruncate(const SmlDevInfProperty *property); char *smlDevInfPropertyGetDisplayName(const SmlDevInfProperty *property); unsigned int smlDevInfPropertyNumValEnums(const SmlDevInfProperty *property); char *smlDevInfPropertyGetNthValEnum( const SmlDevInfProperty *property, unsigned int n); unsigned int smlDevInfPropertyNumPropParams(const SmlDevInfProperty *property); const SmlDevInfPropParam *smlDevInfPropertyGetNthPropParam( const SmlDevInfProperty *property, unsigned int n); /* CTCap stuff */ SmlDevInfContentType *smlDevInfNewContentType( const char *cttype, const char *verct, SmlError **error); char *smlDevInfContentTypeGetCTType(const SmlDevInfContentType *ct); char *smlDevInfContentTypeGetVerCT(const SmlDevInfContentType *ct); void smlDevInfFreeContentType(SmlDevInfContentType *ct); SmlDevInfCTCap *smlDevInfNewCTCap(SmlError **error); void smlDevInfCTCapSetCTType( SmlDevInfCTCap *ctcap, const char *cttype); // REQUIRED => NOT NULL void smlDevInfCTCapSetVerCT( SmlDevInfCTCap *ctcap, const char *verct); // REQUIRED => NOT NULL char *smlDevInfCTCapGetCTType(const SmlDevInfCTCap *ctcap); char *smlDevInfCTCapGetVerCT(const SmlDevInfCTCap *ctcap); void smlDevInfCTCapAddProperty( SmlDevInfCTCap *ctcap, SmlDevInfProperty *property); void smlDevInfAppendCTCap(SmlDevInf *devinf, SmlDevInfCTCap *ctcap); const SmlDevInfCTCap *smlDevInfGetCTCap( const SmlDevInf *devinf, SmlDevInfContentType *ct); unsigned int smlDevInfNumCTCaps(const SmlDevInf *devinf); const SmlDevInfCTCap *smlDevInfGetNthCTCap( const SmlDevInf *devinf, unsigned int n); unsigned int smlDevInfCTCapNumProperties(const SmlDevInfCTCap *ctcap); const SmlDevInfProperty *smlDevInfCTCapGetNthProperty( const SmlDevInfCTCap *ctcap, unsigned int n); /* expire date: 20090120 */ void smlDevInfAddCTCap(SmlDevInf *devinf, SmlDevInfCTCapType type, const char *value) LIBSYNCML_DEPRECATED; SmlDevInfCTCapType smlDevInfGetNthCTCapType(SmlDevInf *devinf, unsigned int nth) LIBSYNCML_DEPRECATED; const char *smlDevInfGetNthCTCapValue(SmlDevInf *devinf, unsigned int nth) LIBSYNCML_DEPRECATED; /* expire date: 20090407 */ void smlDevInfDataStoreSetRx(SmlDevInfDataStore *datastore, const char *contenttype, const char *version) LIBSYNCML_DEPRECATED; SmlBool smlDevInfDataStoreGetRx(const SmlDevInfDataStore *datastore, char **contenttype, char **version) LIBSYNCML_DEPRECATED; void smlDevInfDataStoreSetTx(SmlDevInfDataStore *datastore, const char *contenttype, const char *version) LIBSYNCML_DEPRECATED; SmlBool smlDevInfDataStoreGetTx(const SmlDevInfDataStore *datastore, char **contenttype, char **version) LIBSYNCML_DEPRECATED; #endif //_SML_DEVINF_H_ /*@}*/ libsyncml-0.5.4/libsyncml/sml_devinf_internals.h100644 1750 1750 4676 11211710410 22010 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2005 Armin Bauer * Copyright (C) 2007-2008 Michael Bell * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ /** * @defgroup SmlDevInfPrivate SyncML Device Information Internals * @ingroup PrivateLowLevelAPI * @brief The private part * */ /*@{*/ #ifndef _SML_DEVINF_INTERNALS_H_ #define _SML_DEVINF_INTERNALS_H_ struct SmlDevInf { gint refCount; SmlDevInfVersion version; SmlDevInfDevTyp devtyp; char *manufacturer; char *model; char *oem; char *softwareVersion; char *hardwareVersion; char *firmwareVersion; char *devid; SmlBool supportsUTC; SmlBool supportsLargeObjs; SmlBool supportsNumberOfChanges; GList *datastores; GList *ctcaps; }; struct SmlDevInfDataStore { gint refCount; SmlBool supportsHierarchicalSync; char *sourceref; char *displayname; unsigned int maxGUIDSize; char *rxPrefContentType; char *rxPrefVersion; char *txPrefContentType; char *txPrefVersion; SmlDevInfContentType *rxPref; SmlDevInfContentType *txPref; GList *rx; GList *tx; SmlBool sharedMem; unsigned int maxid; unsigned int maxmem; unsigned int synccap; }; struct SmlDevInfPropParam { char *paramName; char *dataType; char *displayName; GList *valEnums; }; struct SmlDevInfProperty { char *propName; char *dataType; unsigned int maxOccur; unsigned int maxSize; unsigned int propSize; SmlBool noTruncate; char *displayName; GList *valEnums; GList *propParams; }; struct SmlDevInfCTCap { SmlDevInfContentType *ct; GList *properties; }; struct SmlDevInfContentType { char *cttype; char *verct; }; SmlDevInfSyncCap smlDevInfSyncCapConvert(unsigned int id, SmlError **error); #endif //_SML_DEVINF_INTERNALS_H_ /*@}*/ libsyncml-0.5.4/libsyncml/sml_notification.c100644 1750 1750 45205 11211710410 21150 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2005 Armin Bauer * Copyright (C) 2007-2009 Michael Bell * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include "syncml.h" #include "syncml_internals.h" #include "sml_notification_internals.h" #include "sml_transport_internals.h" #include "sml_command_internals.h" #include "sml_manager_internals.h" #include "sml_error_internals.h" #include "objects/sml_auth_internals.h" #include "sml_elements_internals.h" SmlNotification *smlNotificationNew(SmlNotificationVersion version, SmlNotificationUIMode mode, SmlNotificationInitiator init, unsigned int sessionID, const char *identifier, const char *target, SmlMimeType type, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%i, %i, %i, %i, %s, %s, %i, %p)", __func__, version, mode, init, sessionID, VA_STRING(identifier), VA_STRING(target), type, error); CHECK_ERROR_REF SmlNotification *san = smlTryMalloc0(sizeof(SmlNotification), error); if (!san) goto error; san->version = version; san->mode = mode; san->init = init; san->sessionID = sessionID; san->identifier = g_strdup(identifier); san->type = type; san->cred = NULL; san->sessionType = SML_SESSION_TYPE_SERVER; san->manager = NULL; san->target = smlLocationNew(target, NULL, error); if (!san->target) goto error_free_san; smlTrace(TRACE_EXIT, "%s: %p", __func__, san); return san; error_free_san: error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return NULL; } void smlNotificationSetCred(SmlNotification *san, SmlCred *cred) { smlTrace(TRACE_ENTRY, "%s", __func__); smlAssert(san); smlAssert(cred); if (san->cred) smlCredUnref(san->cred); san->cred = cred; // we only set credentials if this is a client // if we set no credentials then we always assume a server // FIXME: this is a hack because the original implementation // FIXME: only support server // Only one question which client sends a notification!? san->sessionType = SML_SESSION_TYPE_CLIENT; smlCredRef(cred); smlTrace(TRACE_EXIT, "%s", __func__); } void smlNotificationSetManager(SmlNotification *san, SmlManager *manager) { smlTrace(TRACE_ENTRY, "%s", __func__); smlAssert(san); smlAssert(manager); san->manager = manager; smlTrace(TRACE_EXIT, "%s", __func__); } void smlNotificationFree(SmlNotification *san) { smlTrace(TRACE_ENTRY, "%s(%p)", __func__, san); smlAssert(san); while (san->alerts) { SmlSanAlert *alert = san->alerts->data; san->alerts = g_list_remove(san->alerts, alert); smlNotificationFreeAlert(alert); } if (san->target) { smlLocationUnref(san->target); san->target = NULL; } if (san->cred) { smlCredUnref(san->cred); san->cred = NULL; } if (san->identifier) smlSafeCFree(&(san->identifier)); smlSafeFree((gpointer *)&san); smlTrace(TRACE_EXIT, "%s", __func__); } SmlBool smlNotificationNewAlert(SmlNotification *san, SmlAlertType type, const char *contenttype, const char *serverURI, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p)", __func__, error); CHECK_ERROR_REF smlAssert(type >= 206 && type <= 210); SmlSanAlert *alert = smlTryMalloc0(sizeof(SmlSanAlert), error); if (!alert) goto error; alert->type = type; alert->contenttype = g_strdup(contenttype); alert->serverURI = g_strdup(serverURI); san->alerts = g_list_append(san->alerts, alert); smlTrace(TRACE_EXIT, "%s: %p", __func__, alert); return TRUE; error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return FALSE; } void smlNotificationFreeAlert(SmlSanAlert *alert) { smlTrace(TRACE_ENTRY, "%s(%p)", __func__, alert); smlAssert(alert); smlSafeCFree(&(alert->contenttype)); smlSafeCFree(&(alert->serverURI)); smlSafeFree((gpointer *)&alert); smlTrace(TRACE_EXIT, "%s", __func__); } SmlNotification *smlNotificationParse(const char *data, unsigned int size, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %i, %p)", __func__, data, size, error); CHECK_ERROR_REF smlAssert(data); smlAssert(size); if (size < 25) { smlErrorSet(error, SML_ERROR_GENERIC, "Size too small"); goto error; } unsigned int idLength = (uint8_t)data[23]; if (size < (25 + idLength)) { smlErrorSet(error, SML_ERROR_GENERIC, "Size too small2"); goto error; } SmlNotification *san = smlTryMalloc0(sizeof(SmlNotification), error); if (!san) goto error; san->type = SML_MIMETYPE_SAN; /* Version */ unsigned int version = ((uint8_t)data[16]) << 2; version = version | ((uint8_t)data[17]) >> 6; switch (version) { case 12: san->version = SML_SAN_VERSION_12; break; default: smlErrorSet(error, SML_ERROR_GENERIC, "Unknown version"); goto error_free_san; } /* ui mode */ san->mode = (((uint8_t)data[17]) & 0x30) >> 4; /* initiator */ san->init = (((uint8_t)data[17]) & 0x08) >> 3; /* session id */ san->sessionID = ((uint8_t)data[21]) << 8; san->sessionID = san->sessionID | (uint8_t)data[22]; /* server identifier */ if (idLength) { /* the trailing NULL byte is usually not present in the SAN */ san->identifier = smlTryMalloc0(idLength + 1, error); if (!san->identifier) goto error_free_san; memcpy(san->identifier, data + 24, idLength); } unsigned int numSync = ((uint8_t)data[24 + idLength]) >> 4; data += 25 + idLength; unsigned int alertLength = 25 + idLength; unsigned int i = 0; for (i = 0; i < numSync; i++) { if (size < alertLength + 5) { smlErrorSet(error, SML_ERROR_GENERIC, "Size too small3"); goto error_free_san; } idLength = (uint8_t)data[4]; if (size < (alertLength + 5 + idLength)) { smlErrorSet(error, SML_ERROR_GENERIC, "Size too small4"); goto error_free_san; } alertLength = alertLength + 5 + idLength; /* Alert type + future */ SmlAlertType alert_type = (((uint8_t)data[0]) >> 4) + 200; if (alert_type < 206 || alert_type > 210) { smlErrorSet(error, SML_ERROR_GENERIC, "Wrong alert type"); goto error_free_san; } unsigned int contenttype = ((uint8_t)data[1]) << 16; contenttype = contenttype | ((uint8_t)data[2]) << 8; contenttype = contenttype | ((uint8_t)data[3]); /* The contenttype */ const char *alert_ct; switch (contenttype) { case 0x00: /* This is exactly like defined in "DS Protocol" section * 12.4.13 "Content Type" of the official OMA document * OMA-TS-DS_Protocol-V1_2_1-20070810-A.pdf. */ alert_ct = NULL; break; case 0x07: alert_ct = SML_ELEMENT_TEXT_VCARD; break; case 0x06: alert_ct = SML_ELEMENT_TEXT_VCAL; break; case 0x03: alert_ct = SML_ELEMENT_TEXT_PLAIN; break; case 0x0305: alert_ct = SML_ELEMENT_TEXT_ICAL; break; case 0x0306: alert_ct = SML_ELEMENT_APPLICATION_OMA_DS_EMAIL; break; case 0x0307: alert_ct = SML_ELEMENT_APPLICATION_OMA_DS_FILE; break; case 0x0308: alert_ct = SML_ELEMENT_APPLICATION_OMA_DS_FOLDER; break; case 0x0309: alert_ct = SML_ELEMENT_TEXT_VCARD_30; break; default: /* http://www.openmobilealliance.org/Tech/omna/omna-wsp-content-type.aspx */ smlErrorSet(error, SML_ERROR_GENERIC, "The OMNA WSP Content Type Number 0x%xd is not supported.", contenttype); goto error_free_san; } /* The server uri */ char *alert_uri; if (idLength) { /* the trailing NULL byte is usually not present in the SAN */ alert_uri = smlTryMalloc0(idLength + 1, error); if (!alert_uri) goto error_free_san; memcpy(alert_uri, data + 5, idLength); } data += 5 + idLength; /* Create new alert */ if (!smlNotificationNewAlert(san, alert_type, alert_ct, alert_uri, error)) goto error_free_san; /* Cleanup */ if (idLength) smlSafeCFree(&alert_uri); } if (size > alertLength) { smlErrorSet(error, SML_ERROR_GENERIC, "Extra chunk at the end of the buffer"); goto error_free_san; } smlTrace(TRACE_EXIT, "%s: %p", __func__, san); return san; error_free_san: while (san->alerts) { smlNotificationFreeAlert(san->alerts->data); san->alerts = g_list_delete_link(san->alerts, san->alerts); } if (san->identifier) smlSafeCFree(&(san->identifier)); smlSafeFree((gpointer *)&san); error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return NULL; } SmlBool smlNotificationAssemble11(SmlNotification *san, char **data, unsigned int *size, SmlProtocolVersion version, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p, %i, %p)", __func__, san, data, size, version, error); CHECK_ERROR_REF smlAssert(san); smlAssert(data); smlAssert(size); /* If a notification is sent via a normal SyncML message * then the used session must be managed to guarantee the * consistency of the session. */ smlAssert(san->manager); SmlAssembler *assm = NULL; SmlLocation *source = NULL; SmlSession *session = NULL; SmlSanAlert *alert = NULL; SmlCommand *cmd = NULL; source = smlLocationNew(san->identifier, NULL, error); if (!source) goto error; char *sessionString = smlManagerGetNewSessionID(san->manager); session = smlSessionNew(san->sessionType, san->type, version, SML_PROTOCOL_SYNCML, san->target, source, sessionString, 0, error); if (!session) { smlSafeCFree(&sessionString); smlLocationUnref(source); goto error; } smlSafeCFree(&sessionString); smlManagerSessionAdd(san->manager, session, NULL, error); assm = smlAssemblerNew(san->type, 0, error); if (!assm) goto error; if (!smlAssemblerStart(assm, session, error)) goto error; if (!smlAssemblerAddHeader(assm, session, error)) goto error; GList *a = NULL; int i = 1; for (a = san->alerts; a; a = a->next) { alert = a->data; SmlLocation *loc = smlLocationNew(alert->serverURI, NULL, error); if (!loc) goto error; cmd = smlCommandNewAlert(SML_ALERT_TWO_WAY_BY_SERVER, NULL, loc, NULL, NULL, alert->contenttype, error); if (!cmd) { smlLocationUnref(loc); goto error; } cmd->cmdID = i; i++; if (!smlAssemblerStartCommand(assm, NULL, cmd, error) == SML_ASSEMBLER_RESULT_OK) goto error; if (!smlAssemblerEndCommand(assm, NULL, error)) goto error; smlLocationUnref(loc); smlCommandUnref(cmd); } if (!smlAssemblerRun(assm, data, size, NULL, TRUE, error)) goto error; smlAssemblerFlush(assm); smlSessionUnref(session); smlLocationUnref(source); smlAssemblerFree(assm); char *hex = smlPrintHex(*data, *size); smlTrace(TRACE_INTERNAL, "San packet assembled: %s", hex); smlSafeCFree(&hex); smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error: if (cmd) smlCommandUnref(cmd); if (session) smlSessionUnref(session); if (assm) smlAssemblerFree(assm); *data = NULL; *size = 0; smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return FALSE; } static SmlBool _smlNotificationAssemble12(SmlNotification *san, char **data, unsigned int *size, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p, %p)", __func__, san, data, size, error); CHECK_ERROR_REF smlAssert(san); smlAssert(data); smlAssert(*data == NULL); smlAssert(size); unsigned int numsync = 0; SmlSanAlert *alert = NULL; /* Calculate the length of the san data */ unsigned int length = 16 /* Digest */ + 8 /* Hdr */ + strlen(san->identifier) /* Identifier */ + 1 /* num-sync + future */; GList *a = NULL; for (a = san->alerts; a; a = a->next) { alert = a->data; length += 5 + strlen(alert->serverURI); numsync++; } /* Malloc the necessary space */ char *buffer = smlTryMalloc0(length, error); if (!buffer) goto error; *data = buffer; *size = length; /* the digest must be created at the end */ /* Create Header */ /* Version - 10 bit */ buffer[16] = 0x03; /* ui mode */ buffer[17] = buffer[17] | (san->mode << 4); /* initiator */ buffer[17] = buffer[17] | (san->init << 3); /* future use is 0 for now - 27 bit */ /* session id */ buffer[21] = san->sessionID >> 8; buffer[22] = san->sessionID; /* server identifier without trailing NULL byte */ buffer[23] = strlen(san->identifier); strncpy(buffer + 24, san->identifier, strlen(san->identifier)); buffer += 24 + strlen(san->identifier); /* Num syncs + future */ buffer[0] = numsync << 4; buffer++; for (a = san->alerts; a; a = a->next) { alert = a->data; /* Alert type + future */ buffer[0] = (alert->type - 200) << 4; /* The contenttype */ if (!strcmp(alert->contenttype, SML_ELEMENT_TEXT_VCARD)) { buffer[3] = 0x07; } else if (!strcmp(alert->contenttype, SML_ELEMENT_TEXT_VCAL)) { buffer[3] = 0x06; } else if (!strcmp(alert->contenttype, SML_ELEMENT_TEXT_PLAIN)) { buffer[3] = 0x03; } else if (!strcmp(alert->contenttype, SML_ELEMENT_TEXT_ICAL)) { buffer[2] = 0x03; buffer[3] = 0x05; } else if (!strcmp(alert->contenttype, SML_ELEMENT_APPLICATION_OMA_DS_EMAIL)) { buffer[2] = 0x03; buffer[3] = 0x06; } else if (!strcmp(alert->contenttype, SML_ELEMENT_APPLICATION_OMA_DS_FILE)) { buffer[2] = 0x03; buffer[3] = 0x07; } else if (!strcmp(alert->contenttype, SML_ELEMENT_APPLICATION_OMA_DS_FOLDER)) { buffer[2] = 0x03; buffer[3] = 0x08; } else if (!strcmp(alert->contenttype, SML_ELEMENT_TEXT_VCARD_30)) { buffer[2] = 0x03; buffer[3] = 0x09; } else { /* http://www.openmobilealliance.org/Tech/omna/omna-wsp-content-type.aspx */ smlTrace(TRACE_INTERNAL, "%s: The OMNA WSP Content Type Number is unknown for %s.", __func__, alert->contenttype); /* All bytes are already set to zero. */ } /* The server uri without a trailing NULL byte */ buffer[4] = strlen(alert->serverURI); strncpy(buffer + 5, alert->serverURI, strlen(alert->serverURI)); buffer += 5 + strlen(alert->serverURI); } /* Create the digest */ /* DO NOT USE buffer because this pointer was manipulated * ALWAYS USE *data. */ /* base64 encoded MD5 digest of the notification */ unsigned char digest[16]; smlMD5GetDigest (*data+16, length - 16 /* digest */, digest); char *b64_san = g_base64_encode(digest, 16); smlTrace(TRACE_INTERNAL, "%s: b64(md5(san)) ::= %s", __func__, b64_san); /* base64 encoded MD5 digest of username:password */ const char *username = ""; const char *password = ""; if (san->cred) { username = san->cred->username; password = san->cred->password; } char *auth = g_strdup_printf("%s:%s", username, password); smlMD5GetDigest (auth, strlen(auth), digest); smlSafeCFree(&auth); char *b64_auth = g_base64_encode(digest, 16); smlTrace(TRACE_INTERNAL, "%s: b64(md5(username:password)) ::= %s", __func__, b64_auth); /* MD5 digest of auth:nonce:notification (empty nonce) */ char *complete = g_strdup_printf("%s::%s", b64_auth, b64_san); smlSafeCFree(&b64_auth); smlSafeCFree(&b64_san); smlMD5GetDigest (complete, strlen(complete), digest); smlSafeCFree(&complete); smlTrace(TRACE_INTERNAL, "%s: md5(auth::san) complete", __func__); /* copy digest to buffer */ memcpy(*data, digest, 16); smlTrace(TRACE_INTERNAL, "%s: md5(auth::san) copied to san", __func__); /* debug */ char *hex = smlPrintHex(*data, *size); smlTrace(TRACE_INTERNAL, "San packet assembled: %s", hex); smlSafeCFree(&hex); smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error: if (*data) smlSafeCFree(data); *size = 0; smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return FALSE; } SmlBool smlNotificationAssemble(SmlNotification *san, char **data, unsigned int *size, SmlError **error) { CHECK_ERROR_REF switch (san->version) { case SML_SAN_VERSION_12: return _smlNotificationAssemble12(san, data, size, error); case SML_SAN_VERSION_10: return smlNotificationAssemble11(san, data, size, SML_VERSION_10, error); case SML_SAN_VERSION_11: return smlNotificationAssemble11(san, data, size, SML_VERSION_11, error); case SML_SAN_VERSION_UNKNOWN: smlErrorSet(error, SML_ERROR_GENERIC, "Unknown SAN version."); break; } return FALSE; } SmlBool smlNotificationSend(SmlNotification *san, SmlTransport *tsp, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, san, tsp, error); CHECK_ERROR_REF smlAssert(san); smlAssert(tsp); char *data = NULL; unsigned int size = 0; if (!smlNotificationAssemble(san, &data, &size, error)) goto error; SmlTransportData *tspdata = NULL; if (san->version == SML_SAN_VERSION_12) tspdata = smlTransportDataNew(data, size, SML_MIMETYPE_SAN, TRUE, error); else tspdata = smlTransportDataNew(data, size, san->type, TRUE, error); if (!tspdata) goto error_free_data; /* Do not free data because smlTransportDateNew does copy by reference. */ data = NULL; /* For SyncML 1.2 and OBEX Transport we use SML_MIMETYPE_SAN for PUT and use the regular SyncML message type (xml/wbxml) for GET. To avoid that we response after the PUT with a GET SML_MIMETYPE_SAN request. */ if (san->version == SML_SAN_VERSION_12) tspdata->type_get = san->type; if (!smlTransportSend(tsp, NULL, tspdata, error)) goto error_free_tspdata; smlTransportDataDeref(tspdata); smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error_free_tspdata: smlTransportDataDeref(tspdata); error_free_data: smlSafeCFree(&data); error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return FALSE; } SmlNotificationVersion smlNotificationGetVersion(SmlNotification *san) { smlAssert(san); return san->version; } SmlNotificationUIMode smlNotificationGetMode(SmlNotification *san) { smlAssert(san); return san->mode; } SmlNotificationInitiator smlNotificationGetInitiator(SmlNotification *san) { smlAssert(san); return san->init; } unsigned int smlNotificationGetSessionID(SmlNotification *san) { smlAssert(san); return san->sessionID; } const char *smlNotificationGetIdentifier(SmlNotification *san) { smlAssert(san); return san->identifier; } unsigned int smlNotificationNumAlerts(SmlNotification *san) { smlAssert(san); return g_list_length(san->alerts); } SmlSanAlert *smlNotificationNthAlert(SmlNotification *san, unsigned int nth) { smlAssert(san); return g_list_nth_data(san->alerts, nth); } SmlAlertType smlSanAlertGetType(SmlSanAlert *alert) { smlAssert(alert); return alert->type; } const char *smlSanAlertGetContentType(SmlSanAlert *alert) { smlAssert(alert); return alert->contenttype; } const char *smlSanAlertGetServerURI(SmlSanAlert *alert) { smlAssert(alert); return alert->serverURI; } libsyncml-0.5.4/libsyncml/sml_manager.c100644 1750 1750 120365 11211710410 20115 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2005 Armin Bauer * Copyright (C) 2007-2009 Michael Bell * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include "syncml.h" #include "syncml_internals.h" #include "sml_error_internals.h" #include "sml_manager_internals.h" #include "sml_transport_internals.h" #include "sml_command_internals.h" #include "sml_elements_internals.h" #include "sml_session_internals.h" typedef struct managerSession { SmlLink *link; SmlSession *session; unsigned int finalLock; SmlTransport *transport; GList *objects; } managerSession; managerSession *_smlManagerGetManagerSession(SmlManager *manager, SmlSession *session); SmlObject *smlManagerObjectFindInternal( SmlManager *manager, SmlSession *session, SmlCommandType type, SmlLocation *target, SmlLocation *source, const char* contentType); static managerSession *_manager_session_find(SmlManager *manager, SmlSession *session) { smlAssert(session); smlAssert(manager); GList *s = NULL; for (s = manager->sessions; s; s = s->next) { managerSession *sess = s->data; if (sess->session == session) return sess; } return NULL; } static void _manager_session_free(managerSession *sess) { smlAssert(sess); smlSessionUnref(sess->session); if (sess->link) smlLinkDeref(sess->link); while (sess->objects) { SmlObject *object = sess->objects->data; smlManagerObjectFree(object); sess->objects = g_list_delete_link(sess->objects, sess->objects); } smlSafeFree((gpointer *)&sess); } static gboolean _manager_prepare_internal(GSource *source, gint *timeout_) { smlTrace(TRACE_INTERNAL, "%s(%p, %p)", __func__, source, timeout_); *timeout_ = 1; return FALSE; } static gboolean _manager_check_internal(GSource *source) { SmlManager *manager = *((SmlManager **)(source + 1)); GList *s = NULL; for (s = manager->sessions; s; s = s->next) { managerSession *session = s->data; if (smlSessionCheck(session->session)) return TRUE; } return FALSE; } static gboolean _manager_dispatch_internal(GSource *source, GSourceFunc callback, gpointer user_data) { smlTrace(TRACE_INTERNAL, "%s(%p, %p, %p)", __func__, source, callback, user_data); int max = 100; SmlManager *manager = user_data; GList *s = NULL; for (s = manager->sessions; s; s = s->next) { managerSession *session = s->data; while (smlSessionCheck(session->session) && max) { /* A dispatch function should never block on a * locked resource. This is like a busy wait * because the thread is not available for this * time which can block the whole system if two * dispatchers use the same thread. */ if (smlSessionTryLock(session->session)) { smlSessionDispatch(session->session); smlSessionUnlock(session->session); } max--; } } return TRUE; } static void _smlManagerSendEvent(SmlManager *manager, SmlManagerEventType type, SmlSession *session, SmlCommand *command, SmlCommand *parent, SmlError *error) { smlTrace(TRACE_ENTRY, "%s(%p, %i, %p, %p, %p, %p)", __func__, manager, type, session, command, parent, error); SmlError *lerr = NULL; SmlManagerEvent *event = smlTryMalloc0(sizeof(SmlManagerEvent), &lerr); if (event) { event->type = type; if (session) { event->session = session; smlSessionRef(session); } else { event->session = NULL; } if (command) { event->command = command; smlCommandRef(command); } else { event->command = NULL; } if (parent) { event->parent = parent; smlCommandRef(parent); } else { event->parent = NULL; } if (error) { event->error = error; smlErrorRef(&error); } smlQueueSend(manager->userEventQueue, event); } else { /* error handling is not possible here :( */ g_error("%s", smlErrorPrint(&lerr)); smlErrorDeref(&lerr); } smlTrace(TRACE_EXIT, "%s", __func__); } void _smlManagerEventFree(SmlManagerEvent *event) { smlTrace(TRACE_ENTRY, "%s(%p)", __func__, event); smlAssert(event); if (event->session) smlSessionUnref(event->session); if (event->command) smlCommandUnref(event->command); if (event->parent) smlCommandUnref(event->parent); if (event->error) smlErrorDeref(&(event->error)); smlSafeFree((gpointer *)&event); smlTrace(TRACE_EXIT, "%s", __func__); } /* If we return FALSE in this function, the current request will get * aborted */ static SmlBool _smlManagerDataHandler(SmlTransport *tsp, SmlLink *link_, SmlTransportEventType type, SmlTransportData *data, SmlError *error, void *userdata) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %i, %p, %p, %p)", __func__, tsp, link_, type, data, error, userdata); smlAssert(userdata); SmlManager *manager = userdata; SmlParser *parser = NULL; SmlHeader *header = NULL; SmlCred *cred = NULL; SmlSession *session = NULL; SmlError *locerror = NULL; switch (type) { case SML_TRANSPORT_EVENT_CONNECT_DONE: /* Pass the connect through */ _smlManagerSendEvent(manager, SML_MANAGER_CONNECT_DONE, NULL, NULL, NULL, NULL); break; case SML_TRANSPORT_EVENT_DISCONNECT_DONE: /* Pass the disconnect through */ _smlManagerSendEvent(manager, SML_MANAGER_DISCONNECT_DONE, NULL, NULL, NULL, NULL); break; case SML_TRANSPORT_EVENT_DATA: parser = smlParserNew(data->type, 0, &locerror); if (!parser) goto session_error; /* add manager to parser for OMA DS 1.2 SAN handling */ smlParserSetManager(parser, manager); /* start to parse the data */ if (!smlParserStart(parser, data->data, data->size, &locerror)) goto error_free_parser; /* Get the header of the message*/ header = NULL; cred = NULL; if (!smlParserGetHeader(parser, &header, &cred, &locerror)) goto error_free_parser; /* Find the session if available otherwise register it as new */ session = smlManagerSessionFind(manager, header->sessionID); if (!session) { /* If we use the target and source from the header of the received message * then we MUST interchange source and target */ SmlSessionType sessionType; switch(smlTransportGetType(tsp)) { case SML_TRANSPORT_OBEX_CLIENT: /* this can happen if the remote * client creates a new session ID. */ sessionType = SML_SESSION_TYPE_SERVER; break; case SML_TRANSPORT_OBEX_SERVER: sessionType = SML_SESSION_TYPE_CLIENT; break; case SML_TRANSPORT_HTTP_SERVER: sessionType = SML_SESSION_TYPE_SERVER; break; default: smlErrorSet(&locerror, SML_ERROR_NOT_IMPLEMENTED, "New session was unexpectedly received for transport %d.", smlTransportGetType(tsp)); goto error_free_header; break; } if (!(session = smlSessionNew( sessionType, data->type, header->version, header->protocol, header->source, header->target, header->sessionID, 1, &locerror))) goto error_free_header; if (link_) { char *responseURI = smlTransportGetResponseURI(link_, session, &locerror); if (!responseURI && locerror) goto error_free_header; if (responseURI) { if (!smlSessionSetResponseURI(session, responseURI, &locerror)) { smlSafeCFree(&responseURI); goto error_free_header; } smlSafeCFree(&responseURI); } } if (!smlManagerSessionAdd(manager, session, link_, &locerror)) goto error_free_header; smlSessionUnref(session); } else { /* SECURITY: let's check ResponseURI if supported * SECURITY: this is important to avoid replay attacks */ if (link_) { char *responseUri = smlTransportGetResponseURI(link_, session, &locerror); if (!responseUri && locerror) { goto error_free_header; } if (responseUri) smlSafeCFree(&responseUri); } } /* This function is called by the tranport layer which * runs in an own thread. Therefore we must lock the * according session because otherwise we can get into * trouble with parallel access to a SmlSession which is * not safe against parallel use by multiple threads. */ smlSessionLock(session); /* Find the manager session so that we can update the link. We * have to do this since each time a transport with links receives * a new data packets, it might create a new link (connectionless * protocols). So we have to update the link to be able to answer * the data */ GList *s; for (s = manager->sessions; s; s = s->next) { managerSession *sess = s->data; if (sess->session == session) { if (sess->link) smlLinkDeref(sess->link); sess->link = link_; if (link_) smlLinkRef(sess->link); break; } } /* Now check if the header is valid etc */ if (!smlSessionReceiveHeader(session, header, &locerror)) goto error_free_header; /* Then check if we are allowed to authenticate */ if (!smlManagerDispatchHeader(manager, session, header, cred, &locerror)) goto error_free_header; smlHeaderFree(header); if (cred) smlCredUnref(cred); /* Now let the session handle the commands etc */ if (!smlSessionReceiveBody(session, parser, &locerror)) goto error_free_parser; /* Free the parser */ smlParserFree(parser); /* make the session accessible for others */ smlSessionUnlock(session); break; case SML_TRANSPORT_EVENT_ERROR: /* Pass the error through */ smlErrorDuplicate(&locerror, &error); goto transport_error; break; } smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error_free_header: if (header) smlHeaderFree(header); if (cred) smlCredUnref(cred); error_free_parser: smlParserFree(parser); if (session) smlSessionUnlock(session); session_error: if (session == NULL && link_ && type == SML_TRANSPORT_EVENT_DATA) { /* If there is no session and a link then this means * that there is a failing server connection. * It is a good idea to close the connection because * the session has no chance to signal a clean * disconnect to the link. */ SmlError *herror = NULL; if (!smlTransportDisconnect(manager->transport, link_, &herror)) { smlTrace(TRACE_ERROR, "%s: Disconnect on error failed. %s", smlErrorPrint(&herror)); smlErrorDeref(&herror); } } _smlManagerSendEvent(manager, SML_MANAGER_SESSION_ERROR, session, NULL, NULL, locerror); smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(&locerror)); smlErrorDeref(&locerror); return FALSE; transport_error: _smlManagerSendEvent(manager, SML_MANAGER_TRANSPORT_ERROR, NULL, NULL, NULL, locerror); smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(&locerror)); smlErrorDeref(&locerror); return FALSE; } SmlManager *smlManagerNew(SmlTransport *tsp, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p)", __func__, tsp, error); smlAssert(tsp); CHECK_ERROR_REF SmlManager *manager = smlTryMalloc0(sizeof(SmlManager), error); if (!manager) goto error; smlTransportSetEventCallback(tsp, _smlManagerDataHandler, manager); manager->transport = tsp; manager->running_mutex = g_mutex_new(); manager->running = g_cond_new(); manager->userEventQueue = smlQueueNew(error); if (!manager->userEventQueue) goto error_free_manager; smlTrace(TRACE_EXIT, "%s", __func__); return manager; error_free_manager: smlSafeFree((gpointer *)&manager); error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return NULL; } void smlManagerFree(SmlManager *manager) { smlTrace(TRACE_ENTRY, "%s(%p)", __func__, manager); smlAssert(manager); /* stop automatic session dispatch environment if necessary */ if (manager->context) smlManagerStop(manager); /* Deactivate the event callback of the transport layer * because the manager is no longer available */ if (manager->transport) smlTransportSetEventCallback(manager->transport, NULL, NULL); while (manager->sessions) { managerSession *sess = manager->sessions->data; _manager_session_free(sess); manager->sessions = g_list_delete_link(manager->sessions, manager->sessions); } while (manager->objects) { SmlObject *object = manager->objects->data; smlManagerObjectFree(object); manager->objects = g_list_remove(manager->objects, object); } if (manager->userEventQueue) { SmlManagerEvent *event = NULL; while ((event = smlQueueTryPop(manager->userEventQueue))) _smlManagerEventFree(event); smlQueueFree(manager->userEventQueue); manager->userEventQueue = NULL; } g_cond_free(manager->running); g_mutex_free(manager->running_mutex); smlSafeFree((gpointer *)&manager); smlTrace(TRACE_EXIT, "%s", __func__); } void smlManagerSetEventCallback(SmlManager *manager, SmlManagerEventCb callback, void *userdata) { smlAssert(manager); smlAssert(callback); manager->eventCallback = callback; manager->eventCallbackUserdata = userdata; } SmlBool smlManagerStart(SmlManager *manager, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p)", __func__, manager, error); smlAssert(manager); CHECK_ERROR_REF manager->context = g_main_context_new(); if (!manager->context) { smlErrorSet(error, SML_ERROR_GENERIC, "Cannot create new main context."); goto error; } manager->functions = smlTryMalloc0(sizeof(GSourceFuncs), error); if (!manager->functions) goto error; manager->functions->prepare = _manager_prepare_internal; manager->functions->check = _manager_check_internal; manager->functions->dispatch = _manager_dispatch_internal; manager->functions->finalize = NULL; manager->thread = smlThreadNew(manager->context, error); if (!manager->thread) goto error; smlThreadStart(manager->thread); manager->source = g_source_new(manager->functions, sizeof(GSource) + sizeof(SmlManager *)); SmlManager **managerptr = (SmlManager **)(manager->source + 1); *managerptr = manager; g_source_set_callback(manager->source, NULL, manager, NULL); g_source_attach(manager->source, manager->context); smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error: if (manager->context) { g_main_context_unref(manager->context); manager->context = NULL; } if (manager->functions) smlSafeFree((gpointer *)&(manager->functions)); smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return FALSE; } /** @brief Stops the active manager part. * * The active part of the manager is the automatic dispatching * of the SmlSession objects. The session dispatching consists * of the status and command dispatching. If the commands and * status are no longer dispatched then the session is no longer * in an active state. * * If this happens the manager should shoulds down the external * communication. In fact the manager disconnects all active * transport connections. * * You must still call smlManagerDispatch until you got all * required SML_MANAGER_DISCONNECT_DONE events. After this you * can safely call smlManagerFree without getting warnings or * errors from the transport layer because of forgotten * connections. * * Errors especially from the transport layer are ignored * because it is not possible to react on these errors. * Therefore it is correct to ignore the errors. Actually it is * a problem that one or more failed disconnects result in a * deadlock if somebody waits correctly for all disconnect * events. Additionally it is impossible to signal a user the * number of failed disconnect via a clean way. * * If a disconnect fails then g_warning is called with an * appropriate message. If there is a (G)UI which reconfigures * the glib to display warnings and errors to the user then * this is the only chance to communicate such errors. * * @param manager The manager * */ void smlManagerStop(SmlManager *manager) { smlTrace(TRACE_ENTRY, "%s(%p)", __func__, manager); smlAssert(manager); smlAssert(manager->thread); /* cleanup automatic session dispatch environment * the order is highly important */ /* stop thread */ smlThreadStop(manager->thread); smlThreadFree(manager->thread); manager->thread = NULL; /* detach source */ g_source_unref(manager->source); manager->source = NULL; /* free context */ g_main_context_unref(manager->context); manager->context = NULL; /* free functions */ smlSafeFree((gpointer *)&(manager->functions)); manager->functions = NULL; /* close all open connections */ GList *sessionItem = manager->sessions; while (sessionItem) { managerSession *sess = sessionItem->data; /* disconnect if necessary * * only do this if: * 1. the transport layer is still connected * and * 2.1. this is a client connection or the server itself * or * 2.2. this is an active server connection */ SmlError *error = NULL; if (manager->transport->connected && (!sess->link || sess->link->link_data) && !smlTransportDisconnect(manager->transport, sess->link, &error)) { g_warning("Errors from the transport layer " \ "cannot be handled while freeing the manager. %s", smlErrorPrint(&error)); smlErrorDeref(&error); } sessionItem = g_list_next(sessionItem); } smlTrace(TRACE_EXIT, "%s", __func__); } void smlManagerRun(SmlManager *manager) { smlTrace(TRACE_ENTRY, "%s(%p)", __func__, manager); smlAssert(manager); g_mutex_lock(manager->running_mutex); g_cond_wait(manager->running, manager->running_mutex); g_mutex_unlock(manager->running_mutex); smlTrace(TRACE_EXIT, "%s", __func__); } void smlManagerQuit(SmlManager *manager) { smlTrace(TRACE_ENTRY, "%s(%p)", __func__, manager); smlAssert(manager); g_mutex_lock(manager->running_mutex); g_cond_signal(manager->running); g_mutex_unlock(manager->running_mutex); smlTrace(TRACE_EXIT, "%s", __func__); } SmlSession *smlManagerSessionFind(SmlManager *manager, const char *sessionID) { smlTrace(TRACE_ENTRY, "%s(%p, %s)", __func__, manager, VA_STRING(sessionID)); GList *s = NULL; for (s = manager->sessions; s; s = s->next) { managerSession *session = s->data; if (!strcmp(smlSessionGetSessionID(session->session), sessionID)) { smlTrace(TRACE_EXIT, "%s: FOUND %p", __func__, session); return session->session; } } smlTrace(TRACE_EXIT, "%s: NOT FOUND", __func__); return NULL; } void smlManagerDispatch(SmlManager *manager) { smlTrace(TRACE_ENTRY, "%s(%p)", __func__, manager); smlAssert(manager); SmlManagerEvent *event = NULL; while ((event = smlQueueTryPop(manager->userEventQueue))) { smlTrace(TRACE_INTERNAL, "%s: type ::= %d", __func__, event->type); /* Check that this is not a locked final event. */ if (event->session != NULL && event->type == SML_MANAGER_SESSION_FINAL) { managerSession *sess = _smlManagerGetManagerSession(manager, event->session); if (sess && sess->finalLock) { smlTrace(TRACE_INTERNAL, "%s - locked final (%i)", __func__, sess->finalLock); smlQueuePushHead(manager->userEventQueue, event); /* It is necessary to stop the dispatching here. * The events MUST BE dispatched in the same * order like they were received. If the while * loop does not break here then the loop tries * to dispatch the locked event again and again. */ break; } } /* Execute the event callback. */ smlAssert(manager->eventCallback); manager->eventCallback(manager, event->type, event->session, event->error, manager->eventCallbackUserdata); _smlManagerEventFree(event); } smlTrace(TRACE_EXIT, "%s", __func__); } SmlBool smlManagerCheck(SmlManager *manager) { return smlQueueCheck(manager->userEventQueue); } static void _event_callback(SmlSession *session, SmlSessionEventType type, SmlCommand *command, SmlCommand *parent, SmlStatus *reply, SmlError *error, void *userdata) { smlTrace(TRACE_ENTRY, "%s(%p, %i, %p, %p, %p, %p, %p)", __func__, session, type, command, parent, reply, error, userdata); SmlManager *manager = userdata; SmlError *locerror = NULL; switch (type) { case SML_SESSION_EVENT_ESTABLISHED: /* Pass the established through */ _smlManagerSendEvent(manager, SML_MANAGER_SESSION_ESTABLISHED, session, NULL, NULL, NULL); break; case SML_SESSION_EVENT_HEADER_REPLY: break; case SML_SESSION_EVENT_RESPONSE_URI: if (!smlTransportSetResponseURI( manager->transport, smlLocationGetURI(smlSessionGetTarget(session)), &locerror)) { _smlManagerSendEvent(manager, SML_MANAGER_SESSION_ERROR, session, NULL, NULL, locerror); goto error; } break; case SML_SESSION_EVENT_COMMAND_START: case SML_SESSION_EVENT_COMMAND_END: if (!smlManagerDispatchCommand(manager, session, command, &locerror)) { _smlManagerSendEvent(manager, SML_MANAGER_SESSION_WARNING, session, NULL, NULL, locerror); goto error; } break; case SML_SESSION_EVENT_CHILD_COMMAND: if (!smlManagerDispatchChildCommand(manager, session, parent, command, &locerror)) { _smlManagerSendEvent(manager, SML_MANAGER_SESSION_WARNING, session, NULL, NULL, locerror); goto error; } break; case SML_SESSION_EVENT_FINAL: /* Pass the final through */ _smlManagerSendEvent(manager, SML_MANAGER_SESSION_FINAL, session, NULL, NULL, NULL); break; case SML_SESSION_EVENT_END: /* Pass the end through */ _smlManagerSendEvent(manager, SML_MANAGER_SESSION_END, session, NULL, NULL, NULL); break; case SML_SESSION_EVENT_FLUSH: /* Pass the flush through */ _smlManagerSendEvent(manager, SML_MANAGER_SESSION_FLUSH, session, NULL, NULL, NULL); break; case SML_SESSION_EVENT_ERROR: /* Pass the error through */ smlErrorDuplicate(&locerror, &error); _smlManagerSendEvent(manager, SML_MANAGER_SESSION_ERROR, session, NULL, NULL, locerror); goto error; break; } smlTrace(TRACE_EXIT, "%s", __func__); return; error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(&locerror)); smlErrorDeref(&locerror); } static void _data_send_callback(SmlSession *session, SmlTransportData *data, void *userdata) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, session, data, userdata); managerSession *sess = userdata; /* The transport layer is able to signal the error via an event. */ SmlError *error = NULL; if (!smlTransportSend(sess->transport, sess->link, data, &error)) { smlTrace(TRACE_ERROR, "%s - %s", __func__, smlErrorPrint(&error)); smlErrorDeref(&error); } smlTrace(TRACE_EXIT, "%s", __func__); } SmlBool smlManagerSessionAdd(SmlManager *manager, SmlSession *session, SmlLink *link_, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p, %p)", __func__, manager, session, link_, error); CHECK_ERROR_REF smlSessionRef(session); if (smlSessionGetSessionID(session)) { //Check if sessionID exists smlTrace(TRACE_INTERNAL, "Checking if session ID %s already exists", smlSessionGetSessionID(session)); if (smlManagerSessionFind(manager, smlSessionGetSessionID(session))) { smlErrorSet(error, SML_ERROR_GENERIC, "Session ID already exists"); goto error; } } else { char *lastid = smlManagerGetNewSessionID(manager); smlSessionSetSessionID(session, lastid); smlSafeCFree(&lastid); } managerSession *sess = smlTryMalloc0(sizeof(managerSession), error); if (!sess) goto error; sess->session = session; sess->finalLock = 0; if (link_) { sess->link = link_; smlLinkRef(link_); } sess->transport = manager->transport; manager->sessions = g_list_append(manager->sessions, sess); /* prepare large object support */ if (0 < manager->localMaxMsgSize && ( manager->localMaxMsgSize < smlSessionGetLocalMaxMsgSize(session) || smlSessionGetLocalMaxMsgSize(session) <= 0 )) smlSessionSetLocalMaxMsgSize(session, manager->localMaxMsgSize); if (0 < manager->localMaxObjSize && ( manager->localMaxObjSize < smlSessionGetLocalMaxObjSize(session) || smlSessionGetLocalMaxObjSize(session) <= 0 )) smlSessionSetLocalMaxObjSize(session, manager->localMaxObjSize); if (smlSessionGetLocalMaxObjSize(session) && smlSessionGetLocalMaxMsgSize(session)) smlSessionUseLargeObjects(session, TRUE); else smlSessionUseLargeObjects(session, FALSE); smlSessionSetEventCallback(session, _event_callback, manager); smlSessionSetDataCallback(session, _data_send_callback, sess); _smlManagerSendEvent(manager, SML_MANAGER_SESSION_NEW, session, NULL, NULL, NULL); smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error: smlSessionUnref(session); smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return FALSE; } managerSession *_smlManagerGetManagerSession(SmlManager *manager, SmlSession *session) { smlTrace(TRACE_ENTRY, "%s(%p, %p)", __func__, manager, session); GList *s; for (s = manager->sessions; s; s = s->next) { managerSession *sess = s->data; if (sess->session == session) { smlTrace(TRACE_EXIT, "%s - %p", __func__, sess); return sess; } } smlTrace(TRACE_EXIT, "%s: Not Found", __func__); return NULL; } void smlManagerSessionRemove(SmlManager *manager, SmlSession *session) { smlTrace(TRACE_ENTRY, "%s(%p, %p)", __func__, manager, session); managerSession *sess = _smlManagerGetManagerSession(manager, session); if (sess) { manager->sessions = g_list_remove(manager->sessions, sess); _manager_session_free(sess); smlTrace(TRACE_EXIT, "%s", __func__); } else { smlTrace(TRACE_EXIT, "%s: Not Found", __func__); } } void smlManagerSessionFinalLockRef(SmlManager *manager, SmlSession *session) { smlTrace(TRACE_ENTRY, "%s(%p, %p)", __func__, manager, session); managerSession *sess = _smlManagerGetManagerSession(manager, session); if (sess) { sess->finalLock++; smlTrace(TRACE_EXIT, "%s", __func__); } else { smlTrace(TRACE_EXIT, "%s: Not Found", __func__); } } void smlManagerSessionFinalLockUnref(SmlManager *manager, SmlSession *session) { smlTrace(TRACE_ENTRY, "%s(%p, %p)", __func__, manager, session); managerSession *sess = _smlManagerGetManagerSession(manager, session); if (sess) { sess->finalLock--; smlTrace(TRACE_EXIT, "%s - %i", __func__, sess->finalLock); } else { smlTrace(TRACE_EXIT, "%s: Not Found", __func__); } } /** @brief Register an object with a session * * A object waits at a certain location for incoming commands. So you can for example * register a object that listens for Get commands on the /test location. * * Note that you cannot deregister an object from a already running session * * @param session The session on which to listen * @param type The command type to listen to or SML_COMMAND_TYPE_UNKNOWN to listen for all * @param session If given, only listens for the commands on the given session. NULL for all * @param location The location where the object listens (This must match the Target of the command). NULL to listen for all targets * @param source The source of the command we want (This must match the Source of the command). NULL to listen for all sources * @param callback The callback that will receive the incoming commands. * @param childCallback The call that will receive the commands from the child commands. Set to NULL if the expected command has no childs * @param userdata The userdata for the callbacks * @param error A error struct * @return TRUE if successful, FALSE otherwise * */ SmlBool smlManagerObjectRegister(SmlManager *manager, SmlCommandType type, SmlSession *session, SmlLocation *location, SmlLocation *source, const char *contentType, SmlCommandCb callback, SmlCommandCb childCallback, void *userdata, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %i, %p, %p, %p, %s, %p, %p, %p, %p)", __func__, manager, type, session, location, source, VA_STRING(contentType), callback, childCallback, userdata, error); smlAssert(manager); smlAssert(callback); CHECK_ERROR_REF /* first we have to check if this an update for an already registered object */ /* this is important for actions which require more than one DsSession */ SmlObject *object = smlManagerObjectFindInternal( manager, session, type, location, source, contentType); if (object != NULL && session != NULL) { /* check that it is not a global manager object */ SmlObject *hObject = smlManagerObjectFindInternal( manager, NULL, type, location, source, contentType); if (hObject != NULL && hObject == object) { /* the found object is a global manager object */ /* so we have to register a new object */ object = NULL; } } if (object) { /* there is an object and so we reconfigure it */ smlTrace(TRACE_INTERNAL, "%s: prepare a reusable object", __func__); if (object->location) smlLocationUnref(object->location); if (object->source) smlLocationUnref(object->source); if (object->contentType) smlSafeCFree(&(object->contentType)); } else { /* let's create and register a new object */ smlTrace(TRACE_INTERNAL, "%s: create and register a new object", __func__); object = smlTryMalloc0(sizeof(SmlObject), error); if (!object) goto error; if (session) { managerSession *sess = _manager_session_find(manager, session); if (!sess) { smlErrorSet(error, SML_ERROR_GENERIC, "Session not found"); goto error_free_object; } sess->objects = g_list_append(sess->objects, object); } else { manager->objects = g_list_append(manager->objects, object); } } smlTrace(TRACE_INTERNAL, "%s: configure registered object", __func__); object->type = type; if (location) { object->location = location; smlLocationRef(location); } if (source) { object->source = source; smlLocationRef(source); } if (contentType) { object->contentType = g_strdup(contentType); } object->commandCallback = callback; object->childCallback = childCallback; object->commandCallbackUserdata = userdata; smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error_free_object: smlManagerObjectFree(object); error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return FALSE; } void smlManagerObjectDeregister(SmlManager *manager, SmlCommandType type, SmlLocation *location, SmlLocation *source) { smlTrace(TRACE_ENTRY, "%s(%p, %i, %p, %p)", __func__, manager, type, location, source); smlAssert(manager); GList *o2 = g_list_copy(manager->objects); GList *o = NULL; for (o = o2; o; o = o->next) { SmlObject *object = o->data; if (object->type != type) continue; if (!smlLocationCompare(NULL, object->location, NULL, location)) continue; if (!smlLocationCompare(NULL, object->source, NULL, source)) continue; smlManagerObjectFree(object); manager->objects = g_list_remove(manager->objects, object); } g_list_free(o2); smlTrace(TRACE_EXIT, "%s", __func__); } void smlManagerObjectFree(SmlObject *object) { smlTrace(TRACE_ENTRY, "%s(%p)", __func__, object); smlAssert(object); if (object->location) smlLocationUnref(object->location); if (object->source) smlLocationUnref(object->source); if (object->contentType) smlSafeCFree(&(object->contentType)); smlSafeFree((gpointer *)&object); smlTrace(TRACE_EXIT, "%s", __func__); } SmlObject *smlManagerObjectFind(SmlManager *manager, SmlSession *session, SmlCommand *cmd) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, manager, session, cmd); smlAssert(manager); smlAssert(cmd); SmlObject *object = smlManagerObjectFindInternal( manager, session, cmd->type, cmd->target, cmd->source, cmd->private.alert.contentType); smlTrace(TRACE_EXIT, "%s(%p)", __func__, object); return object; } SmlObject *smlManagerObjectFindInternal( SmlManager *manager, SmlSession *session, SmlCommandType type, SmlLocation *target, SmlLocation *source, const char* contentType) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %d, %p, %p)", __func__, manager, session, type, target, source); smlAssert(manager); SmlObject *object = NULL; GList *o = NULL; /* We first search for the object in the session specific objects */ if (session) { managerSession *sess = _manager_session_find(manager, session); if (sess) { for (o = sess->objects; o; o = o->next) { object = o->data; if (object->type != SML_COMMAND_TYPE_UNKNOWN && type != object->type) continue; if (!smlLocationCompare(NULL, object->location, NULL, target)) continue; if (!smlLocationCompare(NULL, object->source, NULL, source)) continue; smlTrace(TRACE_EXIT, "%s: FOUND (session): %p", __func__, object); return object; } } } for (o = manager->objects; o; o = o->next) { object = o->data; if (object->type != SML_COMMAND_TYPE_UNKNOWN && type != object->type) continue; if (type == SML_COMMAND_TYPE_ALERT && contentType) { if (object->contentType) { /* This item is a san 11 alert */ if (!strcmp(contentType, object->contentType)) { smlTrace(TRACE_EXIT, "%s: FOUND SAN TARGET: %p", __func__, object); return object; } } continue; } if (!smlLocationCompare(NULL, object->location, NULL, target)) continue; if (!smlLocationCompare(NULL, object->source, NULL, source)) continue; /* Check if the target is a san target */ if (object->contentType) continue; smlTrace(TRACE_EXIT, "%s: FOUND: %p", __func__, object); return object; } smlTrace(TRACE_EXIT, "%s: NOT FOUND", __func__); return NULL; } SmlTransport *smlManagerGetTransport(SmlManager *manager) { smlTrace(TRACE_ENTRY, "%s(%p, %p)", __func__, manager); smlAssert(manager); SmlTransport *tsp = manager->transport; smlTrace(TRACE_EXIT, "%s: %p", __func__, tsp); return tsp; } SmlBool smlManagerDispatchHeader(SmlManager *manager, SmlSession *session, SmlHeader *header, SmlCred *cred, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p, %p, %p)", __func__, manager, session, header, cred, error); smlAssert(manager); smlAssert(session); smlAssert(header); CHECK_ERROR_REF if (manager->headerCallback && session->sessionType == SML_SESSION_TYPE_SERVER) { /* Authentication is only specified for OMA DS server. */ manager->headerCallback(session, header, cred, manager->headerCallbackUserdata); } else { smlTrace(TRACE_INTERNAL, "%s: Header not handled!", __func__); if (session->sessionType == SML_SESSION_TYPE_SERVER && !session->established) { /* An OMA DS server must handle the header for security * reasons - especially authentication. * * Question: can we detect such a bug in an earlier phase? */ g_warning("%s: This is an OMA DS server. " \ "The header callback is missing. " \ "All requests will be accepted without authentication.", __func__); session->established = TRUE; smlSessionDispatchEvent( session, SML_SESSION_EVENT_ESTABLISHED, NULL, NULL, NULL, NULL); } SmlStatus *status = smlStatusNew( SML_NO_ERROR, 0, header->messageID, header->source, header->target, SML_COMMAND_TYPE_HEADER, error); if (!status) goto error; if (!smlSessionSendReply(session, status, error)) { smlStatusUnref(status); goto error; } smlStatusUnref(status); } smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return FALSE; } SmlBool smlManagerDispatchChildCommand(SmlManager *manager, SmlSession *session, SmlCommand *parent, SmlCommand *cmd, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p, %p, %p)", __func__, manager, session, parent, cmd, error); smlAssert(manager); smlAssert(session); smlAssert(parent); CHECK_ERROR_REF //Check if a handler for this object at this path has been installed. SmlObject *object = smlManagerObjectFind(manager, session, parent); if (object) { //Check if a handler for this object at this path has been installed. if (!object->childCallback) { smlErrorSet(error, SML_ERROR_GENERIC, "No handler for the child was installed"); goto error; } object->childCallback(session, cmd, object->commandCallbackUserdata); } else { SmlStatus *reply = smlCommandNewReply(cmd, SML_ERROR_NOT_FOUND, error); if (!reply) goto error; if (!smlSessionSendReply(session, reply, error)) { smlStatusUnref(reply); goto error; } smlStatusUnref(reply); smlErrorSet(error, SML_ERROR_GENERIC, "Unable to find child command handler"); goto error; } smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return FALSE; } SmlBool smlManagerDispatchCommand(SmlManager *manager, SmlSession *session, SmlCommand *cmd, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p, %p)", __func__, manager, session, cmd, error); smlAssert(manager); smlAssert(session); smlAssert(cmd); CHECK_ERROR_REF //Check if a handler for this object at this path has been installed. SmlObject *object = smlManagerObjectFind(manager, session, cmd); if (object) { //Check if a handler for this object at this path has been installed. if (!object->commandCallback) { smlErrorSet(error, SML_ERROR_GENERIC, "No handler for the child was installed"); goto error; } object->commandCallback(session, cmd, object->commandCallbackUserdata); } else { const char *type = smlCommandTypeToString(cmd->type, error); /* If the type is unknown then this can be part of the error. */ smlErrorDeref(error); const char *srcuri = (cmd->source && cmd->source->locURI) ? cmd->source->locURI : "NULL"; const char *dsturi = (cmd->target && cmd->target->locURI) ? cmd->target->locURI : "NULL"; smlErrorSet(error, SML_ERROR_NOT_FOUND, "Unable to find command handler (%s: %s -> %s)", (type) ? type : "UNKNOWN", srcuri, dsturi); SmlError *locerror = NULL; SmlStatus *reply = smlCommandNewReply(cmd, SML_ERROR_NOT_FOUND, &locerror); if (!reply) { smlErrorSet(error, SML_ERROR_NOT_FOUND, "%s %s", smlErrorPrint(error), smlErrorPrint(&locerror)); goto error; } if (!smlSessionSendReply(session, reply, &locerror)) { smlStatusUnref(reply); smlErrorSet(error, SML_ERROR_NOT_FOUND, "%s %s", smlErrorPrint(error), smlErrorPrint(&locerror)); goto error; } smlStatusUnref(reply); goto error; } smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return FALSE; } void smlManagerRegisterHeaderHandler(SmlManager *manager, SmlHeaderCb callback, SmlStatusReplyCb statuscb, void *userdata) { smlAssert(manager); manager->headerCallback = callback; manager->headerStatusCallback = statuscb; manager->headerCallbackUserdata = userdata; } void smlManagerSetLocalMaxMsgSize(SmlManager *manager, unsigned int size) { smlAssert(manager); manager->localMaxMsgSize = size; } void smlManagerSetLocalMaxObjSize(SmlManager *manager, unsigned int size) { smlAssert(manager); manager->localMaxObjSize = size; } char *smlManagerGetNewSessionID(SmlManager *manager) { smlTrace(TRACE_ENTRY, "%s(%p)", __func__, manager); smlAssertMsg(manager, "The manager is required to avoid duplicated session IDs."); char *sessionString = NULL; while (sessionString == NULL) { /* WARNING: only 4 byte session IDs are theoretically allowed !!! */ /* create random session ID - glib only supports 32 bit random numbers */ unsigned int sessionID = (unsigned int) g_random_int_range (0, 0xFFFF); sessionString = g_strdup_printf("%u", sessionID); smlTrace(TRACE_INTERNAL, "%s: new potential session ID is %lu.", __func__, sessionID); if (smlManagerSessionFind(manager, sessionString)) smlSafeCFree(&sessionString); } smlTrace(TRACE_EXIT, "%s - %s", __func__, VA_STRING(sessionString)); return sessionString; } SmlLink *smlManagerSessionGetLink( SmlManager *manager, SmlSession *session, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, manager, session, error); CHECK_ERROR_REF managerSession *_msession = _manager_session_find(manager, session); if (!_msession) { smlErrorSet(error, SML_ERROR_GENERIC, "The session %d is not registered at the manager.", smlSessionGetSessionID(session)); goto error; } if (_msession->link) smlLinkRef(_msession->link); smlTrace(TRACE_EXIT, "%s - %p", __func__, _msession->link); return _msession->link; error: smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(error)); return NULL; } libsyncml-0.5.4/libsyncml/syncml_internals.h100644 1750 1750 5025 11211710410 21154 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2005 Armin Bauer * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ /** * @defgroup PrivateAPI libsyncml API Internals * @ingroup PrivateAPI * @brief The public part * */ /** * @defgroup PrivateObjectAPI libsyncml Object API Internals * @ingroup PrivateAPI * @brief The public part * */ /** * @defgroup PrivateLowLevelAPI Low Level API Internals * @ingroup PrivateAPI * @brief The private part * */ /*@{*/ #ifndef _SYNCML_INTERNALS_H #define _SYNCML_INTERNALS_H #include /* FIXME: Do we need this include? */ /* #include */ #include #include #include #include #include #include #include "config.h" #include extern int errno; #if defined(sun) && defined(__SVR4) #define __FUNCTION__ __func__ #endif #define smlAssert(x) if (!(x)) { fprintf(stderr, "%s:%i:E:%s: Assertion \"" #x "\" failed\n", __FILE__, __LINE__, __FUNCTION__); abort();} #define smlAssertMsg(x, msg) if (!(x)) { fprintf(stderr, "%s:%i:E:%s: %s\n", __FILE__, __LINE__, __FUNCTION__, msg); abort();} #define segfault_me char **blablabla = NULL; *blablabla = "test"; #define return_if_fail(condition) do { \ if (!(condition)) { \ return; \ } } while (0) #define return_val_if_fail(condition, val) do { \ if (!(condition)) { \ return (val); \ } } while (0) #include "sml_support.h" #include "sml_parse.h" #endif /*@}*/ libsyncml-0.5.4/libsyncml/sml_command.h100644 1750 1750 5711 11211710410 20063 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2005 Armin Bauer * Copyright (C) 2008 Michael Bell * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ /** * @defgroup SmlCommand SyncML Command * @ingroup PublicLowLevelAPI * @brief The public part * */ /*@{*/ #ifndef _SML_COMMAND_H_ #define _SML_COMMAND_H_ SmlStatus *smlStatusNew(SmlErrorType data, unsigned int cmdref, unsigned int msgref, SmlLocation *sourceref, SmlLocation *targeref, SmlCommandType type, SmlError **error); SmlStatus *smlStatusRef(SmlStatus *status); void smlStatusUnref(SmlStatus *status); SmlErrorType smlStatusGetCode(SmlStatus *status); SmlErrorClass smlStatusGetClass(SmlStatus *status); SmlCommand *smlStatusGetResult(SmlStatus *status); SmlBool smlStatusIsResult(SmlStatus *status); SmlCommand *smlCommandNew(SmlCommandType type, SmlError **error); SmlStatus *smlCommandNewReply(const SmlCommand *cmd, SmlErrorType code, SmlError **error); SmlCommand *smlCommandRef(SmlCommand *cmd); void smlCommandUnref(SmlCommand *cmd); SmlCommand *smlCommandNewAlert(SmlAlertType type, SmlLocation *target, SmlLocation *source, const char *next, const char *last, const char *contenttype, SmlError **error); SmlCommand *smlCommandNewSync(SmlLocation *target, SmlLocation *source, unsigned int num_changes, SmlError **error); SmlCommand *smlCommandNewChange(SmlChangeType type, const char *uid, const char *data, unsigned int size, const char *contenttype, SmlError **error); SmlCommand *smlCommandNewPartialChange(SmlChangeType type, const char *uid, const char *data, unsigned int complete_size, unsigned int partial_size, const char *contenttype, SmlError **error); SmlCommand *smlCommandNewResult(SmlCommand *cmd, SmlLocation *source, char *data, unsigned int size, const char *contenttype, SmlError **error); SmlCommand *smlCommandNewPut(SmlLocation *target, SmlLocation *source, const char *data, unsigned int size, const char *contenttype, SmlError **error); SmlCommand *smlCommandNewGet(SmlLocation *target, const char *contenttype, SmlError **error); SmlCommand *smlCommandNewMap(SmlLocation *target, SmlLocation *source, SmlError **error); SmlBool smlCommandAddMapItem(SmlCommand *map, SmlMapItem *item, SmlError **error); #endif //_SML_COMMAND_H_ /*@}*/ libsyncml-0.5.4/libsyncml/sml_elements.c100644 1750 1750 55372 11211710410 20304 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2005 Armin Bauer * Copyright (C) 2007-2009 Michael Bell * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include "syncml.h" #include "syncml_internals.h" #include "sml_parse_internals.h" #include "sml_elements_internals.h" #include "sml_command_internals.h" #include "sml_error_internals.h" SmlLocation *smlLocationNew(const char *locURI, const char *locName, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%s, %s, %p)", __func__, VA_STRING(locURI), VA_STRING(locName), error); CHECK_ERROR_REF if (!locURI) { smlErrorSet(error, SML_ERROR_GENERIC, "No locURI was given"); goto error; } SmlLocation *location = smlTryMalloc0(sizeof(SmlLocation), error); if (!location) goto error; location->refCount = 1; location->locURI = g_strdup(locURI); location->locName = g_strdup(locName); smlTrace(TRACE_EXIT, "%s: %p", __func__, location); return location; error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return NULL; } SmlLocation *smlLocationRef(SmlLocation *loc) { smlTrace(TRACE_ENTRY, "%s(%p)", __func__, loc); smlAssert(loc); g_atomic_int_inc(&(loc->refCount)); smlTrace(TRACE_EXIT, "%s: New refcount: %i", __func__, loc->refCount); return loc; } void smlLocationUnref(SmlLocation *loc) { smlTrace(TRACE_ENTRY, "%s(%p)", __func__, loc); smlAssert(loc); if (g_atomic_int_dec_and_test(&(loc->refCount))) { smlTrace(TRACE_INTERNAL, "%s: Refcount == 0!", __func__); if (loc->locURI) smlSafeCFree(&(loc->locURI)); if (loc->locName) smlSafeCFree(&(loc->locName)); smlSafeFree((gpointer *)&loc); } smlTrace(TRACE_EXIT, "%s", __func__); } const char *smlLocationGetURI(SmlLocation *loc) { smlAssert(loc); return loc->locURI; } void smlLocationSetURI(SmlLocation *loc, const char *uri) { smlAssert(loc); smlAssert(uri); if (loc->locURI) smlSafeCFree(&(loc->locURI)); loc->locURI = g_strdup(uri); } const char *smlLocationGetName(SmlLocation *loc) { smlAssert(loc); return loc->locName; } void smlLocationSetName(SmlLocation *loc, const char *name) { smlAssert(loc); smlAssert(name); if (loc->locName) smlSafeCFree(&(loc->locName)); loc->locName = g_strdup(name); } SmlLocation *smlLocationClone(SmlLocation *source, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p)", __func__, source, error); CHECK_ERROR_REF smlAssert(source); SmlLocation *location = smlTryMalloc0(sizeof(SmlLocation), error); if (!location) goto error; location->refCount = 1; smlLocationCopy(source, location); smlTrace(TRACE_EXIT, "%s: %p", __func__, location); return location; error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return NULL; } void smlLocationCopy(SmlLocation *source, SmlLocation *target) { smlTrace(TRACE_ENTRY, "%s(%p, %p)", __func__, source, target); smlAssert(source); smlAssert(target); if (target->locURI) smlSafeCFree(&(target->locURI)); if (target->locName) smlSafeCFree(&(target->locName)); target->locURI = g_strdup(source->locURI); target->locName = g_strdup(source->locName); smlTrace(TRACE_EXIT, "%s", __func__); } #define URL_DELIMITER "/" char *strreplace(const char *input, const char *needle, const char *replacement) { char *output = g_strdup(input); while (g_strrstr(output, needle)) { char *buffer = g_strndup(output, g_strrstr(output, needle) - output); char *buffer2 = g_strconcat(buffer, replacement ? replacement : "", g_strrstr(output, needle) + strlen(needle), NULL); smlSafeCFree(&output); output = buffer2; smlSafeCFree(&buffer); } return output; } char *normalizeUrl(const char *url) { smlTrace(TRACE_ENTRY, "%s(%s)", __func__, VA_STRING(url)); if (!url) return NULL; char *buffer = strreplace(url, "./", ""); char *buffer2 = strreplace(buffer, "//", "/"); smlSafeCFree(&buffer); if (strlen(buffer2) > 0 && buffer2[strlen(buffer2) - 1] == '/') buffer2[strlen(buffer2) - 1] = 0; smlTrace(TRACE_EXIT, "%s: %s", __func__, VA_STRING(buffer2)); return buffer2; } SmlBool smlLocationCompare(SmlLocation *objectroot, SmlLocation *object, SmlLocation *urlroot, SmlLocation *url) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p, %p)", __func__, objectroot, object, urlroot, url); if (objectroot) smlTrace(TRACE_INTERNAL, "%s: objectroot: %s", __func__, VA_STRING(objectroot->locURI)); if (object) smlTrace(TRACE_INTERNAL, "%s: object: %s", __func__, VA_STRING(object->locURI)); if (urlroot) smlTrace(TRACE_INTERNAL, "%s: urlroot: %s", __func__, VA_STRING(urlroot->locURI)); if (url) smlTrace(TRACE_INTERNAL, "%s: url: %s", __func__, VA_STRING(url->locURI)); char *cmpobjurl = NULL; char *cmpurl = NULL; char *buffer = NULL; char *buffer2 = NULL; SmlBool ret = FALSE; if (object && !url) { smlTrace(TRACE_EXIT, "%s: url not given but object: FALSE", __func__); return FALSE; } if (!object) { smlTrace(TRACE_EXIT, "%s: No object given: TRUE", __func__); return TRUE; } if (g_path_is_absolute(url->locURI) || !urlroot) cmpurl = normalizeUrl(url->locURI); else { buffer2 = normalizeUrl(url->locURI); buffer = g_strconcat(urlroot->locURI, "/", buffer2, NULL); cmpurl = normalizeUrl(buffer); smlSafeCFree(&buffer); smlSafeCFree(&buffer2); } if (g_path_is_absolute(object->locURI) || !objectroot) cmpobjurl = normalizeUrl(object->locURI); else { buffer2 = normalizeUrl(object->locURI); buffer = g_strconcat(objectroot->locURI, "/", buffer2, NULL); cmpobjurl = normalizeUrl(buffer); smlSafeCFree(&buffer); smlSafeCFree(&buffer2); } smlTrace(TRACE_INTERNAL, "%s: Comparing %s and %s", __func__, VA_STRING(cmpobjurl), VA_STRING(cmpurl)); if (strcmp(cmpobjurl, cmpurl)) ret = FALSE; else ret = TRUE; smlSafeCFree(&cmpobjurl); smlSafeCFree(&cmpurl); smlTrace(TRACE_EXIT, "%s: %i", __func__, ret); return ret; } SmlBool smlLocationIsRelative(SmlLocation *location) { smlAssert(location); return g_path_is_absolute(location->locURI) ? FALSE : TRUE; } SmlAnchor *smlAnchorNew(const char *last, const char *next, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%s, %s, %p)", __func__, VA_STRING(last), VA_STRING(next), error); CHECK_ERROR_REF SmlAnchor *anchor = smlTryMalloc0(sizeof(SmlAnchor), error); if (!anchor) goto error; anchor->last = g_strdup(last); anchor->next = g_strdup(next); smlTrace(TRACE_EXIT, "%s: %p", __func__, anchor); return anchor; error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return NULL; } void smlAnchorFree(SmlAnchor *anchor) { smlTrace(TRACE_ENTRY, "%s(%p)", __func__, anchor); smlAssert(anchor); if (anchor->last) smlSafeCFree(&(anchor->last)); if (anchor->next) smlSafeCFree(&(anchor->next)); smlSafeFree((gpointer *)&anchor); smlTrace(TRACE_EXIT, "%s", __func__); } void smlHeaderFree(SmlHeader *header) { smlTrace(TRACE_ENTRY, "%s(%p)", __func__, header); if (header->sessionID) smlSafeCFree(&(header->sessionID)); if (header->emi) smlSafeCFree(&(header->emi)); if (header->source) smlLocationUnref(header->source); if (header->target) smlLocationUnref(header->target); if (header->responseURI) smlSafeCFree(&(header->responseURI)); smlSafeFree((gpointer *)&header); smlTrace(TRACE_EXIT, "%s", __func__); } SmlItem *smlItemNew(unsigned int size, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%i, %p)", __func__, size, error); CHECK_ERROR_REF SmlItem *item = smlTryMalloc0(sizeof(SmlItem), error); if (!item) goto error; item->refCount = 1; item->size = size; smlTrace(TRACE_EXIT, "%s: %p", __func__, item); return item; error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return NULL; } /* If data is NULL, this call is the same if smlItemNew */ SmlItem *smlItemNewForData(const char *data, unsigned int size, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %i, %p)", __func__, data, size, error); CHECK_ERROR_REF SmlItem *item = smlItemNew(size, error); if (!item) goto error; if (data) { if (!smlItemAddData(item, data, size, error)) goto error_free_item; } smlTrace(TRACE_EXIT, "%s: %p", __func__, item); return item; error_free_item: smlItemUnref(item); error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return NULL; } SmlItem *smlItemRef(SmlItem *item) { smlTrace(TRACE_ENTRY, "%s(%p)", __func__, item); smlAssert(item); g_atomic_int_inc(&(item->refCount)); smlTrace(TRACE_EXIT, "%s: New refcount: %i", __func__, item->refCount); return item; } void smlItemUnref(SmlItem *item) { smlTrace(TRACE_ENTRY, "%s(%p)", __func__, item); smlAssert(item); if (g_atomic_int_dec_and_test(&(item->refCount))) { smlTrace(TRACE_INTERNAL, "%s: Refcount == 0!", __func__); if (item->source) smlLocationUnref(item->source); if (item->target) smlLocationUnref(item->target); if (item->sourceParent) smlLocationUnref(item->sourceParent); if (item->targetParent) smlLocationUnref(item->targetParent); if (item->anchor) smlAnchorFree(item->anchor); if (item->buffer) xmlBufferFree(item->buffer); if (item->contenttype) smlSafeCFree(&(item->contenttype)); smlSafeFree((gpointer *)&item); } smlTrace(TRACE_EXIT, "%s: %i", __func__, item ? item->refCount : 0); } SmlBool smlItemAddData(SmlItem *item, const char *data, unsigned int size, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %i, %p)", __func__, item, data, size, error); CHECK_ERROR_REF if (item->size && xmlBufferLength(item->buffer) + size > item->size) { smlErrorSet(error, SML_ERROR_GENERIC, "Unable to add data. size limit reached"); goto error; } if (data) { if (!item->buffer) { if (item->size) item->buffer = xmlBufferCreateSize(item->size); else item->buffer = xmlBufferCreateSize(size); } if (xmlBufferAdd(item->buffer, (xmlChar *)data, size) != 0) { smlErrorSet(error, SML_ERROR_GENERIC, "Unable to add data."); goto error; } } smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return FALSE; } /** Checks if the item is complete */ SmlBool smlItemCheck(SmlItem *item) { smlAssert(xmlBufferLength(item->buffer) >= 0); smlAssert(item); if (!item->size) return TRUE; if ((unsigned int)xmlBufferLength(item->buffer) != item->size) { smlTrace(TRACE_INTERNAL, "%s: failed because size (%d != %d) does not match (%s).", __func__, item->size, xmlBufferLength(item->buffer), VA_STRING((char *)xmlBufferContent(item->buffer))); return FALSE; } return TRUE; } SmlBool smlItemHasData(SmlItem *item) { smlAssert(item); return item->buffer ? TRUE : FALSE; } /** Returns the data of the item. The data will not be freed when the item is unrefd. After * this call, smlItemHasData will report FALSE */ SmlBool smlItemStealData(SmlItem *item, char **data, unsigned int *size, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p, %p)", __func__, item, data, size, error); CHECK_ERROR_REF smlAssert(size); if (!smlItemCheck(item)) { smlErrorSet(error, SML_ERROR_GENERIC, "Item check failed"); goto error; } *size = xmlBufferLength(item->buffer); *data = g_strndup((const char *) xmlBufferContent(item->buffer), *size); xmlBufferFree(item->buffer); item->buffer = NULL; smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return FALSE; } /** Returns a const pointer to the data of the item. the data will disappear when the data is derefd */ SmlBool smlItemGetData(SmlItem *item, char **data, unsigned int *size, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p, %p)", __func__, item, data, size, error); CHECK_ERROR_REF if (!smlItemCheck(item)) { smlErrorSet(error, SML_ERROR_GENERIC, "Item check failed"); goto error; } *data = (char *)xmlBufferContent(item->buffer); *size = xmlBufferLength(item->buffer); smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return FALSE; } void smlItemSetSource(SmlItem *item, SmlLocation *source) { smlAssert(item); smlAssert(source); item->source = source; smlLocationRef(source); } SmlLocation *smlItemGetSource(SmlItem *item) { smlAssert(item); return item->source; } void smlItemSetTarget(SmlItem *item, SmlLocation *target) { smlAssert(item); smlAssert(target); item->target = target; smlLocationRef(target); } SmlLocation *smlItemGetTarget(SmlItem *item) { smlAssert(item); return item->target; } void smlItemSetSourceParent(SmlItem *item, SmlLocation *sourceParent) { smlAssert(item); smlAssert(sourceParent); item->sourceParent = sourceParent; smlLocationRef(sourceParent); } SmlLocation *smlItemGetSourceParent(SmlItem *item) { smlAssert(item); return item->sourceParent; } void smlItemSetTargetParent(SmlItem *item, SmlLocation *targetParent) { smlAssert(item); smlAssert(targetParent); item->targetParent = targetParent; smlLocationRef(targetParent); } SmlLocation *smlItemGetTargetParent(SmlItem *item) { smlAssert(item); return item->targetParent; } void smlItemSetRaw(SmlItem *item, SmlBool raw) { smlAssert(item); item->raw = raw; } SmlCred *smlCredNewFromString(const char *type, const char *format, const char *data, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%s, %s, %s, %p)", __func__, VA_STRING(data), VA_STRING(type), VA_STRING(format), error); CHECK_ERROR_REF SmlAuthType smlType = SML_AUTH_TYPE_UNKNOWN; SmlFormatType smlFormat = SML_FORMAT_TYPE_UNKNOWN; if (!type || !strcmp(type, SML_AUTH_BASIC)) { smlType = SML_AUTH_TYPE_BASIC; } else if (!strcmp(type, SML_AUTH_MD5)) { smlType = SML_AUTH_TYPE_MD5; } else { smlErrorSet(error, SML_ERROR_GENERIC, "Unknown type - %s.", type); goto error; } if (!format || !strcmp(format, SML_BASE64)) { smlFormat = SML_FORMAT_TYPE_BASE64; } else { smlErrorSet(error, SML_ERROR_GENERIC, "SyncML credential: Unknown format - %s.", format); goto error; } if (!data) { smlErrorSet(error, SML_ERROR_GENERIC, "Data is missing in %s.", __func__); goto error; } smlTrace(TRACE_EXIT, "%s", __func__); return smlCredNew(smlType, smlFormat, data, NULL, error); error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return NULL; } SmlCred *smlCredNewAuth(SmlAuthType type, const char *username, const char *password, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%d, %s, %p)", __func__, type, VA_STRING(username), error); CHECK_ERROR_REF SmlCred *cred = NULL; if (username == NULL || !strlen(username)) { smlErrorSet(error, SML_ERROR_INTERNAL_MISCONFIGURATION, "If authentication should be used then the username must be set."); goto error; } if (password == NULL || !strlen(password)) { smlErrorSet(error, SML_ERROR_INTERNAL_MISCONFIGURATION, "If authentication should be used then the password must be set."); goto error; } cred = smlTryMalloc0(sizeof(SmlCred), error); if (!cred) goto error; cred->refCount = 1; cred->format = SML_FORMAT_TYPE_BASE64; cred->type = type; cred->username = g_strdup(username); cred->password = g_strdup(password); smlTrace(TRACE_EXIT, "%s", __func__); return cred; error: if (cred) smlSafeFree((gpointer *)&cred); smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return NULL; } SmlCred *smlCredNew(SmlAuthType type, SmlFormatType format, const char *data, const char *username, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%s, %d, %d, %p)", __func__, VA_STRING(data), type, format, error); CHECK_ERROR_REF SmlCred *cred = smlTryMalloc0(sizeof(SmlCred), error); if (!cred) goto error; cred->type = type; cred->format = format; cred->data = g_strdup(data); if (username) cred->username = g_strdup(username); else cred->username = NULL; cred->refCount = 1; smlTrace(TRACE_EXIT, "%s: %p", __func__, cred); return cred; error: if (cred->data) smlSafeCFree(&(cred->data)); if (cred->username) smlSafeCFree(&(cred->username)); if (cred) smlSafeFree((gpointer *)&cred); smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return NULL; } void smlCredRef(SmlCred *cred) { smlTrace(TRACE_ENTRY, "%s(%p)", __func__, cred); smlAssert(cred); g_atomic_int_inc(&(cred->refCount)); smlTrace(TRACE_EXIT, "%s: New refcount: %i", __func__, cred->refCount); } void smlCredUnref(SmlCred *cred) { smlTrace(TRACE_ENTRY, "%s(%p)", __func__, cred); smlAssert(cred); if (g_atomic_int_dec_and_test(&(cred->refCount))) { smlTrace(TRACE_INTERNAL, "%s: Refcount == 0!", __func__); if (cred->data) smlSafeCFree(&(cred->data)); if (cred->username) smlSafeCFree(&(cred->username)); if (cred->password) smlSafeCFree(&(cred->password)); smlSafeFree((gpointer *)&cred); } smlTrace(TRACE_EXIT, "%s", __func__); } /* FIXME: DEPRECATED */ void smlCredFree(SmlCred *cred) { smlCredUnref(cred); } SmlChal *smlChalNew(SmlAuthType type, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%u, %p)", __func__, type, error); CHECK_ERROR_REF SmlChal *chal = NULL; /* allocate memory */ smlAssert(type != SML_AUTH_TYPE_UNKNOWN); chal = smlTryMalloc0(sizeof(SmlChal), error); if (!chal) goto error; chal->refCount = 1; chal->type = type; chal->format = SML_FORMAT_TYPE_BASE64; if (type == SML_AUTH_TYPE_MD5) { /* A nonce must be generated for this type. * minimum strength: 2^128 * strength per byte: 2^6 - 2 > 2^5 * needed bytes: 128 / 5 < 130 / 5 = 26 */ chal->nonce_plain = smlRandStr(26, TRUE); chal->nonce_length = 26; chal->nonce_b64 = g_base64_encode( (const unsigned char *) chal->nonce_plain, chal->nonce_length); if (!chal->nonce_b64) { smlErrorSet(error, SML_ERROR_GENERIC, "The nonce of the challenge cannot be base64 encoded."); goto error; } } smlTrace(TRACE_EXIT, "%s", __func__); return chal; error: if (chal->nonce_plain) smlSafeCFree(&(chal->nonce_plain)); if (chal->nonce_b64) smlSafeCFree(&(chal->nonce_b64)); if (chal) smlSafeFree((gpointer *)&chal); smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(error)); return NULL; } SmlChal *smlChalNewFromBinary( SmlAuthType type, const char *nonce, size_t length, SmlError **error) { smlTrace(TRACE_ENTRY, "%s", __func__); CHECK_ERROR_REF SmlChal *chal = NULL; /* only syncml:auth-md5 needs a nonce */ smlAssert(type == SML_AUTH_TYPE_MD5); /* allocate memory */ chal = smlTryMalloc0(sizeof(SmlChal), error); if (!chal) goto error; chal->refCount = 1; /* copy nonce */ chal->type = SML_AUTH_TYPE_MD5; chal->format = SML_FORMAT_TYPE_BASE64; chal->nonce_plain = g_strndup(nonce, length); chal->nonce_length = length; /* create base64 nonce */ chal->nonce_b64 = g_base64_encode((const unsigned char *) nonce, length); if (!chal->nonce_b64) { smlErrorSet(error, SML_ERROR_GENERIC, "The base64 encoding of the nonce failed."); goto error; } smlTrace(TRACE_EXIT, "%s", __func__); return chal; error: smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(error)); return NULL; } SmlChal *smlChalNewFromBase64( SmlAuthType type, const char *nonce, SmlError **error) { smlTrace(TRACE_ENTRY, "%s", __func__); CHECK_ERROR_REF SmlChal *chal = NULL; /* only syncml:auth-md5 needs a nonce */ smlAssert(type == SML_AUTH_TYPE_MD5); /* allocate memory */ chal = smlTryMalloc0(sizeof(SmlChal), error); if (!chal) goto error; chal->refCount = 1; /* copy nonce */ chal->type = SML_AUTH_TYPE_MD5; chal->format = SML_FORMAT_TYPE_BASE64; chal->nonce_b64 = g_strdup(nonce); /* create binary nonce */ size_t length = 0; chal->nonce_plain = (char *) g_base64_decode(nonce, &length); if (!chal->nonce_plain || length < 1) { smlErrorSet(error, SML_ERROR_GENERIC, "The base64 encoded nonce cannot be decoded."); goto error; } chal->nonce_length = length; smlTrace(TRACE_EXIT, "%s", __func__); return chal; error: smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(error)); return NULL; } void smlChalRef(SmlChal *chal) { smlTrace(TRACE_ENTRY, "%s", __func__); smlAssert(chal); g_atomic_int_inc(&(chal->refCount)); smlTrace(TRACE_EXIT, "%s: New refcount: %i", __func__, chal->refCount); } void smlChalUnref(SmlChal *chal) { smlTrace(TRACE_ENTRY, "%s", __func__); smlAssert(chal); if (g_atomic_int_dec_and_test(&(chal->refCount))) { smlTrace(TRACE_INTERNAL, "%s: Refcount == 0!", __func__); if (chal->nonce_plain) smlSafeCFree(&(chal->nonce_plain)); if (chal->nonce_b64) smlSafeCFree(&(chal->nonce_b64)); smlSafeFree((gpointer *)&chal); } smlTrace(TRACE_EXIT, "%s", __func__); } /* FIXME: DEPRECATED */ void smlChalFree(SmlChal *chal) { smlChalUnref(chal); } SmlMapItem *smlMapItemNew(const char *uid, const char *newuid, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%s, %s, %p)", __func__, VA_STRING(uid), VA_STRING(newuid), error); CHECK_ERROR_REF smlAssert(uid); smlAssert(newuid); SmlMapItem *item = smlTryMalloc0(sizeof(SmlMapItem), error); if (!item) goto error; item->refCount = 1; item->source = smlLocationNew(newuid, NULL, error); if (!item->source) goto error_free_item; item->target = smlLocationNew(uid, NULL, error); if (!item->target) goto error_free_source; smlTrace(TRACE_EXIT, "%s: %p", __func__, item); return item; error_free_source: smlLocationUnref(item->source); error_free_item: smlSafeFree((gpointer *)&item); error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return NULL; } SmlMapItem *smlMapItemRef(SmlMapItem *item) { smlTrace(TRACE_ENTRY, "%s(%p)", __func__, item); smlAssert(item); g_atomic_int_inc(&(item->refCount)); smlTrace(TRACE_EXIT, "%s: New refcount: %i", __func__, item->refCount); return item; } void smlMapItemUnref(SmlMapItem *item) { smlTrace(TRACE_ENTRY, "%s(%p)", __func__, item); smlAssert(item); if (g_atomic_int_dec_and_test(&(item->refCount))) { smlTrace(TRACE_INTERNAL, "%s: Refcount == 0!", __func__); if (item->source) { smlLocationUnref(item->source); item->source = NULL; } if (item->target) { smlLocationUnref(item->target); item->target = NULL; } smlSafeFree((gpointer *)&item); } smlTrace(TRACE_EXIT, "%s", __func__); } libsyncml-0.5.4/libsyncml/sml_base64.h100644 1750 1750 3156 11211710410 17532 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2005 Armin Bauer * Copyright (C) 2008 Michael Bell * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ /** * @defgroup SmlBase64 SyncML Base64 (DEPRECATED) * @ingroup PublicLowLevelAPI * @brief The public part * */ /*@{*/ #ifndef _SML_BASE64_H_ #define _SML_BASE64_H_ /* expire date: 20091028 */ SmlBool smlBase64Decode(const char *input, char **output, unsigned int *outsize, SmlError **error) LIBSYNCML_DEPRECATED; SmlBool smlBase64DecodeBinary(const char *input, unsigned int size, char **output, unsigned int *outsize, SmlError **error) LIBSYNCML_DEPRECATED; SmlBool smlBase64Encode(const char *input, char **output, SmlError **error) LIBSYNCML_DEPRECATED; SmlBool smlBase64EncodeBinary(const char *input, unsigned int size, char **output, SmlError **error) LIBSYNCML_DEPRECATED; #endif //_SML_BASE64_H_ /*@}*/ libsyncml-0.5.4/libsyncml/CMakeLists.txt100644 1750 1750 5022 11211710410 20154 0ustar00bellmichbellmichLINK_DIRECTORIES( ${GLIB2_LIBRARY_DIRS} ${GTHREAD2_LIBRARY_DIRS} ${GOBJECT2_LIBRARY_DIRS} ${LIBXML2_LIBRARY_DIRS} ${OPENOBEX_LIBRARY_DIRS} ${LIBWBXML2_LIBRARY_DIRS} ${LIBSOUP2_LIBRARY_DIRS} ${BLUEZ_LIBRARY_DIRS} ) INCLUDE_DIRECTORIES( ${CMAKE_SOURCE_DIR} ${CMAKE_BINARY_DIR} ${GLIB2_INCLUDE_DIRS} ${GTHREAD2_INCLUDE_DIRS} ${GOBJECT2_INCLUDE_DIRS} ${LIBXML2_INCLUDE_DIRS} ${OPENOBEX_INCLUDE_DIRS} ${LIBWBXML2_INCLUDE_DIRS} ${LIBSOUP2_INCLUDE_DIRS} ${BLUEZ_INCLUDE_DIRS} ) SET( libsyncml_LIB_SRCS sml_base64.c sml_command.c sml_devinf.c sml_elements.c sml_error.c sml_manager.c sml_md5.c sml_notification.c sml_parse.c sml_queue.c sml_session.c sml_support.c sml_transport.c data_sync_api/data_sync.c data_sync_api/data_sync_abort.c data_sync_api/data_sync_callbacks.c data_sync_api/data_sync_common.c data_sync_api/data_sync_devinf.c data_sync_api/data_sync_loop.c data_sync_api/data_sync_client.c data_sync_api/data_sync_server.c data_sync_api/transport_http_client.c data_sync_api/transport_http_server.c data_sync_api/transport_obex_client.c objects/sml_auth.c objects/sml_devinf_obj.c objects/sml_ds_server.c parser/sml_wbxml.c parser/sml_xml_assm.c parser/sml_xml_parse.c ) IF ( ENABLE_OBEX ) SET( libsyncml_LIB_SRCS ${libsyncml_LIB_SRCS} transports/obex_client.c transports/obex_server.c transports/obex_client_samsung.c transports/obex.c ) ENDIF ( ENABLE_OBEX ) IF ( ENABLE_HTTP ) SET( libsyncml_LIB_SRCS ${libsyncml_LIB_SRCS} transports/http_client.c transports/http_server.c ) ENDIF ( ENABLE_HTTP ) ADD_LIBRARY( syncml SHARED ${libsyncml_LIB_SRCS} ) SET_TARGET_PROPERTIES( syncml PROPERTIES SOVERSION ${LIBSYNCML_LIBVERSION_SOVERSION} ) SET_TARGET_PROPERTIES( syncml PROPERTIES VERSION ${LIBSYNCML_LIBVERSION_VERSION} ) TARGET_LINK_LIBRARIES( syncml ${GLIB2_LIBRARIES} ${GTHREAD2_LIBRARIES} ${GOBJECT2_LIBRARIES} ${LIBXML2_LIBRARIES} ${BLUEZ_LIBRARIES} ${LIBWBXML2_LIBRARIES} ${LIBSOUP2_LIBRARIES} ${OPENOBEX_LIBRARIES} ) INSTALL( TARGETS syncml DESTINATION ${LIBSYNCML_LIBRARIES_DIR} ) INSTALL( FILES objects/sml_devinf_obj.h objects/sml_ds_server.h objects/sml_auth.h sml_base64.h sml_command.h sml_defines.h sml_devinf.h sml_elements.h sml_error.h sml_manager.h sml_md5.h sml_notification.h sml_parse.h sml_session.h sml_transport.h syncml.h DESTINATION ${LIBSYNCML_INCLUDE_DIR}/libsyncml ) ## install header files of data sync API INSTALL( FILES data_sync_api/defines.h data_sync_api/standard.h data_sync_api/callbacks.h DESTINATION ${LIBSYNCML_INCLUDE_DIR}/libsyncml/data_sync_api ) libsyncml-0.5.4/libsyncml/sml_session_internals.h100644 1750 1750 5675 11211710410 22220 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2005 Armin Bauer * Copyright (C) 2007-2008 Michael Bell * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #ifndef _SML_SESSION_INTERNALS_H_ #define _SML_SESSION_INTERNALS_H_ #include "sml_queue_internals.h" struct SmlSession { gint refCount; SmlProtocolVersion version; SmlProtocolType protocol; SmlSessionType sessionType; SmlAssembler *assembler; SmlBool onlyReplace; SmlSessionEventCallback eventCallback; void *eventCallbackUserdata; SmlSessionDataCallback dataCallback; void *dataCallbackUserdata; char *sessionID; SmlLocation *target; SmlLocation *orgTarget; SmlLocation *source; char *responseURI; SmlChal *chal; SmlCred *cred; /* These are the local limits of MaxMsgSize and MaxObjSize. * These are the limits which are send to the remote peer * but they are not the remote limits. */ unsigned int localMaxMsgSize; unsigned int localMaxObjSize; GList *pendingReplies; unsigned long lastMessageID; unsigned long lastReceivedMessageID; unsigned long lastCommandID; GList *commands; SmlBool final; SmlBool authenticate; SmlBool established; SmlMimeType type; SmlQueue *command_queue; SmlBool waiting; SmlBool sending; GList *commandStack; SmlBool hasCommand; SmlBool assmHasHeader; SmlBool end; GMutex *reportEnd; SmlBool reportedEnd; SmlCommand *parentCommand; /* The buffer that holds the incoming command which has * an item with a large object. */ SmlCommand *incomingBuffer; /* The outgoing command that gets fragmented */ SmlCommand *frag_command; /* How much of the item of the frag_command already * got sent */ unsigned int frag_size; SmlStatusReplyCb frag_callback; void *frag_userdata; SmlBool active; GMutex *dispatch_mutex; }; struct SmlPendingStatus { unsigned int cmdID; unsigned int msgID; SmlStatusReplyCb callback; void *userdata; }; SmlBool smlSessionTryLock(SmlSession *session); void smlSessionLock(SmlSession *session); void smlSessionUnlock(SmlSession *session); void smlSessionRestoreTargetURI(SmlSession *session); SmlBool smlSessionSetResponseURI( SmlSession *session, const char *responseURI, SmlError **error); #endif //_SML_SESSION_INTERNALS_H_ libsyncml-0.5.4/libsyncml/sml_queue.c100644 1750 1750 24064 11211710410 17606 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2005 Armin Bauer * Copyright (C) 2009 Michael Bell * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include "syncml.h" #include "syncml_internals.h" #include "sml_queue_internals.h" #include "sml_error_internals.h" #ifndef DOXYGEN_SHOULD_SKIP_THIS static gboolean _queue_prepare(GSource *source, gint *timeout_) { smlTrace(TRACE_INTERNAL, "%s(%p, %p)", __func__, source, timeout_); *timeout_ = 1; return FALSE; } /* TODO only use me for debugging */ void smlQueueAssert(SmlQueue *queue) { if (queue->tail) { smlAssert(queue->head); } if (queue->prio) { smlAssert(queue->head); } if (queue->head) { smlAssert(queue->tail); } if (g_list_length(queue->head) == 1) { smlAssert(queue->tail == queue->head); } smlAssert(g_list_last(queue->head) == queue->tail); } static gboolean _queue_check(GSource *source) { SmlQueue *queue = *((SmlQueue **)(source + 1)); return smlQueueCheck(queue); } static gboolean _queue_dispatch(GSource *source, GSourceFunc callback, gpointer user_data) { smlTrace(TRACE_INTERNAL, "%s(%p, %p, %p)", __func__, source, callback, user_data); SmlQueue *queue = user_data; smlAssert(queue->handler); while (smlQueueCheck(queue)) smlQueueDispatch(queue); return TRUE; } #endif /* DOXYGEN_SHOULD_SKIP_THIS */ /*! @brief Creates a new asynchronous queue * * This function return the pointer to a newly created SmlQueue * */ SmlQueue *smlQueueNew(SmlError **error) { CHECK_ERROR_REF SmlQueue *queue = smlTryMalloc0(sizeof(SmlQueue), error); if (!queue) return NULL; if (!g_thread_supported ()) g_thread_init (NULL); queue->mutex = g_mutex_new(); return queue; } void smlQueueFree(SmlQueue *queue) { if (queue->source) smlQueueDetach(queue); if (queue->head) g_list_free(queue->head); g_mutex_free(queue->mutex); smlSafeFree((gpointer *)&queue); } void smlQueueFlush(SmlQueue *queue) { g_mutex_lock(queue->mutex); smlQueueAssert(queue); queue->tail = NULL; g_list_free(queue->head); queue->head = NULL; queue->prio = NULL; smlQueueAssert(queue); g_mutex_unlock(queue->mutex); } SmlBool smlQueueCheckPrio(SmlQueue *queue) { g_mutex_lock(queue->mutex); SmlBool ret = (queue->prio == NULL) ? FALSE : TRUE; g_mutex_unlock(queue->mutex); return ret; } SmlBool smlQueueCheck(SmlQueue *queue) { g_mutex_lock(queue->mutex); SmlBool ret = (queue->head == NULL) ? FALSE : TRUE; g_mutex_unlock(queue->mutex); return ret; } unsigned int smlQueueLength(SmlQueue *queue) { g_mutex_lock(queue->mutex); unsigned int ret = g_list_length(queue->head); g_mutex_unlock(queue->mutex); return ret; } unsigned int smlQueueLengthPrio(SmlQueue *queue) { g_mutex_lock(queue->mutex); unsigned int ret = g_list_length(queue->prio); g_mutex_unlock(queue->mutex); return ret; } void *smlQueueTryPop(SmlQueue *queue) { smlAssert(queue); void *message = NULL; g_mutex_lock(queue->mutex); smlQueueAssert(queue); if (queue->head) { message = queue->head->data; if (queue->head == queue->tail) queue->tail = NULL; if (queue->prio && message == queue->prio->data) queue->prio = g_list_delete_link(queue->prio, queue->prio); queue->head = g_list_delete_link(queue->head, queue->head); } smlQueueAssert(queue); g_mutex_unlock(queue->mutex); return message; } void *smlQueueTryPopPrio(SmlQueue *queue) { smlAssert(queue); void *message = NULL; g_mutex_lock(queue->mutex); smlQueueAssert(queue); message = queue->prio ? queue->prio->data : NULL; queue->prio = g_list_delete_link(queue->prio, queue->prio); if (message) { queue->head = g_list_remove(queue->head, message); queue->tail = g_list_last(queue->head); } smlQueueAssert(queue); g_mutex_unlock(queue->mutex); return message; } void smlQueueLock(SmlQueue *queue) { smlAssert(queue); g_mutex_lock(queue->mutex); } void smlQueueUnlock(SmlQueue *queue) { smlAssert(queue); g_mutex_unlock(queue->mutex); } void *smlQueuePeek(SmlQueue *queue) { smlAssert(queue); return queue->head ? queue->head->data : NULL; } void *smlQueuePeekPrio(SmlQueue *queue) { smlAssert(queue); void *message = NULL; g_mutex_lock(queue->mutex); message = queue->prio ? queue->prio->data : NULL; smlQueueAssert(queue); g_mutex_unlock(queue->mutex); return message; } void smlQueuePrint(SmlQueue *queue) { smlAssert(queue); g_mutex_lock(queue->mutex); GString *info = g_string_new("Contents of queue "); g_string_append_printf(info, "%p:", queue); GList *m = NULL; for (m = queue->head; m; m = m->next) { g_string_append_printf(info, ", %p (list %p)", m->data, m); } smlTrace(TRACE_INTERNAL, "%s: %s", __func__, VA_STRING(info->str)); g_string_free(info, TRUE); info = g_string_new("Contents of prio queue:"); for (m = queue->prio; m; m = m->next) { g_string_append_printf(info, ", %p (list %p)", m->data, m); } smlTrace(TRACE_INTERNAL, "%s: %s", __func__, VA_STRING(info->str)); g_string_free(info, TRUE); smlTrace(TRACE_INTERNAL, "%s: Tail of queue: %p (list %p)", __func__, queue->tail ? queue->tail->data : NULL, queue->tail); g_mutex_unlock(queue->mutex); } GList *smlQueuePeekNext(SmlQueue *queue, GList *prev) { smlAssert(queue); if (!prev) return queue->head; else return prev->next; } void smlQueuePushHeadPrio(SmlQueue *queue, void *data) { smlAssert(queue); smlAssert(data); g_mutex_lock(queue->mutex); smlQueueAssert(queue); queue->head = g_list_prepend(queue->head, data); if (!queue->tail) queue->tail = queue->head; queue->prio = g_list_prepend(queue->prio, data); smlQueueAssert(queue); g_mutex_unlock(queue->mutex); } void smlQueuePushHead(SmlQueue *queue, void *data) { smlAssert(queue); smlAssert(data); g_mutex_lock(queue->mutex); smlQueueAssert(queue); queue->head = g_list_prepend(queue->head, data); if (!queue->tail) queue->tail = queue->head; smlQueueAssert(queue); g_mutex_unlock(queue->mutex); } /*! @brief Sends a message down a queue * * @param queue The queue to send the message to * @param message The message to send * */ void smlQueueSendPrio(SmlQueue *queue, void *data) { smlAssert(queue); smlAssert(data); g_mutex_lock(queue->mutex); smlQueueAssert(queue); if (queue->tail) { queue->tail = g_list_append(queue->tail, data); queue->tail = queue->tail->next; } else { queue->head = g_list_append(queue->head, data); queue->tail = queue->head; } queue->prio = g_list_append(queue->prio, data); smlQueueAssert(queue); g_mutex_unlock(queue->mutex); } /*! @brief Sends a message down a queue * * @param queue The queue to send the message to * @param message The message to send * */ void smlQueueSend(SmlQueue *queue, void *data) { smlAssert(queue); smlAssert(data); g_mutex_lock(queue->mutex); smlQueueAssert(queue); if (queue->tail) { queue->tail = g_list_append(queue->tail, data); queue->tail = queue->tail->next; } else { queue->head = g_list_append(queue->head, data); queue->tail = queue->head; } smlQueueAssert(queue); g_mutex_unlock(queue->mutex); } /*! @brief Sets the message handler for a queue * * Sets the function that will receive all messages, except the methodcall replies * * @param queue The queue to set the handler on * @param handler The message handler function * @param user_data The userdata that the message handler should receive * */ void smlQueueSetHandler(SmlQueue *queue, SmlQueueHandler handler, void *userdata) { queue->handler = handler; queue->userdata = userdata; } /*! @brief Sets the queue to use the gmainloop with the given context * * This function will attach the SmlQueue as a source to the given context. * The queue will then be check for new messages and the messages will be * handled. * * @param queue The queue to set up * @param context The context to use. NULL for default loop * */ void smlQueueAttach(SmlQueue *queue, GMainContext *context) { smlTrace(TRACE_ENTRY, "%s(%p, %p)", __func__, queue, context); smlAssert(queue); smlAssert(queue->source == NULL); GSourceFuncs *functions = g_malloc0(sizeof(GSourceFuncs)); functions->prepare = _queue_prepare; functions->check = _queue_check; functions->dispatch = _queue_dispatch; functions->finalize = NULL; GSource *source = g_source_new(functions, sizeof(GSource) + sizeof(SmlQueue *)); SmlQueue **queueptr = (SmlQueue **)(source + 1); *queueptr = queue; g_source_set_callback(source, NULL, queue, NULL); queue->source = source; queue->functions = functions; g_source_attach(source, context); queue->context = context; if (context) g_main_context_ref(context); smlTrace(TRACE_EXIT, "%s", __func__); } void smlQueueDetach(SmlQueue *queue) { smlTrace(TRACE_ENTRY, "%s(%p)", __func__, queue); smlAssert(queue); smlAssert(queue->source); g_source_destroy(queue->source); g_source_unref(queue->source); smlSafeFree((gpointer *)&(queue->functions)); queue->source = NULL; if (queue->context) { g_main_context_unref(queue->context); queue->context = NULL; } smlTrace(TRACE_EXIT, "%s", __func__); } SmlBool smlQueueIsAttached(SmlQueue *queue) { return queue->source ? TRUE : FALSE; } void smlQueueDispatch(SmlQueue *queue) { void *message = smlQueueTryPop(queue); if (message) queue->handler(message, queue->userdata); } void smlQueueDispatchPrio(SmlQueue *queue) { void *message = smlQueueTryPopPrio(queue); if (message) queue->handler(message, queue->userdata); } /*@}*/ libsyncml-0.5.4/libsyncml/sml_error.c100644 1750 1750 31140 11211710410 17604 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2005 Armin Bauer * Copyright (C) 2008-2009 Michael Bell * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include "syncml.h" #include "syncml_internals.h" #include "sml_error_internals.h" /** * @defgroup SmlErrorPrivate SyncML Error Internals * @ingroup PrivateLowLevelAPI * @brief The private part of the error handling * */ /*@{*/ /*! @brief Returns a string representation for a SyncML error. * * Please see the OMA documents for the according copyrights. * * @param type The type to set * @returns The error message as const string. * If NULL is returned then this is not an error. * If a string with the length zero is returned * then there is no error message for this error. * This is a bug and you can file a ticket. * */ const char *smlErrorTypeGetMessage(SmlErrorType type) { if (SML_ERROR_UNKNOWN) return "An unkown error occured."; /* return NULL if this is not an error */ if (type < 300) return NULL; /* Errors according to SyncML Representation Protocol 1.2.1 * The error messages are the original phrases like specified * by the OMA in the original specifications. */ switch (type) { /* Retry error */ case SML_ERROR_MULTIPLE_CHOICES: return "Multiple choices. The requested target is one of a number of " \ "multiple alternatives requested target. The alternative SHOULD " \ "also be returned in the Item element type in the Status."; case SML_ERROR_MOVED_PERMANENTLY: return "Moved permanently. The requested target has a new URI. The new " \ "URI SHOULD also be returned in the Item element type in the " \ "Status."; case SML_ERROR_FOUND_RETRY: return "Found. The requested target has temporarily moved to a different " \ "URI. The original URI SHOULD continue to be used. The URI of " \ "the temporary location SHOULD also be returned in the Item " \ "element type in the Status. The requestor SHOULD confirm the " \ "identity and authority of the temporary URI to act on behalf of the " \ "original target URI."; case SML_ERROR_SEE_OTHER_RETRY: return "See other. The requested target can be found at another URI. The " \ "other URI SHOULD be returned in the Item element type in the " \ "Status."; case SML_ERROR_NOT_MODIFIED: return "Not modified. The requested SyncML command was not executed " \ "on the target. This is an additional response that can be added to " \ "any of the other Redirection response codes."; case SML_ERROR_USE_PROXY: return "Use proxy. The requested target MUST be accessed through the " \ "specified proxy URI. The proxy URI SHOULD also be returned in " \ "the Item element type in the Status."; /* Errors */ case SML_ERROR_BAD_REQUEST: return "Bad request. The requested command could not be performed " \ "because of malformed syntax in the command. The malformed " \ "command MAY also be returned in the Item element type in the " \ "Status."; case SML_ERROR_AUTH_REJECTED: return "Invalid credentials. The requested command failed because the " \ "requestor MUST provide proper authentication. If the property type " \ "of authentication was presented in the original request, then the " \ "response code indicates that the requested command has been " \ "refused for those credentials."; case SML_ERROR_PAYMENT_NEEDED: return "Paymentneeded. The requested command failed because proper " \ "payment isneeded. This version of SyncML does not standardize " \ "the payment mechanism."; case SML_ERROR_FORBIDDEN: return "Forbidden. The requested command failed, but the recipient " \ "understood the requested command. Authentication will not help " \ "and the request SHOULD NOT be repeated. If the recipient wishes " \ "to make public why the request was denied, then a description " \ "MAY be specified in the Item element type in the Status. If the " \ "recipient does not wish to make public why the request was denied " \ "then the response code 404 MAY be used instead."; case SML_ERROR_NOT_FOUND: return "Not found. The requested target was not found. No indication is " \ "given as to whether this is a temporary or permanent condition. The " \ "response code 410 SHOULD be used when the condition is " \ "permanent and the recipient wishes to make this fact public. This " \ "response code is also used when the recipient does not want to " \ "make public the reason for why a requested command is not " \ "allowed or when no other response code is appropriate."; case SML_ERROR_UNSUPPORTED_FEATURE: return "Optional feature not supported. The requested command failed " \ "because an OPTIONAL feature in the request was not supported. " \ "The unsupported feature SHOULD be specified by the Item " \ "element type in the Status."; case SML_ERROR_RETRY_LATER: return "Retry later. The request failed at this time and the originator " \ "SHOULD retry the request later. The recipient SHOULD specify a " \ "RespURI with the response URI and the date/time that the " \ "command SHOULD be repeated."; case SML_ERROR_ALREADY_EXISTS: return "Already exists. The requested Put or Add command failed " \ "because the target already exists."; case SML_ERROR_SIZE_MISMATCH: return "Size mismatch. The chunked object was received, but the size of " \ "the received object did not match the size declared within the first " \ "chunk."; /* Standard errors */ case SML_ERROR_GENERIC: return "Command failed. The recipient encountered an unexpected " \ "condition which prevented it from fulfilling the request."; case SML_ERROR_NOT_IMPLEMENTED: return "Command not implemented. The recipient does not support the " \ "command REQUIRED to fulfill the request. This is the appropriate " \ "response when the recipient does not recognize the requested " \ "command and is not capable of supporting it for any resource."; case SML_ERROR_SERVICE_UNAVAILABLE: return "Service unavailable. The recipient is currently unable to handle the " \ "request due to a temporary overloading or maintenance of the " \ "recipient. The implication is that this is a temporary condition; " \ "which will be alleviated after some delay. The recipient SHOULD " \ "specify the URI and date/time after which the originator SHOULD " \ "retry in the RespURI in the response."; case SML_ERROR_REQUIRE_REFRESH: return "RefreshREQUIRED. An error occurred that necessitates a refresh " \ "of the current synchronization state of the client with the server. " \ "Client is requested to initiate the session type specified in the " \ "server's ALERT (which is included in the same package as the " \ "Status 508). The only valid values for this ALERT are either a slow " \ "sync (201) or a refresh with the server."; case SML_ERROR_SERVER_FAILURE: return "Server failure. A severe error occurred in the server while " \ "processing the request. The originator SHOULD NOT retry the " \ "request."; /* Internal errors */ case SML_ERROR_INTERNAL_IO_ERROR: return "An internal I/O error occured."; case SML_ERROR_INTERNAL_TIMEOUT: return "An internal timeout occured."; case SML_ERROR_INTERNAL_FILE_NOT_FOUND: return "An internal error occured because of a missing file."; case SML_ERROR_INTERNAL_MISCONFIGURATION: return "An internal misconfiguration was detected."; case SML_ERROR_INTERNAL_NO_MEMORY: return "An internal I/O error occured."; default: return ""; } } /*! @brief Sets a error from a va_list * * @param error A pointer to a error struct * @param type The type to set * @param format The message * @param args The arguments to the message * */ void smlErrorSetVargs(SmlError **error, SmlErrorType type, const char *format, va_list args) { return_if_fail(error); return_if_fail(smlErrorIsSet(error) == FALSE); return_if_fail(format); *error = (SmlError *) malloc(sizeof(SmlError)); return_if_fail(*error); (*error)->message = g_strdup_vprintf(format, args); (*error)->type = type; const char *msg = smlErrorTypeGetMessage(type); if (!msg) { (*error)->printMessage = g_strdup((*error)->message); } else if (strlen(msg) == 0) { (*error)->printMessage = g_strdup_printf( "Error %d: %s", (*error)->type, (*error)->message); } else { (*error)->printMessage = g_strdup_printf( "%s %s", msg, (*error)->message); } (*error)->refCount = 1; return; } /*@}*/ /** * @defgroup SmlError SyncML Errors * @ingroup PublicLowLevelAPI * @brief Libsyncml's error reporting facilities * */ /*@{*/ SmlError **smlErrorRef(SmlError **error) { if (!smlErrorIsSet(error)) return error; g_atomic_int_inc(&(*error)->refCount); return error; } void smlErrorDeref(SmlError **error) { if (!smlErrorIsSet(error)) return; if (!g_atomic_int_dec_and_test(&((*error)->refCount))) { *error = NULL; return; } if ((*error)->message) smlSafeCFree (&((*error)->message)); if ((*error)->printMessage) smlSafeCFree (&((*error)->printMessage)); smlSafeFree((gpointer *)error); } /*! @brief Checks if the error is set * * @param error A pointer to a error struct to check * @returns TRUE if the error is set, FALSE otherwise * */ SmlBool smlErrorIsSet(SmlError **error) { if (!error) return FALSE; if (*error == NULL) return FALSE; return TRUE; } /*! @brief Returns the type of the error * * @param error The error * @returns The type of the error * */ SmlErrorType smlErrorGetType(SmlError **error) { if (!smlErrorIsSet(error)) return SML_NO_ERROR; return (*error)->type; } /*! @brief Returns the message of the error * * @param error The error to print * @returns The message of the error or NULL if no error * */ const char *smlErrorPrint(SmlError **error) { if (!smlErrorIsSet(error)) return NULL; return (*error)->printMessage; } /*! @brief Updates the error message * * You can use this function to update the error message on * a error. You can use the old error->message as a parameter * for this function. * * @param error A pointer to a error struct to update * @param format The new message * */ void smlErrorUpdate(SmlError **error, const char *format, ...) { return_if_fail(smlErrorIsSet(error)); char *old = (*error)->message; va_list args; va_start(args, format); (*error)->message = g_strdup_vprintf(format, args); va_end (args); smlSafeCFree(&old); } /*! @brief Duplicates the error into the target * * * @param target The target error to update * @param source The source error which to duplicate * */ void smlErrorDuplicate(SmlError **target, SmlError **source) { return_if_fail(target != NULL); return_if_fail(smlErrorIsSet(source)); return_if_fail(!smlErrorIsSet(target)); smlErrorSet(target, (*source)->type, (*source)->message); } /*! @brief Sets the error * * You can use this function to set the error to the given type and message * * @param error A pointer to a error struct to set * @param type The Error type to set * @param format The message * */ void smlErrorSet(SmlError **error, SmlErrorType type, const char *format, ...) { va_list args; va_start(args, format); smlErrorSetVargs(error, type, format, args); va_end (args); } /*! @brief Sets the type of an error * * @param error A pointer to a error struct to set * @param type The Error type to set * */ void smlErrorSetType(SmlError **error, SmlErrorType type) { return_if_fail(error != NULL); (*error)->type = type; } /*! @brief Gets the error class * * @param error A pointer to a error struct * @returns The error class * */ SmlErrorClass smlErrorGetClass(SmlError **error) { if (!smlErrorIsSet(error)) return SML_ERRORCLASS_SUCCESS; if ((*error)->type == SML_NO_ERROR) return SML_ERRORCLASS_SUCCESS; return (int)((*error)->type / 100); } /*@}*/ libsyncml-0.5.4/libsyncml/sml_elements.h100644 1750 1750 7735 11211710410 20271 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2005 Armin Bauer * Copyright (C) 2007-2009 Michael Bell * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ /** * @defgroup SmlElements SyncML Elements * @ingroup PublicLowLevelAPI * @brief The public part * */ /*@{*/ #ifndef _SML_ELEMENTS_H_ #define _SML_ELEMENTS_H_ SmlLocation *smlLocationNew (const char *locURI, const char *locName, SmlError **error); SmlLocation *smlLocationRef (SmlLocation *loc); void smlLocationUnref (SmlLocation *loc); const char *smlLocationGetURI (SmlLocation *loc); const char *smlLocationGetName (SmlLocation *loc); void smlLocationSetName(SmlLocation *loc, const char *name); void smlLocationCopy (SmlLocation *source, SmlLocation *target); SmlLocation *smlLocationClone (SmlLocation *source, SmlError **error); SmlBool smlLocationCompare (SmlLocation *objectroot, SmlLocation *object, SmlLocation *urlroot, SmlLocation *url); SmlBool smlLocationIsRelative (SmlLocation *location); SmlCred *smlCredNewFromString(const char *type, const char *format, const char *data, SmlError **error); SmlCred *smlCredNewAuth(SmlAuthType type, const char *username, const char *password, SmlError **error); SmlCred *smlCredNew(SmlAuthType type, SmlFormatType format, const char *data, const char*username, SmlError **error); void smlCredRef(SmlCred *cred); void smlCredUnref(SmlCred *cred); void smlCredFree(SmlCred *cred) LIBSYNCML_DEPRECATED; /* expire date: 20090120 */ SmlAnchor *smlAnchorNew(const char *last, const char *next, SmlError **error); void smlAnchorFree(SmlAnchor *anchor); SmlItem *smlItemNew(unsigned int size, SmlError **error); SmlItem *smlItemNewForData(const char *data, unsigned int size, SmlError **error); SmlItem *smlItemRef(SmlItem *item); void smlItemUnref(SmlItem *item); SmlBool smlItemAddData(SmlItem *item, const char *data, unsigned int size, SmlError **error); SmlBool smlItemCheck(SmlItem *item); SmlBool smlItemHasData(SmlItem *item); SmlBool smlItemGetData(SmlItem *item, char **data, unsigned int *size, SmlError **error); SmlBool smlItemStealData(SmlItem *item, char **data, unsigned int *size, SmlError **error); void smlItemSetSource(SmlItem *item, SmlLocation *source); SmlLocation *smlItemGetSource(SmlItem *item); void smlItemSetTarget(SmlItem *item, SmlLocation *target); SmlLocation *smlItemGetTarget(SmlItem *item); void smlItemSetSourceParent(SmlItem *item, SmlLocation *sourceParent); SmlLocation *smlItemGetSourceParent(SmlItem *item); void smlItemSetTargetParent(SmlItem *item, SmlLocation *targeParent); SmlLocation *smlItemGetTargetParent(SmlItem *item); void smlItemSetRaw(SmlItem *item, SmlBool raw); void smlHeaderFree(SmlHeader *header); SmlChal *smlChalNew(SmlAuthType type, SmlError **error); SmlChal *smlChalNewFromBinary(SmlAuthType type, const char *nonce, size_t length, SmlError **error); SmlChal *smlChalNewFromBase64(SmlAuthType type, const char *nonce, SmlError **error); void smlChalRef(SmlChal *chal); void smlChalUnref(SmlChal *chal); void smlChalFree(SmlChal *chal) LIBSYNCML_DEPRECATED; /* expire date: 20090417 */ SmlMapItem *smlMapItemNew(const char *uid, const char *newuid, SmlError **error); SmlMapItem *smlMapItemRef(SmlMapItem *item); void smlMapItemUnref(SmlMapItem *item); #endif //_SML_ELEMENTS_H_ /*@}*/ libsyncml-0.5.4/libsyncml/sml_support.c100644 1750 1750 41003 11211710410 20166 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2005 Armin Bauer * Copyright (C) 2007-2008 Michael Bell * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include "syncml.h" #include "syncml_internals.h" #include "sml_support.h" #include "sml_error_internals.h" #include "config.h" #include #include #include #include #include #include GPrivate* current_tabs = NULL; GPrivate* thread_id = NULL; #define G_ERRORCHECK_MUTEXES static const char* smlCheckDebugDirectory(const char *env) { const char *dirname = g_getenv(env); if (!dirname) return NULL; if (!g_file_test(dirname, G_FILE_TEST_EXISTS)) { if (g_mkdir_with_parents(dirname, 0700) != 0) { g_warning("The debug directory %s cannot be created.", dirname); return NULL; } } if (!g_file_test(dirname, G_FILE_TEST_IS_DIR)) { g_warning("The debug directory %s is not a directory.", dirname); return NULL; } return dirname; } /** * @defgroup SmlDebugPrivate SyncML Debug * @ingroup PrivateLowLevelAPI * @brief Debug functions used by libsyncml * */ /*@{*/ void smlLog(const char *logname, const char *data, unsigned int size) { #if defined ENABLE_TRACE const char *trace; if (!(trace = smlCheckDebugDirectory("SYNCML_LOG"))) return; int i = 0; char *logfile = NULL; for (;;i = i + 1) { char *logfile_tmp = g_strdup_printf("%s/%s", trace, logname); logfile = g_strdup_printf(logfile_tmp, i); smlSafeCFree(&logfile_tmp); if (!g_file_test(logfile, G_FILE_TEST_EXISTS)) break; smlSafeCFree(&logfile); } GError *error = NULL; GIOChannel *chan = g_io_channel_new_file(logfile, "w", &error); if (!chan) { printf("unable to open %s for writing: %s\n", logfile, error->message); return; } gsize writen; g_io_channel_set_encoding(chan, NULL, NULL); if (g_io_channel_write_chars(chan, data, size, &writen, NULL) != G_IO_STATUS_NORMAL) { printf("unable to write trace to %s\n", logfile); } else g_io_channel_flush(chan, NULL); g_io_channel_shutdown(chan, TRUE, NULL); g_io_channel_unref(chan); #endif } /*! @brief Used for tracing the application * * use this function to trace calls. The call graph will be saved into * the file that is given in the SYNCML_TRACE environment variable * * @param type The type of the trace * @param message The message to save * */ void smlTrace(SmlTraceType type, const char *message, ...) { #if defined ENABLE_TRACE const char *trace; if (!(trace = smlCheckDebugDirectory("SYNCML_TRACE"))) return; if (!g_thread_supported ()) g_thread_init (NULL); int tabs = 0; if (!current_tabs) current_tabs = g_private_new (NULL); else tabs = GPOINTER_TO_INT(g_private_get(current_tabs)); unsigned long int id; pid_t pid; const char *endline; #ifdef _WIN32 #ifdef PTW32_VERSION id = (unsigned long int)pthread_self().p; #else if (!thread_id) thread_id = g_private_new (NULL); id = GPOINTER_TO_INT(thread_id); #endif pid = _getpid(); endline = "\r\n"; #else id = (unsigned long int)pthread_self(); pid = getpid(); endline = "\n"; #endif char *logfile = g_strdup_printf("%s/Thread%lu-%d.log", trace, id, pid); // create message va_list arglist; char *buffer = NULL; va_start(arglist, message); buffer = g_strdup_vprintf(message, arglist); va_end(arglist); // filter message if necessary const char *filter = g_getenv("SYNCML_TRACE_FILTER"); if (filter) { gchar** filters = g_strsplit(filter, ",", 0); gint i; SmlBool matched = FALSE; for (i=0; filters[i] != NULL && !matched ; i++) { if (strstr(buffer, filters[i])) matched = TRUE; } g_strfreev(filters); if (!matched) { smlSafeCFree(&buffer); return; } } GString *tabstr = g_string_new(""); long i = 0; for (i = 0; i < tabs; i++) { tabstr = g_string_append(tabstr, "\t"); } GTimeVal curtime; g_get_current_time(&curtime); char *logmessage = NULL; switch (type) { case TRACE_ENTRY: logmessage = g_strdup_printf("[%li.%06li]\t%s>>>>>>> %s%s", curtime.tv_sec, curtime.tv_usec, tabstr->str, buffer, endline); tabs++; break; case TRACE_INTERNAL: logmessage = g_strdup_printf("[%li.%06li]\t%s%s%s", curtime.tv_sec, curtime.tv_usec, tabstr->str, buffer, endline); break; case TRACE_ERROR: logmessage = g_strdup_printf("[%li.%06li]\t%sERROR: %s%s", curtime.tv_sec, curtime.tv_usec, tabstr->str, buffer, endline); break; case TRACE_EXIT: logmessage = g_strdup_printf("[%li.%06li]%s<<<<<<< %s%s", curtime.tv_sec, curtime.tv_usec, tabstr->str, buffer, endline); tabs--; if (tabs < 0) tabs = 0; break; case TRACE_EXIT_ERROR: logmessage = g_strdup_printf("[%li.%06li]%s<--- ERROR --- %s%s", curtime.tv_sec, curtime.tv_usec, tabstr->str, buffer, endline); tabs--; if (tabs < 0) tabs = 0; break; } smlSafeCFree(&buffer); g_private_set(current_tabs, GINT_TO_POINTER(tabs)); g_string_free(tabstr, TRUE); GError *error = NULL; GIOChannel *chan = g_io_channel_new_file(logfile, "a", &error); if (!chan) { printf("unable to open %s for writing: %s%s", logfile, error->message, endline); smlSafeCFree(&logfile); smlSafeCFree(&logmessage); return; } gsize writen; g_io_channel_set_encoding(chan, NULL, NULL); if (g_io_channel_write_chars(chan, logmessage, strlen(logmessage), &writen, NULL) != G_IO_STATUS_NORMAL) { printf("unable to write trace to %s%s", logfile, endline); } else g_io_channel_flush(chan, NULL); g_io_channel_shutdown(chan, TRUE, NULL); g_io_channel_unref(chan); smlSafeCFree(&logmessage); smlSafeCFree(&logfile); #endif } /*! @brief Used for printing binary data * * Unprintable character will be printed in hex, printable are just printed * * @param data The data to print * @param len The length to print * */ char *smlPrintBinary(const char *data, int len) { int t; GString *str = g_string_new(""); for (t = 0; t < len; t++) { if (data[t] >= ' ' && data[t] <= 'z') g_string_append_c(str, data[t]); else g_string_append_printf(str, " %02x ", (unsigned char) data[t]); } return g_string_free(str, FALSE); } /*! @brief Used for printing binary data in just hex * * @param data The data to print * @param len The length to print * */ char *smlPrintHex(const char *data, int len) { int t; GString *str = g_string_new(""); for (t = 0; t < len; t++) { g_string_append_printf(str, " %02x", (unsigned char) data[t]); if (data[t] >= ' ' && data[t] <= 'z') g_string_append_printf(str, "(%c)", data[t]); g_string_append_c(str, ' '); } return g_string_free(str, FALSE); } /*@}*/ /* End of debug API */ /** * @defgroup SmlSupportPrivate SyncML Support * @ingroup PrivateLowLevelAPI * @brief Support functions used by libsyncml * */ /*@{*/ /*! @brief Creates a random string * * Creates a random string of given length or less * * @param maxlength The maximum length of the string * @returns The random string * */ char *smlRandStr(int maxlength, SmlBool exact) { const char *randchars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIKLMNOPQRSTUVWXYZ1234567890"; int length; char *retchar; int i = 0; if (exact) length = maxlength; else length = g_random_int_range(1, maxlength + 1); retchar = malloc(length * sizeof(char) + 1); retchar[0] = 0; for (i = 0; i < length; i++) { retchar[i] = randchars[g_random_int_range(0, strlen(randchars))]; retchar[i + 1] = 0; } return retchar; } /*! @brief Safely mallocs * * Mallocs or returns an error if OOM * * @param n_bytes The size in bytes to malloc * @param error Pointer to a error struct * @returns The newly allocated memory or NULL in case of error * */ void *smlTryMalloc0(long n_bytes, SmlError **error) { CHECK_ERROR_REF void *result = g_try_malloc(n_bytes); if (!result) { /* set error */ char *msg = NULL; if (n_bytes > 0) msg = g_strdup_printf("No memory left (needed %ld).", n_bytes); else msg = g_strdup_printf("Malloc of zero bytes requested."); /* publish error */ if (error == NULL) g_error("%s", msg); else smlErrorSet(error, SML_ERROR_INTERNAL_NO_MEMORY, "%s", msg); return NULL; } memset(result, 0, n_bytes); return result; } /*! @brief Gets the version of libsyncml as string * * @returns The version as const string * */ const char *smlGetVersion(void) { /** * @version $Id$ */ return "$Id$"; } SmlThread *smlThreadNew(GMainContext *context, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p)", __func__, context, error); CHECK_ERROR_REF /* Never ever run on the default context because a library * thread should never influence the behavior of an user * application and should never be influence by an user * application. * * This is highly critical especially if the user application * user the default context to loop on smlDsSessionDispatch * and smlManagerDispatch. */ smlAssert(context); SmlThread *thread = smlTryMalloc0(sizeof(SmlThread), error); if (!thread) goto error; if (!g_thread_supported ()) g_thread_init (NULL); if (!g_thread_supported ()) { smlErrorSet(error, SML_ERROR_INTERNAL_MISCONFIGURATION, "Threads are not supported."); goto error; } thread->started = FALSE; thread->started_mutex = g_mutex_new(); thread->started_cond = g_cond_new(); thread->context = context; g_main_context_ref(thread->context); thread->loop = g_main_loop_new(thread->context, FALSE); smlTrace(TRACE_EXIT, "%s: %p", __func__, thread); return thread; error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return NULL; } void smlThreadFree(SmlThread *thread) { smlTrace(TRACE_ENTRY, "%s(%p)", __func__, thread); smlAssert(thread); if (thread->started_mutex) g_mutex_free(thread->started_mutex); if (thread->started_cond) g_cond_free(thread->started_cond); if (thread->loop) g_main_loop_unref(thread->loop); if (thread->context) g_main_context_unref(thread->context); smlSafeFree((gpointer *)&thread); smlTrace(TRACE_EXIT, "%s", __func__); } static gpointer smlThreadStartCallback(gpointer data) { smlTrace(TRACE_ENTRY, "%s(%p)", __func__, data); SmlThread *thread = data; smlTrace(TRACE_INTERNAL, "%s: +++++++++ This is the worker thread of thread %p for context %p +++++++++", __func__, thread, thread->context); smlTrace(TRACE_INTERNAL, "%s: locking", __func__); g_mutex_lock(thread->started_mutex); thread->started = TRUE; smlTrace(TRACE_INTERNAL, "%s: sending condition", __func__); g_cond_signal(thread->started_cond); smlTrace(TRACE_INTERNAL, "%s: unlocking", __func__); g_mutex_unlock(thread->started_mutex); /* check main context ownership */ if (!g_main_context_acquire(thread->context)) { smlAssertMsg(FALSE, "This thread is not the owner of the GMainContext."); } else { smlTrace(TRACE_INTERNAL, "%s: Thread is owner of the GMainContext.", __func__); } g_main_loop_run(thread->loop); /* release context ownership / decrement reference counter */ g_main_context_release(thread->context); smlTrace(TRACE_EXIT, "%s", __func__); return FALSE; } static gboolean smlThreadStopCallback(gpointer data) { smlTrace(TRACE_ENTRY, "%s(%p)", __func__, data); SmlThread *thread = data; smlTrace(TRACE_INTERNAL, "%s: +++++++++ Quitting worker thread +++++++++", __func__); g_main_loop_quit(thread->loop); smlTrace(TRACE_EXIT, "%s", __func__); return FALSE; } void smlThreadStart(SmlThread *thread) { smlTrace(TRACE_ENTRY, "%s(%p)", __func__, thread); smlAssert(thread); //Start the thread smlTrace(TRACE_INTERNAL, "%s: locking", __func__); g_mutex_lock(thread->started_mutex); smlTrace(TRACE_INTERNAL, "%s: creating thread", __func__); thread->thread = g_thread_create (smlThreadStartCallback, thread, TRUE, NULL); smlAssert(thread->thread); smlTrace(TRACE_INTERNAL, "%s: waiting for start", __func__); while(!thread->started) { smlTrace(TRACE_INTERNAL, "%s: checking condition", __func__); g_cond_wait(thread->started_cond, thread->started_mutex); } smlTrace(TRACE_INTERNAL, "%s: condition received", __func__); g_mutex_unlock(thread->started_mutex); smlTrace(TRACE_EXIT, "%s", __func__); } void smlThreadStop(SmlThread *thread) { smlTrace(TRACE_ENTRY, "%s(%p)", __func__, thread); smlAssert(thread); GSource *source = g_idle_source_new(); g_source_set_callback(source, smlThreadStopCallback, thread, NULL); g_source_attach(source, thread->context); g_thread_join(thread->thread); thread->thread = NULL; g_source_unref(source); smlTrace(TRACE_EXIT, "%s", __func__); } /** * This context is used to cache the environment for direct function * calls within a special thread. * Please see smlThreadCallFunction for more details. */ typedef struct SmlThreadFunctionContext { GMutex *mutex; GCond *cond; SmlThreadCallFunctionType func; gpointer data; SmlBool result; SmlError **error; } SmlThreadFunctionContext; /** * This callback is used to call a function within a special thread. * Please see smlThreadCallFunction for more details. */ gboolean smlThreadCallFunctionCallback(gpointer data) { smlTrace(TRACE_ENTRY, "%s(%p)", __func__, data); smlAssert(data); SmlThreadFunctionContext *ctx = data; ctx->result = ctx->func(ctx->data, ctx->error); g_mutex_lock(ctx->mutex); g_cond_signal(ctx->cond); g_mutex_unlock(ctx->mutex); /* This function should only run once. */ smlTrace(TRACE_EXIT, "%s", __func__); return FALSE; } /** * This function can be used to execute a function in a special thread. * Some libraries are designed for single-threaded applications. * They require that a set of commands is only executed in one thread. * These applications use g_main_loop too. So the functions must be * executed in this loop. This will be done synchronously by this * function. * * Please note: This function is blocking. * Please note: The glib source priority is IDLE. */ SmlBool smlThreadCallFunction( SmlThread *thread, SmlThreadCallFunctionType func, gpointer data, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p => %p, %p, %p, %p)", __func__, thread, thread?thread->context:NULL, func, data, error); CHECK_ERROR_REF smlAssert(func); /* initialize function context */ smlTrace(TRACE_INTERNAL, "%s: preparing context", __func__); SmlThreadFunctionContext *ctx; ctx = smlTryMalloc0(sizeof(SmlThreadFunctionContext), error); if (!ctx) goto error; ctx->mutex = g_mutex_new(); if (!ctx->mutex) { smlErrorSet(error, SML_ERROR_GENERIC, "Cannot create new mutex."); goto error; } ctx->cond = g_cond_new(); if (!ctx->cond) { smlErrorSet(error, SML_ERROR_GENERIC, "Cannot create new condition."); goto error; } ctx->func = func; ctx->data = data; ctx->error = error; /* prepare glib source */ smlTrace(TRACE_INTERNAL, "%s: preparing source", __func__); GSource *source = g_idle_source_new(); g_source_set_callback(source, smlThreadCallFunctionCallback, ctx, NULL); /* call function "synchronously" */ g_mutex_lock(ctx->mutex); smlTrace(TRACE_INTERNAL, "%s: attach source", __func__); g_source_attach(source, thread->context); smlTrace(TRACE_INTERNAL, "%s: wait for condition", __func__); g_cond_wait(ctx->cond, ctx->mutex); smlTrace(TRACE_INTERNAL, "%s: get condition", __func__); g_mutex_unlock(ctx->mutex); /* cleanup */ smlTrace(TRACE_INTERNAL, "%s: cleanup", __func__); SmlBool result = ctx->result; g_source_unref(source); g_mutex_free(ctx->mutex); g_cond_free(ctx->cond); smlSafeFree((gpointer *) &ctx); /* return result */ smlTrace(TRACE_EXIT, "%s - %i", __func__, result); return result; error: if (ctx->cond) g_cond_free(ctx->cond); if (ctx->mutex) g_mutex_free(ctx->mutex); if (ctx) smlSafeFree((gpointer *) &ctx); smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(error)); return FALSE; } void smlSafeFree(gpointer *address) { smlAssert(address); smlAssert(*address); g_free(*address); *address = NULL; } void smlSafeCFree(char **address) { smlSafeFree((gpointer *)address); } const char *smlGetLibraryVersion() { return PACKAGE_VERSION; } const char *smlGetLibrarySoName() { return PACKAGE_SONAME; } /*@}*/ libsyncml-0.5.4/libsyncml/sml_defines.h100644 1750 1750 26540 11211710410 20105 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2005 Armin Bauer * Copyright (C) 2007-2009 Michael Bell * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ /** * @defgroup SmlDefines SyncML Defines * @ingroup PublicLowLevelAPI * @brief The public part * */ /*@{*/ #ifndef _SML_DEFINES_H #define _SML_DEFINES_H #define SML_ELEMENT_SYNCML "SyncML" #define SML_ELEMENT_SYNCHDR "SyncHdr" #define SML_ELEMENT_SYNCBODY "SyncBody" #define SML_ELEMENT_VERPROTO "VerProto" #define SML_ELEMENT_VERDTD "VerDTD" #define SML_ELEMENT_MSGID "MsgID" #define SML_ELEMENT_SESSIONID "SessionID" #define SML_ELEMENT_TARGET "Target" #define SML_ELEMENT_SOURCE "Source" #define SML_ELEMENT_SOURCE_PARENT "SourceParent" #define SML_ELEMENT_TARGET_PARENT "TargetParent" #define SML_ELEMENT_LOCURI "LocURI" #define SML_ELEMENT_LOCNAME "LocName" #define SML_ELEMENT_RESPURI "RespURI" #define SML_ELEMENT_NORESP "NoResp" #define SML_ELEMENT_SYNC "Sync" #define SML_ELEMENT_STATUS "Status" #define SML_ELEMENT_CMDID "CmdID" #define SML_ELEMENT_MSGREF "MsgRef" #define SML_ELEMENT_CMDREF "CmdRef" #define SML_ELEMENT_CMD "Cmd" #define SML_ELEMENT_ANCHOR "Anchor" #define SML_ELEMENT_NEXT "Next" #define SML_ELEMENT_LAST "Last" #define SML_ELEMENT_ALERT "Alert" #define SML_ELEMENT_PUT "Put" #define SML_ELEMENT_GET "Get" #define SML_ELEMENT_SEQUENCE "Sequence" #define SML_ELEMENT_ATOMIC "Atomic" #define SML_ELEMENT_FINAL "Final" #define SML_ELEMENT_DATA "Data" #define SML_ELEMENT_ITEM "Item" #define SML_ELEMENT_META "Meta" #define SML_ELEMENT_MAXMSGSIZE "MaxMsgSize" #define SML_ELEMENT_TYPE "Type" #define SML_ELEMENT_SOURCEREF "SourceRef" #define SML_ELEMENT_TARGETREF "TargetRef" #define SML_ELEMENT_NUMBEROFCHANGES "NumberOfChanges" #define SML_ELEMENT_ADD "Add" #define SML_ELEMENT_REPLACE "Replace" #define SML_ELEMENT_DELETE "Delete" #define SML_ELEMENT_MAP "Map" #define SML_ELEMENT_MAPITEM "MapItem" #define SML_ELEMENT_FORMAT "Format" #define SML_ELEMENT_CRED "Cred" #define SML_ELEMENT_CHAL "Chal" #define SML_ELEMENT_RESULTS "Results" #define SML_ELEMENT_MAXOBJSIZE "MaxObjSize" #define SML_ELEMENT_EMI "EMI" #define SML_ELEMENT_MOREDATA "MoreData" #define SML_ELEMENT_MEM "Mem" #define SML_ELEMENT_FREEID "FreeID" #define SML_ELEMENT_VERSION "Version" #define SML_ELEMENT_NEXTNONCE "NextNonce" /* For devinf */ #define SML_ELEMENT_CTCAP "CTCap" #define SML_ELEMENT_CTTYPE "CTType" #define SML_ELEMENT_DATASTORE "DataStore" #define SML_ELEMENT_DATATYPE "DataType" #define SML_ELEMENT_DEVID "DevID" #define SML_ELEMENT_DEVINF "DevInf" #define SML_ELEMENT_DEVTYPE "DevTyp" #define SML_ELEMENT_DISPLAYNAME "DisplayName" #define SML_ELEMENT_DSMEM "DSMem" #define SML_ELEMENT_EXT "Ext" #define SML_ELEMENT_FWV "FwV" #define SML_ELEMENT_HWV "HwV" #define SML_ELEMENT_MAN "Man" #define SML_ELEMENT_MAXGUIDSIZE "MaxGUIDSize" #define SML_ELEMENT_MAXID "MaxID" #define SML_ELEMENT_MAXMEM "MaxMem" #define SML_ELEMENT_MAXOCCUR "MaxOccur" #define SML_ELEMENT_MAXSIZE "MaxSize" #define SML_ELEMENT_MOD "Mod" #define SML_ELEMENT_NOTRUNCATE "NoTruncate" #define SML_ELEMENT_OEM "OEM" #define SML_ELEMENT_PARAMNAME "ParamName" #define SML_ELEMENT_PROPERTY "Property" #define SML_ELEMENT_PROPNAME "PropName" #define SML_ELEMENT_PROPPARAM "PropParam" #define SML_ELEMENT_RX "Rx" #define SML_ELEMENT_RXPREF "Rx-Pref" #define SML_ELEMENT_SHAREDMEM "SharedMem" #define SML_ELEMENT_SIZE "Size" #define SML_ELEMENT_SUPPORTLARGEOBJS "SupportLargeObjs" #define SML_ELEMENT_SUPPORTNUMBEROFCHANGES "SupportNumberOfChanges" #define SML_ELEMENT_SUPPORT_HIERARCHICAL_SYNC "SupportHierarchicalSync" #define SML_ELEMENT_SWV "SwV" #define SML_ELEMENT_SYNCCAP "SyncCap" #define SML_ELEMENT_SYNCTYPE "SyncType" #define SML_ELEMENT_TX "Tx" #define SML_ELEMENT_TXPREF "Tx-Pref" #define SML_ELEMENT_UTC "UTC" #define SML_ELEMENT_VALENUM "ValEnum" #define SML_ELEMENT_VERCT "VerCT" #define SML_ELEMENT_XNAM "XNam" #define SML_ELEMENT_XVAL "XVal" /* For metinf */ #define SML_ELEMENT_MARK "Mark" #define SML_ELEMENT_DATATYPE_CHR "chr" #define SML_ELEMENT_DATATYPE_INT "int" #define SML_ELEMENT_DATATYPE_BOOL "bool" #define SML_ELEMENT_DATATYPE_BIN "bin" #define SML_ELEMENT_DATATYPE_DATE "datetime" #define SML_ELEMENT_DATATYPE_PHONE "phonenum" #define SML_ELEMENT_DEVTYP_PAGER "pager" #define SML_ELEMENT_DEVTYP_HANDHELD "handheld" #define SML_ELEMENT_DEVTYP_PDA "pda" #define SML_ELEMENT_DEVTYP_PHONE "phone" #define SML_ELEMENT_DEVTYP_SMARTPHONE "smartphone" #define SML_ELEMENT_DEVTYP_SERVER "server" #define SML_ELEMENT_DEVTYP_WORKSTATION "workstation" typedef enum { SML_DEVINF_DATATYPE_UNKNOWN, SML_DEVINF_DATATYPE_CHR, SML_DEVINF_DATATYPE_INT, SML_DEVINF_DATATYPE_BOOL, SML_DEVINF_DATATYPE_BIN, SML_DEVINF_DATATYPE_DATE, SML_DEVINF_DATATYPE_PHONE } SmlDevInfDataType; typedef enum { SML_DEVINF_DEVTYPE_UNKNOWN, SML_DEVINF_DEVTYPE_PAGER, SML_DEVINF_DEVTYPE_HANDHELD, SML_DEVINF_DEVTYPE_PDA, SML_DEVINF_DEVTYPE_PHONE, SML_DEVINF_DEVTYPE_SMARTPHONE, SML_DEVINF_DEVTYPE_SERVER, SML_DEVINF_DEVTYPE_WORKSTATION } SmlDevInfDevTyp; typedef enum { SML_DEVINF_SYNCTYPE_UNKNOWN = 0, SML_DEVINF_SYNCTYPE_TWO_WAY = 1, SML_DEVINF_SYNCTYPE_SLOW_SYNC = 1 << 1, SML_DEVINF_SYNCTYPE_ONE_WAY_FROM_CLIENT = 1 << 2, SML_DEVINF_SYNCTYPE_REFRESH_FROM_CLIENT = 1 << 3, SML_DEVINF_SYNCTYPE_ONE_WAY_FROM_SERVER = 1 << 4, SML_DEVINF_SYNCTYPE_REFRESH_FROM_SERVER = 1 << 5, SML_DEVINF_SYNCTYPE_SERVER_ALERTED_SYNC = 1 << 6 } SmlDevInfSyncCap; typedef enum { SML_DEVINF_CTCAP_UNKNOWN, SML_DEVINF_CTCAP_CTTYPE, SML_DEVINF_CTCAP_PROPNAME, SML_DEVINF_CTCAP_VALENUM, SML_DEVINF_CTCAP_DATATYPE, SML_DEVINF_CTCAP_SIZE, SML_DEVINF_CTCAP_DISPLAYNAME, SML_DEVINF_CTCAP_PARAMNAME, SML_DEVINF_CTCAP_VERCT, SML_DEVINF_CTCAP_PROPERTY, SML_DEVINF_CTCAP_PROPPARAM, SML_DEVINF_CTCAP_NOTRUNCATE, SML_DEVINF_CTCAP_MAXOCCUR, SML_DEVINF_CTCAP_MAXSIZE } SmlDevInfCTCapType; #define SML_ELEMENT_TEXT_VCARD "text/x-vcard" #define SML_ELEMENT_TEXT_VCARD_30 "text/vcard" #define SML_ELEMENT_TEXT_VCAL "text/x-vcalendar" #define SML_ELEMENT_TEXT_ICAL "text/calendar" #define SML_ELEMENT_TEXT_PLAIN "text/plain" #define SML_ELEMENT_TEXT_MESSAGE "text/x-vMessage" #define SML_ELEMENT_DEVINF_XML "application/vnd.syncml-devinf+xml" #define SML_ELEMENT_WBXML "application/vnd.syncml+wbxml" #define SML_ELEMENT_XML "application/vnd.syncml+xml" #define SML_ELEMENT_SAN "application/vnd.syncml.ds.notification" #define SML_ELEMENT_APPLICATION_OMA_DS_EMAIL "application/vnd.omads-email+xml" #define SML_ELEMENT_APPLICATION_OMA_DS_FILE "application/vnd.omads-file+xml" #define SML_ELEMENT_APPLICATION_OMA_DS_FOLDER "application/vnd.omads-folder+xml" #define SML_NAMESPACE_METINF "syncml:metinf" #define SML_NAMESPACE_DEVINF "syncml:devinf" #define SML_NAMESPACE_SYNCML10 "SYNCML:SYNCML1.0" #define SML_NAMESPACE_SYNCML11 "SYNCML:SYNCML1.1" #define SML_NAMESPACE_SYNCML12 "SYNCML:SYNCML1.2" #define SML_VERSION_STRING_10 "SyncML/1.0" #define SML_VERSION_STRING_11 "SyncML/1.1" #define SML_VERSION_STRING_12 "SyncML/1.2" #define SML_AUTH_BASIC "syncml:auth-basic" #define SML_AUTH_MD5 "syncml:auth-md5" #define SML_BASE64 "b64" /* Transport configuration defines */ #define SML_TRANSPORT_CONFIG_PROXY "PROXY" #define SML_TRANSPORT_CONFIG_USERNAME "USERNAME" #define SML_TRANSPORT_CONFIG_PASSWORD "PASSWORD" #define SML_TRANSPORT_CONFIG_SSL_CA_FILE "SSL_CA_FILE" #define SML_TRANSPORT_CONFIG_PORT "PORT" #define SML_TRANSPORT_CONFIG_URL "URL" #define SML_TRANSPORT_CONFIG_SSL_KEY "SSL_KEY" #define SML_TRANSPORT_CONFIG_SSL_SERVER_CERT "SSL_SERVER_CERT" #define SML_TRANSPORT_CONFIG_BLUETOOTH_ADDRESS "BLUETOOTH_ADDRESS" #define SML_TRANSPORT_CONFIG_BLUETOOTH_CHANNEL "BLUETOOTH_CHANNEL" #define SML_TRANSPORT_CONFIG_IRDA_SERVICE "IRDA_SERVICE" #define SML_TRANSPORT_CONFIG_AT_COMMAND "AT_COMMAND" #define SML_TRANSPORT_CONFIG_AT_MANUFACTURER "AT_MANUFACTURER" #define SML_TRANSPORT_CONFIG_AT_MODEL "AT_MODEL" #define SML_TRANSPORT_CONFIG_DATASTORE "DATASTORE" #define SML_TRANSPORT_CONFIG_DATASTORE_EVENT "EVENT" #define SML_TRANSPORT_CONFIG_DATASTORE_TODO "TODO" #define SML_TRANSPORT_CONFIG_DATASTORE_CONTACT "CONTACT" #define SML_TRANSPORT_CONFIG_DATASTORE_NOTE "NOTE" /* Enumeration types */ typedef enum { SML_DEVINF_VERSION_UNKNOWN = 0, SML_DEVINF_VERSION_10 = 1, SML_DEVINF_VERSION_11 = 2, SML_DEVINF_VERSION_12 = 3 } SmlDevInfVersion; typedef enum { SML_MIMETYPE_UNKNOWN, SML_MIMETYPE_XML, SML_MIMETYPE_WBXML, SML_MIMETYPE_SAN } SmlMimeType; typedef enum { SML_TRANSPORT_HTTP_SERVER, SML_TRANSPORT_HTTP_CLIENT, SML_TRANSPORT_OBEX_CLIENT, SML_TRANSPORT_OBEX_SERVER } SmlTransportType; typedef enum { SML_RESULT_OK, SML_RESULT_RETRY, SML_RESULT_FATAL } SmlTransportResult; typedef enum { SML_VERSION_UNKNOWN = 0, SML_VERSION_10 = 1, SML_VERSION_11 = 2, SML_VERSION_12 = 3 } SmlProtocolVersion; typedef enum { SML_PROTOCOL_UNKNOWN = 0, SML_PROTOCOL_SYNCML = 1, SML_PROTOCOL_DM = 2 } SmlProtocolType; typedef enum { SML_COMMAND_TYPE_UNKNOWN = 0, SML_COMMAND_TYPE_ALERT = 1, SML_COMMAND_TYPE_SYNC = 2, SML_COMMAND_TYPE_PUT = 3, SML_COMMAND_TYPE_HEADER = 4, SML_COMMAND_TYPE_ADD = 5, SML_COMMAND_TYPE_REPLACE = 6, SML_COMMAND_TYPE_DELETE = 7, SML_COMMAND_TYPE_MAP = 8, SML_COMMAND_TYPE_GET = 9, SML_COMMAND_TYPE_RESULTS = 10 } SmlCommandType; typedef enum { SML_ALERT_UNKNOWN = 0, SML_ALERT_DISPLAY = 100, SML_ALERT_TWO_WAY = 200, SML_ALERT_SLOW_SYNC = 201, SML_ALERT_ONE_WAY_FROM_CLIENT = 202, SML_ALERT_REFRESH_FROM_CLIENT = 203, SML_ALERT_ONE_WAY_FROM_SERVER = 204, SML_ALERT_REFRESH_FROM_SERVER = 205, SML_ALERT_TWO_WAY_BY_SERVER = 206, SML_ALERT_ONE_WAY_FROM_CLIENT_BY_SERVER = 207, SML_ALERT_REFRESH_FROM_CLIENT_BY_SERVER = 208, SML_ALERT_ONE_WAY_FROM_SERVER_BY_SERVER = 209, SML_ALERT_REFRESH_FROM_SERVER_BY_SERVER = 210, SML_ALERT_RESULT = 221, SML_ALERT_NEXT_MESSAGE = 222, SML_ALERT_NO_END_OF_DATA = 223 } SmlAlertType; typedef enum { SML_CHANGE_UNKNOWN = 0, SML_CHANGE_ADD = 1, SML_CHANGE_REPLACE = 2, SML_CHANGE_DELETE = 3 } SmlChangeType; typedef enum { SML_AUTH_TYPE_UNKNOWN = 0, SML_AUTH_TYPE_BASIC = 1, SML_AUTH_TYPE_MD5 = 2 } SmlAuthType; typedef enum { SML_FORMAT_TYPE_UNKNOWN = 0, SML_FORMAT_TYPE_BASE64 = 1 } SmlFormatType; typedef enum { SML_DS_UNKNOWN_TYPE = 0, SML_DS_SERVER = 1, SML_DS_CLIENT = 2 } SmlDsServerType; #if __GNUC__ - 0 > 3 || (__GNUC__ - 0 == 3 && __GNUC_MINOR__ - 0 >= 2) /* gcc >= 3.2 */ # define LIBSYNCML_DEPRECATED __attribute__ ((deprecated)) #elif defined(_MSC_VER) && (_MSC_VER >= 1300) && (_MSC_VER < 1400) /* msvc >= 7 */ # define LIBSYNCML_DEPRECATED __declspec(deprecated) #elif defined(_MSV_VER) && (_MSC_VER >= 1400) /* MS Visual Studio 2005 */ # define LIBSYNCML_DEPRECATED #else # define LIBSYNCML_DEPRECATED #endif #endif //_SML_DEFINES_H /*@}*/ libsyncml-0.5.4/libsyncml/sml_session.c100644 1750 1750 243326 11211710410 20171 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2005 Armin Bauer * Copyright (C) 2007-2008 Michael Bell * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include "syncml.h" #include "syncml_internals.h" #include "sml_error_internals.h" #include "sml_queue_internals.h" #include "sml_session_internals.h" #include "sml_command_internals.h" #include "sml_elements_internals.h" #include "sml_parse_internals.h" #include "sml_transport_internals.h" #include "objects/sml_auth_internals.h" /** * @defgroup SmlSessionPrivate SyncML Session Private API * @ingroup PrivateLowLevelAPI * @brief Private Interfaces to create, manipulate and delete sessions * */ /*@{*/ typedef enum SmlSessionCommandType { SML_SESSION_COMMAND_START, SML_SESSION_COMMAND_END, SML_SESSION_STATUS, SML_SESSION_FLUSH } SmlSessionCommandType; typedef struct SmlSessionCommand { SmlSessionCommandType type; SmlCommand *cmd; SmlCommand *parent; SmlStatus *status; SmlStatusReplyCb callback; void *callbackUserdata; SmlBool final; SmlBool end; } SmlSessionCommand; void smlSessionDispatchEvent(SmlSession *session, SmlSessionEventType type, SmlCommand *cmd, SmlCommand *parent, SmlStatus *headerreply, SmlError *error) { smlTrace(TRACE_ENTRY, "%s(%p, %i, %p, %p, %p, %p)", __func__, session, type, cmd, parent, headerreply, error); smlAssert(session); smlAssert(session->eventCallback); session->eventCallback(session, type, cmd, parent, headerreply, error, session->eventCallbackUserdata); smlTrace(TRACE_EXIT, "%s", __func__); } static void _smlSessionFreePendingReplies(SmlSession *session) { while (session->pendingReplies) { smlSafeFree((gpointer *)&(session->pendingReplies->data)); session->pendingReplies = g_list_delete_link(session->pendingReplies, session->pendingReplies); } } /** @brief Flushes a session * * This flushes the already added statuses and/or commands. Note that if the session * has a size limitation, it will get flushed automatically if the size of the already * added commands exceeds the limit. Use this function if you want for some reason * to flush manually. * * @param session The session to flush * @param final Set to TRUE if you want to have the final flag added. Otherwise it will just flush * the already added statuses and commands * @param error A error struct * @return TRUE if successful, FALSE otherwise * */ static SmlBool _smlSessionFlushInternal(SmlSession *session, SmlBool final, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %i, %p)", __func__, session, final, error); CHECK_ERROR_REF smlAssert(session); smlAssert(session->dataCallback); char *data = NULL; unsigned int size = 0; SmlBool end = FALSE; /* Add the latest header */ if (!smlAssemblerAddHeader(session->assembler, session, error)) goto error; /* Get the data that is waiting in the assembler */ if (!smlAssemblerRun(session->assembler, &data, &size, &end, final, error)) goto error; if (session->authenticate) end = FALSE; /* Flush and reset the command ID counter */ if (session->lastCommandID > 1) { smlAssemblerFlush(session->assembler); } else { session->lastCommandID = smlAssemblerFlush(session->assembler) - 1; } smlTrace(TRACE_INTERNAL, "%s: flushed assembler - last command id is %i now", __func__, session->lastCommandID); SmlTransportData *tspdata = smlTransportDataNew(data, size, session->type, TRUE, error); if (!tspdata) goto error_free_data; data = NULL; if (end && session->sessionType == SML_SESSION_TYPE_SERVER) tspdata->needsAnswer = FALSE; /* Send the flush event */ if (!session->authenticate) smlSessionDispatchEvent(session, SML_SESSION_EVENT_FLUSH, NULL, NULL, NULL, NULL); /* Send the data over the transport */ session->dataCallback(session, tspdata, session->dataCallbackUserdata); smlTransportDataDeref(tspdata); session->waiting = TRUE; if (final) session->sending = FALSE; if (end && session->sessionType == SML_SESSION_TYPE_SERVER) { smlTrace(TRACE_INTERNAL, "%s: Ending session now", __func__); session->end = TRUE; smlSessionRestoreTargetURI(session); g_mutex_lock(session->reportEnd); if (!session->reportedEnd) { /* The end should only be reported once. */ session->reportedEnd = TRUE; smlSessionDispatchEvent(session, SML_SESSION_EVENT_END, NULL, NULL, NULL, NULL); } g_mutex_unlock(session->reportEnd); } smlTrace(TRACE_INTERNAL, "%s: incrementing lastMessageID %d (old)", __func__, session->lastMessageID); session->lastMessageID++; session->hasCommand = FALSE; smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error_free_data: smlSafeCFree(&data); error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return FALSE; } static void _check_reply(SmlSession *session, SmlStatus *status, void *userdata) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, session, status, userdata); smlTrace(TRACE_EXIT, "%s", __func__); } static void _smlSessionFragmentStatus(SmlSession *session, SmlStatus *status, void *userdata) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, session, status, userdata); //SmlError *error = NULL; smlTrace(TRACE_INTERNAL, "%s: Got a status reply %i", __func__, status->type); if (smlStatusGetCode(status) != SML_CHUNK_ACCEPTED) { /* We need to send a error reply for the original command */ smlCommandUnref(session->frag_command); session->frag_command = NULL; } smlTrace(TRACE_EXIT, "%s", __func__); return; /*error: smlSessionDispatchEvent(session, SML_SESSION_EVENT_ERROR, NULL, NULL, NULL, error); smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(&error)); smlErrorDeref(&error); return;*/ } static SmlCommand *_smlSessionFragmentSend(SmlSession *session, SmlCommand *orig_cmd, SmlCommand *parent, unsigned int space, unsigned int start, unsigned int complete_size, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p, %i, %i, %i, %p)", __func__, session, orig_cmd, parent, space, start, complete_size, error); CHECK_ERROR_REF /* This library must not send more that one item per change * command. This is compliant with all specification and only a * self limitation. */ smlAssert(g_list_length(orig_cmd->private.change.items) == 1); SmlCommand *frag_cmd = NULL; char *data = NULL; unsigned int size = 0; SmlItem *orig_item = g_list_nth_data(orig_cmd->private.change.items, 0); if (!smlItemGetData(orig_item, &data, &size, error)) goto error; // FIXME: should we add an assertion here to guarantee // FIXME: that size and complete_size are equal if (space < size - start) { /* We need to create a new command. But we only send as much data as space * is available */ frag_cmd = smlCommandNew(orig_cmd->type, error); if (!frag_cmd) goto error; SmlItem *frag_item = smlItemNewForData(data + start, space, error); if (!frag_item) goto error_free_cmd; frag_cmd->private.change.items = g_list_append (NULL, frag_item); if (!frag_cmd->private.change.items) { smlItemUnref(frag_item); goto error_free_cmd; } frag_item->moreData = TRUE; frag_item->target = orig_item->target; if (frag_item->target) smlLocationRef(frag_item->target); frag_item->source = orig_item->source; if (frag_item->source) smlLocationRef(frag_item->source); frag_item->contenttype = g_strdup(orig_item->contenttype); /* If this is the first sent part of the fragmented command * then this command must include the size of the complete * command. */ if (start == 0) frag_cmd->size = complete_size; session->frag_size += space; } else { /* We have enough room to send the original command. * Nevertheless the original item must be replaced * with a new item which contains the rest of the data. * The original item must be freed. */ /* get original item and cleanup item list */ smlAssert(g_list_length(orig_cmd->private.change.items) == 1); smlAssert(g_list_remove(orig_cmd->private.change.items, orig_item) == NULL); orig_cmd->private.change.items = NULL; /* setup new item */ SmlItem *frag_item = smlItemNewForData(data + start, size - start, error); if (!frag_item) { smlItemUnref(orig_item); goto error; } orig_cmd->private.change.items = g_list_append(NULL, frag_item); if (!orig_cmd->private.change.items) { smlItemUnref(orig_item); smlItemUnref(frag_item); goto error; } /* configure new item */ frag_item->contenttype = g_strdup(orig_item->contenttype); frag_item->target = orig_item->target; if (frag_item->target) smlLocationRef(frag_item->target); frag_item->source = orig_item->source; if (frag_item->source) smlLocationRef(frag_item->source); /* cleanup original item */ smlItemUnref(orig_item); /* setup fragmentation command */ frag_cmd = orig_cmd; session->frag_size += size - start; } smlTrace(TRACE_EXIT, "%s: %p", __func__, frag_cmd); return frag_cmd; error_free_cmd: smlCommandUnref(frag_cmd); error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return NULL; } static SmlAssemblerResult _smlSessionStartCommandInternal(SmlSession *session, SmlCommand *cmd, SmlCommand *parent, SmlStatusReplyCb callback, void *userdata, SmlBool addToCommandStack, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p, %p, %p, %i, %p)", __func__, session, cmd, parent, callback, userdata, addToCommandStack, error); smlAssert(session); smlAssert(cmd); CHECK_ERROR_REF SmlPendingStatus *pending = NULL; SmlBool fragmented = FALSE; if (parent && !session->hasCommand) { GList *c = NULL; SmlCommand *oldcmd = NULL; SmlCommand *oldparent = NULL; GList * cmds = g_list_copy(session->commandStack); for (c = cmds; c; c = c->next) { oldcmd = c->data; if (_smlSessionStartCommandInternal(session, oldcmd, oldparent, _check_reply, NULL, FALSE, error) != SML_ASSEMBLER_RESULT_OK) goto error; oldparent = oldcmd; } g_list_free(cmds); } /* Large object handling. Only possible of the session has a limit and * we dont have a 1.0 session */ if ((cmd->type == SML_COMMAND_TYPE_ADD || cmd->type == SML_COMMAND_TYPE_REPLACE) && smlAssemblerGetRemoteMaxMsgSize(session->assembler) > 0 && session->version != SML_VERSION_10) { smlTrace(TRACE_INTERNAL, "%s: Checking if command needs to be fragmented", __func__); /* This library must not send more that one item per change * command. This is compliant with all specification and only a * self limitation. */ smlAssert(g_list_length(cmd->private.change.items) == 1); char *data = NULL; unsigned int size = 0; SmlItem *item = g_list_nth_data(cmd->private.change.items, 0); if (!smlItemGetData(item, &data, &size, error)) goto error; /* If max obj size is not unlimited (0), and the size of the item is larger * than the max obj size, we have to return an error */ int sendingmaxobjsize = smlSessionGetRemoteMaxObjSize(session); if ((sendingmaxobjsize > 0) && (size > (unsigned int)sendingmaxobjsize)) { smlErrorSet(error, SML_ERROR_SIZE_MISMATCH, "Item (%ub) is larger than the limit (%db)", size, smlSessionGetRemoteMaxObjSize(session)); goto error; } if (!session->frag_command) cmd->size = size; item->moreData = TRUE; int space = 0; if (!smlAssemblerGetSpace(session->assembler, &space, parent, cmd, error)) goto error; cmd->size = 0; item->moreData = FALSE; /* Check if item data fits into the current message */ if (session->frag_command || (space > 0 && (unsigned int) space < size - session->frag_size)) { smlTrace(TRACE_INTERNAL, "%s: Space %i, size %i. Fragmenting. Already added: %i", __func__, space, size - session->frag_size, session->frag_size); /* We need to fragment */ /* Store the command for processing */ if (!session->frag_command) { session->frag_size = 0; session->frag_command = cmd; smlCommandRef(cmd); session->frag_callback = callback; session->frag_userdata = userdata; } if (!(cmd = _smlSessionFragmentSend(session, session->frag_command, parent, space, session->frag_size, size, error))) goto error; callback = _smlSessionFragmentStatus; userdata = NULL; fragmented = TRUE; /* Sometime cmd is frag_command. So theoretically it can * happen that the item is replaced. Therefore the item * reference must be determined again. */ item = g_list_nth_data(cmd->private.change.items, 0); if (item->moreData == FALSE) { smlTrace(TRACE_INTERNAL, "%s: This is the last chunk", __func__); callback = session->frag_callback; userdata = session->frag_userdata; fragmented = FALSE; session->frag_size = 0; smlCommandUnref(session->frag_command); session->frag_command = NULL; } smlTrace(TRACE_INTERNAL, "%s: Fragmented. Added %i already", __func__, session->frag_size); } } /* We now increment the session ID */ session->lastCommandID++; cmd->cmdID = session->lastCommandID; smlTrace(TRACE_INTERNAL, "%s: last command id is %i", __func__, session->lastCommandID); /* Now we can try to add the command to the assembler */ switch (smlAssemblerStartCommand(session->assembler, parent, cmd, error)) { case SML_ASSEMBLER_RESULT_OK: /* We successfully added the command */ cmd->pushedBack = FALSE; break; case SML_ASSEMBLER_RESULT_MISMATCH: if (cmd->pushedBack) { smlErrorSet(error, SML_ERROR_GENERIC, "Command is too large"); goto error; } cmd->pushedBack = TRUE; /* We werent able to add the command. So we have to flush the already * added statuses/commands and then add it again later */ if (!_smlSessionFlushInternal(session, FALSE, error)) { session->lastCommandID--; goto error; } smlTrace(TRACE_EXIT, "%s: Mismatch", __func__); return SML_ASSEMBLER_RESULT_MISMATCH; case SML_ASSEMBLER_RESULT_ERROR: session->lastCommandID--; goto error; } /* If the user requested a reply to the command we generate * the pending status so that we can dispatch the incoming status */ if (callback) { pending = smlTryMalloc0(sizeof(SmlPendingStatus), error); if (!pending) { session->lastCommandID--; goto error; } pending->callback = callback; pending->userdata = userdata; pending->cmdID = cmd->cmdID; pending->msgID = session->lastMessageID; smlTrace(TRACE_INTERNAL, "%s: Appending pending status with cmdID %i and msgID %i", __func__, pending->cmdID, pending->msgID); session->pendingReplies = g_list_append(session->pendingReplies, pending); } else cmd->noResp = TRUE; /* We will get a status and a result to a get command * so we register a second callback for the result */ if (cmd->type == SML_COMMAND_TYPE_GET) { pending = smlTryMalloc0(sizeof(SmlPendingStatus), error); if (!pending) { session->lastCommandID--; goto error; } pending->callback = callback; pending->userdata = userdata; pending->cmdID = cmd->cmdID; pending->msgID = session->lastMessageID; smlTrace(TRACE_INTERNAL, "%s: Appending pending status for a result with cmdID %i and msgID %i", __func__, pending->cmdID, pending->msgID); session->pendingReplies = g_list_append(session->pendingReplies, pending); } if (fragmented) { /* We werent able to add the command. So we have to flush the already * added statuses/commands and then add it again later */ if (!_smlSessionFlushInternal(session, FALSE, error)) { session->lastCommandID--; goto error; } smlCommandUnref(cmd); smlTrace(TRACE_EXIT, "%s: Mismatch but fragmented", __func__); return SML_ASSEMBLER_RESULT_MISMATCH; } if (addToCommandStack) session->commandStack = g_list_append(session->commandStack, cmd); session->hasCommand = TRUE; smlTrace(TRACE_EXIT, "%s", __func__); return SML_ASSEMBLER_RESULT_OK; error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return SML_ASSEMBLER_RESULT_ERROR; } static SmlBool _smlSessionEndCommandInternal(SmlSession *session, SmlCommand *parent, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, session, parent, error); smlAssert(session); CHECK_ERROR_REF if (!smlAssemblerEndCommand(session->assembler, parent, error)) goto error; session->commandStack = g_list_delete_link(session->commandStack, g_list_last(session->commandStack)); smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return FALSE; } static void _smlSessionCommandFree(SmlSessionCommand *sesscmd) { if (sesscmd->cmd) smlCommandUnref(sesscmd->cmd); if (sesscmd->parent) smlCommandUnref(sesscmd->parent); if (sesscmd->status) smlStatusUnref(sesscmd->status); smlSafeFree((gpointer *)&sesscmd); } static void _smlSessionCommandHandler(void *message, void *userdata) { smlTrace(TRACE_ENTRY, "%s", __func__); smlAssert(message); smlAssert(userdata); SmlSessionCommand *sesscmd = message; SmlSession *session = userdata; SmlError *error = NULL; //SmlPendingStatus *pending = NULL; smlTrace(TRACE_INTERNAL, "%s: session cmd type %i", __func__, sesscmd->type); /* check if the header is ready */ if (!session->assmHasHeader) { if (!smlAssemblerAddHeader(session->assembler, session, &error)) goto error; session->assmHasHeader = TRUE; } SmlCommand *parent = sesscmd->parent; SmlCommand *cmd = sesscmd->cmd; SmlStatus *status = sesscmd->status; switch (sesscmd->type) { case SML_SESSION_FLUSH: if (sesscmd->end) { session->end = TRUE; smlTrace(TRACE_INTERNAL, "%s: End on flush was set", __func__); } if (!_smlSessionFlushInternal(session, sesscmd->final, &error)) goto error; break; case SML_SESSION_COMMAND_END: if (!_smlSessionEndCommandInternal(session, parent, &error)) goto error; break; case SML_SESSION_COMMAND_START: switch (_smlSessionStartCommandInternal(session, cmd, parent, sesscmd->callback, sesscmd->callbackUserdata, TRUE, &error)) { case SML_ASSEMBLER_RESULT_OK: /* We successfully added the command */ break; case SML_ASSEMBLER_RESULT_MISMATCH: smlQueuePushHead(session->command_queue, message); return; case SML_ASSEMBLER_RESULT_ERROR: goto error; } break; case SML_SESSION_STATUS:; unsigned int cmdRef, msgRef = 0; if (!smlAssemblerGetNextCmdRef(session->assembler, &cmdRef, &msgRef)) { smlErrorSet(&error, SML_ERROR_GENERIC, "No more statuses were needed"); goto error; } if (status->cmdRef != cmdRef || status->msgRef != msgRef) { //Put it on the end of the queue smlQueueSendPrio(session->command_queue, message); smlTrace(TRACE_EXIT, "%s - next needed command status %d for message %d is not this one (cmd %d, msg %d)", __func__, cmdRef, msgRef, status->cmdRef, status->msgRef); return; } /* We ignore if the added status violates the size limitation if * a incoming buffer for a large object is open. the problem is that * the status for the chunk has to go into the next message AND the status * MUST be in the same order as the original commands. so the only solution is * to send all statuses and ignore the size. */ /* Now we can try to add the status to the assembler */ smlTrace(TRACE_INTERNAL, "%s - try to add status", __func__); switch (smlAssemblerAddStatusFull(session->assembler, status, session->incomingBuffer ? TRUE : FALSE, &error)) { case SML_ASSEMBLER_RESULT_OK: /* We successfully added the status */ session->active = TRUE; break; case SML_ASSEMBLER_RESULT_MISMATCH: /* We werent able to add the command. So we have to flush the already * added statuses/commands and then add it again later */ if (!_smlSessionFlushInternal(session, FALSE, &error)) { session->lastCommandID--; goto error; } /* Push the message back into the queue */ smlQueuePushHeadPrio(session->command_queue, message); smlTrace(TRACE_EXIT, "%s - status cannot be added, so push back", __func__); return; break; case SML_ASSEMBLER_RESULT_ERROR: goto error; } break; } _smlSessionCommandFree(sesscmd); smlTrace(TRACE_EXIT, "%s", __func__); return; error: smlSessionDispatchEvent(session, SML_SESSION_EVENT_ERROR, NULL, NULL, NULL, error); _smlSessionCommandFree(sesscmd); return; } SmlBool smlSessionReceiveHeader(SmlSession *session, SmlHeader *header, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, session, header, error); smlAssert(session); smlAssert(header); CHECK_ERROR_REF /* check and set the counters */ if (header->messageID <= session->lastReceivedMessageID) { smlErrorSet(error, SML_ERROR_GENERIC, "Message ID not incremented"); goto error; } session->lastReceivedMessageID = header->messageID; session->lastCommandID++; /* check and set the MaxMsgSize */ if (0 < header->maxmsgsize) { /* If MaxMsgSize is 0 then it is not set. Therefore * a MaxMsgSize of 0 is ignored to not override an * already configured MaxMsgSize from an earlier * message. */ smlAssemblerSetRemoteMaxMsgSize(session->assembler, header->maxmsgsize); } if (0 < header->maxmsgsize && header->maxmsgsize < session->localMaxMsgSize) { /* The localMaxMsgSize is only set if it is already * configured. If there is no local limit then it is not * necessary to configure it only because the remote * peer has a limit. */ smlSessionSetLocalMaxMsgSize(session, header->maxmsgsize); } /* Reserve the status for header reply. It will always be cmdRef 0 * and it will always be the first command in the message */ if (!smlAssemblerReserveStatus(session->assembler, 0, header->messageID, 1, error)) goto error; /* If RespURI is send in the header * then the URI in the transport layer must be adjusted. */ if (header->responseURI) { if (!session->orgTarget) { /* If the original target is already set * then it MUST NOT be set again * because this would destroy the real original * target and an earlier RespURI would be used * as original target. */ session->orgTarget = session->target; session->target = NULL; } if (session->target) { /* This is not the original target. * Perhaps this is from an earlier message. * Nevertheless only the most actual target * is required. */ smlLocationUnref(session->target); } /* build the new target and publish it*/ session->target = smlLocationNew( header->responseURI, smlLocationGetName(session->orgTarget), error); if (!session->target) goto error; smlSessionDispatchEvent(session, SML_SESSION_EVENT_RESPONSE_URI, NULL, NULL, NULL, NULL); smlTrace(TRACE_INTERNAL, "%s: RespURI: %s, Target: %s", __func__, VA_STRING(smlLocationGetURI(session->target)), VA_STRING(smlLocationGetURI(session->orgTarget))); } else { /* Sometimes a client changes the source reference * after the SAN was sent because the SAN does not * include the correct IMEI. * * If the header includes a new SourceRef/LocURI * then we have to change the TargetRef/LocURI * of the session. */ const char *header_source = smlLocationGetURI(header->source); const char *session_target = smlLocationGetURI(session->target); if (header_source && session_target && strcmp(header_source, session_target)) { /* session target needs an update */ smlTrace(TRACE_INTERNAL, "%s: update session target to header source %s", __func__, header_source); smlLocationSetURI(session->target, header_source); } } smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return FALSE; } SmlBool smlSessionDispatchStatus(SmlSession *session, SmlStatus *status, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, session, status, error); smlAssert(status); CHECK_ERROR_REF if (status->cmdRef == 0) { smlAssert(status->type == SML_COMMAND_TYPE_HEADER); smlAssert(status->data); SmlErrorType errorCode = atoi(status->data); if (session->sessionType == SML_SESSION_TYPE_SERVER) { /* If this is an OMA DS server then the session * authorization is done by the header callback. * This is usually handled by functions named * smlAuth*. * * If the OMA DS client code would be active * then the remote client only have to send an * error code 212 to force the server to accept * the connection. So this is highly critical. */ SmlCommand *cmd = smlCommandNew(SML_COMMAND_TYPE_HEADER, error); smlSessionDispatchEvent(session, SML_SESSION_EVENT_HEADER_REPLY, cmd, NULL, status, NULL); smlCommandUnref(cmd); } else if (errorCode == SML_AUTH_ACCEPTED) { /* authentication succeeded * we can remove the credentials from this session * we do it now for better security */ smlTrace(TRACE_INTERNAL, "%s - authentication succeeded", __func__); if (session->cred != NULL) { smlCredUnref(session->cred); session->cred = NULL; } if (!session->established) { session->established = TRUE; smlSessionDispatchEvent( session, SML_SESSION_EVENT_ESTABLISHED, NULL, NULL, NULL, NULL); } } else if (errorCode == SML_ERROR_AUTH_REQUIRED) { /* If the requested authentication method violates the * local security policy then the authentication must * fail. Otherwise the password of the user can be * compromized. */ smlTrace(TRACE_INTERNAL, "%s - authentication required", __func__); session->authenticate = TRUE; session->established = FALSE; smlAssemblerRestoreCommands(session->assembler); smlTrace(TRACE_INTERNAL, "%s - restored commands from previous message", __func__); smlAssert(status->chal); smlAssert(session->cred); if (session->cred->type == SML_AUTH_TYPE_MD5 && status->chal->type != SML_AUTH_TYPE_MD5) { smlErrorSet(error, SML_ERROR_AUTH_REJECTED, "The remote peer tries to enforce an authentication method which violates the local security policy (syncml:auth-md5 is required)."); goto error; } smlTrace(TRACE_INTERNAL, "%s - authentication type conforms to security policy", __func__); /* build the authentication string */ session->cred->data = smlAuthGetCredString( status->chal->type, session->cred->username, session->cred->password, status->chal->nonce_b64, error); if (!session->cred->data) goto error; smlTrace(TRACE_INTERNAL, "%s - credential string set", __func__); } else { if (!session->established) { session->established = TRUE; smlSessionDispatchEvent( session, SML_SESSION_EVENT_ESTABLISHED, NULL, NULL, NULL, NULL); } SmlCommand *cmd = smlCommandNew(SML_COMMAND_TYPE_HEADER, error); smlSessionDispatchEvent(session, SML_SESSION_EVENT_HEADER_REPLY, cmd, NULL, status, NULL); smlCommandUnref(cmd); } goto out; } smlTrace(TRACE_INTERNAL, "%s - no header status", __func__); /* Check if a handler for this object at this path has been installed. * Please note that sometimes (e.g. GET command) a second handler * was installed. So we cannot abort at the first found pending reply. * We have to check every handler. */ GList *o = NULL; SmlBool foundPending = FALSE; for (o = session->pendingReplies; o; o = o ? o->next : NULL ) { SmlPendingStatus *pending = o->data; smlTrace(TRACE_INTERNAL, "%s: check cmd %i of msg %i", __func__, pending->cmdID, pending->msgID); if (pending->cmdID == status->cmdRef && pending->msgID == status->msgRef) { smlTrace(TRACE_INTERNAL, "%s - Found pending status %s of command %d in message %d", __func__, VA_STRING(status->data), status->cmdRef, status->msgRef); if (session->authenticate) { /* modify the pending reply * If there is a required authentication * then all commands must be send again. * Please note that the simple change of the * message ID only works because we never touch * command ID. */ smlTrace(TRACE_INTERNAL, "%s - update message ID to %d", __func__, session->lastMessageID); pending->msgID++; } else { /* normal handling of the first pendingReply (the status one) */ smlTrace(TRACE_INTERNAL, "%s - normal status", __func__); session->pendingReplies = g_list_remove(session->pendingReplies, pending); smlAssert(pending->callback); pending->callback(session, status, pending->userdata); smlSafeFree((gpointer *)&pending); /* We have to abort the for loop here * because we MUST NOT delete a potential * second pending reply. The GET command * registers to pending replies - one for * the status and one for the results. */ o = NULL; } foundPending = TRUE; } } if (foundPending) goto out; smlTrace(TRACE_INTERNAL, "%s - no pending reply found", __func__); /* We have to catch at this point if the status reply is the reply * to our server alerted sync. Since this initial alert is not sent * over a session, the status can of course not be wanted */ if (status->type == SML_COMMAND_TYPE_ALERT && !status->anchor) { smlTrace(TRACE_INTERNAL, "%s: Handling status for server alerted sync", __func__); SmlErrorType errorCode = atoi(status->data); if ((199 < errorCode && errorCode < 300) || errorCode == 508) { /* If the status is 2xx or 508 then it is no error. */ goto out; } else { /* There is an error and this must be signaled. * If there is no callback available * then this is a normal error. */ smlErrorSet(error, errorCode, "The SAN alert was rejected."); goto error; } } smlErrorSet(error, SML_ERROR_GENERIC, "Received unwanted status %s of command %d in message %d", status->data, status->cmdRef, status->msgRef); goto error; out: smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return FALSE; } SmlBool smlSessionCheck(SmlSession *session) { smlAssert(session); if (session->waiting) { smlTrace(TRACE_INTERNAL, "%s: waiting", __func__); return FALSE; } SmlBool result; if (!smlAssemblerIsStatusMissing(session->assembler)) { result = smlQueueCheck(session->command_queue); smlTrace(TRACE_INTERNAL, "%s: no status is missing - %i", __func__, result); } else { result = smlQueueCheckPrio(session->command_queue); smlTrace(TRACE_INTERNAL, "%s: status is missing - %i", __func__, result); } return result; } SmlBool smlSessionTryLock(SmlSession *session) { smlTrace(TRACE_ENTRY, "%s(%p)", __func__, session); smlAssert(session); smlAssert(session->dispatch_mutex); SmlBool ret = g_mutex_trylock(session->dispatch_mutex); smlTrace(TRACE_EXIT, "%s - %d", __func__, ret); return ret; } void smlSessionLock(SmlSession *session) { smlTrace(TRACE_ENTRY, "%s(%p)", __func__, session); smlAssert(session); smlAssert(session->dispatch_mutex); g_mutex_lock(session->dispatch_mutex); smlTrace(TRACE_EXIT, "%s", __func__); } void smlSessionUnlock(SmlSession *session) { smlTrace(TRACE_ENTRY, "%s", __func__); smlAssert(session); smlAssert(session->dispatch_mutex); g_mutex_unlock(session->dispatch_mutex); smlTrace(TRACE_EXIT, "%s", __func__); } void smlSessionDispatch(SmlSession *session) { smlTrace(TRACE_ENTRY, "%s", __func__); smlAssert(session); if (session->waiting) { smlTrace(TRACE_EXIT, "%s - session is waiting", __func__); return; } /* If we are still missing statuses, we just dispatch the statuses * If we are complete on the status side, we dispatch the commands */ if (!smlAssemblerIsStatusMissing(session->assembler)) { smlTrace(TRACE_INTERNAL, "%s: dispatch commands", __func__); smlQueueDispatch(session->command_queue); } else { smlTrace(TRACE_INTERNAL, "%s: dispatch status", __func__); smlQueueDispatchPrio(session->command_queue); } smlTrace(TRACE_EXIT, "%s - done", __func__); } SmlBool smlSessionReceiveBody(SmlSession *session, SmlParser *parser, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, session, parser, error); smlAssert(session); smlAssert(parser); CHECK_ERROR_REF SmlStatus *status = NULL; SmlCommand *cmd = NULL; SmlParserResult result = SML_PARSER_RESULT_ERROR; SmlBool isSan = TRUE; if (session->sessionType == SML_SESSION_TYPE_SERVER) isSan = FALSE; /* The session received some stuff and so it is no longer waiting. * It is important to set the state here because if it is set later * then there is the risk that some dispatched command sends the * next message via a direct flush. In this case a late state change * could lead to a race condition because the correct state WAITING * would be overwritten with the old value. */ session->waiting = FALSE; session->sending = FALSE; parse_status: /* Now lets go through the available statuses (if any) */ while (1) { if (!smlParserGetStatus(parser, &status, error)) goto error_free_status; if (!status) break; /* There is at minimum one status. This means that * this is not the first message and there is an * header reply. */ isSan = FALSE; /* If there is a status then it is necessary to check * the session environment before the user has a chance * to do something with the received information. * * The background is that libsyncml does not handle the * SANs in a SmlSession. Therefore the SmlSession is not * aware of an already used MsgRef 1. * * If a status is received and lastMessageID is still 1 * then a reply to a SAN is assumed and the lastMessageID * is fixed accordingly. */ if (session->lastMessageID == 1) { /* This should be an answer to a SAN. */ smlTrace(TRACE_INTERNAL, "%s - reply to SAN detected", __func__); session->lastMessageID = 2; } /* Call the callback*/ if (!smlSessionDispatchStatus(session, status, error)) goto error_free_status; smlStatusUnref(status); } /* Go through the remaining commands */ while (1) { result = smlParserGetCommand(parser, &cmd, error); if (result == SML_PARSER_RESULT_ERROR) goto error_free_cmd; if (result == SML_PARSER_RESULT_OTHER) break; if (cmd) cmd->msgID = session->lastReceivedMessageID; /* If the handler of the header signals that an authentication * is still required then we must send status 407 to all * commands. The client must send all commands with the * next message again. */ if (!session->established && !isSan) { session->lastCommandID++; /* Reserve the place for the status in the assembler */ if (!smlAssemblerReserveStatus(session->assembler, cmd->cmdID, session->lastReceivedMessageID, session->lastCommandID, error)) goto error_free_cmd; /* send status 407 */ SmlStatus *reply = smlCommandNewReply( cmd, SML_ERROR_AUTH_REQUIRED, error); if (!reply) goto error_free_cmd; if (!smlSessionSendReply(session, reply, error)) goto error_free_cmd; smlStatusUnref(reply); smlCommandUnref(cmd); continue; } switch (result) { case SML_PARSER_RESULT_OPEN: session->lastCommandID++; /* Reserve the place for the status in the assembler */ if (!smlAssemblerReserveStatus(session->assembler, cmd->cmdID, session->lastReceivedMessageID, session->lastCommandID, error)) goto error_free_cmd; /* Store the parent */ if (session->parentCommand) { smlErrorSet(error, SML_ERROR_GENERIC, "Already had a parent"); goto error_free_cmd; } /* If we are a server, we just mimick the behaviour of the client regarding * large object handling and support of number of changes. This way we dont * need to parse the devinf */ if (cmd->type == SML_COMMAND_TYPE_SYNC) { smlTrace(TRACE_INTERNAL, "%s: maxObjSize: %i, numbOfChanges: %i, %i", __func__, cmd->private.sync.maxObjSize, cmd->private.sync.hasNumChanged, cmd->private.sync.numChanged); /* If the sync has the maxObjSize set (>= 0), we set the requested max obj size. * If the max obj size was set before (with the alert, we overwrite it */ if (cmd->private.sync.maxObjSize >= 0) smlSessionSetRemoteMaxObjSize(session, cmd->private.sync.maxObjSize); /* If the DevInf of the client includes SupportNumberOfChanges * but the client does not send NumberOfChanges * then the server still MUST send NumberOfChanges. * The client only MAY send NumberOfChanges. * * So even if NumberOfChanges are missing then never touch * the requested and configured NumberOfChanges property. * * Please see OMA DS Protocol v1.2 * Section 9 Two-Way Sync * Section 9.1 Client Modifications to Server * Section 9.2 Server Modifications to Client */ } session->parentCommand = cmd; cmd->msgID = session->lastReceivedMessageID; if (!session->end) { smlSessionDispatchEvent(session, SML_SESSION_EVENT_COMMAND_START, cmd, NULL, NULL, NULL); } else { smlTrace(TRACE_INTERNAL, "%s: Replying with 407 since the session has ended", __func__); SmlStatus *reply = smlCommandNewReply(cmd, SML_ERROR_AUTH_REQUIRED, error); if (!reply) goto error_free_cmd; if (!smlSessionSendReply(session, reply, error)) goto error_free_cmd; smlStatusUnref(reply); } break; case SML_PARSER_RESULT_NORMAL: session->lastCommandID++; /* Reserve the place for the status in the assembler */ if (!smlAssemblerReserveStatus(session->assembler, cmd->cmdID, session->lastReceivedMessageID, session->lastCommandID, error)) goto error_free_cmd; /* Here we catch Alerts for the next message */ if (cmd->type == SML_COMMAND_TYPE_ALERT) { if (cmd->private.alert.type == SML_ALERT_NEXT_MESSAGE) { SmlStatus *reply = smlCommandNewReply(cmd, SML_NO_ERROR, error); if (!reply) goto error_free_cmd; if (!smlSessionSendReply(session, reply, error)) goto error_free_cmd; smlStatusUnref(reply); smlCommandUnref(cmd); break; } else { smlTrace(TRACE_INTERNAL, "%s: Alert maxObjSize: %i", __func__, cmd->private.alert.maxObjSize); if (cmd->private.alert.maxObjSize >= 0) smlAssemblerSetRemoteMaxObjSize(session->assembler, cmd->private.alert.maxObjSize); } } /* Here we catch changes with moreData set */ if (cmd->type == SML_COMMAND_TYPE_ADD || cmd->type == SML_COMMAND_TYPE_REPLACE) { SmlItem *lastItem = g_list_nth_data(cmd->private.change.items, g_list_length(cmd->private.change.items) - 1); if (session->incomingBuffer) { /* There is a command in the incoming buffer. * This requires that all items of the received * command are merged into this incoming buffer. * Please remember that one command can contain * several item each with a large object inside. * * If the last item of the command has no moreData * flag then the command is dispatched. */ smlTrace(TRACE_INTERNAL, "%s: Appending to incoming buffer", __func__); /* The size of an item must not be set in the * different chunks except the first one. */ if (cmd->size) { smlErrorSet(error, SML_ERROR_GENERIC, "Only the first chunk can have the size set"); goto error_free_cmd; } /* Copy the item data of the first new item. * This includes the moreData flag. * This is a chunk of the previous item in the buffer. */ char *data = NULL; unsigned int size = 0; SmlItem *item = g_list_nth_data(cmd->private.change.items, 0); if (!item) goto error_free_cmd; if (!smlItemGetData(item, &data, &size, error)) goto error_free_cmd; lastItem = g_list_nth_data(session->incomingBuffer->private.change.items, g_list_length(session->incomingBuffer->private.change.items) - 1); if (!smlItemAddData(lastItem, data, size, error)) goto error_free_cmd; lastItem->moreData = item->moreData; smlTrace(TRACE_INTERNAL, "%s: Appended %i to buffer. Buffer size: %i. Required: %i", __func__, size, xmlBufferLength(lastItem->buffer), lastItem->size); /* move all other items from the new to the buffered command */ guint i; for (i=1; i < g_list_length(cmd->private.change.items); i++) { item = g_list_nth_data(cmd->private.change.items, i); session->incomingBuffer->private.change.items = g_list_append( session->incomingBuffer->private.change.items, item); } smlItemUnref(g_list_nth_data(cmd->private.change.items, 0)); g_list_free(cmd->private.change.items); cmd->private.change.items = NULL; /* If the last item of the command is complete * then the command must be prepared for dispatching. */ lastItem = g_list_nth_data(session->incomingBuffer->private.change.items, g_list_length(session->incomingBuffer->private.change.items) - 1); if (!lastItem->moreData) { smlTrace(TRACE_INTERNAL, "%s: Command buffer complete. Dispatching.", __func__); /* check if the item size is correct */ if (!smlItemCheck(lastItem)) { /* We have a size mismatch */ SmlStatus *reply = smlCommandNewReply(cmd, SML_ERROR_SIZE_MISMATCH, error); if (!reply) goto error_free_cmd; if (!smlSessionSendReply(session, reply, error)) goto error_free_cmd; smlStatusUnref(reply); smlErrorSet(error, SML_ERROR_GENERIC, "Chunked item size mismatch"); goto error_free_cmd; } /* The original command is no longer needed. * The incoming buffer cannot be used * because several status informations like * the message ID are required for correct * status replies. */ cmd->private.change.items = session->incomingBuffer->private.change.items; session->incomingBuffer->private.change.items = NULL; smlCommandUnref(session->incomingBuffer); session->incomingBuffer = NULL; } } else if (lastItem->moreData) { /* There is no buffered command yet. * The new command is copied to the buffer. * This is done by reference copy and * an incrementation of the reference counter. */ if (!cmd->size) { smlErrorSet(error, SML_ERROR_GENERIC, "First MoreData item didn't have size set"); goto error_free_cmd; } session->incomingBuffer = cmd; smlCommandRef(cmd); smlTrace(TRACE_INTERNAL, "%s: New Buffer started. Buffered item size: %i. Required: %i", __func__, xmlBufferLength(lastItem->buffer), lastItem->size); char *bin = smlPrintBinary((char *) xmlBufferContent(lastItem->buffer), xmlBufferLength(lastItem->buffer)); smlTrace(TRACE_INTERNAL, "%s: Content so far: %s\n", __func__, VA_STRING(bin)); smlSafeCFree(&bin); } if (lastItem->moreData == TRUE) { smlTrace(TRACE_INTERNAL, "%s: Got item with moreData %i", __func__, cmd->msgID); SmlStatus *reply = smlCommandNewReply(cmd, SML_CHUNK_ACCEPTED, error); if (!reply) goto error_free_cmd; if (!smlSessionSendReply(session, reply, error)) goto error_free_cmd; smlStatusUnref(reply); smlCommandUnref(cmd); break; } } /* if the command is a result, we treat it as a status */ if (cmd->type == SML_COMMAND_TYPE_RESULTS) { /* Call the callback*/ if (!smlSessionDispatchStatus(session, cmd->private.results.status, error)) goto error_free_status; } else { /* Dispatch the command */ cmd->msgID = session->lastReceivedMessageID; if (!session->end) { if (!session->parentCommand) { smlSessionDispatchEvent(session, SML_SESSION_EVENT_COMMAND_START, cmd, NULL, NULL, NULL); } else { smlSessionDispatchEvent(session, SML_SESSION_EVENT_CHILD_COMMAND, cmd, session->parentCommand, NULL, NULL); } } else { smlTrace(TRACE_INTERNAL, "%s: Replying with 407 since the session has ended2", __func__); SmlStatus *reply = smlCommandNewReply(cmd, SML_ERROR_AUTH_REQUIRED, error); if (!reply) goto error_free_cmd; if (!smlSessionSendReply(session, reply, error)) goto error_free_cmd; smlStatusUnref(reply); } } smlCommandUnref(cmd); break; case SML_PARSER_RESULT_CLOSE: /* If it is a sync then it is necessary to signal it twice * because DsSession has an enabled write_lock. * If you add other command types here then please check * twice that the callback are ready to be called twice * (usually this requires some kind of statefulness). */ if (session->parentCommand->type == SML_COMMAND_TYPE_SYNC) { smlSessionDispatchEvent( session, SML_SESSION_EVENT_COMMAND_END, session->parentCommand, NULL, NULL, NULL); } /* Remove the parent */ smlCommandUnref(session->parentCommand); session->parentCommand = NULL; break; case SML_PARSER_RESULT_STATUS: goto parse_status; default: goto error_free_cmd; } } /* Check that the message closes correctly * A final tag is only send if the SyncML package is finished. * A package can consists of several messages if MaxMsgSize * is smaller then the exchange data. */ SmlBool final = FALSE; SmlBool end = FALSE; if (!smlParserEnd(parser, &final, &end, error)) goto error_free_cmd; /* Dispatch the final event before we enter the following loop. Otherwise if upper layers depend on the final event we might end in a deadlock. */ if (final && !session->authenticate) { /* If the session is handling an authentication * then this must be transparent for the user. * This means that the user should not see * the FINAL event. * * Example: If the user flushs on FINAL then a FINAL * signal could crash the complete client * logic. */ /* FIXME: Why do we activate session->sending here? */ session->sending = TRUE; smlSessionDispatchEvent(session, SML_SESSION_EVENT_FINAL, NULL, NULL, NULL, NULL); } /* We have to wait at this point until no status are pending anymore * if there is an incoming buffer for large objs open, * the other side expects to see the status for the open buffer of course. so we have to * wait here for all open statuses, since they have to be added in the correct order and * the status for the open buffer is obviously last */ while (1) { unsigned int cmdRef, msgRef; if (!smlAssemblerGetNextCmdRef(session->assembler, &cmdRef, &msgRef)) break; smlTrace(TRACE_INTERNAL, "%s: command %d of message %d found", __func__, cmdRef, msgRef); /* yes, we do some kind busy wait here */ usleep(10000); /* if there is nothing in the queue (num == 0) then this means * that all status and commands are dispatched but the result of one or * more triggered activities is still not available * (therefore smlAssemblerGetNextCmdRef returns a command). * * smlQueueLengthPrio returns missing status count */ unsigned int num = smlQueueLengthPrio(session->command_queue); smlTrace(TRACE_INTERNAL, "%s: Now dispatching %i statuses. Session waiting: %i, prio: %i", __func__, num, session->waiting, smlQueueCheckPrio(session->command_queue)); /* If the session does not wait for the remote peer (session->waiting) * and there is a missing status in the queue * then the message is dispatched again. * The message is dispatched at maximimum once per missing status (i < num). * If smlSessionDispatch blocks because the dispatch_mutex is already in use * and the situation changes (e.g. session->waiting is true) * then this is no problem because the function is safe against * mutliple calls (the SmlManager already requires this). */ unsigned int i = 0; while (!session->waiting && smlQueueCheckPrio(session->command_queue) && i < num) { smlSessionDispatch(session); i++; } /* should we really call dispatch here or wait? */ } /* A lot of checks are performed before the while loop is executed. * This is necessary because this while loop is only present for one * reason, a NEXT MESSAGE request from the remote peer if the original * message data does not fit into one message (MaxMsgSize to small). * The following stuff is checked: * * - the session must be in normal mode * - not sending or waiting * - no changed message counters * - there must be a waiting command (not a waiting status!) * * Usually this happens if an image is too large and must be splitted * (MaxMsgSize < MaxObjSize). Do not touch this stuff except that you * really test it with an image which must be send and it is correctly * splitted. */ unsigned int receivedMsg = session->lastReceivedMessageID; unsigned int lastMsg = session->lastMessageID; while (!session->waiting && !session->sending && smlQueueCheck(session->command_queue) && smlQueueLength(session->command_queue) != smlQueueLengthPrio(session->command_queue) && receivedMsg == session->lastReceivedMessageID && lastMsg == session->lastMessageID) { /* If the session does not wait for the remote peer (session->waiting) * and there is a command in the queue * then the command is dispatched. * If the command is too large then the session is automatically * flushed. If all commands were dispatched then the queue check * fails and the normal mechanism for sending messages flushes * the session or do some other actions. */ smlQueueDispatch(session->command_queue); } smlTrace(TRACE_INTERNAL, "%s: Final %i, waiting %i, sending %i", __func__, final, session->waiting, session->sending); if (session->authenticate) { /* Do nothing. Simply send the message again. * Please note that final and end MUST be ignored. */ smlTrace(TRACE_INTERNAL, "%s: ongoing authentication", __func__); } else if (final) { /* Final means that the received message is the last message * of this SyncML package. When a final is received then the * library should not flush the session automatically because * the user of the library usually starts some special action. * * This can be for example a new package or some kind of * background action which results in informations expected by * the remote peer in the next message. * Example: OMA DS client (remote peer) sends a SYNC package * and expects that the OMA DS server sends the server * modifications at minimum after the last client * modification. * * So again the library user must flush the session (e.g. handle * the SML_MANAGER_SESSION_FINAL event). */ if (session->pendingReplies) { /* If final is reached then there should be no * pendingReplies anymore. The problem is that some * commands (especially SYNC) results in new commands. * Nevertheless we have to check for old pendingReplies * and this we try to do here. * * Yes, this is some kind of bug detection. */ GList *o = NULL; for (o = session->pendingReplies; o; o = o->next) { SmlPendingStatus *pending = o->data; /* This is an asynchronous library but the * message numbering and sending is a serial * operation. So pendingReplies should only * exist for the last message. Anything else * should be a bug. * The problem is that a race condition can * appear here. If the user of the library * gets the FINAL event and flushs the session * immediately then the flush function will * send the message and increment the counter * lastMessageID. So lastMessageID is in this * case one number too high. The solution is to * detect this event by the state of the * session via the status variable waiting. */ if ((!session->waiting && pending->msgID < session->lastMessageID) || (session->waiting && pending->msgID < session->lastMessageID - 1)) { smlErrorSet(error, SML_ERROR_GENERIC, "Didn't receive a reply for pending status (actual message %i, received message %i, cmdID %i, msgID %i)", session->lastMessageID, session->lastReceivedMessageID, pending->cmdID, pending->msgID); goto error; } } } /* The incomingBuffer is used to store the last unhandled item. * The incoming buffer can be filled after a message is * completely handled if an object is too large for a message. * Usually this happens if you add images to your contacts ;) * The remote peer sends the moreData element in this case. * * Nevertheless if final is received then the package is * finished and so there cannot be any more data which is not * send by the client. * * Summary: there is a bug in this library or in the remote peer. */ if (session->incomingBuffer) { smlErrorSet(error, SML_ERROR_GENERIC, "Incoming buffer was open when final arrived"); smlCommandUnref(session->incomingBuffer); session->incomingBuffer = NULL; goto error; } } else if (!session->waiting && !session->sending) { /* If we don't wait already for an answer from the remote peer * (perhaps because a user of this library directly called * smlSessionFlush which causes a send operation of the * transport layer) and if we are waiting for or already * receiving a package (in terms of OMA DS specifications) * then we should send the collected stuff to the remote peer. */ smlTrace(TRACE_INTERNAL, "%s: This is not the final message. Empty? %i", __func__, smlAssemblerIsEmpty(session->assembler)); /* The received message was not a final message. So this is * only a reaction to a part from a package. Sometimes such * replies only contain status but a message must include a * command. */ if (smlAssemblerIsEmpty(session->assembler)) { /* The assembler is empty. This means there is no * command included which is a requirement. * The solution is simple - an alert called next * message is added. this special alert does not need * a source or target because it only signals that the * remote peer should continue its work. */ SmlCommand *alert = smlCommandNewAlert(SML_ALERT_NEXT_MESSAGE, NULL, NULL, NULL, NULL, NULL, error); if (!alert) goto error; if (_smlSessionStartCommandInternal(session, alert, NULL, NULL, NULL, TRUE, error) != SML_ASSEMBLER_RESULT_OK) goto error; if (!_smlSessionEndCommandInternal(session, NULL, error)) goto error; smlCommandUnref(alert); } /* Anything is fine and nobody else want to send a reply * to the received message. So the library flushs now. */ if (!_smlSessionFlushInternal(session, FALSE, error)) goto error; } if (session->authenticate) { /* Do nothing. Simply send the message again. */ smlTrace(TRACE_INTERNAL, "%s: ongoing authentication", __func__); /* session->end signals true because an authentication request * is signaled via status/error 407 as answer to all commands. */ session->end = FALSE; smlTrace(TRACE_INTERNAL, "%s: flushing server finally", __func__); if (!_smlSessionFlushInternal(session, TRUE, error)) goto error; /* reset authenticate only after flush * because we must surpress the FLUSH event. */ session->authenticate = FALSE; } else if (end) { /* end means the last message does not contain a command which * is clearly illegal in SyncML except that the remote party * thinks that the device synchronization or management action * is successfully completed. * * The library can close the session now. */ smlTrace(TRACE_INTERNAL, "%s: Ending session now", __func__); session->end = TRUE; /* If the OMA DS or DM session ends and a correct FINAL was * received then clients should simply end and servers should do * a final flush according to OMA DS spec. * * This only makes sense after a received FINAL because * otherwise the session was already flushed in some way. This * can happen if the user of the library takes action because of * an event. */ if (final) { smlTrace(TRACE_INTERNAL, "%s: session end on final", __func__); if (session->sessionType == SML_SESSION_TYPE_SERVER) { smlTrace(TRACE_INTERNAL, "%s: flushing server finally", __func__); if (!_smlSessionFlushInternal(session, TRUE, error)) goto error; } } else { if (!session->waiting) { /* The library does not send a message * after it received the last message * and neither the remote peer nor the * library send a final. This means * there is an active package. This is * an error of the library or the remote * peer. */ smlErrorSet(error, SML_ERROR_BAD_REQUEST, "The message from the remote peer does not contain a command."); goto error; } } /* Send the library user the signal that the session ends now * and every use of this session will result in an undefined * behaviour. * If this is a server which received a final * then FlushInternal already signalled the session end. */ if (!final || session->sessionType != SML_SESSION_TYPE_SERVER) { g_mutex_lock(session->reportEnd); if (!session->reportedEnd) { /* The end should only be reported once. */ session->reportedEnd = TRUE; smlSessionRestoreTargetURI(session); smlSessionDispatchEvent(session, SML_SESSION_EVENT_END, NULL, NULL, NULL, NULL); } g_mutex_unlock(session->reportEnd); } } smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error_free_cmd: if (cmd) smlCommandUnref(cmd); error_free_status: if (status) smlStatusUnref(status); error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return FALSE; } void smlSessionSetEventCallback(SmlSession *session, SmlSessionEventCallback callback, void *userdata) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, session, callback, userdata); smlAssert(session); session->eventCallback = callback; session->eventCallbackUserdata = userdata; smlTrace(TRACE_EXIT, "%s", __func__); } void smlSessionSetDataCallback(SmlSession *session, SmlSessionDataCallback callback, void *userdata) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, session, callback, userdata); smlAssert(session); session->dataCallback = callback; session->dataCallbackUserdata = userdata; smlTrace(TRACE_EXIT, "%s", __func__); } const char *smlSessionGetSessionID(SmlSession *session) { smlAssert(session); return session->sessionID; } void smlSessionSetSessionID(SmlSession *session, const char *sessionID) { smlAssert(session); if (session->sessionID) smlSafeCFree(&(session->sessionID)); session->sessionID = g_strdup(sessionID); } SmlProtocolVersion smlSessionGetVersion(SmlSession *session) { smlAssert(session); return session->version; } SmlLocation *smlSessionGetSource(SmlSession *session) { smlAssert(session); return session->source; } SmlLocation *smlSessionGetTarget(SmlSession *session) { smlAssert(session); return session->target; } void smlSessionRegisterCred(SmlSession *session, SmlCred *cred) { smlAssert(session); smlAssert(session->sessionType == SML_SESSION_TYPE_CLIENT); smlAssert(cred); if (session->cred) smlCredUnref(session->cred); session->cred = cred; if (cred->username) smlLocationSetName(session->source, cred->username); smlCredRef(session->cred); } /*@}*/ /** * @defgroup SmlSession SyncML Session * @ingroup PublicLowLevelAPI * @brief Interfaces to create, manipulate and delete sessions * * A session has a unique id and consists of several packages which again contain several commands. * */ /*@{*/ /** * @name Session Management * These function allow to create and delete sessions */ /*@{*/ /** @brief Creates a new session * * Note that if you set the new session callback on the transport, you will * get a callback that this session was created (so that it gets easier to register * objects at a central place) * * @param sessionType If the session is a server or a client. * @param mimetype The desired mime type. Choose if you want xml or wbxml * @param version What version of the protocol do you want to use? * @param protocol Which syncml protocol do you want to use? * @param target The remote target of this session. This is used in the header * @param source The source of this session. Used in the header * @param sessionID If you already have a sessionID, you can enter it here. Set it to NULL if you want to generate a new ID * @param messageID The message Id where this session should start. set to 0 to take the default * @param error A pointer to a error struct * @returns The new session or NULL if an error occured * */ SmlSession *smlSessionNew(SmlSessionType sessionType, SmlMimeType mimetype, SmlProtocolVersion version, SmlProtocolType protocol, SmlLocation *target, SmlLocation *source, const char *sessionID, unsigned int messageID, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%i, %i, %i, %i, %p, %p, %s, %i, %p)", __func__, sessionType, mimetype, version, protocol, target, source, VA_STRING(sessionID), messageID, error); CHECK_ERROR_REF /* Initialize GLib thread system. */ if (!g_thread_supported ()) g_thread_init (NULL); /* Malloc the new session object */ SmlSession *session = smlTryMalloc0(sizeof(SmlSession), error); if (!session) goto error; session->dispatch_mutex = g_mutex_new(); session->refCount = 1; session->eventCallback = NULL; session->version = version; session->protocol = protocol; session->type = mimetype; session->sessionID = g_strdup(sessionID); if (messageID) session->lastMessageID = messageID; else session->lastMessageID = 1; session->end = FALSE; session->reportEnd = g_mutex_new(); session->reportedEnd = FALSE; session->sessionType = sessionType; session->lastCommandID = 0; if (sessionType == SML_SESSION_TYPE_CLIENT) session->sending = TRUE; else session->sending = FALSE; session->source = source; smlLocationRef(source); session->target = target; smlLocationRef(target); session->cred = NULL; session->chal = NULL; /* Create the assembler that will parse messages send * from this session */ session->assembler = smlAssemblerNew(mimetype, 0, error); if (!session->assembler) goto error_free_session; smlAssemblerSetOption(session->assembler, "USE_STRTABLE", "1"); if (!smlAssemblerStart(session->assembler, session, error)) goto error_free_session; /* Do not call smlAssemblerAddHeader here. It is nice to know * if the header is is too large for the maximum message size * but there is sometimes not enough information to pass all * sanity checks of the assembler at this time (e.g. missing * local MaxMsgSize). */ session->assmHasHeader = FALSE; session->command_queue = smlQueueNew(error); if (!session->command_queue) goto error_free_session; smlQueueSetHandler(session->command_queue, (SmlQueueHandler)_smlSessionCommandHandler, session); smlTrace(TRACE_EXIT, "%s: %p", __func__, session); return session; error_free_session: smlSessionUnref(session); error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return NULL; } SmlSession *smlSessionRef(SmlSession *session) { smlTrace(TRACE_ENTRY, "%s(%p)", __func__, session); smlAssert(session); g_atomic_int_inc(&(session->refCount)); smlTrace(TRACE_EXIT, "%s: New refcount: %i", __func__, session->refCount); return session; } void smlSessionUnref(SmlSession *session) { smlTrace(TRACE_ENTRY, "%s(%p)", __func__, session); smlAssert(session); if (g_atomic_int_dec_and_test(&(session->refCount))) { smlTrace(TRACE_INTERNAL, "%s: Refcount == 0!", __func__); if (session->target) smlLocationUnref(session->target); if (session->responseURI) smlSafeCFree(&(session->responseURI)); if (session->source) smlLocationUnref(session->source); if (session->cred) smlCredUnref(session->cred); if (session->chal) smlChalUnref(session->chal); if (session->sessionID) smlSafeCFree(&(session->sessionID)); if (session->command_queue) { SmlSessionCommand *sesscmd = NULL; while ((sesscmd = smlQueueTryPop(session->command_queue))) _smlSessionCommandFree(sesscmd); smlQueueFree(session->command_queue); } _smlSessionFreePendingReplies(session); if (session->assembler) smlAssemblerFree(session->assembler); if (session->incomingBuffer) { smlTrace(TRACE_INTERNAL, "%s: There is an unhandled incoming buffer.", __func__); smlCommandUnref(session->incomingBuffer); } if (session->parentCommand) smlCommandUnref(session->parentCommand); smlTrace(TRACE_INTERNAL, "%s: cleanup dispatch mutex", __func__); if (!g_mutex_trylock(session->dispatch_mutex)) g_warning("%s: The session is still locked for dispatching - forcing unlock/free.", __func__); g_mutex_unlock(session->dispatch_mutex); g_mutex_free(session->dispatch_mutex); smlTrace(TRACE_INTERNAL, "%s: cleanup reportEnd mutex", __func__); /* It is no bug if reportEnd is not used. */ if (!g_mutex_trylock(session->reportEnd)) g_warning("%s: The reportEnd is still locked to set reportEnd - forcing unlock/free.", __func__); g_mutex_unlock(session->reportEnd); g_mutex_free(session->reportEnd); smlSafeFree((gpointer *)&session); } smlTrace(TRACE_EXIT, "%s", __func__); } /*@}*/ /** * @name Session Control * These function allow to control a session */ /*@{*/ /** @brief Flushes a session * * This flushes the already added statuses and/or commands. Note that if the session * has a size limitation, it will get flushed automatically if the size of the already * added commands exceeds the limit. Use this function if you want for some reason * to flush manually. * * @param session The session to flush * @param final Set to TRUE if you want to have the final flag added. Otherwise it will just flush * the already added statuses and commands * @param error A error struct * @return TRUE if successful, FALSE otherwise * */ SmlBool smlSessionFlush(SmlSession *session, SmlBool final, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %i, %p)", __func__, session, final, error); smlAssert(session); CHECK_ERROR_REF SmlSessionCommand *sesscmd = smlTryMalloc0(sizeof(SmlSessionCommand), error); if (!sesscmd) goto error; sesscmd->type = SML_SESSION_FLUSH; sesscmd->final = final; smlTrace(TRACE_INTERNAL, "%s: sending flush (%i) command %p via queue %p", __func__, SML_SESSION_FLUSH, sesscmd, session->command_queue); smlQueueSend(session->command_queue, sesscmd); // session is still active even if the other side sent only status session->end = FALSE; smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return FALSE; } /** @brief Ends the session * * This function will end the session. This means that no more commands will be sent. * If there are replies waiting they will be sent. if there are commands waiting from the * remote side which have not yet been answered, they will get a error reply. If you already * sent commands in this session, you will receive error replies for your callbacks. * * If you registered a session end handler it will get called. if the session is a server type * and it receives a command from the remote side for the ended session libsyncml will * automatically send an error reply. * * Sessions will be deleted from the server session after a timeout. * * @param session The session to flush * @param error A error struct * @return TRUE if successful, FALSE otherwise * */ SmlBool smlSessionEnd(SmlSession *session, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p)", __func__, session, error); smlAssert(session); CHECK_ERROR_REF g_mutex_lock(session->reportEnd); if (session->reportedEnd) { /* If the end was already reported * then this function should not be called. * This can happen because of race conditions * during the event handling. So this event * is not necessarily a bug. */ g_mutex_unlock(session->reportEnd); smlTrace(TRACE_EXIT, "%s - session end already signalled.", __func__); return TRUE; } session->reportedEnd = TRUE; /* If the session received all status and has no command ready * to send then it makes no sense to flush. Such situations can * appear if the user opens a connection to a SyncML server but * after the connect the user notices that there is nothing to * synchronize. * * The only exception is a server which received a map from the * client as answer for a sync command. The server must send an * empty message to the client. If the client sends no map * then this is handled by the function ReceiveBody. */ if (smlSessionCheck(session) || (!session->end && session->lastCommandID)) { /* The session end is reported by the internal * flush function in this situation. */ session->reportedEnd = FALSE; SmlSessionCommand *sesscmd = smlTryMalloc0(sizeof(SmlSessionCommand), error); if (!sesscmd) goto error; sesscmd->type = SML_SESSION_FLUSH; sesscmd->final = TRUE; sesscmd->end = TRUE; smlTrace(TRACE_INTERNAL, "%s: sending command %p", sesscmd); smlQueueSend(session->command_queue, sesscmd); } else { /* If there is nothing to synchronize * then simply signal the end. */ smlTrace(TRACE_INTERNAL, "%s: no status/command ... only sending event", __func__); smlSessionRestoreTargetURI(session); smlSessionDispatchEvent(session, SML_SESSION_EVENT_END, NULL, NULL, NULL, NULL); } g_mutex_unlock(session->reportEnd); smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error: g_mutex_unlock(session->reportEnd); smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return FALSE; } /* This is for the client side of ResponseURI support. */ void smlSessionRestoreTargetURI(SmlSession *session) { smlTrace(TRACE_ENTRY, "%s(%p)", __func__, session); smlAssert(session); if (session->orgTarget) { /* Restore original target if RespURI was used. * This is unimportant because every new session * must use a new link (connection). */ smlLocationUnref(session->target); session->target = session->orgTarget; session->orgTarget = NULL; /* Do not try to reset the ResponseURI via the session * event because the original Target URI is very often * no URL which causes an error in the transport layer. */ } smlTrace(TRACE_EXIT, "%s", __func__); } /* This is for the server side of ResponseURI support. */ SmlBool smlSessionSetResponseURI( SmlSession *session, const char *responseURI, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %s, %p)", __func__, session, VA_STRING(responseURI), error); CHECK_ERROR_REF if (session->responseURI) { g_warning("The response URI (%s) of a session (%s) should never be overwritten (%s).", session->responseURI, session->sessionID, responseURI); smlSafeCFree(&(session->responseURI)); } session->responseURI = g_strdup(responseURI); smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; } void smlSessionUseStringTable(SmlSession *session, SmlBool useStringtable) { smlTrace(TRACE_ENTRY, "%s(%p, %i)", __func__, session, useStringtable); smlAssert(session); smlAssemblerSetOption(session->assembler, "USE_STRTABLE", useStringtable ? "1" : "0"); smlTrace(TRACE_EXIT, "%s", __func__); } void smlSessionUseNumberOfChanges(SmlSession *session, SmlBool support) { smlTrace(TRACE_ENTRY, "%s(%p, %i)", __func__, session, support); smlAssert(session); smlAssemblerSetOption(session->assembler, "USE_NUMBEROFCHANGES", support ? "1" : "0"); smlTrace(TRACE_EXIT, "%s", __func__); } void smlSessionUseLargeObjects(SmlSession *session, SmlBool support) { smlTrace(TRACE_ENTRY, "%s(%p, %i)", __func__, session, support); smlAssert(session); smlAssemblerSetOption(session->assembler, "USE_LARGEOBJECTS", support ? "1" : "0"); smlTrace(TRACE_EXIT, "%s", __func__); } void smlSessionUseOnlyReplace(SmlSession *session, SmlBool onlyReplace) { smlTrace(TRACE_ENTRY, "%s(%p, %i)", __func__, session, onlyReplace); smlAssert(session); smlAssemblerSetOption(session->assembler, "ONLY_REPLACE", onlyReplace ? "1" : "0"); session->onlyReplace = onlyReplace; smlTrace(TRACE_EXIT, "%s", __func__); } /* FIXME: DEPRECATED */ void smlSessionSetSendingLimit(SmlSession *session, unsigned int limit) { smlSessionSetRemoteMaxMsgSize(session, limit); } /* FIXME: DEPRECATED */ unsigned int smlSessionGetSendingLimit(SmlSession *session) { return smlSessionGetRemoteMaxMsgSize(session); } /* FIXME: DEPRECATED */ void smlSessionSetReceivingLimit(SmlSession *session, unsigned int limit) { smlSessionSetLocalMaxMsgSize(session, limit); } /* FIXME: DEPRECATED */ void smlSessionSetSendingMaxMsgSize(SmlSession *session, unsigned int size) { smlSessionSetRemoteMaxMsgSize(session, size); } /* FIXME: DEPRECATED */ unsigned int smlSessionGetSendingMaxMsgSize(SmlSession *session) { return smlSessionGetRemoteMaxMsgSize(session); } /* FIXME: DEPRECATED */ void smlSessionSetReceivingMaxMsgSize(SmlSession *session, unsigned int size) { smlSessionSetLocalMaxMsgSize(session, size); } void smlSessionSetRemoteMaxMsgSize(SmlSession *session, unsigned int size) { smlTrace(TRACE_ENTRY, "%s(%p, %u)", __func__, session, size); smlAssert(session); smlAssemblerSetRemoteMaxMsgSize(session->assembler, size); smlTrace(TRACE_EXIT, "%s", __func__); } unsigned int smlSessionGetRemoteMaxMsgSize(SmlSession *session) { smlAssert(session); return smlAssemblerGetRemoteMaxMsgSize(session->assembler); } void smlSessionSetLocalMaxMsgSize(SmlSession *session, unsigned int size) { smlTrace(TRACE_ENTRY, "%s(%p, %u)", __func__, session, size); smlAssert(session); if (! smlSessionGetRemoteMaxMsgSize(session) > 0 || smlSessionGetRemoteMaxMsgSize(session) > size) { session->localMaxMsgSize = size; } else { session->localMaxMsgSize = smlSessionGetRemoteMaxMsgSize(session); } smlTrace(TRACE_EXIT, "%s", __func__); } unsigned int smlSessionGetLocalMaxMsgSize(SmlSession *session) { smlAssert(session); return session->localMaxMsgSize; } /* FIXME: DEPRECATED */ void smlSessionSetSendingMaxObjSize(SmlSession *session, int limit) { smlSessionSetRemoteMaxObjSize(session, limit); } /* FIXME: DEPRECATED */ void smlSessionSetRequestedMaxObjSize(SmlSession *session, int limit) { smlSessionSetRemoteMaxObjSize(session, limit); } /* FIXME: DEPRECATED */ int smlSessionGetSendingMaxObjSize(SmlSession *session) { return smlSessionGetRemoteMaxObjSize(session); } /* FIXME: DEPRECATED */ void smlSessionSetReceivingMaxObjSize(SmlSession *session, unsigned int limit) { smlSessionSetLocalMaxObjSize(session, limit); } /* FIXME: DEPRECATED */ unsigned int smlSessionGetReceivingMaxObjSize(SmlSession *session) { return smlSessionGetLocalMaxObjSize(session); } /** Sets the maximum obj size for the remote peer. * If we try to send an item to the remote * side which is larger than this limit we return an error * * Possible values for limit are * * 0 means that we can send objects of any size * > 0 means that a limit is set * * */ void smlSessionSetRemoteMaxObjSize(SmlSession *session, unsigned int limit) { smlTrace(TRACE_ENTRY, "%s(%p, %i)", __func__, session, limit); smlAssert(session); smlAssemblerSetRemoteMaxObjSize(session->assembler, limit); smlTrace(TRACE_EXIT, "%s", __func__); } /** Returns the maximum obj size that we can send. If both the sending and the * requested limit are set, this function will return the smaller one of both. * * Otherwise it will return the larger number. */ unsigned int smlSessionGetRemoteMaxObjSize(SmlSession *session) { smlTrace(TRACE_ENTRY, "%s(%p)", __func__, session); smlAssert(session); int result = smlAssemblerGetRemoteMaxObjSize(session->assembler); smlTrace(TRACE_EXIT, "%s => %i", __func__, result); return result; } /** Sets the obj size that will get transmitted to the remote side in the * tag. So this sets the maximum size of the object we want to receive. * If an item is larger, we return an error * * In this function, 0 means that no limit is set. * a value > 0 means that a limit is set. note that this is required if large object * handling has to be supported. * * The value is stored in the session since it has to be used by the assembler (to fill * the MaxObjSize tag) as well as by the session (to determine when to send an error if the * limit is violated) * * */ void smlSessionSetLocalMaxObjSize(SmlSession *session, unsigned int limit) { smlTrace(TRACE_ENTRY, "%s(%p, %u)", __func__, session, limit); smlAssert(session); int remoteLimit = smlSessionGetRemoteMaxObjSize(session); if (remoteLimit > 0) { /* The remote peer already sent MaxObjSize */ if ((unsigned int)remoteLimit > limit && limit > 0) { /* If the limit of the remote peer is higher * than the local limit then the local limit * must be used. */ session->localMaxObjSize = limit; } else { /* If the remote limit is not higher than * the local limit or of the local limit is * not set then the remote limit is used as * the local limit. */ session->localMaxObjSize = remoteLimit; } } else { /* If there is no remote limit then the local limit is used. */ session->localMaxObjSize = limit; } smlTrace(TRACE_EXIT, "%s => %d", __func__, session->localMaxObjSize); } unsigned int smlSessionGetLocalMaxObjSize(SmlSession *session) { smlAssert(session); return session->localMaxObjSize; } /*@}*/ /** @brief Sends a command with a parent * * This function can be used to send subcommands (for example a "Add" inside a "Sync"). You * are guaranteed that you will get a callback if this function returns TRUE. So either this function * returns FALSE (might occur if the command is not complete or if a OOM occured) or you will later * get a reply or an error in the callback. * * Note that if you dont set a callback function, libsyncml will automatically add a "NoResp". * * @param session The session * @param cmd The command to send * @param parent The parent of this command. NULL for syncbody * @param callback The callback that will receive the reply. Set to NULL if you dont want any replies. * @param userdata The userdata to pass to the callback * @param error A error struct * @return TRUE if successful, FALSE otherwise * */ SmlBool smlSessionSendCommand(SmlSession *session, SmlCommand *cmd, SmlCommand *parent, SmlStatusReplyCb callback, void *userdata, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p, %p, %p, %p)", __func__, session, cmd, parent, callback, userdata, error); smlAssert(session); smlAssert(cmd); CHECK_ERROR_REF if (!smlSessionStartCommand(session, cmd, parent, callback, userdata, error)) goto error; if (!smlSessionEndCommand(session, parent, error)) goto error; smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return FALSE; } /** @brief starts a command with a parent * * @param session The session * @param cmd The command to send * @param parent The parent of this command * @param callback The callback that will receive the reply. Set to NULL if you dont want any replies. * @param userdata The userdata to pass to the callback * @param error A error struct * @return TRUE if successful, FALSE otherwise * */ SmlBool smlSessionStartCommand(SmlSession *session, SmlCommand *cmd, SmlCommand *parent, SmlStatusReplyCb callback, void *userdata, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p, %p, %p, %p)", __func__, session, cmd, parent, callback, userdata, error); smlAssert(session); smlAssert(cmd); CHECK_ERROR_REF SmlSessionCommand *sesscmd = smlTryMalloc0(sizeof(SmlSessionCommand), error); if (!sesscmd) goto error; sesscmd->type = SML_SESSION_COMMAND_START; sesscmd->cmd = cmd; smlCommandRef(cmd); if (parent) { sesscmd->parent = parent; smlCommandRef(parent); } sesscmd->callback = callback; sesscmd->callbackUserdata = userdata; smlQueueSend(session->command_queue, sesscmd); smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return FALSE; } /** @brief ends a command * * @param session The session * @param parent The parent of this command, NULL for syncbody * @param error A error struct * @return TRUE if successful, FALSE otherwise * */ SmlBool smlSessionEndCommand(SmlSession *session, SmlCommand *parent, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, session, parent, error); smlAssert(session); CHECK_ERROR_REF SmlSessionCommand *sesscmd = smlTryMalloc0(sizeof(SmlSessionCommand), error); if (!sesscmd) goto error; sesscmd->type = SML_SESSION_COMMAND_END; if (parent) { sesscmd->parent = parent; smlCommandRef(parent); } smlQueueSend(session->command_queue, sesscmd); smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return FALSE; } /** @brief Sends a reply to a command * * This function sends a status reply to a command. * * This function might return an error in the case of an OOM situation or if you forgot to * fill in parts of the reply * * @param session The session * @param status The status to send * @param error A error struct * @return TRUE if successful, FALSE otherwise * */ SmlBool smlSessionSendReply(SmlSession *session, SmlStatus *status, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, session, status, error); smlAssert(session); smlAssert(status); CHECK_ERROR_REF SmlSessionCommand *sesscmd = smlTryMalloc0(sizeof(SmlSessionCommand), error); if (!sesscmd) goto error; sesscmd->type = SML_SESSION_STATUS; sesscmd->status = status; smlStatusRef(status); smlQueueSendPrio(session->command_queue, sesscmd); smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return FALSE; } /*@}*/ /*@}*/ libsyncml-0.5.4/libsyncml/sml_support.h100644 1750 1750 5170 11211710410 20160 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2005 Armin Bauer * Copyright (C) 2008 Michael Bell * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #ifndef _SML_SUPPORT_H_ #define _SML_SUPPORT_H_ /*! @ingroup SmlDebugAPI * @brief The type of the trace */ typedef enum { /** Used when entering a function. This will indent the callgraph */ TRACE_ENTRY, /** Used when exiting a function. This will unindent the callgraph */ TRACE_EXIT, /** Used for traces inside a function. Does not indent. */ TRACE_INTERNAL, /** Used for reporting errors. Does not ident. */ TRACE_ERROR, /** Used when exiting a function with a error. This will unindent the callgraph */ TRACE_EXIT_ERROR } SmlTraceType; /** Solaris g_strdup_vprintf crashes on NULL strings. * Therefore a macro was introduced to sanitize string parameters. */ #define VA_STRING(param) param?param:"NULL" void smlLog(const char *logname, const char *data, unsigned int size); void smlTrace(SmlTraceType type, const char *message, ...); char *smlPrintBinary(const char *data, int len); char *smlPrintHex(const char *data, int len); char *smlRandStr(int maxlength, SmlBool exact); void *smlTryMalloc0(long n_bytes, SmlError **error); typedef struct SmlThread { GThread *thread; gboolean started; GCond *started_cond; GMutex *started_mutex; GMainContext *context; GMainLoop *loop; } SmlThread; SmlThread *smlThreadNew(GMainContext *context, SmlError **error); void smlThreadFree(SmlThread *thread); void smlThreadStart(SmlThread *thread); void smlThreadStop(SmlThread *thread); typedef SmlBool (* SmlThreadCallFunctionType) ( gpointer data, SmlError **error); SmlBool smlThreadCallFunction( SmlThread *thread, SmlThreadCallFunctionType func, gpointer data, SmlError **error); void smlSafeFree(gpointer *address); void smlSafeCFree(char **address); #endif //_SML_SUPPORT_H_ libsyncml-0.5.4/libsyncml/parser/sml_wbxml.c100644 1750 1750 16472 11211710410 21113 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2005 Armin Bauer * Copyright (C) 2007-2009 Michael Bell * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include #include #include #include #include #include "libsyncml/sml_error_internals.h" #ifdef ENABLE_WBXML #include "sml_xml_assm.h" #include "sml_xml_assm_internals.h" #include "sml_xml_parse.h" #include "sml_xml_parse_internals.h" #include "sml_wbxml.h" #include "sml_wbxml_internals.h" SmlBool smlWbxmlConvertTo(WBXMLConvXML2WBXMLParams *params, const char *input, char **output, size_t *outputLen, SmlError** error) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p, %p, %p)", __func__, params, input, output, outputLen, error); smlAssert(input); smlAssert(strlen(input)); smlAssert(output); smlAssert(outputLen); WBXMLError wberror; wberror = wbxml_conv_xml2wbxml((WB_UTINY*)input, (WB_UTINY**)output, (WB_ULONG*)outputLen, params); if (wberror != WBXML_OK) goto error; smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error: smlErrorSet(error, SML_ERROR_GENERIC, (char *)wbxml_errors_string(wberror)); smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return FALSE; } SmlBool smlWbxmlConvertFrom(WBXMLConvWBXML2XMLParams *params, const char *input, size_t inputLen, char **output, size_t *outputLen, SmlError** error) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %i, %p, %p, %p)", __func__, params, input, inputLen, output, outputLen, error); WBXMLError wberror; smlTrace(TRACE_INTERNAL, "WBXML2 VERSION: %s", WBXML_LIB_VERSION); wberror = wbxml_conv_wbxml2xml_withlen((WB_UTINY*)input, inputLen, (WB_UTINY**)output, (WB_ULONG*)outputLen, params); if (wberror != WBXML_OK) goto error; smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error: smlErrorSet(error, SML_ERROR_GENERIC, (char *)wbxml_errors_string(wberror)); smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return FALSE; } static SmlBool smlWbxmlParserStart(SmlXmlParser *parser, const char *data, unsigned int size, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p, %p)", __func__, parser, data, size, error); CHECK_ERROR_REF smlAssert(parser); smlAssert(data); smlAssert(size); char *bin = smlPrintBinary(data, size); smlTrace(TRACE_INTERNAL, "Wbxml input: %s", bin); smlSafeCFree(&bin); smlLog("received-%i.wbxml", data, size); /* Ignorable whitespaces must be preserved because sometimes * a buggy mobile does not the its data objects correctly * encapsulated into CDATA. */ char *buffer = NULL; size_t buffer_size = 0; WBXMLConvWBXML2XMLParams params = {WBXML_ENCODER_XML_GEN_COMPACT, WBXML_LANG_UNKNOWN, 0, TRUE}; if (!smlWbxmlConvertFrom(¶ms, data, size, &buffer, &buffer_size, error)) goto error; smlTrace(TRACE_INTERNAL, "converted XML message: %s", buffer); if (!smlXmlParserStart(parser, buffer, buffer_size, error)) goto error; smlSafeCFree(&buffer); smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error: if (buffer) smlSafeCFree(&buffer); smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return FALSE; } SmlXmlParser *smlWbxmlParserNew(SmlParserFunctions *functions, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p)", __func__, functions, error); CHECK_ERROR_REF smlAssert(functions); SmlXmlParser *parser = smlXmlParserNew(functions, error); if (!parser) goto error; functions->start = (SmlParserStartFunction)smlWbxmlParserStart; smlTrace(TRACE_EXIT, "%s: %p", __func__, parser); return parser; error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return NULL; } SmlBool smlWbxmlAssemblerRun(SmlXmlAssembler *assm, char **data, unsigned int *size, SmlBool *end, SmlBool final, unsigned int maxsize, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p, %p, %i, %i, %p)", __func__, assm, data, size, end, final, maxsize, error); CHECK_ERROR_REF smlAssert(assm); smlAssert(data); smlAssert(size); char *buffer = NULL; unsigned int buffer_size = 0; if (!smlXmlAssemblerRun(assm, &buffer, &buffer_size, end, final, 0, error)) goto error; WBXMLConvXML2WBXMLParams params = {WBXML_VERSION_12, FALSE, FALSE, FALSE}; const char *opt = smlAssemblerGetOption(assm->assembler, "USE_STRTABLE"); if (opt && atoi(opt)) params.use_strtbl = TRUE; if (!smlWbxmlConvertTo(¶ms, buffer, data, size, error)) goto error; smlSafeCFree(&buffer); char *hex = smlPrintHex(*data, *size); smlTrace(TRACE_INTERNAL, "Wbxml assembled: %s", hex); smlSafeCFree(&hex); smlLog("sent-%i.wbxml", *data, *size); smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error: if (buffer) smlSafeCFree(&buffer); smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return FALSE; } unsigned int smlWbxmlAssemblerCheckSize(SmlXmlAssembler *assm, SmlBool headeronly, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %i, %p)", __func__, assm, headeronly, error); CHECK_ERROR_REF smlAssert(assm); unsigned int size = 0; char *data = NULL; char *buffer = NULL; unsigned int buffer_size = 0; if (!smlXmlAssemblerRunFull(assm, &buffer, &buffer_size, NULL, TRUE, FALSE, 0, error)) goto error; WBXMLConvXML2WBXMLParams params = {WBXML_VERSION_12, FALSE, FALSE, FALSE}; const char *opt = smlAssemblerGetOption(assm->assembler, "USE_STRTABLE"); if (opt && atoi(opt)) params.use_strtbl = TRUE; if (!smlWbxmlConvertTo(¶ms, buffer, &data, &size, error)) goto error_free_buffer; smlSafeCFree(&data); smlSafeCFree(&buffer); smlTrace(TRACE_EXIT, "%s: %i", __func__, size); return size; error_free_buffer: smlSafeCFree(&buffer); error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return 0; } /** @brief Creates a new XML assembler * * @param session The session for which to create the assembler * @param error A pointer to an error struct * @return The new assembler or NULL in the case of an error * */ SmlXmlAssembler *smlWbxmlAssemblerNew(SmlAssembler *assembler, SmlAssemblerFunctions *functions, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, assembler, functions, error); CHECK_ERROR_REF SmlXmlAssembler *assm = smlXmlAssemblerNew(assembler, functions, error); if (!assm) goto error; functions->run = (SmlAssemblerRunFunction)smlWbxmlAssemblerRun; functions->check_size = (SmlAssemblerCheckFunction)smlWbxmlAssemblerCheckSize; smlTrace(TRACE_EXIT, "%s: %p", __func__, assm); return assm; error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return NULL; } #endif libsyncml-0.5.4/libsyncml/parser/sml_xml_assm.h100644 1750 1750 5102 11211710410 21556 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2005 Armin Bauer * Copyright (C) 2008 Michael Bell * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ /** * @defgroup XmlAssembler XML Assembler * @ingroup XmlPublic * @brief Interfaces to assemble SyncML XML messages * */ /*@{*/ #ifndef _SML_XML_ASSM_H_ #define _SML_XML_ASSM_H_ typedef struct SmlXmlAssembler SmlXmlAssembler; SmlXmlAssembler *smlXmlAssemblerNew(SmlAssembler *assembler, SmlAssemblerFunctions *functions, SmlError **error); SmlBool smlXmlAssemblerAddHeader(SmlXmlAssembler *assembler, SmlSession *session, SmlError **error); // FIXME: not yet implemented // SmlBool smlXmlAssemblerAddCommand(SmlXmlAssembler *assembler, SmlCommand *cmd, SmlError **error); SmlBool smlXmlAssemblerAddStatus(SmlXmlAssembler *assembler, SmlStatus *status, SmlError **error); void smlXmlAssemblerFree(SmlXmlAssembler *assm); // FIXME: not yet implemented // void smlXmlAssemblerClean(SmlXmlAssembler *assm); SmlBool smlXmlAssemblerStart(SmlXmlAssembler *assm, SmlSession *session, SmlError **error); SmlBool smlXmlAssemblerEnd(SmlXmlAssembler *assm, SmlError **error); SmlBool smlXmlAssemblerRun(SmlXmlAssembler *assm, char **data, unsigned int *size, SmlBool *end, SmlBool final, unsigned int maxsize, SmlError **error); SmlBool smlXmlAssemblerRunFull(SmlXmlAssembler *assm, char **data, unsigned int *size, SmlBool *end, SmlBool final, SmlBool check, unsigned int maxsize, SmlError **error); SmlBool smlXmlDevInfAssemble(SmlDevInf *devinf, SmlDevInfVersion version, char **data, unsigned int *size, SmlError **error); /* This is necessary if the first message results in an error 407. * This error means authentication required. * After such an error the previous commands must be sent again. */ void smlXmlAssemblerRestoreCommands(SmlXmlAssembler *assm); #endif //_SML_XML_ASSM_H_ /*@}*/ libsyncml-0.5.4/libsyncml/parser/sml_xml_parse.c100644 1750 1750 336706 11211710410 22001 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2005 Armin Bauer * Copyright (C) 2007-2009 Michael Bell * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include #include #include #include #include #include #include "libsyncml/sml_error_internals.h" #include "sml_xml_parse.h" #include "sml_xml_parse_internals.h" #define BUFFER_SIZE 500 static SmlBool _smlXmlParserStep(SmlXmlParser *parser) { SmlBool ret = FALSE; do { ret = (xmlTextReaderRead(parser->reader) == 1) ? TRUE : FALSE; } while (ret && (xmlTextReaderNodeType(parser->reader) == XML_READER_TYPE_DOCUMENT_TYPE || \ xmlTextReaderNodeType(parser->reader) == XML_READER_TYPE_WHITESPACE || \ xmlTextReaderNodeType(parser->reader) == XML_READER_TYPE_SIGNIFICANT_WHITESPACE)); return ret; } static SmlBool _smlXmlParserStepData(SmlXmlParser *parser) { SmlBool ret = FALSE; do { ret = (xmlTextReaderRead(parser->reader) == 1) ? TRUE : FALSE; } while (ret && (xmlTextReaderNodeType(parser->reader) == XML_READER_TYPE_DOCUMENT_TYPE || \ xmlTextReaderNodeType(parser->reader) == XML_READER_TYPE_WHITESPACE)); return ret; } static SmlBool _smlXmlSkipNode(SmlXmlParser *parser) { int node_type; if (xmlTextReaderNext(parser->reader) != 1) return FALSE; node_type = xmlTextReaderNodeType(parser->reader); while (xmlTextReaderNodeType(parser->reader) == XML_READER_TYPE_DOCUMENT_TYPE || xmlTextReaderNodeType(parser->reader) == XML_READER_TYPE_WHITESPACE || xmlTextReaderNodeType(parser->reader) == XML_READER_TYPE_SIGNIFICANT_WHITESPACE) { if (!_smlXmlParserStep (parser)) return FALSE; } return TRUE; } static SmlBool _smlXmlParserExpectNode(SmlXmlParser *parser, int type, SmlBool empty, const char *name, SmlError **error) { CHECK_ERROR_REF if (!_smlXmlParserStep(parser)) { smlErrorSet(error, SML_ERROR_GENERIC, "No node at all"); return FALSE; } if (xmlTextReaderNodeType(parser->reader) != type) { smlErrorSet(error, SML_ERROR_GENERIC, "wrong node type"); return FALSE; } switch (type) { case XML_NODE_START: case XML_NODE_CLOSE: if (name) { if (!xmlTextReaderConstName(parser->reader)) { smlErrorSet(error, SML_ERROR_GENERIC, "no name"); return FALSE; } if (strcmp((char *)xmlTextReaderConstName(parser->reader), name)) { smlErrorSet(error, SML_ERROR_GENERIC, "Wrong name"); return FALSE; } } break; case XML_NODE_TEXT: if (!empty && !xmlTextReaderConstName(parser->reader)) { smlErrorSet(error, SML_ERROR_GENERIC, "Empty."); return FALSE; } break; default: smlErrorSet(error, SML_ERROR_GENERIC, "Unknown node type"); return FALSE; } return TRUE; } static SmlBool _smlXmlParserGetID(SmlXmlParser *parser, unsigned int *id, const char *name, SmlError **error) { CHECK_ERROR_REF smlAssert(parser); smlAssert(id); if (*id) { smlErrorSet(error, SML_ERROR_GENERIC, "Id already set"); goto error; } if (!_smlXmlParserExpectNode(parser, XML_NODE_TEXT, FALSE, NULL, error)) goto error; *id = atoi(g_strstrip((char *)xmlTextReaderConstValue(parser->reader))); if (!_smlXmlParserExpectNode(parser, XML_NODE_CLOSE, FALSE, name, error)) goto error; return TRUE; error: return FALSE; } static SmlBool _smlXmlParserGetString(SmlXmlParser *parser, char **string, const char *name, SmlError **error) { CHECK_ERROR_REF smlAssert(parser); smlAssert(string); if (*string) { smlErrorSet(error, SML_ERROR_GENERIC, "string already set"); goto error; } /* required for empty elements like */ if (xmlTextReaderIsEmptyElement(parser->reader)) { *string = g_strdup(""); return TRUE; } if (!_smlXmlParserStep(parser)) { smlErrorSet(error, SML_ERROR_GENERIC, "No node at all"); goto error_clear; } if (xmlTextReaderNodeType(parser->reader) == XML_NODE_TEXT) { *string = g_strstrip(g_strdup((char *)xmlTextReaderConstValue(parser->reader))); if (!_smlXmlParserExpectNode(parser, XML_NODE_CLOSE, FALSE, name, error)) goto error_clear; } else if (xmlTextReaderNodeType(parser->reader) == XML_NODE_CLOSE) { *string = g_strdup(""); } else { smlErrorSet(error, SML_ERROR_GENERIC, "wrong node type"); goto error_clear; } return TRUE; error_clear: *string = NULL; error: return FALSE; } static SmlBool _smlXmlParserGetData(SmlXmlParser *parser, char **string, unsigned int *size, const char *name, SmlError **error) { CHECK_ERROR_REF smlAssert(parser); smlAssert(string); int rc = 0; if (*string) { smlErrorSet(error, SML_ERROR_GENERIC, "string already set"); return FALSE; } xmlBuffer *buffer = xmlBufferCreateSize(BUFFER_SIZE); if (!buffer) { smlErrorSet(error, SML_ERROR_GENERIC, "Unable to create new buffer"); goto error; } xmlTextWriter *writer = xmlNewTextWriterMemory(buffer, 0); if (!writer) { smlErrorSet(error, SML_ERROR_GENERIC, "Unable to create new writer"); goto error_free_buffer; } /* SyncML 1.2 allows empty data elements */ if (xmlTextReaderIsEmptyElement(parser->reader)) goto out; while (1) { if (!_smlXmlParserStepData(parser)) { smlErrorSet(error, SML_ERROR_GENERIC, "There is a missing node during the data parsing of %s.", name); goto error_free_writer; } switch (xmlTextReaderNodeType(parser->reader)) { case XML_NODE_CLOSE: if (!strcmp((char *)xmlTextReaderConstName(parser->reader), name)) goto out; if (!xmlTextReaderIsEmptyElement(parser->reader)) rc = xmlTextWriterEndElement(writer); if (rc < 0) { smlErrorSet(error, SML_ERROR_GENERIC, "Unable to end node"); goto error_free_writer; } break; case XML_NODE_START: if (!xmlTextReaderIsEmptyElement(parser->reader)) rc = xmlTextWriterStartElementNS(writer, NULL, xmlTextReaderConstName(parser->reader), NULL); else rc = xmlTextWriterWriteElementNS(writer, NULL, xmlTextReaderConstName(parser->reader), NULL, (const xmlChar*)""); if (rc < 0) { smlErrorSet(error, SML_ERROR_GENERIC, "Unable to start node"); goto error_free_writer; } break; case XML_NODE_CDATA: case XML_NODE_TEXT: rc = xmlTextWriterWriteRaw(writer, xmlTextReaderConstValue(parser->reader)); if (rc < 0) { smlErrorSet(error, SML_ERROR_GENERIC, "Unable to add string"); goto error_free_writer; } break; case XML_READER_TYPE_SIGNIFICANT_WHITESPACE: rc = xmlTextWriterWriteRaw(writer, xmlTextReaderConstValue(parser->reader)); if (rc < 0) { smlErrorSet(error, SML_ERROR_GENERIC, "Unable to add string"); goto error_free_writer; } break; default: smlErrorSet(error, SML_ERROR_GENERIC, "Unknown node type"); goto error_free_writer; } } out: // do not call xmlTextWriterEndDocument here // the writer was not started with xmlTextWriterStartDocument // the function adds always a newline // if you load only a CDATA field then a newline is additional data // additional data invalidates size information of the remote peer // additional data crashs by this way all length checks if smlItemCheck !!! xmlFreeTextWriter(writer); *string = g_strndup((const char *) xmlBufferContent(buffer), xmlBufferLength(buffer)); if (size) *size = xmlBufferLength(buffer); xmlBufferFree(buffer); return TRUE; error_free_writer: xmlFreeTextWriter(writer); error_free_buffer: xmlBufferFree(buffer); error: *string = NULL; if (size) *size = 0; return FALSE; } static SmlBool _smlSyncHeaderParseDTD(SmlProtocolVersion *version, SmlXmlParser *parser, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, version, parser, error); CHECK_ERROR_REF smlAssert(parser); smlAssert(version); if (*version) { smlErrorSet(error, SML_ERROR_GENERIC, "dtd already set"); smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return FALSE; } char *dtd = NULL; if (!_smlXmlParserGetString(parser, &dtd, SML_ELEMENT_VERDTD, error)) goto error; if (!strcmp(dtd, "1.0")) *version = SML_VERSION_10; else if (!strcmp(dtd, "1.1")) *version = SML_VERSION_11; else if (!strcmp(dtd, "1.2")) *version = SML_VERSION_12; else { smlSafeCFree(&dtd); smlErrorSet(error, SML_ERROR_GENERIC, "Unknown VerDTD"); goto error; } smlSafeCFree(&dtd); smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error: *version = SML_VERSION_UNKNOWN; smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return FALSE; } static SmlBool _smlSyncHeaderParseProto(SmlProtocolType *type, SmlXmlParser *parser, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, type, parser, error); CHECK_ERROR_REF smlAssert(parser); smlAssert(type); if (*type) { smlErrorSet(error, SML_ERROR_GENERIC, "protocol already set"); smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return FALSE; } char *proto = NULL; if (!_smlXmlParserGetString(parser, &proto, SML_ELEMENT_VERPROTO, error)) goto error; if (!strcmp(proto, SML_VERSION_STRING_10) || !strcmp(proto, SML_VERSION_STRING_11) || !strcmp(proto, SML_VERSION_STRING_12)) *type = SML_PROTOCOL_SYNCML; else { smlSafeCFree(&proto); smlErrorSet(error, SML_ERROR_GENERIC, "Unknown VerProto"); goto error; } smlSafeCFree(&proto); smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error: *type = SML_PROTOCOL_UNKNOWN; smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return FALSE; } static SmlBool _smlLocationParse(SmlLocation **location, SmlXmlParser *parser, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, location, parser, error); CHECK_ERROR_REF smlAssert(parser); smlAssert(location); if (*location) { smlErrorSet(error, SML_ERROR_GENERIC, "Location already set"); smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return FALSE; } *location = smlTryMalloc0(sizeof(SmlLocation), error); if (!location) goto error; (*location)->refCount = 1; while (1) { if (!_smlXmlParserStep(parser)) { smlErrorSet(error, SML_ERROR_GENERIC, "Missing nodes"); goto error_free_location; } if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_TARGET) && \ xmlTextReaderNodeType(parser->reader) == XML_NODE_CLOSE) { break; } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_SOURCE) && \ xmlTextReaderNodeType(parser->reader) == XML_NODE_CLOSE) { break; } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_SOURCE_PARENT) && \ xmlTextReaderNodeType(parser->reader) == XML_NODE_CLOSE) { break; } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_TARGET_PARENT) && \ xmlTextReaderNodeType(parser->reader) == XML_NODE_CLOSE) { break; } else if (xmlTextReaderNodeType(parser->reader) != XML_NODE_START) { smlErrorSet(error, SML_ERROR_GENERIC, "The element %s is not a start node in locations (Target, Source, SourceParent or TargetParent).", xmlTextReaderConstName(parser->reader)); goto error_free_location; } if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_LOCURI)) { if (!_smlXmlParserGetString(parser, &((*location)->locURI), SML_ELEMENT_LOCURI, error)) goto error_free_location; } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_LOCNAME)) { if (!_smlXmlParserGetString(parser, &((*location)->locName), SML_ELEMENT_LOCNAME, error)) goto error_free_location; } else { smlErrorSet(error, SML_ERROR_GENERIC, "wrong initial node. expected SyncHdr"); goto error_free_location; } } if (!(*location)->locURI) { smlErrorSet(error, SML_ERROR_GENERIC, "No locURI set"); goto error_free_location; } smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error_free_location: smlLocationUnref(*location); error: *location = NULL; smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return FALSE; } static SmlBool _smlAnchorParse(SmlAnchor **anchor, SmlXmlParser *parser, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, anchor, parser, error); CHECK_ERROR_REF smlAssert(parser); smlAssert(anchor); if (*anchor) { smlErrorSet(error, SML_ERROR_GENERIC, "anchor already set"); smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return FALSE; } *anchor = smlTryMalloc0(sizeof(SmlAnchor), error); if (!anchor) goto error; while (1) { if (!_smlXmlParserStep(parser)) { smlErrorSet(error, SML_ERROR_GENERIC, "Missing nodes"); goto error_free_anchor; } if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_ANCHOR) && \ xmlTextReaderNodeType(parser->reader) == XML_NODE_CLOSE) { break; } else if (xmlTextReaderNodeType(parser->reader) != XML_NODE_START) { smlErrorSet(error, SML_ERROR_GENERIC, "The element %s is not a start node in Anchor.", xmlTextReaderConstName(parser->reader)); goto error_free_anchor; } if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_NEXT)) { if (!_smlXmlParserGetString(parser, &((*anchor)->next), SML_ELEMENT_NEXT, error)) goto error_free_anchor; } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_LAST)) { if (!_smlXmlParserGetString(parser, &((*anchor)->last), SML_ELEMENT_LAST, error)) goto error_free_anchor; } else { smlErrorSet(error, SML_ERROR_GENERIC, "wrong initial node"); goto error_free_anchor; } } if (!(*anchor)->next) { smlErrorSet(error, SML_ERROR_GENERIC, "No next set"); goto error_free_anchor; } smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error_free_anchor: smlAnchorFree(*anchor); error: *anchor = NULL; smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return FALSE; } static SmlBool _smlChalMetaParse(SmlXmlParser *parser, char **format, char **type, char **nonce, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p, %p, %p, %p, %p)", __func__, parser, format, type, nonce, error); CHECK_ERROR_REF smlAssert(parser); while (1) { if (!_smlXmlParserStep(parser)) { smlErrorSet(error, SML_ERROR_GENERIC, "Missing nodes"); goto error; } if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_META) && \ xmlTextReaderNodeType(parser->reader) == XML_NODE_CLOSE) { break; } else if (xmlTextReaderNodeType(parser->reader) != XML_NODE_START) { smlErrorSet(error, SML_ERROR_GENERIC, "The element %s is not a start node in Chal/Meta.", xmlTextReaderConstName(parser->reader)); goto error; } if (type && !strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_TYPE)) { if (!_smlXmlParserGetString(parser, type, SML_ELEMENT_TYPE, error)) goto error; } else if (format && !strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_FORMAT)) { if (!_smlXmlParserGetString(parser, format, SML_ELEMENT_FORMAT, error)) goto error; } else if (format && !strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_NEXTNONCE)) { if (!_smlXmlParserGetString(parser, nonce, SML_ELEMENT_NEXTNONCE, error)) goto error; } else { smlErrorSet(error, SML_ERROR_GENERIC, "wrong initial node: %s", xmlTextReaderConstName(parser->reader)); goto error; } } smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error: if (format) *format = NULL; if (nonce) *nonce = NULL; if (type) *type = NULL; smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return FALSE; } static SmlBool _smlCommandMetaParse(SmlXmlParser *parser, char **format, char **type, SmlAnchor **anchor, unsigned int *size, int *maxobjsize, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p, %p, %p, %p, %p)", __func__, parser, format, type, anchor, size, maxobjsize, error); CHECK_ERROR_REF smlAssert(parser); if (maxobjsize) *maxobjsize = -1; if (xmlTextReaderIsEmptyElement(parser->reader)) { /* empty meta element */ smlTrace(TRACE_EXIT, "%s - empty meta element", __func__); return TRUE; } while (1) { if (!_smlXmlParserStep(parser)) { smlErrorSet(error, SML_ERROR_GENERIC, "Missing nodes"); goto error; } if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_MEM)) { /* Ignored for now */ smlTrace(TRACE_INTERNAL, "%s: Skipping mem node"); if (!_smlXmlSkipNode(parser)) { smlErrorSet(error, SML_ERROR_GENERIC, "Unable to skip mem node"); goto error; } } if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_META) && \ xmlTextReaderNodeType(parser->reader) == XML_NODE_CLOSE) { break; } else if (xmlTextReaderNodeType(parser->reader) != XML_NODE_START) { smlErrorSet(error, SML_ERROR_GENERIC, "The element %s is not a start node in Command/Meta.", xmlTextReaderConstName(parser->reader)); goto error; } if (type && !strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_TYPE)) { if (!_smlXmlParserGetString(parser, type, SML_ELEMENT_TYPE, error)) goto error; } else if (anchor && !strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_ANCHOR)) { if (!_smlAnchorParse(anchor, parser, error)) goto error; } else if (format && !strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_FORMAT)) { if (!_smlXmlParserGetString(parser, format, SML_ELEMENT_FORMAT, error)) goto error; } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_MARK)) { /* Ignore the mark for now */ char *mark = NULL; if (!_smlXmlParserGetString(parser, &mark, SML_ELEMENT_MARK, error)) goto error; smlSafeCFree(&mark); } else if (size && !strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_SIZE)) { if (!_smlXmlParserGetID(parser, size, SML_ELEMENT_SIZE, error)) goto error; } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_MAXOBJSIZE)) { /* MaxObjSize must be parsed even if there is no maxobjsize pointer */ unsigned int loc_maxobjsize = 0; if (!_smlXmlParserGetID(parser, &loc_maxobjsize, SML_ELEMENT_MAXOBJSIZE, error)) goto error; if (maxobjsize) *maxobjsize = loc_maxobjsize; } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_VERSION)) { /* Ignore the version for now */ char *version = NULL; if (!_smlXmlParserGetString(parser, &version, SML_ELEMENT_VERSION, error)) goto error; smlSafeCFree(&version); } else { smlErrorSet(error, SML_ERROR_GENERIC, "wrong initial node for meta information: %s", xmlTextReaderConstName(parser->reader)); goto error; } } smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error: if (format) *format = NULL; if (anchor) *anchor = NULL; if (type) *type = NULL; smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return FALSE; } static SmlItem *_smlItemParse(SmlXmlParser *parser, SmlCommand *cmd, SmlCommandType type, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %i, %p)", __func__, parser, cmd, type, error); CHECK_ERROR_REF smlAssert(parser); if (parser->gotMoreData) { smlErrorSet(error, SML_ERROR_GENERIC, "Last item already had more data set"); goto error; } SmlItem *item = smlItemNew(0, error); if (!item) goto error; /* If the item is an empty element then return immediately. */ if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_ITEM) && xmlTextReaderIsEmptyElement(parser->reader)) { smlTrace(TRACE_EXIT, "%s - empty item", __func__); return item; } if (!_smlXmlParserStep(parser)) { smlErrorSet(error, SML_ERROR_GENERIC, "The first element inside of an Item structure cannot be parsed."); goto error_free_item; } while (1) { if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_ITEM) && \ xmlTextReaderNodeType(parser->reader) == XML_NODE_CLOSE) { break; } else if (xmlTextReaderNodeType(parser->reader) != XML_NODE_START) { smlErrorSet(error, SML_ERROR_GENERIC, "The element %s is not a start node in Item.", xmlTextReaderConstName(parser->reader)); goto error_free_item; } if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_SOURCE)) { SmlLocation *source = NULL; if (!_smlLocationParse(&source, parser, error)) goto error_free_item; smlItemSetSource(item, source); smlLocationUnref(source); } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_TARGET)) { SmlLocation *target = NULL; if (!_smlLocationParse(&target, parser, error)) goto error_free_item; smlItemSetTarget(item, target); smlLocationUnref(target); } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_SOURCE_PARENT)) { SmlLocation *source = NULL; if (!_smlLocationParse(&source, parser, error)) goto error_free_item; smlItemSetSourceParent(item, source); smlLocationUnref(source); } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_TARGET_PARENT)) { SmlLocation *target = NULL; if (!_smlLocationParse(&target, parser, error)) goto error_free_item; smlItemSetTargetParent(item, target); smlLocationUnref(target); } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_META)) { switch (type) { case SML_COMMAND_TYPE_ALERT: if (!cmd) { /* This is an item inside a status. * We must parse the meta data * but we ignore the content completely. * FIXME: Can we ignore the content? */ if (!_smlCommandMetaParse(parser, NULL, NULL, NULL, NULL, NULL, error)) goto error_free_item; } else { /* Some phones send the maxobjsize in the alert */ if (!_smlCommandMetaParse(parser, NULL, &(cmd->private.alert.contentType), &cmd->private.alert.anchor, NULL, &(cmd->private.alert.maxObjSize), error)) goto error_free_item; } break; case SML_COMMAND_TYPE_ADD: case SML_COMMAND_TYPE_DELETE: case SML_COMMAND_TYPE_REPLACE: if (!_smlCommandMetaParse(parser, NULL, &(item->contenttype), NULL, &cmd->size, NULL, error)) goto error_free_item; break; case SML_COMMAND_TYPE_RESULTS: case SML_COMMAND_TYPE_PUT:; /* Some phones send the type information for the devinf put * not in the put itself but in the item */ if (!_smlCommandMetaParse(parser, NULL, &(item->contenttype), NULL, NULL, NULL, error)) goto error_free_item; if (!item->contenttype) goto error_free_item; break; default: smlErrorSet(error, SML_ERROR_GENERIC, "Unknown command type"); goto error_free_item; } } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_DATA)) { /* Do nothing if the Data element is empty. * The first emptyness test only covers . * * Example: Funambol with WBXML on scheduleworld.com */ if (!xmlTextReaderIsEmptyElement(parser->reader)) { switch (type) { case SML_COMMAND_TYPE_ALERT: if (!_smlXmlParserStep(parser)) { smlErrorSet(error, SML_ERROR_GENERIC, "The next element after the starting Data element in an Item is missing."); goto error_free_item; } if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_DATA) && xmlTextReaderNodeType(parser->reader) == XML_NODE_CLOSE) { /* Do nothing if the Data element is empty. * This only covers . * * Example: Funambol with XML on scheduleworld.com */ smlTrace(TRACE_INTERNAL, "%s: detected empty data element", __func__); break; } SmlAnchor *anchor = NULL; if (xmlTextReaderNodeType(parser->reader) == XML_NODE_TEXT) { /* Google just copies the element Next from the Anchor * Please see ticket #230 for more details. */ anchor = smlTryMalloc0(sizeof(SmlAnchor), error); if (!anchor) goto error_free_item; anchor->next = g_strdup((char *)xmlTextReaderConstValue(parser->reader)); } else { /* normal behaviour with anchor copy */ if (!_smlAnchorParse(&anchor, parser, error)) goto error_free_item; } item->anchor = anchor; if (!_smlXmlParserStep(parser)) { smlErrorSet(error, SML_ERROR_GENERIC, "The closing Data element in an Item is missing."); goto error_free_item; } break; default:; char *data = NULL; unsigned int size = 0; if (!_smlXmlParserGetData(parser, &data, &size, SML_ELEMENT_DATA, error)) goto error_free_item; if (!smlItemAddData(item, data, size, error)) { smlSafeCFree(&data); goto error_free_item; } smlSafeCFree(&data); } } } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_MOREDATA)) { if (parser->version == SML_VERSION_10) { smlErrorSet(error, SML_ERROR_GENERIC, "SyncML 1.0 does not allow MoreData"); goto error_free_item; } item->moreData = TRUE; parser->gotMoreData = TRUE; if (!_smlXmlParserStep(parser)) { smlErrorSet(error, SML_ERROR_GENERIC, "Missing nodes2"); goto error_free_item; } if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_MOREDATA) && \ xmlTextReaderNodeType(parser->reader) == XML_NODE_CLOSE) { if (!_smlXmlParserStep(parser)) { smlErrorSet(error, SML_ERROR_GENERIC, "Missing nodes3"); goto error_free_item; } } continue; } else { smlErrorSet(error, SML_ERROR_GENERIC, "The element Item does not support the child element %s.", xmlTextReaderConstName(parser->reader)); goto error_free_item; } if (!_smlXmlParserStep(parser)) { smlErrorSet(error, SML_ERROR_GENERIC, "The next element in an Item structure is missing."); goto error_free_item; } } smlTrace(TRACE_EXIT, "%s", __func__); return item; error_free_item: smlItemUnref(item); error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return NULL; } static SmlCred *_smlCredParse(SmlXmlParser *parser, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p)", __func__, parser, error); CHECK_ERROR_REF smlAssert(parser); SmlCred *cred = NULL; char *format = NULL; char *type = NULL; char *data = NULL; while (1) { if (!_smlXmlParserStep(parser)) { smlErrorSet(error, SML_ERROR_GENERIC, "Missing nodes"); goto error; } if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_CRED) && \ xmlTextReaderNodeType(parser->reader) == XML_NODE_CLOSE) { break; } else if (xmlTextReaderNodeType(parser->reader) != XML_NODE_START) { smlErrorSet(error, SML_ERROR_GENERIC, "The element %s is not a start node in Cred.", xmlTextReaderConstName(parser->reader)); goto error; } if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_META)) { if (!_smlCommandMetaParse(parser, &format, &type, NULL, NULL, NULL, error)) goto error; } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_DATA)) { if (!_smlXmlParserGetString(parser, &data, SML_ELEMENT_DATA, error)) goto error; } else { smlErrorSet(error, SML_ERROR_GENERIC, "wrong initial node %s", xmlTextReaderConstName(parser->reader)); goto error; } } cred = smlCredNewFromString(type, format, data, error); error: if (data) smlSafeCFree(&data); if (format) smlSafeCFree(&format); if (type) smlSafeCFree(&type); if (!smlErrorIsSet(error)) { smlTrace(TRACE_EXIT, "%s: %p", __func__, cred); return cred; } else { if (cred) smlCredUnref(cred); smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return NULL; } } static SmlChal *_smlChalParse(SmlXmlParser *parser, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p)", __func__, parser, error); CHECK_ERROR_REF smlAssert(parser); char *format = NULL; char *type = NULL; char *nonce = NULL; while (1) { if (!_smlXmlParserStep(parser)) { smlErrorSet(error, SML_ERROR_GENERIC, "Missing nodes"); goto error; } if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_CHAL) && \ xmlTextReaderNodeType(parser->reader) == XML_NODE_CLOSE) { break; } else if (xmlTextReaderNodeType(parser->reader) != XML_NODE_START) { smlErrorSet(error, SML_ERROR_GENERIC, "The element %s is not a start node in Chal.", xmlTextReaderConstName(parser->reader)); goto error; } if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_META)) { if (!_smlChalMetaParse(parser, &format, &type, &nonce, error)) goto error; } else { smlErrorSet(error, SML_ERROR_GENERIC, "wrong initial node %s", xmlTextReaderConstName(parser->reader)); goto error; } } if (format && strcmp(format, SML_BASE64)) { smlErrorSet(error, SML_ERROR_GENERIC, "Unknown format"); goto error; } SmlAuthType auth; if (!type || !strcmp(type, SML_AUTH_BASIC)) { auth = SML_AUTH_TYPE_BASIC; } else if (!strcmp(type, SML_AUTH_MD5)) { auth = SML_AUTH_TYPE_MD5; } else { smlErrorSet(error, SML_ERROR_GENERIC, "Unknown type"); goto error; } if (format) smlSafeCFree(&format); if (type) smlSafeCFree(&type); SmlChal *chal = NULL; if (nonce || auth == SML_AUTH_TYPE_MD5) chal = smlChalNewFromBase64(auth, nonce, error); else chal = smlChalNew(auth, error); if (!chal) goto error; if (nonce) smlSafeCFree(&nonce); smlTrace(TRACE_EXIT, "%s: %p", __func__, chal); return chal; error: if (format) smlSafeCFree(&format); if (type) smlSafeCFree(&type); if (nonce) smlSafeCFree(&nonce); smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return NULL; } static SmlBool _smlChangeParse(SmlXmlParser *parser, SmlCommand **cmd, SmlCommandType type, const char *name, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %i, %s, %p)", __func__, parser, type, VA_STRING(name), error); CHECK_ERROR_REF smlAssert(parser); smlAssert(name); char *contenttype = NULL; *cmd = smlCommandNew(type, error); if (!*cmd) goto error; (*cmd)->refCount = 1; while (1) { if (!_smlXmlParserStep(parser)) { smlErrorSet(error, SML_ERROR_GENERIC, "Missing nodes"); goto error_free_cmd; } if (!strcmp((char *)xmlTextReaderConstName(parser->reader), name) && \ xmlTextReaderNodeType(parser->reader) == XML_NODE_CLOSE) { break; } else if (xmlTextReaderNodeType(parser->reader) != XML_NODE_START) { smlErrorSet(error, SML_ERROR_GENERIC, "The element %s is not a start node in %s.", xmlTextReaderConstName(parser->reader), name); goto error_free_cmd; } if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_CMDID)) { if (!_smlXmlParserGetID(parser, &((*cmd)->cmdID), SML_ELEMENT_CMDID, error)) goto error_free_cmd; } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_ITEM)) { SmlItem *item = _smlItemParse(parser, *cmd, type, error); if (!item) goto error_free_cmd; (*cmd)->private.change.items = g_list_append((*cmd)->private.change.items, item); if (!(*cmd)->private.change.items) { smlItemUnref(item); smlErrorSet(error, SML_ERROR_GENERIC, "g_list_append for item list of change command failed."); goto error_free_cmd; } } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_META)) { if (!_smlCommandMetaParse(parser, NULL, &contenttype, NULL, &(*cmd)->size, NULL, error)) goto error_free_cmd; } else { smlErrorSet(error, SML_ERROR_GENERIC, "wrong initial node"); goto error_free_cmd; } } if (!(*cmd)->cmdID) { smlErrorSet(error, SML_ERROR_GENERIC, "No cmdid set"); goto error_free_cmd; } if (!(*cmd)->private.change.items || !g_list_length((*cmd)->private.change.items)) { smlErrorSet(error, SML_ERROR_GENERIC, "No items set"); goto error_free_cmd; } /* some clients set the contentype in the item, don't overwrite it with NULL */ guint i; for (i=0; i < g_list_length((*cmd)->private.change.items); i++) { SmlItem *item = g_list_nth_data((*cmd)->private.change.items, i); if (item->contenttype == NULL && contenttype) { item->contenttype = g_strdup(contenttype); } } if (contenttype) smlSafeCFree(&contenttype); for (i=0; i < g_list_length((*cmd)->private.change.items); i++) { SmlItem *item = g_list_nth_data((*cmd)->private.change.items, i); if ((*cmd)->size && !item->size) item->size = (*cmd)->size; } switch (type) { case SML_COMMAND_TYPE_ADD: (*cmd)->private.change.type = SML_CHANGE_ADD; break; case SML_COMMAND_TYPE_REPLACE: (*cmd)->private.change.type = SML_CHANGE_REPLACE; break; case SML_COMMAND_TYPE_DELETE: (*cmd)->private.change.type = SML_CHANGE_DELETE; break; default: smlErrorSet(error, SML_ERROR_GENERIC, "Unknown change type set"); goto error_free_cmd; } if (!(*cmd)->source) { SmlItem *item = g_list_nth_data((*cmd)->private.change.items, 0); if (item->source) { (*cmd)->source = smlLocationClone(item->source, error); if (!(*cmd)->source) goto error_free_cmd; } } if (!(*cmd)->target) { SmlItem *item = g_list_nth_data((*cmd)->private.change.items, 0); if (item->target) { (*cmd)->target = smlLocationClone(item->target, error); if (!(*cmd)->target) goto error_free_cmd; } } /* Step once more */ if (!_smlXmlParserStep(parser)) { smlErrorSet(error, SML_ERROR_GENERIC, "Missing nodes"); goto error_free_cmd; } smlTrace(TRACE_EXIT, "%s: %p", __func__, *cmd); return TRUE; error_free_cmd: smlCommandUnref(*cmd); error: if (contenttype) smlSafeCFree(&contenttype); *cmd = NULL; smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return FALSE; } static SmlBool _smlMessageParseSynchdrMeta(SmlXmlParser *parser, unsigned int *maxmsgsize, unsigned int *maxobjsize, char **emi, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p, %p)", __func__, parser, maxmsgsize, maxobjsize, error); CHECK_ERROR_REF smlAssert(parser); smlAssert(maxmsgsize); smlAssert(maxobjsize); smlAssert(emi); while (1) { if (!_smlXmlParserStep(parser)) { smlErrorSet(error, SML_ERROR_GENERIC, "Missing nodes"); goto error; } if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_META) && \ xmlTextReaderNodeType(parser->reader) == XML_NODE_CLOSE) { break; } else if (xmlTextReaderNodeType(parser->reader) != XML_NODE_START) { smlErrorSet(error, SML_ERROR_GENERIC, "The element %s is not a start node in SyncHdr/Meta.", xmlTextReaderConstName(parser->reader)); goto error; } if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_MAXMSGSIZE)) { if (!_smlXmlParserGetID(parser, maxmsgsize, SML_ELEMENT_MAXMSGSIZE, error)) goto error; } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_MAXOBJSIZE)) { if (!_smlXmlParserGetID(parser, maxobjsize, SML_ELEMENT_MAXOBJSIZE, error)) goto error; } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_EMI)) { if (!_smlXmlParserGetString(parser, emi, SML_ELEMENT_EMI, error)) goto error; } else { smlErrorSet(error, SML_ERROR_GENERIC, "wrong initial node. expected MaxMsgSize, MaxObjSize or EMI. Instead of that: %s", xmlTextReaderConstName(parser->reader)); goto error; } } if (!(*maxmsgsize) && !(*maxobjsize)) { smlErrorSet(error, SML_ERROR_GENERIC, "No maxmsgsize set"); goto error; } smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error: *maxmsgsize = 0; *maxobjsize = 0; smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return FALSE; } static SmlBool _smlAlertParse(SmlXmlParser *parser, SmlCommand **cmd, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, parser, cmd, error); CHECK_ERROR_REF smlAssert(parser); smlAssert(cmd); *cmd = smlCommandNew(SML_COMMAND_TYPE_ALERT, error); if (!*cmd) goto error; (*cmd)->refCount = 1; (*cmd)->private.alert.maxObjSize = -1; while (1) { if (!_smlXmlParserStep(parser)) { smlErrorSet(error, SML_ERROR_GENERIC, "Missing nodes"); goto error_free_cmd; } if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_ALERT) && \ xmlTextReaderNodeType(parser->reader) == XML_NODE_CLOSE) { break; } else if (xmlTextReaderNodeType(parser->reader) != XML_NODE_START) { smlErrorSet(error, SML_ERROR_GENERIC, "The element %s is not a start node in Alert.", xmlTextReaderConstName(parser->reader)); goto error_free_cmd; } if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_CMDID)) { if (!_smlXmlParserGetID(parser, &((*cmd)->cmdID), SML_ELEMENT_CMDID, error)) goto error_free_cmd; } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_ITEM)) { SmlItem *item = _smlItemParse(parser, (*cmd), SML_COMMAND_TYPE_ALERT, error); if (!item) goto error_free_cmd; (*cmd)->target = item->target; item->target = NULL; (*cmd)->source = item->source; item->source = NULL; smlItemUnref(item); } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_DATA)) { unsigned int id = 0; if (!_smlXmlParserGetID(parser, &id, SML_ELEMENT_DATA, error)) goto error_free_cmd; (*cmd)->private.alert.type = smlAlertTypeConvert(id, error); if ((*cmd)->private.alert.type == SML_ALERT_UNKNOWN && *error != NULL) goto error_free_cmd; } else { smlErrorSet(error, SML_ERROR_GENERIC, "wrong initial node %s", xmlTextReaderConstName(parser->reader)); goto error_free_cmd; } } if (!(*cmd)->private.alert.type) { smlErrorSet(error, SML_ERROR_GENERIC, "No alert type set"); goto error_free_cmd; } /* Step once more */ if (!_smlXmlParserStep(parser)) { smlErrorSet(error, SML_ERROR_GENERIC, "Missing nodes"); goto error_free_cmd; } smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error_free_cmd: smlCommandUnref(*cmd); error: *cmd = NULL; smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return FALSE; } static SmlParserResult _smlCommandSyncParse(SmlXmlParser *parser, SmlCommand **cmd, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, parser, cmd, error); CHECK_ERROR_REF smlAssert(parser); smlAssert(cmd); *cmd = smlCommandNew(SML_COMMAND_TYPE_SYNC, error); if (!*cmd) goto error; (*cmd)->private.sync.maxObjSize = -1; while (1) { if (!_smlXmlParserStep(parser)) { smlErrorSet(error, SML_ERROR_GENERIC, "Missing nodes"); goto error_free_cmd; } if (xmlTextReaderNodeType(parser->reader) == XML_NODE_CLOSE && !strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_SYNC)) break; else if (xmlTextReaderNodeType(parser->reader) != XML_NODE_START) { smlErrorSet(error, SML_ERROR_GENERIC, "The element %s is not a start node in Sync.", xmlTextReaderConstName(parser->reader)); goto error_free_cmd; } if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_ADD) || \ !strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_REPLACE) || \ !strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_DELETE)) break; if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_CMDID)) { if (!_smlXmlParserGetID(parser, &((*cmd)->cmdID), SML_ELEMENT_CMDID, error)) goto error_free_cmd; } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_ITEM)) { SmlItem *item = _smlItemParse(parser, (*cmd), SML_COMMAND_TYPE_SYNC, error); if (!item) goto error_free_cmd; } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_META)) { if (!_smlCommandMetaParse(parser, NULL, NULL, NULL, NULL, &((*cmd)->private.sync.maxObjSize), error)) goto error; } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_TARGET)) { if (!_smlLocationParse(&(*cmd)->target, parser, error)) goto error_free_cmd; } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_SOURCE)) { if (!_smlLocationParse(&(*cmd)->source, parser, error)) goto error_free_cmd; } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_NUMBEROFCHANGES)) { (*cmd)->private.sync.hasNumChanged = TRUE; if (!_smlXmlParserGetID(parser, &((*cmd)->private.sync.numChanged), SML_ELEMENT_NUMBEROFCHANGES, error)) goto error_free_cmd; } else { smlErrorSet(error, SML_ERROR_GENERIC, "wrong initial node: %s", xmlTextReaderConstName(parser->reader)); goto error_free_cmd; } } smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error_free_cmd: smlCommandUnref(*cmd); error: *cmd = NULL; smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return FALSE; } static SmlMapItem *_smlMapItemParse(SmlXmlParser *parser, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p)", __func__, parser, error); CHECK_ERROR_REF smlAssert(parser); SmlMapItem *item = smlTryMalloc0(sizeof(SmlMapItem), error); if (!item) goto error; item->refCount = 1; while (1) { if (!_smlXmlParserStep(parser)) { smlErrorSet(error, SML_ERROR_GENERIC, "Missing nodes"); goto error_free_item; } if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_MAPITEM) && \ xmlTextReaderNodeType(parser->reader) == XML_NODE_CLOSE) { break; } else if (xmlTextReaderNodeType(parser->reader) != XML_NODE_START) { smlErrorSet(error, SML_ERROR_GENERIC, "The element %s is not a start node in MapItem.", xmlTextReaderConstName(parser->reader)); goto error_free_item; } if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_SOURCE)) { if (!_smlLocationParse(&item->source, parser, error)) goto error_free_item; } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_TARGET)) { if (!_smlLocationParse(&item->target, parser, error)) goto error_free_item; } else { smlErrorSet(error, SML_ERROR_GENERIC, "wrong initial node %s", xmlTextReaderConstName(parser->reader)); goto error_free_item; } } smlTrace(TRACE_EXIT, "%s", __func__); return item; error_free_item: smlMapItemUnref(item); error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return NULL; } static SmlBool _smlCommandMapParse(SmlXmlParser *parser, SmlCommand **cmd, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, parser, cmd, error); CHECK_ERROR_REF smlAssert(parser); smlAssert(cmd); *cmd = smlCommandNew(SML_COMMAND_TYPE_MAP, error); if (!*cmd) goto error; (*cmd)->refCount = 1; while (1) { if (!_smlXmlParserStep(parser)) { smlErrorSet(error, SML_ERROR_GENERIC, "Missing nodes"); goto error_free_cmd; } if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_MAP) && \ xmlTextReaderNodeType(parser->reader) == XML_NODE_CLOSE) { break; } else if (xmlTextReaderNodeType(parser->reader) != XML_NODE_START) { smlErrorSet(error, SML_ERROR_GENERIC, "The element %s is not a start node in Map.", xmlTextReaderConstName(parser->reader)); goto error_free_cmd; } if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_CMDID)) { if (!_smlXmlParserGetID(parser, &((*cmd)->cmdID), SML_ELEMENT_CMDID, error)) goto error_free_cmd; } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_MAPITEM)) { SmlMapItem *item = _smlMapItemParse(parser, error); if (!item) goto error_free_cmd; (*cmd)->private.map.items = g_list_append((*cmd)->private.map.items, item); } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_TARGET)) { if (!_smlLocationParse(&(*cmd)->target, parser, error)) goto error_free_cmd; } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_SOURCE)) { if (!_smlLocationParse(&(*cmd)->source, parser, error)) goto error_free_cmd; } else { smlErrorSet(error, SML_ERROR_GENERIC, "wrong initial node"); goto error_free_cmd; } } /* Step once more */ if (!_smlXmlParserStep(parser)) { smlErrorSet(error, SML_ERROR_GENERIC, "Missing nodes"); goto error_free_cmd; } smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error_free_cmd: smlCommandUnref(*cmd); error: *cmd = NULL; smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return FALSE; } static SmlBool _smlCommandAccessParse(SmlXmlParser *parser, SmlCommand **cmd, SmlCommandType type, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %i, %p)", __func__, parser, cmd, type, error); CHECK_ERROR_REF smlAssert(parser); smlAssert(cmd); char *contenttype = NULL; *cmd = smlCommandNew(type, error); if (!*cmd) goto error; (*cmd)->refCount = 1; while (1) { if (!_smlXmlParserStep(parser)) { smlErrorSet(error, SML_ERROR_GENERIC, "Missing nodes"); goto error_free_cmd; } if ((*cmd)->type == SML_COMMAND_TYPE_PUT &&!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_PUT) && \ xmlTextReaderNodeType(parser->reader) == XML_NODE_CLOSE) { break; } else if ((*cmd)->type == SML_COMMAND_TYPE_GET &&!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_GET) && \ xmlTextReaderNodeType(parser->reader) == XML_NODE_CLOSE) { break; } else if (xmlTextReaderNodeType(parser->reader) != XML_NODE_START) { smlErrorSet(error, SML_ERROR_GENERIC, "The element %s is not a start node in Put or Get.", xmlTextReaderConstName(parser->reader)); goto error_free_cmd; } if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_CMDID)) { if (!_smlXmlParserGetID(parser, &((*cmd)->cmdID), SML_ELEMENT_CMDID, error)) goto error_free_cmd; } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_ITEM)) { (*cmd)->private.access.item = _smlItemParse(parser, (*cmd), (*cmd)->type, error); if (!(*cmd)->private.access.item) goto error_free_cmd; (*cmd)->target = (*cmd)->private.access.item->target; (*cmd)->private.access.item->target = NULL; (*cmd)->source = (*cmd)->private.access.item->source; (*cmd)->private.access.item->source = NULL; } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_META)) { char *format = NULL; if (!_smlCommandMetaParse(parser, &format, &contenttype, NULL, NULL, NULL, error)) goto error_free_cmd; if (format) smlSafeCFree(&format); } else { smlErrorSet(error, SML_ERROR_GENERIC, "wrong initial node"); goto error_free_cmd; } } if (!(*cmd)->private.access.item) { smlErrorSet(error, SML_ERROR_GENERIC, "Put/Get is missing item"); goto error_free_cmd; } /* We only use the content type of the put command if the item itself did not have * a content type set */ if (!(*cmd)->private.access.item->contenttype && contenttype) (*cmd)->private.access.item->contenttype = g_strdup(contenttype); if (contenttype) smlSafeCFree(&contenttype); /* Step once more */ if (!_smlXmlParserStep(parser)) { smlErrorSet(error, SML_ERROR_GENERIC, "Missing nodes"); goto error_free_cmd; } smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error_free_cmd: smlCommandUnref(*cmd); error: *cmd = NULL; if (contenttype) smlSafeCFree(&contenttype); smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return FALSE; } static SmlBool _smlResultsParse(SmlXmlParser *parser, SmlCommand **cmd, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, parser, cmd, error); CHECK_ERROR_REF smlAssert(parser); smlAssert(cmd); char *contenttype = NULL; char *locURI = NULL; *cmd = smlCommandNew(SML_COMMAND_TYPE_RESULTS, error); if (!*cmd) goto error; (*cmd)->refCount = 1; (*cmd)->private.results.status = smlTryMalloc0(sizeof(SmlStatus), error); if (!(*cmd)->private.results.status) goto error; (*cmd)->private.results.status->refCount = 1; (*cmd)->private.results.status->result = (*cmd); (*cmd)->private.results.status->type = SML_COMMAND_TYPE_RESULTS; while (1) { if (!_smlXmlParserStep(parser)) { smlErrorSet(error, SML_ERROR_GENERIC, "Missing nodes"); goto error_free_cmd; } if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_RESULTS) && \ xmlTextReaderNodeType(parser->reader) == XML_NODE_CLOSE) { break; } else if (xmlTextReaderNodeType(parser->reader) != XML_NODE_START) { smlErrorSet(error, SML_ERROR_GENERIC, "The element %s is not a start node in Results.", xmlTextReaderConstName(parser->reader)); goto error_free_cmd; } if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_CMDID)) { if (!_smlXmlParserGetID(parser, &((*cmd)->cmdID), SML_ELEMENT_CMDID, error)) goto error_free_cmd; } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_MSGREF)) { if (!_smlXmlParserGetID(parser, &((*cmd)->private.results.status->msgRef), SML_ELEMENT_MSGREF, error)) goto error_free_cmd; } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_CMDREF)) { if (!_smlXmlParserGetID(parser, &((*cmd)->private.results.status->cmdRef), SML_ELEMENT_CMDREF, error)) goto error_free_cmd; } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_SOURCEREF)) { if (!_smlXmlParserGetString(parser, &locURI, SML_ELEMENT_SOURCEREF, error)) goto error_free_cmd; (*cmd)->private.results.status->sourceRef = smlLocationNew(locURI, NULL, error); smlSafeCFree(&locURI); if (!(*cmd)->private.results.status->sourceRef) goto error_free_cmd; } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_TARGETREF)) { if (!_smlXmlParserGetString(parser, &locURI, SML_ELEMENT_TARGETREF, error)) goto error_free_cmd; (*cmd)->private.results.status->targetRef = smlLocationNew(locURI, NULL, error); smlSafeCFree(&locURI); if (!(*cmd)->private.results.status->targetRef) goto error_free_cmd; } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_ITEM)) { (*cmd)->private.results.status->item = _smlItemParse(parser, (*cmd), (*cmd)->type, error); if (!(*cmd)->private.results.status->item) goto error_free_cmd; (*cmd)->target = (*cmd)->private.results.status->item->target; (*cmd)->private.results.status->item->target = NULL; (*cmd)->source = (*cmd)->private.results.status->item->source; (*cmd)->private.results.status->item->source = NULL; } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_META)) { /* ignore format */ char *format = NULL; if (!_smlCommandMetaParse(parser, &format, &contenttype, NULL, NULL, NULL, error)) goto error_free_cmd; if (format) smlSafeCFree(&format); } else { smlErrorSet(error, SML_ERROR_GENERIC, "wrong initial node"); goto error_free_cmd; } } if (!(*cmd)->private.results.status->item) { smlErrorSet(error, SML_ERROR_GENERIC, "Result is missing item"); goto error_free_cmd; } /* We only use the content type of the put command if the item itself did not have * a content type set */ if (!(*cmd)->private.results.status->item->contenttype) { if (!contenttype) { smlErrorSet(error, SML_ERROR_GENERIC, "Result is missing content type"); goto error_free_cmd; } (*cmd)->private.results.status->item->contenttype = g_strdup(contenttype); } if (contenttype) smlSafeCFree(&contenttype); /* Step once more */ if (!_smlXmlParserStep(parser)) { smlErrorSet(error, SML_ERROR_GENERIC, "Missing nodes"); goto error_free_cmd; } smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error_free_cmd: smlCommandUnref(*cmd); error: *cmd = NULL; if (contenttype) smlSafeCFree(&contenttype); smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return FALSE; } static SmlBool _smlXmlParserFixBrokenItemData( const char *data, unsigned int size, char **fixed_data, unsigned int *fixed_size, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %d, %p, %p, %p)", __func__, data, size, fixed_data, fixed_size, error); CHECK_ERROR_REF smlAssert(data); smlAssert(size); smlAssert(fixed_data); smlAssert(fixed_size); /* ******************* * fix wrong enconding * ******************* */ /* This fix was implemented for text/x-vMessage. * Some mobiles encode SMS always as UTF-16 * even if the XML document is encoded in UTF-8. * Example: Nokia E71 */ *fixed_size = size; *fixed_data = smlTryMalloc0(size + 1, error); if (!*fixed_data) { smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(error)); return FALSE; } memcpy(*fixed_data, data, size); const char *position = *fixed_data; while (position + 1 < *fixed_data + *fixed_size) { /* check if the next character is a NULL byte */ const char *byte = position + 1; if (*byte != 0) { /* the next byte is not NULL */ position++; continue; } smlTrace(TRACE_INTERNAL, "%s: Found NULL byte in XML document at %p.", __func__, position); /* the next character is a NULL byte * so let's check how long the UTF-16 string is */ const char *last_utf16 = position; while (last_utf16 + 1 < *fixed_data + *fixed_size && *((char *)(last_utf16 + 1)) == 0) { last_utf16 += 2; } /* go to the last NULL byte */ last_utf16--; /* convert the whole strong to UTF-8 */ smlTrace(TRACE_INTERNAL, "%s: Converting %d bytes ...", __func__, last_utf16 - position + 1); GError *gerror = NULL; size_t read_bytes = 0; size_t written_bytes = 0; gchar *conv_string = g_convert( position, (last_utf16 - position + 1), "UTF-8", "UTF-16", &read_bytes, &written_bytes, &gerror); if (gerror != NULL) { smlErrorSet( error, SML_ERROR_GENERIC, "Character conversion from UTF-16 to UTF-8 failed. %s", gerror->message); g_error_free(gerror); smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(error)); return FALSE; } smlTrace(TRACE_INTERNAL, "%s: read %d --> written %d --> %d ::= %s", __func__, read_bytes, written_bytes, strlen(conv_string), conv_string); /* replace the embedded string */ char *new_data = smlTryMalloc0(*fixed_size - read_bytes + written_bytes + 1, error); if (!new_data) { smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(error)); return FALSE; } memcpy(new_data, *fixed_data, (size_t) position - (size_t) *fixed_data); memcpy(new_data + (size_t) position - (size_t) *fixed_data, conv_string, written_bytes); memcpy(new_data + (size_t) position - (size_t) *fixed_data + written_bytes, position + read_bytes, *fixed_size - ( (size_t) position - (size_t) *fixed_data ) - read_bytes ); /* fix pointers */ *fixed_size = *fixed_size - read_bytes + written_bytes; position = new_data + (position - *fixed_data) + written_bytes; smlSafeCFree(fixed_data); *fixed_data = new_data; new_data = NULL; smlSafeCFree(&conv_string); smlTrace(TRACE_INTERNAL, "%s: Converted UTF-16 string to UTF-8", __func__); } smlTrace(TRACE_INTERNAL, "%s: Correctly encoded: %s", __func__, *fixed_data); /* ***************** * add missing CDATA * ***************** */ position = *fixed_data; while (position + 1 < *fixed_data + *fixed_size) { /* find item */ const char *limit_item_start = strstr(position, ""); if (! limit_item_start) { smlTrace(TRACE_EXIT, "%s - no (more) Item found", __func__); return TRUE; } else { smlTrace(TRACE_INTERNAL, "%s - Item found", __func__); } const char *limit_item_end = strstr(limit_item_start, ""); if (! limit_item_end) { g_warning("%s - no end of Item found.", __func__); smlTrace(TRACE_EXIT, "%s - no end of Item found", __func__); return TRUE; } else { smlTrace(TRACE_INTERNAL, "%s - end of Item found", __func__); } if (limit_item_start >= limit_item_end) { /* is before ?! */ position = limit_item_end + strlen(""); continue; } /* find data */ const char *limit_data_start = strstr(limit_item_start, ""); if (! limit_data_start) { smlTrace(TRACE_EXIT, "%s - no Data found", __func__); return TRUE; } else { smlTrace(TRACE_INTERNAL, "%s - Data found", __func__); } const char *limit_data_end = strstr(limit_data_start, ""); if (! limit_data_end) { g_warning("%s - no end of Data found.", __func__); smlTrace(TRACE_EXIT, "%s - no end of Data found", __func__); return TRUE; } else { smlTrace(TRACE_INTERNAL, "%s - end of Data found", __func__); } if (limit_data_start >= limit_data_end) { /* is before ?! */ position = limit_data_end + strlen(""); continue; } /* check limits */ if (limit_item_start >= limit_data_start || limit_data_start >= limit_data_end || limit_data_end >= limit_item_end) { /* There is something wrong with the encapsulation. * Expected: ......... */ position = limit_item_end + strlen(""); continue; } /* check for CDATA */ const char *cdata_start = strstr(limit_data_start, ""); continue; } /* check that there is no tag inside Data */ if (g_strstr_len( limit_data_start + strlen(""), limit_data_end - limit_data_start - strlen(""), "<")) { /* There is a tag in the Data area. */ position = limit_item_end + strlen(""); continue; } /* There is data in an item element and it is not CDATA. * - allocate new memory * - copy before data * - add ") + 1, error); if (!new_data) { smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(error)); return FALSE; } size_t before_size = limit_data_start + strlen("") - *fixed_data; size_t data_size = limit_data_end - limit_data_start - strlen(""); size_t after_size = *fixed_size - before_size - data_size; smlTrace(TRACE_INTERNAL, "%s: %i = %i + %i +%i", __func__, *fixed_size, before_size, data_size, after_size); memcpy(new_data, *fixed_data, before_size); memcpy(new_data + before_size, ""), data_size); memcpy(new_data + before_size + strlen ("", strlen("]]>")); memcpy(new_data + before_size + strlen ("") + data_size, limit_data_end, after_size); smlSafeCFree(fixed_data); *fixed_data = new_data; new_data = NULL; *fixed_size += strlen(""); /* The position must be calculated on base of the new string. */ position = *fixed_data + before_size + strlen ("") + data_size + strlen(""); smlTrace(TRACE_INTERNAL, "%s: CDATA inserted", __func__); } smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; } /** @brief Start the parsing * * This will set everything up and parse until the SyncHdr * */ SmlBool smlXmlParserStart(SmlXmlParser *parser, const char *data, unsigned int size, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %i, %p)", __func__, parser, data, size, error); CHECK_ERROR_REF smlAssert(parser); smlAssert(data); smlAssert(size); /* Repair item data if necessary. * Some devices does not encapsulate the data correctly * (e.g. SE M600i send the second part of a chunked item * without CDATA and so the CR LF is normalied to a LF * which creates a wrong length and so the item is detected * as damaged). */ parser->data = NULL; parser->size = 0; if (! _smlXmlParserFixBrokenItemData( data, size, &(parser->data), &(parser->size), error)) { smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(error)); return FALSE; } char *debugstr = smlPrintBinary(parser->data, parser->size); smlTrace(TRACE_INTERNAL, "Xml input: %s", debugstr); smlLog("received-%i.xml", parser->data, parser->size); smlSafeCFree(&debugstr); parser->got_command = FALSE; /* Create the new parser */ parser->reader = xmlReaderForMemory(parser->data, parser->size, "/", NULL, XML_PARSE_NONET | XML_PARSE_NOERROR | XML_PARSE_NOWARNING | XML_PARSE_NOCDATA); if (!parser->reader) { smlErrorSet(error, SML_ERROR_GENERIC, "Unable to create new reader"); goto error; } xmlSubstituteEntitiesDefault(1); /* Check the First Node (SyncML)*/ if (!_smlXmlParserExpectNode(parser, XML_NODE_START, FALSE, SML_ELEMENT_SYNCML, error)) goto error_free_reader; /* Check the Second Node (SyncHdr)*/ if (!_smlXmlParserExpectNode(parser, XML_NODE_START, FALSE, SML_ELEMENT_SYNCHDR, error)) goto error_free_reader; smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error_free_reader: xmlFreeTextReader(parser->reader); error: parser->reader = NULL; if (parser->data) smlSafeCFree(&(parser->data)); smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return FALSE; } SmlBool smlXmlParserEnd(SmlXmlParser *parser, SmlBool *final, SmlBool *end, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p, %p)", __func__, parser, final, end, error); CHECK_ERROR_REF smlAssert(parser); SmlBool got_final = FALSE; /* Check for final */ if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_FINAL)) { got_final = TRUE; if (!_smlXmlParserStep(parser)) { smlErrorSet(error, SML_ERROR_GENERIC, "Missing nodes"); goto error; } if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_FINAL) && \ xmlTextReaderNodeType(parser->reader) == XML_NODE_CLOSE) { if (!_smlXmlParserStep(parser)) { smlErrorSet(error, SML_ERROR_GENERIC, "Missing nodes"); goto error; } } } if (final) *final = got_final; /* Check for the end. We can only decide if this was the last message if this * was the final message */ if (end) { if (got_final) *end = parser->got_command ? FALSE : TRUE; else *end = FALSE; } /* Check the closing SyncBody - which is perhaps only an empty element. */ if (strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_SYNCBODY) || (!xmlTextReaderIsEmptyElement(parser->reader) && xmlTextReaderNodeType(parser->reader) != XML_NODE_CLOSE ) ) { smlErrorSet(error, SML_ERROR_GENERIC, "Wrong closing syncbody node"); goto error; } /* Check the next node (SyncML)*/ if (!_smlXmlParserExpectNode(parser, XML_NODE_CLOSE, FALSE, SML_ELEMENT_SYNCML, error)) goto error; xmlFreeTextReader(parser->reader); parser->reader = NULL; parser->size = 0; smlSafeCFree(&(parser->data)); smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return FALSE; } void smlXmlParserFree(SmlXmlParser *parser) { smlTrace(TRACE_ENTRY, "%s(%p)", __func__, parser); smlAssert(parser); if (parser->reader) { xmlFreeTextReader(parser->reader); } if (parser->data) smlSafeCFree(&(parser->data)); smlSafeFree((gpointer *)&parser); smlTrace(TRACE_EXIT, "%s", __func__); } SmlBool smlXmlParserGetHeader(SmlXmlParser *parser, SmlHeader **header, SmlCred **cred, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, parser, header, cred, error); CHECK_ERROR_REF smlAssert(parser); smlAssert(header); smlAssert(cred); if (!xmlTextReaderConstName(parser->reader) || strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_SYNCHDR) || \ xmlTextReaderNodeType(parser->reader) != XML_NODE_START) { /* It is important to notice that empty headers are not allowed. */ smlErrorSet(error, SML_ERROR_GENERIC, "Wrong starting node for a header"); goto error; } parser->version = SML_VERSION_UNKNOWN; *header = smlTryMalloc0(sizeof(SmlHeader), error); if (!*header) goto error; while (1) { if (!_smlXmlParserStep(parser)) { smlErrorSet(error, SML_ERROR_GENERIC, "Missing nodes"); goto error_free_header; } if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_SYNCHDR) && \ xmlTextReaderNodeType(parser->reader) == XML_NODE_CLOSE) { break; } else if (xmlTextReaderNodeType(parser->reader) != XML_NODE_START) { smlErrorSet(error, SML_ERROR_GENERIC, "The element %s is not a start node in SyncHdr.", xmlTextReaderConstName(parser->reader)); goto error_free_header; } if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_VERDTD)) { if (!_smlSyncHeaderParseDTD(&((*header)->version), parser, error)) goto error_free_header; parser->version = (*header)->version; } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_VERPROTO)) { if (!_smlSyncHeaderParseProto(&((*header)->protocol), parser, error)) goto error_free_header; } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_SESSIONID)) { if (!_smlXmlParserGetString(parser, &((*header)->sessionID), SML_ELEMENT_SESSIONID, error)) goto error_free_header; } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_MSGID)) { if (!_smlXmlParserGetID(parser, &((*header)->messageID), SML_ELEMENT_MSGID, error)) goto error_free_header; } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_TARGET)) { if (!_smlLocationParse(&((*header)->target), parser, error)) goto error_free_header; } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_SOURCE)) { if (!_smlLocationParse(&((*header)->source), parser, error)) goto error_free_header; } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_RESPURI)) { /* Only one RespURI is allowed. * If the header is not correct (more than one RespURI) * then the last RespURI is taken. */ if ((*header)->responseURI) { smlTrace(TRACE_ERROR, "%s: There is more than on RespURI.", __func__); smlSafeCFree(&((*header)->responseURI)); } if (!_smlXmlParserGetString(parser, &((*header)->responseURI), SML_ELEMENT_RESPURI, error)) goto error_free_header; } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_NORESP)) { /* This is an empty element. So the parser must not move one step forward. */ (*header)->noResponse = TRUE; } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_META)) { if (!_smlMessageParseSynchdrMeta(parser, &((*header)->maxmsgsize), &((*header)->maxobjsize), &((*header)->emi), error)) goto error_free_header; } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_CRED)) { *cred = _smlCredParse(parser, error); if (!(*cred)) goto error_free_header; } else { smlErrorSet(error, SML_ERROR_GENERIC, "Element %s not supported for SyncHdr.", (char *)xmlTextReaderConstName(parser->reader)); goto error_free_header; } } if (!(*header)->protocol) { smlErrorSet(error, SML_ERROR_GENERIC, "No protocol set"); goto error_free_header; } if (!(*header)->version) { smlErrorSet(error, SML_ERROR_GENERIC, "No dtd version set"); goto error_free_header; } if (!(*header)->sessionID) { smlErrorSet(error, SML_ERROR_GENERIC, "No sessionID set"); goto error_free_header; } if (!(*header)->target) { smlErrorSet(error, SML_ERROR_GENERIC, "No target set"); goto error_free_header; } if (!(*header)->source) { smlErrorSet(error, SML_ERROR_GENERIC, "No source set"); goto error_free_header; } if (!(*header)->messageID) { smlErrorSet(error, SML_ERROR_GENERIC, "No msgid set"); goto error_free_header; } /* Check the Next Node (SyncBody)*/ if (!_smlXmlParserExpectNode(parser, XML_NODE_START, FALSE, SML_ELEMENT_SYNCBODY, error)) goto error_free_header; /* Step once more if it is not an empty element. */ if (!xmlTextReaderIsEmptyElement(parser->reader) && !_smlXmlParserStep(parser)) { smlErrorSet(error, SML_ERROR_GENERIC, "Missing nodes"); goto error_free_header; } smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error_free_header: smlHeaderFree(*header); *header = NULL; if (*cred) smlCredUnref(*cred); error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return FALSE; } SmlBool smlXmlParserGetStatus(SmlXmlParser *parser, SmlStatus **status, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, parser, status, error); CHECK_ERROR_REF smlAssert(parser); smlAssert(status); char *locURI = NULL; SmlItem *item = NULL; /* Lets check if the next node is a command node */ if (smlCommandTypeFromString((char *)xmlTextReaderConstName(parser->reader), error) != SML_COMMAND_TYPE_UNKNOWN && xmlTextReaderNodeType(parser->reader) == XML_NODE_START) { *status = NULL; smlTrace(TRACE_EXIT, "%s: Next is command", __func__); return TRUE; } else { smlErrorDeref(error); } /* Lets check if the next node is a final node */ if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_FINAL) && (xmlTextReaderNodeType(parser->reader) == XML_NODE_START || xmlTextReaderNodeType(parser->reader) == XML_NODE_CLOSE)) { *status = NULL; smlTrace(TRACE_EXIT, "%s: Next is final", __func__); return TRUE; } /* Let's check if the next node is a closing or empty syncbody node. */ if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_SYNCBODY) && (xmlTextReaderNodeType(parser->reader) == XML_NODE_CLOSE || xmlTextReaderIsEmptyElement(parser->reader) ) ) { *status = NULL; smlTrace(TRACE_EXIT, "%s: Next is closing syncbody", __func__); return TRUE; } if (strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_STATUS)) { smlErrorSet(error, SML_ERROR_GENERIC, "Unexpected element <%s>.", (char *)xmlTextReaderConstName(parser->reader)); goto error; } if (xmlTextReaderIsEmptyElement(parser->reader)) { /* An empty status element is not allowed. * Try to finish in a way that the parser can still be used. * The parser can ignore this mistake and finish correctly. * Nevertheless a second mistake which crashs the NextStep * function cannot be handled. */ _smlXmlParserStep(parser); smlErrorSet(error, SML_ERROR_GENERIC, "Empty status element"); goto error; } if (xmlTextReaderNodeType(parser->reader) != XML_NODE_START) { smlErrorSet(error, SML_ERROR_GENERIC, "The element %s is not the start node of Status.", xmlTextReaderConstName(parser->reader)); goto error; } *status = smlStatusNew(SML_ERROR_UNKNOWN, 0, 0, NULL, NULL, SML_COMMAND_TYPE_UNKNOWN, error); if (!*status) goto error; while (1) { if (!_smlXmlParserStep(parser)) { smlErrorSet(error, SML_ERROR_GENERIC, "Missing nodes"); goto error_free_status; } if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_STATUS) && \ xmlTextReaderNodeType(parser->reader) == XML_NODE_CLOSE) { break; } else if (xmlTextReaderNodeType(parser->reader) != XML_NODE_START) { smlErrorSet(error, SML_ERROR_GENERIC, "The element %s is not a start node in Status.", xmlTextReaderConstName(parser->reader)); goto error_free_status; } if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_CMDID)) { //Errr... who cares? if (!_smlXmlParserExpectNode(parser, XML_NODE_TEXT, FALSE, NULL, error)) goto error_free_status; if (!_smlXmlParserExpectNode(parser, XML_NODE_CLOSE, FALSE, SML_ELEMENT_CMDID, error)) goto error_free_status; } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_MSGREF)) { /* MsgRef is defined as parsed character data: OMA-SUP-DTD_SyncML_RepPro-V1_2-20070221-A.txt: SyncML Reprent Version 1.1 20020215 - Chapter 5.1.13 MsgRef: "[...] reference to a SyncML session-uniquie identifier referenced by SyncML result or response status." So it could be something else then an unsigned integer. */ if (!_smlXmlParserGetID(parser, &((*status)->msgRef), SML_ELEMENT_MSGREF, error)) goto error_free_status; } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_CMDREF)) { if (!_smlXmlParserGetID(parser, &((*status)->cmdRef), SML_ELEMENT_CMDREF, error)) goto error_free_status; } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_CMD)) { char *cmdname = NULL; if (!_smlXmlParserGetString(parser, &cmdname, SML_ELEMENT_CMD, error)) goto error_free_status; (*status)->type = smlCommandTypeFromString(cmdname, error); smlSafeCFree(&cmdname); if ((*status)->type == SML_COMMAND_TYPE_UNKNOWN) goto error_free_status; } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_DATA)) { if (!_smlXmlParserGetString(parser, &((*status)->data), SML_ELEMENT_DATA, error)) goto error_free_status; } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_SOURCEREF)) { if (!_smlXmlParserGetString(parser, &locURI, SML_ELEMENT_SOURCEREF, error)) goto error_free_status; (*status)->sourceRef = smlLocationNew(locURI, NULL, error); smlSafeCFree(&locURI); if (!(*status)->sourceRef) goto error_free_status; } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_TARGETREF)) { if (!_smlXmlParserGetString(parser, &locURI, SML_ELEMENT_TARGETREF, error)) goto error_free_status; (*status)->targetRef = smlLocationNew(locURI, NULL, error); smlSafeCFree(&locURI); if (!(*status)->targetRef) goto error_free_status; } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_ITEM)) { /* Do not send SML_COMMAND_TYPE_ALERT * because this can give trouble. * Example: Error message for a failed ADD */ item = _smlItemParse(parser, NULL, (*status)->type, error); if (!item) goto error_free_status; } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_CHAL)) { (*status)->chal = _smlChalParse(parser, error); if (!(*status)->chal) goto error_free_status; } else { smlErrorSet(error, SML_ERROR_GENERIC, "wrong initial node"); goto error; } } /* Step once more */ if (!_smlXmlParserStep(parser)) { smlErrorSet(error, SML_ERROR_GENERIC, "Missing nodes"); goto error_free_status; } if (item) { if ((*status)->type == SML_COMMAND_TYPE_ALERT) { (*status)->anchor = item->anchor; item->anchor = NULL; } else if ((*status)->type == SML_COMMAND_TYPE_ADD || (*status)->type == SML_COMMAND_TYPE_REPLACE || (*status)->type == SML_COMMAND_TYPE_DELETE) { /* Usually Sync is commited at once or together with an anchor. * If a single ADD, REPLACE or DELETE gets an item * then there is something going wrong. */ g_warning("Received explicit status for add, delete or replace (%s).", xmlBufferContent(item->buffer)); } else { smlErrorSet(error, SML_ERROR_GENERIC, "Got wrong item"); smlItemUnref(item); goto error_free_status; } smlItemUnref(item); } /* MsgRef is defined as #PCDATA - so it doesn't have to be a unsigned integer AND it could be set to 0/zero as well. This sanity check breaks if MsgRef is set to 0/zero. if (!(*status)->msgRef) { smlErrorSet(error, SML_ERROR_GENERIC, "No msgref set"); goto error_free_status; } */ if ((*status)->type == SML_COMMAND_TYPE_UNKNOWN) { smlErrorSet(error, SML_ERROR_GENERIC, "No cmd set"); goto error_free_status; } smlTrace(TRACE_INTERNAL, "Got status %p with: cmdRef %i, msgRef %i, type %i, data %s", *status, (*status)->cmdRef, (*status)->msgRef, (*status)->type, VA_STRING((*status)->data)); smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error_free_status: smlStatusUnref(*status); error: *status = NULL; smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return FALSE; } SmlParserResult smlXmlParserGetCommand(SmlXmlParser *parser, SmlCommand **cmd, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, parser, cmd, error); CHECK_ERROR_REF smlAssert(parser); smlAssert(cmd); *cmd = NULL; /* Lets check if the next node is a final node */ if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_FINAL) && (xmlTextReaderNodeType(parser->reader) == XML_NODE_START || xmlTextReaderNodeType(parser->reader) == XML_NODE_CLOSE)) { *cmd = NULL; smlTrace(TRACE_EXIT, "%s: Next is final", __func__); return SML_PARSER_RESULT_OTHER; } /* Let's check if the next node is a closing or empty syncbody node. */ if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_SYNCBODY) && (xmlTextReaderNodeType(parser->reader) == XML_NODE_CLOSE || xmlTextReaderIsEmptyElement(parser->reader) ) ) { *cmd = NULL; smlTrace(TRACE_EXIT, "%s: Next is closing syncbody", __func__); return SML_PARSER_RESULT_OTHER; } /* Lets check if the next node status node */ if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_STATUS) && xmlTextReaderNodeType(parser->reader) == XML_NODE_START) { *cmd = NULL; smlTrace(TRACE_EXIT, "%s: Next is status", __func__); return SML_PARSER_RESULT_STATUS; } SmlCommandType type = smlCommandTypeFromString((char *)xmlTextReaderConstName(parser->reader), error); if (!type) goto error; SmlParserResult result = SML_PARSER_RESULT_NORMAL; switch (type) { case SML_COMMAND_TYPE_ALERT: if (!_smlAlertParse(parser, cmd, error)) goto error; break; case SML_COMMAND_TYPE_PUT: case SML_COMMAND_TYPE_GET: if (!_smlCommandAccessParse(parser, cmd, type, error)) goto error; break; case SML_COMMAND_TYPE_SYNC: if (xmlTextReaderNodeType(parser->reader) == XML_NODE_CLOSE) { if (!_smlXmlParserStep(parser)) { smlErrorSet(error, SML_ERROR_GENERIC, "Missing nodes"); goto error_free_cmd; } smlTrace(TRACE_EXIT, "%s: SML_PARSER_RESULT_CLOSE", __func__); return SML_PARSER_RESULT_CLOSE; } else { if (!_smlCommandSyncParse(parser, cmd, error)) goto error; result = SML_PARSER_RESULT_OPEN; } break; case SML_COMMAND_TYPE_MAP: if (!_smlCommandMapParse(parser, cmd, error)) goto error; break; case SML_COMMAND_TYPE_ADD: if (!_smlChangeParse(parser, cmd, SML_COMMAND_TYPE_ADD, SML_ELEMENT_ADD, error)) goto error; break; case SML_COMMAND_TYPE_REPLACE: if (!_smlChangeParse(parser, cmd, SML_COMMAND_TYPE_REPLACE, SML_ELEMENT_REPLACE, error)) goto error; break; case SML_COMMAND_TYPE_DELETE: if (!_smlChangeParse(parser, cmd, SML_COMMAND_TYPE_DELETE, SML_ELEMENT_DELETE, error)) goto error; break; case SML_COMMAND_TYPE_RESULTS: if (!_smlResultsParse(parser, cmd, error)) goto error; break; default: smlErrorSet(error, SML_ERROR_GENERIC, "Unsupported command type"); goto error; } if (!(*cmd)->cmdID) { smlErrorSet(error, SML_ERROR_GENERIC, "No cmdid set"); goto error_free_cmd; } parser->got_command = TRUE; smlTrace(TRACE_EXIT, "%s: %i", __func__, result); return result; error_free_cmd: if (*cmd) smlCommandUnref(*cmd); error: *cmd = NULL; smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return SML_PARSER_RESULT_ERROR; } SmlXmlParser *smlXmlParserNew(SmlParserFunctions *functions, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p)", __func__, functions,error); CHECK_ERROR_REF smlAssert(functions); SmlXmlParser *parser = smlTryMalloc0(sizeof(SmlXmlParser), error); if (!parser) goto error; functions->start = (SmlParserStartFunction)smlXmlParserStart; functions->free = (SmlParserFreeFunction)smlXmlParserFree; functions->end = (SmlParserEndFunction)smlXmlParserEnd; functions->get_header = (SmlParserHeaderFunction)smlXmlParserGetHeader; functions->get_cmd = (SmlParserCommandFunction)smlXmlParserGetCommand; functions->get_status = (SmlParserStatusFunction)smlXmlParserGetStatus; smlTrace(TRACE_EXIT, "%s: %p", __func__, parser); return parser; error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return NULL; } static SmlBool _smlXmlDevInfDataStoreParseDSMem(SmlXmlParser *parser, SmlDevInfDataStore *datastore, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, parser, datastore, error); CHECK_ERROR_REF smlAssert(parser); smlAssert(datastore); if (xmlTextReaderIsEmptyElement(parser->reader)) { /* An empty DSMem element is allowed according to SyncML DevInf 1.1.2. */ smlTrace(TRACE_EXIT, "%s - empty DSMem", __func__); return TRUE; } while (1) { if (!_smlXmlParserStep(parser)) { smlErrorSet(error, SML_ERROR_GENERIC, "Missing nodes"); goto error; } if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_DSMEM) && \ xmlTextReaderNodeType(parser->reader) == XML_NODE_CLOSE) { break; } else if (xmlTextReaderNodeType(parser->reader) != XML_NODE_START) { smlErrorSet(error, SML_ERROR_GENERIC, "The element %s is not a start node in DSMem.", xmlTextReaderConstName(parser->reader)); goto error; } if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_MAXID)) { if (!_smlXmlParserGetID(parser, &(datastore->maxid), SML_ELEMENT_MAXID, error)) goto error; } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_SHAREDMEM)) { datastore->sharedMem = TRUE; if (!_smlXmlParserStep(parser)) { smlErrorSet(error, SML_ERROR_GENERIC, "Missing nodes"); goto error; } if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_SHAREDMEM) && \ xmlTextReaderNodeType(parser->reader) == XML_NODE_CLOSE) { if (!_smlXmlParserStep(parser)) { smlErrorSet(error, SML_ERROR_GENERIC, "Missing nodes2"); goto error; } } continue; } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_MAXMEM)) { if (!_smlXmlParserGetID(parser, &(datastore->maxmem), SML_ELEMENT_MAXMEM, error)) goto error; } else { smlErrorSet(error, SML_ERROR_GENERIC, "wrong initial node"); goto error; } } smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return FALSE; } static SmlBool _smlXmlDevInfDataStoreParseSyncCap(SmlXmlParser *parser, SmlDevInfDataStore *datastore, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, parser, datastore, error); CHECK_ERROR_REF smlAssert(parser); smlAssert(datastore); while (1) { if (!_smlXmlParserStep(parser)) { smlErrorSet(error, SML_ERROR_GENERIC, "Missing nodes"); goto error; } if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_SYNCCAP) && \ xmlTextReaderNodeType(parser->reader) == XML_NODE_CLOSE) { break; } else if (xmlTextReaderNodeType(parser->reader) != XML_NODE_START) { smlErrorSet(error, SML_ERROR_GENERIC, "The element %s is not a start node in SyncCap.", xmlTextReaderConstName(parser->reader)); goto error; } if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_SYNCTYPE)) { unsigned int id = 0; if (!_smlXmlParserGetID(parser, &id, SML_ELEMENT_SYNCTYPE, error)) goto error; id = 1 << (id - 1); SmlDevInfSyncCap synccap = smlDevInfSyncCapConvert(id, error); if (synccap == SML_DEVINF_SYNCTYPE_UNKNOWN && error != NULL) goto error; if (synccap != SML_DEVINF_SYNCTYPE_UNKNOWN) smlDevInfDataStoreSetSyncCap(datastore, synccap, TRUE); } else { smlErrorSet(error, SML_ERROR_GENERIC, "wrong initial node"); goto error; } } smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return FALSE; } static SmlBool _smlXmlDevInfDataStoreParseCTCap11(SmlXmlParser *parser, SmlDevInf *devinf, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, parser, devinf, error); CHECK_ERROR_REF smlAssert(parser); smlAssert(devinf); /* This function was designed to parse one CTCap section */ /* which can include several CTCap definitions */ if (!_smlXmlParserStep(parser)) { smlErrorSet(error, SML_ERROR_GENERIC, "Missing nodes"); goto error; } SmlDevInfCTCap *ctcap = NULL; SmlDevInfProperty *property = NULL; SmlDevInfPropParam *param = NULL; char *value = NULL; while (1) { const char *elem_name; elem_name = (const char*)xmlTextReaderConstName(parser->reader); smlTrace(TRACE_INTERNAL, "read: %s\n", elem_name); if (!strcmp(elem_name, SML_ELEMENT_CTCAP) && xmlTextReaderNodeType(parser->reader) == XML_NODE_CLOSE) { // this is the end of the CTCap section break; } if (xmlTextReaderNodeType(parser->reader) != XML_NODE_START) { smlErrorSet(error, SML_ERROR_GENERIC, "The element %s is not a start node in CTCap.", xmlTextReaderConstName(parser->reader)); goto error; } /* determine list item type */ SmlDevInfCTCapType type; type = smlDevInfCTCapTypeFromString(elem_name, error); value = NULL; if (type != SML_DEVINF_CTCAP_UNKNOWN) { _smlXmlParserGetString(parser, &value, elem_name, error); } /* now react on the different items */ switch(type) { case SML_DEVINF_CTCAP_CTTYPE: // CTType => new ctcap definition if (ctcap != NULL) { if (property != NULL) { if (param != NULL) { smlDevInfPropertyAddPropParam(property, param); param = NULL; } smlDevInfCTCapAddProperty(ctcap, property); property = NULL; } smlDevInfAppendCTCap(devinf, ctcap); ctcap = NULL; } ctcap = smlDevInfNewCTCap(error); if (!ctcap) goto error; smlDevInfCTCapSetCTType(ctcap, value); break; case SML_DEVINF_CTCAP_VERCT: if (ctcap == NULL) goto error; smlDevInfCTCapSetVerCT(ctcap, value); break; case SML_DEVINF_CTCAP_PROPNAME: // PropName => new property if (ctcap == NULL) goto error; if (property != NULL) { if (param != NULL) { smlDevInfPropertyAddPropParam(property, param); param = NULL; } smlDevInfCTCapAddProperty(ctcap, property); property = NULL; } property = smlDevInfNewProperty(error); if (!property) goto error; smlDevInfPropertySetPropName(property, value); break; case SML_DEVINF_CTCAP_DATATYPE: if (property == NULL) goto error; if (param != NULL) smlDevInfPropParamSetDataType(param, value); else smlDevInfPropertySetDataType(property, value); break; case SML_DEVINF_CTCAP_MAXOCCUR: if (property == NULL) goto error; smlDevInfPropertySetMaxOccur(property, atoi(value)); break; case SML_DEVINF_CTCAP_MAXSIZE: if (property == NULL) goto error; smlDevInfPropertySetMaxSize(property, atoi(value)); break; case SML_DEVINF_CTCAP_NOTRUNCATE: if (property == NULL) goto error; smlDevInfPropertySetNoTruncate(property); break; case SML_DEVINF_CTCAP_DISPLAYNAME: if (property == NULL) goto error; if (param != NULL) smlDevInfPropParamSetDisplayName(param, value); else smlDevInfPropertySetDisplayName(property, value); break; case SML_DEVINF_CTCAP_VALENUM: if (property == NULL) goto error; if (param != NULL) smlDevInfPropParamAddValEnum(param, value); else smlDevInfPropertyAddValEnum(property, value); break; case SML_DEVINF_CTCAP_PARAMNAME: if (property == NULL) goto error; if (param != NULL) { smlDevInfPropertyAddPropParam(property, param); param = NULL; } param = smlDevInfNewPropParam(error); if (!param) goto error; smlDevInfPropParamSetParamName(param, value); break; case SML_DEVINF_CTCAP_SIZE: smlDevInfPropertySetPropSize(property, atoi(value)); break; default: smlErrorSet(error, SML_ERROR_GENERIC, "Unknown CTCapType: %s", elem_name); goto error; } smlSafeCFree(&value); if (!_smlXmlParserStep(parser)) { smlErrorSet(error, SML_ERROR_GENERIC, "Missing nodes"); goto error; } } if (param != NULL) smlDevInfPropertyAddPropParam(property, param); if (property != NULL) smlDevInfCTCapAddProperty(ctcap, property); if (ctcap != NULL) smlDevInfAppendCTCap(devinf, ctcap); smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); if (value != NULL) smlSafeCFree(&value); return FALSE; } static SmlDevInfPropParam *_smlXmlDevInfDataStoreParseCTCap12PropParam(SmlXmlParser *parser, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, parser, error); CHECK_ERROR_REF smlAssert(parser); if (!_smlXmlParserStep(parser)) { smlErrorSet(error, SML_ERROR_GENERIC, "Missing nodes"); goto error; } SmlDevInfPropParam *param = smlDevInfNewPropParam(error); if (!param) goto error; char *value = NULL; while (1) { const char *elem_name; elem_name = (const char*)xmlTextReaderConstName(parser->reader); smlTrace(TRACE_INTERNAL, "read: %s\n", elem_name); if (!strcmp(elem_name, SML_ELEMENT_PROPPARAM) && xmlTextReaderNodeType(parser->reader) == XML_NODE_CLOSE) { // this is the end of the PropParam section break; } if (xmlTextReaderNodeType(parser->reader) != XML_NODE_START) { smlErrorSet(error, SML_ERROR_GENERIC, "The element %s is not a start node in PropParam.", xmlTextReaderConstName(parser->reader)); goto error; } /* determine item type */ SmlDevInfCTCapType type; type = smlDevInfCTCapTypeFromString(elem_name, error); value = NULL; if (type != SML_DEVINF_CTCAP_UNKNOWN) { _smlXmlParserGetString(parser, &value, elem_name, error); } /* now react on the different items */ switch(type) { case SML_DEVINF_CTCAP_PARAMNAME: smlDevInfPropParamSetParamName(param, value); break; case SML_DEVINF_CTCAP_DATATYPE: smlDevInfPropParamSetDataType(param, value); break; case SML_DEVINF_CTCAP_DISPLAYNAME: smlDevInfPropParamSetDisplayName(param, value); break; case SML_DEVINF_CTCAP_VALENUM: smlDevInfPropParamAddValEnum(param, value); break; default: smlErrorSet(error, SML_ERROR_GENERIC, "Unknown CTCapType for PropParam: %s", elem_name); goto error; } smlSafeCFree(&value); if (!_smlXmlParserStep(parser)) { smlErrorSet(error, SML_ERROR_GENERIC, "Missing nodes"); goto error; } } smlTrace(TRACE_EXIT, "%s", __func__); return param; error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); if (value != NULL) smlSafeCFree(&value); return NULL; } static SmlDevInfProperty *_smlXmlDevInfDataStoreParseCTCap12Property(SmlXmlParser *parser, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, parser, error); CHECK_ERROR_REF smlAssert(parser); if (!_smlXmlParserStep(parser)) { smlErrorSet(error, SML_ERROR_GENERIC, "Missing nodes"); goto error; } SmlDevInfProperty *property = smlDevInfNewProperty(error); if (!property) goto error; SmlDevInfPropParam *param; char *value = NULL; while (1) { const char *elem_name; elem_name = (const char*)xmlTextReaderConstName(parser->reader); smlTrace(TRACE_INTERNAL, "read: %s\n", elem_name); if (!strcmp(elem_name, SML_ELEMENT_PROPERTY) && xmlTextReaderNodeType(parser->reader) == XML_NODE_CLOSE) { // this is the end of the Property section break; } if (xmlTextReaderNodeType(parser->reader) != XML_NODE_START) { smlErrorSet(error, SML_ERROR_GENERIC, "The element %s is not a start node in Property.", xmlTextReaderConstName(parser->reader)); goto error; } /* determine item type */ SmlDevInfCTCapType type; type = smlDevInfCTCapTypeFromString(elem_name, error); value = NULL; if (type != SML_DEVINF_CTCAP_UNKNOWN && type != SML_DEVINF_CTCAP_PROPPARAM) { _smlXmlParserGetString(parser, &value, elem_name, error); } /* now react on the different items */ switch(type) { case SML_DEVINF_CTCAP_PROPNAME: smlDevInfPropertySetPropName(property, value); break; case SML_DEVINF_CTCAP_DATATYPE: smlDevInfPropertySetDataType(property, value); break; case SML_DEVINF_CTCAP_MAXOCCUR: smlDevInfPropertySetMaxOccur(property, atoi(value)); break; case SML_DEVINF_CTCAP_MAXSIZE: smlDevInfPropertySetMaxSize(property, atoi(value)); break; case SML_DEVINF_CTCAP_NOTRUNCATE: smlDevInfPropertySetNoTruncate(property); break; case SML_DEVINF_CTCAP_DISPLAYNAME: smlDevInfPropertySetDisplayName(property, value); break; case SML_DEVINF_CTCAP_VALENUM: smlDevInfPropertyAddValEnum(property, value); break; case SML_DEVINF_CTCAP_PROPPARAM: param = _smlXmlDevInfDataStoreParseCTCap12PropParam(parser, error); if (!param) goto error; smlDevInfPropertyAddPropParam(property, param); break; case SML_DEVINF_CTCAP_SIZE: smlDevInfPropertySetPropSize(property, atoi(value)); break; default: smlErrorSet(error, SML_ERROR_GENERIC, "Unknown CTCapType for Property: %s", elem_name); goto error; } if (value) smlSafeCFree(&value); if (!_smlXmlParserStep(parser)) { smlErrorSet(error, SML_ERROR_GENERIC, "Missing nodes"); goto error; } } smlTrace(TRACE_EXIT, "%s", __func__); return property; error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); if (value != NULL) smlSafeCFree(&value); return NULL; } static SmlBool _smlXmlDevInfDataStoreParseCTCap12(SmlXmlParser *parser, SmlDevInf *devinf, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, parser, devinf, error); CHECK_ERROR_REF smlAssert(parser); smlAssert(devinf); /* This function was designed to parse one CTCap section */ /* which can include only one CTCap definition */ if (!_smlXmlParserStep(parser)) { smlErrorSet(error, SML_ERROR_GENERIC, "Missing nodes"); goto error; } SmlDevInfCTCap *ctcap = smlDevInfNewCTCap(error); if (!ctcap) goto error; SmlDevInfProperty *property; char *value = NULL; while (1) { const char *elem_name; elem_name = (const char*)xmlTextReaderConstName(parser->reader); smlTrace(TRACE_INTERNAL, "read: %s\n", elem_name); if (!strcmp(elem_name, SML_ELEMENT_CTCAP) && xmlTextReaderNodeType(parser->reader) == XML_NODE_CLOSE) { // this is the end of the CTCap section break; } if (xmlTextReaderNodeType(parser->reader) != XML_NODE_START) { smlErrorSet(error, SML_ERROR_GENERIC, "The element %s is not a start node in CtCap.", xmlTextReaderConstName(parser->reader)); goto error; } /* determine item type */ SmlDevInfCTCapType type; type = smlDevInfCTCapTypeFromString(elem_name, error); value = NULL; if (type != SML_DEVINF_CTCAP_UNKNOWN && type != SML_DEVINF_CTCAP_PROPERTY) { _smlXmlParserGetString(parser, &value, elem_name, error); } /* now react on the different items */ switch(type) { case SML_DEVINF_CTCAP_CTTYPE: smlDevInfCTCapSetCTType(ctcap, value); break; case SML_DEVINF_CTCAP_VERCT: smlDevInfCTCapSetVerCT(ctcap, value); break; case SML_DEVINF_CTCAP_PROPERTY: property = _smlXmlDevInfDataStoreParseCTCap12Property(parser, error); if (!property) goto error; smlDevInfCTCapAddProperty(ctcap, property); break; default: smlErrorSet(error, SML_ERROR_GENERIC, "Unknown CTCapType for CTCap: %s", elem_name); goto error; } if (value) smlSafeCFree(&value); if (!_smlXmlParserStep(parser)) { smlErrorSet(error, SML_ERROR_GENERIC, "Missing nodes"); goto error; } } smlDevInfAppendCTCap(devinf, ctcap); smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); if (value != NULL) smlSafeCFree(&value); return FALSE; } static SmlBool _smlXmlDevInfDataStoreParseCTCap(SmlXmlParser *parser, SmlDevInf *devinf, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, parser, devinf, error); CHECK_ERROR_REF smlAssert(parser); smlAssert(devinf); /* SyncML 1.0 and 1.1 start a new CTCap with a new CTType definition */ /* SyncML 1.2 starts a new CTCap with a new CTCap definition */ /* SyncML 1.2 attaches the CTCaps to the appropriate datastore */ /* SyncML 1.0 and 1.1 attach the CTCaps to DevInf */ /* The SyncML version is in devinf->version */ SmlBool ret; if (devinf->version == SML_DEVINF_VERSION_12) ret = _smlXmlDevInfDataStoreParseCTCap12(parser, devinf, error); else ret = _smlXmlDevInfDataStoreParseCTCap11(parser, devinf, error); smlTrace(TRACE_EXIT, "%s (%d)", __func__, ret); return ret; } static SmlBool _smlXmlDevInfDataStoreParseRxTx(SmlXmlParser *parser, const char *element, char **cttype, char **version, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %s, %p, %p, %p)", __func__, parser, VA_STRING(element), cttype, version, error); CHECK_ERROR_REF smlAssert(parser); smlAssert(element); smlAssert(cttype); if (!_smlXmlParserStep(parser)) { smlErrorSet(error, SML_ERROR_GENERIC, "Missing nodes"); goto error; } while (1) { if (!strcmp((char *)xmlTextReaderConstName(parser->reader), element) && \ xmlTextReaderNodeType(parser->reader) == XML_NODE_CLOSE) { break; } else if (xmlTextReaderNodeType(parser->reader) != XML_NODE_START) { smlErrorSet(error, SML_ERROR_GENERIC, "The element %s is not a start node in %s.", xmlTextReaderConstName(parser->reader), element); goto error; } if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_CTTYPE)) { if (!_smlXmlParserGetString(parser, cttype, SML_ELEMENT_CTTYPE, error)) goto error; } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_VERCT)) { /* Some phones send an empty VerCT for formats that dont have a version * (like notes). */ if (!_smlXmlParserStep(parser)) { smlErrorSet(error, SML_ERROR_GENERIC, "No node at all"); goto error; } if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_VERCT) && \ xmlTextReaderNodeType(parser->reader) == XML_NODE_CLOSE) { *version = g_strdup(""); } else if (xmlTextReaderNodeType(parser->reader) == XML_NODE_TEXT) { *version = g_strstrip(g_strdup((char *)xmlTextReaderConstValue(parser->reader))); if (!_smlXmlParserExpectNode(parser, XML_NODE_CLOSE, FALSE, SML_ELEMENT_VERCT, error)) goto error; } else { *version = g_strdup(""); continue; } } else { smlErrorSet(error, SML_ERROR_GENERIC, "wrong initial node"); goto error; } if (!_smlXmlParserStep(parser)) { smlErrorSet(error, SML_ERROR_GENERIC, "Missing nodes"); goto error; } } smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return FALSE; } static SmlBool _smlXmlDevInfDataStoreParse(SmlXmlParser *parser, SmlDevInf *devinf, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, parser, devinf, error); CHECK_ERROR_REF smlAssert(devinf); smlAssert(parser); SmlDevInfDataStore *datastore = smlTryMalloc0(sizeof(SmlDevInfDataStore), error); if (!datastore) goto error; datastore->refCount = 1; datastore->rxPrefContentType = NULL; datastore->txPrefContentType = NULL; if (!_smlXmlParserStep(parser)) { smlErrorSet(error, SML_ERROR_GENERIC, "Missing nodes"); goto error_free_datastore; } while (1) { if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_DATASTORE) && \ xmlTextReaderNodeType(parser->reader) == XML_NODE_CLOSE) { break; } else if (xmlTextReaderNodeType(parser->reader) != XML_NODE_START) { smlErrorSet(error, SML_ERROR_GENERIC, "The element %s is not a start node in Datastore.", xmlTextReaderConstName(parser->reader)); goto error_free_datastore; } if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_SOURCEREF)) { if (!_smlXmlParserGetString(parser, &(datastore->sourceref), SML_ELEMENT_SOURCEREF, error)) goto error_free_datastore; } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_DISPLAYNAME)) { if (!_smlXmlParserGetString(parser, &(datastore->displayname), SML_ELEMENT_DISPLAYNAME, error)) goto error_free_datastore; } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_MAXGUIDSIZE)) { if (!_smlXmlParserGetID(parser, &(datastore->maxGUIDSize), SML_ELEMENT_MAXGUIDSIZE, error)) goto error_free_datastore; } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_RXPREF)) { if (!_smlXmlDevInfDataStoreParseRxTx(parser, SML_ELEMENT_RXPREF, &(datastore->rxPrefContentType), &(datastore->rxPrefVersion), error)) goto error_free_datastore; } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_RX)) { char *cttype = NULL; char *verct = NULL; if (!_smlXmlDevInfDataStoreParseRxTx(parser, SML_ELEMENT_RX, &cttype, &verct, error)) goto error_free_datastore; SmlDevInfContentType *ct = smlDevInfNewContentType(cttype, verct, error); smlSafeCFree(&cttype); if (verct) smlSafeCFree(&verct); if (!ct) goto error_free_datastore; smlDevInfDataStoreAddRx(datastore, ct); } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_TXPREF)) { if (!_smlXmlDevInfDataStoreParseRxTx(parser, SML_ELEMENT_TXPREF, &(datastore->txPrefContentType), &(datastore->txPrefVersion), error)) goto error_free_datastore; } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_TX)) { char *cttype = NULL; char *verct = NULL; if (!_smlXmlDevInfDataStoreParseRxTx(parser, SML_ELEMENT_TX, &cttype, &verct, error)) goto error_free_datastore; SmlDevInfContentType *ct = smlDevInfNewContentType(cttype, verct, error); smlSafeCFree(&cttype); if (verct) smlSafeCFree(&verct); if (!ct) goto error_free_datastore; smlDevInfDataStoreAddTx(datastore, ct); } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_CTCAP)) { if (!_smlXmlDevInfDataStoreParseCTCap(parser, devinf, error)) goto error_free_datastore; } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_SYNCCAP)) { if (!_smlXmlDevInfDataStoreParseSyncCap(parser, datastore, error)) goto error_free_datastore; } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_DSMEM)) { if (!_smlXmlDevInfDataStoreParseDSMem(parser, datastore, error)) goto error_free_datastore; } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_SUPPORT_HIERARCHICAL_SYNC)) { if (devinf->version < SML_DEVINF_VERSION_12) { smlErrorSet(error, SML_ERROR_GENERIC, "SupportHierarchicalSync is only supported in OMA DS 1.2 DevInf and later."); goto error; } datastore->supportsHierarchicalSync = TRUE; if (!xmlTextReaderIsEmptyElement(parser->reader)) { if (!_smlXmlParserStep(parser)) { smlErrorSet(error, SML_ERROR_GENERIC, "The closing element of %s is missing.", SML_ELEMENT_SUPPORT_HIERARCHICAL_SYNC); goto error; } } } else { smlErrorSet(error, SML_ERROR_GENERIC, "A DataStore within DevInf includes the unsupported element %s.", (char *)xmlTextReaderConstName(parser->reader)); goto error_free_datastore; } if (!_smlXmlParserStep(parser)) { smlErrorSet(error, SML_ERROR_GENERIC, "Missing nodes"); goto error_free_datastore; } } smlDevInfAddDataStore(devinf, datastore); smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error_free_datastore: smlDevInfDataStoreUnref(datastore); error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return FALSE; } SmlDevInf *smlXmlDevInfParse(const char *data, unsigned int size, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, data, size, error); CHECK_ERROR_REF smlAssert(data); smlAssert(size); SmlDevInf *devinf = NULL; //Fixme debug if char *debugstr = smlPrintBinary(data, size); smlTrace(TRACE_INTERNAL, "Xml devinf input: %s", debugstr); smlSafeCFree(&debugstr); SmlXmlParser *parser = smlTryMalloc0(sizeof(SmlXmlParser), error); if (!parser) goto error; /* Create the new parser */ parser->reader = xmlReaderForMemory(data, size, "/", NULL, XML_PARSE_NONET | XML_PARSE_NOERROR | XML_PARSE_NOWARNING | XML_PARSE_NOCDATA | XML_PARSER_SUBST_ENTITIES); if (!parser->reader) { smlErrorSet(error, SML_ERROR_GENERIC, "Unable to create new reader"); goto error; } xmlSubstituteEntitiesDefault(1); /* Check the First Node (DevInf)*/ if (!_smlXmlParserExpectNode(parser, XML_NODE_START, FALSE, SML_ELEMENT_DEVINF, error)) goto error; devinf = smlTryMalloc0(sizeof(SmlDevInf), error); if (!devinf) goto error; smlDevInfRef(devinf); if (!_smlXmlParserStep(parser)) { smlErrorSet(error, SML_ERROR_GENERIC, "Missing nodes"); goto error; } while (1) { if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_DEVINF) && \ xmlTextReaderNodeType(parser->reader) == XML_NODE_CLOSE) { break; } else if (xmlTextReaderNodeType(parser->reader) != XML_NODE_START) { smlErrorSet(error, SML_ERROR_GENERIC, "The element %s is not a start node in DevInf.", xmlTextReaderConstName(parser->reader)); goto error; } if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_VERDTD)) { char *verdtd = NULL; if (!_smlXmlParserGetString(parser, &verdtd, SML_ELEMENT_VERDTD, error)) goto error; if (verdtd && !strcmp(verdtd, "1.1")) devinf->version = SML_DEVINF_VERSION_11; else if (verdtd && !strcmp(verdtd, "1.0")) devinf->version = SML_DEVINF_VERSION_10; else if (verdtd && !strcmp(verdtd, "1.2")) devinf->version = SML_DEVINF_VERSION_12; else { smlSafeCFree(&verdtd); smlErrorSet(error, SML_ERROR_GENERIC, "Unknown devinf version"); goto error; } smlSafeCFree(&verdtd); } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_MAN)) { if (!_smlXmlParserGetString(parser, &(devinf->manufacturer), SML_ELEMENT_MAN, error)) goto error; } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_MOD)) { if (!_smlXmlParserGetString(parser, &(devinf->model), SML_ELEMENT_MOD, error)) goto error; } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_OEM)) { if (!_smlXmlParserGetString(parser, &(devinf->oem), SML_ELEMENT_OEM, error)) goto error; } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_FWV)) { if (!_smlXmlParserGetString(parser, &(devinf->firmwareVersion), SML_ELEMENT_FWV, error)) goto error; } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_SWV)) { if (!_smlXmlParserGetString(parser, &(devinf->softwareVersion), SML_ELEMENT_SWV, error)) goto error; } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_HWV)) { if (!_smlXmlParserGetString(parser, &(devinf->hardwareVersion), SML_ELEMENT_HWV, error)) goto error; } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_DEVID)) { if (!_smlXmlParserGetString(parser, &(devinf->devid), SML_ELEMENT_DEVID, error)) goto error; } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_DEVTYPE)) { char *devtype = NULL; if (!_smlXmlParserGetString(parser, &devtype, SML_ELEMENT_DEVTYPE, error)) goto error; devinf->devtyp = smlDevInfDevTypeFromString(devtype, error); smlSafeCFree(&devtype); if (devinf->devtyp == SML_DEVINF_DEVTYPE_UNKNOWN) goto error; } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_UTC)) { if (devinf->version == SML_DEVINF_VERSION_10) { smlErrorSet(error, SML_ERROR_GENERIC, "Devinf 1.0 does not allow UTC"); goto error; } devinf->supportsUTC = TRUE; if (!_smlXmlParserStep(parser)) { smlErrorSet(error, SML_ERROR_GENERIC, "Missing nodes"); goto error; } if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_UTC) && \ xmlTextReaderNodeType(parser->reader) == XML_NODE_CLOSE) { if (!_smlXmlParserStep(parser)) { smlErrorSet(error, SML_ERROR_GENERIC, "Missing nodes2"); goto error; } } continue; } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_SUPPORTLARGEOBJS)) { if (devinf->version == SML_DEVINF_VERSION_10) { smlErrorSet(error, SML_ERROR_GENERIC, "Devinf 1.0 does not allow large objects"); goto error; } devinf->supportsLargeObjs = TRUE; if (!_smlXmlParserStep(parser)) { smlErrorSet(error, SML_ERROR_GENERIC, "Missing nodes"); goto error; } if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_SUPPORTLARGEOBJS) && \ xmlTextReaderNodeType(parser->reader) == XML_NODE_CLOSE) { if (!_smlXmlParserStep(parser)) { smlErrorSet(error, SML_ERROR_GENERIC, "Missing nodes2"); goto error; } } continue; } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_SUPPORTNUMBEROFCHANGES)) { if (devinf->version == SML_DEVINF_VERSION_10) { smlErrorSet(error, SML_ERROR_GENERIC, "Devinf 1.0 does not allow number of changes"); goto error; } devinf->supportsNumberOfChanges = TRUE; if (!_smlXmlParserStep(parser)) { smlErrorSet(error, SML_ERROR_GENERIC, "Missing nodes"); goto error; } if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_SUPPORTNUMBEROFCHANGES) && \ xmlTextReaderNodeType(parser->reader) == XML_NODE_CLOSE) { if (!_smlXmlParserStep(parser)) { smlErrorSet(error, SML_ERROR_GENERIC, "Missing nodes2"); goto error; } } continue; } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_DATASTORE)) { if (!_smlXmlDevInfDataStoreParse(parser, devinf, error)) goto error; } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_CTCAP)) { /* This must be SyncML 1.0 or 1.1. * OMA DM 1.2 puts CTCap into the datastores. */ if (!_smlXmlDevInfDataStoreParseCTCap(parser, devinf, error)) goto error; } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_EXT)) { /* Ignored for now */ smlTrace(TRACE_INTERNAL, "%s: Skipping ext node"); if (!_smlXmlSkipNode(parser)) { smlErrorSet(error, SML_ERROR_GENERIC, "Unable to skip ext node"); goto error; } continue; } else { smlErrorSet(error, SML_ERROR_GENERIC, "wrong initial node: %s", (char *)xmlTextReaderConstName(parser->reader)); goto error; } if (!_smlXmlParserStep(parser)) { smlErrorSet(error, SML_ERROR_GENERIC, "Missing nodes"); goto error; } } xmlFreeTextReader(parser->reader); parser->reader = NULL; smlSafeFree((gpointer *)&parser); smlTrace(TRACE_EXIT, "%s", __func__); return devinf; error: if (parser && parser->reader) { xmlFreeTextReader(parser->reader); parser->reader = NULL; } if (parser) smlSafeFree((gpointer *)&parser); if (devinf) smlDevInfUnref(devinf); smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return NULL; } libsyncml-0.5.4/libsyncml/parser/sml_wbxml_internals.h100644 1750 1750 2674 11211710410 23156 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2005 Armin Bauer * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ /** * @defgroup XmlWbxmlPrivate WBXML Parser and Assembler Internals * @ingroup XmlPrivate * @brief XML parser and assembler details only known inside the internal XML/WBXML API. * */ /*@{*/ #ifndef _SML_WBXML_INTERNALS_H_ #define _SML_WBXML_INTERNALS_H_ #include SmlBool smlWbxmlConvertTo(WBXMLConvXML2WBXMLParams *params, const char *input, char **output, size_t *outputLen, SmlError** error); SmlBool smlWbxmlConvertFrom(WBXMLConvWBXML2XMLParams *params, const char *input, size_t inputLen, char **output, size_t *outputLen, SmlError** error); #endif //_SML_WBXML_INTERNALS_H_ /*@}*/ libsyncml-0.5.4/libsyncml/parser/sml_xml_assm_internals.h100644 1750 1750 6327 11211710410 23647 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2005 Armin Bauer * Copyright (C) 2008 Michael Bell * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ /** * @defgroup XmlAssemblerPrivate XML Assembler Internals * @ingroup XmlPrivate * @brief XML assembler details only known inside the internal XML/WBXML API. * */ /*@{*/ #ifndef _SML_XML_ASSM_INTERNALS_H_ #define _SML_XML_ASSM_INTERNALS_H_ #include #define XML_NODE_START 1 #define XML_NODE_TEXT 3 #define XML_NODE_CLOSE 15 #define XML_NODE_CDATA 4 typedef enum { SML_ASSEMBLER_NODE_OPEN, SML_ASSEMBLER_NODE_CLOSE } SmlXmlAssemblerNodeType; typedef struct SmlXmlAssemblerCommand { /** The type of the command. Used the make the opening and closing tags */ SmlCommandType cmdType; /** The buffer that holds the assembled data of this command */ xmlBuffer *buffer; /** The type of the node. Either a opening or a closing node */ SmlXmlAssemblerNodeType nodeType; /** The command id. Needed if you want to add children */ unsigned int cmdID; GList *children; } SmlXmlAssemblerCommand; typedef struct SmlXmlAssemblerStatus { /** The type of the command. Used the make the opening and closing tags */ unsigned int cmdRef; unsigned int msgRef; /** The buffer that holds the assembled data of this status */ xmlBuffer *buffer; /** The command id.*/ unsigned int cmdID; } SmlXmlAssemblerStatus; struct SmlXmlAssembler { xmlTextWriter *writer; xmlBuffer *header_buffer; GList *statuses; GList *commands; GList *last_commands; GList *parent_commands; GList *parent_buffers; SmlSession *session; SmlAssembler *assembler; GMutex *mutex; unsigned int reserved_statuses; unsigned int added_statuses; SmlBool moreDataSet; }; SmlBool smlAssemblerStartNode(SmlAssembler *assm, const char *name, SmlError **error); SmlBool smlAssemblerStartNodeNS(SmlAssembler *assm, const char *prefix, const char *name, const char *uri, SmlError **error); SmlBool smlAssemblerEndNode(SmlAssembler *assm, SmlError **error); SmlBool smlAssemblerAddString(SmlAssembler *assm, const char *name, const char *value, SmlError **error); SmlBool smlAssemblerAddStringNS(SmlAssembler *assm, const char *prefix, const char *name, const char *uri, const char *value, SmlError **error); SmlBool smlAssemblerAddID(SmlAssembler *assm, const char *name, unsigned int id, SmlError **error); SmlBool smlAssemblerAddData(SmlAssembler *assm, const char *name, const char *value, SmlError **error); #endif //_SML_XML_ASSM_INTERNALS_H_ /*@}*/ libsyncml-0.5.4/libsyncml/parser/sml_xml_parse_internals.h100644 1750 1750 4231 11211710410 24006 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2005 Armin Bauer * Copyright (C) 2008 Michael Bell * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ /** * @defgroup XmlPrivate Internal details of XML/WBXML API * @ingroup Xml * @brief XML/WBXML API private part * */ /** * @defgroup XmlParserPrivate XML Parser Internals * @ingroup XmlPrivate * @brief XML parser details only known inside the internal XML/WBXML API. * */ /*@{*/ #ifndef _SML_XML_PARSE_INTERNALS_H_ #define _SML_XML_PARSE_INTERNALS_H_ #include #include #define XML_NODE_START 1 #define XML_NODE_TEXT 3 #define XML_NODE_CLOSE 15 #define XML_NODE_CDATA 4 struct SmlXmlParser { /** The version of the last parsed document */ SmlProtocolVersion version; xmlTextReader *reader; char *data; unsigned int size; SmlTransport *tsp; SmlMimeType type; SmlBool got_command; SmlBool gotMoreData; }; SmlBool smlParserStep(SmlParser *parser); SmlBool smlParserExpectNode(SmlParser *parser, int type, SmlBool empty, const char *name, SmlError **error); SmlBool smlParserGetID(SmlParser *parser, unsigned int *id, const char *name, SmlError **error); SmlBool smlParserGetString(SmlParser *parser, char **string, const char *name, SmlError **error); SmlBool smlParserGetData(SmlParser *parser, char **string, unsigned int *size, const char *name, SmlError **error); #endif //_SML_XML_PARSE_INTERNALS_H_ /*@}*/ libsyncml-0.5.4/libsyncml/parser/sml_xml_assm.c100644 1750 1750 221407 11211710410 21621 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2005 Armin Bauer * Copyright (C) 2007-2009 Michael Bell * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include #include #include #include #include #include #include "libsyncml/sml_error_internals.h" #include "sml_xml_assm.h" #include "sml_xml_assm_internals.h" #define BUFFER_SIZE 500 /** * @defgroup Assembler SyncML XML Assembler * @ingroup PublicAPI * @brief Interfaces to assemble syncml messages * */ /*@{*/ static SmlBool _smlXmlAssemblerStartNodeNS(SmlXmlAssembler *assm, const char *name, const char *uri, SmlError **error) { CHECK_ERROR_REF smlAssert(assm); smlAssert(assm->writer); smlAssert(name != NULL); smlAssert(strlen(name) > 0); smlTrace(TRACE_INTERNAL, "%s: Starting \"%s\"", __func__, VA_STRING(name)); int rc = xmlTextWriterStartElementNS(assm->writer, NULL, (xmlChar *)name, (xmlChar *)uri); if (rc < 0) { smlErrorSet(error, SML_ERROR_GENERIC, "Unable to start node"); return FALSE; } return TRUE; } static SmlBool _smlXmlAssemblerStartNode(SmlXmlAssembler *assm, const char *name, SmlError **error) { CHECK_ERROR_REF return _smlXmlAssemblerStartNodeNS(assm, name, NULL, error); } static SmlBool _smlXmlAssemblerEndNode(SmlXmlAssembler *assm, SmlError **error) { CHECK_ERROR_REF smlTrace(TRACE_INTERNAL, "%s: Ending node", __func__); int rc = xmlTextWriterEndElement(assm->writer); if (rc < 0) { smlErrorSet(error, SML_ERROR_GENERIC, "Unable to end node (%d).", rc); return FALSE; } return TRUE; } static SmlBool _smlXmlAssemblerAddStringNS(SmlXmlAssembler *assm, const char *name, const char *uri, const char *value, SmlError **error) { CHECK_ERROR_REF int rc = xmlTextWriterWriteElementNS(assm->writer, NULL, (xmlChar *)name, (xmlChar *)uri, (xmlChar *)value); if (rc < 0) { smlErrorSet(error, SML_ERROR_GENERIC, "Unable to add string (%d - %s:%s -> %s).", rc, VA_STRING(uri), VA_STRING(name), VA_STRING(value)); return FALSE; } return TRUE; } static SmlBool _smlXmlAssemblerAddString(SmlXmlAssembler *assm, const char *name, const char *value, SmlError **error) { CHECK_ERROR_REF int rc = xmlTextWriterWriteElement(assm->writer, (xmlChar *)name, (xmlChar *)value); if (rc < 0) { smlErrorSet(error, SML_ERROR_GENERIC, "Unable to add pure string (%d - %s -> %s).", rc, VA_STRING(name), VA_STRING(value)); return FALSE; } return TRUE; } static SmlBool _smlXmlAssemblerAddData(SmlXmlAssembler *assm, const char *name, const char *value, unsigned int size, SmlBool raw, SmlError **error) { CHECK_ERROR_REF int rc = 0; if (!_smlXmlAssemblerStartNode(assm, name, error)) return FALSE; if (raw) rc = xmlTextWriterWriteRawLen(assm->writer, (xmlChar *)value, size); else rc = xmlTextWriterWriteFormatCDATA(assm->writer, "%*s", size, (xmlChar *)value); if (rc < 0) { smlErrorSet(error, SML_ERROR_GENERIC, "Unable to add data (%d).", rc); return FALSE; } if (!_smlXmlAssemblerEndNode(assm, error)) return FALSE; return TRUE; } static SmlBool _smlXmlAssemblerAddID(SmlXmlAssembler *assm, const char *name, unsigned int id, SmlError **error) { CHECK_ERROR_REF int rc = xmlTextWriterWriteFormatElement(assm->writer, (xmlChar *)name, "%i", id); if (rc < 0) { smlErrorSet(error, SML_ERROR_GENERIC, "Unable to add id"); return FALSE; } return TRUE; } static SmlBool _smlXmlAssemblerAddIDNS(SmlXmlAssembler *assm, const char *name, const char *uri, unsigned int id, SmlError **error) { CHECK_ERROR_REF int rc = xmlTextWriterWriteFormatElementNS(assm->writer, NULL, (xmlChar *)name, (xmlChar *)uri, "%i", id); if (rc < 0) { smlErrorSet(error, SML_ERROR_GENERIC, "Unable to add id"); return FALSE; } return TRUE; } static SmlBool _smlAssembleUseMaxObjSize(SmlXmlAssembler *assm) { smlTrace(TRACE_ENTRY, "%s(%p)", __func__, assm); /* check the configuration */ const char *opt = smlAssemblerGetOption(assm->assembler, "USE_LARGEOBJECTS"); SmlBool supportsLargeObjects = (opt && !atoi(opt)) ? FALSE : TRUE; /* server should react only the client behavior */ if (assm->session->sessionType == SML_SESSION_TYPE_SERVER) { if (smlAssemblerGetRemoteMaxObjSize(assm->assembler) <= 0) supportsLargeObjects = FALSE; if (smlAssemblerGetRemoteMaxMsgSize(assm->assembler) <= 0) supportsLargeObjects = FALSE; } /* SyncML 1.0 does not support large objects */ if (assm->session->version == SML_VERSION_10) supportsLargeObjects = FALSE; /* If MaxObjsize must really be sent * then check if it is configured */ if (smlSessionGetLocalMaxObjSize(assm->session) <= 0) supportsLargeObjects = FALSE; smlTrace(TRACE_EXIT, "%s - %d", __func__, supportsLargeObjects); return supportsLargeObjects; } static SmlBool _smlAssembleMaxObjSize(SmlXmlAssembler *assm, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p)", __func__, assm); CHECK_ERROR_REF /* It is allowed to add MaxObjSize to the Alert or Sync * command and libsyncml adds the MaxObjSize to the Sync * command. Explanation from OMA DS Protocol v1.2: * * 6 Protocol Fundamentals * 6.10 Large Object Handling * 6.10.1 Conformance statements * Citation: If a device supports receiving Large * Objects it MUST declare the maximum size of * object ( tag) it is capable of * receiving as Meta information within the * Alert or Sync command, as specified in * [META]. * * SyncML 1.0 does not support large objects. Therefore * MaxObjSize must not be sent because otherwise this * could result in errors (bad request/message). */ if (!_smlXmlAssemblerAddIDNS(assm, SML_ELEMENT_MAXOBJSIZE, SML_NAMESPACE_METINF, smlSessionGetLocalMaxObjSize(assm->session), error)) goto error; smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return FALSE; } SmlBool smlLocationAssemble(SmlLocation *location, SmlXmlAssembler *assm, const char *name, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %s, %p)", __func__, location, assm, VA_STRING(name), error); CHECK_ERROR_REF smlAssert(assm); smlAssert(location); if (name) { if (!_smlXmlAssemblerStartNode(assm, name, error)) goto error; } if (!location->locURI) { smlErrorSet(error, SML_ERROR_GENERIC, "No locURI set"); goto error; } if (!_smlXmlAssemblerAddString(assm, SML_ELEMENT_LOCURI, location->locURI, error)) goto error; if (location->locName) { if (!_smlXmlAssemblerAddString(assm, SML_ELEMENT_LOCNAME, location->locName, error)) goto error; } if (name) { if (!_smlXmlAssemblerEndNode(assm, error)) goto error; } smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return FALSE; } SmlBool smlAnchorAssemble(SmlAnchor *anchor, SmlXmlAssembler *assm, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, anchor, assm, error); CHECK_ERROR_REF smlAssert(assm); smlAssert(anchor); /* Start the anchor and switch to syncml:metinf namespace. * It is not possible to remove the namespace from Last and * Next because otherwise the Status commands could be longer * then the Alert commands. If this would happen then the * Status commands alone could be longer than MaxMsgSize. * * It is not sure how a mobile would react in this situation. */ if (!_smlXmlAssemblerStartNodeNS(assm, SML_ELEMENT_ANCHOR, SML_NAMESPACE_METINF, error)) goto error; if (!anchor->next) { smlErrorSet(error, SML_ERROR_GENERIC, "No next set"); goto error; } /* SyncML Meta-Information DTD 1.1, Page 6, 5.1 Anchor - Content Model: (Last?, Next) Last is optional, don't write a empty Last node. */ if (anchor->last) { if (!_smlXmlAssemblerAddStringNS(assm, SML_ELEMENT_LAST, SML_NAMESPACE_METINF, anchor->last, error)) goto error; } if (!_smlXmlAssemblerAddStringNS(assm, SML_ELEMENT_NEXT, SML_NAMESPACE_METINF, anchor->next, error)) goto error; if (!_smlXmlAssemblerEndNode(assm, error)) goto error; smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return FALSE; } SmlBool smlItemAssemble(SmlItem *item, SmlXmlAssembler *assm, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, item, assm, error); CHECK_ERROR_REF smlAssert(assm); smlAssert(item); if (assm->moreDataSet) { smlErrorSet(error, SML_ERROR_GENERIC, "Trying to start a new item while last item had more data"); goto error; } /* Begin of Item */ if (!_smlXmlAssemblerStartNode(assm, SML_ELEMENT_ITEM, error)) goto error; /* Target */ if (smlItemGetTarget(item)) { if (!smlLocationAssemble(smlItemGetTarget(item), assm, SML_ELEMENT_TARGET, error)) goto error; } /* Source */ if (smlItemGetSource(item)) { if (!smlLocationAssemble(smlItemGetSource(item), assm, SML_ELEMENT_SOURCE, error)) goto error; } /* SourceParent */ if (smlItemGetSourceParent(item)) { if (!smlLocationAssemble(smlItemGetSourceParent(item), assm, SML_ELEMENT_SOURCE_PARENT, error)) goto error; } /* TargetParent */ if (smlItemGetTargetParent(item)) { if (!smlLocationAssemble(smlItemGetTargetParent(item), assm, SML_ELEMENT_TARGET_PARENT, error)) goto error; } /* Data */ if (smlItemHasData(item)) { if (item->disabled) { if (!_smlXmlAssemblerAddData(assm, SML_ELEMENT_DATA, "", 0, item->raw, error)) goto error; } else { char *data = NULL; unsigned int size = 0; if (!smlItemGetData(item, &data, &size, error)) goto error; if (!_smlXmlAssemblerAddData(assm, SML_ELEMENT_DATA, data, size, item->raw, error)) goto error; } } /* MoreData */ if (item->moreData) { if (!_smlXmlAssemblerAddString(assm, SML_ELEMENT_MOREDATA, "", error)) goto error; assm->moreDataSet = TRUE; } /* End of Item */ if (!_smlXmlAssemblerEndNode(assm, error)) goto error; smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return FALSE; } SmlBool smlCredAssemble(SmlCred *cred, SmlXmlAssembler *assm, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, cred, assm, error); CHECK_ERROR_REF smlAssert(assm); smlAssert(cred); if (!_smlXmlAssemblerStartNode(assm, SML_ELEMENT_CRED, error)) goto error; //Meta if (!_smlXmlAssemblerStartNode(assm, SML_ELEMENT_META, error)) goto error; switch (cred->format) { case SML_FORMAT_TYPE_BASE64: if (!_smlXmlAssemblerAddStringNS(assm, SML_ELEMENT_FORMAT, SML_NAMESPACE_METINF, SML_BASE64, error)) goto error; break; default: smlErrorSet(error, SML_ERROR_GENERIC, "SyncML credential: Unknown format %d.", cred->format); goto error; } switch (cred->type) { case SML_AUTH_TYPE_BASIC: if (!_smlXmlAssemblerAddStringNS(assm, SML_ELEMENT_TYPE, SML_NAMESPACE_METINF, SML_AUTH_BASIC, error)) goto error; break; case SML_AUTH_TYPE_MD5: if (!_smlXmlAssemblerAddStringNS(assm, SML_ELEMENT_TYPE, SML_NAMESPACE_METINF, SML_AUTH_MD5, error)) goto error; break; default: smlErrorSet(error, SML_ERROR_GENERIC, "Unknown format"); goto error; } //META if (!_smlXmlAssemblerEndNode(assm, error)) goto error; if (!_smlXmlAssemblerAddData(assm, SML_ELEMENT_DATA, cred->data, strlen(cred->data), TRUE, error)) goto error; if (!_smlXmlAssemblerEndNode(assm, error)) goto error; smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return FALSE; } SmlBool smlAccessAssemble(SmlXmlAssembler *assm, SmlCommand *change, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, assm, change, error); CHECK_ERROR_REF smlAssert(change); smlAssert(assm); if (!change->private.access.item) { smlErrorSet(error, SML_ERROR_GENERIC, "Missing item"); goto error; } if (!change->private.access.item->contenttype) { smlErrorSet(error, SML_ERROR_GENERIC, "Missing contenttype"); goto error; } //Meta if (!_smlXmlAssemblerStartNode(assm, SML_ELEMENT_META, error)) goto error; if (!_smlXmlAssemblerAddStringNS(assm, SML_ELEMENT_TYPE, SML_NAMESPACE_METINF, change->private.access.item->contenttype, error)) goto error; //META if (!_smlXmlAssemblerEndNode(assm, error)) goto error; if (!smlItemAssemble(change->private.access.item, assm, error)) goto error; smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return FALSE; } SmlBool smlChangeAssemble(SmlXmlAssembler *assm, SmlCommand *change, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, assm, change, error); CHECK_ERROR_REF smlAssert(change); smlAssert(assm); if (!change->private.change.items || !g_list_length(change->private.change.items)) { smlErrorSet(error, SML_ERROR_GENERIC, "Missing items"); goto error; } /* libsyncml only supports one item per change command */ smlAssert(g_list_length(change->private.change.items) == 1); SmlItem *item = g_list_nth_data(change->private.change.items, 0); if (!item) { smlErrorSet(error, SML_ERROR_GENERIC, "One item of the item list is NULL."); goto error; } if (!item->contenttype) { smlErrorSet(error, SML_ERROR_GENERIC, "Missing contenttype"); goto error; } //Meta if (!_smlXmlAssemblerStartNode(assm, SML_ELEMENT_META, error)) goto error; if (!_smlXmlAssemblerAddStringNS(assm, SML_ELEMENT_TYPE, SML_NAMESPACE_METINF, item->contenttype, error)) goto error; /* We will add the max obj size node, if USE_LARGEOBJECTS is true or not set at all. * And the remote side must have set a maxobjsize if we are a server */ const char *opt = smlAssemblerGetOption(assm->assembler, "USE_LARGEOBJECTS"); SmlBool supportsLargeObjects = (opt && !atoi(opt)) ? FALSE : TRUE; smlTrace(TRACE_INTERNAL, "%s: Large object: use %i, server %i, requestedSize %i", __func__, supportsLargeObjects, assm->session->sessionType == SML_SESSION_TYPE_SERVER ? 1 : 0, smlAssemblerGetRemoteMaxObjSize(assm->assembler)); if (supportsLargeObjects && change->size) { if (!_smlXmlAssemblerAddIDNS(assm, SML_ELEMENT_SIZE, SML_NAMESPACE_METINF, change->size, error)) goto error; } //META if (!_smlXmlAssemblerEndNode(assm, error)) goto error; //Item(s) /* Item has to deal with four different situations: * 1. If this is a new item but the remote peer only supports * the Replace command and the local peer is an OMA DS * server then the ID/location must be send as target. * If the local peer is an OMA DS client then nothing * changes. FYI an OMA DS server must support the Add * command. * => Target must be set (Target is the former Source) * 2. If this is a new item then the local peer only knows * the ID of the item. * => Source must be set * 3. If this is a changed or deleted item and the local peer * is an OMA DS server then the item must reference the ID * of the remote peer because of the submitted map. Please * not that the remote peer as an OMA DS client must only * know its own ID of the item. The mapping of locations * (IDs) is the exclusive job of the OMA DS server. * => Target must be set (Source is optional) * 4. If this is a changed or deleted item and the local peer * is an OMA DS client then the item must reference the ID * of the local peer only because the mapping of locations * (IDs) must be done by the OMA DS server. * => Source must be set */ SmlSessionType sessionType = assm->session->sessionType; opt = smlAssemblerGetOption(assm->assembler, "ONLY_REPLACE"); if (change->type == SML_COMMAND_TYPE_ADD) { if (opt && atoi(opt) && /* remote peer supports ONLY_REPLACE */ sessionType == SML_SESSION_TYPE_SERVER) { /* only Target must be set */ if (item->target) smlLocationUnref(item->target); item->target = item->source; item->source = NULL; } else { /* only Source must be set */ if (item->target) smlLocationUnref(item->target); item->target = NULL; } } else { if (sessionType == SML_SESSION_TYPE_SERVER) { /* Target must be set */ if (item->source) smlLocationUnref(item->source); item->source = NULL; } else { /* only Source must be set */ if (item->target) smlLocationUnref(item->target); item->target = NULL; } } if (!smlItemAssemble(item, assm, error)) goto error; smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return FALSE; } SmlBool smlSyncAssemble(SmlXmlAssembler *assm, SmlCommand *cmd, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, assm, cmd, error); CHECK_ERROR_REF smlAssert(cmd); smlAssert(assm); if (!cmd->target) { smlErrorSet(error, SML_ERROR_GENERIC, "No target set"); goto error; } /* The specification OMA DS Protocol v1.2 allows to add * MaxObjsize to Alert or Sync commands but all examples show * it only in Alert commands. Therefore libsyncml adds it to * Alert commands only. */ if (!smlLocationAssemble(cmd->target, assm, SML_ELEMENT_TARGET, error)) goto error; if (!cmd->source) { smlErrorSet(error, SML_ERROR_GENERIC, "No source set"); goto error; } if (!smlLocationAssemble(cmd->source, assm, SML_ELEMENT_SOURCE, error)) goto error; if (_smlAssembleUseMaxObjSize(assm)) { if (!_smlXmlAssemblerStartNode(assm, SML_ELEMENT_META, error)) goto error; if (!_smlAssembleMaxObjSize(assm, error)) goto error; if (!_smlXmlAssemblerEndNode(assm, error)) goto error; } const char *opt = smlAssemblerGetOption(assm->assembler, "USE_NUMBEROFCHANGES"); SmlBool supportsNumberOfChanges = (opt && !atoi(opt)) ? FALSE : TRUE; if (supportsNumberOfChanges && assm->session->version != SML_VERSION_10) { if (!_smlXmlAssemblerAddID(assm, SML_ELEMENT_NUMBEROFCHANGES, cmd->private.sync.numChanged, error)) goto error; } smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return FALSE; } SmlBool smlMapItemAssemble(SmlXmlAssembler *assm, SmlMapItem *item, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, assm, item, error); CHECK_ERROR_REF smlAssert(assm); smlAssert(item); if (!_smlXmlAssemblerStartNode(assm, SML_ELEMENT_MAPITEM, error)) goto error; if (item->source) { if (!smlLocationAssemble(item->source, assm, SML_ELEMENT_SOURCE, error)) goto error; } if (item->target) { if (!smlLocationAssemble(item->target, assm, SML_ELEMENT_TARGET, error)) goto error; } //MapItem if (!_smlXmlAssemblerEndNode(assm, error)) goto error; smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return FALSE; } SmlBool smlMapAssemble(SmlXmlAssembler *assm, SmlCommand *cmd, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, assm, cmd, error); CHECK_ERROR_REF smlAssert(cmd); smlAssert(assm); if (!cmd->target) { smlErrorSet(error, SML_ERROR_GENERIC, "No target set"); goto error; } if (!smlLocationAssemble(cmd->target, assm, SML_ELEMENT_TARGET, error)) goto error; if (!cmd->source) { smlErrorSet(error, SML_ERROR_GENERIC, "No source set"); goto error; } if (!smlLocationAssemble(cmd->source, assm, SML_ELEMENT_SOURCE, error)) goto error; GList *m = NULL; for (m = cmd->private.map.items; m; m = m->next) { SmlMapItem *item = m->data; if (!smlMapItemAssemble(assm, item, error)) goto error; } smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return FALSE; } SmlBool smlAlertAssemble(SmlXmlAssembler *assm, SmlCommand *cmd, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, assm, cmd, error); CHECK_ERROR_REF smlAssert(cmd); smlAssert(assm); /* Results itself and CmdID must be set by the caller. * This function only add the Results specific content. */ /* No Resp */ /* Cred */ /* Data */ if (!_smlXmlAssemblerAddID(assm, SML_ELEMENT_DATA, cmd->private.alert.type, error)) goto error; /* Correlator */ /* Begin of Item */ if (!_smlXmlAssemblerStartNode(assm, SML_ELEMENT_ITEM, error)) goto error; /* Target */ if (cmd->target) { if (!smlLocationAssemble(cmd->target, assm, SML_ELEMENT_TARGET, error)) goto error; } /* Source */ if (cmd->source) { if (!smlLocationAssemble(cmd->source, assm, SML_ELEMENT_SOURCE, error)) goto error; } else { // NEXT MESSAGE alerts does not need a source/target if (cmd->private.alert.type != SML_ALERT_NEXT_MESSAGE) { smlErrorSet(error, SML_ERROR_GENERIC, "No source set"); goto error; } } /* SourceParent */ /* TargetParent */ /* Begin of META */ SmlBool meta = FALSE; if (cmd->private.alert.contentType) meta = TRUE; if (cmd->private.alert.anchor) meta = TRUE; if (_smlAssembleUseMaxObjSize(assm)) meta = TRUE; if (meta && !_smlXmlAssemblerStartNode(assm, SML_ELEMENT_META, error)) goto error; if (cmd->private.alert.contentType && !_smlXmlAssemblerAddStringNS(assm, SML_ELEMENT_TYPE, SML_NAMESPACE_METINF, cmd->private.alert.contentType, error)) goto error; if (cmd->private.alert.anchor && !smlAnchorAssemble(cmd->private.alert.anchor, assm, error)) goto error; if (_smlAssembleUseMaxObjSize(assm) && !_smlAssembleMaxObjSize(assm, error)) goto error; if (meta && !_smlXmlAssemblerEndNode(assm, error)) goto error; /* End of META */ /* End of Item */ if (!_smlXmlAssemblerEndNode(assm, error)) goto error; smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return FALSE; } SmlBool smlResultsAssemble(SmlXmlAssembler *assm, SmlCommand *cmd, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, assm, cmd, error); CHECK_ERROR_REF smlAssert(cmd); smlAssert(assm); /* Results itself and CmdID must be set by the caller. * This function only add the Results specific content. */ /* MsgRef */ if (!_smlXmlAssemblerAddID(assm, SML_ELEMENT_MSGREF, cmd->private.results.status->msgRef, error)) goto error; /* CmdRef */ if (!_smlXmlAssemblerAddID(assm, SML_ELEMENT_CMDREF, cmd->private.results.status->cmdRef, error)) goto error; /* Meta */ if (!_smlXmlAssemblerStartNode(assm, SML_ELEMENT_META, error)) goto error; if (!_smlXmlAssemblerAddStringNS(assm, SML_ELEMENT_TYPE, SML_NAMESPACE_METINF, cmd->private.results.status->item->contenttype, error)) goto error; if (!_smlXmlAssemblerEndNode(assm, error)) goto error; /* TargetRef */ if (cmd->private.results.status->targetRef) { if (!_smlXmlAssemblerAddString(assm, SML_ELEMENT_TARGETREF, cmd->private.results.status->targetRef->locURI, error)) goto error; } /* SourceRef */ if (cmd->private.results.status->sourceRef) { if (!_smlXmlAssemblerAddString(assm, SML_ELEMENT_SOURCEREF, cmd->private.results.status->sourceRef->locURI, error)) goto error; } /* Item */ if (!smlItemAssemble(cmd->private.results.status->item, assm, error)) goto error; smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return FALSE; } SmlBool smlXmlAssemblerAddHeader(SmlXmlAssembler *assm, SmlSession *session, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, assm, session, error); CHECK_ERROR_REF smlAssert(assm); smlAssert(g_mutex_trylock(assm->mutex)); smlAssert(session); /* Lets see if there already was a header before */ if (assm->header_buffer) { xmlBufferFree(assm->header_buffer); assm->header_buffer = NULL; } /* We first start a new writer that will write our header into a buffer */ assm->header_buffer = xmlBufferCreateSize(BUFFER_SIZE); if (!assm->header_buffer) { smlErrorSet(error, SML_ERROR_GENERIC, "Unable to create new buffer"); goto error; } assm->writer = xmlNewTextWriterMemory(assm->header_buffer, 0); if (!assm->writer) { smlErrorSet(error, SML_ERROR_GENERIC, "Unable to create new writer"); goto error; } if (!_smlXmlAssemblerStartNode(assm, SML_ELEMENT_SYNCHDR, error)) goto error; if (!session->protocol) { smlErrorSet(error, SML_ERROR_GENERIC, "No version set"); goto error; } if (!session->version) { smlErrorSet(error, SML_ERROR_GENERIC, "No dtd set"); goto error; } switch (session->protocol) { case SML_PROTOCOL_SYNCML: switch (session->version) { case SML_VERSION_10: if (!_smlXmlAssemblerAddString(assm, SML_ELEMENT_VERDTD, "1.0", error)) goto error; if (!_smlXmlAssemblerAddString(assm, SML_ELEMENT_VERPROTO, SML_VERSION_STRING_10, error)) goto error; break; case SML_VERSION_11: if (!_smlXmlAssemblerAddString(assm, SML_ELEMENT_VERDTD, "1.1", error)) goto error; if (!_smlXmlAssemblerAddString(assm, SML_ELEMENT_VERPROTO, SML_VERSION_STRING_11, error)) goto error; break; case SML_VERSION_12: if (!_smlXmlAssemblerAddString(assm, SML_ELEMENT_VERDTD, "1.2", error)) goto error; if (!_smlXmlAssemblerAddString(assm, SML_ELEMENT_VERPROTO, SML_VERSION_STRING_12, error)) goto error; break; default: smlErrorSet(error, SML_ERROR_GENERIC, "Unknown version"); goto error; } break; default: smlErrorSet(error, SML_ERROR_GENERIC, "Unknown protocol"); goto error; } if (session->sessionID) { if (!_smlXmlAssemblerAddString(assm, SML_ELEMENT_SESSIONID, session->sessionID, error)) goto error; } if (!_smlXmlAssemblerAddID(assm, SML_ELEMENT_MSGID, session->lastMessageID, error)) goto error; if (!smlLocationAssemble(session->target, assm, SML_ELEMENT_TARGET, error)) goto error; if (!smlLocationAssemble(session->source, assm, SML_ELEMENT_SOURCE, error)) goto error; if (session->responseURI && !_smlXmlAssemblerAddString(assm, SML_ELEMENT_RESPURI, session->responseURI, error)) goto error; /* The credentials must be present and calculated for the correct * authentication schema (e.g. syncml:auth-basic or syncml:auth-md5). */ if (session->cred != NULL && session->cred->data != NULL) { if (!smlCredAssemble(session->cred, assm, error)) goto error; } /* What do we have to check here? * * SyncML 1.0 does not require any checks because large object * handling was first specified for SyncML 1.1. * * SyncML 1.1 and 1.2 require some checks. * * 1. OMA DS server MUST support large objects. * This means that a local MaxMsgSize and a local MaxObjSize * MUST be specified. * 2. If an OMA DS client suppors large objects then it MUST * match the same requirements like the OMA DS server. */ if (session->protocol == SML_PROTOCOL_SYNCML && session->version > SML_VERSION_10) { /* This is a SyncML protocol version which supports * large objects. */ if (session->sessionType == SML_SESSION_TYPE_SERVER || smlSessionGetLocalMaxObjSize(session) > 0) { /* Large object support is enabled. */ if (smlSessionGetLocalMaxMsgSize(session) < 1) { smlErrorSet(error, SML_ERROR_INTERNAL_MISCONFIGURATION, "MaxMsgSize must be set."); goto error; } if (smlSessionGetLocalMaxObjSize(session) < 1) { smlErrorSet(error, SML_ERROR_INTERNAL_MISCONFIGURATION, "MaxObjSize must be set."); goto error; } } } /* set MaxMsgSize if available */ unsigned int localMaxMsgSize = smlSessionGetLocalMaxMsgSize(session); if (localMaxMsgSize) { if (!_smlXmlAssemblerStartNode(assm, SML_ELEMENT_META, error)) goto error; /* Do not add MaxObjSize here. * Please see OMA DS Protocol v1.2 section 6.10.1 */ if (!_smlXmlAssemblerAddIDNS(assm, SML_ELEMENT_MAXMSGSIZE, SML_NAMESPACE_METINF, localMaxMsgSize, error)) goto error; //META if (!_smlXmlAssemblerEndNode(assm, error)) goto error; } if (!_smlXmlAssemblerEndNode(assm, error)) goto error; /* Now close the buffer and get the content */ if (xmlTextWriterEndDocument(assm->writer) < 0) { smlErrorSet(error, SML_ERROR_GENERIC, "Unable to end writer"); goto error; } xmlFreeTextWriter(assm->writer); assm->writer = NULL; g_mutex_unlock(assm->mutex); smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error: if (assm->writer) { xmlFreeTextWriter(assm->writer); assm->writer = NULL; } if (assm->header_buffer) { xmlBufferFree(assm->header_buffer); assm->header_buffer = NULL; } g_mutex_unlock(assm->mutex); smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return FALSE; } SmlBool smlXmlAssemblerStartCommand(SmlXmlAssembler *assm, unsigned int parentID, SmlCommand *cmd, SmlError **error) { CHECK_ERROR_REF smlAssert(assm); smlAssert(cmd); if (cmd->type == SML_COMMAND_TYPE_UNKNOWN) { smlErrorSet(error, SML_ERROR_GENERIC, "No cmd set"); goto error; } if (!cmd->cmdID) { smlErrorSet(error, SML_ERROR_GENERIC, "No cmd ID set"); goto error; } /* Lets see if there already was a header before */ if (!assm->header_buffer) { smlErrorSet(error, SML_ERROR_GENERIC, "Header not yet added"); goto error; } SmlXmlAssemblerCommand *assmcmd = smlTryMalloc0(sizeof(SmlXmlAssemblerCommand), error); if (!assmcmd) goto error; assmcmd->nodeType = SML_ASSEMBLER_NODE_OPEN; assmcmd->cmdID = cmd->cmdID; assmcmd->cmdType = cmd->type; GList **appendto = &(assm->commands); if (parentID) { /* If we have a parent we first have to search for this command */ SmlXmlAssemblerCommand *excmd = NULL; GList *b = NULL; for (b = assm->commands; b; b = b->next) { excmd = b->data; if (excmd->cmdID == parentID) appendto = &(excmd->children); } } /* We first start a new parent writer that will write our command into a buffer */ assmcmd->buffer = xmlBufferCreateSize(BUFFER_SIZE); if (!assmcmd->buffer) { smlErrorSet(error, SML_ERROR_GENERIC, "Unable to create new buffer"); goto error_free_cmd; } assm->writer = xmlNewTextWriterMemory(assmcmd->buffer, 0); if (!assm->writer) { smlErrorSet(error, SML_ERROR_GENERIC, "Unable to create new writer"); goto error_free_buffer; } /* We start without the root node */ if (!_smlXmlAssemblerAddID(assm, SML_ELEMENT_CMDID, cmd->cmdID, error)) goto error_free_writer; switch (cmd->type) { case SML_COMMAND_TYPE_ALERT: if (!smlAlertAssemble(assm, cmd, error)) goto error_free_writer; break; case SML_COMMAND_TYPE_SYNC: if (!smlSyncAssemble(assm, cmd, error)) goto error_free_writer; break; case SML_COMMAND_TYPE_ADD: case SML_COMMAND_TYPE_REPLACE: case SML_COMMAND_TYPE_DELETE: if (!smlChangeAssemble(assm, cmd, error)) goto error_free_writer; break; case SML_COMMAND_TYPE_PUT: case SML_COMMAND_TYPE_GET: if (!smlAccessAssemble(assm, cmd, error)) goto error_free_writer; break; case SML_COMMAND_TYPE_MAP: if (!smlMapAssemble(assm, cmd, error)) goto error_free_writer; break; case SML_COMMAND_TYPE_RESULTS: if (!smlResultsAssemble(assm, cmd, error)) goto error_free_writer; break; default: smlErrorSet(error, SML_ERROR_GENERIC, "Unknown command type"); goto error_free_writer; } /* Now close the buffer */ if (xmlTextWriterEndDocument(assm->writer) < 0) { smlErrorSet(error, SML_ERROR_GENERIC, "Unable to end writer"); goto error_free_writer; } xmlFreeTextWriter(assm->writer); assm->writer = NULL; /* Now we can append the buffer and the parent*/ *appendto = g_list_append(*appendto, assmcmd); return TRUE; error_free_writer: xmlFreeTextWriter(assm->writer); assm->writer = NULL; error_free_buffer: xmlBufferFree(assmcmd->buffer); error_free_cmd: smlSafeFree((gpointer *)&assmcmd); error: return FALSE; } SmlBool smlXmlAssemblerEndCommand(SmlXmlAssembler *assm, unsigned int parentID, SmlError **error) { CHECK_ERROR_REF smlAssert(assm); /* Lets see if there already was a header before */ if (!assm->header_buffer) { smlErrorSet(error, SML_ERROR_GENERIC, "Header not yet added"); goto error; } SmlXmlAssemblerCommand *assmcmd = smlTryMalloc0(sizeof(SmlXmlAssemblerCommand), error); if (!assmcmd) goto error; assmcmd->nodeType = SML_ASSEMBLER_NODE_CLOSE; GList **appendto = &(assm->commands); if (parentID) { /* If we have a parent we first have to search for this command */ SmlXmlAssemblerCommand *excmd = NULL; GList *b = NULL; for (b = assm->commands; b; b = b->next) { excmd = b->data; if (excmd->cmdID == parentID) appendto = &(excmd->children); } } /* Now we can append command */ *appendto = g_list_append(*appendto, assmcmd); return TRUE; error: return FALSE; } SmlBool smlXmlAssemblerRemCommand(SmlXmlAssembler *assm, unsigned int parentID, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %i, %p)", __func__, assm, parentID, error); CHECK_ERROR_REF smlAssert(assm); GList **removefrom = &(assm->commands); if (parentID) { /* If we have a parent we first have to search for this command */ SmlXmlAssemblerCommand *excmd = NULL; GList *b = NULL; for (b = assm->commands; b; b = b->next) { excmd = b->data; if (excmd->cmdID == parentID) removefrom = &(excmd->children); } } if (!*removefrom) { smlErrorSet(error, SML_ERROR_GENERIC, "Nothing to remove"); goto error; } GList *b = g_list_last(*removefrom); SmlXmlAssemblerCommand *cmd = b->data; *removefrom = g_list_delete_link(*removefrom, b); if (cmd->nodeType != SML_ASSEMBLER_NODE_OPEN) { smlErrorSet(error, SML_ERROR_GENERIC, "Trying to remove not a starting command"); goto error; } assm->moreDataSet = FALSE; xmlBufferFree(cmd->buffer); smlSafeFree((gpointer *)&cmd); smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return FALSE; } SmlBool smlXmlAssemblerRemStatus(SmlXmlAssembler *assm, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p)", __func__, assm, error); CHECK_ERROR_REF smlAssert(assm); if (!assm->statuses) { smlErrorSet(error, SML_ERROR_GENERIC, "Trying to remove status but no status available"); goto error; } GList *b; SmlXmlAssemblerStatus *last = NULL; for (b = assm->statuses; b; b = b->next) { SmlXmlAssemblerStatus *status = b->data; if (!status->buffer) break; last = status; } if (last) { xmlBufferFree(last->buffer); last->buffer = NULL; } assm->added_statuses--; smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return FALSE; } SmlBool smlXmlAssemblerReserveStatus(SmlXmlAssembler *assm, unsigned int cmdRef, unsigned int msgRef, unsigned int cmdID, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %i, %i, %i, %p)", __func__, assm, cmdRef, msgRef, cmdID, error); CHECK_ERROR_REF smlAssert(assm); /* We first start a new writer that will write our status into a buffer */ SmlXmlAssemblerStatus *res = smlTryMalloc0(sizeof(SmlXmlAssemblerStatus), error); if (!res) goto error; res->cmdRef = cmdRef; res->cmdID = cmdID; res->msgRef = msgRef; /* Now we can append the buffer */ if (cmdRef != 0) assm->statuses = g_list_append(assm->statuses, res); else assm->statuses = g_list_prepend(assm->statuses, res); assm->reserved_statuses++; smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return FALSE; } SmlBool smlXmlAssemblerAddStatus(SmlXmlAssembler *assm, SmlStatus *status, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, assm, status, error); CHECK_ERROR_REF smlAssert(assm); smlAssert(g_mutex_trylock(assm->mutex)); smlAssert(status); SmlXmlAssemblerStatus *res = NULL; smlTrace(TRACE_INTERNAL, "Adding status with cmdRef %i, msgRef %i, cmd %s", status->cmdRef, status->msgRef, smlCommandTypeToString(status->type, error)); /* this happens if the status is damaged */ if (*error) goto error; if (!status->msgRef) { smlErrorSet(error, SML_ERROR_GENERIC, "No msgref set"); goto error; } if (status->type == SML_COMMAND_TYPE_UNKNOWN) { smlErrorSet(error, SML_ERROR_GENERIC, "No cmd set"); goto error; } /* Lets see if there already was a header before */ if (!assm->header_buffer) { smlErrorSet(error, SML_ERROR_GENERIC, "Header not yet added"); goto error; } /* Get the reserved buffer */ GList *s = NULL; for (s = assm->statuses; s; s = s->next) { res = s->data; if (res->cmdRef == status->cmdRef && res->msgRef == status->msgRef) break; res = NULL; } if (!res) { smlErrorSet(error, SML_ERROR_GENERIC, "Status not reserved"); goto error; } if (!res->cmdID) { smlErrorSet(error, SML_ERROR_GENERIC, "No cmd ID set"); goto error; } if (res->buffer) { smlErrorSet(error, SML_ERROR_GENERIC, "Status already added"); goto error; } /* We first start a new writer that will write our status into a buffer */ res->buffer = xmlBufferCreateSize(BUFFER_SIZE); if (!res->buffer) { smlErrorSet(error, SML_ERROR_GENERIC, "Unable to create new buffer"); goto error; } assm->writer = xmlNewTextWriterMemory(res->buffer, 0); if (!assm->writer) { smlErrorSet(error, SML_ERROR_GENERIC, "Unable to create new writer"); goto error_free_buffer; } /* Begin of Status */ if (!_smlXmlAssemblerStartNode(assm, SML_ELEMENT_STATUS, error)) goto error; /* CmdID */ if (!_smlXmlAssemblerAddID(assm, SML_ELEMENT_CMDID, res->cmdID, error)) goto error; /* MsgRef */ if (!_smlXmlAssemblerAddID(assm, SML_ELEMENT_MSGREF, status->msgRef, error)) goto error; /* CmdRef */ if (!_smlXmlAssemblerAddID(assm, SML_ELEMENT_CMDREF, res->cmdRef, error)) goto error; /* Cmd */ const char *cmdname = smlCommandTypeToString(status->type, error); if (!cmdname) goto error; if (!_smlXmlAssemblerAddString(assm, SML_ELEMENT_CMD, cmdname, error)) goto error; /* TargetRef */ if (status->targetRef) { if (!_smlXmlAssemblerAddString(assm, SML_ELEMENT_TARGETREF, status->targetRef->locURI, error)) goto error; } /* SourceRef */ if (status->sourceRef) { if (!_smlXmlAssemblerAddString(assm, SML_ELEMENT_SOURCEREF, status->sourceRef->locURI, error)) goto error; } /* Cred */ /* Chal */ if (status->type == SML_COMMAND_TYPE_HEADER && status->chal) { if (!_smlXmlAssemblerStartNode(assm, SML_ELEMENT_CHAL, error)) goto error; if (!_smlXmlAssemblerStartNode(assm, SML_ELEMENT_META, error)) goto error; if (!_smlXmlAssemblerAddStringNS(assm, SML_ELEMENT_FORMAT, SML_NAMESPACE_METINF, SML_BASE64, error)) goto error; switch (status->chal->type) { case SML_AUTH_TYPE_BASIC: if (!_smlXmlAssemblerAddStringNS(assm, SML_ELEMENT_TYPE, SML_NAMESPACE_METINF, SML_AUTH_BASIC, error)) goto error; break; case SML_AUTH_TYPE_MD5: if (!_smlXmlAssemblerAddStringNS(assm, SML_ELEMENT_TYPE, SML_NAMESPACE_METINF, SML_AUTH_MD5, error)) goto error; if (status->chal->nonce_b64 && !_smlXmlAssemblerAddStringNS(assm, SML_ELEMENT_NEXTNONCE, SML_NAMESPACE_METINF, status->chal->nonce_b64, error)) goto error; break; default: smlErrorSet(error, SML_ERROR_GENERIC, "Unknown auth type"); goto error; } //META if (!_smlXmlAssemblerEndNode(assm, error)) goto error; //CHAL if (!_smlXmlAssemblerEndNode(assm, error)) goto error; } /* Data */ if (status->data) { if (!_smlXmlAssemblerAddString(assm, SML_ELEMENT_DATA, status->data, error)) goto error; } /* Item */ if (status->type == SML_COMMAND_TYPE_ALERT && status->anchor) { if (!_smlXmlAssemblerStartNode(assm, SML_ELEMENT_ITEM, error)) goto error; if (!_smlXmlAssemblerStartNode(assm, SML_ELEMENT_DATA, error)) goto error; if (!smlAnchorAssemble(status->anchor, assm, error)) goto error; //DATA if (!_smlXmlAssemblerEndNode(assm, error)) goto error; //ITEM if (!_smlXmlAssemblerEndNode(assm, error)) goto error; } /* End of Status */ if (!_smlXmlAssemblerEndNode(assm, error)) goto error; /* Now close the buffer and get the content */ if (xmlTextWriterEndDocument(assm->writer) < 0) { smlErrorSet(error, SML_ERROR_GENERIC, "Unable to end writer"); goto error_free_writer; } xmlFreeTextWriter(assm->writer); assm->writer = NULL; assm->added_statuses++; g_mutex_unlock(assm->mutex); smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error_free_writer: xmlFreeTextWriter(assm->writer); assm->writer = NULL; error_free_buffer: xmlBufferFree(res->buffer); res->buffer = NULL; error: g_mutex_unlock(assm->mutex); smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return FALSE; } SmlBool smlXmlAssemblerMissingStatus(SmlXmlAssembler *assm) { smlAssert(assm); if (assm->reserved_statuses - assm->added_statuses > 0) return TRUE; return FALSE; } static void flush_list(GList *list) { GList *l = NULL; for (l = list; l; l = l->next) { SmlXmlAssemblerCommand *cmd = l->data; if (cmd->nodeType != SML_ASSEMBLER_NODE_CLOSE && cmd->children) flush_list(cmd->children); xmlBufferFree(cmd->buffer); smlSafeFree((gpointer *)&cmd); } g_list_free(list); } void smlXmlAssemblerFree(SmlXmlAssembler *assm) { smlTrace(TRACE_ENTRY, "%s(%p)", __func__, assm); smlAssert(assm); if (assm->header_buffer) { xmlBufferFree(assm->header_buffer); assm->header_buffer = NULL; } while (assm->statuses) { SmlXmlAssemblerStatus *status = assm->statuses->data; if (status->buffer) xmlBufferFree(status->buffer); smlSafeFree((gpointer *)&status); assm->statuses = g_list_delete_link(assm->statuses, assm->statuses); } flush_list(assm->commands); flush_list(assm->last_commands); g_mutex_free(assm->mutex); smlSafeFree((gpointer *)&assm); smlTrace(TRACE_EXIT, "%s", __func__); } /* This function returns the highest command id that is still in the * assembler after flushing which is: number of statuses + 1 */ unsigned int smlXmlAssemblerFlush(SmlXmlAssembler *assm) { smlTrace(TRACE_ENTRY, "%s(%p)", __func__, assm); smlAssert(assm); unsigned int newid = 1; SmlBool missing = FALSE; /* Remove the statuses */ GList *s = NULL; GList *s2 = g_list_copy(assm->statuses); for (s = s2; s; s = s->next) { SmlXmlAssemblerStatus *status = s->data; /* Only remove statuses that were added already */ if (!status->buffer) { /* If the status was not yet added, we have to reset the command id. * We start with id #2 (since #1 will be the header reply) */ /* FIXME: why should we reset a command id? */ newid++; // status->cmdID = newid; missing = TRUE; } else if (!missing) { xmlBufferFree(status->buffer); assm->statuses = g_list_remove(assm->statuses, status); smlSafeFree((gpointer *)&status); assm->reserved_statuses--; assm->added_statuses--; } } g_list_free(s2); /* Remove all commands that are complete * Perhaps more correct remove all commands from the last message. * The actual commands are cached to support error 407 handling. * (AUTHENTICATION_REQUIRED) */ if (assm->last_commands) flush_list(assm->last_commands); assm->last_commands = assm->commands; assm->commands = NULL; /* Reset LargeObject handling */ assm->moreDataSet = FALSE; smlTrace(TRACE_EXIT, "%s: %i", __func__, newid); return newid; } SmlBool smlXmlAssemblerStart(SmlXmlAssembler *assm, SmlSession *session, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, assm, session, error); CHECK_ERROR_REF smlAssert(assm); smlAssert(g_mutex_trylock(assm->mutex)); smlAssert(session); assm->session = session; g_mutex_unlock(assm->mutex); smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; } SmlBool smlXmlAssemblerEnd(SmlXmlAssembler *assm, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p)", __func__, assm, error); CHECK_ERROR_REF smlAssert(assm); smlAssert(g_mutex_trylock(assm->mutex)); //Close syncml if (!_smlXmlAssemblerEndNode(assm, error)) goto error; if (_smlXmlAssemblerEndNode(assm, NULL)) { smlErrorSet(error, SML_ERROR_GENERIC, "Extra node open"); goto error; } g_mutex_unlock(assm->mutex); smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error: g_mutex_unlock(assm->mutex); smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return FALSE; } SmlBool smlXmlAssemblerAddChildren(SmlXmlAssembler *assm, GList *b, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, assm, b, error); CHECK_ERROR_REF smlAssert(assm); const char *opt = smlAssemblerGetOption(assm->assembler, "ONLY_REPLACE"); SmlBool onlyReplace = (opt && atoi(opt)) ? TRUE : FALSE; SmlXmlAssemblerCommand *cmd = NULL; const char *cmdname = NULL; for (; b; b = b->next) { cmd = b->data; switch (cmd->nodeType) { case SML_ASSEMBLER_NODE_OPEN: /* Add the corresponding command opener */ if (cmd->cmdType == SML_COMMAND_TYPE_ADD && onlyReplace) cmdname = SML_ELEMENT_REPLACE; else { cmdname = smlCommandTypeToString(cmd->cmdType, error); if (!cmdname) goto error; } smlTrace(TRACE_INTERNAL, "opening node %s", cmdname); if (!_smlXmlAssemblerStartNode(assm, cmdname, error)) goto error; int rc = xmlTextWriterWriteRawLen(assm->writer, xmlBufferContent(cmd->buffer), xmlBufferLength(cmd->buffer)); if (rc < 0) { smlErrorSet(error, SML_ERROR_GENERIC, "Unable to write raw node data (%d).", rc); goto error; } if (cmd->children) { if (!smlXmlAssemblerAddChildren(assm, cmd->children, error)) goto error; } smlTrace(TRACE_INTERNAL, "%s: closing node", __func__); if (!_smlXmlAssemblerEndNode(assm, error)) goto error; break; case SML_ASSEMBLER_NODE_CLOSE: /*smlTrace(TRACE_INTERNAL, "%s: closing node". __func__); if (!_smlXmlAssemblerEndNode(assm, error)) goto error;*/ break; } } smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return FALSE; } SmlBool smlXmlAssemblerRunFull(SmlXmlAssembler *assm, char **data, unsigned int *size, SmlBool *end, SmlBool final, SmlBool check, unsigned int maxsize, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p, %p, %i, %i, %i, %p)", __func__, assm, data, size, end, final, check, maxsize, error); CHECK_ERROR_REF smlAssert(assm); smlAssert(g_mutex_trylock(assm->mutex)); smlAssert(data); smlAssert(size); smlAssert(assm->session); unsigned int buffersize = 0; /* Return an error if there is no header */ if (!assm->header_buffer) { smlErrorSet(error, SML_ERROR_GENERIC, "No header available"); goto error; } /* Return an error if there is no status/command. Note that if * statuses have been reserved, at least the first status * must be added */ if (check && !assm->statuses && !assm->commands) { smlErrorSet(error, SML_ERROR_GENERIC, "No status/command available"); goto error; } if (check && assm->statuses && final) { SmlXmlAssemblerStatus *status = assm->statuses->data; if (!status->buffer) { smlErrorSet(error, SML_ERROR_GENERIC, "Missing the first status with cmdRef %i", status->cmdRef); goto error; } } /* Create the final buffer and writer */ xmlBuffer *buffer = xmlBufferCreateSize(BUFFER_SIZE); if (!buffer) { smlErrorSet(error, SML_ERROR_GENERIC, "Unable to create new buffer"); goto error; } assm->writer = xmlNewTextWriterMemory(buffer, 0); if (!assm->writer) { smlErrorSet(error, SML_ERROR_GENERIC, "Unable to create new writer"); goto error_free_buffer; } /* Sync4j has a bug and cannot handle the default XML encoding. * The default XML encoding is UTF-8. So this default encoding * is explicitly added to support buggy XML parsers. */ if (xmlTextWriterStartDocument(assm->writer, NULL, "UTF-8", NULL) < 0) { smlErrorSet(error, SML_ERROR_GENERIC, "Unable to create new writer"); goto error_free_writer; } /* Add the syncml start node */ switch (assm->session->version) { case SML_VERSION_10: xmlTextWriterWriteRaw(assm->writer, (xmlChar *)""); if (!_smlXmlAssemblerStartNodeNS(assm, SML_ELEMENT_SYNCML, SML_NAMESPACE_SYNCML10, error)) goto error_free_writer; break; case SML_VERSION_11: xmlTextWriterWriteRaw(assm->writer, (xmlChar *)""); if (!_smlXmlAssemblerStartNodeNS(assm, SML_ELEMENT_SYNCML, SML_NAMESPACE_SYNCML11, error)) goto error_free_writer; break; case SML_VERSION_12: xmlTextWriterWriteRaw(assm->writer, (xmlChar *)""); if (!_smlXmlAssemblerStartNodeNS(assm, SML_ELEMENT_SYNCML, SML_NAMESPACE_SYNCML12, error)) goto error_free_writer; break; default: smlErrorSet(error, SML_ERROR_GENERIC, "Unknown version"); goto error_free_writer; } /* Add the header */ int rc = xmlTextWriterWriteRawLen(assm->writer, xmlBufferContent(assm->header_buffer), xmlBufferLength(assm->header_buffer)); if (rc < 0) { smlErrorSet(error, SML_ERROR_GENERIC, "Unable to write raw header data (%d).", rc); goto error_free_writer; } /* Start the sync body */ if (!_smlXmlAssemblerStartNode(assm, SML_ELEMENT_SYNCBODY, error)) goto error_free_writer; // FIXME: why do we need 20 extra bytes here? // FIXME: buffersize is never read !!! buffersize += 20 + xmlBufferLength(assm->header_buffer); /* Add the statuses */ GList *b = NULL; SmlBool missingstatus = FALSE; smlTrace(TRACE_INTERNAL, "%s: Now adding %i statuses", __func__, g_list_length(assm->statuses)); for (b = assm->statuses; b; b = b->next) { SmlXmlAssemblerStatus *status = b->data; if (!status->buffer || xmlBufferLength(status->buffer) == 0) { if (status->cmdRef == 0 && check) { smlErrorSet(error, SML_ERROR_GENERIC, "Reserved status 0 has not been added"); goto error_free_writer; } smlTrace(TRACE_INTERNAL, "%s: Reserved status %i is missing", __func__, status->cmdRef); missingstatus = TRUE; break; } buffersize += xmlBufferLength(status->buffer); //if (maxsize && buffersize > maxsize) // break; rc = xmlTextWriterWriteRawLen(assm->writer, xmlBufferContent(status->buffer), xmlBufferLength(status->buffer)); if (rc < 0) { smlErrorSet(error, SML_ERROR_GENERIC, "Unable to write raw status data (%d - %d of %d: %s).", rc, xmlBufferLength(status->buffer), buffersize, xmlBufferContent(status->buffer)); goto error_free_writer; } } /* We cannot have missing statuses when its final. And we cannot add commands */ if (missingstatus && final && check) { smlErrorSet(error, SML_ERROR_GENERIC, "Reserved status has not been added"); goto error_free_writer; } /* Add the commands. Parent commands are added in the order they were added. */ if (!smlXmlAssemblerAddChildren(assm, assm->commands, error)) goto error_free_writer; if (final) { smlTrace(TRACE_INTERNAL, "%s: setting final", __func__); if (!_smlXmlAssemblerAddString(assm, SML_ELEMENT_FINAL, "", error)) goto error_free_writer; } /* Close syncbody */ if (!_smlXmlAssemblerEndNode(assm, error)) goto error_free_writer; /* Close syncml */ if (!_smlXmlAssemblerEndNode(assm, error)) goto error_free_writer; if (xmlTextWriterEndDocument(assm->writer) < 0) { smlErrorSet(error, SML_ERROR_GENERIC, "Unable to end writer"); goto error; } xmlFreeTextWriter(assm->writer); assm->writer = NULL; // the buffer was created with xmlBufferCreateSize // so we must free it via the libxml API and not via smlSafeCFree *size = xmlBufferLength(buffer); *data = g_strndup((const char *) xmlBufferContent(buffer), *size); xmlBufferFree(buffer); if (end) { if (final && !assm->commands) *end = TRUE; else *end = FALSE; } smlTrace(TRACE_INTERNAL, "%s: Message Assembled: %s", __func__, VA_STRING(*data)); g_mutex_unlock(assm->mutex); smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error_free_writer: xmlFreeTextWriter(assm->writer); assm->writer = NULL; error_free_buffer: xmlBufferFree(buffer); error: g_mutex_unlock(assm->mutex); smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return FALSE; } static unsigned int calc_list(GList *list) { unsigned int size = 0; for (; list; list = list->next) { SmlXmlAssemblerCommand *cmd = list->data; size += 15; if (cmd->nodeType != SML_ASSEMBLER_NODE_CLOSE) { size += xmlBufferLength(cmd->buffer); if (cmd->children) size += calc_list(cmd->children); } } return size; } SmlBool smlXmlAssemblerRun(SmlXmlAssembler *assm, char **data, unsigned int *size, SmlBool *end, SmlBool final, unsigned int maxsize, SmlError **error) { CHECK_ERROR_REF SmlBool ans = smlXmlAssemblerRunFull(assm, data, size, end, final, TRUE, maxsize, error); if (ans) smlLog("sent-%i.xml", *data, *size); else smlTrace(TRACE_ERROR, "%s - %s", __func__, smlErrorPrint(error)); return ans; } unsigned int smlXmlAssemblerCheckSize(SmlXmlAssembler *assm, SmlBool headeronly, SmlError **error) { CHECK_ERROR_REF smlAssert(assm); SmlXmlAssemblerStatus *status = NULL; unsigned int size = 0; /* Add the size if the syncml tags etc */ size += 20; /* Add the size of the header */ if (assm->header_buffer) size += xmlBufferLength(assm->header_buffer); if (!headeronly) { /* Add the size of the status */ GList *b = NULL; for (b = assm->statuses; b; b = b->next) { status = b->data; if (!status->buffer) break; size += xmlBufferLength(status->buffer); } /* Add the size of the commands */ size += calc_list(assm->commands); } return size; } SmlBool smlXmlAssemblerNextCmdRef(SmlXmlAssembler *assm, unsigned int *cmdRef, unsigned int *msgRef) { smlAssert(assm); smlAssert(cmdRef); smlAssert(msgRef); SmlXmlAssemblerStatus *status = NULL; GList *b = NULL; for (b = assm->statuses; b; b = b->next) { status = b->data; if (!status->buffer) { *cmdRef = status->cmdRef; *msgRef = status->msgRef; return TRUE; } } return FALSE; } /** @brief Creates a new XML assembler * * @param session The session for which to create the assembler * @param error A pointer to an error struct * @return The new assembler or NULL in the case of an error * */ SmlXmlAssembler *smlXmlAssemblerNew(SmlAssembler *assembler, SmlAssemblerFunctions *functions, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, assembler, functions, error); CHECK_ERROR_REF SmlXmlAssembler *assm = smlTryMalloc0(sizeof(SmlXmlAssembler), error); if (!assm) goto error; assm->assembler = assembler; assm->mutex = g_mutex_new(); if (!assm->mutex) goto error_mutex; functions->start = (SmlAssemblerStartFunction)smlXmlAssemblerStart; functions->free = (SmlAssemblerFreeFunction)smlXmlAssemblerFree; functions->run = (SmlAssemblerRunFunction)smlXmlAssemblerRun; functions->end = (SmlAssemblerEndFunction)smlXmlAssemblerEnd; functions->add_header = (SmlAssemblerHeaderFunction)smlXmlAssemblerAddHeader; functions->start_cmd = (SmlAssemblerStartCommandFunction)smlXmlAssemblerStartCommand; functions->end_cmd = (SmlAssemblerEndCommandFunction)smlXmlAssemblerEndCommand; functions->rem_cmd = (SmlAssemblerRemCommandFunction)smlXmlAssemblerRemCommand; functions->add_status = (SmlAssemblerStatusFunction)smlXmlAssemblerAddStatus; functions->rem_status = (SmlAssemblerRemStatusFunction)smlXmlAssemblerRemStatus; functions->reserve_status = (SmlAssemblerReserveStatusFunction)smlXmlAssemblerReserveStatus; functions->missing_status = (SmlAssemblerStatusMissingFunction)smlXmlAssemblerMissingStatus; functions->check_size = (SmlAssemblerCheckFunction)smlXmlAssemblerCheckSize; functions->next_cmdref = (SmlAssemblerNextCmdRefFunction)smlXmlAssemblerNextCmdRef; functions->flush = (SmlAssemblerFlushFunction)smlXmlAssemblerFlush; functions->restore_cmds = (SmlAssemblerRestoreCommandsFunction)smlXmlAssemblerRestoreCommands; smlTrace(TRACE_EXIT, "%s: %p", __func__, assm); return assm; error_mutex: smlSafeFree((gpointer *)&assm); smlErrorSet(error, SML_ERROR_GENERIC, "%s - Cannot create new mutex.", __func__); error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return NULL; } static SmlBool _smlXmlDevInfDataStoreAssembleRxTx(SmlXmlAssembler *assm, const char *element, const char *cttype, const char *version, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %s, %s, %s, %p)", __func__, assm, VA_STRING(element), VA_STRING(cttype), VA_STRING(version), error); CHECK_ERROR_REF smlAssert(assm); smlAssert(element); smlAssert(cttype); if (!_smlXmlAssemblerStartNode(assm, element, error)) goto error; if (!_smlXmlAssemblerAddString(assm, SML_ELEMENT_CTTYPE, cttype, error)) goto error; if (!_smlXmlAssemblerAddString(assm, SML_ELEMENT_VERCT, version, error)) goto error; if (!_smlXmlAssemblerEndNode(assm, error)) goto error; smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return FALSE; } static SmlBool _smlXmlDevInfDataStoreAssembleCTCap( SmlXmlAssembler *assm, const SmlDevInfCTCap *ctcap, SmlBool flat, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p)", __func__, assm, ctcap, error); CHECK_ERROR_REF smlAssert(assm); smlAssert(ctcap); if (!flat) { // start CTCap if (!_smlXmlAssemblerStartNode(assm, SML_ELEMENT_CTCAP, error)) goto error; } // add CTType if (!_smlXmlAssemblerAddString(assm, SML_ELEMENT_CTTYPE, ctcap->ct->cttype, error)) goto error; // add VerCT // SyncML 1.0 and 1.1 does not support VerCT in CTCap // because this info is in the VERSION property. if (!flat) { if (!_smlXmlAssemblerAddString(assm, SML_ELEMENT_VERCT, ctcap->ct->verct, error)) goto error; } // add properties GList *hprop = NULL; for (hprop = ctcap->properties; hprop; hprop = hprop->next) { SmlDevInfProperty *property = hprop->data; if (!flat) { // add Property if (!_smlXmlAssemblerStartNode(assm, SML_ELEMENT_PROPERTY, error)) goto error; } // add PropName if (property->propName != NULL && !_smlXmlAssemblerAddString(assm, SML_ELEMENT_PROPNAME, property->propName, error)) goto error; // add DataType if (property->dataType != NULL && !_smlXmlAssemblerAddString(assm, SML_ELEMENT_DATATYPE, property->dataType, error)) goto error; // add MaxOccur if (property->maxOccur > 0 && !_smlXmlAssemblerAddID(assm, SML_ELEMENT_MAXOCCUR, property->maxOccur, error)) goto error; // add MaxSize if (property->maxSize > 0) { /* There was a change of the element name in OMA DS DevInf 1.2. */ if (flat) { if (!_smlXmlAssemblerAddID( assm, SML_ELEMENT_SIZE, property->maxSize, error)) goto error; } else { if (!_smlXmlAssemblerAddID( assm, SML_ELEMENT_MAXSIZE, property->maxSize, error)) goto error; } } // add NoTruncate if (property->noTruncate) { if (!_smlXmlAssemblerStartNode(assm, SML_ELEMENT_NOTRUNCATE, error)) goto error; if (!_smlXmlAssemblerEndNode(assm, error)) goto error; } // add DisplayName if (property->displayName != NULL && !_smlXmlAssemblerAddString(assm, SML_ELEMENT_DISPLAYNAME, property->displayName, error)) goto error; // add values GList *hvalue = NULL; for (hvalue = property->valEnums; hvalue; hvalue = hvalue->next) { char *valEnum = hvalue->data; // add ValEnum if (!_smlXmlAssemblerAddString(assm, SML_ELEMENT_VALENUM, valEnum, error)) goto error; } // end values for loop // add parameters GList *hparam = NULL; for (hparam = property->propParams; hparam; hparam = hparam->next) { SmlDevInfPropParam *param = hparam->data; if (!flat) { // add PropParam if (!_smlXmlAssemblerStartNode(assm, SML_ELEMENT_PROPPARAM, error)) goto error; } // add ParamName if (param->paramName != NULL && !_smlXmlAssemblerAddString(assm, SML_ELEMENT_PARAMNAME, param->paramName, error)) goto error; // add DataType if (param->dataType != NULL && !_smlXmlAssemblerAddString(assm, SML_ELEMENT_DATATYPE, param->dataType, error)) goto error; // add DisplayName if (param->displayName != NULL && !_smlXmlAssemblerAddString(assm, SML_ELEMENT_DISPLAYNAME, param->displayName, error)) goto error; // add values hvalue = NULL; for (hvalue = param->valEnums; hvalue; hvalue = hvalue->next) { char *valEnum = hvalue->data; // add ValEnum if (!_smlXmlAssemblerAddString(assm, SML_ELEMENT_VALENUM, valEnum, error)) goto error; } // end values for loop if (!flat) { // end PropParam if (!_smlXmlAssemblerEndNode(assm, error)) goto error; } } // end params for loop if (!flat) { // end Property if (!_smlXmlAssemblerEndNode(assm, error)) goto error; } } //end of ctcap->properties for loop if (!flat) { // end CTCap if (!_smlXmlAssemblerEndNode(assm, error)) goto error; } smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return FALSE; } static SmlBool _smlXmlDevInfDataStoreAssemble( SmlXmlAssembler *assm, SmlDevInfDataStore *datastore, SmlDevInf *devinf, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p, %p)", __func__, assm, datastore, devinf, error); CHECK_ERROR_REF smlAssert(datastore); smlAssert(assm); GList *contentTypes = NULL; if (!datastore->sourceref) { smlErrorSet(error, SML_ERROR_GENERIC, "Missing sourceref"); goto error; } if (!datastore->rxPrefContentType) { smlErrorSet(error, SML_ERROR_GENERIC, "Missing rx-pref"); goto error; } if (!datastore->txPrefContentType) { smlErrorSet(error, SML_ERROR_GENERIC, "Missing tx-pref"); goto error; } if (!datastore->synccap) { smlErrorSet(error, SML_ERROR_GENERIC, "No sync capabilities"); goto error; } // Datastore if (!_smlXmlAssemblerStartNode(assm, SML_ELEMENT_DATASTORE, error)) goto error; //SourceRef if (!_smlXmlAssemblerAddString(assm, SML_ELEMENT_SOURCEREF, datastore->sourceref, error)) goto error; //displayname if (datastore->displayname) { if (!_smlXmlAssemblerAddString(assm, SML_ELEMENT_DISPLAYNAME, datastore->displayname, error)) goto error; } //maxguidsize if (datastore->maxGUIDSize) { if (!_smlXmlAssemblerAddID(assm, SML_ELEMENT_MAXGUIDSIZE, datastore->maxGUIDSize, error)) goto error; } //rx-pref if (!_smlXmlDevInfDataStoreAssembleRxTx(assm, SML_ELEMENT_RXPREF, datastore->rxPrefContentType, datastore->rxPrefVersion, error)) goto error; contentTypes = g_list_append( contentTypes, smlDevInfNewContentType( datastore->rxPrefContentType, datastore->rxPrefVersion, error)); //rx if (datastore->rx) { GList *hl; for (hl = datastore->rx; hl; hl = hl->next) { SmlDevInfContentType *ct = hl->data; if (!_smlXmlDevInfDataStoreAssembleRxTx(assm, SML_ELEMENT_RX, ct->cttype, ct->verct, error)) goto error; contentTypes = g_list_append( contentTypes, smlDevInfNewContentType(ct->cttype, ct->verct, error)); } } //tx-pref if (!_smlXmlDevInfDataStoreAssembleRxTx(assm, SML_ELEMENT_TXPREF, datastore->txPrefContentType, datastore->txPrefVersion, error)) goto error; contentTypes = g_list_append( contentTypes, smlDevInfNewContentType( datastore->txPrefContentType, datastore->txPrefVersion, error)); //tx if (datastore->tx) { GList *hl; for (hl = datastore->tx; hl; hl = hl->next) { SmlDevInfContentType *ct = hl->data; if (!_smlXmlDevInfDataStoreAssembleRxTx(assm, SML_ELEMENT_TX, ct->cttype, ct->verct, error)) goto error; contentTypes = g_list_append( contentTypes, smlDevInfNewContentType(ct->cttype, ct->verct, error)); } } // CTCap (if SyncML version 1.2 device info) if (devinf->version >= SML_DEVINF_VERSION_12) { GList *hct = NULL; for (hct = contentTypes; hct; hct = hct->next) { SmlDevInfContentType *ct = hct->data; const SmlDevInfCTCap *ctcap = smlDevInfGetCTCap(devinf, ct); if (ctcap != NULL) { // we found a matching CTCap // so let's dump it if (!_smlXmlDevInfDataStoreAssembleCTCap(assm, ctcap, FALSE, error)) goto error; } else { // we have a content type without CTCap // this is a real source of trouble // WARNING: should we fail on this issue? smlTrace(TRACE_INTERNAL, "%s: found a content type (%s %d) without CTCap", __func__, VA_STRING(ct->cttype), ct->verct); } } // end of contentTypes for loop } // end of SML_DEVINF_VERSION_12 // cleanup list of content types while(contentTypes) { SmlDevInfContentType *ct = contentTypes->data; contentTypes = g_list_remove(contentTypes, ct); smlDevInfFreeContentType(ct); } //Dsmem if (datastore->maxmem || datastore->maxid) { //Dsmem if (!_smlXmlAssemblerStartNode(assm, SML_ELEMENT_DSMEM, error)) goto error; //shared if (datastore->sharedMem) { if (!_smlXmlAssemblerAddString(assm, SML_ELEMENT_SHAREDMEM, "", error)) goto error; } //maxid if (datastore->maxid) { if (!_smlXmlAssemblerAddID(assm, SML_ELEMENT_MAXID, datastore->maxid, error)) goto error; } //maxmem if (datastore->maxmem) { if (!_smlXmlAssemblerAddID(assm, SML_ELEMENT_MAXMEM, datastore->maxmem, error)) goto error; } //DsMem if (!_smlXmlAssemblerEndNode(assm, error)) goto error; } //SyncCap if (!_smlXmlAssemblerStartNode(assm, SML_ELEMENT_SYNCCAP, error)) goto error; //SyncTypes if (smlDevInfDataStoreGetSyncCap(datastore, SML_DEVINF_SYNCTYPE_TWO_WAY)) { if (!_smlXmlAssemblerAddString(assm, SML_ELEMENT_SYNCTYPE, "1", error)) goto error; } if (smlDevInfDataStoreGetSyncCap(datastore, SML_DEVINF_SYNCTYPE_SLOW_SYNC)) { if (!_smlXmlAssemblerAddString(assm, SML_ELEMENT_SYNCTYPE, "2", error)) goto error; } if (smlDevInfDataStoreGetSyncCap(datastore, SML_DEVINF_SYNCTYPE_ONE_WAY_FROM_CLIENT)) { if (!_smlXmlAssemblerAddString(assm, SML_ELEMENT_SYNCTYPE, "3", error)) goto error; } if (smlDevInfDataStoreGetSyncCap(datastore, SML_DEVINF_SYNCTYPE_REFRESH_FROM_CLIENT)) { if (!_smlXmlAssemblerAddString(assm, SML_ELEMENT_SYNCTYPE, "4", error)) goto error; } if (smlDevInfDataStoreGetSyncCap(datastore, SML_DEVINF_SYNCTYPE_ONE_WAY_FROM_SERVER)) { if (!_smlXmlAssemblerAddString(assm, SML_ELEMENT_SYNCTYPE, "5", error)) goto error; } if (smlDevInfDataStoreGetSyncCap(datastore, SML_DEVINF_SYNCTYPE_REFRESH_FROM_SERVER)) { if (!_smlXmlAssemblerAddString(assm, SML_ELEMENT_SYNCTYPE, "6", error)) goto error; } if (smlDevInfDataStoreGetSyncCap(datastore, SML_DEVINF_SYNCTYPE_SERVER_ALERTED_SYNC)) { if (!_smlXmlAssemblerAddString(assm, SML_ELEMENT_SYNCTYPE, "7", error)) goto error; } //SyncCap if (!_smlXmlAssemblerEndNode(assm, error)) goto error; //DataStore if (!_smlXmlAssemblerEndNode(assm, error)) goto error; smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return FALSE; } SmlBool smlXmlDevInfAssemble(SmlDevInf *devinf, SmlDevInfVersion version, char **data, unsigned int *size, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %i, %p, %p, %p)", __func__, devinf, version, data, size, error); CHECK_ERROR_REF smlAssert(devinf); smlAssert(data); smlAssert(size); // sometime devinf->version is empty // both version fields should be identical smlTrace(TRACE_INTERNAL, "%s: devinf version: %i, version: %i", __func__, devinf->version, version); if (devinf->version == SML_DEVINF_VERSION_UNKNOWN) devinf->version = version; if (version == SML_DEVINF_VERSION_UNKNOWN) version = devinf->version; smlAssert(devinf->version == version); SmlXmlAssembler *assm = smlTryMalloc0(sizeof(SmlXmlAssembler), error); if (!assm) goto error; /* We first start a new parent writer that will write our command into a buffer */ xmlBuffer *buffer = xmlBufferCreateSize(BUFFER_SIZE); if (!buffer) { smlErrorSet(error, SML_ERROR_GENERIC, "Unable to create new buffer"); goto error_free_assm; } assm->writer = xmlNewTextWriterMemory(buffer, 0); if (!assm->writer) { smlErrorSet(error, SML_ERROR_GENERIC, "Unable to create new writer"); goto error_free_buffer; } //Devinf if (!_smlXmlAssemblerStartNodeNS(assm, SML_ELEMENT_DEVINF, SML_NAMESPACE_DEVINF, error)) goto error_free_writer; //Verdtd switch (version) { case SML_DEVINF_VERSION_12: if (!_smlXmlAssemblerAddString(assm, SML_ELEMENT_VERDTD, "1.2", error)) goto error_free_writer; break; case SML_DEVINF_VERSION_11: if (!_smlXmlAssemblerAddString(assm, SML_ELEMENT_VERDTD, "1.1", error)) goto error_free_writer; break; case SML_DEVINF_VERSION_10: if (!_smlXmlAssemblerAddString(assm, SML_ELEMENT_VERDTD, "1.0", error)) goto error_free_writer; break; case SML_DEVINF_VERSION_UNKNOWN: smlErrorSet(error, SML_ERROR_GENERIC, "Unknown devinf version"); goto error_free_writer; break; } //Man if (devinf->manufacturer) { if (!_smlXmlAssemblerAddString(assm, SML_ELEMENT_MAN, devinf->manufacturer, error)) goto error_free_writer; } //Mod if (devinf->model) { if (!_smlXmlAssemblerAddString(assm, SML_ELEMENT_MOD, devinf->model, error)) goto error_free_writer; } //OEM if (devinf->oem) { if (!_smlXmlAssemblerAddString(assm, SML_ELEMENT_OEM, devinf->oem, error)) goto error_free_writer; } //FwV if (devinf->firmwareVersion) { if (!_smlXmlAssemblerAddString(assm, SML_ELEMENT_FWV, devinf->firmwareVersion, error)) goto error_free_writer; } //SwV if (devinf->softwareVersion) { if (!_smlXmlAssemblerAddString(assm, SML_ELEMENT_SWV, devinf->softwareVersion, error)) goto error_free_writer; } //HwV if (devinf->hardwareVersion) { if (!_smlXmlAssemblerAddString(assm, SML_ELEMENT_HWV, devinf->hardwareVersion, error)) goto error_free_writer; } //DevID if (!_smlXmlAssemblerAddString(assm, SML_ELEMENT_DEVID, devinf->devid, error)) goto error_free_writer; //Devtyp const char *devtype = smlDevInfDevTypeToString(devinf->devtyp, error); if (!devtype) goto error_free_writer; if (!_smlXmlAssemblerAddString(assm, SML_ELEMENT_DEVTYPE, devtype, error)) goto error_free_writer; //UTC (>= 1.1) if (devinf->supportsUTC && version != SML_DEVINF_VERSION_10) { if (!_smlXmlAssemblerAddString(assm, SML_ELEMENT_UTC, "", error)) goto error_free_writer; } //Large objs (>= 1.1) if (devinf->supportsLargeObjs && version != SML_DEVINF_VERSION_10) { if (!_smlXmlAssemblerAddString(assm, SML_ELEMENT_SUPPORTLARGEOBJS, "", error)) goto error_free_writer; } //Number of changes (>= 1.1) if (devinf->supportsNumberOfChanges && version != SML_DEVINF_VERSION_10) { if (!_smlXmlAssemblerAddString(assm, SML_ELEMENT_SUPPORTNUMBEROFCHANGES, "", error)) goto error_free_writer; } //Add the datastores GList *d = NULL; for (d = devinf->datastores; d; d = d->next) { SmlDevInfDataStore *datastore = d->data; if (!_smlXmlDevInfDataStoreAssemble(assm, datastore, devinf, error)) goto error_free_writer; } // CTCap (only for SyncML 1.0 and 1.1) if ( devinf->version < SML_DEVINF_VERSION_12 && devinf->ctcaps) { if (!_smlXmlAssemblerStartNode(assm, SML_ELEMENT_CTCAP, error)) goto error_free_writer; for (d = devinf->ctcaps; d; d = d->next) { SmlDevInfCTCap *ctcap = d->data; if (!_smlXmlDevInfDataStoreAssembleCTCap(assm, ctcap, TRUE, error)) goto error_free_writer; } if (!_smlXmlAssemblerEndNode(assm, error)) goto error_free_writer; } //Devinf if (!_smlXmlAssemblerEndNode(assm, error)) goto error_free_writer; /* Now close the buffer */ if (xmlTextWriterEndDocument(assm->writer) < 0) { smlErrorSet(error, SML_ERROR_GENERIC, "Unable to end writer"); goto error_free_writer; } xmlFreeTextWriter(assm->writer); assm->writer = NULL; *size = xmlBufferLength(buffer); *data = g_strndup((const char *) xmlBufferContent(buffer), *size); xmlBufferFree(buffer); smlSafeFree((gpointer *)&assm); smlTrace(TRACE_INTERNAL, "Message Assembled: %s", *data); smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error_free_writer: xmlFreeTextWriter(assm->writer); assm->writer = NULL; error_free_buffer: xmlBufferFree(buffer); error_free_assm: smlSafeFree((gpointer *)&assm); error: g_warning("%s: %s", __func__, smlErrorPrint(error)); smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return FALSE; } void smlXmlAssemblerRestoreCommands(SmlXmlAssembler *assm) { smlTrace(TRACE_ENTRY, "%s", __func__); smlAssert(assm->commands == NULL); assm->commands = assm->last_commands; assm->last_commands = NULL; smlTrace(TRACE_EXIT, "%s", __func__); } /*@}*/ libsyncml-0.5.4/libsyncml/parser/sml_xml_parse.h100644 1750 1750 3740 11211710410 21733 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2005 Armin Bauer * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ /** * @defgroup Xml XML/WBXML API * @ingroup PrivateAPI * @brief The public part * */ /** * @defgroup XmlPublic Internal XML/WBXML API * @ingroup Xml * @brief The public part * */ /** * @defgroup XmlParser XML Parser * @ingroup XmlPublic * @brief Interfaces to parse SyncML XML messages * */ /*@{*/ #ifndef _SML_XML_PARSE_H_ #define _SML_XML_PARSE_H_ typedef struct SmlXmlParser SmlXmlParser; SmlXmlParser *smlXmlParserNew(SmlParserFunctions *functions, SmlError **error); SmlBool smlXmlParserStart(SmlXmlParser *parser, const char *data, unsigned int size, SmlError **error); SmlBool smlXmlParserEnd(SmlXmlParser *parser, SmlBool *final, SmlBool *end, SmlError **error); void smlXmlParserFree(SmlXmlParser *parser); SmlBool smlXmlParserGetHeader(SmlXmlParser *parser, SmlHeader **header, SmlCred **cred, SmlError **error); SmlBool smlXmlParserGetStatus(SmlXmlParser *parser, SmlStatus **status, SmlError **error); SmlParserResult smlXmlParserGetCommand(SmlXmlParser *parser, SmlCommand **cmd, SmlError **error); SmlDevInf *smlXmlDevInfParse(const char *data, unsigned int size, SmlError **error); #endif //_SML_XML_PARSE_H_ /*@}*/ libsyncml-0.5.4/libsyncml/parser/sml_wbxml.h100644 1750 1750 2411 11211710410 21064 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2005 Armin Bauer * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ /** * @defgroup XmlWbxml WBXML Parser and Assembler * @ingroup XmlPublic * @brief Interfaces to parse and assemble SyncML WBXML messages * */ /*@{*/ #ifndef _SML_WBXML_H_ #define _SML_WBXML_H_ SmlXmlParser *smlWbxmlParserNew(SmlParserFunctions *functions, SmlError **error); SmlXmlAssembler *smlWbxmlAssemblerNew(SmlAssembler *assembler, SmlAssemblerFunctions *functions, SmlError **error); #endif //_SML_WBXML_H_ /*@}*/ libsyncml-0.5.4/libsyncml/sml_transport.c100644 1750 1750 102100 11211710410 20522 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2005 Armin Bauer * Copyright (C) 2007-2009 Michael Bell * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include "syncml.h" #include "syncml_internals.h" #include "sml_error_internals.h" #include "sml_transport_internals.h" #ifdef ENABLE_HTTP #include "transports/http_client_internals.h" #include "transports/http_server_internals.h" #endif #ifdef ENABLE_OBEX #include "transports/obex_client_internals.h" #include "transports/obex_server_internals.h" #endif /** * @defgroup SmlTransportPrivate SyncML Transport Private API * @ingroup PrivateLowLevelAPI * @brief Private Interfaces to manage transports * */ /*@{*/ static SmlBool smlTransportIsServer(SmlTransport *tsp) { smlAssert(tsp); if (tsp->type == SML_TRANSPORT_HTTP_SERVER) return TRUE; if (tsp->type == SML_TRANSPORT_OBEX_SERVER) return TRUE; return FALSE; } void smlTransportSetEventCallback(SmlTransport *tsp, SmlTransportEventCb callback, void *userdata) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, tsp, callback, userdata); smlAssert(tsp); tsp->event_callback = callback; tsp->event_callback_userdata = userdata; /* Do not return until all running callbacks finished. * This is a busy wait and yes it can happen that new * callbacks are started during sleep but the setter * must get a warranty that the old callback is no * longer in use. * * This is acceptable because the callback is only set * two times. First it is set when the manager registers * the transport and second it is set when the manager * is freed. So this is a protection against sending an * event to an already freed manager. */ while (g_atomic_int_get(&(tsp->event_callback_ref_count)) > 0) { usleep(50); } smlTrace(TRACE_EXIT, "%s", __func__); } SmlBool smlTransportSend(SmlTransport *tsp, SmlLink *link_, SmlTransportData *data, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p, %p)", __func__, tsp, link_, data, error); CHECK_ERROR_REF smlAssert(tsp); smlAssert(data); if (tsp->cached_error != NULL) { // the most parameters should be NULL because the cached error // has nothing to do with the actual send request smlTransportReceiveEvent(tsp, NULL, SML_TRANSPORT_EVENT_ERROR, NULL, NULL); goto error; } SmlTransportCommand *cmd = smlTryMalloc0(sizeof(SmlTransportCommand), error); if (!cmd) { smlTransportReceiveEvent(tsp, NULL, SML_TRANSPORT_EVENT_ERROR, NULL, *error); goto error; } cmd->type = SML_TRANSPORT_CMD_SEND; cmd->data = data; if (link_) { cmd->link = link_; smlLinkRef(cmd->link); } smlTransportDataRef(cmd->data); //Call the fin function smlQueueSend(tsp->command_queue, cmd); smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return FALSE; } void smlTransportWorkerHandler(void *message, void *userdata) { smlTrace(TRACE_ENTRY, "%s(%p, %p)", __func__, message, userdata); smlAssert(message); smlAssert(userdata); SmlTransportCommand *cmd = message; SmlTransport *tsp = userdata; switch (cmd->type) { case SML_TRANSPORT_CMD_SEND: tsp->functions.send(tsp->transport_data, cmd->link ? cmd->link->link_data : NULL, cmd->data, cmd->error); break; case SML_TRANSPORT_CMD_CONNECT: if (!tsp->functions.connect) { smlTransportReceiveEvent(tsp, NULL, SML_TRANSPORT_EVENT_CONNECT_DONE, NULL, NULL); smlTrace(TRACE_INTERNAL, "%s: No connect function", __func__); break; } tsp->functions.connect(tsp->transport_data); break; case SML_TRANSPORT_CMD_DISCONNECT: if (!tsp->functions.disconnect) { smlTransportReceiveEvent(tsp, NULL, SML_TRANSPORT_EVENT_DISCONNECT_DONE, NULL, NULL); smlTrace(TRACE_INTERNAL, "%s: No disconnect function", __func__); break; } /* If there is a disconnect request * but the connection is already down * then an earlier disconnect happened * (perhaps initiated by the remote peer) * and we can ignore the disconnect. */ if (smlTransportIsServer(tsp) && !cmd->link->link_data) { /* The SERVER is already disconnected. */ smlTrace(TRACE_INTERNAL, "%s: The server link was already disconnected.", __func__); break; } if (!smlTransportIsServer(tsp) && !tsp->connected) { /* The CLIENT is already disconnected. */ smlTrace(TRACE_INTERNAL, "%s: The client was already disconnected.", __func__); break; } tsp->functions.disconnect(tsp->transport_data, cmd->link ? cmd->link->link_data : NULL); break; } if (cmd->link) smlLinkDeref(cmd->link); if (cmd->data) smlTransportDataDeref(cmd->data); smlSafeFree((gpointer *)&cmd); smlTrace(TRACE_EXIT, "%s", __func__); return; } SmlBool smlTransportReceiveEvent(SmlTransport *tsp, SmlLink *link_, SmlTransportEventType type, SmlTransportData *data, SmlError *error) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %i, %p, %p)", __func__, tsp, link_, type, data, error); smlAssert(tsp); SmlBool ret = TRUE; if (tsp->event_callback == NULL) { smlTrace(TRACE_INTERNAL, "%s: no callback available", __func__); if (type != SML_TRANSPORT_EVENT_ERROR && type != SML_TRANSPORT_EVENT_DISCONNECT_DONE) { /* Somebody forget to set the event callback. * This is a heavy bug which cannot be compensated. * The whole state management will fail. */ g_error("The transport layer of type %d " \ "must send a normal event %d " \ "but there is no event callback set.", tsp->type, type); /* abort if g_error is not fatal */ exit(1); } /* If there is a cached error then the transport layer * uses the error event without an error as a trigger * to send the original error. */ if (tsp->cached_error && error != NULL) { /* Wow, this is the second error and * there is still no event callback. */ g_warning("The transport layer already caches an error " \ "because the event callback is not present until now." \ "The received error is ignored. %s", smlErrorPrint(&error)); // do not free the error here because you are not the owner of the error } if (!tsp->cached_error && error) { // we stop all communications here smlTrace(TRACE_INTERNAL, "%s: init failed in transport protocol -> %s", __func__, smlErrorPrint(&error)); tsp->state = SML_TRANSPORT_ERROR; tsp->cached_error = error; smlErrorRef(&error); } } else { smlTrace(TRACE_INTERNAL, "%s: callback available", __func__); if (tsp->cached_error != NULL) { /* First we have to send the cached error. */ smlTrace(TRACE_INTERNAL, "%s: cached error detected - %s", __func__, smlErrorPrint(&(tsp->cached_error))); g_atomic_int_inc(&(tsp->event_callback_ref_count)); ret = tsp->event_callback( tsp, NULL, SML_TRANSPORT_EVENT_ERROR, NULL, tsp->cached_error, tsp->event_callback_userdata); smlTrace(TRACE_INTERNAL, "%s: %d event callbacks", __func__, g_atomic_int_dec_and_test(&(tsp->event_callback_ref_count))); /* Second we have to prepare the internal states. */ /* Third we have to send the original event. */ } /* If a connect or disconnect is received without a link * then this means that this is a new connection or a * closed connection of a client. If such a constallation * happens with a server then this is a fatal error. * * If a connect is reveived with a link * then this must be a server and * the link_data must be set. * * If a disconnect is received with a link * then this must be a server and * the link_data must not be present * because the link is down now. */ if (type == SML_TRANSPORT_EVENT_CONNECT_DONE && !link_) { if (smlTransportIsServer(tsp)) g_error("A connect event without a link was received " \ "but the transport layer is a server."); if (tsp->connected) g_error("A connect event was received " \ "but the transport layer is already connected."); smlTrace(TRACE_INTERNAL, "%s: connect + no link"); tsp->connected = TRUE; } if (type == SML_TRANSPORT_EVENT_DISCONNECT_DONE && !link_) { if (smlTransportIsServer(tsp)) g_error("A disconnect event without a link was received " \ "but the transport layer is a server."); if (!tsp->connected) g_error("A disconnect event was received " \ "but there is no connected transport."); smlTrace(TRACE_INTERNAL, "%s: disconnect + no link"); tsp->connected = FALSE; } if (type == SML_TRANSPORT_EVENT_CONNECT_DONE && link_) { if (!smlTransportIsServer(tsp)) g_error("A connect event with a link was received " \ "but the transport layer is a server."); if (!link_->link_data) g_error("A connect event with a link was received " \ "but the link does not contain the required " \ "transport environment."); smlTrace(TRACE_INTERNAL, "%s: connect + link"); g_mutex_lock(tsp->connections_mutex); tsp->connections++; g_mutex_unlock(tsp->connections_mutex); } if (type == SML_TRANSPORT_EVENT_DISCONNECT_DONE && link_) { if (!smlTransportIsServer(tsp)) g_error("A disconnect event with a link was received " \ "but the transport layer is not a server."); if (link_->link_data) g_error("A disconnect event with a link was received " \ "but the link still contains the " \ "transport environment."); smlTrace(TRACE_INTERNAL, "%s: disconnect + link"); g_mutex_lock(tsp->connections_mutex); tsp->connections--; g_mutex_unlock(tsp->connections_mutex); } /* now execute the callback */ if (!(tsp->cached_error && type == SML_TRANSPORT_EVENT_ERROR && error == NULL)) { /* send the event */ g_atomic_int_inc(&(tsp->event_callback_ref_count)); ret = tsp->event_callback(tsp, link_, type, data, error, tsp->event_callback_userdata); smlTrace(TRACE_INTERNAL, "%s: %d event callbacks", __func__, g_atomic_int_dec_and_test(&(tsp->event_callback_ref_count))); } if (tsp->cached_error) { smlErrorDeref(&(tsp->cached_error)); tsp->cached_error = NULL; } } /* end of tsp->event_callback */ smlTrace(TRACE_EXIT, "%s: %i", __func__, ret); return ret; } /* FIXME: DEPRECATED */ SmlBool smlTransportRunAsync(SmlTransport *tsp, SmlError **error) { smlTrace(TRACE_ERROR, "%s(%p,%p)", __func__, tsp, error); CHECK_ERROR_REF /* All transports run in asynchronous mode. * Therefore this function should never be called. * The functions always returns TRUE to avoid any complications. */ return TRUE; } static void _smlTransportStop(SmlTransport *tsp) { smlTrace(TRACE_ENTRY, "%s(%p)", __func__, tsp); smlAssert(tsp->thread); smlThreadStop(tsp->thread); smlThreadFree(tsp->thread); tsp->thread = NULL; smlTrace(TRACE_EXIT, "%s", __func__); } /* FIXME: DEPRECATED */ void smlTransportStop(SmlTransport *tsp) { _smlTransportStop(tsp); } SmlBool smlTransportConnect(SmlTransport *tsp, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p)", __func__, tsp, error); CHECK_ERROR_REF smlAssert(tsp); /* Only clients can actively connect and * a client can only connect once. */ if (smlTransportIsServer(tsp)) { smlErrorSet(error, SML_ERROR_GENERIC, "Only a transport client can be actively connected."); goto error; } if (tsp->connected) { smlErrorSet(error, SML_ERROR_GENERIC, "A transport client can be connected only once."); goto error; } /* put the command into the queue */ SmlTransportCommand *cmd = smlTryMalloc0(sizeof(SmlTransportCommand), error); if (!cmd) goto error; cmd->type = SML_TRANSPORT_CMD_CONNECT; //Call the connect function smlQueueSend(tsp->command_queue, cmd); smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return FALSE; } SmlBool smlTransportDisconnect(SmlTransport *tsp, SmlLink *link_, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, tsp, link_, error); CHECK_ERROR_REF smlAssert(tsp); /* The transport must (still) be connected. */ if (!tsp->connected) { smlErrorSet(error, SML_ERROR_GENERIC, "The transport is not connected and so it cannot be disconnected."); goto error; } /* If this is a client then there must not be a link * because every client can have only one connection. */ if (link_ && !smlTransportIsServer(tsp)) { smlErrorSet(error, SML_ERROR_GENERIC, "A transport client has no link " \ "because there is only one connection."); goto error; } /* If this is a server then there are two types of disconnects. * * If there is link then this is a shutdown for a connection. * If a connection is closed then there must be link_data in * the link because otherwise the connection is already closed. * * If there is no link then this is a shutdown for the server. * This means that all links must be shut down. */ if (link_ && !link_->link_data) { /* If there is a very fast or aggressive client * then it can happen that the client closes * the connection and the server registers this * event before the disconnect function was * called. * * If this happens then the link_data is perhaps * already empty and the disconnect event was * already triggered. */ smlTrace(TRACE_EXIT, "%s: A server connection should be closed " \ "but the connection is already closed.", __func__); return TRUE; } if (!link_ && smlTransportIsServer(tsp) && tsp->connections) { smlErrorSet(error, SML_ERROR_GENERIC, "A server shutdown is requested " \ "but there are still open connections (%d).", tsp->connections); goto error; } /* check that the link is used at the correct transport layer * this is also a check for the correct registration of the link */ if (link_) { if (tsp != link_->tsp) { smlErrorSet(error, SML_ERROR_GENERIC, "The link %p is registered at another transport layer %p than this one %p.", link_, link_->tsp, tsp); goto error; } g_mutex_lock(tsp->links_mutex); if (!g_hash_table_lookup(tsp->links, link_)) { g_mutex_unlock(tsp->links_mutex); smlErrorSet(error, SML_ERROR_GENERIC, "The link %p is not registered at the transport layer %p", link_, tsp); goto error; } g_mutex_unlock(tsp->links_mutex); } /* send the command */ SmlTransportCommand *cmd = smlTryMalloc0(sizeof(SmlTransportCommand), error); if (!cmd) goto error; cmd->type = SML_TRANSPORT_CMD_DISCONNECT; if (link_) { cmd->link = link_; smlLinkRef(cmd->link); } //Call the disconnect function smlQueueSend(tsp->command_queue, cmd); smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return FALSE; } SmlTransportType smlTransportGetType(SmlTransport *tsp) { smlAssert(tsp); return tsp->type; } SmlTransportData *smlTransportDataNew(char *data, unsigned long size, SmlMimeType mimetype, SmlBool ownsData, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %d, %i, %i, %p)", __func__, data, size, mimetype, ownsData, error); CHECK_ERROR_REF //Append the data to the outgoing queue SmlTransportData *cmd = smlTryMalloc0(sizeof(SmlTransportData), error); if (!cmd) goto error; cmd->type = mimetype; cmd->data = data; cmd->size = size; cmd->ownsData = ownsData; cmd->refCount = 1; cmd->needsAnswer = TRUE; cmd->type_get = SML_MIMETYPE_UNKNOWN; smlTrace(TRACE_EXIT, "%s: %p", __func__, cmd); return cmd; error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return NULL; } SmlTransportData *smlTransportDataRef(SmlTransportData *data) { smlTrace(TRACE_ENTRY, "%s(%p)", __func__, data); smlAssert(data); g_atomic_int_inc(&(data->refCount)); smlTrace(TRACE_EXIT, "%s", __func__); return data; } void smlTransportDataDeref(SmlTransportData *data) { smlTrace(TRACE_ENTRY, "%s(%p)", __func__, data); smlAssert(data); if (!g_atomic_int_dec_and_test(&(data->refCount))) { smlTrace(TRACE_EXIT, "%s: refCount > 0", __func__); return; } if (data->ownsData && data->data != NULL) smlSafeCFree(&(data->data)); smlSafeFree((gpointer *)&data); smlTrace(TRACE_EXIT, "%s: Freed", __func__); } void smlTransportSetError(SmlTransport *tsp, SmlLink *link_, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p(%p))", __func__, tsp, link_, error, error ? *error : NULL); /* Do no use CHECK_ERROR_REF here. * SmlError **error contains an error which should be send. */ smlAssert(tsp); SmlError *locerror = NULL; SmlTransportCommand *cmd = smlTryMalloc0(sizeof(SmlTransportCommand), &locerror); if (!cmd) return; cmd->type = SML_TRANSPORT_CMD_SEND; cmd->data = NULL; if (link_) { cmd->link = link_; smlLinkRef(cmd->link); } if (error && *error) { cmd->error = *error; smlErrorRef(error); } //Call the fin function smlQueueSend(tsp->command_queue, cmd); smlTrace(TRACE_EXIT, "%s", __func__); } SmlLink *smlLinkNew(SmlTransport *tsp, void *link_data, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, tsp, link_data, error); CHECK_ERROR_REF smlAssert(link_data); SmlLink *link_ = smlTryMalloc0(sizeof(SmlLink), error); if (!link_) goto error; link_->tsp = tsp; link_->link_data = link_data; link_->refCount = 1; /* register the link at the transport */ g_mutex_lock(tsp->links_mutex); g_hash_table_insert(tsp->links, link_, GINT_TO_POINTER(1)); g_mutex_unlock(tsp->links_mutex); smlTrace(TRACE_EXIT, "%s: %p", __func__, link_); return link_; error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return NULL; } /* FIXME: DEPRECATED */ SmlLink *smlLinkFind(SmlTransport *tsp, void *link_data) { /* The function always returns NULL. * The function is not removed to protect the intergrity of the library. * Actually no user of this function is known. */ smlTrace(TRACE_INTERNAL, "%s(%p, %p)", __func__, tsp, link_data); return NULL; } SmlLink *smlLinkRef(SmlLink *link_) { smlTrace(TRACE_ENTRY, "%s(%p)", __func__, link_); smlAssert(link_); g_atomic_int_inc(&(link_->refCount)); smlTrace(TRACE_EXIT, "%s", __func__); return link_; } void smlLinkDeref(SmlLink *link_) { smlTrace(TRACE_ENTRY, "%s(%p)", __func__, link_); smlAssert(link_); if (!g_atomic_int_dec_and_test(&(link_->refCount))) { smlTrace(TRACE_EXIT, "%s: refCount > 0", __func__); return; } /* deregister the link from the transport */ g_mutex_lock(link_->tsp->links_mutex); if (!g_hash_table_remove(link_->tsp->links, link_)) g_warning("The link %p was never registered.", link_); g_mutex_unlock(link_->tsp->links_mutex); /* free the memory */ smlSafeFree((gpointer *)&link_); smlTrace(TRACE_EXIT, "%s: Freed", __func__); } /*@}*/ /** * @defgroup SmlTransport SyncML Transport API * @ingroup PublicLowLevelAPI * @brief Transports can be used to connect to other syncml capable devices and servers * */ /*@{*/ /** * @name Transport Management * These functions allow to create, delete, initialize and finalize transports */ /*@{*/ /** @brief Creates a new transport * * A transport is a abstraction of a transport type like http or obex * * @param type The type of the transport * @param error Return location if an error occured * @returns The new transport or NULL in the case of an error * */ SmlTransport *smlTransportNew(SmlTransportType type, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%i, %p)", __func__, type, error); CHECK_ERROR_REF /* Initialize GLib thread system. */ if (!g_thread_supported ()) g_thread_init (NULL); g_type_init(); SmlTransport *tsp = smlTryMalloc0(sizeof(SmlTransport), error); if (!tsp) goto error; tsp->type = type; tsp->cached_error = NULL; tsp->event_callback = NULL; tsp->context = NULL; switch (type) { #ifdef ENABLE_HTTP case SML_TRANSPORT_HTTP_SERVER: if (!smlTransportHttpServerNew(tsp, error)) goto error_free_tsp; break; case SML_TRANSPORT_HTTP_CLIENT: if (!smlTransportHttpClientNew(tsp, error)) goto error_free_tsp; break; #else case SML_TRANSPORT_HTTP_SERVER: case SML_TRANSPORT_HTTP_CLIENT: smlErrorSet(error, SML_ERROR_GENERIC, "HTTP Transport not enabled in this build"); goto error_free_tsp; #endif #ifdef ENABLE_OBEX case SML_TRANSPORT_OBEX_CLIENT: if (!smlTransportObexClientNew(tsp, error)) goto error_free_tsp; break; case SML_TRANSPORT_OBEX_SERVER: if (!smlTransportObexServerNew(tsp, error)) goto error_free_tsp; break; #else case SML_TRANSPORT_OBEX_SERVER: case SML_TRANSPORT_OBEX_CLIENT: smlErrorSet(error, SML_ERROR_GENERIC, "OBEX Transport not enabled in this build"); goto error_free_tsp; #endif } tsp->command_queue = smlQueueNew(error); if (!tsp->command_queue) goto error_free_tsp; /* links must be tracked to detect server connections * which are not cleaned up before server finalization * * connections must be tracked to detect open server connections * which were not closed before server shutdown */ if (smlTransportIsServer(tsp)) { tsp->links = g_hash_table_new(g_direct_hash, g_direct_equal); tsp->links_mutex = g_mutex_new(); tsp->connections = 0; tsp->connections_mutex = g_mutex_new(); } else { tsp->links = NULL; tsp->links_mutex = NULL; tsp->connections = 0; tsp->connections_mutex = NULL; } tsp->connected = FALSE; smlTrace(TRACE_EXIT, "%s: %p", __func__, tsp); return tsp; error_free_tsp: smlTransportFree(tsp); error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return NULL; } /** @brief Frees the given transport * * @param tsp The transport to free * */ void smlTransportFree(SmlTransport *tsp) { smlTrace(TRACE_ENTRY, "%s(%p)", __func__, tsp); smlAssert(tsp); if (tsp->command_queue) smlQueueFree(tsp->command_queue); SmlError *error = NULL; if (tsp->transport_data && !tsp->functions.finalize(tsp->transport_data, &error)) { g_warning("The library libsyncml cannot free the transport. %s", smlErrorPrint(&error)); smlErrorDeref(&error); } if (tsp->context) g_main_context_unref(tsp->context); tsp->context = NULL; /* check for open connections */ if (tsp->connections) { g_warning("The transport layer of libsyncml is freed " \ "but not all connections were close (%d).", tsp->connections); } if (tsp->connections_mutex) g_mutex_free(tsp->connections_mutex); /* check for forgotten connections */ if (tsp->links && g_hash_table_size(tsp->links)) g_warning("The transport layer of libsyncml is freed " \ "but not all connections were cleaned up (%d).", g_hash_table_size(tsp->links)); if (tsp->links) g_hash_table_unref(tsp->links); if (tsp->links_mutex) g_mutex_free(tsp->links_mutex); /* check for forgotten errors */ if (tsp->cached_error) { g_warning("The transport layer is cleaned up and an error is ignored. %s", smlErrorPrint(&(tsp->cached_error))); smlErrorDeref(&(tsp->cached_error)); } /* free the memory */ smlSafeFree((gpointer *)&tsp); smlTrace(TRACE_EXIT, "%s", __func__); } /** @brief Sets a configuration parameter. * * This function sets the configuration option "name" to * the value which you specified. The option is checked by * the according transport layer implementation. * The transport must be in the state "Uninitialized" to use this functions. * The state will then is not switched. * * @param tsp The transport * @param name The name of the configuration option * @param value The value of the configuration option * @param error Return location if an error occured * @returns TRUE if the call succeded or FALSE in the case of an error * */ SmlBool smlTransportSetConfigOption( SmlTransport *tsp, const char *name, const char *value, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %s, %s, %p)", __func__, tsp, VA_STRING(name), strcmp(name, "PASSWORD") ? VA_STRING(value) : "***sensitive***", error); /* Do not change the assertion to simple return FALSE stuff * because to many developers incl. me ignore returned FALSE * if it is only configuration. */ CHECK_ERROR_REF smlAssert(tsp); smlAssert(tsp->state == SML_TRANSPORT_UNINITIALIZED); smlAssert(tsp->functions.set_config_option); if (!name) { smlErrorSet(error, SML_ERROR_INTERNAL_MISCONFIGURATION, "The name of the configuration option is missing."); goto error; } if (!tsp->functions.set_config_option(tsp, name, value, error)) goto error; smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error: smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(error)); return FALSE; } /** @brief Sets a configuration parameter. * * This function sets the configuration option "name" to * the value which you specified. The option is checked by * the according transport layer implementation. * The transport must be in the state "Uninitialized" to use this functions. * The state will then is not switched. * * @param tsp The transport * @param name The name of the configuration option * @param value The value of the configuration option * @param error Return location if an error occured * @returns TRUE if the call succeded or FALSE in the case of an error * */ SmlBool smlTransportSetConnectionType( SmlTransport *tsp, SmlTransportConnectionType type, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %i, %p)", __func__, tsp, type, error); /* Do not change the assertion to simple return FALSE stuff * because to many developers incl. me ignore returned FALSE * if it is only configuration. */ CHECK_ERROR_REF smlAssert(tsp); smlAssert(type != SML_TRANSPORT_CONNECTION_TYPE_UNKNOWN); smlAssert(tsp->state == SML_TRANSPORT_UNINITIALIZED); smlAssert(tsp->functions.set_connection_type); if (tsp->functions.set_connection_type(tsp, type, error)) { smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; } else { smlTrace(TRACE_EXIT_ERROR, "%s", __func__); return FALSE; } } /** @brief Initializes the transport with the given config * * This function will init the transport with the options that you specify * in the options. The options that are available depend on the transport used. * The transport must be in the state "Uninitialized" to use this functions. The state will then * switch to "Initialized". * * @param tsp The transport * @param error Return location if an error occured * @returns TRUE if the call succeded or FALSE in the case of an error * */ SmlBool smlTransportInitialize(SmlTransport *tsp, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p)", __func__, tsp, error); CHECK_ERROR_REF smlAssert(tsp); smlAssert(tsp->state == SML_TRANSPORT_UNINITIALIZED); /* Intialize the context and thread for the g_main_loop. */ tsp->context = g_main_context_new(); if (!tsp->context) { smlErrorSet(error, SML_ERROR_GENERIC, "Cannot create new GMainContext for asynchronous transport."); goto error; } tsp->thread = smlThreadNew(tsp->context, error); if (!tsp->thread) goto error_free_loop; /* The transport always needs a context based loop for the * command queue handling. Never attach this queue to * another context because this can block the transport. */ /* start the queue - e.g. to handle errors */ smlQueueSetHandler(tsp->command_queue, (SmlQueueHandler)smlTransportWorkerHandler, tsp); smlQueueAttach(tsp->command_queue, tsp->context); if (tsp->functions.initialize && !tsp->functions.initialize(tsp, error)) goto error_detach; /* Now start the GMainLoop. * Do not start earlier to avoid confusion with libsoup * because of registering a context at a running main loop. */ smlThreadStart(tsp->thread); tsp->state = SML_TRANSPORT_INITIALIZED; /* If this is a server then the server is running now. */ if (smlTransportIsServer(tsp)) tsp->connected = TRUE; smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error_detach: smlQueueDetach(tsp->command_queue); error_free_loop: if (tsp->context) { g_main_context_unref(tsp->context); tsp->context = NULL; } error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return FALSE; } /** @brief Sets the response URI after initialization. * * This function sets the response URI after initialization * if the transport layer supports this. If the transport * layer does not support this feature then this is a fatal * error. The URI must be an absolute URI according to * OMA DS 1.2 Representation Protocol * * @param tsp The transport * @param uri The response URI * @param error Return location if an error occured * @returns TRUE if the call succeded or FALSE in the case of an error * */ SmlBool smlTransportSetResponseURI( SmlTransport *tsp, const char *uri, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %s, %p)", __func__, tsp, VA_STRING(uri), error); /* Do not change the assertion to simple return FALSE stuff * because to many developers incl. me ignore returned FALSE * if it is only configuration. */ CHECK_ERROR_REF smlAssert(tsp); smlAssert(uri); smlAssert(tsp->state == SML_TRANSPORT_INITIALIZED || tsp->state == SML_TRANSPORT_CONNECTED); smlAssert(tsp->functions.set_response_uri); if (tsp->functions.set_response_uri(tsp, uri, error)) { smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; } else { smlTrace(TRACE_EXIT_ERROR, "%s", __func__); return FALSE; } } static SmlBool smlTransportDetachQueueCallback( gpointer data, SmlError **error) { smlTrace(TRACE_ENTRY, "%s", __func__); CHECK_ERROR_REF smlAssert(data); SmlQueue *queue = data; smlQueueDetach(queue); smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; } static SmlBool smlTransportDispatchQueueCallback( gpointer data, SmlError **error) { smlTrace(TRACE_ENTRY, "%s", __func__); CHECK_ERROR_REF smlAssert(data); SmlQueue *queue = data; smlQueueDispatch(queue); smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; } /** @brief Finalizes the transport * * This function will finalize the transport . The transport must be in the state "Initialized" * to use this functions. The state will then switch to "Uninitialized". * * @param tsp The transport * @param error Return location if an error occured * @returns TRUE if the call succeded or FALSE in the case of an error * */ SmlBool smlTransportFinalize(SmlTransport *tsp, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p)", __func__, tsp, error); CHECK_ERROR_REF smlAssert(tsp); smlAssert(tsp->functions.finalize); if (tsp->connected && !smlTransportIsServer(tsp)) { smlErrorSet(error, SML_ERROR_GENERIC, "If a client transport is connected then it cannot be finalized."); goto error; } if (tsp->state != SML_TRANSPORT_INITIALIZED && tsp->state != SML_TRANSPORT_ERROR) { smlErrorSet(error, SML_ERROR_GENERIC, "Transport was not in the state \"Initialized\""); goto error; } /* FIXME: Is there a situation where no thread is present? */ /* OBEX */ if (tsp->type != SML_TRANSPORT_HTTP_CLIENT && tsp->type != SML_TRANSPORT_HTTP_SERVER && tsp->thread) _smlTransportStop(tsp); /* stop the command queue */ if (tsp->thread) { /* HTTP - thread safe destroy */ if (!smlThreadCallFunction( tsp->thread, smlTransportDetachQueueCallback, tsp->command_queue, error)) goto error; } else { /* OBEX */ smlQueueDetach(tsp->command_queue); } /* give all jobs a chance to finish cleanly */ unsigned int i = 0; unsigned int queueLength = smlQueueLength(tsp->command_queue); for (; i < queueLength; i++) { if (tsp->thread) { /* HTTP */ if (!smlThreadCallFunction( tsp->thread, smlTransportDispatchQueueCallback, tsp->command_queue, error)) goto error; } else { /* OBEX */ smlQueueDispatch(tsp->command_queue); } } if (!tsp->functions.finalize(tsp->transport_data, error)) goto error; /* HTTP */ if (tsp->thread) _smlTransportStop(tsp); tsp->transport_data = NULL; tsp->state = SML_TRANSPORT_UNINITIALIZED; /* If this is a server then the server is shutdown now. */ if (smlTransportIsServer(tsp)) tsp->connected = FALSE; smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return FALSE; } char * smlTransportGetResponseURI(SmlLink *link_, SmlSession *session, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, link_, session, error); /* Do not change the assertion to simple return FALSE stuff * because to many developers incl. me ignore returned FALSE * if it is only configuration. */ CHECK_ERROR_REF smlAssert(link_); smlAssert(link_->tsp); smlAssert(session); if (link_->tsp->functions.get_response_uri) { char *result = link_->tsp->functions.get_response_uri(link_, session, error); smlTrace(TRACE_EXIT, "%s - %s", __func__, VA_STRING(result)); return result; } else { smlTrace(TRACE_EXIT, "%s - unsupported feature", __func__); return NULL; } } /*@}*/ /*@}*/ libsyncml-0.5.4/libsyncml/objects/sml_ds_server.h100644 1750 1750 12505 11211710410 22111 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2005 Armin Bauer * Copyright (C) 2007 Michael Bell * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ /** * @defgroup SmlObjectDatastoreServer SyncML Datastore Server Object * @ingroup PublicObjectAPI * @brief The public part * */ /*@{*/ #ifndef _SML_DS_SERVER_H_ #define _SML_DS_SERVER_H_ typedef struct SmlDsServer SmlDsServer; typedef struct SmlDsSession SmlDsSession; typedef enum { SML_DS_EVENT_GOTCHANGES = 0, SML_DS_EVENT_COMMITEDCHANGES = 1 } SmlDsEvent; typedef void (* SmlDsSessionConnectCb) (SmlDsSession *dsession, void *userdata); typedef SmlBool (* SmlDsSessionAlertCb) (SmlDsSession *dsession, SmlAlertType type, const char *last, const char *next, void *userdata); typedef void (* SmlDsSessionSyncCb) (SmlDsSession *dsession, unsigned int numchanges, void *userdata); typedef void (* SmlDsSessionEventCb) (SmlDsSession *dsession, SmlDsEvent event, void *userdata); typedef SmlBool (* SmlDsSessionChangesCb) (SmlDsSession *dsession, SmlChangeType type, const char *uid, char *data, unsigned int size, const char *contenttype, void *userdata, SmlError **error); /* FIXME: newuid must be removed before next API break */ /* FIXME: an internal mapping callback already exists */ /* FIXME: DEPRECATED */ typedef void (* SmlDsSessionWriteCb) (SmlDsSession *dsession, SmlStatus *status, const char *newuid, void *userdata); SmlDsServer *smlDsServerNew(const char *type, SmlLocation *location, SmlError **error); SmlDsServer *smlDsClientNew(const char *type, SmlLocation *location, SmlLocation *target, SmlError **error); SmlDsServerType smlDsServerGetServerType(SmlDsServer *server); void smlDsServerFree(SmlDsServer *server); SmlBool smlDsServerRegister(SmlDsServer *server, SmlManager *manager, SmlError **error); SmlBool smlDsServerAddSan(SmlDsServer *server, SmlNotification *san, SmlError **error); void smlDsServerReset(SmlDsServer *server); void smlDsServerSetConnectCallback(SmlDsServer *server, SmlDsSessionConnectCb callback, void *userdata); const char *smlDsServerGetLocation(SmlDsServer *server); const char *smlDsServerGetContentType(SmlDsServer *server); SmlDsSession *smlDsServerSendAlert(SmlDsServer *server, SmlSession *session, SmlAlertType type, const char *last, const char *next, SmlStatusReplyCb callback, void *userdata, SmlError **error); SmlDsSession *smlDsSessionNew(SmlDsServer *server, SmlSession *session, SmlError **error); SmlDsSession *smlDsSessionRef(SmlDsSession *dsession); void smlDsSessionUnref(SmlDsSession *dsession); void smlDsSessionDispatch(SmlDsSession *dsession); SmlBool smlDsSessionCheck(SmlDsSession *dsession); void smlDsSessionGetAlert(SmlDsSession *dsession, SmlDsSessionAlertCb callback, void *userdata); SmlBool smlDsSessionSendAlert(SmlDsSession *dsession, SmlAlertType type, const char *last, const char *next, SmlStatusReplyCb callback, void *userdata, SmlError **error); void smlDsSessionGetChanges(SmlDsSession *dsession, SmlDsSessionChangesCb chgCallback, void *userdata); void smlDsSessionGetSync(SmlDsSession *dsession, SmlDsSessionSyncCb chgCallback, void *userdata); void smlDsSessionGetEvent(SmlDsSession *dsession, SmlDsSessionEventCb eventCallback, void *userdata); SmlBool smlDsSessionSendSync(SmlDsSession *dsession, unsigned int num_changes, SmlStatusReplyCb callback, void *userdata, SmlError **error); SmlBool smlDsSessionQueueChange(SmlDsSession *dsession, SmlChangeType type, const char *uid, const char *data, unsigned int size, const char *contenttype, SmlDsSessionWriteCb callback, void *userdata, SmlError **error); SmlBool smlDsSessionCloseSync(SmlDsSession *dsession, SmlError **error); SmlBool smlDsSessionQueueMap(SmlDsSession *dsession, const char *uid, const char *newuid, SmlError **error); SmlBool smlDsSessionCloseMap(SmlDsSession *dsession, SmlStatusReplyCb callback, void *userdata, SmlError **error); const char *smlDsSessionGetLocation(SmlDsSession *dsession); const char *smlDsSessionGetContentType(SmlDsSession *dsession); SmlDsServer *smlDsSessionGetServer(SmlDsSession *dsession); SmlLocation *smlDsSessionGetTarget(SmlDsSession *dsession); /* multi session safe SAN handling */ typedef SmlErrorType (* SmlDsServerSanSessionCb) (SmlDsServer *dsserver, SmlSession *session, SmlAlertType type, void *userdata); void smlDsServerSetSanSessionCallback(SmlDsServer *server, SmlDsServerSanSessionCb callback, void *userdata); /* deprecated SAN handling */ typedef SmlErrorType (* SmlDsServerSanCb) (SmlDsServer *dsserver, SmlAlertType type, void *userdata); void smlDsServerSetSanCallback(SmlDsServer *server, SmlDsServerSanCb callback, void *userdata) LIBSYNCML_DEPRECATED; #endif //_SML_DS_SERVER_H_ /*@}*/ libsyncml-0.5.4/libsyncml/objects/sml_auth.c100644 1750 1750 32666 11211710410 21063 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2005 Armin Bauer * Copyright (C) 2008 Michael Bell * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include #include "sml_auth.h" #include #include "sml_auth_internals.h" #include #include #include #include "libsyncml/sml_error_internals.h" static SmlStatus *_smlAuthHeaderReply( SmlSession *session, SmlErrorType code, SmlAuthType auth, SmlError **error); void _status_callback(SmlSession *session, SmlStatus *status, void *userdata) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, session, status, userdata); smlTrace(TRACE_EXIT, "%s", __func__); } void _header_callback(SmlSession *session, SmlHeader *header, SmlCred *cred, void *userdata) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p, %p)", __func__, session, header, cred, userdata); smlAssert(session); smlAssert(userdata); SmlStatus *reply = NULL; SmlAuthenticator *auth = userdata; SmlError *error = NULL; if (session->sessionType == SML_SESSION_TYPE_CLIENT) { /* If this is an OMA DS client then there will be no * authentication. Only OMA DS servers can request an * authentication from the remote peer. */ g_warning("This is an OMA DS client. An OMA DS client should not use this authentication callback."); smlTrace(TRACE_INTERNAL, "%s: This is an OMA DS client and so auth is not supported.", __func__); auth->state = SML_NO_ERROR; if (auth->enabled) smlTrace(TRACE_ERROR, "%s: authentication is enabled but this is an OMA DS client."); } else if (!cred) { if (!auth->enabled) { smlTrace(TRACE_INTERNAL, "%s: Auth is disabled and no cred given", __func__); auth->state = SML_NO_ERROR; } else { /* auth->enabled */ if (auth->state != SML_AUTH_ACCEPTED) { /* Ask the remote peer to authenticate. * This is not an error because it is really dangerous * for the remote peer to send its password without * be asked for it. Please note that syncml:auth-basic * is a clear text password. */ smlTrace(TRACE_INTERNAL, "%s: Auth is required", __func__); auth->state = SML_ERROR_AUTH_REQUIRED; session->authenticate = TRUE; } else { /* auth->state == SML_AUTH_ACCEPTED */ smlTrace(TRACE_INTERNAL, "%s: Auth is already accepted.", __func__); auth->state = SML_AUTH_ACCEPTED; } } } else { /* cred available */ smlTrace(TRACE_INTERNAL, "%s: Cred is \"%s\"", __func__, VA_STRING(cred->data)); if (!auth->enabled) { smlTrace(TRACE_INTERNAL, "%s: Cred received but unwanted", __func__); auth->state = SML_AUTH_ACCEPTED; } else { /* auth->enabled */ if (auth->verifyCallback) { /* The callback needs the following stuff: * Chal * Cred * LocName(username) */ if (auth->verifyCallback(session->chal, cred, smlLocationGetName(session->source), auth->verifyCallbackUserdata, &error)) { auth->state = SML_AUTH_ACCEPTED; } else { smlErrorSet(&error, SML_ERROR_AUTH_REJECTED, "Auth rejected for username %s", smlLocationGetName(session->source)); smlSessionDispatchEvent(session, SML_SESSION_EVENT_ERROR, NULL, NULL, NULL, error); smlErrorDeref(&error); auth->state = SML_ERROR_AUTH_REJECTED; } } else { smlTrace(TRACE_INTERNAL, "%s: No verify callback set", __func__); auth->state = SML_ERROR_AUTH_REJECTED; } } } if (auth->state == SML_ERROR_AUTH_REJECTED) { smlTrace(TRACE_INTERNAL, "%s: Ending session due to wrong / missing creds", __func__); session->end = TRUE; } reply = _smlAuthHeaderReply(session, auth->state, auth->type, &error); if (!reply) goto error; if (!smlSessionSendReply(session, reply, &error)) { smlStatusUnref(reply); goto error; } smlStatusUnref(reply); if (!session->established && !session->end && !session->authenticate && session->sessionType == SML_SESSION_TYPE_SERVER) { session->established = TRUE; smlSessionDispatchEvent( session, SML_SESSION_EVENT_ESTABLISHED, NULL, NULL, NULL, NULL); } smlTrace(TRACE_EXIT, "%s", __func__); return; error: smlSessionDispatchEvent(session, SML_SESSION_EVENT_ERROR, NULL, NULL, NULL, error); smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(&error)); smlErrorDeref(&error); return; } char *smlAuthGetCredString( SmlAuthType type, const char *username, const char *password, const char *b64_nonce, SmlError **error) { smlTrace(TRACE_ENTRY, "%s", __func__); CHECK_ERROR_REF char *cred = NULL; switch (type) { case SML_AUTH_TYPE_BASIC: smlTrace(TRACE_INTERNAL, "%s - SML_AUTH_TYPE_BASIC", __func__); char *plain = g_strjoin(":", username, password, NULL); cred = g_base64_encode((unsigned char *) plain, strlen(plain)); if (!cred) { smlErrorSet(error, SML_ERROR_GENERIC, "The syncml:auth-basic credential cannot be base64 encoded."); smlSafeCFree(&plain); goto error; } smlSafeCFree(&plain); break; case SML_AUTH_TYPE_MD5: smlTrace(TRACE_INTERNAL, "%s - SML_AUTH_TYPE_MD5", __func__); /* How does syncml:auth-md5 works? * * base64( * md5( * base64( * md5( * username + ":" + password * ) * ) + * ":" + nonce * ) * ) */ /* Let's determine the string for the comparison. */ ; char *auth = g_strjoin (":", username, password, NULL); unsigned char digest[16]; smlMD5GetDigest (auth, strlen(auth), digest); smlSafeCFree(&auth); cred = g_base64_encode(digest, 16); if (!cred) { smlErrorSet(error, SML_ERROR_GENERIC, "The username:password part of the syncml:auth-md5 "\ "credential cannot be base64 encoded."); goto error; } auth = g_strjoin (":", cred, b64_nonce, NULL); smlSafeCFree(&cred); smlMD5GetDigest (auth, strlen(auth), digest); smlSafeCFree(&auth); cred = g_base64_encode(digest, 16); if (!cred) { smlErrorSet(error, SML_ERROR_GENERIC, "The complete syncml:auth-md5 credential cannot be base64 encoded."); goto error; } break; default: smlTrace(TRACE_ERROR, "%s - unknown authentication type", __func__); smlErrorSet(error, SML_ERROR_GENERIC, "Unknown auth format"); goto error; } smlTrace(TRACE_EXIT, "%s", __func__); return cred; error: smlTrace(TRACE_EXIT_ERROR, "%s - cannot create credential string"); if (*error == NULL) smlErrorSet(error, SML_ERROR_GENERIC, "Cannot create credential string for user %s.", username); return NULL; } SmlBool smlAuthVerify(SmlChal *chal, SmlCred *cred, const char *username, const char *password, SmlError **error) { smlTrace(TRACE_ENTRY, "%s", __func__); CHECK_ERROR_REF /* If no Chal is send to the client but the client offers a Cred * then we accept it. Theoretically this is not 100% perfect if * syncml:auth-md5 is used but if the client offers it then we * accept it because some implementations like UIQ 3 are broken * and implemented the protocol in a wrong way if we answer with * error 407 and a fresh nonce. * * SECURITY NOTE: This part of the code makes libsyncml vulnerable * SECURITY NOTE: against replay attacks. * */ if (chal && chal->type != cred->type) { if (chal->type == SML_AUTH_TYPE_BASIC && cred->type == SML_AUTH_TYPE_MD5) { /* This is an upgrade to more security. * So it is acceptable. */ smlTrace(TRACE_INTERNAL, "%s - replace syncml:auth-basic by syncml:auth-md5", __func__); } else { /* This is a security event. */ smlErrorSet(error, SML_ERROR_AUTH_REJECTED, "The type of the authentication was changed to a lower security level."); goto error; } } smlTrace(TRACE_INTERNAL, "%s - authentication security policy ok", __func__); char *wanted = NULL; switch (cred->type) { case SML_AUTH_TYPE_BASIC: smlTrace(TRACE_INTERNAL, "%s - SML_AUTH_TYPE_BASIC", __func__); wanted = smlAuthGetCredString(SML_AUTH_TYPE_BASIC, username, password, NULL, error); break; case SML_AUTH_TYPE_MD5: smlTrace(TRACE_INTERNAL, "%s - SML_AUTH_TYPE_MD5", __func__); if (chal) wanted = smlAuthGetCredString( SML_AUTH_TYPE_MD5, username, password, chal->nonce_b64, error); else wanted = smlAuthGetCredString( SML_AUTH_TYPE_MD5, username, password, "", error); break; default: smlTrace(TRACE_ERROR, "%s - unknown authentication type", __func__); smlErrorSet(error, SML_ERROR_GENERIC, "Unknown auth format"); goto error; } smlTrace(TRACE_INTERNAL, "%s - credential string calculated", __func__); /* compare the authentication string */ if (strcmp(wanted, cred->data)) { smlTrace(TRACE_INTERNAL, "%s - credentials mismatch", __func__); smlSafeCFree(&wanted); goto error; } smlSafeCFree(&wanted); smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error: smlTrace(TRACE_EXIT_ERROR, "%s - auth rejected"); if (*error == NULL) smlErrorSet(error, SML_ERROR_AUTH_REJECTED, "Authentication rejected for username %s.", username); return FALSE; } SmlAuthenticator *smlAuthNew(SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p)", __func__, error); CHECK_ERROR_REF SmlAuthenticator *auth = smlTryMalloc0(sizeof(SmlAuthenticator), error); if (!auth) goto error; auth->enabled = TRUE; auth->state = SML_ERROR_AUTH_REQUIRED; smlTrace(TRACE_EXIT, "%s: %p", __func__, auth); return auth; error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return NULL; } void smlAuthFree(SmlAuthenticator *auth) { smlTrace(TRACE_ENTRY, "%s(%p)", __func__, auth); smlAssert(auth); smlSafeFree((gpointer *)&auth); smlTrace(TRACE_EXIT, "%s", __func__); } SmlBool smlAuthRegister(SmlAuthenticator *auth, SmlManager *manager, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, auth, manager, error); CHECK_ERROR_REF smlAssert(auth); smlAssert(manager); smlManagerRegisterHeaderHandler(manager, _header_callback, _status_callback, auth); smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; } void smlAuthSetState(SmlAuthenticator *auth, SmlErrorType type) { smlTrace(TRACE_ENTRY, "%s(%p, %i)", __func__, auth, type); smlAssert(auth); auth->state = type; smlTrace(TRACE_EXIT, "%s", __func__); } /* FIXME: DEPRECATED*/ SmlStatus *smlAuthHeaderReply( SmlSession *session, SmlAuthType code, SmlError **error) { CHECK_ERROR_REF g_warning("SmlAuthType of smlAuthHeaderReply is used as SmlErrorType."); return _smlAuthHeaderReply(session, (SmlErrorType) code, SML_AUTH_TYPE_BASIC, error); } static SmlStatus *_smlAuthHeaderReply( SmlSession *session, SmlErrorType code, SmlAuthType auth, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %i, %i, %p)", __func__, session, code, auth, error); CHECK_ERROR_REF // the session structure is from the viewpoint of this machine // SourceRef and TargetRef of the status MUST use the viewpoint // of the remote peer // we have to revert source and target smlTrace(TRACE_INTERNAL, "%s: SourceRef: %s --> TargetRef: %s", __func__, VA_STRING(session->target->locURI), VA_STRING(session->source->locURI)); SmlStatus *reply = smlStatusNew(code, 0, session->lastReceivedMessageID, session->target, session->source, SML_COMMAND_TYPE_HEADER, error); if (!reply) goto error; if (code == SML_ERROR_AUTH_REJECTED || code == SML_ERROR_AUTH_REQUIRED) { reply->chal = smlChalNew(auth, error); if (!reply->chal) goto error_free_reply; session->chal = reply->chal; smlChalRef(session->chal); } smlTrace(TRACE_EXIT, "%s: %p", __func__, reply); return reply; error_free_reply: smlStatusUnref(reply); error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return NULL; } void smlAuthSetVerifyCallback(SmlAuthenticator *auth, SmlAuthVerifyCb callback, void *userdata) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, auth, callback, userdata); smlAssert(auth); auth->verifyCallback = callback; auth->verifyCallbackUserdata = userdata; smlTrace(TRACE_EXIT, "%s", __func__); } void smlAuthSetEnable(SmlAuthenticator *auth, SmlBool enabled) { smlTrace(TRACE_ENTRY, "%s(%p, %i)", __func__, auth, enabled); smlAssert(auth); auth->enabled = enabled; smlTrace(TRACE_EXIT, "%s", __func__); } SmlBool smlAuthIsEnabled(SmlAuthenticator *auth) { smlTrace(TRACE_ENTRY, "%s(%p)", __func__, auth); smlAssert(auth); smlTrace(TRACE_EXIT, "%s - %u", __func__, auth->enabled); return auth->enabled; } void smlAuthSetType(SmlAuthenticator *auth, SmlAuthType type) { smlTrace(TRACE_ENTRY, "%s(%p, %i)", __func__, auth, type); smlAssert(auth); smlAssert(type != SML_AUTH_TYPE_UNKNOWN); auth->type = type; smlTrace(TRACE_EXIT, "%s", __func__); } libsyncml-0.5.4/libsyncml/objects/sml_devinf_obj.c100644 1750 1750 50710 11211710410 22215 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2005 Armin Bauer * Copyright (C) 2007-2009 Michael Bell * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include #include "sml_devinf_obj.h" #include #include "sml_devinf_obj_internals.h" #include #include #include #include "libsyncml/sml_error_internals.h" #ifdef WIN32 #include #else #include #endif /* Design notice * * There is only one SmlDevInfAgent per SmlManager * because there is only one local device information. * Therefore the agent must be able to manage one * device information per session because every remote * device can have different capabilities. */ /* functions to manage SmlDevInfAgentSession */ static SmlDevInfAgentSession* _new_session( SmlDevInfAgent *agent, SmlSession *session, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, agent, session, error); CHECK_ERROR_REF smlAssert(agent); smlAssert(agent->sessions); smlAssert(session); SmlDevInfAgentSession *as = smlTryMalloc0(sizeof(SmlDevInfAgentSession), error); if (!as) goto error; g_hash_table_insert(agent->sessions, session, as); smlTrace(TRACE_EXIT, "%s - %p", __func__, as); return as; error: smlSafeFree((gpointer *) &as); smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(error)); return NULL; } static SmlDevInfAgentSession* _get_session( SmlDevInfAgent *agent, SmlSession *session) { smlTrace(TRACE_ENTRY, "%s(%p, %p)", __func__, agent, session); smlAssert(agent); smlAssert(agent->sessions); smlAssert(session); SmlDevInfAgentSession *as = g_hash_table_lookup(agent->sessions, session); smlTrace(TRACE_EXIT, "%s - %p", __func__, as); return as; } static void _free_session (gpointer data) { smlTrace(TRACE_ENTRY, "%s(%p)", __func__, data); SmlDevInfAgentSession *as = data; if (as->recvDevInf) smlDevInfUnref(as->recvDevInf); smlSafeFree((gpointer *) &as); smlTrace(TRACE_EXIT, "%s", __func__); } /* functions to manage SmlDevInfAgent */ static void _get_devinf_reply(SmlSession *session, SmlStatus *status, void *userdata) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, session, status, userdata); SmlError *error = NULL; SmlDevInfAgent *agent = userdata; if (smlStatusIsResult(status)) { SmlCommand *result = smlStatusGetResult(status); /* get cached session or add session to agent cache */ SmlDevInfAgentSession *as = _get_session(agent, session); if (!as) { as = _new_session(agent, session, &error); if (!as) goto error; } /* cache device information */ as->recvDevInf = smlDevInfFromResult(result, &error); if (!as->recvDevInf) goto error; /* send answer */ SmlStatus *reply = smlCommandNewReply(result, SML_NO_ERROR, &error); if (!reply) goto error; if (!smlSessionSendReply(session, reply, &error)) { smlStatusUnref(reply); goto error; } smlStatusUnref(reply); } smlTrace(TRACE_EXIT, "%s", __func__); return; error: smlSessionDispatchEvent(session, SML_SESSION_EVENT_ERROR, NULL, NULL, NULL, error); smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(&error)); smlErrorDeref(&error); } static void _devinf_reply(SmlSession *session, SmlStatus *status, void *userdata) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, session, status, userdata); smlTrace(TRACE_EXIT, "%s", __func__); } static SmlBool _send_devinf(SmlDevInfAgent *agent, SmlSession *session, SmlCommand *get, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p, %p)", __func__, agent, session, get, error); CHECK_ERROR_REF SmlCommand *result = NULL; SmlCommand *cmd = NULL; /* It is a good idea to perform some sanity checks on the * configuration before the device information is sent. */ /* If this is SyncML 1.1 or higher then large object support is * required for OMA DS servers. */ if (smlSessionGetVersion(session) >= SML_VERSION_11 && session->sessionType == SML_SESSION_TYPE_SERVER && !smlDevInfSupportsLargeObjs(agent->devinf)) { smlErrorSet(error, SML_ERROR_INTERNAL_MISCONFIGURATION, "OMA DS Server must support large object handling if SyncML 1.1 or higher is used."); goto error; } /* If large object support is enabled then MaxMsgSize and * MaxObjSize must be set. */ if (smlDevInfSupportsLargeObjs(agent->devinf)) { if (smlSessionGetLocalMaxMsgSize(session) < 1) { smlErrorSet(error, SML_ERROR_INTERNAL_MISCONFIGURATION, "If large object support is enabled then MaxMsgSize must be set."); goto error; } if (smlSessionGetLocalMaxObjSize(session) < 1) { smlErrorSet(error, SML_ERROR_INTERNAL_MISCONFIGURATION, "If large object support is enabled then MaxObjSize must be set."); goto error; } } /* get cached session or add session to agent cache */ SmlDevInfAgentSession *as = _get_session(agent, session); if (!as) { as = _new_session(agent, session, error); if (!as) goto error; } /* Sanity checks complete. Sending device information ... */ if (!as->devinfSent) { if (get) { if (smlSessionGetVersion(session) == SML_VERSION_10) result = smlDevInfNewResult(get, agent->devinf, SML_DEVINF_VERSION_10, error); else if (smlSessionGetVersion(session) == SML_VERSION_12) result = smlDevInfNewResult(get, agent->devinf, SML_DEVINF_VERSION_12, error); else result = smlDevInfNewResult(get, agent->devinf, SML_DEVINF_VERSION_11, error); if (!result) goto error; if (!smlSessionSendCommand(session, result, NULL, _devinf_reply, agent, error)) { smlCommandUnref(result); goto error; } smlCommandUnref(result); SmlStatus *reply = smlCommandNewReply(get, SML_NO_ERROR, error); if (!reply) goto error; if (!smlSessionSendReply(session, reply, error)) { smlStatusUnref(reply); goto error; } smlStatusUnref(reply); } else { if (smlSessionGetVersion(session) == SML_VERSION_10) cmd = smlDevInfNewPut(agent->devinf, SML_DEVINF_VERSION_10, error); else if (smlSessionGetVersion(session) == SML_VERSION_12) cmd = smlDevInfNewPut(agent->devinf, SML_DEVINF_VERSION_12, error); else cmd = smlDevInfNewPut(agent->devinf, SML_DEVINF_VERSION_11, error); if (!cmd) goto error; if (!smlSessionSendCommand(session, cmd, NULL, _devinf_reply, agent, error)) { smlCommandUnref(cmd); goto error; } smlCommandUnref(cmd); } as->devinfSent = TRUE; } else { smlTrace(TRACE_INTERNAL, "%s: Already sent the devinf!", __func__); if (get) { /* We return a generic error if we dont want to send the devinf to a get * request. Hope that all devices like this */ SmlStatus *reply = smlCommandNewReply(get, SML_ERROR_GENERIC, error); if (!reply) goto error; if (!smlSessionSendReply(session, reply, error)) { smlStatusUnref(reply); goto error; } smlStatusUnref(reply); } else { /* This means that a software component tries to * send the device information but it was already * sent. This can happen if the local library * user is missing the remote device information * and wants to send the get request together * with its own device information. Nevertheless * this is an error - but it can be ignored. */ smlTrace(TRACE_INTERNAL, "%s: libsyncml does not send local device information twice.", __func__); } } smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return FALSE; } static void _recv_devinf(SmlSession *session, SmlCommand *cmd, void *userdata) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, session, cmd, userdata); SmlDevInfAgent *agent = userdata; SmlError *error = NULL; char *data = NULL; unsigned int size = 0; if (!smlItemGetData(cmd->private.access.item, &data, &size, &error)) goto error; SmlDevInfAgentSession *as = _get_session(agent, session); if (!as) { as = _new_session(agent, session, &error); if (!as) goto error; } as->recvDevInf = smlDevInfParse(data, size, &error); if (!as->recvDevInf) goto error; SmlStatus *reply = smlCommandNewReply(cmd, SML_NO_ERROR, &error); if (!reply) goto error; if (!smlSessionSendReply(session, reply, &error)) { smlStatusUnref(reply); goto error; } smlStatusUnref(reply); smlTrace(TRACE_EXIT, "%s", __func__); return; error: smlSessionDispatchEvent(session, SML_SESSION_EVENT_ERROR, NULL, NULL, NULL, error); smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(&error)); smlErrorDeref(&error); } static void _request_devinf(SmlSession *session, SmlCommand *cmd, void *userdata) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, session, cmd, userdata); SmlDevInfAgent *agent = userdata; SmlError *error = NULL; if (!_send_devinf(agent, session, cmd, &error)) goto error; smlTrace(TRACE_EXIT, "%s", __func__); return; error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(&error)); } SmlDevInfAgent *smlDevInfAgentNew(SmlDevInf *devinf, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p)", __func__, devinf, error); CHECK_ERROR_REF smlAssert(devinf); SmlDevInfAgent *agent = smlTryMalloc0(sizeof(SmlDevInfAgent), error); if (!agent) goto error; agent->devinf = devinf; agent->sessions = g_hash_table_new_full(NULL, NULL, NULL, _free_session); if (!agent->sessions) { smlErrorSet(error, SML_ERROR_INTERNAL_NO_MEMORY, "Cannot create new hash table."); goto error; } if (!smlDevInfGetManufacturer(devinf)) smlDevInfSetManufacturer(devinf, "OpenSync"); if (!smlDevInfGetModel(devinf)) smlDevInfSetModel(devinf, "libsyncml"); if (!smlDevInfGetOEM(devinf)) { #ifdef WIN32 smlDevInfSetOEM(devinf, "Windows"); DWORD dwVersion = GetVersion(); DWORD dwMajorVersion = (DWORD)(LOBYTE(LOWORD(dwVersion))); DWORD dwMinorVersion = (DWORD)(HIBYTE(LOWORD(dwVersion))); DWORD dwBuild = 0; if (dwVersion < 0x80000000) dwBuild = (DWORD)(HIWORD(dwVersion)); char szVersion[1024]; sprintf(szVersion, "%d.%d (%d)", dwMajorVersion, dwMinorVersion, dwBuild); smlDevInfSetFirmwareVersion(devinf, szVersion); #else struct utsname *buf = malloc(sizeof(struct utsname)); if (uname(buf) == 0) { smlDevInfSetOEM(devinf, buf->sysname); smlDevInfSetFirmwareVersion(devinf, buf->release); } smlSafeFree((gpointer *)&buf); #endif } if (!smlDevInfGetSoftwareVersion(devinf)) smlDevInfSetSoftwareVersion(devinf, VERSION); smlTrace(TRACE_EXIT, "%s: %p", __func__, agent); return agent; error: if (agent) smlSafeFree((gpointer *) &agent); smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return NULL; } void smlDevInfAgentFree(SmlDevInfAgent *agent) { smlTrace(TRACE_ENTRY, "%s(%p)", __func__, agent); smlAssert(agent); if (agent->devinf) smlDevInfUnref(agent->devinf); g_hash_table_destroy(agent->sessions); smlSafeFree((gpointer *)&agent); smlTrace(TRACE_EXIT, "%s", __func__); } /* FIXME: DEPRECATED */ void smlDevInfAgentSetDevInf(SmlDevInfAgent *agent, SmlDevInf *devinf) { smlTrace(TRACE_ERROR, "%s(%p, %p)", __func__, agent, devinf); smlAssertMsg(NULL, "This function is a design bug."); } /* FIXME: DEPRECATED */ SmlDevInf *smlDevInfAgentGetDevInf(SmlDevInfAgent *agent) { smlTrace(TRACE_ERROR, "%s(%p, %p)", __func__, agent); smlAssertMsg(NULL, "This function is a design bug."); return NULL; } /* Set the devinf of the remote peer. */ SmlBool smlDevInfAgentSetSessionDevInf( SmlDevInfAgent *agent, SmlSession *session, SmlDevInf *devinf, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p, %p)", __func__, agent, session, devinf, error); CHECK_ERROR_REF smlAssert(agent); smlAssert(agent->sessions); smlAssert(session); smlAssert(devinf); SmlDevInfAgentSession *as = _get_session(agent, session); if (!as) { as = _new_session(agent, session, error); if (!as) goto error; } as->recvDevInf = devinf; smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error: smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(error)); return FALSE; } /* Get the devinf that was sent in the session. Returns FALSE if no devinf was received yet. */ SmlDevInf *smlDevInfAgentGetSessionDevInf(SmlDevInfAgent *agent, SmlSession *session) { smlTrace(TRACE_ENTRY, "%s(%p, %p)", __func__, agent, session); smlAssert(agent); smlAssert(agent->sessions); smlAssert(session); SmlDevInfAgentSession *as = _get_session(agent, session); if (!as) { smlTrace(TRACE_EXIT, "%s - the session is not cached until now", __func__); return NULL; } smlTrace(TRACE_EXIT, "%s - %p", __func__, as->recvDevInf); return as->recvDevInf; } /** Issues a put request on the session if needed */ SmlBool smlDevInfAgentSendDevInf(SmlDevInfAgent *agent, SmlSession *session, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, agent, session, error); CHECK_ERROR_REF smlAssert(agent); if (!_send_devinf(agent, session, NULL, error)) goto error; smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return FALSE; } /** Issues a Get request for the devinf on the session if needed */ SmlBool smlDevInfAgentRequestDevInf(SmlDevInfAgent *agent, SmlSession *session, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, agent, session, error); CHECK_ERROR_REF smlAssert(agent); SmlCommand *get = NULL; SmlDevInfAgentSession *as = _get_session(agent, session); if (!as) { as = _new_session(agent, session, error); if (!as) goto error; } if (as->recvDevInf) { smlTrace(TRACE_EXIT, "%s: Already have the devinf", __func__); return TRUE; } if (!as->devinfRequested) { if (smlSessionGetVersion(session) == SML_VERSION_10) get = smlDevInfNewGet(SML_DEVINF_VERSION_10, error); else if (smlSessionGetVersion(session) == SML_VERSION_12) get = smlDevInfNewGet(SML_DEVINF_VERSION_12, error); else get = smlDevInfNewGet(SML_DEVINF_VERSION_11, error); if (!get) goto error; if (!smlSessionSendCommand(session, get, NULL, _get_devinf_reply, agent, error)) { smlCommandUnref(get); goto error; } smlCommandUnref(get); as->devinfRequested = TRUE; } else { smlTrace(TRACE_INTERNAL, "%s: Already requested the devinf!", __func__); } smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return FALSE; } SmlBool smlDevInfAgentRegisterSession(SmlDevInfAgent *agent, SmlManager *manager, SmlSession *session, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p, %p)", __func__, agent, manager, session, error); CHECK_ERROR_REF smlAssert(agent); smlAssert(manager); SmlLocation *devinf12 = smlLocationNew("./devinf12", NULL, error); SmlLocation *devinf11 = smlLocationNew("./devinf11", NULL, error); SmlLocation *devinf10 = smlLocationNew("./devinf10", NULL, error); if (!devinf12 || !devinf11 || !devinf10) goto error; /* PUT callbacks * * This command is used to actively send device information without * being asked for. Usually a client do this if it is the first * connection with the server or the client has no problems with * its bandwith. * * Sometimes a server is missing the client's device information. * In this situation the server can send a PUT and a GET to force * the client to send the device information. This can happen if * the client know that server should have its device information * because of an earlier synchronization but the server does not * have the device information. Sometimes server databases (incl. * the device information database) are lost or it is simply a * new server but with the old server address (IP) or name (DNS). * * Please note that a client can ignore a PUT from a server. * Nevertheless it is recommended that a client does not ignore * the device information of a server. */ smlTrace(TRACE_INTERNAL, "%s: register callbacks for PUT command", __func__); if (!smlManagerObjectRegister( manager, SML_COMMAND_TYPE_PUT, session, NULL, devinf10, NULL, _recv_devinf, NULL, agent, error)) goto error_free_loc; if (!smlManagerObjectRegister( manager, SML_COMMAND_TYPE_PUT, session, NULL, devinf11, NULL, _recv_devinf, NULL, agent, error)) goto error_free_loc; if (!smlManagerObjectRegister( manager, SML_COMMAND_TYPE_PUT, session, NULL, devinf12, NULL, _recv_devinf, NULL, agent, error)) goto error_free_loc; /* GET callbacks * * This command is used to request the device information of a * remote peer. Usually the client do this if it is the first * connection with this server or the client does not remember * the server's device information. The most mobiles only do * this for the first successful connection. Data costs usually * high amounts of money in the mobile world and the bandwith is * small in the mobile world. * * Nevertheless if a mobile does not perform the PUT command and * the server does not know the device information of the client * then the server can send a GET command and the client has to * react on it. Please see above why this can happen. * * Please note that client and server must be able to handle the * GET command. A RESULTS command must be send with the local * device information. */ smlTrace(TRACE_INTERNAL, "%s: register callbacks for GET command", __func__); if (!smlManagerObjectRegister( manager, SML_COMMAND_TYPE_GET, session, devinf10, NULL, NULL, _request_devinf, NULL, agent, error)) goto error_free_loc; if (!smlManagerObjectRegister( manager, SML_COMMAND_TYPE_GET, session, devinf11, NULL, NULL, _request_devinf, NULL, agent, error)) goto error_free_loc; if (!smlManagerObjectRegister( manager, SML_COMMAND_TYPE_GET, session, devinf12, NULL, NULL, _request_devinf, NULL, agent, error)) goto error_free_loc; /* RESULTS callbacks * * This command is used to send the device information which * was requested with a GET command. This command can be send by * server and clients. Please see above when this happens. * * A server must be able to handle and interpret a RESULTS * command from a client. Especially this is required because a * server must explicitly request such a command with a previous * GET command. * * Please note that a client can ignore a RESULTS from a server. * Nevertheless it is recommended that a client does not ignore * the device information of a server. */ smlTrace(TRACE_INTERNAL, "%s: register callbacks for RESULTS command", __func__); if (!smlManagerObjectRegister( manager, SML_COMMAND_TYPE_RESULTS, session, devinf10, NULL, NULL, _recv_devinf, NULL, agent, error)) goto error_free_loc; if (!smlManagerObjectRegister( manager, SML_COMMAND_TYPE_RESULTS, session, devinf11, NULL, NULL, _recv_devinf, NULL, agent, error)) goto error_free_loc; if (!smlManagerObjectRegister( manager, SML_COMMAND_TYPE_RESULTS, session, devinf12, NULL, NULL, _recv_devinf, NULL, agent, error)) goto error_free_loc; smlLocationUnref(devinf10); smlLocationUnref(devinf11); smlLocationUnref(devinf12); smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error_free_loc: if (devinf10) smlLocationUnref(devinf10); if (devinf11) smlLocationUnref(devinf11); if (devinf12) smlLocationUnref(devinf12); error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return FALSE; } SmlBool smlDevInfAgentRegister(SmlDevInfAgent *agent, SmlManager *manager, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, agent, manager, error); CHECK_ERROR_REF SmlBool retval = smlDevInfAgentRegisterSession(agent, manager, NULL, error); if (!retval) goto error; smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return FALSE; } libsyncml-0.5.4/libsyncml/objects/sml_auth.h100644 1750 1750 4253 11211710410 21037 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2005 Armin Bauer * Copyright (C) 2008 Michael Bell * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ /** * @defgroup SmlObjectAuth SyncML Authentication Object * @ingroup PublicObjectAPI * @brief The public part * */ /*@{*/ #ifndef _SML_AUTH_H_ #define _SML_AUTH_H_ typedef struct SmlAuthenticator SmlAuthenticator; typedef SmlBool (* SmlAuthVerifyCb)(SmlChal *chal, SmlCred *cred, const char *username, void *userdata, SmlError **error); SmlAuthenticator *smlAuthNew(SmlError **error); void smlAuthFree(SmlAuthenticator *auth); SmlBool smlAuthRegister(SmlAuthenticator *auth, SmlManager *manager, SmlError **error); void smlAuthSetState(SmlAuthenticator *auth, SmlErrorType type); void smlAuthSetVerifyCallback(SmlAuthenticator *auth, SmlAuthVerifyCb callback, void *userdata); void smlAuthSetEnable(SmlAuthenticator *auth, SmlBool enabled); SmlBool smlAuthIsEnabled(SmlAuthenticator *auth); /* This can be used from within the SmlAuthVerifyCb to do the authentication itself. */ SmlBool smlAuthVerify(SmlChal *chal, SmlCred *cred, const char *username, const char *password, SmlError **error); /* set required authentication type if this is a server */ void smlAuthSetType(SmlAuthenticator *auth, SmlAuthType code); /* expire date: 20090813 */ SmlStatus *smlAuthHeaderReply(SmlSession *session, SmlAuthType code, SmlError **error) LIBSYNCML_DEPRECATED; #endif //_SML_AUTH_H_ /*@}*/ libsyncml-0.5.4/libsyncml/objects/sml_devinf_obj_internals.h100644 1750 1750 2555 11211710410 24265 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2005 Armin Bauer * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ /** * @defgroup SmlObjectDevInfPrivate SyncML Device Information Object Internals * @ingroup PrivateObjectAPI * @brief The public part * */ /*@{*/ #ifndef _SML_DEVINF_OBJ_INTERNALS_H_ #define _SML_DEVINF_OBJ_INTERNALS_H_ typedef struct SmlDevInfAgentSession { /* states */ SmlBool devinfSent; SmlBool devinfRequested; /* remote device information */ SmlDevInf *recvDevInf; } SmlDevInfAgentSession; struct SmlDevInfAgent { SmlDevInf *devinf; GHashTable *sessions; }; #endif //_SML_DEVINF_OBJ_INTERNALS_H_ /*@}*/ libsyncml-0.5.4/libsyncml/objects/sml_auth_internals.h100644 1750 1750 2716 11211710410 23120 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2005 Armin Bauer * Copyright (C) 2008 Michael Bell * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ /** * @defgroup SmlObjectAuthPrivate SyncML Authentication Object Internals * @ingroup PrivateObjectAPI * @brief The public part * */ /*@{*/ #ifndef _SML_AUTH_INTERNALS_H_ #define _SML_AUTH_INTERNALS_H_ #include "sml_auth.h" struct SmlAuthenticator { SmlErrorType state; SmlAuthVerifyCb verifyCallback; void *verifyCallbackUserdata; SmlBool enabled; SmlAuthType type; }; char *smlAuthGetCredString( SmlAuthType type, const char *username, const char *password, const char *b64_nonce, SmlError **error); #endif //_SML_AUTH_INTERNALS_H_ /*@}*/ libsyncml-0.5.4/libsyncml/objects/sml_ds_server_internals.h100644 1750 1750 10144 11211710410 24165 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2005 Armin Bauer * Copyright (C) 2008 Michael Bell * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ /** * @defgroup SmlObjectDatastoreServerPrivate SyncML Datastore Server Object Internals * @ingroup PrivateObjectAPI * @brief The public part * */ /*@{*/ #ifndef _SML_DS_SERVER_INTERNALS_H_ #define _SML_DS_SERVER_INTERNALS_H_ typedef void (* SmlDsSessionMapCb) (SmlDsSession *dsession, SmlLocation *orig, SmlLocation *mapped, void *userdata); typedef struct SmlWriteContext { SmlDsSessionWriteCb callback; char *uid; char *newuid; SmlStatus *status; void *userdata; SmlChangeType type; SmlDsSession *session; } SmlWriteContext; struct SmlDsSession { gint refCount; SmlDsServer *server; SmlSession *session; SmlLocation *target; SmlLocation *location; /** Callback that will receive the alert once it is received */ SmlDsSessionAlertCb recvAlertCallback; void *recvAlertCallbackUserdata; SmlCommand *alertCommand; /** Callback that will receive the reply to the alert */ SmlStatusReplyCb sentAlertCallback; void *sentAlertCallbackUserdata; /** Callback that will receive the sync command */ SmlDsSessionSyncCb recvSyncCallback; void *recvSyncCallbackUserdata; SmlDsSessionChangesCb changesCallback; void *changesCallbackUserdata; /** List of received sync commands. We need a list here * since sync commands might get split due to size limitations * and the answer to a sync command might arrive after several * sync commands have been received */ GList *recvSync; GList *recvChanges; SmlErrorType syncReply; SmlBool finalLock; SmlBool emptySync; /** Callback that will receive the reply to the sync command */ SmlStatusReplyCb sentSyncCallback; void *sentSyncCallbackUserdata; /** Callback that will information about the Ds Session events */ SmlDsSessionEventCb recvEventCallback; void *recvEventCallbackUserdata; /** The temporary storage for the sync command to send */ SmlCommand *syncCommand; GList *pendingMaps; GMutex *pendingMapsLock; GList *mapItems; /** Callback that signals mappings */ SmlDsSessionMapCb recvMappingCallback; void *recvMappingCallbackUserdata; GMutex *write_lock; GMutex *lock; }; struct SmlDsServer { SmlLocation *location; /** The target if the ds server is in client mode */ SmlLocation *target; char *contenttype; SmlDsServerType servertype; SmlManager *manager; /** Callback that will get called once a new client connects */ SmlDsSessionConnectCb connectCallback; void *connectCallbackUserdata; SmlDsServerSanSessionCb sanSessionCallback; void *sanSessionCallbackUserdata; SmlDsServerSanCb sanCallback; void *sanCallbackUserdata; }; void smlDsSessionRecvAlert(SmlSession *session, SmlCommand *cmd, void *userdata); void smlDsSessionRecvSync(SmlSession *session, SmlCommand *cmd, void *userdata); void smlDsSessionRecvChange(SmlSession *session, SmlCommand *cmd, void *userdata); void smlDsSessionRecvMap(SmlSession *session, SmlCommand *cmd, void *userdata); SmlDsSession *smlDsServerRecvAlert(SmlDsServer *server, SmlSession *session, SmlCommand *cmd); SmlDsSession *smlDsSessionNew(SmlDsServer *server, SmlSession *session, SmlError **error); void smlDsSessionFree(SmlDsSession *dsession); void smlDsSessionGetMapping(SmlDsSession *dsession, SmlDsSessionMapCb mapCallback, void *userdata); #endif //_SML_DS_SERVER_INTERNALS_H_ /*@}*/ libsyncml-0.5.4/libsyncml/objects/sml_devinf_obj.h100644 1750 1750 4706 11211710410 22206 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2005 Armin Bauer * Copyright (C) 2008 Michael Bell * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ /** * @defgroup SmlObjectDevInf SyncML Device Information Object * @ingroup PublicObjectAPI * @brief The public part * */ /*@{*/ #ifndef _SML_DEVINF_OBJ_H_ #define _SML_DEVINF_OBJ_H_ typedef struct SmlDevInfAgent SmlDevInfAgent; // only the SmlDevInf pointer of smlDevInfAgentNew is the local DevInf // all other SmlDevInf pointers are the DevInf of the remote peer SmlDevInfAgent *smlDevInfAgentNew(SmlDevInf *devinf, SmlError **error); void smlDevInfAgentFree(SmlDevInfAgent *agent); SmlBool smlDevInfAgentRegisterSession(SmlDevInfAgent *agent, SmlManager *manager, SmlSession *session, SmlError **error); SmlBool smlDevInfAgentRegister(SmlDevInfAgent *agent, SmlManager *manager, SmlError **error); SmlBool smlDevInfAgentSendDevInf(SmlDevInfAgent *agent, SmlSession *session, SmlError **error); SmlBool smlDevInfAgentRequestDevInf(SmlDevInfAgent *agent, SmlSession *session, SmlError **error); SmlBool smlDevInfAgentSetSessionDevInf(SmlDevInfAgent *agent, SmlSession *session, SmlDevInf *devinf, SmlError **error); SmlDevInf *smlDevInfAgentGetSessionDevInf(SmlDevInfAgent *agent, SmlSession *session); /* These functions can only work in a single session environemnt. * This is a design bug. The functions are not removed immediately * to avoid breaking applications which ignore the device information. * These functions always fire an assertion. */ void smlDevInfAgentSetDevInf(SmlDevInfAgent *agent, SmlDevInf *devinf) LIBSYNCML_DEPRECATED; SmlDevInf *smlDevInfAgentGetDevInf(SmlDevInfAgent *agent) LIBSYNCML_DEPRECATED; #endif //_SML_DEVINF_OBJ_H_ /*@}*/ libsyncml-0.5.4/libsyncml/objects/sml_ds_server.c100644 1750 1750 123601 11211710410 22124 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2005 Armin Bauer * Copyright (C) 2007-2009 Michael Bell * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include #include "sml_ds_server.h" #include #include "sml_ds_server_internals.h" #include #include #include #include #include static SmlWriteContext *_write_context_find(SmlDsSession *dsession, const char *uid, SmlChangeType type) { smlTrace(TRACE_ENTRY, "%s(%p, %s, %i)", __func__, dsession, VA_STRING(uid), type); g_mutex_lock(dsession->pendingMapsLock); GList *c = NULL; for (c = dsession->pendingMaps; c; c = c->next) { SmlWriteContext *ctx = c->data; if (!strcmp(uid, ctx->uid) && ctx->type == type) { g_mutex_unlock(dsession->pendingMapsLock); smlTrace(TRACE_EXIT, "%s: %p", __func__, ctx); return ctx; } } g_mutex_unlock(dsession->pendingMapsLock); smlTrace(TRACE_EXIT_ERROR, "%s: Not found", __func__); return NULL; } static void _write_context_free(SmlWriteContext *ctx) { smlTrace(TRACE_ENTRY, "%s(%p)", __func__, ctx); if (ctx->status) smlStatusUnref(ctx->status); if (ctx->uid) smlSafeCFree(&(ctx->uid)); if (ctx->newuid) smlSafeCFree(&(ctx->newuid)); smlSafeFree((gpointer *)&ctx); smlTrace(TRACE_EXIT, "%s", __func__); } static void _write_context_dispatch(SmlDsSession *dsession, SmlWriteContext *ctx) { smlTrace(TRACE_ENTRY, "%s(%p, %p)", __func__, dsession, ctx); if (!ctx->status) { smlTrace(TRACE_EXIT, "%s: No status yet", __func__); return; } smlTrace(TRACE_INTERNAL, "%s: Dispatching: uid %s, Type %i, newuid %s, result %i", __func__, VA_STRING(ctx->uid), ctx->type, VA_STRING(ctx->newuid), smlStatusGetCode(ctx->status)); if (ctx->type == SML_CHANGE_ADD && smlStatusGetClass(ctx->status) == SML_ERRORCLASS_SUCCESS && !dsession->recvMappingCallback && !ctx->newuid && dsession->server->servertype == SML_DS_SERVER) { smlTrace(TRACE_EXIT, "%s: No mapitem yet", __func__); return; } ctx->callback(dsession, ctx->status, ctx->newuid, ctx->userdata); g_mutex_lock(dsession->pendingMapsLock); dsession->pendingMaps = g_list_remove(dsession->pendingMaps, ctx); g_mutex_unlock(dsession->pendingMapsLock); if (ctx->type == SML_CHANGE_ADD && smlStatusGetClass(ctx->status) == SML_ERRORCLASS_SUCCESS && dsession->recvEventCallback && !dsession->pendingMaps) { /* FIXME: I'm sure that this event is buggy. * FIXME: What is the semantic of this event? * Now there are no more MapItems ... * do some fancy callback. Some applications will love it ;) */ dsession->recvEventCallback(dsession, SML_DS_EVENT_COMMITEDCHANGES, dsession->recvEventCallbackUserdata); smlTrace(TRACE_INTERNAL, "%s: recvEventCallback commited changes callback", __func__); } _write_context_free(ctx); smlTrace(TRACE_EXIT, "%s", __func__); } static void _alert_reply(SmlSession *session, SmlStatus *status, void *userdata) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, session, status, userdata); SmlDsSession *dsession = userdata; if (dsession->sentAlertCallback) dsession->sentAlertCallback(session, status, dsession->sentAlertCallbackUserdata); dsession->sentAlertCallback = NULL; dsession->sentAlertCallbackUserdata = NULL; smlTrace(TRACE_EXIT, "%s", __func__); } static void _sync_reply(SmlSession *session, SmlStatus *status, void *userdata) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, session, status, userdata); SmlDsSession *dsession = userdata; if (dsession->sentSyncCallback) dsession->sentSyncCallback(session, status, dsession->sentSyncCallbackUserdata); dsession->sentSyncCallback = NULL; dsession->sentSyncCallbackUserdata = NULL; // Now there are no more MapItems ... do some fancy callback. Some applications will love it ;) if (dsession->recvEventCallback && !dsession->pendingMaps) { dsession->recvEventCallback(dsession, SML_DS_EVENT_COMMITEDCHANGES, dsession->recvEventCallbackUserdata); smlTrace(TRACE_INTERNAL, "%s: recvEventCallback commited changes callback", __func__); } smlTrace(TRACE_EXIT, "%s", __func__); } static void _change_reply(SmlSession *session, SmlStatus *status, void *userdata) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, session, status, userdata); smlAssert(session); smlAssert(status); SmlWriteContext *ctx = userdata; SmlDsSession *dsession = ctx->session; /* Please see smlChangeAssemble in sml_xml_parser.c for * a more detailed description on the checked behaviour. * If the received command is an Add or the remote peer * is an OMA DS client then the remote peer must send a * Source. Otherwise a Target must be sent by the remote * peer. We only check the required behaviour and not * the optional one. */ if (status->type == SML_COMMAND_TYPE_ADD || session->sessionType == SML_SESSION_TYPE_CLIENT) { /* FIXME: How do we handle remote peers which are clients * FIXME: and only support replace? The assembler will * FIXME: send a replace command with a target instead of * FIXME: an add command with a source. */ if (!status->sourceRef) { smlTrace(TRACE_EXIT_ERROR, "%s: Received add status or change reply from an OMA DS server without sourceRef", __func__); return; } } else { if (!status->targetRef) { smlTrace(TRACE_EXIT_ERROR, "%s: Received delete or modify status or change reply from an OMA DS client without targetRef", __func__); return; } } ctx->status = status; smlStatusRef(status); _write_context_dispatch(dsession, ctx); smlTrace(TRACE_EXIT, "%s", __func__); } SmlDsServer *smlDsServerNew(const char *type, SmlLocation *location, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%s, %p, %p)", __func__, VA_STRING(type), location, error); smlAssert(location); CHECK_ERROR_REF SmlDsServer *server = smlTryMalloc0(sizeof(SmlDsServer), error); if (!server) goto error; server->location = location; smlLocationRef(location); server->contenttype = g_strdup(type); server->servertype = SML_DS_SERVER; smlTrace(TRACE_EXIT, "%s: %p", __func__, server); return server; error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return NULL; } SmlDsServer *smlDsClientNew(const char *type, SmlLocation *location, SmlLocation *target, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%s, %p, %p, %p)", __func__, VA_STRING(type), location, target, error); smlAssert(location); smlAssert(target); CHECK_ERROR_REF SmlDsServer *server = smlTryMalloc0(sizeof(SmlDsServer), error); if (!server) goto error; server->location = location; smlLocationRef(location); server->target = target; smlLocationRef(target); server->contenttype = g_strdup(type); server->servertype = SML_DS_CLIENT; smlTrace(TRACE_EXIT, "%s: %p", __func__, server); return server; error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return NULL; } SmlDsServerType smlDsServerGetServerType(SmlDsServer *server) { smlAssert(server); return server->servertype; } void smlDsServerFree(SmlDsServer *server) { smlTrace(TRACE_ENTRY, "%s(%p)", __func__, server); smlAssert(server); if (server->location) smlLocationUnref(server->location); if (server->target) smlLocationUnref(server->target); if (server->contenttype) smlSafeCFree(&(server->contenttype)); smlSafeFree((gpointer *)&server); smlTrace(TRACE_EXIT, "%s", __func__); } /** @brief Registers a callback that will get called once a client connects * * This function will get called once a client connects to our ds server (which means * that it sent a alert to our server). You can then use the smlDsServerRequestAlert() function * to get the alert * * @param server The DS server * @param callback The callback that will receive the alert * @param userdata The userdata that will be passed to the alert */ void smlDsServerSetConnectCallback(SmlDsServer *server, SmlDsSessionConnectCb callback, void *userdata) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, server, callback, userdata); smlAssert(server); server->connectCallback = callback; server->connectCallbackUserdata = userdata; smlTrace(TRACE_EXIT, "%s", __func__); } void smlDsServerSetSanCallback(SmlDsServer *server, SmlDsServerSanCb callback, void *userdata) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, server, callback, userdata); smlAssert(server); smlAssert(server->servertype == SML_DS_CLIENT); server->sanCallback = callback; server->sanCallbackUserdata = userdata; smlTrace(TRACE_EXIT, "%s", __func__); } void smlDsServerSetSanSessionCallback(SmlDsServer *server, SmlDsServerSanSessionCb callback, void *userdata) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, server, callback, userdata); smlAssert(server); smlAssert(server->servertype == SML_DS_CLIENT); server->sanSessionCallback = callback; server->sanSessionCallbackUserdata = userdata; smlTrace(TRACE_EXIT, "%s", __func__); } const char *smlDsServerGetLocation(SmlDsServer *server) { smlAssert(server); if (server->location) return server->location->locURI; return NULL; } const char *smlDsServerGetContentType(SmlDsServer *server) { smlAssert(server); return server->contenttype; } SmlBool smlDsServerAddSan(SmlDsServer *server, SmlNotification *san, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, server, san, error); smlAssert(server); smlAssert(san); CHECK_ERROR_REF if (!smlNotificationNewAlert(san, SML_ALERT_TWO_WAY_BY_SERVER, server->contenttype, smlLocationGetURI(server->location), error)) goto error; smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return FALSE; } SmlDsSession *smlDsServerRecvAlert(SmlDsServer *server, SmlSession *session, SmlCommand *cmd) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, server, session, cmd); SmlError *error = NULL; SmlDsSession *dsession = smlDsSessionNew(server, session, &error); if (!dsession) goto error; smlDsSessionRecvAlert(session, cmd, dsession); if (server->connectCallback) server->connectCallback(dsession, server->connectCallbackUserdata); smlDsSessionUnref(dsession); smlTrace(TRACE_EXIT, "%s", __func__); return dsession; error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(&error)); smlErrorDeref(&error); return NULL; } SmlDsSession *smlDsServerSendAlert(SmlDsServer *server, SmlSession *session, SmlAlertType type, const char *last, const char *next, SmlStatusReplyCb callback, void *userdata, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %i, %s, %s, %p)", __func__, server, session, type, VA_STRING(last), VA_STRING(next), error); smlAssert(server); smlAssert(session); CHECK_ERROR_REF SmlDsSession *dsession = smlDsSessionNew(server, session, error); if (!dsession) goto error; if (server->manager) { if (!smlManagerObjectRegister(server->manager, SML_COMMAND_TYPE_SYNC, session, server->location, NULL, NULL, smlDsSessionRecvSync, smlDsSessionRecvChange, dsession, error)) goto error_free_dsession; if (!smlManagerObjectRegister(server->manager, SML_COMMAND_TYPE_MAP, session, server->location, NULL, NULL, smlDsSessionRecvMap, NULL, dsession, error)) goto error_free_dsession; if (!smlManagerObjectRegister(server->manager, SML_COMMAND_TYPE_ALERT, session, server->location, NULL, NULL, smlDsSessionRecvAlert, NULL, dsession, error)) goto error_free_dsession; } if (!smlDsSessionSendAlert(dsession, type, last, next, callback, userdata, error)) goto error_free_dsession; smlTrace(TRACE_EXIT, "%s", __func__); return dsession; error_free_dsession: smlSafeFree((gpointer *)&dsession); error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return NULL; } SmlDsSession *smlDsSessionNew(SmlDsServer *server, SmlSession *session, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, server, session, error); smlAssert(server); CHECK_ERROR_REF SmlDsSession *dsession = smlTryMalloc0(sizeof(SmlDsSession), error); if (!dsession) goto error; dsession->server = server; dsession->session = session; dsession->write_lock = g_mutex_new(); dsession->lock = g_mutex_new(); dsession->syncReply = SML_ERROR_UNKNOWN; dsession->refCount = 1; if (server->servertype == SML_DS_CLIENT) { dsession->target = server->target; smlLocationRef(dsession->target); } dsession->location = server->location; smlLocationRef(dsession->location); dsession->pendingMapsLock = g_mutex_new(); smlTrace(TRACE_EXIT, "%s: %p", __func__, dsession); return dsession; error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return NULL; } SmlDsSession *smlDsSessionRef(SmlDsSession *dsession) { smlTrace(TRACE_ENTRY, "%s(%p)", __func__, dsession); smlAssert(dsession); g_atomic_int_inc(&(dsession->refCount)); smlTrace(TRACE_EXIT, "%s: New refcount: %i", __func__, dsession->refCount); return dsession; } void smlDsSessionUnref(SmlDsSession *dsession) { smlTrace(TRACE_ENTRY, "%s(%p)", __func__, dsession); smlAssert(dsession); if (g_atomic_int_dec_and_test(&(dsession->refCount))) { smlTrace(TRACE_INTERNAL, "%s: Refcount == 0!", __func__); if (dsession->target) smlLocationUnref(dsession->target); if (dsession->location) smlLocationUnref(dsession->location); if (dsession->alertCommand) smlCommandUnref(dsession->alertCommand); while (dsession->recvSync) { SmlCommand *cmd = dsession->recvSync->data; smlCommandUnref(cmd); dsession->recvSync = g_list_delete_link(dsession->recvSync, dsession->recvSync); } while (dsession->recvChanges) { SmlCommand *cmd = dsession->recvChanges->data; smlCommandUnref(cmd); dsession->recvChanges = g_list_delete_link(dsession->recvChanges, dsession->recvChanges); } if (dsession->syncCommand) smlCommandUnref(dsession->syncCommand); if (!g_mutex_trylock(dsession->pendingMapsLock)) { smlTrace(TRACE_ERROR, "%s: somebody still uses this object", __func__); g_mutex_lock(dsession->pendingMapsLock); } while (dsession->pendingMaps) { SmlWriteContext *ctx = dsession->pendingMaps->data; _write_context_free(ctx); dsession->pendingMaps = g_list_delete_link(dsession->pendingMaps, dsession->pendingMaps); } g_mutex_unlock(dsession->pendingMapsLock); g_mutex_free(dsession->pendingMapsLock); while (dsession->mapItems) { SmlMapItem *item = dsession->mapItems->data; smlMapItemUnref(item); dsession->mapItems = g_list_delete_link(dsession->mapItems, dsession->mapItems); } if (dsession->lock) g_mutex_free(dsession->lock); if (dsession->write_lock) g_mutex_free(dsession->write_lock); smlSafeFree((gpointer *)&dsession); } smlTrace(TRACE_EXIT, "%s", __func__); } void smlDsSessionDispatch(SmlDsSession *dsession) { smlTrace(TRACE_ENTRY, "%s(%p)", __func__, dsession); SmlError *error = NULL; SmlStatus *reply = NULL; /* A dispatch function should never block on a * locked resource. This is like a busy wait * because the thread is not available for this * time which can block the whole system if two * dispatchers use the same thread. */ if (!g_mutex_trylock(dsession->lock)) { smlTrace(TRACE_EXIT, "%s - DsSession is already locked", __func__); return; } smlTrace(TRACE_INTERNAL, "%s - locked DsSession successfully", __func__); if (dsession->alertCommand && dsession->recvAlertCallback) { smlTrace(TRACE_INTERNAL, "%s: Dispatching alert", __func__); SmlErrorType type = SML_NO_ERROR; if (!dsession->recvAlertCallback(dsession, dsession->alertCommand->private.alert.type, dsession->alertCommand->private.alert.anchor->last, dsession->alertCommand->private.alert.anchor->next, dsession->recvAlertCallbackUserdata)) type = SML_ERROR_REQUIRE_REFRESH; dsession->recvAlertCallback = NULL; reply = smlCommandNewReply(dsession->alertCommand, type, &error); if (!reply) goto error; if (!smlSessionSendReply(dsession->session, reply, &error)) goto error; smlStatusUnref(reply); smlCommandUnref(dsession->alertCommand); dsession->alertCommand = NULL; /* unlock the final event at the manager * * If this is called from a test case then the datastore * is sometimes not registered at a SmlManager. */ if (dsession->server->manager && dsession->finalLock) { dsession->finalLock = FALSE; smlManagerSessionFinalLockUnref(dsession->server->manager, dsession->session); } } else if (dsession->recvSync && dsession->recvSyncCallback) { smlTrace(TRACE_INTERNAL, "%s: Dispatching sync", __func__); dsession->recvSyncCallback(dsession, ((SmlCommand *)(dsession->recvSync->data))->private.sync.numChanged, dsession->recvSyncCallbackUserdata); dsession->recvSyncCallback = NULL; while (dsession->recvSync) { SmlCommand *cmd = dsession->recvSync->data; smlTrace(TRACE_INTERNAL, "%s: answering sync command with cmdRef %i and msgRef %i", __func__, cmd->cmdID, cmd->msgID); reply = smlCommandNewReply(cmd, SML_NO_ERROR, &error); if (!reply) goto error; if (!smlSessionSendReply(dsession->session, reply, &error)) goto error; smlStatusUnref(reply); smlCommandUnref(cmd); dsession->recvSync = g_list_delete_link(dsession->recvSync, dsession->recvSync); } dsession->syncReply = SML_NO_ERROR; if (!dsession->recvChanges) { /* There are no changes. */ /* ... do some fancy callback. Some applications will love it ;) */ if (dsession->recvEventCallback) { dsession->recvEventCallback(dsession, SML_DS_EVENT_GOTCHANGES, dsession->recvEventCallbackUserdata); smlTrace(TRACE_INTERNAL, "%s: recvEventCallback no changes in recvSync callback", __func__); } /* unlock the final event at the manager * * If this is called from a test case then the datastore * is sometimes not registered at a SmlManager. */ if (dsession->server->manager && dsession->finalLock) { dsession->finalLock = FALSE; smlManagerSessionFinalLockUnref(dsession->server->manager, dsession->session); } smlTrace(TRACE_INTERNAL, "%s: final handling done", __func__); } } else if (dsession->recvChanges && dsession->changesCallback) { smlTrace(TRACE_INTERNAL, "%s: Dispatching changes", __func__); while (dsession->recvChanges) { SmlCommand *cmd = dsession->recvChanges->data; if (cmd) { if (!cmd->private.change.items || !g_list_length(cmd->private.change.items)) { smlErrorSet(&error, SML_ERROR_GENERIC, "No items found in command."); goto error; } /* All items handled at once because libsyncml * only supports one status code for all items. * So one failed item means that the complete * command is aborted. */ guint i; for (i=0; i < g_list_length(cmd->private.change.items); i++) { SmlItem *item = g_list_nth_data(cmd->private.change.items, i); if (!item) { smlErrorSet(&error, SML_ERROR_GENERIC, "Item %i of the command's item list is NULL.", i); goto error; } /* We'd rather use the target of the change since it already the mapped * uid (if we are a client for example). If it is not given we use the * source uri. This has then to be translated by the sync engine of course */ if ((!item->source && !item->target)) { smlErrorSet(&error, SML_ERROR_GENERIC, "Cannot determine UID because source an target are missing on item %i.", i); goto error; } char *data = NULL; unsigned int size = 0; if (!smlItemStealData(item, &data, &size, &error)) goto error; if (!dsession->changesCallback(dsession, cmd->private.change.type, item->target ? item->target->locURI : item->source->locURI, data, size, item->contenttype, dsession->changesCallbackUserdata, &error)) goto error; } if (cmd->private.change.type == SML_CHANGE_ADD) reply = smlCommandNewReply(cmd, SML_ITEM_ADDED, &error); else reply = smlCommandNewReply(cmd, SML_NO_ERROR, &error); if (!reply) goto error; if (!smlSessionSendReply(dsession->session, reply, &error)) goto error; smlStatusUnref(reply); smlCommandUnref(cmd); } dsession->recvChanges = g_list_delete_link(dsession->recvChanges, dsession->recvChanges); } // Now there are no more changes... do some fancy callback. Some applications will love it ;) if (dsession->recvEventCallback) { dsession->recvEventCallback(dsession, SML_DS_EVENT_GOTCHANGES, dsession->recvEventCallbackUserdata); smlTrace(TRACE_INTERNAL, "%s: recvEventCallback all changes sent in recvChanges callback", __func__); } /* unlock the final event at the manager * * If this is called from a test case then the datastore * is sometimes not registered at a SmlManager. */ if (dsession->server->manager) { dsession->finalLock = FALSE; smlManagerSessionFinalLockUnref(dsession->server->manager, dsession->session); } else smlTrace(TRACE_INTERNAL, "%s - no manager so should be a test", __func__); } else { smlTrace(TRACE_INTERNAL, "%s: recvChanges: %p changesCallback: %p", __func__, dsession->recvChanges, dsession->changesCallback); } smlTrace(TRACE_EXIT, "%s()", __func__); g_mutex_unlock(dsession->lock); return; error: if (reply) smlStatusUnref(reply); g_mutex_unlock(dsession->lock); smlTrace(TRACE_EXIT_ERROR, "%s: Unable to dispatch: %s", __func__, smlErrorPrint(&error)); smlErrorDeref(&error); } SmlBool smlDsSessionCheck(SmlDsSession *dsession) { if ((dsession->alertCommand && dsession->recvAlertCallback) || \ (dsession->recvSync && dsession->recvSyncCallback) || \ (dsession->recvChanges && dsession->changesCallback)) return TRUE; return FALSE; } void smlDsSessionRecvAlert(SmlSession *session, SmlCommand *cmd, void *userdata) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, session, cmd, userdata); SmlDsSession *dsession = userdata; SmlError *error = NULL; smlAssert(dsession->location); g_mutex_lock(dsession->lock); if (!cmd->target || !cmd->source) { SmlStatus *reply = smlCommandNewReply(cmd, SML_ERROR_BAD_REQUEST, &error); if (!reply) goto error; if (!smlSessionSendReply(session, reply, &error)) { smlStatusUnref(reply); goto error; } smlStatusUnref(reply); smlTrace(TRACE_EXIT, "%s: Alert had no target or source", __func__); return; } if (!smlLocationCompare(NULL, dsession->location, NULL, cmd->target)) { SmlStatus *reply = smlCommandNewReply(cmd, SML_ERROR_NOT_FOUND, &error); if (!reply) goto error; if (!smlSessionSendReply(session, reply, &error)) { smlStatusUnref(reply); goto error; } smlStatusUnref(reply); smlTrace(TRACE_EXIT, "%s: Alert does not match our location", __func__); return; } smlCommandRef(cmd); if (!dsession->target) { dsession->target = cmd->source; smlLocationRef(cmd->source); } dsession->alertCommand = cmd; /* Lock the final event at the manager. * * If this is called from a test case then the datastore * is sometimes not registered at a SmlManager. */ if (dsession->server->manager) { smlManagerSessionFinalLockRef(dsession->server->manager, session); dsession->finalLock = TRUE; } else smlTrace(TRACE_INTERNAL, "%s - no manager so should be a test", __func__); g_mutex_unlock(dsession->lock); smlTrace(TRACE_EXIT, "%s", __func__); return; error: g_mutex_unlock(dsession->lock); smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(&error)); smlErrorDeref(&error); return; } void smlDsSessionRecvSync(SmlSession *session, SmlCommand *cmd, void *userdata) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, session, cmd, userdata); SmlDsSession *dsession = userdata; SmlError *error = NULL; /* Create a write lock on the complete DsSession object to avoid race * conditions. If the write lock is already present then this is the * end of the sync block and the write lock must only be removed. */ if (g_mutex_trylock(dsession->write_lock)) { /* write lock succeeded so lock the complete DsSession */ g_mutex_lock(dsession->lock); smlTrace(TRACE_INTERNAL, "%s - write lock enabled", __func__); /* Lock the final event at the manager. * * If this is called from a test case then the datastore * is sometimes not registered at a SmlManager. */ if (dsession->server->manager) { smlManagerSessionFinalLockRef(dsession->server->manager, session); dsession->finalLock = TRUE; dsession->emptySync = TRUE; } else smlTrace(TRACE_INTERNAL, "%s - no manager so should be a test", __func__); } else { /* detected an old write lock so this is the closing sync call */ if (dsession->finalLock && dsession->emptySync) { smlTrace(TRACE_INTERNAL, "%s - empty sync of moreData ?", __func__); dsession->finalLock = FALSE; smlManagerSessionFinalLockUnref(dsession->server->manager, session); } g_mutex_unlock(dsession->lock); g_mutex_unlock(dsession->write_lock); smlTrace(TRACE_EXIT, "%s - removed write lock", __func__); return; } if (dsession->syncReply == SML_ERROR_UNKNOWN) { smlTrace(TRACE_INTERNAL, "%s: Storing sync command with cmdRef %i and msgRef %i", __func__, cmd->cmdID, cmd->msgID); smlCommandRef(cmd); dsession->recvSync = g_list_append(dsession->recvSync, cmd); } else { smlTrace(TRACE_INTERNAL, "%s: Using stored sync reply on cmd with cmdRef %i and msgRef %i", __func__, cmd->cmdID, cmd->msgID); SmlStatus *reply = smlCommandNewReply(cmd, dsession->syncReply, &error); if (!reply) goto error; if (!smlSessionSendReply(dsession->session, reply, &error)) goto error; smlStatusUnref(reply); } smlTrace(TRACE_EXIT, "%s", __func__); return; error: g_mutex_unlock(dsession->lock); g_mutex_unlock(dsession->write_lock); smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(&error)); smlErrorDeref(&error); } void smlDsSessionRecvChange(SmlSession *session, SmlCommand *cmd, void *userdata) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, session, cmd, userdata); SmlDsSession *dsession = userdata; /* It is not necessary to lock the DsSesion object * because RecvSync already enabled a global write_lock. */ dsession->recvChanges = g_list_append(dsession->recvChanges, cmd); smlCommandRef(cmd); /* This is important for fast and consistent final signalling. */ dsession->emptySync = FALSE; smlTrace(TRACE_EXIT, "%s", __func__); } void smlDsSessionRecvMap(SmlSession *session, SmlCommand *cmd, void *userdata) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, session, cmd, userdata); SmlDsSession *dsession = userdata; SmlError *error = NULL; g_mutex_lock(dsession->lock); SmlStatus *reply = smlCommandNewReply(cmd, SML_NO_ERROR, &error); if (!reply) goto error; if (!smlSessionSendReply(session, reply, &error)) goto error; smlStatusUnref(reply); GList *m = NULL; for (m = cmd->private.map.items; m; m = m->next) { SmlMapItem *item = m->data; if (dsession->recvMappingCallback) { dsession->recvMappingCallback( dsession, item->target, item->source, dsession->recvMappingCallbackUserdata); } else { SmlWriteContext *ctx = _write_context_find(dsession, item->target->locURI, SML_CHANGE_ADD); if (ctx) { ctx->newuid = g_strdup(item->source->locURI); _write_context_dispatch(dsession, ctx); } else { smlTrace(TRACE_ERROR, "%s: Unknown map ... %s => %s", __func__, VA_STRING(item->target->locURI), VA_STRING(item->source->locURI)); } } } g_mutex_unlock(dsession->lock); smlTrace(TRACE_EXIT, "%s", __func__); return; error: g_mutex_unlock(dsession->lock); smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(&error)); smlErrorDeref(&error); } /** @brief Gets a already received alert * * This function will get a already received alert or register a callback that will be * called once the alert is received. If the alert already was waiting the callback is * called immediatly. * * @param server The DS server * @param callback The callback that will receive the alert * @param userdata The userdata that will be passed to the alert * @param error A pointer to a error struct * @returns TRUE if the call was successful, FALSE otherwise */ void smlDsSessionGetAlert(SmlDsSession *dsession, SmlDsSessionAlertCb callback, void *userdata) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, dsession, callback, userdata); smlAssert(dsession); smlAssert(callback); dsession->recvAlertCallback = callback; dsession->recvAlertCallbackUserdata = userdata; smlDsSessionDispatch(dsession); smlTrace(TRACE_EXIT, "%s", __func__); } /** @brief Sends the alert to the remote side * * This function will get a already received alert or register a callback that will be * called once the alert is received. If the alert already was waiting the callback is * called immediatly. * * @param server The DS server * @param callback The callback that will receive the alert * @param userdata The userdata that will be passed to the alert * @param error A pointer to a error struct * @returns TRUE if the call was successful, FALSE otherwise */ SmlBool smlDsSessionSendAlert(SmlDsSession *dsession, SmlAlertType type, const char *last, const char *next, SmlStatusReplyCb callback, void *userdata, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %i, %s, %s, %p)", __func__, dsession, type, VA_STRING(last), VA_STRING(next), error); smlAssert(dsession); CHECK_ERROR_REF SmlCommand *alert = smlCommandNewAlert(type, dsession->target, dsession->location, next, last, NULL, error); if (!alert) goto error; dsession->sentAlertCallback = callback; dsession->sentAlertCallbackUserdata = userdata; if (!smlSessionSendCommand(dsession->session, alert, NULL, _alert_reply, dsession, error)) goto error; smlCommandUnref(alert); smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return FALSE; } void smlDsSessionGetMapping( SmlDsSession *dsession, SmlDsSessionMapCb mapCallback, void *userdata) { smlTrace(TRACE_ENTRY, "%s", __func__); dsession->recvMappingCallback = mapCallback; dsession->recvMappingCallbackUserdata = userdata; smlTrace(TRACE_EXIT, "%s", __func__); } /** @brief Gets a already received sync command * * This function will get a already received sync command or register a callback that will be * called once the sync is received. If the sync already was waiting the callback is * called immediatly. The read callback is called with every subcommand of the sync. * * @param server The DS server * @param chgCallback The callback that will receive all the changes (subcommands of sync) * @param syncCallback The callback that will receive the sync command * @param userdata The userdata that will be passed to the sync and change callbacks * @param error A pointer to a error struct * @returns TRUE if the call was successful, FALSE otherwise */ void smlDsSessionGetChanges(SmlDsSession *dsession, SmlDsSessionChangesCb chgCallback, void *userdata) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, dsession, chgCallback, userdata); smlAssert(dsession); smlAssert(chgCallback); dsession->changesCallback = chgCallback; dsession->changesCallbackUserdata = userdata; smlDsSessionDispatch(dsession); smlTrace(TRACE_EXIT, "%s", __func__); } void smlDsSessionGetSync(SmlDsSession *dsession, SmlDsSessionSyncCb syncCallback, void *userdata) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, dsession, syncCallback, userdata); smlAssert(dsession); smlAssert(syncCallback); dsession->recvSyncCallback = syncCallback; dsession->recvSyncCallbackUserdata = userdata; smlDsSessionDispatch(dsession); smlTrace(TRACE_EXIT, "%s", __func__); } void smlDsSessionGetEvent(SmlDsSession *dsession, SmlDsSessionEventCb eventCallback, void *userdata) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, dsession, eventCallback, userdata); smlAssert(dsession); smlAssert(eventCallback); dsession->recvEventCallback = eventCallback; dsession->recvEventCallbackUserdata = userdata; smlDsSessionDispatch(dsession); smlTrace(TRACE_EXIT, "%s", __func__); } /** @brief Start the sync command to send to the other side * * This function will start the sync command with which the changes will be sent to the other side. * After this command you can start to queue the changes. After you are done queueing changes, you * have to end the sync command with smlDsServerCloseSync(). * * @param server The DS server * @param callback The callback that will the answer to the sync command * @param userdata The userdata that will be passed to the alert * @param error A pointer to a error struct * @returns TRUE if the call was successful, FALSE otherwise */ SmlBool smlDsSessionSendSync(SmlDsSession *dsession, unsigned int num_changes, SmlStatusReplyCb callback, void *userdata, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %i, %p, %p, %p)", __func__, dsession, num_changes, callback, userdata, error); smlAssert(dsession); CHECK_ERROR_REF if (dsession->syncCommand) { smlErrorSet(error, SML_ERROR_GENERIC, "There already was a sync command started"); goto error; } dsession->sentSyncCallback = callback; dsession->sentSyncCallbackUserdata = userdata; dsession->syncCommand = smlCommandNewSync(dsession->target, dsession->location, num_changes, error); if (!dsession->syncCommand) goto error; if (!smlSessionStartCommand(dsession->session, dsession->syncCommand, NULL, _sync_reply, dsession, error)) goto error; smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return FALSE; } //Send a change to the remote side SmlBool smlDsSessionQueueChange(SmlDsSession *dsession, SmlChangeType type, const char *uid, const char *data, unsigned int size, const char *contenttype, SmlDsSessionWriteCb callback, void *userdata, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %i, %s, %p, %i, %s, %p, %p, %p)", __func__, dsession, type, VA_STRING(uid), data, size, VA_STRING(contenttype), callback, userdata, error); smlAssert(dsession); CHECK_ERROR_REF if (!dsession->syncCommand) { smlErrorSet(error, SML_ERROR_GENERIC, "You have to start a sync command first"); goto error; } SmlCommand *cmd = smlCommandNewChange(type, uid, data, size, contenttype, error); if (!cmd) goto error; SmlWriteContext *ctx = smlTryMalloc0(sizeof(SmlWriteContext), error); if (!ctx) goto error_free_cmd; ctx->callback = callback; ctx->userdata = userdata; ctx->uid = g_strdup(uid); ctx->type = type; ctx->session = dsession; g_mutex_lock(dsession->pendingMapsLock); dsession->pendingMaps = g_list_append(dsession->pendingMaps, ctx); g_mutex_unlock(dsession->pendingMapsLock); if (!smlSessionSendCommand(dsession->session, cmd, dsession->syncCommand, _change_reply, ctx, error)) goto error_free_ctx; smlCommandUnref(cmd); smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error_free_ctx: smlSafeCFree(&(ctx->uid)); smlSafeFree((gpointer *)&ctx); error_free_cmd: smlCommandUnref(cmd); error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return FALSE; } /** @brief Closes the sync command * * @param server The DS server * @param error A pointer to a error struct * @returns TRUE if the call was successful, FALSE otherwise */ SmlBool smlDsSessionCloseSync(SmlDsSession *dsession, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p)", __func__, dsession, error); smlAssert(dsession); CHECK_ERROR_REF if (!dsession->syncCommand) { smlErrorSet(error, SML_ERROR_GENERIC, "There already was a sync command started"); goto error; } if (!smlSessionEndCommand(dsession->session, NULL, error)) goto error; smlCommandUnref(dsession->syncCommand); dsession->syncCommand = NULL; smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return FALSE; } SmlBool smlDsSessionQueueMap(SmlDsSession *dsession, const char *uid, const char *newuid, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %s, %s, %p)", __func__, dsession, VA_STRING(uid), VA_STRING(newuid), error); smlAssert(dsession); CHECK_ERROR_REF SmlMapItem *item = smlMapItemNew(uid, newuid, error); if (!item) goto error; dsession->mapItems = g_list_append(dsession->mapItems, item); smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return FALSE; } /** @brief Closes the map command * * This will tell the ds server that you are not going to queue * any more map commands. * * @param server The DS server * @param error A pointer to a error struct * @returns TRUE if the call was successful, FALSE otherwise */ SmlBool smlDsSessionCloseMap(SmlDsSession *dsession, SmlStatusReplyCb callback, void *userdata, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p, %p)", __func__, dsession, callback, userdata, error); smlAssert(dsession); CHECK_ERROR_REF if (!dsession->mapItems) { smlTrace(TRACE_EXIT, "%s: No mapitems", __func__); return TRUE; } SmlCommand *cmd = smlCommandNewMap(dsession->server->target, dsession->server->location, error); if (!cmd) goto error; while (dsession->mapItems) { SmlMapItem *item = dsession->mapItems->data; if (!smlCommandAddMapItem(cmd, item, error)) goto error_free_cmd; smlMapItemUnref(item); dsession->mapItems = g_list_remove(dsession->mapItems, item); } if (!smlSessionSendCommand(dsession->session, cmd, NULL, callback, userdata, error)) goto error_free_cmd; smlCommandUnref(cmd); smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error_free_cmd: smlCommandUnref(cmd); error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return FALSE; } const char *smlDsSessionGetLocation(SmlDsSession *dsession) { smlAssert(dsession); return smlDsServerGetLocation(dsession->server); } SmlDsServer *smlDsSessionGetServer(SmlDsSession *dsession) { smlAssert(dsession); return dsession->server; } const char *smlDsSessionGetContentType(SmlDsSession *dsession) { smlAssert(dsession); return smlDsServerGetContentType(dsession->server); } static void _recv_manager_alert(SmlSession *session, SmlCommand *cmd, void *userdata) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, session, cmd, userdata); SmlDsServer *server = userdata; SmlError *error = NULL; SmlDsSession *dsession = smlDsServerRecvAlert(server, session, cmd); if (!dsession) goto error; if (!smlManagerObjectRegister(server->manager, SML_COMMAND_TYPE_SYNC, session, server->location, NULL, NULL, smlDsSessionRecvSync, smlDsSessionRecvChange, dsession, &error)) goto error_free_dsession; if (!smlManagerObjectRegister(server->manager, SML_COMMAND_TYPE_MAP, session, server->location, NULL, NULL, smlDsSessionRecvMap, NULL, dsession, &error)) goto error_free_dsession; smlTrace(TRACE_EXIT, "%s", __func__); return; error_free_dsession: smlSafeFree((gpointer *)&dsession); error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(&error)); if (error) smlErrorDeref(&error); } static void _recv_manager_san(SmlSession *session, SmlCommand *cmd, void *userdata) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, session, cmd, userdata); SmlDsServer *server = userdata; SmlError *error = NULL; /* ensure that the session is in client mode */ session->sessionType = SML_SESSION_TYPE_CLIENT; /* fix target */ smlLocationUnref(server->target); server->target = cmd->source; smlLocationRef(server->target); /* handle the SAN */ if (server->sanSessionCallback) { SmlErrorType type = server->sanSessionCallback( server, session, cmd->private.alert.type, server->sanSessionCallbackUserdata); SmlStatus *reply = smlCommandNewReply(cmd, type, &error); if (!reply) goto error; if (!smlSessionSendReply(session, reply, &error)) goto error; smlStatusUnref(reply); } else if (server->sanCallback) { SmlErrorType type = server->sanCallback(server, cmd->private.alert.type, server->sanCallbackUserdata); SmlStatus *reply = smlCommandNewReply(cmd, type, &error); if (!reply) goto error; if (!smlSessionSendReply(session, reply, &error)) goto error; smlStatusUnref(reply); } else { smlTrace(TRACE_INTERNAL, "%s: SAN ignored", __func__); SmlStatus *reply = smlCommandNewReply(cmd, SML_ERROR_NOT_IMPLEMENTED, &error); if (!reply) goto error; if (!smlSessionSendReply(session, reply, &error)) goto error; smlStatusUnref(reply); } smlTrace(TRACE_EXIT, "%s", __func__); return; error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(&error)); if (error) smlErrorDeref(&error); } SmlBool smlDsServerRegister(SmlDsServer *server, SmlManager *manager, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, server, manager, error); smlAssert(server); smlAssert(manager); CHECK_ERROR_REF if (!smlManagerObjectRegister(manager, SML_COMMAND_TYPE_ALERT, NULL, server->location, NULL, NULL, _recv_manager_alert, NULL, server, error)) goto error; if (!smlManagerObjectRegister(manager, SML_COMMAND_TYPE_ALERT, NULL, NULL, NULL,server->contenttype, _recv_manager_san, NULL, server, error)) goto error; server->manager = manager; smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return FALSE; } SmlLocation *smlDsSessionGetTarget(SmlDsSession *dsession) { smlAssert(dsession); return dsession->target; } libsyncml-0.5.4/libsyncml/sml_command.c100644 1750 1750 45300 11211710410 20074 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2005 Armin Bauer * Copyright (C) 2008 Michael Bell * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include "syncml.h" #include "syncml_internals.h" #include "sml_parse_internals.h" #include "sml_command_internals.h" #include "sml_session_internals.h" #include "sml_elements_internals.h" #include "sml_error_internals.h" SmlCommandType smlCommandTypeFromString(const char *name, SmlError **error) { CHECK_ERROR_REF if (!name) return SML_COMMAND_TYPE_UNKNOWN; if (!strcmp(name, SML_ELEMENT_ALERT)) { return SML_COMMAND_TYPE_ALERT; } else if (!strcmp(name, SML_ELEMENT_SYNC)) { return SML_COMMAND_TYPE_SYNC; } else if (!strcmp(name, SML_ELEMENT_PUT)) { return SML_COMMAND_TYPE_PUT; } else if (!strcmp(name, SML_ELEMENT_SYNCHDR)) { return SML_COMMAND_TYPE_HEADER; } else if (!strcmp(name, SML_ELEMENT_ADD)) { return SML_COMMAND_TYPE_ADD; } else if (!strcmp(name, SML_ELEMENT_REPLACE)) { return SML_COMMAND_TYPE_REPLACE; } else if (!strcmp(name, SML_ELEMENT_MAP)) { return SML_COMMAND_TYPE_MAP; } else if (!strcmp(name, SML_ELEMENT_DELETE)) { return SML_COMMAND_TYPE_DELETE; } else if (!strcmp(name, SML_ELEMENT_RESULTS)) { return SML_COMMAND_TYPE_RESULTS; } else if (!strcmp(name, SML_ELEMENT_GET)) { return SML_COMMAND_TYPE_GET; } smlErrorSet(error, SML_ERROR_GENERIC, "Unknown command name \"%s\"", name); return SML_COMMAND_TYPE_UNKNOWN; } const char *smlCommandTypeToString(SmlCommandType type, SmlError **error) { CHECK_ERROR_REF switch (type) { case SML_COMMAND_TYPE_ALERT: return SML_ELEMENT_ALERT; case SML_COMMAND_TYPE_SYNC: return SML_ELEMENT_SYNC; case SML_COMMAND_TYPE_PUT: return SML_ELEMENT_PUT; case SML_COMMAND_TYPE_HEADER: return SML_ELEMENT_SYNCHDR; case SML_COMMAND_TYPE_ADD: return SML_ELEMENT_ADD; case SML_COMMAND_TYPE_REPLACE: return SML_ELEMENT_REPLACE; case SML_COMMAND_TYPE_DELETE: return SML_ELEMENT_DELETE; case SML_COMMAND_TYPE_MAP: return SML_ELEMENT_MAP; case SML_COMMAND_TYPE_GET: return SML_ELEMENT_GET; case SML_COMMAND_TYPE_RESULTS: return SML_ELEMENT_RESULTS; default: ; } smlErrorSet(error, SML_ERROR_GENERIC, "Unknown command type \"%i\"", type); return NULL; } SmlStatus *smlStatusNew(SmlErrorType data, unsigned int cmdref, unsigned int msgref, SmlLocation *sourceref, SmlLocation *targetref, SmlCommandType type, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%i, %i, %i, %p, %p, %i, %p)", __func__, data, cmdref, msgref, sourceref, targetref, type, error); CHECK_ERROR_REF SmlStatus *status = smlTryMalloc0(sizeof(SmlStatus), error); if (!status) goto error; status->refCount = 1; status->cmdRef = cmdref; status->msgRef = msgref; status->type = type; if (data != SML_ERROR_UNKNOWN) status->data = g_strdup_printf("%i", data); if (sourceref) { status->sourceRef = sourceref; smlLocationRef(sourceref); } if (targetref) { status->targetRef = targetref; smlLocationRef(targetref); } smlTrace(TRACE_EXIT, "%s: %p", __func__, status); return status; error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return NULL; } SmlStatus *smlStatusRef(SmlStatus *status) { smlTrace(TRACE_ENTRY, "%s(%p)", __func__, status); smlAssert(status); g_atomic_int_inc(&(status->refCount)); smlTrace(TRACE_EXIT, "%s: New refcount: %i", __func__, status->refCount); return status; } void smlStatusUnref(SmlStatus *status) { smlTrace(TRACE_ENTRY, "%s(%p)", __func__, status); smlAssert(status); if (g_atomic_int_dec_and_test(&(status->refCount))) { smlTrace(TRACE_INTERNAL, "%s: Refcount == 0!", __func__); if (status->sourceRef) smlLocationUnref(status->sourceRef); if (status->targetRef) smlLocationUnref(status->targetRef); if (status->data) smlSafeCFree(&(status->data)); if (status->anchor) smlAnchorFree(status->anchor); if (status->item) smlItemUnref(status->item); smlSafeFree((gpointer *)&status); } smlTrace(TRACE_EXIT, "%s", __func__); } SmlErrorType smlStatusGetCode(SmlStatus *status) { smlAssert(status); smlAssert(status->data); return atoi(status->data); } SmlErrorClass smlStatusGetClass(SmlStatus *status) { smlAssert(status); smlAssert(status->data); return (atoi(status->data) / 100); } SmlCommand *smlStatusGetResult(SmlStatus *status) { if (status->type == SML_COMMAND_TYPE_RESULTS) return status->result; return NULL; } SmlBool smlStatusIsResult(SmlStatus *status) { return status->type == SML_COMMAND_TYPE_RESULTS ? TRUE : FALSE; } SmlCommand *smlCommandNew(SmlCommandType type, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%i, %p)", __func__, type, error); CHECK_ERROR_REF SmlCommand *cmd = smlTryMalloc0(sizeof(SmlCommand), error); if (!cmd) goto error; cmd->refCount = 1; cmd->type = type; smlTrace(TRACE_EXIT, "%s: %p", __func__, cmd); return cmd; error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return NULL; } SmlStatus *smlCommandNewReply(const SmlCommand *cmd, SmlErrorType code, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %i, %p)", __func__, cmd, code, error); CHECK_ERROR_REF smlAssert(cmd); SmlStatus *reply = smlStatusNew(code, cmd->cmdID, cmd->msgID, cmd->source, cmd->target, cmd->type, error); if (!reply) goto error; switch (cmd->type) { case SML_COMMAND_TYPE_ALERT: if (cmd->private.alert.anchor) { reply->anchor = smlAnchorNew(NULL, cmd->private.alert.anchor->next, error); if (!reply->anchor) goto error; } break; default: ; } smlTrace(TRACE_EXIT, "%s: %p", __func__, reply); return reply; error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return NULL; } SmlCommand *smlCommandNewResult(SmlCommand *cmd, SmlLocation *source, char *data, unsigned int size, const char *contenttype, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p, %i, %s, %p)", __func__, cmd, source, data, size, VA_STRING(contenttype), error); CHECK_ERROR_REF smlAssert(cmd); SmlCommand *result = smlCommandNew(SML_COMMAND_TYPE_RESULTS, error); if (!result) goto error; result->private.results.status = smlStatusNew(SML_NO_ERROR, cmd->cmdID, cmd->msgID, cmd->source, cmd->target, SML_COMMAND_TYPE_RESULTS, error); if (!result->private.results.status) goto error_free_cmd; result->private.results.status->item = smlItemNewForData(data, size, error); smlSafeCFree(&data); if (!result->private.results.status->item) goto error_free_cmd; result->private.results.status->item->contenttype = g_strdup(contenttype); result->private.results.status->item->source = smlLocationClone(source, error); if (!result->private.results.status->item->source) goto error_free_cmd; smlTrace(TRACE_EXIT, "%s: %p", __func__, result); return result; error_free_cmd: smlCommandUnref(result); error: if (data) smlSafeCFree(&data); smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return NULL; } SmlCommand *smlCommandRef(SmlCommand *cmd) { smlTrace(TRACE_ENTRY, "%s(%p)", __func__, cmd); smlAssert(cmd); g_atomic_int_inc(&(cmd->refCount)); smlTrace(TRACE_EXIT, "%s: New refcount: %i", __func__, cmd->refCount); return cmd; } void smlCommandUnref(SmlCommand *cmd) { smlTrace(TRACE_ENTRY, "%s(%p)", __func__, cmd); smlAssert(cmd); if (g_atomic_int_dec_and_test(&(cmd->refCount))) { smlTrace(TRACE_INTERNAL, "%s: Refcount == 0!", __func__); if (cmd->parent) { cmd->parent->children = g_list_remove(cmd->parent->children, cmd); smlCommandUnref(cmd->parent); cmd->parent = NULL; } switch (cmd->type) { case SML_COMMAND_TYPE_UNKNOWN: case SML_COMMAND_TYPE_HEADER: case SML_COMMAND_TYPE_SYNC: break; case SML_COMMAND_TYPE_ALERT: if (cmd->private.alert.anchor) smlAnchorFree(cmd->private.alert.anchor); if (cmd->private.alert.contentType) smlSafeCFree(&(cmd->private.alert.contentType)); break; case SML_COMMAND_TYPE_PUT: case SML_COMMAND_TYPE_GET: if (cmd->private.access.type) smlSafeCFree(&(cmd->private.access.type)); if (cmd->private.access.item) smlItemUnref(cmd->private.access.item); break; case SML_COMMAND_TYPE_ADD: case SML_COMMAND_TYPE_REPLACE: case SML_COMMAND_TYPE_DELETE: if (cmd->private.change.items) { guint i; for (i = 0; i < g_list_length(cmd->private.change.items); i++) { SmlItem *item = g_list_nth_data(cmd->private.change.items, i); smlItemUnref(item); } g_list_free(cmd->private.change.items); } break; case SML_COMMAND_TYPE_MAP: while (cmd->private.map.items) { SmlMapItem *item = cmd->private.map.items->data; smlMapItemUnref(item); cmd->private.map.items = g_list_delete_link(cmd->private.map.items, cmd->private.map.items); } break; case SML_COMMAND_TYPE_RESULTS: if (cmd->private.results.status) smlStatusUnref(cmd->private.results.status); break; } if (cmd->target) smlLocationUnref(cmd->target); if (cmd->source) smlLocationUnref(cmd->source); smlSafeFree((gpointer *)&cmd); } smlTrace(TRACE_EXIT, "%s", __func__); } SmlCommand *smlCommandNewChange(SmlChangeType type, const char *uid, const char *data, unsigned int size, const char *contenttype, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%i, %s, %p, %i, %s, %p)", __func__, type, VA_STRING(uid), data, size, VA_STRING(contenttype), error); CHECK_ERROR_REF SmlCommand *cmd = NULL; switch (type) { case SML_CHANGE_ADD: cmd = smlCommandNew(SML_COMMAND_TYPE_ADD, error); break; case SML_CHANGE_REPLACE: cmd = smlCommandNew(SML_COMMAND_TYPE_REPLACE, error); break; case SML_CHANGE_DELETE: cmd = smlCommandNew(SML_COMMAND_TYPE_DELETE, error); break; default: smlErrorSet(error, SML_ERROR_GENERIC, "Unknown changetype"); } if (!cmd) goto error; SmlItem *item = smlItemNewForData(data, size, error); if (!item) goto error_free_cmd; cmd->private.change.items = g_list_append(NULL, item); if (!cmd->private.change.items) { smlItemUnref(item); goto error_free_cmd; } SmlLocation *loc = smlLocationNew(uid, NULL, error); if (!loc) goto error_free_cmd; /* The usage of target and source depends on the role of the * local peer. We cannot determine if the local peer is an * OMA DS client or server. This function is only used by * smlDsSessionQueueChange. So the correct usage of target * and source must be ensured by the XML assembler. */ item->source = loc; if (type != SML_CHANGE_ADD) { /* If this is an Add command then nobody knows * which ID the remote peer will be use for this item. */ smlLocationRef(loc); item->target = loc; } item->contenttype = g_strdup(contenttype); smlTrace(TRACE_EXIT, "%s: %p", __func__, cmd); return cmd; error_free_cmd: smlCommandUnref(cmd); error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return NULL; } /** Send a fragmented change. You can use this command to fragment a very large change into several * objects. * @param complete_size The overall size of the object. must be the sum over all partial_sizes * @param partial_size The size of this part. */ SmlCommand *smlCommandNewPartialChange(SmlChangeType type, const char *uid, const char *data, unsigned int complete_size, unsigned int partial_size, const char *contenttype, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%i, %s, %p, %i, %i, %s, %p)", __func__, type, VA_STRING(uid), data, complete_size, partial_size, VA_STRING(contenttype), error); CHECK_ERROR_REF SmlCommand *cmd = NULL; switch (type) { case SML_CHANGE_ADD: cmd = smlCommandNew(SML_COMMAND_TYPE_ADD, error); break; case SML_CHANGE_REPLACE: cmd = smlCommandNew(SML_COMMAND_TYPE_REPLACE, error); break; case SML_CHANGE_DELETE: cmd = smlCommandNew(SML_COMMAND_TYPE_DELETE, error); break; default: smlErrorSet(error, SML_ERROR_GENERIC, "Unknown changetype"); } if (!cmd) goto error; cmd->size = complete_size; SmlItem *item = smlItemNewForData(data, partial_size, error); if (!item) goto error_free_cmd; cmd->private.change.items = g_list_append(NULL, item); if (!cmd->private.change.items) { smlItemUnref(item); goto error_free_cmd; } SmlLocation *loc = smlLocationNew(uid, NULL, error); if (!loc) goto error_free_cmd; if (type != SML_CHANGE_ADD) item->target = loc; else item->source = loc; item->moreData = TRUE; item->contenttype = g_strdup(contenttype); smlTrace(TRACE_EXIT, "%s: %p", __func__, cmd); return cmd; error_free_cmd: smlCommandUnref(cmd); error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return NULL; } SmlCommand *smlCommandNewAlert(SmlAlertType type, SmlLocation *target, SmlLocation *source, const char *next, const char *last, const char *contenttype, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%i, %p, %p, %s, %s, %s, %p)", __func__, type, target, source, VA_STRING(next), VA_STRING(last), VA_STRING(contenttype), error); CHECK_ERROR_REF SmlCommand *cmd = smlCommandNew(SML_COMMAND_TYPE_ALERT, error); if (!cmd) goto error; if (target) { cmd->target = target; smlLocationRef(target); } if (source) { cmd->source = source; smlLocationRef(source); } /* A synchronization anchor makes only sense if it is not an * alert for the next part of an incomplete package (next * message alert) or SAN. */ if (type != SML_ALERT_NEXT_MESSAGE && type != SML_ALERT_TWO_WAY_BY_SERVER) { /* If this is a slow sync alert then it makes no sense * to send the last sync anchor because a slow sync is * only necessary if there was no earlier sync or * something goes wrong since then which means there is * no safe last anchor. */ if (type == SML_ALERT_SLOW_SYNC) { if (last) smlTrace(TRACE_INTERNAL, "%s: removing last anchor (%s) from slow sync alert", __func__, VA_STRING(last)); cmd->private.alert.anchor = smlAnchorNew(NULL, next, error); } else cmd->private.alert.anchor = smlAnchorNew(last, next, error); if (!cmd->private.alert.anchor) goto error; } cmd->private.alert.type = type; cmd->private.alert.contentType = g_strdup(contenttype); smlTrace(TRACE_EXIT, "%s: %p", __func__, cmd); return cmd; error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return NULL; } SmlCommand *smlCommandNewSync(SmlLocation *target, SmlLocation *source, unsigned int num_changes, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %i, %p)", __func__, target, source, num_changes, error); CHECK_ERROR_REF SmlCommand *cmd = smlCommandNew(SML_COMMAND_TYPE_SYNC, error); if (!cmd) goto error; cmd->target = target; smlLocationRef(target); cmd->source = source; smlLocationRef(source); cmd->private.sync.numChanged = num_changes; smlTrace(TRACE_EXIT, "%s: %p", __func__, cmd); return cmd; error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return NULL; } SmlCommand *smlCommandNewPut(SmlLocation *target, SmlLocation *source, const char *data, unsigned int size, const char *contenttype, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p, %i, %s, %p)", __func__, target, source, data, size, VA_STRING(contenttype), error); CHECK_ERROR_REF SmlCommand *cmd = smlCommandNew(SML_COMMAND_TYPE_PUT, error); if (!cmd) goto error; cmd->private.access.item = smlItemNewForData(data, size, error); if (!cmd->private.access.item) goto error_free_cmd; if (target) { cmd->target = target; smlLocationRef(target); smlItemSetTarget(cmd->private.access.item, cmd->target); } if (source) { cmd->source = source; smlLocationRef(source); smlItemSetSource(cmd->private.access.item, cmd->source); } cmd->private.access.item->contenttype = g_strdup(contenttype); smlTrace(TRACE_EXIT, "%s: %p", __func__, cmd); return cmd; error_free_cmd: smlCommandUnref(cmd); error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return NULL; } SmlCommand *smlCommandNewGet(SmlLocation *target, const char *contenttype, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %s, %p)", __func__, target, VA_STRING(contenttype), error); CHECK_ERROR_REF smlAssert(target); SmlCommand *cmd = smlCommandNew(SML_COMMAND_TYPE_GET, error); if (!cmd) goto error; cmd->private.access.item = smlItemNew(0, error); if (!cmd->private.access.item) goto error_free_cmd; cmd->target = target; smlLocationRef(target); smlItemSetTarget(cmd->private.access.item, cmd->target); cmd->private.access.item->contenttype = g_strdup(contenttype); smlTrace(TRACE_EXIT, "%s: %p", __func__, cmd); return cmd; error_free_cmd: smlCommandUnref(cmd); error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return NULL; } SmlCommand *smlCommandNewMap(SmlLocation *target, SmlLocation *source, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, target, source, error); CHECK_ERROR_REF SmlCommand *cmd = smlCommandNew(SML_COMMAND_TYPE_MAP, error); if (!cmd) goto error; cmd->target = target; smlLocationRef(target); cmd->source = source; smlLocationRef(source); smlTrace(TRACE_EXIT, "%s: %p", __func__, cmd); return cmd; error: smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); return NULL; } SmlBool smlCommandAddMapItem(SmlCommand *map, SmlMapItem *item, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, map, item, error); CHECK_ERROR_REF smlAssert(map); smlAssert(map->type == SML_COMMAND_TYPE_MAP); smlAssert(item); smlMapItemRef(item); map->private.map.items = g_list_append(map->private.map.items, item); smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; } SmlAlertType smlAlertTypeConvert(unsigned int id, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%u, %p)", __func__, id, error); CHECK_ERROR_REF if (id == 0 || id == 100 || (200 <= id && id <= 210) || (221 <= id && id <= 223)) { SmlAlertType result = (SmlAlertType) id; smlTrace(TRACE_EXIT, "%s - %u", __func__, result); return result; } else { smlErrorSet(error, SML_ERROR_GENERIC, "The unknown alert code %u was detected.", id); smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(error)); return SML_ALERT_UNKNOWN; } } libsyncml-0.5.4/tools/syncml-obex-client.c100644 1750 1750 63717 11211710410 20477 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2005 Armin Bauer * Copyright (C) 2008 Michael Bell * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include #include #include #include #include #include #include #include #include #include #include #ifdef ENABLE_OBEX #include #endif #include GList *sessions = NULL; SmlManager *manager = NULL; SmlDevInfAgent *agent = NULL; GMainLoop *loop = NULL; GList *dbLocations = NULL; GList *dbSlow = NULL; GList *dbTypes = NULL; SmlBool onlyInfo = FALSE; char *useTimeAnchor = NULL; unsigned int recvLimit = 65535; unsigned int maxObjSize = 3000000; static void usage (char *name, int ecode) { fprintf (stderr, "Usage: %s\n\n", name); fprintf (stderr, "--sync \t\tEmulate a database of the given type on the url.\n"); fprintf (stderr, "--slow-sync \tEmulate a database of the given type on the url and use slow-sync\n"); fprintf (stderr, "\t\t\t\tType should be a IANA registered mimetype or your own type. Common types are:\n"); fprintf (stderr, "\t\t\t\t\t\"text/x-vcard\" for contacts, \"text/x-vcalendar\" for events, \"text/plain\" for\n"); fprintf (stderr, "\t\t\t\t\tnotes and \"text/x-vMessage\" for SMS\n"); fprintf (stderr, "\t\t\t\tPath is the local name of the database. You can choose something there\n\n"); fprintf (stderr, "[-s ]\t\tConnect to the serial device\n\n"); fprintf (stderr, "[-u ]\t\t\tConnect to the given usb interface number\n"); fprintf (stderr, "\t\t\t\tIf you dont specify an id, all available interface will be listed\n\n"); fprintf (stderr, "[-b ]\t\tConnect to the given bluetooth device\n\n"); fprintf (stderr, "[--identifier ]\t\tUse the given identifier in the initial alert.\n"); fprintf (stderr, "\t\t\t\tSome devices require a special string here. Nokias for example require \"PC Suite\"\n\n"); fprintf (stderr, "[--version ]\t\tSet the given version. can be \"1.0\", \"1.1\" or \"1.2\"\n"); fprintf (stderr, "\t\t\t\tThe default is \"1.1\"\n\n"); fprintf (stderr, "--add \t\tAdd the file given in path to the device as the given type\n"); fprintf (stderr, "\t\t\t\tType should be a IANA registered mimetype or your own type. Common types are:\n"); fprintf (stderr, "\t\t\t\t\t\"text/x-vcard\" for contacts, \"text/x-vcalendar\" for events, \"text/plain\" for\n"); fprintf (stderr, "\t\t\t\t\tnotes and \"text/x-vMessage\" for SMS\n"); fprintf (stderr, "\t\t\t\tPath to the file to add. The file has to be a VCard, VCalendar, etc.\n\n"); fprintf (stderr, "[--wbxml]\t\t\tUse wbxml (WAP Binary XML) instead of plain xml\n\n"); fprintf (stderr, "[--recvLimit ]\t\t\tLimit the size of the receiving buffer to this size (default: %d)\n\n", recvLimit); fprintf (stderr, "[--maxObjSize ]\t\t\tThe maximum size of a object that we can receive (default: %d)\n\n", maxObjSize); fprintf (stderr, "[--useStringTable]\t\t\tUse wbxml string tables (Improves transmission size, but not supported by some phones)\n\n"); fprintf (stderr, "[--disableNumberOfChanges]\t\t\tDisable NumberOfChanges feature (the most new phones need it) (default: enabled)\n\n"); fprintf (stderr, "[--useTimeAnchor]\t\t\tUse timestamps as anchors (only for new Nokia series 40 phones)\n\n"); fprintf (stderr, "[--dumpinfo]\t\t\tPrint info about the phone at the end which can be sent to the developers\n"); exit (ecode); } static SmlBool _recv_change(SmlDsSession *dsession, SmlChangeType type, const char *uid, char *data, unsigned int size, const char *contenttype, void *userdata, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %i, %s, %p, %i, %s, %p, %p)", __func__, dsession, type, VA_STRING(uid), data, size, VA_STRING(contenttype), userdata, error); printf("Received a "); switch (type) { case SML_CHANGE_ADD: printf("added entry"); break; case SML_CHANGE_REPLACE: printf("modified entry"); break; case SML_CHANGE_DELETE: printf("deleted entry"); break; default: ; } printf(" %s of size %i and type %s\n", uid, size, contenttype); printf("\t\tData: %s\n", data); g_free(data); smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; } static void _recv_sync_reply(SmlSession *session, SmlStatus *status, void *userdata) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, session, status, userdata); printf("Received an reply to our Sync: %i\n", smlStatusGetCode(status)); smlTrace(TRACE_EXIT, "%s", __func__); } static void _add_reply(SmlDsSession *session, SmlStatus *status, const char *newuid, void *userdata) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %s, %p)", __func__, session, status, VA_STRING(newuid), userdata); printf("Received an reply to our Add command: %i. The new uid is %s\n", smlStatusGetCode(status), newuid); smlTrace(TRACE_EXIT, "%s", __func__); } GList *types = NULL; GList *paths = NULL; static void _recv_sync(SmlDsSession *dsession, unsigned int numchanges, void *userdata) { smlTrace(TRACE_ENTRY, "%s(%p, %i, %p)", __func__, dsession, numchanges, userdata); SmlError *error = NULL; printf("Going to receive %i changes\n", numchanges); GList *t = types; int num = 0; while (t) { if (!strcmp(smlDsSessionGetContentType(dsession), t->data)) num++; t = t->next; } if (!onlyInfo) { if (!smlDsSessionSendSync(dsession, num, _recv_sync_reply, NULL, &error)) goto error; t = types; GList *p = paths; while (t) { if (!strcmp(smlDsSessionGetContentType(dsession), t->data)) { char *filename = (char *)p->data; printf("Adding file %s\n", filename); GError *gerror = NULL; gsize sz = 0; char *data = NULL; GIOChannel *chan = g_io_channel_new_file(filename, "r", &gerror); if (!chan) { printf("Unable to open file %s for reading: %s\n", filename, gerror->message); } else { g_io_channel_set_encoding(chan, NULL, NULL); if (g_io_channel_read_to_end(chan, &data, &sz, &gerror) != G_IO_STATUS_NORMAL) { printf("Unable to read contents of file %s: %s\n", filename, gerror->message); } else { if (!smlDsSessionQueueChange(dsession, SML_CHANGE_ADD, filename, data, (int)sz, t->data, _add_reply, NULL, NULL)) printf("Unable to queue change\n"); } g_io_channel_shutdown(chan, FALSE, NULL); g_io_channel_unref(chan); } } t = t->next; p = p->next; } if (!smlDsSessionCloseSync(dsession, &error)) goto error; } smlTrace(TRACE_EXIT, "%s", __func__); error: smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(&error)); smlErrorDeref(&error); } static void _recv_alert_reply(SmlSession *session, SmlStatus *status, void *userdata) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, session, status, userdata); printf("Received an reply to our Alert\n"); smlTrace(TRACE_EXIT, "%s", __func__); } static SmlBool _recv_alert(SmlDsSession *dsession, SmlAlertType type, const char *last, const char *next, void *userdata) { smlTrace(TRACE_ENTRY, "%s(%p, %i, %s, %s, %p)", __func__, dsession, type, VA_STRING(last), VA_STRING(next), userdata); SmlError *error = NULL; const char *anchor = next; if (useTimeAnchor) anchor = useTimeAnchor; printf("Received an Alert for the DS Server at %s: Type: %i, Last %s, Next %s\n", smlDsSessionGetLocation(dsession), type, last, next); SmlBool slow = FALSE; int i = 0; for (i = 0; i < g_list_length(dbTypes); i++) { if (!strcmp(smlDsSessionGetContentType(dsession), g_list_nth_data(dbTypes, i))) { slow = GPOINTER_TO_INT(g_list_nth_data(dbSlow, i)); break; } } if (onlyInfo) { if (!smlDsSessionSendAlert(dsession, SML_ALERT_ONE_WAY_FROM_SERVER_BY_SERVER, last, next, _recv_alert_reply, NULL, &error)) goto error; } else if (slow && type != SML_ALERT_SLOW_SYNC) { /* SLOW-SYNC enforced by tool */ printf("Enforcing SLOW-SYNC\n"); if (!smlDsSessionSendAlert(dsession, SML_ALERT_SLOW_SYNC, NULL, anchor, _recv_alert_reply, NULL, &error)) goto error; smlTrace(TRACE_EXIT, "%s: Slow syncing", __func__); return FALSE; } else { /* We only support SLOW-SYNC and TWO-WAY-SYNC */ /* FIXME: Why do we use alert 206? */ /* FIXME: Usually 200 and 201 are the correct alert codes. */ /* FIXME: 206 is only useful in SANs */ if (type != SML_ALERT_SLOW_SYNC && type != SML_ALERT_TWO_WAY && type != SML_ALERT_TWO_WAY_BY_SERVER) { smlErrorSet(&error, SML_ERROR_GENERIC, "Unsupported alert type %d.", type); goto error; } if (!smlDsSessionSendAlert(dsession, type, last, anchor, _recv_alert_reply, NULL, &error)) goto error; } smlTrace(TRACE_EXIT, "%s", __func__); return TRUE; error: //smlDsSessionSetError(dsession, error); smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(&error)); smlErrorDeref(&error); return TRUE; } static void _ds_alert(SmlDsSession *dsession, void *userdata) { smlTrace(TRACE_ENTRY, "%s(%p, %p)", __func__, dsession, userdata); smlDsSessionGetAlert(dsession, _recv_alert, NULL); smlDsSessionGetSync(dsession, _recv_sync, NULL); smlDsSessionGetChanges(dsession, _recv_change, NULL); smlDsSessionRef(dsession); sessions = g_list_append(sessions, dsession); smlTrace(TRACE_EXIT, "%s", __func__); } SmlBool dumpinfo = FALSE; SmlBool useStringTable = FALSE; SmlBool useNumberOfChanges = TRUE; SmlBool useLargeObjs = TRUE; SmlProtocolVersion sessionVersion = SML_VERSION_UNKNOWN; SmlDevInf *deviceDevinf = NULL; SmlDevInf *devinf = NULL; static void _manager_event(SmlManager *manager, SmlManagerEventType type, SmlSession *session, SmlError *error, void *userdata) { smlTrace(TRACE_ENTRY, "%s(%p, %i, %p, %p, %p)", __func__, manager, type, session, error, userdata); SmlError *locerror = NULL; switch (type) { case SML_MANAGER_CONNECT_DONE: printf("connection with device succeeded\n"); break; case SML_MANAGER_SESSION_ESTABLISHED: printf("session incl. authentication successfully established\n"); break; case SML_MANAGER_DISCONNECT_DONE: printf("connection with device has ended\n"); break; case SML_MANAGER_TRANSPORT_ERROR: printf("Received an transport error: %s\n", smlErrorPrint(&error)); smlManagerQuit(manager); g_main_loop_quit(loop); break; case SML_MANAGER_SESSION_NEW: printf("Just received a new session with ID %s\n", smlSessionGetSessionID(session)); sessionVersion = smlSessionGetVersion(session); if (smlSessionGetRemoteMaxMsgSize(session) > recvLimit && recvLimit > 0) recvLimit = smlSessionGetRemoteMaxMsgSize(session); if (recvLimit) smlSessionSetLocalMaxMsgSize(session, recvLimit); if (smlSessionGetRemoteMaxObjSize(session) > maxObjSize && maxObjSize > 0) maxObjSize = smlSessionGetRemoteMaxObjSize(session); if (maxObjSize) smlSessionSetLocalMaxObjSize(session, maxObjSize); if (useStringTable) smlSessionUseStringTable(session, TRUE); smlSessionUseNumberOfChanges(session, useNumberOfChanges); smlSessionUseLargeObjects(session, useLargeObjs); break; case SML_MANAGER_SESSION_FINAL: if (!deviceDevinf && (deviceDevinf = smlDevInfAgentGetDevInf(agent))) { printf("Received the DevInf\n"); smlSessionUseNumberOfChanges(session, smlDevInfSupportsNumberOfChanges(deviceDevinf)); smlDevInfSetSupportsNumberOfChanges(devinf, smlDevInfSupportsNumberOfChanges(deviceDevinf)); } if ((deviceDevinf && smlDevInfSupportsLargeObjs(deviceDevinf)) || (!deviceDevinf && useLargeObjs)) { /* enable standard compliant large object support */ if (recvLimit) smlSessionSetLocalMaxMsgSize(session, recvLimit); if (maxObjSize) smlSessionSetLocalMaxObjSize(session, maxObjSize); smlSessionUseLargeObjects(session, TRUE); smlDevInfSetSupportsLargeObjs(devinf, TRUE); } /* We want to know about the device so we check if we received * the devinf already */ if (dumpinfo && !deviceDevinf) { printf("Going to request the devinf\n"); if (!smlDevInfAgentRequestDevInf(agent, session, &locerror)) goto error; } printf("Session %s reported final. flushing\n", smlSessionGetSessionID(session)); SmlError *locerror = NULL; if (onlyInfo && deviceDevinf) smlSessionEnd(session, &locerror); else smlSessionFlush(session, TRUE, &locerror); break; case SML_MANAGER_SESSION_END: printf("Session %s has ended\n", smlSessionGetSessionID(session)); smlManagerQuit(manager); g_main_loop_quit(loop); break; case SML_MANAGER_SESSION_ERROR: printf("There was an error in the session %s: %s", smlSessionGetSessionID(session), smlErrorPrint(&error)); smlManagerQuit(manager); g_main_loop_quit(loop); break; case SML_MANAGER_SESSION_WARNING: printf("WARNING: %s", smlErrorPrint(&error)); break; case SML_MANAGER_SESSION_FLUSH: break; } smlTrace(TRACE_EXIT, "%s", __func__); return; error: printf("An error occured while handling events: %s\n", smlErrorPrint(&locerror)); smlManagerQuit(manager); g_main_loop_quit(loop); smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(&locerror)); smlErrorDeref(&locerror); } #ifdef ENABLE_OBEX static void discover_cb(obex_t *handle, obex_object_t *object, int mode, int event, int obex_cmd, int obex_rsp) { (void) handle; (void) object; (void) mode; (void) event; (void) obex_cmd; (void) obex_rsp; } void list_interfaces() { obex_t *handle; obex_interface_t* obex_intf; int i, interfaces_number = 0; if(!(handle = OBEX_Init(OBEX_TRANS_USB, discover_cb, 0))) { printf("OBEX_Init failed\n"); return; } if (geteuid() != 0) fprintf(stderr, "Superuser privileges are required to access complete USB information.\n"); interfaces_number = OBEX_FindInterfaces(handle, &obex_intf); printf("Found %d USB OBEX interfaces\n", interfaces_number); for (i = 0; i < interfaces_number; i++) printf("Interface %d:\n\tManufacturer: %s\n\tProduct: %s\n\tInterface description: %s\n", i, obex_intf[i].usb.manufacturer, obex_intf[i].usb.product, obex_intf[i].usb.control_interface); printf("Use '-u interface_number' to connect\n"); OBEX_Cleanup(handle); } #endif gboolean _sessions_prepare(GSource *source, gint *timeout_) { *timeout_ = 50; return FALSE; } gboolean _sessions_check(GSource *source) { GList *s = NULL; for (s = sessions; s; s = s->next) { SmlDsSession *session = s->data; if (smlDsSessionCheck(session)) return TRUE; } if (smlManagerCheck(manager)) return TRUE; return FALSE; } gboolean _sessions_dispatch(GSource *source, GSourceFunc callback, gpointer user_data) { GList *s = NULL; for (s = sessions; s; s = s->next) { SmlDsSession *session = s->data; smlDsSessionDispatch(session); } smlManagerDispatch(manager); return TRUE; } GMainContext *_sessions_attach() { GMainContext *context = g_main_context_new(); GSourceFuncs *functions = g_malloc0(sizeof(GSourceFuncs)); functions->prepare = _sessions_prepare; functions->check = _sessions_check; functions->dispatch = _sessions_dispatch; functions->finalize = NULL; GSource *source = g_source_new(functions, sizeof(GSource)); g_source_set_callback(source, NULL, NULL, NULL); g_source_attach(source, context); return context; } int main(int argc, char *argv[]) { SmlTransportConnectionType type = SML_TRANSPORT_CONNECTION_TYPE_USB; char *url = NULL; char *port = NULL; SmlMimeType mimeType = SML_MIMETYPE_XML; SmlError *error = NULL; char *identifier = NULL; char *username = NULL; char *password = NULL; SmlNotificationVersion sanVersion = SML_SAN_VERSION_11; if (!g_thread_supported ()) g_thread_init (NULL); if (argc == 1) usage (argv[0], 1); int i = 0; for (i = 1; i < argc; i++) { char *arg = argv[i]; if (!strcmp (arg, "--sync") || !strcmp(arg, "--slow-sync") || !strcmp(arg, "--add")) { i += 2; continue; } else if (!strcmp (arg, "-u")) { i++; if (!argv[i]) { #ifdef ENABLE_OBEX list_interfaces(); return 0; #else printf("OBEX not available in this build\n"); return 1; #endif } errno = 0; port = argv[i]; if (!port) usage (argv[0], 1); } else if (!strcmp (arg, "-b")) { #ifdef ENABLE_BLUETOOTH type = SML_TRANSPORT_CONNECTION_TYPE_BLUETOOTH; i++; if (!argv[i]) usage (argv[0], 1); url = g_strdup(argv[i]); i++; if (!argv[i]) usage (argv[0], 1); errno = 0; port = argv[i]; if (!port) usage (argv[0], 1); #else printf("Bluetooth not available in this build\n"); return 1; #endif } else if (!strcmp (arg, "-s")) { type = SML_TRANSPORT_CONNECTION_TYPE_SERIAL; i++; if (!argv[i]) usage (argv[0], 1); url = g_strdup(argv[i]); } else if (!strcmp (arg, "--identifier")) { i++; if (!argv[i]) usage (argv[0], 1); identifier = g_strdup(argv[i]); } else if (!strcmp (arg, "--username")) { i++; if (!argv[i]) usage (argv[0], 1); username = g_strdup(argv[i]); } else if (!strcmp (arg, "--password")) { i++; if (!argv[i]) usage (argv[0], 1); password = g_strdup(argv[i]); } else if (!strcmp (arg, "--recvLimit")) { i++; if (!argv[i]) usage (argv[0], 1); recvLimit = atoi(argv[i]); } else if (!strcmp (arg, "--maxObjSize")) { i++; if (!argv[i]) usage (argv[0], 1); maxObjSize = atoi(argv[i]); } else if (!strcmp (arg, "--useStringTable")) { useStringTable = TRUE; } else if (!strcmp (arg, "--disableNumberOfChanges")) { useNumberOfChanges = FALSE; } else if (!strcmp (arg, "--useTimeAnchor")) { useTimeAnchor = malloc(sizeof(char)*17); time_t htime = time(NULL); strftime(useTimeAnchor, 17, "%Y%m%dT%H%M%SZ", gmtime(&htime)); } else if (!strcmp (arg, "--version")) { i++; if (!argv[i]) usage (argv[0], 1); if (!strcmp (argv[i], "1.0")) { sanVersion = SML_SAN_VERSION_10; } else if (!strcmp (argv[i], "1.1")) { sanVersion = SML_SAN_VERSION_11; } else if (!strcmp (argv[i], "1.2")) { sanVersion = SML_SAN_VERSION_12; } else usage (argv[0], 1); } else if (!strcmp (arg, "--help")) { usage (argv[0], 0); } else if (!strcmp (arg, "--wbxml")) { mimeType = SML_MIMETYPE_WBXML; } else if (!strcmp (arg, "--dumpinfo")) { dumpinfo = TRUE; } else if (!strcmp (arg, "--onlyinfo")) { onlyInfo = TRUE; } else if (!strcmp (arg, "--")) { break; } else if (arg[0] == '-') { usage (argv[0], 1); } else { usage (argv[0], 1); } } /* The transport needed to transport the data */ SmlTransport *client = smlTransportNew(SML_TRANSPORT_OBEX_CLIENT, &error); if (!client) goto error; /* The manager responsible for handling the other objects */ manager = smlManagerNew(client, &error); if (!manager) goto error; smlManagerSetEventCallback(manager, _manager_event, NULL); if (useLargeObjs) { /* This is a server which supports SyncML 1.1 or higher. * So large objects must be supported. */ smlManagerSetLocalMaxMsgSize(manager, recvLimit); smlManagerSetLocalMaxObjSize(manager, maxObjSize); } /* The authenticator */ SmlAuthenticator *auth = smlAuthNew(&error); if (!auth) goto error; if (!username) smlAuthSetEnable(auth, FALSE); if (!smlAuthRegister(auth, manager, &error)) goto error_free_auth; /* Now create the devinf handler */ devinf = smlDevInfNew("LibSyncmML", SML_DEVINF_DEVTYPE_WORKSTATION, &error); if (!devinf) goto error_free_manager; smlDevInfSetSupportsNumberOfChanges(devinf, useNumberOfChanges); smlDevInfSetSupportsLargeObjs(devinf, useLargeObjs); smlDevInfSetSupportsUTC(devinf, TRUE); agent = smlDevInfAgentNew(devinf, &error); if (!agent) goto error_free_manager; if (!smlDevInfAgentRegister(agent, manager, &error)) goto error_free_manager; /* Create the alert for the remote device */ if (!identifier) identifier = g_strdup("LibSyncML Test Suite"); SmlNotification *san = smlNotificationNew(sanVersion, SML_SAN_UIMODE_UNSPECIFIED, SML_SAN_INITIATOR_USER, 1, identifier, "/", mimeType, &error); if (!san) goto error; smlNotificationSetManager(san, manager); for (i = 1; i < argc; i++) { char *arg = argv[i]; if (!strcmp (arg, "--sync") || !strcmp(arg, "--slow-sync")) { i++; if (!argv[i]) usage (argv[0], 1); dbTypes = g_list_append(dbTypes, argv[i]); if (!strstr(argv[i], "/")) fprintf(stderr, "WARNING: Specified database type \"%s\" doesn't look like a valid MIME type!\n" "WARNING: (Mixed up database path/location with database type?)\n", argv[i] ? argv[i] : ""); i++; if (!argv[i]) usage (argv[0], 1); dbLocations = g_list_append(dbLocations, argv[i]); if (!strcmp(arg, "--slow-sync")) dbSlow = g_list_append(dbSlow, GINT_TO_POINTER(TRUE)); else dbSlow = g_list_append(dbSlow, GINT_TO_POINTER(FALSE)); /* We now create the ds server hat the given location */ SmlLocation *loc = smlLocationNew(g_list_last(dbLocations)->data, NULL, &error); if (!loc) goto error; SmlDsServer *dsserver = smlDsServerNew(g_list_last(dbTypes)->data, loc, &error); if (!dsserver) goto error_free_manager; if (!smlDsServerRegister(dsserver, manager, &error)) goto error_free_auth; smlDsServerSetConnectCallback(dsserver, _ds_alert, NULL); /* Then we add the alert to the SAN */ if (!smlDsServerAddSan(dsserver, san, &error)) goto error; /* And we also add the devinfo to the devinf agent */ SmlDevInfDataStore *datastore = smlDevInfDataStoreNew(smlLocationGetURI(loc), &error); if (!datastore) goto error; if (!strcmp(g_list_last(dbTypes)->data, SML_ELEMENT_TEXT_VCARD)) { smlDevInfDataStoreSetRxPref(datastore, SML_ELEMENT_TEXT_VCARD, "2.1"); smlDevInfDataStoreSetTxPref(datastore, SML_ELEMENT_TEXT_VCARD, "2.1"); } else if (!strcmp(g_list_last(dbTypes)->data, SML_ELEMENT_TEXT_VCAL)) { smlDevInfDataStoreSetRxPref(datastore, SML_ELEMENT_TEXT_VCAL, "1.0"); smlDevInfDataStoreSetTxPref(datastore, SML_ELEMENT_TEXT_VCAL, "1.0"); } else if (!strcmp(g_list_last(dbTypes)->data, SML_ELEMENT_TEXT_PLAIN)) { smlDevInfDataStoreSetRxPref(datastore, SML_ELEMENT_TEXT_PLAIN, "1.0"); smlDevInfDataStoreSetTxPref(datastore, SML_ELEMENT_TEXT_PLAIN, "1.0"); } smlDevInfDataStoreSetSyncCap(datastore, SML_DEVINF_SYNCTYPE_TWO_WAY, TRUE); smlDevInfDataStoreSetSyncCap(datastore, SML_DEVINF_SYNCTYPE_SLOW_SYNC, TRUE); smlDevInfDataStoreSetSyncCap(datastore, SML_DEVINF_SYNCTYPE_SERVER_ALERTED_SYNC, TRUE); smlDevInfAddDataStore(devinf, datastore); } else if (!strcmp (arg, "--add")) { i++; if (!argv[i]) usage (argv[0], 1); types = g_list_append(types, argv[i]); i++; if (!argv[i]) usage (argv[0], 1); paths = g_list_append(paths, argv[i]); } } if (g_list_length(dbLocations) == 0) { smlErrorSet(&error, SML_ERROR_GENERIC, "You have to configure at least one database"); goto error; } /* Initialize the Transport */ if (!smlTransportSetConfigOption(client, "PORT", port, &error) || !smlTransportSetConfigOption(client, "URL", url, &error) || !smlTransportSetConnectionType(client, type, &error) || !smlTransportInitialize(client, &error)) goto error; /* Run the manager */ if (!smlManagerStart(manager, &error)) goto error; if (!smlTransportConnect(client, &error)) goto error; if (!smlNotificationSend(san, client, &error)) goto error; smlNotificationFree(san); GMainContext *context = _sessions_attach(); loop = g_main_loop_new(context, TRUE); g_main_loop_run(loop); if (!smlTransportDisconnect(client, NULL, &error)) goto error; /* Stop the manager */ smlManagerStop(manager); smlTransportFinalize(client, &error); smlTransportFree(client); if (dumpinfo) { if (!deviceDevinf) { printf("Didnt receive the devinf though it was requested\n"); } else { printf("Send the output below to the libsyncml developers\n"); printf("\n========================================\n"); printf("Man: %s\n", smlDevInfGetManufacturer(deviceDevinf)); printf("Mod: %s\n", smlDevInfGetModel(deviceDevinf)); printf("FirmwareVersion: %s\n", smlDevInfGetFirmwareVersion(deviceDevinf)); printf("SoftwareVersion: %s\n", smlDevInfGetSoftwareVersion(deviceDevinf)); printf("HardwareVersion: %s\n", smlDevInfGetHardwareVersion(deviceDevinf)); printf("\n"); printf("ReceiveLimit: %i\n", recvLimit); printf("MaxObjSize: %i\n", maxObjSize); printf("Connection used: OBEX Client\n"); printf("Identifier: %s\n", identifier); printf("\nDatabases:\n"); int i = 0; for (i = 0; i < g_list_length(dbLocations); i++) { printf("DB Locations: %s\n", (char *)g_list_nth_data(dbLocations, i)); printf("DB Type: %s\n", (char *)g_list_nth_data(dbTypes, i)); printf("DB Slow: %i\n\n", GPOINTER_TO_INT(g_list_nth_data(dbSlow, i))); } printf("Bluetooth: %s\n", type == SML_TRANSPORT_CONNECTION_TYPE_BLUETOOTH ? "Yes" : "Unknown"); printf("Wbxml: %s\n", mimeType == SML_MIMETYPE_WBXML ? "Yes" : "No"); printf("SyncML Version: 1.%i\n", sessionVersion - 1); printf("SupportsNumberOfChanges: %s\n", smlDevInfSupportsNumberOfChanges(deviceDevinf) ? "Yes" : "No"); printf("SupportsLargeObjects: %s\n", smlDevInfSupportsLargeObjs(deviceDevinf) ? "Yes" : "No"); } } g_free(identifier); g_free(url); return 0; error_free_auth: smlAuthFree(auth); error_free_manager: smlManagerFree(manager); error: printf("Failed to start the client: %s\n", smlErrorPrint(&error)); smlErrorDeref(&error); return -1; } libsyncml-0.5.4/tools/Doxyfile.in100644 1750 1750 132161 11211710410 16740 0ustar00bellmichbellmich# Doxyfile 1.3.8 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project # # All text after a hash (#) is considered a comment and will be ignored # The format is: # TAG = value [value, ...] # For lists items can also be appended using: # TAG += value [value, ...] # Values that contain spaces should be placed between quotes (" ") #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- # The PROJECT_NAME tag is a single word (or a sequence of words surrounded # by quotes) that should identify the project. PROJECT_NAME = libsyncml # The PROJECT_NUMBER tag can be used to enter a project or revision number. # This could be handy for archiving the generated documentation or # if some version control system is used. PROJECT_NUMBER = @VERSION@ # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) # base path where the generated documentation will be put. # If a relative path is entered, it will be relative to the location # where doxygen was started. If left blank the current directory will be used. OUTPUT_DIRECTORY = docs # If the CREATE_SUBDIRS tag is set to YES, then doxygen will create # 4096 sub-directories (in 2 levels) under the output directory of each output # format and will distribute the generated files over these directories. # Enabling this option can be useful when feeding doxygen a huge amount of source # files, where putting all generated files in the same directory would otherwise # cause performance problems for the file system. CREATE_SUBDIRS = NO # The OUTPUT_LANGUAGE tag is used to specify the language in which all # documentation generated by doxygen is written. Doxygen will use this # information to generate all constant output in the proper language. # The default language is English, other supported languages are: # Brazilian, Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, # Dutch, Finnish, French, German, Greek, Hungarian, Italian, Japanese, # Japanese-en (Japanese with English messages), Korean, Korean-en, Norwegian, # Polish, Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish, # Swedish, and Ukrainian. OUTPUT_LANGUAGE = English # This tag can be used to specify the encoding used in the generated output. # The encoding is not always determined by the language that is chosen, # but also whether or not the output is meant for Windows or non-Windows users. # In case there is a difference, setting the USE_WINDOWS_ENCODING tag to YES # forces the Windows encoding (this is the default for the Windows binary), # whereas setting the tag to NO uses a Unix-style encoding (the default for # all platforms other than Windows). USE_WINDOWS_ENCODING = NO # If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will # include brief member descriptions after the members that are listed in # the file and class documentation (similar to JavaDoc). # Set to NO to disable this. BRIEF_MEMBER_DESC = YES # If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend # the brief description of a member or function before the detailed description. # Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the # brief descriptions will be completely suppressed. REPEAT_BRIEF = YES # This tag implements a quasi-intelligent brief description abbreviator # that is used to form the text in various listings. Each string # in this list, if found as the leading text of the brief description, will be # stripped from the text and the result after processing the whole list, is used # as the annotated text. Otherwise, the brief description is used as-is. If left # blank, the following values are used ("$name" is automatically replaced with the # name of the entity): "The $name class" "The $name widget" "The $name file" # "is" "provides" "specifies" "contains" "represents" "a" "an" "the" ABBREVIATE_BRIEF = # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then # Doxygen will generate a detailed section even if there is only a brief # description. ALWAYS_DETAILED_SEC = NO # If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all inherited # members of a class in the documentation of that class as if those members were # ordinary class members. Constructors, destructors and assignment operators of # the base classes will not be shown. INLINE_INHERITED_MEMB = YES # If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full # path before files name in the file list and in the header files. If set # to NO the shortest path that makes the file name unique will be used. FULL_PATH_NAMES = YES # If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag # can be used to strip a user-defined part of the path. Stripping is # only done if one of the specified strings matches the left-hand part of # the path. The tag can be used to show relative paths in the file list. # If left blank the directory from which doxygen is run is used as the # path to strip. STRIP_FROM_PATH = # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of # the path mentioned in the documentation of a class, which tells # the reader which header file to include in order to use a class. # If left blank only the name of the header file containing the class # definition is used. Otherwise one should specify the include paths that # are normally passed to the compiler using the -I flag. STRIP_FROM_INC_PATH = # If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter # (but less readable) file names. This can be useful is your file systems # doesn't support long names like on DOS, Mac, or CD-ROM. SHORT_NAMES = NO # If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen # will interpret the first line (until the first dot) of a JavaDoc-style # comment as the brief description. If set to NO, the JavaDoc # comments will behave just like the Qt-style comments (thus requiring an # explicit @brief command for a brief description. JAVADOC_AUTOBRIEF = NO # The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen # treat a multi-line C++ special comment block (i.e. a block of //! or /// # comments) as a brief description. This used to be the default behaviour. # The new default is to treat a multi-line C++ comment block as a detailed # description. Set this tag to YES if you prefer the old behaviour instead. MULTILINE_CPP_IS_BRIEF = NO # If the DETAILS_AT_TOP tag is set to YES then Doxygen # will output the detailed description near the top, like JavaDoc. # If set to NO, the detailed description appears after the member # documentation. DETAILS_AT_TOP = NO # If the INHERIT_DOCS tag is set to YES (the default) then an undocumented # member inherits the documentation from any documented member that it # re-implements. INHERIT_DOCS = YES # If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC # tag is set to YES, then doxygen will reuse the documentation of the first # member in the group (if any) for the other members of the group. By default # all members of a group must be documented explicitly. DISTRIBUTE_GROUP_DOC = NO # The TAB_SIZE tag can be used to set the number of spaces in a tab. # Doxygen uses this value to replace tabs by spaces in code fragments. TAB_SIZE = 8 # This tag can be used to specify a number of aliases that acts # as commands in the documentation. An alias has the form "name=value". # For example adding "sideeffect=\par Side Effects:\n" will allow you to # put the command \sideeffect (or @sideeffect) in the documentation, which # will result in a user-defined paragraph with heading "Side Effects:". # You can put \n's in the value part of an alias to insert newlines. ALIASES = # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources # only. Doxygen will then generate output that is more tailored for C. # For instance, some of the names that are used will be different. The list # of all members will be omitted, etc. OPTIMIZE_OUTPUT_FOR_C = YES # Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java sources # only. Doxygen will then generate output that is more tailored for Java. # For instance, namespaces will be presented as packages, qualified scopes # will look different, etc. OPTIMIZE_OUTPUT_JAVA = NO # Set the SUBGROUPING tag to YES (the default) to allow class member groups of # the same type (for instance a group of public functions) to be put as a # subgroup of that type (e.g. under the Public Functions section). Set it to # NO to prevent subgrouping. Alternatively, this can be done per class using # the \nosubgrouping command. SUBGROUPING = YES #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- # If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in # documentation are documented, even if no documentation was available. # Private class members and static file members will be hidden unless # the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES EXTRACT_ALL = NO # If the EXTRACT_PRIVATE tag is set to YES all private members of a class # will be included in the documentation. EXTRACT_PRIVATE = NO # If the EXTRACT_STATIC tag is set to YES all static members of a file # will be included in the documentation. EXTRACT_STATIC = NO # If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) # defined locally in source files will be included in the documentation. # If set to NO only classes defined in header files are included. EXTRACT_LOCAL_CLASSES = YES # This flag is only useful for Objective-C code. When set to YES local # methods, which are defined in the implementation section but not in # the interface are included in the documentation. # If set to NO (the default) only methods in the interface are included. EXTRACT_LOCAL_METHODS = NO # If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all # undocumented members of documented classes, files or namespaces. # If set to NO (the default) these members will be included in the # various overviews, but no documentation section is generated. # This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_MEMBERS = NO # If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all # undocumented classes that are normally visible in the class hierarchy. # If set to NO (the default) these classes will be included in the various # overviews. This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_CLASSES = NO # If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all # friend (class|struct|union) declarations. # If set to NO (the default) these declarations will be included in the # documentation. HIDE_FRIEND_COMPOUNDS = NO # If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any # documentation blocks found inside the body of a function. # If set to NO (the default) these blocks will be appended to the # function's detailed documentation block. HIDE_IN_BODY_DOCS = NO # The INTERNAL_DOCS tag determines if documentation # that is typed after a \internal command is included. If the tag is set # to NO (the default) then the documentation will be excluded. # Set it to YES to include the internal documentation. INTERNAL_DOCS = NO # If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate # file names in lower-case letters. If set to YES upper-case letters are also # allowed. This is useful if you have classes or files whose names only differ # in case and if your file system supports case sensitive file names. Windows # and Mac users are advised to set this option to NO. CASE_SENSE_NAMES = YES # If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen # will show members with their full class and namespace scopes in the # documentation. If set to YES the scope will be hidden. HIDE_SCOPE_NAMES = NO # If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen # will put a list of the files that are included by a file in the documentation # of that file. SHOW_INCLUDE_FILES = YES # If the INLINE_INFO tag is set to YES (the default) then a tag [inline] # is inserted in the documentation for inline members. INLINE_INFO = YES # If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen # will sort the (detailed) documentation of file and class members # alphabetically by member name. If set to NO the members will appear in # declaration order. SORT_MEMBER_DOCS = NO # If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the # brief documentation of file, namespace and class members alphabetically # by member name. If set to NO (the default) the members will appear in # declaration order. SORT_BRIEF_DOCS = NO # If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be # sorted by fully-qualified names, including namespaces. If set to # NO (the default), the class list will be sorted only by class name, # not including the namespace part. # Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. # Note: This option applies only to the class list, not to the # alphabetical list. SORT_BY_SCOPE_NAME = NO # The GENERATE_TODOLIST tag can be used to enable (YES) or # disable (NO) the todo list. This list is created by putting \todo # commands in the documentation. GENERATE_TODOLIST = YES # The GENERATE_TESTLIST tag can be used to enable (YES) or # disable (NO) the test list. This list is created by putting \test # commands in the documentation. GENERATE_TESTLIST = YES # The GENERATE_BUGLIST tag can be used to enable (YES) or # disable (NO) the bug list. This list is created by putting \bug # commands in the documentation. GENERATE_BUGLIST = YES # The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or # disable (NO) the deprecated list. This list is created by putting # \deprecated commands in the documentation. GENERATE_DEPRECATEDLIST = YES # The ENABLED_SECTIONS tag can be used to enable conditional # documentation sections, marked by \if sectionname ... \endif. ENABLED_SECTIONS = # The MAX_INITIALIZER_LINES tag determines the maximum number of lines # the initial value of a variable or define consists of for it to appear in # the documentation. If the initializer consists of more lines than specified # here it will be hidden. Use a value of 0 to hide initializers completely. # The appearance of the initializer of individual variables and defines in the # documentation can be controlled using \showinitializer or \hideinitializer # command in the documentation regardless of this setting. MAX_INITIALIZER_LINES = 30 # Set the SHOW_USED_FILES tag to NO to disable the list of files generated # at the bottom of the documentation of classes and structs. If set to YES the # list will mention the files that were used to generate the documentation. SHOW_USED_FILES = YES #--------------------------------------------------------------------------- # configuration options related to warning and progress messages #--------------------------------------------------------------------------- # The QUIET tag can be used to turn on/off the messages that are generated # by doxygen. Possible values are YES and NO. If left blank NO is used. QUIET = NO # The WARNINGS tag can be used to turn on/off the warning messages that are # generated by doxygen. Possible values are YES and NO. If left blank # NO is used. WARNINGS = YES # If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings # for undocumented members. If EXTRACT_ALL is set to YES then this flag will # automatically be disabled. WARN_IF_UNDOCUMENTED = YES # If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for # potential errors in the documentation, such as not documenting some # parameters in a documented function, or documenting parameters that # don't exist or using markup commands wrongly. WARN_IF_DOC_ERROR = YES # The WARN_FORMAT tag determines the format of the warning messages that # doxygen can produce. The string should contain the $file, $line, and $text # tags, which will be replaced by the file and line number from which the # warning originated and the warning text. WARN_FORMAT = "$file:$line: $text" # The WARN_LOGFILE tag can be used to specify a file to which warning # and error messages should be written. If left blank the output is written # to stderr. WARN_LOGFILE = #--------------------------------------------------------------------------- # configuration options related to the input files #--------------------------------------------------------------------------- # The INPUT tag can be used to specify the files and/or directories that contain # documented source files. You may enter file names like "myfile.cpp" or # directories like "/usr/src/myproject". Separate the files or directories # with spaces. INPUT = @CMAKE_SOURCE_DIR@/tools # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank the following patterns are tested: # *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx *.hpp # *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm FILE_PATTERNS = *.c and *.h # The RECURSIVE tag can be used to turn specify whether or not subdirectories # should be searched for input files as well. Possible values are YES and NO. # If left blank NO is used. RECURSIVE = YES # The EXCLUDE tag can be used to specify files and/or directories that should # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. EXCLUDE = # The EXCLUDE_SYMLINKS tag can be used select whether or not files or directories # that are symbolic links (a Unix filesystem feature) are excluded from the input. EXCLUDE_SYMLINKS = NO # If the value of the INPUT tag contains directories, you can use the # EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude # certain files from those directories. EXCLUDE_PATTERNS = # The EXAMPLE_PATH tag can be used to specify one or more files or # directories that contain example code fragments that are included (see # the \include command). EXAMPLE_PATH = # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank all files are included. EXAMPLE_PATTERNS = # If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be # searched for input files to be used with the \include or \dontinclude # commands irrespective of the value of the RECURSIVE tag. # Possible values are YES and NO. If left blank NO is used. EXAMPLE_RECURSIVE = NO # The IMAGE_PATH tag can be used to specify one or more files or # directories that contain image that are included in the documentation (see # the \image command). IMAGE_PATH = # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program # by executing (via popen()) the command , where # is the value of the INPUT_FILTER tag, and is the name of an # input file. Doxygen will then use the output that the filter program writes # to standard output. If FILTER_PATTERNS is specified, this tag will be # ignored. INPUT_FILTER = # The FILTER_PATTERNS tag can be used to specify filters on a per file pattern # basis. Doxygen will compare the file name with each pattern and apply the # filter if there is a match. The filters are a list of the form: # pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further # info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER # is applied to all files. FILTER_PATTERNS = # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using # INPUT_FILTER) will be used to filter the input files when producing source # files to browse (i.e. when SOURCE_BROWSER is set to YES). FILTER_SOURCE_FILES = NO #--------------------------------------------------------------------------- # configuration options related to source browsing #--------------------------------------------------------------------------- # If the SOURCE_BROWSER tag is set to YES then a list of source files will # be generated. Documented entities will be cross-referenced with these sources. # Note: To get rid of all source code in the generated output, make sure also # VERBATIM_HEADERS is set to NO. SOURCE_BROWSER = YES # Setting the INLINE_SOURCES tag to YES will include the body # of functions and classes directly in the documentation. INLINE_SOURCES = NO # Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct # doxygen to hide any special comment blocks from generated source code # fragments. Normal C and C++ comments will always remain visible. STRIP_CODE_COMMENTS = YES # If the REFERENCED_BY_RELATION tag is set to YES (the default) # then for each documented function all documented # functions referencing it will be listed. REFERENCED_BY_RELATION = YES # If the REFERENCES_RELATION tag is set to YES (the default) # then for each documented function all documented entities # called/used by that function will be listed. REFERENCES_RELATION = NO # If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen # will generate a verbatim copy of the header file for each class for # which an include is specified. Set to NO to disable this. VERBATIM_HEADERS = YES #--------------------------------------------------------------------------- # configuration options related to the alphabetical class index #--------------------------------------------------------------------------- # If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index # of all compounds will be generated. Enable this if the project # contains a lot of classes, structs, unions or interfaces. ALPHABETICAL_INDEX = NO # If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then # the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns # in which this list will be split (can be a number in the range [1..20]) COLS_IN_ALPHA_INDEX = 5 # In case all classes in a project start with a common prefix, all # classes will be put under the same header in the alphabetical index. # The IGNORE_PREFIX tag can be used to specify one or more prefixes that # should be ignored while generating the index headers. IGNORE_PREFIX = #--------------------------------------------------------------------------- # configuration options related to the HTML output #--------------------------------------------------------------------------- # If the GENERATE_HTML tag is set to YES (the default) Doxygen will # generate HTML output. GENERATE_HTML = NO # The HTML_OUTPUT tag is used to specify where the HTML docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `html' will be used as the default path. HTML_OUTPUT = html # The HTML_FILE_EXTENSION tag can be used to specify the file extension for # each generated HTML page (for example: .htm,.php,.asp). If it is left blank # doxygen will generate files with .html extension. HTML_FILE_EXTENSION = .html # The HTML_HEADER tag can be used to specify a personal HTML header for # each generated HTML page. If it is left blank doxygen will generate a # standard header. HTML_HEADER = # The HTML_FOOTER tag can be used to specify a personal HTML footer for # each generated HTML page. If it is left blank doxygen will generate a # standard footer. HTML_FOOTER = # The HTML_STYLESHEET tag can be used to specify a user-defined cascading # style sheet that is used by each HTML page. It can be used to # fine-tune the look of the HTML output. If the tag is left blank doxygen # will generate a default style sheet. Note that doxygen will try to copy # the style sheet file to the HTML output directory, so don't put your own # stylesheet in the HTML output directory as well, or it will be erased! HTML_STYLESHEET = misc/doxygen.css # If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, # files or namespaces will be aligned in HTML using tables. If set to # NO a bullet list will be used. HTML_ALIGN_MEMBERS = YES # If the GENERATE_HTMLHELP tag is set to YES, additional index files # will be generated that can be used as input for tools like the # Microsoft HTML help workshop to generate a compressed HTML help file (.chm) # of the generated HTML documentation. GENERATE_HTMLHELP = NO # If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can # be used to specify the file name of the resulting .chm file. You # can add a path in front of the file if the result should not be # written to the html output directory. CHM_FILE = # If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can # be used to specify the location (absolute path including file name) of # the HTML help compiler (hhc.exe). If non-empty doxygen will try to run # the HTML help compiler on the generated index.hhp. HHC_LOCATION = # If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag # controls if a separate .chi index file is generated (YES) or that # it should be included in the master .chm file (NO). GENERATE_CHI = NO # If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag # controls whether a binary table of contents is generated (YES) or a # normal table of contents (NO) in the .chm file. BINARY_TOC = NO # The TOC_EXPAND flag can be set to YES to add extra items for group members # to the contents of the HTML help documentation and to the tree view. TOC_EXPAND = NO # The DISABLE_INDEX tag can be used to turn on/off the condensed index at # top of each HTML page. The value NO (the default) enables the index and # the value YES disables it. DISABLE_INDEX = NO # This tag can be used to set the number of enum values (range [1..20]) # that doxygen will group on one line in the generated HTML documentation. ENUM_VALUES_PER_LINE = 4 # If the GENERATE_TREEVIEW tag is set to YES, a side panel will be # generated containing a tree-like index structure (just like the one that # is generated for HTML Help). For this to work a browser that supports # JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, # Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are # probably better off using the HTML help feature. GENERATE_TREEVIEW = NO # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be # used to set the initial width (in pixels) of the frame in which the tree # is shown. TREEVIEW_WIDTH = 250 #--------------------------------------------------------------------------- # configuration options related to the LaTeX output #--------------------------------------------------------------------------- # If the GENERATE_LATEX tag is set to YES (the default) Doxygen will # generate Latex output. GENERATE_LATEX = NO # The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `latex' will be used as the default path. LATEX_OUTPUT = latex # The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be # invoked. If left blank `latex' will be used as the default command name. LATEX_CMD_NAME = latex # The MAKEINDEX_CMD_NAME tag can be used to specify the command name to # generate index for LaTeX. If left blank `makeindex' will be used as the # default command name. MAKEINDEX_CMD_NAME = makeindex # If the COMPACT_LATEX tag is set to YES Doxygen generates more compact # LaTeX documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_LATEX = NO # The PAPER_TYPE tag can be used to set the paper type that is used # by the printer. Possible values are: a4, a4wide, letter, legal and # executive. If left blank a4wide will be used. PAPER_TYPE = a4wide # The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX # packages that should be included in the LaTeX output. EXTRA_PACKAGES = # The LATEX_HEADER tag can be used to specify a personal LaTeX header for # the generated latex document. The header should contain everything until # the first chapter. If it is left blank doxygen will generate a # standard header. Notice: only use this tag if you know what you are doing! LATEX_HEADER = # If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated # is prepared for conversion to pdf (using ps2pdf). The pdf file will # contain links (just like the HTML output) instead of page references # This makes the output suitable for online browsing using a pdf viewer. PDF_HYPERLINKS = NO # If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of # plain latex in the generated Makefile. Set this option to YES to get a # higher quality PDF documentation. USE_PDFLATEX = NO # If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. # command to the generated LaTeX files. This will instruct LaTeX to keep # running if errors occur, instead of asking the user for help. # This option is also used when generating formulas in HTML. LATEX_BATCHMODE = NO # If LATEX_HIDE_INDICES is set to YES then doxygen will not # include the index chapters (such as File Index, Compound Index, etc.) # in the output. LATEX_HIDE_INDICES = NO #--------------------------------------------------------------------------- # configuration options related to the RTF output #--------------------------------------------------------------------------- # If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output # The RTF output is optimized for Word 97 and may not look very pretty with # other RTF readers or editors. GENERATE_RTF = NO # The RTF_OUTPUT tag is used to specify where the RTF docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `rtf' will be used as the default path. RTF_OUTPUT = rtf # If the COMPACT_RTF tag is set to YES Doxygen generates more compact # RTF documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_RTF = NO # If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated # will contain hyperlink fields. The RTF file will # contain links (just like the HTML output) instead of page references. # This makes the output suitable for online browsing using WORD or other # programs which support those fields. # Note: wordpad (write) and others do not support links. RTF_HYPERLINKS = NO # Load stylesheet definitions from file. Syntax is similar to doxygen's # config file, i.e. a series of assignments. You only have to provide # replacements, missing definitions are set to their default value. RTF_STYLESHEET_FILE = # Set optional variables used in the generation of an rtf document. # Syntax is similar to doxygen's config file. RTF_EXTENSIONS_FILE = #--------------------------------------------------------------------------- # configuration options related to the man page output #--------------------------------------------------------------------------- # If the GENERATE_MAN tag is set to YES (the default) Doxygen will # generate man pages GENERATE_MAN = YES # The MAN_OUTPUT tag is used to specify where the man pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `man' will be used as the default path. MAN_OUTPUT = man # The MAN_EXTENSION tag determines the extension that is added to # the generated man pages (default is the subroutine's section .3) MAN_EXTENSION = .1 # If the MAN_LINKS tag is set to YES and Doxygen generates man output, # then it will generate one additional man file for each entity # documented in the real man page(s). These additional files # only source the real man page, but without them the man command # would be unable to find the correct page. The default is NO. MAN_LINKS = NO #--------------------------------------------------------------------------- # configuration options related to the XML output #--------------------------------------------------------------------------- # If the GENERATE_XML tag is set to YES Doxygen will # generate an XML file that captures the structure of # the code including all documentation. GENERATE_XML = NO # The XML_OUTPUT tag is used to specify where the XML pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `xml' will be used as the default path. XML_OUTPUT = xml # The XML_SCHEMA tag can be used to specify an XML schema, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_SCHEMA = # The XML_DTD tag can be used to specify an XML DTD, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_DTD = # If the XML_PROGRAMLISTING tag is set to YES Doxygen will # dump the program listings (including syntax highlighting # and cross-referencing information) to the XML output. Note that # enabling this will significantly increase the size of the XML output. XML_PROGRAMLISTING = YES #--------------------------------------------------------------------------- # configuration options for the AutoGen Definitions output #--------------------------------------------------------------------------- # If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will # generate an AutoGen Definitions (see autogen.sf.net) file # that captures the structure of the code including all # documentation. Note that this feature is still experimental # and incomplete at the moment. GENERATE_AUTOGEN_DEF = NO #--------------------------------------------------------------------------- # configuration options related to the Perl module output #--------------------------------------------------------------------------- # If the GENERATE_PERLMOD tag is set to YES Doxygen will # generate a Perl module file that captures the structure of # the code including all documentation. Note that this # feature is still experimental and incomplete at the # moment. GENERATE_PERLMOD = NO # If the PERLMOD_LATEX tag is set to YES Doxygen will generate # the necessary Makefile rules, Perl scripts and LaTeX code to be able # to generate PDF and DVI output from the Perl module output. PERLMOD_LATEX = NO # If the PERLMOD_PRETTY tag is set to YES the Perl module output will be # nicely formatted so it can be parsed by a human reader. This is useful # if you want to understand what is going on. On the other hand, if this # tag is set to NO the size of the Perl module output will be much smaller # and Perl will parse it just the same. PERLMOD_PRETTY = YES # The names of the make variables in the generated doxyrules.make file # are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. # This is useful so different doxyrules.make files included by the same # Makefile don't overwrite each other's variables. PERLMOD_MAKEVAR_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the preprocessor #--------------------------------------------------------------------------- # If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will # evaluate all C-preprocessor directives found in the sources and include # files. ENABLE_PREPROCESSING = YES # If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro # names in the source code. If set to NO (the default) only conditional # compilation will be performed. Macro expansion can be done in a controlled # way by setting EXPAND_ONLY_PREDEF to YES. MACRO_EXPANSION = NO # If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES # then the macro expansion is limited to the macros specified with the # PREDEFINED and EXPAND_AS_PREDEFINED tags. EXPAND_ONLY_PREDEF = NO # If the SEARCH_INCLUDES tag is set to YES (the default) the includes files # in the INCLUDE_PATH (see below) will be search if a #include is found. SEARCH_INCLUDES = YES # The INCLUDE_PATH tag can be used to specify one or more directories that # contain include files that are not input files but should be processed by # the preprocessor. INCLUDE_PATH = # You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard # patterns (like *.h and *.hpp) to filter out the header-files in the # directories. If left blank, the patterns specified with FILE_PATTERNS will # be used. INCLUDE_FILE_PATTERNS = # The PREDEFINED tag can be used to specify one or more macro names that # are defined before the preprocessor is started (similar to the -D option of # gcc). The argument of the tag is a list of macros of the form: name # or name=definition (no spaces). If the definition and the = are # omitted =1 is assumed. PREDEFINED = DOXYGEN_SHOULD_SKIP_THIS # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then # this tag can be used to specify a list of macro names that should be expanded. # The macro definition that is found in the sources will be used. # Use the PREDEFINED tag if you want to use a different macro definition. EXPAND_AS_DEFINED = # If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then # doxygen's preprocessor will remove all function-like macros that are alone # on a line, have an all uppercase name, and do not end with a semicolon. Such # function macros are typically used for boiler-plate code, and will confuse the # parser if not removed. SKIP_FUNCTION_MACROS = YES #--------------------------------------------------------------------------- # Configuration::additions related to external references #--------------------------------------------------------------------------- # The TAGFILES option can be used to specify one or more tagfiles. # Optionally an initial location of the external documentation # can be added for each tagfile. The format of a tag file without # this location is as follows: # TAGFILES = file1 file2 ... # Adding location for the tag files is done as follows: # TAGFILES = file1=loc1 "file2 = loc2" ... # where "loc1" and "loc2" can be relative or absolute paths or # URLs. If a location is present for each tag, the installdox tool # does not have to be run to correct the links. # Note that each tag file must have a unique name # (where the name does NOT include the path) # If a tag file is not located in the directory in which doxygen # is run, you must also specify the path to the tagfile here. TAGFILES = # When a file name is specified after GENERATE_TAGFILE, doxygen will create # a tag file that is based on the input files it reads. GENERATE_TAGFILE = # If the ALLEXTERNALS tag is set to YES all external classes will be listed # in the class index. If set to NO only the inherited external classes # will be listed. ALLEXTERNALS = NO # If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed # in the modules index. If set to NO, only the current project's groups will # be listed. EXTERNAL_GROUPS = YES # The PERL_PATH should be the absolute path and name of the perl script # interpreter (i.e. the result of `which perl'). PERL_PATH = /usr/bin/perl #--------------------------------------------------------------------------- # Configuration options related to the dot tool #--------------------------------------------------------------------------- # If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will # generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base or # super classes. Setting the tag to NO turns the diagrams off. Note that this # option is superseded by the HAVE_DOT option below. This is only a fallback. It is # recommended to install and use dot, since it yields more powerful graphs. CLASS_DIAGRAMS = YES # If set to YES, the inheritance and collaboration graphs will hide # inheritance and usage relations if the target is undocumented # or is not a class. HIDE_UNDOC_RELATIONS = YES # If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is # available from the path. This tool is part of Graphviz, a graph visualization # toolkit from AT&T and Lucent Bell Labs. The other options in this section # have no effect if this option is set to NO (the default) HAVE_DOT = YES # If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect inheritance relations. Setting this tag to YES will force the # the CLASS_DIAGRAMS tag to NO. CLASS_GRAPH = YES # If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect implementation dependencies (inheritance, containment, and # class references variables) of the class with other documented classes. COLLABORATION_GRAPH = YES # If the UML_LOOK tag is set to YES doxygen will generate inheritance and # collaboration diagrams in a style similar to the OMG's Unified Modeling # Language. UML_LOOK = YES # If set to YES, the inheritance and collaboration graphs will show the # relations between templates and their instances. TEMPLATE_RELATIONS = NO # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT # tags are set to YES then doxygen will generate a graph for each documented # file showing the direct and indirect include dependencies of the file with # other documented files. INCLUDE_GRAPH = YES # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and # HAVE_DOT tags are set to YES then doxygen will generate a graph for each # documented header file showing the documented files that directly or # indirectly include this file. INCLUDED_BY_GRAPH = YES # If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will # generate a call dependency graph for every global function or class method. # Note that enabling this option will significantly increase the time of a run. # So in most cases it will be better to enable call graphs for selected # functions only using the \callgraph command. CALL_GRAPH = YES # If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen # will graphical hierarchy of all classes instead of a textual one. GRAPHICAL_HIERARCHY = YES # The DOT_IMAGE_FORMAT tag can be used to set the image format of the images # generated by dot. Possible values are png, jpg, or gif # If left blank png will be used. DOT_IMAGE_FORMAT = png # The tag DOT_PATH can be used to specify the path where the dot tool can be # found. If left blank, it is assumed the dot tool can be found on the path. DOT_PATH = # The DOTFILE_DIRS tag can be used to specify one or more directories that # contain dot files that are included in the documentation (see the # \dotfile command). DOTFILE_DIRS = # The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width # (in pixels) of the graphs generated by dot. If a graph becomes larger than # this value, doxygen will try to truncate the graph, so that it fits within # the specified constraint. Beware that most browsers cannot cope with very # large images. MAX_DOT_GRAPH_WIDTH = 1024 # The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height # (in pixels) of the graphs generated by dot. If a graph becomes larger than # this value, doxygen will try to truncate the graph, so that it fits within # the specified constraint. Beware that most browsers cannot cope with very # large images. MAX_DOT_GRAPH_HEIGHT = 1024 # The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the # graphs generated by dot. A depth value of 3 means that only nodes reachable # from the root by following a path via at most 3 edges will be shown. Nodes that # lay further from the root node will be omitted. Note that setting this option to # 1 or 2 may greatly reduce the computation time needed for large code bases. Also # note that a graph may be further truncated if the graph's image dimensions are # not sufficient to fit the graph (see MAX_DOT_GRAPH_WIDTH and MAX_DOT_GRAPH_HEIGHT). # If 0 is used for the depth value (the default), the graph is not depth-constrained. MAX_DOT_GRAPH_DEPTH = 0 # If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will # generate a legend page explaining the meaning of the various boxes and # arrows in the dot generated graphs. GENERATE_LEGEND = YES # If the DOT_CLEANUP tag is set to YES (the default) Doxygen will # remove the intermediate dot files that are used to generate # the various graphs. DOT_CLEANUP = YES #--------------------------------------------------------------------------- # Configuration::additions related to the search engine #--------------------------------------------------------------------------- # The SEARCHENGINE tag specifies whether or not a search engine should be # used. If set to NO the values of all tags below this one will be ignored. SEARCHENGINE = NO libsyncml-0.5.4/tools/syncml-obex-client.1100644 1750 1750 12040 11211710410 20374 0ustar00bellmichbellmich.TH "syncml-obex-client" "1" "0.4.1" "Armin Bauer " "libs" .SH "NAME" .LP syncml\-obex\-client \- simple obex client built on libsyncml .SH "SYNTAX" .LP syncml\-obex\-client [\fIoption\fP] .br syncml\-obex\-client \fI\-\-sync\fP <\fItype\fP> <\fIpath\fP> .SH "DESCRIPTION" .LP Simple obex client built on libsyncml .br syncml\-obex\-client is not a real synchronization tool. It is rather used for testing. The tool will list all entries that the device wants to sync and is also capable of adding items to the device. .SH "USAGE" First you should connect your device with the usb cable. .br Then make sure that the lsusb command lists your device. .br Now we can enumerate the interface available on your device. To do this type (as root!): .IP syncml-obex-client -u .LP This should generate some output like this: .IP Found 2 USB OBEX interfaces .br Interface 0: .br Manufacturer: Nokia .br Product: Nokia 6680 .br Interface description: SYNCML-SYNC .br Interface 1: .br Manufacturer: Nokia .br Product: Nokia 6680 .br Interface description: PC Suite Services .LP It is important that you have an interface with the description "SYNCML-SYNC". This is the interface we are going to use. Now you can run the first "sync" against the device. .SH "OPTIONS" .LP .TP \fB\-\-sync\fR <\fItype\fP> <\fIpath\fP> Emulate a database of the given type on the url. .TP \fB\-\-slow\-sync\fR <\fItype\fP> <\fIpath\fP> Emulate a database of the given type on the url and use slow\-sync .IP \fItype\fP should be a IANA registered mimetype or your own type. .br Common types are: .IP - "text/x\-vcard" for contacts, .br - "text/x\-vcalendar" for events, .br - "text/plain" for notes and .br - "text/x\-vMessage" for SMS .IP \fIpath\fP is the local name of the database. You can choose anything there. .TP [\fB\-u\fR <\fIid\fP>] Connect to the given usb interface number .br If you don't specify an id, all available interfaces will be listed. .TP [\fB\-b\fR <\fIaddr\fP> <\fIchannel\fP>] Connect to the given bluetooth device .TP [\fB\-\-identifier\fR <\fIname\fP>] Use the given identifier in the initial alert. .br Some devices require a special string here. Nokias for example require "PC Suite". .TP [\fB\-\-version\fR <\fIversion\fP>] Set the given version. \fIversion\fP can be "1.0", .br "1.1" or "1.2" (The default is "1.1") .TP \fB\-\-add\fR <\fItype\fP> <\fIpath\fP> Add the file given in path to the device as the given type .IP \fItype\fP should be a IANA registered mimetype or your own type. .br Common types are: .IP - "text/x\-vcard" for contacts, .br - "text/x\-vcalendar" for events, .br - "text/plain" for notes and .br - "text/x\-vMessage" for SMS .IP \fIpath\fP to the file to add. The file has to be a VCard, VCalendar, etc. .TP [\fB\-\-wbxml\fR] Use wbxml (WAP Binary XML) instead of plain xml .TP [\fB\-\-recvLimit\fR <\fIlimit\fP>] Limit the size of the receiving buffer to this size (Needed for some phones) .TP [\fB\-\-maxObjSize\fR <\fIlimit\fP>] The maximum size of a object that we can receive (Needed for some phones) .TP [\fB\-\-useStringTable\fR] Use wbxml string tables (Improves transmission size, but not supported by some phones) .TP [\fB\-\-dumpinfo\fR] Print info about the phone at the end which can be sent to the developers .SH "EXAMPLES" If you want to display the contacts for example you could type: .IP syncml-obex-client -u 0 --identifier "PC Suite" --sync text/x-vcard Contacts .LP The number after -u has to be the interface number of "SYNCML-SYNC". With the identifier you can tell the tool to identify itself as something different (like the Nokia PC Suite in the example). The --sync options states that you want to sync vcards and that your local database is named "Contacts". This example would send syncml as plain xml. .br Another example: .IP syncml-obex-client -u 0 --identifier "PC Suite" --sync text/x-vcard Contacts --sync text/x-vcalendar Calendar --wbxml .LP This would enable the usage of wap binary xml and get the contacts and the calendar entries (This example works for a Nokia 6680). .SH "TROUBLESHOOTING" If it does not work try the following: .br - Run the syncml-obex-client commands as root. .br - Play with the identifier string .br - Switch between xml and wbxml using the --wbxml switch (Most devices use wbxml) .br - Change the name of the database ("Contacts" and "Calendar" in the example) .br - Phones (and parts of phones) crash quite often. You should restart your phone if everything fails and see if that helps .SH "ENVIRONMENT VARIABLES" When you want to provide trace files please turn on tracing like this: .LP export SYNCML_TRACE=/path/to/log/dir .br export SYNCML_LOG = /path/to/log/dir .LP Run the tool again with tracing enabled to get a trace (2 files in the log directory). .SH SEE ALSO .BR syncml-http-server (1) .SH "AUTHORS" .LP This manual page was written for the Debian GNU/Linux project by Matthias Jahn . But it may be used by other distributions. .PP syncml-obex-client was written by Armin Bauer and the OpenSync project libsyncml-0.5.4/tools/CMakeLists.txt100644 1750 1750 1020 11211710410 17312 0ustar00bellmichbellmichLINK_DIRECTORIES( ${GLIB2_LIBRARY_DIRS} ${LIBXML2_LIBRARY_DIRS} ${OPENOBEX_LIBRARY_DIRS} ${LIBWBXML2_LIBRARY_DIRS} ${LIBSOUP2_LIBRARY_DIRS} ${BLUEZ_LIBRARY_DIRS} ) INCLUDE_DIRECTORIES( ${CMAKE_SOURCE_DIR} ${CMAKE_BINARY_DIR} ${GLIB2_INCLUDE_DIRS} ${OPENOBEX_INCLUDE_DIRS} ) if(COMMAND cmake_policy) cmake_policy(SET CMP0003 NEW) endif(COMMAND cmake_policy) ADD_EXECUTABLE( syncml-ds-tool syncml-ds-tool.c ) TARGET_LINK_LIBRARIES( syncml-ds-tool syncml ) INSTALL( TARGETS syncml-ds-tool DESTINATION ${LIBSYNCML_BIN_DIR} ) libsyncml-0.5.4/tools/syncml-ds-tool.c100644 1750 1750 125554 11211710410 17665 0ustar00bellmichbellmich/* * libsyncml - A syncml protocol implementation * Copyright (C) 2005 Armin Bauer * Copyright (C) 2008 Felix Moeller (man page) * Copyright (C) 2008-2009 Michael Bell * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ /** @page syncml-ds-tool * * @section SYNOPSIS * syncml-ds-tool 'OPTIONS' ... * * @brief A SyncML Data Synchronization tool for Unix. * The syncml-ds-tool supports OMA DS server and client mode. * Additionally OBEX and HTTP transports are supported in * client and server mode. * * @section OPTIONS * * @subsection OPTIONS_DS_CONFIG Datastore configuration * * @param --sync "" "" "" * normal two-way sync * * @param --slow-sync "" "" "" * slow two-way sync * * @arg @b type is the content-type of a datastore * text/x-vcard for contacts * text/x-vcalendar for calendar * text/plain for notes * text/x-vMessage for SMS * * @arg @b path is the used (virtual) source URL/path * It is the local name of the database. * You can choose something there. * * @arg @b directory is the local path to the synchronized directory * The directory is optional and an absolute path. * This directory is a persistent storage. * * @subsection OPTION_HTTP_CLIENT_CONFIG HTTP client configuration * * @param --http-client "" * * @arg @b url must be an http URL like http://localhost:8080 * * @subsection OPTION_HTTP_CLIENT_SERVER_CONFIG HTTP server configuration * * @param --http-server "" * * @arg @b port must be a port for the http server. * * @subsection OPTION_OBEX_CLIENT_CONFIG OBEX client configuration * * @param -s "" * Connect to the serial device. * * @param -u * List all available USB interfaces. * * @param -u "" * Connect to the given usb interface number. You may discover them with -u. * * @param -b "" "" * Connect to the given bluetooth device. * * @param --ip "" "" * Connect to this TCP/IP address. * * @param --irda * Connect using IrDA. * * @param --irda-service "" * Use the given IrDA service (default: OBEX). * * @subsection OPTION_OBEX_SERVER_CONFIG OBEX server configuration * * @param --port "" * Listen to this TCP/IP port. * * @subsection OPTION_GENERAL General SyncML options * * @param --identifier "" * set the local identity of SyncML (source). * * @param --target "" * set the remote identity of SyncML (target). * * @param --username "" * set the username for authentication. * * @param --password "" * set the password for authentication. * * @param --maxMsgSize "" * set the maximum message size (default: 0) * * @param --maxObjSize* "" * set the maximum object size (default: 0) * * @param --useStringTable * Use wbxml string tables (default: NEVER EVER) * * @param --disableNumberOfChanges * the most new phones support it (default: enabled) * * @param --useNumberAnchor * Use numbers as anchors. * * @param --wbxml * Use wbxml (WAP Binary XML) instead of plain xml. * * @param --read-only * No write actions will be performed. * * @param --remoteWinsConflicts * If there is a conflict then the remote change wins. * The default is local wins always. * This option is only usable in OMA DS server mode. * * @param --dumpinfo * Print info about the phone. * * @param --version * prints the version of the tool. * * @param --version "" * sets the SyncML version. * * @arg @b ident Some devices require a special identity string. * Nokias for example often requires "PC Suite". * Please use --identifier "PC Suite" in this case. * @arg @b version can be "1.0", "1.1" or "1.2". * The default version is "1.1". * * @subsection OPTION_FAKE_DEVICE Device faking options * * Some SyncML servers try to enforce access policies via device filtering. * These options can be used to work around such filters. * * @param --fake-manufacturer "" * set the manufacturer of the faked device. * * @param --fake-model "" * set the model of the faked device. * * @param --fake-software-version "" * set the software version of the faked device. * * @section EXAMPLES * * @subsection EXAMPLE_BLUETOOTH Get the contacts from your phone via Bluetooth * @verbatim $ syncml-ds-tool -b --slow-sync text/x-vcard contacts --wbxml --identifier "PC Suite" @endverbatim * @subsection EXAMPLE_USB Get the notes from a USB connected phone * @verbatim $ syncml-ds-tool -u --slow-sync text/plain notes --wbxml --identifier "PC Suite" @endverbatim * * @section BUGS * * @par * There is a bugtracker running at http://libsyncml.opensync.org/. * If you have a problem please look there to see * if it is already reported and add your information * to the relavant ticket if possible. * * @par * When opening a new ticket please provide as many information as possible. * For faster processing of your bug it helps to attach the trace files. * You may find a description how to create them at * http://opensync.org/wiki/tracing. * For crashes the output of gdb could help. * * @section AUTHOR * * Written by Felix Moeller, * * @section RESOURCES * * Website: http://libsyncml.opensync.org * * @section COPYING * * Copyright (C) 2008 OpenSync Team. Free use of this software is * granted under the terms of the GNU Lesser General Public License (LGPL). * */ #include #include #include #include #include #include #include #include #include #include #ifdef ENABLE_OBEX /* necessary for list_interfaces */ #include #endif #define STATUS_FILENAME "SYNCML-DS-TOOL-LAST-SYNC" /* ************************************ */ /* *********** CONFIG ***************** */ /* ************************************ */ typedef struct SmlDsToolLocationType { char *source; SmlBool slow; char *contentType; char *directory; GHashTable *remoteHash; } SmlDsToolLocationType; GList *datastores = NULL; char *identifier = NULL; char *target = NULL; char *username = NULL; char *password = NULL; SmlSessionType sessionType = SML_SESSION_TYPE_SERVER; SmlMimeType mimeType = SML_MIMETYPE_XML; char *syncmlVersion = NULL; char *maxMsgSize = NULL; char *maxObjSize = NULL; GMutex *runMutex = NULL; SmlBool dumpinfo = FALSE; SmlBool useNumberOfChanges = TRUE; SmlBool useStringTable = FALSE; SmlDevInf *remoteDevinf = NULL; SmlBool localWinsConflicts = TRUE; time_t checkpoint; SmlBool readOnly = FALSE; /* ************************************ */ /* *********** CALLBACKS ************** */ /* ************************************ */ static void writeSyncStatus(SmlBool success) { SmlDsToolLocationType *datastore = NULL; GList *o = datastores; for(;o;o = o->next) { datastore = o->data; if (datastore->directory) { char *absolute = g_strdup_printf("%s/%s", datastore->directory, STATUS_FILENAME); if (success) { GError *gerror = NULL; if (!g_file_set_contents(absolute, "DONE", 4, &gerror)) { g_warning("Cannot write data to %s. %s", absolute, gerror->message); g_error_free(gerror); } } else { g_unlink(STATUS_FILENAME); } smlSafeCFree(&absolute); } } } SmlChangeType getChangeType( SmlDsToolLocationType *datastore, const char *filename, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%s, %s, %p)", __func__, VA_STRING(datastore->source), VA_STRING(filename), error); struct stat fdata; struct stat fstatus; char *absolute_status = NULL; /* does the file exist */ if (g_stat(filename, &fdata) != 0) { smlErrorSet(error, SML_ERROR_GENERIC, "Cannot stat file %s (%d).", filename, errno); goto error; } /* was the file touched after the checkpoint */ if (fdata.st_mtime >= checkpoint) { if (sessionType == SML_SESSION_TYPE_CLIENT) { smlErrorSet(error, SML_ERROR_GENERIC, "Someone accessed the file absolute after the synchronization started.", filename); goto error; } else { /* this can be an error but it is not sure */ smlTrace(TRACE_EXIT, "%s: changed after checkpoint (%d >= %d)", __func__, fdata.st_mtime, checkpoint); return SML_CHANGE_UNKNOWN; } } /* is there a status file from an earlier sync */ absolute_status = g_strdup_printf("%s/%s", datastore->directory, STATUS_FILENAME); if (!g_file_test(absolute_status, G_FILE_TEST_EXISTS)) { if (!datastore->slow) { smlErrorSet(error, SML_ERROR_GENERIC, "Status file %s is missing but it is no SLOW-SYNC.", absolute_status); goto error; } else { smlSafeCFree(&absolute_status); smlTrace(TRACE_EXIT, "%s: %d", __func__, SML_CHANGE_ADD); return SML_CHANGE_ADD; } } /* read the stat from the status file */ if (g_stat(absolute_status, &fstatus) != 0) { /* this is a general error */ smlErrorSet(error, SML_ERROR_GENERIC, "Cannot stat file %s (%d).", absolute_status, errno); goto error; } smlSafeCFree(&absolute_status); /* check if it was added after the last sync */ if (fdata.st_mtime <= fstatus.st_mtime) { if (datastore->slow) { if (sessionType == SML_SESSION_TYPE_SERVER && g_hash_table_lookup(datastore->remoteHash, filename)) { smlTrace(TRACE_EXIT, "%s: %d (old known item but slowsync)", __func__, SML_CHANGE_REPLACE); return SML_CHANGE_REPLACE; } else { smlTrace(TRACE_EXIT, "%s: %d (old item but slowsync)", __func__, SML_CHANGE_ADD); return SML_CHANGE_ADD; } } else { smlTrace(TRACE_EXIT, "%s: %d (old item and no slowsync)", __func__, SML_CHANGE_UNKNOWN); return SML_CHANGE_UNKNOWN; } } else { /* ctime cannot be used - to unreliable */ /* normal sync does not work reliable therefore */ if (sessionType == SML_SESSION_TYPE_SERVER && g_hash_table_lookup(datastore->remoteHash, filename)) { smlTrace(TRACE_EXIT, "%s: %d (new but known)", __func__, SML_CHANGE_REPLACE); return SML_CHANGE_REPLACE; } else { smlTrace(TRACE_EXIT, "%s: %d (new)", __func__, SML_CHANGE_ADD); return SML_CHANGE_ADD; } } error: if (absolute_status) smlSafeCFree(&absolute_status); smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(error)); return SML_CHANGE_UNKNOWN; } SmlBool sendAllChanges( SmlDataSyncObject *dsObject, SmlError **error) { smlTrace(TRACE_ENTRY, "%s", __func__); GList *o = datastores; GError *gerror = NULL; /* If readOnly then data MUST NOT be send. */ for (;!readOnly && o;o=o->next) { SmlDsToolLocationType *datastore = o->data; if (!datastore->directory) continue; smlTrace(TRACE_INTERNAL, "%s: checking %s", __func__, VA_STRING(datastore->source)); GDir *dir = g_dir_open(datastore->directory, 0, &gerror); if (!dir) goto gerror; const gchar *filename = g_dir_read_name(dir); for (;filename; filename = g_dir_read_name(dir)) { smlTrace(TRACE_INTERNAL, "%s: checking %s", __func__, VA_STRING(filename)); if (!strcmp(filename, STATUS_FILENAME)) continue; char *absolute = g_strdup_printf("%s/%s", datastore->directory, filename); SmlChangeType changeType = getChangeType(datastore, absolute, error); if (changeType == SML_CHANGE_UNKNOWN) { /* error or ignorable file */ smlSafeCFree(&absolute); if (*error) { goto error; } else { continue; } } /* all time checks succeeded, so send sync */ smlTrace(TRACE_INTERNAL, "%s: sending %s", __func__, VA_STRING(absolute)); gsize length; char *data = NULL; if (!g_file_get_contents(absolute, &data, &length, &gerror)) { smlSafeCFree(&absolute); goto gerror; } smlSafeCFree(&absolute); if (!smlDataSyncAddChange(dsObject, datastore->source, changeType, filename, data, length, NULL, error)) goto error; smlSafeCFree(&data); } g_dir_close(dir); dir = NULL; } smlTrace(TRACE_EXIT, "%s", __func__); return smlDataSyncSendChanges(dsObject, error); gerror: smlErrorSet(error, SML_ERROR_GENERIC, gerror->message); g_error_free(gerror); error: smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(error)); return FALSE; } static void recvEventCallback( SmlDataSyncObject *dsObject, SmlDataSyncEventType type, void *userdata, SmlError *error) { smlTrace(TRACE_ENTRY, "%s(%p, %i, %p, %p)", __func__, dsObject, type, userdata, error); SmlError *locerror = NULL; switch (type) { case SML_DATA_SYNC_EVENT_ERROR: writeSyncStatus(FALSE); g_message("ERROR: %s\n", smlErrorPrint(&error)); smlErrorDeref(&error); exit(2); break; case SML_DATA_SYNC_EVENT_CONNECT: g_message("Remote device was successfully connected."); break; case SML_DATA_SYNC_EVENT_DISCONNECT: g_message("Remote device was successfully disconnected."); break; case SML_DATA_SYNC_EVENT_FINISHED: g_message("SyncML session finished successfully."); writeSyncStatus(TRUE); g_mutex_unlock(runMutex); break; case SML_DATA_SYNC_EVENT_GOT_ALL_ALERTS: g_message("All alerts of the remote device were received."); if (sessionType == SML_SESSION_TYPE_CLIENT) { if (!sendAllChanges(dsObject, &locerror)) goto error; } break; case SML_DATA_SYNC_EVENT_GOT_ALL_CHANGES: g_message("All changes of the remote device were received."); if (sessionType == SML_SESSION_TYPE_SERVER) { if (!sendAllChanges(dsObject, &locerror)) goto error; } /* the map of the client is send automatically */ break; case SML_DATA_SYNC_EVENT_GOT_ALL_MAPPINGS: if (sessionType == SML_SESSION_TYPE_SERVER) { g_message("All mappings of the remote device were received."); } else { g_error("Received a map but I'm a client!"); } break; default: g_error("Unknown event(%d).\n", type); break; } smlTrace(TRACE_EXIT, "%s", __func__); return; error: fprintf(stderr, "An error occured while handling events: %s\n", smlErrorPrint(&locerror)); smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(&locerror)); smlErrorDeref(&locerror); exit(3); } static char * getSafeFilename(const char *filename) { SmlBool clean = TRUE; size_t i; for (i=0; i < strlen(filename); i++) { if (!g_ascii_isalnum(filename[i]) && filename[i] != '-' && filename[i] != '_') clean = FALSE; } if (clean) { return g_strdup(filename); } else { return g_base64_encode((const unsigned char *) filename, strlen(filename)); } } static SmlBool recvChangeCallback( SmlDataSyncObject *dsObject, const char *source, SmlChangeType type, const char *uid, char *data, unsigned int size, void *userdata, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %s, %d, %s, %p, %d, %p, %p)", __func__, dsObject, VA_STRING(source), type, VA_STRING(uid), data, size, userdata, error); char *absolute_uid = NULL; char *absolute_status = NULL; /* find the appropriate datasoure */ SmlDsToolLocationType *datastore = NULL; GList *o = datastores; while (o) { datastore = o->data; if (!strcmp(datastore->source, source)) { /* abort the scan */ o = NULL; } else { datastore = NULL; } if (o) o = o->next; } smlTrace(TRACE_INTERNAL, "%s: datastores scanned", __func__); /* handle the item */ if (datastore) { if (datastore->directory) { printf("Writing item %s to directory %s.\n", uid, datastore->directory); /* prepare absolute filenames */ char *safeUID = getSafeFilename(uid); absolute_uid = g_strdup_printf("%s/%s", datastore->directory, safeUID); absolute_status = g_strdup_printf("%s/%s", datastore->directory, STATUS_FILENAME); /* sanity check for uid */ if (!strcmp(safeUID, STATUS_FILENAME)) { smlErrorSet(error, SML_ERROR_GENERIC, "The filename %s cannot be used as UID. This is a potential attack.", STATUS_FILENAME); printf("\tIllegal filename %s detected.\n", STATUS_FILENAME); g_warning("Potential attack against status file %s detected.", STATUS_FILENAME); goto error; } smlSafeCFree(&safeUID); /* cache that the remote device knows the uid */ if (datastore->remoteHash) { g_hash_table_insert(datastore->remoteHash, g_strdup(absolute_uid), (char *)"1"); } /* the directory is checked by scanArguments */ SmlBool doWrite = FALSE; if (!doWrite && !g_file_test(absolute_uid, G_FILE_TEST_EXISTS)) doWrite = TRUE; if (!doWrite && sessionType == SML_SESSION_TYPE_CLIENT) doWrite = TRUE; if (!doWrite && !localWinsConflicts) doWrite = TRUE; if (!doWrite && g_file_test(absolute_status, G_FILE_TEST_EXISTS)) { if (datastore->slow) { /* We have to check the content. * If the content is identical * then we simply touch the file * to commit it. The file will * not be uploaded because of the * new timestamp. */ char *remoteData = NULL; gsize remoteSize = 0; if (g_file_get_contents(absolute_uid, &remoteData, &remoteSize, NULL) && remoteSize == size && !strncmp(data, remoteData, size)) g_file_set_contents(absolute_uid, data, size, NULL); } else { //!datastore->slow /* let's check if there is a local change */ struct stat fdata; struct stat status; if (g_stat(absolute_uid, &fdata) != 0) { smlErrorSet(error, SML_ERROR_GENERIC, "Cannot stat uid file %s (%d).", absolute_uid, errno); goto error; } if (g_stat(absolute_status, &status) != 0) { smlErrorSet(error, SML_ERROR_GENERIC, "Cannot stat status file %s (%d).", absolute_status, errno); goto error; } if (status.st_mtime > fdata.st_mtime) doWrite = TRUE; } } printf("\tConflicts were checked.\n"); /* write the change */ if (doWrite) { if (type == SML_CHANGE_DELETE) { g_unlink(absolute_uid); printf("\tThe item was successfully deleted.\n"); } else { GError *gerror = NULL; if (!g_file_set_contents(absolute_uid, data, size, &gerror)) { smlErrorSet(error, SML_ERROR_GENERIC, "Cannot write data to %s. %s", absolute_uid, gerror->message); g_error_free(gerror); goto error; } printf("\tThe item was successfully written.\n"); } } else { printf("\tThe item was not touched.\n"); } /* free absolute filenames */ smlSafeCFree(&absolute_uid); smlSafeCFree(&absolute_status); } else { /* print received change */ printf("-----BEGIN CHANGE-----\n"); if (type == SML_CHANGE_DELETE) printf("DELETE %s\n", uid); else printf("%s", data); printf("-----END CHANGE-----\n"); } } smlTrace(TRACE_EXIT, "%s - TRUE", __func__); return TRUE; error: if (absolute_uid) smlSafeCFree(&absolute_uid); if (absolute_status) smlSafeCFree(&absolute_status); smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(error)); return FALSE; } static SmlBool recvDevInfCallback( SmlDataSyncObject *dsObject, SmlDevInf *devinf, void *userdata, SmlError **error) { smlTrace(TRACE_INTERNAL, "%s(%p, %p, %p, %p)", dsObject, devinf, userdata, error); printf("Received device information.\n"); remoteDevinf = devinf; smlDevInfRef(remoteDevinf); return TRUE; } static SmlAlertType recvAlertTypeCallback( SmlDataSyncObject *dsObject, const char *source, SmlAlertType type, void *userdata, SmlError **error) { smlTrace(TRACE_ENTRY, "%s(%p, %s, %d, %p, %p)", __func__, dsObject, VA_STRING(source), type, userdata, error); /* find the appropriate datasoure */ SmlDsToolLocationType *datastore = NULL; GList *o = datastores; while (o) { datastore = o->data; if (!strcmp(datastore->source, source)) { /* abort the scan */ o = NULL; } else { datastore = NULL; } if (o) o = o->next; } if (!datastore) { smlErrorSet(error, SML_ERROR_GENERIC, "Cannot found datastore %s.", source); goto error; } smlTrace(TRACE_INTERNAL, "%s: datastores scanned", __func__); /* synchronize the alert type */ if (type == SML_ALERT_SLOW_SYNC) datastore->slow = TRUE; if (datastore->slow) type = SML_ALERT_SLOW_SYNC; smlTrace(TRACE_EXIT, "%s - slow == %d", __func__, datastore->slow); return type; error: smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(error)); return SML_ALERT_UNKNOWN; } #ifdef ENABLE_OBEX /* directly copied from syncml-obex-client */ static void discover_cb(obex_t *handle, obex_object_t *object, int mode, int event, int obex_cmd, int obex_rsp) { (void) handle; (void) object; (void) mode; (void) event; (void) obex_cmd; (void) obex_rsp; } void list_interfaces() { obex_t *handle; obex_interface_t* obex_intf; int i, interfaces_number = 0; if(!(handle = OBEX_Init(OBEX_TRANS_USB, discover_cb, 0))) { printf("OBEX_Init failed\n"); return; } if (geteuid() != 0) fprintf(stderr, "Superuser privileges are required to access complete USB information.\n"); interfaces_number = OBEX_FindInterfaces(handle, &obex_intf); printf("Found %d USB OBEX interfaces\n", interfaces_number); for (i = 0; i < interfaces_number; i++) printf("Interface %d:\n\tManufacturer: %s\n\tProduct: %s\n\tInterface description: %s\n", i, obex_intf[i].usb.manufacturer, obex_intf[i].usb.product, obex_intf[i].usb.control_interface); printf("Use '-u interface_number' to connect\n"); OBEX_Cleanup(handle); } #endif /* ************************************ */ /* *********** USAGE ****************** */ /* ************************************ */ /* This usage message is from syncml-obex-client.c * FIXME: It must be replaced by a new message. */ static void usage (char *name) { fprintf(stderr, "Usage: %s\n\n", name); fprintf(stderr, "\tDatastore configuration:\n"); fprintf(stderr, "\t========================\n\n"); fprintf(stderr, "\t--sync \tnormal two-way sync\n"); fprintf(stderr, "\t--slow-sync \tslow two-way sync\n\n"); fprintf(stderr, "\t\tis the content-type of a datastore\n"); fprintf(stderr, "\t\ttext/x-vcard for contacts\n"); fprintf(stderr, "\t\ttext/x-vcalendar for calendar\n"); fprintf(stderr, "\t\ttext/plain for notes\n"); fprintf(stderr, "\t\ttext/x-vMessage for SMS\n"); fprintf(stderr, "\t\tis the used (virtual) source URL/path\n"); fprintf(stderr, "\t\tIt is the local name of the database.\n"); fprintf(stderr, "\t\tYou can choose something there.\n"); fprintf(stderr, "\t\tis the local path to the synchronized directory\n"); fprintf(stderr, "\t\tThe directory is optional and an absolute path.\n"); fprintf(stderr, "\t\tThis directory is a persistent storage.\n\n"); fprintf(stderr, "\tHTTP client configuration:\n"); fprintf(stderr, "\t==========================\n\n"); fprintf(stderr, "\t--http-client \n\n"); fprintf(stderr, "\t--ssl-ca-certs \n\n"); fprintf(stderr, "\t\tmust be an http URL like http://localhost:8080\n\n"); fprintf(stderr, "\tHTTP server configuration:\n"); fprintf(stderr, "\t==========================\n\n"); fprintf(stderr, "\t--http-server \n"); fprintf(stderr, "\t--ssl-key \n"); fprintf(stderr, "\t--ssl-cert \n\n"); fprintf(stderr, "\t\tmust be a port for the http server.\n\n"); fprintf(stderr, "\tOBEX client configuration:\n"); fprintf(stderr, "\t==========================\n\n"); fprintf(stderr, "\t-s \tConnect to the serial device.\n"); fprintf(stderr, "\t-u\t\tList all available USB interfaces.\n"); fprintf(stderr, "\t-u \t\tConnect to the given usb interface number.\n"); fprintf(stderr, "\t-b \tConnect to the given bluetooth device.\n"); fprintf(stderr, "\t--ip \tConnect to this TCP/IP address.\n"); fprintf(stderr, "\t--irda\t\tConnect using IrDA.\n"); fprintf(stderr, "\t--irda-service \tUse the given IrDA service (default: OBEX).\n\n"); fprintf(stderr, "\tOBEX server configuration:\n"); fprintf(stderr, "\t==========================\n\n"); fprintf(stderr, "\t--port \tListen to this TCP/IP port.\n\n"); fprintf(stderr, "\tGeneral SyncML options:\n"); fprintf(stderr, "\t=======================\n\n"); fprintf(stderr, "\t--identifier \tsets the local identity of the SyncML (source).\n"); fprintf(stderr, "\t--target \tsets the remote identity of SyncML (target).\n"); fprintf(stderr, "\t--username \tsets the username for authentication.\n"); fprintf(stderr, "\t--password \tsets the password for authentication.\n"); fprintf(stderr, "\t--maxMsgSize \tsets the maximum message size (default: %s)\n", maxMsgSize); fprintf(stderr, "\t--maxObjSize \tsets the maximum object size (default: %s)\n", maxObjSize); fprintf(stderr, "\t--useStringTable\tUse wbxml string tables (default: NEVER EVER)\n"); fprintf(stderr, "\t--disableNumberOfChanges\tthe most new phones support it (default: enabled)\n"); fprintf(stderr, "\t--useNumberAnchor\t\tUse numbers as anchors.\n"); fprintf(stderr, "\t--useLocaltime\t\tUse localtime instead of UTC.\n"); fprintf(stderr, "\t--wbxml\t\t\tUse wbxml (WAP Binary XML) instead of plain xml.\n"); fprintf(stderr, "\t--read-only\t\tno write actions will be performed.\n"); fprintf(stderr, "\t--remoteWinsConflicts\tIf there is a conflict then the remote change wins.\n"); fprintf(stderr, "\t\t\t\tThe default is local wins always.\n"); fprintf(stderr, "\t\t\t\tThis option is only usable in OMA DS server mode.\n"); fprintf(stderr, "\t--dumpinfo\t\tPrint info about the phone.\n"); fprintf(stderr, "\t--version\t\tprints the version of the tool.\n"); fprintf(stderr, "\t--version \tsets the SyncML version.\n\n"); fprintf(stderr, "\t\tSome devices require a special identity string.\n"); fprintf(stderr, "\t\tNokias for example often requires \"PC Suite\".\n"); fprintf(stderr, "\t\tPlease use --identifier \"PC Suite\" in this case.\n"); fprintf(stderr, "\t\tcan be \"1.0\", \"1.1\" or \"1.2\".\n"); fprintf(stderr, "\t\tThe default version is \"1.1\".\n\n"); fprintf(stderr, "\tDevice faking configuration:\n"); fprintf(stderr, "\t============================\n\n"); fprintf(stderr, "\t--fake-manufacturer \tset the manufacturer of the faked device.\n"); fprintf(stderr, "\t--fake-model \t\tset the model of the faked device.\n"); fprintf(stderr, "\t--fake-software-version \tset the software version of the faked device.\n"); fprintf(stderr, "\n"); exit (1); } SmlTransportType getTransportType(int argc, char *argv[]) { smlTrace(TRACE_ENTRY, "%s", __func__); SmlTransportType tspType = SML_TRANSPORT_OBEX_CLIENT; int i = 0; for (i = 1; i < argc; i++) { char *arg = argv[i]; if (!strcmp (arg, "--http-client")) { tspType = SML_TRANSPORT_HTTP_CLIENT; } else if (!strcmp (arg, "--http-server")) { tspType = SML_TRANSPORT_HTTP_SERVER; } else if (!strcmp (arg, "--port")) { tspType = SML_TRANSPORT_OBEX_SERVER; } } smlTrace(TRACE_EXIT, "%s - %d", __func__, tspType); return tspType; } SmlSessionType getSessionType(int argc, char *argv[]) { smlTrace(TRACE_ENTRY, "%s", __func__); SmlSessionType type = SML_SESSION_TYPE_SERVER; int i = 0; for (i = 1; i < argc; i++) { char *arg = argv[i]; if (!strcmp (arg, "--http-client")) { type = SML_SESSION_TYPE_CLIENT; } else if (!strcmp (arg, "--http-server")) { type = SML_SESSION_TYPE_SERVER; } else if (!strcmp (arg, "--port")) { /* this is not a typo */ type = SML_SESSION_TYPE_CLIENT; } } smlTrace(TRACE_EXIT, "%s - %d", __func__, type); return type; } SmlBool scanArguments( SmlDataSyncObject *dsObject, int argc, char *argv[], SmlError **error) { smlTrace(TRACE_ENTRY, "%s", __func__); if (argc == 1) usage (argv[0]); maxMsgSize = g_strdup("65535"); maxObjSize = g_strdup("3000000"); int i = 0; for (i = 1; i < argc; i++) { char *arg = argv[i]; if (!strcmp (arg, "--sync") || !strcmp(arg, "--slow-sync")) { /* prepare datastore */ SmlDsToolLocationType *datastore = NULL; datastore = (SmlDsToolLocationType *) smlTryMalloc0(sizeof(SmlDsToolLocationType), error); if (!datastore) goto error; datastores = g_list_append(datastores, datastore); /* sync type */ if (!strcmp(arg, "--slow-sync")) datastore->slow = TRUE; else datastore->slow = FALSE; /* load content type */ i++; if (!argv[i]) usage (argv[0]); datastore->contentType = argv[i]; if (!strstr(argv[i], "/")) fprintf(stderr, "WARNING: Specified database type \"%s\" doesn't look like a valid MIME type!\n" "WARNING: (Mixed up database path/location with database type?)\n", argv[i]); /* load location */ i++; if (!argv[i]) usage (argv[0]); datastore->source = argv[i]; /* load directory if available */ if (argv[i+1] && argv[i+1][0] != '-') { i++; datastore->directory = argv[i]; /* check the directory */ if (g_mkdir_with_parents(datastore->directory, 0700) != 0) { smlErrorSet(error, SML_ERROR_INTERNAL_MISCONFIGURATION, "There is a problem with the directory %s (%d).", datastore->directory, errno); goto error; } } else { datastore->directory = NULL; } /* init uid hash table if it is an OMA DS server */ if (sessionType == SML_SESSION_TYPE_SERVER) datastore->remoteHash = g_hash_table_new(g_str_hash, g_str_equal); /* register datastore */ if (!smlDataSyncAddDatastore( dsObject, datastore->contentType, NULL, datastore->source, error)) goto error; } else if (!strcmp (arg, "-u")) { if (!smlDataSyncSetOption( dsObject, SML_DATA_SYNC_CONFIG_CONNECTION_TYPE, SML_DATA_SYNC_CONFIG_CONNECTION_USB, error)) goto error; i++; if (!argv[i]) { #ifdef ENABLE_OBEX list_interfaces(); return 0; #else printf("OBEX not available in this build\n"); return 1; #endif } if (!smlDataSyncSetOption( dsObject, SML_TRANSPORT_CONFIG_PORT, argv[i], error)) goto error; } else if (!strcmp (arg, "-b")) { #ifdef ENABLE_BLUETOOTH if (!smlDataSyncSetOption( dsObject, SML_DATA_SYNC_CONFIG_CONNECTION_TYPE, SML_DATA_SYNC_CONFIG_CONNECTION_BLUETOOTH, error)) goto error; i++; if (!argv[i]) usage (argv[0]); if (!smlDataSyncSetOption( dsObject, SML_TRANSPORT_CONFIG_BLUETOOTH_ADDRESS, argv[i], error)) goto error; i++; if (!argv[i]) usage (argv[0]); if (!smlDataSyncSetOption( dsObject, SML_TRANSPORT_CONFIG_BLUETOOTH_CHANNEL, argv[i], error)) goto error; #else printf("Bluetooth is not available in this build\n"); return 1; #endif } else if (!strcmp (arg, "--irda")) { if (!smlDataSyncSetOption( dsObject, SML_DATA_SYNC_CONFIG_CONNECTION_TYPE, SML_DATA_SYNC_CONFIG_CONNECTION_IRDA, error)) goto error; } else if (!strcmp (arg, "--irda-service")) { if (!smlDataSyncSetOption( dsObject, SML_DATA_SYNC_CONFIG_CONNECTION_TYPE, SML_DATA_SYNC_CONFIG_CONNECTION_IRDA, error)) goto error; i++; if (!argv[i]) usage (argv[0]); if (!smlDataSyncSetOption( dsObject, SML_TRANSPORT_CONFIG_IRDA_SERVICE, argv[i], error)) goto error; } else if (!strcmp (arg, "-s")) { if (!smlDataSyncSetOption( dsObject, SML_DATA_SYNC_CONFIG_CONNECTION_TYPE, SML_DATA_SYNC_CONFIG_CONNECTION_SERIAL, error)) goto error; i++; if (!argv[i]) usage (argv[0]); if (!smlDataSyncSetOption( dsObject, SML_TRANSPORT_CONFIG_URL, argv[i], error)) goto error; } else if (!strcmp (arg, "--channel")) { #ifdef ENABLE_BLUETOOTH if (!smlDataSyncSetOption( dsObject, SML_DATA_SYNC_CONFIG_CONNECTION_TYPE, SML_DATA_SYNC_CONFIG_CONNECTION_BLUETOOTH, error)) goto error; i++; if (!argv[i]) usage (argv[0]); if (!smlDataSyncSetOption( dsObject, SML_TRANSPORT_CONFIG_BLUETOOTH_CHANNEL, argv[i], error)) goto error; #else printf("Bluetooth is not available in this build\n"); return 1; #endif } else if (!strcmp (arg, "--ip")) { if (!smlDataSyncSetOption( dsObject, SML_DATA_SYNC_CONFIG_CONNECTION_TYPE, SML_DATA_SYNC_CONFIG_CONNECTION_NET, error)) goto error; i++; if (!argv[i]) usage (argv[0]); if (!smlDataSyncSetOption( dsObject, SML_TRANSPORT_CONFIG_URL, argv[i], error)) goto error; i++; if (!argv[i]) usage (argv[0]); if (!smlDataSyncSetOption( dsObject, SML_TRANSPORT_CONFIG_PORT, argv[i], error)) goto error; } else if (!strcmp (arg, "--port")) { if (!smlDataSyncSetOption( dsObject, SML_DATA_SYNC_CONFIG_CONNECTION_TYPE, SML_DATA_SYNC_CONFIG_CONNECTION_NET, error)) goto error; i++; if (!argv[i]) usage (argv[0]); if (!smlDataSyncSetOption( dsObject, SML_TRANSPORT_CONFIG_PORT, argv[i], error)) goto error; } else if (!strcmp (arg, "--identifier")) { i++; if (!argv[i]) usage (argv[0]); if (!smlDataSyncSetOption( dsObject, SML_DATA_SYNC_CONFIG_IDENTIFIER, argv[i], error)) goto error; identifier = g_strdup(argv[i]); } else if (!strcmp (arg, "--target")) { i++; if (!argv[i]) usage (argv[0]); if (!smlDataSyncSetOption( dsObject, SML_DATA_SYNC_CONFIG_TARGET, argv[i], error)) goto error; target = g_strdup(argv[i]); } else if (!strcmp (arg, "--username")) { i++; if (!argv[i]) usage (argv[0]); if (!smlDataSyncSetOption( dsObject, SML_DATA_SYNC_CONFIG_AUTH_USERNAME, argv[i], error)) goto error; } else if (!strcmp (arg, "--password")) { i++; if (!argv[i]) usage (argv[0]); if (!smlDataSyncSetOption( dsObject, SML_DATA_SYNC_CONFIG_AUTH_PASSWORD, argv[i], error)) goto error; } else if (!strcmp (arg, "--maxMsgSize")) { i++; if (!argv[i]) usage (argv[0]); maxMsgSize = argv[i]; if (!smlDataSyncSetOption( dsObject, SML_DATA_SYNC_CONFIG_MAX_MSG_SIZE, maxMsgSize, error)) goto error; } else if (!strcmp (arg, "--maxObjSize")) { i++; if (!argv[i]) usage (argv[0]); maxObjSize = argv[i]; if (!smlDataSyncSetOption( dsObject, SML_DATA_SYNC_CONFIG_MAX_OBJ_SIZE, maxObjSize, error)) goto error; } else if (!strcmp (arg, "--useStringTable")) { if (!smlDataSyncSetOption( dsObject, SML_DATA_SYNC_CONFIG_USE_STRING_TABLE, "1", error)) goto error; } else if (!strcmp (arg, "--disableNumberOfChanges")) { if (!smlDataSyncSetOption( dsObject, SML_DATA_SYNC_CONFIG_USE_NUMBER_OF_CHANGES, "0", error)) goto error; } else if (!strcmp (arg, "--useNumberAnchor")) { if (!smlDataSyncSetOption( dsObject, SML_DATA_SYNC_CONFIG_USE_TIMESTAMP_ANCHOR, "0", error)) goto error; } else if (!strcmp (arg, "--useLocaltime")) { if (!smlDataSyncSetOption( dsObject, SML_DATA_SYNC_CONFIG_USE_LOCALTIME, "1", error)) goto error; } else if (!strcmp (arg, "--version")) { i++; if (!argv[i]) { fprintf(stdout, "Version: %s ($Revision: 1075 $)\n", VERSION); return 0; } if (!smlDataSyncSetOption( dsObject, SML_DATA_SYNC_CONFIG_VERSION, argv[i], error)) goto error; syncmlVersion = g_strdup(argv[i]); } else if (!strcmp (arg, "--help")) { usage (argv[0]); } else if (!strcmp (arg, "--wbxml")) { if (!smlDataSyncSetOption( dsObject, SML_DATA_SYNC_CONFIG_USE_WBXML, "1", error)) goto error; mimeType = SML_MIMETYPE_WBXML; } else if (!strcmp (arg, "--dumpinfo")) { dumpinfo = TRUE; smlDataSyncRegisterHandleRemoteDevInfCallback(dsObject, recvDevInfCallback, NULL); } else if (!strcmp (arg, "--remoteWinsConflicts")) { localWinsConflicts = FALSE; if (sessionType == SML_SESSION_TYPE_CLIENT) usage(argv[0]); } else if (!strcmp(arg, "--read-only")) { readOnly = TRUE; } else if (!strcmp (arg, "--http-client")) { i++; if (!argv[i]) usage (argv[0]); if (!smlDataSyncSetOption( dsObject, SML_TRANSPORT_CONFIG_URL, argv[i], error)) goto error; } else if (!strcmp (arg, "--ssl-ca-certs")) { i++; if (!argv[i]) usage (argv[0]); if (!smlDataSyncSetOption( dsObject, SML_TRANSPORT_CONFIG_SSL_CA_FILE, argv[i], error)) goto error; } else if (!strcmp (arg, "--http-server")) { i++; if (!argv[i]) usage (argv[0]); if (!smlDataSyncSetOption( dsObject, SML_TRANSPORT_CONFIG_PORT, argv[i], error)) goto error; } else if (!strcmp (arg, "--ssl-key")) { i++; if (!argv[i]) usage (argv[0]); if (!smlDataSyncSetOption( dsObject, SML_TRANSPORT_CONFIG_SSL_KEY, argv[i], error)) goto error; } else if (!strcmp (arg, "--ssl-cert")) { i++; if (!argv[i]) usage (argv[0]); if (!smlDataSyncSetOption( dsObject, SML_TRANSPORT_CONFIG_SSL_SERVER_CERT, argv[i], error)) goto error; } else if (!strcmp (arg, "--fake-manufacturer")) { i++; if (!argv[i]) usage (argv[0]); if (!smlDataSyncSetOption( dsObject, SML_DATA_SYNC_CONFIG_FAKE_DEVICE, "1", error)) goto error; if (!smlDataSyncSetOption( dsObject, SML_DATA_SYNC_CONFIG_FAKE_MANUFACTURER, argv[i], error)) goto error; } else if (!strcmp (arg, "--fake-model")) { i++; if (!argv[i]) usage (argv[0]); if (!smlDataSyncSetOption( dsObject, SML_DATA_SYNC_CONFIG_FAKE_DEVICE, "1", error)) goto error; if (!smlDataSyncSetOption( dsObject, SML_DATA_SYNC_CONFIG_FAKE_MODEL, argv[i], error)) goto error; } else if (!strcmp (arg, "--fake-software-version")) { i++; if (!argv[i]) usage (argv[0]); if (!smlDataSyncSetOption( dsObject, SML_DATA_SYNC_CONFIG_FAKE_DEVICE, "1", error)) goto error; if (!smlDataSyncSetOption( dsObject, SML_DATA_SYNC_CONFIG_FAKE_SOFTWARE_VERSION, argv[i], error)) goto error; } else if (!strcmp (arg, "--")) { break; } else { g_warning("Unknown parameter: %s", arg); usage (argv[0]); } } if (g_list_length(datastores) == 0) { if (syncmlVersion == NULL || strcmp(syncmlVersion, "1.2")) { smlErrorSet(error, SML_ERROR_GENERIC, "You have to configure at least one database"); goto error; } else { printf("All datastores will be requested because no datastore is configured.\n"); } } smlTrace(TRACE_EXIT, "%s - TRUE", __func__); return TRUE; error: smlTrace(TRACE_EXIT_ERROR, "Failed to start the client: %s\n", smlErrorPrint(error)); return FALSE; } /* ************************************ */ /* ************** TOOL **************** */ /* ************************************ */ int main(int argc, char *argv[]) { SmlError *error = NULL; if (!g_thread_supported ()) g_thread_init (NULL); /* init DS object */ SmlTransportType tspType = getTransportType(argc, argv); sessionType = getSessionType(argc, argv); SmlDataSyncObject *dsObject = smlDataSyncNew(sessionType, tspType, &error); if (!dsObject) goto error; if (!scanArguments(dsObject, argc, argv, &error)) goto error; smlDataSyncRegisterEventCallback(dsObject, recvEventCallback, NULL); smlDataSyncRegisterGetAlertTypeCallback(dsObject, recvAlertTypeCallback, NULL); smlDataSyncRegisterChangeCallback(dsObject, recvChangeCallback, NULL); // smlDataSyncRegisterChangeStatusCallback(dsObject, recvChangeStatusCallback); // smlDataSyncRegisterMappingCallback(dsObject, recvMappingCallback, NULL); if (!smlDataSyncInit(dsObject, &error)) goto error; /* run the sync */ checkpoint = time(NULL); if (!smlDataSyncRun(dsObject, &error)) goto error; runMutex = g_mutex_new(); g_mutex_lock(runMutex); g_mutex_lock(runMutex); g_mutex_unlock(runMutex); g_mutex_free(runMutex); runMutex = NULL; /* dump some information */ if (dumpinfo) { if (!remoteDevinf) { printf("Didn't receive the device information though it was requested.\n"); } else { printf("Send the output below to the libsyncml developers\n"); printf("\n========================================\n"); printf("Man: %s\n", smlDevInfGetManufacturer(remoteDevinf)); printf("Mod: %s\n", smlDevInfGetModel(remoteDevinf)); printf("FirmwareVersion: %s\n", smlDevInfGetFirmwareVersion(remoteDevinf)); printf("SoftwareVersion: %s\n", smlDevInfGetSoftwareVersion(remoteDevinf)); printf("HardwareVersion: %s\n", smlDevInfGetHardwareVersion(remoteDevinf)); printf("\n"); printf("MaxMsgSize: %s\n", maxMsgSize); printf("MaxObjSize: %s\n", maxObjSize); printf("Transport used: "); switch(tspType) { case SML_TRANSPORT_HTTP_CLIENT: printf("HTTP client\n"); break; case SML_TRANSPORT_HTTP_SERVER: printf("HTTP server\n"); break; case SML_TRANSPORT_OBEX_CLIENT: printf("OBEX client\n"); break; default: printf("unknown\n"); break; } printf("OMA DS mode used: "); switch(sessionType) { case SML_SESSION_TYPE_CLIENT: printf("client\n"); break; case SML_SESSION_TYPE_SERVER: printf("server\n"); break; default: printf("unknown\n"); break; } printf("Identifier (Source): %s \n", identifier); printf("Target: %s\n", target); printf("\nDatastores:\n"); unsigned int i = 0; for (i = 0; i < smlDevInfNumDataStores(remoteDevinf); i++) { const SmlDevInfDataStore *datastore = smlDevInfGetNthDataStore(remoteDevinf, i); printf("\tLocations: %s\n", smlDevInfDataStoreGetSourceRef(datastore)); } printf("Wbxml: %s\n", mimeType == SML_MIMETYPE_WBXML ? "Yes" : "No"); printf("SyncML Version: %s\n", syncmlVersion); printf("SupportsUTC: %s\n", smlDevInfSupportsUTC(remoteDevinf) ? "Yes" : "No"); printf("SupportsNumberOfChanges: %s\n", smlDevInfSupportsNumberOfChanges(remoteDevinf) ? "Yes" : "No"); printf("SupportsLargeObjects: %s\n", smlDevInfSupportsLargeObjs(remoteDevinf) ? "Yes" : "No"); smlDevInfUnref(remoteDevinf); printf("\nlibsyncml Version: %s ($Revision: 1075 $)\n", VERSION); } } /* close the object */ smlDataSyncObjectUnref(&dsObject); return 0; error: if (error != NULL) { fprintf(stderr, "ERROR: %s\n", smlErrorPrint(&error)); smlErrorDeref(&error); } return 1; } libsyncml-0.5.4/README100644 1750 1750 74 11211710410 14242 0ustar00bellmichbellmichlibsyncml - C library implementation of the SyncML protocol