pax_global_header00006660000000000000000000000064147603356070014525gustar00rootroot0000000000000052 comment=a7278128f1f01653f1d414d7c453be36bfd8f8c3 buteo-sync-plugins-0.8.36/000077500000000000000000000000001476033560700153725ustar00rootroot00000000000000buteo-sync-plugins-0.8.36/.gitignore000066400000000000000000000003671476033560700173700ustar00rootroot00000000000000Makefile *.so* *.o *.gcno moc_*.cpp *.list *.prl *.tag doc/html storageplugins/hcontacts/unittest/hcontacts-tests syncmlcommon/pkgconfig/ /storageplugins/hcalendar/unittest/hcalendar-tests /storageplugins/hnotes/unittest/hnotes-tests /utils/utils buteo-sync-plugins-0.8.36/COPYING000066400000000000000000000635271476033560700164420ustar00rootroot00000000000000GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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! buteo-sync-plugins-0.8.36/bin/000077500000000000000000000000001476033560700161425ustar00rootroot00000000000000buteo-sync-plugins-0.8.36/bin/gcov_info.pl000066400000000000000000000045631476033560700204600ustar00rootroot00000000000000#!/usr/bin/perl #/* # * This file is part of buteo-sync-plugins package # * # * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). # * # * Contact: Sateesh Kavuri # * # * This library is free software; you can redistribute it and/or # * modify it under the terms of the GNU Lesser General Public License # * version 2.1 as published by the Free Software Foundation. # * # * This library is distributed in the hope that it will be useful, but # * WITHOUT ANY WARRANTY; without even the implied warranty of # * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # * Lesser General Public License for more details. # * # * You should have received a copy of the GNU Lesser General Public # * License along with this library; if not, write to the Free Software # * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA # * 02110-1301 USA # * # */ # Author : Srikanth Kavoori # Not Tested fully yet. There could be some issues. # If you see any issues Let me know and i shall fix it :) open(INPUTFILE, "<$ARGV[0]"); open(EXTRACTED_INFO,">$ARGV[2]"); open(EXTRACTED_FILES,">$ARGV[3]"); $exclude_string = "/usr/include/"; $exclude_string2 = ".h"; $coverage_count_string ="Lines executed:"; $include_string = ".cpp"; $count = 0; $filecount = 0; $coverage_percent = 0; while() { my($line) = $_; if ($count == 3) { $count = 0; } if(/$exclude_string/ || /$exclude_string2/) { #print "Found usr_include or header file on line $. \n" ; $count ++; } if( /$include_string/ ) { $count = 0; } if ($count == 0) { # Print the line to the extracted_info and add a newline print EXTRACTED_INFO "$line\n"; if(/$coverage_count_string/) { $filecount ++; $index = rindex($line,':') + 1; $percent = substr($line,$index); $perc_index = rindex($percent,'%'); $percent = substr($percent,0,$perc_index); $coverage_percent += $percent; } } else { #count should be 1 or 2 omit the line $count ++; } } if($filecount != 0 ) { $coverage_percent=sprintf("%.2f",$coverage_percent/$filecount); } print "Total No. of files : $filecount Coverage Percent : $coverage_percent "; print EXTRACTED_INFO "Total No. of files : $filecount Coverage Percent : $coverage_percent "; open(PERCENTFILE,">$ARGV[1]"); print PERCENTFILE "$coverage_percent\n" ; close(PERCENTFILE); close(INPUTFILE); close(EXTRACTED_INFO); close(EXTRACTED_FILES); buteo-sync-plugins-0.8.36/bin/run-tests-sync-app.sh000077500000000000000000000107411476033560700222000ustar00rootroot00000000000000#!/bin/bash #/* # * This file is part of buteo-sync-plugins package # * # * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). # * # * Contact: Sateesh Kavuri # * # * This library is free software; you can redistribute it and/or # * modify it under the terms of the GNU Lesser General Public License # * version 2.1 as published by the Free Software Foundation. # * # * This library is distributed in the hope that it will be useful, but # * WITHOUT ANY WARRANTY; without even the implied warranty of # * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # * Lesser General Public License for more details. # * # * You should have received a copy of the GNU Lesser General Public # * License along with this library; if not, write to the Free Software # * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA # * 02110-1301 USA # * # */ #Author - Srikanth Kavoori # This file should run unittests for sync-app # and create the result file with unittest rate # and coverage to this folder with name # sync-app-results # # The release number should be in the file # this script generates the results automatically # for the latest weekXxX directory under sync-app #this script updation should be rarely needed #Script Specific Variables TARGET=sync-app TARGET_WEEK=week$(date +%V)$(date +%G) if [ $# == 0 ]; then WD=$PWD ROOTDIR=$WD/.. RESULTS_FILE=$TARGET-results_$TARGET_WEEK else WD=$1 TARGET_WEEK=$(ls -c $WD/../$TARGET | head -1) echo "TARGET WEEK is $TARGET_WEEK" ROOTDIR=$WD/../$TARGET/$TARGET_WEEK echo "ROOTDIR is $ROOTDIR" echo $1 RESULTS_DIR=$2 echo "RESULTS_DIR is $RESULTS_DIR" RESULTS_FILE=$RESULTS_DIR/$TARGET-results_$TARGET_WEEK fi echo "if running inside scratchbox use export SBOX_USE_CCACHE=no and ccache -c commands for gcov to work" PLUGINS=(clientplugins storageplugins syncmlcommon) #PLUGINTARGETS=(syncmlclient hcalendar hcontacts hbookmarks hnotes unittest) PLUGINTARGETS=(syncmlclient hcalendar hcontacts hnotes unittest) TEMPFILE1=$WD/.temp_results if [ -f $TEMPFILE1 ] then rm -f $TEMPFILE1 fi TEMPFILE2=$WD/.gcov_info.txt if [ -f $TEMPFILE2 ] then rm -f $TEMPFILE2 fi TEMPFILE3=$WD/.percent if [ -f $TEMPFILE3 ] then rm -f $TEMPFILE3 fi echo "Running the unit tests for $TARGET..." echo "Results will be stored in: $RESULTS_FILE ...." cd $ROOTDIR echo ${PLUGINS[@]} echo ${PLUGINTARGETS[@]} for plugin in ${PLUGINS[@]} do cd $plugin for target in ${PLUGINTARGETS[@]} do if [ -d $target ]; then echo "Building the plugin $target in $PWD" cd $target # qmake # make clean # make if [ -d unittest ]; then cd unittest fi echo "Building the unittest for plugin $target in $PWD" if [ -f run-test ] then echo "Running the unittest for plugin $target in $PWD" ./run-test cat unit_test_results.txt >> $TEMPFILE1 cat gcov_results.txt >> $TEMPFILE2 cd .. else echo" run-test script not present for $target " cd .. fi cd .. fi done if [ -d syncmlcommon ]; then echo "do nothing" else cd .. fi done # get coverage information for the files using perl echo "executing perl $ROOTDIR/bin/gcov_info.pl $TEMPFILE2 $TEMPFILE3" GCOV_REPORT=$WD/gcov_report.txt perl $WD/gcov_info.pl $TEMPFILE2 $TEMPFILE3 $GCOV_REPORT if [ ! $? -eq 0 ]; then #echo "Perl Script for Gcov information exit normal" #else echo "Perl Script Failed to execute ... Exiting ... " exit 0 fi SUMMARY_FILE=$WD/.summary_file if [ -f $SUMMARY_FILE ] then rm -f $SUMMARY_FILE fi perl $WD/test_info.pl $TEMPFILE1 $SUMMARY_FILE if [ ! $? -eq 0 ]; then #echo "Perl Script for test information exit normal" #else echo "Perl Script for test information Failed to execute ... Exiting ... " exit 0 fi echo "Writing the file $RESULTS_FILE" echo "#Results for $TARGET_WEEK " > $RESULTS_FILE echo "Results Summary STARTED " >> $RESULTS_FILE echo "#Current gcov reported coverage (line rate) is" >> $RESULTS_FILE cat $TEMPFILE3 >> $RESULTS_FILE echo "Unit test Results Summary " >> $RESULTS_FILE cat $SUMMARY_FILE >> $RESULTS_FILE echo "Results Summary ENDED " >> $RESULTS_FILE echo "****************UNIT_TEST Results **************" >> $RESULTS_FILE cat $TEMPFILE1 >> $RESULTS_FILE rm -f $TEMPFILE1 $TEMPFILE3 $SUMMARY_FILE cd $ROOTDIR echo $PWD qmake make distclean cd $WD echo "$RESULTS_FILE created" buteo-sync-plugins-0.8.36/bin/runstarget.sh000077500000000000000000000001361476033560700206770ustar00rootroot00000000000000#!/bin/sh echo "running ${1}..." cd /opt/tests/buteo-sync-plugins exec ${1} -maxwarnings 0 buteo-sync-plugins-0.8.36/bin/set_sync_log_level000066400000000000000000000000021476033560700217340ustar00rootroot000000000000008 buteo-sync-plugins-0.8.36/bin/test_info.pl000077500000000000000000000051571476033560700205040ustar00rootroot00000000000000#!/usr/bin/perl #/* # * This file is part of buteo-sync-plugins package # * # * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). # * # * Contact: Sateesh Kavuri # * # * This library is free software; you can redistribute it and/or # * modify it under the terms of the GNU Lesser General Public License # * version 2.1 as published by the Free Software Foundation. # * # * This library is distributed in the hope that it will be useful, but # * WITHOUT ANY WARRANTY; without even the implied warranty of # * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # * Lesser General Public License for more details. # * # * You should have received a copy of the GNU Lesser General Public # * License along with this library; if not, write to the Free Software # * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA # * 02110-1301 USA # * # */ # Author : Srikanth Kavoori # Not Tested fully yet. There could be some issues. # If you see any issues Let me know and i shall fix it :) open(INPUTFILE, "<$ARGV[0]"); # Totals: 0 passed, 2 failed, 0 skipped $tests_string = "Totals:"; $pass_count = 0; $fail_count = 0; $skip_count = 0; $total_count = 0; while() { my($line) = $_; if(/$tests_string/) { #print $line; #print "Found usr_include or header file on line $. \n" ; $pass_start_index = rindex($line,':') + 1; $passed_index = rindex($line,"passed") - 1; $length = $passed_index - $start_index; $pass_count += substr($line,$pass_start_index,$length); #print "pass_count $pass_count "; $fail_start_index = rindex($line,'passed,') + 8; $failed_index = rindex($line,"failed") - 1; $length = $failed_index - $fail_start_index; $fail_count += substr($line,$fail_start_index,$length); #print "fail_count $fail_count "; $skip_start_index = rindex($line,'failed,') + 8; $skipped_index = rindex($line,"skipped") - 1; $length = $failed_index - $skip_start_index; $skip_count += substr($line,$skip_start_index,$length); #print "skip_count $skip_count \n"; } } #if($filecount != 0 ) { # $coverage_percent=sprintf("%.2f",$coverage_percent/$filecount); #} $total_count += $pass_count + $fail_count + $skip_count; print "Total No. TESTS: $total_count \n"; print "Passed: $pass_count \n"; print "Failed: $fail_count \n"; print "Skipped: $skip_count \n"; open(SUMMARY_FILE,">$ARGV[1]"); print SUMMARY_FILE "" ; print SUMMARY_FILE "Total TESTS: $total_count \n"; print SUMMARY_FILE "Passed: $pass_count \n"; print SUMMARY_FILE "Failed: $fail_count \n"; print SUMMARY_FILE "Skipped: $skip_count \n"; close(SUMMARY_FILE); close(INPUTFILE); buteo-sync-plugins-0.8.36/bin/tests.xml000066400000000000000000000037251476033560700200350ustar00rootroot00000000000000 /usr/sbin/run-blts-root /opt/tests/buteo-sync-plugins/./runstarget.sh /opt/tests/buteo-sync-plugins/hcalendar-tests /usr/sbin/run-blts-root /opt/tests/buteo-sync-plugins/./runstarget.sh /opt/tests/buteo-sync-plugins/hnotes-tests buteo-sync-plugins-0.8.36/buteo-sync-plugins.pro000066400000000000000000000021051476033560700216610ustar00rootroot00000000000000#include(doc/doc.pro) TEMPLATE = subdirs syncmlcommon.subdir = syncmlcommon syncmlcommon.target = sub-syncmlcommon utils.subdir = utils utils.target = sub-utils clientplugins.subdir = clientplugins clientplugins.target = sub-clientplugins clientplugins.depends = sub-syncmlcommon serverplugins.subdir = serverplugins serverplugins.target = sub-serverplugins serverplugins.depends = sub-syncmlcommon storageplugins.subdir = storageplugins storageplugins.target = sub-storageplugins storageplugins.depends = sub-syncmlcommon storagechangenotifierplugins.subdir = storagechangenotifierplugins storagechangenotifierplugins.target = sub-storagechangenotifierplugins doc.subdir = doc doc.target = sub-doc SUBDIRS += \ syncmlcommon \ utils \ clientplugins \ serverplugins \ storageplugins \ storagechangenotifierplugins \ doc testdefinition.path = /opt/tests/buteo-sync-plugins/test-definition testdefinition.files = bin/tests.xml tests.path = /opt/tests/buteo-sync-plugins/ tests.files = bin/runstarget.sh INSTALLS += tests testdefinition OTHER_FILES += rpm/* buteo-sync-plugins-0.8.36/clientplugins/000077500000000000000000000000001476033560700202525ustar00rootroot00000000000000buteo-sync-plugins-0.8.36/clientplugins/clientplugins.pro000066400000000000000000000000531476033560700236520ustar00rootroot00000000000000TEMPLATE = subdirs SUBDIRS += syncmlclient buteo-sync-plugins-0.8.36/clientplugins/syncmlclient/000077500000000000000000000000001476033560700227565ustar00rootroot00000000000000buteo-sync-plugins-0.8.36/clientplugins/syncmlclient/BTConnection.cpp000066400000000000000000000255241476033560700260170ustar00rootroot00000000000000/* * This file is part of buteo-sync-plugins package * * Copyright (C) 2010 Nokia Corporation. All rights reserved. * * Contact: Sateesh Kavuri * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * Neither the name of Nokia Corporation nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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. * */ #include "BTConnection.h" #include #include #include #include #include #include #include #include "SyncMLPluginLogging.h" #define BLUEZ_DEST "org.bluez" #define BLUEZ_MANAGER_INTERFACE "org.bluez.Manager" #define BLUEZ_ADAPTER_INTERFACE "org.bluez.Adapter" #define BLUEZ_SERIAL_INTERFACE "org.bluez.Serial" #define REQUEST_SESSION "RequestSession" #define RELEASE_SESSION "ReleaseSession" #define GET_DEFAULT_ADAPTER "DefaultAdapter" #define FIND_DEVICE "FindDevice" #define CREATE_DEVICE "CreateDevice" #define CREATE_PAIRED_DEVICE "CreatePairedDevice" #define CONNECT "Connect" #define DISCONNECT "Disconnect" BTConnection::BTConnection() : iFd( -1 ) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); } BTConnection::~BTConnection() { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); disconnect(); } void BTConnection::setConnectionInfo( const QString& aBTAddress, const QString& aServiceUUID ) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); iBTAddress = aBTAddress; iServiceUUID = aServiceUUID; } int BTConnection::connect() { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); if( iFd != -1 ) { qCDebug(lcSyncMLPlugin) << "Using existing connection"; return iFd; } iDevice = connectDevice( iBTAddress, iServiceUUID ); if( iDevice.isEmpty() ) { qCCritical(lcSyncMLPlugin) << "Could not connect to device" << iBTAddress << ", aborting"; return -1; } // HACK: In Sailfish, sometimes, opening the device // immediately after the bluetooth connect fails and works only // if some delay is introduced. // Since a plugin runs in a separate thread/process (incase of oop) // it is okay to introduce some delay before the open. We will use // a retry count of 3 to open the connection and finally giveup // otherwise int retryCount = 3; do { iFd = open( iDevice.toLatin1().constData(), O_RDWR | O_NOCTTY | O_SYNC ); if (iFd > 0) break; QThread::msleep (100); // Sleep for 100msec before trying again } while ((--retryCount > 0) && (iFd == -1)); if( iFd == -1 ) { qCCritical(lcSyncMLPlugin) << "Could not open file descriptor of the connection, aborting"; disconnectDevice( iBTAddress, iDevice ); return -1; } fdRawMode( iFd ); return iFd; } bool BTConnection::isConnected() const { if( iFd != -1 ) { return true; } else { return false; } } void BTConnection::disconnect() { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); if( iFd != -1 ) { close( iFd ); iFd = -1; } if( !iDevice.isEmpty() ) { disconnectDevice( iBTAddress, iDevice ); } } QString BTConnection::connectDevice( const QString& aBTAddress, const QString& aServiceUUID ) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); QDBusInterface managerInterface( BLUEZ_DEST, "/", BLUEZ_MANAGER_INTERFACE, QDBusConnection::systemBus() ); if( !managerInterface.isValid() ) { qCCritical(lcSyncMLPlugin) << "Could not find BlueZ manager interface"; return ""; } QDBusReply pathReply = managerInterface.call( QLatin1String( GET_DEFAULT_ADAPTER ) ); if( !pathReply.isValid() ) { qCCritical(lcSyncMLPlugin) << "Could not find default adapter path:" << pathReply.error(); return ""; } QString defaultAdapterPath = pathReply.value().path(); qCDebug(lcSyncMLPlugin) << "Using adapter path: " << defaultAdapterPath; QDBusInterface adapterInterface( BLUEZ_DEST, defaultAdapterPath, BLUEZ_ADAPTER_INTERFACE, QDBusConnection::systemBus() ); if( !adapterInterface.isValid() ) { qCCritical(lcSyncMLPlugin) << "Could not find adapter interface: " << adapterInterface.lastError(); return ""; } QDBusReply voidReply = adapterInterface.call( QLatin1String( REQUEST_SESSION ) ); if( !voidReply.isValid() ) { qCCritical(lcSyncMLPlugin) << "Session request failed"; qCCritical(lcSyncMLPlugin) << "Reason:" << voidReply.error(); } qCDebug(lcSyncMLPlugin) << "BT session created"; pathReply = adapterInterface.call( QLatin1String( FIND_DEVICE ), aBTAddress ); if( !pathReply.isValid() ) { qCWarning(lcSyncMLPlugin) << "Couldn't find device " << aBTAddress << "Reason:" << pathReply.error(); qCDebug(lcSyncMLPlugin) << "Create Device :" << aBTAddress; pathReply = adapterInterface.call( QLatin1String( CREATE_DEVICE ), aBTAddress ); if (pathReply.isValid()){ qCDebug(lcSyncMLPlugin) << "Create Paired Device :" << aBTAddress << "Path :" << pathReply.value().path(); QDBusReply reply = adapterInterface.call(QLatin1String( CREATE_PAIRED_DEVICE ), aBTAddress, qVariantFromValue(pathReply.value()), QString()); if( !reply.isValid() ) { qCCritical(lcSyncMLPlugin) << "Pairing failed Reason:" << reply.error(); } } } if( !pathReply.isValid() ) { qCCritical(lcSyncMLPlugin) << "Couldn't find device " << aBTAddress; qCCritical(lcSyncMLPlugin) << "Reason:" << pathReply.error(); adapterInterface.call( QLatin1String( RELEASE_SESSION ) ); qCCritical(lcSyncMLPlugin) << "BT session closed"; return ""; } QString devicePath = pathReply.value().path(); qCDebug(lcSyncMLPlugin) << "Using path" << devicePath << "for device " << aBTAddress; QDBusInterface serialInterface( BLUEZ_DEST, devicePath, BLUEZ_SERIAL_INTERFACE, QDBusConnection::systemBus() ); if( !serialInterface.isValid() ) { qCCritical(lcSyncMLPlugin) << "Could not find serial interface: " << serialInterface.lastError(); adapterInterface.call( QLatin1String( RELEASE_SESSION ) ); qCCritical(lcSyncMLPlugin) << "BT session closed"; return ""; } QDBusReply stringReply = serialInterface.call( QLatin1String( CONNECT ), aServiceUUID ); if( !stringReply.isValid() ) { qCCritical(lcSyncMLPlugin) << "Could not connect to device " << devicePath << " with service uuid " << aServiceUUID; qCCritical(lcSyncMLPlugin) << "Reason:" << stringReply.error(); adapterInterface.call( QLatin1String( RELEASE_SESSION ) ); qCCritical(lcSyncMLPlugin) << "BT session closed"; return ""; } qCDebug(lcSyncMLPlugin) << "Device connected:" << aBTAddress; return stringReply.value(); } void BTConnection::disconnectDevice( const QString& aBTAddress, const QString& aDevice ) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); QDBusInterface managerInterface( BLUEZ_DEST, "/", BLUEZ_MANAGER_INTERFACE, QDBusConnection::systemBus() ); if( !managerInterface.isValid() ) { qCCritical(lcSyncMLPlugin) << "Could not find BlueZ manager interface"; return; } QDBusReply pathReply = managerInterface.call( QLatin1String( GET_DEFAULT_ADAPTER ) ); if( !pathReply.isValid() ) { qCCritical(lcSyncMLPlugin) << "Could not find default adapter path"; qCCritical(lcSyncMLPlugin) << "Reason:" << pathReply.error(); return; } QString defaultAdapterPath = pathReply.value().path(); qCDebug(lcSyncMLPlugin) << "Using adapter path: " << defaultAdapterPath; QDBusInterface adapterInterface( BLUEZ_DEST, defaultAdapterPath, BLUEZ_ADAPTER_INTERFACE, QDBusConnection::systemBus() ); if( !adapterInterface.isValid() ) { qCCritical(lcSyncMLPlugin) << "Could not find adapter interface: " << adapterInterface.lastError(); return; } pathReply = adapterInterface.call( QLatin1String( FIND_DEVICE ), aBTAddress ); if( !pathReply.isValid() ) { qCCritical(lcSyncMLPlugin) << "Couldn't find device " << aBTAddress; qCCritical(lcSyncMLPlugin) << "Reason:" << pathReply.error(); return; } QString devicePath = pathReply.value().path(); qCDebug(lcSyncMLPlugin) << "Using path" << devicePath << "for device " << aBTAddress; QDBusInterface serialInterface( BLUEZ_DEST, devicePath, BLUEZ_SERIAL_INTERFACE, QDBusConnection::systemBus() ); if( !serialInterface.isValid() ) { qCCritical(lcSyncMLPlugin) << "Could not find serial interface: " << serialInterface.lastError(); return; } QDBusReply voidReply = serialInterface.call( QLatin1String( DISCONNECT ), aDevice ); if( !voidReply.isValid() ) { qCCritical(lcSyncMLPlugin) << "Device disconnection failed"; qCCritical(lcSyncMLPlugin) << "Reason:" << voidReply.error(); return; } qCDebug(lcSyncMLPlugin) << "Device disconnected:" << aBTAddress; voidReply = adapterInterface.call( RELEASE_SESSION ); if( !voidReply.isValid() ) { qCCritical(lcSyncMLPlugin) << "Session release failed"; qCCritical(lcSyncMLPlugin) << "Reason:" << voidReply.error(); return; } qCDebug(lcSyncMLPlugin) << "BT session closed"; iDevice.clear(); } bool BTConnection::fdRawMode( int aFD ) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); struct termios mode; if (tcgetattr(aFD, &mode)) { return false; } cfmakeraw(&mode); if (tcsetattr(aFD, TCSADRAIN, &mode)) { return false; } return true; } buteo-sync-plugins-0.8.36/clientplugins/syncmlclient/BTConnection.h000066400000000000000000000056731476033560700254670ustar00rootroot00000000000000/* * This file is part of buteo-sync-plugins package * * Copyright (C) 2010 Nokia Corporation. All rights reserved. * * Contact: Sateesh Kavuri * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * Neither the name of Nokia Corporation nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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. * */ #ifndef BTCONNECTION_H #define BTCONNECTION_H #include #include /*! \brief Class for creating a connection to another device over * Bluetooth for libmeegosyncml * */ class BTConnection : public DataSync::OBEXConnection { public: /*! \brief Constructor * */ BTConnection(); /*! \brief Destructor * */ virtual ~BTConnection(); /*! \brief Sets connection info * * @param aBTAddress Bluetooth addess of remote device * @param aServiceUUID Service UUID of remote service */ void setConnectionInfo( const QString& aBTAddress, const QString& aServiceUUID ); /*! \sa DataSync::OBEXConnection::connect() * */ virtual int connect(); /*! \sa DataSync::OBEXConnection::isConnected() * */ virtual bool isConnected() const; /*! \sa DataSync::OBEXConnection::disconnect() * */ virtual void disconnect(); private: QString connectDevice( const QString& aBTAddress, const QString& aServiceUUID ); void disconnectDevice( const QString& aBTAddress, const QString& aDevice ); bool fdRawMode( int aFD ); private: QString iBTAddress; QString iServiceUUID; int iFd; QString iDevice; }; #endif // BTCONNECTION_H buteo-sync-plugins-0.8.36/clientplugins/syncmlclient/SyncMLClient.cpp000066400000000000000000000713021476033560700257710ustar00rootroot00000000000000/* * This file is part of buteo-sync-plugins package * * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). * * Contact: Sateesh Kavuri * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * */ #include "SyncMLClient.h" #include #include #include #include #include #include #include #include #include #include "SyncMLPluginLogging.h" #include #include #include "SyncMLConfig.h" #include "SyncMLCommon.h" #include "DeviceInfo.h" const QString DEFAULTCONFIGFILE("/etc/buteo/meego-syncml-conf.xml"); const QString EXTCONFIGFILE("/etc/buteo/ext-syncml-conf.xml"); Buteo::ClientPlugin* SyncMLClientLoader::createClientPlugin( const QString& pluginName, const Buteo::SyncProfile& profile, Buteo::PluginCbInterface* cbInterface) { return new SyncMLClient(pluginName, profile, cbInterface); } SyncMLClient::SyncMLClient(const QString& aPluginName, const Buteo::SyncProfile& aProfile, Buteo::PluginCbInterface *aCbInterface) : ClientPlugin(aPluginName, aProfile, aCbInterface), iAgent(0), iTransport(0), iConfig(0), iCommittedItems(0) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); } SyncMLClient::~SyncMLClient() { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); } bool SyncMLClient::init() { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); iProperties = iProfile.allNonStorageKeys(); if (initAgent() && initTransport() && initConfig()) { if (useAccounts () && initAccount()) { // Fetch the credentials from SSO. Currently, only "password" // method and mechanism are supported to be retrieved getCredentials(); // Fetch the key/values settings from Account and merge them with iProperties QMap accSettings = accountSettings(); QMap::iterator iter; for (iter = accSettings.begin(); iter != accSettings.end(); ++iter) { iProperties[iter.key()] = iter.value(); } } return true; } else { // Uninitialize everything that was initialized before failure. uninit(); return false; } } bool SyncMLClient::uninit() { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); closeAgent(); closeConfig(); closeTransport(); return true; } bool SyncMLClient::startSync() { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); if (iAgent == 0 || iConfig == 0 || iTransport == 0) { return false; } connect(iAgent, SIGNAL(stateChanged(DataSync::SyncState)), this, SLOT(syncStateChanged(DataSync::SyncState))); connect(iAgent, SIGNAL(syncFinished(DataSync::SyncState)), this, SLOT(syncFinished(DataSync::SyncState))); connect(iAgent, SIGNAL(itemProcessed(DataSync::ModificationType, DataSync::ModifiedDatabase, QString, QString,int)), this, SLOT(receiveItemProcessed(DataSync::ModificationType, DataSync::ModifiedDatabase, QString, QString,int))); connect(iAgent, SIGNAL(storageAccquired(QString)), this, SLOT(storageAccquired(QString))); iConfig->setTransport(iTransport); if (useAccounts()) // The actual sync start would be done in credentialsResponse() slot return true; else return iAgent->startSync(*iConfig); } void SyncMLClient::abortSync(Sync::SyncStatus aStatus) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); DataSync::SyncState state = DataSync::ABORTED; if (aStatus == Sync::SYNC_ERROR) { state = DataSync::CONNECTION_ERROR; } if( iAgent ) { if( !iAgent->abort(state) ) { qCDebug(lcSyncMLPlugin) << "Agent not active, aborting immediately"; syncFinished(DataSync::ABORTED); } else { qCDebug(lcSyncMLPlugin) << "Agent active, abort event posted"; } } else { qCWarning(lcSyncMLPlugin) << "abortSync() called before init(), ignoring"; } } bool SyncMLClient::cleanUp() { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); iProperties = iProfile.allNonStorageKeys(); initAgent(); initConfig(); bool retVal = iAgent->cleanUp(iConfig); closeAgent(); closeConfig(); return retVal; } void SyncMLClient::syncStateChanged(DataSync::SyncState aState) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); switch(aState) { case DataSync::LOCAL_INIT: case DataSync::REMOTE_INIT: { emit syncProgressDetail(getProfileName(),Sync::SYNC_PROGRESS_INITIALISING); break; } case DataSync::SENDING_ITEMS: { emit syncProgressDetail(getProfileName(),Sync::SYNC_PROGRESS_SENDING_ITEMS); break; } case DataSync::RECEIVING_ITEMS: { emit syncProgressDetail(getProfileName(),Sync::SYNC_PROGRESS_RECEIVING_ITEMS); break; } case DataSync::FINALIZING: { emit syncProgressDetail(getProfileName(),Sync::SYNC_PROGRESS_FINALISING); break; } default: //do nothing break; }; #ifndef QT_NO_DEBUG qCDebug(lcSyncMLPlugin) << "*********** Sync Status has Changed to:" << toText(aState) << "****************"; #endif // QT_NO_DEBUG } void SyncMLClient::syncFinished(DataSync::SyncState aState) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); #ifndef QT_NO_DEBUG qCDebug(lcSyncMLPlugin) << "*********** Sync has finished with:" << toText(aState) << "****************"; #endif // QT_NO_DEBUG switch(aState) { case DataSync::INTERNAL_ERROR: case DataSync::AUTHENTICATION_FAILURE: case DataSync::DATABASE_FAILURE: case DataSync::CONNECTION_ERROR: case DataSync::INVALID_SYNCML_MESSAGE: case DataSync::UNSUPPORTED_SYNC_TYPE: case DataSync::UNSUPPORTED_STORAGE_TYPE: { generateResults( false ); emit error(getProfileName(), "", Buteo::SyncResults::ABORTED); break; } case DataSync::SUSPENDED: case DataSync::ABORTED: case DataSync::SYNC_FINISHED: { generateResults( true ); emit success( getProfileName(), QString::number(aState)); break; } case DataSync::NOT_PREPARED: case DataSync::PREPARED: case DataSync::LOCAL_INIT: case DataSync::REMOTE_INIT: case DataSync::SENDING_ITEMS: case DataSync::RECEIVING_ITEMS: case DataSync::FINALIZING: case DataSync::SUSPENDING: default: { // do nothing // @todo: do nothing??? We'll deadlock then! Fix this at some point! break; } } } void SyncMLClient::storageAccquired(QString aMimeType) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); qCDebug(lcSyncMLPlugin) << " MimeType " << aMimeType; emit accquiredStorage(aMimeType); } void SyncMLClient::receiveItemProcessed( DataSync::ModificationType aModificationType, DataSync::ModifiedDatabase aModifiedDatabase, QString aLocalDatabase, QString aMimeType, int aCommittedItems) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); qCDebug(lcSyncMLPlugin) << "Modification Type " << aModificationType; qCDebug(lcSyncMLPlugin) << "Modification Database " << aModifiedDatabase; qCDebug(lcSyncMLPlugin) << " Database " << aLocalDatabase; qCDebug(lcSyncMLPlugin) << " MimeType " << aMimeType; ++iCommittedItems; if(!receivedItems.contains(aLocalDatabase)) { ReceivedItemDetails details; details.added = details.modified = details.deleted = details.error = 0; details.mime = aMimeType; receivedItems[aLocalDatabase] = details; } Sync::TransferDatabase db = Sync::LOCAL_DATABASE; switch (aModificationType) { case DataSync::MOD_ITEM_ADDED: { ++receivedItems[aLocalDatabase].added; break; } case DataSync::MOD_ITEM_MODIFIED: { ++receivedItems[aLocalDatabase].modified; break; } case DataSync::MOD_ITEM_DELETED: { ++receivedItems[aLocalDatabase].deleted; break; } case DataSync::MOD_ITEM_ERROR: { ++receivedItems[aLocalDatabase].error; break; } default: { Q_ASSERT(0); break; } } if (aModifiedDatabase == DataSync::MOD_LOCAL_DATABASE) { db = Sync::LOCAL_DATABASE; } else { db = Sync::REMOTE_DATABASE; } if( iCommittedItems == aCommittedItems ) { QMapIterator itr(receivedItems); while( itr.hasNext() ) { itr.next(); if( itr.value().added ) { emit transferProgress(getProfileName(), db, Sync::ITEM_ADDED, itr.value().mime, itr.value().added); } if( itr.value().modified ) { emit transferProgress(getProfileName(), db, Sync::ITEM_MODIFIED, itr.value().mime, itr.value().modified); } if( itr.value().deleted ) { emit transferProgress(getProfileName(), db, Sync::ITEM_DELETED, itr.value().mime, itr.value().deleted); } if( itr.value().error ) { emit transferProgress(getProfileName(), db, Sync::ITEM_ERROR, itr.value().mime, itr.value().error); } } iCommittedItems = 0; receivedItems.clear(); } } bool SyncMLClient::initAgent() { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); qCDebug(lcSyncMLPlugin) << "Creating agent..."; bool success = false; iAgent = new DataSync::SyncAgent(); if (!iAgent) { qCDebug(lcSyncMLPlugin) << "Agent creation failed"; } else { success = true; qCDebug(lcSyncMLPlugin) << "Agent created"; } return success; } void SyncMLClient::closeAgent() { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); qCDebug(lcSyncMLPlugin) << "Destroying agent..."; if (iAgent) { delete iAgent; iAgent = 0; } } bool SyncMLClient::initTransport() { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); qCDebug(lcSyncMLPlugin) << "Initiating transport..."; bool success = false; QString transportType = iProperties[PROF_SYNC_TRANSPORT]; if (transportType == HTTP_TRANSPORT) { success = initHttpTransport(); } else if (transportType == OBEX_TRANSPORT) { success = initObexTransport(); } else { qCDebug(lcSyncMLPlugin) << "Unknown transport type:" << transportType; } return success; } void SyncMLClient::closeTransport() { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); qCDebug(lcSyncMLPlugin) << "Closing transport..."; delete iTransport; iTransport = NULL; qCDebug(lcSyncMLPlugin) << "Transport closed"; } bool SyncMLClient::initConfig() { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); qCDebug(lcSyncMLPlugin) << "Initiating config..."; QStringList storageNames = iProfile.subProfileNames( Buteo::Profile::TYPE_STORAGE); if (storageNames.isEmpty()) { qCCritical(lcSyncMLPlugin) << "No storages defined for profile, nothing to sync"; return false; } if (!iStorageProvider.init(&iProfile, this, iCbInterface, false)) { qCCritical(lcSyncMLPlugin) << "Could not initialize storage provider"; return false; } iConfig = new DataSync::SyncAgentConfig; // ** Read configuration // Two configuration files are being read: first the Meego default config file, // and then possible external config file, which can be used to add additional // configuration, or replace some of the configuration of Meego default config. // Default configuration file should always exist if( !iConfig->fromFile( DEFAULTCONFIGFILE ) ) { qCCritical(lcSyncMLPlugin) << "Could not read default SyncML configuration file:" << DEFAULTCONFIGFILE; return false; } if( iConfig->fromFile( EXTCONFIGFILE ) ) { qCDebug(lcSyncMLPlugin) << "Found & read external configuration file:" << EXTCONFIGFILE; } else { qCDebug(lcSyncMLPlugin) << "Could not find external configuration file" << EXTCONFIGFILE <<", skipping"; } // ** Set up storage provider iConfig->setStorageProvider(&iStorageProvider); // ** Set up device info QString DEV_INFO_FILE_PATH = SyncMLConfig::getDevInfoFile(); QFile devInfoFile(DEV_INFO_FILE_PATH); if (!devInfoFile.exists()) { Buteo::DeviceInfo appDevInfo; QMap < QString, QString > deviceInfoMap = appDevInfo.getDeviceInformation(); appDevInfo.saveDevInfoToFile(deviceInfoMap, DEV_INFO_FILE_PATH); } DataSync::DeviceInfo syncDeviceInfo; syncDeviceInfo.readFromFile(DEV_INFO_FILE_PATH); iConfig->setDeviceInfo(syncDeviceInfo); // ** Set up sync targets for (int i = 0; i < storageNames.count(); ++i) { const Buteo::Profile *storageProfile = iProfile.subProfile( storageNames[i], Buteo::Profile::TYPE_STORAGE); QString sourceDb = storageProfile->key(STORAGE_SOURCE_URI); if (storageProfile->isEnabled()) { QString targetDb = storageProfile->key(STORAGE_REMOTE_URI); qCDebug(lcSyncMLPlugin) << "Adding sync target:" << sourceDb << "->" << targetDb; iConfig->addSyncTarget(sourceDb, targetDb); } else { qCDebug(lcSyncMLPlugin) << "Adding disabled sync target:" << sourceDb; iConfig->addDisabledSyncTarget(sourceDb); } } // ** Set up sync parameters QString transportType = iProperties[PROF_SYNC_TRANSPORT]; QString remoteDeviceName; if (transportType == HTTP_TRANSPORT) { // Ovi.com requires remote device name to be the sync URI remoteDeviceName = iProperties[PROF_REMOTE_URI]; } else if (transportType == OBEX_TRANSPORT) { // Over OBEX, set remote device to it's address as designated in profile remoteDeviceName = iProperties[PROF_REMOTE_ADDRESS]; if (remoteDeviceName.isEmpty()) { // There is no code to set PROF_REMOTE_ADDRESS. // It may be set via Buteo::KEY_REMOTE_ID as it just happens to be the same. // Alternatively, it may be hardcoded into the profile from the template. // For Bluetooth OBEX however, it is sometimes never set. // Instead, use the KEY_REMOTE_NAME which will be set for OBEX profiles... remoteDeviceName = iProperties[Buteo::KEY_REMOTE_NAME]; } } QString versionProp = iProperties[PROF_SYNC_PROTOCOL]; DataSync::ProtocolVersion version = DataSync::SYNCML_1_2; if (versionProp == SYNCML11) { qCDebug(lcSyncMLPlugin) << "Using SyncML DS 1.1 protocol"; version = DataSync::SYNCML_1_1; } else if (versionProp == SYNCML12) { qCDebug(lcSyncMLPlugin) << "Using SyncML DS 1.2 protocol"; version = DataSync::SYNCML_1_2; } DataSync::SyncInitiator initiator = DataSync::INIT_CLIENT; if (transportType == HTTP_TRANSPORT) { initiator = DataSync::INIT_CLIENT; } else if (transportType == OBEX_TRANSPORT) { initiator = DataSync::INIT_SERVER; } DataSync::SyncDirection direction = resolveSyncDirection(initiator); bool forceSlowSync = iProfile.boolKey(Buteo::KEY_FORCE_SLOW_SYNC); DataSync::SyncMode syncMode(direction, initiator); if (forceSlowSync) { syncMode.toSlowSync(); } iConfig->setSyncParams(remoteDeviceName, version, syncMode); // ** Set up auth parameters DataSync::AuthType type = DataSync::AUTH_NONE; QString username; QString password; if (transportType == HTTP_TRANSPORT) { type = DataSync::AUTH_BASIC; username = iProperties[PROF_USERID]; password = iProperties[PROF_PASSWD]; } else if (transportType == OBEX_TRANSPORT) { type = DataSync::AUTH_NONE; } iConfig->setAuthParams(type, username, password); // ** Set up other parameters DataSync::ConflictResolutionPolicy policy = resolveConflictResolutionPolicy(initiator); iConfig->setAgentProperty(DataSync::CONFLICTRESOLUTIONPOLICYPROP, QString::number(policy)); if (transportType == HTTP_TRANSPORT) { // Make sure that S60 EMI tags are not sent over HTTP. iConfig->clearExtension(DataSync::EMITAGSEXTENSION); } return true; } void SyncMLClient::closeConfig() { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); qCDebug(lcSyncMLPlugin) << "Closing config..."; delete iConfig; iConfig = NULL; if (!iStorageProvider.uninit()) { qCCritical(lcSyncMLPlugin) << "Could not uninitialize storage provider"; } qCDebug(lcSyncMLPlugin) << "Config closed"; } Buteo::SyncResults SyncMLClient::getSyncResults() const { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); return iResults; } void SyncMLClient::connectivityStateChanged(Sync::ConnectivityType aType, bool aState) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); qCDebug(lcSyncMLPlugin) << "Received connectivity change event:" << aType << " changed to " << aState; } #ifndef QT_NO_DEBUG // this function exists only debugging purposes. // should not be used to send messages as feedback // only the state of the app will be sent now // and UI has to map to a localisation string based on // the state of the stack QString SyncMLClient::toText(const DataSync::SyncState& aState) { switch (aState) { case DataSync::NOT_PREPARED: return "NOT PREPARED"; case DataSync::LOCAL_INIT: case DataSync::REMOTE_INIT: return "INITIALIZING"; case DataSync::SENDING_ITEMS: return "SENDING ITEMS"; case DataSync::RECEIVING_ITEMS: return "RECEIVING_ITEMS"; case DataSync::SENDING_MAPPINGS: return "SENDING MAPPINGS"; case DataSync::RECEIVING_MAPPINGS: return "RECEIVING MAPPINGS"; case DataSync::FINALIZING: return "FINALIZING"; case DataSync::SUSPENDING: return "SUSPENDING"; case DataSync::PREPARED: return "PREPARED"; case DataSync::SYNC_FINISHED: return "SYNC FINISHED"; case DataSync::INTERNAL_ERROR: return "INTERNAL_ERROR"; case DataSync::AUTHENTICATION_FAILURE: return "AUTHENTICATION FAILURE"; case DataSync::DATABASE_FAILURE: return "DATABASE_FAILURE"; case DataSync::SUSPENDED: return "SUSPENDED"; case DataSync::ABORTED: return "ABORTED"; case DataSync::CONNECTION_ERROR: return "CONNECTION ERROR"; case DataSync::INVALID_SYNCML_MESSAGE: return "INVALID SYNCML MESSAGE"; case DataSync::UNSUPPORTED_SYNC_TYPE: return "UNSUPPORTED SYNC TYPE"; case DataSync::UNSUPPORTED_STORAGE_TYPE: return "UNSUPPORTED STORAGE TYPE"; default: return "UNKNOWN"; break; } } #endif //#ifndef QT_NO_DEBUG bool SyncMLClient::initObexTransport() { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); qCDebug(lcSyncMLPlugin) << "Creating OBEX transport"; QString btAddress = iProperties[PROF_BT_ADDRESS]; if( btAddress.isEmpty() ) { qCCritical(lcSyncMLPlugin) << "Could not find mandatory property:" << PROF_BT_ADDRESS; return false; } QString btService = iProperties[PROF_BT_UUID]; if( btService.isEmpty() ) { qCCritical(lcSyncMLPlugin) << "Could not find mandatory property:" << PROF_BT_UUID; return false; } qCDebug(lcSyncMLPlugin) << "Using BT address:" << btAddress; qCDebug(lcSyncMLPlugin) << "Using BT service UUID:" << btService; iBTConnection.setConnectionInfo( btAddress, btService ); DataSync::OBEXTransport* transport = new DataSync::OBEXTransport( iBTConnection, DataSync::OBEXTransport::MODE_OBEX_CLIENT, DataSync::OBEXTransport::TYPEHINT_BT ); if (iProperties[PROF_USE_WBXML] == PROPS_TRUE) { qCDebug(lcSyncMLPlugin) << "Using wbXML"; transport->setWbXml(true); } else { qCDebug(lcSyncMLPlugin) << "Not using wbXML"; transport->setWbXml(false); } iTransport = transport; return true; } bool SyncMLClient::initHttpTransport() { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); qCDebug(lcSyncMLPlugin) << "Creating HTTP transport"; QString remoteURI = iProperties[PROF_REMOTE_URI]; bool success = false; if (!remoteURI.isEmpty()) { DataSync::HTTPTransport* transport = new DataSync::HTTPTransport(); qCDebug(lcSyncMLPlugin) << "Setting remote URI to" << remoteURI; transport->setRemoteLocURI(remoteURI); QString proxyHost = iProperties[PROF_HTTP_PROXY_HOST]; if (!proxyHost.isEmpty()) { QString proxyPort = iProperties[PROF_HTTP_PROXY_PORT]; QNetworkProxy proxy = transport->getProxyConfig(); proxy.setType(QNetworkProxy::HttpProxy); proxy.setHostName(proxyHost); proxy.setPort(proxyPort.toInt()); transport->setProxyConfig(proxy); qCDebug(lcSyncMLPlugin) << "Using proxy"; qCDebug(lcSyncMLPlugin) << "Proxy host:" << proxyHost; qCDebug(lcSyncMLPlugin) << "Proxy port:" << proxyPort; } else { qCDebug(lcSyncMLPlugin) << "Not using proxy"; } if (iProperties[PROF_USE_WBXML] == PROPS_TRUE) { qCDebug(lcSyncMLPlugin) << "Using wbXML"; transport->setWbXml(true); } else { qCDebug(lcSyncMLPlugin) << "Not using wbXML"; transport->setWbXml(false); } QString xheaders = iProperties[PROF_HTTP_XHEADERS]; QStringList hdrlist = xheaders.split("\r\n"); foreach (QString hdr, hdrlist) { QString fname = hdr.section(':', 0, 0); QString fvalue = hdr.section(':', 1); qCDebug(lcSyncMLPlugin) << "fname: " << fname << ", fvalue" << fvalue; transport->addXheader(fname, fvalue); } iTransport = transport; success = true; } else { qCDebug(lcSyncMLPlugin) << "Could not find 'Remote database' property"; } return success; } DataSync::SyncDirection SyncMLClient::resolveSyncDirection( const DataSync::SyncInitiator& aInitiator) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); Buteo::SyncProfile::SyncDirection directionFromProfile = iProfile.syncDirection(); DataSync::SyncDirection direction = DataSync::DIRECTION_TWO_WAY; if (aInitiator == DataSync::INIT_CLIENT) { if (directionFromProfile == Buteo::SyncProfile::SYNC_DIRECTION_FROM_REMOTE) { direction = DataSync::DIRECTION_FROM_SERVER; } else if (directionFromProfile == Buteo::SyncProfile::SYNC_DIRECTION_TO_REMOTE) { direction = DataSync::DIRECTION_FROM_CLIENT; } } else if (aInitiator == DataSync::INIT_SERVER) { if (directionFromProfile == Buteo::SyncProfile::SYNC_DIRECTION_FROM_REMOTE) { direction = DataSync::DIRECTION_FROM_CLIENT; } else if (directionFromProfile == Buteo::SyncProfile::SYNC_DIRECTION_TO_REMOTE) { direction = DataSync::DIRECTION_FROM_SERVER; } } return direction; } DataSync::ConflictResolutionPolicy SyncMLClient::resolveConflictResolutionPolicy( const DataSync::SyncInitiator& aInitiator) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); Buteo::SyncProfile::ConflictResolutionPolicy crPolicyFromProfile = iProfile.conflictResolutionPolicy(); /* In case if we have to resolve conflict the choice will be based on the user selection when * creating a sync profile , if to prefer local changes or remote changes. */ DataSync::ConflictResolutionPolicy crPolicy = DataSync::PREFER_LOCAL_CHANGES; switch (crPolicyFromProfile) { case Buteo::SyncProfile::CR_POLICY_PREFER_LOCAL_CHANGES: { qCDebug(lcSyncMLPlugin) << "Buteo::SyncProfile::CR_POLICY_PREFER_LOCAL_CHANGES"; crPolicy = DataSync::PREFER_LOCAL_CHANGES; break; } case Buteo::SyncProfile::CR_POLICY_PREFER_REMOTE_CHANGES: { qCDebug(lcSyncMLPlugin) << "Buteo::SyncProfile::CR_POLICY_PREFER_REMOTE_CHANGES"; crPolicy = DataSync::PREFER_REMOTE_CHANGES; break; } default: { break; } } return crPolicy; } void SyncMLClient::generateResults( bool aSuccessful ) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); iResults.setMajorCode( aSuccessful ? Buteo::SyncResults::SYNC_RESULT_SUCCESS : Buteo::SyncResults::SYNC_RESULT_FAILED ); iResults.setTargetId(iAgent->getResults().getRemoteDeviceId()); const QMap* dbResults = iAgent->getResults().getDatabaseResults(); if (dbResults->isEmpty()) { qCDebug(lcSyncMLPlugin) << "No items transferred"; } else { QMapIterator i( *dbResults ); while ( i.hasNext() ) { i.next(); const DataSync::DatabaseResults& r = i.value(); Buteo::TargetResults targetResults( i.key(), // Target name Buteo::ItemCounts( r.iLocalItemsAdded, r.iLocalItemsDeleted, r.iLocalItemsModified ), Buteo::ItemCounts( r.iRemoteItemsAdded, r.iRemoteItemsDeleted, r.iRemoteItemsModified )); iResults.addTargetResults( targetResults ); qCDebug(lcSyncMLPlugin) << "Items for" << targetResults.targetName() << ":"; qCDebug(lcSyncMLPlugin) << "LA:" << targetResults.localItems().added << "LD:" << targetResults.localItems().deleted << "LM:" << targetResults.localItems().modified << "RA:" << targetResults.remoteItems().added << "RD:" << targetResults.remoteItems().deleted << "RM:" << targetResults.remoteItems().modified; } } } Accounts::AccountId SyncMLClient::accountId() { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); Accounts::AccountId accountId = 0; QStringList accountList = iProfile.keyValues ( Buteo::KEY_ACCOUNT_ID ); if ( !accountList.isEmpty() ) { accountId = accountList.first().toUInt(); } return accountId; } bool SyncMLClient::initAccount() { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); Accounts::Manager* manager = new Accounts::Manager(); Accounts::AccountId accId = accountId(); if ( accId != (Accounts::AccountId)0 ) { iAccount = manager->account( accId ); return true; } else { return false; } } void SyncMLClient::getCredentials () { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); quint32 credentialsId = iAccount->credentialsId(); SignOn::Identity* identity = SignOn::Identity::existingIdentity( credentialsId ); SignOn::SessionData data; // Currently, we support only "password" method and mechanism for // SyncML iAuthSession = identity->createSession( QLatin1String("password") ); QObject::connect( iAuthSession, SIGNAL(response(const SignOn::SessionData &)), this, SLOT(credentialsResponse(const SessionData&))); QObject::connect( iAuthSession, SIGNAL(error(const SignOn::Error &)), this, SLOT(credentialsError(const Error&))); iAuthSession->process(data, QLatin1String("password")); } bool SyncMLClient::useAccounts() const { return iProfile.boolKey( Buteo::KEY_USE_ACCOUNTS ); } QMap SyncMLClient::accountSettings() const { QStringList keys = iAccount->allKeys(); QMap accSettings; foreach (const QString key, keys) { accSettings[key] = iAccount->valueAsString( key ); } return accSettings; } void SyncMLClient::credentialsResponse( const SignOn::SessionData &sessionData ) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); QStringList sdpns = sessionData.propertyNames(); foreach (const QString &sdpn, sdpns) { qCDebug(lcSyncMLPlugin) << sdpn << sessionData.getProperty(sdpn).toString(); if (sdpn.compare("username", Qt::CaseInsensitive) == 0) iProperties[Buteo::KEY_USERNAME] = sessionData.getProperty( sdpn ).toString(); else if (sdpn.compare("secret", Qt::CaseInsensitive) == 0) iProperties[Buteo::KEY_PASSWORD] = sessionData.getProperty( sdpn ).toString(); } if ( iProperties[Buteo::KEY_USERNAME].isEmpty() || iProperties[Buteo::KEY_PASSWORD].isEmpty() ) { SignOn::Error error(SignOn::Error::Unknown, "Empty username or password returned from signond"); credentialsError(error); } // Start the actual sync process if (iAgent) { // Set the config with the credentials from SSO iConfig->setAuthParams(DataSync::AUTH_BASIC, iProperties[Buteo::KEY_USERNAME], iProperties[Buteo::KEY_PASSWORD]); iAgent->startSync(*iConfig); } } void SyncMLClient::credentialsError( const SignOn::Error &error ) { qCWarning(lcSyncMLPlugin) << "Error in retrieving credentials from SSO." << error.type() << error.message(); qCWarning(lcSyncMLPlugin) << "Emitting authentication failure"; // Emitting authentication failure for lack of a proper enum from // DataSync:: syncFinished(DataSync::AUTHENTICATION_FAILURE); } buteo-sync-plugins-0.8.36/clientplugins/syncmlclient/SyncMLClient.h000066400000000000000000000151051476033560700254350ustar00rootroot00000000000000/* * This file is part of buteo-sync-plugins package * * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). * * Contact: Sateesh Kavuri * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * */ #ifndef SYNCMLCLIENT_H #define SYNCMLCLIENT_H #include "BTConnection.h" #include "SyncMLStorageProvider.h" #include #include #include #include #include #include #include #include #include #include #include #include namespace DataSync { class Transport; class SyncAgentConfig; } /*! \brief Implementation for SyncML client plugin * */ class SyncMLClient : public Buteo::ClientPlugin { Q_OBJECT; public: /*! \brief Constructor * * @param aPluginName Name of this client plugin * @param aProfile Sync profile * @param aCbInterface Pointer to the callback interface */ SyncMLClient( const QString& aPluginName, const Buteo::SyncProfile& aProfile, Buteo::PluginCbInterface *aCbInterface ); /*! \brief Destructor * * Call uninit before destroying the object. */ virtual ~SyncMLClient(); //! @see SyncPluginBase::init virtual bool init(); //! @see SyncPluginBase::uninit virtual bool uninit(); //! @see ClientPlugin::startSync virtual bool startSync(); //! @see SyncPluginBase::abortSync virtual void abortSync(Sync::SyncStatus aStatus = Sync::SYNC_ABORTED); //! @see SyncPluginBase::getSyncResults virtual Buteo::SyncResults getSyncResults() const; //! @see SyncPluginBase::cleanUp virtual bool cleanUp(); public slots: //! @see SyncPluginBase::connectivityStateChanged virtual void connectivityStateChanged( Sync::ConnectivityType aType, bool aState ); protected slots: /*! * \brief state change slot for DataSync::SyncAgent::stateChanged signal * \param aState - new state */ void syncStateChanged( DataSync::SyncState aState ); /*! * \brief sync Finished slot for DataSync::SyncAgent::syncFinished signal * \param aState - final state */ void syncFinished( DataSync::SyncState aState ); /*! * \brief slot for DataSync::SyncAgent::storageAcquired signal * \param aMimeType - mimetype of the storage acquired. */ void storageAccquired(QString aMimeType); /*! * \brief slot for DataSync::SyncAgent::itemProcessed signal * \param aModificationType - modification type * \param aModifiedDatabase - modified database . * \param aLocalDatabase - local database * \param aMimeType - mime type of the database * \param aCommittedItems - No. of items committed for this operation */ void receiveItemProcessed( DataSync::ModificationType aModificationType, DataSync::ModifiedDatabase aModifiedDatabase, QString aLocalDatabase, QString aMimeType, int aCommittedItems ); /*! * \brief Slot for response on call for retrieving credentials */ void credentialsResponse( const SignOn::SessionData& data ); /*! * \brief Error slot for response on call for retrieving credentials */ void credentialsError( const SignOn::Error& error ); private: bool initAgent(); void closeAgent(); bool initTransport(); void closeTransport(); bool initConfig(); void closeConfig(); /** * \brief Subroutine for obex transport initiation * @return True is success, false if not */ bool initObexTransport(); /** * \brief Subroutine for http transport initiation * @return True is success, false if not */ bool initHttpTransport(); /*! \brief Resolves sync direction from current profile * * @param aInitiator Initiator of the sync * @return Resolved sync direction */ DataSync::SyncDirection resolveSyncDirection( const DataSync::SyncInitiator& aInitiator ); /*! \brief Resolves conflict resolution policy from current profile * * @param aInitiator Initiator of the sync * @return Resolved conflict resolution policy */ DataSync::ConflictResolutionPolicy resolveConflictResolutionPolicy( const DataSync::SyncInitiator& aInitiator ); void generateResults( bool aSuccessful ); Accounts::AccountId accountId(); bool initAccount(); void getCredentials(); bool useAccounts() const; QMap accountSettings() const; #ifndef QT_NO_DEBUG // helper function for debugging // does nothing in release mode QString toText( const DataSync::SyncState& aState ); #endif //#ifndef QT_NO_DEBUG QMap iProperties; DataSync::SyncAgent* iAgent; BTConnection iBTConnection; DataSync::Transport* iTransport; DataSync::SyncAgentConfig* iConfig; Buteo::SyncResults iResults; SyncMLStorageProvider iStorageProvider; quint32 iCommittedItems; Accounts::Account* iAccount; SignOn::AuthSession* iAuthSession; }; class SyncMLClientLoader : public Buteo::SyncPluginLoader { Q_OBJECT Q_PLUGIN_METADATA(IID "com.buteo.plugins.sync.SyncMLClientLoader") Q_INTERFACES(Buteo::SyncPluginLoader) public: /*! \brief Creates SyncML client plugin * * @param aPluginName Name of this client plugin * @param aProfile Profile to use * @param aCbInterface Pointer to the callback interface * @return Client plugin on success, otherwise NULL */ Buteo::ClientPlugin* createClientPlugin(const QString& pluginName, const Buteo::SyncProfile& profile, Buteo::PluginCbInterface* cbInterface) override; }; #endif // SYNCMLCLIENT_H buteo-sync-plugins-0.8.36/clientplugins/syncmlclient/syncmlclient.pro000066400000000000000000000022601476033560700262040ustar00rootroot00000000000000TARGET = syncml-client DEPENDPATH += . INCLUDEPATH += . ../../syncmlcommon CONFIG += link_pkgconfig PKGCONFIG = buteosyncfw5 buteosyncml5 accounts-qt5 libsignon-qt5 systemsettings LIBS += -lsyncmlcommon5 LIBS += -L../../syncmlcommon QT += dbus sql network QT -= gui VER_MAJ = 1 VER_MIN = 0 VER_PAT = 0 #DEFINES += BUTEO_ENABLE_DEBUG HEADERS += SyncMLClient.h BTConnection.h SOURCES += SyncMLClient.cpp BTConnection.cpp TEMPLATE = lib CONFIG += plugin target.path = $$[QT_INSTALL_LIBS]/buteo-plugins-qt5/oopp OTHER_FILES += xml/* \ xml/sync/* \ xml/service/* \ xml/storage/* QMAKE_CXXFLAGS = -Wall \ -g \ -Wno-cast-align \ -O2 -finline-functions QMAKE_CLEAN += $(TARGET) $(TARGET0) $(TARGET1) $(TARGET2) QMAKE_CLEAN += $(OBJECTS_DIR)/*.gcda $(OBJECTS_DIR)/*.gcno $(OBJECTS_DIR)/*.gcov $(OBJECTS_DIR)/moc_* client.path = /etc/buteo/profiles/client client.files = xml/syncml.xml sync.path = /etc/buteo/profiles/sync sync.files = xml/sync/* service.path = /etc/buteo/profiles/service service.files = xml/service/* storage.path = /etc/buteo/profiles/storage storage.files = xml/storage/* INSTALLS += target client sync service storage buteo-sync-plugins-0.8.36/clientplugins/syncmlclient/unittest/000077500000000000000000000000001476033560700246355ustar00rootroot00000000000000buteo-sync-plugins-0.8.36/clientplugins/syncmlclient/unittest/TestSyncmlClient.cpp000077500000000000000000000017511476033560700306140ustar00rootroot00000000000000/* * This file is part of buteo-sync-plugins package * * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). * * Contact: Sateesh Kavuri * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * */ #include "TestSyncmlClient.h" // @TODO add more tests to make proper unit tests for syncml client plugin. buteo-sync-plugins-0.8.36/clientplugins/syncmlclient/unittest/TestSyncmlClient.h000077500000000000000000000024501476033560700302560ustar00rootroot00000000000000/* * This file is part of buteo-sync-plugins package * * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). * * Contact: Sateesh Kavuri * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * */ #ifndef TESTSYNCMLCLIENT_H #define TESTSYNCMLCLIENT_H // @TODO add more tests to make proper unit tests for syncml client plugin. #include class TestSyncmlClient : public QObject { Q_OBJECT private slots: // @TODO : write some tests private: // @TODO : write some tests public: TestSyncmlClient() {} ~TestSyncmlClient() {} }; #endif // TESTSYNCMLCLIENT_H buteo-sync-plugins-0.8.36/clientplugins/syncmlclient/unittest/main.cpp000077500000000000000000000021751476033560700262750ustar00rootroot00000000000000/* * This file is part of buteo-sync-plugins package * * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). * * Contact: Sateesh Kavuri * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * */ #include #include #include "TestSyncmlClient.h" int main(int argc, char* argv[]) { QCoreApplication app(argc, argv); TestSyncmlClient clientTest; QTest::qExec(&clientTest, argc, argv); return 0; } buteo-sync-plugins-0.8.36/clientplugins/syncmlclient/unittest/run-test000077500000000000000000000026021476033560700263440ustar00rootroot00000000000000#/* # * This file is part of buteo-sync-plugins package # * # * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). # * # * Contact: Sateesh Kavuri # * # * This library is free software; you can redistribute it and/or # * modify it under the terms of the GNU Lesser General Public License # * version 2.1 as published by the Free Software Foundation. # * # * This library is distributed in the hope that it will be useful, but # * WITHOUT ANY WARRANTY; without even the implied warranty of # * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # * Lesser General Public License for more details. # * # * You should have received a copy of the GNU Lesser General Public # * License along with this library; if not, write to the Free Software # * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA # * 02110-1301 USA # * # */ echo "Building Unit Tests for syncmlclient" #clean sbox cache export SBOX_USE_CCACHE=no ccache -c qmake make -j2 if [ -f unit_test_results.txt ]; then rm unit_test_results.txt fi # pre-conditions to run the tests .... #sb-conf killall meego-run ./syncmlclientplugtest >> unit_test_results.txt 2>&1 if [ -f gcov_results.txt ]; then rm gcov_results.txt fi echo "Running gcov ... results will be stored in $PWD/gcov_results.txt" gcov syncMLClient.gcno >> gcov_results.txt 2>&1 make distclean > /dev/null rm *.gcov buteo-sync-plugins-0.8.36/clientplugins/syncmlclient/unittest/unittest.pro000077500000000000000000000012311476033560700272360ustar00rootroot00000000000000# ------------------------------------------------- # Project created by QtCreator 2009-07-07T08:59:55 # ------------------------------------------------- QT += network \ script \ xml \ testlib QT -= gui TARGET = syncmlclientplugtest CONFIG += console CONFIG -= app_bundle TEMPLATE = app SOURCES += main.cpp \ TestSyncmlClient.cpp HEADERS += TestSyncmlClient.h INCLUDEPATH += ../ \ /usr/include/sync/ \ QMAKE_CLEAN += $(OBJECTS_DIR)/*.gcda $(OBJECTS_DIR)/*.gcno QMAKE_CXXFLAGS += -fprofile-arcs -ftest-coverage QMAKE_LFLAGS += -fprofile-arcs -ftest-coverage #install target.path = /opt/tests/buteo-sync-plugins/ INSTALLS += target buteo-sync-plugins-0.8.36/clientplugins/syncmlclient/xml/000077500000000000000000000000001476033560700235565ustar00rootroot00000000000000buteo-sync-plugins-0.8.36/clientplugins/syncmlclient/xml/service/000077500000000000000000000000001476033560700252165ustar00rootroot00000000000000buteo-sync-plugins-0.8.36/clientplugins/syncmlclient/xml/service/bt.xml000066400000000000000000000027031476033560700263470ustar00rootroot00000000000000 buteo-sync-plugins-0.8.36/clientplugins/syncmlclient/xml/service/btS40.xml000066400000000000000000000020461476033560700266360ustar00rootroot00000000000000 buteo-sync-plugins-0.8.36/clientplugins/syncmlclient/xml/service/memotoo.com.xml000066400000000000000000000023311476033560700301730ustar00rootroot00000000000000 buteo-sync-plugins-0.8.36/clientplugins/syncmlclient/xml/storage/000077500000000000000000000000001476033560700252225ustar00rootroot00000000000000buteo-sync-plugins-0.8.36/clientplugins/syncmlclient/xml/storage/hcalendar.xml000066400000000000000000000003671476033560700276730ustar00rootroot00000000000000 buteo-sync-plugins-0.8.36/clientplugins/syncmlclient/xml/storage/hcontacts.xml000066400000000000000000000002531476033560700277320ustar00rootroot00000000000000 buteo-sync-plugins-0.8.36/clientplugins/syncmlclient/xml/storage/hnotes.xml000066400000000000000000000005051476033560700272440ustar00rootroot00000000000000 buteo-sync-plugins-0.8.36/clientplugins/syncmlclient/xml/sync/000077500000000000000000000000001476033560700245325ustar00rootroot00000000000000buteo-sync-plugins-0.8.36/clientplugins/syncmlclient/xml/sync/bt_template.xml000066400000000000000000000022461476033560700275600ustar00rootroot00000000000000 buteo-sync-plugins-0.8.36/clientplugins/syncmlclient/xml/sync/memotoo.com.xml000066400000000000000000000026631476033560700275170ustar00rootroot00000000000000 buteo-sync-plugins-0.8.36/clientplugins/syncmlclient/xml/sync/switch.xml000077500000000000000000000024011476033560700265550ustar00rootroot00000000000000 buteo-sync-plugins-0.8.36/clientplugins/syncmlclient/xml/syncml.xml000066400000000000000000000003501476033560700256030ustar00rootroot00000000000000 buteo-sync-plugins-0.8.36/doc/000077500000000000000000000000001476033560700161375ustar00rootroot00000000000000buteo-sync-plugins-0.8.36/doc/Doxyfile000066400000000000000000002041301476033560700176450ustar00rootroot00000000000000# Doxyfile 1.6.3 # 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 #--------------------------------------------------------------------------- # This tag specifies the encoding used for all characters in the config file # that follow. The default is UTF-8 which is also the encoding used for all # text before the first occurrence of this tag. Doxygen uses libiconv (or the # iconv built into libc) for the transcoding. See # http://www.gnu.org/software/libiconv for the list of possible encodings. DOXYFILE_ENCODING = UTF-8 # The PROJECT_NAME tag is a single word (or a sequence of words surrounded # by quotes) that should identify the project. PROJECT_NAME = HarmattanSyncApplications # 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 = # 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 = ../doc/ # 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: # Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, # Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, # Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English # messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, # Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrilic, Slovak, # Slovene, Spanish, Swedish, Ukrainian, and Vietnamese. OUTPUT_LANGUAGE = English # 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 = "The $name class" \ "The $name widget" \ "The $name file" \ is \ provides \ specifies \ contains \ represents \ a \ an \ the # 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 = NO # 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 = NO # 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 regular Qt-style comments # (thus requiring an explicit @brief command for a brief description.) JAVADOC_AUTOBRIEF = NO # If the QT_AUTOBRIEF tag is set to YES then Doxygen will # interpret the first line (until the first dot) of a Qt-style # comment as the brief description. If set to NO, the comments # will behave just like regular Qt-style comments (thus requiring # an explicit \brief command for a brief description.) QT_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 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 the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce # a new page for each member. If set to NO, the documentation of a member will # be part of the file/class/namespace that contains it. SEPARATE_MEMBER_PAGES = 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 = 4 # 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 = NO # 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 OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran # sources only. Doxygen will then generate output that is more tailored for # Fortran. OPTIMIZE_FOR_FORTRAN = NO # Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL # sources. Doxygen will then generate output that is tailored for # VHDL. OPTIMIZE_OUTPUT_VHDL = NO # Doxygen selects the parser to use depending on the extension of the files it parses. # With this tag you can assign which parser to use for a given extension. # Doxygen has a built-in mapping, but you can override or extend it using this tag. # The format is ext=language, where ext is a file extension, and language is one of # the parsers supported by doxygen: IDL, Java, Javascript, C#, C, C++, D, PHP, # Objective-C, Python, Fortran, VHDL, C, C++. For instance to make doxygen treat # .inc files as Fortran files (default is PHP), and .f files as C (default is Fortran), # use: inc=Fortran f=C. Note that for custom extensions you also need to set FILE_PATTERNS otherwise the files are not read by doxygen. EXTENSION_MAPPING = # If you use STL classes (i.e. std::string, std::vector, etc.) but do not want # to include (a tag file for) the STL sources as input, then you should # set this tag to YES in order to let doxygen match functions declarations and # definitions whose arguments contain STL classes (e.g. func(std::string); v.s. # func(std::string) {}). This also make the inheritance and collaboration # diagrams that involve STL classes more complete and accurate. BUILTIN_STL_SUPPORT = NO # If you use Microsoft's C++/CLI language, you should set this option to YES to # enable parsing support. CPP_CLI_SUPPORT = NO # Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. # Doxygen will parse them like normal C++ but will assume all classes use public # instead of private inheritance when no explicit protection keyword is present. SIP_SUPPORT = NO # For Microsoft's IDL there are propget and propput attributes to indicate getter # and setter methods for a property. Setting this option to YES (the default) # will make doxygen to replace the get and set methods by a property in the # documentation. This will only work if the methods are indeed getting or # setting a simple type. If this is not the case, or you want to show the # methods anyway, you should set this option to NO. IDL_PROPERTY_SUPPORT = 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 # 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 # When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum # is documented as struct, union, or enum with the name of the typedef. So # typedef struct TypeS {} TypeT, will appear in the documentation as a struct # with name TypeT. When disabled the typedef will appear as a member of a file, # namespace, or class. And the struct will be named TypeS. This can typically # be useful for C code in case the coding convention dictates that all compound # types are typedef'ed and only the typedef is referenced, never the tag name. TYPEDEF_HIDES_STRUCT = NO # The SYMBOL_CACHE_SIZE determines the size of the internal cache use to # determine which symbols to keep in memory and which to flush to disk. # When the cache is full, less often used symbols will be written to disk. # For small to medium size projects (<1000 input files) the default value is # probably good enough. For larger projects a too small cache size can cause # doxygen to be busy swapping symbols to and from disk most of the time # causing a significant performance penality. # If the system has enough physical memory increasing the cache will improve the # performance by keeping more symbols in memory. Note that the value works on # a logarithmic scale so increasing the size by one will rougly double the # memory usage. The cache size is given by this formula: # 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, # corresponding to a cache size of 2^16 = 65536 symbols SYMBOL_CACHE_SIZE = 0 #--------------------------------------------------------------------------- # 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 = NO # 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 this flag is set to YES, the members of anonymous namespaces will be # extracted and appear in the documentation as a namespace called # 'anonymous_namespace{file}', where file will be replaced with the base # name of the file that contains the anonymous namespace. By default # anonymous namespace are hidden. EXTRACT_ANON_NSPACES = 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 FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen # will list include files with double quotes in the documentation # rather than with sharp brackets. FORCE_LOCAL_INCLUDES = NO # 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 = YES # 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_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the (brief and detailed) documentation of class members so that constructors and destructors are listed first. If set to NO (the default) the constructors will appear in the respective orders defined by SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO. SORT_MEMBERS_CTORS_1ST = NO # If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the # hierarchy of group names into alphabetical order. If set to NO (the default) # the group names will appear in their defined order. SORT_GROUP_NAMES = 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 # If the sources in your project are distributed over multiple directories # then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy # in the documentation. The default is NO. SHOW_DIRECTORIES = NO # Set the SHOW_FILES tag to NO to disable the generation of the Files page. # This will remove the Files entry from the Quick Index and from the # Folder Tree View (if specified). The default is YES. SHOW_FILES = YES # Set the SHOW_NAMESPACES tag to NO to disable the generation of the # Namespaces page. # This will remove the Namespaces entry from the Quick Index # and from the Folder Tree View (if specified). The default is YES. SHOW_NAMESPACES = YES # The FILE_VERSION_FILTER tag can be used to specify a program or script that # doxygen should invoke to get the current version for each file (typically from # the version control system). Doxygen will invoke the program by executing (via # popen()) the command , where is the value of # the FILE_VERSION_FILTER tag, and is the name of an input file # provided by doxygen. Whatever the program writes to standard output # is used as the file version. See the manual for examples. FILE_VERSION_FILTER = # The LAYOUT_FILE tag can be used to specify a layout file which will be parsed by # doxygen. The layout file controls the global structure of the generated output files # in an output format independent way. The create the layout file that represents # doxygen's defaults, run doxygen with the -l option. You can optionally specify a # file name after the option, if omitted DoxygenLayout.xml will be used as the name # of the layout file. LAYOUT_FILE = #--------------------------------------------------------------------------- # 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 # This WARN_NO_PARAMDOC option can be abled to get warnings for # functions that are documented, but have no documentation for their parameters # or return value. If set to NO (the default) doxygen will only warn about # wrong or incomplete parameter documentation, but not about the absence of # documentation. WARN_NO_PARAMDOC = NO # 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. Optionally the format may contain # $version, which will be replaced by the version of the file (if it could # be obtained via FILE_VERSION_FILTER) 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 = ../. # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is # also the default input encoding. Doxygen uses libiconv (or the iconv built # into libc) for the transcoding. See http://www.gnu.org/software/libiconv for # the list of possible encodings. INPUT_ENCODING = UTF-8 # 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 *.py *.f90 FILE_PATTERNS = *.c \ *.cc \ *.cxx \ *.c++ \ *.d \ *.java \ *.ii \ *.ixx \ *.ipp \ *.i++ \ *.inl \ *.h \ *.hh \ *.hxx \ *.hpp \ *.h++ \ *.idl \ *.odl \ *.cs \ *.php \ *.php3 \ *.inc \ *.m \ *.mm \ *.dox \ *.py \ *.f90 \ *.f \ *.vhd \ *.vhdl \ *.C \ *.CC \ *.C++ \ *.II \ *.I++ \ *.H \ *.HH \ *.H++ \ *.CS \ *.PHP \ *.PHP3 \ *.M \ *.MM \ *.PY \ *.F90 \ *.F \ *.VHD \ *.VHDL \ *.C \ *.H \ *.tlh \ *.diff \ *.patch \ *.moc \ *.xpm \ *.dox # 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. Note that the wildcards are matched # against the file with absolute path, so to exclude all test directories # for example use the pattern */test/* EXCLUDE_PATTERNS = */unittest/* \ */.git/* # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names # (namespaces, classes, functions, etc.) that should be excluded from the # output. The symbol name can be a fully qualified name, a word, or if the # wildcard * is used, a substring. Examples: ANamespace, AClass, # AClass::ANamespace, ANamespace::*Test EXCLUDE_SYMBOLS = YES # 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 = NO # 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 # then for each documented function all documented # functions referencing it will be listed. REFERENCED_BY_RELATION = NO # If the REFERENCES_RELATION tag is set to YES # then for each documented function all documented entities # called/used by that function will be listed. REFERENCES_RELATION = NO # If the REFERENCES_LINK_SOURCE tag is set to YES (the default) # and SOURCE_BROWSER tag is set to YES, then the hyperlinks from # functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will # link to the source code. # Otherwise they will link to the documentation. REFERENCES_LINK_SOURCE = YES # If the USE_HTAGS tag is set to YES then the references to source code # will point to the HTML generated by the htags(1) tool instead of doxygen # built-in source browser. The htags tool is part of GNU's global source # tagging system (see http://www.gnu.org/software/global/global.html). You # will need version 4.8.6 or higher. USE_HTAGS = 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 = # If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML # page will contain the date and time when the page was generated. Setting # this to NO can help when comparing the output of multiple runs. HTML_TIMESTAMP = YES # 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 HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML # documentation will contain sections that can be hidden and shown after the # page has loaded. For this to work a browser that supports # JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox # Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). HTML_DYNAMIC_SECTIONS = NO # If the GENERATE_DOCSET tag is set to YES, additional index files # will be generated that can be used as input for Apple's Xcode 3 # integrated development environment, introduced with OSX 10.5 (Leopard). # To create a documentation set, doxygen will generate a Makefile in the # HTML output directory. Running make will produce the docset in that # directory and running "make install" will install the docset in # ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find # it at startup. # See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html for more information. GENERATE_DOCSET = NO # When GENERATE_DOCSET tag is set to YES, this tag determines the name of the # feed. A documentation feed provides an umbrella under which multiple # documentation sets from a single provider (such as a company or product suite) # can be grouped. DOCSET_FEEDNAME = "Doxygen generated docs" # When GENERATE_DOCSET tag is set to YES, this tag specifies a string that # should uniquely identify the documentation set bundle. This should be a # reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen # will append .docset to the name. DOCSET_BUNDLE_ID = org.doxygen.Project # 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 compiled 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 CHM_INDEX_ENCODING # is used to encode HtmlHelp index (hhk), content (hhc) and project file # content. CHM_INDEX_ENCODING = # 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 # If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and QHP_VIRTUAL_FOLDER # are set, an additional index file will be generated that can be used as input for # Qt's qhelpgenerator to generate a Qt Compressed Help (.qch) of the generated # HTML documentation. GENERATE_QHP = NO # If the QHG_LOCATION tag is specified, the QCH_FILE tag can # be used to specify the file name of the resulting .qch file. # The path specified is relative to the HTML output folder. QCH_FILE = # The QHP_NAMESPACE tag specifies the namespace to use when generating # Qt Help Project output. For more information please see # http://doc.trolltech.com/qthelpproject.html#namespace QHP_NAMESPACE = org.doxygen.Project # The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating # Qt Help Project output. For more information please see # http://doc.trolltech.com/qthelpproject.html#virtual-folders QHP_VIRTUAL_FOLDER = doc # If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to add. # For more information please see # http://doc.trolltech.com/qthelpproject.html#custom-filters QHP_CUST_FILTER_NAME = # The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the custom filter to add.For more information please see # Qt Help Project / Custom Filters. QHP_CUST_FILTER_ATTRS = # The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this project's # filter section matches. # Qt Help Project / Filter Attributes. QHP_SECT_FILTER_ATTRS = # If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can # be used to specify the location of Qt's qhelpgenerator. # If non-empty doxygen will try to run qhelpgenerator on the generated # .qhp file. QHG_LOCATION = # If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files # will be generated, which together with the HTML files, form an Eclipse help # plugin. To install this plugin and make it available under the help contents # menu in Eclipse, the contents of the directory containing the HTML and XML # files needs to be copied into the plugins directory of eclipse. The name of # the directory within the plugins directory should be the same as # the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before the help appears. GENERATE_ECLIPSEHELP = NO # A unique identifier for the eclipse help plugin. When installing the plugin # the directory name containing the HTML and XML files should also have # this name. ECLIPSE_DOC_ID = org.doxygen.Project # 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 # The GENERATE_TREEVIEW tag is used to specify whether a tree-like index # structure should be generated to display hierarchical information. # If the tag value 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 (i.e. any modern browser). # Windows users are probably better off using the HTML help feature. GENERATE_TREEVIEW = NONE # By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories, # and Class Hierarchy pages using a tree view instead of an ordered list. USE_INLINE_TREES = 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 # Use this tag to change the font size of Latex formulas included # as images in the HTML documentation. The default is 10. Note that # when you change the font size after a successful doxygen run you need # to manually remove any form_*.png images from the HTML output directory # to force them to be regenerated. FORMULA_FONTSIZE = 10 # When the SEARCHENGINE tag is enabled doxygen will generate a search box for the HTML output. The underlying search engine uses javascript # and DHTML and should work on any modern browser. Note that when using HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) there is already a search function so this one should # typically be disabled. For large projects the javascript based search engine # can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution. SEARCHENGINE = NO # When the SERVER_BASED_SEARCH tag is enabled the search engine will be implemented using a PHP enabled web server instead of at the web client using Javascript. Doxygen will generate the search PHP script and index # file to put on the web server. The advantage of the server based approach is that it scales better to large projects and allows full text search. The disadvances is that it is more difficult to setup # and does not have live searching capabilities. SERVER_BASED_SEARCH = NO #--------------------------------------------------------------------------- # 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. # Note that when enabling USE_PDFLATEX this option is only used for # generating bitmaps for formulas in the HTML output, but not in the # Makefile that is written to the output directory. 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 = YES # 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 = YES # 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 # If LATEX_SOURCE_CODE is set to YES then doxygen will include source code with syntax highlighting in the LaTeX output. Note that which sources are shown also depends on other settings such as SOURCE_BROWSER. LATEX_SOURCE_CODE = 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_DEFINED 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. To prevent a macro definition from being # undefined via #undef or recursively expanded use the := operator # instead of the = operator. PREDEFINED = # 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 = sync-app.tag # 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 # You can define message sequence charts within doxygen comments using the \msc # command. Doxygen will then run the mscgen tool (see # http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the # documentation. The MSCGEN_PATH tag allows you to specify the directory where # the mscgen tool resides. If left empty the tool is assumed to be found in the # default search path. MSCGEN_PATH = # 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 = NO # By default doxygen will write a font called FreeSans.ttf to the output # directory and reference it in all dot files that doxygen generates. This # font does not include all possible unicode characters however, so when you need # these (or just want a differently looking font) you can specify the font name # using DOT_FONTNAME. You need need to make sure dot is able to find the font, # which can be done by putting it in a standard location or by setting the # DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory # containing the font. DOT_FONTNAME = FreeSans # The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. # The default size is 10pt. DOT_FONTSIZE = 10 # By default doxygen will tell dot to use the output directory to look for the # FreeSans.ttf font (which doxygen will put there itself). If you specify a # different font using DOT_FONTNAME you can set the path where dot # can find it using this tag. DOT_FONTPATH = # 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 GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen # will generate a graph for groups, showing the direct groups dependencies GROUP_GRAPHS = 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 = NO # 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 options 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 = NO # If the CALLER_GRAPH and HAVE_DOT tags are set to YES then # doxygen will generate a caller 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 caller # graphs for selected functions only using the \callergraph command. CALLER_GRAPH = NO # 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 # If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES # then doxygen will show the dependencies a directory has on other directories # in a graphical way. The dependency relations are determined by the #include # relations between the files in the directories. DIRECTORY_GRAPH = 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 in 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 DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of # nodes that will be shown in the graph. If the number of nodes in a graph # becomes larger than this value, doxygen will truncate the graph, which is # visualized by representing a node as a red box. Note that doxygen if the # number of direct children of the root node in a graph is already larger than # DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note # that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. DOT_GRAPH_MAX_NODES = 50 # 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 the size of a graph can be further restricted by # DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. MAX_DOT_GRAPH_DEPTH = 1000 # Set the DOT_TRANSPARENT tag to YES to generate images with a transparent # background. This is disabled by default, because dot on Windows does not # seem to support this out of the box. Warning: Depending on the platform used, # enabling this option may lead to badly anti-aliased labels on the edges of # a graph (i.e. they become hard to read). DOT_TRANSPARENT = YES # Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output # files in one run (i.e. multiple -o and -T options on the command line). This # makes dot run faster, but since only newer versions of dot (>1.8.10) # support this, this feature is disabled by default. DOT_MULTI_TARGETS = NO # 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 buteo-sync-plugins-0.8.36/doc/doc.pro000077500000000000000000000006171476033560700174350ustar00rootroot00000000000000DOXYGEN_BIN=doxygen QT -= gui QMAKE_EXTRA_TARGETS += doc doc.target = doc isEmpty(DOXYGEN_BIN) { doc.commands = @echo "Unable to detect doxygen in PATH" } else { doc.commands = @$${DOXYGEN_BIN} Doxyfile; } doc.depends = FORCE # Install rules htmldocs.files = ../doc/html/* htmldocs.path = /${DEB_DESTDIR}/usr/share/doc/sync-app-doc htmldocs.CONFIG += no_check_exist INSTALLS += htmldocs buteo-sync-plugins-0.8.36/rpm/000077500000000000000000000000001476033560700161705ustar00rootroot00000000000000buteo-sync-plugins-0.8.36/rpm/buteo-sync-plugins-qt5.spec000066400000000000000000000050721476033560700233260ustar00rootroot00000000000000Name: buteo-sync-plugins-qt5 Version: 0.8.29 Release: 1 Summary: Synchronization plugins URL: https://github.com/sailfishos/buteo-sync-plugins License: LGPLv2.1 Source0: %{name}-%{version}.tar.gz BuildRequires: pkgconfig(glib-2.0) BuildRequires: pkgconfig(Qt5Core) BuildRequires: pkgconfig(Qt5Network) BuildRequires: pkgconfig(Qt5Contacts) BuildRequires: pkgconfig(Qt5Versit) BuildRequires: pkgconfig(Qt5Sql) BuildRequires: pkgconfig(Qt5DBus) BuildRequires: pkgconfig(Qt5Test) BuildRequires: pkgconfig(openobex) BuildRequires: pkgconfig(accounts-qt5) BuildRequires: pkgconfig(libsignon-qt5) BuildRequires: pkgconfig(buteosyncml5) BuildRequires: pkgconfig(buteosyncfw5) >= 0.10.0 BuildRequires: pkgconfig(qtcontacts-sqlite-qt5-extensions) BuildRequires: pkgconfig(contactcache-qt5) >= 0.0.76 BuildRequires: pkgconfig(libmkcal-qt5) BuildRequires: pkgconfig(KF5CalendarCore) BuildRequires: pkgconfig(sqlite3) BuildRequires: pkgconfig(systemsettings) BuildRequires: doxygen %description %{summary}. %files %defattr(-,root,root,-) %config %{_sysconfdir}/buteo/xml/*.xml %config %{_sysconfdir}/buteo/profiles/server/*.xml %config %{_sysconfdir}/buteo/profiles/client/*.xml %config %{_sysconfdir}/buteo/profiles/storage/*.xml %config %{_sysconfdir}/buteo/profiles/service/*.xml %config %{_sysconfdir}/buteo/profiles/sync/bt_template.xml %config %{_sysconfdir}/buteo/plugins/syncmlserver/*.xml %{_libdir}/buteo-plugins-qt5/oopp/* %{_libdir}/buteo-plugins-qt5/*.so %{_libdir}/*.so.* %package devel Requires: %{name} = %{version}-%{release} Summary: Development files for %{name} %description devel %{summary}. %files devel %defattr(-,root,root,-) %{_includedir}/* %{_libdir}/*.so %{_libdir}/*.prl %{_libdir}/pkgconfig/*.pc %package doc Summary: Documentation for %{name} %description doc %{summary}. %files doc %defattr(-,root,root,-) %{_docdir}/sync-app-doc %package tests Summary: Tests for %{name} Requires: %{name} = %{version}-%{release} Requires: blts-tools %description tests %{summary}. %files tests %defattr(-,root,root,-) /opt/tests/buteo-sync-plugins %package -n buteo-service-memotoo Summary: Memotoo service description for Buteo SyncML Requires: %{name} = %{version} %description -n buteo-service-memotoo %{summary}. %files -n buteo-service-memotoo %defattr(-,root,root,-) %config %{_sysconfdir}/buteo/profiles/sync/memotoo.com.xml %prep %setup -q -n %{name}-%{version} %build %qmake5 "VERSION=%{version}" make %{?_smp_mflags} %install make INSTALL_ROOT=%{buildroot} install rm -f %{buildroot}/%{_sysconfdir}/buteo/profiles/sync/switch.xml %post -p /sbin/ldconfig %postun -p /sbin/ldconfig buteo-sync-plugins-0.8.36/rpm/buteo-sync-plugins.changes000066400000000000000000000024631476033560700232760ustar00rootroot00000000000000* Mon Sep 24 2012 Bernd Wachter - 0.7.0 - Update to nemo upstream, contributing to JB#2310 * Sun Sep 09 2012 Bernd Wachter - 0.6.5 - Update to latest upstream - Move tests to /opt/tests * Mon Jan 31 2011 Bernd Wachter - 0.5.6.64 - Update version, fixing BMC#13137 * Wed Jan 05 2011 Bernd Wachter - 0.5.6.61 - Update version, fixing BMC#11997 * Fri Dec 17 2010 Bernd Wachter - 0.5.6.60 - Update version, fixing BMC#4945 * Wed Nov 24 2010 Bernd Wachter - 0.5.6.57 - Update version, fixes: BME#3869 * Sun Oct 17 2010 Bernd Wachter - 0.5.6.48 - Update to latest version * Thu Sep 23 2010 Bernd Wachter - 0.5.6.46 - Update version, fixing BMC#3869, BMC#3888, BMC#4945 * Tue Aug 24 2010 Bernd Wachter - 0.5.6.34 - Update to latest version * Fri Aug 13 2010 Bernd Wachter - 0.5.6 - Change build requires to pkgconfig * Wed Aug 11 2010 Kaitlin Rupert - 0.5.6 - Replace qt4-devel with QtCore and QtNetwork * Tue Jun 29 2010 Bernd Wachter - 0.5.6 - Initial RPM version buteo-sync-plugins-0.8.36/serverplugins/000077500000000000000000000000001476033560700203025ustar00rootroot00000000000000buteo-sync-plugins-0.8.36/serverplugins/serverplugins.pro000066400000000000000000000000531476033560700237320ustar00rootroot00000000000000TEMPLATE = subdirs SUBDIRS += syncmlserver buteo-sync-plugins-0.8.36/serverplugins/syncmlserver/000077500000000000000000000000001476033560700230365ustar00rootroot00000000000000buteo-sync-plugins-0.8.36/serverplugins/syncmlserver/BTConnection.cpp000066400000000000000000000532111476033560700260710ustar00rootroot00000000000000/* * This file is part of buteo-sync-plugins package * * Copyright (C) 2013 Jolla Ltd. and/or its subsidiary(-ies). * * Author: Sateesh Kavuri * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include "SyncMLPluginLogging.h" #include #include #include #include #include #include "BTConnection.h" const QString CLIENT_BT_SR_FILE ("syncml_client_sdp_record.xml"); const QString SERVER_BT_SR_FILE ("syncml_server_sdp_record.xml"); const int BT_RFCOMM_PROTO = 3; const int RFCOMM_LM = 0x03; const int SOL_RFCOMM = 18; const int RFCOMM_LM_SECURE = 0x0200; const int BT_SERVER_CHANNEL = 26; const int BT_CLIENT_CHANNEL = 25; typedef struct { uint8_t b[6]; } __attribute__((packed)) btbdaddr_t; struct sockaddr_rc { sa_family_t rc_family; btbdaddr_t rc_bdaddr; uint8_t rc_channel; }; static QString btAddrInHex (const btbdaddr_t* ba, char* str) { sprintf(str, "%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X", ba->b[5], ba->b[4], ba->b[3], ba->b[2], ba->b[1], ba->b[0]); QString btAddr (str); return btAddr.toUpper (); } BTConnection::BTConnection() : mServerFd (-1), mClientFd (-1), mPeerSocket (-1), mMutex (QMutex::Recursive), mDisconnected (true), mClientServiceRecordId (-1), mServerServiceRecordId (-1), mServerReadNotifier (0), mServerWriteNotifier (0), mServerExceptionNotifier (0), mClientReadNotifier (0), mClientWriteNotifier (0), mClientExceptionNotifier (0), mServerFdWatching (false), mClientFdWatching (false) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); } BTConnection::~BTConnection () { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); if (mServerReadNotifier) { delete mServerReadNotifier; mServerReadNotifier = 0; } if (mServerWriteNotifier) { delete mServerWriteNotifier; mServerWriteNotifier = 0; } if (mServerExceptionNotifier) { delete mServerExceptionNotifier; mServerExceptionNotifier = 0; } if (mClientReadNotifier) { delete mClientReadNotifier; mClientReadNotifier = 0; } if (mClientWriteNotifier) { delete mClientWriteNotifier; mClientWriteNotifier = 0; } if (mClientExceptionNotifier) { delete mClientExceptionNotifier; mClientExceptionNotifier = 0; } } int BTConnection::connect () { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); return mPeerSocket; } bool BTConnection::isConnected () const { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); if (mPeerSocket == -1) return false; else return true; } void BTConnection::disconnect () { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); if (mPeerSocket != -1) { close (mPeerSocket); mPeerSocket = -1; } } void BTConnection::handleSyncFinished (bool isSyncInError) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); if (isSyncInError == true) { // If sync error, then close the BT connection and reopen it removeFdListener (BT_SERVER_CHANNEL); removeFdListener (BT_CLIENT_CHANNEL); closeBTSocket (mServerFd); closeBTSocket (mClientFd); openBTSocket (BT_SERVER_CHANNEL); openBTSocket (BT_CLIENT_CHANNEL); addFdListener (BT_SERVER_CHANNEL, mServerFd); addFdListener (BT_CLIENT_CHANNEL, mClientFd); } else { // No errors during sync. Add the fd listener qCDebug(lcSyncMLPlugin) << "Sync finished. Adding fd listener"; addFdListener (BT_SERVER_CHANNEL, mServerFd); addFdListener (BT_CLIENT_CHANNEL, mClientFd); } } int BTConnection::openBTSocket (const int channelNumber) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); int sock = socket (AF_BLUETOOTH, SOCK_STREAM, BT_RFCOMM_PROTO); if (sock < 0) { qCWarning(lcSyncMLPlugin) << "Unable to open bluetooth socket"; return -1; } int lm = RFCOMM_LM_SECURE; if (setsockopt (sock, SOL_RFCOMM, RFCOMM_LM, &lm, sizeof (lm)) < 0) { qCWarning(lcSyncMLPlugin) << "Unable to set socket options." << errno; return -1; } struct sockaddr_rc localAddr; memset (&localAddr, 0, sizeof (localAddr)); localAddr.rc_family = AF_BLUETOOTH; btbdaddr_t anyAddr = {{0, 0, 0, 0, 0, 0}}; // bind to any local bluetooth address localAddr.rc_channel = channelNumber; memcpy (&localAddr.rc_bdaddr, &anyAddr, sizeof (btbdaddr_t)); // Bind the socket if (bind (sock, (struct sockaddr*)&localAddr, sizeof (localAddr)) < 0) { qCWarning(lcSyncMLPlugin) << "Unable to bind to local address"; return -1; } // Listen for incoming connections if (listen (sock, 1) < 0) // We allow a max of 1 connection per SyncML session { qCWarning(lcSyncMLPlugin) << "Error while starting listening"; return -1; } // Set the socket into non-blocking mode long flags = fcntl (sock, F_GETFL); if (flags < 0) { qCWarning(lcSyncMLPlugin) << "Error while getting flags for socket"; } else { flags |= O_NONBLOCK; if (fcntl (sock, F_SETFL, flags) < 0) { qCWarning(lcSyncMLPlugin) << "Error while setting socket into non-blocking mode"; } } qCDebug(lcSyncMLPlugin) << "Opened BT socket with fd " << sock << " for channel " << channelNumber; return sock; } void BTConnection::closeBTSocket (int& fd) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); if (fd != -1) { close (fd); fd = -1; } } void BTConnection::addFdListener (const int channelNumber, int fd) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); if ((channelNumber == BT_SERVER_CHANNEL) && (mServerFdWatching == false) && (fd != -1)) { mServerReadNotifier = new QSocketNotifier (fd, QSocketNotifier::Read); mServerWriteNotifier = new QSocketNotifier (fd, QSocketNotifier::Write); mServerExceptionNotifier = new QSocketNotifier (fd, QSocketNotifier::Exception); mServerReadNotifier->setEnabled (true); mServerWriteNotifier->setEnabled (true); mServerExceptionNotifier->setEnabled (true); QObject::connect (mServerReadNotifier, SIGNAL (activated (int)), this, SLOT (handleIncomingBTConnection (int))); QObject::connect (mServerWriteNotifier, SIGNAL (activated (int)), this, SLOT (handleIncomingBTConnection (int))); QObject::connect (mServerExceptionNotifier, SIGNAL (activated (int)), this, SLOT (handleBTError (int))); qCDebug(lcSyncMLPlugin) << "Added listener for server socket " << fd; mServerFdWatching = true; } if ((channelNumber == BT_CLIENT_CHANNEL) && (mClientFdWatching == false) && (fd != -1)) { mClientReadNotifier = new QSocketNotifier (fd, QSocketNotifier::Read); mClientWriteNotifier = new QSocketNotifier (fd, QSocketNotifier::Write); mClientExceptionNotifier = new QSocketNotifier (fd, QSocketNotifier::Exception); mClientReadNotifier->setEnabled (true); mClientWriteNotifier->setEnabled (true); mClientExceptionNotifier->setEnabled (true); QObject::connect (mClientReadNotifier, SIGNAL (activated (int)), this, SLOT (handleIncomingBTConnection (int))); QObject::connect (mClientWriteNotifier, SIGNAL (activated (int)), this, SLOT (handleIncomingBTConnection (int))); QObject::connect (mClientExceptionNotifier, SIGNAL (activated (int)), this, SLOT (handleBTError (int))); qCDebug(lcSyncMLPlugin) << "Added listener for client socket " << fd; mClientFdWatching = true; } mDisconnected = false; } void BTConnection::removeFdListener (const int channelNumber) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); if (channelNumber == BT_SERVER_CHANNEL) { mServerReadNotifier->setEnabled (false); mServerWriteNotifier->setEnabled (false); mServerExceptionNotifier->setEnabled (false); QObject::disconnect (mServerReadNotifier, SIGNAL (activated (int)), this, SLOT (handleIncomingBTConnection (int))); QObject::disconnect (mServerWriteNotifier, SIGNAL (activated (int)), this, SLOT (handleIncomingBTConnection (int))); QObject::disconnect (mServerExceptionNotifier, SIGNAL (activated (int)), this, SLOT (handleBTError (int))); mServerFdWatching = false; } else if (channelNumber == BT_CLIENT_CHANNEL) { mClientReadNotifier->setEnabled (false); mClientWriteNotifier->setEnabled (false); mClientExceptionNotifier->setEnabled (false); QObject::disconnect (mClientReadNotifier, SIGNAL (activated (int)), this, SLOT (handleIncomingBTConnection (int))); QObject::disconnect (mClientWriteNotifier, SIGNAL (activated (int)), this, SLOT (handleIncomingBTConnection (int))); QObject::disconnect (mClientExceptionNotifier, SIGNAL (activated (int)), this, SLOT (handleBTError (int))); mClientFdWatching = false; } } void BTConnection::handleIncomingBTConnection (int fd) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); qCDebug(lcSyncMLPlugin) << "Incoming BT connection. Emitting signal to handle the incoming data"; struct sockaddr_rc remote; socklen_t len = sizeof (remote); mPeerSocket = accept (fd, (struct sockaddr*)&remote, &len); if (mPeerSocket < 0) { qCDebug(lcSyncMLPlugin) << "Error in accept:" << strerror (errno); } else { char buf[128] = { 0 }; QString btAddr = btAddrInHex (&remote.rc_bdaddr, buf); emit btConnected (mPeerSocket, btAddr); } // Disable event notifier if (fd == mServerFd) removeFdListener (BT_SERVER_CHANNEL); else if (fd == mClientFd) removeFdListener (BT_CLIENT_CHANNEL); } void BTConnection::handleBTError (int fd) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); qCDebug(lcSyncMLPlugin) << "Error in BT connection"; // Should this be similar to USB that we close and re-init BT? // FIXME: Ugly API for fd listeners. Add a more decent way if (fd == mServerFd) removeFdListener (BT_SERVER_CHANNEL); else if (fd == mClientFd) removeFdListener (BT_CLIENT_CHANNEL); closeBTSocket (fd); if (fd == mServerFd) openBTSocket (BT_SERVER_CHANNEL); else if (fd == mClientFd) openBTSocket (BT_CLIENT_CHANNEL); if (fd == mServerFd) addFdListener (BT_SERVER_CHANNEL, fd); else if (fd == mClientFd) addFdListener (BT_CLIENT_CHANNEL, fd); } bool BTConnection::init () { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); // Add client and server SyncML bluetooth records // Read the client record from file and if fails, read from code QByteArray clientSDP; if (!readSRFromFile (CLIENT_BT_SR_FILE, clientSDP)) { clientSDP = clientServiceRecordDef ().toLatin1 (); } addServiceRecord (clientSDP, mClientServiceRecordId); // Add client and server bluetooth sdp records QByteArray serverSDP; if (!readSRFromFile (SERVER_BT_SR_FILE, serverSDP)) { serverSDP = serverServiceRecordDef ().toLatin1 (); } addServiceRecord (serverSDP, mServerServiceRecordId); // Open the server and client socket mServerFd = openBTSocket (BT_SERVER_CHANNEL); mClientFd = openBTSocket (BT_CLIENT_CHANNEL); if (mServerFd == -1 || mClientFd == -1) { qCWarning(lcSyncMLPlugin) << "Error in opening BT client and server sockets"; return false; } addFdListener (BT_SERVER_CHANNEL, mServerFd); addFdListener (BT_CLIENT_CHANNEL, mClientFd); return true; } void BTConnection::uninit() { // Remove listeners removeFdListener (BT_SERVER_CHANNEL); removeFdListener (BT_CLIENT_CHANNEL); // Close the fd's closeBTSocket (mServerFd); closeBTSocket (mClientFd); // Close the peer socket closeBTSocket (mPeerSocket); // Remove service records removeServiceRecords (); } bool BTConnection::addServiceRecord (const QByteArray& sdp, quint32& recordId) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); // Get the Bluez manager dbus interface QDBusInterface mgrIface ("org.bluez", "/", "org.bluez.Manager", QDBusConnection::systemBus ()); if (!mgrIface.isValid ()) { qCWarning(lcSyncMLPlugin) << "Unable to get bluez manager iface"; return false; } // Fetch the default bluetooth adapter QDBusReply reply = mgrIface.call (QLatin1String ("DefaultAdapter")); QString adapterPath = reply.value ().path (); qCDebug(lcSyncMLPlugin) << "Bluetooth adapter path:" << adapterPath; QDBusInterface serviceIface ("org.bluez", adapterPath, "org.bluez.Service", QDBusConnection::systemBus ()); if (!serviceIface.isValid ()) { qCWarning(lcSyncMLPlugin) << "Unable to get bluez service iface"; return false; } QDBusReply response = serviceIface.call (QLatin1String ("AddRecord"), QLatin1String (sdp)); if (!response.isValid ()) { qCWarning(lcSyncMLPlugin) << "Unable to add client bluetooth service record"; return false; } recordId = response.value (); return true; } bool BTConnection::removeServiceRecords () { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); // Get the Bluez manager dbus interface QDBusInterface mgrIface ("org.bluez", "/", "org.bluez.Manager", QDBusConnection::systemBus ()); if (!mgrIface.isValid ()) { qCWarning(lcSyncMLPlugin) << "Unable to get bluez manager iface"; return false; } // Fetch the default bluetooth adapter QDBusReply reply = mgrIface.call (QLatin1String ("DefaultAdapter")); QString adapterPath = reply.value ().path (); qCDebug(lcSyncMLPlugin) << "Bluetooth adapter path:" << adapterPath; QDBusInterface serviceIface ("org.bluez", adapterPath, "org.bluez.Service", QDBusConnection::systemBus ()); if (!serviceIface.isValid ()) { qCWarning(lcSyncMLPlugin) << "Unable to get bluez service iface"; return false; } QDBusReply response = serviceIface.call (QLatin1String ("RemoveRecord"), mClientServiceRecordId); if (!response.isValid ()) { qCDebug(lcSyncMLPlugin) << "Unable to remove client bluetooth service record"; return false; } response = serviceIface.call (QLatin1String ("RemoveRecord"), mServerServiceRecordId); if (!response.isValid ()) { qCDebug(lcSyncMLPlugin) << "Unable to remove server bluetooth service record"; return false; } return true; } bool BTConnection::readSRFromFile (const QString filename, QByteArray &record) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); QFile srFile (filename); if (!srFile.open (QIODevice::ReadOnly)) { qCWarning(lcSyncMLPlugin) << "Unable to open service record files"; return false; } record = srFile.readAll (); srFile.close (); return true; } const QString BTConnection::clientServiceRecordDef () const { return " \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ "; } const QString BTConnection::serverServiceRecordDef () const { return " \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ "; } buteo-sync-plugins-0.8.36/serverplugins/syncmlserver/BTConnection.h000066400000000000000000000070401476033560700255350ustar00rootroot00000000000000/* * This file is part of buteo-sync-plugins package * * Copyright (C) 2013 Jolla Ltd. and/or its subsidiary(-ies). * * Author: Sateesh Kavuri * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef BTCONNECTION_H #define BTCONNECTION_H #include #include #include #include #include class BTConnection : public QObject, public DataSync::OBEXConnection { Q_OBJECT public: BTConnection (); virtual ~BTConnection (); /*! \sa DataSync::OBEXConnection::connect () * */ virtual int connect (); /*! \sa DataSync::OBEXConnection::isConnected () * */ virtual bool isConnected () const; /*! \sa DataSync::OBEXConnection::disconnect () * */ virtual void disconnect (); void handleSyncFinished (bool isSyncInError); /** * ! \brief BT initialization method */ bool init (); /** * ! \brief BT uninitialization method */ void uninit (); signals: void btConnected (int fd, QString btAddr); protected slots: void handleIncomingBTConnection (int fd); void handleBTError (int fd); private: // Functions /** * ! \brief Method to open bluetooth socket */ int openBTSocket (const int channelNumber); /** * ! \brief Method to close bluetooth socket */ void closeBTSocket (int &fd); /** * ! \brief FD listener method */ void addFdListener (const int channelNumber, int fd); /** * ! \brief Removes fd listening */ void removeFdListener (const int channelNumber); /** * ! \brief Method to add service record using Bluez dbus API */ bool addServiceRecord (const QByteArray& sdp, quint32& recordId); /** * ! \brief Method to remove service record using Bluez dbus API */ bool removeServiceRecords (); /** * ! \brief Method to read the service records from file */ bool readSRFromFile (const QString filename, QByteArray& record); const QString clientServiceRecordDef () const; const QString serverServiceRecordDef () const; private: int mServerFd; int mClientFd; int mPeerSocket; QMutex mMutex; bool mDisconnected; quint32 mClientServiceRecordId; quint32 mServerServiceRecordId; QSocketNotifier *mServerReadNotifier; QSocketNotifier *mServerWriteNotifier; QSocketNotifier *mServerExceptionNotifier; QSocketNotifier *mClientReadNotifier; QSocketNotifier *mClientWriteNotifier; QSocketNotifier *mClientExceptionNotifier; bool mServerFdWatching; bool mClientFdWatching; }; #endif // BTCONNECTION_H buteo-sync-plugins-0.8.36/serverplugins/syncmlserver/SyncMLServer.cpp000066400000000000000000000424161476033560700261050ustar00rootroot00000000000000/* * This file is part of buteo-sync-plugins package * * Copyright (C) 2013 Jolla Ltd. and/or its subsidiary(-ies). * * Author: Sateesh Kavuri * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include "SyncMLServer.h" #include "SyncMLPluginLogging.h" #include #include #include #include #include "SyncMLConfig.h" #include "DeviceInfo.h" Buteo::ServerPlugin* SyncMLServerLoader::createServerPlugin( const QString& pluginName, const Buteo::Profile& profile, Buteo::PluginCbInterface* cbInterface) { return new SyncMLServer(pluginName, profile, cbInterface); } SyncMLServer::SyncMLServer (const QString& pluginName, const Buteo::Profile profile, Buteo::PluginCbInterface *cbInterface) : ServerPlugin (pluginName, profile, cbInterface), mAgent (0), mConfig (0), mTransport (0), mCommittedItems (0), mConnectionType (Sync::CONNECTIVITY_USB), mIsSessionInProgress (false), mBTActive (false), mUSBActive (false) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); } SyncMLServer::~SyncMLServer () { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); closeSyncAgentConfig (); closeSyncAgent (); if (mUSBActive) closeUSBTransport (); if (mBTActive) closeBTTransport (); delete mTransport; } bool SyncMLServer::init () { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); return true; } bool SyncMLServer::uninit () { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); closeSyncAgentConfig (); closeSyncAgent (); // uninit() is called after completion of every sync session // Do not invoke close of transports, since in server mode // sync would be initiated from external entities and so // transport has to be open return true; } void SyncMLServer::abortSync (Sync::SyncStatus status) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); DataSync::SyncState state = DataSync::ABORTED; if (status == Sync::SYNC_ERROR) state = DataSync::CONNECTION_ERROR; if (mAgent && mAgent->abort (state)) { qCDebug(lcSyncMLPlugin) << "Signaling SyncML agent abort"; } else { handleSyncFinished (DataSync::ABORTED); } } bool SyncMLServer::cleanUp () { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); // FIXME: Perform necessary cleanup return true; } Buteo::SyncResults SyncMLServer::getSyncResults () const { return mResults; } bool SyncMLServer::startListen () { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); qCDebug(lcSyncMLPlugin) << "Starting listener"; bool listening = false; if (iCbInterface->isConnectivityAvailable (Sync::CONNECTIVITY_USB)) { mUSBActive = listening = createUSBTransport (); } if (iCbInterface->isConnectivityAvailable (Sync::CONNECTIVITY_BT)) { mBTActive = listening |= createBTTransport (); } if (iCbInterface->isConnectivityAvailable (Sync::CONNECTIVITY_INTERNET)) { // No sync over IP as of now } return listening; } void SyncMLServer::stopListen () { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); // Stop all connections if (mUSBActive) closeUSBTransport (); if (mBTActive) closeBTTransport (); } void SyncMLServer::suspend () { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); // Not implementing suspend } void SyncMLServer::resume () { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); // Not implementing suspend } void SyncMLServer::connectivityStateChanged (Sync::ConnectivityType type, bool state) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); qCDebug(lcSyncMLPlugin) << "Connectivity state changed event " << type << ". Connectivity changed to " << state; if (type == Sync::CONNECTIVITY_USB) { // Only connectivity changes would be USB enabled/disabled if (state) { qCDebug(lcSyncMLPlugin) << "USB available. Starting sync..."; mUSBActive = createUSBTransport (); } else { qCDebug(lcSyncMLPlugin) << "USB connection not available. Stopping sync..."; closeUSBTransport (); mUSBActive = false; // FIXME: Should we also abort any ongoing sync session? } } else if (type == Sync::CONNECTIVITY_BT) { if (state) { qCDebug(lcSyncMLPlugin) << "BT connection is available. Creating BT connection..."; mBTActive = createBTTransport (); } else { qCDebug(lcSyncMLPlugin) << "BT connection unavailable. Closing BT connection..."; closeBTTransport (); mBTActive = false; } } } bool SyncMLServer::initSyncAgent () { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); qCDebug(lcSyncMLPlugin) << "Creating SyncML agent..."; mAgent = new DataSync::SyncAgent (); return true; } void SyncMLServer::closeSyncAgent () { delete mAgent; mAgent = 0; } DataSync::SyncAgentConfig* SyncMLServer::initSyncAgentConfig () { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); if (!mTransport || !mStorageProvider.init (&iProfile, this, iCbInterface, true)) return 0; mConfig = new DataSync::SyncAgentConfig (); QString defaultSyncMLConfigFile, extSyncMLConfigFile; SyncMLConfig::syncmlConfigFilePaths (defaultSyncMLConfigFile, extSyncMLConfigFile); if (!mConfig->fromFile (defaultSyncMLConfigFile)) { qCCritical(lcSyncMLPlugin) << "Unable to read default SyncML config"; delete mConfig; mConfig = 0; return mConfig; } if (!mConfig->fromFile (extSyncMLConfigFile)) { qCDebug(lcSyncMLPlugin) << "Could not find external configuration file"; } mConfig->setStorageProvider (&mStorageProvider); mConfig->setTransport (mTransport); // Do we need to read the device info from file? QString DEV_INFO_FILE = SyncMLConfig::getDevInfoFile (); QFile devInfoFile (DEV_INFO_FILE); if (!devInfoFile.exists ()) { Buteo::DeviceInfo devInfo; QMap deviceInfoMap = devInfo.getDeviceInformation (); devInfo.saveDevInfoToFile (deviceInfoMap, DEV_INFO_FILE); } DataSync::DeviceInfo syncDeviceInfo; syncDeviceInfo.readFromFile (DEV_INFO_FILE); mConfig->setDeviceInfo (syncDeviceInfo); return mConfig; } void SyncMLServer::closeSyncAgentConfig () { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); qCDebug(lcSyncMLPlugin) << "Closing config..."; delete mConfig; mConfig = 0; if (!mStorageProvider.uninit ()) qCCritical(lcSyncMLPlugin) << "Unable to close storage provider"; } bool SyncMLServer::createUSBTransport () { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); qCDebug(lcSyncMLPlugin) << "Opening new USB connection"; mUSBConnection.connect (); QObject::connect (&mUSBConnection, SIGNAL (usbConnected (int)), this, SLOT (handleUSBConnected (int))); return mUSBConnection.isConnected (); } bool SyncMLServer::createBTTransport () { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); qCDebug(lcSyncMLPlugin) << "Creating new BT connection"; bool btInitRes = mBTConnection.init (); QObject::connect (&mBTConnection, SIGNAL (btConnected (int, QString)), this, SLOT (handleBTConnected (int, QString))); return btInitRes; } void SyncMLServer::closeUSBTransport () { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); QObject::disconnect (&mUSBConnection, SIGNAL (usbConnected (int)), this, SLOT (handleUSBConnected (int))); mUSBConnection.disconnect (); } void SyncMLServer::closeBTTransport () { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); QObject::disconnect (&mBTConnection, SIGNAL (btConnected (int, QString)), this, SLOT (handleBTConnected (int, QString))); mBTConnection.uninit (); } void SyncMLServer::handleUSBConnected (int fd) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); Q_UNUSED (fd); if (mIsSessionInProgress) { qCDebug(lcSyncMLPlugin) << "Sync session is in progress over transport " << mConnectionType; emit sessionInProgress (mConnectionType); return; } qCDebug(lcSyncMLPlugin) << "New incoming data over USB"; if (mTransport == NULL) { mTransport = new DataSync::OBEXTransport (mUSBConnection, DataSync::OBEXTransport::MODE_OBEX_SERVER, DataSync::OBEXTransport::TYPEHINT_USB); } if (!mTransport) { qCDebug(lcSyncMLPlugin) << "Creation of USB transport failed"; return; } if (!mAgent) { mConnectionType = Sync::CONNECTIVITY_USB; startNewSession ("USB"); } } void SyncMLServer::handleBTConnected (int fd, QString btAddr) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); Q_UNUSED (fd); if (mIsSessionInProgress) { qCDebug(lcSyncMLPlugin) << "Sync session is in progress over transport " << mConnectionType; emit sessionInProgress (mConnectionType); return; } qCDebug(lcSyncMLPlugin) << "New incoming connection over BT"; if (mTransport == NULL) { mTransport = new DataSync::OBEXTransport (mBTConnection, DataSync::OBEXTransport::MODE_OBEX_SERVER, DataSync::OBEXTransport::TYPEHINT_BT); } if (!mTransport) { qCDebug(lcSyncMLPlugin) << "Creation of BT transport failed"; return; } if (!mAgent) { mConnectionType = Sync::CONNECTIVITY_BT; startNewSession (btAddr); } } bool SyncMLServer::startNewSession (QString address) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); if (!initSyncAgent () || !initSyncAgentConfig ()) return false; QObject::connect (mAgent, SIGNAL (stateChanged (DataSync::SyncState)), this, SLOT (handleStateChanged (DataSync::SyncState))); QObject::connect (mAgent, SIGNAL (syncFinished (DataSync::SyncState)), this, SLOT (handleSyncFinished (DataSync::SyncState))); QObject::connect (mAgent, SIGNAL (storageAccquired (QString)), this, SLOT (handleStorageAccquired (QString))); QObject::connect (mAgent, SIGNAL (itemProcessed (DataSync::ModificationType, DataSync::ModifiedDatabase, QString, QString, int)), this, SLOT (handleItemProcessed (DataSync::ModificationType, DataSync::ModifiedDatabase, QString, QString, int))); mIsSessionInProgress = true; if (mAgent->listen (*mConfig)) { emit newSession (address); return true; } else { return false; } } void SyncMLServer::handleStateChanged (DataSync::SyncState state) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); qCDebug(lcSyncMLPlugin) << "SyncML new state " << state; } void SyncMLServer::handleSyncFinished (DataSync::SyncState state) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); qCDebug(lcSyncMLPlugin) << "Sync finished with state " << state; bool errorStatus = true; switch (state) { case DataSync::SUSPENDED: case DataSync::ABORTED: case DataSync::SYNC_FINISHED: { generateResults (true); errorStatus = false; emit success(getProfileName(), QString::number(state)); break; } case DataSync::INTERNAL_ERROR: case DataSync::DATABASE_FAILURE: case DataSync::CONNECTION_ERROR: case DataSync::INVALID_SYNCML_MESSAGE: { generateResults (false); emit error(getProfileName(), QString::number(state), Buteo::SyncResults::INTERNAL_ERROR); break; } default: { qCCritical(lcSyncMLPlugin) << "Unexpected state change"; generateResults (false); emit error(getProfileName(), QString::number(state), Buteo::SyncResults::INTERNAL_ERROR); break; } } uninit (); // Signal the USBConnection that sync has finished if (mConnectionType == Sync::CONNECTIVITY_USB) mUSBConnection.handleSyncFinished (errorStatus); else if (mConnectionType == Sync::CONNECTIVITY_BT) mBTConnection.handleSyncFinished (errorStatus); mIsSessionInProgress = false; } void SyncMLServer::handleStorageAccquired (QString type) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); // emit signal that storage has been acquired emit accquiredStorage (type); } void SyncMLServer::handleItemProcessed (DataSync::ModificationType modificationType, DataSync::ModifiedDatabase modifiedDb, QString localDb, QString dbType, int committedItems) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); qCDebug(lcSyncMLPlugin) << "Modification type:" << modificationType; qCDebug(lcSyncMLPlugin) << "ModificationType database:" << modifiedDb; qCDebug(lcSyncMLPlugin) << "Local database:" << localDb; qCDebug(lcSyncMLPlugin) << "Database type:" << dbType; qCDebug(lcSyncMLPlugin) << "Committed items:" << committedItems; mCommittedItems++; if (!receivedItems.contains (localDb)) { ReceivedItemDetails details; details.added = details.modified = details.deleted = details.error = 0; details.mime = dbType; receivedItems[localDb] = details; } switch (modificationType) { case DataSync::MOD_ITEM_ADDED: { ++receivedItems[localDb].added; break; } case DataSync::MOD_ITEM_MODIFIED: { ++receivedItems[localDb].modified; break; } case DataSync::MOD_ITEM_DELETED: { ++receivedItems[localDb].deleted; break; } case DataSync::MOD_ITEM_ERROR: { ++receivedItems[localDb].error; break; } default: { Q_ASSERT (0); break; } } Sync::TransferDatabase db = Sync::LOCAL_DATABASE; if (modifiedDb == DataSync::MOD_LOCAL_DATABASE) db = Sync::LOCAL_DATABASE; else db = Sync::REMOTE_DATABASE; if (mCommittedItems == committedItems) { QMapIterator itr (receivedItems); while (itr.hasNext ()) { itr.next (); if (itr.value ().added) emit transferProgress (getProfileName (), db, Sync::ITEM_ADDED, itr.value ().mime, itr.value ().added); if (itr.value ().modified) emit transferProgress (getProfileName (), db, Sync::ITEM_MODIFIED, itr.value ().mime, itr.value ().modified); if (itr.value ().deleted) emit transferProgress (getProfileName (), db, Sync::ITEM_DELETED, itr.value ().mime, itr.value ().deleted); if (itr.value ().error) emit transferProgress (getProfileName (), db, Sync::ITEM_ERROR, itr.value ().mime, itr.value ().error); } mCommittedItems = 0; receivedItems.clear (); } } void SyncMLServer::generateResults (bool success) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); mResults.setMajorCode (success ? Buteo::SyncResults::SYNC_RESULT_SUCCESS : Buteo::SyncResults::SYNC_RESULT_FAILED); mResults.setTargetId (mAgent->getResults().getRemoteDeviceId ()); const QMap* dbResults = mAgent->getResults ().getDatabaseResults (); if (dbResults->isEmpty ()) { qCDebug(lcSyncMLPlugin) << "No items transferred"; } else { QMapIterator itr (*dbResults); while (itr.hasNext ()) { itr.next (); const DataSync::DatabaseResults& r = itr.value (); Buteo::TargetResults targetResults( itr.key(), // Target name Buteo::ItemCounts (r.iLocalItemsAdded, r.iLocalItemsDeleted, r.iLocalItemsModified), Buteo::ItemCounts (r.iRemoteItemsAdded, r.iRemoteItemsDeleted, r.iRemoteItemsModified)); mResults.addTargetResults (targetResults); qCDebug(lcSyncMLPlugin) << "Items for" << targetResults.targetName () << ":"; qCDebug(lcSyncMLPlugin) << "LA:" << targetResults.localItems ().added << "LD:" << targetResults.localItems ().deleted << "LM:" << targetResults.localItems ().modified << "RA:" << targetResults.remoteItems ().added << "RD:" << targetResults.remoteItems ().deleted << "RM:" << targetResults.remoteItems ().modified; } } } buteo-sync-plugins-0.8.36/serverplugins/syncmlserver/SyncMLServer.h000066400000000000000000000116231476033560700255460ustar00rootroot00000000000000/* * This file is part of buteo-sync-plugins package * * Copyright (C) 2013 Jolla Ltd. and/or its subsidiary(-ies). * * Author: Sateesh Kavuri * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef SYNCMLSERVER_H #define SYNCMLSERVER_H #include "syncmlserver_global.h" #include "USBConnection.h" #include "BTConnection.h" #include "SyncMLStorageProvider.h" #include #include #include #include #include #include #include #include #include namespace Buteo { class ServerPlugin; class Profile; } namespace DataSync { class SyncAgent; class Transport; } class SYNCMLSERVERSHARED_EXPORT SyncMLServer : public Buteo::ServerPlugin { Q_OBJECT public: SyncMLServer (const QString& pluginName, const Buteo::Profile profile, Buteo::PluginCbInterface *cbInterface); virtual ~SyncMLServer (); virtual bool init (); virtual bool uninit (); virtual void abortSync (Sync::SyncStatus status = Sync::SYNC_ABORTED); virtual bool cleanUp (); virtual Buteo::SyncResults getSyncResults () const; virtual bool startListen (); virtual void stopListen (); virtual void suspend (); virtual void resume (); signals: void syncFinished (Sync::SyncStatus); void sessionInProgress (Sync::ConnectivityType); public slots: virtual void connectivityStateChanged (Sync::ConnectivityType type, bool state); protected slots: void handleUSBConnected (int fd); void handleBTConnected (int fd, QString btAddr); void handleSyncFinished (DataSync::SyncState state); void handleStateChanged (DataSync::SyncState state); void handleStorageAccquired (QString storageType); void handleItemProcessed (DataSync::ModificationType modificationType, DataSync::ModifiedDatabase modifiedDb, QString localDb, QString dbType, int committedItems); private: bool initSyncAgent (); void closeSyncAgent (); void closeUSBTransport (); void closeBTTransport (); DataSync::SyncAgentConfig *initSyncAgentConfig (); void closeSyncAgentConfig (); bool initStorageProvider (); bool createUSBTransport (); bool createBTTransport (); bool startNewSession (QString address); void generateResults (bool success); QMap mProperties; DataSync::SyncAgent* mAgent; DataSync::SyncAgentConfig* mConfig; USBConnection mUSBConnection; BTConnection mBTConnection; DataSync::Transport* mTransport; Buteo::SyncResults mResults; SyncMLStorageProvider mStorageProvider; qint32 mCommittedItems; /** * ! \brief The connectivity type used for the current sync session */ Sync::ConnectivityType mConnectionType; /** * ! \brief Flag to indicate if the sync session is in progress */ bool mIsSessionInProgress; /** * ! \brief Flag to indicate if bluetooth is active */ bool mBTActive; /** * ! \brief Flag to indicate if USB is active */ bool mUSBActive; }; class SyncMLServerLoader : public Buteo::SyncPluginLoader { Q_OBJECT Q_PLUGIN_METADATA(IID "com.buteo.plugins.sync.SyncMLServerLoader") Q_INTERFACES(Buteo::SyncPluginLoader) public: /*! \brief Creates SyncML server plugin * * @param aPluginName Name of this server plugin * @param aProfile Profile to use * @param aCbInterface Pointer to the callback interface * @return Server plugin on success, otherwise NULL */ Buteo::ServerPlugin* createServerPlugin(const QString& pluginName, const Buteo::Profile& profile, Buteo::PluginCbInterface* cbInterface) override; }; #endif // SYNCMLSERVER_H buteo-sync-plugins-0.8.36/serverplugins/syncmlserver/USBConnection.cpp000066400000000000000000000264441476033560700262250ustar00rootroot00000000000000/* * This file is part of buteo-sync-plugins package * * Copyright (C) 2013 Jolla Ltd. and/or its subsidiary(-ies). * * Author: Sateesh Kavuri * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include "USBConnection.h" #include "SyncMLPluginLogging.h" #include #include #include #include #include #ifdef GLIB_FD_WATCH #include #endif USBConnection::USBConnection () : mFd (-1), mMutex (QMutex::Recursive), mDisconnected (true), mFdWatching (false), #ifdef GLIB_FD_WATCH mIOChannel (0), mIdleEventSource (0), mFdWatchEventSource (0) #else mReadNotifier (0), mWriteNotifier (0), mExceptionNotifier (0) #endif { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); } USBConnection::~USBConnection () { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); #ifdef GLIB_FD_WATCH // Make sure glibc does not try to deliver more events to us. // This also frees mIOChannel by removing the last ref, if any. removeFdListener(); #else if (mReadNotifier) { delete mReadNotifier; mReadNotifier = 0; } if (mWriteNotifier) { delete mWriteNotifier; mWriteNotifier = 0; } if (mExceptionNotifier) { delete mExceptionNotifier; mExceptionNotifier = 0; } #endif } int USBConnection::connect () { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); QMutexLocker lock (&mMutex); if (isConnected ()) { qCDebug(lcSyncMLPlugin) << "Already connected. Returning fd"; } else { mFd = openUSBDevice (); addFdListener (); } return mFd; } void USBConnection::disconnect () { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); QMutexLocker lock (&mMutex); #ifdef GLIB_FD_WATCH removeEventSource (); #endif removeFdListener (); // In server mode, we do not disconnect the connection, since // the host (PC/device/...) might initiate sync again } bool USBConnection::isConnected () const { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); if (mFd == -1) return false; else return true; } int USBConnection::openUSBDevice () { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); QMutexLocker lock (&mMutex); if (isConnected ()) { qCWarning(lcSyncMLPlugin) << "USB connection already open with fd " << mFd; return mFd; } const QString USB_DEVICE ("/dev/ttyGS1"); mFd = open (USB_DEVICE.toLocal8Bit ().constData (), O_RDWR | O_NOCTTY); if (mFd < 0) { qCWarning(lcSyncMLPlugin) << "Count not open USB device"; return -1; } long flags = fcntl (mFd, F_GETFL); fcntl (mFd, F_SETFL, flags & ~O_NONBLOCK); struct termios opts; tcgetattr (mFd, &opts); cfmakeraw (&opts); opts.c_oflag &= ~ONLCR; tcsetattr (mFd, TCSANOW, &opts); int arg = fcntl (mFd, F_GETFL); if (arg < 0) { qCWarning(lcSyncMLPlugin) << "Unable to get file attributes"; close (mFd); return -1; } arg |= O_NONBLOCK; if (fcntl (mFd, F_SETFL, arg) < 0) { qCWarning(lcSyncMLPlugin) << "Could not set file attributes"; close (mFd); return -1; } qCDebug(lcSyncMLPlugin) << "Opened USB device with fd " << mFd; return mFd; } void USBConnection::closeUSBDevice () { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); QMutexLocker lock (&mMutex); if (isConnected ()) { qCDebug(lcSyncMLPlugin) << "Closing USB device with fd " << mFd; shutdown (mFd, SHUT_RDWR); close (mFd); mFd = -1; mDisconnected = true; } } void USBConnection::handleSyncFinished (bool isSyncInError) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); QMutexLocker lock (&mMutex); if (isSyncInError == true) { // What needs to be done here? Should we close the USB? // For now completely closing USB device and reopening again // syncml-ds-tool sends LINKERR for closing USB connection. This causes // buteosyncml stack to think that a link error has occured and marks the // sync session as error // The following would ensure that the server plugin would return back // to sane state incase of any unexpected sync errors removeFdListener (); closeUSBDevice (); openUSBDevice (); addFdListener (); } else { // No errors during sync. Just add channel watcher, // which was removed at the start of the sync qCDebug(lcSyncMLPlugin) << "Handling sync finished. Adding fd listener"; addFdListener (); } } void USBConnection::addFdListener () { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); QMutexLocker lock (&mMutex); if ((mFdWatching == false) && isConnected ()) { #ifdef GLIB_FD_WATCH mIOChannel = g_io_channel_unix_new (mFd); g_io_channel_set_close_on_unref (mIOChannel, FALSE); mFdWatchEventSource = g_io_add_watch_full (mIOChannel, G_PRIORITY_DEFAULT, (GIOCondition) (G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL), handleIncomingUSBEvent, this, NULL); g_io_channel_unref (mIOChannel); qCDebug(lcSyncMLPlugin) << "Added fd listner for fd " << mFd << " with event source " << mFdWatchEventSource; #else mReadNotifier = new QSocketNotifier (mFd, QSocketNotifier::Read); mWriteNotifier = new QSocketNotifier (mFd, QSocketNotifier::Write); mExceptionNotifier = new QSocketNotifier (mFd, QSocketNotifier::Exception); mReadNotifier->setEnabled (true); mWriteNotifier->setEnabled (true); mExceptionNotifier->setEnabled (true); QObject::connect (mReadNotifier, SIGNAL (activated (int)), this, SLOT (handleUSBActivated (int)), Qt::BlockingQueuedConnection); QObject::connect (mWriteNotifier, SIGNAL (activated (int)), this, SLOT (handleUSBActivated (int)), Qt::BlockingQueuedConnection); QObject::connect (mExceptionNotifier, SIGNAL (activated (int)), this, SLOT (handleUSBError (int)), Qt::BlockingQueuedConnection); #endif mFdWatching = true; mDisconnected = false; } } void USBConnection::removeFdListener () { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); QMutexLocker lock (&mMutex); #ifdef GLIB_FD_WATCH if (mFdWatchEventSource > 0) { gboolean removed = g_source_remove (mFdWatchEventSource); if (removed) { qCDebug(lcSyncMLPlugin) << "Removed fd listener with event source " << mFdWatchEventSource; mFdWatchEventSource = 0; } } #else mWriteNotifier->setEnabled (false); mReadNotifier->setEnabled (false); mExceptionNotifier->setEnabled (false); QObject::disconnect (mReadNotifier, SIGNAL (activated (int)), this, SLOT (handleUSBActivated (int))); QObject::disconnect (mWriteNotifier, SIGNAL (activated (int)), this, SLOT (handleUSBActivated (int))); QObject::disconnect (mExceptionNotifier, SIGNAL (activated (int)), this, SLOT (handleUSBError (int))); #endif mFdWatching = false; } void USBConnection::signalNewSession () { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); emit usbConnected (mFd); } #ifdef GLIB_FD_WATCH void USBConnection::setFdWatchEventSource (guint fdEventSource) { mFdWatchEventSource = fdEventSource; } void USBConnection::setIdleEventSource (guint idleEventSource) { mIdleEventSource = idleEventSource; } guint USBConnection::fdWatchEventSource () { return mFdWatchEventSource; } guint USBConnection::idleEventSource () { return mIdleEventSource; } void USBConnection::removeEventSource () { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); if ((mIdleEventSource > 0) && (g_source_remove (mIdleEventSource))) { qCDebug(lcSyncMLPlugin) << "Removing idle event source " << mIdleEventSource; mIdleEventSource = 0; } } gboolean USBConnection::handleIncomingUSBEvent (GIOChannel *ioChannel, GIOCondition condition, gpointer user_data) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); USBConnection* connection = (USBConnection*) user_data; int fd = g_io_channel_unix_get_fd (ioChannel); qCDebug(lcSyncMLPlugin) << "Channel fd: " << fd; if (condition & (G_IO_HUP | G_IO_ERR)) { // Receved a hangup or an error. Remove the watchers and // also disconnect the listeners if (connection->isConnected ()) { guint eventSource = connection->idleEventSource (); if ((eventSource > 0) && g_source_remove (eventSource)) { qCDebug(lcSyncMLPlugin) << "Removed event source " << eventSource; connection->setIdleEventSource (0); } // Add an idle loop to reopen USB incase of HUP or ERR eventSource = g_idle_add (reopenUSB, connection); connection->setIdleEventSource (eventSource); qCDebug(lcSyncMLPlugin) << "Added watch on the idle event source " << eventSource; } // If in error, remove the fd listner and also close the USB device connection->removeFdListener (); connection->closeUSBDevice (); } else if (condition & G_IO_IN) { // Some incoming data. Better remove the listener connection->removeFdListener (); // Signal a new session connection->signalNewSession (); } connection->setFdWatchEventSource (0); return false; } gboolean USBConnection::reopenUSB (gpointer data) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); USBConnection* connection = (USBConnection*) data; if ((connection->mDisconnected == true) && !connection->isConnected ()) { qCDebug(lcSyncMLPlugin) << "USB Not disconnected and not listening"; connection->openUSBDevice (); connection->addFdListener (); } else { qCDebug(lcSyncMLPlugin) << "Already listening. No need to reopen"; } connection->setIdleEventSource (0); return false; } #else void USBConnection::handleUSBActivated (int fd) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); qCDebug(lcSyncMLPlugin) << "USB is activated. Emitting signal to handle incoming data"; emit usbConnected (fd); // Disable the event notifier removeFdListener (); } void USBConnection::handleUSBError (int fd) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); qCDebug(lcSyncMLPlugin) << "Error in USB connection"; removeFdListener (); closeUSBDevice (); openUSBDevice (); addFdListener (); } #endif buteo-sync-plugins-0.8.36/serverplugins/syncmlserver/USBConnection.h000066400000000000000000000056551476033560700256730ustar00rootroot00000000000000/* * This file is part of buteo-sync-plugins package * * Copyright (C) 2013 Jolla Ltd. and/or its subsidiary(-ies). * * Author: Sateesh Kavuri * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef USBCONNECTION_H #define USBCONNECTION_H #include #include #ifdef GLIB_FD_WATCH #include #else #include #endif #include /*! \brief Class for creating connection to a PC that acts as a USB * host for synchronization of data using buteosyncml * */ class USBConnection : public QObject, public DataSync::OBEXConnection { Q_OBJECT public: USBConnection (); virtual ~USBConnection (); /*! \sa DataSync::OBEXConnection::connect () * */ virtual int connect (); /*! \sa DataSync::OBEXConnection::isConnected () * */ virtual bool isConnected () const; /*! \sa DataSync::OBEXConnection::disconnect () * */ virtual void disconnect (); void handleSyncFinished (bool isSyncInError); signals: void usbConnected (int fd); #ifndef GLIB_FD_WATCH protected slots: void handleUSBActivated (int fd); void handleUSBError (int fd); #endif private: // Functions int openUSBDevice (); void closeUSBDevice (); void addFdListener (); void removeFdListener (); void signalNewSession (); #ifdef GLIB_FD_WATCH void setFdWatchEventSource (guint = 0); void setIdleEventSource (guint = 0); guint fdWatchEventSource (); guint idleEventSource (); static gboolean handleIncomingUSBEvent (GIOChannel* ioChannel, GIOCondition condition, gpointer user_data); void removeEventSource (); static gboolean reopenUSB (gpointer data); #endif private: int mFd; QMutex mMutex; bool mDisconnected; bool mFdWatching; #ifdef GLIB_FD_WATCH GIOChannel *mIOChannel; guint mIdleEventSource; guint mFdWatchEventSource; #else QSocketNotifier *mReadNotifier; QSocketNotifier *mWriteNotifier; QSocketNotifier *mExceptionNotifier; #endif }; #endif // USBCONNECTION_H buteo-sync-plugins-0.8.36/serverplugins/syncmlserver/syncmlserver.pro000066400000000000000000000021601476033560700263130ustar00rootroot00000000000000TARGET = syncml-server CONFIG += link_pkgconfig PKGCONFIG += glib-2.0 buteosyncfw5 buteosyncml5 systemsettings INCLUDEPATH += . ../../syncmlcommon LIBS += -L../../syncmlcommon LIBS += -lsyncmlcommon5 QT += dbus QT -= gui VER_MAJ = 1 VER_MIN = 0 VER_PAT = 0 QMAKE_CXXFLAGS = -Wall \ -g \ -Wno-cast-align \ -O2 -finline-functions QMAKE_CLEAN += $(TARGET) $(TARGET0) $(TARGET1) $(TARGET2) QMAKE_CLEAN += $(OBJECTS_DIR)/*.gcda $(OBJECTS_DIR)/*.gcno $(OBJECTS_DIR)/*.gcov $(OBJECTS_DIR)/moc_* SOURCES += SyncMLServer.cpp \ USBConnection.cpp \ BTConnection.cpp HEADERS += SyncMLServer.h\ syncmlserver_global.h \ USBConnection.h \ BTConnection.h OTHER_FILES += xml/* TEMPLATE = lib CONFIG += plugin target.path = $$[QT_INSTALL_LIBS]/buteo-plugins-qt5/oopp/ DEFINES += SYNCMLSERVER_LIBRARY sync.path = /etc/buteo/profiles/server sync.files = xml/syncml.xml template.path = /etc/buteo/profiles/sync template.files = xml/bt_template.xml btsrs.path = /etc/buteo/plugins/syncmlserver btsrs.files = xml/syncml_server_sdp_record.xml xml/syncml_client_sdp_record.xml INSTALLS += target sync btsrs template buteo-sync-plugins-0.8.36/serverplugins/syncmlserver/syncmlserver_global.h000066400000000000000000000021201476033560700272560ustar00rootroot00000000000000/* * This file is part of buteo-sync-plugins package * * Copyright (C) 2013 Jolla Ltd. and/or its subsidiary(-ies). * * Author: Sateesh Kavuri * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef SYNCMLSERVER_GLOBAL_H #define SYNCMLSERVER_GLOBAL_H #include #if defined(SYNCMLSERVER_LIBRARY) # define SYNCMLSERVERSHARED_EXPORT Q_DECL_EXPORT #else # define SYNCMLSERVERSHARED_EXPORT Q_DECL_IMPORT #endif #endif // SYNCMLSERVER_GLOBAL_H buteo-sync-plugins-0.8.36/serverplugins/syncmlserver/xml/000077500000000000000000000000001476033560700236365ustar00rootroot00000000000000buteo-sync-plugins-0.8.36/serverplugins/syncmlserver/xml/bt_template.xml000066400000000000000000000017571476033560700266720ustar00rootroot00000000000000 buteo-sync-plugins-0.8.36/serverplugins/syncmlserver/xml/syncml.xml000066400000000000000000000005221476033560700256640ustar00rootroot00000000000000 buteo-sync-plugins-0.8.36/serverplugins/syncmlserver/xml/syncml_client_sdp_record.xml000066400000000000000000000023411476033560700314270ustar00rootroot00000000000000 buteo-sync-plugins-0.8.36/serverplugins/syncmlserver/xml/syncml_server_sdp_record.xml000066400000000000000000000024011476033560700314540ustar00rootroot00000000000000 buteo-sync-plugins-0.8.36/storagechangenotifierplugins/000077500000000000000000000000001476033560700233465ustar00rootroot00000000000000buteo-sync-plugins-0.8.36/storagechangenotifierplugins/hcontacts/000077500000000000000000000000001476033560700253345ustar00rootroot00000000000000buteo-sync-plugins-0.8.36/storagechangenotifierplugins/hcontacts/ContactsChangeNotifier.cpp000066400000000000000000000042541476033560700324310ustar00rootroot00000000000000#include "ContactsChangeNotifier.h" #include "LogMacros.h" #include const QString DEFAULT_CONTACTS_MANAGER("tracker"); ContactsChangeNotifier::ContactsChangeNotifier() : iDisabled(true) { FUNCTION_CALL_TRACE(lcSyncMLContactChangeTrace); iManager = new QContactManager("org.nemomobile.contacts.sqlite"); } ContactsChangeNotifier::~ContactsChangeNotifier() { disable(); delete iManager; } void ContactsChangeNotifier::enable() { if(iManager && iDisabled) { QObject::connect(iManager, SIGNAL(contactsAdded(const QList&)), this, SLOT(onContactsAdded(const QList&))); QObject::connect(iManager, SIGNAL(contactsRemoved(const QList&)), this, SLOT(onContactsRemoved(const QList&))); QObject::connect(iManager, SIGNAL(contactsChanged(const QList&)), this, SLOT(onContactsChanged(const QList&))); iDisabled = false; } } void ContactsChangeNotifier::onContactsAdded(const QList& ids) { FUNCTION_CALL_TRACE(lcSyncMLContactChangeTrace); if(ids.count()) { QList contacts = iManager->contacts(ids); emit change(); } } void ContactsChangeNotifier::onContactsRemoved(const QList& ids) { FUNCTION_CALL_TRACE(lcSyncMLContactChangeTrace); if(ids.count()) { foreach(QContactId id, ids) { qCDebug(lcSyncMLContactChange) << "Removed contact with id" << id; } emit change(); } } void ContactsChangeNotifier::onContactsChanged(const QList& ids) { FUNCTION_CALL_TRACE(lcSyncMLContactChangeTrace); if(ids.count()) { QList contacts = iManager->contacts(ids); emit change(); } } void ContactsChangeNotifier::disable() { FUNCTION_CALL_TRACE(lcSyncMLContactChangeTrace); iDisabled = true; QObject::disconnect(iManager, 0, this, 0); } Q_LOGGING_CATEGORY(lcSyncMLContactChange, "buteo.syncml.plugin.contactchange", QtWarningMsg) Q_LOGGING_CATEGORY(lcSyncMLContactChangeTrace, "buteo.syncml.plugin.contactchange.trace", QtWarningMsg) buteo-sync-plugins-0.8.36/storagechangenotifierplugins/hcontacts/ContactsChangeNotifier.h000066400000000000000000000020531476033560700320710ustar00rootroot00000000000000#ifndef CONTACTSCHANGENOTIFIER_H #define CONTACTSCHANGENOTIFIER_H #include #include #include #include #include using namespace QtContacts; class ContactsChangeNotifier : public QObject { Q_OBJECT public: /*! \brief constructor */ ContactsChangeNotifier(); /*! \brief constructor */ ~ContactsChangeNotifier(); /*! \brief start listening to changes from QContactManager */ void enable(); /*! \brief stop listening to changes from QContactManager */ void disable(); Q_SIGNALS: /*! emit this signal to notify a change in contacts backend */ void change(); private Q_SLOTS: void onContactsAdded(const QList& ids); void onContactsRemoved(const QList& ids); void onContactsChanged(const QList& ids); private: QContactManager* iManager; bool iDisabled; }; Q_DECLARE_LOGGING_CATEGORY(lcSyncMLContactChange) Q_DECLARE_LOGGING_CATEGORY(lcSyncMLContactChangeTrace) #endif buteo-sync-plugins-0.8.36/storagechangenotifierplugins/hcontacts/ContactsChangeNotifierPlugin.cpp000066400000000000000000000055161476033560700336120ustar00rootroot00000000000000/* * This file is part of buteo-sync-plugins package * * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). * Copyright (C) 2013 - 2021 Jolla Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * */ #include "ContactsChangeNotifierPlugin.h" #include "ContactsChangeNotifier.h" #include "LogMacros.h" #include using namespace Buteo; Buteo::StorageChangeNotifierPlugin* ContactsChangeNotifierPluginLoader::createPlugin(const QString& aStorageName) { return new ContactsChangeNotifierPlugin(aStorageName); } ContactsChangeNotifierPlugin::ContactsChangeNotifierPlugin(const QString& aStorageName) : StorageChangeNotifierPlugin(aStorageName), ihasChanges(false), iDisableLater(false) { FUNCTION_CALL_TRACE(lcSyncMLContactChangeTrace); icontactsChangeNotifier = new ContactsChangeNotifier; QObject::connect(icontactsChangeNotifier, SIGNAL(change()), this, SLOT(onChange())); } ContactsChangeNotifierPlugin::~ContactsChangeNotifierPlugin() { FUNCTION_CALL_TRACE(lcSyncMLContactChangeTrace); delete icontactsChangeNotifier; } QString ContactsChangeNotifierPlugin::name() const { FUNCTION_CALL_TRACE(lcSyncMLContactChangeTrace); return iStorageName; } bool ContactsChangeNotifierPlugin::hasChanges() const { FUNCTION_CALL_TRACE(lcSyncMLContactChangeTrace); return ihasChanges; } void ContactsChangeNotifierPlugin::changesReceived() { FUNCTION_CALL_TRACE(lcSyncMLContactChangeTrace); ihasChanges = false; } void ContactsChangeNotifierPlugin::onChange() { FUNCTION_CALL_TRACE(lcSyncMLContactChangeTrace); qCDebug(lcSyncMLContactChange) << "Change in contacts detected"; ihasChanges = true; if(iDisableLater) { icontactsChangeNotifier->disable(); } else { emit storageChange(); } } void ContactsChangeNotifierPlugin::enable() { FUNCTION_CALL_TRACE(lcSyncMLContactChangeTrace); icontactsChangeNotifier->enable(); iDisableLater = false; } void ContactsChangeNotifierPlugin::disable(bool disableAfterNextChange) { FUNCTION_CALL_TRACE(lcSyncMLContactChangeTrace); if(disableAfterNextChange) { iDisableLater = true; } else { icontactsChangeNotifier->disable(); } } buteo-sync-plugins-0.8.36/storagechangenotifierplugins/hcontacts/ContactsChangeNotifierPlugin.h000066400000000000000000000046141476033560700332550ustar00rootroot00000000000000/* * This file is part of buteo-sync-plugins package * * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). * Copyright (C) 2013 - 2021 Jolla Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * */ #ifndef CONTACTSCHANGENOTIFIERPLUGIN_H #define CONTACTSCHANGENOTIFIERPLUGIN_H #include "StorageChangeNotifierPlugin.h" #include "StorageChangeNotifierPluginLoader.h" class ContactsChangeNotifier; class ContactsChangeNotifierPlugin : public Buteo::StorageChangeNotifierPlugin { Q_OBJECT public: /*! \brief constructor * see StorageChangeNotifierPlugin */ ContactsChangeNotifierPlugin(const QString& aStorageName); /*! \brief destructor */ ~ContactsChangeNotifierPlugin(); /*! \brief see StorageChangeNotifierPlugin::name */ QString name() const; /*! \brief see StorageChangeNotifierPlugin::hasChanges */ bool hasChanges() const; /*! \brief see StorageChangeNotifierPlugin::changesReceived */ void changesReceived(); /*! \brief see StorageChangeNotifierPlugin::enable */ void enable(); /*! \brief see StorageChangeNotifierPlugin::disable */ void disable(bool disableAfterNextChange = false); private Q_SLOTS: /*! \brief handles a change notification from contacts notifier */ void onChange(); private: ContactsChangeNotifier* icontactsChangeNotifier; bool ihasChanges; bool iDisableLater; }; class ContactsChangeNotifierPluginLoader : public Buteo::StorageChangeNotifierPluginLoader { Q_OBJECT Q_PLUGIN_METADATA(IID "com.buteo.plugins.storage.ContactsChangeNotifierPluginLoader") Q_INTERFACES(Buteo::StorageChangeNotifierPluginLoader) public: Buteo::StorageChangeNotifierPlugin* createPlugin(const QString& aStorageName) override; }; #endif buteo-sync-plugins-0.8.36/storagechangenotifierplugins/hcontacts/hcontacts.pro000066400000000000000000000010451476033560700300440ustar00rootroot00000000000000TEMPLATE = lib TARGET = hcontacts-changenotifier DEPENDPATH += . CONFIG += link_pkgconfig plugin link_pkgconfig PKGCONFIG += buteosyncfw5 Qt5Contacts target.path = $$[QT_INSTALL_LIBS]/buteo-plugins-qt5 VER_MAJ = 1 VER_MIN = 0 VER_PAT = 0 QT -= gui HEADERS += ContactsChangeNotifierPlugin.h \ ContactsChangeNotifier.h SOURCES += ContactsChangeNotifierPlugin.cpp \ ContactsChangeNotifier.cpp QMAKE_CXXFLAGS = -Wall \ -g \ -Wno-cast-align \ -O2 -finline-functions QMAKE_CLEAN += $(TARGET) INSTALLS += target buteo-sync-plugins-0.8.36/storagechangenotifierplugins/storagechangenotifierplugins.pro000066400000000000000000000000511476033560700320400ustar00rootroot00000000000000TEMPLATE = subdirs SUBDIRS += hcontacts buteo-sync-plugins-0.8.36/storageplugins/000077500000000000000000000000001476033560700204405ustar00rootroot00000000000000buteo-sync-plugins-0.8.36/storageplugins/hcalendar/000077500000000000000000000000001476033560700223615ustar00rootroot00000000000000buteo-sync-plugins-0.8.36/storageplugins/hcalendar/CalendarBackend.cpp000066400000000000000000000355701476033560700260600ustar00rootroot00000000000000/* * This file is part of buteo-sync-plugins package * * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). * * Contact: Sateesh Kavuri * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * */ #include "CalendarBackend.h" #include #include #include "SyncMLPluginLogging.h" #include #include CalendarBackend::CalendarBackend() : iCalendar( 0 ), iStorage( 0 ) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); } CalendarBackend::~CalendarBackend() { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); } bool CalendarBackend::init(const QString &aNotebookName, const QString& aUid) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); if( aNotebookName.isEmpty() ) { qCDebug(lcSyncMLPlugin) << "NoteBook Name to Sync is expected. It Cannot be Empty"; return false; } iNotebookStr = aNotebookName; iCalendar = mKCal::ExtendedCalendar::Ptr( new mKCal::ExtendedCalendar( QTimeZone::systemTimeZone()) ); qCDebug(lcSyncMLPlugin) << "Creating Default Maemo Storage"; iStorage = iCalendar->defaultStorage( iCalendar ); bool opened = iStorage->open(); if(!opened) { qCDebug(lcSyncMLPluginTrace) << "Calendar storage open failed"; } mKCal::Notebook::Ptr openedNb; // If we have an Uid, we try to get the corresponding Notebook if (!aUid.isEmpty()) { openedNb = iStorage->notebook(aUid); // If we didn't get one, we create one and set its Uid if (!openedNb) { openedNb = mKCal::Notebook::Ptr(new mKCal::Notebook(aNotebookName, "Synchronization Created Notebook for " + aNotebookName)); if (!openedNb.isNull()) { openedNb->setUid(aUid); if (!iStorage->addNotebook(openedNb)) { qCWarning(lcSyncMLPlugin) << "Failed to add notebook to storage"; openedNb.clear(); } } } } // If we didn't have an Uid or the creation above failed, // we use the default notebook if (openedNb.isNull()) { openedNb = iStorage->defaultNotebook(); if(openedNb.isNull()) { qCDebug(lcSyncMLPlugin) << "No default notebook exists, creating one"; openedNb = mKCal::Notebook::Ptr(new mKCal::Notebook("Default", QString())); if (!iStorage->setDefaultNotebook(openedNb)) { qCWarning(lcSyncMLPlugin) << "Failed to set default notebook of storage"; openedNb.clear(); } } } bool loaded = false; if(opened && openedNb) { qCDebug(lcSyncMLPlugin) << "Loading all incidences from::" << openedNb->uid(); loaded = iStorage->loadNotebookIncidences(openedNb->uid()); if(!loaded) { qCWarning(lcSyncMLPlugin) << "Failed to load calendar!"; } } if (opened && loaded && !openedNb.isNull()) { iNotebookStr = openedNb->uid(); qCDebug(lcSyncMLPlugin) << "Calendar initialized"; return true; } else { qCWarning(lcSyncMLPlugin) << "Not able to initialize calendar"; iStorage.clear(); qCDebug(lcSyncMLPluginTrace) << "Storage deleted"; iCalendar.clear(); qCDebug(lcSyncMLPluginTrace) << "Calendar deleted"; return false; } } bool CalendarBackend::uninit() { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); if( iStorage ) { qCDebug(lcSyncMLPluginTrace) << "Closing calendar storage..."; iStorage->close(); qCDebug(lcSyncMLPluginTrace) << "Done"; iStorage.clear(); } if( iCalendar ) { qCDebug(lcSyncMLPluginTrace) << "Closing calendar..."; iCalendar->close(); qCDebug(lcSyncMLPluginTrace) << "Done"; iCalendar.clear(); } return true; } bool CalendarBackend::getAllIncidences( KCalendarCore::Incidence::List& aIncidences ) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); if( !iStorage ) { return false; } if( !iStorage->allIncidences( &aIncidences, iNotebookStr ) ) { qCWarning(lcSyncMLPlugin) << "Error Retrieving ALL Incidences from the Storage "; return false; } filterIncidences( aIncidences ); return true; } void CalendarBackend::filterIncidences(KCalendarCore::Incidence::List& aList) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); QString event(INCIDENCE_TYPE_EVENT); QString todo(INCIDENCE_TYPE_TODO); for (int i = 0; i < aList.size(); ++i) { KCalendarCore::Incidence::Ptr incidence = aList.at(i); if ((incidence->type() != KCalendarCore::Incidence::TypeEvent) && (incidence->type() != KCalendarCore::Incidence::TypeTodo)) { qCDebug(lcSyncMLPlugin) << "Removing incidence type" << incidence->typeStr(); aList.remove( i, 1); incidence.clear(); } } } bool CalendarBackend::getAllNew( KCalendarCore::Incidence::List& aIncidences, const QDateTime& aTime ) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); if( !iStorage ) { return false; } if( !iStorage->insertedIncidences( &aIncidences, aTime, iNotebookStr) ) { qCWarning(lcSyncMLPlugin) << "Error Retrieving New Incidences from the Storage"; return false; } filterIncidences( aIncidences ); return true; } bool CalendarBackend::getAllModified( KCalendarCore::Incidence::List& aIncidences, const QDateTime& aTime ) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); if( !iStorage ) { return false; } if( !iStorage->modifiedIncidences( &aIncidences, aTime, iNotebookStr ) ) { qCWarning(lcSyncMLPlugin) << " Error retrieving modified Incidences "; return false; } filterIncidences( aIncidences ); return true; } bool CalendarBackend::getAllDeleted( KCalendarCore::Incidence::List& aIncidences, const QDateTime& aTime ) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); if( !iStorage ) { return false; } if( !iStorage->deletedIncidences( &aIncidences, aTime, iNotebookStr ) ) { qCWarning(lcSyncMLPlugin) << " Error retrieving deleted Incidences "; return false; } filterIncidences( aIncidences ); return true; } KCalendarCore::Incidence::Ptr CalendarBackend::getIncidence( const QString& aUID ) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); QStringList iDs = aUID.split(ID_SEPARATOR); KCalendarCore::Incidence::Ptr incidence; if (iDs.size() == 2) { iStorage->load ( iDs.at(0), QDateTime::fromString(iDs.at(1), Qt::ISODate) ); incidence = iCalendar->incidence(iDs.at(0), QDateTime::fromString(iDs.at(1), Qt::ISODate)); } else { iStorage->load ( aUID ); incidence = iCalendar->incidence( aUID ); } return incidence; } QString CalendarBackend::getVCalString(KCalendarCore::Incidence::Ptr aInci) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); Q_ASSERT( aInci ); QString vcal; KCalendarCore::Incidence::Ptr temp = KCalendarCore::Incidence::Ptr ( aInci->clone() ); if(temp) { KCalendarCore::Calendar::Ptr tempCalendar( new KCalendarCore::MemoryCalendar( QTimeZone::utc() ) ); tempCalendar->addIncidence(temp); KCalendarCore::VCalFormat vcf; vcal = vcf.toString(tempCalendar); } else { qCWarning(lcSyncMLPlugin) << "Error Cloning the Incidence for VCal String"; } return vcal; } QString CalendarBackend::getICalString(KCalendarCore::Incidence::Ptr aInci) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); Q_ASSERT( aInci ); KCalendarCore::Incidence::Ptr temp = KCalendarCore::Incidence::Ptr ( aInci->clone() ); QString ical; if( temp ) { KCalendarCore::Calendar::Ptr tempCalendar( new KCalendarCore::MemoryCalendar( QTimeZone::utc() ) ); tempCalendar->addIncidence(temp); KCalendarCore::ICalFormat icf; ical = icf.toString(tempCalendar); } else { qCWarning(lcSyncMLPlugin) << "Error Cloning the Incidence for Ical String"; } return ical; } KCalendarCore::Incidence::Ptr CalendarBackend::getIncidenceFromVcal( const QString& aVString ) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); KCalendarCore::Incidence::Ptr pInci; KCalendarCore::Calendar::Ptr tempCalendar( new KCalendarCore::MemoryCalendar( QTimeZone::systemTimeZone()) ); KCalendarCore::VCalFormat vcf; vcf.fromString(tempCalendar, aVString); KCalendarCore::Incidence::List lst = tempCalendar->rawIncidences(); if(!lst.isEmpty()) { pInci = KCalendarCore::Incidence::Ptr ( lst[0]->clone() ); } else { qCWarning(lcSyncMLPlugin) << "VCal to Incidence Conversion Failed "; } return pInci; } KCalendarCore::Incidence::Ptr CalendarBackend::getIncidenceFromIcal( const QString& aIString ) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); KCalendarCore::Incidence::Ptr pInci; KCalendarCore::Calendar::Ptr tempCalendar( new KCalendarCore::MemoryCalendar( QTimeZone::systemTimeZone()) ); KCalendarCore::ICalFormat icf; icf.fromString(tempCalendar, aIString); KCalendarCore::Incidence::List lst = tempCalendar->rawIncidences(); if(!lst.isEmpty()) { pInci = KCalendarCore::Incidence::Ptr ( lst[0]->clone() ); } else { qCWarning(lcSyncMLPlugin) << "ICal to Incidence Conversion Failed "; } return pInci; } bool CalendarBackend::addIncidence( KCalendarCore::Incidence::Ptr aInci, bool commitNow ) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); if( !iCalendar || !iStorage ) { return false; } switch(aInci->type()) { case KCalendarCore::Incidence::TypeEvent: { KCalendarCore::Event::Ptr event = aInci.staticCast(); if(!iCalendar->addEvent(event, iNotebookStr)) { qCWarning(lcSyncMLPlugin) << "Could not add event"; return false; } } break; case KCalendarCore::Incidence::TypeTodo: { KCalendarCore::Todo::Ptr todo = aInci.staticCast(); if(!iCalendar->addTodo(todo, iNotebookStr)) { qCWarning(lcSyncMLPlugin) << "Could not add todo"; return false; } } break; default: qCWarning(lcSyncMLPlugin) << "Could not add incidence, wrong type" << aInci->type(); return false; } // if you add an incidence, that incidence will be owned by calendar // so no need to delete it. Committing for each modification, can cause performance // problems. if( commitNow ) { if( !iStorage->save() ) { qCWarning(lcSyncMLPlugin) << "Could not commit changes to calendar"; return false; } qCDebug(lcSyncMLPlugin) << "Single incidence committed"; } qCDebug(lcSyncMLPlugin) << "Added an item with UID : " << aInci->uid() << "Recurrence Id :" << aInci->recurrenceId().toString(); return true; } bool CalendarBackend::commitChanges() { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); bool changesCommitted = false; if( !iStorage ) { qCWarning(lcSyncMLPlugin) << "No calendar storage!"; } else if( iStorage->save() ) { qCDebug(lcSyncMLPlugin) << "Committed changes to calendar"; changesCommitted = true; } else { qCDebug(lcSyncMLPlugin) << "Could not commit changes to calendar"; } return changesCommitted; } bool CalendarBackend::modifyIncidence( KCalendarCore::Incidence::Ptr aInci, const QString& aUID, bool commitNow ) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); if( !iCalendar || !iStorage ) { return false; } KCalendarCore::Incidence::Ptr origInci = getIncidence ( aUID ); if( !origInci ) { qCWarning(lcSyncMLPlugin) << "Item with UID" << aUID << "does not exist. Cannot modify"; return false; } if( !modifyIncidence( origInci, aInci ) ) { qCWarning(lcSyncMLPlugin) << "Could not make modifications to incidence"; return false; } if( commitNow ) { if( !iStorage->save() ) { qCWarning(lcSyncMLPlugin) << "Could not commit changes to calendar"; return false; } qCDebug(lcSyncMLPlugin) << "Single incidence committed"; } return true; } CalendarBackend::ErrorStatus CalendarBackend::deleteIncidence( const QString& aUID ) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); CalendarBackend::ErrorStatus errorCode = CalendarBackend::STATUS_OK; if( !iCalendar || !iStorage ) { errorCode = CalendarBackend::STATUS_GENERIC_ERROR; } KCalendarCore::Incidence::Ptr incidence = getIncidence( aUID ); if( !incidence ) { qCWarning(lcSyncMLPlugin) << "Could not find incidence to delete with UID" << aUID; errorCode = CalendarBackend::STATUS_ITEM_NOT_FOUND; } if( !iCalendar->deleteIncidence( incidence) ) { qCWarning(lcSyncMLPlugin) << "Could not delete incidence with UID" << aUID; errorCode = CalendarBackend::STATUS_GENERIC_ERROR; } if( !iStorage->save() ) { qCWarning(lcSyncMLPlugin) << "Could not commit changes to calendar"; errorCode = CalendarBackend::STATUS_GENERIC_ERROR; } return errorCode; } bool CalendarBackend::modifyIncidence( KCalendarCore::Incidence::Ptr aIncidence, KCalendarCore::Incidence::Ptr aIncidenceData ) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); Q_ASSERT( aIncidence ); Q_ASSERT( aIncidenceData ); // Save critical data from original item aIncidenceData->setUid( aIncidence->uid() ); aIncidenceData->setCreated( aIncidence->created() ); if( aIncidence->type() != aIncidenceData->type() ) { qCWarning(lcSyncMLPlugin) << "Expected incidence type" << aIncidence->typeStr() <<", got" << aIncidenceData->typeStr(); return false; } if( aIncidence->type() == KCalendarCore::Incidence::TypeEvent || aIncidence->type() == KCalendarCore::Incidence::TypeTodo ) { KCalendarCore::IncidenceBase::Ptr inc = aIncidence; KCalendarCore::IncidenceBase::Ptr data = aIncidenceData; *inc = *data; } else { qCWarning(lcSyncMLPlugin) << "Unsupported incidence type:" << aIncidence->typeStr(); return false; } iCalendar->setNotebook( aIncidence, iNotebookStr ); return true; } buteo-sync-plugins-0.8.36/storageplugins/hcalendar/CalendarBackend.h000066400000000000000000000136471476033560700255260ustar00rootroot00000000000000/* * This file is part of buteo-sync-plugins package * * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). * * Contact: Sateesh Kavuri * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * */ #ifndef CALENDARBACKEND_H_490498898043897984389983478 #define CALENDARBACKEND_H_490498898043897984389983478 #include #include "definitions.h" //calendar related includes #include "extendedcalendar.h" #include "notebook.h" #include #include #include #include static const QString ID_SEPARATOR("::"); //! \brief Calendar implementation for synchronization class CalendarBackend { public: //error status code return by calender backend. enum ErrorStatus { STATUS_GENERIC_ERROR = -3, /*!< General error occurred during operation*/ STATUS_ITEM_DUPLICATE = -2, /*!< Operation was not performed as object was duplicate*/ STATUS_ITEM_NOT_FOUND = -1, /*!< Operation failed as object was not found*/ STATUS_OK = 0 /*!< Operation was completed successfully*/ }; //! \brief constructor CalendarBackend(); //! \brief destructor virtual ~CalendarBackend(); //! \brief Initializes the CalendarBackend // \param strNotebookName Name of the notebook to use bool init( const QString& aNotebookName, const QString& aUid = "" ); //! \brief Uninitializes the storage bool uninit(); //! \brief returns all incidences inside this calendar // @param aIncidences List of incidences // @return True on success, otherwise false bool getAllIncidences( KCalendarCore::Incidence::List& aIncidences ); //! \brief returns all new items after the date // @param aIncidences List of incidences // @param aTime Timestamp // @return True on success, otherwise false bool getAllNew( KCalendarCore::Incidence::List& aIncidences, const QDateTime& aTime ); //! \brief returns all modified items after the date // @param aIncidences List of incidences // @param aTime Timestamp // @return True on success, otherwise false bool getAllModified( KCalendarCore::Incidence::List& aIncidences, const QDateTime& aTime ); //! \brief returns all deleted items after the date // @param aIncidences List of incidences // @param aTime Timestamp // @return True on success, otherwise false bool getAllDeleted( KCalendarCore::Incidence::List& aIncidences, const QDateTime& aTime ); //! \brief Get incidence based on uid. // Caller must not free the returned pointer. // \param aUID Item UID // \return The incidence (should not be freed by caller). KCalendarCore::Incidence::Ptr getIncidence( const QString& aUID ); //! \brief returns VCalendar representation of incidence // \param pInci Incidence QString getVCalString( KCalendarCore::Incidence::Ptr aInci ); //! \brief returns ICalendar representation of incidence // \param pInci Incidence QString getICalString( KCalendarCore::Incidence::Ptr aInci ); //! \brief get Incidence from VCalendar string // Caller has to free the returned incidence after user. // \param aVString Incidence representation in VCalendar format. // \return Incidence pointer KCalendarCore::Incidence::Ptr getIncidenceFromVcal( const QString& aVString ); //! \brief get Incidence from ICalendar string // Caller has to free the returned incidence after user. // \param aIString Incidence representation in ICalendar format. // \return Incidence pointer KCalendarCore::Incidence::Ptr getIncidenceFromIcal( const QString& aIString ); //! \brief Add the incidence to calendar // // Duplicate checking will be done if id the of item is not empty. // If an entry exists, it will be overwritten. // The uid of incidence will be updated. // \param aInci Incidence to be added. // \param commitNow - indicates if we have to commit to the backend immediately // \return true if addition is success, otherwise false bool addIncidence( KCalendarCore::Incidence::Ptr aInci, bool commitNow = true ); //! \brief Tell Calendar to commit changes to their db /// \return true if committed succesfully, false otherwise bool commitChanges(); //! \brief Modify the incidence in calendar // // if there is no incidence with old id exists, a new incidence // will be created. // The uid of incidence will be updated. // \param aInci Incidence to be modified // \param aUID UID of item // \return true if modification was success, otherwise false bool modifyIncidence( KCalendarCore::Incidence::Ptr aInci, const QString& aUID, bool commitNow = true ); //! \brief delete the incidence // \param aUID id of the incidence to be deleted // \return errorCode of the operation as status. ErrorStatus deleteIncidence( const QString& aUID); private: bool modifyIncidence( KCalendarCore::Incidence::Ptr aIncidence, KCalendarCore::Incidence::Ptr aIncidenceData ); void filterIncidences( KCalendarCore::Incidence::List& aList ); QString iNotebookStr; mKCal::ExtendedCalendar::Ptr iCalendar; mKCal::ExtendedStorage::Ptr iStorage; }; #endif //CALENDARBACKEND_H_490498898043897984389983478 buteo-sync-plugins-0.8.36/storageplugins/hcalendar/CalendarStorage.cpp000077500000000000000000000377661476033560700261510ustar00rootroot00000000000000/* * This file is part of buteo-sync-plugins package * * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). * Copyright (C) 2013 - 2021 Jolla Ltd. * * Contact: Sateesh Kavuri * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * */ #include "CalendarStorage.h" #include #include #include "SimpleItem.h" #include "SyncMLCommon.h" #include "SyncMLConfig.h" #include "SyncMLPluginLogging.h" // @todo: Because CalendarMaemo does not support batched operations ( or it does // but we can't use it as we cannot retrieve the id's of committed items ), // batched operations are currently done in series. const char* CTCAPSFILENAME11 = "CTCaps_calendar_11.xml"; const char* CTCAPSFILENAME12 = "CTCaps_calendar_12.xml"; CalendarStorage::CalendarStorage( const QString& aPluginName ) : Buteo::StoragePlugin(aPluginName) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); iCommitNow = true; iStorageType = VCALENDAR_FORMAT; } CalendarStorage::~CalendarStorage() { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); } bool CalendarStorage::init( const QMap& aProperties ) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); iProperties = aProperties; // Use remote name (e.g. bt name) as notebook name. if (iProperties.contains(Buteo::KEY_REMOTE_NAME)) { qCDebug(lcSyncMLPlugin) << "Using remote name as notebook name"; iProperties[NOTEBOOKNAME] = iProperties.value(Buteo::KEY_REMOTE_NAME); } else if( iProperties.value( NOTEBOOKNAME ).isEmpty() ) { qCWarning(lcSyncMLPlugin) << NOTEBOOKNAME << " property not found" << "for calendar storage, using default of" << DEFAULT_NOTEBOOK_NAME; iProperties[NOTEBOOKNAME] = DEFAULT_NOTEBOOK_NAME; } qCDebug(lcSyncMLPlugin) << "Initializing calendar, notebook name:" << iProperties[NOTEBOOKNAME]; if( !iCalendar.init( iProperties[NOTEBOOKNAME], iProperties[Buteo::KEY_UUID] ) ) { return false; } if( iProperties[CALENDAR_FORMAT] == CALENDAR_FORMAT_ICAL ) { qCDebug(lcSyncMLPlugin) << "The calendar storage is using icalendar format"; iStorageType = ICALENDAR_FORMAT; iProperties[STORAGE_DEFAULT_MIME_PROP] = "text/calendar"; iProperties[STORAGE_DEFAULT_MIME_VERSION_PROP] = "2.0"; } else { qCDebug(lcSyncMLPlugin) << "The calendar storage is using vcalendar format"; iStorageType = VCALENDAR_FORMAT; } iProperties[STORAGE_SYNCML_CTCAPS_PROP_11] = getCtCaps( CTCAPSFILENAME11 ); iProperties[STORAGE_SYNCML_CTCAPS_PROP_12] = getCtCaps( CTCAPSFILENAME12 ); return true; } bool CalendarStorage::uninit() { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); return iCalendar.uninit(); } bool CalendarStorage::getAllItems( QList& aItems ) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); qCDebug(lcSyncMLPlugin) << "Retrieving all calendar events and todo's"; KCalendarCore::Incidence::List incidences; if( !iCalendar.getAllIncidences( incidences ) ) { qCDebug(lcSyncMLPlugin) << "Could not retrieve all calendar events and todo's"; return false; } retrieveItems( incidences, aItems ); qCDebug(lcSyncMLPlugin) << "Found" << aItems.count() << "items"; return true; } bool CalendarStorage::getAllItemIds( QList& aItemIds ) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); qCDebug(lcSyncMLPlugin) << "Retrieving all calendar events and todo's"; KCalendarCore::Incidence::List incidences; if( !iCalendar.getAllIncidences( incidences ) ) { qCDebug(lcSyncMLPlugin) << "Could not retrieve all calendar events and todo's"; return false; } retrieveIds( incidences, aItemIds ); qCDebug(lcSyncMLPlugin) << "Found" << aItemIds.count() << "items"; return true; } bool CalendarStorage::getNewItems( QList& aNewItems, const QDateTime& aTime ) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); qCDebug(lcSyncMLPlugin) << "Retrieving new calendar events and todo's"; KCalendarCore::Incidence::List incidences; if( !iCalendar.getAllNew( incidences, normalizeTime( aTime ) ) ) { qCDebug(lcSyncMLPlugin) << "Could not retrieve new calendar events and todo's"; return false; } retrieveItems( incidences, aNewItems ); qCDebug(lcSyncMLPlugin) << "Found" << aNewItems.count() << "new items"; return true; } bool CalendarStorage::getNewItemIds( QList& aNewItemIds, const QDateTime& aTime ) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); qCDebug(lcSyncMLPlugin) << "Retrieving new calendar events and todo's"; KCalendarCore::Incidence::List incidences; if( !iCalendar.getAllNew( incidences, normalizeTime( aTime ) ) ) { qCDebug(lcSyncMLPlugin) << "Could not retrieve new calendar events and todo's"; return false; } retrieveIds( incidences, aNewItemIds ); qCDebug(lcSyncMLPlugin) << "Found" << aNewItemIds.count() << "new items"; return true; } bool CalendarStorage::getModifiedItems( QList& aModifiedItems, const QDateTime& aTime ) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); qCDebug(lcSyncMLPlugin) << "Retrieving modified calendar events and todo's"; KCalendarCore::Incidence::List incidences; if( !iCalendar.getAllModified( incidences, normalizeTime( aTime ) ) ) { qCDebug(lcSyncMLPlugin) << "Could not retrieve modified calendar events and todo's"; return false; } retrieveItems( incidences, aModifiedItems ); qCDebug(lcSyncMLPlugin) << "Found" << aModifiedItems.count() << "modified items"; return true; } bool CalendarStorage::getModifiedItemIds( QList& aModifiedItemIds, const QDateTime& aTime ) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); qCDebug(lcSyncMLPlugin) << "Retrieving modified calendar events and todo's"; KCalendarCore::Incidence::List incidences; if( !iCalendar.getAllModified( incidences, normalizeTime( aTime ) ) ) { qCDebug(lcSyncMLPlugin) << "Could not retrieve modified calendar events and todo's"; return false; } retrieveIds( incidences, aModifiedItemIds ); qCDebug(lcSyncMLPlugin) << "Found" << aModifiedItemIds.count() << "modified items"; return true; } bool CalendarStorage::getDeletedItemIds( QList& aDeletedItemIds, const QDateTime& aTime ) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); qCDebug(lcSyncMLPlugin) << "Retrieving deleted calendar events and todo's"; KCalendarCore::Incidence::List incidences; if( !iCalendar.getAllDeleted( incidences, normalizeTime( aTime ) ) ) { qCDebug(lcSyncMLPlugin) << "Could not retrieve deleted calendar events and todo's"; return false; } retrieveIds( incidences, aDeletedItemIds ); qCDebug(lcSyncMLPlugin) << "Found" << aDeletedItemIds.count() << "deleted items"; return true; } Buteo::StorageItem* CalendarStorage::newItem() { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); return new SimpleItem(); } QList CalendarStorage::getItems( const QStringList& aItemIdList ) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); KCalendarCore::Incidence::List incidences; KCalendarCore::Incidence::Ptr item; QList items; QStringListIterator itr( aItemIdList ); while( itr.hasNext() ) { //TODO Does calendar backend support batch fetch, check! QString id = itr.next(); item = iCalendar.getIncidence( id ); if( item ) { incidences.append( item ); } else { qCWarning(lcSyncMLPlugin) << "Could not find item " << id; } } retrieveItems( incidences, items ); return items; } Buteo::StorageItem* CalendarStorage::getItem( const QString& aItemId ) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); KCalendarCore::Incidence::Ptr item = iCalendar.getIncidence( aItemId ); if( item ) { return retrieveItem( item ); } else { qCWarning(lcSyncMLPlugin) << "Could not find item:" << aItemId; return NULL; } } CalendarStorage::OperationStatus CalendarStorage::addItem( Buteo::StorageItem& aItem ) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); KCalendarCore::Incidence::Ptr item = generateIncidence( aItem ); if( !item ) { qCWarning(lcSyncMLPlugin) << "Item has invalid format"; return STATUS_INVALID_FORMAT; } if( !iCalendar.addIncidence( item, iCommitNow ) ) { qCWarning(lcSyncMLPlugin) << "Could not add item"; // no need to delete item as item is owned by backend return STATUS_ERROR; } if (item->recurrenceId().isValid()) { QString reccurId = QString(ID_SEPARATOR).append(item->recurrenceId().toString()); aItem.setId( item->uid().append(reccurId) ); } else { aItem.setId( item->uid() ); } qCDebug(lcSyncMLPlugin) << "Item successfully added:" << aItem.getId(); return STATUS_OK; } QList CalendarStorage::addItems( const QList& aItems ) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); QList results; // Disable auto commit as this is a batch add iCommitNow = false; for( int i = 0; i < aItems.count(); ++i ) { results.append( addItem( *aItems[i] ) ); } //Do a batch commit now if( iCalendar.commitChanges() ) { qCDebug(lcSyncMLPlugin) << "Items successfully added"; } iCommitNow = true; return results; } CalendarStorage::OperationStatus CalendarStorage::modifyItem( Buteo::StorageItem& aItem ) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); KCalendarCore::Incidence::Ptr item = generateIncidence( aItem ); if( !item ) { qCWarning(lcSyncMLPlugin) << "Item has invalid format"; return STATUS_INVALID_FORMAT; } if( !iCalendar.modifyIncidence( item, aItem.getId(), iCommitNow ) ) { qCWarning(lcSyncMLPlugin) << "Could not replace item:" << aItem.getId(); // no need to delete item as item is owned by backend return STATUS_ERROR; } qCDebug(lcSyncMLPlugin) << "Item successfully replaced:" << aItem.getId(); // modifyIncidence doesn't take ownership of the item, need to delete it. item.clear(); return STATUS_OK; } QList CalendarStorage::modifyItems( const QList& aItems ) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); QList results; // Disable auto commit as this is a batch add iCommitNow = false; for( int i = 0; i < aItems.count(); ++i ) { results.append( modifyItem( *aItems[i] ) ); } //Do a batch commit now if( iCalendar.commitChanges() ) { qCDebug(lcSyncMLPlugin) << "Items successfully modified"; } iCommitNow = true; return results; } CalendarStorage::OperationStatus CalendarStorage::deleteItem( const QString& aItemId ) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); CalendarBackend::ErrorStatus error = iCalendar.deleteIncidence( aItemId); CalendarStorage::OperationStatus status = mapErrorStatus(error); return status; } QList CalendarStorage::deleteItems( const QList& aItemIds ) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); QList results; for( int i = 0; i < aItemIds.count(); ++i ) { results.append( deleteItem( aItemIds[i] ) ); } return results; } KCalendarCore::Incidence::Ptr CalendarStorage::generateIncidence( Buteo::StorageItem& aItem ) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); KCalendarCore::Incidence::Ptr incidence; QByteArray itemData; if( !aItem.read( 0, aItem.getSize(), itemData ) ) { qCWarning(lcSyncMLPlugin) << "Could not read item data"; return incidence; } QString data = QString::fromUtf8( itemData.data() ); // we are getting a temporary incidence from the calendar if( iStorageType == VCALENDAR_FORMAT ) { incidence = iCalendar.getIncidenceFromVcal( data ); } else { incidence = iCalendar.getIncidenceFromIcal( data ); } return incidence; } void CalendarStorage::retrieveItems( KCalendarCore::Incidence::List& aIncidences, QList& aItems ) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); for( int i = 0; i < aIncidences.count(); ++i ) { Buteo::StorageItem* item = retrieveItem( aIncidences[i] ); aItems.append( item ); } } Buteo::StorageItem* CalendarStorage::retrieveItem( KCalendarCore::Incidence::Ptr& aIncidence ) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); QString data; if(iStorageType == VCALENDAR_FORMAT) { data = iCalendar.getVCalString( aIncidence ); } else { data = iCalendar.getICalString( aIncidence); } Buteo::StorageItem* item = newItem(); QString iId = aIncidence->uid(); if (aIncidence->recurrenceId().isValid()) { QString reccurId = QString(ID_SEPARATOR).append(aIncidence->recurrenceId().toString()); iId.append(reccurId); } item->setId(iId); item->write( 0, data.toUtf8() ); item->setType(iProperties[STORAGE_DEFAULT_MIME_PROP]); return item; } void CalendarStorage::retrieveIds( KCalendarCore::Incidence::List& aIncidences, QList& aIds ) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); for( int i = 0; i < aIncidences.count(); ++i ) { QString iID = aIncidences[i]->uid(); if (aIncidences[i]->recurrenceId().isValid()) { QString reccurId = QString(ID_SEPARATOR).append(aIncidences[i]->recurrenceId().toString()); iID = iID.append(reccurId); } aIds.append( iID ); } } QDateTime CalendarStorage::normalizeTime( const QDateTime& aTime ) const { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); QDateTime normTime = aTime; QTime time = aTime.time(); time.setHMS( time.hour(), time.minute(), time.second(), 0 ); normTime.setTime( time ); normTime = normTime.toUTC(); return normTime; } QByteArray CalendarStorage::getCtCaps( const QString& aFilename ) const { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); QFile ctCapsFile( SyncMLConfig::getXmlDataPath() + aFilename ); QByteArray ctCaps; if( ctCapsFile.open(QIODevice::ReadOnly)) { ctCaps = ctCapsFile.readAll(); ctCapsFile.close(); } else { qCWarning(lcSyncMLPlugin) << "Failed to open CTCaps file for calendar storage:" << aFilename; } return ctCaps; } CalendarStorage::OperationStatus CalendarStorage::mapErrorStatus\ (const CalendarBackend::ErrorStatus &aCalenderError) const { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); CalendarStorage::OperationStatus iStorageStatus = STATUS_OK; switch(aCalenderError) { case CalendarBackend::STATUS_OK: iStorageStatus = STATUS_OK; break; case CalendarBackend::STATUS_ITEM_DUPLICATE: iStorageStatus = STATUS_DUPLICATE; break; case CalendarBackend::STATUS_ITEM_NOT_FOUND: iStorageStatus = STATUS_NOT_FOUND; break; case CalendarBackend::STATUS_GENERIC_ERROR: iStorageStatus = STATUS_ERROR; break; default: iStorageStatus = STATUS_ERROR; break; } return iStorageStatus; } Buteo::StoragePlugin* CalendarStoragePluginLoader::createPlugin(const QString& aPluginName) { return new CalendarStorage(aPluginName); } buteo-sync-plugins-0.8.36/storageplugins/hcalendar/CalendarStorage.h000077500000000000000000000117761476033560700256070ustar00rootroot00000000000000/* * This file is part of buteo-sync-plugins package * * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). * Copyright (C) 2013 - 2021 Jolla Ltd. * * Contact: Sateesh Kavuri * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * */ #ifndef CALENDARSTORAGE_H #define CALENDARSTORAGE_H //sync backend related includes #include "definitions.h" #include "StoragePlugin.h" #include "StorageItem.h" #include "CalendarBackend.h" #include #include #include enum STORAGE_TYPE {VCALENDAR_FORMAT,ICALENDAR_FORMAT}; /// \brief StoragePlugin class for harmattan class CalendarStorage : public Buteo::StoragePlugin { public: /// \brief constructor CalendarStorage(const QString& aPluginName); /// \brief destructor ~CalendarStorage(); /*! \see StoragePlugin::init() * */ virtual bool init( const QMap& aProperties ); /*! \see StoragePlugin::uninit() * */ virtual bool uninit(); /*! \see StoragePlugin::getAllItems() * */ virtual bool getAllItems( QList& aItems ); /*! \see StoragePlugin::getAllItemIds() * */ virtual bool getAllItemIds( QList& aItemIds ); /*! \see StoragePlugin::getNewItems() * */ virtual bool getNewItems( QList& aNewItems, const QDateTime& aTime ); /*! \see StoragePlugin::getNewItemIds() * */ virtual bool getNewItemIds( QList& aNewItemIds, const QDateTime& aTime ); /*! \see StoragePlugin::getModifiedItems() * */ virtual bool getModifiedItems( QList& aModifiedItems, const QDateTime& aTime ); /*! \see StoragePlugin::getModifiedItemIds() * */ virtual bool getModifiedItemIds( QList& aModifiedItemIds, const QDateTime& aTime ); /*! \see StoragePlugin::getDeletedItemIds() * */ virtual bool getDeletedItemIds( QList& aDeletedItemIds, const QDateTime& aTime ); /*! \see StoragePlugin::newItem() * */ virtual Buteo::StorageItem* newItem(); /*! \see StoragePlugin::getItem() * */ virtual Buteo::StorageItem* getItem( const QString& aItemId ); /*! \see StoragePlugin::getItems() * */ virtual QList getItems( const QStringList& aItemIdList ); /*! \see StoragePlugin::addItem() * */ virtual OperationStatus addItem( Buteo::StorageItem& aItem ); /*! \see StoragePlugin::addItems() * */ virtual QList addItems( const QList& aItems ); /*! \see StoragePlugin::modifyItem() * */ virtual OperationStatus modifyItem( Buteo::StorageItem& aItem ); /*! \see StoragePlugin::modifyItems() * */ virtual QList modifyItems( const QList& aItems ); /*! \see StoragePlugin::deleteItem() * */ virtual OperationStatus deleteItem( const QString& aItemId ); /*! \see StoragePlugin::deleteItems() * */ virtual QList deleteItems( const QList& aItemIds ); private: KCalendarCore::Incidence::Ptr generateIncidence( Buteo::StorageItem& aItem ); void retrieveItems( KCalendarCore::Incidence::List& aIncidences, QList& aItems ); Buteo::StorageItem* retrieveItem( KCalendarCore::Incidence::Ptr& aIncidence ); void retrieveIds( KCalendarCore::Incidence::List& aIncidences, QList& aIds ); QDateTime normalizeTime( const QDateTime& aTime ) const; QByteArray getCtCaps( const QString& aFilename ) const; CalendarStorage::OperationStatus mapErrorStatus(const CalendarBackend::ErrorStatus &aCalenderError) const; CalendarBackend iCalendar; STORAGE_TYPE iStorageType; bool iCommitNow; }; class CalendarStoragePluginLoader : public Buteo::StoragePluginLoader { Q_OBJECT Q_PLUGIN_METADATA(IID "com.buteo.plugins.storage.CalendarStoragePluginLoader") Q_INTERFACES(Buteo::StoragePluginLoader) public: /*! \brief Creates calendar storage plugin * * @param aPluginName Human-readable name for plugin * @return Calendar storage plugin instance */ Buteo::StoragePlugin* createPlugin(const QString& aPluginName) override; }; #endif // CALENDARSTORAGE_H buteo-sync-plugins-0.8.36/storageplugins/hcalendar/definitions.h000077500000000000000000000041611476033560700250520ustar00rootroot00000000000000/* * This file is part of buteo-sync-plugins package * * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). * * Contact: Sateesh Kavuri * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * */ #ifndef DEFINITIONS_HEADER_4089094908098437549308790580985 #define DEFINITIONS_HEADER_4089094908098437549308790580985 #include #include const QString DEFAULT_NOTEBOOK_NAME = "myNotebook"; const QString BACKEND_DATABASE = "organizer.db"; //The storage expect this property from outside. If no name is specified, it // will use DEFAULT_NOTEBOOK_NAME. const QString NOTEBOOKNAME = "Notebook Name"; //The storage expect this property from outside. If no format is specified // the storage will use CALENDAR_FORMAT_VCAL. const QString CALENDAR_FORMAT = "Calendar Format"; //Possible values of calendar format are CALENDAR_FORMAT_VCAL // and CALENDAR_FORMAT_ICAL const QString CALENDAR_FORMAT_VCAL = "vcalendar"; const QString CALENDAR_FORMAT_ICAL = "icalendar"; //The incidences before this date wont be considered for sync const QDate OLDESTDATE(1970,01,01); // Calendar incidence types. Needed for filtering purposes. #define CalendarIncidenceType QString const CalendarIncidenceType INCIDENDE_TYPE_ALL = ""; const CalendarIncidenceType INCIDENCE_TYPE_JOURNAL = "Journal"; const CalendarIncidenceType INCIDENCE_TYPE_EVENT = "Event"; const CalendarIncidenceType INCIDENCE_TYPE_TODO = "Todo"; #endif //DEFINITIONS_HEADER_4089094908098437549308790580985 buteo-sync-plugins-0.8.36/storageplugins/hcalendar/hcalendar.pro000077500000000000000000000015461476033560700250350ustar00rootroot00000000000000TEMPLATE = lib TARGET = hcalendar-storage DEPENDPATH += . \ INCLUDEPATH += . \ ../../syncmlcommon CONFIG += link_pkgconfig plugin PKGCONFIG = buteosyncfw5 KF5CalendarCore libmkcal-qt5 LIBS += -lsyncmlcommon5 target.path = $$[QT_INSTALL_LIBS]/buteo-plugins-qt5 VER_MAJ = 1 VER_MIN = 0 VER_PAT = 0 QT -= gui LIBS += -L../../syncmlcommon HEADERS += CalendarStorage.h \ definitions.h \ CalendarBackend.h \ SOURCES += CalendarStorage.cpp \ CalendarBackend.cpp QMAKE_CXXFLAGS = -Wall \ -g \ -Wno-cast-align \ -O2 -finline-functions QMAKE_CLEAN += $(TARGET) $(TARGET0) $(TARGET1) $(TARGET2) ctcaps.path =/etc/buteo/xml/ ctcaps.files=xml/CTCaps_calendar_11.xml xml/CTCaps_calendar_12.xml INSTALLS += target ctcaps QMAKE_CLEAN += $(OBJECTS_DIR)/*.gcda $(OBJECTS_DIR)/*.gcno $(OBJECTS_DIR)/*.gcov $(OBJECTS_DIR)/moc_* buteo-sync-plugins-0.8.36/storageplugins/hcalendar/unittest/000077500000000000000000000000001476033560700242405ustar00rootroot00000000000000buteo-sync-plugins-0.8.36/storageplugins/hcalendar/unittest/CalendarTest.cpp000066400000000000000000000251371476033560700273250ustar00rootroot00000000000000/* * This file is part of buteo-sync-plugins package * * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). * Copyright (C) 2014 Jolla Ltd. * * Contributors: Sateesh Kavuri * Valério Valério * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * */ #include "CalendarTest.h" #include #include void CalendarTest::initTestCase() { iCalendarStorage = new CalendarStorage("hcalendar"); QMap props; props[NOTEBOOKNAME] = "testnotebook"; QVERIFY( iCalendarStorage->init( props ) ); } void CalendarTest::cleanupTestCase() { QVERIFY( iCalendarStorage->uninit() ); delete iCalendarStorage; } void CalendarTest::testSuite() { const QByteArray originalData( "BEGIN:VCALENDAR\r\n" \ "VERSION:1.0\r\n" \ "BEGIN:VEVENT\r\n" \ "UID:D5G8OBE64EFnl46ib91EM2\r\n" \ "SUMMARY:Test\r\n" \ "DTSTART:20090909T080000\r\n" \ "DTEND:20090909T080000\r\n" \ "CLASS:PRIVATE\r\n" \ "LOCATION:Hell\r\n" \ "PRIORITY:2\r\n" \ "END:VEVENT\r\n" \ "END:VCALENDAR\r\n" ); const QByteArray modifiedData( "BEGIN:VCALENDAR\r\n" \ "VERSION:1.0\r\n" \ "BEGIN:VEVENT\r\n" \ "UID:D5G8OBE64EFnl46ib9\r\n" \ "SUMMARY:Test2\r\n" \ "DTSTART:20090909T090000\r\n" \ "DTEND:20090909T090000\r\n" \ "CLASS:PRIVATE\r\n" \ "LOCATION:Heaven\r\n" \ "PRIORITY:2\r\n" \ "END:VEVENT\r\n" \ "END:VCALENDAR\r\n" ); runTestSuite( originalData, modifiedData); } void CalendarTest::runTestSuite( const QByteArray& aOriginalData, const QByteArray& aModifiedData) { QByteArray data; qDebug() << "Starting suite..."; // Get timestamp of 1 seconds in the past. Storages have timestamp accuracy of 1 seconds and // the current second is NOT included in getNewItems(), getModifiedItems() and getDeletedItems() QDateTime t1 = QDateTime::currentDateTime(); qDebug() << "Marking time t1:" << t1; QTest::qSleep( 2000 ); // ** Test New Item Buteo::StorageItem* item = iCalendarStorage->newItem(); QVERIFY( item ); QCOMPARE( item->getId(), QString( "" ) ); // ** Test Add Item QVERIFY( item->write( 0, aOriginalData ) ); QVERIFY( item->getSize() == aOriginalData.size() ); QVERIFY( item->read( 0, item->getSize(), data ) ); QVERIFY( data == aOriginalData ); qDebug() << "Adding new item..."; Buteo::StoragePlugin::OperationStatus status = iCalendarStorage->addItem( *item ); QVERIFY( status == Buteo::StoragePlugin::STATUS_OK ); QVERIFY( !item->getId().isEmpty() ); QString id = item->getId(); QTest::qSleep( 2000 ); QDateTime t2 = QDateTime::currentDateTime(); qDebug() << "Marking time t2:" << t2; QTest::qSleep( 2000 ); // ** Check that item is now found from all items qDebug() << "Checking that the item is now found from getItems()..."; QList items; QVERIFY( iCalendarStorage->getAllItemIds( items ) ); bool found = false; for( int i = 0; i < items.count(); ++i ) { if( items[i] == id ) { found = true; break; } } QVERIFY( found ); items.clear(); // ** Check that item is now found from new items at t1 qDebug() << "Checking that the item is found from getNewItems(t1)..."; QVERIFY( iCalendarStorage->getNewItemIds( items, t1 ) ); found = false; for( int i = 0; i < items.count(); ++i ) { if( items[i] == id ) { found = true; break; } } items.clear(); QVERIFY( found ); // ** Check that item is not found from new items at t2 qDebug() << "Checking that the item is NOT found from getNewItems(t2)..."; // @todo: There's no mechanism in storage plugin API for error handling, // therefore we can't check if this call failed or not QVERIFY( iCalendarStorage->getNewItemIds( items, t2 ) ); found = false; for( int i = 0; i < items.count(); ++i ) { if( items[i] == id ) { found = true; break; } } items.clear(); QVERIFY( !found ); // ** Test Modify Item QVERIFY( item->write( 0, aModifiedData ) ); QVERIFY( item->getSize() == aModifiedData.size() ); QVERIFY( item->read( 0, item->getSize(), data ) ); QVERIFY( data == aModifiedData ); qDebug() << "Modifying item..."; status = iCalendarStorage->modifyItem( *item ); QVERIFY( status == Buteo::StoragePlugin::STATUS_OK ); QVERIFY( item->getId() == id ); delete item; QTest::qSleep( 2000 ); QDateTime t3 = QDateTime::currentDateTime(); qDebug() << "Marking time t3:" << t3; QTest::qSleep( 2000 ); // ** Check that item is still found from new items at t1 qDebug() << "Checking that the item is found from getNewItems(t1)..."; QVERIFY( iCalendarStorage->getNewItemIds( items, t1 ) ); found = false; for( int i = 0; i < items.count(); ++i ) { if( items[i] == id ) { found = true; break; } } items.clear(); QVERIFY( found ); // ** Check that item is not found from modified items at t1 qDebug() << "Checking that the item is NOT found from getModifiedItems(t1)..."; QVERIFY( iCalendarStorage->getModifiedItemIds( items, t1 ) ); found = false; for( int i = 0; i < items.count(); ++i ) { if( items[i] == id ) { found = true; break; } } items.clear(); QVERIFY( !found ); // ** Check that item is now found from modified items at t2 qDebug() << "Checking that the item is found from getModifiedItems(t2)..."; QVERIFY( iCalendarStorage->getModifiedItemIds( items, t2 ) ); found = false; for( int i = 0; i < items.count(); ++i ) { if( items[i] == id ) { found = true; break; } } items.clear(); QVERIFY( found ); // ** Check that item is not found from modified items at t3 qDebug() << "Checking that the item is NOT found from getModifiedItems(t3)..."; QVERIFY( iCalendarStorage->getModifiedItemIds( items, t3 ) ); found = false; for( int i = 0; i < items.count(); ++i ) { if( items[i] == id ) { found = true; break; } } items.clear(); QVERIFY( !found ); // ** Test Delete Item qDebug() << "Deleting item..."; QVERIFY( iCalendarStorage->deleteItem( id ) == Buteo::StoragePlugin::STATUS_OK ); // ** Check that item is no longer found from new items at t1 qDebug() << "Checking that the item is NOT found from getNewItems(t1)..."; QVERIFY( iCalendarStorage->getNewItemIds( items, t1 ) ); found = false; for( int i = 0; i < items.count(); ++i ) { if( items[i] == id ) { found = true; break; } } items.clear(); QVERIFY( !found ); // ** Check that item is not found from modified items at t1 qDebug() << "Checking that the item is NOT found from getModifiedItems(t1)..."; QVERIFY( iCalendarStorage->getModifiedItemIds( items, t1 ) ); found = false; for( int i = 0; i < items.count(); ++i ) { if( items[i] == id ) { found = true; break; } } items.clear(); QVERIFY( !found ); // ** Check that item is not found from deleted items at t1 qDebug() << "Checking that the item is NOT found from getDeletedItems(t1)..."; QVERIFY( iCalendarStorage->getDeletedItemIds( items, t1 ) ); found = false; for( int i = 0; i < items.count(); ++i ) { if( items[i] == id ) { found = true; break; } } items.clear(); QVERIFY( !found ); // ** Check that item is no longer found from modified items at t2 qDebug() << "Checking that the item is NOT found from getModifiedItems(t2)..."; QVERIFY( iCalendarStorage->getModifiedItemIds( items, t2 ) ); found = false; for( int i = 0; i < items.count(); ++i ) { if( items[i] == id ) { found = true; break; } } items.clear(); QVERIFY( !found ); // ** Check that item is now found from deleted items at t2 qDebug() << "Checking that the item is now found from getDeletedItems(t2)..."; QVERIFY( iCalendarStorage->getDeletedItemIds( items, t2 ) ); found = false; for( int i = 0; i < items.count(); ++i ) { if( items[i] == id ) { found = true; break; } } items.clear(); QVERIFY( found ); // ** Check that item is now found from deleted items at t3 qDebug() << "Checking that the item is found from getDeletedItems(t3)..."; QVERIFY( iCalendarStorage->getDeletedItemIds( items, t3 ) ); found = false; for( int i = 0; i < items.count(); ++i ) { if( items[i] == id ) { found = true; break; } } items.clear(); QVERIFY( found ); // ** Check that item is no longer found from all items qDebug() << "Checking that the item is NOT found from getItems()..."; QVERIFY( iCalendarStorage->getAllItemIds( items ) ); found = false; for( int i = 0; i < items.count(); ++i ) { if( items[i] == id ) { found = true; break; } } items.clear(); QVERIFY( !found ); } QTEST_MAIN(CalendarTest) buteo-sync-plugins-0.8.36/storageplugins/hcalendar/unittest/CalendarTest.h000066400000000000000000000026341476033560700267670ustar00rootroot00000000000000/* * This file is part of buteo-sync-plugins package * * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). * Copyright (C) 2014 Jolla Ltd. * * Contributors: Sateesh Kavuri * Valério Valério * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * */ #ifndef HCALENDARTEST_H #define HCALENDARTEST_H #include #include #include #include "CalendarStorage.h" class StorageItem; class CalendarTest : public QObject { Q_OBJECT private slots: void initTestCase(); void cleanupTestCase(); void testSuite(); private: void runTestSuite(const QByteArray& aOriginalData, const QByteArray& aModifiedData); CalendarStorage *iCalendarStorage; }; #endif // HCALENDARTEST_H buteo-sync-plugins-0.8.36/storageplugins/hcalendar/unittest/run-test000077500000000000000000000035431476033560700257540ustar00rootroot00000000000000#/* # * This file is part of buteo-sync-plugins package # * # * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). # * # * Contact: Sateesh Kavuri # * # * This library is free software; you can redistribute it and/or # * modify it under the terms of the GNU Lesser General Public License # * version 2.1 as published by the Free Software Foundation. # * # * This library is distributed in the hope that it will be useful, but # * WITHOUT ANY WARRANTY; without even the implied warranty of # * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # * Lesser General Public License for more details. # * # * You should have received a copy of the GNU Lesser General Public # * License along with this library; if not, write to the Free Software # * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA # * 02110-1301 USA # * # */ # make distclean echo "Building Unit Tests for Calendar Storage " #clean sbox cache export SBOX_USE_CCACHE=no ccache -c qmake make -j2 if [ -f unit_test_results.txt ]; then rm unit_test_results.txt fi echo "Running unit tests ...results will be stored in $PWD/unit_test_results.txt" # pre-conditions to run the tests .... #sb-conf killall meego-run #source /tmp/session_bus_address.user;export DISPLAY=:1 #/usr/lib/tracker/tracker-store & > /dev/null #clear the tracker data base before running tests #tracker-control -r > /dev/null ./hcalendar-tests >> unit_test_results.txt 2>&1 if [ -f gcov_results.txt ]; then rm gcov_results.txt fi # it is easy and convenient to add required files here becuase # the plugins are small and are not really that large when # compared to stack echo "Running gcov ... results will be stored in $PWD/gcov_results.txt" gcov CalendarStorage.gcno >> gcov_results.txt 2>&1 gcov CalendarBackend.gcno >> gcov_results.txt 2>&1 make clean > /dev/null rm *.gcov buteo-sync-plugins-0.8.36/storageplugins/hcalendar/unittest/unittest.pro000066400000000000000000000014131476033560700266400ustar00rootroot00000000000000TEMPLATE = app TARGET = hcalendar-tests DEPENDPATH += . \ ../ \ ../../../syncmlcommon VPATH = .. \ ../../../syncmlcommon INCLUDEPATH += . \ ../ \ ../../../syncmlcommon HEADERS += CalendarTest.h \ CalendarStorage.h \ CalendarBackend.h \ SimpleItem.h \ SyncMLConfig.h SOURCES += CalendarTest.cpp \ CalendarStorage.cpp \ CalendarBackend.cpp \ SimpleItem.cpp \ SyncMLConfig.cpp CONFIG += link_pkgconfig LIBS += -L../../../syncmlcommon PKGCONFIG = buteosyncfw5 KF5CalendarCore libmkcal-qt5 LIBS += -lsyncmlcommon5 QT += testlib \ core \ network \ xml \ sql QT -= gui target.path = /opt/tests/buteo-sync-plugins/ INSTALLS += target buteo-sync-plugins-0.8.36/storageplugins/hcalendar/xml/000077500000000000000000000000001476033560700231615ustar00rootroot00000000000000buteo-sync-plugins-0.8.36/storageplugins/hcalendar/xml/CTCaps_calendar_11.xml000066400000000000000000000026441476033560700271600ustar00rootroot00000000000000 text/x-vcalendar BEGIN VCALENDAR VEVENT VTODO END VCALENDAR VEVENT VTODO VERSION 1.0 UID SUMMARY DESCRIPTION DTSTART DTEND AALARM CLASS PUBLIC PRIVATE CONFIDENTIAL LOCATION DCREATED LAST-MODIFIED PRIORITY STATUS RRULE DUE EXDATE TZ DAYLIGHT ATTENDEE STATUS X-SYMBIAN-DTSTAMP X-SENTBY X-EPOCAGENDAENTRYTYPE APPOINTMENT EVENT ANNIVERSARY TODO X-ADAPTERVERSION 2010SE 18-05-2010 NO-KIA (c)Nokia buteo-sync-plugins-0.8.36/storageplugins/hcalendar/xml/CTCaps_calendar_12.xml000066400000000000000000000076141476033560700271630ustar00rootroot00000000000000 text/x-vcalendar 1.0 BEGIN 256 VCALENDAR VEVENT VTODO Begin END 256 VCALENDAR VEVENT VTODO End VERSION 256 1.0 Version UID 256 Uid SUMMARY 256 Summary DESCRIPTION 256 Description DTSTART 256 Dstart DTEND 256 Dtend AALARM 256 Aalarm TYPE Alarm type CLASS 256 PUBLIC PRIVATE CONFIDENTIAL Class LOCATION 256 Location LAST-MODIFIED 256 Last Modified PRIORITY 256 Priority STATUS 256 Status RRULE 256 Rrule COMPLETED 256 Completed DCREATED 256 Dcreated DUE 256 Due EXDATE 256 ExDate CATEGORIES 256 Categories SEQUENCE 256 Sequence TZ 256 TZ DAYLIGHT 256 Daylight RDATE 256 RDate ATTENDEE 256 Attendee TYPE ROLE STATUS X-CN X-ROLE X-SENTBY X-STATUS Type buteo-sync-plugins-0.8.36/storageplugins/hcontacts/000077500000000000000000000000001476033560700224265ustar00rootroot00000000000000buteo-sync-plugins-0.8.36/storageplugins/hcontacts/ContactBuilder.cpp000066400000000000000000000072051476033560700260400ustar00rootroot00000000000000#include "ContactBuilder.h" #include #include #include #include #include #include #include #include ContactBuilder::ContactBuilder(QContactManager *mgr, const QString &syncTarget, const QString &originId, ContactBuilder::MatchFilterMode mode) { QSet ignoredDetailTypes = QSet() << QContactDetail::TypeGlobalPresence << QContactDetail::TypePresence << QContactDetail::TypeOnlineAccount << QContactDetail::TypeVersion << QContactDetail::TypeSyncTarget << QContactDetail::TypeRingtone; d->manager = mgr; d->propertyHandler = new SeasidePropertyHandler(ignoredDetailTypes); d->unimportableDetailTypes = ignoredDetailTypes; d->extraData.insert("syncTarget", syncTarget); d->extraData.insert("originId", originId); d->extraData.insert("mode", static_cast(mode)); } ContactBuilder::~ContactBuilder() { delete d->propertyHandler; d->propertyHandler = 0; } QContactFilter ContactBuilder::mergeSubsetFilter() const { ContactBuilder::MatchFilterMode mode = static_cast(d->extraData.value("mode").toInt()); if (mode == ContactBuilder::NoFilterRequiredMode) { // the caller already knows which id is for which contact // and we don't need to do any merging or matching. return QContactInvalidFilter(); } // Import the vcard data into existing contacts. We want to do a careful merge instead of // overwriting existing contacts to avoid losing data about user-applied contact links. QString syncTarget = d->extraData.value("syncTarget").toString(); QString originId = d->extraData.value("originId").toString(); QContactDetailFilter syncTargetFilter; syncTargetFilter.setDetailType(QContactSyncTarget::Type, QContactSyncTarget::FieldSyncTarget); syncTargetFilter.setValue(syncTarget); QContactDetailFilter originIdFilter = QContactOriginMetadata::matchId(originId); // If the origin id is unknown, every contact is a new contact. Otherwise, ensure we filter // based on the origin id as well as the synctarget, to minimise match surface to valid only. QContactFilter mergeMatchFilter = (originId.isEmpty() ? QContactInvalidFilter() : originIdFilter & syncTargetFilter); return mergeMatchFilter; } bool ContactBuilder::mergeLocalIntoImport(QContact &import, const QContact &local, bool *erase) { // Always perform "clobber" save, never attempt to merge details. // This is because the "local" contact here will actually have the appropriate // sync target and origin Id already (due to our mergeMatchFilter() impl). import.setId(local.id()); // overwrite the local with the import contact. *erase = false; // we don't allow erasure. return true; // contact is modified / requires save. } // don't allow merging contacts in the import list. bool ContactBuilder::mergeImportIntoImport(QContact &, QContact &, bool *erase) { *erase = false; return false; } // don't allow de-duplication of contacts in the import list. int ContactBuilder::previousDuplicateIndex(QList &, QContact &, int) { return -1; } buteo-sync-plugins-0.8.36/storageplugins/hcontacts/ContactBuilder.h000066400000000000000000000030001476033560700254720ustar00rootroot00000000000000/* * This file is part of buteo-sync-plugins package * * Copyright (C) 2015 Jolla Ltd. * Contact: Chris Adams * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * */ #ifndef CONTACTBUILDER_H #define CONTACTBUILDER_H #include #include class ContactBuilder : public SeasideContactBuilder { public: enum MatchFilterMode { NoFilterRequiredMode = 0, FilterRequiredMode }; ContactBuilder(QContactManager *mgr, const QString &syncTarget, const QString &originId, MatchFilterMode mode); ~ContactBuilder(); QContactFilter mergeSubsetFilter() const; bool mergeLocalIntoImport(QContact &import, const QContact &local, bool *erase); // no-op functions: bool mergeImportIntoImport(QContact &, QContact &, bool *erase); int previousDuplicateIndex(QList &, QContact &, int); }; #endif buteo-sync-plugins-0.8.36/storageplugins/hcontacts/ContactsBackend.cpp000066400000000000000000000621401476033560700261630ustar00rootroot00000000000000/* * This file is part of buteo-sync-plugins package * * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). * Copyright (C) 2014 Jolla Ltd. * * Contributors: Sateesh Kavuri * Bea Lam * Valério Valério * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * */ #include "ContactsBackend.h" #include "ContactBuilder.h" #include #include #include "SyncMLPluginLogging.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include ContactsBackend::ContactsBackend(QVersitDocument::VersitType aVCardVer, const QString &syncTarget, const QString &originId) : iReadMgr(NULL), iWriteMgr(NULL), iVCardVer(aVCardVer) //CID 26531 , iSyncTarget(syncTarget) , iOriginId(originId) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); } ContactsBackend::~ContactsBackend() { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); } bool ContactsBackend::init() { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); QMap params; params.insert(QStringLiteral("nonprivileged"), QStringLiteral("true")); iReadMgr = new QContactManager(QLatin1String("org.nemomobile.contacts.sqlite"), params); iWriteMgr = new QContactManager(QLatin1String("org.nemomobile.contacts.sqlite")); return (iReadMgr != NULL && iWriteMgr != NULL); } bool ContactsBackend::uninit() { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); delete iReadMgr; iReadMgr = NULL; delete iWriteMgr; iWriteMgr = NULL; return true; } QList ContactsBackend::getAllContactIds() { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); QList contactIDs; if (iReadMgr != NULL) { contactIDs = iReadMgr->contactIds(); } else { qCWarning(lcSyncMLPlugin) << "Contacts backend not available"; } return contactIDs; } QList ContactsBackend::getAllNewContactIds(const QDateTime &aTimeStamp) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); qCDebug(lcSyncMLPlugin) << "Retrieve New Contacts Since " << aTimeStamp; QList idList; const QContactChangeLogFilter::EventType eventType = QContactChangeLogFilter::EventAdded; getSpecifiedContactIds(eventType, aTimeStamp, idList); return idList; } QList ContactsBackend::getAllModifiedContactIds(const QDateTime &aTimeStamp) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); qCDebug(lcSyncMLPlugin) << "Retrieve Modified Contacts Since " << aTimeStamp; QList idList; const QContactChangeLogFilter::EventType eventType = QContactChangeLogFilter::EventChanged; getSpecifiedContactIds(eventType, aTimeStamp, idList); return idList; } QList ContactsBackend::getAllDeletedContactIds(const QDateTime &aTimeStamp) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); qCDebug(lcSyncMLPlugin) << "Retrieve Deleted Contacts Since " << aTimeStamp; QList idList; const QContactChangeLogFilter::EventType eventType = QContactChangeLogFilter::EventRemoved; getSpecifiedContactIds(eventType, aTimeStamp, idList); return idList; } bool ContactsBackend::addContacts( const QStringList& aContactDataList, QMap& aStatusMap ) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); Q_ASSERT( iReadMgr ); Q_ASSERT( iWriteMgr ); QList documents = convertVCardListToVersitDocumentList(aContactDataList); if (documents.isEmpty()) { qCWarning(lcSyncMLPlugin) << "invalid sync data, aborting"; return false; } qCDebug(lcSyncMLPlugin) << "converted" << aContactDataList.size() << "concatenated vCards into" << documents.size() << "versit documents"; int newCount = 0; int updatedCount = 0; int ignoredCount = 0; ContactBuilder builder(iWriteMgr, iSyncTarget, iOriginId, ContactBuilder::FilterRequiredMode); QList contactList = SeasideImport::buildImportContacts( documents, &newCount, &updatedCount, &ignoredCount, &builder); qCDebug(lcSyncMLPlugin) << "imported" << contactList.size() << "contacts from" << documents.size() << "versit documents"; if (contactList.size() != documents.size()) { qCWarning(lcSyncMLPlugin) << "internal error: could not convert every versit document to a contact:" << contactList.size() << "<" << documents.size(); return false; } prepareContactSave(&contactList); qCDebug(lcSyncMLPlugin) << "New contacts:" << newCount << "Updated contacts:" << updatedCount; QMap errorMap; bool retVal = iWriteMgr->saveContacts(&contactList, &errorMap); if (!retVal) { qCWarning(lcSyncMLPlugin) << "Errors reported while saving contacts:" << iWriteMgr->error(); } // Populate the status value for each addition item (document). ContactsStatus status; for (int i = 0; i < documents.size(); ++i) { status.id = contactList.at(i).id().toString(); status.errorCode = errorMap.value(i, QContactManager::NoError); aStatusMap.insert(i, status); } return retVal; } QContactManager::Error ContactsBackend::modifyContact(const QString &aID, const QString &aContact) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); qCDebug(lcSyncMLPlugin) << "Modifying a Contact with ID" << aID; QContactManager::Error modificationStatus = QContactManager::UnspecifiedError; if (iWriteMgr == NULL) { qCWarning(lcSyncMLPlugin) << "Contacts backend not available"; } else { QContact oldContactData; getContact(QContactId::fromString (aID), oldContactData); QList documents = convertVCardListToVersitDocumentList(QStringList() << aContact); if (documents.size() < 1) { qCWarning(lcSyncMLPlugin) << "Not a valid vCard:" << aContact; return QContactManager::UnspecifiedError; } int newCount = 0; int updatedCount = 0; int ignoredCount = 0; ContactBuilder builder(iWriteMgr, iSyncTarget, iOriginId, ContactBuilder::NoFilterRequiredMode); QList contacts = SeasideImport::buildImportContacts( documents, &newCount, &updatedCount, &ignoredCount, &builder); if (contacts.size() < 1) { qCWarning(lcSyncMLPlugin) << "Unable to convert vCard to contact:" << aContact; return QContactManager::UnspecifiedError; } else if (contacts.size() > 1) { qCWarning(lcSyncMLPlugin) << "vCard encodes multiple contacts when one is expected:" << aContact; // just process the first one, ignore the rest. } QContact newContactData = contacts.first(); newContactData.setId(oldContactData.id()); bool modificationOk = iWriteMgr->saveContact(&oldContactData); modificationStatus = iWriteMgr->error(); if(!modificationOk) { qCWarning(lcSyncMLPlugin) << "Contact Modification Failed"; } } return modificationStatus; } QMap ContactsBackend::modifyContacts( const QStringList &aVCardDataList, const QStringList &aContactIdList) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); Q_ASSERT (iWriteMgr); ContactsStatus status; QMap errors; QMap statusMap; int newCount = 0; int updatedCount = 0; int ignoredCount = 0; QList documents = convertVCardListToVersitDocumentList(aVCardDataList); qCDebug(lcSyncMLPlugin) << "converted" << aVCardDataList.size() << "concatenated vCards into" << documents.size() << "versit documents"; ContactBuilder builder(iWriteMgr, iSyncTarget, iOriginId, ContactBuilder::NoFilterRequiredMode); QList contacts = SeasideImport::buildImportContacts( documents, &newCount, &updatedCount, &ignoredCount, &builder); qCDebug(lcSyncMLPlugin) << "imported" << contacts.size() << "contacts from" << documents.size() << "versit documents"; if (contacts.size() != aContactIdList.size()) { qCWarning(lcSyncMLPlugin) << "internal error: could not convert every versit document to a contact:" << contacts.size() << "<" << documents.size(); } else { for (int i = 0; i < contacts.size(); i++) { qCDebug(lcSyncMLPlugin) << "Id of the contact to be replaced" << aContactIdList.at(i); QContactLocalId uniqueContactItemID = QContactId::fromString (aContactIdList.at(i)); contacts[i].setId(uniqueContactItemID); qCDebug(lcSyncMLPlugin) << "Replacing item's ID " << contacts.at(i); } if(iWriteMgr->saveContacts(&contacts , &errors)) { qCDebug(lcSyncMLPlugin) << "Batch Modification of Contacts Succeeded"; } else { qCDebug(lcSyncMLPlugin) << "Batch Modification of Contacts Failed"; } // QContactManager will populate errorMap only for errors, but we use this as a status map, // so populate NoError if there's no error. // TODO QContactManager populates indices from the qContactList, but we populate keys, is this OK? for (int i = 0; i < contacts.size(); i++) { QContactLocalId contactId = contacts.at(i).id(); status.id = contactId.toString (); if( !errors.contains(i) ) { qCDebug(lcSyncMLPlugin) << "No error for contact with id " << contactId << " and index " << i; status.errorCode = QContactManager::NoError; } else { qCDebug(lcSyncMLPlugin) << "contact with id " << contactId << " and index " << i <<" is in error"; QContactManager::Error errorCode = errors.value(i); status.errorCode = errorCode; } statusMap.insert(i, status); } } return statusMap; } QMap ContactsBackend::deleteContacts(const QStringList &aContactIDList) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); ContactsStatus status; QMap errors; QMap statusMap; if (iWriteMgr == NULL) { for (int i=0; i < aContactIDList.size(); i++) { errors.insert(i, QContactManager::UnspecifiedError); } qCWarning(lcSyncMLPlugin) << "Contacts backend not available"; } else { QList qContactIdList; foreach (QString id, aContactIDList ) { qContactIdList.append(QContactLocalId::fromString (id)); } if(iWriteMgr->removeContacts(qContactIdList , &errors)) { qCDebug(lcSyncMLPlugin) << "Successfully Removed all contacts "; } else { qCWarning(lcSyncMLPlugin) << "Failed Removing Contacts"; } // QContactManager will populate errorMap only for errors, but we use this as a status map, // so populate NoError if there's no error. // TODO QContactManager populates indices from the qContactList, but we populate keys, is this OK? for (int i = 0; i < qContactIdList.size(); i++) { QContactLocalId contactId = qContactIdList.value(i); status.id = contactId.toString (); if( !errors.contains(i) ) { qCDebug(lcSyncMLPlugin) << "No error for contact with id " << contactId << " and index " << i; status.errorCode = QContactManager::NoError; } else { qCDebug(lcSyncMLPlugin) << "contact with id " << contactId << " and index " << i <<" is in error"; QContactManager::Error errorCode = errors.value(i); status.errorCode = errorCode; } statusMap.insert(i, status); } } return statusMap; } void ContactsBackend::prepareContactSave(QList *contactList) { if (!iSyncTarget.isEmpty() || !iOriginId.isEmpty()) { for (int i=0; icount(); i++) { QContact *contact = &((*contactList)[i]); if (!iSyncTarget.isEmpty()) { QContactSyncTarget syncTarget = contact->detail(); syncTarget.setSyncTarget(iSyncTarget); contact->saveDetail(&syncTarget); } if (!iOriginId.isEmpty()) { QContactOriginMetadata originMetaData = contact->detail(); originMetaData.setId(iOriginId); contact->saveDetail(&originMetaData); } Q_FOREACH (QContactDetail det, contact->details()) { det.setValue(QContactDetail__FieldModifiable, true); contact->saveDetail(&det); } } } } QList ContactsBackend::convertVCardListToVersitDocumentList(const QStringList &aVCardList) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); QList retn; Q_FOREACH (const QString &vCard, aVCardList) { // remove any characters after the END:VCARD stanza. // importantly, we do NOT ensure it ends in \r\n or \r\n\r\n // TODO: fix QVersitReader to strip \r\n and \r\n\r\n endings. int endIdx = vCard.lastIndexOf(QStringLiteral("END:VCARD"), -1, Qt::CaseInsensitive); QString modifiedVCard = vCard.mid(0, endIdx + 9); /* 9 = strlen("END:VCARD") */ // convert the vCard to a contact. QVersitReader versitReader(modifiedVCard.toUtf8()); versitReader.startReading(); versitReader.waitForFinished(); QList results = versitReader.results(); if (results.size() == 0) { qCWarning(lcSyncMLPlugin) << "Unable to convert vCard to versit document:" << versitReader.error() << ":"; QStringList erroneousVCardLines = modifiedVCard.split('\n', QString::KeepEmptyParts); Q_FOREACH(QString line, erroneousVCardLines) { if (line.contains(':') || line.trimmed().isEmpty()) { line.replace('\r', ""); line.append(""); qCWarning(lcSyncMLPlugin) << line; } } return QList(); } else if (versitReader.results().size() > 1) { qCWarning(lcSyncMLPlugin) << "Multiple contacts from single vCard:" << modifiedVCard; } retn.append(results.first()); } return retn; } QString ContactsBackend::convertQContactToVCard(const QContact &aContact) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); QList contactsList; contactsList.append (aContact); QVersitContactExporter contactExporter; QSet ignoredDetailTypes = QSet() << QContactDetail::TypeGlobalPresence << QContactDetail::TypePresence << QContactDetail::TypeOnlineAccount << QContactDetail::TypeVersion << QContactDetail::TypeSyncTarget << QContactDetail::TypeRingtone; SeasidePropertyHandler handler(ignoredDetailTypes); contactExporter.setDetailHandler(&handler); QString vCard; bool contactsExported = contactExporter.exportContacts(contactsList, iVCardVer); if (contactsExported){ QList versitDocumentList; versitDocumentList = contactExporter.documents(); QBuffer writeBuf; writeBuf.open(QBuffer::ReadWrite); QVersitWriter writer; writer.setDevice(&writeBuf); if (!writer.startWriting(versitDocumentList)) { qCCritical(lcSyncMLPlugin) << "Error While writing -- " << writer.error(); } if (writer.waitForFinished()) { vCard = writeBuf.buffer(); } writeBuf.close(); } return vCard; } QMap ContactsBackend::convertQContactListToVCardList( const QList & aContactList) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); QMap idDataMap; foreach (QContact contact, aContactList) { idDataMap[contact.id ().toString ()] = convertQContactToVCard(contact); } return idDataMap; } void ContactsBackend::getSpecifiedContactIds(const QContactChangeLogFilter::EventType aEventType, const QDateTime& aTimeStamp, QList& aIdList) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); QContactChangeLogFilter filter(aEventType); filter.setSince(aTimeStamp); aIdList = iReadMgr->contactIds(filter); // Fetch the ids from aIdList QList strIdList; foreach (const QContactId& id, aIdList) { strIdList << id.toString (); } // Filter out ids for items that were added after the specified time. if (aEventType != QContactChangeLogFilter::EventAdded) { filter.setEventType(QContactChangeLogFilter::EventAdded); QList addedList = iReadMgr->contactIds(filter); QList addedStrIdList; foreach (const QContactId& id, addedList) { addedStrIdList << id.toString (); } foreach (const QString addedId, addedStrIdList) { strIdList.removeAll (addedId); } foreach (const QContactLocalId &id, addedList) { aIdList.removeAll(id); } } // This is a defensive procedure to prevent duplicate items being sent. // QSet does not allow duplicates, thus transforming QList to QSet and back // again will remove any duplicate items in the original QList. int originalIdCount = strIdList.size (); QSet idSet = strIdList.toSet (); int idCountAfterDupRemoval = idSet.size (); strIdList = idSet.toList (); qCDebug(lcSyncMLPlugin) << "Item IDs found (returned / incl. duplicates): " << idCountAfterDupRemoval << "/" << originalIdCount; if (originalIdCount != idCountAfterDupRemoval) { qCWarning(lcSyncMLPlugin) << "Contacts backend returned duplicate items for requested list"; qCWarning(lcSyncMLPlugin) << "Duplicate item IDs have been removed"; } // no else // Convert strIdList to aIdList (QContactId) aIdList.clear(); foreach (const QString &id, strIdList) { aIdList << QContactId::fromString (id); } } QDateTime ContactsBackend::lastModificationTime(const QContactLocalId &aContactId) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); QDateTime lastModificationTime = QDateTime::fromTime_t(0); if (iReadMgr == NULL) { qCWarning(lcSyncMLPlugin) << "Contacts backend not available"; } else { QContact contact; getContact(aContactId, contact); QContactTimestamp contactTimestamps; contactTimestamps = contact.detail (QContactTimestamp::Type); lastModificationTime = contactTimestamps.lastModified(); } return lastModificationTime; } /*! \fn ContactsBackend::getContact(QContactLocalId aContactId) */ void ContactsBackend::getContact(const QContactLocalId& aContactId, QContact& aContact) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); QList contactId; contactId.append(aContactId); QList returnedContacts; getContacts(contactId, returnedContacts); if (!returnedContacts.isEmpty()) { aContact = returnedContacts.first(); } } /*! \fn ContactsBackend::getContacts(QContactLocalId aContactId) */ void ContactsBackend::getContacts(const QList& aContactIds, QList& aContacts) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); QContactIdFilter contactFilter; contactFilter.setIds(aContactIds); if (iReadMgr != NULL) { aContacts = iReadMgr->contacts(contactFilter); } } void ContactsBackend::getContacts(const QList& aIdsList, QMap& aDataMap) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); QList returnedContacts; // As this is an overloaded convenience function, these two functions // are utilized to get contacts from the backend and to convert them // to vcard format. getContacts(aIdsList, returnedContacts); aDataMap = convertQContactListToVCardList(returnedContacts); } QDateTime ContactsBackend::getCreationTime( const QContact& aContact ) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); QContactTimestamp contactTimestamp = aContact.detail(); return contactTimestamp.created(); } QList ContactsBackend::getCreationTimes( const QList& aContactIds ) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); Q_ASSERT( iReadMgr ); /* Retrieve QContacts from backend based on id's in aContactsIds. Since we're only interested * in timestamps, set up fetch hint accordingly to speed up the operation. */ QList creationTimes; QList contacts; QContactIdFilter contactFilter; contactFilter.setIds(aContactIds); QList detailTypes; detailTypes << QContactTimestamp::Type; /* Set up fetch hints so that not all details of QContacts be fetched: * 1) Fetch only QContactTimestamp details * 2) Do not try to resolve contact relationships (siblings etc) * 3) Do not include action preferences of contacts * 4) Do not fetch binary blogs (avatar pictures etc) */ QContactFetchHint contactHint; contactHint.setOptimizationHints( QContactFetchHint::NoRelationships | QContactFetchHint::NoActionPreferences | QContactFetchHint::NoBinaryBlobs ); contactHint.setDetailTypesHint (detailTypes); QDateTime currentTime = QDateTime::currentDateTime(); contacts = iReadMgr->contacts( contactFilter, QList(), contactHint ); if( contacts.count() == aContactIds.count() ) { for( int i = 0; i < aContactIds.count(); ++i ) { QDateTime creationTime = currentTime; for( int a = 0; a < contacts.count(); ++a ) { if( contacts[a].id().toString () == aContactIds[i].toString () ) { QContactTimestamp contactTimestamp = contacts[a].detail(); if( !contactTimestamp.created().isNull() && contactTimestamp.created().isValid() ) { creationTime = contactTimestamp.created(); } contacts.removeAt( a ); break; } } creationTimes.append( creationTime ); } } else { qCWarning(lcSyncMLPlugin) << "Unable to fetch creation times"; for( int i = 0; i < aContactIds.count(); ++i ) { creationTimes.append( currentTime ); } } return creationTimes; } buteo-sync-plugins-0.8.36/storageplugins/hcontacts/ContactsBackend.h000066400000000000000000000162661476033560700256400ustar00rootroot00000000000000/* * This file is part of buteo-sync-plugins package * * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). * * Contact: Sateesh Kavuri * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * */ #ifndef CONTACTSBACKEND_H_ #define CONTACTSBACKEND_H_ #include #include #include #include #include #include using namespace QtContacts; using namespace QtVersit; #define QContactLocalId QContactId enum VCARD_VERSION { VCARD_VERSION21, VCARD_VERSION30 }; struct ContactsStatus { QString id; QContactManager::Error errorCode; }; //! \brief Harmattan Contact storage plugin backend interface class /// /// This class interfaces with the backend implementation of contact manager on harmattan /// device class ContactsBackend { public: /*! * \brief Constructor * @param aVerType */ ContactsBackend(QVersitDocument::VersitType aVerType, const QString &syncTarget, const QString &originId); /*! * \brief Destructor */ ~ContactsBackend(); /*! * \brief Searches for available storage plugins and sets the manager to that plugin * @return */ bool init(); /*! * \brief releases the resources held. * @return */ bool uninit(); /*! * \brief Return ids of all contacts retrieved from the backend * @return List of contact IDs */ QList getAllContactIds(); /*! * \brief Return all new contacts ids in a QList of QStrings * @param aTimeStamp Timestamp of the oldest contact ID to be returned * @return List of contact IDs */ QList getAllNewContactIds(const QDateTime& aTimeStamp); /*! * \brief Return all modified contact ids in a QList of QStrings * @param aTimeStamp Timestamp of the oldest contact ID to be returned * @return List of contact IDs */ QList getAllModifiedContactIds(const QDateTime& aTimeStamp); /*! * \brief Return all deleted contacts ids in a QList of QStrings * @param aTimeStamp Timestamp of the oldest contact ID to be returned * @return List of contact IDs */ QList getAllDeletedContactIds(const QDateTime& aTimeStamp); /*! * \brief Get contact data for a given gontact ID as a QContact object * @param aContactId The ID of the contact * @param aContact The returned data of the contact */ void getContact(const QContactLocalId& aContactId, QContact& aContact); /*! * \brief Get multiple contacts at once as vcards * @param aContactIDs List of contact IDs to be returned * @param aContactData Returned contact data */ void getContacts(const QList &aContactIDs, QMap& aContactData ); /*! * \brief Get multiple contacts at once as QContact objects * @param aContactIds List of contact IDs * @param aContacts List of returned contact data */ void getContacts(const QList& aContactIds, QList& aContacts); /*! * \brief Batch addition of contacts * @param aContactDataList Contact data * @param aStatusMap Returned status data * @return Errors */ bool addContacts( const QStringList &aContactDataList, QMap &aStatusMap ); // Functions for modifying contacts /*! * \brief Modify a contact that whose data and ID are given as Input * @param id Contact ID * @param contactdata Contact data * @return Error */ QContactManager::Error modifyContact(const QString &id, const QString &contactdata); /*! * \brief Batch modification * @param aContactDataList Contact data * @param aContactsIdList Contact IDs * @return Errors */ QMap modifyContacts(const QStringList &aContactDataList, const QStringList &aContactsIdList); /*! * \brief Batch deletion of contacts * @param aContactIDList Contact IDs * @return Errors */ QMap deleteContacts(const QStringList &aContactIDList); /*! * \brief Tells if batch updates are enabled * @return True if enabled, false if not */ inline bool batchUpdatesEnabled() { return true; } /*! * \brief Returns the last time the contact was modified * @param aContactId Id of the contact * @return Timestamp of contact's last modification time */ QDateTime lastModificationTime(const QContactLocalId &aContactId); /*! \brief Return creation time of single contact * * @param aContact Contact * @return Creation time */ QDateTime getCreationTime( const QContact& aContact ); /*! \brief Returns creation times of the contacts * * @param aContactIds Ids of the contacts * @return Creation times */ QList getCreationTimes( const QList& aContactIds ); /*! \brief Converts a QContact to a VCard * * @param aContact Contact * @return VCard */ QString convertQContactToVCard(const QContact &aContact); private: // functions QMap convertQContactListToVCardList \ (const QList &aContactList); QList convertVCardListToVersitDocumentList \ (const QStringList &aVCardList); void prepareContactSave(QList *contactList); /*! * \brief Returns contact IDs specified by event type and timestamp * @param aEventType Added/changed/removed contacts * @param aTimeStamp Contacts older than aTimeStamp are filtered out * @param aIdList Returned contact IDs */ void getSpecifiedContactIds(const QContactChangeLogFilter::EventType aEventType, const QDateTime &aTimeStamp, QList &aIdList); private: // data QContactManager *iReadMgr; ///< A pointer to contact manager QContactManager *iWriteMgr; ///< A pointer to contact manager QVersitDocument::VersitType iVCardVer; ///< VCard Version type to operate on QString iSyncTarget; ///< syncTarget to use for contact details QString iOriginId; ///< origin meta-data ID to use for contact details }; #endif /* CONTACTSBACKEND_H_ */ buteo-sync-plugins-0.8.36/storageplugins/hcontacts/ContactsStorage.cpp000066400000000000000000000637641476033560700262550ustar00rootroot00000000000000/* * This file is part of buteo-sync-plugins package * * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). * Copyright (C) 2013 - 2021 Jolla Ltd. * * Contact: Sateesh Kavuri * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * */ #include #include #include "SyncMLPluginLogging.h" #include "ContactsStorage.h" #include "SimpleItem.h" #include "SyncMLCommon.h" #include "SyncMLConfig.h" #include "ProfileEngineDefs.h" #include const char* CTCAPSFILENAME11 = "CTCaps_contacts_11.xml"; const char* CTCAPSFILENAME12 = "CTCaps_contacts_12.xml"; ContactStorage::ContactStorage(const QString& aPluginName) : Buteo::StoragePlugin(aPluginName), iBackend( 0 ) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); } ContactStorage::~ContactStorage() { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); if(iBackend) { qCWarning(lcSyncMLPlugin) << "Uninit method has not been called!"; delete iBackend; iBackend = 0; } } //////////////////////////////////////////////////////////////////////////////////// //////////// Below functions are derived from storage plugin /////////////// //////////////////////////////////////////////////////////////////////////////////// bool ContactStorage::init( const QMap& aProperties ) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); iDeletedItems.uninit(); const QString dbFile = "hcontacts.db"; QString fullDbPath = SyncMLConfig::getDatabasePath() + dbFile; if( !iDeletedItems.init(fullDbPath) ) { return false; } QVersitDocument::VersitType vCardVersion; iProperties = aProperties; QString propVersion = iProperties[STORAGE_DEFAULT_MIME_VERSION_PROP]; if(propVersion == "3.0") { qCDebug(lcSyncMLPlugin) << "Storage is using VCard version 3.0"; vCardVersion = QVersitDocument::VCard30Type; iProperties[STORAGE_DEFAULT_MIME_PROP] = "text/vcard"; } else { qCDebug(lcSyncMLPlugin) << "Storage is using VCard version 2.1"; vCardVersion = QVersitDocument::VCard21Type; } iProperties[STORAGE_SYNCML_CTCAPS_PROP_11] = getCtCaps( CTCAPSFILENAME11 ); iProperties[STORAGE_SYNCML_CTCAPS_PROP_12] = getCtCaps( CTCAPSFILENAME12 ); iBackend = new ContactsBackend(vCardVersion, iProperties.value(STORAGE_SYNC_TARGET), iProperties.value(STORAGE_ORIGIN_ID)); if( !iBackend->init() ) { qCCritical(lcSyncMLPlugin) << "Failed to init contacts backend"; return false; } if( !doInitItemAnalysis() ) { return false; } return true; } bool ContactStorage::uninit() { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); doUninitItemAnalysis(); // If the backend object is NULL, there is nothing to do anyway, // so the default value can be 'true' here. bool backendUninitOk = true; if( iBackend != NULL) { backendUninitOk = iBackend->uninit(); delete iBackend; iBackend = NULL; } bool deleteItemsIdStorageUninitOk = iDeletedItems.uninit(); return (backendUninitOk && deleteItemsIdStorageUninitOk); } bool ContactStorage::getAllItems(QList &aItems) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); bool operationStatus = false; QList list; if(iBackend) { list = iBackend->getAllContactIds(); if(list.size() != 0) { qDebug() << " Number of items retrieved from Contacts " << list.size(); aItems = getStoreList(list); } operationStatus = true; } return operationStatus; } bool ContactStorage::getAllItemIds( QList& aItems ) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); bool operationStatus = false; QList list; if(iBackend) { list = iBackend->getAllContactIds(); qDebug() << " Number of items retrieved from Contacts " << list.size(); foreach(QContactLocalId id , list) { aItems.append(id.toString()); } operationStatus = true; } return operationStatus; } bool ContactStorage::getNewItems(QList &aItems ,const QDateTime& aTime) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); bool operationStatus = false; QList list; if(iBackend) { qDebug() << "****** getNewItems : Added After: ********" << aTime; list = iBackend->getAllNewContactIds(aTime); if(list.size() != 0) { qDebug() << "New Item List Size is " << list.size(); aItems = getStoreList(list); } operationStatus = true; } return operationStatus; } bool ContactStorage::getNewItemIds( QList& aNewItemIds, const QDateTime& aTime ) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); bool operationStatus = false; QList list; if(iBackend) { qDebug() << "****** getNewItem Ids : Added After: ********" << aTime; list = iBackend->getAllNewContactIds(aTime); foreach(QContactLocalId id , list) { aNewItemIds.append(id.toString()); } operationStatus = true; } return operationStatus; } bool ContactStorage::getModifiedItems( QList& aModifiedItems, const QDateTime& aTime ) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); QList list; bool operationStatus = false; if(iBackend) { qDebug() << "******* getModifiedItems: From ********" << aTime; list = iBackend->getAllModifiedContactIds(aTime); aModifiedItems = getStoreList(list); operationStatus = true; } return operationStatus; } bool ContactStorage::getModifiedItemIds( QList& aModifiedItemIds, const QDateTime& aTime ) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); QList list; bool operationStatus = false; if(iBackend) { qDebug() << "******* getModifiedItemIds : From ********" << aTime; list = iBackend->getAllModifiedContactIds(aTime); foreach(QContactLocalId id , list) { aModifiedItemIds.append(id.toString()); } operationStatus = true; } return operationStatus; } bool ContactStorage::getDeletedItemIds( QList& aDeletedItemIds, const QDateTime& aTime ) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); qCDebug(lcSyncMLPlugin) << "Getting deleted contacts since" << aTime; return iDeletedItems.getDeletedItems( aDeletedItemIds, aTime ); } Buteo::StorageItem* ContactStorage::newItem() { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); return new SimpleItem; } QList ContactStorage::getItems( const QStringList& aItemIdList ) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); QList items; QMap vcards; QList ids; QStringListIterator itr( aItemIdList ); if( iBackend ) { foreach (const QString itr, aItemIdList) { ids.append( QContactId::fromString (itr) ); } iBackend->getContacts( ids, vcards ); QMapIterator i(vcards); while( i.hasNext() ) { i.next(); if( !i.value().isEmpty() ) { SimpleItem *item = new SimpleItem; item->setId( i.key() ); item->setType( iProperties[STORAGE_DEFAULT_MIME_PROP] ); item->write( 0, i.value().toUtf8() ); items.append( item ); } else { qCWarning(lcSyncMLPlugin) << "Contact with id " << i.key() <<" doesn't exist!"; } } } return items; } Buteo::StorageItem* ContactStorage::getItem( const QString& aItemId ) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); if( !iBackend ) { return NULL; } SimpleItem* newItem = NULL; QContactLocalId id; id = QContactId::fromString (aItemId); QContact contact; iBackend->getContact( id, contact ); QDateTime creationTime = iBackend->getCreationTime( contact ); if( iFreshItems.contains( id.toString () ) ) { qCDebug(lcSyncMLPlugin) << "Intercepted fresh item:" << id.toString (); iSnapshot.insert( id.toString (), creationTime ); iFreshItems.removeOne( id.toString () ); } QString contactData = iBackend->convertQContactToVCard( contact ); if(!contactData.isEmpty()) { newItem = new SimpleItem; newItem->setId(aItemId); newItem->setType(iProperties[STORAGE_DEFAULT_MIME_PROP]); newItem->write(0,contactData.toUtf8()); } else { qCWarning(lcSyncMLPlugin) << "Contact does not exist:" << aItemId; } return newItem; } ContactStorage::OperationStatus ContactStorage::addItem(Buteo::StorageItem& aItem) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); QList items; items.append( &aItem ); QList status = addItems( items ); return status.first(); } QList ContactStorage::addItems( const QList& aItems ) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); QList storageErrorList; QDateTime currentTime = QDateTime::currentDateTime(); if( !iBackend ) { for ( int i = 0; i < aItems.size(); i++) { storageErrorList.append(STATUS_ERROR); } return storageErrorList; } QList contactsList; foreach(Buteo::StorageItem *item , aItems) { QByteArray data; item->read(0,item->getSize(),data); contactsList.append(QString::fromUtf8(data.data())); } QList contactsIdList; QMap contactsErrorMap; bool retVal = iBackend->addContacts(contactsList, contactsErrorMap); if((contactsErrorMap.size() != contactsList.size()) || (contactsList.size() != aItems.size())) { qCWarning(lcSyncMLPlugin) << "Something Wrong with Batch Addition in Contacts Backend : " << retVal; qCDebug(lcSyncMLPlugin) << "contactsErrorMap.size() " << contactsErrorMap.size(); qCDebug(lcSyncMLPlugin) << "contactsList.size()" << contactsList.size(); qCDebug(lcSyncMLPlugin) << "aItems.size()" << aItems.size(); for ( int i = 0; i < aItems.size(); i++) { storageErrorList.append(STATUS_ERROR); } } else { QMapIterator i(contactsErrorMap); int j = 0; while (i.hasNext()) { i.next(); Buteo::StorageItem *item = aItems[j]; item->setId(i.value().id); ContactStorage::OperationStatus status = mapErrorStatus(i.value().errorCode); if( status == STATUS_OK ) { // This item was successfully added, so let's add it to the snapshot iSnapshot.insert( i.value().id, currentTime ); } storageErrorList.append(status); j++; } } return storageErrorList; } ContactStorage::OperationStatus ContactStorage::modifyItem(Buteo::StorageItem& aItem) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); ContactStorage::OperationStatus status = STATUS_ERROR; if(iBackend ) { QString strID = aItem.getId(); QByteArray data; aItem.read( 0, aItem.getSize(), data ); QString Contact = QString::fromUtf8( data ); qDebug() << "Modifying an Item with data : " << Contact; qDebug() << "Modifying an Item with ID : " << strID; QContactManager::Error error = iBackend->modifyContact(strID ,Contact); status = mapErrorStatus(error); qDebug() << "After Modification String ID is " << strID; } return status; } QList ContactStorage::modifyItems(const QList &aItems) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); QList storageErrorList; qDebug() << "Items to Modify :" << aItems.size(); if(iBackend) { QStringList contactsList; QStringList contactsIdList; foreach(Buteo::StorageItem *item , aItems) { QByteArray data; item->read(0,item->getSize(),data); contactsList.append(QString::fromUtf8(data.data())); contactsIdList.append(item->getId()); } QMap contactsErrorMap = iBackend->modifyContacts(contactsList, contactsIdList); if(contactsErrorMap.size() != contactsList.size()) { qCWarning(lcSyncMLPlugin) << "Something Wrong with Batch Mofication in Contacts Backend"; qCDebug(lcSyncMLPlugin) << "contactsErrroMap.size() " << contactsErrorMap.size(); qCDebug(lcSyncMLPlugin) << "contactsList.size()" << contactsList.size(); for ( int i = 0; i < aItems.size(); i++) { storageErrorList.append(STATUS_ERROR); } } else { QMapIterator i(contactsErrorMap); int j = 0; while (i.hasNext()) { i.next(); Buteo::StorageItem *item = aItems[j]; item->setId(i.value().id); qCDebug(lcSyncMLPlugin) << "Id set in Storage " << item->getId(); storageErrorList.append(mapErrorStatus(i.value().errorCode)); j++; } } // end if contactsErrroMap.size() != contactsList.size() } else { for ( int i = 0; i < aItems.size(); i++) { storageErrorList.append(STATUS_ERROR); } } return storageErrorList; } ContactStorage::OperationStatus ContactStorage::deleteItem( const QString& aItemId ) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); QList itemIds; itemIds.append( aItemId ); QList status = deleteItems( itemIds ); return status.first(); } QList ContactStorage::deleteItems(const QList& aItemIds ) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); QList statusList; QDateTime currentTime = QDateTime::currentDateTime(); if( !iBackend ) { for ( int i = 0; i < aItemIds.size(); i++) { statusList.append(STATUS_ERROR); } return statusList; } QMap errorMap = iBackend->deleteContacts(aItemIds); if(errorMap.size() !=aItemIds.size() ) { qCWarning(lcSyncMLPlugin) << "Something wrong with batch deletion of Contacts"; qCDebug(lcSyncMLPlugin) << "contactsErrroMap.size() " << errorMap.size(); qCDebug(lcSyncMLPlugin) << "contactsList.size()" << aItemIds.size(); for ( int i = 0; i < aItemIds.size(); i++) { statusList.append(STATUS_ERROR); } } else { QList itemIds; QList creationTimes; QList deletionTimes; QMapIterator i(errorMap); int j = 0; while( i.hasNext() ) { i.next(); ContactStorage::OperationStatus status = mapErrorStatus( i.value().errorCode ); if( status == STATUS_OK ) { // This item was successfully deleted, so let's remove it from the snapshot and // add it to the deleted items. QString itemId = aItemIds[j]; itemIds.append( itemId ); creationTimes.append( iSnapshot.value( itemId )); iSnapshot.remove( itemId ); deletionTimes.append( currentTime ); } statusList.append( status ); j++; } if( !itemIds.isEmpty() ) { iDeletedItems.addDeletedItems( itemIds, creationTimes, deletionTimes ); } } return statusList; } bool ContactStorage::doInitItemAnalysis() { /* Items are analyzed using two sets of items: those that existed at the end * of the previous time this plugin was uninitiated (called snapshot), and those * that exists now (called backend). The point of the analysis is to divide the * items into 3 groups: * 1) Items that exist only in the snapshot. These items have been deleted, and * should be moved to the list of deleted items. The creation time of these * items is known, as they are stored in the database. * 2) Items that exist both in the snapshot and the backend. Since there's no * change in the lifetime of these items, they do not need any special * attention. * 3) Items that exist only in the backed. These items have been created recently, * so their creation time needs to be fetched from the backend before they * are added to snapshot we are storing to database during uninit(). We could * retrieve creation times here, but because these items are usually accessed * anyway during a session, we will just add them to a list of "fresh items" * which will be checked whenever a contact is retrieved from backend. * The creation times of all remaining "fresh" items which were not accessed * during the session will be retrieved in uninit() * * After items have been analyzed, the in-memory snapshot will be identical to * backend. In-memory snapshot is updated whenever we add or delete items. In * the item analysis of uninit() we therefore have an up-to-date snapshot of the * contents of the backend. Changes that external application do the beckend * during the sync session will get discovered in the next session. */ FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); Q_ASSERT( iBackend ); iSnapshot.clear(); iFreshItems.clear(); QDateTime currentTime = QDateTime::currentDateTime(); QMap snapshot; QList backend; QList freshItems; // ** Retrieve previous snapshot from db and convert to QHash QList snapshotItems; QList snapshotCreationTimes; if( !iDeletedItems.getSnapshot(snapshotItems, snapshotCreationTimes) ) { return false; } for( int i = 0; i < snapshotItems.count(); ++i ) { snapshot.insert( snapshotItems[i], snapshotCreationTimes[i] ); } // ** Retrieve backend QList backendIds = iBackend->getAllContactIds(); foreach (const QContactId id, backendIds) { backend << id.toString (); } qCDebug(lcSyncMLPlugin) << "Found" << snapshot.count() << "items from snapshot"; qCDebug(lcSyncMLPlugin) << "Found" << backend.count() << "items from backend"; QList itemIds; QList creationTimes; QList deletionTimes; // ** Find items only in the snapshot and mark them as deleted QMutableMapIterator i( snapshot ); while( i.hasNext() ) { i.next(); if( !backend.contains( i.key() ) ) { itemIds.append( i.key() ); creationTimes.append( i.value() ); deletionTimes.append( currentTime ); i.remove(); } } qCDebug(lcSyncMLPlugin) << "Detected" << itemIds.count() <<"deleted items"; if( !itemIds.isEmpty() ) { iDeletedItems.addDeletedItems( itemIds, creationTimes, deletionTimes ); } // ** Find items only in backend and mark them as fresh items for( int i = 0; i < backend.count(); ++i ) { if( !snapshot.contains( backend[i] ) ) { freshItems.append( backend[i] ); snapshot.insert( backend[i], QDateTime() ); } } iSnapshot = snapshot; iFreshItems = freshItems; qCDebug(lcSyncMLPlugin) << "Detected" << iFreshItems.count() <<"fresh items"; return true; } bool ContactStorage::doUninitItemAnalysis() { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); Q_ASSERT( iBackend ); // ** Retrieve creation times for the remaining "fresh" items from the backend if( !iFreshItems.isEmpty() ) { qCDebug(lcSyncMLPlugin) << "Retrieving creation times for" << iFreshItems.count() << "fresh items"; QList idList; foreach (const QString freshItem, iFreshItems) { idList << QContactId::fromString (freshItem); } QList freshCreationTimes = iBackend->getCreationTimes( idList ); for( int i = 0; i < iFreshItems.count(); ++i ) { iSnapshot.insert( iFreshItems[i], freshCreationTimes[i] ); } } // ** Store the snapshot to the database QTime timer; timer.start(); QList intIds = iSnapshot.keys(); QList ids; for( int i = 0; i < intIds.count(); ++i ) { ids.append( intIds[i] ); } QList creationTimes = iSnapshot.values(); qCDebug(lcSyncMLPlugin) << "Storing" << ids.count() <<"items to snapshot"; iDeletedItems.setSnapshot( ids, creationTimes ); iSnapshot.clear(); iFreshItems.clear(); return true; } QList ContactStorage::getStoreList(QList &aStrIDList) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); QList itemList; if (iBackend != NULL) { QMap idDataMap; iBackend->getContacts(aStrIDList, idDataMap); QMapIterator iter(idDataMap); while (iter.hasNext()) { iter.next(); SimpleItem* item = convertVcardToStorageItem(QContactId::fromString (iter.key()), iter.value()); if (item != NULL) { itemList.append(item); } } } return itemList; } QByteArray ContactStorage::getCtCaps( const QString& aFilename ) const { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); QFile ctCapsFile( SyncMLConfig::getXmlDataPath() + aFilename ); QByteArray ctCaps; if( ctCapsFile.open(QIODevice::ReadOnly)) { ctCaps = ctCapsFile.readAll(); ctCapsFile.close(); } else { qCWarning(lcSyncMLPlugin) << "Failed to open CTCaps file for contacts storage:" << aFilename; } return ctCaps; } ContactStorage::OperationStatus ContactStorage::mapErrorStatus\ (const QContactManager::Error &aContactError) const { ContactStorage::OperationStatus iStorageStatus = STATUS_ERROR; switch(aContactError) { case QContactManager::NoError: iStorageStatus = STATUS_OK; break; case QContactManager::DoesNotExistError: iStorageStatus = STATUS_NOT_FOUND; break; case QContactManager::AlreadyExistsError: iStorageStatus = STATUS_DUPLICATE; break; case QContactManager::InvalidDetailError: case QContactManager::VersionMismatchError: case QContactManager::InvalidContactTypeError: iStorageStatus = STATUS_INVALID_FORMAT; break; case QContactManager::OutOfMemoryError: iStorageStatus = STATUS_STORAGE_FULL; break; case QContactManager::LimitReachedError: iStorageStatus = STATUS_OBJECT_TOO_BIG; break; case QContactManager::InvalidRelationshipError: case QContactManager::LockedError: case QContactManager::DetailAccessError: case QContactManager::PermissionsError: case QContactManager::NotSupportedError: case QContactManager::BadArgumentError: case QContactManager::UnspecifiedError: default: iStorageStatus = STATUS_ERROR; break; } return iStorageStatus; } /*! \fn ContactStorage::convertVcardToStorageItem(const QContactLocalId, const QString&) */ SimpleItem* ContactStorage::convertVcardToStorageItem(const QContactLocalId aItemKey, const QString& aItemData) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); SimpleItem* storageItem = new SimpleItem; if(storageItem != NULL) { qDebug() << "ID is " << aItemKey; qDebug() << "Data is " << aItemData; storageItem->write( 0, aItemData.toUtf8() ); storageItem->setId(aItemKey.toString()); storageItem->setType(iProperties[STORAGE_DEFAULT_MIME_PROP]); } else { qCWarning(lcSyncMLPlugin) << "Memory Allocation Failed"; } return storageItem; } Buteo::StoragePlugin* ContactsStoragePluginLoader::createPlugin(const QString& aPluginName) { return new ContactStorage(aPluginName); } buteo-sync-plugins-0.8.36/storageplugins/hcontacts/ContactsStorage.h000066400000000000000000000171101476033560700257020ustar00rootroot00000000000000/* * This file is part of buteo-sync-plugins package * * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). * Copyright (C) 2013 - 2021 Jolla Ltd. * * Contact: Sateesh Kavuri * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * */ #ifndef CONTACT_STORAGE_HEADER_1717 #define CONTACT_STORAGE_HEADER_1717 #include #include #include "StoragePlugin.h" #include "StoragePluginLoader.h" #include "ContactsBackend.h" #include "buteosyncfw5/DeletedItemsIdStorage.h" class SimpleItem; //! \brief Harmattan Contact storage plugin // // Interface to Storage Plugin towards Sync FW class ContactStorage : public Buteo::StoragePlugin { public: /*! \brief Constructor * */ ContactStorage(const QString& aPluginName); /*! \brief Destructor * */ virtual ~ContactStorage(); //////////////////////////////////////////////////////////////////////////////// // Functions below are derived from storage plugin /////////////// //////////////////////////////////////////////////////////////////////////////// /*! \brief Initializes the plugin * * * @param aProperties Properties that should be set for this plugin * @return True on success, otherwise false */ virtual bool init( const QMap& aProperties ); /*! \brief Uninitializes the plugin * */ virtual bool uninit(); /*! \brief Returns all known items * * @param aItems Array where to place items * @return True on success, otherwise false */ virtual bool getAllItems(QList &aItems); /*! \brief Returns id's of all known items * * @param aItems Array where to place item id's * @return True on success, otherwise false */ virtual bool getAllItemIds( QList& aItems ); /*! \brief Returns all new items since aTime * * @param aNewItems Array where to place items * @param aTime Timestamp * @return True on success, otherwise false */ virtual bool getNewItems( QList& aNewItems, const QDateTime& aTime ); /*! \brief Returns id's of all new items since aTime * * @param aNewItemIds Array where to place item id's * @param aTime Timestamp * @return True on success, otherwise false */ virtual bool getNewItemIds( QList& aNewItemIds, const QDateTime& aTime ); /*! \brief Returns all modified items since aTime * * @param aModifiedItems Array where to place items * @param aTime Timestamp * @return True on success, otherwise false */ virtual bool getModifiedItems( QList& aModifiedItems, const QDateTime& aTime ); /*! \brief Returns id's of all modified items since aTime * * @param aModifiedItemIds Array where to place item id's * @param aTime Timestamp * @return True on success, otherwise false */ virtual bool getModifiedItemIds( QList& aModifiedItemIds, const QDateTime& aTime ); /*! \brief Returns id's of all deleted items since aTime * * @param aDeletedItemIds Array where to place item id's * @param aTime Timestamp * @return True on success, otherwise false */ virtual bool getDeletedItemIds( QList& aDeletedItemIds, const QDateTime& aTime ); /*! \brief Generates a new item * * Returned item is temporary. Therefore returned item ALWAYS has its id * set as empty ID (""). ID will be assigned only after addItem() has been * called for the item. * * @return On success pointer to the item generated, otherwise NULL */ virtual Buteo::StorageItem* newItem(); /*! \brief Returns an item based on id * * @param aItemId Id of the item to return * @return On success pointer to the item, otherwise NULL */ virtual Buteo::StorageItem* getItem( const QString& aItemId ); /*! \brief Returns items based on ids * * @param aItemIdList Ids of the items * @return List of items */ virtual QList getItems( const QStringList& aItemIdList ); /*! \brief Adds an item to the storage * * Upon successful addition, item is updated with its * assigned ID. * * @param aItem Item to add * @return Operation status code */ virtual OperationStatus addItem( Buteo::StorageItem& aItem ); /*! \brief Adds items to the storage * * Upon successful addition, items are updated with its * assigned ID. * * @param aItems Items to add * @return Operation status codes */ virtual QList addItems( const QList& aItems ); /*! \brief Modifies an item in the storage * * @param aItem Item to modify * @return Operation status code */ virtual OperationStatus modifyItem( Buteo::StorageItem& aItem ); /*! \brief Modifies item in the storage * * @param aItems Items to add * @return Operation status codes */ virtual QList modifyItems( const QList& aItems ); /*! \brief Deletes an item from the storage * * @param aItemId Id of the item to be deleted * @return Operation status code */ virtual OperationStatus deleteItem( const QString& aItemId ); /*! \brief Deletes an item from the storage * * @param aItemIds Id's of the item to be deleted * @return Operation status codes */ virtual QList deleteItems( const QList& aItemIds ); private: bool doInitItemAnalysis(); bool doUninitItemAnalysis(); /*! \brief convert list of contacts into vector of storage items * * * @param aList List of contacts * @return list of storage items */ QList getStoreList(QList&aList); QByteArray getCtCaps( const QString& aFilename ) const; ContactStorage::OperationStatus mapErrorStatus(const QContactManager::Error &aContactError) const; /** * \brief Converts a vcard data to a storage item object * @param aItemKey ID of the item * @param aItemData Data of the item * @return Storage item object (a pointer to SimpleItem) */ SimpleItem* convertVcardToStorageItem(const QContactLocalId aItemKey, const QString& aItemData); ContactsBackend* iBackend; Buteo::DeletedItemsIdStorage iDeletedItems; ///< Backend for tracking deleted items QMap iSnapshot; QList iFreshItems; }; class ContactsStoragePluginLoader : public Buteo::StoragePluginLoader { Q_OBJECT Q_PLUGIN_METADATA(IID "com.buteo.plugins.storage.ContactsStoragePluginLoader") Q_INTERFACES(Buteo::StoragePluginLoader) public: Buteo::StoragePlugin* createPlugin(const QString& aPluginName) override; }; #endif //CONTACT_STORAGE_HEADER_1717 buteo-sync-plugins-0.8.36/storageplugins/hcontacts/hcontacts.pro000066400000000000000000000015251476033560700251410ustar00rootroot00000000000000TEMPLATE = lib TARGET = hcontacts-storage DEPENDPATH += . INCLUDEPATH += . \ ../../syncmlcommon CONFIG += link_pkgconfig plugin PKGCONFIG = buteosyncfw5 Qt5Contacts Qt5Versit qtcontacts-sqlite-qt5-extensions contactcache-qt5 LIBS += -lsyncmlcommon5 target.path = $$[QT_INSTALL_LIBS]/buteo-plugins-qt5 VER_MAJ = 1 VER_MIN = 0 VER_PAT = 0 QT -= gui QT += sql HEADERS += ContactsStorage.h \ ContactsBackend.h \ ContactBuilder.h SOURCES += ContactsStorage.cpp \ ContactsBackend.cpp \ ContactBuilder.cpp QMAKE_CXXFLAGS = -Wall \ -g \ -Wno-cast-align \ -O2 -finline-functions LIBS += -L../../syncmlcommon QMAKE_CLEAN += $(TARGET) $(TARGET0) $(TARGET1) $(TARGET2) ctcaps.path =/etc/buteo/xml/ ctcaps.files=xml/CTCaps_contacts_11.xml xml/CTCaps_contacts_12.xml INSTALLS += target ctcaps buteo-sync-plugins-0.8.36/storageplugins/hcontacts/unittest/000077500000000000000000000000001476033560700243055ustar00rootroot00000000000000buteo-sync-plugins-0.8.36/storageplugins/hcontacts/unittest/ContactsTest.cpp000066400000000000000000000337151476033560700274400ustar00rootroot00000000000000/* * This file is part of buteo-sync-plugins package * * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). * Copyright (C) 2014 Jolla Ltd. * * Contributors: Sateesh Kavuri * Valério Valério * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * */ #include "ContactsTest.h" #include #include #include #include #include "SyncMLPluginLogging.h" #include "ContactsStorage.h" #include "SimpleItem.h" static const QByteArray originalData( "BEGIN:VCARD\r\n" "VERSION:2.1\r\n" "REV:20091214T091343Z\r\n" "N:B;A\r\n" "SOUND:\r\n" "PHOTO:\r\n" "URL: \r\n" "TITLE:\r\n" "NOTE:\r\n" "END:VCARD\r\n"); static const QByteArray modifiedData( "BEGIN:VCARD\r\n" "VERSION:2.1\r\n" "REV:20091214T091343Z\r\n" "N:B;A\r\n" "SOUND:\r\n" "PHOTO:\r\n" "URL: \r\n" "TITLE:\r\n" "NOTE:\r\n" "END:VCARD\r\n"); // allocate all resources needed here void ContactsTest::initTestCase() { } // de-allocate all resources used void ContactsTest::cleanupTestCase() { } void ContactsTest::testSuiteSingle() { QMap props; props.insert(QLatin1String("Sync Target"), QLatin1String("local")); ContactStorage storage("hcontacts"); QVERIFY(storage.init( props )); runTestSuite( originalData, modifiedData, storage, false ); QVERIFY(storage.uninit()); } void ContactsTest::testSuiteBatched() { QMap props; props.insert(QLatin1String("Sync Target"), QLatin1String("local")); ContactStorage storage("hcontacts"); QVERIFY(storage.init( props )); runTestSuite( originalData, modifiedData, storage, true ); QVERIFY(storage.uninit()); } void ContactsTest::runTestSuite( const QByteArray& aOriginalData, const QByteArray& aModifiedData, Buteo::StoragePlugin& aPlugin, bool aBatched ) { const int WAIT_TIME = 2000; QByteArray data; qDebug() << "Starting suite..."; // Get timestamp of 1 seconds in the past. Storages have timestamp accuracy of 1 seconds and // the current second is NOT included in getNewItems(), getModifiedItems() and getDeletedItems() QDateTime t1 = QDateTime::currentDateTime(); qDebug() << "Marking time t1:" << t1; QTest::qSleep( WAIT_TIME ); // ** Test New Item Buteo::StorageItem* item = aPlugin.newItem(); QVERIFY( item ); QCOMPARE( item->getId(), QString( "" ) ); // ** Test Add Item QVERIFY( item->write( 0, aOriginalData ) ); QVERIFY( item->getSize() == aOriginalData.size() ); QVERIFY( item->read( 0, item->getSize(), data ) ); QVERIFY( data == aOriginalData ); qDebug() << "Adding new item..."; Buteo::StoragePlugin::OperationStatus status; if( aBatched ) { QList items; items.append( item ); QList results = aPlugin.addItems( items); QCOMPARE( results.count(), 1 ); status = results.first(); } else { status = aPlugin.addItem( *item ); } QVERIFY( status == Buteo::StoragePlugin::STATUS_OK ); QVERIFY( !item->getId().isEmpty() ); QString id = item->getId(); QTest::qSleep( WAIT_TIME ); QDateTime t2 = QDateTime::currentDateTime(); qDebug() << "Marking time t2:" << t2; QTest::qSleep( WAIT_TIME ); // ** Check that item is now found from all items qDebug() << "Checking that the item is now found from getItems()..."; QList items; QVERIFY( aPlugin.getAllItemIds( items ) ); qDebug() << "id expected" << id; QVERIFY( items.contains( id ) ); // ** Check that item is now found from new items since t1 qDebug() << "Checking that the item is found from getNewItems(t1)..."; items.clear(); QVERIFY( aPlugin.getNewItemIds( items, t1 ) ); QVERIFY( items.contains( id ) ); // ** Check that item is not found from new items since t2 qDebug() << "Checking that the item is NOT found from getNewItems(t2)..."; items.clear(); QVERIFY( aPlugin.getNewItemIds( items, t2 ) ); QVERIFY( !items.contains( id ) ); // ** Test Modify Item QVERIFY( item->write( 0, aModifiedData ) ); QVERIFY( item->getSize() == aModifiedData.size() ); QVERIFY( item->read( 0, item->getSize(), data ) ); QVERIFY( data == aModifiedData ); qDebug() << "Modifying item..."; if( aBatched ) { QList items; items.append( item ); QList results = aPlugin.modifyItems( items); QCOMPARE( results.count(), 1 ); status = results.first(); } else { status = aPlugin.modifyItem( *item ); } QDateTime time = QDateTime::currentDateTime(); qDebug() << "Item modified at :" << time; QVERIFY( status == Buteo::StoragePlugin::STATUS_OK ); QVERIFY( item->getId() == id ); delete item; QTest::qSleep( WAIT_TIME ); QDateTime t3 = QDateTime::currentDateTime(); qDebug() << "Marking time t3:" << t3; QTest::qSleep( WAIT_TIME ); // ** Check that item is NOT found from new items since t1 qDebug() << "Checking that the item is found from getNewItems(t1)..."; items.clear(); QVERIFY( aPlugin.getNewItemIds( items, t1 ) ); QVERIFY( !items.contains( id ) ); // ** Check that item is found from modified items since t1 qDebug() << "Checking that the item is NOT found from getModifiedItems(t1)..."; items.clear(); QVERIFY( aPlugin.getModifiedItemIds( items, t1 ) ); QVERIFY( items.contains( id ) ); // ** Check that item is now found from modified items since t2 qDebug() << "Checking that the item is found from getModifiedItems(t2)..."; items.clear(); QVERIFY( aPlugin.getModifiedItemIds( items, t2 ) ); QVERIFY( items.contains( id ) ); // ** Check that item is not found from modified items since t3 qDebug() << "Checking that the item is NOT found from getModifiedItems(t3)..."; items.clear(); QVERIFY( aPlugin.getModifiedItemIds( items, t3 ) ); QVERIFY( !items.contains( id ) ); // ** Test Delete Item qDebug() << "Deleting item..."; if( aBatched ) { QList items; items.append( id ); QList results = aPlugin.deleteItems( items ); QCOMPARE( results.count(), 1 ); status = results.first(); } else { status = aPlugin.deleteItem( id ); } QVERIFY( status == Buteo::StoragePlugin::STATUS_OK ); // ** Check that item is no longer found from new items since t1 qDebug() << "Checking that the item is NOT found from getNewItems(t1)..."; items.clear(); QVERIFY( aPlugin.getNewItemIds( items, t1 ) ); QVERIFY( !items.contains( id ) ); // ** Check that item is not found from modified items since t1 qDebug() << "Checking that the item is NOT found from getModifiedItems(t1)..."; items.clear(); QVERIFY( aPlugin.getModifiedItemIds( items, t1 ) ); QVERIFY( !items.contains( id ) ); // ** Check that item is not found from deleted items since t1 qDebug() << "Checking that the item is NOT found from getDeletedItems(t1)..."; items.clear(); QVERIFY( aPlugin.getDeletedItemIds( items, t1 ) ); QVERIFY( !items.contains( id ) ); // ** Check that item is no longer found from modified items since t2 qDebug() << "Checking that the item is NOT found from getModifiedItems(t2)..."; items.clear(); QVERIFY( aPlugin.getModifiedItemIds( items, t2 ) ); QVERIFY( !items.contains( id ) ); // ** Check that item is now found from deleted items since t2 qDebug() << "Checking that the item is now found from getDeletedItems(t2)..."; items.clear(); QVERIFY( aPlugin.getDeletedItemIds( items, t2 ) ); QVERIFY( items.contains( id ) ); // ** Check that item is now found from deleted items since t3 qDebug() << "Checking that the item is found from getDeletedItems(t3)..."; items.clear(); QVERIFY( aPlugin.getDeletedItemIds( items, t3 ) ); QVERIFY( items.contains( id ) ); // ** Check that item is no longer found from all items qDebug() << "Checking that the item is NOT found from getItems()..."; items.clear(); QVERIFY( aPlugin.getAllItemIds( items ) ); QVERIFY( !items.contains( id ) ); } /* void ContactsTest::pf177715() { const QString vcardTemplate( "BEGIN:VCARD\r\n" "VERSION:2.1\r\n" "N:%1;%2\r\n" "TEL:%3\r\n" "END:VCARD\r\n"); const int numContacts = 1000; const int contactsPerBatch = 20; QStringList vcards; for( int i = 0; i < numContacts; ++i ) { QString number = QString::number(i); QString vcard = vcardTemplate.arg( number ).arg( number ).arg( number); vcards.append( vcard); } qDebug() << "Testing with" << numContacts << "contacts, using batches of" << contactsPerBatch; QTime timer; QStringList availableManagers = QContactManager::availableManagers(); QContactManager manager( "tracker" ); qDebug() << "Clearing existing contacts..."; QList contactIDs = manager.contactIds(); for( int i = 0; i < contactIDs.count(); i += contactsPerBatch ) { directDelete( contactIDs.mid( i, contactsPerBatch ), manager ); } qDebug() << "Starting direct add..."; timer.start(); for( int i = 0; i < numContacts; i += contactsPerBatch ) { directAdd( vcards.mid( i, contactsPerBatch ), manager ); } qDebug() << "Direct add finished, took" << timer.elapsed() << "ms"; qDebug() << "Starting direct ids..."; timer.start(); contactIDs = manager.contactIds(); qDebug() << "Get direct ids finished, took" << timer.elapsed() << "ms"; qDebug() << "Starting direct delete..."; timer.restart(); contactIDs = manager.contactIds(); for( int i = 0; i < contactIDs.count(); i += contactsPerBatch ) { directDelete( contactIDs.mid( i, contactsPerBatch ), manager ); } qDebug() << "Direct delete finished, took" << timer.elapsed() << "ms"; qDebug() << "Initiating plugin..."; timer.restart(); QMap props; ContactStorage storage("hcontacts"); QVERIFY(storage.init( props )); qDebug() << "Plugin init finished, took" << timer.elapsed() << "ms"; QList items; for( int i = 0; i < numContacts; ++i ) { Buteo::StorageItem* item = storage.newItem(); QVERIFY( item ); QVERIFY( item->write( 0, vcards[i].toAscii() ) ); items.append( item ); } qDebug() << "Starting plugin add..."; timer.start(); for( int i = 0; i < numContacts; i += contactsPerBatch ) { QList status = storage.addItems( items.mid(i, contactsPerBatch ) ); QVERIFY( status.contains( Buteo::StoragePlugin::STATUS_OK ) == contactsPerBatch ); } qDebug() << "Plugin add finished, took" << timer.elapsed() << "ms"; qDeleteAll( items ); items.clear(); qDebug() << "Starting plugin ids..."; timer.start(); QList ids; QVERIFY( storage.getAllItemIds( ids) ); qDebug() << "Get plugin ids finished, took" << timer.elapsed() << "ms"; qDebug() << "Starting plugin delete..."; timer.restart(); contactIDs = manager.contactIds(); for( int i = 0; i < contactIDs.count(); i += contactsPerBatch ) { QList status = storage.deleteItems( ids.mid( i, contactsPerBatch ) ); QVERIFY( status.contains( Buteo::StoragePlugin::STATUS_OK ) == contactsPerBatch ); } qDebug() << "Plugin delete finished, took" << timer.elapsed() << "ms"; qDebug() << "Uninitiating plugin..."; timer.restart(); QVERIFY(storage.uninit()); qDebug() << "Plugin uninit finished, took" << timer.elapsed() << "ms"; } void ContactsTest::directAdd( const QStringList& aVCards, QContactManager& aManager ) { QByteArray byteArray; //QVersitReader needs LF/CRLF/CR between successive vcard's in the list, //CRLF didn't work though. QString LF = "\n"; foreach ( QString vcard, aVCards ) { byteArray.append(vcard.toUtf8()); byteArray.append(LF.toUtf8()); } QBuffer readBuf(&byteArray); readBuf.open(QIODevice::ReadOnly); readBuf.seek(0); QVersitReader versitReader; versitReader.setDevice (&readBuf); if (!versitReader.startReading()) qCWarning(lcSyncMLPlugin) << "Error while reading vcard"; if (!versitReader.waitForFinished()) qCWarning(lcSyncMLPlugin) << "Error while finishing reading vcard"; QList versitDocList = versitReader.results (); readBuf.close(); QVersitContactImporter contactImporter; QList contactList; QVERIFY( contactImporter.importDocuments(versitDocList) ); contactList = contactImporter.contacts(); QMap errorMap; QVERIFY( aManager.saveContacts(&contactList, &errorMap) ); QVERIFY( errorMap.isEmpty() ); } void ContactsTest::directDelete( const QList& aContactIds, QContactManager& manager ) { QMap errorMap; QVERIFY( manager.removeContacts( aContactIds, &errorMap ) ); QVERIFY( errorMap.isEmpty() ); } */ QTEST_MAIN(ContactsTest) buteo-sync-plugins-0.8.36/storageplugins/hcontacts/unittest/ContactsTest.h000066400000000000000000000033421476033560700270760ustar00rootroot00000000000000/* * This file is part of buteo-sync-plugins package * * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). * Copyright (C) 2014 Jolla Ltd. * * Contributors: Sateesh Kavuri * Valério Valério * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * */ #ifndef TESTCONTACTS_H_ #define TESTCONTACTS_H_ #include #include #include #include #include namespace Buteo { class StoragePlugin; } class ContactsTest : public QObject { Q_OBJECT private slots: void initTestCase(); void cleanupTestCase(); void testSuiteSingle(); void testSuiteBatched(); //void pf177715(); private: void runTestSuite( const QByteArray& aOriginalData, const QByteArray& aModifiedData, Buteo::StoragePlugin& aPlugin, bool aBatched ); /* void directDelete( const QList& aContactIds, QContactManager& manager ); void directAdd( const QStringList& aVCards, QContactManager& manager ); */ }; #endif /* TESTCONTACTS_H_ */ buteo-sync-plugins-0.8.36/storageplugins/hcontacts/unittest/run-test000077500000000000000000000035371476033560700260240ustar00rootroot00000000000000#/* # * This file is part of buteo-sync-plugins package # * # * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). # * # * Contact: Sateesh Kavuri # * # * This library is free software; you can redistribute it and/or # * modify it under the terms of the GNU Lesser General Public License # * version 2.1 as published by the Free Software Foundation. # * # * This library is distributed in the hope that it will be useful, but # * WITHOUT ANY WARRANTY; without even the implied warranty of # * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # * Lesser General Public License for more details. # * # * You should have received a copy of the GNU Lesser General Public # * License along with this library; if not, write to the Free Software # * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA # * 02110-1301 USA # * # */ # rm Makefile echo "Building Unit Tests for Calendar Storage " export SBOX_USE_CCACHE=no ccache -c qmake make clean make if [ -f unit_test_results.txt ]; then rm unit_test_results.txt fi echo "Running unit tests ...results will be stored in $PWD/unit_test_results.txt" echo "dbus session address before export is $DBUS_SESSION_BUS_ADDRESS " # pre-conditions to run the tests .... #sb-conf killall meego-run source /tmp/session_bus_address.user;export DISPLAY=:1 /usr/lib/tracker/tracker-store & > /dev/null tracker-control -r > /dev/null ./hcontacts-tests >> unit_test_results.txt 2>&1 if [ -f gcov_results.txt ]; then rm gcov_results.txt fi # it is easy and convenient to add required files here becuase # the plugins are small and are not really that large when # compared to stack echo "Running gcov ... results will be stored in $PWD/gcov_results.txt" gcov ContactsStorage >> gcov_results.txt 2>&1 gcov ContactsBackend >> gcov_results.txt 2>&1 make clean > /dev/null rm *.gcov buteo-sync-plugins-0.8.36/storageplugins/hcontacts/unittest/unittest.pro000066400000000000000000000014721476033560700267120ustar00rootroot00000000000000TEMPLATE = app TARGET = hcontacts-tests QT -= gui QT += core testlib sql CONFIG += link_pkgconfig PKGCONFIG = buteosyncfw5 Qt5Contacts Qt5Versit buteosyncml5 qtcontacts-sqlite-qt5-extensions contactcache-qt5 LIBS += -lsyncmlcommon5 DEPENDPATH += . \ ../ \ VPATH = .. \ ../../../ INCLUDEPATH += . \ ../ \ ../../../syncmlcommon LIBS += -L../../../syncmlcommon HEADERS += ContactsTest.h \ ContactsStorage.h \ ContactsBackend.h \ ContactBuilder.h SOURCES += ContactsTest.cpp \ ContactsStorage.cpp \ ContactsBackend.cpp \ ContactBuilder.cpp testfiles.path = /opt/tests/buteo-sync-plugins/ testfiles.files = vcard1.txt vcard2.txt vcard3.txt target.path = /opt/tests/buteo-sync-plugins/ INSTALLS += target \ testfiles buteo-sync-plugins-0.8.36/storageplugins/hcontacts/unittest/vcard1.txt000066400000000000000000000012071476033560700262260ustar00rootroot00000000000000BEGIN:VCARD VERSION:2.1 REV:20091106T102538Z N:Udupa;Kiran;Shama;Mr. FN:"Udupa Kiran" X-EPOCSECONDNAME: X-EPOCSECONDNAME: EMAIL;WORK:kudupa2@wipro.com EMAIL;HOME:kudupa3@gmail.com X-SIP;SWIS: X-SIP;POC: X-SIP: X-SIP;HOME;VOIP: X-SIP;WORK;VOIP: X-SIP;VOIP: X-ASSISTANT: X-ASSISTANT: X-ANNIVERSARY: X-ANNIVERSARY: X-ASSISTANT-TEL: X-ASSISTANT-TEL: X-SPOUSE: X-SPOUSE: X-CHILDREN: X-CHILDREN: NOTE:notes notes URL:www.web.com EMAIL:kudupa@nokia.com X-NICKNAME:KSU TITLE:Test Lead X-CHILDREN:kkkkk X-SPOUSE:xyz ORG:Wipro TEL:99999 TEL;CELL:44444 TEL;FAX;HOME:88888 TEL;FAX;WORK:77777 TEL;HOME;VOICE:33333 TEL;PAGER:66666 TEL;WORK;VOICE:11111 END:VCARDbuteo-sync-plugins-0.8.36/storageplugins/hcontacts/unittest/vcard2.txt000066400000000000000000000002131476033560700262230ustar00rootroot00000000000000BEGIN:VCARD VERSION:2.1 N:;sateesh FN:kavuri TEL;WORK;VOICE:488484888484 EMAIL;PREF;INTERNET:rajk@gmsil.vom REV:20090812T134232Z END:VCARD buteo-sync-plugins-0.8.36/storageplugins/hcontacts/unittest/vcard3.txt000066400000000000000000000002061476033560700262260ustar00rootroot00000000000000BEGIN:VCARD VERSION:2.1 N:;srikanth FN: TEL;WORK;VOICE:488484888484 EMAIL;PREF;INTERNET:rajk@gmsil.vom REV:20090812T134232Z END:VCARD buteo-sync-plugins-0.8.36/storageplugins/hcontacts/xml/000077500000000000000000000000001476033560700232265ustar00rootroot00000000000000buteo-sync-plugins-0.8.36/storageplugins/hcontacts/xml/CTCaps_contacts_11.xml000066400000000000000000000024541476033560700272710ustar00rootroot00000000000000 text/x-vcard BEGIN VCARD END VCARD VERSION 2.1 REV N ADR HOME WORK PREF TEL HOME WORK CELL PAGER FAX VOICE CAR VIDEO FN EMAIL URL HOME WORK NOTE TITLE ORG PHOTO BDAY LABEL X-ASSISTANT X-SPOUSE X-CHILDREN X-ASSISTANT-TEL X-ANNIVERSARY X-GENDER X-JABBER X-SIP buteo-sync-plugins-0.8.36/storageplugins/hcontacts/xml/CTCaps_contacts_12.xml000066400000000000000000000074761476033560700273030ustar00rootroot00000000000000 text/x-vcard 2.1 BEGIN 256 VCARD END 256 VCARD VERSION 256 2.1 REV 256 N 256 ADR 256 TYPE HOME WORK TEL 256 TYPE HOME WORK CELL PAGER FAX VIDEO PREF CAR FN 256 EMAIL 256 TYPE HOME WORK URL 256 TYPE HOME WORK NOTE 256 TITLE 256 ORG 256 PHOTO 160000 BDAY 256 SOUND 160000 X-ASSISTANT 256 X-ASSISTANT-TEL 256 X-SPOUSE 256 X-CHILDREN 256 X-ANNIVERSARY 256 X-GENDER 256 X-JABBER 256 X-SIP 256 TYPE SWIS VOIP buteo-sync-plugins-0.8.36/storageplugins/hnotes/000077500000000000000000000000001476033560700217405ustar00rootroot00000000000000buteo-sync-plugins-0.8.36/storageplugins/hnotes/NotesBackend.cpp000066400000000000000000000307101476033560700250050ustar00rootroot00000000000000/* * This file is part of buteo-sync-plugins package * * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). * * Contact: Sateesh Kavuri * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * */ #include "NotesBackend.h" #include #include #include #include "SyncMLPluginLogging.h" #include "SimpleItem.h" // @todo: handle unicode notes better. For example S60 seems to send only ascii. // Ovi.com seems to send latin-1 in base64-encoded form. UTF-8 really should // be preferred here, but how would we know which format is given to us as // latin-1 and utf-8 are not compatible? static const QString INCIDENCE_TYPE_JOURNAL( "Journal" ); NotesBackend::NotesBackend() : iCalendar( 0 ), iStorage( 0 ) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); } NotesBackend::~NotesBackend() { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); } bool NotesBackend::init( const QString& aNotebookName, const QString& aUid, const QString &aMimeType ) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); qCDebug(lcSyncMLPlugin) << "Notes backend using notebook" << aNotebookName << "And uuid" << aUid; if( aNotebookName.isEmpty() ) { qCDebug(lcSyncMLPlugin) << "NoteBook Name to Sync is expected. It Cannot be Empty"; return false; } iNotebookName = aNotebookName; iMimeType = aMimeType; iCalendar = mKCal::ExtendedCalendar::Ptr( new mKCal::ExtendedCalendar(QTimeZone::systemTimeZone()) ); qCDebug(lcSyncMLPlugin) << "Creating Default Maemo Storage for Notes"; iStorage = iCalendar->defaultStorage( iCalendar ); bool opened = iStorage->open(); if (!opened) { qCDebug(lcSyncMLPluginTrace) << "Calendar storage open failed"; } mKCal::Notebook::Ptr openedNb; // If we have an Uid, we try to get the corresponding Notebook if (!aUid.isEmpty()) { openedNb = iStorage->notebook(aUid); // If we didn't get one, we create one and set its Uid if (!openedNb) { openedNb = mKCal::Notebook::Ptr(new mKCal::Notebook(aNotebookName, "Synchronization Created Notebook for " + aNotebookName)); if (!openedNb.isNull()) { openedNb->setUid(aUid); if (!iStorage->addNotebook(openedNb)) { qCWarning(lcSyncMLPlugin) << "Failed to add notebook to storage"; openedNb.clear(); } } } } // If we didn't have an Uid or the creation above failed, // we use the default notebook if (openedNb.isNull()) { qCDebug(lcSyncMLPlugin) << "Using default notebook"; openedNb = iStorage->defaultNotebook(); if(openedNb.isNull()) { qCDebug(lcSyncMLPlugin) << "No default notebook exists, creating one"; openedNb = mKCal::Notebook::Ptr(new mKCal::Notebook("Default", QString())); if (!iStorage->setDefaultNotebook(openedNb)) { qCWarning(lcSyncMLPlugin) << "Failed to set default notebook of storage"; openedNb.clear(); } } } bool loaded = false; if(opened && openedNb) { qCDebug(lcSyncMLPlugin) << "Loading all incidences from::" << openedNb->uid(); loaded = iStorage->loadNotebookIncidences(openedNb->uid()); if(!loaded) { qCWarning(lcSyncMLPlugin) << "Failed to load calendar"; } } if (opened && loaded && !openedNb.isNull()) { iNotebookName = openedNb->uid(); qCDebug(lcSyncMLPlugin) << "Calendar initialized for notes"; return true; } else { qCWarning(lcSyncMLPlugin) << "Not able to initialize calendar"; iStorage.clear(); qCDebug(lcSyncMLPluginTrace) << "Storage deleted"; iCalendar.clear(); qCDebug(lcSyncMLPluginTrace) << "Calendar deleted"; return false; } } bool NotesBackend::uninit() { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); if( iStorage ) { iStorage->close(); iStorage.clear(); } if( iCalendar ) { iCalendar->close(); iCalendar.clear(); } return true; } bool NotesBackend::getAllNotes( QList& aItems ) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); KCalendarCore::Incidence::List incidences; if( !iStorage->allIncidences( &incidences, iNotebookName ) ) { qCWarning(lcSyncMLPlugin) << "Could not retrieve all notes"; return false; } retrieveNoteItems( incidences, aItems ); return true; } bool NotesBackend::getAllNoteIds( QList& aItemIds ) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); KCalendarCore::Incidence::List incidences; if( !iStorage->allIncidences( &incidences, iNotebookName ) ) { qCWarning(lcSyncMLPlugin) << "Could not retrieve all notes"; return false; } retrieveNoteIds( incidences, aItemIds ); return true; } bool NotesBackend::getNewNotes( QList& aNewItems, const QDateTime& aTime ) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); KCalendarCore::Incidence::List incidences; if( !iStorage->insertedIncidences( &incidences, aTime, iNotebookName ) ) { qCWarning(lcSyncMLPlugin) << "Could not retrieve new notes"; return false; } retrieveNoteItems( incidences, aNewItems ); return true; } bool NotesBackend::getNewNoteIds( QList& aNewItemIds, const QDateTime& aTime ) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); KCalendarCore::Incidence::List incidences; if( !iStorage->insertedIncidences( &incidences, aTime, iNotebookName ) ) { qCWarning(lcSyncMLPlugin) << "Could not retrieve new notes"; return false; } retrieveNoteIds( incidences, aNewItemIds ); return true; } bool NotesBackend::getModifiedNotes( QList& aModifiedItems, const QDateTime& aTime ) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); KCalendarCore::Incidence::List incidences; if( !iStorage->modifiedIncidences( &incidences, aTime, iNotebookName ) ) { qCWarning(lcSyncMLPlugin) << "Could not retrieve modified notes"; return false; } retrieveNoteItems( incidences, aModifiedItems ); return true; } bool NotesBackend::getModifiedNoteIds( QList& aModifiedItemIds, const QDateTime& aTime ) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); KCalendarCore::Incidence::List incidences; if( !iStorage->modifiedIncidences( &incidences, aTime, iNotebookName ) ) { qCWarning(lcSyncMLPlugin) << "Could not retrieve modified notes"; return false; } retrieveNoteIds( incidences, aModifiedItemIds ); return true; } bool NotesBackend::getDeletedNoteIds( QList& aDeletedItemIds, const QDateTime& aTime ) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); KCalendarCore::Incidence::List incidences; if( !iStorage->deletedIncidences( &incidences, aTime, iNotebookName ) ) { qCWarning(lcSyncMLPlugin) << "Could not retrieve modified notes"; return false; } retrieveNoteIds( incidences, aDeletedItemIds ); return true; } Buteo::StorageItem* NotesBackend::newItem() { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); return new SimpleItem; } Buteo::StorageItem* NotesBackend::getItem( const QString& aItemId ) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); iStorage->load ( aItemId ); KCalendarCore::Incidence::Ptr item = iCalendar->incidence( aItemId ); if( !item ) { qCWarning(lcSyncMLPlugin) << "Could not find item:" << aItemId; return NULL; } Buteo::StorageItem* storageItem = newItem(); storageItem->setId( item->uid() ); storageItem->setType(iMimeType); storageItem->write( 0, item->description().toUtf8() ); return storageItem; } bool NotesBackend::addNote( Buteo::StorageItem& aItem, bool aCommitNow ) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); QByteArray data; if( !aItem.read( 0, aItem.getSize(), data ) ) { qCWarning(lcSyncMLPlugin) << "Reading item data failed"; return false; } KCalendarCore::Journal::Ptr journal; journal = KCalendarCore::Journal::Ptr( new KCalendarCore::Journal() ); QString description = QString::fromUtf8( data.constData() ); journal->setDescription( description ); // addJournal() takes ownership of journal -> we cannot delete it if( !iCalendar->addJournal( journal, iNotebookName ) ) { qCWarning(lcSyncMLPlugin) << "Could not add note to calendar"; journal.clear(); return false; } QString id = journal->uid(); qCDebug(lcSyncMLPlugin) << "New note added, id:" << id; aItem.setId( id ); if( aCommitNow ) { if( !commitChanges() ) { return false; } } return true; } bool NotesBackend::modifyNote( Buteo::StorageItem& aItem, bool aCommitNow ) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); iStorage->load ( aItem.getId() ); KCalendarCore::Incidence::Ptr item = iCalendar->incidence( aItem.getId() ); if( !item ) { qCWarning(lcSyncMLPlugin) << "Could not find item to be modified:" << aItem.getId(); return false; } QByteArray data; if( !aItem.read( 0, aItem.getSize(), data ) ) { qCWarning(lcSyncMLPlugin) << "Reading item data failed:" << aItem.getId(); return false; } QString description = QString::fromLatin1( data.constData() ); item->setDescription( description ); if( aCommitNow ) { if( !commitChanges() ) { return false; } } qCDebug(lcSyncMLPlugin) << "Note modified, id:" << aItem.getId(); return true; } bool NotesBackend::deleteNote( const QString& aId, bool aCommitNow ) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); iStorage->load ( aId ); KCalendarCore::Incidence::Ptr journal = iCalendar->incidence( aId ); if( !journal ) { qCWarning(lcSyncMLPlugin) << "Could not find item to be deleted:" << aId; return false; } if( !iCalendar->deleteIncidence( journal ) ) { qCWarning(lcSyncMLPlugin) << "Could not delete note:" << aId; return false; } if( aCommitNow ) { if( !commitChanges() ) { return false; } } return true; } bool NotesBackend::commitChanges() { bool saved = false; if( iStorage && iStorage->save() ) { saved = true; } else { qCCritical(lcSyncMLPlugin) << "Couldn't save to storage"; } return saved; } void NotesBackend::retrieveNoteItems( KCalendarCore::Incidence::List& aIncidences, QList& aItems ) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); filterIncidences( aIncidences ); for( int i = 0; i < aIncidences.count(); ++i ) { Buteo::StorageItem* item = newItem(); item->setId( aIncidences[i]->uid() ); item->setType(iMimeType); item->write( 0, aIncidences[i]->description().toUtf8() ); aItems.append( item ); } } void NotesBackend::retrieveNoteIds( KCalendarCore::Incidence::List& aIncidences, QList& aIds ) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); filterIncidences( aIncidences ); for( int i = 0; i < aIncidences.count(); ++i ) { aIds.append( aIncidences[i]->uid() ); } } void NotesBackend::filterIncidences( KCalendarCore::Incidence::List& aIncidences ) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); QString journal( INCIDENCE_TYPE_JOURNAL ); int i = 0; while( i < aIncidences.count() ) { KCalendarCore::Incidence::Ptr incidence = aIncidences[i]; if( incidence->type() != KCalendarCore::Incidence::TypeJournal ) { aIncidences.remove( i, 1 ); incidence.clear(); } else { ++i; } } } buteo-sync-plugins-0.8.36/storageplugins/hnotes/NotesBackend.h000066400000000000000000000126321476033560700244550ustar00rootroot00000000000000/* * This file is part of buteo-sync-plugins package * * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). * * Contact: Sateesh Kavuri * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * */ #ifndef NOTESBACKEND_H #define NOTESBACKEND_H #include #include #include class QDateTime; namespace Buteo { class StorageItem; } /*! \brief Notes Calendar backend proxy * */ class NotesBackend { public: /*! \brief Constructor * */ NotesBackend(); /*! \brief Destructor * */ virtual ~NotesBackend(); /*! \brief Initializes backend * * @return True on success, otherwise false */ bool init( const QString& aNotebookName, const QString& aUid, const QString &aMimeType ); /*! \brief Uninitializes backend * * @return True on success, otherwise false */ bool uninit(); /*! \brief retrieves all Notes from the backend * * @param aItems Output Parameter - List of Buteo::StorageItems retrieved from Backend. * @return True on success, otherwise false */ bool getAllNotes( QList& aItems ); /*! \brief gets are note ids from the backend * * @param aIds - list of notes ids * @return True on success, otherwise false */ bool getAllNoteIds( QList& aIds ); /*! \brief get all new notes from a timestamp * * @param aNewItems List of new items.(output parameter) * @param aTime - time from which to retrieve the notes * @return True on success, otherwise false */ bool getNewNotes( QList& aNewItems, const QDateTime& aTime ); /*! \brief get all new note ids from a timestamp * * @param aNewIds List of new ids (output parameter) * @param aTime - time from which to retrieve the notes * @return True on success, otherwise false */ bool getNewNoteIds( QList& aNewIds, const QDateTime& aTime ); /*! \brief get all modified notes from the backend * * @param aModifiedItems - list of modified items (output parameter) * @param aTime - timestamp from which the modified notes are needed. * @return True on success, otherwise false */ bool getModifiedNotes( QList& aModifiedItems, const QDateTime& aTime ); /*! \brief get all modified notes ids from the backend * * @param aModifiedIds - list of modified ids (output parameter) * @param aTime - timestamp from which the modified notes ids are needed. * @return True on success, otherwise false */ bool getModifiedNoteIds( QList& aModifiedIds, const QDateTime& aTime ); /*! \brief gets all deleted note ids * * @param aDeletedIds - deleted ids. * @param aTime - timestamp from which the deleted ids are needed. * @return True on success, otherwise false */ bool getDeletedNoteIds( QList& aDeletedIds, const QDateTime& aTime ); /*! \brief fetch a new StorageItem * * @return pointer to the newly created StorageItem */ Buteo::StorageItem* newItem(); /*! \brief get an item * * @param aItemId - id of the item to get * @return pointer to the StorageItem */ Buteo::StorageItem* getItem( const QString& aItemId ); /*! \brief Uninitializes backend * * @param aItem - item to add * @param aCommitNow - if true persist db changes, if false do this later * @return True on success, otherwise false */ bool addNote( Buteo::StorageItem& aItem, bool commitNow ); /*! \brief Uninitializes backend * * @param aItem - item to modify * @param aCommitNow - if true persist db changes, if false do this later * @return True on success, otherwise false */ bool modifyNote( Buteo::StorageItem& aItem, bool commitNow ); /*! \brief Uninitializes backend * * @param aId - id of item to delete * @param aCommitNow - if true persist db changes, if false do this later * @return True on success, otherwise false */ bool deleteNote( const QString& aId, bool commitNow ); /*! \brief Persist notes db * * @return True on success, otherwise false */ bool commitChanges(); protected: private: void retrieveNoteItems( KCalendarCore::Incidence::List& aIncidences, QList& aItems ); void retrieveNoteIds( KCalendarCore::Incidence::List& aIncidences, QList& aIds ); void filterIncidences( KCalendarCore::Incidence::List& aIncidences ); QString iNotebookName; QString iMimeType; mKCal::ExtendedCalendar::Ptr iCalendar; mKCal::ExtendedStorage::Ptr iStorage; }; #endif // NOTESBACKEND_H buteo-sync-plugins-0.8.36/storageplugins/hnotes/NotesStorage.cpp000066400000000000000000000216501476033560700250650ustar00rootroot00000000000000/* * This file is part of buteo-sync-plugins package * * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). * Copyright (C) 2013 - 2021 Jolla Ltd. * * Contact: Sateesh Kavuri * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * */ #include "NotesStorage.h" #include #include #include #include "SyncMLPluginLogging.h" #include "SyncMLCommon.h" #include "SyncMLConfig.h" // @todo: Because CalendarMaemo does not support batched operations ( or it does // but we can't use it as we cannot retrieve the id's of committed items ), // batched operations are currently done in series. const char* CTCAPSFILENAME11 = "CTCaps_notes_11.xml"; const char* CTCAPSFILENAME12 = "CTCaps_notes_12.xml"; const char* STORAGE_NOTEBOOK_PROP = "Notebook Name"; const char* DEFAULT_TYPE = "text/plain"; const char* DEFAULT_TYPE_VERSION = "1.0"; const char* DEFAULT_NOTEBOOK = "Personal"; const char* DEFAULT_NOTEBOOK_NAME = "myNotebook"; NotesStorage::NotesStorage( const QString& aPluginName ) : Buteo::StoragePlugin( aPluginName ), iCommitNow( true ) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); } NotesStorage::~NotesStorage() { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); } bool NotesStorage::init( const QMap& aProperties ) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); iProperties = aProperties; iProperties[STORAGE_SYNCML_CTCAPS_PROP_11] = getCTCaps( CTCAPSFILENAME11 ); iProperties[STORAGE_SYNCML_CTCAPS_PROP_12] = getCTCaps( CTCAPSFILENAME12 ); // Use remote name (e.g. bt name) as notebook name. if(iProperties.contains(Buteo::KEY_REMOTE_NAME)) { qCDebug(lcSyncMLPlugin) << "Using remote name as notebook name"; iProperties[STORAGE_NOTEBOOK_PROP] = iProperties.value(Buteo::KEY_REMOTE_NAME); } else if( iProperties.value( STORAGE_NOTEBOOK_PROP ).isEmpty() ) { qCWarning(lcSyncMLPlugin) << STORAGE_NOTEBOOK_PROP << " property not found" << "for notes storage, using default of" << DEFAULT_NOTEBOOK_NAME; iProperties[STORAGE_NOTEBOOK_PROP] = DEFAULT_NOTEBOOK_NAME; } qCDebug(lcSyncMLPlugin) << "Initializing notes, notebook name:" << iProperties[STORAGE_NOTEBOOK_PROP]; if( iProperties.value( STORAGE_DEFAULT_MIME_PROP ).isEmpty() ) { qCWarning(lcSyncMLPlugin) << STORAGE_DEFAULT_MIME_PROP << "property not found" << "for notes storage, using default of" << DEFAULT_TYPE; iProperties[STORAGE_DEFAULT_MIME_PROP] = DEFAULT_TYPE; } if( iProperties.value( STORAGE_DEFAULT_MIME_VERSION_PROP ).isEmpty() ) { qCWarning(lcSyncMLPlugin) << STORAGE_DEFAULT_MIME_VERSION_PROP << " property not found" <<"for notes storage, using default of" << DEFAULT_TYPE_VERSION; iProperties[STORAGE_DEFAULT_MIME_VERSION_PROP] = DEFAULT_TYPE_VERSION; } if( iProperties.value( STORAGE_NOTEBOOK_PROP ).isEmpty() ) { qCWarning(lcSyncMLPlugin) << STORAGE_NOTEBOOK_PROP << " property not found" << "for notes storage, using default of" << DEFAULT_NOTEBOOK; iProperties[STORAGE_NOTEBOOK_PROP] = DEFAULT_NOTEBOOK; } return iBackend.init( iProperties[STORAGE_NOTEBOOK_PROP], iProperties[Buteo::KEY_NOTES_UUID], iProperties[STORAGE_DEFAULT_MIME_PROP] ); } bool NotesStorage::uninit() { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); return iBackend.uninit(); } bool NotesStorage::getAllItems( QList& aItems ) { return iBackend.getAllNotes( aItems ); } bool NotesStorage::getAllItemIds( QList& aItemIds ) { return iBackend.getAllNoteIds( aItemIds ); } bool NotesStorage::getNewItems( QList& aNewItems, const QDateTime& aTime ) { return iBackend.getNewNotes( aNewItems, normalizeTime( aTime ) ); } bool NotesStorage::getNewItemIds( QList& aNewItemIds, const QDateTime& aTime ) { return iBackend.getNewNoteIds( aNewItemIds, normalizeTime( aTime ) ); } bool NotesStorage::getModifiedItems( QList& aModifiedItems, const QDateTime& aTime ) { return iBackend.getModifiedNotes( aModifiedItems, normalizeTime( aTime ) ); } bool NotesStorage::getModifiedItemIds( QList& aModifiedItemIds, const QDateTime& aTime ) { return iBackend.getModifiedNoteIds( aModifiedItemIds, normalizeTime( aTime ) ); } bool NotesStorage::getDeletedItemIds( QList& aDeletedItemIds, const QDateTime& aTime ) { return iBackend.getDeletedNoteIds( aDeletedItemIds, normalizeTime( aTime ) ); } Buteo::StorageItem* NotesStorage::newItem() { return iBackend.newItem(); } QList NotesStorage::getItems( const QStringList& aItemIdList ) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); QList items; QStringListIterator itr( aItemIdList ); while( itr.hasNext() ) { items.append( iBackend.getItem( itr.next() ) ); } return items; } Buteo::StorageItem* NotesStorage::getItem( const QString& aItemId ) { return iBackend.getItem( aItemId ); } Buteo::StoragePlugin::OperationStatus NotesStorage::addItem( Buteo::StorageItem& aItem ) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); if( iBackend.addNote( aItem, iCommitNow ) ) { return STATUS_OK; } else { return STATUS_ERROR; } } QList NotesStorage::addItems( const QList& aItems ) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); QList results; //Commit once at the end of the batch update iCommitNow = false; for( int i = 0; i < aItems.count(); ++i ) { results.append( addItem( *aItems[i] ) ); } iCommitNow = true; bool saved = iBackend.commitChanges(); Q_UNUSED( saved ); return results; } Buteo::StoragePlugin::OperationStatus NotesStorage::modifyItem( Buteo::StorageItem& aItem ) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); if( iBackend.modifyNote( aItem, iCommitNow ) ) { return STATUS_OK; } else { return STATUS_ERROR; } } QList NotesStorage::modifyItems( const QList& aItems ) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); QList results; //Commit once at the end of the batch update iCommitNow = false; for( int i = 0; i < aItems.count(); ++i ) { results.append( modifyItem( *aItems[i] ) ); } iCommitNow = true; bool saved = iBackend.commitChanges(); Q_UNUSED( saved ); return results; } Buteo::StoragePlugin::OperationStatus NotesStorage::deleteItem( const QString& aItemId ) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); if( iBackend.deleteNote( aItemId, iCommitNow ) ) { return STATUS_OK; } else { return STATUS_ERROR; } } QList NotesStorage::deleteItems( const QList& aItemIds ) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); QList results; //Commit once at the end of the batch update iCommitNow = false; for( int i = 0; i < aItemIds.count(); ++i ) { results.append( deleteItem( aItemIds[i] ) ); } iCommitNow = true; bool saved = iBackend.commitChanges(); Q_UNUSED( saved ); return results; } QDateTime NotesStorage::normalizeTime( const QDateTime& aTime ) const { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); QDateTime normTime = aTime; QTime time = aTime.time(); time.setHMS( time.hour(), time.minute(), time.second(), 0 ); normTime.setTime( time ); normTime = normTime.toUTC(); return normTime; } QByteArray NotesStorage::getCTCaps( const QString& aFilename ) const { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); QFile ctCapsFile( SyncMLConfig::getXmlDataPath() + aFilename ); QByteArray ctCaps; if( ctCapsFile.open(QIODevice::ReadOnly)) { ctCaps = ctCapsFile.readAll(); ctCapsFile.close(); } else { qCWarning(lcSyncMLPlugin) << "Failed to open CTCaps file for notes storage:" << aFilename; } return ctCaps; } Buteo::StoragePlugin* NotesStoragePluginLoader::createPlugin(const QString& aPluginName) { return new NotesStorage(aPluginName); } buteo-sync-plugins-0.8.36/storageplugins/hnotes/NotesStorage.h000066400000000000000000000106641476033560700245350ustar00rootroot00000000000000/* * This file is part of buteo-sync-plugins package * * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). * Copyright (C) 2013 - 2021 Jolla Ltd. * * Contact: Sateesh Kavuri * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * */ #ifndef NOTESSTORAGE_H #define NOTESSTORAGE_H #include "NotesBackend.h" #include #include #include /*! \brief Harmattan notes storage plugin * * */ class NotesStorage : public Buteo::StoragePlugin { public: /*! \brief Constructor * * @param aPluginName aPluginName Name of the plugin */ NotesStorage( const QString& aPluginName ); /*! \brief Destructor * */ virtual ~NotesStorage(); /*! \see StoragePlugin::init() * */ virtual bool init( const QMap& aProperties ); /*! \see StoragePlugin::uninit() * */ virtual bool uninit(); /*! \see StoragePlugin::getAllItems() * */ virtual bool getAllItems( QList& aItems ); /*! \see StoragePlugin::getAllItemIds() * */ virtual bool getAllItemIds( QList& aItemIds ); /*! \see StoragePlugin::getNewItems() * */ virtual bool getNewItems( QList& aNewItems, const QDateTime& aTime ); /*! \see StoragePlugin::getNewItemIds() * */ virtual bool getNewItemIds( QList& aNewItemIds, const QDateTime& aTime ); /*! \see StoragePlugin::getModifiedItems() * */ virtual bool getModifiedItems( QList& aModifiedItems, const QDateTime& aTime ); /*! \see StoragePlugin::getModifiedItemIds() * */ virtual bool getModifiedItemIds( QList& aModifiedItemIds, const QDateTime& aTime ); /*! \see StoragePlugin::getDeletedItemIds() * */ virtual bool getDeletedItemIds( QList& aDeletedItemIds, const QDateTime& aTime ); /*! \see StoragePlugin::newItem() * */ virtual Buteo::StorageItem* newItem(); /*! \see StoragePlugin::getItem() * */ virtual Buteo::StorageItem* getItem( const QString& aItemId ); /*! \see StoragePlugin::getItems() * */ virtual QList getItems( const QStringList& aItemIdList ); /*! \see StoragePlugin::addItem() * */ virtual OperationStatus addItem( Buteo::StorageItem& aItem ); /*! \see StoragePlugin::addItems() * */ virtual QList addItems( const QList& aItems ); /*! \see StoragePlugin::modifyItem() * */ virtual OperationStatus modifyItem( Buteo::StorageItem& aItem ); /*! \see StoragePlugin::modifyItems() * */ virtual QList modifyItems( const QList& aItems ); /*! \see StoragePlugin::deleteItem() * */ virtual OperationStatus deleteItem( const QString& aItemId ); /*! \see StoragePlugin::deleteItems() * */ virtual QList deleteItems( const QList& aItemIds ); protected: private: QDateTime normalizeTime( const QDateTime& aTime ) const; QByteArray getCTCaps( const QString& aFilename ) const; NotesBackend iBackend; bool iCommitNow; }; class NotesStoragePluginLoader : public Buteo::StoragePluginLoader { Q_OBJECT Q_PLUGIN_METADATA(IID "com.buteo.plugins.storage.NotesStoragePluginLoader") Q_INTERFACES(Buteo::StoragePluginLoader) public: /*! \brief Creates notes storage plugin * * @param aPluginName Human-readable name for plugin * @return Notes storage plugin instance */ Buteo::StoragePlugin* createPlugin(const QString& aPluginName) override; }; #endif // NOTESSTORAGE_H buteo-sync-plugins-0.8.36/storageplugins/hnotes/hnotes.pro000066400000000000000000000014751476033560700237710ustar00rootroot00000000000000TEMPLATE = lib TARGET = hnotes-storage DEPENDPATH += . INCLUDEPATH += . ../../syncmlcommon LIBS += -L../../syncmlcommon CONFIG += link_pkgconfig plugin PKGCONFIG = buteosyncfw5 KF5CalendarCore libmkcal-qt5 LIBS += -lsyncmlcommon5 target.path = $$[QT_INSTALL_LIBS]/buteo-plugins-qt5 VER_MAJ = 1 VER_MIN = 0 VER_PAT = 0 QT -= gui #input HEADERS += NotesStorage.h \ NotesBackend.h \ SOURCES += NotesStorage.cpp \ NotesBackend.cpp \ QMAKE_CXXFLAGS = -Wall \ -g \ -Wno-cast-align \ -O2 -finline-functions #clean QMAKE_CLEAN += $(TARGET) $(TARGET0) $(TARGET1) $(TARGET2) QMAKE_CLEAN += $(OBJECTS_DIR)/*.gcda $(OBJECTS_DIR)/*.gcno $(OBJECTS_DIR)/*.gcov $(OBJECTS_DIR)/moc_* ctcaps.path =/etc/buteo/xml/ ctcaps.files=xml/CTCaps_notes_11.xml xml/CTCaps_notes_12.xml INSTALLS += target ctcaps buteo-sync-plugins-0.8.36/storageplugins/hnotes/unittest/000077500000000000000000000000001476033560700236175ustar00rootroot00000000000000buteo-sync-plugins-0.8.36/storageplugins/hnotes/unittest/NotesTest.cpp000066400000000000000000000222751476033560700262630ustar00rootroot00000000000000/* * This file is part of buteo-sync-plugins package * * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). * Copyright (C) 2014 Jolla Ltd. * * Contributors: Sateesh Kavuri * Valério Valério * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * */ #include "NotesTest.h" #include #include void NotesTest::initTestCase() { iNotesStorage = new NotesStorage("hnotes"); QMap props; QVERIFY( iNotesStorage->init( props) ); } void NotesTest::cleanupTestCase() { QVERIFY( iNotesStorage->uninit() ); delete iNotesStorage; } void NotesTest::testSuite() { const QByteArray originalData( "I'm a note" ); const QByteArray modifiedData( "I'm a modified note" ); runTestSuite( originalData, modifiedData); } void NotesTest::runTestSuite(const QByteArray& aOriginalData, const QByteArray& aModifiedData) { QByteArray data; qDebug() << "Starting suite..."; // Get timestamp of 1 seconds in the past. Storages have timestamp accuracy of 1 seconds and // the current second is NOT included in getNewItems(), getModifiedItems() and getDeletedItems() QDateTime t1 = QDateTime::currentDateTime(); qDebug() << "Marking time t1:" << t1; QTest::qSleep( 2000 ); // ** Test New Item Buteo::StorageItem* item = iNotesStorage->newItem(); QVERIFY( item ); QCOMPARE( item->getId(), QString( "" ) ); // ** Test Add Item QVERIFY( item->write( 0, aOriginalData ) ); QVERIFY( item->getSize() == aOriginalData.size() ); QVERIFY( item->read( 0, item->getSize(), data ) ); QVERIFY( data == aOriginalData ); qDebug() << "Adding new item..."; Buteo::StoragePlugin::OperationStatus status = iNotesStorage->addItem( *item ); QVERIFY( status == Buteo::StoragePlugin::STATUS_OK ); QVERIFY( !item->getId().isEmpty() ); QString id = item->getId(); QTest::qSleep( 2000 ); QDateTime t2 = QDateTime::currentDateTime(); qDebug() << "Marking time t2:" << t2; QTest::qSleep( 2000 ); // ** Check that item is now found from all items qDebug() << "Checking that the item is now found from getItems()..."; QList items; QVERIFY( iNotesStorage->getAllItemIds( items ) ); bool found = false; for( int i = 0; i < items.count(); ++i ) { if( items[i] == id ) { found = true; break; } } QVERIFY( found ); items.clear(); // ** Check that item is now found from new items at t1 qDebug() << "Checking that the item is found from getNewItems(t1)..."; QVERIFY( iNotesStorage->getNewItemIds( items, t1 ) ); found = false; for( int i = 0; i < items.count(); ++i ) { if( items[i] == id ) { found = true; break; } } items.clear(); QVERIFY( found ); // ** Check that item is not found from new items at t2 qDebug() << "Checking that the item is NOT found from getNewItems(t2)..."; // @todo: There's no mechanism in storage plugin API for error handling, // therefore we can't check if this call failed or not QVERIFY( iNotesStorage->getNewItemIds( items, t2 ) ); found = false; for( int i = 0; i < items.count(); ++i ) { if( items[i] == id ) { found = true; break; } } items.clear(); QVERIFY( !found ); // ** Test Modify Item QVERIFY( item->write( 0, aModifiedData ) ); QVERIFY( item->getSize() == aModifiedData.size() ); QVERIFY( item->read( 0, item->getSize(), data ) ); QVERIFY( data == aModifiedData ); qDebug() << "Modifying item..."; status = iNotesStorage->modifyItem( *item ); QVERIFY( status == Buteo::StoragePlugin::STATUS_OK ); QVERIFY( item->getId() == id ); delete item; QTest::qSleep( 2000 ); QDateTime t3 = QDateTime::currentDateTime(); qDebug() << "Marking time t3:" << t3; QTest::qSleep( 2000 ); // ** Check that item is still found from new items at t1 qDebug() << "Checking that the item is found from getNewItems(t1)..."; QVERIFY( iNotesStorage->getNewItemIds( items, t1 ) ); found = false; for( int i = 0; i < items.count(); ++i ) { if( items[i] == id ) { found = true; break; } } items.clear(); QVERIFY( found ); // ** Check that item is not found from modified items at t1 qDebug() << "Checking that the item is NOT found from getModifiedItems(t1)..."; QVERIFY( iNotesStorage->getModifiedItemIds( items, t1 ) ); found = false; for( int i = 0; i < items.count(); ++i ) { if( items[i] == id ) { found = true; break; } } items.clear(); QVERIFY( !found ); // ** Check that item is now found from modified items at t2 qDebug() << "Checking that the item is found from getModifiedItems(t2)..."; QVERIFY( iNotesStorage->getModifiedItemIds( items, t2 ) ); found = false; for( int i = 0; i < items.count(); ++i ) { if( items[i] == id ) { found = true; break; } } items.clear(); QVERIFY( found ); // ** Check that item is not found from modified items at t3 qDebug() << "Checking that the item is NOT found from getModifiedItems(t3)..."; QVERIFY( iNotesStorage->getModifiedItemIds( items, t3 ) ); found = false; for( int i = 0; i < items.count(); ++i ) { if( items[i] == id ) { found = true; break; } } items.clear(); QVERIFY( !found ); // ** Test Delete Item qDebug() << "Deleting item..."; QVERIFY( iNotesStorage->deleteItem( id ) == Buteo::StoragePlugin::STATUS_OK ); // ** Check that item is no longer found from new items at t1 qDebug() << "Checking that the item is NOT found from getNewItems(t1)..."; QVERIFY( iNotesStorage->getNewItemIds( items, t1 ) ); found = false; for( int i = 0; i < items.count(); ++i ) { if( items[i] == id ) { found = true; break; } } items.clear(); QVERIFY( !found ); // ** Check that item is not found from modified items at t1 qDebug() << "Checking that the item is NOT found from getModifiedItems(t1)..."; QVERIFY( iNotesStorage->getModifiedItemIds( items, t1 ) ); found = false; for( int i = 0; i < items.count(); ++i ) { if( items[i] == id ) { found = true; break; } } items.clear(); QVERIFY( !found ); // ** Check that item is not found from deleted items at t1 qDebug() << "Checking that the item is NOT found from getDeletedItems(t1)..."; QVERIFY( iNotesStorage->getDeletedItemIds( items, t1 ) ); found = false; for( int i = 0; i < items.count(); ++i ) { if( items[i] == id ) { found = true; break; } } items.clear(); QVERIFY( !found ); // ** Check that item is no longer found from modified items at t2 qDebug() << "Checking that the item is NOT found from getModifiedItems(t2)..."; QVERIFY( iNotesStorage->getModifiedItemIds( items, t2 ) ); found = false; for( int i = 0; i < items.count(); ++i ) { if( items[i] == id ) { found = true; break; } } items.clear(); QVERIFY( !found ); // ** Check that item is now found from deleted items at t2 qDebug() << "Checking that the item is now found from getDeletedItems(t2)..."; QVERIFY( iNotesStorage->getDeletedItemIds( items, t2 ) ); found = false; for( int i = 0; i < items.count(); ++i ) { if( items[i] == id ) { found = true; break; } } items.clear(); QVERIFY( found ); // ** Check that item is now found from deleted items at t3 qDebug() << "Checking that the item is found from getDeletedItems(t3)..."; QVERIFY( iNotesStorage->getDeletedItemIds( items, t3 ) ); found = false; for( int i = 0; i < items.count(); ++i ) { if( items[i] == id ) { found = true; break; } } items.clear(); QVERIFY( found ); // ** Check that item is no longer found from all items qDebug() << "Checking that the item is NOT found from getItems()..."; QVERIFY( iNotesStorage->getAllItemIds( items ) ); found = false; for( int i = 0; i < items.count(); ++i ) { if( items[i] == id ) { found = true; break; } } items.clear(); QVERIFY( !found ); } QTEST_MAIN(NotesTest) buteo-sync-plugins-0.8.36/storageplugins/hnotes/unittest/NotesTest.h000066400000000000000000000025171476033560700257250ustar00rootroot00000000000000/* * This file is part of buteo-sync-plugins package * * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). * Copyright (C) 2014 Jolla Ltd. * * Contributors: Sateesh Kavuri * Valério Valério * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * */ #ifndef NOTESTEST_H #define NOTESTEST_H #include #include "NotesStorage.h" class NotesTest : public QObject { Q_OBJECT private slots: void initTestCase(); void cleanupTestCase(); void testSuite(); private: void runTestSuite( const QByteArray& aOriginalData, const QByteArray& aModifiedData); NotesStorage *iNotesStorage; }; #endif // NOTESTEST_H buteo-sync-plugins-0.8.36/storageplugins/hnotes/unittest/run-test000077500000000000000000000035301476033560700253270ustar00rootroot00000000000000#/* # * This file is part of buteo-sync-plugins package # * # * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). # * # * Contact: Sateesh Kavuri # * # * This library is free software; you can redistribute it and/or # * modify it under the terms of the GNU Lesser General Public License # * version 2.1 as published by the Free Software Foundation. # * # * This library is distributed in the hope that it will be useful, but # * WITHOUT ANY WARRANTY; without even the implied warranty of # * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # * Lesser General Public License for more details. # * # * You should have received a copy of the GNU Lesser General Public # * License along with this library; if not, write to the Free Software # * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA # * 02110-1301 USA # * # */ # echo "Building Unit Tests for Notes Storage" #clean sbox cache export SBOX_USE_CCACHE=no ccache -c qmake make clean make -j2 if [ -f unit_test_results.txt ]; then rm unit_test_results.txt fi echo "Running unit tests ...results will be stored in $PWD/unit_test_results.txt" # pre-conditions to run the tests .... #sb-conf killall #meego-run #source /tmp/session_bus_address.user;export DISPLAY=:1 #/usr/lib/tracker/tracker-store & > /dev/null #clear the tracker data base before running tests #tracker-control -r > /dev/null ./hnotes-tests >> unit_test_results.txt 2>&1 if [ -f gcov_results.txt ]; then rm gcov_results.txt fi # it is easy and convenient to add required files here becuase # the plugins are small and are not really that large when # compared to stack echo "Running gcov ... results will be stored in $PWD/gcov_results.txt" gcov NotesStorage.gcno >> gcov_results.txt 2>&1 gcov NotesBackend.gcno >> gcov_results.txt 2>&1 make distclean > /dev/null rm *.gcov buteo-sync-plugins-0.8.36/storageplugins/hnotes/unittest/unittest.pro000066400000000000000000000031611476033560700262210ustar00rootroot00000000000000#/* # * This file is part of buteo-sync-plugins package # * # * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). # * # * Contact: Sateesh Kavuri # * # * This library is free software; you can redistribute it and/or # * modify it under the terms of the GNU Lesser General Public License # * version 2.1 as published by the Free Software Foundation. # * # * This library is distributed in the hope that it will be useful, but # * WITHOUT ANY WARRANTY; without even the implied warranty of # * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # * Lesser General Public License for more details. # * # * You should have received a copy of the GNU Lesser General Public # * License along with this library; if not, write to the Free Software # * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA # * 02110-1301 USA # * # */ # TEMPLATE = app TARGET = hnotes-tests DEPENDPATH += . \ ../ \ VPATH = .. \ ../../../ INCLUDEPATH += . \ ../ \ ../../../syncmlcommon LIBS += -L../../../syncmlcommon HEADERS += NotesTest.h \ NotesStorage.h \ NotesBackend.h \ syncmlcommon/SimpleItem.h \ syncmlcommon/SyncMLConfig.h \ syncmlcommon/SyncMLCommon.h SOURCES += NotesTest.cpp \ NotesStorage.cpp \ NotesBackend.cpp \ syncmlcommon/SimpleItem.cpp \ syncmlcommon/SyncMLConfig.cpp QT += testlib QT -= gui CONFIG += link_pkgconfig PKGCONFIG = buteosyncfw5 KF5CalendarCore libmkcal-qt5 LIBS += -lsyncmlcommon5 target.path = /opt/tests/buteo-sync-plugins/ INSTALLS += target buteo-sync-plugins-0.8.36/storageplugins/hnotes/xml/000077500000000000000000000000001476033560700225405ustar00rootroot00000000000000buteo-sync-plugins-0.8.36/storageplugins/hnotes/xml/CTCaps_notes_11.xml000066400000000000000000000002141476033560700261050ustar00rootroot00000000000000 text/plain Note chr buteo-sync-plugins-0.8.36/storageplugins/hnotes/xml/CTCaps_notes_12.xml000066400000000000000000000003631476033560700261130ustar00rootroot00000000000000 text/plain 1.0 Note chr 0 Note buteo-sync-plugins-0.8.36/storageplugins/storageplugins.pro000066400000000000000000000012611476033560700242300ustar00rootroot00000000000000TEMPLATE = subdirs hcalendar.subdir = hcalendar hcalendar.target = sub-hcalendar hcalendar_tests.subdir = hcalendar/unittest hcalendar_tests.target = sub-hcalendar-tests hcalendar_tests.depends = sub-hcalendar hcontacts.subdir = hcontacts hcontacts.target = sub-hcontacts hcontacts_tests.subdir = hcontacts/unittest hcontacts_tests.target = sub-hcontacts-tests hcontacts_tests.depends = sub-hcontacts hnotes.subdir = hnotes hnotes.target = sub-hnotes hnotes_tests.subdir = hnotes/unittest hnotes_tests.target = sub-hnotes-tests hnotes_tests.depends = sub-hnotes SUBDIRS += \ hcalendar \ hcalendar_tests \ hcontacts \ hcontacts_tests \ hnotes \ hnotes_tests buteo-sync-plugins-0.8.36/syncmlcommon/000077500000000000000000000000001476033560700201105ustar00rootroot00000000000000buteo-sync-plugins-0.8.36/syncmlcommon/DeviceInfo.cpp000066400000000000000000000150041476033560700226270ustar00rootroot00000000000000/* * This file is part of buteo-sync-plugins package * * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). * * Contact: Sateesh Kavuri * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * */ #include "DeviceInfo.h" #include "SyncMLPluginLogging.h" #include #include #include using namespace Buteo; const QString XML_KEY_MANUFACTURER("Manufacturer"); const QString XML_KEY_MODEL("Model"); const QString XML_KEY_OEM("OEM"); const QString XML_KEY_HW_VER("HwVersion"); const QString XML_KEY_SW_VER("SwVersion"); const QString XML_KEY_FW_VER("FwVersion"); const QString XML_KEY_ID("Id"); const QString XML_KEY_DEV_TYPE("DeviceType"); const QString IMEI("IMEI:"); const QString DUMMY_IMEI("000000000000000"); const QString DEVINFO_DEVTYPE("phone"); Buteo::DeviceInfo::DeviceInfo() { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); iProperties << XML_KEY_MANUFACTURER << XML_KEY_MODEL << XML_KEY_HW_VER << XML_KEY_SW_VER << XML_KEY_FW_VER << XML_KEY_ID << XML_KEY_DEV_TYPE; iSource = ReadFromSystem; } Buteo::DeviceInfo::~DeviceInfo() { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); } QString Buteo::DeviceInfo::getDeviceIMEI() { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); /// @todo returning first IMEI for now; needs fixing on multisim devices return IMEI + deviceInfo.imeiNumbers().value(0, QString()); } QString Buteo::DeviceInfo::getManufacturer() { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); return deviceInfo.manufacturer(); } QString Buteo::DeviceInfo::getModel() { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); return deviceInfo.model(); } QString Buteo::DeviceInfo::getSwVersion() { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); return deviceInfo.osVersion(); } QString Buteo::DeviceInfo::getHwVersion() { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); //Empty now return iHwVersion; } QString Buteo::DeviceInfo::getFwVersion() { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); return getSwVersion(); } QString Buteo::DeviceInfo::getDeviceType() { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); if( iDeviceType.isEmpty()) { iDeviceType = DEVINFO_DEVTYPE; } return iDeviceType; } void Buteo::DeviceInfo::setSourceToRead(Source &aSource) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); iSource = aSource; } Buteo::DeviceInfo::Source Buteo::DeviceInfo::getSourceToRead() { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); return iSource; } bool Buteo::DeviceInfo::setDeviceXmlFile(QString &aFileName) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); QFile file(aFileName); bool status = false; if(file.exists()) { iDeviceInfoFile = aFileName; status = true; } return status; } QString Buteo::DeviceInfo::DeviceXmlFile() { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); return iDeviceInfoFile; } QMap Buteo::DeviceInfo::getDeviceInformation() { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); QMap deviceMap; switch(iSource) { case ReadFromSystem: foreach(const QString& property,iProperties) { if(property == XML_KEY_MANUFACTURER) { deviceMap.insert(property,getManufacturer()); }else if (property == XML_KEY_MODEL) { deviceMap.insert(property,getModel()); }else if (property == XML_KEY_SW_VER){ deviceMap.insert(property,getSwVersion()); }else if (property == XML_KEY_HW_VER) { deviceMap.insert(property,getHwVersion()); } else if (property == XML_KEY_FW_VER) { deviceMap.insert(property,getFwVersion()); }else if(property == XML_KEY_ID) { deviceMap.insert(property,getDeviceIMEI()); } else if (property == XML_KEY_DEV_TYPE){ deviceMap.insert(property,getDeviceType()); } else { qCDebug(lcSyncMLPlugin) << "Unknown Property:" << property; } } break; case ReadFromXml: { QFile file(iDeviceInfoFile); if(file.open(QIODevice::ReadOnly)) { QByteArray data = file.readAll(); QXmlStreamReader reader(data); while(!reader.atEnd()) { if(reader.tokenType() == QXmlStreamReader::StartElement) { if(reader.name() == "DevInfo" ) { reader.readNext(); } else { QString key = reader.name().toString(); reader.readNext(); deviceMap.insert(key,reader.text().toString()); reader.readNext(); } } reader.readNext(); } file.close(); } else { qCDebug(lcSyncMLPlugin) << "Failed to open the file " << iDeviceInfoFile; } } break; default: qCDebug(lcSyncMLPlugin) << "Source to read the system information is not set "; break; } return deviceMap; } void Buteo::DeviceInfo::saveDevInfoToFile(QMap &aDevInfo , QString &aFileName) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); QByteArray data; QXmlStreamWriter writer(&data); writer.setAutoFormatting(true); writer.writeStartDocument(); writer.writeStartElement("DevInfo"); // @TODO - add a DTD QMapIterator i(aDevInfo); while (i.hasNext()) { i.next(); qCDebug(lcSyncMLPlugin) << i.key() << ": " << i.value(); writer.writeTextElement(i.key(),i.value()); } writer.writeEndElement(); writer.writeEndDocument(); QFile file(aFileName); if(file.open(QIODevice::WriteOnly | QIODevice::Truncate)) { file.write(data); file.close(); } } buteo-sync-plugins-0.8.36/syncmlcommon/DeviceInfo.h000066400000000000000000000067221476033560700223030ustar00rootroot00000000000000/* * This file is part of buteo-sync-plugins package * * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). * * Contact: Sateesh Kavuri * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * */ #ifndef DEFAULTDEVICEINFO_H #define DEFAULTDEVICEINFO_H #include #include #include #include #include namespace Buteo { /*! \brief Default Implementation of DeviceInfo class * */ class DeviceInfo { public: //! getDeviceInformation call checks this enum enum Source { //! read from system ReadFromSystem, //! read from xml ReadFromXml }; /*! \brief Constructor * */ DeviceInfo(); /*! \brief Destructor * */ virtual ~DeviceInfo(); /*! \brief set properties to read from the devicse * * This API sets the source to read from * @return none */ void setSourceToRead(Source &); /*! \brief get method for source * * @return Source */ Source getSourceToRead(); /*! \brief set the file path to read device information from * * This API sets the xml file on the system * from where the device info has to be read from * @return value of the QFile exists method */ bool setDeviceXmlFile(QString &fileName); /*! \brief get the file name from where the device information is read from * * get method * @return value of the fileName set */ QString DeviceXmlFile(); /*! \brief Retrieves Device Information as Map * * This API reads the device information as per the respective implementation * @return key , value Map */ QMap getDeviceInformation(); /*! \brief Saves Device Information to the filename * * This API saves the device information to the file */ void saveDevInfoToFile(QMap &aDevInfo , QString &aFileName); protected: private: Source iSource; QStringList iProperties; QString iDeviceInfoFile; QString iManufacturer; QString iModel; QString iSwVersion; QString iHwVersion; QString iFwVersion; QString iDeviceIMEI; QString iDeviceType; QString getManufacturer(); QString getModel(); QString getSwVersion(); QString getHwVersion(); QString getFwVersion(); QString getDeviceIMEI(); QString getDeviceType(); ::DeviceInfo deviceInfo; #ifdef SYNC_APP_UNITTESTS friend class DeviceInfoTest; #endif }; } #endif // DEFAULTDEVICEINFO_H buteo-sync-plugins-0.8.36/syncmlcommon/FolderItemParser.cpp000066400000000000000000000073111476033560700240250ustar00rootroot00000000000000/* * This file is part of buteo-sync-plugins package * * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). * * Contact: Sateesh Kavuri * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * */ #include "FolderItemParser.h" #include "SyncMLPluginLogging.h" #include static const QString TAG_FOLDER("Folder"); static const QString TAG_FOLDER_NAME("name"); static const QString TAG_FOLDER_CREATED("created"); static const QString TAG_FOLDER_MODIFIED("modified"); static const QString DATE_TIME_FORMAT("yyyyMMddThhmmssZ"); const QString FolderItemParser::FOLDER_MIME_TYPE("application/vnd.omads-folder+xml"); bool FolderItemParser::readFolderData(const QByteArray &aRawData, FolderData &aFolderData) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); QDomDocument doc; if (!doc.setContent(aRawData)) return false; QDomElement root = doc.documentElement(); if (root.tagName() != TAG_FOLDER) return false; QDomElement name = root.firstChildElement(TAG_FOLDER_NAME); if (name.isNull()) return false; aFolderData.iName = name.text(); QDomElement created = root.firstChildElement(TAG_FOLDER_CREATED); if (!created.isNull()) { aFolderData.iCreated = parseDateTime(created.text()); } QDomElement modified = root.firstChildElement(TAG_FOLDER_MODIFIED); if (!modified.isNull()) { aFolderData.iModified = parseDateTime(modified.text()); } return true; } QByteArray FolderItemParser::writeFolderData(const FolderData &aFolderData) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); QDomDocument doc; QDomElement root = doc.createElement(TAG_FOLDER); doc.appendChild(root); QDomElement name = doc.createElement(TAG_FOLDER_NAME); root.appendChild(name); name.appendChild(doc.createTextNode(aFolderData.iName)); if (!aFolderData.iCreated.isNull()) { QDomElement created = doc.createElement(TAG_FOLDER_CREATED); root.appendChild(created); created.appendChild(doc.createTextNode(encodeDateTime(aFolderData.iCreated))); } if (!aFolderData.iModified.isNull()) { QDomElement modified = doc.createElement(TAG_FOLDER_MODIFIED); root.appendChild(modified); modified.appendChild(doc.createTextNode(encodeDateTime(aFolderData.iModified))); } return doc.toByteArray(2); // Indent = 2 } QDateTime FolderItemParser::parseDateTime(const QString &aDateTime) { QDateTime dateTime; if (aDateTime.endsWith('Z', Qt::CaseInsensitive)) { // UTC format. dateTime = QLocale::c().toDateTime(aDateTime, DATE_TIME_FORMAT); dateTime.setTimeSpec(Qt::UTC); dateTime = dateTime.toLocalTime(); } else { // Local time format. dateTime = QLocale::c().toDateTime(aDateTime, DATE_TIME_FORMAT.left(DATE_TIME_FORMAT.size() - 1)); dateTime.setTimeSpec(Qt::LocalTime); } return dateTime; } QString FolderItemParser::encodeDateTime(const QDateTime &aDateTime) { return QLocale::c().toString(aDateTime.toUTC(), DATE_TIME_FORMAT); } buteo-sync-plugins-0.8.36/syncmlcommon/FolderItemParser.h000066400000000000000000000046641476033560700235020ustar00rootroot00000000000000/* * This file is part of buteo-sync-plugins package * * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). * * Contact: Sateesh Kavuri * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * */ #ifndef FOLDERITEMPARSER_H #define FOLDERITEMPARSER_H #include #include /*! \brief Reads and writes data in application/vnd.omads-folder+xml format */ class FolderItemParser { public: //! Folder item MIME type. static const QString FOLDER_MIME_TYPE; //! Structure for storing folder data. struct FolderData { //! Name of the folder QString iName; //! Created Time QDateTime iCreated; //! Modified Time QDateTime iModified; }; /*! \brief Parses folder data from the provided byte array. * * @param aRawData Raw data in vnd.omads-folder-xml format. * @param aFolderData Parsed folder data. * @return Success indicator. */ static bool readFolderData(const QByteArray &aRawData, FolderData &aFolderData); /*! \brief Writes folder data to a byte array. * * @param aFolderData Folder data to write. * @return Folder data in vnd.omads-folder+xml format. */ static QByteArray writeFolderData(const FolderData &aFolderData); private: /*! \brief Parses date and time from the given string. * * @param aDateTime String containing the date and time. * @return Parsed date/time, specified using Qt::LocalTime. */ static QDateTime parseDateTime(const QString &aDateTime); /*! \brief Encodes date and time to a string in UTC format. * * @param aDateTime Date/time to encode. * @return Encoded date/time string. */ static QString encodeDateTime(const QDateTime &aDateTime); friend class FolderItemParserTest; }; #endif buteo-sync-plugins-0.8.36/syncmlcommon/ItemAdapter.cpp000066400000000000000000000032031476033560700230110ustar00rootroot00000000000000/* * This file is part of buteo-sync-plugins package * * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). * * Contact: Sateesh Kavuri * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * */ #include "ItemAdapter.h" #include ItemAdapter::ItemAdapter( Buteo::StorageItem* aItem ) : iItem( aItem ) { } ItemAdapter::~ItemAdapter() { delete iItem; iItem = NULL; } bool ItemAdapter::isValid() { if( iItem ) { return true; } else { return false; } } Buteo::StorageItem& ItemAdapter::getItem() const { return *iItem; } qint64 ItemAdapter::getSize() const { return iItem->getSize(); } bool ItemAdapter::read( qint64 aOffset, qint64 aLength, QByteArray& aData ) const { return iItem->read( aOffset, aLength, aData ); } bool ItemAdapter::write( qint64 aOffset, const QByteArray& aData ) { return iItem->write( aOffset, aData ); } bool ItemAdapter::resize( qint64 aLen ) { return iItem->resize( aLen ); } buteo-sync-plugins-0.8.36/syncmlcommon/ItemAdapter.h000066400000000000000000000042341476033560700224630ustar00rootroot00000000000000/* * This file is part of buteo-sync-plugins package * * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). * * Contact: Sateesh Kavuri * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * */ #ifndef ITEMADAPTER_H #define ITEMADAPTER_H #include namespace Buteo { class StorageItem; } /*! \brief Adapter to adapt framework storage item to SyncML stack sync item * */ class ItemAdapter : public DataSync::SyncItem { public: /*! \brief Constructor * * @param aItem Item that this instance should adapt. Ownership transferred */ ItemAdapter( Buteo::StorageItem* aItem ); /*! \brief Destructor * */ virtual ~ItemAdapter(); /*! \brief Returns if this adapter instance is valid * * @return True if this adapter instance is valid, otherwise false */ bool isValid(); /*! \brief Return the FW item instance * * @return Item * */ Buteo::StorageItem& getItem() const; /*! \see DataSync::SyncItem::getSize() * */ virtual qint64 getSize() const; /*! \see DataSync::SyncItem::read() * */ virtual bool read( qint64 aOffset, qint64 aLength, QByteArray& aData ) const; /*! \see DataSync::SyncItem::write() * */ virtual bool write( qint64 aOffset, const QByteArray& aData ); /*! \see DataSync::SyncItem::resize() * */ virtual bool resize( qint64 aLen ); protected: private: Buteo::StorageItem* iItem; }; #endif // ITEMADAPTER_H buteo-sync-plugins-0.8.36/syncmlcommon/ItemIdMapper.cpp000066400000000000000000000133401476033560700231350ustar00rootroot00000000000000/* * This file is part of buteo-sync-plugins package * * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). * * Contact: Sateesh Kavuri * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * */ #include "ItemIdMapper.h" #include "SyncMLPluginLogging.h" const QString CONNECTIONNAME( "idmapper" ); ItemIdMapper::ItemIdMapper() : iNextValue(1) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); } ItemIdMapper::~ItemIdMapper() { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); } bool ItemIdMapper::init( const QString& aDbFile, const QString& aStorageId ) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); static unsigned connectionNumber = 0; qCDebug(lcSyncMLPlugin) << "Initiating ID mapper..."; if( !iDb.isOpen() ) { iConnectionName = CONNECTIONNAME + QString::number( connectionNumber++ ); iDb = QSqlDatabase::addDatabase( "QSQLITE", iConnectionName ); iDb.setDatabaseName( aDbFile ); if(!iDb.open()) { //CID 29154 qCCritical(lcSyncMLPlugin) << "Could open ID database file:" << aDbFile; return false; } } iStorageId = aStorageId; QString queryString; QSqlQuery query; queryString.append( "CREATE TABLE if not exists " ); queryString.append( iStorageId ); queryString.append(" (value integer primary key, key varchar(512))" ); query = QSqlQuery( queryString, iDb ); if( !query.exec() ) { qCCritical(lcSyncMLPlugin) << "Create Query failed: " << query.lastError(); return false; } // Load the key,value pairs in memory queryString.clear(); queryString.append( "SELECT key, value FROM " ); queryString.append( iStorageId ); query = QSqlQuery( queryString, iDb ); if( query.exec() ) { while( query.next() ) { iKeyToValueMap[query.value(0).toString()] = query.value(1).toUInt(); iValueToKeyMap[query.value(1).toUInt()] = query.value(0).toString(); qCDebug(lcSyncMLPlugin) << "Mapped key " << query.value(0).toString() << " and value " << query.value(1).toString(); } iNextValue = iKeyToValueMap.count() + 1; } qCDebug(lcSyncMLPlugin) << "ID mapper initiated"; return true; } void ItemIdMapper::uninit() { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); qCDebug(lcSyncMLPlugin) << "Uninitiating ID mapper..."; { QString queryString; QSqlQuery query; bool supportsTransaction = iDb.transaction(); if( !supportsTransaction ) { qCDebug(lcSyncMLPlugin) << "Db doesn't support transactions"; } queryString.append( "DELETE FROM " ); queryString.append( iStorageId ); query = QSqlQuery( queryString, iDb ); if( !query.exec() ) { qCWarning(lcSyncMLPlugin) << "Delete Query failed: " << query.lastError(); } queryString.clear(); queryString.append( "INSERT INTO " ); queryString.append( iStorageId ); queryString.append( " (value, key) values(:values, :key)" ); query = QSqlQuery( queryString, iDb ); QVariantList keys, values; for( int i = 0; i < iValueToKeyMap.count(); ++i ) { values << (i + 1); keys << iValueToKeyMap[i+1]; } query.addBindValue( values ); query.addBindValue( keys ); if( !query.execBatch() ) { qCCritical(lcSyncMLPlugin) << "Save Query failed: " << query.lastError(); } if( supportsTransaction ) { if( !iDb.commit() ) { qCCritical(lcSyncMLPlugin) << "Commit failed"; } } } iDb.close(); iDb = QSqlDatabase(); QSqlDatabase::removeDatabase( iConnectionName ); iNextValue = 1; qCDebug(lcSyncMLPlugin) << "ID mapper uninitiated"; } QString ItemIdMapper::key( const QString& aValue ) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); // NB#153991:In case SyncML stack asks for empty key, we shouldn't treat // it as an error situation, rather just not do mapping in that case. QString key = aValue; if( !iValueToKeyMap.contains( aValue.toUInt() ) ) { qCDebug(lcSyncMLPlugin) << "Value is empty, mapping not done"; } else { key = iValueToKeyMap.value( aValue.toUInt() ); } return key; } QString ItemIdMapper::value( const QString& aKey ) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); QString value = aKey; // If the key is already an integer, no mapping is needed. bool keyIsInt; int id = aKey.toInt(&keyIsInt); Q_UNUSED(id); if (aKey.isEmpty()) { qCWarning(lcSyncMLPlugin) << "Key is empty. Not trying to do mapping"; } else if( !keyIsInt ) { if( !iKeyToValueMap.contains( aKey ) ) { value = add( aKey ); } else { value = QString::number( iKeyToValueMap.value( aKey ) ); } } return value; } QString ItemIdMapper::add( const QString &aKey ) { iKeyToValueMap[aKey] = iNextValue; iValueToKeyMap[iNextValue] = aKey; return QString::number( iNextValue++ ); } buteo-sync-plugins-0.8.36/syncmlcommon/ItemIdMapper.h000066400000000000000000000045211476033560700226030ustar00rootroot00000000000000/* * This file is part of buteo-sync-plugins package * * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). * * Contact: Sateesh Kavuri * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * */ #ifndef ITEMIDMAPPER_H #define ITEMIDMAPPER_H #include #include /*! \brief Storage for persistently mapping ID's supplied by storage plugins to * formats suitable for remote SyncML parties * */ class ItemIdMapper { public: /*! \brief Constructor * */ ItemIdMapper(); /*! \brief Destructor * */ virtual ~ItemIdMapper(); /*! \brief Initializes ID mapper for storage * * @param aDbFile Path to database to use as persistent storage * @param aStorageId Identifier for storage * @return True if successfully initialized, otherwise false */ bool init( const QString& aDbFile, const QString& aStorageId ); /*! \brief Uninitializes ID mapper for storage * */ void uninit(); /*! \brief Maps the specified value to key * * @param aValue Value * @return Key */ QString key( const QString& aValue ); /*! \brief Maps the specified key to value * * @param aKey Key * @return Value */ QString value( const QString& aKey ); protected: /*! \brief Adds a new key * * @param aKey Key * @return Mapped value */ QString add( const QString &aKey ); private: QSqlDatabase iDb; QString iConnectionName; QString iStorageId; QMap iKeyToValueMap; QMap iValueToKeyMap; quint32 iNextValue; friend class ItemIdMapperTest; }; #endif // ITEMIDMAPPER_H buteo-sync-plugins-0.8.36/syncmlcommon/SimpleItem.cpp000066400000000000000000000026361476033560700226730ustar00rootroot00000000000000/* * This file is part of buteo-sync-plugins package * * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). * * Contact: Sateesh Kavuri * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * */ #include "SimpleItem.h" SimpleItem::SimpleItem() { } SimpleItem::~SimpleItem() { } bool SimpleItem::write( qint64 aOffset, const QByteArray& aData ) { iData.resize( aOffset + aData.size() ); iData.replace( aOffset, aData.size(), aData ); return true; } bool SimpleItem::read( qint64 aOffset, qint64 aLength, QByteArray& aData ) const { aData = iData.mid( aOffset, aLength ); return true; } bool SimpleItem::resize( qint64 aLen ) { iData.resize( aLen ); return true; } qint64 SimpleItem::getSize() const { return iData.size(); } buteo-sync-plugins-0.8.36/syncmlcommon/SimpleItem.h000066400000000000000000000034421476033560700223340ustar00rootroot00000000000000/* * This file is part of buteo-sync-plugins package * * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). * * Contact: Sateesh Kavuri * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * */ #ifndef SIMPLEITEM_H #define SIMPLEITEM_H #include #include /*! \brief Simple implementation for storage item * * This implementation can be used when data of the item is so small in size * that it can be cached in memory */ class SimpleItem : public Buteo::StorageItem { public: /*! \brief Constructor * */ SimpleItem(); /*! \brief Destructor * */ virtual ~SimpleItem(); /*! \see StorageItem::write() * */ virtual bool write( qint64 aOffset, const QByteArray& aData ); /*! \see StorageItem::read() * */ virtual bool read( qint64 aOffset, qint64 aLength, QByteArray& aData ) const; /*! \see StorageItem::resize() * */ virtual bool resize( qint64 aLen ); /*! \see StorageItem::getSize() * */ virtual qint64 getSize() const; protected: private: QByteArray iData; }; #endif // SIMPLEITEM_H buteo-sync-plugins-0.8.36/syncmlcommon/StorageAdapter.cpp000066400000000000000000000311621476033560700235240ustar00rootroot00000000000000/* * This file is part of buteo-sync-plugins package * * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). * * Contact: Sateesh Kavuri * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * */ #include "StorageAdapter.h" #include #include #include "SyncMLCommon.h" #include "ItemAdapter.h" #include "SyncMLConfig.h" #include "SyncMLPluginLogging.h" // Database file for SyncML storage adapter database #define ADAPTERDBFILE "syncmladapter.db" StorageAdapter::StorageAdapter( Buteo::StoragePlugin* aPlugin ) : iPlugin( aPlugin ) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); } StorageAdapter::~StorageAdapter() { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); } bool StorageAdapter::isValid() { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); if( iPlugin ) { return true; } else { return false; } } bool StorageAdapter::init() { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); // ** Process properties from client/server plugin // ** Process properties from storage plugin QMap pluginProperties; iPlugin->getProperties( pluginProperties ); qCDebug(lcSyncMLPlugin) << "StorageAdapter: dumping storage properties:"; qCDebug(lcSyncMLPlugin) << pluginProperties; // Preferred format QString preferredFormat = pluginProperties.value( STORAGE_DEFAULT_MIME_PROP ); QString preferredVersion = pluginProperties.value( STORAGE_DEFAULT_MIME_VERSION_PROP ); if( preferredFormat.isEmpty() || preferredVersion.isEmpty() ) { qCCritical(lcSyncMLPlugin) << "No STORAGE_DEFAULT_MIME_PROP or STORAGE_DEFAULT_MIME_VERSION_PROP" <<"found for storage: " << iPlugin->getPluginName(); return false; } // Currently we support only one format per storage DataSync::ContentFormat format; format.iType = preferredFormat; format.iVersion = preferredVersion; iFormats.setPreferredRx( format ); iFormats.setPreferredTx( format ); iFormats.rx().append( format ); iFormats.tx().append( format ); // Source URI iSourceDB = pluginProperties.value( STORAGE_SOURCE_URI ); if( iSourceDB.isEmpty() ) { qCCritical(lcSyncMLPlugin) << "No STORAGE_SOURCE_URI prop found for storage: " << iPlugin->getPluginName(); return false; } // Target URI iTargetDB = pluginProperties[STORAGE_REMOTE_URI]; // ** Own initialization iType = preferredFormat; QString dbFilePath = SyncMLConfig::getDatabasePath() + ADAPTERDBFILE; iIdMapper.init( dbFilePath, iPlugin->getPluginName() ); return true; } bool StorageAdapter::uninit() { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); iIdMapper.uninit(); return true; } Buteo::StoragePlugin* StorageAdapter::getPlugin() const { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); return iPlugin; } const QString& StorageAdapter::getSourceURI() const { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); return iSourceDB; } const DataSync::StorageContentFormatInfo& StorageAdapter::getFormatInfo() const { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); return iFormats; } qint64 StorageAdapter::getMaxObjSize() const { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); // Max object size not supported at the moment return 0; } QByteArray StorageAdapter::getPluginCTCaps( DataSync::ProtocolVersion aVersion ) const { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); Q_ASSERT( iPlugin ); if( aVersion == DataSync::SYNCML_1_1 ) { return iPlugin->getProperty( STORAGE_SYNCML_CTCAPS_PROP_11 ).toLatin1(); } else if( aVersion == DataSync::SYNCML_1_2 ) { return iPlugin->getProperty( STORAGE_SYNCML_CTCAPS_PROP_12 ).toLatin1(); } else { Q_ASSERT( 0 ); return ""; } } QByteArray StorageAdapter::getPluginExts() const { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); Q_ASSERT( iPlugin ); return iPlugin->getProperty( STORAGE_SYNCML_EXTENSIONS ).toLatin1(); } bool StorageAdapter::getAll( QList& aKeys ) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); QList newKeys; if (!iPlugin->getAllItemIds( newKeys )) { return false; } foreach (const QString &key, newKeys) { aKeys.append(iIdMapper.value(key)); } return true; } bool StorageAdapter::getModifications( QList& aNewKeys, QList& aReplacedKeys, QList& aDeletedKeys, const QDateTime& aTimeStamp ) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); QList newKeys; QList replacedKeys; QList deletedKeys; if( !iPlugin->getNewItemIds( newKeys, aTimeStamp ) || !iPlugin->getModifiedItemIds( replacedKeys, aTimeStamp ) || !iPlugin->getDeletedItemIds( deletedKeys, aTimeStamp ) ) { return false; } for( int i = 0; i < newKeys.count(); ++i ) { aNewKeys.append( iIdMapper.value( newKeys[i] ) ); } for( int i = 0; i < replacedKeys.count(); ++i ) { aReplacedKeys.append( iIdMapper.value( replacedKeys[i] ) ); } for( int i = 0; i < deletedKeys.count(); ++i ) { aDeletedKeys.append( iIdMapper.value( deletedKeys[i] ) ); } return true; } DataSync::SyncItem* StorageAdapter::newItem() { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); Buteo::StorageItem* item = iPlugin->newItem(); if( item ) { ItemAdapter* adapter = new ItemAdapter( item ); adapter->setKey( "" ); adapter->setType( iType ); return adapter; } else { return NULL; } } DataSync::SyncItem* StorageAdapter::getSyncItem( const DataSync::SyncItemKey& aKey ) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); QString id = iIdMapper.key( aKey ); Buteo::StorageItem* item = iPlugin->getItem( id ); if( item ) { ItemAdapter* adapter = new ItemAdapter( item ); adapter->setKey( aKey ); adapter->setType( item->getType() ); QString version = item->getVersion(); if (!version.isEmpty()) { adapter->setVersion(version); } if( !item->getParentId().isEmpty() ) { adapter->setParentKey( iIdMapper.value( item->getParentId() ) ); } return adapter; } else { return NULL; } } QList StorageAdapter::getSyncItems( const QList& aKeyList ) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); QStringList idList; QList::const_iterator i; for( i = aKeyList.constBegin(); i != aKeyList.constEnd(); ++i) { idList.append( iIdMapper.key( *i ) ); } QList items = iPlugin->getItems( idList ); QList adapters; QList::const_iterator j; for( j = items.constBegin(); j != items.constEnd(); ++j) { if( *j ) { ItemAdapter* adapter = new ItemAdapter( *j ); adapter->setKey( iIdMapper.value( (*j)->getId() ) ); adapter->setType( (*j)->getType() ); QString version = (*j)->getVersion(); if (!version.isEmpty()) { adapter->setVersion(version); } if( !(*j)->getParentId().isEmpty() ) { adapter->setParentKey( iIdMapper.value( (*j)->getParentId() ) ); } adapters.append( adapter ); } else { adapters.append( NULL ); } } return adapters; } QList StorageAdapter::addItems( const QList& aItems ) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); QList results; QList items; for( int i = 0; i < aItems.count(); ++i ) { items.append( toStorageItem( aItems[i] ) ); } QList< Buteo::StoragePlugin::OperationStatus > operations; if( aItems.count() ) { operations = iPlugin->addItems( items ); } for( int i = 0; i < operations.count(); ++i ) { StoragePlugin::StoragePluginStatus status = convertStatus( operations[i] ); if( status == STATUS_OK ) { QString mappedId = iIdMapper.value( items[i]->getId() ); ItemAdapter* adapter = static_cast( aItems[i] ); adapter->setKey( mappedId ); } results.append( status ); } return results; } QList StorageAdapter::replaceItems( const QList& aItems ) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); QList results; QList items; // There is no need to do item id mapping here, as the StorageItems always have their correct id's. // Only ItemAdapter houses mapped id's. for( int i = 0; i < aItems.count(); ++i ) { items.append( toStorageItem( aItems[i] ) ); } QList< Buteo::StoragePlugin::OperationStatus > operations; if( aItems.count() ) { operations = iPlugin->modifyItems( items ); } for( int i = 0; i < operations.count(); ++i ) { StoragePlugin::StoragePluginStatus status = convertStatus( operations[i] ); if( status == STATUS_OK ) { QString mappedId = iIdMapper.value( items[i]->getId() ); ItemAdapter* adapter = static_cast( aItems[i] ); adapter->setKey( mappedId ); } results.append( status ); } return results; } QList StorageAdapter::deleteItems( const QList& aKeys ) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); QList ids; QList results; // aKeys houses mapped id's, so they must be converted back to actual item id's for( int i = 0; i < aKeys.count(); ++i ) { ids.append( iIdMapper.key( aKeys[i] ) ); } QList< Buteo::StoragePlugin::OperationStatus > operations; if( aKeys.count() ) { operations = iPlugin->deleteItems( ids ); } for( int i = 0; i < operations.count(); ++i ) { StoragePlugin::StoragePluginStatus status = convertStatus( operations[i] ); results.append( status ); } return results; } DataSync::StoragePlugin::StoragePluginStatus StorageAdapter::convertStatus( Buteo::StoragePlugin::OperationStatus aStatus ) const { StoragePlugin::StoragePluginStatus status; switch( aStatus ) { case Buteo::StoragePlugin::STATUS_OK: { status = STATUS_OK; break; } case Buteo::StoragePlugin::STATUS_NOT_FOUND: { status = STATUS_NOT_FOUND; break; } case Buteo::StoragePlugin::STATUS_DUPLICATE: { status = STATUS_DUPLICATE; break; } case Buteo::StoragePlugin::STATUS_OBJECT_TOO_BIG: { status = STATUS_OBJECT_TOO_BIG; break; } case Buteo::StoragePlugin::STATUS_STORAGE_FULL: { status = STATUS_STORAGE_FULL; break; } case Buteo::StoragePlugin::STATUS_INVALID_FORMAT: { status = STATUS_INVALID_FORMAT; break; } case Buteo::StoragePlugin::STATUS_ERROR: default: { status = STATUS_ERROR; break; } } return status; } Buteo::StorageItem* StorageAdapter::toStorageItem( const DataSync::SyncItem* aSyncItem ) const { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); const ItemAdapter* adapter = static_cast( aSyncItem ); Buteo::StorageItem& item = adapter->getItem(); item.setType( adapter->getType() ); item.setParentId( *adapter->getParentKey() ); item.setVersion( adapter->getVersion() ); return &item; } buteo-sync-plugins-0.8.36/syncmlcommon/StorageAdapter.h000066400000000000000000000116351476033560700231740ustar00rootroot00000000000000/* * This file is part of buteo-sync-plugins package * * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). * * Contact: Sateesh Kavuri * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * */ #ifndef STORAGEADAPTER_H #define STORAGEADAPTER_H #include #include #include #include #include #include #include "ItemIdMapper.h" class StoragePlugin; class StorageItem; /*! \brief Adapter to adapt framework storage plugin to SyncML stack storage * plugin * * This adapter presumes that all DataSync::SyncItem instances passed as parameters * to functions of this adapter are originally created by this adapter. */ class StorageAdapter : public DataSync::StoragePlugin { public: /*! \brief Constructor * * @param aPlugin Plugin that this instance should adapt. Not owned */ StorageAdapter( Buteo::StoragePlugin* aPlugin ); /*! \brief Destructor * */ virtual ~StorageAdapter(); /*! \brief Returns if this adapter instance is valid * * @return True if this adapter instance is valid, otherwise false */ bool isValid(); /*! \brief Returns the FW plugin instance * * @return Plugin */ Buteo::StoragePlugin* getPlugin() const; /*! \brief Initializes adapter * * Sets up SyncML storage plugin based on FW plugin properties * * @return True if initialization was successful, otherwise false */ bool init(); /*! \brief Uninitializes adapter * * @return True if uninitialization was successful, otherwise false */ bool uninit(); /*! \see DataSync::StoragePlugin::getSourceURI() * */ virtual const QString& getSourceURI() const; /*! \see DataSync::StoragePlugin::getSourceURI() * */ virtual const DataSync::StorageContentFormatInfo& getFormatInfo() const; /*! \see DataSync::StoragePlugin::getMaxObjSize() * */ virtual qint64 getMaxObjSize() const; /*! \see DataSync::StoragePlugin::getPluginCTCaps() * */ virtual QByteArray getPluginCTCaps( DataSync::ProtocolVersion aVersion ) const; /*! \see DataSync::StoragePlugin::getPluginExts() * */ virtual QByteArray getPluginExts() const; /*! \see DataSync::StoragePlugin::getAll() * */ virtual bool getAll( QList& aKeys ); /*! \see DataSync::StoragePlugin::getModifications() * */ virtual bool getModifications( QList& aNewKeys, QList& aReplacedKeys, QList& aDeletedKeys, const QDateTime& aTimeStamp ); /*! \see DataSync::StoragePlugin::newItem() * */ virtual DataSync::SyncItem* newItem(); /*! \see DataSync::StoragePlugin::getSyncItem() * */ virtual DataSync::SyncItem* getSyncItem( const DataSync::SyncItemKey& aKey ); /*! \see DataSync::StoragePlugin::getSyncItems() * */ virtual QList getSyncItems( const QList & aKeyList ); /*! \see DataSync::StoragePlugin::addItems() * */ virtual QList addItems( const QList& aItems ); /*! \see DataSync::StoragePlugin::replaceItems() * */ virtual QList replaceItems( const QList& aItems ); /*! \see DataSync::StoragePlugin::deleteItems() * */ virtual QList deleteItems( const QList& aKeys ); protected: private: DataSync::StoragePlugin::StoragePluginStatus convertStatus( Buteo::StoragePlugin::OperationStatus aStatus ) const; Buteo::StorageItem* toStorageItem( const DataSync::SyncItem* aSyncItem ) const; Buteo::StoragePlugin* iPlugin; QString iType; DataSync::StorageContentFormatInfo iFormats; QString iSourceDB; QString iTargetDB; ItemIdMapper iIdMapper; }; #endif // STORAGEADAPTER_H buteo-sync-plugins-0.8.36/syncmlcommon/SyncMLCommon.h000066400000000000000000000063741476033560700226110ustar00rootroot00000000000000/* * This file is part of buteo-sync-plugins package * * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). * * Contact: Sateesh Kavuri * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * */ #ifndef SYNCMLCOMMON_H #define SYNCMLCOMMON_H #include const QString PROPS_FALSE = "false"; const QString PROPS_TRUE = "true"; // Properties found from storage plug-ins that can be used to configure storage // adapter // Preferred MIME type const QString STORAGE_DEFAULT_MIME_PROP = "Type"; // Preferred MIME version const QString STORAGE_DEFAULT_MIME_VERSION_PROP = "Version"; // CTCaps for SyncML protocol const QString STORAGE_SYNCML_CTCAPS_PROP_11 = "CTCaps_SyncML11"; const QString STORAGE_SYNCML_CTCAPS_PROP_12 = "CTCaps_SyncML12"; // Extensions supported by plugin const QString STORAGE_SYNCML_EXTENSIONS = "Extensions"; // Properties found from server/client plug-ins that can be used to configure storage // adapter // SyncML Source URI to associate with a storage const QString STORAGE_SOURCE_URI = "Local URI"; // SyncML Target URI to associate with a storage const QString STORAGE_REMOTE_URI = "Target URI"; // Sync target to associate with a storage session const QString STORAGE_SYNC_TARGET = "Sync Target"; // Bluetooth storage sync target const QString STORAGE_SYNC_TARGET_BLUETOOTH = "bluetooth"; // ID of the origin data source to associate with a storage session const QString STORAGE_ORIGIN_ID = "Origin ID"; // Profile properties const QString PROF_SYNC_TRANSPORT = "Sync Transport"; const QString PROF_SYNC_PROTOCOL = "Sync Protocol"; const QString HTTP_TRANSPORT = "HTTP"; const QString OBEX_TRANSPORT = "OBEX"; const QString PROF_HTTP_PROXY_HOST = "http_proxy_host"; const QString PROF_HTTP_PROXY_PORT = "http_proxy_port"; const QString PROF_BT_ADDRESS = "bt_address"; const QString PROF_REMOTE_ADDRESS = "remote_id"; const QString PROF_BT_UUID = "bt_uuid"; const QString PROF_REMOTE_URI = "Remote database"; const QString PROF_USE_WBXML = "use_wbxml"; const QString PROF_PASSWD = "Password"; const QString PROF_USERID = "Username"; const QString SYNCML11 = "SyncML11"; const QString SYNCML12 = "SyncML12"; const QString PROF_HTTP_XHEADERS = "http_xheaders"; Q_DECLARE_LOGGING_CATEGORY(lcSyncMLPlugin) #endif // SYNCMLCOMMON_H buteo-sync-plugins-0.8.36/syncmlcommon/SyncMLConfig.cpp000066400000000000000000000035601476033560700231130ustar00rootroot00000000000000/* * This file is part of buteo-sync-plugins package * * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). * * Contact: Sateesh Kavuri * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * */ #include "SyncMLConfig.h" #include #include "SyncMLPluginLogging.h" #include "SyncCommonDefs.h" const QString XMLDIR( "/etc/buteo/xml/"); const QString DBDIR( "/sync-app/" ); const QString DEVINFO_FILE_NAME("devInfo.xml"); SyncMLConfig::SyncMLConfig() { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); } SyncMLConfig::~SyncMLConfig() { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); } QString SyncMLConfig::getDatabasePath() { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); QString path = Sync::syncConfigDir() + DBDIR; QDir dir( path ); dir.mkpath( path ); return path; } QString SyncMLConfig::getXmlDataPath() { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); return XMLDIR; } QString SyncMLConfig::getDevInfoFile() { return SyncMLConfig::getDatabasePath() + DEVINFO_FILE_NAME; } void SyncMLConfig::syncmlConfigFilePaths (QString& aDefaultConfigFile, QString& aExtConfigFile) { aDefaultConfigFile = "/etc/buteo/meego-syncml-conf.xml"; aExtConfigFile = "/etc/buteo/ext-syncml-conf.xml"; } buteo-sync-plugins-0.8.36/syncmlcommon/SyncMLConfig.h000066400000000000000000000037511476033560700225620ustar00rootroot00000000000000/* * This file is part of buteo-sync-plugins package * * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). * * Contact: Sateesh Kavuri * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * */ #ifndef SYNCMLCONFIG_H #define SYNCMLCONFIG_H #include /*! \brief Common configuration class for SyncML related things * */ class SyncMLConfig { public: /*! \brief Constructor * */ SyncMLConfig(); /*! \brief Destructor * */ ~SyncMLConfig(); /*! \brief Returns path that should be used for storing * databases * */ static QString getDatabasePath(); /*! \brief Returns path that stores misc xml data */ static QString getXmlDataPath(); /*! \brief Returns file used to store the device information * * @return QString - contains the full path to the file. */ static QString getDevInfoFile(); /*! \brief Returns the config XML files for configuring SyncML stack * * @param aDefaultConfigFile - the default config file, out parameter * @param aExtConfigFile - the extended properties config file, out parameter * @return void */ static void syncmlConfigFilePaths (QString& aDefaultConfigFile, QString& aExtConfigFile); protected: private: static QString getHomePath(); }; #endif // SYNCMLCONFIG_H buteo-sync-plugins-0.8.36/syncmlcommon/SyncMLPluginLogging.cpp000066400000000000000000000017031476033560700244500ustar00rootroot00000000000000/* * This file is part of buteo-sync-plugins package * * Copyright (C) 2021 Jolla Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * */ #include "SyncMLPluginLogging.h" Q_LOGGING_CATEGORY(lcSyncMLPlugin, "buteo.syncml.plugin", QtWarningMsg) Q_LOGGING_CATEGORY(lcSyncMLPluginTrace, "buteo.syncml.plugin.trace", QtWarningMsg) buteo-sync-plugins-0.8.36/syncmlcommon/SyncMLPluginLogging.h000066400000000000000000000020031476033560700241070ustar00rootroot00000000000000/* * This file is part of buteo-sync-plugins package * * Copyright (C) 2021 Jolla Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * */ #ifndef SYNCMLPLUGINLOGGING_H #define SYNCMLPLUGINLOGGING_H #include #include Q_DECLARE_LOGGING_CATEGORY(lcSyncMLPlugin) Q_DECLARE_LOGGING_CATEGORY(lcSyncMLPluginTrace) #endif // SYNCMLPLUGINLOGGING_H buteo-sync-plugins-0.8.36/syncmlcommon/SyncMLStorageProvider.cpp000066400000000000000000000221461476033560700250260ustar00rootroot00000000000000/* * This file is part of buteo-sync-plugins package * * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). * * Contact: Sateesh Kavuri * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * */ #include "SyncMLStorageProvider.h" #include #include #include #include #include #include #include "SyncMLCommon.h" #include "StorageAdapter.h" #include "SyncMLPluginLogging.h" SyncMLStorageProvider::SyncMLStorageProvider() : iProfile( 0 ), iPlugin( 0 ), iCbInterface( 0 ), iRequestStorages( false ) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); } SyncMLStorageProvider::~SyncMLStorageProvider() { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); } bool SyncMLStorageProvider::init( Buteo::Profile* aProfile, Buteo::SyncPluginBase* aPlugin, Buteo::PluginCbInterface* aCbInterface, bool aRequestStorages ) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); if( !aProfile || !aPlugin || !aCbInterface ) { qCCritical(lcSyncMLPlugin) << "NULL parameters passed to init()"; return false; } iProfile = aProfile; iPlugin = aPlugin; iCbInterface = aCbInterface; iRequestStorages = aRequestStorages; return true; } bool SyncMLStorageProvider::uninit() { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); return true; } QString SyncMLStorageProvider::getPreferredURINames( const QString &aURI ) { Q_UNUSED(aURI); // TODO : Handle possible multiple URI names in storage profiles // One way to do this is to have separators for Local URI, like ./notes;./Notepad return QString(); } bool SyncMLStorageProvider::getStorageContentFormatInfo( const QString& aURI, DataSync::StorageContentFormatInfo& aInfo ) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); const Buteo::Profile* storageProfile = iProfile->subProfileByKeyValue( STORAGE_SOURCE_URI, aURI, Buteo::Profile::TYPE_STORAGE, true ); if( !storageProfile ) { qCDebug(lcSyncMLPlugin) << "Could not find storage for URI" << aURI; return false; } QString preferredFormat = storageProfile->key( STORAGE_DEFAULT_MIME_PROP ); QString preferredVersion = storageProfile->key( STORAGE_DEFAULT_MIME_VERSION_PROP ); // Currently we support only one format per storage DataSync::ContentFormat format; format.iType = preferredFormat; format.iVersion = preferredVersion; aInfo.setPreferredRx( format ); aInfo.setPreferredTx( format ); aInfo.rx().append( format ); aInfo.tx().append( format ); return true; } DataSync::StoragePlugin* SyncMLStorageProvider::acquireStorageByURI( const QString& aURI ) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); qCDebug(lcSyncMLPlugin) << "Incoming request to acquire storage by URI:" << aURI; #if 0 QString preferredURI = getPreferredURINames( aURI ); #endif const Buteo::Profile* storageProfile = iProfile->subProfileByKeyValue( STORAGE_SOURCE_URI, aURI, Buteo::Profile::TYPE_STORAGE, true ); if( !storageProfile ) { qCDebug(lcSyncMLPlugin) << "Could not find storage for URI" << aURI; return NULL; } qCDebug(lcSyncMLPlugin) << "Found storage for URI" << aURI << ":" << storageProfile->name(); return acquireStorage( storageProfile ); } DataSync::StoragePlugin* SyncMLStorageProvider::acquireStorageByMIME( const QString& aMIME ) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); qCDebug(lcSyncMLPlugin) << "Incoming request to acquire storage by MIME:" << aMIME; const Buteo::Profile* storageProfile = iProfile->subProfileByKeyValue( STORAGE_DEFAULT_MIME_PROP, aMIME, Buteo::Profile::TYPE_STORAGE, true ); if( !storageProfile ) { qCDebug(lcSyncMLPlugin) << "Could not find storage for MIME" << aMIME; return NULL; } qCDebug(lcSyncMLPlugin) << "Found storage for MIME" << aMIME << ":" << storageProfile->name(); return acquireStorage( storageProfile ); } void SyncMLStorageProvider::releaseStorage( DataSync::StoragePlugin* aStorage ) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); if (!aStorage) return; qCDebug(lcSyncMLPlugin) << "Incoming request to release storage with source URI" << aStorage->getSourceURI(); StorageAdapter* adapter = static_cast( aStorage ); if( !adapter->uninit() ) { qCWarning(lcSyncMLPlugin) << "Storage adapter uninitialization failed"; } Buteo::StoragePlugin* storage = adapter->getPlugin(); QString backend = storage->getProperty( Buteo::KEY_BACKEND ); if( !storage->uninit() ) { qCWarning(lcSyncMLPlugin) << "Storage uninitialization failed"; } iCbInterface->destroyStorage( storage ); if( iRequestStorages ) { iCbInterface->releaseStorage( backend, iPlugin ); } delete aStorage; } DataSync::StoragePlugin* SyncMLStorageProvider::acquireStorage( const Buteo::Profile* aProfile ) { FUNCTION_CALL_TRACE(lcSyncMLPluginTrace); if (!aProfile) return NULL; QString backend = aProfile->key( Buteo::KEY_BACKEND, aProfile->name() ); QString pluginName = aProfile->key( Buteo::KEY_PLUGIN, aProfile->name() ); QString uuid = iProfile->key(Buteo::KEY_UUID); QString remoteName = iProfile->key(Buteo::KEY_REMOTE_NAME); if(!uuid.isEmpty() && !remoteName.isEmpty()) { qCDebug(lcSyncMLPlugin) << "uuid and remote name fetched from profile" << uuid << remoteName; } if(!iUUID.isEmpty() && !iRemoteName.isEmpty()) { uuid = iUUID; remoteName = iRemoteName; qCDebug(lcSyncMLPlugin) << "uuid and remote name created on the fly" << uuid << remoteName; } if( iRequestStorages && !iCbInterface->requestStorage( backend, iPlugin ) ) { qCCritical(lcSyncMLPlugin) << "Could not reserve storage backend:" << backend; } Buteo::StoragePlugin* storage = iCbInterface->createStorage( pluginName ); if( !storage ) { iCbInterface->releaseStorage( backend, iPlugin ); qCDebug(lcSyncMLPlugin) << "Could not create storage:" << pluginName; return NULL; } // Make sure that the backend name that was used in storage reservation is // saved to the properties of storage plug-in. This name must be used again // when the storage backend is released. QMap keys = aProfile->allKeys(); keys.insert( Buteo::KEY_BACKEND, backend ); if(!uuid.isEmpty()) { keys.insert(Buteo::KEY_UUID, uuid); } if(!remoteName.isEmpty()) { keys.insert(Buteo::KEY_REMOTE_NAME, remoteName); } // Configure the storage syncTarget and originId if known if (!iProfile->key(Buteo::KEY_BT_ADDRESS).isEmpty()) { keys.insert(STORAGE_SYNC_TARGET, STORAGE_SYNC_TARGET_BLUETOOTH); keys.insert(STORAGE_ORIGIN_ID, iProfile->key(Buteo::KEY_BT_ADDRESS)); } // If protocol version is not defined in the keys read from profile, try to // read the version from the session handler and insert a corresponding key, // so that storage plug-in knows which protocol version is in use. if (!keys.contains(PROF_SYNC_PROTOCOL) && iSessionHandler != 0) { if (iSessionHandler->getProtocolVersion() == DataSync::SYNCML_1_1) { keys[PROF_SYNC_PROTOCOL] = SYNCML11; } else { keys[PROF_SYNC_PROTOCOL] = SYNCML12; } } if( !storage->init( keys ) ) { qCDebug(lcSyncMLPlugin) << "Could not initialize storage:" << pluginName; iCbInterface->destroyStorage( storage ); iCbInterface->releaseStorage( backend, iPlugin ); return NULL; } StorageAdapter* adapter = new StorageAdapter( storage ); if( !adapter->init() ) { qCDebug(lcSyncMLPlugin) << "Initialization of adapter for storage" << pluginName << "FAILED"; iCbInterface->destroyStorage( storage ); iCbInterface->releaseStorage( backend, iPlugin ); delete adapter; return NULL; } return adapter; } void SyncMLStorageProvider::setRemoteName(const QString& aRemoteName) { iRemoteName = aRemoteName; } void SyncMLStorageProvider::setUUID(const QString& aUUID) { iUUID = aUUID; } buteo-sync-plugins-0.8.36/syncmlcommon/SyncMLStorageProvider.h000066400000000000000000000074741476033560700245020ustar00rootroot00000000000000/* * This file is part of buteo-sync-plugins package * * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). * * Contact: Sateesh Kavuri * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * */ #ifndef SYNCMLSTORAGEPROVIDER_H #define SYNCMLSTORAGEPROVIDER_H #include namespace Buteo { class Profile; class SyncPluginBase; class PluginCbInterface; class SyncMLStorageProviderTest; } /*! \brief Module that provides storages to libmeegosyncml in syncml * client/server plugins * * This storage provider presumes that all DataSync::StoragePlugin instances * passed as parameters to function of this storage provider are originally * from this storage provider */ class SyncMLStorageProvider : public DataSync::StorageProvider { public: /*! \brief Constructor * */ SyncMLStorageProvider(); /*! \brief Destructor * */ virtual ~SyncMLStorageProvider(); /*! \brief Initializes the storage provider * * @param aProfile Profile with storage sub-profiles * @param aPlugin Plugin utilizing this storage provider * @param aCbInterface Callback interface to use to acquire and release storages * @param aRequestStorages If true, storage provider will request storages while creating them * @return True on success, otherwise false */ bool init( Buteo::Profile* aProfile, Buteo::SyncPluginBase* aPlugin, Buteo::PluginCbInterface* aCbInterface, bool aRequestStorages ); /*! \brief Uninitializes the storage provider * * @return True on success, otherwise false */ bool uninit(); /*! \see DataSync::StorageProvider::getStorageContentFormatInfo * */ virtual bool getStorageContentFormatInfo( const QString& aURI, DataSync::StorageContentFormatInfo& aInfo ); /*! \see DataSync::StorageProvider::acquireStorageByURI() * */ virtual DataSync::StoragePlugin* acquireStorageByURI( const QString& aURI ); /*! \see DataSync::StorageProvider::acquireStorageByMIME() * */ virtual DataSync::StoragePlugin* acquireStorageByMIME( const QString& aMIME ); /*! \see DataSync::StorageProvider::releaseStorage() * */ virtual void releaseStorage( DataSync::StoragePlugin* aStorage ); /*! \brief set the name of the remote party that initiated sync * * @param aRemoteName remote name */ void setRemoteName(const QString& aRemoteName); /*! \brief set a UUID for the remote party that initiated sync * * @param aRemoteUUID remote name */ void setUUID(const QString& aRemoteUUID); private: QString getPreferredURINames( const QString &aURI ); DataSync::StoragePlugin* acquireStorage( const Buteo::Profile* aProfile ); Buteo::Profile* iProfile; Buteo::SyncPluginBase* iPlugin; Buteo::PluginCbInterface* iCbInterface; bool iRequestStorages; QString iRemoteName; QString iUUID; friend class Buteo::SyncMLStorageProviderTest; }; #endif // SYNCMLSTORAGEPROVIDER_H buteo-sync-plugins-0.8.36/syncmlcommon/syncmlcommon.pro000066400000000000000000000031261476033560700233520ustar00rootroot00000000000000TEMPLATE = lib DEPENDPATH += . CONFIG += link_pkgconfig create_pc create_prl TARGET = syncmlcommon5 PKGCONFIG = buteosyncfw5 buteosyncml5 systemsettings QT += sql xml QT -= gui VER_MAJ = 1 VER_MIN = 0 VER_PAT = 0 #input HEADERS += ItemAdapter.h \ ItemIdMapper.h \ SimpleItem.h \ StorageAdapter.h \ SyncMLCommon.h \ SyncMLConfig.h \ SyncMLPluginLogging.h \ SyncMLStorageProvider.h \ FolderItemParser.h \ DeviceInfo.h SOURCES += ItemAdapter.cpp \ ItemIdMapper.cpp \ SimpleItem.cpp \ StorageAdapter.cpp \ SyncMLConfig.cpp \ SyncMLPluginLogging.cpp \ SyncMLStorageProvider.cpp \ FolderItemParser.cpp \ DeviceInfo.cpp QMAKE_CXXFLAGS = -Wall \ -g \ -Wno-cast-align \ -O2 -finline-functions #clean QMAKE_CLEAN += $(TARGET) QMAKE_CLEAN += $(OBJECTS_DIR)/*.gcda $(OBJECTS_DIR)/*.gcno $(OBJECTS_DIR)/*.gcov $(OBJECTS_DIR)/moc_* lib$${TARGET}.prl pkgconfig/* #install target.path = $$[QT_INSTALL_LIBS]/ headers.path = /usr/include/syncmlcommon/ headers.files = ItemAdapter.h \ ItemIdMapper.h \ SimpleItem.h \ StorageAdapter.h \ SyncMLCommon.h \ SyncMLConfig.h \ SyncMLStorageProvider.h \ FolderItemParser.h \ DeviceInfo.h INSTALLS += target headers QMAKE_PKGCONFIG_DESTDIR = pkgconfig QMAKE_PKGCONFIG_LIBDIR = $$target.path QMAKE_PKGCONFIG_INCDIR = $$headers.path QMAKE_PKGCONFIG_VERSION = $$VERSION pkgconfig.files = $${TARGET}.pc buteo-sync-plugins-0.8.36/syncmlcommon/unittest/000077500000000000000000000000001476033560700217675ustar00rootroot00000000000000buteo-sync-plugins-0.8.36/syncmlcommon/unittest/DeviceInfoTest.cpp000066400000000000000000000053761476033560700253610ustar00rootroot00000000000000/* * This file is part of buteo-sync-plugins package * * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). * * Contact: Sateesh Kavuri * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * */ #include #include "DeviceInfo.h" #include "DeviceInfoTest.h" using namespace Buteo; void DeviceInfoTest::initTestCase() { iDevInfo = new Buteo::DeviceInfo(); } void DeviceInfoTest::cleanupTestCase() { delete iDevInfo; } void DeviceInfoTest::testSourceToRead() { Buteo::DeviceInfo::Source source = Buteo::DeviceInfo::ReadFromXml; iDevInfo->setSourceToRead(source); QCOMPARE(iDevInfo->getSourceToRead(),Buteo::DeviceInfo::ReadFromXml); } void DeviceInfoTest::testSetDeviceXml() { QString file("test.xml"); QVERIFY(iDevInfo->setDeviceXmlFile(file)); } void DeviceInfoTest::testGetDeviceInformation() { QMap deviceMap; deviceMap = iDevInfo->getDeviceInformation(); QVERIFY(deviceMap.size() != 0); QCOMPARE(deviceMap.size(),4); } void DeviceInfoTest::testSaveDeviceInformation() { QString file("test.xml"); QMap deviceMap; deviceMap.insert("Id","1234567789"); deviceMap.insert("Model","N900"); deviceMap.insert("SwVersion","RX-blahblahblah"); deviceMap.insert("HwVErsion","0322"); iDevInfo->saveDevInfoToFile(deviceMap,file); } void DeviceInfoTest::testGetSysInfo() { QString dummy = iDevInfo->getSysInfo("/component/product-name"); QVERIFY(dummy.size() == 0); } void DeviceInfoTest::testGetDeviceIMEI() { QString imei = iDevInfo->getDeviceIMEI(); QVERIFY(!imei.isEmpty()); } void DeviceInfoTest::testGetSwVersion() { QString swver = iDevInfo->getSwVersion(); QVERIFY(swver.isEmpty()); } void DeviceInfoTest::testGetHwVersion() { QString hwver = iDevInfo->getHwVersion(); QVERIFY(hwver.isEmpty()); } void DeviceInfoTest::testGetFwVersion() { QString fwver = iDevInfo->getFwVersion(); QVERIFY(fwver.isEmpty()); } void DeviceInfoTest::testGetModel() { QString model = iDevInfo->getModel(); QVERIFY(model.isEmpty()); } void DeviceInfoTest::testGetDeviceType() { QString devType = iDevInfo->getDeviceType(); QVERIFY(!devType.isEmpty()); QVERIFY(devType == "phone" ); } buteo-sync-plugins-0.8.36/syncmlcommon/unittest/DeviceInfoTest.h000066400000000000000000000027271476033560700250230ustar00rootroot00000000000000/* * This file is part of buteo-sync-plugins package * * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). * * Contact: Sateesh Kavuri * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * */ #ifndef DEVICEINFOTEST_H_ #define DEVICEINFOTEST_H_ #include #include #include "DeviceInfo.h" namespace Buteo { class DeviceInfoTest: public QObject { Q_OBJECT private slots: void initTestCase(); void cleanupTestCase(); void testSaveDeviceInformation(); void testSourceToRead(); void testSetDeviceXml(); void testGetDeviceInformation(); void testGetSysInfo(); void testGetDeviceIMEI(); void testGetSwVersion(); void testGetHwVersion(); void testGetFwVersion(); void testGetModel(); void testGetDeviceType(); private: Buteo::DeviceInfo *iDevInfo; }; }; #endif /*DEVICEINFOTEST_H_*/ buteo-sync-plugins-0.8.36/syncmlcommon/unittest/FolderItemParserTest.cpp000066400000000000000000000057311476033560700265500ustar00rootroot00000000000000/* * This file is part of buteo-sync-plugins package * * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). * * Contact: Sateesh Kavuri * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * */ #include "FolderItemParserTest.h" //#include "FolderItemParser.cpp" void FolderItemParserTest::initTestCase() { } void FolderItemParserTest::cleanupTestCase() { } void FolderItemParserTest::testWriteFolderData() { FolderItemParser::FolderData folderData; FolderItemParser::FolderData fldrData; QByteArray byte; folderData.iName = "Parser"; QVERIFY(folderData.iCreated.isNull()); QVERIFY(folderData.iModified.isNull()); byte = iFolder.writeFolderData(folderData); //qDebug()<<"Byte is"< * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * */ #ifndef FOLDERITEMPARSERTEST_H_ #define FOLDERITEMPARSERTEST_H_ #include #include #include "FolderItemParser.h" class FolderItemParserTest: public QObject { Q_OBJECT private slots: void initTestCase(); void cleanupTestCase(); void testWriteFolderData(); void testReadFolderData(); public: FolderItemParser iFolder; }; #endif /*FOLDERITEMPARSERTEST_H_*/ buteo-sync-plugins-0.8.36/syncmlcommon/unittest/ItemAdapterTest.cpp000066400000000000000000000030211476033560700255260ustar00rootroot00000000000000/* * This file is part of buteo-sync-plugins package * * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). * * Contact: Sateesh Kavuri * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * */ #include #include "ItemAdapterTest.h" #include "SimpleItem.h" void ItemAdapterTest::initTestCase() { iItemAd = new ItemAdapter(0); QCOMPARE(iItemAd->isValid(), false); Buteo::StorageItem *storage = new SimpleItem(); iItemAd = new ItemAdapter(storage); QCOMPARE(iItemAd->isValid(), true); } void ItemAdapterTest::cleanupTestCase() { QVERIFY(iItemAd); delete iItemAd; iItemAd = 0; } void ItemAdapterTest::testReadWriteSize() { QByteArray byte("ItemAdapter"); QByteArray byte1; QCOMPARE(iItemAd->write(4, byte), true); QCOMPARE(iItemAd->getSize(),(qint64)(byte.size()+4)); QCOMPARE(iItemAd->read(4, -1, byte1), true); QVERIFY(byte1.contains("ItemAdapter")); } buteo-sync-plugins-0.8.36/syncmlcommon/unittest/ItemAdapterTest.h000066400000000000000000000022611476033560700252000ustar00rootroot00000000000000/* * This file is part of buteo-sync-plugins package * * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). * * Contact: Sateesh Kavuri * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * */ #ifndef ITEMADAPTERTEST_H_ #define ITEMADAPTERTEST_H_ #include #include #include "ItemAdapter.h" class ItemAdapterTest: public QObject { Q_OBJECT private slots: void initTestCase(); void cleanupTestCase(); void testReadWriteSize(); public: ItemAdapter *iItemAd; }; #endif /*ITEMADAPTERTEST_H_*/ buteo-sync-plugins-0.8.36/syncmlcommon/unittest/ItemIdMapperTest.cpp000066400000000000000000000050771476033560700256640ustar00rootroot00000000000000/* * This file is part of buteo-sync-plugins package * * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). * * Contact: Sateesh Kavuri * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * */ #include "ItemIdMapperTest.h" void ItemIdMapperTest::initTestCase() { iMapper = new ItemIdMapper(); QCOMPARE(iMapper->iRecursionGuard, false); } void ItemIdMapperTest::cleanupTestCase() { QVERIFY(iMapper); delete iMapper; iMapper = 0; } void ItemIdMapperTest::testInit() { QString DbFile; //= "/scratchbox/users/vineela/home/vineela/database.db"; QCOMPARE(iMapper->iDb.isOpen(), false); QCOMPARE(iMapper->init("database.db", "plugin"), true); QCOMPARE(iMapper->iDb.isOpen(), true); QCOMPARE(iMapper->iDb.isValid(), true); QCOMPARE(iMapper->iDb.connectionName(), QString("idmapper0")); QCOMPARE(iMapper->iDb.databaseName(), QString("database.db")); QCOMPARE(iMapper->iStorageId, QString("plugin")); } void ItemIdMapperTest::testKeyValueAdd() { //testing the function add(const QString& aKey) QCOMPARE(iMapper->iStorageId, QString("plugin")); QCOMPARE(iMapper->add("key"), QString("1")); QCOMPARE(iMapper->iRecursionGuard, false); //testing the function key(const QString& aValue) QString val = ""; QCOMPARE(val.isEmpty(), true); QCOMPARE(iMapper->key(val), val); QCOMPARE(iMapper->key("key"), QString("key")); //testing the function value(const QString& aValue) QCOMPARE(val.isEmpty(), true); QCOMPARE(iMapper->value(val), val); QCOMPARE(iMapper->value("key"), QString("1")); // Mapping id that is already an integer does nothing. QCOMPARE(iMapper->value("1234"), QString("1234")); QCOMPARE(iMapper->key("1234"), QString("1234")); } void ItemIdMapperTest::testUninit() { QStringList list = iMapper->iDb.tables(QSql::Tables); QVERIFY(list.contains("plugin")); iMapper->uninit(); QCOMPARE(iMapper->iDb.tables(QSql::Tables).isEmpty(), true); QCOMPARE(iMapper->iDb.isOpen(), false); } buteo-sync-plugins-0.8.36/syncmlcommon/unittest/ItemIdMapperTest.h000066400000000000000000000023321476033560700253200ustar00rootroot00000000000000/* * This file is part of buteo-sync-plugins package * * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). * * Contact: Sateesh Kavuri * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * */ #ifndef ITEMIDMAPPERTEST_H_ #define ITEMIDMAPPERTEST_H_ #include #include #include "ItemIdMapper.h" class ItemIdMapperTest: public QObject { Q_OBJECT private slots: void initTestCase(); void cleanupTestCase(); void testInit(); void testKeyValueAdd(); void testUninit(); public: ItemIdMapper *iMapper; }; #endif /*ITEMIDMAPPERTEST_H_*/ buteo-sync-plugins-0.8.36/syncmlcommon/unittest/SimpleItemTest.cpp000066400000000000000000000026051476033560700254060ustar00rootroot00000000000000/* * This file is part of buteo-sync-plugins package * * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). * * Contact: Sateesh Kavuri * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * */ #include "SimpleItemTest.h" void SimpleItemTest::initTestCase() { iSimple = new SimpleItem(); } void SimpleItemTest::cleanupTestCase() { QVERIFY(iSimple); delete iSimple; iSimple = 0; } void SimpleItemTest::testReadWriteSize() { QByteArray byte("SimpleItem"); QByteArray tempByte; QCOMPARE(iSimple->write(5, byte), true); QCOMPARE(iSimple->getSize(), (qint64)15); QCOMPARE(iSimple->read(5, -1, tempByte), true); QVERIFY(tempByte.contains("SimpleItem")); QCOMPARE(iSimple->resize(6), true); QCOMPARE(iSimple->getSize(), (qint64)6); } buteo-sync-plugins-0.8.36/syncmlcommon/unittest/SimpleItemTest.h000066400000000000000000000023001476033560700250430ustar00rootroot00000000000000/* * This file is part of buteo-sync-plugins package * * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). * * Contact: Sateesh Kavuri * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * */ #ifndef SIMPLEITEMTEST_H_ #define SIMPLEITEMTEST_H_ #include #include #include #include "SimpleItem.h" class SimpleItemTest: public QObject { Q_OBJECT private slots: void initTestCase(); void cleanupTestCase(); void testReadWriteSize(); public: SimpleItem *iSimple; }; #endif /*SIMPLEITEMTEST_H_*/ buteo-sync-plugins-0.8.36/syncmlcommon/unittest/SyncMLConfigTest.cpp000066400000000000000000000026121476033560700256270ustar00rootroot00000000000000/* * This file is part of buteo-sync-plugins package * * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). * * Contact: Sateesh Kavuri * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * */ #include "SyncMLConfigTest.h" void SyncMLConfigTest::initTestCase() { iConfig = new SyncMLConfig(); } void SyncMLConfigTest::cleanupTestCase() { QVERIFY(iConfig); delete iConfig; iConfig = 0; } void SyncMLConfigTest::testXmldatabasePath() { //testing the function getDatabasePath() QString DBDIR1 = Sync::syncDir(); QString home = QDir::homePath(); QString path = home + DBDIR1; QVERIFY(iConfig->getDatabasePath().contains(path)); //testing the function getXmlDataPath() QVERIFY(iConfig->getXmlDataPath().contains("/etc/buteo/xml/")); } buteo-sync-plugins-0.8.36/syncmlcommon/unittest/SyncMLConfigTest.h000066400000000000000000000022661476033560700253010ustar00rootroot00000000000000/* * This file is part of buteo-sync-plugins package * * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). * * Contact: Sateesh Kavuri * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * */ #ifndef SYNCMLCONFIGTEST_H_ #define SYNCMLCONFIGTEST_H_ #include #include #include "SyncMLConfig.h" class SyncMLConfigTest:public QObject { Q_OBJECT private slots: void initTestCase(); void cleanupTestCase(); void testXmldatabasePath(); public: SyncMLConfig *iConfig; }; #endif /*SYNCMLCONFIGTEST_H_*/ buteo-sync-plugins-0.8.36/syncmlcommon/unittest/SyncMLStorageProviderTest.cpp000066400000000000000000000111541476033560700275420ustar00rootroot00000000000000/* * This file is part of buteo-sync-plugins package * * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). * * Contact: Sateesh Kavuri * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * */ #include "SyncMLStorageProviderTest.h" #if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) #include #else #include #endif #include #include using namespace Buteo; void SyncMLStorageProviderTest :: initTestCase() { iSyncMLStorageProvider = new SyncMLStorageProvider(); iProfile = new Buteo::Profile("dummyprofile", Buteo::Profile::TYPE_STORAGE); iTempPluginCbInterface = new TempPluginCbInterface(); iTempSyncPluginBase = new TempSyncPluginBase(iTempPluginCbInterface); // call init() QVERIFY(iSyncMLStorageProvider->init(iProfile, iTempSyncPluginBase, iTempPluginCbInterface, true)); } void SyncMLStorageProviderTest :: cleanupTestCase() { // uninit() is always returning true QVERIFY(iSyncMLStorageProvider->uninit()); // deallocate the memory delete iSyncMLStorageProvider; delete iTempSyncPluginBase; delete iTempPluginCbInterface; delete iProfile; } void SyncMLStorageProviderTest :: testStorages() { // test acqurieStorage() & releaseStorage() without any sub profiles // acquireStorageByURI() & acquireStorageByMIME() internally calls acquireStorage() DataSync::StoragePlugin *uriStorage = iSyncMLStorageProvider->acquireStorageByURI("./contacts"); DataSync::StoragePlugin *mimeStorage = iSyncMLStorageProvider->acquireStorageByMIME("text/x-vcard"); QVERIFY(uriStorage == 0); QVERIFY(mimeStorage == 0); iSyncMLStorageProvider->releaseStorage(uriStorage); iSyncMLStorageProvider->releaseStorage(mimeStorage); // test acquireStorage() & releaseStorage() functions with sub profiles // create a profile from XML const QString profileXML = " " " " " " " " " " " " " " "" ""; QDomDocument doc; QVERIFY(doc.setContent(profileXML, false)); Profile anotherProfile(doc.documentElement()); anotherProfile.setName("anotherProfile"); SyncMLStorageProvider *tempSyncMLStorageProvider = new SyncMLStorageProvider(); tempSyncMLStorageProvider->init(&anotherProfile, iTempSyncPluginBase, iTempPluginCbInterface, true); uriStorage = tempSyncMLStorageProvider->acquireStorageByURI("./contacts"); QVERIFY(uriStorage); tempSyncMLStorageProvider->releaseStorage(uriStorage); mimeStorage = tempSyncMLStorageProvider->acquireStorageByMIME("text/x-vcard"); QVERIFY(mimeStorage); tempSyncMLStorageProvider->releaseStorage(mimeStorage); // deallocate memory tempSyncMLStorageProvider->uninit(); delete tempSyncMLStorageProvider; } /* ##################################### TempPluginCbInterface class functions ##################################### */ StoragePlugin* TempPluginCbInterface ::createStorage(const QString& aStorage) { StoragePlugin* plugin = NULL; QDir dir = QDir::current(); QString path = dir.absolutePath(); // need to replace the library path with dummy library path if (dir.cd("/usr/lib")) { path = dir.absolutePath(); } iPluginManager = new PluginManager(path) ; if (!aStorage.isEmpty()) plugin = iPluginManager->createStorage(aStorage); return plugin; } void TempPluginCbInterface ::destroyStorage(StoragePlugin *aStorage) { iPluginManager->destroyStorage(aStorage); delete iPluginManager; } buteo-sync-plugins-0.8.36/syncmlcommon/unittest/SyncMLStorageProviderTest.h000066400000000000000000000051071476033560700272100ustar00rootroot00000000000000/* * This file is part of buteo-sync-plugins package * * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). * * Contact: Sateesh Kavuri * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * */ #ifndef SYNCMLSTORAGEPROVIDERTEST_H #define SYNCMLSTORAGEPROVIDERTEST_H #include "SyncMLStorageProvider.h" #include #include #include #include namespace Buteo { class TempSyncPluginBase; class TempPluginCbInterface; class SyncMLStorageProviderTest : public QObject { Q_OBJECT private slots: void initTestCase(); void cleanupTestCase(); void testStorages(); private: SyncMLStorageProvider *iSyncMLStorageProvider; Buteo::Profile *iProfile; TempSyncPluginBase *iTempSyncPluginBase; TempPluginCbInterface *iTempPluginCbInterface; }; class TempSyncPluginBase :public SyncPluginBase { private: bool init(){return true;} bool uninit(){return true;} void connectivityStateChanged( Sync::ConnectivityType aType, bool aState ){Q_UNUSED(aType);Q_UNUSED(aState);} public: TempSyncPluginBase(PluginCbInterface *myPluginCbInterface) :SyncPluginBase("dummyPlugin", "dummyProfile", myPluginCbInterface){} }; class TempPluginCbInterface : public PluginCbInterface { public: bool requestStorage(const QString&, const SyncPluginBase *aCaller) {Q_UNUSED(aCaller);return true;} void releaseStorage(const QString&, const SyncPluginBase *aCaller) {Q_UNUSED(aCaller);} QString getDeviceIMEI() {return QString("0");} bool isConnectivityAvailable(Sync::ConnectivityType) {return true;} // defined in source file - required for creating & releasing storage StoragePlugin* createStorage(const QString&); void destroyStorage(StoragePlugin *aStorage); private: PluginManager *iPluginManager; }; } // end - Buteo namespace #endif // SYNCMLSTORAGEPROVIDERTEST_H buteo-sync-plugins-0.8.36/syncmlcommon/unittest/main.cpp000066400000000000000000000034761476033560700234310ustar00rootroot00000000000000/* * This file is part of buteo-sync-plugins package * * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). * * Contact: Sateesh Kavuri * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * */ #include #include "ItemAdapterTest.h" #include "SimpleItemTest.h" #include "ItemIdMapperTest.h" #include "SyncMLConfigTest.h" #include "SyncMLStorageProviderTest.h" #include "FolderItemParserTest.h" #include "DeviceInfoTest.h" int main(int argc, char* argv[]) { QCoreApplication app(argc, argv); ItemAdapterTest itemAdapterTest; SimpleItemTest simpleItemTest; ItemIdMapperTest mapperTest; SyncMLConfigTest configTest; Buteo::SyncMLStorageProviderTest storageTest; FolderItemParserTest parserTest; Buteo::DeviceInfoTest deviceInfoTest; if (QTest::qExec(&simpleItemTest, argc, argv)) return 1; if (QTest::qExec(&mapperTest, argc, argv)) return 1; if (QTest::qExec(&itemAdapterTest, argc, argv)) return 1; if (QTest::qExec(&configTest, argc, argv)) return 1; if (QTest::qExec(&storageTest, argc, argv)) return 1; if (QTest::qExec(&parserTest, argc, argv)) return 1; if (QTest::qExec(&deviceInfoTest, argc, argv)) return 1; return 0; } buteo-sync-plugins-0.8.36/syncmlcommon/unittest/run-test000077500000000000000000000031721476033560700235010ustar00rootroot00000000000000#/* # * This file is part of buteo-sync-plugins package # * # * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). # * # * Contact: Sateesh Kavuri # * # * This library is free software; you can redistribute it and/or # * modify it under the terms of the GNU Lesser General Public License # * version 2.1 as published by the Free Software Foundation. # * # * This library is distributed in the hope that it will be useful, but # * WITHOUT ANY WARRANTY; without even the implied warranty of # * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # * Lesser General Public License for more details. # * # * You should have received a copy of the GNU Lesser General Public # * License along with this library; if not, write to the Free Software # * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA # * 02110-1301 USA # * # */ echo "Building unit tests of SyncmlCommon" #clean Sbox cache export SBOX_USE_CCACHE=no ccache -c qmake make -j2 if [ -f unit_test_results.txt ]; then rm unit_test_results.txt fi echo "Running unit tests and results will be stored in unit_test_results.txt" ./syncmlcommon-tests >> unit_test_results.txt 2>&1 if [ -f gcov_results.txt ]; then rm gcov_results.txt fi echo "Running gcov .... Results are stored in gcov_results.txt" gcov ItemAdapter.gcno >> gcov_results.txt 2>&1 gcov SimpleItem.gcno >> gcov_results.txt 2>&1 gcov ItemIdMapper.gcno >> gcov_results.txt 2>&1 gcov SyncMLConfig.gcno >> gcov_results.txt 2>&1 gcov SyncMLStorageProvider.gcno >> gcov_results.txt 2>&1 gcov FolderItemParser.gcno >> gcov_results.txt 2>&1 make distclean > /dev/null rm *.gcov buteo-sync-plugins-0.8.36/syncmlcommon/unittest/unittest.pro000066400000000000000000000050241476033560700243710ustar00rootroot00000000000000#/* # * This file is part of buteo-sync-plugins package # * # * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). # * # * Contact: Sateesh Kavuri # * # * This library is free software; you can redistribute it and/or # * modify it under the terms of the GNU Lesser General Public License # * version 2.1 as published by the Free Software Foundation. # * # * This library is distributed in the hope that it will be useful, but # * WITHOUT ANY WARRANTY; without even the implied warranty of # * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # * Lesser General Public License for more details. # * # * You should have received a copy of the GNU Lesser General Public # * License along with this library; if not, write to the Free Software # * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA # * 02110-1301 USA # * # */ TEMPLATE = app TARGET = syncmlcommon-tests DEPENDPATH += . \ ../ \ INCLUDEPATH += . \ ../ \ LIBS += -lsyncpluginmgr -lsynccommon -lmeegosyncml -lsyncprofile -lQtTest DEFINES += SYNC_APP_UNITTESTS #inputs HEADERS += ItemAdapterTest.h \ ../ItemAdapter.h \ ../SimpleItem.h \ SimpleItemTest.h \ ../ItemIdMapper.h \ ItemIdMapperTest.h \ ../SyncMLConfig.h \ SyncMLConfigTest.h \ ../StorageAdapter.h \ ../SyncMLStorageProvider.h \ SyncMLStorageProviderTest.h \ FolderItemParserTest.h \ ../FolderItemParser.h \ DeviceInfoTest.h \ ../DeviceInfo.h \ SOURCES += main.cpp \ ItemAdapterTest.cpp \ ../ItemAdapter.cpp \ ../SimpleItem.cpp \ SimpleItemTest.cpp \ ../ItemIdMapper.cpp \ ItemIdMapperTest.cpp \ ../SyncMLConfig.cpp \ SyncMLConfigTest.cpp \ ../StorageAdapter.cpp \ ../SyncMLStorageProvider.cpp \ SyncMLStorageProviderTest.cpp \ FolderItemParserTest.cpp \ ../FolderItemParser.cpp \ DeviceInfoTest.cpp \ ../DeviceInfo.cpp QT += testlib sql xml QT -= gui CONFIG += link_pkgconfig PKGCONFIG = buteosyncfw QMAKE_CLEAN += $(OBJECTS_DIR)/*.gcda $(OBJECTS_DIR)/*.gcno QMAKE_CXXFLAGS += -fprofile-arcs -ftest-coverage QMAKE_LFLAGS += -fprofile-arcs -ftest-coverage #install tests.files = syncmlcommon-tests.ref tests.path = /opt/tests/buteo-sync-plugins/ target.path = /opt/tests/buteo-sync-plugins/ INSTALLS += target \ tests buteo-sync-plugins-0.8.36/utils/000077500000000000000000000000001476033560700165325ustar00rootroot00000000000000buteo-sync-plugins-0.8.36/utils/buteosync-tool000077500000000000000000000056051476033560700214540ustar00rootroot00000000000000#!/bin/bash MSYNCD_HOME=$HOME/.cache/msyncd BUTEO_CONFIG=/etc/buteo/ BUTEO_LOG_SETTING=$BUTEO_LOG_SETTING/set_sync_log_level BUTEO_PROCESS=msync function usage () { echo " usage: $0 [options] This is a common line tool for Buteo sync. It can be used to peform various tasks like initiating sync, fetching the available profiles etc. Some options require you to run this tool as a root user -h | --help : this help -e | --enableprofile: enables a given profile -d | --disableprofile: disables a given profile -l | --listprofiles: lists all available profiles -s | --startsync: starts sync for a given profile -r | --syncresult: dumps the sync results " } function is_msyncd_running () { if [ -z $(pidof $BUTEO_PROCESS) ] ; then return 0 else return 1 fi } function enable_debug () { echo 4 > $BUTEO_LOG_SETTING pkill -9 $BUTEO_PROCESS } function disable_debug () { :> $BUTEO_LOG_SETTING pkill -9 $BUTEO_PROCESS } function list_sync_profiles () { ls $BUTEO_CONFIG/profiles/sync } function list_enabled_profiles () { echo "Enabled profiles " } function disable_profile () { echo "Disabling profile " $1 } function enable_profile () { echo "Enabling profile " $1 } function start_sync () { profile_name=$1 # Set the dbus session bus before sending the message export $(dbus-launch |grep DBUS_SESSION_BUS_ADDRESS) # Send dbus message to start sync for profile $profile_name dbus-send --session --type=method_call --print-reply --dest=com.meego.msyncd /synchronizer com.meego.msyncd.startSync string:'$profile_name' echo "Initiated sync. Check $HOME/.cache/msyncd/synchronizer.log to follow sync process" } function sync_result () { profile_name=$1 # List all the sync results for now cat $MSYNCD_HOME/sync/logs/$profile_name.log.xml echo "A non-zero minor/major code means error" echo "If your results are not seen, then the plugin has not exited properly (probably did not emit a signal to sync fw)" # minorcode=$(xmllint --xpath 'string(//synclog/syncresults/@minorcode)' $MSYNCD_HOME/sync/logs/$profile_name.log.xml) # majorcode=$(xmllint --xpath 'string(//synclog/syncresults/@majorcode)' $MSYNCD_HOME/sync/logs/$profile_name.log.xml) # timestamp=$(xmllint --xpath 'string(//synclog/syncresults/@time)' $MSYNCD_HOME/sync/logs/$profile_name.log.xml) } if [ $# -lt 1 ] then usage exit 127 fi ARGS=$(getopt -o "he:d:ls:r:" -l "help,enableprofile:,disableprofile:,listprofiles,startsync:,syncresult:" -n "buteosync-tool" -- "$@") eval set -- "$ARGS" case "$1" in -e | --enableprofile) enable_profile $2 shift;; -h | --help) usage shift;; -d | --disableprofile) disable_profile $2 shift;; -l | --listprofiles) list_sync_profiles shift;; -s | --startsync) start_sync $2 shift;; -r | --syncresult) sync_result $2 shift;; esac buteo-sync-plugins-0.8.36/utils/main.cpp000066400000000000000000000002001476033560700201520ustar00rootroot00000000000000#include int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); return a.exec(); } buteo-sync-plugins-0.8.36/utils/utils.pro000066400000000000000000000005061476033560700204150ustar00rootroot00000000000000#------------------------------------------------- # # Project created by QtCreator 2013-06-20T10:26:56 # #------------------------------------------------- QT += core QT -= gui TARGET = utils CONFIG += console CONFIG -= app_bundle TEMPLATE = app SOURCES += main.cpp OTHER_FILES += \ buteosync-tool