--- /dev/null
+{
+ "phabricator.uri" : "https://phabricator.kde.org/project/profile/34/",
+ "history.immutable" : true
+}
--- /dev/null
+SKIP /scripts/|/tests/|/testroundtrip
--- /dev/null
+REVIEWBOARD_URL = "https://git.reviewboard.kde.org"
+#REPOSITORY = "git://anongit.kde.org/kcontacts"
+BRANCH = "master"
+TARGET_GROUPS = "kdepimlibs"
+TARGET_PEOPLE = "mlaurent"
--- /dev/null
+cmake_minimum_required(VERSION 2.8.12)
+
+project(KContacts)
+
+# ECM setup
+find_package(ECM 5.19.0 CONFIG REQUIRED)
+set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH} ${KContacts_SOURCE_DIR}/cmake)
+
+include(GenerateExportHeader)
+include(ECMGenerateHeaders)
+include(ECMGeneratePriFile)
+include(ECMPackageConfigHelpers)
+include(ECMSetupVersion)
+include(FeatureSummary)
+include(KDEInstallDirs)
+include(KDECMakeSettings)
+include(KDEFrameworkCompilerSettings NO_POLICY_SCOPE)
+include(ECMQtDeclareLoggingCategory)
+
+set(KF5_VERSION "5.19.0")
+set(KCONTACTS_LIB_VERSION "5.2.2")
+
+ecm_setup_version(${KCONTACTS_LIB_VERSION} VARIABLE_PREFIX KContacts
+ VERSION_HEADER "${CMAKE_CURRENT_BINARY_DIR}/kcontacts_version.h"
+ PACKAGE_VERSION_FILE "${CMAKE_CURRENT_BINARY_DIR}/KF5ContactsConfigVersion.cmake"
+ SOVERSION 5
+)
+
+########### Find packages ###########
+find_package(Qt5 5.4 REQUIRED COMPONENTS DBus Gui)
+find_package(KF5 ${KF5_VERSION} REQUIRED COMPONENTS CoreAddons I18n Config Codecs)
+
+########### Targets ###########
+
+add_definitions(-DTRANSLATION_DOMAIN=\"kcontacts5\")
+add_definitions("-DQT_NO_CAST_FROM_ASCII -DQT_NO_CAST_TO_ASCII")
+add_subdirectory(src)
+
+if(BUILD_TESTING)
+ add_subdirectory(autotests)
+ add_subdirectory(tests)
+endif()
+
+########### CMake Config Files ###########
+set(CMAKECONFIG_INSTALL_DIR "${KDE_INSTALL_CMAKEPACKAGEDIR}/KF5Contacts")
+
+ecm_configure_package_config_file(
+ "${CMAKE_CURRENT_SOURCE_DIR}/KF5ContactsConfig.cmake.in"
+ "${CMAKE_CURRENT_BINARY_DIR}/KF5ContactsConfig.cmake"
+ INSTALL_DESTINATION ${CMAKECONFIG_INSTALL_DIR}
+)
+
+install(FILES
+ "${CMAKE_CURRENT_BINARY_DIR}/KF5ContactsConfig.cmake"
+ "${CMAKE_CURRENT_BINARY_DIR}/KF5ContactsConfigVersion.cmake"
+ DESTINATION "${CMAKECONFIG_INSTALL_DIR}"
+ COMPONENT Devel
+)
+
+install(EXPORT KF5ContactsTargets DESTINATION "${CMAKECONFIG_INSTALL_DIR}" FILE KF5ContactsTargets.cmake NAMESPACE KF5::)
+
+install(FILES
+ ${CMAKE_CURRENT_BINARY_DIR}/kcontacts_version.h
+ DESTINATION ${KDE_INSTALL_INCLUDEDIR_KF5} COMPONENT Devel
+)
+
+feature_summary(WHAT ALL FATAL_ON_MISSING_REQUIRED_PACKAGES)
--- /dev/null
+
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+ 51 Franklin St, 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.
+\f
+ 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.
+\f
+ 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.
+\f
+ 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.
+\f
+ 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.
+\f
+ 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.
+\f
+ 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.
+\f
+ 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.
+\f
+ 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
+\f
+ How to Apply These Terms to Your New Libraries
+
+ If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change. You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms
+of the ordinary General Public License).
+
+ To apply these terms, attach the following notices to the library.
+It is safest to attach them to the start of each source file to most
+effectively convey the exclusion of warranty; and each file should
+have at least the "copyright" line and a pointer to where the full
+notice is found.
+
+
+ <one line to give the library's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, 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.
+
+ <signature of Ty Coon>, 1 April 1990
+ Ty Coon, President of Vice
+
+That's all there is to it!
+
+
--- /dev/null
+@PACKAGE_INIT@
+
+find_dependency(KF5CoreAddons "@KF5_VERSION@")
+
+include("${CMAKE_CURRENT_LIST_DIR}/KF5ContactsTargets.cmake")
--- /dev/null
+/*
+ Mainpage.dox -- for now, copied from README
+ */
+
+/**
+@mainpage LIBKContacts - new address book API for KDE
+
+@section purpose Purpose
+
+libkabc provides an API for address book data. This can be used by all KDE
+application using data of this type, e.g. KAddressBook, KMail, KOrganizer,
+KPilot etc. It is meant as replacement for libkab (in kdebase/kab).
+
+@section features Features
+
+- Value based interface, addressbook entry data is implicitly shared.
+- Address book entries are identified by a unique id.
+- vCard backend (RFC 2425 / RFC 2426).
+- Locking mechanism to support concurrent access to the address book by
+ multiple processes.
+- Notification on change of addressbook by other process.
+- Dialog for selecting address book entries, supports mouse and keyboard
+ selection, supports automatic name completion.
+- GUI client for viewing, modifying address book data. This is aimed at
+ developers not end users.
+- Tool for converting data, written with libkab, to libkabc format.
+- Multiple backends (resources) for storing entries e.g. LDAP
+
+@authors Cornelius Schumacher \<schumacher@kde.org\>
+
+<b>LICENCE: LGPL</b>
+*/
+// DOXYGEN_REFERENCES = kdecore kdeui kresources
+// DOXYGEN_TOOLTIP = "An API for the KDE Addressbook."
--- /dev/null
+KContacts - new address book API for KDE
+
+PURPOSE:
+
+KCcontacts provides an API for address book data. This can be used by all
+application using data of this type, e.g. KAddressBook, KMail, KOrganizer,
+etc.
+
+FEATURES:
+
+- Value based interface, addressbook entry data is implicitly shared.
+- Address book entries are identified by a unique id.
+- vCard backend (RFC 2425 / RFC 2426).
+- Locking mechanism to support concurrent access to the address book by
+ multiple processes.
+- Notification on change of addressbook by other process.
+- Dialog for selecting address book entries, supports mouse and keyboard
+ selection, supports automatic name completion.
+- GUI client for viewing, modifying address book data. This is aimed at
+ developers not end users.
+- Tool for converting data, written with libkab, to libkabc format.
+- Multiple backends (resources) for storing entries e.g. LDAP
+
+AUTHOR: Cornelius Schumacher <schumacher@kde.org>
+
+LICENCE: LGPL
+
+DATE: 13 Oct 2001
--- /dev/null
+Address formats can be a tricky thing. KContacts tries very hard to perfectly fit
+the needs of ~95% of users and to be at least sufficient for the other 5%.
+
+The formatting of an address depends on the destination country as well as on
+the origin country of a letter. Basically, the part indicating the destination
+country follows the rules of the country of origin, all the rest follows the
+rules of the destination country. So we need to store for every country a) the
+country positioning and b) the address formatting.
+
+Address formats should usually be stored in a country's entry.desktop. There we
+store the country position in field "AddressCountryPosition" and the address
+format in a field "AddressFormat". Note that for most countries one field
+"AddressFormat" is sufficient for personal as well as company addresses
+(because personal addresses look just like business addresses without company);
+however, in some countries (eg. Hungary) business addresses differ in their
+structure. In this case you have the possibility of adding another field
+"BusinessAddressFormat" which will be preferred for formatting of business
+addresses; if KContacts can't find such a field, it will fall back to
+"AddressFormat". (Please use BusinessAddressFormat ONLY if you really need to)
+
+The format consists mainly of tags that will be replaced by address fields.
+The list of tags may grow in the future, the format *might* change in the near
+future, but I hope not.
+
+Any comments very very welcome to kde-pim@kde.org or to jost@schenck.de.
+
+-Jost.
+
+Fields AddressFormat and BusinessAddressFormat
+------------------------------------------------
+%n = real name
+%N = REAL NAME
+%cm = company
+%CM = COMPANY
+%s = street
+%S = STREET
+%z = zip code
+%l = location
+%L = LOCATION
+%r = region
+%R = REGION
+%p = post office box
+%, = conditional comma+whitespace,
+ will be left out if the value left or right of it is purged
+%w = conditional whitespace,
+ will be left out if the value left or right of it is purged
+%0(...) = the text inside the brackets will be completely purged if not
+ at least one tag inside it evaluates to something. Example: when the
+ address doesn't have a postbox, the string %0(PO Box %p) will not
+ evaluate to "PO Box " but to an empty string.
+\n = newline
+
+Field AddressCountryPosition
+------------------------------------------------
+below = country name below rest of address
+BELOW = country name below in capital letters
+above = country name above rest of address
+ABOVE = country name above in capital letters
+
+Some Tips
+------------------------------------------------
+- You sometimes have three fields in a line which can all be empty. If you eg.
+separate them all with conditional whitespace (same goes for cond. comma) like
+in "%z%w%r%w%l" and only the middle value (here: region) is empty, there will
+be no whitespace at all between the outer values (here: zipcode and location).
+To avoid this, combine two of these values with purge brackets: %0(%z%w%r)%w%l.
--- /dev/null
+include(ECMAddTests)
+
+set(QT_REQUIRED_VERSION "5.2.0")
+find_package(Qt5Test ${QT_REQUIRED_VERSION} CONFIG REQUIRED)
+
+########### next target ###############
+
+set(testroundtrip_srcs testroundtrip.cpp)
+qt5_add_resources(testroundtrip_srcs testroundtrip.qrc)
+add_executable(testroundtrip ${testroundtrip_srcs})
+add_test(NAME kcontacts-testroundtrip COMMAND testroundtrip)
+target_link_libraries(testroundtrip KF5Contacts Qt5::Test)
+
+ecm_add_tests(addresseetest.cpp impptest.cpp emailtest.cpp addresstest.cpp geotest.cpp keytest.cpp phonenumbertest.cpp picturetest.cpp secrecytest.cpp soundtest.cpp timezonetest.cpp contactgrouptest.cpp vcarddragtest.cpp langtest.cpp gendertest.cpp calendarurltest.cpp ldifconvertertest.cpp relatedtest.cpp resourcelocatorurltest.cpp NAME_PREFIX "kcontacts-" LINK_LIBRARIES KF5Contacts Qt5::Test KF5::ConfigCore Qt5::Gui)
--- /dev/null
+/*
+ This file is part of the KContacts framework.
+ Copyright (c) 2007 Tobias Koenig <tokoe@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+//krazy:excludeall=contractions
+
+#include "addresseetest.h"
+#include "kcontacts/addressee.h"
+#include <qtest.h>
+
+QTEST_MAIN(AddresseeTest)
+
+void AddresseeTest::emptyTest()
+{
+ KContacts::Addressee addressee;
+ QVERIFY(addressee.isEmpty());
+
+ KContacts::Addressee addresseeWithMail;
+ addresseeWithMail.insertEmail(QStringLiteral("foo@bar.org"));
+ QVERIFY(!addresseeWithMail.isEmpty());
+}
+
+void AddresseeTest::storeTest()
+{
+ KContacts::Addressee addressee;
+
+ KContacts::Picture logo(QStringLiteral("http://scottlandyard.info/pics/logo.png"));
+ KContacts::Picture photo(QStringLiteral("http://scottlandyard.info/~sinclair/photo.png"));
+ KContacts::Sound sound(QStringLiteral("http://scottlandyard.info/~sinclair/sound.wav"));
+
+ QStringList emails;
+ emails << QStringLiteral("john@sinclair.com") << QStringLiteral("ghosthunter@sinclair.com");
+
+ KContacts::Key::List keys;
+ keys << KContacts::Key(QStringLiteral("SecretKey"));
+
+ QStringList categories;
+ categories << QStringLiteral("Helper") << QStringLiteral("Friend");
+
+ QStringList customs;
+ customs << QStringLiteral("X-Danger: high");
+
+ KContacts::Gender gender(QStringLiteral("H"));
+ addressee.setGender(gender);
+ KContacts::Lang lang(QLatin1String("lang"));
+ addressee.setLangs(KContacts::Lang::List() << lang);
+
+ addressee.setUid(QStringLiteral("My uid"));
+ addressee.setName(QStringLiteral("John Sinclair"));
+ addressee.setFormattedName(QStringLiteral("Sinclair, John"));
+ addressee.setFamilyName(QStringLiteral("Sinclair"));
+ addressee.setGivenName(QStringLiteral("John"));
+ addressee.setAdditionalName(QStringLiteral("Bob"));
+ addressee.setPrefix(QStringLiteral("Sir"));
+ addressee.setSuffix(QStringLiteral("II"));
+ addressee.setNickName(QStringLiteral("ghosthunter"));
+ addressee.setBirthday(QDateTime(QDate(1982, 7, 19)));
+ addressee.setMailer(QStringLiteral("mutt"));
+ addressee.setTimeZone(KContacts::TimeZone(2));
+ addressee.setGeo(KContacts::Geo(42, 23));
+ addressee.setTitle(QStringLiteral("Ghost Hunter"));
+ addressee.setRole(QStringLiteral("Leader"));
+ addressee.setOrganization(QStringLiteral("Scottland Yard"));
+ addressee.setNote(QStringLiteral("Don't cross black deads way..."));
+ addressee.setProductId(QStringLiteral("ProductId45"));
+ addressee.setRevision(QDateTime(QDate(1982, 9, 15)));
+ addressee.setSortString(QStringLiteral("Name"));
+ KContacts::ResourceLocatorUrl url;
+ url.setUrl(QUrl(QStringLiteral("www.scottlandyard.info")));
+ addressee.setUrl(url);
+ addressee.setSecrecy(KContacts::Secrecy(KContacts::Secrecy::Public));
+ addressee.setLogo(logo);
+ addressee.setPhoto(photo);
+ addressee.setSound(sound);
+ addressee.setEmails(emails);
+ addressee.setKeys(keys);
+ addressee.setCategories(categories);
+ addressee.setCustoms(customs);
+ addressee.setKind(QStringLiteral("foo"));
+ addressee.setChanged(false);
+ KContacts::Impp imp;
+ imp.setType(KContacts::Impp::GaduGadu);
+ imp.setAddress(QStringLiteral("foo@kde.org"));
+ KContacts::Impp::List listImp;
+ listImp << imp;
+ addressee.setImppList(listImp);
+
+ QVERIFY(addressee.imppList() == listImp);
+ QVERIFY(addressee.langs() == (KContacts::Lang::List() << lang));
+ QVERIFY(addressee.gender() == gender);
+ QVERIFY(addressee.uid() == QStringLiteral("My uid"));
+ QVERIFY(addressee.name() == QStringLiteral("John Sinclair"));
+ QVERIFY(addressee.formattedName() == QStringLiteral("Sinclair, John"));
+ QVERIFY(addressee.familyName() == QStringLiteral("Sinclair"));
+ QVERIFY(addressee.givenName() == QStringLiteral("John"));
+ QVERIFY(addressee.additionalName() == QStringLiteral("Bob"));
+ QVERIFY(addressee.prefix() == QStringLiteral("Sir"));
+ QVERIFY(addressee.suffix() == QStringLiteral("II"));
+ QVERIFY(addressee.nickName() == QStringLiteral("ghosthunter"));
+ QVERIFY(addressee.birthday() == QDateTime(QDate(1982, 7, 19)));
+ QVERIFY(addressee.mailer() == QStringLiteral("mutt"));
+ QVERIFY(addressee.timeZone() == KContacts::TimeZone(2));
+ QVERIFY(addressee.geo() == KContacts::Geo(42, 23));
+ QVERIFY(addressee.title() == QStringLiteral("Ghost Hunter"));
+ QVERIFY(addressee.role() == QStringLiteral("Leader"));
+ QVERIFY(addressee.organization() == QStringLiteral("Scottland Yard"));
+ QVERIFY(addressee.note() == QStringLiteral("Don't cross black deads way..."));
+ QVERIFY(addressee.productId() == QStringLiteral("ProductId45"));
+ QVERIFY(addressee.revision() == QDateTime(QDate(1982, 9, 15)));
+ QVERIFY(addressee.sortString() == QStringLiteral("Name"));
+ QVERIFY(addressee.url() == url);
+ QVERIFY(addressee.secrecy() == KContacts::Secrecy(KContacts::Secrecy::Public));
+ QVERIFY(addressee.logo() == logo);
+ QVERIFY(addressee.photo() == photo);
+ QVERIFY(addressee.sound() == sound);
+ QVERIFY(addressee.emails() == emails);
+ QVERIFY(addressee.keys() == keys);
+ QVERIFY(addressee.categories() == categories);
+ QVERIFY(addressee.customs() == customs);
+ QVERIFY(addressee.changed() == false);
+ QCOMPARE(addressee.kind(), QStringLiteral("foo"));
+}
+
+void AddresseeTest::equalsTest()
+{
+ KContacts::Addressee addressee1, addressee2;
+
+ KContacts::Picture logo(QStringLiteral("http://scottlandyard.info/pics/logo.png"));
+ KContacts::Picture photo(QStringLiteral("http://scottlandyard.info/~sinclair/photo.png"));
+ KContacts::Sound sound(QStringLiteral("http://scottlandyard.info/~sinclair/sound.wav"));
+
+ QStringList emails;
+ emails << QStringLiteral("john@sinclair.com") << QStringLiteral("ghosthunter@sinclair.com");
+
+ KContacts::Key::List keys;
+ keys << KContacts::Key(QStringLiteral("SecretKey"));
+
+ QStringList categories;
+ categories << QStringLiteral("Helper") << QStringLiteral("Friend");
+
+ QStringList customs;
+ customs << QStringLiteral("X-Danger: high");
+
+ addressee1.setUid(QStringLiteral("My uid"));
+ addressee1.setName(QStringLiteral("John Sinclair"));
+ addressee1.setFormattedName(QStringLiteral("Sinclair, John"));
+ addressee1.setFamilyName(QStringLiteral("Sinclair"));
+ addressee1.setGivenName(QStringLiteral("John"));
+ addressee1.setAdditionalName(QStringLiteral("Bob"));
+ addressee1.setPrefix(QStringLiteral("Sir"));
+ addressee1.setSuffix(QStringLiteral("II"));
+ addressee1.setNickName(QStringLiteral("ghosthunter"));
+ addressee1.setBirthday(QDateTime(QDate(1982, 7, 19)));
+ addressee1.setMailer(QStringLiteral("mutt"));
+ addressee1.setTimeZone(KContacts::TimeZone(2));
+ addressee1.setGeo(KContacts::Geo(42, 23));
+ addressee1.setTitle(QStringLiteral("Ghost Hunter"));
+ addressee1.setRole(QStringLiteral("Leader"));
+ addressee1.setOrganization(QStringLiteral("Scottland Yard"));
+ addressee1.setNote(QStringLiteral("Don't cross black deads way..."));
+ addressee1.setProductId(QStringLiteral("ProductId45"));
+ addressee1.setRevision(QDateTime(QDate(1982, 9, 15)));
+ addressee1.setSortString(QStringLiteral("Name"));
+ KContacts::ResourceLocatorUrl url;
+ url.setUrl(QUrl(QStringLiteral("www.scottlandyard.info")));
+ addressee1.setUrl(url);
+ addressee1.setSecrecy(KContacts::Secrecy(KContacts::Secrecy::Public));
+ addressee1.setLogo(logo);
+ addressee1.setPhoto(photo);
+ addressee1.setSound(sound);
+ addressee1.setEmails(emails);
+ addressee1.setKeys(keys);
+ addressee1.setCategories(categories);
+ addressee1.setCustoms(customs);
+ addressee1.setChanged(false);
+
+ addressee2.setUid(QStringLiteral("My uid"));
+ addressee2.setName(QStringLiteral("John Sinclair"));
+ addressee2.setFormattedName(QStringLiteral("Sinclair, John"));
+ addressee2.setFamilyName(QStringLiteral("Sinclair"));
+ addressee2.setGivenName(QStringLiteral("John"));
+ addressee2.setAdditionalName(QStringLiteral("Bob"));
+ addressee2.setPrefix(QStringLiteral("Sir"));
+ addressee2.setSuffix(QStringLiteral("II"));
+ addressee2.setNickName(QStringLiteral("ghosthunter"));
+ addressee2.setBirthday(QDateTime(QDate(1982, 7, 19)));
+ addressee2.setMailer(QStringLiteral("mutt"));
+ addressee2.setTimeZone(KContacts::TimeZone(2));
+ addressee2.setGeo(KContacts::Geo(42, 23));
+ addressee2.setTitle(QStringLiteral("Ghost Hunter"));
+ addressee2.setRole(QStringLiteral("Leader"));
+ addressee2.setOrganization(QStringLiteral("Scottland Yard"));
+ addressee2.setNote(QStringLiteral("Don't cross black deads way..."));
+ addressee2.setProductId(QStringLiteral("ProductId45"));
+ addressee2.setRevision(QDateTime(QDate(1982, 9, 15)));
+ addressee2.setSortString(QStringLiteral("Name"));
+ addressee2.setUrl(url);
+ addressee2.setSecrecy(KContacts::Secrecy(KContacts::Secrecy::Public));
+ addressee2.setLogo(logo);
+ addressee2.setPhoto(photo);
+ addressee2.setSound(sound);
+ addressee2.setEmails(emails);
+ addressee2.setKeys(keys);
+ addressee2.setCategories(categories);
+ addressee2.setCustoms(customs);
+ addressee2.setChanged(false);
+
+ QVERIFY(addressee1 == addressee2);
+}
+
+void AddresseeTest::differsTest()
+{
+ KContacts::Addressee addressee1, addressee2;
+
+ addressee1.setNameFromString(QStringLiteral("John Sinclair"));
+ addressee2.setNameFromString(QStringLiteral("Suko"));
+
+ QVERIFY(addressee1 != addressee2);
+}
+
+void AddresseeTest::assignmentTest()
+{
+ KContacts::Addressee addressee1, addressee2;
+
+ KContacts::Picture logo(QStringLiteral("http://scottlandyard.info/pics/logo.png"));
+ KContacts::Picture photo(QStringLiteral("http://scottlandyard.info/~sinclair/photo.png"));
+ KContacts::Sound sound(QStringLiteral("http://scottlandyard.info/~sinclair/sound.wav"));
+
+ QStringList emails;
+ emails << QStringLiteral("john@sinclair.com") << QStringLiteral("ghosthunter@sinclair.com");
+
+ KContacts::Key::List keys;
+ keys << KContacts::Key(QStringLiteral("SecretKey"));
+
+ QStringList categories;
+ categories << QStringLiteral("Helper") << QStringLiteral("Friend");
+
+ QStringList customs;
+ customs << QStringLiteral("X-Danger: high");
+
+ addressee1.setUid(QStringLiteral("My uid"));
+ addressee1.setName(QStringLiteral("John Sinclair"));
+ addressee1.setFormattedName(QStringLiteral("Sinclair, John"));
+ addressee1.setFamilyName(QStringLiteral("Sinclair"));
+ addressee1.setGivenName(QStringLiteral("John"));
+ addressee1.setAdditionalName(QStringLiteral("Bob"));
+ addressee1.setPrefix(QStringLiteral("Sir"));
+ addressee1.setSuffix(QStringLiteral("II"));
+ addressee1.setNickName(QStringLiteral("ghosthunter"));
+ addressee1.setBirthday(QDateTime(QDate(1982, 7, 19)));
+ addressee1.setMailer(QStringLiteral("mutt"));
+ addressee1.setTimeZone(KContacts::TimeZone(2));
+ addressee1.setGeo(KContacts::Geo(42, 23));
+ addressee1.setTitle(QStringLiteral("Ghost Hunter"));
+ addressee1.setRole(QStringLiteral("Leader"));
+ addressee1.setOrganization(QStringLiteral("Scottland Yard"));
+ addressee1.setNote(QStringLiteral("Don't cross black deads way..."));
+ addressee1.setProductId(QStringLiteral("ProductId45"));
+ addressee1.setRevision(QDateTime(QDate(1982, 9, 15)));
+ addressee1.setSortString(QStringLiteral("Name"));
+ KContacts::ResourceLocatorUrl url;
+ url.setUrl(QUrl(QStringLiteral("www.scottlandyard.info")));
+ addressee1.setUrl(url);
+ addressee1.setSecrecy(KContacts::Secrecy(KContacts::Secrecy::Public));
+ addressee1.setLogo(logo);
+ addressee1.setPhoto(photo);
+ addressee1.setSound(sound);
+ addressee1.setEmails(emails);
+ addressee1.setKeys(keys);
+ addressee1.setCategories(categories);
+ addressee1.setCustoms(customs);
+ addressee1.setChanged(false);
+
+ addressee2 = addressee1;
+
+ QVERIFY(addressee1 == addressee2);
+}
+
+void AddresseeTest::serializeTest()
+{
+ KContacts::Addressee addressee1, addressee2;
+
+ KContacts::Picture logo(QStringLiteral("http://scottlandyard.info/pics/logo.png"));
+ KContacts::Picture photo(QStringLiteral("http://scottlandyard.info/~sinclair/photo.png"));
+ KContacts::Sound sound(QStringLiteral("http://scottlandyard.info/~sinclair/sound.wav"));
+
+ QStringList emails;
+ emails << QStringLiteral("john@sinclair.com") << QStringLiteral("ghosthunter@sinclair.com");
+
+ KContacts::Key::List keys;
+ keys << KContacts::Key(QStringLiteral("SecretKey"));
+
+ QStringList categories;
+ categories << QStringLiteral("Helper") << QStringLiteral("Friend");
+
+ QStringList customs;
+ customs << QStringLiteral("FirstApp-FirstKey:FirstValue")
+ << QStringLiteral("SecondApp-SecondKey:SecondValue")
+ << QStringLiteral("ThirdApp-ThirdKey:ThirdValue");
+
+ addressee1.setUid(QStringLiteral("My uid"));
+ addressee1.setName(QStringLiteral("John Sinclair"));
+ addressee1.setFormattedName(QStringLiteral("Sinclair, John"));
+ addressee1.setFamilyName(QStringLiteral("Sinclair"));
+ addressee1.setGivenName(QStringLiteral("John"));
+ addressee1.setAdditionalName(QStringLiteral("Bob"));
+ addressee1.setPrefix(QStringLiteral("Sir"));
+ addressee1.setSuffix(QStringLiteral("II"));
+ addressee1.setNickName(QStringLiteral("ghosthunter"));
+ addressee1.setBirthday(QDateTime(QDate(1982, 7, 19)));
+ addressee1.setMailer(QStringLiteral("mutt"));
+ addressee1.setTimeZone(KContacts::TimeZone(2));
+ addressee1.setGeo(KContacts::Geo(42, 23));
+ addressee1.setTitle(QStringLiteral("Ghost Hunter"));
+ addressee1.setRole(QStringLiteral("Leader"));
+ addressee1.setOrganization(QStringLiteral("Scottland Yard"));
+ addressee1.setNote(QStringLiteral("Don't cross black deads way..."));
+ addressee1.setProductId(QStringLiteral("ProductId45"));
+ addressee1.setRevision(QDateTime(QDate(1982, 9, 15)));
+ addressee1.setSortString(QStringLiteral("Name"));
+ KContacts::ResourceLocatorUrl url;
+ url.setUrl(QUrl(QStringLiteral("www.scottlandyard.info")));
+
+ addressee1.setUrl(url);
+ addressee1.setSecrecy(KContacts::Secrecy(KContacts::Secrecy::Public));
+ addressee1.setLogo(logo);
+ addressee1.setPhoto(photo);
+ addressee1.setSound(sound);
+ addressee1.setEmails(emails);
+ addressee1.setKeys(keys);
+ addressee1.setCategories(categories);
+ addressee1.setCustoms(customs);
+ addressee1.setChanged(false);
+
+ QByteArray data;
+ QDataStream s(&data, QIODevice::WriteOnly);
+ s << addressee1;
+
+ QDataStream t(&data, QIODevice::ReadOnly);
+ t >> addressee2;
+
+ QVERIFY(addressee1 == addressee2);
+}
+
+void AddresseeTest::fullEmailTest()
+{
+ KContacts::Addressee a;
+ QStringList emails;
+ emails << QStringLiteral("foo@bar.com");
+ a.setEmails(emails);
+ a.setFormattedName(QStringLiteral("firstname \"nickname\" lastname"));
+ QCOMPARE(a.fullEmail(),
+ QStringLiteral("\"firstname \\\"nickname\\\" lastname\" <foo@bar.com>"));
+}
+
+void AddresseeTest::nameFromStringTest()
+{
+ KContacts::Addressee a;
+ a.setNameFromString(QStringLiteral("Firstname Lastname"));
+ QCOMPARE(a.givenName(), QStringLiteral("Firstname"));
+ QCOMPARE(a.familyName(), QStringLiteral("Lastname"));
+ QCOMPARE(a.formattedName(), QStringLiteral("Firstname Lastname"));
+}
+
+void AddresseeTest::customFieldsTest()
+{
+ KContacts::Addressee a;
+
+ // test for empty
+ QVERIFY(a.customs().isEmpty());
+
+ // test insert
+ a.insertCustom(QStringLiteral("MyApp"), QStringLiteral("MyKey"), QStringLiteral("MyValue"));
+ QCOMPARE(a.customs().count(), 1);
+ QCOMPARE(a.custom(QStringLiteral("MyApp"), QStringLiteral("MyKey")), QStringLiteral("MyValue"));
+
+ a.insertCustom(QStringLiteral("MyApp"), QStringLiteral("MyKey"), QStringLiteral("YourValue"));
+ QCOMPARE(a.customs().count(), 1); // still one, we overwrite...
+ QCOMPARE(a.custom(QStringLiteral("MyApp"), QStringLiteral("MyKey")), QStringLiteral("YourValue"));
+
+ // test query non-existing app/key
+ QCOMPARE(a.custom(QStringLiteral("MyApp"), QStringLiteral("UnknownKey")), QString());
+ QCOMPARE(a.custom(QStringLiteral("UnknownApp"), QStringLiteral("MyKey")), QString());
+
+ // test insert with different key
+ a.insertCustom(QStringLiteral("MyApp"), QStringLiteral("AnotherKey"), QStringLiteral("OtherValue"));
+ QCOMPARE(a.customs().count(), 2);
+ QCOMPARE(a.custom(QStringLiteral("MyApp"), QStringLiteral("AnotherKey")), QStringLiteral("OtherValue"));
+ QCOMPARE(a.custom(QStringLiteral("MyApp"), QStringLiteral("MyKey")), QStringLiteral("YourValue"));
+
+ // test insert with different app
+ a.insertCustom(QStringLiteral("OtherApp"), QStringLiteral("OtherKey"), QStringLiteral("OurValue"));
+ QCOMPARE(a.customs().count(), 3);
+ QCOMPARE(a.custom(QStringLiteral("OtherApp"), QStringLiteral("OtherKey")), QStringLiteral("OurValue"));
+ QCOMPARE(a.custom(QStringLiteral("MyApp"), QStringLiteral("AnotherKey")), QStringLiteral("OtherValue"));
+ QCOMPARE(a.custom(QStringLiteral("MyApp"), QStringLiteral("MyKey")), QStringLiteral("YourValue"));
+
+#if 0 //Order is not defined now as we use a QHash
+ // test customs
+ QCOMPARE(a.customs().at(0), QStringLiteral("MyApp-MyKey:YourValue"));
+ QCOMPARE(a.customs().at(1), QStringLiteral("MyApp-AnotherKey:OtherValue"));
+ QCOMPARE(a.customs().at(2), QStringLiteral("OtherApp-OtherKey:OurValue"));
+#endif
+ // test equal operator
+ KContacts::Addressee b;
+ b.setUid(a.uid());
+ b.insertCustom(QStringLiteral("OtherApp"), QStringLiteral("OtherKey"), QStringLiteral("OurValue"));
+ b.insertCustom(QStringLiteral("MyApp"), QStringLiteral("MyKey"), QStringLiteral("YourValue"));
+ b.insertCustom(QStringLiteral("MyApp"), QStringLiteral("AnotherKey"), QStringLiteral("OtherValue"));
+
+ QCOMPARE(a, b);
+
+ b.insertCustom(QStringLiteral("MyApp"), QStringLiteral("AnotherKey"), QStringLiteral("WrongValue"));
+ QVERIFY(a != b);
+
+ // test setCustoms
+ KContacts::Addressee c;
+ c.insertCustom(QStringLiteral("ThisApp"), QStringLiteral("ShouldNotBe"), QStringLiteral("There"));
+ QCOMPARE(c.customs().count(), 1);
+
+ const QStringList testData = QStringList() << QStringLiteral("FirstApp-FirstKey:FirstValue")
+ << QStringLiteral("SecondApp-SecondKey:SecondValue")
+ << QStringLiteral("ThirdApp-ThirdKey:ThirdValue");
+
+ c.setCustoms(testData);
+ QCOMPARE(c.customs().count(), 3);
+
+ QCOMPARE(c.custom(QStringLiteral("FirstApp"), QStringLiteral("FirstKey")), QStringLiteral("FirstValue"));
+ QCOMPARE(c.custom(QStringLiteral("SecondApp"), QStringLiteral("SecondKey")), QStringLiteral("SecondValue"));
+ QCOMPARE(c.custom(QStringLiteral("ThirdApp"), QStringLiteral("ThirdKey")), QStringLiteral("ThirdValue"));
+
+ // test remove
+ QCOMPARE(c.customs().count(), 3);
+ c.removeCustom(QStringLiteral("UnknownApp"), QStringLiteral("FirstKey"));
+ QCOMPARE(c.customs().count(), 3);
+ c.removeCustom(QStringLiteral("FirstApp"), QStringLiteral("UnknownKey"));
+ QCOMPARE(c.customs().count(), 3);
+ c.removeCustom(QStringLiteral("FirstApp"), QStringLiteral("FirstKey"));
+ QCOMPARE(c.customs().count(), 2);
+}
+
+void AddresseeTest::parseEmailAddress_data()
+{
+ QTest::addColumn<QString>("inputEmail");
+ QTest::addColumn<QString>("email");
+ QTest::addColumn<QString>("name");
+ QTest::newRow("simpleemail") << QStringLiteral("foo@kde.org") << QStringLiteral("foo@kde.org") << QString();
+ QTest::newRow("email") << QStringLiteral("foo <foo@kde.org>") << QStringLiteral("foo@kde.org") << QStringLiteral("foo");
+ QTest::newRow("namewithdoublequote") << QStringLiteral("\"foo\" <foo@kde.org>") << QStringLiteral("foo@kde.org") << QStringLiteral("foo");
+}
+
+void AddresseeTest::parseEmailAddress()
+{
+ QFETCH(QString, inputEmail);
+ QFETCH(QString, email);
+ QFETCH(QString, name);
+
+ QString parsedName;
+ QString parsedEmail;
+ KContacts::Addressee::parseEmailAddress(inputEmail, parsedName, parsedEmail);
+ QCOMPARE(parsedEmail, email);
+ QCOMPARE(parsedName, name);
+}
--- /dev/null
+/*
+ This file is part of the KContacts framework.
+ Copyright (c) 2007 Tobias Koenig <tokoe@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef ADDRESSEE_TEST_H
+#define ADDRESSEE_TEST_H
+
+#include <QtCore/QObject>
+
+class AddresseeTest : public QObject
+{
+ Q_OBJECT
+
+private Q_SLOTS:
+ void emptyTest();
+ void storeTest();
+ void equalsTest();
+ void differsTest();
+ void assignmentTest();
+ void serializeTest();
+ void fullEmailTest();
+ void nameFromStringTest();
+ void customFieldsTest();
+ void parseEmailAddress_data();
+ void parseEmailAddress();
+};
+
+#endif
--- /dev/null
+/*
+ This file is part of the KContacts framework.
+ Copyright (c) 2007 Tobias Koenig <tokoe@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "addresstest.h"
+#include "kcontacts/address.h"
+#include <kconfig.h>
+#include <kconfiggroup.h>
+#include <qtest.h>
+#include <QStandardPaths>
+#include <QFileInfo>
+
+QTEST_MAIN(AddressTest)
+
+void AddressTest::initTestCase()
+{
+ setenv("LANG", "C", 1);
+}
+
+void AddressTest::emptyTest()
+{
+ KContacts::Address address;
+
+ QVERIFY(address.isEmpty());
+}
+
+void AddressTest::storeTest()
+{
+ KContacts::Address address;
+
+ address.setId(QStringLiteral("My Id"));
+ address.setType(KContacts::Address::Home);
+ address.setPostOfficeBox(QStringLiteral("1234"));
+ address.setExtended(QStringLiteral("My Extended Label"));
+ address.setStreet(QStringLiteral("My Street"));
+ address.setLocality(QStringLiteral("My Locality"));
+ address.setRegion(QStringLiteral("My Region"));
+ address.setPostalCode(QStringLiteral("My PostalCode"));
+ address.setCountry(QStringLiteral("My Country"));
+ address.setLabel(QStringLiteral("My Label"));
+
+ QCOMPARE(address.id(), QStringLiteral("My Id"));
+ QCOMPARE(address.type(), KContacts::Address::Home);
+ QCOMPARE(address.postOfficeBox(), QStringLiteral("1234"));
+ QCOMPARE(address.extended(), QStringLiteral("My Extended Label"));
+ QCOMPARE(address.street(), QStringLiteral("My Street"));
+ QCOMPARE(address.locality(), QStringLiteral("My Locality"));
+ QCOMPARE(address.region(), QStringLiteral("My Region"));
+ QCOMPARE(address.postalCode(), QStringLiteral("My PostalCode"));
+ QCOMPARE(address.country(), QStringLiteral("My Country"));
+ QCOMPARE(address.label(), QStringLiteral("My Label"));
+}
+
+void AddressTest::equalsTest()
+{
+ KContacts::Address address1, address2;
+
+ address1.setId(QStringLiteral("My Id"));
+ address1.setType(KContacts::Address::Home);
+ address1.setPostOfficeBox(QStringLiteral("1234"));
+ address1.setExtended(QStringLiteral("My Extended Label"));
+ address1.setStreet(QStringLiteral("My Street"));
+ address1.setLocality(QStringLiteral("My Locality"));
+ address1.setRegion(QStringLiteral("My Region"));
+ address1.setPostalCode(QStringLiteral("My Postalcode"));
+ address1.setCountry(QStringLiteral("My country"));
+ address1.setLabel(QStringLiteral("My Label"));
+
+ address2.setId(QStringLiteral("My Id"));
+ address2.setType(KContacts::Address::Home);
+ address2.setPostOfficeBox(QStringLiteral("1234"));
+ address2.setExtended(QStringLiteral("My Extended Label"));
+ address2.setStreet(QStringLiteral("My Street"));
+ address2.setLocality(QStringLiteral("My Locality"));
+ address2.setRegion(QStringLiteral("My Region"));
+ address2.setPostalCode(QStringLiteral("My Postalcode"));
+ address2.setCountry(QStringLiteral("My country"));
+ address2.setLabel(QStringLiteral("My Label"));
+
+ QVERIFY(address1 == address2);
+}
+
+void AddressTest::differsTest()
+{
+ KContacts::Address address1(KContacts::Address::Home);
+ KContacts::Address address2(KContacts::Address::Work);
+
+ QVERIFY(address1 != address2);
+}
+
+void AddressTest::assignmentTest()
+{
+ KContacts::Address address1, address2;
+
+ address1.setId(QStringLiteral("My Id"));
+ address1.setType(KContacts::Address::Home);
+ address1.setPostOfficeBox(QStringLiteral("1234"));
+ address1.setExtended(QStringLiteral("My Extended Label"));
+ address1.setStreet(QStringLiteral("My Street"));
+ address1.setLocality(QStringLiteral("My Locality"));
+ address1.setRegion(QStringLiteral("My Region"));
+ address1.setPostalCode(QStringLiteral("My Postalcode"));
+ address1.setCountry(QStringLiteral("My country"));
+ address1.setLabel(QStringLiteral("My Label"));
+
+ address2 = address1;
+
+ QVERIFY(address1 == address2);
+}
+
+void AddressTest::serializeTest()
+{
+ KContacts::Address address1, address2;
+
+ address1.setType(KContacts::Address::Work);
+ address1.setPostOfficeBox(QStringLiteral("1234"));
+ address1.setExtended(QStringLiteral("My Extended Label"));
+ address1.setStreet(QStringLiteral("My Street"));
+ address1.setLocality(QStringLiteral("My Locality"));
+ address1.setRegion(QStringLiteral("My Region"));
+ address1.setPostalCode(QStringLiteral("My Postalcode"));
+ address1.setCountry(QStringLiteral("My country"));
+ address1.setLabel(QStringLiteral("My Label"));
+
+ QByteArray data;
+ QDataStream s(&data, QIODevice::WriteOnly);
+ s << address1;
+
+ QDataStream t(&data, QIODevice::ReadOnly);
+ t >> address2;
+
+ QVERIFY(address1 == address2);
+}
+
+void AddressTest::formatTest()
+{
+ {
+ // check availability of country to ISO code mapping data file
+ const QString mapfile = QStandardPaths::locate(QStandardPaths::GenericDataLocation, QStringLiteral("kf5/kcontacts/countrytransl.map"));
+ QVERIFY2(!mapfile.isEmpty(), "Country to ISO code mapping data file does not exist");
+
+ QFileInfo fileInfo(mapfile);
+ QVERIFY2(fileInfo.exists(), "Country to ISO code mapping data file does not exist");
+ QVERIFY2(fileInfo.isReadable(), "Country to ISO code mapping data file is not readable");
+ }
+
+ {
+ const QString templateFile = QStandardPaths::locate(QStandardPaths::GenericDataLocation, QStringLiteral("kf5/locale/countries/de/country.desktop"));
+ QVERIFY(!templateFile.isEmpty());
+ const KConfig templateConfig(templateFile);
+ QVERIFY2(templateConfig.hasGroup("KCM Locale"),
+ "Address format config for 'de' is missing expected 'KCM Locale' group");
+ const KConfigGroup templateGroup = templateConfig.group("KCM Locale");
+ QVERIFY2(templateGroup.hasKey("AddressFormat"),
+ "Address format config is missing expected key 'AddressFormat'");
+ const QString addressTemplate = templateGroup.readEntry("AddressFormat");
+ QVERIFY2(!addressTemplate.isEmpty(),
+ "Address format template for 'de' is empty");
+
+ KContacts::Address address;
+ address.setStreet(QStringLiteral("Lummerlandstr. 1"));
+ address.setPostalCode(QStringLiteral("12345"));
+ address.setLocality(QStringLiteral("Lummerstadt"));
+ address.setCountry(QStringLiteral("Germany"));
+
+ const QString result(QStringLiteral("Jim Knopf\nLummerlandstr. 1\n"
+ "12345 Lummerstadt\n\nGERMANY"));
+
+ QCOMPARE(address.formattedAddress(QStringLiteral("Jim Knopf")), result);
+ }
+
+ {
+ KContacts::Address address;
+ address.setStreet(QStringLiteral("457 Foobar Ave"));
+ address.setPostalCode(QStringLiteral("1A2B3C"));
+ address.setLocality(QStringLiteral("Nervousbreaktown"));
+ address.setRegion(QStringLiteral("DC"));
+ address.setCountry(QStringLiteral("United States of America"));
+
+ const QString result(
+ QStringLiteral("Huck Finn\n457 Foobar Ave\nNervousbreaktown,"
+ " DC 1A2B3C\n\nUNITED STATES OF AMERICA"));
+ QCOMPARE(address.formattedAddress(QStringLiteral("Huck Finn")), result);
+ }
+
+ {
+ KContacts::Address address;
+ address.setStreet(QStringLiteral("Lummerlandstr. 1"));
+ address.setPostalCode(QStringLiteral("12345"));
+ address.setLocality(QStringLiteral("Lummerstadt"));
+ address.setCountry(QStringLiteral("Deutschland"));
+
+ const QString result(QStringLiteral("Jim Knopf\nLummerlandstr. 1\n"
+ "12345 Lummerstadt\n\nDEUTSCHLAND"));
+
+ QCOMPARE(address.formattedAddress(QStringLiteral("Jim Knopf")), result);
+ }
+
+ {
+ KContacts::Address address;
+ address.setStreet(QStringLiteral("Lummerlandstr. 1"));
+ address.setPostalCode(QStringLiteral("12345"));
+ address.setLocality(QStringLiteral("Lummerstadt"));
+ address.setCountry(QString());
+
+ const QString result(QStringLiteral("Jim Knopf\nLummerlandstr. 1\nLummerstadt, 12345"));
+
+ QCOMPARE(address.formattedAddress(QStringLiteral("Jim Knopf")), result);
+ }
+}
--- /dev/null
+/*
+ This file is part of the KContacts framework.
+ Copyright (c) 2007 Tobias Koenig <tokoe@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef ADDRESS_TEST_H
+#define ADDRESS_TEST_H
+
+#include <QtCore/QObject>
+
+class AddressTest : public QObject
+{
+ Q_OBJECT
+
+private Q_SLOTS:
+ void initTestCase();
+ void emptyTest();
+ void storeTest();
+ void equalsTest();
+ void differsTest();
+ void assignmentTest();
+ void serializeTest();
+ void formatTest();
+};
+
+#endif
--- /dev/null
+/*
+ This file is part of the KContacts framework.
+ Copyright (c) 2015 Laurent Montel <montel@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "calendarurltest.h"
+
+#include "calendarurl.h"
+#include "vcardtool.h"
+#include <qtest.h>
+
+using namespace KContacts;
+Q_DECLARE_METATYPE(KContacts::CalendarUrl::CalendarType)
+CalendarUrlTest::CalendarUrlTest(QObject *parent)
+ : QObject(parent)
+{
+
+}
+
+CalendarUrlTest::~CalendarUrlTest()
+{
+
+}
+
+void CalendarUrlTest::shouldHaveDefaultValue()
+{
+ CalendarUrl calendarUrl(CalendarUrl::FBUrl);
+ QVERIFY(!calendarUrl.isValid());
+ QVERIFY(calendarUrl.url().isEmpty());
+ QVERIFY(calendarUrl.parameters().isEmpty());
+}
+
+void CalendarUrlTest::shouldAssignValue()
+{
+ QMap<QString, QStringList> params;
+ params.insert(QStringLiteral("Foo1"), QStringList() << QStringLiteral("bla1") << QStringLiteral("blo1"));
+ params.insert(QStringLiteral("Foo2"), QStringList() << QStringLiteral("bla2") << QStringLiteral("blo2"));
+ CalendarUrl calendarUrl(CalendarUrl::FBUrl);
+ calendarUrl.setParameters(params);
+ QVERIFY(!calendarUrl.isValid());
+ QCOMPARE(calendarUrl.type(), CalendarUrl::FBUrl);
+ QVERIFY(calendarUrl.url().isEmpty());
+ QVERIFY(!calendarUrl.parameters().isEmpty());
+ QCOMPARE(calendarUrl.parameters(), params);
+}
+
+void CalendarUrlTest::shouldAssignExternal()
+{
+ CalendarUrl calendarUrl(CalendarUrl::FBUrl);
+ const CalendarUrl::CalendarType type = CalendarUrl::CALUri;
+ calendarUrl.setType(type);
+ QVERIFY(calendarUrl.url().isEmpty());
+ QCOMPARE(calendarUrl.type(), type);
+}
+
+void CalendarUrlTest::shouldSerialized()
+{
+ for (int i = 0; i < CalendarUrl::EndCalendarType; ++i) {
+ CalendarUrl calendarUrl;
+ CalendarUrl result;
+ CalendarUrl::CalendarType type = static_cast<CalendarUrl::CalendarType>(i);
+ calendarUrl.setType(type);
+ QMap<QString, QStringList> params;
+ params.insert(QStringLiteral("Foo1"), QStringList() << QStringLiteral("bla1") << QStringLiteral("blo1"));
+ params.insert(QStringLiteral("Foo2"), QStringList() << QStringLiteral("bla2") << QStringLiteral("blo2"));
+ calendarUrl.setParameters(params);
+ calendarUrl.setUrl(QUrl(QStringLiteral("mailto:foo@kde.org")));
+
+ QByteArray data;
+ QDataStream s(&data, QIODevice::WriteOnly);
+ s << calendarUrl;
+
+ QDataStream t(&data, QIODevice::ReadOnly);
+ t >> result;
+
+ QVERIFY(calendarUrl == result);
+ }
+}
+
+void CalendarUrlTest::shouldEqualCalendarUrl()
+{
+ for (int i = 0; i < CalendarUrl::EndCalendarType; ++i) {
+ CalendarUrl calendarUrl;
+ CalendarUrl result;
+ CalendarUrl::CalendarType type = static_cast<CalendarUrl::CalendarType>(i);
+ calendarUrl.setType(type);
+ QMap<QString, QStringList> params;
+ params.insert(QStringLiteral("Foo1"), QStringList() << QStringLiteral("bla1") << QStringLiteral("blo1"));
+ params.insert(QStringLiteral("Foo2"), QStringList() << QStringLiteral("bla2") << QStringLiteral("blo2"));
+ calendarUrl.setUrl(QUrl(QStringLiteral("mailto:foo@kde.org")));
+ calendarUrl.setParameters(params);
+
+ result = calendarUrl;
+ QVERIFY(calendarUrl == result);
+ }
+}
+
+void CalendarUrlTest::shouldParseCalendarUrl()
+{
+ for (int i = CalendarUrl::Unknown + 1; i < CalendarUrl::EndCalendarType; ++i) {
+ CalendarUrl::CalendarType type = static_cast<CalendarUrl::CalendarType>(i);
+ QByteArray baType;
+ switch (type) {
+ case CalendarUrl::Unknown:
+ case CalendarUrl::EndCalendarType:
+ break;
+ case CalendarUrl::FBUrl:
+ baType = QByteArray("FBURL");
+ break;
+ case CalendarUrl::CALUri:
+ baType = QByteArray("CALURI");
+ break;
+ case CalendarUrl::CALADRUri:
+ baType = QByteArray("CALADRURI");
+ break;
+
+ }
+
+ QByteArray vcarddata("BEGIN:VCARD\n"
+ "VERSION:3.0\n"
+ "N:LastName;FirstName;;;\n"
+ "UID:c80cf296-0825-4eb0-ab16-1fac1d522a33@xxxxxx.xx\n");
+ vcarddata += baType;
+ vcarddata += QByteArray(
+ ";PREF=1:https://sherlockholmes.com/calendar/sherlockholmes\n"
+ "REV:2015-03-14T09:24:45+00:00\n"
+ "FN:FirstName LastName\n"
+ "END:VCARD\n");
+
+ KContacts::VCardTool vcard;
+ const KContacts::AddresseeList lst = vcard.parseVCards(vcarddata);
+ QCOMPARE(lst.count(), 1);
+ QCOMPARE(lst.at(0).calendarUrlList().count(), 1);
+ const CalendarUrl calurl = lst.at(0).calendarUrlList().at(0);
+ QCOMPARE(calurl.type(), type);
+ QCOMPARE(calurl.url(), QUrl(QStringLiteral("https://sherlockholmes.com/calendar/sherlockholmes")));
+ QVERIFY(!calurl.parameters().isEmpty());
+ }
+}
+
+void CalendarUrlTest::shouldGenerateVCard_data()
+{
+ QTest::addColumn<KContacts::CalendarUrl::CalendarType>("type");
+ QTest::addColumn<QByteArray>("value");
+ for (int i = CalendarUrl::Unknown + 1; i < CalendarUrl::EndCalendarType; ++i) {
+ KContacts::CalendarUrl::CalendarType type = static_cast<KContacts::CalendarUrl::CalendarType>(i);
+ QByteArray baType;
+ switch (type) {
+ case CalendarUrl::Unknown:
+ case CalendarUrl::EndCalendarType:
+ break;
+ case CalendarUrl::FBUrl:
+ baType = QByteArray("FBURL");
+ break;
+ case CalendarUrl::CALUri:
+ baType = QByteArray("CALURI");
+ break;
+ case CalendarUrl::CALADRUri:
+ baType = QByteArray("CALADRURI");
+ break;
+
+ }
+ QTest::newRow(baType.constData()) << type << baType;
+ }
+}
+
+void CalendarUrlTest::shouldGenerateVCard()
+{
+ QFETCH(KContacts::CalendarUrl::CalendarType, type);
+ QFETCH(QByteArray, value);
+
+ KContacts::AddresseeList lst;
+ KContacts::Addressee addr;
+ addr.setEmails(QStringList() << QStringLiteral("foo@kde.org"));
+ addr.setUid(QStringLiteral("testuid"));
+ CalendarUrl url;
+ url.setType(type);
+ url.setUrl(QUrl(QStringLiteral("https://sherlockholmes.com/calendar/sherlockholmes")));
+ addr.insertCalendarUrl(url);
+ lst << addr;
+ KContacts::VCardTool vcard;
+ const QByteArray ba = vcard.exportVCards(lst, KContacts::VCard::v4_0);
+ QByteArray expected;
+ // Different order
+ if (type == KContacts::CalendarUrl::FBUrl) {
+ expected = QByteArray("BEGIN:VCARD\r\n"
+ "VERSION:4.0\r\n"
+ "EMAIL:foo@kde.org\r\n");
+ expected += value + QByteArray(":https://sherlockholmes.com/calendar/sherlockholmes\r\n"
+ "N:;;;;\r\n"
+ "UID:testuid\r\n"
+ "END:VCARD\r\n\r\n");
+ } else {
+ expected = QByteArray("BEGIN:VCARD\r\n"
+ "VERSION:4.0\r\n");
+ expected += value + QByteArray(":https://sherlockholmes.com/calendar/sherlockholmes\r\n"
+ "EMAIL:foo@kde.org\r\n"
+ "N:;;;;\r\n"
+ "UID:testuid\r\n"
+ "END:VCARD\r\n\r\n");
+ }
+
+ QCOMPARE(ba, expected);
+}
+
+void CalendarUrlTest::shouldGenerateVCardWithParameter()
+{
+ KContacts::AddresseeList lst;
+ KContacts::Addressee addr;
+ addr.setEmails(QStringList() << QStringLiteral("foo@kde.org"));
+ addr.setUid(QStringLiteral("testuid"));
+ CalendarUrl url;
+ url.setType(CalendarUrl::CALUri);
+ url.setUrl(QUrl(QStringLiteral("https://sherlockholmes.com/calendar/sherlockholmes")));
+ QMap<QString, QStringList> params;
+ params.insert(QStringLiteral("Foo2"), QStringList() << QStringLiteral("bla2") << QStringLiteral("blo2"));
+ url.setParameters(params);
+ addr.insertCalendarUrl(url);
+ lst << addr;
+ KContacts::VCardTool vcard;
+ const QByteArray ba = vcard.exportVCards(lst, KContacts::VCard::v4_0);
+ QByteArray expected = QByteArray("BEGIN:VCARD\r\n"
+ "VERSION:4.0\r\n"
+ "CALURI;FOO2=bla2,blo2:https://sherlockholmes.com/calendar/sherlockholmes\r\n"
+ "EMAIL:foo@kde.org\r\n"
+ "N:;;;;\r\n"
+ "UID:testuid\r\n"
+ "END:VCARD\r\n\r\n");
+ QCOMPARE(ba, expected);
+}
+
+void CalendarUrlTest::shouldNotGeneratedAttributeForVcard3()
+{
+ KContacts::AddresseeList lst;
+ KContacts::Addressee addr;
+ addr.setEmails(QStringList() << QStringLiteral("foo@kde.org"));
+ addr.setUid(QStringLiteral("testuid"));
+ CalendarUrl url;
+ url.setType(CalendarUrl::CALUri);
+ url.setUrl(QUrl(QStringLiteral("https://sherlockholmes.com/calendar/sherlockholmes")));
+ QMap<QString, QStringList> params;
+ params.insert(QStringLiteral("Foo2"), QStringList() << QStringLiteral("bla2") << QStringLiteral("blo2"));
+ url.setParameters(params);
+ addr.insertCalendarUrl(url);
+ lst << addr;
+ KContacts::VCardTool vcard;
+ const QByteArray ba = vcard.exportVCards(lst, KContacts::VCard::v3_0);
+ QByteArray expected = QByteArray("BEGIN:VCARD\r\n"
+ "VERSION:3.0\r\n"
+ "EMAIL:foo@kde.org\r\n"
+ "N:;;;;\r\n"
+ "UID:testuid\r\n"
+ "END:VCARD\r\n\r\n");
+ QCOMPARE(ba, expected);
+}
+
+void CalendarUrlTest::shouldGenerateMultiCalendarUrl()
+{
+ KContacts::AddresseeList lst;
+ KContacts::Addressee addr;
+ addr.setEmails(QStringList() << QStringLiteral("foo@kde.org"));
+ addr.setUid(QStringLiteral("testuid"));
+ CalendarUrl url;
+ url.setType(CalendarUrl::CALUri);
+ url.setUrl(QUrl(QStringLiteral("https://sherlockholmes.com/calendar/sherlockholmes")));
+ QMap<QString, QStringList> params;
+ params.insert(QStringLiteral("Foo2"), QStringList() << QStringLiteral("bla2") << QStringLiteral("blo2"));
+ url.setParameters(params);
+ addr.insertCalendarUrl(url);
+
+ url.setType(CalendarUrl::FBUrl);
+ url.setUrl(QUrl(QStringLiteral("https://sherlockholmes.com/calendar/sherlockholmes2")));
+ params.clear();
+
+ params.insert(QStringLiteral("Foo1"), QStringList() << QStringLiteral("bla1") << QStringLiteral("blo1"));
+ url.setParameters(params);
+ addr.insertCalendarUrl(url);
+
+ lst << addr;
+ KContacts::VCardTool vcard;
+ const QByteArray ba = vcard.exportVCards(lst, KContacts::VCard::v4_0);
+ QByteArray expected = QByteArray("BEGIN:VCARD\r\n"
+ "VERSION:4.0\r\n"
+ "CALURI;FOO2=bla2,blo2:https://sherlockholmes.com/calendar/sherlockholmes\r\n"
+ "EMAIL:foo@kde.org\r\n"
+ "FBURL;FOO1=bla1,blo1:https://sherlockholmes.com/calendar/sherlockholmes2\r\n"
+ "N:;;;;\r\n"
+ "UID:testuid\r\n"
+ "END:VCARD\r\n\r\n");
+ QCOMPARE(ba, expected);
+
+}
+
+QTEST_MAIN(CalendarUrlTest)
+
--- /dev/null
+/*
+ This file is part of the KContacts framework.
+ Copyright (c) 2015 Laurent Montel <montel@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef CALENDARURLTEST_H
+#define CALENDARURLTEST_H
+
+#include <QObject>
+
+class CalendarUrlTest : public QObject
+{
+ Q_OBJECT
+public:
+ explicit CalendarUrlTest(QObject *parent = Q_NULLPTR);
+ ~CalendarUrlTest();
+
+private Q_SLOTS:
+ void shouldHaveDefaultValue();
+ void shouldAssignValue();
+ void shouldAssignExternal();
+ void shouldSerialized();
+ void shouldEqualCalendarUrl();
+ void shouldParseCalendarUrl();
+ void shouldGenerateVCard_data();
+ void shouldGenerateVCard();
+ void shouldGenerateVCardWithParameter();
+ void shouldNotGeneratedAttributeForVcard3();
+ void shouldGenerateMultiCalendarUrl();
+};
+
+#endif // CALENDARURLTEST_H
--- /dev/null
+/*
+ This file is part of the KContacts framework.
+ Copyright (c) 2008 Kevin Krammer <kevin.krammer@gmx.at>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <qtest.h>
+
+#include "kcontacts/contactgroup.h"
+#include "kcontacts/contactgrouptool.h"
+
+#include <QBuffer>
+
+using namespace KContacts;
+
+class ContactGroupTest : public QObject
+{
+ Q_OBJECT
+
+private Q_SLOTS:
+ void contactGroupContactReference();
+ void contactGroupContactGroupReference();
+ void contactGroupData();
+ void contactGroup();
+ void testGroupRoundTrip();
+ void testGroupListRoundTrip();
+};
+
+QTEST_MAIN(ContactGroupTest)
+
+void ContactGroupTest::contactGroupContactReference()
+{
+ const QLatin1String uid("MyReferenceId");
+ const QLatin1String gid("GID");
+ const QLatin1String preferredEMail("tokoe@kde.org");
+ const QLatin1String customKey("MyCustomKey");
+ const QLatin1String customValue("MyCustomValue");
+
+ // uid test
+ {
+ ContactGroup::ContactReference ref(uid);
+ QCOMPARE(ref.uid(), uid);
+ }
+
+ // uid test
+ {
+ ContactGroup::ContactReference ref;
+ ref.setUid(uid);
+ QCOMPARE(ref.uid(), uid);
+ }
+
+ // preferredEmail test
+ {
+ ContactGroup::ContactReference ref(uid);
+ ref.setPreferredEmail(preferredEMail);
+ QCOMPARE(ref.preferredEmail(), preferredEMail);
+ }
+
+ // custom test
+ {
+ ContactGroup::ContactReference ref(uid);
+ ref.insertCustom(customKey, customValue);
+ QCOMPARE(ref.custom(customKey), customValue);
+ ref.removeCustom(customKey);
+ QCOMPARE(ref.custom(customKey), QString());
+ }
+
+ // assignment test
+ {
+ ContactGroup::ContactReference ref(uid);
+ ref.setGid(gid);
+ ref.setPreferredEmail(preferredEMail);
+ ref.insertCustom(customKey, customValue);
+
+ ContactGroup::ContactReference ref2(ref);
+ QCOMPARE(ref.uid(), ref2.uid());
+ QCOMPARE(ref.gid(), ref2.gid());
+ QCOMPARE(ref.preferredEmail(), ref2.preferredEmail());
+ QCOMPARE(ref.custom(customKey), ref2.custom(customKey));
+
+ QVERIFY(ref == ref2);
+ }
+
+ // const test
+ {
+ ContactGroup::ContactReference ref(uid);
+ ref.setPreferredEmail(preferredEMail);
+ ref.insertCustom(customKey, customValue);
+
+ const ContactGroup::ContactReference constRef(ref);
+ constRef.uid();
+ constRef.preferredEmail();
+ constRef.custom(customKey);
+ constRef.gid();
+ }
+}
+
+void ContactGroupTest::contactGroupContactGroupReference()
+{
+ const QLatin1String uid("MyReferenceId");
+ const QLatin1String customKey("MyCustomKey");
+ const QLatin1String customValue("MyCustomValue");
+
+ // uid test
+ {
+ ContactGroup::ContactGroupReference ref(uid);
+ QCOMPARE(ref.uid(), uid);
+ }
+
+ // uid test
+ {
+ ContactGroup::ContactGroupReference ref;
+ ref.setUid(uid);
+ QCOMPARE(ref.uid(), uid);
+ }
+
+ // custom test
+ {
+ ContactGroup::ContactGroupReference ref(uid);
+ ref.insertCustom(customKey, customValue);
+ QCOMPARE(ref.custom(customKey), customValue);
+ ref.removeCustom(customKey);
+ QCOMPARE(ref.custom(customKey), QString());
+ }
+
+ // assignment test
+ {
+ ContactGroup::ContactGroupReference ref(uid);
+ ref.insertCustom(customKey, customValue);
+
+ ContactGroup::ContactGroupReference ref2(ref);
+ QCOMPARE(ref.uid(), ref2.uid());
+ QCOMPARE(ref.custom(customKey), ref2.custom(customKey));
+
+ QVERIFY(ref == ref2);
+ }
+
+ // const test
+ {
+ ContactGroup::ContactGroupReference ref(uid);
+ ref.insertCustom(customKey, customValue);
+
+ const ContactGroup::ContactGroupReference constRef(ref);
+ constRef.uid();
+ constRef.custom(customKey);
+ }
+}
+
+void ContactGroupTest::contactGroupData()
+{
+ const QLatin1String name("Tobias Koenig");
+ const QLatin1String email("tokoe@kde.org");
+ const QLatin1String customKey("MyCustomKey");
+ const QLatin1String customValue("MyCustomValue");
+
+ // name/email test
+ {
+ ContactGroup::Data data(name, email);
+ QCOMPARE(data.name(), name);
+ QCOMPARE(data.email(), email);
+ }
+
+ // name test
+ {
+ ContactGroup::Data data;
+ data.setName(name);
+ QCOMPARE(data.name(), name);
+ }
+
+ // email test
+ {
+ ContactGroup::Data data;
+ data.setEmail(email);
+ QCOMPARE(data.email(), email);
+ }
+
+ // custom test
+ {
+ ContactGroup::Data data(name, email);
+ data.insertCustom(customKey, customValue);
+ QCOMPARE(data.custom(customKey), customValue);
+ data.removeCustom(customKey);
+ QCOMPARE(data.custom(customKey), QString());
+ }
+
+ // assignment test
+ {
+ ContactGroup::Data data(name, email);
+ data.insertCustom(customKey, customValue);
+
+ ContactGroup::Data data2(data);
+ QCOMPARE(data.name(), data2.name());
+ QCOMPARE(data.email(), data2.email());
+ QCOMPARE(data.custom(customKey), data2.custom(customKey));
+
+ QVERIFY(data == data2);
+ }
+
+ // const test
+ {
+ ContactGroup::Data data(name, email);
+ data.insertCustom(customKey, customValue);
+
+ const ContactGroup::Data constData(data);
+ constData.name();
+ constData.email();
+ constData.custom(customKey);
+ }
+}
+
+void ContactGroupTest::contactGroup()
+{
+ const QLatin1String groupName("MyGroupName");
+ const QLatin1String groupId("MyGroupID");
+ const QLatin1String name("Tobias Koenig");
+ const QLatin1String email("tokoe@kde.org");
+ const QLatin1String uid("MyUid");
+
+ // name test
+ {
+ ContactGroup group(groupName);
+ QCOMPARE(group.name(), groupName);
+ }
+
+ // id test
+ {
+ ContactGroup group(groupName);
+ group.setId(groupId);
+ QCOMPARE(group.id(), groupId);
+ }
+
+ // contact reference test
+ {
+ ContactGroup group(groupName);
+ QCOMPARE(group.contactReferenceCount(), (unsigned int)0);
+
+ ContactGroup::ContactReference ref(uid);
+ ref.setPreferredEmail(email);
+
+ group.append(ref);
+ QCOMPARE(group.contactReferenceCount(), (unsigned int)1);
+
+ const ContactGroup::ContactReference ref2 = group.contactReference(0);
+ QCOMPARE(ref, ref2);
+
+ group.remove(ref);
+ QCOMPARE(group.contactReferenceCount(), (unsigned int)0);
+ }
+
+ // contact group reference test
+ {
+ ContactGroup group(groupName);
+ QCOMPARE(group.contactGroupReferenceCount(), (unsigned int)0);
+
+ ContactGroup::ContactGroupReference ref(uid);
+
+ group.append(ref);
+ QCOMPARE(group.contactGroupReferenceCount(), (unsigned int)1);
+
+ const ContactGroup::ContactGroupReference ref2 = group.contactGroupReference(0);
+ QCOMPARE(ref, ref2);
+
+ group.remove(ref);
+ QCOMPARE(group.contactGroupReferenceCount(), (unsigned int)0);
+ }
+
+ // data test
+ {
+ ContactGroup group(groupName);
+ QCOMPARE(group.dataCount(), (unsigned int)0);
+
+ ContactGroup::Data data(name, email);
+
+ group.append(data);
+ QCOMPARE(group.dataCount(), (unsigned int)1);
+
+ const ContactGroup::Data data2 = group.data(0);
+ QCOMPARE(data, data2);
+
+ group.remove(data);
+ QCOMPARE(group.dataCount(), (unsigned int)0);
+ }
+
+ // mimetype test
+ {
+ ContactGroup group(groupName);
+ QCOMPARE(group.mimeType(), QLatin1String("application/x-vnd.kde.contactgroup"));
+ }
+}
+
+void ContactGroupTest::testGroupRoundTrip()
+{
+ // TODO should also test empty group
+
+ ContactGroup group(QLatin1String("TestGroup"));
+ group.append(ContactGroup::ContactReference(QLatin1String("Xggdjetw")));
+ ContactGroup::ContactReference gidReference;
+ gidReference.setGid(QLatin1String("gid"));
+ group.append(gidReference);
+ group.append(ContactGroup::ContactGroupReference(QLatin1String("aaXggdjetw")));
+ group.append(ContactGroup::Data(QLatin1String("Tobias Koenig"),
+ QLatin1String("tokoe@kde.org")));
+ group.append(ContactGroup::Data(QLatin1String("Kevin Krammer"),
+ QLatin1String("kevin.krammer@gmx.at")));
+
+ QBuffer buffer;
+ buffer.open(QIODevice::WriteOnly);
+
+ QString errorMessage;
+ bool result = ContactGroupTool::convertToXml(group, &buffer, &errorMessage);
+
+ QVERIFY(result);
+ QVERIFY(errorMessage.isEmpty());
+ buffer.close();
+ QVERIFY(buffer.size() > 0);
+ buffer.open(QIODevice::ReadOnly);
+
+ ContactGroup group2;
+ result = ContactGroupTool::convertFromXml(&buffer, group2, &errorMessage);
+ QVERIFY(result);
+ QVERIFY(errorMessage.isEmpty());
+ QCOMPARE(group, group2);
+}
+
+void ContactGroupTest::testGroupListRoundTrip()
+{
+ // TODO should also test empty list
+
+ ContactGroup::List list;
+
+ ContactGroup group1(QLatin1String("TestGroup1"));
+ group1.append(ContactGroup::ContactReference(QLatin1String("Xggdjetw")));
+ group1.append(ContactGroup::Data(QLatin1String("Tobias Koenig"),
+ QLatin1String("tokoe@kde.org")));
+ group1.append(ContactGroup::Data(QLatin1String("Kevin Krammer"),
+ QLatin1String("kevin.krammer@gmx.at")));
+
+ list.append(group1);
+
+ ContactGroup group2(QLatin1String("TestGroup2"));
+ group2.append(ContactGroup::ContactReference(QLatin1String("Xggdjetw")));
+ group2.append(ContactGroup::Data(QLatin1String("Tobias Koenig"),
+ QLatin1String("tokoe@kde.org")));
+ group2.append(ContactGroup::Data(QLatin1String("Kevin Krammer"),
+ QLatin1String("kevin.krammer@gmx.at")));
+
+ list.append(group2);
+
+ QBuffer buffer;
+ buffer.open(QIODevice::WriteOnly);
+
+ QString errorMessage;
+ bool result = ContactGroupTool::convertToXml(list, &buffer, &errorMessage);
+
+ QVERIFY(result);
+ QVERIFY(errorMessage.isEmpty());
+ buffer.close();
+ QVERIFY(buffer.size() > 0);
+
+ buffer.open(QIODevice::ReadOnly);
+
+ ContactGroup::List list2;
+ result = ContactGroupTool::convertFromXml(&buffer, list2, &errorMessage);
+ QVERIFY(result);
+ QVERIFY(errorMessage.isEmpty());
+ QVERIFY(list2.size() == 2);
+ QCOMPARE(list2[0], group1);
+ QCOMPARE(list2[1], group2);
+}
+
+#include "contactgrouptest.moc"
--- /dev/null
+BEGIN:VCARD
+VERSION:4.0
+ADR;TYPE=parcel;TYPE=postal;TYPE=work:;;6544 Battleford Drive;Raleigh;NC;27
+ 613-3502;U.S.A.
+EMAIL;TYPE=PREF:Frank_Dawson@Lotus.com
+EMAIL:fdawson@earthlink.net
+FN:Frank Dawson
+N:;;;;
+ORG:Lotus Development Corporation
+TEL;TYPE=MSG;TYPE=VOICE;TYPE=WORK:+1-919-676-9515
+TEL;TYPE=FAX;TYPE=WORK:+1-919-676-9564
+UID:gDVbA6LY3t
+URL:http://home.earthlink.net/~fdawson
+END:VCARD
+
--- /dev/null
+BEGIN:VCARD
+VERSION:4.0
+ADR;TYPE=work:;;501 E. Middlefield Rd.;Mountain View;CA; 94043;U.S.A.
+EMAIL:howes@netscape.com
+FN:Tim Howes
+N:;;;;
+ORG:Netscape Communications Corp.
+TEL;TYPE=MSG;TYPE=VOICE;TYPE=WORK:+1-415-937-3419
+TEL;TYPE=FAX;TYPE=WORK:+1-415-528-4164
+UID:1UgvYejJMs
+END:VCARD
+
--- /dev/null
+BEGIN:VCARD
+VERSION:4.0
+EMAIL:geiseri@yahoo.com
+FN:ian geiser
+N:geiser;ian;;;
+ORG:Source eXtreme
+TITLE:VP of Engineering
+UID:ebvq9Wo9rO
+X-mozilla-cpt:;0
+X-mozilla-html:FALSE
+END:VCARD
+
--- /dev/null
+BEGIN:VCARD
+VERSION:4.0
+EMAIL:hello@ximian.com
+FN:
+LABEL;TYPE=work:401 Park Drive 3 West\nBoston\, MA 02215\nUSA
+NOTE:Welcome to the Ximian Addressbook.
+ORG:Ximian\, Inc.
+TEL;TYPE=VOICE;TYPE=WORK:(617) 236-0442
+TEL;TYPE=FAX;TYPE=WORK:(617) 236-8630
+UID:pas-id-3E136F9B00000000
+URL:www.ximian.com/
+X-EVOLUTION-FILE-AS:Ximian\, Inc.
+END:VCARD
+
--- /dev/null
+BEGIN:VCARD
+VERSION:4.0
+ADR;TYPE=home;TYPE=pref:;;Buehlauer Strasse 45;Dresden;Sachsen;01327;German
+ y
+ADR;TYPE=work:;;Prager Strasse 55;Dresden;Sachsen;01066;Germany
+BDAY:1955-07-19T00:00:00Z
+CATEGORIES:Friend
+CLASS:CONFIDENTIAL
+EMAIL;TYPE=PREF:heiko.mustermann@freenet.org
+EMAIL:heiko8@tst.inf.tu-dresden.de
+FN:Mustermann\, Heiko
+GEO:19.283333;166.616669
+LOGO;ENCODING=b;TYPE=image/png:iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAYAAABw4pVU
+ AAAOW0lEQVR4nO1df2hb1xX+OlyQwQEJXJAgBQlaiEwDsdqO2l1H47RjMe2gbjOoszG2dozG7aC
+ YMIqTjS7NYKSmbE1StsQpWxMXmsSF1WhlTeSwJlZY06gsSVXWUAkakKAGPajBDxrQ/jjnez8k27
+ EjJdyU+/0jPz29X9L57jnnO+deAxYWFhYWFhYWFu3Hbe082XT2ZF3+WgAAdHZ0AgBqTg0A4H7DT
+ 7oAgNSdKQDAg99/sK33caPB53RqFQBA5PYIAMBdkOf6yc9+ct3P852W786irWjJMs/8+0wdACpV
+ sZTS50V5vSLb1UoVQMCCvnFDx0c65f3BHw4CABJ3RL19mwYfM4Y1e/+0V5h/VbbPXzwPACiVSgA
+ A15XnikVjAIB44Dli3TIKjL+2e0XPYxliGFZshSdzZ+r8OyKGjdl8AQCQfe84AKBaFUaUrojlRL
+ vEUpx5h0eGjo9EZH+kQ7Yz9/d71+vdkAYApO+W16d+/NQNZ8ye8T11ACiV5TkcR5jufCX3XyrLc
+ 9XmxUe6bvi5XH3OaNRnSKRL9vWsywAAstNTyz6HZYhhsD+IYbjmMPDxfz6uA0BMqQcAR96eAgBM
+ vSevtTkJa6tzQnVSNn2XOLSZ03ljHHQ7MLxlSIa2kg5pOrTVHHHu/hANRDrke4t2y3cy+KgEMPs
+ P7F/0O7EMMQzXtNxLn16qA8DUu1nvvcm3DgEAFlxxbo4jFpFYK4woXix8qxhxLYxuH6sDQG5Gvq
+ NSueLtcxwdNTTASemoUTi3+HdkGWIYlrTkj2clzC1ckGRv3xv7vH2VK7QAlUDuktA0f/bG+YpL5
+ 4WpDDXv7TdPbjm472AdACbe9L+r4mdMHuW+42uTAIByuWwZciugY6kdER3zzn8iMkFt3pc93Kvy
+ d0QzvHYxI5h8Qq/BiK1YLur78nJw4mBIznj2V88ueg+HjxyrA0BEdE7EumLePp773u/e25b7jyb
+ kfAObh7z3SleELS40SVZ/u+2F0ToA7H99PHRtyxDD0GQZZ9RKKxUZ+/YdmAAAFD4peJ9hbF2dq7
+ aHGSpn12p+dJI7PQsAcDS3YcxfmZPXnrt65F40P+pd3wsgwF69x/xHedlWNkfX+PlUep0ck0omA
+ ACxO+R10w82tfRch8leAJOas82ek+cho/sfkGtnT8xYhpiMJh9CiytVZayjYIgO37KCmWgrOPy3
+ w3UAKKpsf/zd496+wkVhpOu5Lje0XS6X9X5lbJ49KxZIJqSSEu+Xrsj9V1Xw5OcBIPJBDoCfPw0
+ 9IVn0sanpOgA8NXR9JYBILO7/rd8n/RV9SM1tPg6wDDEOTQxhFEKLYjbuBljBX9tjzyox/Q+xQO
+ crOf7I20cAAIVz+cCnVNJu8Alo3Nb43nEjoSfa8dIOAMDs6Zy+3wcAyM3kvCtUyZ6qXLd0WZj6z
+ E+fAeAX4FZbYo5Fmt9zXfeanwEsQ4xDE0Nqbi203ZhztANVZUb2PdF+imqZLgLX0OvSd7lLbPO+
+ OFan1B8wGotEE3pCYfpWtX4A2L1rZ+gcHN+Pa8EtEpX3mR9tGlieKSf/dVJ9Ysl7j/fhMYTfuDa
+ ANMIyxDA0Z+r6Qy7MC1Mi3lge1PijTYetBNNTkjUfOjQJAMi+LzE6S7nJtX50krknE74hZQZbij
+ o19U7eKcfQAKuaP7lam+hRdZXl19kZX7Xe+PBG2acM7YzE9Bpi1UfeFN9G7Y6+77EfLR59UdGtV
+ X2G8D7IEPrf7PtZq2XdCmhiCBsUYnGxLJfxP5rzkI0Pb6wDwMypmWXHVupOk0eFEfQZIy+MAQB6
+ 79OGhnSvd0yk4c5o4c7Xamlrwj7Nqck9uVf5eblGVnONqIY1W38+4h3DyJH1i6j6jFi3+B1GaPm
+ 8RGFsa9qrqu7zI6KfHXtHmM8KKq8ZfNZg/rMcLEMMQ5NlH/zLwVDz28SbomVRUxI0RDZJZrqici
+ biYmHFz8Q6cmox6bR8bsfOVwD44ylzH47dgK9lTf5dqpOzZ0V1Hnh0AIDfXMdmO7Zx0h8MaO2aT
+ JtQf7D16Se9a9CS0+uEofQVmV7ZjqhPmXhrIvQcnV2doeemv6UfIysAeNoVg9TMfdLqZH3ILYIl
+ x36Oi/v+Knp+/mwhsFfHcR0X2W3Su0Gy4ZrG3tU5GaOHtwhzXv3jqwB8ZgFiaezamFVWAMDO30u
+ OQAsjfvFL8QHpdFLOoPE8FQXG99UvxecMbhameOrCnB8tbh0WtjA3IZuYl6TXC1PoY/b9eRwAUL
+ hYDH3emXdD20EwX4p3SzS4VKWQsAwxDPYHMQxLlnDpJNlbSyEO8BvjvDKrJnZFlcxJ+biGkRT6Y
+ nf45VMAqHypXfMa0uY+8JM2Fpycr+QzfQ+JM0+nhPoMBHit3FFxuHT6FB8rGsYnusWZVsoBAVOH
+ QzrlkoqlcW1qSyQkOMmsE+c9sk2Gy+d//Xzo+Ago40RD3wsARKMrG6oIyxDDsCRDOAtodLsU44M
+ d3QtXKcnzLGELoXN7cos4y3jcl0QAYOFrOZ4ySLGooWqgOYBs4XVp+Qw9i2XZX1GyZtIJvQdhRi
+ Il23S4ntgYSNB67xcWTs2ouDmn97FRrlX6MlzUSt8jo8XQlq0AgMm3J8Ln1OfmnBBg9U2DliGGY
+ UmGEON7pE1lVNtWAGD2IwlPK1fF6jhziGMxE8eR54QhnWtUatY5hpS5ixfCPmexsDHRLedOeDK6
+ YOARsdLxabHqVJIiozbvqQzvsZnvJ33r7dkgfuXQBWHC6NMSIrvqZ+grOTOsX+evPLlZRMlCXsv
+ GGsZn1osgOt7Q2rMaWIYYhmsyhAj+6tue2ybNZ59ruVfl5k614igL+90NvoNz9LT5jkJgKiVWS5
+ 8CAOVSGYAv9FU0eezXaItsHHkkCQBI360RnDKBzODx7iKNGcPa1FCZk3JArZzT53FC5yB4DxGN8
+ IY04d3+m+23AcDMqZmma6wWliGGYcUMCWL/G+HJJsNbhkPtPBxrGwv5pcufAgDcrzlPXayX430w
+ D2GMTx/CQlkqqUzokGO8MpZGUwtagqbASTAScuZ8ATOVlGa7wT6Jnnb/QacTaO4CFR0JFsXiiXj
+ oGrte3lUHgJ2/29ly46BliGG4LoY0YvLoZMgyjr9zXCKyTrEozuemsEfRjtEZfUq+4MvWjFxojd
+ ympTNqamq+iKjP8LJlln6VGQGxkj4hpS2lbJYeXC++xZuQpOxjO2hCi3f0lSxVtAOWIYahLQxpB
+ KXmijJjQed1R9nbptbNAhbbgRBoQYomxAobW0M5jvuWrpGQRj7MyFlsYg6RSDCS863ZnZf3EmuF
+ VcNPDMv9/FNKsfsPHAoxf/RFmbpWLLBtVa5JNvY90FcHWpueYRliGNrKkC/+90Ud8EucLjR7dtQ
+ 3qALLaCz7vsT9nO6V7vVXcqBi6jYUqHB7wyvCDWccz6kGpFU1ZqNCENWaKAWOMjZzn8RsbOTDgU
+ Ohz690vZJWYBliGNr6i1/6r0zM9LQqVXGZI3yqeQjfZ4ae2SCWyaY3QbhldOB7kqHHEuGaSiNe+
+ a3UXlh2zeiaKYOPS7nW19uA8dekPB3TXGf0xVEAgXKv1oCok+VOCcs2DbY2oWc5WIYYhrb4kOms
+ tFgWL0tUlf9QNB0ygcwoXw5XzQY3D9YBIK7M4MQZwM87HM1dSmzP1KgrFgv7joUFNjlwqSF5efV
+ 1YUHurFj32PYx75gdL+uUhbyuf6UZeq9WFznJv6KqL33fjYRliGFoiSGc0FLUxQW8VsolmsAa4U
+ VCSRnng1PlqBPFNO/gKnVs76RP6WRuo35q6HHJsqkKsPZOto7v2e1dY+QF8RkDfaqIdZCVmsOo+
+ swIjbX/GwnLEMPQEkPatZoomdE47QsAoHX6aDRcm+B4X/K6YbT+oYxg/ZttopzKxsmhgF8zrzR0
+ 0bDjhp/l8iL508s3lbcDliGGwf4ghsGIFXWONaxHAvgrDMVUhmGLEfuA4xoiT70rgQQdrteBr6X
+ bktcoF94G/GY6hrO5U9pipAEAz1mttmfFipXAMsQw3BD5fbVwuJbUGl868UJMXdNEa0eIdocLUJ
+ wH8souSfI8eV7DYcr2lPqDgUNlPtzKSqawIMXQ+3rn418PLEMMgxE+hNirCxkDQK82SrgqBqY5K
+ 1eZUanK+94ahrpaUfGCyCCDm0VMpDBImb4SaHKgD/FWFVVmMGFl6Tl3Qgpok0eXXwS5HbAMMQxG
+ MSSIsZekXNp7v8zKymzo0T26WpHO42MjNxsmGHWx6a6/rz/0uWDBi+coFJRdnDHLiI4rTqxQCmo
+ HLEMMgxFR1mJgMOQ1YHO7S14b1zQhQ5iHsLXoiM6g9SbTICDPdIRbiLw5kyqpNK72djNgGWIYjG
+ VIPB5e+cBrauvSdh5tGWKbEHMJFrn6HxDf0bNOfE+Na7cEWaFPT+m+oNMjip9J/pE90Xrz9GphG
+ WIYjGUIW/zZyMysOcrGuTjXVAwXjbgST0WjKbZ70nXkC77VFy9r/jEXZteC077W0NXCMsQwGJuH
+ NGJsp+QlfZqXsHWHKi4n1xS0YZvToWc+lPLr+U+k2BSqgV31MnNjvgfLEMNgjGWsFFytiM3WcZW
+ BOUWgoj6kqv/Ii00RXBm7GljViBFXwaD/d2IZYhiMjbKWgreUhlb3OAFz4CHZz6aGWHd4hTnHFc
+ WWjeBAeJKpKbAMMQy3HEO45Mfecfl3qNSyuB5iRtt/XP43hK5w3nK+4rcBNa7FZQIsQwyDMdFFq
+ xh9UZb+6HtIlr1wF8SHFM6JPsVGueDiMzej8W21sAwxDPYHMQy3nFNfCmltrKuWRDrhv0HlUMWV
+ 8Rrn1JsGyxDDYLS1XA927ZZWooL+MzC29sycuHmNCq3AMsQwfGt8CFHISwEqskbDWwPlkeVgGWJ
+ xczH20lidTXe3AixDLCwsLCwsviX4P68/8cprSSqmAAAAAElFTkSuQmCC
+N:Mustermann;Heiko;;;
+NICKNAME:clown
+NOTE:I'm a friendly note text\,\nplease copy me to your address book...
+ORG:KDE
+PHOTO;ENCODING=b;TYPE=image/png:iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAYAAABw4pV
+ UAAAOW0lEQVR4nO1df2hb1xX+OlyQwQEJXJAgBQlaiEwDsdqO2l1H47RjMe2gbjOoszG2dozG7a
+ CYMIqTjS7NYKSmbE1StsQpWxMXmsSF1WhlTeSwJlZY06gsSVXWUAkakKAGPajBDxrQ/jjnez8k2
+ 7EjJdyU+/0jPz29X9L57jnnO+deAxYWFhYWFhYWFu3Hbe082XT2ZF3+WgAAdHZ0AgBqTg0A4H7D
+ T7oAgNSdKQDAg99/sK33caPB53RqFQBA5PYIAMBdkOf6yc9+ct3P852W786irWjJMs/8+0wdACp
+ VsZTS50V5vSLb1UoVQMCCvnFDx0c65f3BHw4CABJ3RL19mwYfM4Y1e/+0V5h/VbbPXzwPACiVSg
+ AA15XnikVjAIB44Dli3TIKjL+2e0XPYxliGFZshSdzZ+r8OyKGjdl8AQCQfe84AKBaFUaUrojlR
+ LvEUpx5h0eGjo9EZH+kQ7Yz9/d71+vdkAYApO+W16d+/NQNZ8ye8T11ACiV5TkcR5jufCX3XyrL
+ c9XmxUe6bvi5XH3OaNRnSKRL9vWsywAAstNTyz6HZYhhsD+IYbjmMPDxfz6uA0BMqQcAR96eAgB
+ MvSevtTkJa6tzQnVSNn2XOLSZ03ljHHQ7MLxlSIa2kg5pOrTVHHHu/hANRDrke4t2y3cy+KgEMP
+ sP7F/0O7EMMQzXtNxLn16qA8DUu1nvvcm3DgEAFlxxbo4jFpFYK4woXix8qxhxLYxuH6sDQG5Gv
+ qNSueLtcxwdNTTASemoUTi3+HdkGWIYlrTkj2clzC1ckGRv3xv7vH2VK7QAlUDuktA0f/bG+YpL
+ 54WpDDXv7TdPbjm472AdACbe9L+r4mdMHuW+42uTAIByuWwZciugY6kdER3zzn8iMkFt3pc93Kv
+ yd0QzvHYxI5h8Qq/BiK1YLur78nJw4mBIznj2V88ueg+HjxyrA0BEdE7EumLePp773u/e25b7jy
+ bkfAObh7z3SleELS40SVZ/u+2F0ToA7H99PHRtyxDD0GQZZ9RKKxUZ+/YdmAAAFD4peJ9hbF2dq
+ 7aHGSpn12p+dJI7PQsAcDS3YcxfmZPXnrt65F40P+pd3wsgwF69x/xHedlWNkfX+PlUep0ck0om
+ AACxO+R10w82tfRch8leAJOas82ek+cho/sfkGtnT8xYhpiMJh9CiytVZayjYIgO37KCmWgrOPy
+ 3w3UAKKpsf/zd496+wkVhpOu5Lje0XS6X9X5lbJ49KxZIJqSSEu+Xrsj9V1Xw5OcBIPJBDoCfPw
+ 09IVn0sanpOgA8NXR9JYBILO7/rd8n/RV9SM1tPg6wDDEOTQxhFEKLYjbuBljBX9tjzyox/Q+xQ
+ OcrOf7I20cAAIVz+cCnVNJu8Alo3Nb43nEjoSfa8dIOAMDs6Zy+3wcAyM3kvCtUyZ6qXLd0WZj6
+ zE+fAeAX4FZbYo5Fmt9zXfeanwEsQ4xDE0Nqbi203ZhztANVZUb2PdF+imqZLgLX0OvSd7lLbPO
+ +OFan1B8wGotEE3pCYfpWtX4A2L1rZ+gcHN+Pa8EtEpX3mR9tGlieKSf/dVJ9Ysl7j/fhMYTfuD
+ aANMIyxDA0Z+r6Qy7MC1Mi3lge1PijTYetBNNTkjUfOjQJAMi+LzE6S7nJtX50krknE74hZQZbi
+ jo19U7eKcfQAKuaP7lam+hRdZXl19kZX7Xe+PBG2acM7YzE9Bpi1UfeFN9G7Y6+77EfLR59UdGt
+ VX2G8D7IEPrf7PtZq2XdCmhiCBsUYnGxLJfxP5rzkI0Pb6wDwMypmWXHVupOk0eFEfQZIy+MAQB
+ 679OGhnSvd0yk4c5o4c7Xamlrwj7Nqck9uVf5eblGVnONqIY1W38+4h3DyJH1i6j6jFi3+B1GaP
+ m8RGFsa9qrqu7zI6KfHXtHmM8KKq8ZfNZg/rMcLEMMQ5NlH/zLwVDz28SbomVRUxI0RDZJZrqic
+ ibiYmHFz8Q6cmox6bR8bsfOVwD44ylzH47dgK9lTf5dqpOzZ0V1Hnh0AIDfXMdmO7Zx0h8MaO2a
+ TJtQf7D16Se9a9CS0+uEofQVmV7ZjqhPmXhrIvQcnV2doeemv6UfIysAeNoVg9TMfdLqZH3ILYI
+ lx36Oi/v+Knp+/mwhsFfHcR0X2W3Su0Gy4ZrG3tU5GaOHtwhzXv3jqwB8ZgFiaezamFVWAMDO30
+ uOQAsjfvFL8QHpdFLOoPE8FQXG99UvxecMbhameOrCnB8tbh0WtjA3IZuYl6TXC1PoY/b9eRwAU
+ LhYDH3emXdD20EwX4p3SzS4VKWQsAwxDPYHMQxLlnDpJNlbSyEO8BvjvDKrJnZFlcxJ+biGkRT6
+ Ynf45VMAqHypXfMa0uY+8JM2Fpycr+QzfQ+JM0+nhPoMBHit3FFxuHT6FB8rGsYnusWZVsoBAVO
+ HQzrlkoqlcW1qSyQkOMmsE+c9sk2Gy+d//Xzo+Ago40RD3wsARKMrG6oIyxDDsCRDOAtodLsU44
+ Md3QtXKcnzLGELoXN7cos4y3jcl0QAYOFrOZ4ySLGooWqgOYBs4XVp+Qw9i2XZX1GyZtIJvQdhR
+ iIl23S4ntgYSNB67xcWTs2ouDmn97FRrlX6MlzUSt8jo8XQlq0AgMm3J8Ln1OfmnBBg9U2DliGG
+ YUmGEON7pE1lVNtWAGD2IwlPK1fF6jhziGMxE8eR54QhnWtUatY5hpS5ixfCPmexsDHRLedOeDK
+ 6YOARsdLxabHqVJIiozbvqQzvsZnvJ33r7dkgfuXQBWHC6NMSIrvqZ+grOTOsX+evPLlZRMlCXs
+ vGGsZn1osgOt7Q2rMaWIYYhmsyhAj+6tue2ybNZ59ruVfl5k614igL+90NvoNz9LT5jkJgKiVWS
+ 58CAOVSGYAv9FU0eezXaItsHHkkCQBI360RnDKBzODx7iKNGcPa1FCZk3JArZzT53FC5yB4DxGN
+ 8IY04d3+m+23AcDMqZmma6wWliGGYcUMCWL/G+HJJsNbhkPtPBxrGwv5pcufAgDcrzlPXayX430
+ wD2GMTx/CQlkqqUzokGO8MpZGUwtagqbASTAScuZ8ATOVlGa7wT6Jnnb/QacTaO4CFR0JFsXiiX
+ joGrte3lUHgJ2/29ly46BliGG4LoY0YvLoZMgyjr9zXCKyTrEozuemsEfRjtEZfUq+4MvWjFxoj
+ dympTNqamq+iKjP8LJlln6VGQGxkj4hpS2lbJYeXC++xZuQpOxjO2hCi3f0lSxVtAOWIYahLQxp
+ BKXmijJjQed1R9nbptbNAhbbgRBoQYomxAobW0M5jvuWrpGQRj7MyFlsYg6RSDCS863ZnZf3Emu
+ FVcNPDMv9/FNKsfsPHAoxf/RFmbpWLLBtVa5JNvY90FcHWpueYRliGNrKkC/+90Ud8EucLjR7dt
+ Q3qALLaCz7vsT9nO6V7vVXcqBi6jYUqHB7wyvCDWccz6kGpFU1ZqNCENWaKAWOMjZzn8RsbOTDg
+ UOhz690vZJWYBliGNr6i1/6r0zM9LQqVXGZI3yqeQjfZ4ae2SCWyaY3QbhldOB7kqHHEuGaSiNe
+ +a3UXlh2zeiaKYOPS7nW19uA8dekPB3TXGf0xVEAgXKv1oCok+VOCcs2DbY2oWc5WIYYhrb4kOm
+ stFgWL0tUlf9QNB0ygcwoXw5XzQY3D9YBIK7M4MQZwM87HM1dSmzP1KgrFgv7joUFNjlwqSF5ef
+ V1YUHurFj32PYx75gdL+uUhbyuf6UZeq9WFznJv6KqL33fjYRliGFoiSGc0FLUxQW8VsolmsAa4
+ UVCSRnng1PlqBPFNO/gKnVs76RP6WRuo35q6HHJsqkKsPZOto7v2e1dY+QF8RkDfaqIdZCVmsOo
+ +swIjbX/GwnLEMPQEkPatZoomdE47QsAoHX6aDRcm+B4X/K6YbT+oYxg/ZttopzKxsmhgF8zrzR
+ 00bDjhp/l8iL508s3lbcDliGGwf4ghsGIFXWONaxHAvgrDMVUhmGLEfuA4xoiT70rgQQdrteBr6
+ XbktcoF94G/GY6hrO5U9pipAEAz1mttmfFipXAMsQw3BD5fbVwuJbUGl868UJMXdNEa0eIdocLU
+ JwH8souSfI8eV7DYcr2lPqDgUNlPtzKSqawIMXQ+3rn418PLEMMgxE+hNirCxkDQK82SrgqBqY5
+ K1eZUanK+94ahrpaUfGCyCCDm0VMpDBImb4SaHKgD/FWFVVmMGFl6Tl3Qgpok0eXXwS5HbAMMQx
+ GMSSIsZekXNp7v8zKymzo0T26WpHO42MjNxsmGHWx6a6/rz/0uWDBi+coFJRdnDHLiI4rTqxQCm
+ oHLEMMgxFR1mJgMOQ1YHO7S14b1zQhQ5iHsLXoiM6g9SbTICDPdIRbiLw5kyqpNK72djNgGWIYj
+ GVIPB5e+cBrauvSdh5tGWKbEHMJFrn6HxDf0bNOfE+Na7cEWaFPT+m+oNMjip9J/pE90Xrz9Gph
+ GWIYjGUIW/zZyMysOcrGuTjXVAwXjbgST0WjKbZ70nXkC77VFy9r/jEXZteC077W0NXCMsQwGJu
+ HNGJsp+QlfZqXsHWHKi4n1xS0YZvToWc+lPLr+U+k2BSqgV31MnNjvgfLEMNgjGWsFFytiM3WcZ
+ WBOUWgoj6kqv/Ii00RXBm7GljViBFXwaD/d2IZYhiMjbKWgreUhlb3OAFz4CHZz6aGWHd4hTnHF
+ cWWjeBAeJKpKbAMMQy3HEO45Mfecfl3qNSyuB5iRtt/XP43hK5w3nK+4rcBNa7FZQIsQwyDMdFF
+ qxh9UZb+6HtIlr1wF8SHFM6JPsVGueDiMzej8W21sAwxDPYHMQy3nFNfCmltrKuWRDrhv0HlUMW
+ V8Rrn1JsGyxDDYLS1XA927ZZWooL+MzC29sycuHmNCq3AMsQwfGt8CFHISwEqskbDWwPlkeVgGW
+ JxczH20lidTXe3AixDLCwsLCwsviX4P68/8cprSSqmAAAAAElFTkSuQmCC
+ROLE:Developer
+SOUND;ENCODING=b:UklGRiQgAABXQVZFZm10IBAAAAABAAEAQB8AAEAfAAABAAgAZGF0YQAgAA
+ B/f39/f39/f39/f39/f4B/gH+Af4CAgIGBgYGBgYGBgYGBgYGBgYGBgIGAgICBgYGBgYGBgYCAg
+ YGAgICAgICAgIGBgICAgYCAgICBgICAgICAgICAgIGAgICAgYCAgICAgICAgICAgICAgICAgICA
+ gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC
+ AgICAgICAf4CAgICAgICAgICAgICAgIB/f4CAgICAgICAgIB/f4B/f39/f39/f3+AgICAf4CAf3
+ 9/gIB/f4CAgH9/gICAgH+AgICAgICAgICAf4CAgIB/gICAgICAgICAgICAgICAgICAgICAgICAg
+ ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA
+ gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC
+ AgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI
+ CAgICAgICAgICAgICAgICAgIB/gICAf39/f39/f3+Af4CAgICAgICAgICAgICAgICAgICAgICAg
+ ICAgICAgICAgICAgH9/f39/f39/f39/f39/f4CAgICAgICAgICAgICAgICAgICAgICAgICAgICA
+ gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC
+ AgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI
+ CAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
+ ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA
+ gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC
+ AgICAgICAgICAgIGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYCAgICAgICAgI
+ CAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
+ ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA
+ gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC
+ AgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI
+ CAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
+ ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA
+ gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC
+ AgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI
+ CAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
+ ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBgYCAgICB
+ gICAgYGBgICAgICAgICAgIGAgICBgICBgYGBgYGBgYGAgYGBgYCBgYGBgYGBgYGBgYGBgYGBgYG
+ BgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgICAgYGBgIGBgYGAgI
+ CAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
+ ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYGAgICAgICAgICAgICAgICAgICAgICA
+ gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC
+ AgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI
+ CAgICAgICAgICAgICAgICAgH+AgICAgICAgICAgICAgICAgICAf4CAgIB/gH+Af4B/f39/f39/f
+ 39/f39/f4CAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA
+ gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBgYG
+ BgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgY
+ GBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGAgIGBgYCAgICBgYCAgYGBgYCAgICBg
+ YCAgICAgICAgICAgICAgIGAgICAgICAgICAgICAgYGBgYGAgICAgIGBgYCAgICBgYGAgICAgIGA
+ gICAgICAgIGBgYCBgYGAgYGBgYGBgoGBgYGCgoGAgICBgYGBgYCBgYKCgYGBgYGBgYGAgYGBgH9
+ /gIB/f3+AgIB/gH9/gICAf4CBgYB/f35+gIB/f4CBgX9/gYCAgYKCgYCAgYOBgICAgoGAf4GCgn
+ 9/gIB/gICBgH5/f4GAfX+BgYB+fn9/fn+Afn6Af39+f35+fn9+fn6AgH9/f4CAgYCAgYKCgH9/g
+ IKBf3+AgYJ/f4GCg4F/gIGCgoOBfoCDgYF/fH+BgYGAfn6Af4CCgn58gIN/fX+AgICBgYGAgYCB
+ goOCgICBgYB/fXyBhIGAgH5+f4GBgX9/f35+gIKCgXt9goN/f318f4GAf4B/fHt9fn5+fXx+fn5
+ /gH9+fHx/gHx9f4CAfn18gIB9e4GBfn5+foCBfHyAgoGAfX6CgYCBgH+DgHt9gYN/fX2BhYB7en
+ 6AgH98foKCgH18foCAfoCAf4CAf31+fn+AgH1+goJ/fX5/gIKAgIGAfH6CgX17foCBf3+BgoB/g
+ YOBgIB/f4KDgoJ+e3+ChIOBfn1/gX+BfX2BgH59foCCfn1/gX99fICAgoB/f39/gISCf36AgoSB
+ foCBgYGAf4CCf4CCgX5/gYKDgYB/gH+BhIOBgYB/gIOEhIF9foGCg4OBgICBgoOCgICChIOBg4O
+ CgoSDgoKAgYKBgoODhISBf4CCg4SEgoGCg4SEgH6BhIWEgX+EhYKAgoKFhIB+gIKChYKAgYOCgo
+ B+gYWFhIKAg4WEg4ODhIWFhYaGhIWGhYWGh4eHhYOCgoSFg4B/gIB+fX1+fn57e3t7fHt6fH5/f
+ 4GDhYiMkJGQj5GVmZycmZiXlZGIfXRwcnZ4d3Nva2hoamppaWxvc3R0dXl+iJCPjZShqrCzvNHi
+ rFYxOmKSrJ6UmJOAbV1ZboSMjI6JfnNjW2JweYGFg4B/e3Z0c3Btc3p9fHp4fIGBf3+Dh4qLjJG
+ YnZuWkY6MhnpwbnN6fHlya2hlZmdmaW9ycXFzd3t/g42cpquzvMzd/sRADiBZkL6xpLa1jFpANV
+ iHoJ2ioJWGbEQ2VHaOm5aHhIFuYmZzgoVxZFxfdJCSgnt/kKewr7bDsopcSV6JopyRjpOQfmNXZ
+ HmGhYB8fXtvXExKXnyKgnJsc3t8fZC0ysfK0+vHTxEeXY6yr6rAxJRSNTdbh5+fp7KjglQ6PVx3
+ ho6Ph3dmW15oa2x0hIuNkK3R18jJ0Ys8LUlxkqais8WtdlBFT2yDjpywro9mS0VVaXaBiIdyX2J
+ rcG5udYKKjaXT4dfV2Y82JkBpiaKkvdO2eE9GTGZ4hZu6u51yTUNOX2l9kZWKdl5PXG93dHeAip
+ KZut7j2tacRjJIYHCOo77XvoRdVlFYZniVuL+kfl9ST1Rcb4mTjoNxW1pqdXd5fH6CiKHN4d7k2
+ 4E4N05Yaoqo1eO0emVbTU5ZdKDCuZV9b1tMSVlyiYp8dHl7cmpqdYCCgIqixNTR2OqnRTlPXFt3
+ ksbnw4lzcFdKS2KMtLWZiIZwV0lPZXZ1b3uNinZqbXJ3dX2XxOPg4/zDUDRCTUhmiMXx1p+If1g
+ +O1J7pK+yspN3W0pGVGdugYmCen54b21rb3V9i6vZ7vD92WpAS0gzSny04tq3qp5qPDhHX3uVrs
+ KukXVhT0hRYnF/gnuCh31ubG9zdHeMs+Dr8P7KalFVOylJeq7QzMPIqmtIRUZOY4KovqicknhZS
+ 1BWXWh6gIeLiH91b21vc4GcyuXt/umTZGhGIjJfh6y+yt7LkGlfTD1GYYOipKKwnXhkXldVUFhs
+ dYOMjYWBem9ucoCWvNTm9+2weHdZMSpQboujvtnUrY6BZEdDUmV4jZypppeFd2dcWVFWWWh8hYS
+ Ii393c3Z7iJ3A1ePp3aGDfVYyOVZkfJe5zsavpJNsU1BTVmR9kpmcn5uGdGxoWU5VVGZ0fIKLh4
+ F/d3Z6g4ufuc3e3depjoViPz9VWm2FqLu8tLGifmphWlJZbH+Lj5+elod+c19WU0xUZW11gISEg
+ nx6e3h6g4qWp7zM3NrSpZGIYkRFVVVlfZ6vsbW3qIl7b2BUWGVwe4ybn52TkIRuX2BVRVFjZmp7
+ hIF9fX12cnZ6eX6LlZyousfP0c++jot6X0ZRXF9sgaCnqa6yn4eAdGZZYGlvd4mcnqCWnY91aWN
+ cSUtYYmJxf399f351cXFzcHF4foOIlZ+hp7CytLm8uLKNg4RtYF5oanN8j5qZnqGaioV9dGpqb3
+ J1f42Rk5iZjIKAcmFcW1RXYGhwdXt+e3Z2c25tcXJxd3yChY2Tl5udn6Gho6ioq6uonoaHbWNzZ
+ GdxgoGPlZqdj5CJgHFzcWxwdH1/hYqOioSFfnFpaWBdX2Jqb3N5fHh4eHNxcXFxc3d7foOJjI6Q
+ lZOSlZOTl5eYnJucnpyZkYiEfnd1dnZ5fYKHio6QkIyHg394dHRzc3Z5fHt2enJrcG5obG9sbW9
+ ucHJzdnh3eXp5eXt9foCDhoeJjI6OkJGSk5aYmZudn6Gjn5qLh4J3cnJ0dHR5g4GEi42Ih4aBfH
+ h4dXR1eHl4dXhuaW5rZ2ltaWttbW5vcnR1dHZ2dXV2d3d7fn+BhIeIiYuOjpCTlJWZnJueoKarr
+ ZuJhntvaW1ucnh+hIWJi4qFg4F7d3V1c3R3fH1/gHlvbXJnXmdpYmdtamtxcW9vbm9tamxtbG5z
+ dXZ5fHx7fX9+fH6AgoWHioyNj5CRlZeYmp2TiYyGenp9eXh9fX19foB/fH1/e3p8e3l5e3x7e3x
+ 6d3FxcnBwcG9vb29vb29wb25tbWxsbW5vb3Fyc3N1dXV1dnd4ent9fn+BgoGAgoWEhoqJiYyLi4
+ yPioaLiYSEh4WDhIOCgoKAgX58fXx5eXp4eHl4dXZ1cnN0dHR1cnJycXBxcnJycW9ubGxsbW1ub
+ m5ub29vcXNzdHZ2dXh6enp+fn5/gYCBhIKFiYeGiomJi4qKjIuLjIyLiomKh4aKioeIiIWDgYB9
+ fHx7e3l4eHh2dnd3d3l7enp6enp5ent7e3x7enl6e3t7fHx7e3p8fX5/gIKDg4GCg4KCg4OEhoe
+ Hh4iJiomLjIqLi4uLi46Pjo2OjouJiomHh4aDgH9/fXp5eXh3d3h4eHh4d3V2d3Z0dnd0dXd3d3
+ p7fH59fX19fH5+fn+Af4CAf3+Af359f4KDgoSIiIeJjI6PkJOUk5SYmZiYmZqZmJqamJiZmJaWl
+ ZSTkZCQj46Ni4qHh4iFgoKBfn9+fn+AgYCAgYOCgoSEg4SFhIODg4OCgICBf35/gICAgYKCgYGD
+ hIOBgYOCgYGAgIGBgIGCgoKBgoSEg4KCgH9/f318fHt6e3t7enl5eHh5fH18foCAf4GDg4OFhoa
+ GhoeJh4aJioiIiYiIhoWGh4aGh4eHiImHh4mIiIeHh4iIiIqJioqJh4mKh4eJiYiHh4eHhoWGhY
+ OEhYWEhYWDg4SFhYWEg4SDgYKCgH+AgICBgoOCgYGBgYKEhoaGhoiIh4eJiYmKioqKiomKioiJi
+ oqJiYmJiIiIiYiHh4eHh4eGhYWFhISDgoKCgoKCgYGAf31+fXx9fn58e3x8fHx9fX19fX19fX19
+ fHx9fn5/gICBgYGCgoKCg4OCgoODgoKDg4OCgoKCgoGBgYGBgYGCgYCBgIGCgoKDg4KCg4OEhIS
+ FhYWFhYWFhYWFhoWGhoWEhISDg4ODg4ODg4ODg4SDgoKDg4OCg4SDgoKDgoGBgoGAgIB/f35+fn
+ 9+fn9/f35+fn5/gICAgIGBgYKCg4ODg4SEg4OEhIODhIODhIODg4ODg4OCgoKBgoKCg4OCgoODg
+ 4ODg4OEhISEhIWEhIWFhISEhISEhIWEhISEhIODhISEg4ODg4ODg4ODg4ODgoKCgoKCg4KCgoKC
+ goKCgoKCgoOCgoKCgoKBgYKCgoKCgoGBgYGAgICAgYGBgYCAf39/f39/f3+Af39/f39/f39/gIC
+ AgIB/f39/f39/gICAgIB/f39/gIB/f39/gH9/f39/f39/fn5+f39/f39/fn5+fn5/f39/f39/fn
+ 5+fn9/f39/f35+fn5+fn9/f35/f39+fn5+fn9/fn5+fn5+fn5+f39+fn5+fn19fX5+fn5+fn5+f
+ X5+fn5+fn5+fn19fn5+fn5+fX19fX59fn5+fn19fX19fX1+fX19fX19fX19fX19fX19fX19fX19
+ fX19fX19fX19fX19fX19fX19fX19fX19fXx9fX18fH19fXx8fXx9fXx8fHx8fHx8fH19fX19fXx
+ 9fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX
+ 19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19f
+ X19fX19fX19fX19fX19fX19fX19fX19fX1+fX5+fn19fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+
+ fn5+fn5+fn5+fn5+f39/fn5/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39
+ /f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f4B/f3
+ 9/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f
+ 39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/
+ f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f4B/f39/f39/f39/f39/f39/f39
+ /f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f3
+ 9/f39/f39/f39/f39/f39/f35+fn5+f35/f39/f39/f39/f39/f39/f39/f39/f39/f39/f35+f
+ 39+fn5/fn5+f39/fn9/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/
+ f39/f39/f39/f39/f39+fn9/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39
+ /f39/f39/f39/f39/f39/f39/f39/f4CAf39/f39/f39/gIB/f39/f39/f4B/f4CAgICAgICAgI
+ CAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
+ ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA
+ gICAgICAgICAgIB/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/gICAgIC
+ AgICAgICAgICAgICAgICAgICAgICAgIGBgYGAgYGBgICAgIGAgICBgYGAgYGBgYGBgYGBgYGBgY
+ GBgYGBgYGBgYGBgYGBgYGAgYCAgICAgICAgICAgICAgICAgICAgICAgICAgH+AgICAf39/gH9/f
+ 3+Af39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f4CAgH9/gIB/f39/f4B/f3+AgICAf4CA
+ gICAgICAgICAgICAgH9/f4CAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC
+ AgICAgICAgICAgICAgICAgICAgICAgIB/f39/f39/f39/f4CAf39/f39/f39/f39/f39/f39+fn
+ 9/fn5+fn5+fn5+fn5+fX19fX19fX19fX19fX19fX19fn5+fn5+fn9/f39/f4CAgICAgICBgYGBg
+ YGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYCAgICAgICAgICAgICAgICAgYGAgICA
+ gICAgICAgICAgICBgYGAgICAgICAgICAgICAgICAgICAgICAgIB/gICAgH9/f39/f39/f39/f39
+ /f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/gICAgICAf39/f39/gH+AgI
+ CAgICAgIB/f39/f39/f4B/f39/f39/f39/f39/f39/f39/f39/f39/f39/fn9/f39/f39/f39+f
+ 39/f39/f39/f39/f39/f39/f39/f4B/f4CAgICAf39/f39/gICAf39/gICAgICAgICAgICAgICA
+ gICAgIGAgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYCAgICBgYGBgYGBgYCBgYGBgYCAgIG
+ BgICAgICAgICAgICAgICAgICAgICAgICAgICBgICAgICAgICAgICAgICAgICAgICAgICAgICAgI
+ CAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
+ ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA
+ gICAgICAgICAgICAf3+AgIB/f4CAf39/f39/f3+AgICAgH+AgICAf3+AgICAgICAgH9/f39/f39
+ /f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f3
+ 9/f39/f39/gH9/gICAgICAgICAgIB/gICAgH+AgIB/f39/f39/gICAgICAgH9/f3+AgH9/f4B/f
+ 39/f39/f39/f39/f3+AgICAgICAf3+AgIB/f4CAgIB/f4CAgICAgICAgICAf39/f3+AgIB/f4CA
+ gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAf39/f39
+ /f4CAgH9/f39/f39/f39/f39/f39/f39/f39/f39/f4B/f39/f39/gIB/f39/f39/f39/gH9/f3
+ 9/f4CAgICAgIB/gICAgICAgICAgICAgICAgICAgICAgICAgH+AgICAf4CAgICAgICAgIB/gICAf
+ 4CAgICAgH+Af4CAgH9/f39/f39/f39/gICAgICAgICAgICAf39/f39/f4CAgH9/gICAf3+AgICA
+ gICAgICAgICAgICAgICAgICAgIB/f39/gIB/f4CAgIB/f4CAgH9/gICAf39/f39/f39/f39/f39
+ /f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f3
+ 9/f39/f39/f39/f39/f39/f39/f39/f39/f39/gICAf39/gH9/f3+AgH9/f39/f39/f39/f39/f
+ 39/f39/f39/f39/f39/f39/f39/gICAf3+AgH9/f3+AgH9/f4CAgH9/gICAgICAgICAgICAgICA
+ gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC
+ AgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI
+ CAgICAgICAgICAgICAgICAgICAgICBgYGBgIGBgYCAgYGAgICAgYCAgICAgICAgICAgICAgICAg
+ ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA
+ gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC
+ AgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI
+ CAgICAgICAgICAgICAgICAf39/f39/f4CAgIB/f4CAgICAgICAgICAgICAgICAgICAgICAgICAg
+ ICAf39/f3+Af39/f39/f39/f4B/f39/f4CAgICAgICAgICAgA==
+TEL;TYPE=HOME:0351 223344
+TEL;TYPE=WORK:0351 443322
+TEL;TYPE=CELL:0173 223344
+UID:P9HXg34Oav
+URL:http://www.mustermann.de/~heiko/
+X-KADDRESSBOOK-X-Anniversary:1982-07-07
+X-KADDRESSBOOK-X-AssistantsName:Mr. Smithers
+X-KADDRESSBOOK-X-Department:Edutainment
+X-KADDRESSBOOK-X-IMAddress:122334455
+X-KADDRESSBOOK-X-ManagersName:Mr. Burnes
+X-KADDRESSBOOK-X-Office:223 2nd stage
+X-KADDRESSBOOK-X-Profession:Clown
+X-KADDRESSBOOK-X-SpousesName:femal clown
+END:VCARD
+
--- /dev/null
+BEGIN:VCARD
+VERSION:4.0
+CLASS:PUBLIC
+EMAIL;TYPE=PREF:email1@abc.de
+EMAIL:email2@abc.de
+FN:Test User
+N:User;Test;;;
+UID:uJTkVqH5Qt
+END:VCARD
+
--- /dev/null
+BEGIN:VCARD
+VERSION:4.0
+FN:
+LABEL;TYPE=work:401 Park Drive 3 West\nBoston\, MA 02215\nUSA\nHerecomesye
+ tanotherline
+UID:pas-id-3E136F9B00000000
+END:VCARD
+
--- /dev/null
+BEGIN:VCARD
+VERSION:4.0
+FN:test
+N:test;;;;
+NOTE:line one\nline two\nline three\n
+UID:8OD165Pope
+END:VCARD
+
--- /dev/null
+BEGIN:vCard
+VERSION:3.0
+UID:gDVbA6LY3t
+FN:Frank Dawson
+ORG:Lotus Development Corporation
+ADR;TYPE=WORK,POSTAL,PARCEL:;;6544 Battleford Drive
+ ;Raleigh;NC;27613-3502;U.S.A.
+TEL;TYPE=VOICE,MSG,WORK:+1-919-676-9515
+TEL;TYPE=FAX,WORK:+1-919-676-9564
+EMAIL;TYPE=INTERNET,PREF:Frank_Dawson@Lotus.com
+EMAIL;TYPE=INTERNET:fdawson@earthlink.net
+URL:http://home.earthlink.net/~fdawson
+END:vCard
+
--- /dev/null
+BEGIN:VCARD\r
+VERSION:2.1\r
+ADR;PARCEL;POSTAL;WORK:;;6544 Battleford Drive;Raleigh;NC;27613-3502;U.S.A.\r
+EMAIL;INTERNET;PREF:Frank_Dawson@Lotus.com\r
+EMAIL;INTERNET:fdawson@earthlink.net\r
+FN:Frank Dawson\r
+N:;;;;\r
+ORG:Lotus Development Corporation\r
+TEL;MSG;VOICE;WORK:+1-919-676-9515\r
+TEL;FAX;WORK:+1-919-676-9564\r
+UID:gDVbA6LY3t\r
+URL:http://home.earthlink.net/~fdawson\r
+END:VCARD\r
+\r
--- /dev/null
+BEGIN:VCARD\r
+VERSION:3.0\r
+ADR;TYPE=parcel,postal,work:;;6544 Battleford Drive;Raleigh;NC;27613-3502;U\r
+ .S.A.\r
+EMAIL;TYPE=INTERNET,PREF:Frank_Dawson@Lotus.com\r
+EMAIL;TYPE=INTERNET:fdawson@earthlink.net\r
+FN:Frank Dawson\r
+N:;;;;\r
+ORG:Lotus Development Corporation\r
+TEL;TYPE=MSG,VOICE,WORK:+1-919-676-9515\r
+TEL;TYPE=FAX,WORK:+1-919-676-9564\r
+UID:gDVbA6LY3t\r
+URL:http://home.earthlink.net/~fdawson\r
+END:VCARD\r
+\r
--- /dev/null
+BEGIN:VCARD\r
+VERSION:2.1\r
+UID:bfa5fdc5-fbfc-4ce2-8196-29ca0deb3bd3\r
+ADR;WORK;CHARSET=UTF-8;ENCODING=QUOTED-PRINTABLE:;;=44=44=44=44=44=44=44=44=44=44=44=44=44=44=44=2D=53=74=61=C3=9F=65=20=\r
+=32=0A=30=30=30=30=30=20=44=44=44=44=44=44=44=44=44=44;;;;\r
+ORG:Bike Shop\r
+Note:This one has a funny character at the end in the contact list\r
+END:VCARD\r
+BEGIN:VCARD\r
+VERSION:2.1\r
+UID:f8361311-b25c-4237-a94e-3015d8fe19de\r
+N:;Broken;;;\r
+FN:Field after Address broken\r
+ADR;HOME;CHARSET=UTF-8;ENCODING=QUOTED-PRINTABLE:;;=41=41=41=41=41=41=41=2D=41=C3=A4=41=41=41=41=41=20=\r
+=31=31;=55=72=74;;=30=30=30=30=30;\r
+URL:http://some-webseite.com\r
+NOTE:This one's URL field is truncated (see contact's edit form). Remove the linebreak in the VCF's address field and the URL will will be correct.\r
+END:VCARD\r
+BEGIN:VCARD\r
+VERSION:2.1\r
+UID:462269fd-607c-4284-998b-6771143b63a7\r
+N:;Broken;;;\r
+FN:Field after Address not broken\r
+ADR;HOME;CHARSET=UTF-8;ENCODING=QUOTED-PRINTABLE:;;=41=41=41=41=41=41=41=2D=41=C3=A4=41=41=41=41=41=20=\r
+=31=31;=55=72=74;;=30=30=30=30=30;\r
+NOTE:this is identical to "Website broken", but with Note and URL swapped. The Note field does not get truncated as the URL field does.\r
+URL:http://some-webseite.com\r
+END:VCARD\r
+BEGIN:VCARD\r
+VERSION:2.1\r
+UID:b4fc4930-043f-446a-9a76-cf0b548368d8\r
+N:Name;Surname;;Dr. med.;\r
+FN:Dr. med. Surname Name\r
+TITLE;CHARSET=UTF-8;ENCODING=QUOTED-PRINTABLE:=46=61=63=68=61=72=7A=74=20=66=C3=BC=72=20=41=6C=6C=67=65=6D=65=69=6E=\r
+=6D=65=64=69=7A=69=6E\r
+NOTE;CHARSET=UTF-8;ENCODING=QUOTED-PRINTABLE:=53=70=72=65=63=68=7A=65=69=74=65=6E=3A=0A=4D=6F=20=20=20=38=E2=80=93=\r
+=31=32=2C=20=31=35=E2=80=93=31=38=0A=44=69=20=20=20=20=20=38=E2=80=93=\r
+=31=32=0A=4D=69=20=20=20=20=38=E2=80=93=31=32=2C=20=31=34=E2=80=93=31=\r
+=35=0A=44=6F=20=31=34=E2=80=93=31=39=0A=46=72=20=20=20=20=20=38=E2=80=\r
+=93=31=32\r
+END:VCARD\r
+BEGIN:VCARD\r
+VERSION:2.1\r
+UID:941b057d-e959-4644-b41f-e122b26c3807\r
+N:Doctor;Second;;;\r
+FN:Second Doctor\r
+ADR;WORK;CHARSET=UTF-8;ENCODING=QUOTED-PRINTABLE:;;=44=44=44=44=44=44=44=44=44=44=44=73=74=72=61=C3=9F=65=20=32=36=0A=30=\r
+=30=30=30=30=20=44=44=44=44=44=44=44=44=44=44=44=44=44=44=44=44=44;;;;\r
+ORG:\r
+TITLE:Dentist\r
+NOTE;CHARSET=UTF-8;ENCODING=QUOTED-PRINTABLE:=53=70=72=65=63=68=7A=65=69=74=65=6E=3A=0A=4D=6F=20=20=20=38=E2=80=93=\r
+=31=33=0A=44=69=20=20=20=31=30=E2=80=93=31=32=2C=20=31=33=E2=80=93=31=\r
+=38=0A=4D=69=20=20=31=30=E2=80=93=31=32=2C=20=31=33=E2=80=93=31=38=0A=\r
+=44=6F=20=20=31=33=E2=80=93=31=38=0A=46=72=20=20=20=20=20=20=38=E2=80=\r
+=93=31=32\r
+END:VCARD\r
--- /dev/null
+BEGIN:VCARD\r
+VERSION:3.0\r
+ADR;TYPE=work:;;DDDDDDDDDDDDDDD-Staße 2\n00000 DDDDDDDDDD;;;;\r
+N:;;;;\r
+NOTE:This one has a funny character at the end in the contact list\r
+ORG:Bike Shop\r
+UID:bfa5fdc5-fbfc-4ce2-8196-29ca0deb3bd3\r
+END:VCARD\r
+\r
+BEGIN:VCARD\r
+VERSION:3.0\r
+ADR;TYPE=home:;;AAAAAAA-AäAAAAA 11;Urt;;00000;\r
+FN:Field after Address broken\r
+N:;Broken;;;\r
+NOTE:This one's URL field is truncated (see contact's edit form). Remove th\r
+ e linebreak in the VCF's address field and the URL will will be correct.\r
+UID:f8361311-b25c-4237-a94e-3015d8fe19de\r
+URL:http://some-webseite.com\r
+END:VCARD\r
+\r
+BEGIN:VCARD\r
+VERSION:3.0\r
+ADR;TYPE=home:;;AAAAAAA-AäAAAAA 11;Urt;;00000;\r
+FN:Field after Address not broken\r
+N:;Broken;;;\r
+NOTE:this is identical to "Website broken"\, but with Note and URL swapped.\r
+ The Note field does not get truncated as the URL field does.\r
+UID:462269fd-607c-4284-998b-6771143b63a7\r
+URL:http://some-webseite.com\r
+END:VCARD\r
+\r
+BEGIN:VCARD\r
+VERSION:3.0\r
+FN:Dr. med. Surname Name\r
+N:Name;Surname;;Dr. med.;\r
+NOTE:Sprechzeiten:\nMo 8–12\, 15–18\nDi 8–12\nMi 8–12\, 14\r
+ –15\nDo 14–19\nFr 8–12\r
+TITLE:Facharzt für Allgemeinmedizin\r
+UID:b4fc4930-043f-446a-9a76-cf0b548368d8\r
+END:VCARD\r
+\r
+BEGIN:VCARD\r
+VERSION:3.0\r
+ADR;TYPE=work:;;DDDDDDDDDDDstraße 26\n00000 DDDDDDDDDDDDDDDDD;;;;\r
+FN:Second Doctor\r
+N:Doctor;Second;;;\r
+NOTE:Sprechzeiten:\nMo 8–13\nDi 10–12\, 13–18\nMi 10–12\, 13\r
+ –18\nDo 13–18\nFr 8–12\r
+TITLE:Dentist\r
+UID:941b057d-e959-4644-b41f-e122b26c3807\r
+END:VCARD\r
+\r
--- /dev/null
+BEGIN:VCARD
+CLASS:PUBLIC
+EMAIL;TYPE=HOME;X-EVOLUTION-UI-SLOT=2:thejoe@abc.com
+EMAIL;TYPE=WORK;X-EVOLUTION-UI-SLOT=1:johndoe@abc.com
+FN:Test User
+N:User;Test;;;
+UID:uJTkVqH5Qt
+VERSION:3.0
+END:VCARD
+
--- /dev/null
+BEGIN:VCARD\r
+VERSION:3.0\r
+CLASS:PUBLIC\r
+EMAIL;TYPE=HOME;X-EVOLUTION-UI-SLOT=2:thejoe@abc.com\r
+EMAIL;TYPE=WORK;X-EVOLUTION-UI-SLOT=1:johndoe@abc.com\r
+FN:Test User\r
+N:User;Test;;;\r
+UID:uJTkVqH5Qt\r
+END:VCARD\r
+\r
--- /dev/null
+BEGIN:VCARD\r
+VERSION:3.0\r
+UID:pas-id-54B2522600000001\r
+FN:Good Looking\r
+N:Looking;Good;;;\r
+PHOTO;TYPE=WORK;ENCODING=b:iVBORw0KGgoAAAANSUhEUgAAAAMAAAADCAIAAADZSiLoAAAA\r
+ CXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3wELCiUrjAUGmgAAABl0RVh0Q29tbWVudABDcm\r
+ VhdGVkIHdpdGggR0lNUFeBDhcAAAAZSURBVAjXY/zPAAVMDAwMDP//MzAwMMLFAEMrBAHo3Yr/\r
+ AAAAAElFTkSuQmCC\r
+PHOTO;TYPE=HOME;ENCODING=b:iVBORw0KGgoAAAANSUhEUgAAAAMAAAADCAIAAADZSiLoAAAA\r
+ CXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3wELCiQG0MFrrgAAABl0RVh0Q29tbWVudABDcm\r
+ VhdGVkIHdpdGggR0lNUFeBDhcAAAAUSURBVAjXY/j//z8DAwOEhAG4GACzagv1unIx3wAAAABJ\r
+ RU5ErkJggg==\r
+EMAIL;TYPE=WORK;X-EVOLUTION-UI-SLOT=1:goodlooking@example.com\r
+END:VCARD\r
--- /dev/null
+BEGIN:VCARD\r
+VERSION:3.0\r
+EMAIL;TYPE=WORK;X-EVOLUTION-UI-SLOT=1:goodlooking@example.com\r
+FN:Good Looking\r
+N:Looking;Good;;;\r
+PHOTO;ENCODING=b;TYPE=WORK:iVBORw0KGgoAAAANSUhEUgAAAAMAAAADCAIAAADZSiLoAAAA\r
+ CXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3wELCiUrjAUGmgAAABl0RVh0Q29tbWVudABDcmV\r
+ hdGVkIHdpdGggR0lNUFeBDhcAAAAZSURBVAjXY/zPAAVMDAwMDP//MzAwMMLFAEMrBAHo3Yr/AA\r
+ AAAElFTkSuQmCC\r
+PHOTO;ENCODING=b;TYPE=HOME:iVBORw0KGgoAAAANSUhEUgAAAAMAAAADCAIAAADZSiLoAAAA\r
+ CXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3wELCiQG0MFrrgAAABl0RVh0Q29tbWVudABDcmV\r
+ hdGVkIHdpdGggR0lNUFeBDhcAAAAUSURBVAjXY/j//z8DAwOEhAG4GACzagv1unIx3wAAAABJRU\r
+ 5ErkJggg==\r
+UID:pas-id-54B2522600000001\r
+END:VCARD\r
+\r
--- /dev/null
+BEGIN:VCARD
+CLASS:PUBLIC
+EMAIL;TYPE=HOME;X-EVOLUTION-UI-SLOT=2:thejoe@abc.com
+EMAIL;TYPE=WORK;X-EVOLUTION-UI-SLOT=1:johndoe@abc.com
+FN:Test User
+N:User;Test;;;
+UID:uJTkVqH5Qt
+URL:test1.url
+URL:test2.url
+VERSION:3.0
+END:VCARD
+
--- /dev/null
+BEGIN:VCARD\r
+VERSION:3.0\r
+CLASS:PUBLIC\r
+EMAIL;TYPE=HOME;X-EVOLUTION-UI-SLOT=2:thejoe@abc.com\r
+EMAIL;TYPE=WORK;X-EVOLUTION-UI-SLOT=1:johndoe@abc.com\r
+FN:Test User\r
+N:User;Test;;;\r
+UID:uJTkVqH5Qt\r
+URL:test1.url\r
+URL:test2.url\r
+END:VCARD\r
+\r
--- /dev/null
+BEGIN:VCARD\r
+VERSION:3.0\r
+CLASS:PUBLIC\r
+EMAIL;TYPE=HOME,PREF;X-EVOLUTION-UI-SLOT=2:thejoe@abc.com\r
+EMAIL;TYPE=WORK;X-EVOLUTION-UI-SLOT=1:johndoe@abc.com\r
+FN:Test User\r
+N:User;Test;;;\r
+UID:uJTkVqH5Qt\r
+SOURCE:http://www.kde.org\r
+SOURCE:http://www.kde1.org\r
+END:VCARD\r
+\r
--- /dev/null
+BEGIN:VCARD\r
+VERSION:2.1\r
+EMAIL;HOME;PREF;X-EVOLUTION-UI-SLOT=2:thejoe@abc.com\r
+EMAIL;WORK;X-EVOLUTION-UI-SLOT=1:johndoe@abc.com\r
+FN:Test User\r
+N:User;Test;;;\r
+SOURCE:http://www.kde.org\r
+SOURCE:http://www.kde1.org\r
+UID:uJTkVqH5Qt\r
+END:VCARD\r
+\r
--- /dev/null
+BEGIN:VCARD\r
+VERSION:3.0\r
+CLASS:PUBLIC\r
+EMAIL;TYPE=HOME,PREF;X-EVOLUTION-UI-SLOT=2:thejoe@abc.com\r
+EMAIL;TYPE=WORK;X-EVOLUTION-UI-SLOT=1:johndoe@abc.com\r
+FN:Test User\r
+N:User;Test;;;\r
+SOURCE:http://www.kde.org\r
+SOURCE:http://www.kde1.org\r
+UID:uJTkVqH5Qt\r
+END:VCARD\r
+\r
--- /dev/null
+BEGIN:vCard
+VERSION:3.0
+UID:1UgvYejJMs
+FN:Tim Howes
+ORG:Netscape Communications Corp.
+ADR;TYPE=WORK:;;501 E. Middlefield Rd.;Mountain View;
+ CA; 94043;U.S.A.
+TEL;TYPE=VOICE,MSG,WORK:+1-415-937-3419
+TEL;TYPE=FAX,WORK:+1-415-528-4164
+EMAIL;TYPE=INTERNET:howes@netscape.com
+END:vCard
+
--- /dev/null
+BEGIN:VCARD\r
+VERSION:2.1\r
+ADR;WORK:;;501 E. Middlefield Rd.;Mountain View;CA; 94043;U.S.A.\r
+EMAIL;INTERNET:howes@netscape.com\r
+FN:Tim Howes\r
+N:;;;;\r
+ORG:Netscape Communications Corp.\r
+TEL;MSG;VOICE;WORK:+1-415-937-3419\r
+TEL;FAX;WORK:+1-415-528-4164\r
+UID:1UgvYejJMs\r
+END:VCARD\r
+\r
--- /dev/null
+BEGIN:VCARD\r
+VERSION:3.0\r
+ADR;TYPE=work:;;501 E. Middlefield Rd.;Mountain View;CA; 94043;U.S.A.\r
+EMAIL;TYPE=INTERNET:howes@netscape.com\r
+FN:Tim Howes\r
+N:;;;;\r
+ORG:Netscape Communications Corp.\r
+TEL;TYPE=MSG,VOICE,WORK:+1-415-937-3419\r
+TEL;TYPE=FAX,WORK:+1-415-528-4164\r
+UID:1UgvYejJMs\r
+END:VCARD\r
+\r
--- /dev/null
+begin:vcard
+uid:ebvq9Wo9rO
+n:geiser;ian
+x-mozilla-html:FALSE
+org:Source eXtreme
+version:2.1
+email;internet:geiseri@yahoo.com
+title:VP of Engineering
+x-mozilla-cpt:;0
+fn:ian geiser
+end:vcard
+
--- /dev/null
+BEGIN:VCARD\r
+VERSION:2.1\r
+EMAIL;INTERNET:geiseri@yahoo.com\r
+FN:ian geiser\r
+N:geiser;ian;;;\r
+ORG:Source eXtreme\r
+TITLE:VP of Engineering\r
+UID:ebvq9Wo9rO\r
+X-mozilla-cpt:;0\r
+X-mozilla-html:FALSE\r
+END:VCARD\r
+\r
--- /dev/null
+BEGIN:VCARD\r
+VERSION:3.0\r
+EMAIL;TYPE=internet:geiseri@yahoo.com\r
+FN:ian geiser\r
+N:geiser;ian;;;\r
+ORG:Source eXtreme\r
+TITLE:VP of Engineering\r
+UID:ebvq9Wo9rO\r
+X-mozilla-cpt:;0\r
+X-mozilla-html:FALSE\r
+END:VCARD\r
+\r
--- /dev/null
+BEGIN:VCARD
+X-EVOLUTION-FILE-AS:Ximian, Inc.
+FN
+N:
+LABEL;QUOTED-PRINTABLE;WORK:401 Park Drive 3 West=0ABoston, MA 02215=0AUSA
+TEL;WORK;VOICE:(617) 236-0442
+TEL;WORK;FAX:(617) 236-8630
+EMAIL;INTERNET:hello@ximian.com
+URL:www.ximian.com/
+ORG:Ximian, Inc.
+NOTE:Welcome to the Ximian Addressbook.
+UID:pas-id-3E136F9B00000000
+END:VCARD
+
--- /dev/null
+BEGIN:VCARD\r
+VERSION:3.0\r
+EMAIL;TYPE=INTERNET:hello@ximian.com\r
+LABEL;TYPE=work:401 Park Drive 3 West\nBoston\, MA 02215\nUSA\r
+N:;;;;\r
+NOTE:Welcome to the Ximian Addressbook.\r
+ORG:Ximian\, Inc.\r
+TEL;TYPE=VOICE,WORK:(617) 236-0442\r
+TEL;TYPE=FAX,WORK:(617) 236-8630\r
+UID:pas-id-3E136F9B00000000\r
+URL:www.ximian.com/\r
+X-EVOLUTION-FILE-AS:Ximian\, Inc.\r
+END:VCARD\r
+\r
--- /dev/null
+BEGIN:VCARD
+ADR;TYPE=home;TYPE=pref:;;Buehlauer Strasse 45;Dresden;Sachsen;01327;German
+ y
+ADR;TYPE=work:;;Prager Strasse 55;Dresden;Sachsen;01066;Germany
+BDAY:1955-07-19T00:00:00Z
+CATEGORIES:Friend
+CLASS:CONFIDENTIAL
+EMAIL;TYPE=PREF:heiko.mustermann@freenet.org
+EMAIL:heiko8@tst.inf.tu-dresden.de
+FN:Mustermann, Heiko
+GEO:19.283333;166.616669
+LOGO;ENCODING=b;TYPE=image/png:iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAYAAABw4pVU
+ AAAOW0lEQVR4nO1df2hb1xX+OlyQwQEJXJAgBQlaiEwDsdqO2l1H47RjMe2gbjOoszG2dozG7aC
+ YMIqTjS7NYKSmbE1StsQpWxMXmsSF1WhlTeSwJlZY06gsSVXWUAkakKAGPajBDxrQ/jjnez8k27
+ EjJdyU+/0jPz29X9L57jnnO+deAxYWFhYWFhYWFu3Hbe082XT2ZF3+WgAAdHZ0AgBqTg0A4H7DT
+ 7oAgNSdKQDAg99/sK33caPB53RqFQBA5PYIAMBdkOf6yc9+ct3P852W786irWjJMs/8+0wdACpV
+ sZTS50V5vSLb1UoVQMCCvnFDx0c65f3BHw4CABJ3RL19mwYfM4Y1e/+0V5h/VbbPXzwPACiVSgA
+ A15XnikVjAIB44Dli3TIKjL+2e0XPYxliGFZshSdzZ+r8OyKGjdl8AQCQfe84AKBaFUaUrojlRL
+ vEUpx5h0eGjo9EZH+kQ7Yz9/d71+vdkAYApO+W16d+/NQNZ8ye8T11ACiV5TkcR5jufCX3XyrLc
+ 9XmxUe6bvi5XH3OaNRnSKRL9vWsywAAstNTyz6HZYhhsD+IYbjmMPDxfz6uA0BMqQcAR96eAgBM
+ vSevtTkJa6tzQnVSNn2XOLSZ03ljHHQ7MLxlSIa2kg5pOrTVHHHu/hANRDrke4t2y3cy+KgEMPs
+ P7F/0O7EMMQzXtNxLn16qA8DUu1nvvcm3DgEAFlxxbo4jFpFYK4woXix8qxhxLYxuH6sDQG5Gvq
+ NSueLtcxwdNTTASemoUTi3+HdkGWIYlrTkj2clzC1ckGRv3xv7vH2VK7QAlUDuktA0f/bG+YpL5
+ 4WpDDXv7TdPbjm472AdACbe9L+r4mdMHuW+42uTAIByuWwZciugY6kdER3zzn8iMkFt3pc93Kvy
+ d0QzvHYxI5h8Qq/BiK1YLur78nJw4mBIznj2V88ueg+HjxyrA0BEdE7EumLePp773u/e25b7jyb
+ kfAObh7z3SleELS40SVZ/u+2F0ToA7H99PHRtyxDD0GQZZ9RKKxUZ+/YdmAAAFD4peJ9hbF2dq7
+ aHGSpn12p+dJI7PQsAcDS3YcxfmZPXnrt65F40P+pd3wsgwF69x/xHedlWNkfX+PlUep0ck0omA
+ ACxO+R10w82tfRch8leAJOas82ek+cho/sfkGtnT8xYhpiMJh9CiytVZayjYIgO37KCmWgrOPy3
+ w3UAKKpsf/zd496+wkVhpOu5Lje0XS6X9X5lbJ49KxZIJqSSEu+Xrsj9V1Xw5OcBIPJBDoCfPw0
+ 9IVn0sanpOgA8NXR9JYBILO7/rd8n/RV9SM1tPg6wDDEOTQxhFEKLYjbuBljBX9tjzyox/Q+xQO
+ crOf7I20cAAIVz+cCnVNJu8Alo3Nb43nEjoSfa8dIOAMDs6Zy+3wcAyM3kvCtUyZ6qXLd0WZj6z
+ E+fAeAX4FZbYo5Fmt9zXfeanwEsQ4xDE0Nqbi203ZhztANVZUb2PdF+imqZLgLX0OvSd7lLbPO+
+ OFan1B8wGotEE3pCYfpWtX4A2L1rZ+gcHN+Pa8EtEpX3mR9tGlieKSf/dVJ9Ysl7j/fhMYTfuDa
+ ANMIyxDA0Z+r6Qy7MC1Mi3lge1PijTYetBNNTkjUfOjQJAMi+LzE6S7nJtX50krknE74hZQZbij
+ o19U7eKcfQAKuaP7lam+hRdZXl19kZX7Xe+PBG2acM7YzE9Bpi1UfeFN9G7Y6+77EfLR59UdGtV
+ X2G8D7IEPrf7PtZq2XdCmhiCBsUYnGxLJfxP5rzkI0Pb6wDwMypmWXHVupOk0eFEfQZIy+MAQB6
+ 79OGhnSvd0yk4c5o4c7Xamlrwj7Nqck9uVf5eblGVnONqIY1W38+4h3DyJH1i6j6jFi3+B1GaPm
+ 8RGFsa9qrqu7zI6KfHXtHmM8KKq8ZfNZg/rMcLEMMQ5NlH/zLwVDz28SbomVRUxI0RDZJZrqici
+ biYmHFz8Q6cmox6bR8bsfOVwD44ylzH47dgK9lTf5dqpOzZ0V1Hnh0AIDfXMdmO7Zx0h8MaO2aT
+ JtQf7D16Se9a9CS0+uEofQVmV7ZjqhPmXhrIvQcnV2doeemv6UfIysAeNoVg9TMfdLqZH3ILYIl
+ x36Oi/v+Knp+/mwhsFfHcR0X2W3Su0Gy4ZrG3tU5GaOHtwhzXv3jqwB8ZgFiaezamFVWAMDO30u
+ OQAsjfvFL8QHpdFLOoPE8FQXG99UvxecMbhameOrCnB8tbh0WtjA3IZuYl6TXC1PoY/b9eRwAUL
+ hYDH3emXdD20EwX4p3SzS4VKWQsAwxDPYHMQxLlnDpJNlbSyEO8BvjvDKrJnZFlcxJ+biGkRT6Y
+ nf45VMAqHypXfMa0uY+8JM2Fpycr+QzfQ+JM0+nhPoMBHit3FFxuHT6FB8rGsYnusWZVsoBAVOH
+ QzrlkoqlcW1qSyQkOMmsE+c9sk2Gy+d//Xzo+Ago40RD3wsARKMrG6oIyxDDsCRDOAtodLsU44M
+ d3QtXKcnzLGELoXN7cos4y3jcl0QAYOFrOZ4ySLGooWqgOYBs4XVp+Qw9i2XZX1GyZtIJvQdhRi
+ Il23S4ntgYSNB67xcWTs2ouDmn97FRrlX6MlzUSt8jo8XQlq0AgMm3J8Ln1OfmnBBg9U2DliGGY
+ UmGEON7pE1lVNtWAGD2IwlPK1fF6jhziGMxE8eR54QhnWtUatY5hpS5ixfCPmexsDHRLedOeDK6
+ YOARsdLxabHqVJIiozbvqQzvsZnvJ33r7dkgfuXQBWHC6NMSIrvqZ+grOTOsX+evPLlZRMlCXsv
+ GGsZn1osgOt7Q2rMaWIYYhmsyhAj+6tue2ybNZ59ruVfl5k614igL+90NvoNz9LT5jkJgKiVWS5
+ 8CAOVSGYAv9FU0eezXaItsHHkkCQBI360RnDKBzODx7iKNGcPa1FCZk3JArZzT53FC5yB4DxGN8
+ IY04d3+m+23AcDMqZmma6wWliGGYcUMCWL/G+HJJsNbhkPtPBxrGwv5pcufAgDcrzlPXayX430w
+ D2GMTx/CQlkqqUzokGO8MpZGUwtagqbASTAScuZ8ATOVlGa7wT6Jnnb/QacTaO4CFR0JFsXiiXj
+ oGrte3lUHgJ2/29ly46BliGG4LoY0YvLoZMgyjr9zXCKyTrEozuemsEfRjtEZfUq+4MvWjFxojd
+ ympTNqamq+iKjP8LJlln6VGQGxkj4hpS2lbJYeXC++xZuQpOxjO2hCi3f0lSxVtAOWIYahLQxpB
+ KXmijJjQed1R9nbptbNAhbbgRBoQYomxAobW0M5jvuWrpGQRj7MyFlsYg6RSDCS863ZnZf3EmuF
+ VcNPDMv9/FNKsfsPHAoxf/RFmbpWLLBtVa5JNvY90FcHWpueYRliGNrKkC/+90Ud8EucLjR7dtQ
+ 3qALLaCz7vsT9nO6V7vVXcqBi6jYUqHB7wyvCDWccz6kGpFU1ZqNCENWaKAWOMjZzn8RsbOTDgU
+ Ohz690vZJWYBliGNr6i1/6r0zM9LQqVXGZI3yqeQjfZ4ae2SCWyaY3QbhldOB7kqHHEuGaSiNe+
+ a3UXlh2zeiaKYOPS7nW19uA8dekPB3TXGf0xVEAgXKv1oCok+VOCcs2DbY2oWc5WIYYhrb4kOms
+ tFgWL0tUlf9QNB0ygcwoXw5XzQY3D9YBIK7M4MQZwM87HM1dSmzP1KgrFgv7joUFNjlwqSF5efV
+ 1YUHurFj32PYx75gdL+uUhbyuf6UZeq9WFznJv6KqL33fjYRliGFoiSGc0FLUxQW8VsolmsAa4U
+ VCSRnng1PlqBPFNO/gKnVs76RP6WRuo35q6HHJsqkKsPZOto7v2e1dY+QF8RkDfaqIdZCVmsOo+
+ swIjbX/GwnLEMPQEkPatZoomdE47QsAoHX6aDRcm+B4X/K6YbT+oYxg/ZttopzKxsmhgF8zrzR0
+ 0bDjhp/l8iL508s3lbcDliGGwf4ghsGIFXWONaxHAvgrDMVUhmGLEfuA4xoiT70rgQQdrteBr6X
+ bktcoF94G/GY6hrO5U9pipAEAz1mttmfFipXAMsQw3BD5fbVwuJbUGl868UJMXdNEa0eIdocLUJ
+ wH8souSfI8eV7DYcr2lPqDgUNlPtzKSqawIMXQ+3rn418PLEMMgxE+hNirCxkDQK82SrgqBqY5K
+ 1eZUanK+94ahrpaUfGCyCCDm0VMpDBImb4SaHKgD/FWFVVmMGFl6Tl3Qgpok0eXXwS5HbAMMQxG
+ MSSIsZekXNp7v8zKymzo0T26WpHO42MjNxsmGHWx6a6/rz/0uWDBi+coFJRdnDHLiI4rTqxQCmo
+ HLEMMgxFR1mJgMOQ1YHO7S14b1zQhQ5iHsLXoiM6g9SbTICDPdIRbiLw5kyqpNK72djNgGWIYjG
+ VIPB5e+cBrauvSdh5tGWKbEHMJFrn6HxDf0bNOfE+Na7cEWaFPT+m+oNMjip9J/pE90Xrz9GphG
+ WIYjGUIW/zZyMysOcrGuTjXVAwXjbgST0WjKbZ70nXkC77VFy9r/jEXZteC077W0NXCMsQwGJuH
+ NGJsp+QlfZqXsHWHKi4n1xS0YZvToWc+lPLr+U+k2BSqgV31MnNjvgfLEMNgjGWsFFytiM3WcZW
+ BOUWgoj6kqv/Ii00RXBm7GljViBFXwaD/d2IZYhiMjbKWgreUhlb3OAFz4CHZz6aGWHd4hTnHFc
+ WWjeBAeJKpKbAMMQy3HEO45Mfecfl3qNSyuB5iRtt/XP43hK5w3nK+4rcBNa7FZQIsQwyDMdFFq
+ xh9UZb+6HtIlr1wF8SHFM6JPsVGueDiMzej8W21sAwxDPYHMQy3nFNfCmltrKuWRDrhv0HlUMWV
+ 8Rrn1JsGyxDDYLS1XA927ZZWooL+MzC29sycuHmNCq3AMsQwfGt8CFHISwEqskbDWwPlkeVgGWJ
+ xczH20lidTXe3AixDLCwsLCwsviX4P68/8cprSSqmAAAAAElFTkSuQmCC
+N:Mustermann;Heiko;;;
+NICKNAME:clown
+NOTE:I'm a friendly note text,\nplease copy me to your address book...
+ORG:KDE
+PHOTO;ENCODING=b;TYPE=image/png:iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAYAAABw4pV
+ UAAAOW0lEQVR4nO1df2hb1xX+OlyQwQEJXJAgBQlaiEwDsdqO2l1H47RjMe2gbjOoszG2dozG7a
+ CYMIqTjS7NYKSmbE1StsQpWxMXmsSF1WhlTeSwJlZY06gsSVXWUAkakKAGPajBDxrQ/jjnez8k2
+ 7EjJdyU+/0jPz29X9L57jnnO+deAxYWFhYWFhYWFu3Hbe082XT2ZF3+WgAAdHZ0AgBqTg0A4H7D
+ T7oAgNSdKQDAg99/sK33caPB53RqFQBA5PYIAMBdkOf6yc9+ct3P852W786irWjJMs/8+0wdACp
+ VsZTS50V5vSLb1UoVQMCCvnFDx0c65f3BHw4CABJ3RL19mwYfM4Y1e/+0V5h/VbbPXzwPACiVSg
+ AA15XnikVjAIB44Dli3TIKjL+2e0XPYxliGFZshSdzZ+r8OyKGjdl8AQCQfe84AKBaFUaUrojlR
+ LvEUpx5h0eGjo9EZH+kQ7Yz9/d71+vdkAYApO+W16d+/NQNZ8ye8T11ACiV5TkcR5jufCX3XyrL
+ c9XmxUe6bvi5XH3OaNRnSKRL9vWsywAAstNTyz6HZYhhsD+IYbjmMPDxfz6uA0BMqQcAR96eAgB
+ MvSevtTkJa6tzQnVSNn2XOLSZ03ljHHQ7MLxlSIa2kg5pOrTVHHHu/hANRDrke4t2y3cy+KgEMP
+ sP7F/0O7EMMQzXtNxLn16qA8DUu1nvvcm3DgEAFlxxbo4jFpFYK4woXix8qxhxLYxuH6sDQG5Gv
+ qNSueLtcxwdNTTASemoUTi3+HdkGWIYlrTkj2clzC1ckGRv3xv7vH2VK7QAlUDuktA0f/bG+YpL
+ 54WpDDXv7TdPbjm472AdACbe9L+r4mdMHuW+42uTAIByuWwZciugY6kdER3zzn8iMkFt3pc93Kv
+ yd0QzvHYxI5h8Qq/BiK1YLur78nJw4mBIznj2V88ueg+HjxyrA0BEdE7EumLePp773u/e25b7jy
+ bkfAObh7z3SleELS40SVZ/u+2F0ToA7H99PHRtyxDD0GQZZ9RKKxUZ+/YdmAAAFD4peJ9hbF2dq
+ 7aHGSpn12p+dJI7PQsAcDS3YcxfmZPXnrt65F40P+pd3wsgwF69x/xHedlWNkfX+PlUep0ck0om
+ AACxO+R10w82tfRch8leAJOas82ek+cho/sfkGtnT8xYhpiMJh9CiytVZayjYIgO37KCmWgrOPy
+ 3w3UAKKpsf/zd496+wkVhpOu5Lje0XS6X9X5lbJ49KxZIJqSSEu+Xrsj9V1Xw5OcBIPJBDoCfPw
+ 09IVn0sanpOgA8NXR9JYBILO7/rd8n/RV9SM1tPg6wDDEOTQxhFEKLYjbuBljBX9tjzyox/Q+xQ
+ OcrOf7I20cAAIVz+cCnVNJu8Alo3Nb43nEjoSfa8dIOAMDs6Zy+3wcAyM3kvCtUyZ6qXLd0WZj6
+ zE+fAeAX4FZbYo5Fmt9zXfeanwEsQ4xDE0Nqbi203ZhztANVZUb2PdF+imqZLgLX0OvSd7lLbPO
+ +OFan1B8wGotEE3pCYfpWtX4A2L1rZ+gcHN+Pa8EtEpX3mR9tGlieKSf/dVJ9Ysl7j/fhMYTfuD
+ aANMIyxDA0Z+r6Qy7MC1Mi3lge1PijTYetBNNTkjUfOjQJAMi+LzE6S7nJtX50krknE74hZQZbi
+ jo19U7eKcfQAKuaP7lam+hRdZXl19kZX7Xe+PBG2acM7YzE9Bpi1UfeFN9G7Y6+77EfLR59UdGt
+ VX2G8D7IEPrf7PtZq2XdCmhiCBsUYnGxLJfxP5rzkI0Pb6wDwMypmWXHVupOk0eFEfQZIy+MAQB
+ 679OGhnSvd0yk4c5o4c7Xamlrwj7Nqck9uVf5eblGVnONqIY1W38+4h3DyJH1i6j6jFi3+B1GaP
+ m8RGFsa9qrqu7zI6KfHXtHmM8KKq8ZfNZg/rMcLEMMQ5NlH/zLwVDz28SbomVRUxI0RDZJZrqic
+ ibiYmHFz8Q6cmox6bR8bsfOVwD44ylzH47dgK9lTf5dqpOzZ0V1Hnh0AIDfXMdmO7Zx0h8MaO2a
+ TJtQf7D16Se9a9CS0+uEofQVmV7ZjqhPmXhrIvQcnV2doeemv6UfIysAeNoVg9TMfdLqZH3ILYI
+ lx36Oi/v+Knp+/mwhsFfHcR0X2W3Su0Gy4ZrG3tU5GaOHtwhzXv3jqwB8ZgFiaezamFVWAMDO30
+ uOQAsjfvFL8QHpdFLOoPE8FQXG99UvxecMbhameOrCnB8tbh0WtjA3IZuYl6TXC1PoY/b9eRwAU
+ LhYDH3emXdD20EwX4p3SzS4VKWQsAwxDPYHMQxLlnDpJNlbSyEO8BvjvDKrJnZFlcxJ+biGkRT6
+ Ynf45VMAqHypXfMa0uY+8JM2Fpycr+QzfQ+JM0+nhPoMBHit3FFxuHT6FB8rGsYnusWZVsoBAVO
+ HQzrlkoqlcW1qSyQkOMmsE+c9sk2Gy+d//Xzo+Ago40RD3wsARKMrG6oIyxDDsCRDOAtodLsU44
+ Md3QtXKcnzLGELoXN7cos4y3jcl0QAYOFrOZ4ySLGooWqgOYBs4XVp+Qw9i2XZX1GyZtIJvQdhR
+ iIl23S4ntgYSNB67xcWTs2ouDmn97FRrlX6MlzUSt8jo8XQlq0AgMm3J8Ln1OfmnBBg9U2DliGG
+ YUmGEON7pE1lVNtWAGD2IwlPK1fF6jhziGMxE8eR54QhnWtUatY5hpS5ixfCPmexsDHRLedOeDK
+ 6YOARsdLxabHqVJIiozbvqQzvsZnvJ33r7dkgfuXQBWHC6NMSIrvqZ+grOTOsX+evPLlZRMlCXs
+ vGGsZn1osgOt7Q2rMaWIYYhmsyhAj+6tue2ybNZ59ruVfl5k614igL+90NvoNz9LT5jkJgKiVWS
+ 58CAOVSGYAv9FU0eezXaItsHHkkCQBI360RnDKBzODx7iKNGcPa1FCZk3JArZzT53FC5yB4DxGN
+ 8IY04d3+m+23AcDMqZmma6wWliGGYcUMCWL/G+HJJsNbhkPtPBxrGwv5pcufAgDcrzlPXayX430
+ wD2GMTx/CQlkqqUzokGO8MpZGUwtagqbASTAScuZ8ATOVlGa7wT6Jnnb/QacTaO4CFR0JFsXiiX
+ joGrte3lUHgJ2/29ly46BliGG4LoY0YvLoZMgyjr9zXCKyTrEozuemsEfRjtEZfUq+4MvWjFxoj
+ dympTNqamq+iKjP8LJlln6VGQGxkj4hpS2lbJYeXC++xZuQpOxjO2hCi3f0lSxVtAOWIYahLQxp
+ BKXmijJjQed1R9nbptbNAhbbgRBoQYomxAobW0M5jvuWrpGQRj7MyFlsYg6RSDCS863ZnZf3Emu
+ FVcNPDMv9/FNKsfsPHAoxf/RFmbpWLLBtVa5JNvY90FcHWpueYRliGNrKkC/+90Ud8EucLjR7dt
+ Q3qALLaCz7vsT9nO6V7vVXcqBi6jYUqHB7wyvCDWccz6kGpFU1ZqNCENWaKAWOMjZzn8RsbOTDg
+ UOhz690vZJWYBliGNr6i1/6r0zM9LQqVXGZI3yqeQjfZ4ae2SCWyaY3QbhldOB7kqHHEuGaSiNe
+ +a3UXlh2zeiaKYOPS7nW19uA8dekPB3TXGf0xVEAgXKv1oCok+VOCcs2DbY2oWc5WIYYhrb4kOm
+ stFgWL0tUlf9QNB0ygcwoXw5XzQY3D9YBIK7M4MQZwM87HM1dSmzP1KgrFgv7joUFNjlwqSF5ef
+ V1YUHurFj32PYx75gdL+uUhbyuf6UZeq9WFznJv6KqL33fjYRliGFoiSGc0FLUxQW8VsolmsAa4
+ UVCSRnng1PlqBPFNO/gKnVs76RP6WRuo35q6HHJsqkKsPZOto7v2e1dY+QF8RkDfaqIdZCVmsOo
+ +swIjbX/GwnLEMPQEkPatZoomdE47QsAoHX6aDRcm+B4X/K6YbT+oYxg/ZttopzKxsmhgF8zrzR
+ 00bDjhp/l8iL508s3lbcDliGGwf4ghsGIFXWONaxHAvgrDMVUhmGLEfuA4xoiT70rgQQdrteBr6
+ XbktcoF94G/GY6hrO5U9pipAEAz1mttmfFipXAMsQw3BD5fbVwuJbUGl868UJMXdNEa0eIdocLU
+ JwH8souSfI8eV7DYcr2lPqDgUNlPtzKSqawIMXQ+3rn418PLEMMgxE+hNirCxkDQK82SrgqBqY5
+ K1eZUanK+94ahrpaUfGCyCCDm0VMpDBImb4SaHKgD/FWFVVmMGFl6Tl3Qgpok0eXXwS5HbAMMQx
+ GMSSIsZekXNp7v8zKymzo0T26WpHO42MjNxsmGHWx6a6/rz/0uWDBi+coFJRdnDHLiI4rTqxQCm
+ oHLEMMgxFR1mJgMOQ1YHO7S14b1zQhQ5iHsLXoiM6g9SbTICDPdIRbiLw5kyqpNK72djNgGWIYj
+ GVIPB5e+cBrauvSdh5tGWKbEHMJFrn6HxDf0bNOfE+Na7cEWaFPT+m+oNMjip9J/pE90Xrz9Gph
+ GWIYjGUIW/zZyMysOcrGuTjXVAwXjbgST0WjKbZ70nXkC77VFy9r/jEXZteC077W0NXCMsQwGJu
+ HNGJsp+QlfZqXsHWHKi4n1xS0YZvToWc+lPLr+U+k2BSqgV31MnNjvgfLEMNgjGWsFFytiM3WcZ
+ WBOUWgoj6kqv/Ii00RXBm7GljViBFXwaD/d2IZYhiMjbKWgreUhlb3OAFz4CHZz6aGWHd4hTnHF
+ cWWjeBAeJKpKbAMMQy3HEO45Mfecfl3qNSyuB5iRtt/XP43hK5w3nK+4rcBNa7FZQIsQwyDMdFF
+ qxh9UZb+6HtIlr1wF8SHFM6JPsVGueDiMzej8W21sAwxDPYHMQy3nFNfCmltrKuWRDrhv0HlUMW
+ V8Rrn1JsGyxDDYLS1XA927ZZWooL+MzC29sycuHmNCq3AMsQwfGt8CFHISwEqskbDWwPlkeVgGW
+ JxczH20lidTXe3AixDLCwsLCwsviX4P68/8cprSSqmAAAAAElFTkSuQmCC
+ROLE:Developer
+SOUND;ENCODING=b:UklGRiQgAABXQVZFZm10IBAAAAABAAEAQB8AAEAfAAABAAgAZGF0YQAgAA
+ B/f39/f39/f39/f39/f4B/gH+Af4CAgIGBgYGBgYGBgYGBgYGBgYGBgIGAgICBgYGBgYGBgYCAg
+ YGAgICAgICAgIGBgICAgYCAgICBgICAgICAgICAgIGAgICAgYCAgICAgICAgICAgICAgICAgICA
+ gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC
+ AgICAgICAf4CAgICAgICAgICAgICAgIB/f4CAgICAgICAgIB/f4B/f39/f39/f3+AgICAf4CAf3
+ 9/gIB/f4CAgH9/gICAgH+AgICAgICAgICAf4CAgIB/gICAgICAgICAgICAgICAgICAgICAgICAg
+ ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA
+ gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC
+ AgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI
+ CAgICAgICAgICAgICAgICAgIB/gICAf39/f39/f3+Af4CAgICAgICAgICAgICAgICAgICAgICAg
+ ICAgICAgICAgICAgH9/f39/f39/f39/f39/f4CAgICAgICAgICAgICAgICAgICAgICAgICAgICA
+ gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC
+ AgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI
+ CAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
+ ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA
+ gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC
+ AgICAgICAgICAgIGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYCAgICAgICAgI
+ CAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
+ ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA
+ gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC
+ AgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI
+ CAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
+ ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA
+ gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC
+ AgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI
+ CAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
+ ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBgYCAgICB
+ gICAgYGBgICAgICAgICAgIGAgICBgICBgYGBgYGBgYGAgYGBgYCBgYGBgYGBgYGBgYGBgYGBgYG
+ BgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgICAgYGBgIGBgYGAgI
+ CAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
+ ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYGAgICAgICAgICAgICAgICAgICAgICA
+ gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC
+ AgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI
+ CAgICAgICAgICAgICAgICAgH+AgICAgICAgICAgICAgICAgICAf4CAgIB/gH+Af4B/f39/f39/f
+ 39/f39/f4CAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA
+ gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBgYG
+ BgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgY
+ GBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGAgIGBgYCAgICBgYCAgYGBgYCAgICBg
+ YCAgICAgICAgICAgICAgIGAgICAgICAgICAgICAgYGBgYGAgICAgIGBgYCAgICBgYGAgICAgIGA
+ gICAgICAgIGBgYCBgYGAgYGBgYGBgoGBgYGCgoGAgICBgYGBgYCBgYKCgYGBgYGBgYGAgYGBgH9
+ /gIB/f3+AgIB/gH9/gICAf4CBgYB/f35+gIB/f4CBgX9/gYCAgYKCgYCAgYOBgICAgoGAf4GCgn
+ 9/gIB/gICBgH5/f4GAfX+BgYB+fn9/fn+Afn6Af39+f35+fn9+fn6AgH9/f4CAgYCAgYKCgH9/g
+ IKBf3+AgYJ/f4GCg4F/gIGCgoOBfoCDgYF/fH+BgYGAfn6Af4CCgn58gIN/fX+AgICBgYGAgYCB
+ goOCgICBgYB/fXyBhIGAgH5+f4GBgX9/f35+gIKCgXt9goN/f318f4GAf4B/fHt9fn5+fXx+fn5
+ /gH9+fHx/gHx9f4CAfn18gIB9e4GBfn5+foCBfHyAgoGAfX6CgYCBgH+DgHt9gYN/fX2BhYB7en
+ 6AgH98foKCgH18foCAfoCAf4CAf31+fn+AgH1+goJ/fX5/gIKAgIGAfH6CgX17foCBf3+BgoB/g
+ YOBgIB/f4KDgoJ+e3+ChIOBfn1/gX+BfX2BgH59foCCfn1/gX99fICAgoB/f39/gISCf36AgoSB
+ foCBgYGAf4CCf4CCgX5/gYKDgYB/gH+BhIOBgYB/gIOEhIF9foGCg4OBgICBgoOCgICChIOBg4O
+ CgoSDgoKAgYKBgoODhISBf4CCg4SEgoGCg4SEgH6BhIWEgX+EhYKAgoKFhIB+gIKChYKAgYOCgo
+ B+gYWFhIKAg4WEg4ODhIWFhYaGhIWGhYWGh4eHhYOCgoSFg4B/gIB+fX1+fn57e3t7fHt6fH5/f
+ 4GDhYiMkJGQj5GVmZycmZiXlZGIfXRwcnZ4d3Nva2hoamppaWxvc3R0dXl+iJCPjZShqrCzvNHi
+ rFYxOmKSrJ6UmJOAbV1ZboSMjI6JfnNjW2JweYGFg4B/e3Z0c3Btc3p9fHp4fIGBf3+Dh4qLjJG
+ YnZuWkY6MhnpwbnN6fHlya2hlZmdmaW9ycXFzd3t/g42cpquzvMzd/sRADiBZkL6xpLa1jFpANV
+ iHoJ2ioJWGbEQ2VHaOm5aHhIFuYmZzgoVxZFxfdJCSgnt/kKewr7bDsopcSV6JopyRjpOQfmNXZ
+ HmGhYB8fXtvXExKXnyKgnJsc3t8fZC0ysfK0+vHTxEeXY6yr6rAxJRSNTdbh5+fp7KjglQ6PVx3
+ ho6Ph3dmW15oa2x0hIuNkK3R18jJ0Ys8LUlxkqais8WtdlBFT2yDjpywro9mS0VVaXaBiIdyX2J
+ rcG5udYKKjaXT4dfV2Y82JkBpiaKkvdO2eE9GTGZ4hZu6u51yTUNOX2l9kZWKdl5PXG93dHeAip
+ KZut7j2tacRjJIYHCOo77XvoRdVlFYZniVuL+kfl9ST1Rcb4mTjoNxW1pqdXd5fH6CiKHN4d7k2
+ 4E4N05Yaoqo1eO0emVbTU5ZdKDCuZV9b1tMSVlyiYp8dHl7cmpqdYCCgIqixNTR2OqnRTlPXFt3
+ ksbnw4lzcFdKS2KMtLWZiIZwV0lPZXZ1b3uNinZqbXJ3dX2XxOPg4/zDUDRCTUhmiMXx1p+If1g
+ +O1J7pK+yspN3W0pGVGdugYmCen54b21rb3V9i6vZ7vD92WpAS0gzSny04tq3qp5qPDhHX3uVrs
+ KukXVhT0hRYnF/gnuCh31ubG9zdHeMs+Dr8P7KalFVOylJeq7QzMPIqmtIRUZOY4KovqicknhZS
+ 1BWXWh6gIeLiH91b21vc4GcyuXt/umTZGhGIjJfh6y+yt7LkGlfTD1GYYOipKKwnXhkXldVUFhs
+ dYOMjYWBem9ucoCWvNTm9+2weHdZMSpQboujvtnUrY6BZEdDUmV4jZypppeFd2dcWVFWWWh8hYS
+ Ii393c3Z7iJ3A1ePp3aGDfVYyOVZkfJe5zsavpJNsU1BTVmR9kpmcn5uGdGxoWU5VVGZ0fIKLh4
+ F/d3Z6g4ufuc3e3depjoViPz9VWm2FqLu8tLGifmphWlJZbH+Lj5+elod+c19WU0xUZW11gISEg
+ nx6e3h6g4qWp7zM3NrSpZGIYkRFVVVlfZ6vsbW3qIl7b2BUWGVwe4ybn52TkIRuX2BVRVFjZmp7
+ hIF9fX12cnZ6eX6LlZyousfP0c++jot6X0ZRXF9sgaCnqa6yn4eAdGZZYGlvd4mcnqCWnY91aWN
+ cSUtYYmJxf399f351cXFzcHF4foOIlZ+hp7CytLm8uLKNg4RtYF5oanN8j5qZnqGaioV9dGpqb3
+ J1f42Rk5iZjIKAcmFcW1RXYGhwdXt+e3Z2c25tcXJxd3yChY2Tl5udn6Gho6ioq6uonoaHbWNzZ
+ GdxgoGPlZqdj5CJgHFzcWxwdH1/hYqOioSFfnFpaWBdX2Jqb3N5fHh4eHNxcXFxc3d7foOJjI6Q
+ lZOSlZOTl5eYnJucnpyZkYiEfnd1dnZ5fYKHio6QkIyHg394dHRzc3Z5fHt2enJrcG5obG9sbW9
+ ucHJzdnh3eXp5eXt9foCDhoeJjI6OkJGSk5aYmZudn6Gjn5qLh4J3cnJ0dHR5g4GEi42Ih4aBfH
+ h4dXR1eHl4dXhuaW5rZ2ltaWttbW5vcnR1dHZ2dXV2d3d7fn+BhIeIiYuOjpCTlJWZnJueoKarr
+ ZuJhntvaW1ucnh+hIWJi4qFg4F7d3V1c3R3fH1/gHlvbXJnXmdpYmdtamtxcW9vbm9tamxtbG5z
+ dXZ5fHx7fX9+fH6AgoWHioyNj5CRlZeYmp2TiYyGenp9eXh9fX19foB/fH1/e3p8e3l5e3x7e3x
+ 6d3FxcnBwcG9vb29vb29wb25tbWxsbW5vb3Fyc3N1dXV1dnd4ent9fn+BgoGAgoWEhoqJiYyLi4
+ yPioaLiYSEh4WDhIOCgoKAgX58fXx5eXp4eHl4dXZ1cnN0dHR1cnJycXBxcnJycW9ubGxsbW1ub
+ m5ub29vcXNzdHZ2dXh6enp+fn5/gYCBhIKFiYeGiomJi4qKjIuLjIyLiomKh4aKioeIiIWDgYB9
+ fHx7e3l4eHh2dnd3d3l7enp6enp5ent7e3x7enl6e3t7fHx7e3p8fX5/gIKDg4GCg4KCg4OEhoe
+ Hh4iJiomLjIqLi4uLi46Pjo2OjouJiomHh4aDgH9/fXp5eXh3d3h4eHh4d3V2d3Z0dnd0dXd3d3
+ p7fH59fX19fH5+fn+Af4CAf3+Af359f4KDgoSIiIeJjI6PkJOUk5SYmZiYmZqZmJqamJiZmJaWl
+ ZSTkZCQj46Ni4qHh4iFgoKBfn9+fn+AgYCAgYOCgoSEg4SFhIODg4OCgICBf35/gICAgYKCgYGD
+ hIOBgYOCgYGAgIGBgIGCgoKBgoSEg4KCgH9/f318fHt6e3t7enl5eHh5fH18foCAf4GDg4OFhoa
+ GhoeJh4aJioiIiYiIhoWGh4aGh4eHiImHh4mIiIeHh4iIiIqJioqJh4mKh4eJiYiHh4eHhoWGhY
+ OEhYWEhYWDg4SFhYWEg4SDgYKCgH+AgICBgoOCgYGBgYKEhoaGhoiIh4eJiYmKioqKiomKioiJi
+ oqJiYmJiIiIiYiHh4eHh4eGhYWFhISDgoKCgoKCgYGAf31+fXx9fn58e3x8fHx9fX19fX19fX19
+ fHx9fn5/gICBgYGCgoKCg4OCgoODgoKDg4OCgoKCgoGBgYGBgYGCgYCBgIGCgoKDg4KCg4OEhIS
+ FhYWFhYWFhYWFhoWGhoWEhISDg4ODg4ODg4ODg4SDgoKDg4OCg4SDgoKDgoGBgoGAgIB/f35+fn
+ 9+fn9/f35+fn5/gICAgIGBgYKCg4ODg4SEg4OEhIODhIODhIODg4ODg4OCgoKBgoKCg4OCgoODg
+ 4ODg4OEhISEhIWEhIWFhISEhISEhIWEhISEhIODhISEg4ODg4ODg4ODg4ODgoKCgoKCg4KCgoKC
+ goKCgoKCgoOCgoKCgoKBgYKCgoKCgoGBgYGAgICAgYGBgYCAf39/f39/f3+Af39/f39/f39/gIC
+ AgIB/f39/f39/gICAgIB/f39/gIB/f39/gH9/f39/f39/fn5+f39/f39/fn5+fn5/f39/f39/fn
+ 5+fn9/f39/f35+fn5+fn9/f35/f39+fn5+fn9/fn5+fn5+fn5+f39+fn5+fn19fX5+fn5+fn5+f
+ X5+fn5+fn5+fn19fn5+fn5+fX19fX59fn5+fn19fX19fX1+fX19fX19fX19fX19fX19fX19fX19
+ fX19fX19fX19fX19fX19fX19fX19fX19fXx9fX18fH19fXx8fXx9fXx8fHx8fHx8fH19fX19fXx
+ 9fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX
+ 19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19f
+ X19fX19fX19fX19fX19fX19fX19fX19fX1+fX5+fn19fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+
+ fn5+fn5+fn5+fn5+f39/fn5/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39
+ /f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f4B/f3
+ 9/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f
+ 39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/
+ f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f4B/f39/f39/f39/f39/f39/f39
+ /f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f3
+ 9/f39/f39/f39/f39/f39/f35+fn5+f35/f39/f39/f39/f39/f39/f39/f39/f39/f39/f35+f
+ 39+fn5/fn5+f39/fn9/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/
+ f39/f39/f39/f39/f39+fn9/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39
+ /f39/f39/f39/f39/f39/f39/f39/f4CAf39/f39/f39/gIB/f39/f39/f4B/f4CAgICAgICAgI
+ CAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
+ ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA
+ gICAgICAgICAgIB/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/gICAgIC
+ AgICAgICAgICAgICAgICAgICAgICAgIGBgYGAgYGBgICAgIGAgICBgYGAgYGBgYGBgYGBgYGBgY
+ GBgYGBgYGBgYGBgYGBgYGAgYCAgICAgICAgICAgICAgICAgICAgICAgICAgH+AgICAf39/gH9/f
+ 3+Af39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f4CAgH9/gIB/f39/f4B/f3+AgICAf4CA
+ gICAgICAgICAgICAgH9/f4CAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC
+ AgICAgICAgICAgICAgICAgICAgICAgIB/f39/f39/f39/f4CAf39/f39/f39/f39/f39/f39+fn
+ 9/fn5+fn5+fn5+fn5+fX19fX19fX19fX19fX19fX19fn5+fn5+fn9/f39/f4CAgICAgICBgYGBg
+ YGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYCAgICAgICAgICAgICAgICAgYGAgICA
+ gICAgICAgICAgICBgYGAgICAgICAgICAgICAgICAgICAgICAgIB/gICAgH9/f39/f39/f39/f39
+ /f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/gICAgICAf39/f39/gH+AgI
+ CAgICAgIB/f39/f39/f4B/f39/f39/f39/f39/f39/f39/f39/f39/f39/fn9/f39/f39/f39+f
+ 39/f39/f39/f39/f39/f39/f39/f4B/f4CAgICAf39/f39/gICAf39/gICAgICAgICAgICAgICA
+ gICAgIGAgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYCAgICBgYGBgYGBgYCBgYGBgYCAgIG
+ BgICAgICAgICAgICAgICAgICAgICAgICAgICBgICAgICAgICAgICAgICAgICAgICAgICAgICAgI
+ CAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
+ ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA
+ gICAgICAgICAgICAf3+AgIB/f4CAf39/f39/f3+AgICAgH+AgICAf3+AgICAgICAgH9/f39/f39
+ /f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f3
+ 9/f39/f39/gH9/gICAgICAgICAgIB/gICAgH+AgIB/f39/f39/gICAgICAgH9/f3+AgH9/f4B/f
+ 39/f39/f39/f39/f3+AgICAgICAf3+AgIB/f4CAgIB/f4CAgICAgICAgICAf39/f3+AgIB/f4CA
+ gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAf39/f39
+ /f4CAgH9/f39/f39/f39/f39/f39/f39/f39/f39/f4B/f39/f39/gIB/f39/f39/f39/gH9/f3
+ 9/f4CAgICAgIB/gICAgICAgICAgICAgICAgICAgICAgICAgH+AgICAf4CAgICAgICAgIB/gICAf
+ 4CAgICAgH+Af4CAgH9/f39/f39/f39/gICAgICAgICAgICAf39/f39/f4CAgH9/gICAf3+AgICA
+ gICAgICAgICAgICAgICAgICAgIB/f39/gIB/f4CAgIB/f4CAgH9/gICAf39/f39/f39/f39/f39
+ /f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f3
+ 9/f39/f39/f39/f39/f39/f39/f39/f39/f39/gICAf39/gH9/f3+AgH9/f39/f39/f39/f39/f
+ 39/f39/f39/f39/f39/f39/f39/gICAf3+AgH9/f3+AgH9/f4CAgH9/gICAgICAgICAgICAgICA
+ gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC
+ AgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI
+ CAgICAgICAgICAgICAgICAgICAgICBgYGBgIGBgYCAgYGAgICAgYCAgICAgICAgICAgICAgICAg
+ ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA
+ gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC
+ AgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI
+ CAgICAgICAgICAgICAgICAf39/f39/f4CAgIB/f4CAgICAgICAgICAgICAgICAgICAgICAgICAg
+ ICAf39/f3+Af39/f39/f39/f4B/f39/f4CAgICAgICAgICAgA==
+TEL;TYPE=HOME:0351 223344
+TEL;TYPE=WORK:0351 443322
+TEL;TYPE=CELL:0173 223344
+UID:P9HXg34Oav
+URL:http://www.mustermann.de/~heiko/
+VERSION:3.0
+X-KADDRESSBOOK-X-Anniversary:1982-07-07
+X-KADDRESSBOOK-X-AssistantsName:Mr. Smithers
+X-KADDRESSBOOK-X-Department:Edutainment
+X-KADDRESSBOOK-X-IMAddress:122334455
+X-KADDRESSBOOK-X-ManagersName:Mr. Burnes
+X-KADDRESSBOOK-X-Office:223 2nd stage
+X-KADDRESSBOOK-X-Profession:Clown
+X-KADDRESSBOOK-X-SpousesName:femal clown
+END:VCARD
+
--- /dev/null
+BEGIN:VCARD\r
+VERSION:3.0\r
+ADR;TYPE=home,pref:;;Buehlauer Strasse 45;Dresden;Sachsen;01327;Germany\r
+ADR;TYPE=work:;;Prager Strasse 55;Dresden;Sachsen;01066;Germany\r
+BDAY:1955-07-19T00:00:00Z\r
+CATEGORIES:Friend\r
+CLASS:CONFIDENTIAL\r
+EMAIL;TYPE=PREF:heiko.mustermann@freenet.org\r
+EMAIL:heiko8@tst.inf.tu-dresden.de\r
+FN:Mustermann\, Heiko\r
+GEO:19.283333;166.616669\r
+LOGO;ENCODING=b;TYPE=image/png:iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAYAAABw4pVU\r
+ AAAOW0lEQVR4nO1df2hb1xX+OlyQwQEJXJAgBQlaiEwDsdqO2l1H47RjMe2gbjOoszG2dozG7aC\r
+ YMIqTjS7NYKSmbE1StsQpWxMXmsSF1WhlTeSwJlZY06gsSVXWUAkakKAGPajBDxrQ/jjnez8k27\r
+ EjJdyU+/0jPz29X9L57jnnO+deAxYWFhYWFhYWFu3Hbe082XT2ZF3+WgAAdHZ0AgBqTg0A4H7DT\r
+ 7oAgNSdKQDAg99/sK33caPB53RqFQBA5PYIAMBdkOf6yc9+ct3P852W786irWjJMs/8+0wdACpV\r
+ sZTS50V5vSLb1UoVQMCCvnFDx0c65f3BHw4CABJ3RL19mwYfM4Y1e/+0V5h/VbbPXzwPACiVSgA\r
+ A15XnikVjAIB44Dli3TIKjL+2e0XPYxliGFZshSdzZ+r8OyKGjdl8AQCQfe84AKBaFUaUrojlRL\r
+ vEUpx5h0eGjo9EZH+kQ7Yz9/d71+vdkAYApO+W16d+/NQNZ8ye8T11ACiV5TkcR5jufCX3XyrLc\r
+ 9XmxUe6bvi5XH3OaNRnSKRL9vWsywAAstNTyz6HZYhhsD+IYbjmMPDxfz6uA0BMqQcAR96eAgBM\r
+ vSevtTkJa6tzQnVSNn2XOLSZ03ljHHQ7MLxlSIa2kg5pOrTVHHHu/hANRDrke4t2y3cy+KgEMPs\r
+ P7F/0O7EMMQzXtNxLn16qA8DUu1nvvcm3DgEAFlxxbo4jFpFYK4woXix8qxhxLYxuH6sDQG5Gvq\r
+ NSueLtcxwdNTTASemoUTi3+HdkGWIYlrTkj2clzC1ckGRv3xv7vH2VK7QAlUDuktA0f/bG+YpL5\r
+ 4WpDDXv7TdPbjm472AdACbe9L+r4mdMHuW+42uTAIByuWwZciugY6kdER3zzn8iMkFt3pc93Kvy\r
+ d0QzvHYxI5h8Qq/BiK1YLur78nJw4mBIznj2V88ueg+HjxyrA0BEdE7EumLePp773u/e25b7jyb\r
+ kfAObh7z3SleELS40SVZ/u+2F0ToA7H99PHRtyxDD0GQZZ9RKKxUZ+/YdmAAAFD4peJ9hbF2dq7\r
+ aHGSpn12p+dJI7PQsAcDS3YcxfmZPXnrt65F40P+pd3wsgwF69x/xHedlWNkfX+PlUep0ck0omA\r
+ ACxO+R10w82tfRch8leAJOas82ek+cho/sfkGtnT8xYhpiMJh9CiytVZayjYIgO37KCmWgrOPy3\r
+ w3UAKKpsf/zd496+wkVhpOu5Lje0XS6X9X5lbJ49KxZIJqSSEu+Xrsj9V1Xw5OcBIPJBDoCfPw0\r
+ 9IVn0sanpOgA8NXR9JYBILO7/rd8n/RV9SM1tPg6wDDEOTQxhFEKLYjbuBljBX9tjzyox/Q+xQO\r
+ crOf7I20cAAIVz+cCnVNJu8Alo3Nb43nEjoSfa8dIOAMDs6Zy+3wcAyM3kvCtUyZ6qXLd0WZj6z\r
+ E+fAeAX4FZbYo5Fmt9zXfeanwEsQ4xDE0Nqbi203ZhztANVZUb2PdF+imqZLgLX0OvSd7lLbPO+\r
+ OFan1B8wGotEE3pCYfpWtX4A2L1rZ+gcHN+Pa8EtEpX3mR9tGlieKSf/dVJ9Ysl7j/fhMYTfuDa\r
+ ANMIyxDA0Z+r6Qy7MC1Mi3lge1PijTYetBNNTkjUfOjQJAMi+LzE6S7nJtX50krknE74hZQZbij\r
+ o19U7eKcfQAKuaP7lam+hRdZXl19kZX7Xe+PBG2acM7YzE9Bpi1UfeFN9G7Y6+77EfLR59UdGtV\r
+ X2G8D7IEPrf7PtZq2XdCmhiCBsUYnGxLJfxP5rzkI0Pb6wDwMypmWXHVupOk0eFEfQZIy+MAQB6\r
+ 79OGhnSvd0yk4c5o4c7Xamlrwj7Nqck9uVf5eblGVnONqIY1W38+4h3DyJH1i6j6jFi3+B1GaPm\r
+ 8RGFsa9qrqu7zI6KfHXtHmM8KKq8ZfNZg/rMcLEMMQ5NlH/zLwVDz28SbomVRUxI0RDZJZrqici\r
+ biYmHFz8Q6cmox6bR8bsfOVwD44ylzH47dgK9lTf5dqpOzZ0V1Hnh0AIDfXMdmO7Zx0h8MaO2aT\r
+ JtQf7D16Se9a9CS0+uEofQVmV7ZjqhPmXhrIvQcnV2doeemv6UfIysAeNoVg9TMfdLqZH3ILYIl\r
+ x36Oi/v+Knp+/mwhsFfHcR0X2W3Su0Gy4ZrG3tU5GaOHtwhzXv3jqwB8ZgFiaezamFVWAMDO30u\r
+ OQAsjfvFL8QHpdFLOoPE8FQXG99UvxecMbhameOrCnB8tbh0WtjA3IZuYl6TXC1PoY/b9eRwAUL\r
+ hYDH3emXdD20EwX4p3SzS4VKWQsAwxDPYHMQxLlnDpJNlbSyEO8BvjvDKrJnZFlcxJ+biGkRT6Y\r
+ nf45VMAqHypXfMa0uY+8JM2Fpycr+QzfQ+JM0+nhPoMBHit3FFxuHT6FB8rGsYnusWZVsoBAVOH\r
+ QzrlkoqlcW1qSyQkOMmsE+c9sk2Gy+d//Xzo+Ago40RD3wsARKMrG6oIyxDDsCRDOAtodLsU44M\r
+ d3QtXKcnzLGELoXN7cos4y3jcl0QAYOFrOZ4ySLGooWqgOYBs4XVp+Qw9i2XZX1GyZtIJvQdhRi\r
+ Il23S4ntgYSNB67xcWTs2ouDmn97FRrlX6MlzUSt8jo8XQlq0AgMm3J8Ln1OfmnBBg9U2DliGGY\r
+ UmGEON7pE1lVNtWAGD2IwlPK1fF6jhziGMxE8eR54QhnWtUatY5hpS5ixfCPmexsDHRLedOeDK6\r
+ YOARsdLxabHqVJIiozbvqQzvsZnvJ33r7dkgfuXQBWHC6NMSIrvqZ+grOTOsX+evPLlZRMlCXsv\r
+ GGsZn1osgOt7Q2rMaWIYYhmsyhAj+6tue2ybNZ59ruVfl5k614igL+90NvoNz9LT5jkJgKiVWS5\r
+ 8CAOVSGYAv9FU0eezXaItsHHkkCQBI360RnDKBzODx7iKNGcPa1FCZk3JArZzT53FC5yB4DxGN8\r
+ IY04d3+m+23AcDMqZmma6wWliGGYcUMCWL/G+HJJsNbhkPtPBxrGwv5pcufAgDcrzlPXayX430w\r
+ D2GMTx/CQlkqqUzokGO8MpZGUwtagqbASTAScuZ8ATOVlGa7wT6Jnnb/QacTaO4CFR0JFsXiiXj\r
+ oGrte3lUHgJ2/29ly46BliGG4LoY0YvLoZMgyjr9zXCKyTrEozuemsEfRjtEZfUq+4MvWjFxojd\r
+ ympTNqamq+iKjP8LJlln6VGQGxkj4hpS2lbJYeXC++xZuQpOxjO2hCi3f0lSxVtAOWIYahLQxpB\r
+ KXmijJjQed1R9nbptbNAhbbgRBoQYomxAobW0M5jvuWrpGQRj7MyFlsYg6RSDCS863ZnZf3EmuF\r
+ VcNPDMv9/FNKsfsPHAoxf/RFmbpWLLBtVa5JNvY90FcHWpueYRliGNrKkC/+90Ud8EucLjR7dtQ\r
+ 3qALLaCz7vsT9nO6V7vVXcqBi6jYUqHB7wyvCDWccz6kGpFU1ZqNCENWaKAWOMjZzn8RsbOTDgU\r
+ Ohz690vZJWYBliGNr6i1/6r0zM9LQqVXGZI3yqeQjfZ4ae2SCWyaY3QbhldOB7kqHHEuGaSiNe+\r
+ a3UXlh2zeiaKYOPS7nW19uA8dekPB3TXGf0xVEAgXKv1oCok+VOCcs2DbY2oWc5WIYYhrb4kOms\r
+ tFgWL0tUlf9QNB0ygcwoXw5XzQY3D9YBIK7M4MQZwM87HM1dSmzP1KgrFgv7joUFNjlwqSF5efV\r
+ 1YUHurFj32PYx75gdL+uUhbyuf6UZeq9WFznJv6KqL33fjYRliGFoiSGc0FLUxQW8VsolmsAa4U\r
+ VCSRnng1PlqBPFNO/gKnVs76RP6WRuo35q6HHJsqkKsPZOto7v2e1dY+QF8RkDfaqIdZCVmsOo+\r
+ swIjbX/GwnLEMPQEkPatZoomdE47QsAoHX6aDRcm+B4X/K6YbT+oYxg/ZttopzKxsmhgF8zrzR0\r
+ 0bDjhp/l8iL508s3lbcDliGGwf4ghsGIFXWONaxHAvgrDMVUhmGLEfuA4xoiT70rgQQdrteBr6X\r
+ bktcoF94G/GY6hrO5U9pipAEAz1mttmfFipXAMsQw3BD5fbVwuJbUGl868UJMXdNEa0eIdocLUJ\r
+ wH8souSfI8eV7DYcr2lPqDgUNlPtzKSqawIMXQ+3rn418PLEMMgxE+hNirCxkDQK82SrgqBqY5K\r
+ 1eZUanK+94ahrpaUfGCyCCDm0VMpDBImb4SaHKgD/FWFVVmMGFl6Tl3Qgpok0eXXwS5HbAMMQxG\r
+ MSSIsZekXNp7v8zKymzo0T26WpHO42MjNxsmGHWx6a6/rz/0uWDBi+coFJRdnDHLiI4rTqxQCmo\r
+ HLEMMgxFR1mJgMOQ1YHO7S14b1zQhQ5iHsLXoiM6g9SbTICDPdIRbiLw5kyqpNK72djNgGWIYjG\r
+ VIPB5e+cBrauvSdh5tGWKbEHMJFrn6HxDf0bNOfE+Na7cEWaFPT+m+oNMjip9J/pE90Xrz9GphG\r
+ WIYjGUIW/zZyMysOcrGuTjXVAwXjbgST0WjKbZ70nXkC77VFy9r/jEXZteC077W0NXCMsQwGJuH\r
+ NGJsp+QlfZqXsHWHKi4n1xS0YZvToWc+lPLr+U+k2BSqgV31MnNjvgfLEMNgjGWsFFytiM3WcZW\r
+ BOUWgoj6kqv/Ii00RXBm7GljViBFXwaD/d2IZYhiMjbKWgreUhlb3OAFz4CHZz6aGWHd4hTnHFc\r
+ WWjeBAeJKpKbAMMQy3HEO45Mfecfl3qNSyuB5iRtt/XP43hK5w3nK+4rcBNa7FZQIsQwyDMdFFq\r
+ xh9UZb+6HtIlr1wF8SHFM6JPsVGueDiMzej8W21sAwxDPYHMQy3nFNfCmltrKuWRDrhv0HlUMWV\r
+ 8Rrn1JsGyxDDYLS1XA927ZZWooL+MzC29sycuHmNCq3AMsQwfGt8CFHISwEqskbDWwPlkeVgGWJ\r
+ xczH20lidTXe3AixDLCwsLCwsviX4P68/8cprSSqmAAAAAElFTkSuQmCC\r
+N:Mustermann;Heiko;;;\r
+NICKNAME:clown\r
+NOTE:I'm a friendly note text\,\nplease copy me to your address book...\r
+ORG:KDE\r
+PHOTO;ENCODING=b;TYPE=image/png:iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAYAAABw4pV\r
+ UAAAOW0lEQVR4nO1df2hb1xX+OlyQwQEJXJAgBQlaiEwDsdqO2l1H47RjMe2gbjOoszG2dozG7a\r
+ CYMIqTjS7NYKSmbE1StsQpWxMXmsSF1WhlTeSwJlZY06gsSVXWUAkakKAGPajBDxrQ/jjnez8k2\r
+ 7EjJdyU+/0jPz29X9L57jnnO+deAxYWFhYWFhYWFu3Hbe082XT2ZF3+WgAAdHZ0AgBqTg0A4H7D\r
+ T7oAgNSdKQDAg99/sK33caPB53RqFQBA5PYIAMBdkOf6yc9+ct3P852W786irWjJMs/8+0wdACp\r
+ VsZTS50V5vSLb1UoVQMCCvnFDx0c65f3BHw4CABJ3RL19mwYfM4Y1e/+0V5h/VbbPXzwPACiVSg\r
+ AA15XnikVjAIB44Dli3TIKjL+2e0XPYxliGFZshSdzZ+r8OyKGjdl8AQCQfe84AKBaFUaUrojlR\r
+ LvEUpx5h0eGjo9EZH+kQ7Yz9/d71+vdkAYApO+W16d+/NQNZ8ye8T11ACiV5TkcR5jufCX3XyrL\r
+ c9XmxUe6bvi5XH3OaNRnSKRL9vWsywAAstNTyz6HZYhhsD+IYbjmMPDxfz6uA0BMqQcAR96eAgB\r
+ MvSevtTkJa6tzQnVSNn2XOLSZ03ljHHQ7MLxlSIa2kg5pOrTVHHHu/hANRDrke4t2y3cy+KgEMP\r
+ sP7F/0O7EMMQzXtNxLn16qA8DUu1nvvcm3DgEAFlxxbo4jFpFYK4woXix8qxhxLYxuH6sDQG5Gv\r
+ qNSueLtcxwdNTTASemoUTi3+HdkGWIYlrTkj2clzC1ckGRv3xv7vH2VK7QAlUDuktA0f/bG+YpL\r
+ 54WpDDXv7TdPbjm472AdACbe9L+r4mdMHuW+42uTAIByuWwZciugY6kdER3zzn8iMkFt3pc93Kv\r
+ yd0QzvHYxI5h8Qq/BiK1YLur78nJw4mBIznj2V88ueg+HjxyrA0BEdE7EumLePp773u/e25b7jy\r
+ bkfAObh7z3SleELS40SVZ/u+2F0ToA7H99PHRtyxDD0GQZZ9RKKxUZ+/YdmAAAFD4peJ9hbF2dq\r
+ 7aHGSpn12p+dJI7PQsAcDS3YcxfmZPXnrt65F40P+pd3wsgwF69x/xHedlWNkfX+PlUep0ck0om\r
+ AACxO+R10w82tfRch8leAJOas82ek+cho/sfkGtnT8xYhpiMJh9CiytVZayjYIgO37KCmWgrOPy\r
+ 3w3UAKKpsf/zd496+wkVhpOu5Lje0XS6X9X5lbJ49KxZIJqSSEu+Xrsj9V1Xw5OcBIPJBDoCfPw\r
+ 09IVn0sanpOgA8NXR9JYBILO7/rd8n/RV9SM1tPg6wDDEOTQxhFEKLYjbuBljBX9tjzyox/Q+xQ\r
+ OcrOf7I20cAAIVz+cCnVNJu8Alo3Nb43nEjoSfa8dIOAMDs6Zy+3wcAyM3kvCtUyZ6qXLd0WZj6\r
+ zE+fAeAX4FZbYo5Fmt9zXfeanwEsQ4xDE0Nqbi203ZhztANVZUb2PdF+imqZLgLX0OvSd7lLbPO\r
+ +OFan1B8wGotEE3pCYfpWtX4A2L1rZ+gcHN+Pa8EtEpX3mR9tGlieKSf/dVJ9Ysl7j/fhMYTfuD\r
+ aANMIyxDA0Z+r6Qy7MC1Mi3lge1PijTYetBNNTkjUfOjQJAMi+LzE6S7nJtX50krknE74hZQZbi\r
+ jo19U7eKcfQAKuaP7lam+hRdZXl19kZX7Xe+PBG2acM7YzE9Bpi1UfeFN9G7Y6+77EfLR59UdGt\r
+ VX2G8D7IEPrf7PtZq2XdCmhiCBsUYnGxLJfxP5rzkI0Pb6wDwMypmWXHVupOk0eFEfQZIy+MAQB\r
+ 679OGhnSvd0yk4c5o4c7Xamlrwj7Nqck9uVf5eblGVnONqIY1W38+4h3DyJH1i6j6jFi3+B1GaP\r
+ m8RGFsa9qrqu7zI6KfHXtHmM8KKq8ZfNZg/rMcLEMMQ5NlH/zLwVDz28SbomVRUxI0RDZJZrqic\r
+ ibiYmHFz8Q6cmox6bR8bsfOVwD44ylzH47dgK9lTf5dqpOzZ0V1Hnh0AIDfXMdmO7Zx0h8MaO2a\r
+ TJtQf7D16Se9a9CS0+uEofQVmV7ZjqhPmXhrIvQcnV2doeemv6UfIysAeNoVg9TMfdLqZH3ILYI\r
+ lx36Oi/v+Knp+/mwhsFfHcR0X2W3Su0Gy4ZrG3tU5GaOHtwhzXv3jqwB8ZgFiaezamFVWAMDO30\r
+ uOQAsjfvFL8QHpdFLOoPE8FQXG99UvxecMbhameOrCnB8tbh0WtjA3IZuYl6TXC1PoY/b9eRwAU\r
+ LhYDH3emXdD20EwX4p3SzS4VKWQsAwxDPYHMQxLlnDpJNlbSyEO8BvjvDKrJnZFlcxJ+biGkRT6\r
+ Ynf45VMAqHypXfMa0uY+8JM2Fpycr+QzfQ+JM0+nhPoMBHit3FFxuHT6FB8rGsYnusWZVsoBAVO\r
+ HQzrlkoqlcW1qSyQkOMmsE+c9sk2Gy+d//Xzo+Ago40RD3wsARKMrG6oIyxDDsCRDOAtodLsU44\r
+ Md3QtXKcnzLGELoXN7cos4y3jcl0QAYOFrOZ4ySLGooWqgOYBs4XVp+Qw9i2XZX1GyZtIJvQdhR\r
+ iIl23S4ntgYSNB67xcWTs2ouDmn97FRrlX6MlzUSt8jo8XQlq0AgMm3J8Ln1OfmnBBg9U2DliGG\r
+ YUmGEON7pE1lVNtWAGD2IwlPK1fF6jhziGMxE8eR54QhnWtUatY5hpS5ixfCPmexsDHRLedOeDK\r
+ 6YOARsdLxabHqVJIiozbvqQzvsZnvJ33r7dkgfuXQBWHC6NMSIrvqZ+grOTOsX+evPLlZRMlCXs\r
+ vGGsZn1osgOt7Q2rMaWIYYhmsyhAj+6tue2ybNZ59ruVfl5k614igL+90NvoNz9LT5jkJgKiVWS\r
+ 58CAOVSGYAv9FU0eezXaItsHHkkCQBI360RnDKBzODx7iKNGcPa1FCZk3JArZzT53FC5yB4DxGN\r
+ 8IY04d3+m+23AcDMqZmma6wWliGGYcUMCWL/G+HJJsNbhkPtPBxrGwv5pcufAgDcrzlPXayX430\r
+ wD2GMTx/CQlkqqUzokGO8MpZGUwtagqbASTAScuZ8ATOVlGa7wT6Jnnb/QacTaO4CFR0JFsXiiX\r
+ joGrte3lUHgJ2/29ly46BliGG4LoY0YvLoZMgyjr9zXCKyTrEozuemsEfRjtEZfUq+4MvWjFxoj\r
+ dympTNqamq+iKjP8LJlln6VGQGxkj4hpS2lbJYeXC++xZuQpOxjO2hCi3f0lSxVtAOWIYahLQxp\r
+ BKXmijJjQed1R9nbptbNAhbbgRBoQYomxAobW0M5jvuWrpGQRj7MyFlsYg6RSDCS863ZnZf3Emu\r
+ FVcNPDMv9/FNKsfsPHAoxf/RFmbpWLLBtVa5JNvY90FcHWpueYRliGNrKkC/+90Ud8EucLjR7dt\r
+ Q3qALLaCz7vsT9nO6V7vVXcqBi6jYUqHB7wyvCDWccz6kGpFU1ZqNCENWaKAWOMjZzn8RsbOTDg\r
+ UOhz690vZJWYBliGNr6i1/6r0zM9LQqVXGZI3yqeQjfZ4ae2SCWyaY3QbhldOB7kqHHEuGaSiNe\r
+ +a3UXlh2zeiaKYOPS7nW19uA8dekPB3TXGf0xVEAgXKv1oCok+VOCcs2DbY2oWc5WIYYhrb4kOm\r
+ stFgWL0tUlf9QNB0ygcwoXw5XzQY3D9YBIK7M4MQZwM87HM1dSmzP1KgrFgv7joUFNjlwqSF5ef\r
+ V1YUHurFj32PYx75gdL+uUhbyuf6UZeq9WFznJv6KqL33fjYRliGFoiSGc0FLUxQW8VsolmsAa4\r
+ UVCSRnng1PlqBPFNO/gKnVs76RP6WRuo35q6HHJsqkKsPZOto7v2e1dY+QF8RkDfaqIdZCVmsOo\r
+ +swIjbX/GwnLEMPQEkPatZoomdE47QsAoHX6aDRcm+B4X/K6YbT+oYxg/ZttopzKxsmhgF8zrzR\r
+ 00bDjhp/l8iL508s3lbcDliGGwf4ghsGIFXWONaxHAvgrDMVUhmGLEfuA4xoiT70rgQQdrteBr6\r
+ XbktcoF94G/GY6hrO5U9pipAEAz1mttmfFipXAMsQw3BD5fbVwuJbUGl868UJMXdNEa0eIdocLU\r
+ JwH8souSfI8eV7DYcr2lPqDgUNlPtzKSqawIMXQ+3rn418PLEMMgxE+hNirCxkDQK82SrgqBqY5\r
+ K1eZUanK+94ahrpaUfGCyCCDm0VMpDBImb4SaHKgD/FWFVVmMGFl6Tl3Qgpok0eXXwS5HbAMMQx\r
+ GMSSIsZekXNp7v8zKymzo0T26WpHO42MjNxsmGHWx6a6/rz/0uWDBi+coFJRdnDHLiI4rTqxQCm\r
+ oHLEMMgxFR1mJgMOQ1YHO7S14b1zQhQ5iHsLXoiM6g9SbTICDPdIRbiLw5kyqpNK72djNgGWIYj\r
+ GVIPB5e+cBrauvSdh5tGWKbEHMJFrn6HxDf0bNOfE+Na7cEWaFPT+m+oNMjip9J/pE90Xrz9Gph\r
+ GWIYjGUIW/zZyMysOcrGuTjXVAwXjbgST0WjKbZ70nXkC77VFy9r/jEXZteC077W0NXCMsQwGJu\r
+ HNGJsp+QlfZqXsHWHKi4n1xS0YZvToWc+lPLr+U+k2BSqgV31MnNjvgfLEMNgjGWsFFytiM3WcZ\r
+ WBOUWgoj6kqv/Ii00RXBm7GljViBFXwaD/d2IZYhiMjbKWgreUhlb3OAFz4CHZz6aGWHd4hTnHF\r
+ cWWjeBAeJKpKbAMMQy3HEO45Mfecfl3qNSyuB5iRtt/XP43hK5w3nK+4rcBNa7FZQIsQwyDMdFF\r
+ qxh9UZb+6HtIlr1wF8SHFM6JPsVGueDiMzej8W21sAwxDPYHMQy3nFNfCmltrKuWRDrhv0HlUMW\r
+ V8Rrn1JsGyxDDYLS1XA927ZZWooL+MzC29sycuHmNCq3AMsQwfGt8CFHISwEqskbDWwPlkeVgGW\r
+ JxczH20lidTXe3AixDLCwsLCwsviX4P68/8cprSSqmAAAAAElFTkSuQmCC\r
+ROLE:Developer\r
+SOUND;ENCODING=b:UklGRiQgAABXQVZFZm10IBAAAAABAAEAQB8AAEAfAAABAAgAZGF0YQAgAA\r
+ B/f39/f39/f39/f39/f4B/gH+Af4CAgIGBgYGBgYGBgYGBgYGBgYGBgIGAgICBgYGBgYGBgYCAg\r
+ YGAgICAgICAgIGBgICAgYCAgICBgICAgICAgICAgIGAgICAgYCAgICAgICAgICAgICAgICAgICA\r
+ gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC\r
+ AgICAgICAf4CAgICAgICAgICAgICAgIB/f4CAgICAgICAgIB/f4B/f39/f39/f3+AgICAf4CAf3\r
+ 9/gIB/f4CAgH9/gICAgH+AgICAgICAgICAf4CAgIB/gICAgICAgICAgICAgICAgICAgICAgICAg\r
+ ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA\r
+ gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC\r
+ AgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI\r
+ CAgICAgICAgICAgICAgICAgIB/gICAf39/f39/f3+Af4CAgICAgICAgICAgICAgICAgICAgICAg\r
+ ICAgICAgICAgICAgH9/f39/f39/f39/f39/f4CAgICAgICAgICAgICAgICAgICAgICAgICAgICA\r
+ gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC\r
+ AgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI\r
+ CAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg\r
+ ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA\r
+ gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC\r
+ AgICAgICAgICAgIGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYCAgICAgICAgI\r
+ CAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg\r
+ ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA\r
+ gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC\r
+ AgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI\r
+ CAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg\r
+ ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA\r
+ gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC\r
+ AgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI\r
+ CAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg\r
+ ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBgYCAgICB\r
+ gICAgYGBgICAgICAgICAgIGAgICBgICBgYGBgYGBgYGAgYGBgYCBgYGBgYGBgYGBgYGBgYGBgYG\r
+ BgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgICAgYGBgIGBgYGAgI\r
+ CAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg\r
+ ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYGAgICAgICAgICAgICAgICAgICAgICA\r
+ gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC\r
+ AgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI\r
+ CAgICAgICAgICAgICAgICAgH+AgICAgICAgICAgICAgICAgICAf4CAgIB/gH+Af4B/f39/f39/f\r
+ 39/f39/f4CAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA\r
+ gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBgYG\r
+ BgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgY\r
+ GBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGAgIGBgYCAgICBgYCAgYGBgYCAgICBg\r
+ YCAgICAgICAgICAgICAgIGAgICAgICAgICAgICAgYGBgYGAgICAgIGBgYCAgICBgYGAgICAgIGA\r
+ gICAgICAgIGBgYCBgYGAgYGBgYGBgoGBgYGCgoGAgICBgYGBgYCBgYKCgYGBgYGBgYGAgYGBgH9\r
+ /gIB/f3+AgIB/gH9/gICAf4CBgYB/f35+gIB/f4CBgX9/gYCAgYKCgYCAgYOBgICAgoGAf4GCgn\r
+ 9/gIB/gICBgH5/f4GAfX+BgYB+fn9/fn+Afn6Af39+f35+fn9+fn6AgH9/f4CAgYCAgYKCgH9/g\r
+ IKBf3+AgYJ/f4GCg4F/gIGCgoOBfoCDgYF/fH+BgYGAfn6Af4CCgn58gIN/fX+AgICBgYGAgYCB\r
+ goOCgICBgYB/fXyBhIGAgH5+f4GBgX9/f35+gIKCgXt9goN/f318f4GAf4B/fHt9fn5+fXx+fn5\r
+ /gH9+fHx/gHx9f4CAfn18gIB9e4GBfn5+foCBfHyAgoGAfX6CgYCBgH+DgHt9gYN/fX2BhYB7en\r
+ 6AgH98foKCgH18foCAfoCAf4CAf31+fn+AgH1+goJ/fX5/gIKAgIGAfH6CgX17foCBf3+BgoB/g\r
+ YOBgIB/f4KDgoJ+e3+ChIOBfn1/gX+BfX2BgH59foCCfn1/gX99fICAgoB/f39/gISCf36AgoSB\r
+ foCBgYGAf4CCf4CCgX5/gYKDgYB/gH+BhIOBgYB/gIOEhIF9foGCg4OBgICBgoOCgICChIOBg4O\r
+ CgoSDgoKAgYKBgoODhISBf4CCg4SEgoGCg4SEgH6BhIWEgX+EhYKAgoKFhIB+gIKChYKAgYOCgo\r
+ B+gYWFhIKAg4WEg4ODhIWFhYaGhIWGhYWGh4eHhYOCgoSFg4B/gIB+fX1+fn57e3t7fHt6fH5/f\r
+ 4GDhYiMkJGQj5GVmZycmZiXlZGIfXRwcnZ4d3Nva2hoamppaWxvc3R0dXl+iJCPjZShqrCzvNHi\r
+ rFYxOmKSrJ6UmJOAbV1ZboSMjI6JfnNjW2JweYGFg4B/e3Z0c3Btc3p9fHp4fIGBf3+Dh4qLjJG\r
+ YnZuWkY6MhnpwbnN6fHlya2hlZmdmaW9ycXFzd3t/g42cpquzvMzd/sRADiBZkL6xpLa1jFpANV\r
+ iHoJ2ioJWGbEQ2VHaOm5aHhIFuYmZzgoVxZFxfdJCSgnt/kKewr7bDsopcSV6JopyRjpOQfmNXZ\r
+ HmGhYB8fXtvXExKXnyKgnJsc3t8fZC0ysfK0+vHTxEeXY6yr6rAxJRSNTdbh5+fp7KjglQ6PVx3\r
+ ho6Ph3dmW15oa2x0hIuNkK3R18jJ0Ys8LUlxkqais8WtdlBFT2yDjpywro9mS0VVaXaBiIdyX2J\r
+ rcG5udYKKjaXT4dfV2Y82JkBpiaKkvdO2eE9GTGZ4hZu6u51yTUNOX2l9kZWKdl5PXG93dHeAip\r
+ KZut7j2tacRjJIYHCOo77XvoRdVlFYZniVuL+kfl9ST1Rcb4mTjoNxW1pqdXd5fH6CiKHN4d7k2\r
+ 4E4N05Yaoqo1eO0emVbTU5ZdKDCuZV9b1tMSVlyiYp8dHl7cmpqdYCCgIqixNTR2OqnRTlPXFt3\r
+ ksbnw4lzcFdKS2KMtLWZiIZwV0lPZXZ1b3uNinZqbXJ3dX2XxOPg4/zDUDRCTUhmiMXx1p+If1g\r
+ +O1J7pK+yspN3W0pGVGdugYmCen54b21rb3V9i6vZ7vD92WpAS0gzSny04tq3qp5qPDhHX3uVrs\r
+ KukXVhT0hRYnF/gnuCh31ubG9zdHeMs+Dr8P7KalFVOylJeq7QzMPIqmtIRUZOY4KovqicknhZS\r
+ 1BWXWh6gIeLiH91b21vc4GcyuXt/umTZGhGIjJfh6y+yt7LkGlfTD1GYYOipKKwnXhkXldVUFhs\r
+ dYOMjYWBem9ucoCWvNTm9+2weHdZMSpQboujvtnUrY6BZEdDUmV4jZypppeFd2dcWVFWWWh8hYS\r
+ Ii393c3Z7iJ3A1ePp3aGDfVYyOVZkfJe5zsavpJNsU1BTVmR9kpmcn5uGdGxoWU5VVGZ0fIKLh4\r
+ F/d3Z6g4ufuc3e3depjoViPz9VWm2FqLu8tLGifmphWlJZbH+Lj5+elod+c19WU0xUZW11gISEg\r
+ nx6e3h6g4qWp7zM3NrSpZGIYkRFVVVlfZ6vsbW3qIl7b2BUWGVwe4ybn52TkIRuX2BVRVFjZmp7\r
+ hIF9fX12cnZ6eX6LlZyousfP0c++jot6X0ZRXF9sgaCnqa6yn4eAdGZZYGlvd4mcnqCWnY91aWN\r
+ cSUtYYmJxf399f351cXFzcHF4foOIlZ+hp7CytLm8uLKNg4RtYF5oanN8j5qZnqGaioV9dGpqb3\r
+ J1f42Rk5iZjIKAcmFcW1RXYGhwdXt+e3Z2c25tcXJxd3yChY2Tl5udn6Gho6ioq6uonoaHbWNzZ\r
+ GdxgoGPlZqdj5CJgHFzcWxwdH1/hYqOioSFfnFpaWBdX2Jqb3N5fHh4eHNxcXFxc3d7foOJjI6Q\r
+ lZOSlZOTl5eYnJucnpyZkYiEfnd1dnZ5fYKHio6QkIyHg394dHRzc3Z5fHt2enJrcG5obG9sbW9\r
+ ucHJzdnh3eXp5eXt9foCDhoeJjI6OkJGSk5aYmZudn6Gjn5qLh4J3cnJ0dHR5g4GEi42Ih4aBfH\r
+ h4dXR1eHl4dXhuaW5rZ2ltaWttbW5vcnR1dHZ2dXV2d3d7fn+BhIeIiYuOjpCTlJWZnJueoKarr\r
+ ZuJhntvaW1ucnh+hIWJi4qFg4F7d3V1c3R3fH1/gHlvbXJnXmdpYmdtamtxcW9vbm9tamxtbG5z\r
+ dXZ5fHx7fX9+fH6AgoWHioyNj5CRlZeYmp2TiYyGenp9eXh9fX19foB/fH1/e3p8e3l5e3x7e3x\r
+ 6d3FxcnBwcG9vb29vb29wb25tbWxsbW5vb3Fyc3N1dXV1dnd4ent9fn+BgoGAgoWEhoqJiYyLi4\r
+ yPioaLiYSEh4WDhIOCgoKAgX58fXx5eXp4eHl4dXZ1cnN0dHR1cnJycXBxcnJycW9ubGxsbW1ub\r
+ m5ub29vcXNzdHZ2dXh6enp+fn5/gYCBhIKFiYeGiomJi4qKjIuLjIyLiomKh4aKioeIiIWDgYB9\r
+ fHx7e3l4eHh2dnd3d3l7enp6enp5ent7e3x7enl6e3t7fHx7e3p8fX5/gIKDg4GCg4KCg4OEhoe\r
+ Hh4iJiomLjIqLi4uLi46Pjo2OjouJiomHh4aDgH9/fXp5eXh3d3h4eHh4d3V2d3Z0dnd0dXd3d3\r
+ p7fH59fX19fH5+fn+Af4CAf3+Af359f4KDgoSIiIeJjI6PkJOUk5SYmZiYmZqZmJqamJiZmJaWl\r
+ ZSTkZCQj46Ni4qHh4iFgoKBfn9+fn+AgYCAgYOCgoSEg4SFhIODg4OCgICBf35/gICAgYKCgYGD\r
+ hIOBgYOCgYGAgIGBgIGCgoKBgoSEg4KCgH9/f318fHt6e3t7enl5eHh5fH18foCAf4GDg4OFhoa\r
+ GhoeJh4aJioiIiYiIhoWGh4aGh4eHiImHh4mIiIeHh4iIiIqJioqJh4mKh4eJiYiHh4eHhoWGhY\r
+ OEhYWEhYWDg4SFhYWEg4SDgYKCgH+AgICBgoOCgYGBgYKEhoaGhoiIh4eJiYmKioqKiomKioiJi\r
+ oqJiYmJiIiIiYiHh4eHh4eGhYWFhISDgoKCgoKCgYGAf31+fXx9fn58e3x8fHx9fX19fX19fX19\r
+ fHx9fn5/gICBgYGCgoKCg4OCgoODgoKDg4OCgoKCgoGBgYGBgYGCgYCBgIGCgoKDg4KCg4OEhIS\r
+ FhYWFhYWFhYWFhoWGhoWEhISDg4ODg4ODg4ODg4SDgoKDg4OCg4SDgoKDgoGBgoGAgIB/f35+fn\r
+ 9+fn9/f35+fn5/gICAgIGBgYKCg4ODg4SEg4OEhIODhIODhIODg4ODg4OCgoKBgoKCg4OCgoODg\r
+ 4ODg4OEhISEhIWEhIWFhISEhISEhIWEhISEhIODhISEg4ODg4ODg4ODg4ODgoKCgoKCg4KCgoKC\r
+ goKCgoKCgoOCgoKCgoKBgYKCgoKCgoGBgYGAgICAgYGBgYCAf39/f39/f3+Af39/f39/f39/gIC\r
+ AgIB/f39/f39/gICAgIB/f39/gIB/f39/gH9/f39/f39/fn5+f39/f39/fn5+fn5/f39/f39/fn\r
+ 5+fn9/f39/f35+fn5+fn9/f35/f39+fn5+fn9/fn5+fn5+fn5+f39+fn5+fn19fX5+fn5+fn5+f\r
+ X5+fn5+fn5+fn19fn5+fn5+fX19fX59fn5+fn19fX19fX1+fX19fX19fX19fX19fX19fX19fX19\r
+ fX19fX19fX19fX19fX19fX19fX19fX19fXx9fX18fH19fXx8fXx9fXx8fHx8fHx8fH19fX19fXx\r
+ 9fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX\r
+ 19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19f\r
+ X19fX19fX19fX19fX19fX19fX19fX19fX1+fX5+fn19fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+\r
+ fn5+fn5+fn5+fn5+f39/fn5/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39\r
+ /f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f4B/f3\r
+ 9/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f\r
+ 39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/\r
+ f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f4B/f39/f39/f39/f39/f39/f39\r
+ /f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f3\r
+ 9/f39/f39/f39/f39/f39/f35+fn5+f35/f39/f39/f39/f39/f39/f39/f39/f39/f39/f35+f\r
+ 39+fn5/fn5+f39/fn9/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/\r
+ f39/f39/f39/f39/f39+fn9/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39\r
+ /f39/f39/f39/f39/f39/f39/f39/f4CAf39/f39/f39/gIB/f39/f39/f4B/f4CAgICAgICAgI\r
+ CAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg\r
+ ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA\r
+ gICAgICAgICAgIB/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/gICAgIC\r
+ AgICAgICAgICAgICAgICAgICAgICAgIGBgYGAgYGBgICAgIGAgICBgYGAgYGBgYGBgYGBgYGBgY\r
+ GBgYGBgYGBgYGBgYGBgYGAgYCAgICAgICAgICAgICAgICAgICAgICAgICAgH+AgICAf39/gH9/f\r
+ 3+Af39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f4CAgH9/gIB/f39/f4B/f3+AgICAf4CA\r
+ gICAgICAgICAgICAgH9/f4CAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC\r
+ AgICAgICAgICAgICAgICAgICAgICAgIB/f39/f39/f39/f4CAf39/f39/f39/f39/f39/f39+fn\r
+ 9/fn5+fn5+fn5+fn5+fX19fX19fX19fX19fX19fX19fn5+fn5+fn9/f39/f4CAgICAgICBgYGBg\r
+ YGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYCAgICAgICAgICAgICAgICAgYGAgICA\r
+ gICAgICAgICAgICBgYGAgICAgICAgICAgICAgICAgICAgICAgIB/gICAgH9/f39/f39/f39/f39\r
+ /f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/gICAgICAf39/f39/gH+AgI\r
+ CAgICAgIB/f39/f39/f4B/f39/f39/f39/f39/f39/f39/f39/f39/f39/fn9/f39/f39/f39+f\r
+ 39/f39/f39/f39/f39/f39/f39/f4B/f4CAgICAf39/f39/gICAf39/gICAgICAgICAgICAgICA\r
+ gICAgIGAgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYCAgICBgYGBgYGBgYCBgYGBgYCAgIG\r
+ BgICAgICAgICAgICAgICAgICAgICAgICAgICBgICAgICAgICAgICAgICAgICAgICAgICAgICAgI\r
+ CAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg\r
+ ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA\r
+ gICAgICAgICAgICAf3+AgIB/f4CAf39/f39/f3+AgICAgH+AgICAf3+AgICAgICAgH9/f39/f39\r
+ /f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f3\r
+ 9/f39/f39/gH9/gICAgICAgICAgIB/gICAgH+AgIB/f39/f39/gICAgICAgH9/f3+AgH9/f4B/f\r
+ 39/f39/f39/f39/f3+AgICAgICAf3+AgIB/f4CAgIB/f4CAgICAgICAgICAf39/f3+AgIB/f4CA\r
+ gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAf39/f39\r
+ /f4CAgH9/f39/f39/f39/f39/f39/f39/f39/f39/f4B/f39/f39/gIB/f39/f39/f39/gH9/f3\r
+ 9/f4CAgICAgIB/gICAgICAgICAgICAgICAgICAgICAgICAgH+AgICAf4CAgICAgICAgIB/gICAf\r
+ 4CAgICAgH+Af4CAgH9/f39/f39/f39/gICAgICAgICAgICAf39/f39/f4CAgH9/gICAf3+AgICA\r
+ gICAgICAgICAgICAgICAgICAgIB/f39/gIB/f4CAgIB/f4CAgH9/gICAf39/f39/f39/f39/f39\r
+ /f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f3\r
+ 9/f39/f39/f39/f39/f39/f39/f39/f39/f39/gICAf39/gH9/f3+AgH9/f39/f39/f39/f39/f\r
+ 39/f39/f39/f39/f39/f39/f39/gICAf3+AgH9/f3+AgH9/f4CAgH9/gICAgICAgICAgICAgICA\r
+ gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC\r
+ AgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI\r
+ CAgICAgICAgICAgICAgICAgICAgICBgYGBgIGBgYCAgYGAgICAgYCAgICAgICAgICAgICAgICAg\r
+ ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA\r
+ gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC\r
+ AgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI\r
+ CAgICAgICAgICAgICAgICAf39/f39/f4CAgIB/f4CAgICAgICAgICAgICAgICAgICAgICAgICAg\r
+ ICAf39/f3+Af39/f39/f39/f4B/f39/f4CAgICAgICAgICAgA==\r
+TEL;TYPE=HOME:0351 223344\r
+TEL;TYPE=WORK:0351 443322\r
+TEL;TYPE=CELL:0173 223344\r
+UID:P9HXg34Oav\r
+URL:http://www.mustermann.de/~heiko/\r
+X-KADDRESSBOOK-X-Anniversary:1982-07-07\r
+X-KADDRESSBOOK-X-AssistantsName:Mr. Smithers\r
+X-KADDRESSBOOK-X-Department:Edutainment\r
+X-KADDRESSBOOK-X-IMAddress:122334455\r
+X-KADDRESSBOOK-X-ManagersName:Mr. Burnes\r
+X-KADDRESSBOOK-X-Office:223 2nd stage\r
+X-KADDRESSBOOK-X-Profession:Clown\r
+X-KADDRESSBOOK-X-SpousesName:femal clown\r
+END:VCARD\r
+\r
--- /dev/null
+BEGIN:VCARD
+CLASS:PUBLIC
+EMAIL;TYPE=PREF:email1@abc.de
+EMAIL:email2@abc.de
+FN:Test User
+N:User;Test;;;
+UID:uJTkVqH5Qt
+VERSION:3.0
+END:VCARD
+
--- /dev/null
+BEGIN:VCARD\r
+VERSION:2.1\r
+EMAIL;PREF:email1@abc.de\r
+EMAIL:email2@abc.de\r
+FN:Test User\r
+N:User;Test;;;\r
+UID:uJTkVqH5Qt\r
+END:VCARD\r
+\r
--- /dev/null
+BEGIN:VCARD\r
+VERSION:3.0\r
+CLASS:PUBLIC\r
+EMAIL;TYPE=PREF:email1@abc.de\r
+EMAIL:email2@abc.de\r
+FN:Test User\r
+N:User;Test;;;\r
+UID:uJTkVqH5Qt\r
+END:VCARD\r
+\r
--- /dev/null
+BEGIN:VCARD
+N:
+LABEL;QUOTED-PRINTABLE;WORK:401 Park Drive 3 West=0ABoston, MA 02215=0AUSA=0A=
+Herecomesyetanotherline
+UID:pas-id-3E136F9B00000000
+END:VCARD
+
--- /dev/null
+BEGIN:VCARD\r
+VERSION:2.1\r
+LABEL;CHARSET=UTF-8;ENCODING=QUOTED-PRINTABLE;WORK:401 Park Drive 3 West\n\r
+ Boston\, MA 02215\nUSA\nHerecomesyetanotherline\r
+N:;;;;\r
+UID:pas-id-3E136F9B00000000\r
+END:VCARD\r
+\r
--- /dev/null
+BEGIN:VCARD\r
+VERSION:3.0\r
+LABEL;TYPE=work:401 Park Drive 3 West\nBoston\, MA 02215\nUSA\nHerecomesye\r
+ tanotherline\r
+N:;;;;\r
+UID:pas-id-3E136F9B00000000\r
+END:VCARD\r
+\r
--- /dev/null
+BEGIN:VCARD\r
+FN:test\r
+N:test;;;;\r
+NOTE:line one\Nline two\Nline three\N\r
+UID:8OD165Pope\r
+VERSION:3.0\r
+END:VCARD\r
+\r
--- /dev/null
+BEGIN:VCARD\r
+VERSION:3.0\r
+FN:test\r
+N:test;;;;\r
+NOTE:line one\nline two\nline three\n\r
+UID:8OD165Pope\r
+END:VCARD\r
+\r
--- /dev/null
+BEGIN:VCARD\r
+FN:βγδεαβγδ1βγδεαβγδ1βγδεαβγδ1βγδεαβγδ1βγ\r
+ δεαβγδ1βγδεαβγδ1βγδεαβγδ1βγδεαβγδ1βγδεα\r
+ βγδ1βγδεαβγδ1βγδεαβγδ1\r
+N:123ㄓㄕㄖbcdeαβγδαβγδαβγδαβγδαβγδαβγδαβㄤ\r
+ ㄓㄕㄖ;;;;\r
+NOTE:Длинный комментарий на русском языке\,\r
+ Ñ\87Ñ\82обÑ\8b в Ñ\80езÑ\83лÑ\8cÑ\82аÑ\82е полÑ\83Ñ\87илаÑ\81Ñ\8c Ñ\81Ñ\82Ñ\80ока боÐ\r
+ »ÐµÐµ 70 Ñ\81имволов.\r
+PRODID:-//ownCloud//NONSGML Contacts 0.3//EN\r
+UID:20140316T155019.877e370c11@martin\r
+VERSION:3.0\r
+END:VCARD\r
+\r
--- /dev/null
+BEGIN:VCARD\r
+VERSION:3.0\r
+FN:βγδεαβγδ1βγδεαβγδ1βγδεαβγδ1βγδεαβγδ1βγ\r
+ δεαβγδ1βγδεαβγδ1βγδεαβγδ1βγδεαβγδ1βγδεα\r
+ βγδ1βγδεαβγδ1βγδεαβγδ1\r
+N:123ㄓㄕㄖbcdeαβγδαβγδαβγδαβγδαβγδαβγδαβㄤ\r
+ ㄓㄕㄖ;;;;\r
+NOTE:Длинный комментарий на русском языке\,\r
+ чтобы в результате получилась строка бо\r
+ лее 70 символов.\r
+PRODID:-//ownCloud//NONSGML Contacts 0.3//EN\r
+UID:20140316T155019.877e370c11@martin\r
+END:VCARD\r
+\r
--- /dev/null
+/*
+ This file is part of the KContacts framework.
+ Copyright (c) 2015 Laurent Montel <montel@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+#include "emailtest.h"
+#include "email.h"
+#include <qtest.h>
+#include "vcardtool.h"
+
+EmailTest::EmailTest(QObject *parent)
+ : QObject(parent)
+{
+
+}
+
+EmailTest::~EmailTest()
+{
+
+}
+
+void EmailTest::shouldHaveDefaultValue()
+{
+ KContacts::Email email;
+ QVERIFY(!email.isValid());
+ QVERIFY(email.mail().isEmpty());
+ QVERIFY(email.parameters().isEmpty());
+}
+
+void EmailTest::shouldAssignValue()
+{
+ const QString mail(QStringLiteral("foo@kde.org"));
+ QMap<QString, QStringList> params;
+ params.insert(QStringLiteral("Foo1"), QStringList() << QStringLiteral("bla1") << QStringLiteral("blo1"));
+ params.insert(QStringLiteral("Foo2"), QStringList() << QStringLiteral("bla2") << QStringLiteral("blo2"));
+ KContacts::Email email(mail);
+ email.setParameters(params);
+ QVERIFY(email.isValid());
+ QVERIFY(!email.mail().isEmpty());
+ QCOMPARE(email.mail(), mail);
+ QVERIFY(!email.parameters().isEmpty());
+ QCOMPARE(email.parameters(), params);
+}
+
+void EmailTest::shouldAssignExternal()
+{
+ KContacts::Email email;
+ const QString mail(QStringLiteral("foo@kde.org"));
+ email.setEmail(mail);
+ QVERIFY(email.isValid());
+ QVERIFY(!email.mail().isEmpty());
+ QCOMPARE(email.mail(), mail);
+}
+
+void EmailTest::shouldSerialized()
+{
+ KContacts::Email email;
+ KContacts::Email result;
+ const QString mail(QStringLiteral("foo@kde.org"));
+ email.setEmail(mail);
+ QMap<QString, QStringList> params;
+ params.insert(QStringLiteral("Foo1"), QStringList() << QStringLiteral("bla1") << QStringLiteral("blo1"));
+ params.insert(QStringLiteral("Foo2"), QStringList() << QStringLiteral("bla2") << QStringLiteral("blo2"));
+ email.setParameters(params);
+
+ QByteArray data;
+ QDataStream s(&data, QIODevice::WriteOnly);
+ s << email;
+
+ QDataStream t(&data, QIODevice::ReadOnly);
+ t >> result;
+
+ QVERIFY(email == result);
+}
+
+void EmailTest::shouldEqualEmail()
+{
+ KContacts::Email email;
+ KContacts::Email result;
+ const QString mail(QStringLiteral("foo@kde.org"));
+ email.setEmail(mail);
+ QMap<QString, QStringList> params;
+ params.insert(QStringLiteral("Foo1"), QStringList() << QStringLiteral("bla1") << QStringLiteral("blo1"));
+ params.insert(QStringLiteral("Foo2"), QStringList() << QStringLiteral("bla2") << QStringLiteral("blo2"));
+ email.setParameters(params);
+
+ result = email;
+ QVERIFY(email == result);
+}
+
+void EmailTest::shouldParseEmailVCard()
+{
+ QByteArray vcarddata("BEGIN:VCARD\n"
+ "VERSION:3.0\n"
+ "EMAIL;TYPE=HOME,PREF;X-EVOLUTION-UI-SLOT=2:foo@foo.com\n"
+ "N:LastName;FirstName;;;\n"
+ "UID:c80cf296-0825-4eb0-ab16-1fac1d522a33@xxxxxx.xx\n"
+ "REV:2015-03-14T09:24:45+00:00\n"
+ "FN:FirstName LastName\n"
+ "END:VCARD\n");
+
+ KContacts::VCardTool vcard;
+ const KContacts::AddresseeList lst = vcard.parseVCards(vcarddata);
+ QCOMPARE(lst.count(), 1);
+ QVERIFY(!lst.at(0).emailList().isEmpty());
+ QCOMPARE(lst.at(0).emailList().count(), 1);
+ KContacts::Email email = lst.at(0).emailList().at(0);
+ QCOMPARE(email.mail(), QStringLiteral("foo@foo.com"));
+ QCOMPARE(email.parameters().count(), 2);
+}
+
+void EmailTest::shouldParseEmailVCardWithMultiEmails()
+{
+ QByteArray vcarddata("BEGIN:VCARD\n"
+ "VERSION:3.0\n"
+ "EMAIL;TYPE=HOME,PREF;X-EVOLUTION-UI-SLOT=2:foo@foo.com\n"
+ "EMAIL;TYPE=HOME,PREF;X-EVOLUTION-UI-SLOT=2:bla@bla.com\n"
+ "N:LastName;FirstName;;;\n"
+ "UID:c80cf296-0825-4eb0-ab16-1fac1d522a33@xxxxxx.xx\n"
+ "REV:2015-03-14T09:24:45+00:00\n"
+ "FN:FirstName LastName\n"
+ "END:VCARD\n");
+
+ KContacts::VCardTool vcard;
+ const KContacts::AddresseeList lst = vcard.parseVCards(vcarddata);
+ QCOMPARE(lst.count(), 1);
+ QVERIFY(!lst.at(0).emailList().isEmpty());
+ QCOMPARE(lst.at(0).emailList().count(), 2);
+ KContacts::Email email = lst.at(0).emailList().at(0);
+ QCOMPARE(email.mail(), QStringLiteral("bla@bla.com"));
+ email = lst.at(0).emailList().at(1);
+ QCOMPARE(email.mail(), QStringLiteral("foo@foo.com"));
+
+ QCOMPARE(email.parameters().count(), 2);
+}
+
+void EmailTest::shouldParseEmailVCardWithoutEmail()
+{
+ QByteArray vcarddata("BEGIN:VCARD\n"
+ "VERSION:3.0\n"
+ "N:LastName;FirstName;;;\n"
+ "UID:c80cf296-0825-4eb0-ab16-1fac1d522a33@xxxxxx.xx\n"
+ "REV:2015-03-14T09:24:45+00:00\n"
+ "FN:FirstName LastName\n"
+ "END:VCARD\n");
+
+ KContacts::VCardTool vcard;
+ const KContacts::AddresseeList lst = vcard.parseVCards(vcarddata);
+ QCOMPARE(lst.count(), 1);
+ QVERIFY(lst.at(0).emailList().isEmpty());
+}
+
+void EmailTest::shouldExportVcard()
+{
+ KContacts::AddresseeList lst;
+ KContacts::Addressee addr;
+ addr.setEmails(QStringList() << QStringLiteral("foo@kde.org") << QStringLiteral("bla@kde.org"));
+ addr.setUid(QStringLiteral("testuid"));
+ lst << addr;
+ KContacts::VCardTool vcard;
+ const QByteArray ba = vcard.exportVCards(lst, KContacts::VCard::v4_0);
+ QByteArray expected("BEGIN:VCARD\r\n"
+ "VERSION:4.0\r\n"
+ "EMAIL:foo@kde.org\r\n"
+ "EMAIL:bla@kde.org\r\n"
+ "N:;;;;\r\n"
+ "UID:testuid\r\n"
+ "END:VCARD\r\n\r\n");
+
+ QCOMPARE(ba, expected);
+}
+
+QTEST_MAIN(EmailTest)
--- /dev/null
+/*
+ This file is part of the KContacts framework.
+ Copyright (c) 2015 Laurent Montel <montel@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef EMAILTEST_H
+#define EMAILTEST_H
+
+#include <QObject>
+
+class EmailTest : public QObject
+{
+ Q_OBJECT
+public:
+ explicit EmailTest(QObject *parent = Q_NULLPTR);
+ ~EmailTest();
+
+private Q_SLOTS:
+ void shouldHaveDefaultValue();
+ void shouldAssignValue();
+ void shouldAssignExternal();
+ void shouldSerialized();
+ void shouldEqualEmail();
+ void shouldParseEmailVCard();
+ void shouldParseEmailVCardWithoutEmail();
+ void shouldParseEmailVCardWithMultiEmails();
+ void shouldExportVcard();
+};
+
+#endif // EMAILTEST_H
--- /dev/null
+/*
+ This file is part of the KContacts framework.
+ Copyright (c) 2015 Laurent Montel <montel@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "gendertest.h"
+#include "gender.h"
+#include "vcardtool.h"
+#include <qtest.h>
+
+GenderTest::GenderTest(QObject *parent)
+ : QObject(parent)
+{
+
+}
+
+GenderTest::~GenderTest()
+{
+
+}
+
+void GenderTest::shouldHaveDefaultValue()
+{
+ KContacts::Gender gender;
+ QVERIFY(!gender.isValid());
+ QVERIFY(gender.gender().isEmpty());
+ QVERIFY(gender.comment().isEmpty());
+}
+
+void GenderTest::shouldAssignValue()
+{
+ const QString genderStr(QStringLiteral("F"));
+ KContacts::Gender gender(genderStr);
+ const QString commentStr(QStringLiteral("foo"));
+ gender.setComment(commentStr);
+ QVERIFY(gender.isValid());
+ QVERIFY(!gender.gender().isEmpty());
+ QCOMPARE(gender.gender(), genderStr);
+ QVERIFY(!gender.comment().isEmpty());
+ QCOMPARE(gender.comment(), commentStr);
+}
+
+void GenderTest::shouldAssignExternal()
+{
+ KContacts::Gender gender;
+ const QString genderStr(QStringLiteral("H"));
+ gender.setGender(genderStr);
+ QVERIFY(gender.isValid());
+ QVERIFY(!gender.gender().isEmpty());
+ QCOMPARE(gender.gender(), genderStr);
+}
+
+void GenderTest::shouldSerialized()
+{
+ KContacts::Gender gender;
+ KContacts::Gender result;
+ const QString genderStr(QStringLiteral("H"));
+ gender.setGender(genderStr);
+ gender.setComment(QStringLiteral("foo"));
+
+ QByteArray data;
+ QDataStream s(&data, QIODevice::WriteOnly);
+ s << gender;
+
+ QDataStream t(&data, QIODevice::ReadOnly);
+ t >> result;
+
+ QVERIFY(gender == result);
+}
+
+void GenderTest::shouldEqualGender()
+{
+ KContacts::Gender gender;
+ KContacts::Gender result;
+ const QString genderStr(QStringLiteral("H"));
+ gender.setGender(genderStr);
+ gender.setComment(QStringLiteral("foo"));
+
+ result = gender;
+ QVERIFY(gender == result);
+}
+
+void GenderTest::shouldParseGender_data()
+{
+ QTest::addColumn<QByteArray>("vcarddata");
+ QTest::addColumn<QString>("genre");
+ QTest::addColumn<QString>("comment");
+ QTest::addColumn<bool>("hasGender");
+
+ QByteArray str("BEGIN:VCARD\n"
+ "VERSION:3.0\n"
+ "N:LastName;FirstName;;;\n"
+ "UID:c80cf296-0825-4eb0-ab16-1fac1d522a33@xxxxxx.xx\n"
+ "REV:2015-03-14T09:24:45+00:00\n"
+ "FN:FirstName LastName\n"
+ "END:VCARD\n");
+ QTest::newRow("nogender") << str << QString() << QString() << false;
+
+ str = QByteArray("BEGIN:VCARD\n"
+ "VERSION:3.0\n"
+ "N:LastName;FirstName;;;\n"
+ "UID:c80cf296-0825-4eb0-ab16-1fac1d522a33@xxxxxx.xx\n"
+ "REV:2015-03-14T09:24:45+00:00\n"
+ "FN:FirstName LastName\n"
+ "GENDER:H\n"
+ "END:VCARD\n");
+ QTest::newRow("hasgenderbutnocomment") << str << QStringLiteral("H") << QString() << true;
+
+ str = QByteArray("BEGIN:VCARD\n"
+ "VERSION:3.0\n"
+ "N:LastName;FirstName;;;\n"
+ "UID:c80cf296-0825-4eb0-ab16-1fac1d522a33@xxxxxx.xx\n"
+ "REV:2015-03-14T09:24:45+00:00\n"
+ "FN:FirstName LastName\n"
+ "GENDER:;foo\n"
+ "END:VCARD\n");
+ QTest::newRow("hasgenderbutnotypebutcomment") << str << QString() << QStringLiteral("foo") << true;
+
+ str = QByteArray("BEGIN:VCARD\n"
+ "VERSION:3.0\n"
+ "N:LastName;FirstName;;;\n"
+ "UID:c80cf296-0825-4eb0-ab16-1fac1d522a33@xxxxxx.xx\n"
+ "REV:2015-03-14T09:24:45+00:00\n"
+ "FN:FirstName LastName\n"
+ "GENDER:H;foo\n"
+ "END:VCARD\n");
+ QTest::newRow("hasgendertypeandcomment") << str << QStringLiteral("H") << QStringLiteral("foo") << true;
+}
+
+void GenderTest::shouldParseGender()
+{
+ QFETCH(QByteArray, vcarddata);
+ QFETCH(QString, genre);
+ QFETCH(QString, comment);
+ QFETCH(bool, hasGender);
+
+ KContacts::VCardTool vcard;
+ const KContacts::AddresseeList lst = vcard.parseVCards(vcarddata);
+ QCOMPARE(lst.count(), 1);
+ QCOMPARE(lst.at(0).gender().isValid(), hasGender);
+ QCOMPARE(lst.at(0).gender().comment(), comment);
+ QCOMPARE(lst.at(0).gender().gender(), genre);
+}
+
+QByteArray GenderTest::createCard(const QByteArray &gender)
+{
+ QByteArray expected("BEGIN:VCARD\r\n"
+ "VERSION:4.0\r\n"
+ "EMAIL:foo@kde.org\r\n");
+ if (!gender.isEmpty()) {
+ expected += gender + "\r\n";
+ }
+ expected += QByteArray(
+ "N:;;;;\r\n"
+ "UID:testuid\r\n"
+ "END:VCARD\r\n\r\n");
+ return expected;
+}
+
+void GenderTest::shouldExportEmptyGender()
+{
+ KContacts::AddresseeList lst;
+ KContacts::Addressee addr;
+ addr.setEmails(QStringList() << QStringLiteral("foo@kde.org"));
+ addr.setUid(QStringLiteral("testuid"));
+ lst << addr;
+ KContacts::VCardTool vcard;
+ const QByteArray ba = vcard.exportVCards(lst, KContacts::VCard::v4_0);
+ QByteArray expected = createCard(QByteArray());
+ QCOMPARE(ba, expected);
+}
+
+void GenderTest::shouldExportOnlyGenderWithoutCommentGender()
+{
+ KContacts::AddresseeList lst;
+ KContacts::Addressee addr;
+ addr.setEmails(QStringList() << QStringLiteral("foo@kde.org"));
+ addr.setUid(QStringLiteral("testuid"));
+ KContacts::Gender gender;
+ gender.setGender(QStringLiteral("H"));
+ addr.setGender(gender);
+ lst << addr;
+ KContacts::VCardTool vcard;
+ const QByteArray ba = vcard.exportVCards(lst, KContacts::VCard::v4_0);
+ QByteArray expected = createCard(QByteArray("GENDER:H"));
+ QCOMPARE(ba, expected);
+}
+
+void GenderTest::shouldExportOnlyGenderWithCommentGender()
+{
+ KContacts::AddresseeList lst;
+ KContacts::Addressee addr;
+ addr.setEmails(QStringList() << QStringLiteral("foo@kde.org"));
+ addr.setUid(QStringLiteral("testuid"));
+ KContacts::Gender gender;
+ gender.setGender(QStringLiteral("H"));
+ gender.setComment(QStringLiteral("comment"));
+ addr.setGender(gender);
+ lst << addr;
+ KContacts::VCardTool vcard;
+ const QByteArray ba = vcard.exportVCards(lst, KContacts::VCard::v4_0);
+ QByteArray expected = createCard(QByteArray("GENDER:H;comment"));
+ QCOMPARE(ba, expected);
+}
+
+void GenderTest::shouldExportOnlyGenderWithoutTypeCommentGender()
+{
+ KContacts::AddresseeList lst;
+ KContacts::Addressee addr;
+ addr.setEmails(QStringList() << QStringLiteral("foo@kde.org"));
+ addr.setUid(QStringLiteral("testuid"));
+ KContacts::Gender gender;
+ gender.setComment(QStringLiteral("comment"));
+ addr.setGender(gender);
+ lst << addr;
+ KContacts::VCardTool vcard;
+ const QByteArray ba = vcard.exportVCards(lst, KContacts::VCard::v4_0);
+ QByteArray expected = createCard(QByteArray("GENDER:;comment"));
+ QCOMPARE(ba, expected);
+}
+
+void GenderTest::shouldNotExportInVcard3()
+{
+ KContacts::AddresseeList lst;
+ KContacts::Addressee addr;
+ addr.setEmails(QStringList() << QStringLiteral("foo@kde.org"));
+ addr.setUid(QStringLiteral("testuid"));
+ KContacts::Gender gender;
+ gender.setComment(QStringLiteral("comment"));
+ addr.setGender(gender);
+ lst << addr;
+ KContacts::VCardTool vcard;
+ const QByteArray ba = vcard.exportVCards(lst, KContacts::VCard::v3_0);
+ QByteArray expected("BEGIN:VCARD\r\n"
+ "VERSION:3.0\r\n"
+ "EMAIL:foo@kde.org\r\n"
+ "N:;;;;\r\n"
+ "UID:testuid\r\n"
+ "END:VCARD\r\n\r\n");
+ QCOMPARE(ba, expected);
+}
+
+QTEST_MAIN(GenderTest)
--- /dev/null
+/*
+ This file is part of the KContacts framework.
+ Copyright (c) 2015 Laurent Montel <montel@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef GENDERTEST_H
+#define GENDERTEST_H
+
+#include <QObject>
+
+class GenderTest : public QObject
+{
+ Q_OBJECT
+public:
+ explicit GenderTest(QObject *parent = Q_NULLPTR);
+ ~GenderTest();
+
+private:
+ QByteArray createCard(const QByteArray &gender);
+
+private Q_SLOTS:
+ void shouldHaveDefaultValue();
+ void shouldAssignValue();
+ void shouldAssignExternal();
+ void shouldSerialized();
+ void shouldEqualGender();
+ void shouldParseGender();
+ void shouldParseGender_data();
+ void shouldExportOnlyGenderWithoutCommentGender();
+ void shouldExportEmptyGender();
+ void shouldExportOnlyGenderWithCommentGender();
+ void shouldExportOnlyGenderWithoutTypeCommentGender();
+ void shouldNotExportInVcard3();
+};
+
+#endif // GENDERTEST_H
--- /dev/null
+/*
+ This file is part of the KContacts framework.
+ Copyright (c) 2007 KDE-PIM team <kde-pim@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "geotest.h"
+#include "kcontacts/geo.h"
+#include "vcardtool.h"
+#include <qtest.h>
+
+QTEST_MAIN(GeoTest)
+
+void GeoTest::constructor()
+{
+ KContacts::Geo geo(1.2f, 3.4f);
+
+ QVERIFY((float)geo.latitude() == (float)1.2);
+ QVERIFY((float)geo.longitude() == (float)3.4);
+}
+
+void GeoTest::isValid()
+{
+ KContacts::Geo geo;
+
+ QVERIFY(!geo.isValid());
+
+ geo.setLatitude(23);
+
+ QVERIFY(!geo.isValid());
+
+ geo.setLongitude(45);
+
+ QVERIFY(geo.isValid());
+
+ geo.clear();
+
+ QVERIFY(!geo.isValid());
+ QVERIFY(geo == KContacts::Geo());
+}
+
+void GeoTest::setData()
+{
+ KContacts::Geo geo;
+
+ geo.setLatitude(22.5f);
+ geo.setLongitude(45.1f);
+
+ QVERIFY((float)geo.latitude() == (float)22.5);
+ QVERIFY((float)geo.longitude() == (float)45.1);
+}
+
+void GeoTest::equals()
+{
+ KContacts::Geo geo1(22.5f, 33.7f);
+ KContacts::Geo geo2(22.5f, 33.7f);
+
+ QVERIFY(geo1 == geo2);
+}
+
+void GeoTest::differs()
+{
+ KContacts::Geo geo1(22.5f, 33.7f);
+ KContacts::Geo geo2(22.5f, 33.6f);
+
+ QVERIFY(geo1 != geo2);
+}
+
+void GeoTest::serialization()
+{
+ KContacts::Geo geo1(22.5f, 33.7f);
+ QByteArray data;
+
+ QDataStream s(&data, QIODevice::WriteOnly);
+ s << geo1;
+
+ KContacts::Geo geo2;
+ QDataStream t(&data, QIODevice::ReadOnly);
+ t >> geo2;
+
+ QVERIFY(geo1 == geo2);
+}
+
+void GeoTest::shouldParseGeoVCard3()
+{
+ QByteArray vcarddata("BEGIN:VCARD\n"
+ "VERSION:3.0\n"
+ "N:LastName;FirstName;;;\n"
+ "UID:c80cf296-0825-4eb0-ab16-1fac1d522a33@xxxxxx.xx\n"
+ "GEO:22.5;180.0\n"
+ "REV:2015-03-14T09:24:45+00:00\n"
+ "FN:FirstName LastName\n"
+ "END:VCARD\n");
+
+ KContacts::VCardTool vcard;
+ const KContacts::AddresseeList lst = vcard.parseVCards(vcarddata);
+ QCOMPARE(lst.count(), 1);
+ QVERIFY(lst.at(0).geo().isValid());
+ KContacts::Geo geo = lst.at(0).geo();
+ QCOMPARE(geo.latitude(), 22.5);
+ QCOMPARE(geo.longitude(), 180.0);
+}
+
+void GeoTest::shouldParseGeoVCard4()
+{
+ QByteArray vcarddata("BEGIN:VCARD\n"
+ "VERSION:4.0\n"
+ "N:LastName;FirstName;;;\n"
+ "UID:c80cf296-0825-4eb0-ab16-1fac1d522a33@xxxxxx.xx\n"
+ "GEO:geo:22.5,180.0\n"
+ "REV:2015-03-14T09:24:45+00:00\n"
+ "FN:FirstName LastName\n"
+ "END:VCARD\n");
+
+ KContacts::VCardTool vcard;
+ const KContacts::AddresseeList lst = vcard.parseVCards(vcarddata);
+ QCOMPARE(lst.count(), 1);
+ QVERIFY(lst.at(0).geo().isValid());
+ KContacts::Geo geo = lst.at(0).geo();
+ QCOMPARE(geo.latitude(), 22.5);
+ QCOMPARE(geo.longitude(), 180.0);
+}
+
+void GeoTest::shouldGenerateVCard3()
+{
+ KContacts::AddresseeList lst;
+ KContacts::Addressee addr;
+ addr.setEmails(QStringList() << QStringLiteral("foo@kde.org"));
+ addr.setUid(QStringLiteral("testuid"));
+
+ KContacts::Geo geo;
+ geo.setLongitude(180.0);
+ geo.setLatitude(22.5);
+ addr.setGeo(geo);
+
+ lst << addr;
+ KContacts::VCardTool vcard;
+ const QByteArray ba = vcard.exportVCards(lst, KContacts::VCard::v3_0);
+ QByteArray expected("BEGIN:VCARD\r\n"
+ "VERSION:3.0\r\n"
+ "EMAIL:foo@kde.org\r\n"
+ "GEO:22.500000;180.000000\r\n"
+ "N:;;;;\r\n"
+ "UID:testuid\r\n"
+ "END:VCARD\r\n\r\n");
+ QCOMPARE(ba, expected);
+
+}
+
+void GeoTest::shouldGenerateVCard4()
+{
+ KContacts::AddresseeList lst;
+ KContacts::Addressee addr;
+ addr.setEmails(QStringList() << QStringLiteral("foo@kde.org"));
+ addr.setUid(QStringLiteral("testuid"));
+
+ KContacts::Geo geo;
+ geo.setLongitude(180.0);
+ geo.setLatitude(22.5);
+ addr.setGeo(geo);
+
+ lst << addr;
+ KContacts::VCardTool vcard;
+ const QByteArray ba = vcard.exportVCards(lst, KContacts::VCard::v4_0);
+ QByteArray expected("BEGIN:VCARD\r\n"
+ "VERSION:4.0\r\n"
+ "EMAIL:foo@kde.org\r\n"
+ "GEO:geo:22.500000,180.000000\r\n"
+ "N:;;;;\r\n"
+ "UID:testuid\r\n"
+ "END:VCARD\r\n\r\n");
+ QCOMPARE(ba, expected);
+}
+
+void GeoTest::shouldGenerateWithoutGeo()
+{
+ KContacts::AddresseeList lst;
+ KContacts::Addressee addr;
+ addr.setEmails(QStringList() << QStringLiteral("foo@kde.org"));
+ addr.setUid(QStringLiteral("testuid"));
+
+ lst << addr;
+ KContacts::VCardTool vcard;
+ const QByteArray ba = vcard.exportVCards(lst, KContacts::VCard::v4_0);
+ QByteArray expected("BEGIN:VCARD\r\n"
+ "VERSION:4.0\r\n"
+ "EMAIL:foo@kde.org\r\n"
+ "N:;;;;\r\n"
+ "UID:testuid\r\n"
+ "END:VCARD\r\n\r\n");
+ QCOMPARE(ba, expected);
+}
--- /dev/null
+/*
+ This file is part of the KContacts framework.
+ Copyright (c) 2007 KDE-PIM team <kde-pim@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef GEOTEST_H
+#define GEOTEST_H
+
+#include <QtCore/QObject>
+
+class GeoTest : public QObject
+{
+ Q_OBJECT
+
+private Q_SLOTS:
+ void constructor();
+ void isValid();
+ void setData();
+ void equals();
+ void differs();
+ void serialization();
+ void shouldParseGeoVCard3();
+ void shouldParseGeoVCard4();
+ void shouldGenerateVCard3();
+ void shouldGenerateVCard4();
+ void shouldGenerateWithoutGeo();
+};
+
+#endif
--- /dev/null
+/*
+ This file is part of libkabc.
+ Copyright (c) 2015 Laurent Montel <montel@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "impptest.h"
+#include "impp.h"
+#include <qtest.h>
+#include "vcardtool.h"
+Q_DECLARE_METATYPE(KContacts::Impp::ImppType)
+
+ImppTest::ImppTest(QObject *parent)
+ : QObject(parent)
+{
+
+}
+
+ImppTest::~ImppTest()
+{
+
+}
+
+void ImppTest::shouldHaveDefaultValue()
+{
+ KContacts::Impp impp;
+ QVERIFY(!impp.isValid());
+ QVERIFY(impp.address().isEmpty());
+ QCOMPARE(impp.type(), KContacts::Impp::Unknown);
+ QVERIFY(impp.parameters().isEmpty());
+}
+
+void ImppTest::shouldAssignValue()
+{
+ const QString address(QStringLiteral("address"));
+ QMap<QString, QStringList> params;
+ params.insert(QStringLiteral("Foo1"), QStringList() << QStringLiteral("bla1") << QStringLiteral("blo1"));
+ params.insert(QStringLiteral("Foo2"), QStringList() << QStringLiteral("bla2") << QStringLiteral("blo2"));
+ KContacts::Impp impp;
+ impp.setParameters(params);
+ impp.setType(KContacts::Impp::Icq);
+ impp.setAddress(address);
+ QVERIFY(impp.isValid());
+ QVERIFY(!impp.address().isEmpty());
+ QCOMPARE(impp.address(), address);
+ QCOMPARE(impp.type(), KContacts::Impp::Icq);
+ QVERIFY(!impp.parameters().isEmpty());
+ QCOMPARE(impp.parameters(), params);
+}
+
+void ImppTest::shouldSerialized()
+{
+ const QString address(QStringLiteral("address"));
+ QMap<QString, QStringList> params;
+ params.insert(QStringLiteral("Foo1"), QStringList() << QStringLiteral("bla1") << QStringLiteral("blo1"));
+ params.insert(QStringLiteral("Foo2"), QStringList() << QStringLiteral("bla2") << QStringLiteral("blo2"));
+ KContacts::Impp impp;
+ impp.setParameters(params);
+ impp.setType(KContacts::Impp::Icq);
+ impp.setAddress(address);
+
+ QByteArray data;
+ QDataStream s(&data, QIODevice::WriteOnly);
+ s << impp;
+
+ KContacts::Impp result;
+ QDataStream t(&data, QIODevice::ReadOnly);
+ t >> result;
+
+ QVERIFY(impp == result);
+}
+
+void ImppTest::shouldEqualImpp()
+{
+ const QString address(QStringLiteral("address"));
+ QMap<QString, QStringList> params;
+ params.insert(QStringLiteral("Foo1"), QStringList() << QStringLiteral("bla1") << QStringLiteral("blo1"));
+ params.insert(QStringLiteral("Foo2"), QStringList() << QStringLiteral("bla2") << QStringLiteral("blo2"));
+ KContacts::Impp impp;
+ impp.setParameters(params);
+ impp.setType(KContacts::Impp::Icq);
+ impp.setAddress(address);
+
+ KContacts::Impp result(impp);
+ QVERIFY(impp == result);
+}
+
+void ImppTest::shouldParseWithoutImpp()
+{
+ QByteArray vcarddata("BEGIN:VCARD\n"
+ "VERSION:3.0\n"
+ "N:LastName;FirstName;;;\n"
+ "UID:c80cf296-0825-4eb0-ab16-1fac1d522a33@xxxxxx.xx\n"
+ "LANG:fr"
+ "REV:2015-03-14T09:24:45+00:00\n"
+ "FN:FirstName LastName\n"
+ "END:VCARD\n");
+
+ KContacts::VCardTool vcard;
+ const KContacts::AddresseeList lst = vcard.parseVCards(vcarddata);
+ QCOMPARE(lst.count(), 1);
+ QCOMPARE(lst.at(0).imppList().count(), 0);
+}
+
+void ImppTest::shouldParseImpp()
+{
+ QByteArray vcarddata("BEGIN:VCARD\n"
+ "VERSION:3.0\n"
+ "N:LastName;FirstName;;;\n"
+ "UID:c80cf296-0825-4eb0-ab16-1fac1d522a33@xxxxxx.xx\n"
+ "IMPP;X-SERVICE-TYPE=skype:skype:xxxxxxxx\n"
+ "REV:2015-03-14T09:24:45+00:00\n"
+ "FN:FirstName LastName\n"
+ "END:VCARD\n");
+
+ KContacts::VCardTool vcard;
+ const KContacts::AddresseeList lst = vcard.parseVCards(vcarddata);
+ QCOMPARE(lst.count(), 1);
+ QCOMPARE(lst.at(0).imppList().count(), 1);
+ KContacts::Impp impp = lst.at(0).imppList().at(0);
+ QCOMPARE(impp.address(), QStringLiteral("skype:xxxxxxxx"));
+ QCOMPARE(impp.type(), KContacts::Impp::Skype);
+}
+
+QByteArray createCard(KContacts::Impp::ImppType type)
+{
+ QByteArray expected("BEGIN:VCARD\n"
+ "VERSION:3.0\n"
+ "EMAIL:foo@kde.org\n");
+ if (type != KContacts::Impp::Unknown) {
+ const QByteArray baType = KContacts::Impp::typeToString(type).toLatin1();
+ expected += "IMPP;X-SERVICE-TYPE=" + baType + ":" + baType + ":address\n";
+ }
+ expected += QByteArray(
+ "N:;;;;\n"
+ "UID:testuid\n"
+ "END:VCARD\n\n");
+ return expected;
+}
+
+void ImppTest::shouldParseServiceType_data()
+{
+ QTest::addColumn<KContacts::Impp::ImppType>("type");
+ QTest::addColumn<bool>("hasImpp");
+ QTest::newRow("withoutimpp") << KContacts::Impp::Unknown << false;
+ QTest::newRow("skype") << KContacts::Impp::Skype << true;
+ for (int i = KContacts::Impp::Unknown + 1; i < KContacts::Impp::EndList; ++i) {
+ KContacts::Impp::ImppType type = static_cast<KContacts::Impp::ImppType>(i);
+ QTest::newRow(KContacts::Impp::typeToString(type).toLatin1().constData()) << type << true;
+ }
+}
+
+void ImppTest::shouldParseServiceType()
+{
+ QFETCH(KContacts::Impp::ImppType, type);
+ QFETCH(bool, hasImpp);
+
+ QByteArray vcarddata = createCard(type);
+
+ KContacts::VCardTool vcard;
+ const KContacts::AddresseeList lst = vcard.parseVCards(vcarddata);
+ QCOMPARE(lst.count(), 1);
+
+ QCOMPARE(!lst.at(0).imppList().isEmpty(), hasImpp);
+ if (hasImpp) {
+ KContacts::Impp impp = lst.at(0).imppList().at(0);
+ QCOMPARE(impp.address(), QStringLiteral("%1:address").arg(KContacts::Impp::typeToString(type)));
+ QCOMPARE(impp.type(), type);
+ }
+}
+
+QByteArray expectedVcard(KContacts::Impp::ImppType type)
+{
+ QByteArray expected("BEGIN:VCARD\r\n"
+ "VERSION:4.0\r\n"
+ "EMAIL:foo@kde.org\r\n");
+ if (type != KContacts::Impp::Unknown) {
+ const QByteArray baType = KContacts::Impp::typeToString(type).toLatin1();
+ expected += "IMPP;X-SERVICE-TYPE=" + baType + ":address\r\n";
+ }
+
+ expected += ("N:;;;;\r\n"
+ "UID:testuid\r\n"
+ "END:VCARD\r\n\r\n");
+ return expected;
+}
+
+void ImppTest::shouldExportEmptyType()
+{
+ QByteArray expected("BEGIN:VCARD\r\n"
+ "VERSION:4.0\r\n"
+ "EMAIL:foo@kde.org\r\n"
+ "N:;;;;\r\n"
+ "UID:testuid\r\n"
+ "END:VCARD\r\n\r\n");
+ KContacts::AddresseeList lst;
+ KContacts::Addressee addr;
+ addr.setEmails(QStringList() << QStringLiteral("foo@kde.org"));
+ addr.setUid(QStringLiteral("testuid"));
+ lst << addr;
+ KContacts::VCardTool vcard;
+ const QByteArray ba = vcard.exportVCards(lst, KContacts::VCard::v4_0);
+ QCOMPARE(ba, expected);
+}
+
+void ImppTest::shouldExportType_data()
+{
+ QTest::addColumn<KContacts::Impp::ImppType>("type");
+ for (int i = KContacts::Impp::Unknown + 1; i < KContacts::Impp::EndList; ++i) {
+ KContacts::Impp::ImppType type = static_cast<KContacts::Impp::ImppType>(i);
+ QTest::newRow(KContacts::Impp::typeToString(type).toLatin1().constData()) << type;
+ }
+}
+
+void ImppTest::shouldExportType()
+{
+ QFETCH(KContacts::Impp::ImppType, type);
+
+ QByteArray expected = expectedVcard(type);
+ KContacts::AddresseeList lst;
+ KContacts::Addressee addr;
+ addr.setEmails(QStringList() << QStringLiteral("foo@kde.org"));
+ addr.setUid(QStringLiteral("testuid"));
+ KContacts::Impp impp;
+ impp.setAddress(QStringLiteral("address"));
+ impp.setType(type);
+ addr.insertImpp(impp);
+ lst << addr;
+ KContacts::VCardTool vcard;
+ const QByteArray ba = vcard.exportVCards(lst, KContacts::VCard::v4_0);
+ QCOMPARE(ba, expected);
+}
+
+void ImppTest::shouldExportWithParameters()
+{
+ QByteArray expected("BEGIN:VCARD\r\n"
+ "VERSION:4.0\r\n"
+ "EMAIL:foo@kde.org\r\n"
+ "IMPP;FOO1=bla1,blo1;FOO2=bla2,blo2;X-SERVICE-TYPE=skype:address\r\n"
+ "N:;;;;\r\n"
+ "UID:testuid\r\n"
+ "END:VCARD\r\n\r\n");
+ KContacts::AddresseeList lst;
+ KContacts::Addressee addr;
+ addr.setEmails(QStringList() << QStringLiteral("foo@kde.org"));
+ addr.setUid(QStringLiteral("testuid"));
+ QMap<QString, QStringList> params;
+ params.insert(QStringLiteral("Foo1"), QStringList() << QStringLiteral("bla1") << QStringLiteral("blo1"));
+ params.insert(QStringLiteral("Foo2"), QStringList() << QStringLiteral("bla2") << QStringLiteral("blo2"));
+ KContacts::Impp impp;
+ impp.setAddress(QStringLiteral("address"));
+ impp.setType(KContacts::Impp::Skype);
+ impp.setParameters(params);
+ addr.insertImpp(impp);
+ lst << addr;
+
+ KContacts::VCardTool vcard;
+ const QByteArray ba = vcard.exportVCards(lst, KContacts::VCard::v4_0);
+ QCOMPARE(ba, expected);
+}
+
+void ImppTest::shouldShouldNoyExportTwiceServiceType()
+{
+ QByteArray expected("BEGIN:VCARD\r\n"
+ "VERSION:4.0\r\n"
+ "EMAIL:foo@kde.org\r\n"
+ "IMPP;FOO1=bla1,blo1;FOO2=bla2,blo2;X-SERVICE-TYPE=skype:address\r\n"
+ "N:;;;;\r\n"
+ "UID:testuid\r\n"
+ "END:VCARD\r\n\r\n");
+ KContacts::AddresseeList lst;
+ KContacts::Addressee addr;
+ addr.setEmails(QStringList() << QStringLiteral("foo@kde.org"));
+ addr.setUid(QStringLiteral("testuid"));
+ QMap<QString, QStringList> params;
+ params.insert(QStringLiteral("Foo1"), QStringList() << QStringLiteral("bla1") << QStringLiteral("blo1"));
+ params.insert(QStringLiteral("Foo2"), QStringList() << QStringLiteral("bla2") << QStringLiteral("blo2"));
+ params.insert(QStringLiteral("X-SERVICE-TYPE"), QStringList() << QStringLiteral("aim"));
+ KContacts::Impp impp;
+ impp.setAddress(QStringLiteral("address"));
+ impp.setType(KContacts::Impp::Skype);
+ impp.setParameters(params);
+ addr.insertImpp(impp);
+ lst << addr;
+
+ KContacts::VCardTool vcard;
+ const QByteArray ba = vcard.exportVCards(lst, KContacts::VCard::v4_0);
+ QCOMPARE(ba, expected);
+}
+
+QTEST_MAIN(ImppTest)
--- /dev/null
+/*
+ This file is part of libkabc.
+ Copyright (c) 2015 Laurent Montel <montel@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef IMPPTEST_H
+#define IMPPTEST_H
+
+#include <QObject>
+
+class ImppTest : public QObject
+{
+ Q_OBJECT
+public:
+ explicit ImppTest(QObject *parent = Q_NULLPTR);
+ ~ImppTest();
+
+private Q_SLOTS:
+ void shouldHaveDefaultValue();
+ void shouldAssignValue();
+ void shouldSerialized();
+ void shouldEqualImpp();
+ void shouldParseWithoutImpp();
+ void shouldParseImpp();
+ void shouldParseServiceType_data();
+ void shouldParseServiceType();
+ void shouldExportEmptyType();
+
+ void shouldExportType_data();
+ void shouldExportType();
+
+ void shouldExportWithParameters();
+ void shouldShouldNoyExportTwiceServiceType();
+};
+
+#endif // IMPPTEST_H
--- /dev/null
+/*
+ This file is part of the KContacts framework.
+ Copyright (c) 2007 Tobias Koenig <tokoe@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "keytest.h"
+#include "kcontacts/key.h"
+#include <qtest.h>
+
+QTEST_MAIN(KeyTest)
+
+void KeyTest::storeTest()
+{
+ KContacts::Key key;
+
+ key.setId(QStringLiteral("My Id"));
+ key.setType(KContacts::Key::Custom);
+ key.setCustomTypeString(QStringLiteral("GnuPG"));
+ key.setTextData(QStringLiteral("That's my super secret key"));
+
+ QVERIFY(key.id() == QStringLiteral("My Id"));
+ QVERIFY(key.type() == KContacts::Key::Custom);
+ QVERIFY(key.customTypeString() == QStringLiteral("GnuPG"));
+ QVERIFY(key.textData() == QStringLiteral("That's my super secret key"));
+ QVERIFY(key.isBinary() == false);
+}
+
+void KeyTest::equalsTest()
+{
+ KContacts::Key key1, key2;
+
+ key1.setId(QStringLiteral("My Id"));
+ key1.setType(KContacts::Key::Custom);
+ key1.setCustomTypeString(QStringLiteral("GnuPG"));
+ key1.setTextData(QStringLiteral("That's my super secret key"));
+
+ key2.setId(QStringLiteral("My Id"));
+ key2.setType(KContacts::Key::Custom);
+ key2.setCustomTypeString(QStringLiteral("GnuPG"));
+ key2.setTextData(QStringLiteral("That's my super secret key"));
+
+ QVERIFY(key1 == key2);
+}
+
+void KeyTest::differsTest()
+{
+ KContacts::Key key1(QStringLiteral("TextKey"), KContacts::Key::PGP);
+ KContacts::Key key2(QStringLiteral("TextKey"), KContacts::Key::Custom);
+
+ QVERIFY(key1 != key2);
+}
+
+void KeyTest::assignmentTest()
+{
+ KContacts::Key key1, key2;
+
+ key1.setId(QStringLiteral("My Id"));
+ key1.setType(KContacts::Key::Custom);
+ key1.setCustomTypeString(QStringLiteral("GnuPG"));
+ key1.setTextData(QStringLiteral("That's my super secret key"));
+
+ key2 = key1;
+
+ QVERIFY(key1 == key2);
+}
+
+void KeyTest::serializeTest()
+{
+ KContacts::Key key1, key2;
+
+ key1.setId(QStringLiteral("My Id"));
+ key1.setType(KContacts::Key::Custom);
+ key1.setCustomTypeString(QStringLiteral("GnuPG"));
+ key1.setTextData(QStringLiteral("That's my super secret key"));
+
+ QByteArray data;
+ QDataStream s(&data, QIODevice::WriteOnly);
+ s << key1;
+
+ QDataStream t(&data, QIODevice::ReadOnly);
+ t >> key2;
+
+ QVERIFY(key1 == key2);
+}
--- /dev/null
+/*
+ This file is part of the KContacts framework.
+ Copyright (c) 2007 Tobias Koenig <tokoe@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KEY_TEST_H
+#define KEY_TEST_H
+
+#include <QtCore/QObject>
+
+class KeyTest : public QObject
+{
+ Q_OBJECT
+
+private Q_SLOTS:
+ void storeTest();
+ void equalsTest();
+ void differsTest();
+ void assignmentTest();
+ void serializeTest();
+};
+
+#endif
--- /dev/null
+/*
+ This file is part of the KContacts framework.
+ Copyright (c) 2015 Laurent Montel <montel@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "langtest.h"
+#include "lang.h"
+#include "vcardtool.h"
+#include <qtest.h>
+
+LangTest::LangTest(QObject *parent)
+ : QObject(parent)
+{
+
+}
+
+LangTest::~LangTest()
+{
+
+}
+
+void LangTest::shouldHaveDefaultValue()
+{
+ KContacts::Lang language;
+ QVERIFY(!language.isValid());
+ QVERIFY(language.language().isEmpty());
+ QVERIFY(language.parameters().isEmpty());
+}
+
+void LangTest::shouldAssignValue()
+{
+ const QString lang(QStringLiteral("fr"));
+ QMap<QString, QStringList> params;
+ params.insert(QStringLiteral("Foo1"), QStringList() << QStringLiteral("bla1") << QStringLiteral("blo1"));
+ params.insert(QStringLiteral("Foo2"), QStringList() << QStringLiteral("bla2") << QStringLiteral("blo2"));
+ KContacts::Lang language(lang);
+ language.setParameters(params);
+ QVERIFY(language.isValid());
+ QVERIFY(!language.language().isEmpty());
+ QCOMPARE(language.language(), lang);
+ QVERIFY(!language.parameters().isEmpty());
+ QCOMPARE(language.parameters(), params);
+
+}
+
+void LangTest::shouldAssignExternal()
+{
+ KContacts::Lang language;
+ const QString lang(QStringLiteral("fr"));
+ language.setLanguage(lang);
+ QVERIFY(language.isValid());
+ QCOMPARE(language.language(), lang);
+}
+
+void LangTest::shouldSerialized()
+{
+ KContacts::Lang language;
+ KContacts::Lang result;
+ const QString lang(QStringLiteral("fr"));
+ language.setLanguage(lang);
+ QMap<QString, QStringList> params;
+ params.insert(QStringLiteral("Foo1"), QStringList() << QStringLiteral("bla1") << QStringLiteral("blo1"));
+ params.insert(QStringLiteral("Foo2"), QStringList() << QStringLiteral("bla2") << QStringLiteral("blo2"));
+ language.setParameters(params);
+
+ QByteArray data;
+ QDataStream s(&data, QIODevice::WriteOnly);
+ s << language;
+
+ QDataStream t(&data, QIODevice::ReadOnly);
+ t >> result;
+
+ QVERIFY(language == result);
+
+}
+
+void LangTest::shouldEqualLanguage()
+{
+ KContacts::Lang language;
+ KContacts::Lang result;
+ const QString lang(QStringLiteral("fr"));
+ language.setLanguage(lang);
+ QMap<QString, QStringList> params;
+ params.insert(QStringLiteral("Foo1"), QStringList() << QStringLiteral("bla1") << QStringLiteral("blo1"));
+ params.insert(QStringLiteral("Foo2"), QStringList() << QStringLiteral("bla2") << QStringLiteral("blo2"));
+ language.setParameters(params);
+
+ result = language;
+ QVERIFY(language == result);
+}
+
+void LangTest::shouldParseLanguage()
+{
+ QByteArray vcarddata("BEGIN:VCARD\n"
+ "VERSION:3.0\n"
+ "N:LastName;FirstName;;;\n"
+ "UID:c80cf296-0825-4eb0-ab16-1fac1d522a33@xxxxxx.xx\n"
+ "LANG:fr"
+ "REV:2015-03-14T09:24:45+00:00\n"
+ "FN:FirstName LastName\n"
+ "END:VCARD\n");
+
+ KContacts::VCardTool vcard;
+ const KContacts::AddresseeList lst = vcard.parseVCards(vcarddata);
+ QCOMPARE(lst.count(), 1);
+ QCOMPARE(lst.at(0).langs().count(), 1);
+}
+
+void LangTest::shouldParseWithoutLanguage()
+{
+ QByteArray vcarddata("BEGIN:VCARD\n"
+ "VERSION:3.0\n"
+ "N:LastName;FirstName;;;\n"
+ "UID:c80cf296-0825-4eb0-ab16-1fac1d522a33@xxxxxx.xx\n"
+ "REV:2015-03-14T09:24:45+00:00\n"
+ "FN:FirstName LastName\n"
+ "END:VCARD\n");
+
+ KContacts::VCardTool vcard;
+ const KContacts::AddresseeList lst = vcard.parseVCards(vcarddata);
+ QCOMPARE(lst.count(), 1);
+ QCOMPARE(lst.at(0).langs().count(), 0);
+}
+
+void LangTest::shouldCreateVCard()
+{
+ KContacts::AddresseeList lst;
+ KContacts::Addressee addr;
+ addr.setEmails(QStringList() << QStringLiteral("foo@kde.org"));
+ addr.setUid(QStringLiteral("testuid"));
+ KContacts::Lang::List lstLang;
+ KContacts::Lang lang(QStringLiteral("fr"));
+ lstLang << lang;
+ addr.setLangs(lstLang);
+ lst << addr;
+ KContacts::VCardTool vcard;
+ const QByteArray ba = vcard.exportVCards(lst, KContacts::VCard::v4_0);
+ QByteArray expected("BEGIN:VCARD\r\n"
+ "VERSION:4.0\r\n"
+ "EMAIL:foo@kde.org\r\n"
+ "LANG:fr\r\n"
+ "N:;;;;\r\n"
+ "UID:testuid\r\n"
+ "END:VCARD\r\n\r\n");
+
+ QCOMPARE(ba, expected);
+}
+
+void LangTest::shouldCreateVCardWithTwoLang()
+{
+ KContacts::AddresseeList lst;
+ KContacts::Addressee addr;
+ addr.setEmails(QStringList() << QStringLiteral("foo@kde.org"));
+ addr.setUid(QStringLiteral("testuid"));
+ KContacts::Lang::List lstLang;
+ KContacts::Lang lang(QStringLiteral("fr"));
+ KContacts::Lang lang2(QStringLiteral("fr2"));
+ lstLang << lang << lang2;
+ addr.setLangs(lstLang);
+ lst << addr;
+ KContacts::VCardTool vcard;
+ const QByteArray ba = vcard.exportVCards(lst, KContacts::VCard::v4_0);
+ QByteArray expected("BEGIN:VCARD\r\n"
+ "VERSION:4.0\r\n"
+ "EMAIL:foo@kde.org\r\n"
+ "LANG:fr\r\n"
+ "LANG:fr2\r\n"
+ "N:;;;;\r\n"
+ "UID:testuid\r\n"
+ "END:VCARD\r\n\r\n");
+
+ QCOMPARE(ba, expected);
+
+}
+
+void LangTest::shouldCreateVCardWithParameters()
+{
+ KContacts::AddresseeList lst;
+ KContacts::Addressee addr;
+ addr.setEmails(QStringList() << QStringLiteral("foo@kde.org"));
+ addr.setUid(QStringLiteral("testuid"));
+ KContacts::Lang::List lstLang;
+ KContacts::Lang lang(QStringLiteral("fr"));
+ QMap<QString, QStringList> params;
+ params.insert(QStringLiteral("Foo1"), QStringList() << QStringLiteral("bla1") << QStringLiteral("blo1"));
+ params.insert(QStringLiteral("Foo2"), QStringList() << QStringLiteral("bla2") << QStringLiteral("blo2"));
+ lang.setParameters(params);
+ lstLang << lang;
+ addr.setLangs(lstLang);
+ lst << addr;
+ KContacts::VCardTool vcard;
+ const QByteArray ba = vcard.exportVCards(lst, KContacts::VCard::v4_0);
+ QByteArray expected("BEGIN:VCARD\r\n"
+ "VERSION:4.0\r\n"
+ "EMAIL:foo@kde.org\r\n"
+ "LANG;FOO1=bla1,blo1;FOO2=bla2,blo2:fr\r\n"
+ "N:;;;;\r\n"
+ "UID:testuid\r\n"
+ "END:VCARD\r\n\r\n");
+ QCOMPARE(ba, expected);
+}
+
+void LangTest::shouldNotGenerateLangForVCard3()
+{
+ KContacts::AddresseeList lst;
+ KContacts::Addressee addr;
+ addr.setEmails(QStringList() << QStringLiteral("foo@kde.org"));
+ addr.setUid(QStringLiteral("testuid"));
+ KContacts::Lang::List lstLang;
+ KContacts::Lang lang(QStringLiteral("fr"));
+ QMap<QString, QStringList> params;
+ params.insert(QStringLiteral("Foo1"), QStringList() << QStringLiteral("bla1") << QStringLiteral("blo1"));
+ params.insert(QStringLiteral("Foo2"), QStringList() << QStringLiteral("bla2") << QStringLiteral("blo2"));
+ lang.setParameters(params);
+ lstLang << lang;
+ addr.setLangs(lstLang);
+ lst << addr;
+ KContacts::VCardTool vcard;
+ const QByteArray ba = vcard.exportVCards(lst, KContacts::VCard::v3_0);
+ QByteArray expected("BEGIN:VCARD\r\n"
+ "VERSION:3.0\r\n"
+ "EMAIL:foo@kde.org\r\n"
+ "N:;;;;\r\n"
+ "UID:testuid\r\n"
+ "END:VCARD\r\n\r\n");
+ QCOMPARE(ba, expected);
+}
+
+QTEST_MAIN(LangTest)
--- /dev/null
+/*
+ This file is part of the KContacts framework.
+ Copyright (c) 2015 Laurent Montel <montel@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef LANGTEST_H
+#define LANGTEST_H
+
+#include <QObject>
+
+class LangTest : public QObject
+{
+ Q_OBJECT
+public:
+ explicit LangTest(QObject *parent = Q_NULLPTR);
+ ~LangTest();
+private Q_SLOTS:
+ void shouldHaveDefaultValue();
+ void shouldAssignValue();
+ void shouldAssignExternal();
+ void shouldSerialized();
+ void shouldEqualLanguage();
+ void shouldParseLanguage();
+ void shouldParseWithoutLanguage();
+ void shouldCreateVCard();
+ void shouldCreateVCardWithTwoLang();
+ void shouldCreateVCardWithParameters();
+ void shouldNotGenerateLangForVCard3();
+};
+
+#endif // LANGTEST_H
--- /dev/null
+/*
+ This file is part of libkabc.
+ Copyright (c) 2015 Laurent Montel <montel@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "ldifconvertertest.h"
+#include "converter/ldifconverter.h"
+#include <qtest.h>
+using namespace KContacts;
+
+LDifConverterTest::LDifConverterTest(QObject *parent)
+ : QObject(parent)
+{
+
+}
+
+LDifConverterTest::~LDifConverterTest()
+{
+
+}
+
+void LDifConverterTest::shouldImportEmail()
+{
+ QString str = QStringLiteral("dn: cn=laurent,mail=foo@kde.org\n"
+ "sn: laurent\n"
+ "cn: laurent\n"
+ "uid: d1d5cdd4-7d5d-484b-828d-58864d8efe74\n"
+ "mail: foo@kde.org\n"
+ "objectclass: top_n"
+ "objectclass: person\n"
+ "objectclass: organizationalPerson");
+ AddresseeList lst;
+ ContactGroup::List contactGroup;
+ bool result = LDIFConverter::LDIFToAddressee(str, lst, contactGroup);
+ QVERIFY(result);
+ QCOMPARE(lst.count(), 1);
+ QCOMPARE(lst.at(0).emails().count(), 1);
+ QCOMPARE(lst.at(0).emails().at(0), QStringLiteral("foo@kde.org"));
+ QCOMPARE(contactGroup.count(), 0);
+}
+
+void LDifConverterTest::shouldImportMultiEmails()
+{
+ QString str = QStringLiteral("dn: cn=laurent,mail=foo@kde.org\n"
+ "sn: laurent\n"
+ "cn: laurent\n"
+ "uid: d1d5cdd4-7d5d-484b-828d-58864d8efe74\n"
+ "mail: foo@kde.org\n"
+ "mail: foo2@kde.org\n"
+ "objectclass: top_n"
+ "objectclass: person\n"
+ "objectclass: organizationalPerson");
+ AddresseeList lst;
+ ContactGroup::List contactGroup;
+ bool result = LDIFConverter::LDIFToAddressee(str, lst, contactGroup);
+ QVERIFY(result);
+ QCOMPARE(lst.count(), 1);
+ QCOMPARE(lst.at(0).emails().count(), 2);
+ QCOMPARE(lst.at(0).emails().at(0), QStringLiteral("foo@kde.org"));
+ QCOMPARE(lst.at(0).emails().at(1), QStringLiteral("foo2@kde.org"));
+ QCOMPARE(contactGroup.count(), 0);
+}
+
+void LDifConverterTest::shouldImportStandardBirthday()
+{
+ QString str = QStringLiteral("dn: cn=laurent,mail=foo@kde.org\n"
+ "sn: laurent\n"
+ "cn: laurent\n"
+ "uid: d1d5cdd4-7d5d-484b-828d-58864d8efe74\n"
+ "birthyear: 2015\n"
+ "birthmonth: 3\n"
+ "birthday: 19\n"
+ "mail: foo@kde.org\n"
+ "objectclass: top_n"
+ "objectclass: person\n"
+ "objectclass: organizationalPerson");
+ AddresseeList lst;
+ ContactGroup::List contactGroup;
+ bool result = LDIFConverter::LDIFToAddressee(str, lst, contactGroup);
+ QVERIFY(result);
+ QCOMPARE(lst.count(), 1);
+ QVERIFY(lst.at(0).birthday().date().isValid());
+ QCOMPARE(lst.at(0).birthday().date(), QDate(2015, 3, 19));
+ QCOMPARE(contactGroup.count(), 0);
+}
+
+void LDifConverterTest::shouldImportTheBatsBirthday()
+{
+ QString str = QStringLiteral("dn: cn=laurent,mail=foo@kde.org\n"
+ "sn: laurent\n"
+ "cn: laurent\n"
+ "uid: d1d5cdd4-7d5d-484b-828d-58864d8efe74\n"
+ "xbatBirthday: 20150319\n"
+ "mail: foo@kde.org\n"
+ "objectclass: top_n"
+ "objectclass: person\n"
+ "objectclass: organizationalPerson");
+ AddresseeList lst;
+ ContactGroup::List contactGroup;
+ bool result = LDIFConverter::LDIFToAddressee(str, lst, contactGroup);
+ QVERIFY(result);
+ QCOMPARE(lst.count(), 1);
+ QVERIFY(lst.at(0).birthday().date().isValid());
+ QCOMPARE(lst.at(0).birthday().date(), QDate(2015, 3, 19));
+ QCOMPARE(contactGroup.count(), 0);
+}
+
+void LDifConverterTest::shouldImportTheBatsEmails()
+{
+ QString str = QStringLiteral("dn: cn=laurent,mail=foo@kde.org\n"
+ "sn: laurent\n"
+ "cn: laurent\n"
+ "uid: d1d5cdd4-7d5d-484b-828d-58864d8efe74\n"
+ "mail: foo@kde.org\n"
+ "othermailbox: foo2@kde.org\n"
+ "othermailbox: foo3@kde.org\n"
+ "objectclass: top_n"
+ "objectclass: person\n"
+ "objectclass: organizationalPerson");
+ AddresseeList lst;
+ ContactGroup::List contactGroup;
+ bool result = LDIFConverter::LDIFToAddressee(str, lst, contactGroup);
+ QVERIFY(result);
+ QCOMPARE(lst.count(), 1);
+ QCOMPARE(lst.at(0).emails().count(), 3);
+ QCOMPARE(lst.at(0).emails().at(0), QStringLiteral("foo@kde.org"));
+ QCOMPARE(lst.at(0).emails().at(1), QStringLiteral("foo2@kde.org"));
+ QCOMPARE(lst.at(0).emails().at(2), QStringLiteral("foo3@kde.org"));
+ QCOMPARE(contactGroup.count(), 0);
+}
+
+void LDifConverterTest::shouldImportTitle()
+{
+ QString str = QStringLiteral("dn: cn=laurent,mail=foo@kde.org\n"
+ "sn: laurent\n"
+ "cn: laurent\n"
+ "uid: d1d5cdd4-7d5d-484b-828d-58864d8efe74\n"
+ "title: foo\n"
+ "mail: foo@kde.org\n"
+ "objectclass: top_n"
+ "objectclass: person\n"
+ "objectclass: organizationalPerson");
+ AddresseeList lst;
+ ContactGroup::List contactGroup;
+ bool result = LDIFConverter::LDIFToAddressee(str, lst, contactGroup);
+ QVERIFY(result);
+ QCOMPARE(lst.count(), 1);
+ QCOMPARE(lst.at(0).title(), QStringLiteral("foo"));
+ QCOMPARE(contactGroup.count(), 0);
+}
+
+void LDifConverterTest::shouldImportWorkStreet()
+{
+ QString str = QStringLiteral("dn: cn=laurent,mail=foo@kde.org\n"
+ "sn: laurent\n"
+ "cn: laurent\n"
+ "uid: d1d5cdd4-7d5d-484b-828d-58864d8efe74\n"
+ "title: foo\n"
+ "mail: foo@kde.org\n"
+ "street: work address\n"
+ "mozillaWorkStreet2: work address next\n"
+ "objectclass: top_n"
+ "objectclass: person\n"
+ "objectclass: organizationalPerson");
+ AddresseeList lst;
+ ContactGroup::List contactGroup;
+ bool result = LDIFConverter::LDIFToAddressee(str, lst, contactGroup);
+ QVERIFY(result);
+ QCOMPARE(lst.count(), 1);
+ QCOMPARE(lst.at(0).address(Address::Work).street(), QStringLiteral("work address\nwork address next"));
+ QCOMPARE(contactGroup.count(), 0);
+}
+
+void LDifConverterTest::shouldImportContactGroup()
+{
+ QString str = QStringLiteral("dn: cn=test,mail=\n"
+ "cn: test\n"
+ "modifyTimeStamp: 20080526T234914Z\n"
+ "display-name: Test\n"
+ "objectclass: top\n"
+ "objectclass: groupOfNames\n"
+ "member: cn=Jim Doe,mail=jim.doe@foobar.com\n"
+ "member: cn=Jane Doe,mail=jane.doe@foobar.com\n"
+ "member: cn=John Doe,mail=john.doe@foobar.com\n");
+ AddresseeList lst;
+ ContactGroup::List contactGroup;
+ bool result = LDIFConverter::LDIFToAddressee(str, lst, contactGroup);
+ QVERIFY(result);
+ QCOMPARE(lst.count(), 0);
+ QCOMPARE(contactGroup.count(), 1);
+ ContactGroup first = contactGroup.first();
+ QCOMPARE(first.name(), QStringLiteral("Test"));
+ QCOMPARE((int)first.count(), 3);
+}
+
+void LDifConverterTest::shouldImportMultiEntries()
+{
+ QString str = QStringLiteral("dn: cn=test1,mail=test1@test.test\n"
+ "sn: test1\n"
+ "cn: test1\n"
+ "uid: jpgdf2NrLQ\n"
+ "mail: test1@test.test\n"
+ "modifytimestamp: 20121219T140848Z\n"
+ "objectclass: top\n"
+ "objectclass: person\n"
+ "objectclass: organizationalPerson\n"
+ "\n"
+ "dn: cn=test2,mail=test2@test.test\n"
+ "sn: test2\n"
+ "cn: test2\n"
+ "uid: ow2mwdUb6A\n"
+ "mail: test2@test.test\n"
+ "objectclass: top\n"
+ "objectclass: person\n"
+ "objectclass: organizationalPerson\n");
+ AddresseeList lst;
+ ContactGroup::List contactGroup;
+ bool result = LDIFConverter::LDIFToAddressee(str, lst, contactGroup);
+ QVERIFY(result);
+ QCOMPARE(lst.count(), 2);
+ QCOMPARE(contactGroup.count(), 0);
+ QCOMPARE(lst.at(0).emails().at(0), QStringLiteral("test1@test.test"));
+ QCOMPARE(lst.at(1).emails().at(0), QStringLiteral("test2@test.test"));
+}
+
+void LDifConverterTest::shouldImportGroupAndAddress()
+{
+ QString str = QStringLiteral("dn: cn=laurent,mail=foo@kde.org\n"
+ "sn: laurent\n"
+ "cn: laurent\n"
+ "uid: d1d5cdd4-7d5d-484b-828d-58864d8efe74\n"
+ "title: foo\n"
+ "mail: foo@kde.org\n"
+ "street: work address\n"
+ "mozillaWorkStreet2: work address next\n"
+ "objectclass: top_n"
+ "objectclass: person\n"
+ "objectclass: organizationalPerson\n"
+ "\n"
+ "dn: cn=test,mail=\n"
+ "cn: test\n"
+ "modifyTimeStamp: 20080526T234914Z\n"
+ "display-name: Test\n"
+ "objectclass: top\n"
+ "objectclass: groupOfNames\n"
+ "member: cn=Jim Doe,mail=jim.doe@foobar.com\n"
+ "member: cn=Jane Doe,mail=jane.doe@foobar.com\n"
+ "member: cn=John Doe,mail=john.doe@foobar.com\n");
+
+ AddresseeList lst;
+ ContactGroup::List contactGroup;
+ bool result = LDIFConverter::LDIFToAddressee(str, lst, contactGroup);
+ QVERIFY(result);
+ QCOMPARE(lst.count(), 1);
+ QCOMPARE(contactGroup.count(), 1);
+}
+
+void LDifConverterTest::shouldExportEmail()
+{
+ AddresseeList lst;
+ ContactGroup::List contactGroup;
+ Addressee addr;
+ addr.setEmails(QStringList() << QStringLiteral("foo@kde.org"));
+ addr.setUid(QStringLiteral("testuid"));
+ lst << addr;
+ QString str;
+ bool result = LDIFConverter::addresseeAndContactGroupToLDIF(lst, contactGroup, str);
+ QVERIFY(result);
+ QString expected = QStringLiteral("dn: cn=,mail=foo@kde.org\n"
+ "objectclass: top\n"
+ "objectclass: person\n"
+ "objectclass: organizationalPerson\n"
+ "uid: testuid\n"
+ "mail: foo@kde.org\n\n");
+
+ QCOMPARE(str, expected);
+}
+
+void LDifConverterTest::shouldExportMultiEmails()
+{
+ AddresseeList lst;
+ ContactGroup::List contactGroup;
+ Addressee addr;
+ addr.setEmails(QStringList() << QStringLiteral("foo@kde.org") << QStringLiteral("foo2@kde.org") << QStringLiteral("foo3@kde.org"));
+ addr.setUid(QStringLiteral("testuid"));
+ lst << addr;
+ QString str;
+ bool result = LDIFConverter::addresseeAndContactGroupToLDIF(lst, contactGroup, str);
+ QVERIFY(result);
+ QString expected = QStringLiteral("dn: cn=,mail=foo@kde.org\n"
+ "objectclass: top\n"
+ "objectclass: person\n"
+ "objectclass: organizationalPerson\n"
+ "uid: testuid\n"
+ "mail: foo@kde.org\n"
+ "mozillasecondemail: foo2@kde.org\n"
+ "othermailbox: foo3@kde.org\n"
+ "\n");
+
+ QCOMPARE(str, expected);
+
+}
+
+void LDifConverterTest::shouldExportBirthday()
+{
+ AddresseeList lst;
+ ContactGroup::List contactGroup;
+ Addressee addr;
+ QDate date(2015, 3, 3);
+ addr.setBirthday(QDateTime(date));
+ addr.setEmails(QStringList() << QStringLiteral("foo@kde.org"));
+ addr.setUid(QStringLiteral("testuid"));
+ lst << addr;
+ QString str;
+ bool result = LDIFConverter::addresseeAndContactGroupToLDIF(lst, contactGroup, str);
+ QVERIFY(result);
+ QString expected = QStringLiteral("dn: cn=,mail=foo@kde.org\n"
+ "objectclass: top\n"
+ "objectclass: person\n"
+ "objectclass: organizationalPerson\n"
+ "uid: testuid\n"
+ "mail: foo@kde.org\n"
+ "birthyear: 2015\n"
+ "birthmonth: 3\n"
+ "birthday: 3\n"
+ "\n");
+
+ QCOMPARE(str, expected);
+}
+
+void LDifConverterTest::shouldExportTitle()
+{
+ AddresseeList lst;
+ ContactGroup::List contactGroup;
+ Addressee addr;
+ addr.setEmails(QStringList() << QStringLiteral("foo@kde.org"));
+ addr.setTitle(QStringLiteral("foo"));
+ addr.setUid(QStringLiteral("testuid"));
+ lst << addr;
+ QString str;
+ bool result = LDIFConverter::addresseeAndContactGroupToLDIF(lst, contactGroup, str);
+ QVERIFY(result);
+ QString expected = QStringLiteral("dn: cn=,mail=foo@kde.org\n"
+ "objectclass: top\n"
+ "objectclass: person\n"
+ "objectclass: organizationalPerson\n"
+ "uid: testuid\n"
+ "mail: foo@kde.org\n"
+ "title: foo\n"
+ "\n");
+
+ QCOMPARE(str, expected);
+}
+
+void LDifConverterTest::shouldExportMultiEntries()
+{
+ AddresseeList lst;
+ ContactGroup::List contactGroup;
+ Addressee addr;
+ addr.setEmails(QStringList() << QStringLiteral("foo@kde.org"));
+ addr.setTitle(QStringLiteral("foo"));
+ addr.setUid(QStringLiteral("testuid"));
+ lst << addr;
+
+ Addressee addr2;
+ QDate date(2015, 3, 3);
+ addr2.setBirthday(QDateTime(date));
+ addr2.setEmails(QStringList() << QStringLiteral("foo@kde.org"));
+ addr2.setUid(QStringLiteral("testuid"));
+ lst << addr2;
+
+ QString str;
+ bool result = LDIFConverter::addresseeAndContactGroupToLDIF(lst, contactGroup, str);
+ QVERIFY(result);
+
+ const QString expected = QStringLiteral("dn: cn=,mail=foo@kde.org\n"
+ "objectclass: top\n"
+ "objectclass: person\n"
+ "objectclass: organizationalPerson\n"
+ "uid: testuid\n"
+ "mail: foo@kde.org\n"
+ "title: foo\n"
+ "\n"
+ "dn: cn=,mail=foo@kde.org\n"
+ "objectclass: top\n"
+ "objectclass: person\n"
+ "objectclass: organizationalPerson\n"
+ "uid: testuid\n"
+ "mail: foo@kde.org\n"
+ "birthyear: 2015\n"
+ "birthmonth: 3\n"
+ "birthday: 3\n"
+ "\n");
+ QCOMPARE(str, expected);
+}
+
+void LDifConverterTest::shouldExportGroup()
+{
+ AddresseeList lst;
+ ContactGroup::List contactGroup;
+ ContactGroup grp;
+ ContactGroup::Data data;
+ data.setEmail(QStringLiteral("foo@kde.org"));
+ data.setName(QStringLiteral("foo"));
+ grp.append(data);
+ ContactGroup::Data data2;
+ data2.setEmail(QStringLiteral("foo2@kde.org"));
+ data2.setName(QStringLiteral("foo2"));
+ grp.append(data2);
+ contactGroup.append(grp);
+
+ QString str;
+ bool result = LDIFConverter::addresseeAndContactGroupToLDIF(lst, contactGroup, str);
+ QVERIFY(result);
+
+ const QString expected = QStringLiteral("objectclass: top\n"
+ "objectclass: groupOfNames\n"
+ "member: cn=foo,mail=foo@kde.org\n"
+ "member: cn=foo2,mail=foo2@kde.org\n"
+ "\n");
+ QCOMPARE(str, expected);
+}
+
+void LDifConverterTest::shouldExportWorkStreet()
+{
+ AddresseeList lst;
+ Addressee addr;
+ addr.setEmails(QStringList() << QStringLiteral("foo@kde.org"));
+ addr.setUid(QStringLiteral("testuid"));
+ Address address(Address::Work);
+ address.setStreet(QStringLiteral("work address"));
+ address.setPostalCode(QStringLiteral("postal"));
+ addr.insertAddress(address);
+ lst << addr;
+ ContactGroup::List contactGroup;
+
+ QString str;
+ bool result = LDIFConverter::addresseeAndContactGroupToLDIF(lst, contactGroup, str);
+ QVERIFY(result);
+
+ const QString expected = QStringLiteral("dn: cn=,mail=foo@kde.org\n"
+ "objectclass: top\n"
+ "objectclass: person\n"
+ "objectclass: organizationalPerson\n"
+ "uid: testuid\n"
+ "mail: foo@kde.org\n"
+ "postalcode: postal\n"
+ "streetaddress: work address\n"
+ "street: work address\n"
+ "\n");
+ QCOMPARE(str, expected);
+}
+
+void LDifConverterTest::shouldExportFullName()
+{
+ AddresseeList lst;
+ Addressee addr;
+ addr.setEmails(QStringList() << QStringLiteral("foo@kde.org"));
+ addr.setUid(QStringLiteral("testuid"));
+ addr.setName(QStringLiteral("name"));
+ addr.setNickName(QStringLiteral("nickname"));
+ addr.setFamilyName(QStringLiteral("familyname"));
+ lst << addr;
+ ContactGroup::List contactGroup;
+
+ QString str;
+ bool result = LDIFConverter::addresseeAndContactGroupToLDIF(lst, contactGroup, str);
+ QVERIFY(result);
+
+ const QString expected = QStringLiteral("dn: cn=,mail=foo@kde.org\n"
+ "objectclass: top\n"
+ "objectclass: person\n"
+ "objectclass: organizationalPerson\n"
+ "sn: familyname\n"
+ "uid: testuid\n"
+ "nickname: nickname\n"
+ "xmozillanickname: nickname\n"
+ "mozillanickname: nickname\n"
+ "mail: foo@kde.org\n"
+ "\n");
+
+ QCOMPARE(str, expected);
+}
+
+QTEST_MAIN(LDifConverterTest)
--- /dev/null
+/*
+ This file is part of libkabc.
+ Copyright (c) 2015 Laurent Montel <montel@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef LDIFCONVERTERTEST_H
+#define LDIFCONVERTERTEST_H
+
+#include <QObject>
+
+class LDifConverterTest : public QObject
+{
+ Q_OBJECT
+public:
+ explicit LDifConverterTest(QObject *parent = Q_NULLPTR);
+ ~LDifConverterTest();
+
+private Q_SLOTS:
+ //Import
+ void shouldImportEmail();
+ void shouldImportMultiEmails();
+ void shouldImportStandardBirthday();
+ void shouldImportTheBatsBirthday();
+ void shouldImportTheBatsEmails();
+ void shouldImportTitle();
+ void shouldImportWorkStreet();
+ void shouldImportContactGroup();
+ void shouldImportMultiEntries();
+ void shouldImportGroupAndAddress();
+
+ //Export
+ void shouldExportEmail();
+ void shouldExportBirthday();
+ void shouldExportTitle();
+ void shouldExportMultiEntries();
+ void shouldExportGroup();
+ void shouldExportWorkStreet();
+ void shouldExportMultiEmails();
+ void shouldExportFullName();
+};
+
+#endif // LDIFCONVERTERTEST_H
--- /dev/null
+/*
+ This file is part of the KContacts framework.
+ Copyright (c) 2007 Tobias Koenig <tokoe@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "phonenumbertest.h"
+#include "kcontacts/phonenumber.h"
+#include <qtest.h>
+
+QTEST_MAIN(PhoneNumberTest)
+
+void PhoneNumberTest::emptyTest()
+{
+ KContacts::PhoneNumber number;
+
+ QVERIFY(number.isEmpty());
+}
+
+void PhoneNumberTest::storeTest()
+{
+ KContacts::PhoneNumber number;
+
+ number.setId(QStringLiteral("My Id"));
+ number.setType(KContacts::PhoneNumber::Work | KContacts::PhoneNumber::Cell);
+ number.setNumber(QStringLiteral("2734826345"));
+
+ QVERIFY(number.id() == QLatin1String("My Id"));
+ QVERIFY(number.type() == (KContacts::PhoneNumber::Work | KContacts::PhoneNumber::Cell));
+ QVERIFY(number.number() == QLatin1String("2734826345"));
+}
+
+void PhoneNumberTest::equalsTest()
+{
+ KContacts::PhoneNumber number1, number2;
+
+ number1.setId(QStringLiteral("My Id"));
+ number1.setType(KContacts::PhoneNumber::Work | KContacts::PhoneNumber::Cell);
+ number1.setNumber(QStringLiteral("2734826345"));
+
+ number2.setId(QStringLiteral("My Id"));
+ number2.setType(KContacts::PhoneNumber::Work | KContacts::PhoneNumber::Cell);
+ number2.setNumber(QStringLiteral("2734826345"));
+
+ QVERIFY(number1 == number2);
+}
+
+void PhoneNumberTest::differsTest()
+{
+ KContacts::PhoneNumber number1(QStringLiteral("123"), KContacts::PhoneNumber::Home);
+ KContacts::PhoneNumber number2(QStringLiteral("123"), KContacts::PhoneNumber::Work);
+
+ QVERIFY(number1 != number2);
+}
+
+void PhoneNumberTest::assignmentTest()
+{
+ KContacts::PhoneNumber number1, number2;
+
+ number1.setId(QStringLiteral("My Id"));
+ number1.setType(KContacts::PhoneNumber::Work | KContacts::PhoneNumber::Cell);
+ number1.setNumber(QStringLiteral("2734826345"));
+
+ number1 = number2;
+
+ QVERIFY(number1 == number2);
+}
+
+void PhoneNumberTest::serializeTest()
+{
+ KContacts::PhoneNumber number1, number2;
+
+ number1.setId(QStringLiteral("My Id"));
+ number1.setType(KContacts::PhoneNumber::Work | KContacts::PhoneNumber::Cell);
+ number1.setNumber(QStringLiteral("2734826345"));
+
+ QByteArray data;
+ QDataStream s(&data, QIODevice::WriteOnly);
+ s << number1;
+
+ QDataStream t(&data, QIODevice::ReadOnly);
+ t >> number2;
+
+ QVERIFY(number1 == number2);
+}
+
+void PhoneNumberTest::labelTest()
+{
+ QMap<KContacts::PhoneNumber::Type, QString> labels;
+
+ const KContacts::PhoneNumber::TypeList types = KContacts::PhoneNumber::typeList();
+
+ // check all types standalone
+ Q_FOREACH (KContacts::PhoneNumber::Type type, types) {
+ const KContacts::PhoneNumber phone(QStringLiteral("1"), type);
+ QCOMPARE(phone.type(), type);
+
+ // Pref is special cased
+ if (type != KContacts::PhoneNumber::Pref) {
+ QCOMPARE(phone.typeLabel(), KContacts::PhoneNumber::typeFlagLabel((KContacts::PhoneNumber::TypeFlag)(int)type));
+ labels.insert(type, phone.typeLabel());
+ } else {
+ labels.insert(type, KContacts::PhoneNumber::typeFlagLabel((KContacts::PhoneNumber::TypeFlag)(int)type));
+ }
+ QCOMPARE(KContacts::PhoneNumber::typeLabel(type), phone.typeLabel());
+ }
+
+ // combine all with Pref
+ Q_FOREACH (KContacts::PhoneNumber::Type type, types) {
+ KContacts::PhoneNumber::Type combinedType = type | KContacts::PhoneNumber::Pref;
+ const KContacts::PhoneNumber phone(QLatin1String("1"), combinedType);
+ QCOMPARE(phone.type(), combinedType);
+ QCOMPARE(KContacts::PhoneNumber::typeLabel(combinedType), phone.typeLabel());
+
+ if (type < KContacts::PhoneNumber::Pref) {
+ const QString expectedCombinedString = QStringLiteral("%1/%2").arg(labels[type]).arg(labels[KContacts::PhoneNumber::Pref]);
+ QCOMPARE(phone.typeLabel(), expectedCombinedString);
+ } else if (type > KContacts::PhoneNumber::Pref) {
+ const QString expectedCombinedString = QStringLiteral("%1/%2").arg(labels[KContacts::PhoneNumber::Pref]).arg(labels[type]);
+ QCOMPARE(phone.typeLabel(), expectedCombinedString);
+ }
+ }
+
+ // combine all with Fax
+ Q_FOREACH (KContacts::PhoneNumber::Type type, types) {
+ KContacts::PhoneNumber::Type combinedType = type | KContacts::PhoneNumber::Fax;
+ const KContacts::PhoneNumber phone(QLatin1String("1"), combinedType);
+ QCOMPARE(phone.type(), combinedType);
+ QCOMPARE(KContacts::PhoneNumber::typeLabel(combinedType), phone.typeLabel());
+
+ if (type == KContacts::PhoneNumber::Home ||
+ type == KContacts::PhoneNumber::Work) {
+ // special cased
+ } else if (type < KContacts::PhoneNumber::Fax) {
+ const QString expectedCombinedString = QStringLiteral("%1/%2").arg(labels[type]).arg(labels[KContacts::PhoneNumber::Fax]);
+ QCOMPARE(phone.typeLabel(), expectedCombinedString);
+ } else if (type > KContacts::PhoneNumber::Fax) {
+ const QString expectedCombinedString = QStringLiteral("%1/%2").arg(labels[KContacts::PhoneNumber::Fax]).arg(labels[type]);
+ QCOMPARE(phone.typeLabel(), expectedCombinedString);
+ }
+ }
+
+ // special cases
+ QCOMPARE(KContacts::PhoneNumber::typeLabel(KContacts::PhoneNumber::Pref), QLatin1String("Preferred Number"));
+ QCOMPARE(KContacts::PhoneNumber::typeLabel(KContacts::PhoneNumber::Home |
+ KContacts::PhoneNumber::Fax),
+ QLatin1String("Home Fax"));
+ QCOMPARE(KContacts::PhoneNumber::typeLabel(KContacts::PhoneNumber::Work |
+ KContacts::PhoneNumber::Fax),
+ QLatin1String("Work Fax"));
+ QCOMPARE(KContacts::PhoneNumber::typeLabel(KContacts::PhoneNumber::Home |
+ KContacts::PhoneNumber::Fax |
+ KContacts::PhoneNumber::Pref),
+ QLatin1String("Home Fax/Preferred"));
+ QCOMPARE(KContacts::PhoneNumber::typeLabel(KContacts::PhoneNumber::Work |
+ KContacts::PhoneNumber::Fax |
+ KContacts::PhoneNumber::Pref),
+ QLatin1String("Work Fax/Preferred"));
+}
--- /dev/null
+/*
+ This file is part of the KContacts framework.
+ Copyright (c) 2007 Tobias Koenig <tokoe@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef PHONENUMBER_TEST_H
+#define PHONENUMBER_TEST_H
+
+#include <QtCore/QObject>
+
+class PhoneNumberTest : public QObject
+{
+ Q_OBJECT
+
+private Q_SLOTS:
+ void emptyTest();
+ void storeTest();
+ void equalsTest();
+ void differsTest();
+ void assignmentTest();
+ void serializeTest();
+ void labelTest();
+};
+
+#endif
--- /dev/null
+/*
+ This file is part of the KContacts framework.
+ Copyright (c) 2007 Tobias Koenig <tokoe@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "picturetest.h"
+#include "kcontacts/picture.h"
+#include <QPainter>
+#include <qtest.h>
+#include <QBuffer>
+
+QTEST_MAIN(PictureTest)
+
+static QImage testImage()
+{
+ static QImage image;
+
+ if (image.isNull()) {
+ image = QImage(200, 200, QImage::Format_RGB32);
+ QPainter p(&image);
+ p.drawRect(10, 10, 50, 50);
+ }
+
+ return image;
+}
+
+static QByteArray testImageRawPNG()
+{
+ static QByteArray raw;
+
+ if (raw.isNull()) {
+ QBuffer buffer(&raw);
+ buffer.open(QIODevice::WriteOnly);
+ testImage().save(&buffer, "PNG");
+ }
+
+ return raw;
+}
+
+static QByteArray testImageRawJPEG()
+{
+ static QByteArray raw;
+
+ if (raw.isNull()) {
+ QBuffer buffer(&raw);
+ buffer.open(QIODevice::WriteOnly);
+ testImage().save(&buffer, "JPEG");
+ }
+
+ return raw;
+}
+
+void PictureTest::emptyTest()
+{
+ KContacts::Picture picture;
+
+ QVERIFY(picture.isEmpty());
+}
+
+void PictureTest::storeTestInternImage()
+{
+ KContacts::Picture picture;
+
+ picture.setData(testImage());
+
+ QVERIFY(picture.isEmpty() == false);
+ QVERIFY(picture.isIntern() == true);
+ QVERIFY(picture.type() == QLatin1String("jpeg"));
+ QVERIFY(picture.data() == testImage());
+ QVERIFY(picture.rawData() == testImageRawJPEG());
+}
+
+void PictureTest::storeTestInternRawData()
+{
+ KContacts::Picture picture;
+
+ picture.setRawData(testImageRawPNG(), QStringLiteral("png"));
+
+ QVERIFY(picture.isEmpty() == false);
+ QVERIFY(picture.isIntern() == true);
+ QVERIFY(picture.type() == QLatin1String("png"));
+ QVERIFY(picture.rawData() == testImageRawPNG());
+ QVERIFY(picture.data() == testImage());
+}
+
+void PictureTest::storeTestExtern()
+{
+ KContacts::Picture picture;
+
+ picture.setUrl(QStringLiteral("http://myhomepage.com/foto.png"), QStringLiteral("png"));
+
+ QVERIFY(picture.isEmpty() == false);
+ QVERIFY(picture.isIntern() == false);
+ QVERIFY(picture.type() == QLatin1String("png"));
+ QVERIFY(picture.url() == QLatin1String("http://myhomepage.com/foto.png"));
+}
+
+void PictureTest::equalsTestInternImage()
+{
+ KContacts::Picture picture1, picture2;
+
+ picture1.setData(testImage());
+
+ picture2.setData(testImage());
+
+ QVERIFY(picture1 == picture2);
+
+ // access rawData() so a QByteArray is created
+ picture1.rawData();
+ QVERIFY(picture1 == picture2);
+}
+
+void PictureTest::equalsTestInternRawData()
+{
+ KContacts::Picture picture1, picture2;
+
+ picture1.setRawData(testImageRawPNG(), QStringLiteral("png"));
+
+ picture2.setRawData(testImageRawPNG(), QStringLiteral("png"));
+
+ QVERIFY(picture1 == picture2);
+
+ // access data() so a QImage is created
+ picture1.data();
+ QVERIFY(picture1 == picture2);
+}
+
+void PictureTest::equalsTestInternImageAndRawData()
+{
+ KContacts::Picture picture1, picture2;
+
+ picture1.setData(testImage());
+
+ picture2.setRawData(testImageRawJPEG(), QStringLiteral("jpeg"));
+
+ QVERIFY(picture1.rawData() == picture2.rawData());
+}
+
+void PictureTest::equalsTestExtern()
+{
+ KContacts::Picture picture1, picture2;
+
+ picture1.setUrl(QStringLiteral("http://myhomepage.com/foto.png"), QStringLiteral("png"));
+
+ picture2.setUrl(QStringLiteral("http://myhomepage.com/foto.png"), QStringLiteral("png"));
+
+ QVERIFY(picture1 == picture2);
+}
+
+void PictureTest::differsTest()
+{
+ KContacts::Picture picture1, picture2;
+
+ picture1.setUrl(QStringLiteral("http://myhomepage.com/foto.png"), QStringLiteral("png"));
+
+ picture2.setData(testImage());
+
+ QVERIFY(picture1 != picture2);
+}
+
+void PictureTest::differsTestInternRawData()
+{
+ KContacts::Picture picture1, picture2;
+
+ picture1.setRawData(testImageRawJPEG(), QStringLiteral("jpeg"));
+
+ picture2.setRawData(testImageRawPNG(), QStringLiteral("png"));
+
+ QVERIFY(picture1 != picture2);
+ QVERIFY(picture1.rawData() != picture2.rawData());
+}
+
+void PictureTest::differsTestExtern()
+{
+ KContacts::Picture picture1, picture2;
+
+ picture1.setUrl(QStringLiteral("http://myhomepage.com/foto.png"), QStringLiteral("png"));
+
+ picture1.setUrl(QStringLiteral("http://myhomepage.com/foto2.png"), QStringLiteral("png"));
+
+ QVERIFY(picture1 != picture2);
+}
+
+void PictureTest::assignmentTestIntern()
+{
+ KContacts::Picture picture1, picture2;
+
+ picture1.setData(testImage());
+
+ picture2 = picture1;
+
+ QVERIFY(picture1 == picture2);
+}
+
+void PictureTest::assignmentTestExtern()
+{
+ KContacts::Picture picture1, picture2;
+
+ picture1.setUrl(QStringLiteral("http://myhomepage.com/foto.png"), QStringLiteral("png"));
+
+ picture2 = picture1;
+
+ QVERIFY(picture1 == picture2);
+}
+
+void PictureTest::serializeTestInternImage()
+{
+ KContacts::Picture picture1, picture2;
+
+ picture1.setData(testImage());
+
+ QByteArray data;
+ QDataStream s(&data, QIODevice::WriteOnly);
+ s << picture1;
+
+ QDataStream t(&data, QIODevice::ReadOnly);
+ t >> picture2;
+
+ QVERIFY(picture1 == picture2);
+}
+
+void PictureTest::serializeTestInternRawData()
+{
+ KContacts::Picture picture1, picture2;
+
+ picture1.setRawData(testImageRawPNG(), QStringLiteral("png"));
+
+ QByteArray data;
+ QDataStream s(&data, QIODevice::WriteOnly);
+ s << picture1;
+
+ QDataStream t(&data, QIODevice::ReadOnly);
+ t >> picture2;
+
+ QVERIFY(picture1 == picture2);
+}
+
+void PictureTest::serializeTestExtern()
+{
+ KContacts::Picture picture1, picture2;
+
+ picture1.setUrl(QStringLiteral("http://myhomepage.com/foto.png"), QStringLiteral("png"));
+
+ QByteArray data;
+ QDataStream s(&data, QIODevice::WriteOnly);
+ s << picture1;
+
+ QDataStream t(&data, QIODevice::ReadOnly);
+ t >> picture2;
+
+ QVERIFY(picture1 == picture2);
+}
--- /dev/null
+/*
+ This file is part of the KContacts framework.
+ Copyright (c) 2007 Tobias Koenig <tokoe@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef PICTURE_TEST_H
+#define PICTURE_TEST_H
+
+#include <QtCore/QObject>
+
+class PictureTest : public QObject
+{
+ Q_OBJECT
+
+private Q_SLOTS:
+ void emptyTest();
+ void storeTestInternImage();
+ void storeTestInternRawData();
+ void storeTestExtern();
+ void equalsTestInternImage();
+ void equalsTestInternRawData();
+ void equalsTestInternImageAndRawData();
+ void equalsTestExtern();
+ void differsTest();
+ void differsTestInternRawData();
+ void differsTestExtern();
+ void assignmentTestIntern();
+ void assignmentTestExtern();
+ void serializeTestInternImage();
+ void serializeTestInternRawData();
+ void serializeTestExtern();
+};
+
+#endif
--- /dev/null
+/*
+ This file is part of the KContacts framework.
+ Copyright (c) 2015 Laurent Montel <montel@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "relatedtest.h"
+#include "related.h"
+#include "vcardtool.h"
+#include <qtest.h>
+
+RelatedTest::RelatedTest(QObject *parent)
+ : QObject(parent)
+{
+
+}
+
+RelatedTest::~RelatedTest()
+{
+
+}
+
+void RelatedTest::shouldHaveDefaultValue()
+{
+ KContacts::Related related;
+ QVERIFY(!related.isValid());
+ QVERIFY(related.related().isEmpty());
+ QVERIFY(related.parameters().isEmpty());
+}
+
+void RelatedTest::shouldAssignValue()
+{
+ const QString relatedTo(QStringLiteral("friend"));
+ QMap<QString, QStringList> params;
+ params.insert(QStringLiteral("Foo1"), QStringList() << QStringLiteral("bla1") << QStringLiteral("blo1"));
+ params.insert(QStringLiteral("Foo2"), QStringList() << QStringLiteral("bla2") << QStringLiteral("blo2"));
+ KContacts::Related related(relatedTo);
+ related.setParameters(params);
+ QVERIFY(related.isValid());
+ QVERIFY(!related.related().isEmpty());
+ QCOMPARE(related.related(), relatedTo);
+ QVERIFY(!related.parameters().isEmpty());
+ QCOMPARE(related.parameters(), params);
+
+}
+
+void RelatedTest::shouldAssignExternal()
+{
+ KContacts::Related related;
+ const QString relatedTo(QStringLiteral("friend"));
+ related.setRelated(relatedTo);
+ QVERIFY(related.isValid());
+ QCOMPARE(related.related(), relatedTo);
+}
+
+void RelatedTest::shouldSerialized()
+{
+ KContacts::Related related;
+ KContacts::Related result;
+ const QString relatedTo(QStringLiteral("friend"));
+ related.setRelated(relatedTo);
+ QMap<QString, QStringList> params;
+ params.insert(QStringLiteral("Foo1"), QStringList() << QStringLiteral("bla1") << QStringLiteral("blo1"));
+ params.insert(QStringLiteral("Foo2"), QStringList() << QStringLiteral("bla2") << QStringLiteral("blo2"));
+ related.setParameters(params);
+
+ QByteArray data;
+ QDataStream s(&data, QIODevice::WriteOnly);
+ s << related;
+
+ QDataStream t(&data, QIODevice::ReadOnly);
+ t >> result;
+
+ QVERIFY(related == result);
+}
+
+void RelatedTest::shouldEqualRelated()
+{
+ KContacts::Related related;
+ KContacts::Related result;
+ const QString relatedTo(QStringLiteral("friend"));
+ related.setRelated(relatedTo);
+ QMap<QString, QStringList> params;
+ params.insert(QStringLiteral("Foo1"), QStringList() << QStringLiteral("bla1") << QStringLiteral("blo1"));
+ params.insert(QStringLiteral("Foo2"), QStringList() << QStringLiteral("bla2") << QStringLiteral("blo2"));
+ related.setParameters(params);
+
+ result = related;
+ QVERIFY(related == result);
+}
+
+void RelatedTest::shouldParseRelated()
+{
+ QByteArray vcarddata("BEGIN:VCARD\n"
+ "VERSION:4.0\n"
+ "N:LastName;FirstName;;;\n"
+ "UID:c80cf296-0825-4eb0-ab16-1fac1d522a33@xxxxxx.xx\n"
+ "RELATED:friend"
+ "REV:2015-03-14T09:24:45+00:00\n"
+ "FN:FirstName LastName\n"
+ "END:VCARD\n");
+
+ KContacts::VCardTool vcard;
+ const KContacts::AddresseeList lst = vcard.parseVCards(vcarddata);
+ QCOMPARE(lst.count(), 1);
+ QCOMPARE(lst.at(0).relationShips().count(), 1);
+}
+
+void RelatedTest::shouldParseWithoutRelated()
+{
+ QByteArray vcarddata("BEGIN:VCARD\n"
+ "VERSION:3.0\n"
+ "N:LastName;FirstName;;;\n"
+ "UID:c80cf296-0825-4eb0-ab16-1fac1d522a33@xxxxxx.xx\n"
+ "REV:2015-03-14T09:24:45+00:00\n"
+ "FN:FirstName LastName\n"
+ "END:VCARD\n");
+
+ KContacts::VCardTool vcard;
+ const KContacts::AddresseeList lst = vcard.parseVCards(vcarddata);
+ QCOMPARE(lst.count(), 1);
+ QCOMPARE(lst.at(0).relationShips().count(), 0);
+}
+
+void RelatedTest::shouldCreateVCard4()
+{
+ KContacts::AddresseeList lst;
+ KContacts::Addressee addr;
+ addr.setEmails(QStringList() << QStringLiteral("foo@kde.org"));
+ addr.setUid(QStringLiteral("testuid"));
+ KContacts::Related::List lstRelated;
+ KContacts::Related related(QStringLiteral("friend"));
+ lstRelated << related;
+ addr.setRelationShips(lstRelated);
+ lst << addr;
+ KContacts::VCardTool vcard;
+ const QByteArray ba = vcard.exportVCards(lst, KContacts::VCard::v4_0);
+ QByteArray expected("BEGIN:VCARD\r\n"
+ "VERSION:4.0\r\n"
+ "EMAIL:foo@kde.org\r\n"
+ "N:;;;;\r\n"
+ "RELATED:friend\r\n"
+ "UID:testuid\r\n"
+ "END:VCARD\r\n\r\n");
+
+ QCOMPARE(ba, expected);
+}
+
+void RelatedTest::shouldCreateVCardWithTwoRelated()
+{
+ KContacts::AddresseeList lst;
+ KContacts::Addressee addr;
+ addr.setEmails(QStringList() << QStringLiteral("foo@kde.org"));
+ addr.setUid(QStringLiteral("testuid"));
+ KContacts::Related::List lstRelated;
+ KContacts::Related related(QStringLiteral("friend"));
+ KContacts::Related related2(QStringLiteral("kde"));
+ lstRelated << related << related2;
+ addr.setRelationShips(lstRelated);
+ lst << addr;
+ KContacts::VCardTool vcard;
+ const QByteArray ba = vcard.exportVCards(lst, KContacts::VCard::v4_0);
+ QByteArray expected("BEGIN:VCARD\r\n"
+ "VERSION:4.0\r\n"
+ "EMAIL:foo@kde.org\r\n"
+ "N:;;;;\r\n"
+ "RELATED:friend\r\n"
+ "RELATED:kde\r\n"
+ "UID:testuid\r\n"
+ "END:VCARD\r\n\r\n");
+
+ QCOMPARE(ba, expected);
+
+}
+
+void RelatedTest::shouldCreateVCardWithParameters()
+{
+ KContacts::AddresseeList lst;
+ KContacts::Addressee addr;
+ addr.setEmails(QStringList() << QStringLiteral("foo@kde.org"));
+ addr.setUid(QStringLiteral("testuid"));
+ KContacts::Related::List lstRelated;
+ KContacts::Related related(QStringLiteral("friend"));
+ QMap<QString, QStringList> params;
+ params.insert(QStringLiteral("Foo1"), QStringList() << QStringLiteral("bla1") << QStringLiteral("blo1"));
+ params.insert(QStringLiteral("Foo2"), QStringList() << QStringLiteral("bla2") << QStringLiteral("blo2"));
+ related.setParameters(params);
+ lstRelated << related;
+ addr.setRelationShips(lstRelated);
+ lst << addr;
+ KContacts::VCardTool vcard;
+ const QByteArray ba = vcard.exportVCards(lst, KContacts::VCard::v4_0);
+ QByteArray expected("BEGIN:VCARD\r\n"
+ "VERSION:4.0\r\n"
+ "EMAIL:foo@kde.org\r\n"
+ "N:;;;;\r\n"
+ "RELATED;FOO1=bla1,blo1;FOO2=bla2,blo2:friend\r\n"
+ "UID:testuid\r\n"
+ "END:VCARD\r\n\r\n");
+ QCOMPARE(ba, expected);
+}
+
+void RelatedTest::shouldNotExportInVcard3()
+{
+ KContacts::AddresseeList lst;
+ KContacts::Addressee addr;
+ addr.setEmails(QStringList() << QStringLiteral("foo@kde.org"));
+ addr.setUid(QStringLiteral("testuid"));
+ KContacts::Related::List lstRelated;
+ KContacts::Related related(QStringLiteral("friend"));
+ QMap<QString, QStringList> params;
+ params.insert(QStringLiteral("Foo1"), QStringList() << QStringLiteral("bla1") << QStringLiteral("blo1"));
+ params.insert(QStringLiteral("Foo2"), QStringList() << QStringLiteral("bla2") << QStringLiteral("blo2"));
+ related.setParameters(params);
+ lstRelated << related;
+ addr.setRelationShips(lstRelated);
+ lst << addr;
+ KContacts::VCardTool vcard;
+ const QByteArray ba = vcard.exportVCards(lst, KContacts::VCard::v3_0);
+ QByteArray expected("BEGIN:VCARD\r\n"
+ "VERSION:3.0\r\n"
+ "EMAIL:foo@kde.org\r\n"
+ "N:;;;;\r\n"
+ "UID:testuid\r\n"
+ "END:VCARD\r\n\r\n");
+ QCOMPARE(ba, expected);
+}
+
+QTEST_MAIN(RelatedTest)
--- /dev/null
+/*
+ This file is part of the KContacts framework.
+ Copyright (c) 2015 Laurent Montel <montel@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef RELATEDTEST_H
+#define RELATEDTEST_H
+
+#include <QObject>
+
+class RelatedTest : public QObject
+{
+ Q_OBJECT
+public:
+ explicit RelatedTest(QObject *parent = Q_NULLPTR);
+ ~RelatedTest();
+private Q_SLOTS:
+ void shouldHaveDefaultValue();
+ void shouldAssignValue();
+ void shouldAssignExternal();
+ void shouldSerialized();
+ void shouldEqualRelated();
+ void shouldParseRelated();
+ void shouldParseWithoutRelated();
+ void shouldCreateVCard4();
+ void shouldCreateVCardWithTwoRelated();
+ void shouldCreateVCardWithParameters();
+ void shouldNotExportInVcard3();
+};
+
+#endif // RELATEDTEST_H
--- /dev/null
+/*
+ This file is part of the KContacts framework.
+ Copyright (c) 2015 Laurent Montel <montel@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "resourcelocatorurltest.h"
+
+#include "resourcelocatorurl.h"
+#include "vcardtool.h"
+#include <qtest.h>
+
+using namespace KContacts;
+ResourceLocatorUrlTest::ResourceLocatorUrlTest(QObject *parent)
+ : QObject(parent)
+{
+
+}
+
+ResourceLocatorUrlTest::~ResourceLocatorUrlTest()
+{
+
+}
+
+void ResourceLocatorUrlTest::shouldHaveDefaultValue()
+{
+ ResourceLocatorUrl ResourceLocatorUrl;
+ QVERIFY(!ResourceLocatorUrl.isValid());
+ QVERIFY(ResourceLocatorUrl.url().isEmpty());
+ QVERIFY(ResourceLocatorUrl.parameters().isEmpty());
+}
+
+void ResourceLocatorUrlTest::shouldAssignValue()
+{
+ QMap<QString, QStringList> params;
+ params.insert(QStringLiteral("Foo1"), QStringList() << QStringLiteral("bla1") << QStringLiteral("blo1"));
+ params.insert(QStringLiteral("Foo2"), QStringList() << QStringLiteral("bla2") << QStringLiteral("blo2"));
+ ResourceLocatorUrl ResourceLocatorUrl;
+ ResourceLocatorUrl.setParameters(params);
+ QVERIFY(!ResourceLocatorUrl.isValid());
+ QVERIFY(ResourceLocatorUrl.url().isEmpty());
+ QVERIFY(!ResourceLocatorUrl.parameters().isEmpty());
+ QCOMPARE(ResourceLocatorUrl.parameters(), params);
+}
+
+void ResourceLocatorUrlTest::shouldAssignExternal()
+{
+ ResourceLocatorUrl resourcelocatorurl;
+ QUrl url = QUrl(QStringLiteral("https://www.kde.org"));
+ resourcelocatorurl.setUrl(url);
+ QVERIFY(!resourcelocatorurl.url().isEmpty());
+ QCOMPARE(resourcelocatorurl.url(), url);
+}
+
+void ResourceLocatorUrlTest::shouldSerialized()
+{
+ ResourceLocatorUrl resourcelocatorurl;
+ ResourceLocatorUrl result;
+ QMap<QString, QStringList> params;
+ params.insert(QStringLiteral("Foo1"), QStringList() << QStringLiteral("bla1") << QStringLiteral("blo1"));
+ params.insert(QStringLiteral("Foo2"), QStringList() << QStringLiteral("bla2") << QStringLiteral("blo2"));
+ resourcelocatorurl.setParameters(params);
+ resourcelocatorurl.setUrl(QUrl(QStringLiteral("mailto:foo@kde.org")));
+
+ QByteArray data;
+ QDataStream s(&data, QIODevice::WriteOnly);
+ s << resourcelocatorurl;
+
+ QDataStream t(&data, QIODevice::ReadOnly);
+ t >> result;
+
+ QVERIFY(resourcelocatorurl == result);
+}
+
+void ResourceLocatorUrlTest::shouldEqualResourceLocatorUrl()
+{
+ ResourceLocatorUrl resourcelocatorurl;
+ ResourceLocatorUrl result;
+ QMap<QString, QStringList> params;
+ params.insert(QStringLiteral("Foo1"), QStringList() << QStringLiteral("bla1") << QStringLiteral("blo1"));
+ params.insert(QStringLiteral("Foo2"), QStringList() << QStringLiteral("bla2") << QStringLiteral("blo2"));
+ resourcelocatorurl.setUrl(QUrl(QStringLiteral("mailto:foo@kde.org")));
+ resourcelocatorurl.setParameters(params);
+
+ result = resourcelocatorurl;
+ QVERIFY(resourcelocatorurl == result);
+}
+
+void ResourceLocatorUrlTest::shouldParseResourceLocatorUrl()
+{
+ QByteArray vcarddata("BEGIN:VCARD\n"
+ "VERSION:3.0\n"
+ "N:LastName;FirstName;;;\n"
+ "UID:c80cf296-0825-4eb0-ab16-1fac1d522a33@xxxxxx.xx\n"
+ "URL;PREF=1:https://firsturl\n"
+ "URL;PREF=1:https://sherlockholmes.com/calendar/sherlockholmes\n"
+ "REV:2015-03-14T09:24:45+00:00\n"
+ "FN:FirstName LastName\n"
+ "END:VCARD\n");
+
+ KContacts::VCardTool vcard;
+ const KContacts::AddresseeList lst = vcard.parseVCards(vcarddata);
+ QCOMPARE(lst.count(), 1);
+ QCOMPARE(lst.at(0).extraUrlList().count(), 2);
+ const ResourceLocatorUrl calurl = lst.at(0).extraUrlList().at(0);
+ QCOMPARE(calurl.url(), QUrl(QStringLiteral("https://firsturl")));
+ QVERIFY(!calurl.parameters().isEmpty());
+}
+
+void ResourceLocatorUrlTest::shouldGenerateVCard4()
+{
+ KContacts::AddresseeList lst;
+ KContacts::Addressee addr;
+ addr.setEmails(QStringList() << QStringLiteral("foo@kde.org"));
+ addr.setUid(QStringLiteral("testuid"));
+ KContacts::ResourceLocatorUrl webpage;
+ webpage.setUrl(QUrl(QStringLiteral("https://www.kde.org")));
+ addr.setUrl(webpage);
+ ResourceLocatorUrl url;
+ url.setUrl(QUrl(QStringLiteral("https://sherlockholmes.com/calendar/sherlockholmes")));
+ addr.insertExtraUrl(url);
+ url.setUrl(QUrl(QStringLiteral("https://foo.kde.org")));
+ addr.insertExtraUrl(url);
+ lst << addr;
+ KContacts::VCardTool vcard;
+ const QByteArray ba = vcard.exportVCards(lst, KContacts::VCard::v4_0);
+ QByteArray expected;
+ expected = QByteArray("BEGIN:VCARD\r\n"
+ "VERSION:4.0\r\n"
+ "EMAIL:foo@kde.org\r\n"
+ "N:;;;;\r\n"
+ "UID:testuid\r\n"
+ "URL:https://www.kde.org\r\n"
+ "URL:https://sherlockholmes.com/calendar/sherlockholmes\r\n"
+ "URL:https://foo.kde.org\r\n"
+ "END:VCARD\r\n\r\n");
+
+ QCOMPARE(ba, expected);
+}
+
+void ResourceLocatorUrlTest::shouldGenerateVCardWithParameter()
+{
+ KContacts::AddresseeList lst;
+ KContacts::Addressee addr;
+ addr.setEmails(QStringList() << QStringLiteral("foo@kde.org"));
+ addr.setUid(QStringLiteral("testuid"));
+ KContacts::ResourceLocatorUrl webpage;
+ webpage.setUrl(QUrl(QStringLiteral("https://www.kde.org")));
+ addr.setUrl(webpage);
+ ResourceLocatorUrl url;
+ url.setUrl(QUrl(QStringLiteral("https://sherlockholmes.com/calendar/sherlockholmes")));
+ QMap<QString, QStringList> params;
+ params.insert(QStringLiteral("Foo2"), QStringList() << QStringLiteral("bla2") << QStringLiteral("blo2"));
+ url.setParameters(params);
+ addr.insertExtraUrl(url);
+ url.setUrl(QUrl(QStringLiteral("https://foo.kde.org")));
+ QMap<QString, QStringList> params2;
+ url.setParameters(params2);
+ addr.insertExtraUrl(url);
+ lst << addr;
+ KContacts::VCardTool vcard;
+ const QByteArray ba = vcard.exportVCards(lst, KContacts::VCard::v4_0);
+ QByteArray expected;
+ expected = QByteArray("BEGIN:VCARD\r\n"
+ "VERSION:4.0\r\n"
+ "EMAIL:foo@kde.org\r\n"
+ "N:;;;;\r\n"
+ "UID:testuid\r\n"
+ "URL:https://www.kde.org\r\n"
+ "URL;FOO2=bla2,blo2:https://sherlockholmes.com/calendar/sherlockholmes\r\n"
+ "URL:https://foo.kde.org\r\n"
+ "END:VCARD\r\n\r\n");
+
+ QCOMPARE(ba, expected);
+}
+
+void ResourceLocatorUrlTest::shouldGenerateVCard3()
+{
+ KContacts::AddresseeList lst;
+ KContacts::Addressee addr;
+ addr.setEmails(QStringList() << QStringLiteral("foo@kde.org"));
+ addr.setUid(QStringLiteral("testuid"));
+ KContacts::ResourceLocatorUrl webpage;
+ webpage.setUrl(QUrl(QStringLiteral("https://www.kde.org")));
+ addr.setUrl(webpage);
+ ResourceLocatorUrl url;
+ url.setUrl(QUrl(QStringLiteral("https://sherlockholmes.com/calendar/sherlockholmes")));
+ QMap<QString, QStringList> params;
+ params.insert(QStringLiteral("Foo2"), QStringList() << QStringLiteral("bla2") << QStringLiteral("blo2"));
+ url.setParameters(params);
+ addr.insertExtraUrl(url);
+ url.setUrl(QUrl(QStringLiteral("https://foo.kde.org")));
+ QMap<QString, QStringList> params2;
+ url.setParameters(params2);
+ addr.insertExtraUrl(url);
+ lst << addr;
+ KContacts::VCardTool vcard;
+ const QByteArray ba = vcard.exportVCards(lst, KContacts::VCard::v3_0);
+ QByteArray expected;
+ expected = QByteArray("BEGIN:VCARD\r\n"
+ "VERSION:3.0\r\n"
+ "EMAIL:foo@kde.org\r\n"
+ "N:;;;;\r\n"
+ "UID:testuid\r\n"
+ "URL:https://www.kde.org\r\n"
+ "URL;FOO2=bla2,blo2:https://sherlockholmes.com/calendar/sherlockholmes\r\n"
+ "URL:https://foo.kde.org\r\n"
+ "END:VCARD\r\n\r\n");
+
+ QCOMPARE(ba, expected);
+
+}
+
+QTEST_MAIN(ResourceLocatorUrlTest)
+
--- /dev/null
+/*
+ This file is part of the KContacts framework.
+ Copyright (c) 2015 Laurent Montel <montel@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef ResourceLocatorUrlTest_H
+#define ResourceLocatorUrlTest_H
+
+#include <QObject>
+
+class ResourceLocatorUrlTest : public QObject
+{
+ Q_OBJECT
+public:
+ explicit ResourceLocatorUrlTest(QObject *parent = Q_NULLPTR);
+ ~ResourceLocatorUrlTest();
+
+private Q_SLOTS:
+ void shouldHaveDefaultValue();
+ void shouldAssignValue();
+ void shouldAssignExternal();
+ void shouldSerialized();
+ void shouldEqualResourceLocatorUrl();
+ void shouldParseResourceLocatorUrl();
+ void shouldGenerateVCard4();
+ void shouldGenerateVCardWithParameter();
+ void shouldGenerateVCard3();
+};
+
+#endif // ResourceLocatorUrlTest_H
--- /dev/null
+/*
+ This file is part of the KContacts framework.
+ Copyright (c) 2007 Tobias Koenig <tokoe@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "secrecytest.h"
+#include "kcontacts/secrecy.h"
+#include "vcardtool.h"
+#include <qtest.h>
+
+QTEST_MAIN(SecrecyTest)
+
+void SecrecyTest::emptyTest()
+{
+ KContacts::Secrecy secrecy;
+
+ QVERIFY(secrecy.type() == KContacts::Secrecy::Invalid);
+}
+
+void SecrecyTest::storeTest()
+{
+ KContacts::Secrecy secrecy;
+
+ secrecy.setType(KContacts::Secrecy::Private);
+
+ QVERIFY(secrecy.type() == KContacts::Secrecy::Private);
+}
+
+void SecrecyTest::equalsTest()
+{
+ KContacts::Secrecy secrecy1, secrecy2;
+
+ secrecy1.setType(KContacts::Secrecy::Confidential);
+ secrecy2.setType(KContacts::Secrecy::Confidential);
+
+ QVERIFY(secrecy1 == secrecy2);
+}
+
+void SecrecyTest::differsTest()
+{
+ KContacts::Secrecy secrecy1(KContacts::Secrecy::Private);
+ KContacts::Secrecy secrecy2(KContacts::Secrecy::Confidential);
+
+ QVERIFY(secrecy1 != secrecy2);
+}
+
+void SecrecyTest::assignmentTest()
+{
+ KContacts::Secrecy secrecy1, secrecy2;
+
+ secrecy1.setType(KContacts::Secrecy::Confidential);
+ secrecy1 = secrecy2;
+
+ QVERIFY(secrecy1 == secrecy2);
+}
+
+void SecrecyTest::serializeTest()
+{
+ KContacts::Secrecy secrecy1, secrecy2;
+
+ secrecy1.setType(KContacts::Secrecy::Confidential);
+
+ QByteArray data;
+ QDataStream s(&data, QIODevice::WriteOnly);
+ s << secrecy1;
+
+ QDataStream t(&data, QIODevice::ReadOnly);
+ t >> secrecy2;
+
+ QVERIFY(secrecy1 == secrecy2);
+}
--- /dev/null
+/*
+ This file is part of the KContacts framework.
+ Copyright (c) 2007 Tobias Koenig <tokoe@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef SECRECY_TEST_H
+#define SECRECY_TEST_H
+
+#include <QtCore/QObject>
+
+class SecrecyTest : public QObject
+{
+ Q_OBJECT
+
+private Q_SLOTS:
+ void emptyTest();
+ void storeTest();
+ void equalsTest();
+ void differsTest();
+ void assignmentTest();
+ void serializeTest();
+};
+
+#endif
--- /dev/null
+/*
+ This file is part of the KContacts framework.
+ Copyright (c) 2007 Tobias Koenig <tokoe@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "soundtest.h"
+#include "kcontacts/sound.h"
+#include "addressee.h"
+#include <qtest.h>
+#include "vcardtool.h"
+
+QTEST_MAIN(SoundTest)
+
+static QByteArray testData()
+{
+ static QByteArray data;
+
+ if (data.isNull()) {
+ for (int i = 0; i < 20; ++i) {
+ data.append(char(i));
+ }
+ }
+
+ return data;
+}
+
+void SoundTest::emptyTest()
+{
+ KContacts::Sound sound;
+
+ QVERIFY(sound.isEmpty());
+}
+
+void SoundTest::storeTestIntern()
+{
+ KContacts::Sound sound;
+
+ sound.setData(testData());
+
+ QVERIFY(sound.isIntern() == true);
+ QVERIFY(sound.data() == testData());
+}
+
+void SoundTest::storeTestExtern()
+{
+ KContacts::Sound sound;
+
+ sound.setUrl(QLatin1String("http://myhomepage.com/sound.wav"));
+
+ QVERIFY(sound.isIntern() == false);
+ QVERIFY(sound.url() == QLatin1String("http://myhomepage.com/sound.wav"));
+}
+
+void SoundTest::equalsTestIntern()
+{
+ KContacts::Sound sound1, sound2;
+
+ sound1.setData(testData());
+ sound2.setData(testData());
+
+ QVERIFY(sound1 == sound2);
+}
+
+void SoundTest::equalsTestExtern()
+{
+ KContacts::Sound sound1, sound2;
+
+ sound1.setUrl(QStringLiteral("http://myhomepage.com/sound.wav"));
+ sound2.setUrl(QStringLiteral("http://myhomepage.com/sound.wav"));
+
+ QVERIFY(sound1 == sound2);
+}
+
+void SoundTest::differsTest()
+{
+ KContacts::Sound sound1, sound2;
+
+ sound1.setUrl(QStringLiteral("http://myhomepage.com/sound.wav"));
+ sound2.setData(testData());
+
+ QVERIFY(sound1 != sound2);
+}
+
+void SoundTest::assignmentTestIntern()
+{
+ KContacts::Sound sound1, sound2;
+
+ sound1.setData(testData());
+
+ sound2 = sound1;
+
+ QVERIFY(sound1 == sound2);
+}
+
+void SoundTest::assignmentTestExtern()
+{
+ KContacts::Sound sound1, sound2;
+
+ sound1.setUrl(QStringLiteral("http://myhomepage.com/sound.wav"));
+
+ sound2 = sound1;
+
+ QVERIFY(sound1 == sound2);
+}
+
+void SoundTest::serializeTest()
+{
+ KContacts::Sound sound1, sound2;
+
+ sound1.setUrl(QStringLiteral("http://myhomepage.com/sound.wav"));
+ sound1.setData(testData());
+
+ QByteArray data;
+ QDataStream s(&data, QIODevice::WriteOnly);
+ s << sound1;
+
+ QDataStream t(&data, QIODevice::ReadOnly);
+ t >> sound2;
+
+ QVERIFY(sound1 == sound2);
+}
+
+void SoundTest::shouldParseSource()
+{
+ QByteArray vcarddata("BEGIN:VCARD\n"
+ "VERSION:3.0\n"
+ "N:LastName;FirstName;;;\n"
+ "UID:c80cf296-0825-4eb0-ab16-1fac1d522a33@xxxxxx.xx\n"
+ "REV:2015-03-14T09:24:45+00:00\n"
+ "SOUND;VALUE=URI:http://myhomepage.com/sound.wav\n"
+ "FN:FirstName LastName\n"
+ "END:VCARD\n");
+
+ KContacts::VCardTool vcard;
+ const KContacts::AddresseeList lst = vcard.parseVCards(vcarddata);
+ QCOMPARE(lst.count(), 1);
+ QVERIFY(!lst.at(0).sound().isEmpty());
+ KContacts::Sound sound = lst.at(0).sound();
+ QVERIFY(!sound.isIntern());
+ QCOMPARE(sound.url(), QStringLiteral("http://myhomepage.com/sound.wav"));
+}
+
+void SoundTest::shouldGenerateVCard4WithData()
+{
+ KContacts::Addressee::List lst;
+ KContacts::Addressee addr;
+ addr.setEmails(QStringList() << QStringLiteral("foo@kde.org"));
+ addr.setUid(QStringLiteral("testuid"));
+ KContacts::Sound sound1;
+
+ sound1.setUrl(QStringLiteral("http://myhomepage.com/sound.wav"));
+ sound1.setData(testData());
+ addr.setSound(sound1);
+
+ lst << addr;
+ KContacts::VCardTool vcard;
+ const QByteArray ba = vcard.exportVCards(lst, KContacts::VCard::v4_0);
+ QByteArray expected;
+ expected = QByteArray("BEGIN:VCARD\r\n"
+ "VERSION:4.0\r\n"
+ "EMAIL:foo@kde.org\r\n"
+ "N:;;;;\r\n"
+ "SOUND;ENCODING=b:AAECAwQFBgcICQoLDA0ODxAREhM=\r\n"
+ "UID:testuid\r\n"
+ "END:VCARD\r\n\r\n");
+
+ QCOMPARE(ba, expected);
+}
+
+void SoundTest::shouldGenerateVCard4WithUrl()
+{
+ KContacts::Addressee::List lst;
+ KContacts::Addressee addr;
+ addr.setEmails(QStringList() << QStringLiteral("foo@kde.org"));
+ addr.setUid(QStringLiteral("testuid"));
+ KContacts::Sound sound1;
+
+ sound1.setUrl(QStringLiteral("http://myhomepage.com/sound.wav"));
+ addr.setSound(sound1);
+
+ lst << addr;
+ KContacts::VCardTool vcard;
+ const QByteArray ba = vcard.exportVCards(lst, KContacts::VCard::v4_0);
+ QByteArray expected;
+ expected = QByteArray("BEGIN:VCARD\r\n"
+ "VERSION:4.0\r\n"
+ "EMAIL:foo@kde.org\r\n"
+ "N:;;;;\r\n"
+ "SOUND;VALUE=URI:http://myhomepage.com/sound.wav\r\n"
+ "UID:testuid\r\n"
+ "END:VCARD\r\n\r\n");
+
+ QCOMPARE(ba, expected);
+}
+
+void SoundTest::shouldGenerateVCard3WithData()
+{
+ KContacts::Addressee::List lst;
+ KContacts::Addressee addr;
+ addr.setEmails(QStringList() << QStringLiteral("foo@kde.org"));
+ addr.setUid(QStringLiteral("testuid"));
+ KContacts::Sound sound1;
+
+ sound1.setUrl(QStringLiteral("http://myhomepage.com/sound.wav"));
+ sound1.setData(testData());
+ addr.setSound(sound1);
+
+ lst << addr;
+ KContacts::VCardTool vcard;
+ const QByteArray ba = vcard.exportVCards(lst, KContacts::VCard::v3_0);
+ QByteArray expected;
+ expected = QByteArray("BEGIN:VCARD\r\n"
+ "VERSION:3.0\r\n"
+ "EMAIL:foo@kde.org\r\n"
+ "N:;;;;\r\n"
+ "SOUND;ENCODING=b:AAECAwQFBgcICQoLDA0ODxAREhM=\r\n"
+ "UID:testuid\r\n"
+ "END:VCARD\r\n\r\n");
+
+ QCOMPARE(ba, expected);
+}
+
+void SoundTest::shouldGenerateVCard3WithUrl()
+{
+ KContacts::Addressee::List lst;
+ KContacts::Addressee addr;
+ addr.setEmails(QStringList() << QStringLiteral("foo@kde.org"));
+ addr.setUid(QStringLiteral("testuid"));
+ KContacts::Sound sound1;
+
+ sound1.setUrl(QStringLiteral("http://myhomepage.com/sound.wav"));
+ addr.setSound(sound1);
+
+ lst << addr;
+ KContacts::VCardTool vcard;
+ const QByteArray ba = vcard.exportVCards(lst, KContacts::VCard::v3_0);
+ QByteArray expected;
+ expected = QByteArray("BEGIN:VCARD\r\n"
+ "VERSION:3.0\r\n"
+ "EMAIL:foo@kde.org\r\n"
+ "N:;;;;\r\n"
+ "SOUND;VALUE=URI:http://myhomepage.com/sound.wav\r\n"
+ "UID:testuid\r\n"
+ "END:VCARD\r\n\r\n");
+
+ QCOMPARE(ba, expected);
+}
--- /dev/null
+/*
+ This file is part of the KContacts framework.
+ Copyright (c) 2007 Tobias Koenig <tokoe@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef SOUND_TEST_H
+#define SOUND_TEST_H
+
+#include <QtCore/QObject>
+
+class SoundTest : public QObject
+{
+ Q_OBJECT
+
+private Q_SLOTS:
+ void emptyTest();
+ void storeTestIntern();
+ void storeTestExtern();
+ void equalsTestIntern();
+ void equalsTestExtern();
+ void differsTest();
+ void assignmentTestIntern();
+ void assignmentTestExtern();
+ void serializeTest();
+ void shouldParseSource();
+ void shouldGenerateVCard4WithData();
+ void shouldGenerateVCard4WithUrl();
+ void shouldGenerateVCard3WithData();
+ void shouldGenerateVCard3WithUrl();
+};
+
+#endif
--- /dev/null
+/*
+ This file is part of the KContacts framework.
+
+ Copyright (c) 2003 Cornelius Schumacher <schumacher@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+#ifndef KCONTACTS_TESTLOCK_H
+#define KCONTACTS_TESTLOCK_H
+
+#include <QWidget>
+#include <QLabel>
+
+#include "kcontacts/lock.h"
+
+class QLabel;
+class QTreeWidget;
+
+class LockWidget : public QWidget
+{
+ Q_OBJECT
+public:
+ LockWidget(const QString &identifier);
+ ~LockWidget();
+
+protected Q_SLOTS:
+ void lock();
+ void unlock();
+
+ void updateLockView();
+
+private:
+ KContacts::Lock *mLock;
+
+ QLabel *mStatus;
+ QTreeWidget *mLockView;
+};
+
+#endif
--- /dev/null
+/*
+ This file is part of the KContacts framework.
+ Copyright (c) 2012 Kevin Krammer <krammer@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "addressee.h"
+#include "converter/vcardconverter.h"
+
+#include <qtest.h>
+#include <QDir>
+#include <QObject>
+
+using namespace KContacts;
+
+class RoundtripTest : public QObject
+{
+ Q_OBJECT
+
+private:
+
+ QDir mInputDir;
+ QDir mOutput2_1Dir;
+ QDir mOutput3_0Dir;
+ QDir mOutput4_0Dir;
+
+ QStringList mInputFiles;
+
+private Q_SLOTS:
+ void initTestCase();
+ void testVCardRoundtrip_data();
+ void testVCardRoundtrip();
+};
+
+// check the validity of our test data set
+void RoundtripTest::initTestCase()
+{
+
+ // check that all resource prefixes exist
+
+ mInputDir = QDir(QStringLiteral(":/input"));
+ QVERIFY(mInputDir.exists());
+ QVERIFY(mInputDir.cd(QStringLiteral("data")));
+
+ mOutput2_1Dir = QDir(QStringLiteral(":/output2.1"));
+ QVERIFY(mOutput2_1Dir.exists());
+ QVERIFY(mOutput2_1Dir.cd(QStringLiteral("data")));
+
+ mOutput3_0Dir = QDir(QStringLiteral(":/output3.0"));
+ QVERIFY(mOutput3_0Dir.exists());
+ QVERIFY(mOutput3_0Dir.cd(QStringLiteral("data")));
+
+ mOutput4_0Dir = QDir(QStringLiteral(":/output4.0"));
+ QVERIFY(mOutput4_0Dir.exists());
+ QVERIFY(mOutput4_0Dir.cd(QStringLiteral("data")));
+
+ // check that there are input files
+
+ mInputFiles = mInputDir.entryList();
+
+ QVERIFY(!mInputFiles.isEmpty());
+}
+
+void RoundtripTest::testVCardRoundtrip_data()
+{
+ QTest::addColumn<QString>("inputFile");
+ QTest::addColumn<QString>("output2_1File");
+ QTest::addColumn<QString>("output3_0File");
+ QTest::addColumn<QString>("output4_0File");
+
+ QString outFile21Pattern = QLatin1String("%1.2_1ref");
+ QString outFile4Pattern = QLatin1String("v4_0.%1.ref");
+ QString outFilePattern = QLatin1String("%1.ref");
+ Q_FOREACH (const QString &inputFile, mInputFiles) {
+ const QString outFile = outFilePattern.arg(inputFile);
+ const QString outFileV2_1 = outFile21Pattern.arg(inputFile);
+ const QString outFileV4 = outFile4Pattern.arg(inputFile);
+ QTest::newRow(QFile::encodeName(inputFile).constData())
+ << inputFile
+ << (mOutput2_1Dir.exists(outFileV2_1) ? outFileV2_1 : QString())
+ << (mOutput3_0Dir.exists(outFile) ? outFile : QString())
+ << (mOutput4_0Dir.exists(outFileV4) ? outFileV4 : QString());
+ }
+}
+
+void RoundtripTest::testVCardRoundtrip()
+{
+ QFETCH(QString, inputFile);
+ QFETCH(QString, output2_1File);
+ QFETCH(QString, output3_0File);
+ QFETCH(QString, output4_0File);
+
+ QVERIFY2(!output2_1File.isEmpty()
+ || !output3_0File.isEmpty()
+ || !output4_0File.isEmpty(),
+ "No reference output file for either format version");
+
+ QFile input(QFileInfo(mInputDir, inputFile).absoluteFilePath());
+ QVERIFY(input.open(QIODevice::ReadOnly));
+
+ const QByteArray inputData = input.readAll();
+ QVERIFY(!inputData.isEmpty());
+
+ VCardConverter converter;
+ const Addressee::List list = converter.parseVCards(inputData);
+ QVERIFY(!list.isEmpty());
+
+ if (!output2_1File.isEmpty()) {
+ const QByteArray outputData = converter.createVCards(list, VCardConverter::v2_1);
+
+ QFile outputFile(QFileInfo(mOutput2_1Dir, output2_1File).absoluteFilePath());
+ QVERIFY(outputFile.open(QIODevice::ReadOnly));
+
+ const QByteArray outputRefData = outputFile.readAll();
+ QCOMPARE(outputData.size(), outputRefData.size());
+
+ const QList<QByteArray> outputLines = outputData.split('\n');
+ const QList<QByteArray> outputRefLines = outputRefData.split('\n');
+ QCOMPARE(outputLines.count(), outputRefLines.count());
+ for (int i = 0; i < outputLines.count(); ++i) {
+ const QByteArray actual = outputLines[i];
+ const QByteArray expect = outputRefLines[i];
+
+ if (actual != expect) {
+ qCritical() << "Mismatch in v2.1 output line" << (i + 1);
+ QCOMPARE(actual.count(), expect.count());
+
+ qCritical() << "\nActual:" << actual << "\nExpect:" << expect;
+ QCOMPARE(actual, expect);
+ }
+ }
+ }
+
+ if (!output3_0File.isEmpty()) {
+ const QByteArray outputData = converter.createVCards(list, VCardConverter::v3_0);
+
+ QFile outputFile(QFileInfo(mOutput3_0Dir, output3_0File).absoluteFilePath());
+ QVERIFY(outputFile.open(QIODevice::ReadOnly));
+
+ const QByteArray outputRefData = outputFile.readAll();
+ QCOMPARE(outputData.size(), outputRefData.size());
+
+ const QList<QByteArray> outputLines = outputData.split('\n');
+ const QList<QByteArray> outputRefLines = outputRefData.split('\n');
+ QCOMPARE(outputLines.count(), outputRefLines.count());
+
+ for (int i = 0; i < outputLines.count(); ++i) {
+ const QByteArray actual = outputLines[i];
+ const QByteArray expect = outputRefLines[i];
+
+ if (actual != expect) {
+ qCritical() << "Mismatch in v3.0 output line" << (i + 1);
+
+ qCritical() << "\nActual:" << actual << "\nExpect:" << expect;
+ QCOMPARE(actual.count(), expect.count());
+ QCOMPARE(actual, expect);
+ }
+ }
+ }
+#if 0
+ if (!output4_0File.isEmpty()) {
+ const QByteArray outputData = converter.createVCards(list, VCardConverter::v4_0);
+
+ QFile outputFile(QFileInfo(mOutput4_0Dir, output4_0File).absoluteFilePath());
+ QVERIFY(outputFile.open(QIODevice::ReadOnly));
+
+ const QByteArray outputRefData = outputFile.readAll();
+ //QCOMPARE( outputData.size(), outputRefData.size() );
+
+ const QList<QByteArray> outputLines = outputData.split('\n');
+ const QList<QByteArray> outputRefLines = outputRefData.split('\n');
+ //QCOMPARE(outputLines.count(), outputRefLines.count());
+
+ for (int i = 0; i < outputLines.count(); ++i) {
+ const QByteArray actual = outputLines[i];
+ const QByteArray expect = outputRefLines[i];
+
+ if (actual != expect) {
+ qCritical() << "Mismatch in v4.0 output line" << (i + 1);
+
+ qCritical() << "\nActual:" << actual << "\nExpect:" << expect;
+ QCOMPARE(actual.count(), expect.count());
+ QCOMPARE(actual, expect);
+ }
+ }
+ }
+#endif
+}
+
+QTEST_MAIN(RoundtripTest)
+
+#include "testroundtrip.moc"
--- /dev/null
+<!DOCTYPE RCC><RCC version="1.0">
+ <!-- input files -->
+ <qresource prefix="/input">
+ <file>data/vcard1.vcf</file>
+ <file>data/vcard2.vcf</file>
+ <file>data/vcard3.vcf</file>
+ <file>data/vcard4.vcf</file>
+ <file>data/vcard5.vcf</file>
+ <file>data/vcard6.vcf</file>
+ <file>data/vcard7.vcf</file>
+ <file>data/vcard8.vcf</file>
+ <file>data/vcard9.vcf</file>
+ <file>data/vcard10.vcf</file>
+ <file>data/vcard11.vcf</file>
+ <file>data/vcard12.vcf</file>
+ <file>data/vcard13.vcf</file>
+ <file>data/vcard14.vcf</file>
+ </qresource>
+
+ <!-- output files formatted for vcard version 2.1 -->
+ <qresource prefix="/output2.1">
+ <file>data/vcard1.vcf.2_1ref</file>
+ <file>data/vcard2.vcf.2_1ref</file>
+ <file>data/vcard3.vcf.2_1ref</file>
+ <file>data/vcard6.vcf.2_1ref</file>
+ <file>data/vcard7.vcf.2_1ref</file>
+ <file>data/vcard12.vcf.2_1ref</file>
+ <file>data/vcard14.vcf.2_1ref</file>
+ </qresource>
+
+ <!-- output files formatted for vcard version 3.0 -->
+ <qresource prefix="/output3.0">
+ <file>data/vcard1.vcf.ref</file>
+ <file>data/vcard2.vcf.ref</file>
+ <file>data/vcard3.vcf.ref</file>
+ <file>data/vcard4.vcf.ref</file>
+ <file>data/vcard5.vcf.ref</file>
+ <file>data/vcard6.vcf.ref</file>
+ <file>data/vcard7.vcf.ref</file>
+ <file>data/vcard8.vcf.ref</file>
+ <file>data/vcard9.vcf.ref</file>
+ <file>data/vcard10.vcf.ref</file>
+ <file>data/vcard11.vcf.ref</file>
+ <file>data/vcard12.vcf.ref</file>
+ <file>data/vcard13.vcf.ref</file>
+ <file>data/vcard14.vcf.ref</file>
+ </qresource>
+
+ <!-- output files formatted for vcard version 4.0 -->
+ <qresource prefix="/output4.0">
+ <file>data/v4_0.vcard1.vcf.ref</file>
+ <file>data/v4_0.vcard2.vcf.ref</file>
+ <file>data/v4_0.vcard3.vcf.ref</file>
+ <file>data/v4_0.vcard4.vcf.ref</file>
+ <file>data/v4_0.vcard5.vcf.ref</file>
+ <file>data/v4_0.vcard6.vcf.ref</file>
+ <file>data/v4_0.vcard7.vcf.ref</file>
+ <file>data/v4_0.vcard8.vcf.ref</file>
+ </qresource>
+
+</RCC>
--- /dev/null
+/*
+ This file is part of the KContacts framework.
+ Copyright (c) 2007 Tobias Koenig <tokoe@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "timezonetest.h"
+#include "kcontacts/timezone.h"
+#include <qtest.h>
+#include "vcardtool.h"
+
+QTEST_MAIN(TimeZoneTest)
+
+void TimeZoneTest::emptyTest()
+{
+ KContacts::TimeZone timezone;
+
+ QVERIFY(timezone.isValid() == false);
+}
+
+void TimeZoneTest::storeTest()
+{
+ KContacts::TimeZone timezone;
+
+ timezone.setOffset(2);
+
+ QVERIFY(timezone.offset() == 2);
+}
+
+void TimeZoneTest::equalsTest()
+{
+ KContacts::TimeZone timezone1, timezone2;
+
+ timezone1.setOffset(2);
+ timezone2.setOffset(2);
+
+ QVERIFY(timezone1 == timezone2);
+}
+
+void TimeZoneTest::differsTest()
+{
+ KContacts::TimeZone timezone1(2);
+ KContacts::TimeZone timezone2(3);
+
+ QVERIFY(timezone1 != timezone2);
+ QVERIFY(timezone1 != KContacts::TimeZone());
+}
+
+void TimeZoneTest::assignmentTest()
+{
+ KContacts::TimeZone timezone1, timezone2;
+
+ timezone1.setOffset(2);
+ timezone1 = timezone2;
+
+ QVERIFY(timezone1 == timezone2);
+}
+
+void TimeZoneTest::serializeTest()
+{
+ KContacts::TimeZone timezone1, timezone2;
+
+ timezone1.setOffset(2);
+
+ QByteArray data;
+ QDataStream s(&data, QIODevice::WriteOnly);
+ s << timezone1;
+
+ QDataStream t(&data, QIODevice::ReadOnly);
+ t >> timezone2;
+
+ QVERIFY(timezone1 == timezone2);
+}
+
+void TimeZoneTest::shouldGenerateVCard3()
+{
+ KContacts::Addressee::List lst;
+ KContacts::Addressee addr;
+ addr.setEmails(QStringList() << QStringLiteral("foo@kde.org"));
+ addr.setUid(QStringLiteral("testuid"));
+ KContacts::TimeZone timezone;
+
+ timezone.setOffset(2);
+ addr.setTimeZone(timezone);
+
+ lst << addr;
+ KContacts::VCardTool vcard;
+ const QByteArray ba = vcard.exportVCards(lst, KContacts::VCard::v3_0);
+ QByteArray expected;
+ expected = QByteArray("BEGIN:VCARD\r\n"
+ "VERSION:3.0\r\n"
+ "EMAIL:foo@kde.org\r\n"
+ "N:;;;;\r\n"
+ "TZ:+00:02\r\n"
+ "UID:testuid\r\n"
+ "END:VCARD\r\n\r\n");
+ QCOMPARE(ba, expected);
+}
--- /dev/null
+/*
+ This file is part of the KContacts framework.
+ Copyright (c) 2007 Tobias Koenig <tokoe@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef TIMEZONE_TEST_H
+#define TIMEZONE_TEST_H
+
+#include <QtCore/QObject>
+
+class TimeZoneTest : public QObject
+{
+ Q_OBJECT
+
+private Q_SLOTS:
+ void emptyTest();
+ void storeTest();
+ void equalsTest();
+ void differsTest();
+ void assignmentTest();
+ void serializeTest();
+ void shouldGenerateVCard3();
+};
+
+#endif
--- /dev/null
+/*
+ This file is part of the KContacts framework.
+ Copyright (C) 2010 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.net
+ Author: Kevin Krammer, krake@kdab.com
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <qtest.h>
+
+#include "converter/kcontacts/vcardconverter.h"
+#include "kcontacts/vcarddrag.h"
+
+#include <QMimeData>
+using namespace KContacts;
+
+class VCardDragTest : public QObject
+{
+ Q_OBJECT
+
+public:
+ VCardDragTest();
+
+private:
+ Addressee mAddressee1;
+ Addressee mAddressee2;
+
+private Q_SLOTS:
+ void testPopulate();
+ void testCanDecode();
+ void testFromMimeData();
+};
+
+QTEST_MAIN(VCardDragTest)
+
+VCardDragTest::VCardDragTest()
+ : QObject()
+{
+ mAddressee1.setGivenName(QStringLiteral("Kevin"));
+ mAddressee1.setFamilyName(QStringLiteral("Krammer"));
+ mAddressee1.insertEmail(QStringLiteral("kevin.krammer@gmx.at"));
+
+ mAddressee2.setGivenName(QStringLiteral("Tobias"));
+ mAddressee2.setFamilyName(QStringLiteral("König"));
+ mAddressee2.insertEmail(QStringLiteral("tokoe@kde.org"));
+}
+
+void VCardDragTest::testPopulate()
+{
+ VCardConverter converter;
+ const QByteArray vcard = converter.createVCard(mAddressee1);
+ QVERIFY(!vcard.isEmpty());
+
+ QMimeData *data = new QMimeData();
+ bool result = VCardDrag::populateMimeData(data, vcard);
+ QVERIFY(result);
+ QVERIFY(data->hasFormat(KContacts::Addressee::mimeType()));
+ QCOMPARE(data->data(KContacts::Addressee::mimeType()), vcard);
+ delete data;
+
+ data = new QMimeData();
+ result = VCardDrag::populateMimeData(data, Addressee::List() << mAddressee1);
+ QVERIFY(result);
+ QVERIFY(data->hasFormat(KContacts::Addressee::mimeType()));
+ QCOMPARE(data->data(KContacts::Addressee::mimeType()), vcard);
+ delete data;
+
+ const QByteArray vcards = converter.createVCards(Addressee::List() << mAddressee1 << mAddressee2);
+ data = new QMimeData();
+ result = VCardDrag::populateMimeData(data, Addressee::List() << mAddressee1 << mAddressee2);
+ QVERIFY(result);
+ QVERIFY(data->hasFormat(KContacts::Addressee::mimeType()));
+ QCOMPARE(data->data(KContacts::Addressee::mimeType()), vcards);
+ delete data;
+
+ data = new QMimeData();
+ result = VCardDrag::populateMimeData(data, Addressee::List());
+ QVERIFY(!result);
+ QVERIFY(!data->hasFormat(KContacts::Addressee::mimeType()));
+ delete data;
+}
+
+void VCardDragTest::testCanDecode()
+{
+ VCardConverter converter;
+ const QByteArray vcard = converter.createVCard(mAddressee1);
+ QVERIFY(!vcard.isEmpty());
+
+ QMimeData *data = new QMimeData();
+ data->setData(Addressee::mimeType(), vcard);
+ QVERIFY(VCardDrag::canDecode(data));
+ delete data;
+
+ data = new QMimeData();
+ data->setData(QStringLiteral("text/x-vcard"), vcard);
+ QVERIFY(VCardDrag::canDecode(data));
+ delete data;
+
+ data = new QMimeData();
+ data->setData(QStringLiteral("application/octetstream"), vcard);
+ QVERIFY(!VCardDrag::canDecode(data));
+ delete data;
+}
+
+void VCardDragTest::testFromMimeData()
+{
+ VCardConverter converter;
+ const QByteArray vcard = converter.createVCard(mAddressee1);
+ QVERIFY(!vcard.isEmpty());
+
+ QByteArray content;
+
+ QMimeData *data = new QMimeData();
+ data->setData(Addressee::mimeType(), vcard);
+ bool result = VCardDrag::fromMimeData(data, content);
+ QVERIFY(result);
+ QCOMPARE(content, vcard);
+ delete data;
+
+ data = new QMimeData();
+ data->setData(QStringLiteral("text/x-vcard"), vcard);
+ result = VCardDrag::fromMimeData(data, content);
+ QVERIFY(result);
+ QCOMPARE(content, vcard);
+ delete data;
+
+ data = new QMimeData();
+ data->setData(QStringLiteral("application/octetstream"), vcard);
+ result = VCardDrag::fromMimeData(data, content);
+ QVERIFY(!result);
+ delete data;
+
+ const QByteArray vcards = converter.createVCards(Addressee::List() << mAddressee1 << mAddressee2);
+ QVERIFY(!vcards.isEmpty());
+
+ Addressee::List addresseeList;
+
+ data = new QMimeData();
+ data->setData(Addressee::mimeType(), vcards);
+ result = VCardDrag::fromMimeData(data, addresseeList);
+ QVERIFY(result);
+ QCOMPARE(addresseeList.count(), 2);
+ QCOMPARE(addresseeList[0], mAddressee1);
+ QCOMPARE(addresseeList[1], mAddressee2);
+ delete data;
+
+ data = new QMimeData();
+ data->setData(QStringLiteral("text/x-vcard"), vcards);
+ result = VCardDrag::fromMimeData(data, addresseeList);
+ QVERIFY(result);
+ QCOMPARE(addresseeList.count(), 2);
+ QCOMPARE(addresseeList[0], mAddressee1);
+ QCOMPARE(addresseeList[1], mAddressee2);
+ delete data;
+
+ data = new QMimeData();
+ data->setData(QStringLiteral("application/octetstream"), vcards);
+ result = VCardDrag::fromMimeData(data, addresseeList);
+ QVERIFY(!result);
+ delete data;
+
+ data = new QMimeData();
+ data->setData(Addressee::mimeType(), QByteArray());
+ result = VCardDrag::fromMimeData(data, addresseeList);
+ QVERIFY(!result);
+ delete data;
+}
+
+#include "vcarddragtest.moc"
--- /dev/null
+maintainer:
+description: Address book API for KDE
+tier: 3
+type: functional
+platforms:
+ - name: All
+portingAid: false
+deprecated: false
+release: false
+libraries:
+ - qmake: KContacts
+ cmake: "KF5::Contacts"
+cmakename: KF5Contacts
+
--- /dev/null
+set(vcardparser_SRCS
+ vcardparser/vcard.cpp
+ vcardparser/vcardline.cpp
+ vcardparser/vcardparser.cpp
+)
+
+set(kcontacts_SRCS
+ address.cpp
+ addressee.cpp
+ addresseehelper.cpp
+ addresseelist.cpp
+ calendarurl.cpp
+ contactgroup.cpp
+ contactgrouptool.cpp
+ email.cpp
+ field.cpp
+ geo.cpp
+ gender.cpp
+ impp.cpp
+ key.cpp
+ lang.cpp
+ ldapdn.cpp
+ ldif.cpp
+ phonenumber.cpp
+ picture.cpp
+ related.cpp
+ resourcelocatorurl.cpp
+ secrecy.cpp
+ sortmode.cpp
+ sound.cpp
+ timezone.cpp
+ vcarddrag.cpp
+ vcardtool.cpp
+ ${vcardparser_SRCS}
+)
+
+set(kcontacts_converter_SRCS
+ converter/vcardconverter.cpp
+ converter/ldifconverter.cpp
+)
+
+ecm_qt_declare_logging_category(kcontacts_converter_SRCS HEADER kcontacts_debug.h IDENTIFIER KCONTACTS_LOG CATEGORY_NAME log_kcontacts)
+
+add_library(KF5Contacts ${kcontacts_SRCS} ${kcontacts_converter_SRCS})
+
+generate_export_header(KF5Contacts BASE_NAME kcontacts)
+
+add_library(KF5::Contacts ALIAS KF5Contacts)
+
+target_include_directories(KF5Contacts INTERFACE "$<INSTALL_INTERFACE:${KDE_INSTALL_INCLUDEDIR_KF5}/KContacts>")
+target_include_directories(KF5Contacts PUBLIC "$<BUILD_INTERFACE:${KContacts_SOURCE_DIR}/src;${KContacts_BINARY_DIR}/src>")
+target_include_directories(KF5Contacts PUBLIC "$<BUILD_INTERFACE:${KContacts_SOURCE_DIR}/src/vcardparser>")
+
+target_link_libraries(KF5Contacts
+PUBLIC
+ KF5::CoreAddons
+ Qt5::Gui
+PRIVATE
+ Qt5::DBus
+ KF5::ConfigCore
+ KF5::I18n
+ KF5::Codecs # for the vcard parser
+)
+
+set_target_properties(KF5Contacts PROPERTIES
+ VERSION ${KContacts_VERSION_STRING}
+ SOVERSION ${KContacts_SOVERSION}
+ EXPORT_NAME Contacts
+)
+
+install(TARGETS KF5Contacts EXPORT KF5ContactsTargets ${KF5_INSTALL_TARGETS_DEFAULT_ARGS})
+
+ecm_generate_headers(KContacts_CamelCase_HEADERS
+ HEADER_NAMES
+ Address
+ Addressee
+ AddresseeList
+ CalendarUrl
+ ContactGroup
+ ContactGroupTool
+ Email
+ Field
+ Geo
+ Gender
+ Key
+ Lang
+ Impp
+ PhoneNumber
+ Picture
+ Related
+ ResourceLocatorUrl
+ Secrecy
+ SortMode
+ Sound
+ TimeZone
+ VCardDrag
+ PREFIX KContacts
+ REQUIRED_HEADERS KContacts_HEADERS
+)
+
+add_subdirectory(converter)
+
+install(FILES
+ ${CMAKE_CURRENT_BINARY_DIR}/kcontacts_export.h
+ ${KContacts_HEADERS}
+ DESTINATION ${KDE_INSTALL_INCLUDEDIR_KF5}/KContacts/kcontacts
+ COMPONENT Devel
+)
+
+install(FILES
+ ${KContacts_CamelCase_HEADERS}
+ DESTINATION ${KDE_INSTALL_INCLUDEDIR_KF5}/KContacts/KContacts
+ COMPONENT Devel
+)
+
+
+install(FILES countrytransl.map DESTINATION ${KDE_INSTALL_DATADIR_KF5}/kcontacts)
+
+ecm_generate_pri_file(BASE_NAME KContacts LIB_NAME KF5Contacts DEPS "CoreAddons" FILENAME_VAR PRI_FILENAME INCLUDE_INSTALL_DIR ${KDE_INSTALL_INCLUDEDIR_KF5}/KContacts)
+install(FILES ${PRI_FILENAME} DESTINATION ${ECM_MKSPECS_INSTALL_DIR})
--- /dev/null
+#! /usr/bin/env bash
+$XGETTEXT *.cpp -o $podir/kcontacts5.pot
--- /dev/null
+/*
+ This file is part of the KContacts framework.
+ Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "address.h"
+
+#include "kcontacts_debug.h"
+#include <krandom.h>
+#include <klocalizedstring.h>
+#include <kconfig.h>
+
+#include <kconfiggroup.h>
+
+#include <QtCore/QFile>
+#include <QtCore/QMap>
+#include <QtCore/QTextStream>
+#include <QtCore/QSharedData>
+#include <QtCore/QStandardPaths>
+#include <QtCore/QLocale>
+#include <QtCore/QDataStream>
+
+using namespace KContacts;
+
+// template tags for address formatting localization
+#define KCONTACTS_FMTTAG_realname QStringLiteral("%n")
+#define KCONTACTS_FMTTAG_REALNAME QStringLiteral("%N")
+#define KCONTACTS_FMTTAG_company QStringLiteral("%cm")
+#define KCONTACTS_FMTTAG_COMPANY QStringLiteral("%CM")
+#define KCONTACTS_FMTTAG_pobox QStringLiteral("%p")
+#define KCONTACTS_FMTTAG_street QStringLiteral("%s")
+#define KCONTACTS_FMTTAG_STREET QStringLiteral("%S")
+#define KCONTACTS_FMTTAG_zipcode QStringLiteral("%z")
+#define KCONTACTS_FMTTAG_location QStringLiteral("%l")
+#define KCONTACTS_FMTTAG_LOCATION QStringLiteral("%L")
+#define KCONTACTS_FMTTAG_region QStringLiteral("%r")
+#define KCONTACTS_FMTTAG_REGION QStringLiteral("%R")
+#define KCONTACTS_FMTTAG_newline QStringLiteral("\\n")
+#define KCONTACTS_FMTTAG_condcomma QStringLiteral("%,")
+#define KCONTACTS_FMTTAG_condwhite QStringLiteral("%w")
+#define KCONTACTS_FMTTAG_purgeempty QStringLiteral("%0")
+
+/**
+ Finds the balanced closing bracket starting from the opening bracket at
+ pos in tsection.
+ @return position of closing bracket, -1 for unbalanced brackets
+*/
+static int findBalancedBracket(const QString &tsection, int pos)
+{
+ int balancecounter = 0;
+ for (int i = pos + 1; i < tsection.length(); ++i) {
+ if (QLatin1Char(')') == tsection[i] && 0 == balancecounter) {
+ // found end of brackets
+ return i;
+ } else {
+ if (QLatin1Char('(') == tsection[i]) {
+ // nested brackets
+ balancecounter++;
+ }
+ }
+ }
+ return -1;
+}
+
+/**
+ Parses a snippet of an address template
+ @param tsection the template string to be parsed
+ @param result QString reference in which the result will be stored
+ @return true if at least one tag evaluated positively, else false
+*/
+static bool parseAddressTemplateSection(const QString &tsection, QString &result,
+ const QString &realName, const QString &orgaName,
+ const KContacts::Address &address)
+{
+ // This method first parses and substitutes any bracketed sections and
+ // after that replaces any tags with their values. If a bracketed section
+ // or a tag evaluate to zero, they are not just removed but replaced
+ // with a placeholder. This is because in the last step conditionals are
+ // resolved which depend on information about zero-evaluations.
+ result = tsection;
+ int stpos = 0;
+ bool ret = false;
+
+ // first check for brackets that have to be evaluated first
+ int fpos = result.indexOf(KCONTACTS_FMTTAG_purgeempty, stpos);
+ while (-1 != fpos) {
+ int bpos1 = fpos + KCONTACTS_FMTTAG_purgeempty.length();
+ int bpos2;
+ // expect opening bracket and find next balanced closing bracket. If
+ // next char is no opening bracket, continue parsing (no valid tag)
+ if (QLatin1Char('(') == result[bpos1]) {
+ bpos2 = findBalancedBracket(result, bpos1);
+ if (-1 != bpos2) {
+ // we have balanced brackets, recursively parse:
+ QString rplstr;
+ bool purge = !parseAddressTemplateSection(result.mid(bpos1 + 1,
+ bpos2 - bpos1 - 1), rplstr,
+ realName, orgaName, address);
+ if (purge) {
+ // purge -> remove all
+ // replace with !_P_!, so conditional tags work later
+ result.replace(fpos, bpos2 - fpos + 1, QStringLiteral("!_P_!"));
+ // leave stpos as it is
+ } else {
+ // no purge -> replace with recursively parsed string
+ result.replace(fpos, bpos2 - fpos + 1, rplstr);
+ ret = true;
+ stpos = fpos + rplstr.length();
+ }
+ } else {
+ // unbalanced brackets: keep on parsing (should not happen
+ // and will result in bad formatting)
+ stpos = bpos1;
+ }
+ }
+ fpos = result.indexOf(KCONTACTS_FMTTAG_purgeempty, stpos);
+ }
+
+ // after sorting out all purge tags, we just search'n'replace the rest,
+ // keeping track of whether at least one tag evaluates to something.
+ // The following macro needs QString for R_FIELD
+ // It substitutes !_P_! for empty fields so conditional tags work later
+#define REPLTAG(R_TAG,R_FIELD) \
+ if ( result.indexOf( R_TAG ) != -1 ) { \
+ QString rpl = R_FIELD.isEmpty() ? QStringLiteral( "!_P_!" ) : R_FIELD; \
+ result.replace( R_TAG, rpl ); \
+ if ( !R_FIELD.isEmpty() ) { \
+ ret = true; \
+ } \
+ }
+ REPLTAG(KCONTACTS_FMTTAG_realname, realName);
+ REPLTAG(KCONTACTS_FMTTAG_REALNAME, realName.toUpper());
+ REPLTAG(KCONTACTS_FMTTAG_company, orgaName);
+ REPLTAG(KCONTACTS_FMTTAG_COMPANY, orgaName.toUpper());
+ REPLTAG(KCONTACTS_FMTTAG_pobox, address.postOfficeBox());
+ REPLTAG(KCONTACTS_FMTTAG_street, address.street());
+ REPLTAG(KCONTACTS_FMTTAG_STREET, address.street().toUpper());
+ REPLTAG(KCONTACTS_FMTTAG_zipcode, address.postalCode());
+ REPLTAG(KCONTACTS_FMTTAG_location, address.locality());
+ REPLTAG(KCONTACTS_FMTTAG_LOCATION, address.locality().toUpper());
+ REPLTAG(KCONTACTS_FMTTAG_region, address.region());
+ REPLTAG(KCONTACTS_FMTTAG_REGION, address.region().toUpper());
+ result.replace(KCONTACTS_FMTTAG_newline, QLatin1String("\n"));
+#undef REPLTAG
+
+ // conditional comma
+ fpos = result.indexOf(KCONTACTS_FMTTAG_condcomma, 0);
+ while (-1 != fpos) {
+ const QString str1 = result.mid(fpos - 5, 5);
+ const QString str2 = result.mid(fpos + 2, 5);
+ if (str1 != QLatin1String("!_P_!") && str2 != QLatin1String("!_P_!")) {
+ result.replace(fpos, 2, QStringLiteral(", "));
+ } else {
+ result.remove(fpos, 2);
+ }
+ fpos = result.indexOf(KCONTACTS_FMTTAG_condcomma, fpos);
+ }
+ // conditional whitespace
+ fpos = result.indexOf(KCONTACTS_FMTTAG_condwhite, 0);
+ while (-1 != fpos) {
+ const QString str1 = result.mid(fpos - 5, 5);
+ const QString str2 = result.mid(fpos + 2, 5);
+ if (str1 != QLatin1String("!_P_!") && str2 != QLatin1String("!_P_!")) {
+ result.replace(fpos, 2, QStringLiteral(" "));
+ } else {
+ result.remove(fpos, 2);
+ }
+ fpos = result.indexOf(KCONTACTS_FMTTAG_condwhite, fpos);
+ }
+
+ // remove purged:
+ result.remove(QStringLiteral("!_P_!"));
+
+ return ret;
+}
+
+class Q_DECL_HIDDEN Address::Private : public QSharedData
+{
+public:
+ Private()
+ : mEmpty(true)
+ , mType(Q_NULLPTR)
+ {
+ mId = KRandom::randomString(10);
+ }
+
+ Private(const Private &other)
+ : QSharedData(other)
+ {
+ mEmpty = other.mEmpty;
+ mId = other.mId;
+ mType = other.mType;
+
+ mPostOfficeBox = other.mPostOfficeBox;
+ mExtended = other.mExtended;
+ mStreet = other.mStreet;
+ mLocality = other.mLocality;
+ mRegion = other.mRegion;
+ mPostalCode = other.mPostalCode;
+ mCountry = other.mCountry;
+ mLabel = other.mLabel;
+ }
+
+ bool mEmpty;
+ QString mId;
+ Type mType;
+
+ QString mPostOfficeBox;
+ QString mExtended;
+ QString mStreet;
+ QString mLocality;
+ QString mRegion;
+ QString mPostalCode;
+ QString mCountry;
+ QString mLabel;
+};
+
+Address::Address()
+ : d(new Private)
+{
+}
+
+Address::Address(Type type)
+ : d(new Private)
+{
+ d->mType = type;
+}
+
+Address::Address(const Address &other)
+ : d(other.d)
+{
+}
+
+Address::~Address()
+{
+}
+
+Address &Address::operator=(const Address &other)
+{
+ if (this != &other) {
+ d = other.d;
+ }
+
+ return *this;
+}
+
+bool Address::operator==(const Address &other) const
+{
+ if (d->mId != other.d->mId) {
+ return false;
+ }
+ if (d->mType != other.d->mType) {
+ return false;
+ }
+ if (d->mPostOfficeBox != other.d->mPostOfficeBox) {
+ return false;
+ }
+ if (d->mExtended != other.d->mExtended) {
+ return false;
+ }
+ if (d->mStreet != other.d->mStreet) {
+ return false;
+ }
+ if (d->mLocality != other.d->mLocality) {
+ return false;
+ }
+ if (d->mRegion != other.d->mRegion) {
+ return false;
+ }
+ if (d->mPostalCode != other.d->mPostalCode) {
+ return false;
+ }
+ if (d->mCountry != other.d->mCountry) {
+ return false;
+ }
+ if (d->mLabel != other.d->mLabel) {
+ return false;
+ }
+
+ return true;
+}
+
+bool Address::operator!=(const Address &a) const
+{
+ return !(a == *this);
+}
+
+bool Address::isEmpty() const
+{
+ return d->mEmpty;
+}
+
+void Address::clear()
+{
+ *this = Address();
+}
+
+void Address::setId(const QString &id)
+{
+ d->mEmpty = false;
+ d->mId = id;
+}
+
+QString Address::id() const
+{
+ return d->mId;
+}
+
+void Address::setType(Type type)
+{
+ d->mEmpty = false;
+ d->mType = type;
+}
+
+Address::Type Address::type() const
+{
+ return d->mType;
+}
+
+QString Address::typeLabel(Type type)
+{
+ QString label;
+ bool first = true;
+ const TypeList list = typeList();
+
+ TypeList::ConstIterator it;
+ TypeList::ConstIterator end(list.end());
+ for (it = list.begin(); it != end; ++it) {
+ // these are actually flags
+ const TypeFlag flag = static_cast<TypeFlag>(static_cast<int>(*it));
+ if (type & flag) {
+ if (!first) {
+ label.append(QLatin1Char('/'));
+ }
+
+ label.append(typeFlagLabel(flag));
+
+ if (first) {
+ first = false;
+ }
+ }
+ }
+ return label;
+}
+
+QString Address::typeLabel() const
+{
+ QString label;
+ bool first = true;
+
+ const TypeList list = typeList();
+
+ TypeList::ConstIterator it;
+ for (it = list.begin(); it != list.end(); ++it) {
+ if ((type() & (*it)) && ((*it) != Pref)) {
+ if (!first) {
+ label.append(QLatin1Char('/'));
+ }
+ label.append(typeLabel(*it));
+ if (first) {
+ first = false;
+ }
+ }
+ }
+
+ return label;
+}
+
+void Address::setPostOfficeBox(const QString &postOfficeBox)
+{
+ d->mEmpty = false;
+ d->mPostOfficeBox = postOfficeBox;
+}
+
+QString Address::postOfficeBox() const
+{
+ return d->mPostOfficeBox;
+}
+
+QString Address::postOfficeBoxLabel()
+{
+ return i18n("Post Office Box");
+}
+
+void Address::setExtended(const QString &extended)
+{
+ d->mEmpty = false;
+ d->mExtended = extended;
+}
+
+QString Address::extended() const
+{
+ return d->mExtended;
+}
+
+QString Address::extendedLabel()
+{
+ return i18n("Extended Address Information");
+}
+
+void Address::setStreet(const QString &street)
+{
+ d->mEmpty = false;
+ d->mStreet = street;
+}
+
+QString Address::street() const
+{
+ return d->mStreet;
+}
+
+QString Address::streetLabel()
+{
+ return i18n("Street");
+}
+
+void Address::setLocality(const QString &locality)
+{
+ d->mEmpty = false;
+ d->mLocality = locality;
+}
+
+QString Address::locality() const
+{
+ return d->mLocality;
+}
+
+QString Address::localityLabel()
+{
+ return i18n("Locality");
+}
+
+void Address::setRegion(const QString ®ion)
+{
+ d->mEmpty = false;
+ d->mRegion = region;
+}
+
+QString Address::region() const
+{
+ return d->mRegion;
+}
+
+QString Address::regionLabel()
+{
+ return i18n("Region");
+}
+
+void Address::setPostalCode(const QString &postalCode)
+{
+ d->mEmpty = false;
+ d->mPostalCode = postalCode;
+}
+
+QString Address::postalCode() const
+{
+ return d->mPostalCode;
+}
+
+QString Address::postalCodeLabel()
+{
+ return i18n("Postal Code");
+}
+
+void Address::setCountry(const QString &country)
+{
+ d->mEmpty = false;
+ d->mCountry = country;
+}
+
+QString Address::country() const
+{
+ return d->mCountry;
+}
+
+QString Address::countryLabel()
+{
+ return i18n("Country");
+}
+
+void Address::setLabel(const QString &label)
+{
+ d->mEmpty = false;
+ d->mLabel = label;
+}
+
+QString Address::label() const
+{
+ return d->mLabel;
+}
+
+QString Address::labelLabel()
+{
+ return i18n("Delivery Label");
+}
+
+Address::TypeList Address::typeList()
+{
+ static TypeList list;
+
+ if (list.isEmpty()) {
+ list << Dom << Intl << Postal << Parcel << Home << Work << Pref;
+ }
+
+ return list;
+}
+
+QString Address::typeFlagLabel(TypeFlag type)
+{
+ switch (type) {
+ case Dom:
+ return i18nc("Address is in home country", "Domestic");
+ case Intl:
+ return i18nc("Address is not in home country", "International");
+ case Postal:
+ return i18nc("Address for delivering letters", "Postal");
+ case Parcel:
+ return i18nc("Address for delivering packages", "Parcel");
+ case Home:
+ return i18nc("Home Address", "Home");
+ case Work:
+ return i18nc("Work Address", "Work");
+ case Pref:
+ return i18n("Preferred Address");
+ default:
+ return i18nc("another type of address", "Other");
+ }
+}
+
+QString Address::toString() const
+{
+ QString str;
+
+ str += QLatin1String("Address {\n");
+ str += QStringLiteral(" IsEmpty: %1\n").
+ arg(d->mEmpty ? QStringLiteral("true") : QStringLiteral("false"));
+ str += QStringLiteral(" Id: %1\n").arg(d->mId);
+ str += QStringLiteral(" Type: %1\n").arg(typeLabel(d->mType));
+ str += QStringLiteral(" Post office box: %1\n").arg(d->mPostOfficeBox);
+ str += QStringLiteral(" Extended: %1\n").arg(d->mExtended);
+ str += QStringLiteral(" Street: %1\n").arg(d->mStreet);
+ str += QStringLiteral(" Locality: %1\n").arg(d->mLocality);
+ str += QStringLiteral(" Region: %1\n").arg(d->mRegion);
+ str += QStringLiteral(" Postal code: %1\n").arg(d->mPostalCode);
+ str += QStringLiteral(" Country: %1\n").arg(d->mCountry);
+ str += QStringLiteral(" Label: %1\n").arg(d->mLabel);
+ str += QLatin1String("}\n");
+
+ return str;
+}
+
+QString Address::formattedAddress(const QString &realName,
+ const QString &orgaName) const
+{
+ QString ciso;
+ QString addrTemplate;
+ QString ret;
+
+ // FIXME: first check for iso-country-field and prefer that one
+ if (!country().isEmpty()) {
+ ciso = countryToISO(country());
+ } else {
+ // fall back to our own country
+ ciso = QLocale().bcp47Name();
+ }
+ KConfig entry(QStandardPaths::locate(QStandardPaths::GenericDataLocation, QLatin1String("kf5/locale/countries/") + ciso + QLatin1String("/country.desktop")));
+
+ KConfigGroup group = entry.group("KCM Locale");
+ // decide whether this needs special business address formatting
+ if (orgaName.isEmpty()) {
+ addrTemplate = group.readEntry("AddressFormat");
+ } else {
+ addrTemplate = group.readEntry("BusinessAddressFormat");
+ if (addrTemplate.isEmpty()) {
+ addrTemplate = group.readEntry("AddressFormat");
+ }
+ }
+
+ // in the case there's no format found at all, default to what we've always
+ // used:
+ if (addrTemplate.isEmpty()) {
+ qCWarning(KCONTACTS_LOG) << "address format database incomplete"
+ << "(no format for locale" << ciso
+ << "found). Using default address formatting.";
+ addrTemplate = QStringLiteral("%0(%n\\n)%0(%cm\\n)%0(%s\\n)%0(PO BOX %p\\n)%0(%l%w%r)%,%z");
+ }
+
+ // scan
+ parseAddressTemplateSection(addrTemplate, ret, realName, orgaName, *this);
+
+ // now add the country line if needed (formatting this time according to
+ // the rules of our own system country )
+ if (!country().isEmpty()) {
+ KConfig entry(QStandardPaths::locate(QStandardPaths::GenericDataLocation, QLatin1String("kf5/locale/countries/") +
+ QLocale().name() +
+ QLatin1String("/country.desktop")));
+ KConfigGroup group = entry.group("KCM Locale");
+ QString cpos = group.readEntry("AddressCountryPosition");
+ if (QLatin1String("BELOW") == cpos || cpos.isEmpty()) {
+ ret = ret + QLatin1String("\n\n") + country().toUpper();
+ } else if (QLatin1String("below") == cpos) {
+ ret = ret + QLatin1String("\n\n") + country();
+ } else if (QLatin1String("ABOVE") == cpos) {
+ ret = country().toUpper() + QLatin1String("\n\n") + ret;
+ } else if (QLatin1String("above") == cpos) {
+ ret = country() + QLatin1String("\n\n") + ret;
+ }
+ }
+
+ return ret;
+}
+
+typedef QMap<QString, QString> StringMap;
+Q_GLOBAL_STATIC(StringMap, sISOMap)
+
+QString Address::countryToISO(const QString &cname)
+{
+ // we search a map file for translations from country names to
+ // iso codes, storing caching things in a QMap for faster future
+ // access.
+
+ QMap<QString, QString>::ConstIterator it;
+ it = sISOMap->constFind(cname);
+ if (it != sISOMap->constEnd()) {
+ return it.value();
+ }
+
+ QString mapfile = QStandardPaths::locate(QStandardPaths::GenericDataLocation, QStringLiteral("kf5/kcontacts/countrytransl.map"));
+ if (mapfile.isEmpty()) {
+ qWarning() << "Installation error, couldn't find the countrytransl.map file";
+ }
+
+ QFile file(mapfile);
+ if (file.open(QIODevice::ReadOnly)) {
+ QTextStream s(&file);
+ QString strbuf = s.readLine();
+ while (!strbuf.isEmpty()) {
+ QStringList countryInfo = strbuf.split(QLatin1Char('\t'), QString::KeepEmptyParts);
+ if (countryInfo[0] == cname) {
+ file.close();
+ sISOMap->insert(cname, countryInfo[1]);
+ return countryInfo[1];
+ }
+ strbuf = s.readLine();
+ }
+ file.close();
+ }
+
+ // fall back to system country
+ QString systemCountry = QLocale().bcp47Name();
+ sISOMap->insert(cname, systemCountry);
+ return systemCountry;
+}
+
+QString Address::ISOtoCountry(const QString &ISOname)
+{
+ // get country name from ISO country code (e.g. "no" -> i18n("Norway"))
+ if (ISOname.simplified().isEmpty()) {
+ return QString();
+ }
+
+ QString mapfile = QStandardPaths::locate(QStandardPaths::GenericDataLocation, QStringLiteral("kf5/kabc/countrytransl.map"));
+
+ QFile file(mapfile);
+ if (file.open(QIODevice::ReadOnly)) {
+ QTextStream s(&file);
+ QString searchStr = QLatin1Char('\t') + ISOname.simplified().toLower();
+ QString strbuf = s.readLine();
+ int pos;
+ while (!strbuf.isEmpty()) {
+ if ((pos = strbuf.indexOf(searchStr)) != -1) {
+ file.close();
+ return i18n(strbuf.left(pos).toUtf8().constData());
+ }
+ strbuf = s.readLine();
+ }
+ file.close();
+ }
+
+ return ISOname;
+}
+
+QDataStream &KContacts::operator<<(QDataStream &s, const Address &addr)
+{
+ return s << addr.d->mId << (uint)addr.d->mType << addr.d->mPostOfficeBox
+ << addr.d->mExtended << addr.d->mStreet << addr.d->mLocality
+ << addr.d->mRegion << addr.d->mPostalCode << addr.d->mCountry
+ << addr.d->mLabel << addr.d->mEmpty;
+}
+
+QDataStream &KContacts::operator>>(QDataStream &s, Address &addr)
+{
+ uint type;
+ s >> addr.d->mId >> type >> addr.d->mPostOfficeBox >> addr.d->mExtended
+ >> addr.d->mStreet >> addr.d->mLocality >> addr.d->mRegion
+ >> addr.d->mPostalCode >> addr.d->mCountry >> addr.d->mLabel
+ >> addr.d->mEmpty;
+
+ addr.d->mType = Address::Type(type);
+
+ return s;
+}
--- /dev/null
+/*
+ This file is part of the KContacts framework.
+ Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KCONTACTS_ADDRESS_H
+#define KCONTACTS_ADDRESS_H
+
+#include <QtCore/QSharedDataPointer>
+#include <QtCore/QString>
+#include <QtCore/QVector>
+
+#include "kcontacts_export.h"
+
+namespace KContacts
+{
+
+/**
+ @brief
+ Postal address information.
+
+ This class represents information about a postal address.
+*/
+class KCONTACTS_EXPORT Address
+{
+ friend KCONTACTS_EXPORT QDataStream &operator<<(QDataStream &s, const Address &addr);
+ friend KCONTACTS_EXPORT QDataStream &operator>>(QDataStream &s, Address &addr);
+
+public:
+ /**
+ List of addresses.
+ */
+ typedef QVector<Address> List;
+
+ /**
+ Address types:
+ */
+ enum TypeFlag {
+ Dom = 1, /**< domestic */
+ Intl = 2, /**< international */
+ Postal = 4, /**< postal */
+ Parcel = 8, /**< parcel */
+ Home = 16, /**< home address */
+ Work = 32, /**< address at work */
+ Pref = 64 /**< preferred address */
+ };
+
+ Q_DECLARE_FLAGS(Type, TypeFlag)
+
+ /**
+ List of address types.
+ */
+ typedef QList<TypeFlag> TypeList;
+
+ /**
+ Creates an empty address.
+ */
+ Address();
+
+ /**
+ Creates an address of the given @p type.
+ */
+ Address(Type type);
+
+ /**
+ Copy constructor.
+ */
+ Address(const Address &address);
+
+ /**
+ Destroys the address.
+ */
+ ~Address();
+
+ /**
+ Equality operator.
+
+ @param addr the address to compare to
+ @return @c true if @c this and @p addr are equal, otherwise @c false
+ */
+ bool operator==(const Address &other) const;
+
+ /**
+ Not-equal operator.
+
+ @param addr the address to compare to
+ @return @c true if @c this and @p addr are not equal, otherwise @c false
+ */
+ bool operator!=(const Address &other) const;
+
+ /**
+ Assignment operator.
+
+ @param addr the address data to assign to @c this
+ @return a reference to @c this
+ */
+ Address &operator=(const Address &other);
+
+ /**
+ Returns true, if the address is empty.
+ */
+ bool isEmpty() const;
+
+ /**
+ Clears all entries of the address.
+ */
+ void clear();
+
+ /**
+ Sets the unique @p identifier.
+ */
+ void setId(const QString &identifier);
+
+ /**
+ Returns the unique identifier.
+ */
+ QString id() const;
+
+ /**
+ Sets the type of address. See enum for definiton of types.
+
+ @param type type, can be a bitwise or of multiple types.
+ */
+ void setType(Type type);
+
+ /**
+ Returns the type of address. Can be a bitwise or of multiple types.
+ */
+ Type type() const;
+
+ /**
+ Returns a translated string of all types the address has.
+ */
+ QString typeLabel() const;
+
+ /**
+ Sets the post office box.
+ */
+ void setPostOfficeBox(const QString &postOfficeBox);
+
+ /**
+ Returns the post office box.
+ */
+ QString postOfficeBox() const;
+
+ /**
+ Returns the translated label for post office box field.
+ */
+ static QString postOfficeBoxLabel();
+
+ /**
+ Sets the @p extended address information.
+ */
+ void setExtended(const QString &extended);
+
+ /**
+ Returns the extended address information.
+ */
+ QString extended() const;
+
+ /**
+ Returns the translated label for extended field.
+ */
+ static QString extendedLabel();
+
+ /**
+ Sets the @p street (including house number).
+ */
+ void setStreet(const QString &street);
+
+ /**
+ Returns the street.
+ */
+ QString street() const;
+
+ /**
+ Returns the translated label for street field.
+ */
+ static QString streetLabel();
+
+ /**
+ Sets the @p locality, e.g. city.
+
+ @param locality the locality of the address, e.g. city
+ */
+ void setLocality(const QString &locality);
+
+ /**
+ Returns the locality.
+ */
+ QString locality() const;
+
+ /**
+ Returns the translated label for locality field.
+ */
+ static QString localityLabel();
+
+ /**
+ Sets the @p region, e.g. state.
+
+ @param region the region the address falls into, e.g. state
+ */
+ void setRegion(const QString ®ion);
+
+ /**
+ Returns the region.
+ */
+ QString region() const;
+
+ /**
+ Returns the translated label for region field.
+ */
+ static QString regionLabel();
+
+ /**
+ Sets the postal @p code.
+ */
+ void setPostalCode(const QString &code);
+
+ /**
+ Returns the postal code.
+ */
+ QString postalCode() const;
+
+ /**
+ Returns the translated label for postal code field.
+ */
+ static QString postalCodeLabel();
+
+ /**
+ Sets the @p country.
+ */
+ void setCountry(const QString &country);
+
+ /**
+ Returns the country.
+ */
+ QString country() const;
+
+ /**
+ Returns the translated label for country field.
+ */
+ static QString countryLabel();
+
+ /**
+ Sets the delivery @p label. This is the literal text to be used as label.
+
+ @param label the string to use for delivery labels
+ */
+ void setLabel(const QString &label);
+
+ /**
+ Returns the delivery label.
+ */
+ QString label() const;
+
+ /**
+ Returns the translated label for delivery label field.
+ */
+ static QString labelLabel();
+
+ /**
+ Returns the list of available types.
+ */
+ static TypeList typeList();
+
+ /**
+ Returns the translated label for the given @p type.
+ */
+ static QString typeLabel(Type type);
+
+ /**
+ Returns a string representation of the address.
+ */
+ QString toString() const;
+
+ /**
+ Returns this address formatted according to the country-specific
+ address formatting rules. The formatting rules applied depend on
+ either the addresses {@link #country country} field, or (if the
+ latter is empty) on the system country setting. If companyName is
+ provided, an available business address format will be preferred.
+
+ @param realName the formatted name of the contact
+ @param orgaName the name of the organization or company
+ @return the formatted address (containing newline characters)
+ */
+ QString formattedAddress(const QString &realName = QString(),
+ const QString &orgaName = QString()) const;
+
+ /**
+ Returns ISO code for a localized country name. Only localized country
+ names will be understood. This might be replaced by a KLocale method in
+ the future.
+ @param cname name of the country
+ @return two digit ISO code
+ */
+ static QString countryToISO(const QString &cname);
+
+ /**
+ Returns a localized country name for a ISO code.
+ This might be replaced by a KLocale method in the future.
+ @param ISOname two digit ISO code
+ @return localized name of the country
+ */
+ static QString ISOtoCountry(const QString &ISOname);
+
+ static QString typeFlagLabel(TypeFlag type);
+private:
+ class Private;
+ QSharedDataPointer<Private> d;
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(Address::Type)
+
+/**
+ Serializes the @p address object into the @p stream.
+*/
+KCONTACTS_EXPORT QDataStream &operator<<(QDataStream &stream, const Address &address);
+
+/**
+ Initializes the @p address object from the @p stream.
+*/
+KCONTACTS_EXPORT QDataStream &operator>>(QDataStream &stream, Address &address);
+
+}
+
+#endif
--- /dev/null
+/*
+ This file is part of the KContacts framework.
+ Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org>
+ Copyright (c) 2003 Carsten Pfeiffer <pfeiffer@kde.org>
+ Copyright (c) 2005 Ingo Kloecker <kloecker@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <QtCore/QList>
+#include <QtCore/QRegExp>
+#include <QtCore/QSharedData>
+#include <QtCore/QUuid>
+
+#include "kcontacts_debug.h"
+#include <klocalizedstring.h>
+
+#include "addresseehelper.h"
+#include "field.h"
+#include "sortmode.h"
+
+#include "addressee.h"
+
+using namespace KContacts;
+
+static bool matchBinaryPattern(int value, int pattern);
+
+template <class L>
+static bool listEquals(const QVector<L> &list, const QVector<L> &pattern);
+static bool listEquals(const QStringList &list, const QStringList &pattern);
+
+class Q_DECL_HIDDEN Addressee::Private : public QSharedData
+{
+public:
+ Private()
+ : mUid(QUuid::createUuid().toString().mid(1, 36))
+ , mEmpty(true)
+ , mChanged(false)
+ {
+ //We avoid the curly braces so the string is RFC4122 compliant and can be used as urn
+ }
+
+ Private(const Private &other)
+ : QSharedData(other)
+ {
+ mUid = other.mUid;
+ mName = other.mName;
+ mFormattedName = other.mFormattedName;
+ mFamilyName = other.mFamilyName;
+ mGivenName = other.mGivenName;
+ mAdditionalName = other.mAdditionalName;
+ mPrefix = other.mPrefix;
+ mSuffix = other.mSuffix;
+ mNickName = other.mNickName;
+ mBirthday = other.mBirthday;
+ mMailer = other.mMailer;
+ mTimeZone = other.mTimeZone;
+ mGeo = other.mGeo;
+ mTitle = other.mTitle;
+ mRole = other.mRole;
+ mOrganization = other.mOrganization;
+ mDepartment = other.mDepartment;
+ mNote = other.mNote;
+ mProductId = other.mProductId;
+ mRevision = other.mRevision;
+ mSortString = other.mSortString;
+ mSecrecy = other.mSecrecy;
+ mLogo = other.mLogo;
+ mPhoto = other.mPhoto;
+ mSound = other.mSound;
+
+ mPhoneNumbers = other.mPhoneNumbers;
+ mAddresses = other.mAddresses;
+ mKeys = other.mKeys;
+ mLangs = other.mLangs;
+ mGender = other.mGender;
+ mEmails = other.mEmails;
+ mCategories = other.mCategories;
+ mCustomFields = other.mCustomFields;
+ mCalendarUrl = other.mCalendarUrl;
+ mSoundListExtra = other.mSoundListExtra;
+ mPhotoExtraList = other.mPhotoExtraList;
+ mLogoExtraList = other.mLogoExtraList;
+ mUrlExtraList = other.mUrlExtraList;
+ mMembers = other.mMembers;
+ mRelationShips = other.mRelationShips;
+ mSources = other.mSources;
+ mEmpty = other.mEmpty;
+ mImpps = other.mImpps;
+ mChanged = other.mChanged;
+ }
+
+ ~Private()
+ {
+ }
+
+ QString mUid;
+ QString mName;
+ QString mFormattedName;
+ QString mFamilyName;
+ QString mGivenName;
+ QString mAdditionalName;
+ QString mPrefix;
+ QString mSuffix;
+ QString mNickName;
+ QDateTime mBirthday;
+ QString mMailer;
+ TimeZone mTimeZone;
+ Geo mGeo;
+ QString mTitle;
+ QString mRole;
+ QString mOrganization;
+ QString mDepartment;
+ QString mNote;
+ QString mProductId;
+ QDateTime mRevision;
+ QString mSortString;
+ Secrecy mSecrecy;
+ Picture mLogo;
+ Picture mPhoto;
+ Sound mSound;
+
+ PhoneNumber::List mPhoneNumbers;
+ Address::List mAddresses;
+ Key::List mKeys;
+ Email::List mEmails;
+ Lang::List mLangs;
+ Impp::List mImpps;
+ Gender mGender;
+ QString mKind;
+ QStringList mCategories;
+ QHash<QString, QString> mCustomFields;
+ CalendarUrl::List mCalendarUrl;
+ Sound::List mSoundListExtra;
+ Picture::List mPhotoExtraList;
+ Picture::List mLogoExtraList;
+ ResourceLocatorUrl::List mUrlExtraList;
+ QVector<QUrl> mSources;
+ QStringList mMembers;
+ Related::List mRelationShips;
+ bool mEmpty : 1;
+ bool mChanged : 1;
+
+ static KContacts::SortMode *mSortMode;
+};
+
+KContacts::SortMode *Addressee::Private::mSortMode = Q_NULLPTR;
+
+Addressee::Addressee()
+ : d(new Private)
+{
+}
+
+Addressee::~Addressee()
+{
+}
+
+Addressee::Addressee(const Addressee &other)
+ : d(other.d)
+{
+}
+
+Addressee &Addressee::operator=(const Addressee &other)
+{
+ if (this != &other) {
+ d = other.d;
+ }
+
+ return *this;
+}
+
+bool Addressee::operator==(const Addressee &addressee) const
+{
+ if (d->mUid != addressee.d->mUid) {
+ qCDebug(KCONTACTS_LOG) << "uid differs";
+ return false;
+ }
+
+ if (d->mName != addressee.d->mName &&
+ !(d->mName.isEmpty() && addressee.d->mName.isEmpty())) {
+ qCDebug(KCONTACTS_LOG) << "name differs";
+ return false;
+ }
+
+ if (d->mFormattedName != addressee.d->mFormattedName &&
+ !(d->mFormattedName.isEmpty() && addressee.d->mFormattedName.isEmpty())) {
+ qCDebug(KCONTACTS_LOG) << "formattedName differs";
+ return false;
+ }
+
+ if (d->mFamilyName != addressee.d->mFamilyName &&
+ !(d->mFamilyName.isEmpty() && addressee.d->mFamilyName.isEmpty())) {
+ qCDebug(KCONTACTS_LOG) << "familyName differs";
+ return false;
+ }
+
+ if (d->mGivenName != addressee.d->mGivenName &&
+ !(d->mGivenName.isEmpty() && addressee.d->mGivenName.isEmpty())) {
+ qCDebug(KCONTACTS_LOG) << "givenName differs";
+ return false;
+ }
+
+ if (d->mAdditionalName != addressee.d->mAdditionalName &&
+ !(d->mAdditionalName.isEmpty() && addressee.d->mAdditionalName.isEmpty())) {
+ qCDebug(KCONTACTS_LOG) << "additionalName differs";
+ return false;
+ }
+
+ if (d->mPrefix != addressee.d->mPrefix &&
+ !(d->mPrefix.isEmpty() && addressee.d->mPrefix.isEmpty())) {
+ qCDebug(KCONTACTS_LOG) << "prefix differs";
+ return false;
+ }
+
+ if (d->mSuffix != addressee.d->mSuffix &&
+ !(d->mSuffix.isEmpty() && addressee.d->mSuffix.isEmpty())) {
+ qCDebug(KCONTACTS_LOG) << "suffix differs";
+ return false;
+ }
+
+ if (d->mNickName != addressee.d->mNickName &&
+ !(d->mNickName.isEmpty() && addressee.d->mNickName.isEmpty())) {
+ qCDebug(KCONTACTS_LOG) << "nickName differs";
+ return false;
+ }
+
+ if (d->mBirthday != addressee.d->mBirthday) {
+ qCDebug(KCONTACTS_LOG) << "birthday differs";
+ return false;
+ }
+
+ if (d->mMailer != addressee.d->mMailer &&
+ !(d->mMailer.isEmpty() && addressee.d->mMailer.isEmpty())) {
+ qCDebug(KCONTACTS_LOG) << "mailer differs";
+ return false;
+ }
+
+ if (d->mTimeZone != addressee.d->mTimeZone) {
+ qCDebug(KCONTACTS_LOG) << "timeZone differs";
+ return false;
+ }
+
+ if (d->mGeo != addressee.d->mGeo) {
+ qCDebug(KCONTACTS_LOG) << "geo differs";
+ return false;
+ }
+
+ if (d->mTitle != addressee.d->mTitle &&
+ !(d->mTitle.isEmpty() && addressee.d->mTitle.isEmpty())) {
+ qCDebug(KCONTACTS_LOG) << "title differs";
+ return false;
+ }
+
+ if (d->mRole != addressee.d->mRole &&
+ !(d->mRole.isEmpty() && addressee.d->mRole.isEmpty())) {
+ qCDebug(KCONTACTS_LOG) << "role differs";
+ return false;
+ }
+
+ if (d->mOrganization != addressee.d->mOrganization &&
+ !(d->mOrganization.isEmpty() && addressee.d->mOrganization.isEmpty())) {
+ qCDebug(KCONTACTS_LOG) << "organization differs";
+ return false;
+ }
+
+ if (d->mDepartment != addressee.d->mDepartment &&
+ !(d->mDepartment.isEmpty() && addressee.d->mDepartment.isEmpty())) {
+ qCDebug(KCONTACTS_LOG) << "department differs";
+ return false;
+ }
+
+ if (d->mNote != addressee.d->mNote &&
+ !(d->mNote.isEmpty() && addressee.d->mNote.isEmpty())) {
+ qCDebug(KCONTACTS_LOG) << "note differs";
+ return false;
+ }
+
+ if (d->mProductId != addressee.d->mProductId &&
+ !(d->mProductId.isEmpty() && addressee.d->mProductId.isEmpty())) {
+ qCDebug(KCONTACTS_LOG) << "productId differs";
+ return false;
+ }
+
+ if (d->mSortString != addressee.d->mSortString &&
+ !(d->mSortString.isEmpty() && addressee.d->mSortString.isEmpty())) {
+ qCDebug(KCONTACTS_LOG) << "sortString differs";
+ return false;
+ }
+
+ if (d->mSecrecy != addressee.d->mSecrecy) {
+ qCDebug(KCONTACTS_LOG) << "secrecy differs";
+ return false;
+ }
+
+ if (d->mLogo != addressee.d->mLogo) {
+ qCDebug(KCONTACTS_LOG) << "logo differs";
+ return false;
+ }
+
+ if (d->mPhoto != addressee.d->mPhoto) {
+ qCDebug(KCONTACTS_LOG) << "photo differs";
+ return false;
+ }
+
+ if (d->mSound != addressee.d->mSound) {
+ qCDebug(KCONTACTS_LOG) << "sound differs";
+ return false;
+ }
+
+ if (!listEquals(d->mPhoneNumbers, addressee.d->mPhoneNumbers)) {
+ qCDebug(KCONTACTS_LOG) << "phoneNumbers differs";
+ return false;
+ }
+
+ if (!listEquals(d->mAddresses, addressee.d->mAddresses)) {
+ qCDebug(KCONTACTS_LOG) << "addresses differs";
+ return false;
+ }
+
+ if (!listEquals(d->mKeys, addressee.d->mKeys)) {
+ qCDebug(KCONTACTS_LOG) << "keys differs";
+ return false;
+ }
+ if (!listEquals(d->mEmails, addressee.d->mEmails)) {
+ qCDebug(KCONTACTS_LOG) << "emails differs";
+ return false;
+ }
+
+ if (!listEquals(d->mCategories, addressee.d->mCategories)) {
+ qCDebug(KCONTACTS_LOG) << "categories differs";
+ return false;
+ }
+
+ if (d->mCustomFields != addressee.d->mCustomFields) {
+ qCDebug(KCONTACTS_LOG) << "custom differs";
+ return false;
+ }
+ if (d->mLangs != addressee.d->mLangs) {
+ qCDebug(KCONTACTS_LOG) << "langs differs";
+ return false;
+ }
+ if (d->mImpps != addressee.d->mImpps) {
+ qCDebug(KCONTACTS_LOG) << "impps differs";
+ return false;
+ }
+ if (d->mGender != addressee.d->mGender) {
+ qCDebug(KCONTACTS_LOG) << "gender differs";
+ return false;
+ }
+ if (d->mKind != addressee.d->mKind) {
+ qCDebug(KCONTACTS_LOG) << "kind differs";
+ return false;
+ }
+ if (!listEquals(d->mCalendarUrl, addressee.d->mCalendarUrl)) {
+ qCDebug(KCONTACTS_LOG) << "calendarUrl differs";
+ return false;
+ }
+ if (!listEquals(d->mSoundListExtra, addressee.d->mSoundListExtra)) {
+ qCDebug(KCONTACTS_LOG) << "Extra sound differs";
+ return false;
+ }
+ if (!listEquals(d->mPhotoExtraList, addressee.d->mPhotoExtraList)) {
+ qCDebug(KCONTACTS_LOG) << "Extra photo differs";
+ return false;
+ }
+ if (!listEquals(d->mLogoExtraList, addressee.d->mLogoExtraList)) {
+ qCDebug(KCONTACTS_LOG) << "Extra logo differs";
+ return false;
+ }
+ if (!listEquals(d->mUrlExtraList, addressee.d->mUrlExtraList)) {
+ qCDebug(KCONTACTS_LOG) << "Extra url differs";
+ return false;
+ }
+ if (!listEquals(d->mMembers, addressee.d->mMembers)) {
+ qCDebug(KCONTACTS_LOG) << "Extra url differs";
+ return false;
+ }
+ if (!listEquals(d->mRelationShips, addressee.d->mRelationShips)) {
+ qCDebug(KCONTACTS_LOG) << "RelationShips differs";
+ return false;
+ }
+ if (!listEquals(d->mSources, addressee.d->mSources)) {
+ qCDebug(KCONTACTS_LOG) << "Sources differs";
+ return false;
+ }
+
+ return true;
+}
+
+bool Addressee::operator!=(const Addressee &a) const
+{
+ return !(a == *this);
+}
+
+bool Addressee::isEmpty() const
+{
+ return d->mEmpty;
+}
+
+void Addressee::setUid(const QString &id)
+{
+ if (id == d->mUid) {
+ return;
+ }
+
+ d->mEmpty = false;
+ d->mUid = id;
+}
+
+QString Addressee::uid() const
+{
+ return d->mUid;
+}
+
+QString Addressee::uidLabel()
+{
+ return i18n("Unique Identifier");
+}
+
+void Addressee::setName(const QString &name)
+{
+ if (name == d->mName) {
+ return;
+ }
+
+ d->mEmpty = false;
+ d->mName = name;
+}
+
+QString Addressee::name() const
+{
+ return d->mName;
+}
+
+QString Addressee::nameLabel()
+{
+ return i18n("Name");
+}
+
+void Addressee::setKind(const QString &kind)
+{
+ if (kind == d->mKind) {
+ return;
+ }
+
+ d->mEmpty = false;
+ d->mKind = kind;
+}
+
+QString Addressee::kind() const
+{
+ return d->mKind;
+}
+
+void Addressee::insertExtraSound(const Sound &sound)
+{
+ d->mEmpty = false;
+ d->mSoundListExtra.append(sound);
+}
+
+Sound::List Addressee::extraSoundList() const
+{
+ return d->mSoundListExtra;
+}
+
+void Addressee::insertExtraPhoto(const Picture &picture)
+{
+ d->mEmpty = false;
+ d->mPhotoExtraList.append(picture);
+}
+
+Picture::List Addressee::extraPhotoList() const
+{
+ return d->mPhotoExtraList;
+}
+
+void Addressee::insertExtraLogo(const Picture &logo)
+{
+ d->mEmpty = false;
+ d->mLogoExtraList.append(logo);
+}
+
+Picture::List Addressee::extraLogoList() const
+{
+ return d->mLogoExtraList;
+}
+
+void Addressee::setExtraSoundList(const Sound::List &soundList)
+{
+ d->mEmpty = false;
+ d->mSoundListExtra = soundList;
+}
+
+void Addressee::setExtraPhotoList(const Picture::List &pictureList)
+{
+ d->mEmpty = false;
+ d->mPhotoExtraList = pictureList;
+}
+
+void Addressee::setExtraLogoList(const Picture::List &logoList)
+{
+ d->mEmpty = false;
+ d->mLogoExtraList = logoList;
+}
+
+void Addressee::insertExtraUrl(const ResourceLocatorUrl &url)
+{
+ if (url.isValid()) {
+ d->mEmpty = false;
+ d->mUrlExtraList.append(url);
+ }
+}
+
+void Addressee::setExtraUrlList(const ResourceLocatorUrl::List &urlList)
+{
+ d->mEmpty = false;
+ d->mUrlExtraList = urlList;
+}
+
+ResourceLocatorUrl::List Addressee::extraUrlList() const
+{
+ return d->mUrlExtraList;
+}
+
+void Addressee::insertSourceUrl(const QUrl &url)
+{
+ d->mEmpty = false;
+ d->mSources.append(url);
+}
+
+void Addressee::setSourcesUrlList(const QVector<QUrl> &urlList)
+{
+ d->mEmpty = false;
+ d->mSources = urlList;
+}
+
+QVector<QUrl> Addressee::sourcesUrlList() const
+{
+ return d->mSources;
+}
+
+void Addressee::insertImpp(const Impp &impp)
+{
+ if (impp.isValid()) {
+ d->mEmpty = false;
+ //Don't duplicate ?
+ d->mImpps.append(impp);
+ }
+}
+
+void Addressee::setImppList(const Impp::List &imppList)
+{
+ d->mEmpty = false;
+ d->mImpps = imppList;
+}
+
+Impp::List Addressee::imppList() const
+{
+ return d->mImpps;
+}
+
+void Addressee::insertCalendarUrl(const CalendarUrl &calendarUrl)
+{
+ d->mEmpty = false;
+ //TODO verify that there is not same calendarurl
+ if (calendarUrl.isValid()) {
+ d->mCalendarUrl.append(calendarUrl);
+ }
+}
+
+CalendarUrl::List Addressee::calendarUrlList() const
+{
+ return d->mCalendarUrl;
+}
+
+void Addressee::setFormattedName(const QString &formattedName)
+{
+ if (formattedName == d->mFormattedName) {
+ return;
+ }
+
+ d->mEmpty = false;
+ d->mFormattedName = formattedName;
+}
+
+QString Addressee::formattedName() const
+{
+ return d->mFormattedName;
+}
+
+QString Addressee::formattedNameLabel()
+{
+ return i18n("Formatted Name");
+}
+
+void Addressee::setFamilyName(const QString &familyName)
+{
+ if (familyName == d->mFamilyName) {
+ return;
+ }
+
+ d->mEmpty = false;
+ d->mFamilyName = familyName;
+}
+
+QString Addressee::familyName() const
+{
+ return d->mFamilyName;
+}
+
+QString Addressee::familyNameLabel()
+{
+ return i18n("Family Name");
+}
+
+void Addressee::setGivenName(const QString &givenName)
+{
+ if (givenName == d->mGivenName) {
+ return;
+ }
+
+ d->mEmpty = false;
+ d->mGivenName = givenName;
+}
+
+QString Addressee::givenName() const
+{
+ return d->mGivenName;
+}
+
+QString Addressee::givenNameLabel()
+{
+ return i18n("Given Name");
+}
+
+void Addressee::setAdditionalName(const QString &additionalName)
+{
+ if (additionalName == d->mAdditionalName) {
+ return;
+ }
+
+ d->mEmpty = false;
+ d->mAdditionalName = additionalName;
+}
+
+QString Addressee::additionalName() const
+{
+ return d->mAdditionalName;
+}
+
+QString Addressee::additionalNameLabel()
+{
+ return i18n("Additional Names");
+}
+
+void Addressee::setPrefix(const QString &prefix)
+{
+ if (prefix == d->mPrefix) {
+ return;
+ }
+
+ d->mEmpty = false;
+ d->mPrefix = prefix;
+}
+
+QString Addressee::prefix() const
+{
+ return d->mPrefix;
+}
+
+QString Addressee::prefixLabel()
+{
+ return i18n("Honorific Prefixes");
+}
+
+void Addressee::setSuffix(const QString &suffix)
+{
+ if (suffix == d->mSuffix) {
+ return;
+ }
+
+ d->mEmpty = false;
+ d->mSuffix = suffix;
+}
+
+QString Addressee::suffix() const
+{
+ return d->mSuffix;
+}
+
+QString Addressee::suffixLabel()
+{
+ return i18n("Honorific Suffixes");
+}
+
+void Addressee::setNickName(const QString &nickName)
+{
+ if (nickName == d->mNickName) {
+ return;
+ }
+
+ d->mEmpty = false;
+ d->mNickName = nickName;
+}
+
+QString Addressee::nickName() const
+{
+ return d->mNickName;
+}
+
+QString Addressee::nickNameLabel()
+{
+ return i18n("Nick Name");
+}
+
+void Addressee::setBirthday(const QDateTime &birthday)
+{
+ if (birthday == d->mBirthday) {
+ return;
+ }
+
+ d->mEmpty = false;
+ d->mBirthday = birthday;
+}
+
+QDateTime Addressee::birthday() const
+{
+ return d->mBirthday;
+}
+
+QString Addressee::birthdayLabel()
+{
+ return i18n("Birthday");
+}
+
+QString Addressee::homeAddressStreetLabel()
+{
+ return i18n("Home Address Street");
+}
+
+QString Addressee::homeAddressPostOfficeBoxLabel()
+{
+ return i18n("Home Address Post Office Box");
+}
+
+QString Addressee::homeAddressLocalityLabel()
+{
+ return i18n("Home Address City");
+}
+
+QString Addressee::homeAddressRegionLabel()
+{
+ return i18n("Home Address State");
+}
+
+QString Addressee::homeAddressPostalCodeLabel()
+{
+ return i18n("Home Address Zip Code");
+}
+
+QString Addressee::homeAddressCountryLabel()
+{
+ return i18n("Home Address Country");
+}
+
+QString Addressee::homeAddressLabelLabel()
+{
+ return i18n("Home Address Label");
+}
+
+QString Addressee::businessAddressStreetLabel()
+{
+ return i18n("Business Address Street");
+}
+
+QString Addressee::businessAddressPostOfficeBoxLabel()
+{
+ return i18n("Business Address Post Office Box");
+}
+
+QString Addressee::businessAddressLocalityLabel()
+{
+ return i18n("Business Address City");
+}
+
+QString Addressee::businessAddressRegionLabel()
+{
+ return i18n("Business Address State");
+}
+
+QString Addressee::businessAddressPostalCodeLabel()
+{
+ return i18n("Business Address Zip Code");
+}
+
+QString Addressee::businessAddressCountryLabel()
+{
+ return i18n("Business Address Country");
+}
+
+QString Addressee::businessAddressLabelLabel()
+{
+ return i18n("Business Address Label");
+}
+
+QString Addressee::homePhoneLabel()
+{
+ return i18n("Home Phone");
+}
+
+QString Addressee::businessPhoneLabel()
+{
+ return i18n("Business Phone");
+}
+
+QString Addressee::mobilePhoneLabel()
+{
+ return i18n("Mobile Phone");
+}
+
+QString Addressee::homeFaxLabel()
+{
+ return i18n("Home Fax");
+}
+
+QString Addressee::businessFaxLabel()
+{
+ return i18n("Business Fax");
+}
+
+QString Addressee::carPhoneLabel()
+{
+ return i18n("Car Phone");
+}
+
+QString Addressee::isdnLabel()
+{
+ return i18n("ISDN");
+}
+
+QString Addressee::pagerLabel()
+{
+ return i18n("Pager");
+}
+
+QString Addressee::emailLabel()
+{
+ return i18n("Email Address");
+}
+
+void Addressee::setMailer(const QString &mailer)
+{
+ if (mailer == d->mMailer) {
+ return;
+ }
+
+ d->mEmpty = false;
+ d->mMailer = mailer;
+}
+
+QString Addressee::mailer() const
+{
+ return d->mMailer;
+}
+
+QString Addressee::mailerLabel()
+{
+ return i18n("Mail Client");
+}
+
+void Addressee::setTimeZone(const TimeZone &timeZone)
+{
+ if (timeZone == d->mTimeZone) {
+ return;
+ }
+
+ d->mEmpty = false;
+ d->mTimeZone = timeZone;
+}
+
+TimeZone Addressee::timeZone() const
+{
+ return d->mTimeZone;
+}
+
+QString Addressee::timeZoneLabel()
+{
+ return i18n("Time Zone");
+}
+
+void Addressee::setGeo(const Geo &geo)
+{
+ if (geo == d->mGeo) {
+ return;
+ }
+
+ d->mEmpty = false;
+ d->mGeo = geo;
+}
+
+Geo Addressee::geo() const
+{
+ return d->mGeo;
+}
+
+QString Addressee::geoLabel()
+{
+ return i18n("Geographic Position");
+}
+
+void Addressee::setTitle(const QString &title)
+{
+ if (title == d->mTitle) {
+ return;
+ }
+
+ d->mEmpty = false;
+ d->mTitle = title;
+}
+
+QString Addressee::title() const
+{
+ return d->mTitle;
+}
+
+QString Addressee::titleLabel()
+{
+ return i18nc("a person's title", "Title");
+}
+
+void Addressee::setRole(const QString &role)
+{
+ if (role == d->mRole) {
+ return;
+ }
+
+ d->mEmpty = false;
+ d->mRole = role;
+}
+
+QString Addressee::role() const
+{
+ return d->mRole;
+}
+
+QString Addressee::roleLabel()
+{
+ return i18nc("of a person in an organization", "Role");
+}
+
+void Addressee::setOrganization(const QString &organization)
+{
+ if (organization == d->mOrganization) {
+ return;
+ }
+
+ d->mEmpty = false;
+ d->mOrganization = organization;
+}
+
+QString Addressee::organization() const
+{
+ return d->mOrganization;
+}
+
+QString Addressee::organizationLabel()
+{
+ return i18n("Organization");
+}
+
+void Addressee::setDepartment(const QString &department)
+{
+ if (department == d->mDepartment) {
+ return;
+ }
+
+ d->mEmpty = false;
+ d->mDepartment = department;
+}
+
+QString Addressee::department() const
+{
+ return d->mDepartment;
+}
+
+QString Addressee::departmentLabel()
+{
+ return i18n("Department");
+}
+
+void Addressee::setNote(const QString ¬e)
+{
+ if (note == d->mNote) {
+ return;
+ }
+
+ d->mEmpty = false;
+ d->mNote = note;
+}
+
+QString Addressee::note() const
+{
+ return d->mNote;
+}
+
+QString Addressee::noteLabel()
+{
+ return i18n("Note");
+}
+
+void Addressee::setProductId(const QString &productId)
+{
+ if (productId == d->mProductId) {
+ return;
+ }
+
+ d->mEmpty = false;
+ d->mProductId = productId;
+}
+
+QString Addressee::productId() const
+{
+ return d->mProductId;
+}
+
+QString Addressee::productIdLabel()
+{
+ return i18n("Product Identifier");
+}
+
+void Addressee::setRevision(const QDateTime &revision)
+{
+ if (revision == d->mRevision) {
+ return;
+ }
+
+ d->mEmpty = false;
+ d->mRevision = revision;
+}
+
+QDateTime Addressee::revision() const
+{
+ return d->mRevision;
+}
+
+QString Addressee::revisionLabel()
+{
+ return i18n("Revision Date");
+}
+
+void Addressee::setSortString(const QString &sortString)
+{
+ if (sortString == d->mSortString) {
+ return;
+ }
+
+ d->mEmpty = false;
+ d->mSortString = sortString;
+}
+
+QString Addressee::sortString() const
+{
+ return d->mSortString;
+}
+
+QString Addressee::sortStringLabel()
+{
+ return i18n("Sort String");
+}
+
+void Addressee::setUrl(const QUrl &url)
+{
+ KContacts::ResourceLocatorUrl resourceLocator;
+ resourceLocator.setUrl(url);
+ insertExtraUrl(resourceLocator);
+}
+
+void Addressee::setUrl(const ResourceLocatorUrl &url)
+{
+ insertExtraUrl(url);
+}
+
+ResourceLocatorUrl Addressee::url() const
+{
+ if (d->mUrlExtraList.isEmpty()) {
+ return ResourceLocatorUrl();
+ } else {
+ return d->mUrlExtraList.at(0);
+ }
+}
+
+QString Addressee::urlLabel()
+{
+ return i18n("Homepage");
+}
+
+void Addressee::setSecrecy(const Secrecy &secrecy)
+{
+ if (secrecy == d->mSecrecy) {
+ return;
+ }
+
+ d->mEmpty = false;
+ d->mSecrecy = secrecy;
+}
+
+Secrecy Addressee::secrecy() const
+{
+ return d->mSecrecy;
+}
+
+QString Addressee::secrecyLabel()
+{
+ return i18n("Security Class");
+}
+
+void Addressee::setLogo(const Picture &logo)
+{
+ if (logo == d->mLogo) {
+ return;
+ }
+
+ d->mEmpty = false;
+ d->mLogo = logo;
+}
+
+Picture Addressee::logo() const
+{
+ return d->mLogo;
+}
+
+QString Addressee::logoLabel()
+{
+ return i18n("Logo");
+}
+
+void Addressee::setPhoto(const Picture &photo)
+{
+ if (photo == d->mPhoto) {
+ return;
+ }
+
+ d->mEmpty = false;
+ d->mPhoto = photo;
+}
+
+Picture Addressee::photo() const
+{
+ return d->mPhoto;
+}
+
+QString Addressee::photoLabel()
+{
+ return i18n("Photo");
+}
+
+void Addressee::setSound(const Sound &sound)
+{
+ if (sound == d->mSound) {
+ return;
+ }
+
+ d->mEmpty = false;
+ d->mSound = sound;
+}
+
+Sound Addressee::sound() const
+{
+ return d->mSound;
+}
+
+QString Addressee::soundLabel()
+{
+ return i18n("Sound");
+}
+
+void Addressee::setNameFromString(const QString &s)
+{
+ QString str = s;
+ //remove enclosing quotes from string
+ if (str.length() > 1 &&
+ s[0] == QLatin1Char('"') &&
+ s[s.length() - 1] == QLatin1Char('"')) {
+ str = s.mid(1, s.length() - 2);
+ }
+
+ setFormattedName(str);
+ setName(str);
+
+ // clear all name parts
+ setPrefix(QString());
+ setGivenName(QString());
+ setAdditionalName(QString());
+ setFamilyName(QString());
+ setSuffix(QString());
+
+ if (str.isEmpty()) {
+ return;
+ }
+
+ static QString spaceStr = QStringLiteral(" ");
+ static QString emptyStr = QStringLiteral("");
+ AddresseeHelper *helper = AddresseeHelper::self();
+
+ int i = str.indexOf(QLatin1Char(','));
+ if (i < 0) {
+ QStringList parts = str.split(spaceStr);
+ int leftOffset = 0;
+ int rightOffset = parts.count() - 1;
+
+ QString suffix;
+ while (rightOffset >= 0) {
+ if (helper->containsSuffix(parts[rightOffset])) {
+ suffix.prepend(parts[rightOffset] + (suffix.isEmpty() ? emptyStr : spaceStr));
+ rightOffset--;
+ } else {
+ break;
+ }
+ }
+ setSuffix(suffix);
+
+ if (rightOffset < 0) {
+ return;
+ }
+
+ if (rightOffset - 1 >= 0 && helper->containsPrefix(parts[rightOffset - 1].toLower())) {
+ setFamilyName(parts[rightOffset - 1] + spaceStr + parts[rightOffset]);
+ rightOffset--;
+ } else {
+ if (helper->tradeAsFamilyName()) {
+ setFamilyName(parts[rightOffset]);
+ } else {
+ setGivenName(parts[rightOffset]);
+ }
+ }
+
+ QString prefix;
+ while (leftOffset < rightOffset) {
+ if (helper->containsTitle(parts[leftOffset])) {
+ prefix.append((prefix.isEmpty() ? emptyStr : spaceStr) + parts[leftOffset]);
+ leftOffset++;
+ } else {
+ break;
+ }
+ }
+ setPrefix(prefix);
+
+ if (leftOffset < rightOffset) {
+ setGivenName(parts[leftOffset]);
+ leftOffset++;
+ }
+
+ QString additionalName;
+ while (leftOffset < rightOffset) {
+ additionalName.append((additionalName.isEmpty() ? emptyStr : spaceStr) + parts[leftOffset]);
+ leftOffset++;
+ }
+ setAdditionalName(additionalName);
+ } else {
+ QString part1 = str.left(i);
+ QString part2 = str.mid(i + 1);
+
+ QStringList parts = part1.split(spaceStr);
+ int leftOffset = 0;
+ int rightOffset = parts.count() - 1;
+
+ if (parts.count() > 0) {
+
+ QString suffix;
+ while (rightOffset >= 0) {
+ if (helper->containsSuffix(parts[rightOffset])) {
+ suffix.prepend(parts[rightOffset] + (suffix.isEmpty() ? emptyStr : spaceStr));
+ rightOffset--;
+ } else {
+ break;
+ }
+ }
+ setSuffix(suffix);
+
+ if (rightOffset - 1 >= 0 && helper->containsPrefix(parts[rightOffset - 1].toLower())) {
+ setFamilyName(parts[rightOffset - 1] + spaceStr + parts[rightOffset]);
+ rightOffset--;
+ } else {
+ setFamilyName(parts[rightOffset]);
+ }
+
+ QString prefix;
+ while (leftOffset < rightOffset) {
+ if (helper->containsTitle(parts[leftOffset])) {
+ prefix.append((prefix.isEmpty() ? emptyStr : spaceStr) + parts[leftOffset]);
+ leftOffset++;
+ } else {
+ break;
+ }
+ }
+ } else {
+ setPrefix(QString());
+ setFamilyName(QString());
+ setSuffix(QString());
+ }
+
+ parts = part2.split(spaceStr);
+
+ leftOffset = 0;
+ rightOffset = parts.count();
+
+ if (parts.count() > 0) {
+
+ QString prefix;
+ while (leftOffset < rightOffset) {
+ if (helper->containsTitle(parts[leftOffset])) {
+ prefix.append((prefix.isEmpty() ? emptyStr : spaceStr) + parts[leftOffset]);
+ leftOffset++;
+ } else {
+ break;
+ }
+ }
+ setPrefix(prefix);
+
+ if (leftOffset < rightOffset) {
+ setGivenName(parts[leftOffset]);
+ leftOffset++;
+ }
+
+ QString additionalName;
+ while (leftOffset < rightOffset) {
+ additionalName.append((additionalName.isEmpty() ? emptyStr : spaceStr) + parts[leftOffset]);
+ leftOffset++;
+ }
+ setAdditionalName(additionalName);
+ } else {
+ setGivenName(QString());
+ setAdditionalName(QString());
+ }
+ }
+}
+
+QString Addressee::realName() const
+{
+ QString n(formattedName());
+ if (!n.isEmpty()) {
+ return n;
+ }
+
+ n = assembledName();
+ if (!n.isEmpty()) {
+ return n;
+ }
+
+ n = name();
+ if (!n.isEmpty()) {
+ return n;
+ }
+
+ return organization();
+}
+
+QString Addressee::assembledName() const
+{
+ const QString name = prefix() + QLatin1Char(' ') +
+ givenName() + QLatin1Char(' ') +
+ additionalName() + QLatin1Char(' ') +
+ familyName() + QLatin1Char(' ') +
+ suffix();
+
+ return name.simplified();
+}
+
+QString Addressee::fullEmail(const QString &email) const
+{
+ QString e;
+ if (email.isNull()) {
+ e = preferredEmail();
+ } else {
+ e = email;
+ }
+ if (e.isEmpty()) {
+ return QString();
+ }
+
+ QString text;
+ if (realName().isEmpty()) {
+ text = e;
+ } else {
+ QRegExp needQuotes(QStringLiteral("[^ 0-9A-Za-z\\x0080-\\xFFFF]"));
+ if (realName().indexOf(needQuotes) != -1) {
+ QString name = realName();
+ name.replace(QLatin1String("\""), QLatin1String("\\\""));
+ text = QLatin1String("\"") + name + QLatin1String("\" <") + e + QLatin1Char('>');
+ } else {
+ text = realName() + QLatin1String(" <") + e + QLatin1Char('>');
+ }
+ }
+
+ return text;
+}
+void Addressee::insertEmail(const QString &email, bool preferred, const QMap<QString, QStringList> ¶m)
+{
+ if (email.simplified().isEmpty()) {
+ return;
+ }
+
+ for (int i = 0; i < d->mEmails.size(); ++i) {
+ if (d->mEmails.at(i).mail() == email) {
+ if (!preferred || i == 0) {
+ return;
+ }
+ Email tempMail = d->mEmails.takeAt(i);
+ d->mEmails.prepend(tempMail);
+ return;
+ }
+ }
+
+ Email mail(email);
+ mail.setParameters(param);
+ d->mEmpty = false;
+ if (preferred) {
+ d->mEmails.prepend(mail);
+ } else {
+ d->mEmails.append(mail);
+ }
+}
+
+void Addressee::removeEmail(const QString &email)
+{
+ for (int i = 0; i < d->mEmails.size(); ++i) {
+ if (d->mEmails.at(i).mail() == email) {
+ d->mEmails.removeAt(i);
+ }
+ }
+}
+
+QString Addressee::preferredEmail() const
+{
+ if (d->mEmails.count() == 0) {
+ return QString();
+ } else {
+ return d->mEmails.first().mail();
+ }
+}
+
+QStringList Addressee::emails() const
+{
+ QStringList list;
+ const int numberOfEmail = d->mEmails.size();
+ list.reserve(numberOfEmail);
+ for (int i = 0; i < numberOfEmail; ++i) {
+ list << d->mEmails.at(i).mail();
+ }
+
+ return list;
+}
+
+Email::List Addressee::emailList() const
+{
+ return d->mEmails;
+}
+
+void Addressee::setEmails(const QStringList &emails)
+{
+ d->mEmails.clear();
+ const int numEmails = emails.size();
+ d->mEmails.reserve(numEmails);
+ for (int i = 0; i < numEmails; ++i) {
+ d->mEmails.append(Email(emails.at(i)));
+ }
+ d->mEmpty = false;
+}
+
+void Addressee::setEmailList(const Email::List &list)
+{
+ d->mEmails = list;
+ d->mEmpty = false;
+}
+
+void Addressee::removeLang(const QString &language)
+{
+ for (int i = 0; i < d->mLangs.size(); ++i) {
+ if (d->mLangs.at(i).language() == language) {
+ d->mLangs.removeAt(i);
+ }
+ }
+}
+
+void Addressee::setLangs(const Lang::List &langs)
+{
+ d->mLangs = langs;
+ d->mEmpty = false;
+}
+
+void Addressee::insertLang(const Lang &language)
+{
+ const QString languageStr = language.language();
+ if (languageStr.simplified().isEmpty()) {
+ return;
+ }
+ d->mEmpty = false;
+
+ Lang::List::Iterator it;
+ Lang::List::Iterator end(d->mLangs.end());
+ for (it = d->mLangs.begin(); it != end; ++it) {
+ if ((*it).language() == languageStr) {
+ (*it).setParameters(language.parameters());
+ return;
+ }
+ }
+ d->mLangs.append(language);
+}
+
+Lang::List Addressee::langs() const
+{
+ return d->mLangs;
+}
+
+void Addressee::setGender(const Gender &gender)
+{
+ if (gender == d->mGender) {
+ return;
+ }
+
+ d->mEmpty = false;
+ d->mGender = gender;
+}
+
+Gender Addressee::gender() const
+{
+ return d->mGender;
+}
+
+void Addressee::insertPhoneNumber(const PhoneNumber &phoneNumber)
+{
+ d->mEmpty = false;
+
+ PhoneNumber::List::Iterator it;
+ for (it = d->mPhoneNumbers.begin(); it != d->mPhoneNumbers.end(); ++it) {
+ if ((*it).id() == phoneNumber.id()) {
+ *it = phoneNumber;
+ return;
+ }
+ }
+ if (!phoneNumber.number().simplified().isEmpty()) {
+ d->mPhoneNumbers.append(phoneNumber);
+ }
+}
+
+void Addressee::removePhoneNumber(const PhoneNumber &phoneNumber)
+{
+ PhoneNumber::List::Iterator it;
+ for (it = d->mPhoneNumbers.begin(); it != d->mPhoneNumbers.end(); ++it) {
+ if ((*it).id() == phoneNumber.id()) {
+ d->mPhoneNumbers.erase(it);
+ return;
+ }
+ }
+}
+
+PhoneNumber Addressee::phoneNumber(PhoneNumber::Type type) const
+{
+ PhoneNumber phoneNumber(QString(), type);
+ PhoneNumber::List::ConstIterator it;
+ for (it = d->mPhoneNumbers.constBegin(); it != d->mPhoneNumbers.constEnd(); ++it) {
+ if (matchBinaryPattern((*it).type(), type)) {
+ if ((*it).type() & PhoneNumber::Pref) {
+ return (*it);
+ } else if (phoneNumber.number().isEmpty()) {
+ phoneNumber = (*it);
+ }
+ }
+ }
+
+ return phoneNumber;
+}
+
+PhoneNumber::List Addressee::phoneNumbers() const
+{
+ return d->mPhoneNumbers;
+}
+
+void Addressee::setPhoneNumbers(const PhoneNumber::List &phoneNumbers)
+{
+ d->mEmpty = false;
+ d->mPhoneNumbers.clear();
+ d->mPhoneNumbers = phoneNumbers;
+}
+
+PhoneNumber::List Addressee::phoneNumbers(PhoneNumber::Type type) const
+{
+ PhoneNumber::List list;
+
+ PhoneNumber::List::ConstIterator it;
+ PhoneNumber::List::ConstIterator end(d->mPhoneNumbers.constEnd());
+ for (it = d->mPhoneNumbers.constBegin(); it != end; ++it) {
+ if (matchBinaryPattern((*it).type(), type)) {
+ list.append(*it);
+ }
+ }
+ return list;
+}
+
+PhoneNumber Addressee::findPhoneNumber(const QString &id) const
+{
+ PhoneNumber::List::ConstIterator it;
+ PhoneNumber::List::ConstIterator end(d->mPhoneNumbers.constEnd());
+ for (it = d->mPhoneNumbers.constBegin(); it != end; ++it) {
+ if ((*it).id() == id) {
+ return *it;
+ }
+ }
+ return PhoneNumber();
+}
+
+void Addressee::insertKey(const Key &key)
+{
+ d->mEmpty = false;
+
+ Key::List::Iterator it;
+ for (it = d->mKeys.begin(); it != d->mKeys.end(); ++it) {
+ if ((*it).id() == key.id()) {
+ *it = key;
+ return;
+ }
+ }
+ d->mKeys.append(key);
+}
+
+void vectorRemoveAll(Key::List &t, const Key &key)
+{
+ t.removeAll(key);
+}
+
+void Addressee::removeKey(const Key &key)
+{
+ Key::List::Iterator it;
+ for (it = d->mKeys.begin(); it != d->mKeys.end(); ++it) {
+ if ((*it).id() == key.id()) {
+ //Just use d->mKeys.removeAll(key) when depending on Qt 5.4
+ vectorRemoveAll(d->mKeys, key);
+ return;
+ }
+ }
+}
+
+Key Addressee::key(Key::Type type, const QString &customTypeString) const
+{
+ Key::List::ConstIterator it;
+ Key::List::ConstIterator end(d->mKeys.constEnd());
+ for (it = d->mKeys.constBegin(); it != end; ++it) {
+ if ((*it).type() == type) {
+ if (type == Key::Custom) {
+ if (customTypeString.isEmpty()) {
+ return *it;
+ } else {
+ if ((*it).customTypeString() == customTypeString) {
+ return (*it);
+ }
+ }
+ } else {
+ return *it;
+ }
+ }
+ }
+ return Key(QString(), type);
+}
+
+void Addressee::setKeys(const Key::List &list)
+{
+ d->mKeys = list;
+ d->mEmpty = false;
+}
+
+Key::List Addressee::keys() const
+{
+ return d->mKeys;
+}
+
+Key::List Addressee::keys(Key::Type type, const QString &customTypeString) const
+{
+ Key::List list;
+
+ Key::List::ConstIterator it;
+ Key::List::ConstIterator end(d->mKeys.constEnd());
+ for (it = d->mKeys.constBegin(); it != end; ++it) {
+ if ((*it).type() == type) {
+ if (type == Key::Custom) {
+ if (customTypeString.isEmpty()) {
+ list.append(*it);
+ } else {
+ if ((*it).customTypeString() == customTypeString) {
+ list.append(*it);
+ }
+ }
+ } else {
+ list.append(*it);
+ }
+ }
+ }
+ return list;
+}
+
+Key Addressee::findKey(const QString &id) const
+{
+ Key::List::ConstIterator it;
+ Key::List::ConstIterator end(d->mKeys.constEnd());
+ for (it = d->mKeys.constBegin(); it != end; ++it) {
+ if ((*it).id() == id) {
+ return *it;
+ }
+ }
+ return Key();
+}
+
+QString Addressee::toString() const
+{
+ QString str;
+
+ str += QLatin1String("Addressee {\n");
+ str += QStringLiteral(" Uid: %1\n").arg(uid());
+
+ str += QStringLiteral(" Name: %1\n").arg(name());
+ str += QStringLiteral(" FormattedName: %1\n").arg(formattedName());
+ str += QStringLiteral(" FamilyName: %1\n").arg(familyName());
+ str += QStringLiteral(" GivenName: %1\n").arg(givenName());
+ str += QStringLiteral(" AdditionalName: %1\n").arg(additionalName());
+ str += QStringLiteral(" Prefix: %1\n").arg(prefix());
+ str += QStringLiteral(" Suffix: %1\n").arg(suffix());
+ str += QStringLiteral(" NickName: %1\n").arg(nickName());
+ str += QStringLiteral(" Birthday: %1\n").arg(birthday().toString());
+ str += QStringLiteral(" Mailer: %1\n").arg(mailer());
+ str += QStringLiteral(" TimeZone: %1\n").arg(timeZone().toString());
+ str += QStringLiteral(" Geo: %1\n").arg(geo().toString());
+ str += QStringLiteral(" Title: %1\n").arg(title());
+ str += QStringLiteral(" Role: %1\n").arg(role());
+ str += QStringLiteral(" Organization: %1\n").arg(organization());
+ str += QStringLiteral(" Department: %1\n").arg(department());
+ str += QStringLiteral(" Note: %1\n").arg(note());
+ str += QStringLiteral(" ProductId: %1\n").arg(productId());
+ str += QStringLiteral(" Revision: %1\n").arg(revision().toString());
+ str += QStringLiteral(" SortString: %1\n").arg(sortString());
+ str += QStringLiteral(" Url: %1\n").arg(url().url().url());
+ str += QStringLiteral(" Secrecy: %1\n").arg(secrecy().toString());
+ str += QStringLiteral(" Logo: %1\n").arg(logo().toString());
+ str += QStringLiteral(" Photo: %1\n").arg(photo().toString());
+ str += QStringLiteral(" Sound: %1\n").arg(sound().toString());
+ str += QStringLiteral(" Gender: %1\n").arg(gender().toString());
+ str += QStringLiteral(" Kind: %1\n").arg(kind());
+
+ str += QLatin1String(" Emails {\n");
+ const Email::List listEmail = d->mEmails;
+ Email::List::ConstIterator it5;
+ for (it5 = listEmail.begin(); it5 != listEmail.end(); ++it5) {
+ str += (*it5).toString();
+ }
+ str += QLatin1String(" }\n");
+
+ str += QLatin1String(" Langs {\n");
+ const Lang::List listLang = d->mLangs;
+ Lang::List::ConstIterator it6;
+ for (it6 = listLang.begin(); it6 != listLang.end(); ++it6) {
+ str += (*it6).toString();
+ }
+ str += QLatin1String(" }\n");
+
+ str += QLatin1String(" PhoneNumbers {\n");
+ const PhoneNumber::List p = phoneNumbers();
+ PhoneNumber::List::ConstIterator it2;
+ for (it2 = p.begin(); it2 != p.end(); ++it2) {
+ str += (*it2).toString();
+ }
+ str += QLatin1String(" }\n");
+
+ str += QLatin1String(" Addresses {\n");
+ const Address::List a = addresses();
+ Address::List::ConstIterator it3;
+ for (it3 = a.begin(); it3 != a.end(); ++it3) {
+ str += (*it3).toString();
+ }
+ str += QLatin1String(" }\n");
+
+ str += QLatin1String(" Keys {\n");
+ const Key::List k = keys();
+ Key::List::ConstIterator it4;
+ for (it4 = k.begin(); it4 != k.end(); ++it4) {
+ str += (*it4).toString();
+ }
+ str += QLatin1String(" }\n");
+
+ str += QLatin1String("}\n");
+
+ return str;
+}
+
+void Addressee::insertAddress(const Address &address)
+{
+ if (address.isEmpty()) {
+ return;
+ }
+
+ d->mEmpty = false;
+
+ Address::List::Iterator it;
+ for (it = d->mAddresses.begin(); it != d->mAddresses.end(); ++it) {
+ if ((*it).id() == address.id()) {
+ *it = address;
+ return;
+ }
+ }
+
+ d->mAddresses.append(address);
+}
+
+void Addressee::removeAddress(const Address &address)
+{
+ Address::List::Iterator it;
+ for (it = d->mAddresses.begin(); it != d->mAddresses.end(); ++it) {
+ if ((*it).id() == address.id()) {
+ d->mAddresses.erase(it);
+ return;
+ }
+ }
+}
+
+Address Addressee::address(Address::Type type) const
+{
+ Address address(type);
+ Address::List::ConstIterator it;
+ Address::List::ConstIterator end(d->mAddresses.constEnd());
+ for (it = d->mAddresses.constBegin(); it != end; ++it) {
+ if (matchBinaryPattern((*it).type(), type)) {
+ if ((*it).type() & Address::Pref) {
+ return (*it);
+ } else if (address.isEmpty()) {
+ address = (*it);
+ }
+ }
+ }
+
+ return address;
+}
+
+Address::List Addressee::addresses() const
+{
+ return d->mAddresses;
+}
+
+Address::List Addressee::addresses(Address::Type type) const
+{
+ Address::List list;
+
+ Address::List::ConstIterator it;
+ Address::List::ConstIterator end(d->mAddresses.constEnd());
+ for (it = d->mAddresses.constBegin(); it != end; ++it) {
+ if (matchBinaryPattern((*it).type(), type)) {
+ list.append(*it);
+ }
+ }
+
+ return list;
+}
+
+Address Addressee::findAddress(const QString &id) const
+{
+ Address::List::ConstIterator it;
+ Address::List::ConstIterator end(d->mAddresses.constEnd());
+ for (it = d->mAddresses.constBegin(); it != end; ++it) {
+ if ((*it).id() == id) {
+ return *it;
+ }
+ }
+ return Address();
+}
+
+void Addressee::insertCategory(const QString &c)
+{
+ d->mEmpty = false;
+
+ if (d->mCategories.contains(c)) {
+ return;
+ }
+
+ d->mCategories.append(c);
+}
+
+void Addressee::removeCategory(const QString &category)
+{
+ if (d->mCategories.contains(category)) {
+ d->mCategories.removeAll(category);
+ }
+}
+
+bool Addressee::hasCategory(const QString &category) const
+{
+ return d->mCategories.contains(category);
+}
+
+void Addressee::setCategories(const QStringList &c)
+{
+ d->mEmpty = false;
+
+ d->mCategories = c;
+}
+
+QStringList Addressee::categories() const
+{
+ return d->mCategories;
+}
+
+void Addressee::insertMember(const QString &member)
+{
+ d->mEmpty = false;
+
+ if (d->mMembers.contains(member)) {
+ return;
+ }
+
+ d->mMembers.append(member);
+}
+
+void Addressee::setMembers(const QStringList &m)
+{
+ d->mEmpty = false;
+ d->mMembers = m;
+}
+
+QStringList Addressee::members() const
+{
+ return d->mMembers;
+}
+
+void Addressee::insertRelationShip(const Related &relation)
+{
+ d->mEmpty = false;
+
+ if (d->mRelationShips.contains(relation)) {
+ return;
+ }
+
+ d->mRelationShips.append(relation);
+}
+
+void Addressee::setRelationShips(const Related::List &c)
+{
+ d->mEmpty = false;
+ d->mRelationShips = c;
+}
+
+Related::List Addressee::relationShips() const
+{
+ return d->mRelationShips;
+}
+
+void Addressee::insertCustom(const QString &app, const QString &name,
+ const QString &value)
+{
+ if (value.isEmpty() || name.isEmpty() || app.isEmpty()) {
+ return;
+ }
+
+ d->mEmpty = false;
+
+ const QString qualifiedName = app + QLatin1Char('-') + name;
+
+ d->mCustomFields.insert(qualifiedName, value);
+}
+
+void Addressee::removeCustom(const QString &app, const QString &name)
+{
+ const QString qualifiedName = app + QLatin1Char('-') + name;
+
+ d->mCustomFields.remove(qualifiedName);
+}
+
+QString Addressee::custom(const QString &app, const QString &name) const
+{
+ const QString qualifiedName = app + QLatin1Char('-') + name;
+
+ return d->mCustomFields.value(qualifiedName);
+}
+
+void Addressee::setCustoms(const QStringList &customs)
+{
+ d->mEmpty = false;
+
+ d->mCustomFields.clear();
+
+ foreach (const QString &custom, customs) {
+ const int index = custom.indexOf(QLatin1Char(':'));
+ if (index == -1) {
+ continue;
+ }
+
+ const QString qualifiedName = custom.left(index);
+ const QString value = custom.mid(index + 1);
+
+ d->mCustomFields.insert(qualifiedName, value);
+ }
+}
+
+QStringList Addressee::customs() const
+{
+ QStringList result;
+
+ QHashIterator<QString, QString> it(d->mCustomFields);
+ result.reserve(d->mCustomFields.count());
+ while (it.hasNext()) {
+ it.next();
+ result << it.key() + QLatin1Char(':') + it.value();
+ }
+
+ return result;
+}
+
+void Addressee::parseEmailAddress(const QString &rawEmail, QString &fullName,
+ QString &email)
+{
+ // This is a simplified version of KPIM::splitAddress().
+
+ fullName.clear();
+ email.clear();
+ if (rawEmail.isEmpty()) {
+ return; // KPIM::AddressEmpty;
+ }
+
+ // The code works on 8-bit strings, so convert the input to UTF-8.
+ QByteArray address = rawEmail.toUtf8();
+
+ QByteArray displayName;
+ QByteArray addrSpec;
+ QByteArray comment;
+
+ // The following is a primitive parser for a mailbox-list (cf. RFC 2822).
+ // The purpose is to extract a displayable string from the mailboxes.
+ // Comments in the addr-spec are not handled. No error checking is done.
+
+ enum sourceLevel {
+ TopLevel,
+ InComment,
+ InAngleAddress
+ };
+ sourceLevel context = TopLevel;
+ bool inQuotedString = false;
+ int commentLevel = 0;
+ bool stop = false;
+
+ for (char *p = address.data(); *p && !stop; ++p) {
+ switch (context) {
+ case TopLevel : {
+ switch (*p) {
+ case '"':
+ inQuotedString = !inQuotedString;
+ displayName += *p;
+ break;
+ case '(':
+ if (!inQuotedString) {
+ context = InComment;
+ commentLevel = 1;
+ } else {
+ displayName += *p;
+ }
+ break;
+ case '<':
+ if (!inQuotedString) {
+ context = InAngleAddress;
+ } else {
+ displayName += *p;
+ }
+ break;
+ case '\\': // quoted character
+ displayName += *p;
+ ++p; // skip the '\'
+ if (*p) {
+ displayName += *p;
+ } else {
+ //return KPIM::UnexpectedEnd;
+ goto ABORT_PARSING;
+ }
+ break;
+ case ',':
+ if (!inQuotedString) {
+ //if ( allowMultipleAddresses )
+ // stop = true;
+ //else
+ // return KPIM::UnexpectedComma;
+ goto ABORT_PARSING;
+ } else {
+ displayName += *p;
+ }
+ break;
+ default:
+ displayName += *p;
+ }
+ break;
+ }
+ case InComment: {
+ switch (*p) {
+ case '(':
+ ++commentLevel;
+ comment += *p;
+ break;
+ case ')':
+ --commentLevel;
+ if (commentLevel == 0) {
+ context = TopLevel;
+ comment += ' '; // separate the text of several comments
+ } else {
+ comment += *p;
+ }
+ break;
+ case '\\': // quoted character
+ comment += *p;
+ ++p; // skip the '\'
+ if (*p) {
+ comment += *p;
+ } else {
+ //return KPIM::UnexpectedEnd;
+ goto ABORT_PARSING;
+ }
+ break;
+ default:
+ comment += *p;
+ }
+ break;
+ }
+ case InAngleAddress: {
+ switch (*p) {
+ case '"':
+ inQuotedString = !inQuotedString;
+ addrSpec += *p;
+ break;
+ case '>':
+ if (!inQuotedString) {
+ context = TopLevel;
+ } else {
+ addrSpec += *p;
+ }
+ break;
+ case '\\': // quoted character
+ addrSpec += *p;
+ ++p; // skip the '\'
+ if (*p) {
+ addrSpec += *p;
+ } else {
+ //return KPIM::UnexpectedEnd;
+ goto ABORT_PARSING;
+ }
+ break;
+ default:
+ addrSpec += *p;
+ }
+ break;
+ }
+ } // switch ( context )
+ }
+
+ABORT_PARSING:
+ displayName = displayName.trimmed();
+ comment = comment.trimmed();
+ addrSpec = addrSpec.trimmed();
+ fullName = QString::fromUtf8(displayName);
+ email = QString::fromUtf8(addrSpec); // check for errors
+ if (inQuotedString) {
+ return; // KPIM::UnbalancedQuote;
+ }
+ if (context == InComment) {
+ return; // KPIM::UnbalancedParens;
+ }
+ if (context == InAngleAddress) {
+ return; // KPIM::UnclosedAngleAddr;
+ }
+
+ if (addrSpec.isEmpty()) {
+ if (displayName.isEmpty()) {
+ return; // KPIM::NoAddressSpec;
+ } else {
+ //addrSpec = displayName;
+ //displayName.truncate( 0 );
+ // Address of the form "foo@bar" or "foo@bar (Name)".
+ email = fullName;
+ fullName = QString::fromUtf8(comment);
+ }
+ }
+
+ email = email.toLower();
+ // Check that we do not have any extra characters on the end of the
+ // strings
+ unsigned int len = fullName.length();
+ if (fullName[0] == QLatin1Char('"') && fullName[len - 1] == QLatin1Char('"')) {
+ fullName = fullName.mid(1, len - 2);
+ }
+}
+
+void Addressee::setChanged(bool value)
+{
+ d->mChanged = value;
+}
+
+bool Addressee::changed() const
+{
+ return d->mChanged;
+}
+
+void Addressee::setSortMode(KContacts::SortMode *mode)
+{
+ Private::mSortMode = mode;
+}
+
+bool Addressee::operator<(const Addressee &addr) const
+{
+ if (!Private::mSortMode) {
+ return false;
+ } else {
+ return Private::mSortMode->lesser(*this, addr);
+ }
+}
+
+QString Addressee::mimeType()
+{
+ return QStringLiteral("text/directory");
+}
+
+QDataStream &KContacts::operator<<(QDataStream &s, const Addressee &a)
+{
+ s << a.d->mUid;
+
+ s << a.d->mName;
+ s << a.d->mFormattedName;
+ s << a.d->mFamilyName;
+ s << a.d->mGivenName;
+ s << a.d->mAdditionalName;
+ s << a.d->mPrefix;
+ s << a.d->mSuffix;
+ s << a.d->mNickName;
+ s << a.d->mBirthday;
+ s << a.d->mMailer;
+ s << a.d->mTimeZone;
+ s << a.d->mGeo;
+ s << a.d->mTitle;
+ s << a.d->mRole;
+ s << a.d->mOrganization;
+ s << a.d->mDepartment;
+ s << a.d->mNote;
+ s << a.d->mProductId;
+ s << a.d->mRevision;
+ s << a.d->mSortString;
+ s << a.d->mSecrecy;
+ s << a.d->mLogo;
+ s << a.d->mPhoto;
+ s << a.d->mSound;
+ s << a.d->mPhoneNumbers;
+ s << a.d->mAddresses;
+ s << a.d->mEmails;
+ s << a.d->mCategories;
+ s << a.customs();
+ s << a.d->mKeys;
+ s << a.d->mLangs;
+ s << a.d->mGender;
+ s << a.d->mKind;
+ s << a.d->mCalendarUrl;
+ s << a.d->mSoundListExtra;
+ s << a.d->mPhotoExtraList;
+ s << a.d->mLogoExtraList;
+ s << a.d->mUrlExtraList;
+ s << a.d->mMembers;
+ s << a.d->mRelationShips;
+ s << a.d->mSources;
+ s << a.d->mImpps;
+
+ return s;
+}
+
+QDataStream &KContacts::operator>>(QDataStream &s, Addressee &a)
+{
+ s >> a.d->mUid;
+
+ s >> a.d->mName;
+ s >> a.d->mFormattedName;
+ s >> a.d->mFamilyName;
+ s >> a.d->mGivenName;
+ s >> a.d->mAdditionalName;
+ s >> a.d->mPrefix;
+ s >> a.d->mSuffix;
+ s >> a.d->mNickName;
+ s >> a.d->mBirthday;
+ s >> a.d->mMailer;
+ s >> a.d->mTimeZone;
+ s >> a.d->mGeo;
+ s >> a.d->mTitle;
+ s >> a.d->mRole;
+ s >> a.d->mOrganization;
+ s >> a.d->mDepartment;
+ s >> a.d->mNote;
+ s >> a.d->mProductId;
+ s >> a.d->mRevision;
+ s >> a.d->mSortString;
+ s >> a.d->mSecrecy;
+ s >> a.d->mLogo;
+ s >> a.d->mPhoto;
+ s >> a.d->mSound;
+ s >> a.d->mPhoneNumbers;
+ s >> a.d->mAddresses;
+ s >> a.d->mEmails;
+ s >> a.d->mCategories;
+ QStringList customFields;
+ s >> customFields;
+ a.setCustoms(customFields);
+ s >> a.d->mKeys;
+ s >> a.d->mLangs;
+ s >> a.d->mGender;
+ s >> a.d->mKind;
+ s >> a.d->mCalendarUrl;
+ s >> a.d->mSoundListExtra;
+ s >> a.d->mPhotoExtraList;
+ s >> a.d->mLogoExtraList;
+ s >> a.d->mUrlExtraList;
+ s >> a.d->mMembers;
+ s >> a.d->mRelationShips;
+ s >> a.d->mSources;
+ s >> a.d->mImpps;
+ a.d->mEmpty = false;
+
+ return s;
+}
+
+bool matchBinaryPattern(int value, int pattern)
+{
+ /**
+ We want to match all telephonnumbers/addresses which have the bits in the
+ pattern set. More are allowed.
+ if pattern == 0 we have a special handling, then we want only those with
+ exactly no bit set.
+ */
+ if (pattern == 0) {
+ return (value == 0);
+ } else {
+ return (pattern == (pattern & value));
+ }
+}
+
+template <class L>
+bool listEquals(const QVector<L> &list, const QVector<L> &pattern)
+{
+ if (list.count() != pattern.count()) {
+ return false;
+ }
+ const int numberOfElement(list.count());
+ for (int i = 0; i < numberOfElement; ++i) {
+ if (!pattern.contains(list[i])) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool listEquals(const QStringList &list, const QStringList &pattern)
+{
+ if (list.count() != pattern.count()) {
+ return false;
+ }
+
+ const int numberOfElement(list.count());
+ for (int i = 0; i < numberOfElement; ++i) {
+ if (!pattern.contains(list[i])) {
+ return false;
+ }
+ }
+
+ return true;
+}
--- /dev/null
+/*
+ This file is part of the KContacts framework.
+ Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org>
+ 2013 Tobias Koenig <tokoe@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KCONTACTS_ADDRESSEE_H
+#define KCONTACTS_ADDRESSEE_H
+
+#include <QtCore/QDateTime>
+#include <QtCore/QStringList>
+#include <QtCore/QSharedDataPointer>
+#include <QtCore/QUrl>
+#include <QtCore/QMap>
+
+#include "address.h"
+#include "geo.h"
+#include "key.h"
+#include "email.h"
+#include "lang.h"
+#include "gender.h"
+#include "phonenumber.h"
+#include "picture.h"
+#include "secrecy.h"
+#include "sound.h"
+#include "impp.h"
+#include "timezone.h"
+#include "calendarurl.h"
+#include "related.h"
+#include "addresseelist.h"
+#include "resourcelocatorurl.h"
+
+namespace KContacts
+{
+
+class SortMode;
+
+/**
+ @short address book entry
+
+ This class represents an entry in the address book.
+
+ The data of this class is implicitly shared. You can pass this class by value.
+
+ If you need the name of a field for presenting it to the user you should use
+ the functions ending in Label(). They return a translated string which can be
+ used as label for the corresponding field.
+
+ About the name fields:
+
+ givenName() is the first name and familyName() the last name. In some
+ countries the family name comes first, that's the reason for the
+ naming. formattedName() is the full name with the correct formatting.
+ It is used as an override, when the correct formatting can't be generated
+ from the other name fields automatically.
+
+ realName() returns a fully formatted name(). It uses formattedName, if set,
+ otherwise it constucts the name from the name fields. As fallback, if
+ nothing else is set it uses name().
+
+ name() is the NAME type of RFC2426. It can be used as internal name for the
+ data enty, but shouldn't be used for displaying the data to the user.
+ */
+class KCONTACTS_EXPORT Addressee
+{
+ friend KCONTACTS_EXPORT QDataStream &operator<<(QDataStream &, const Addressee &);
+ friend KCONTACTS_EXPORT QDataStream &operator>>(QDataStream &, Addressee &);
+
+public:
+ /**
+ A list of addressee objects
+ */
+ typedef AddresseeList List;
+ /**
+ A map from unique identifier to addressee.
+
+ @see uid()
+ */
+ typedef QHash<QString, Addressee> Map;
+
+ /**
+ Construct an empty address book entry.
+ */
+ Addressee();
+
+ /**
+ Destroys the address book entry.
+ */
+ ~Addressee();
+
+ /**
+ Copy constructor.
+ */
+ Addressee(const Addressee &other);
+
+ /**
+ Assignment operator.
+
+ @return a reference to @c this
+ */
+ Addressee &operator=(const Addressee &other);
+
+ /**
+ Equality operator.
+
+ @return @c true if @c this and the given addressee are equal,
+ otherwise @c false
+ */
+ bool operator==(const Addressee &other) const;
+
+ /**
+ Not-equal operator.
+
+ @return @c true if @c this and the given addressee are not equal,
+ otherwise @c false
+ */
+ bool operator!=(const Addressee &other) const;
+
+ /**
+ Return if the address book entry is empty.
+ */
+ bool isEmpty() const;
+
+ /**
+ Set unique identifier.
+
+ @param uid the KABC unique identifier
+ */
+ void setUid(const QString &uid);
+
+ /**
+ Return unique identifier.
+ */
+ QString uid() const;
+
+ /**
+ Return translated label for uid field.
+ */
+ static QString uidLabel();
+
+ /**
+ Set name.
+ */
+ void setName(const QString &name);
+
+ /**
+ Return name.
+ */
+ QString name() const;
+
+ /**
+ Return translated label for name field.
+ */
+ static QString nameLabel();
+
+ /**
+ Set formatted name.
+ */
+ void setFormattedName(const QString &formattedName);
+
+ /**
+ Return formatted name.
+ */
+ QString formattedName() const;
+
+ /**
+ Return translated label for formattedName field.
+ */
+ static QString formattedNameLabel();
+
+ /**
+ Set family name.
+ */
+ void setFamilyName(const QString &familyName);
+
+ /**
+ Return family name.
+ */
+ QString familyName() const;
+
+ /**
+ Return translated label for familyName field.
+ */
+ static QString familyNameLabel();
+
+ /**
+ Set given name.
+ */
+ void setGivenName(const QString &givenName);
+
+ /**
+ Return given name.
+ */
+ QString givenName() const;
+
+ /**
+ Return translated label for givenName field.
+ */
+ static QString givenNameLabel();
+
+ /**
+ Set additional names.
+ */
+ void setAdditionalName(const QString &additionalName);
+
+ /**
+ Return additional names.
+ */
+ QString additionalName() const;
+
+ /**
+ Return translated label for additionalName field.
+ */
+ static QString additionalNameLabel();
+
+ /**
+ Set honorific prefixes.
+ */
+ void setPrefix(const QString &prefix);
+
+ /**
+ Return honorific prefixes.
+ */
+ QString prefix() const;
+
+ /**
+ Return translated label for prefix field.
+ */
+ static QString prefixLabel();
+
+ /**
+ Set honorific suffixes.
+ */
+ void setSuffix(const QString &suffix);
+
+ /**
+ Return honorific suffixes.
+ */
+ QString suffix() const;
+
+ /**
+ Return translated label for suffix field.
+ */
+ static QString suffixLabel();
+
+ /**
+ Set nick name.
+ */
+ void setNickName(const QString &nickName);
+
+ /**
+ Return nick name.
+ */
+ QString nickName() const;
+
+ /**
+ Return translated label for nickName field.
+ */
+ static QString nickNameLabel();
+
+ /**
+ Set birthday.
+ */
+ void setBirthday(const QDateTime &birthday);
+
+ /**
+ Return birthday.
+ */
+ QDateTime birthday() const;
+
+ /**
+ Return translated label for birthday field.
+ */
+ static QString birthdayLabel();
+
+ /**
+ Return translated label for homeAddressStreet field.
+ */
+ static QString homeAddressStreetLabel();
+
+ /**
+ Return translated label for homeAddressPostOfficeBox field.
+ */
+ static QString homeAddressPostOfficeBoxLabel();
+
+ /**
+ Return translated label for homeAddressLocality field.
+ */
+ static QString homeAddressLocalityLabel();
+
+ /**
+ Return translated label for homeAddressRegion field.
+ */
+ static QString homeAddressRegionLabel();
+
+ /**
+ Return translated label for homeAddressPostalCode field.
+ */
+ static QString homeAddressPostalCodeLabel();
+
+ /**
+ Return translated label for homeAddressCountry field.
+ */
+ static QString homeAddressCountryLabel();
+
+ /**
+ Return translated label for homeAddressLabel field.
+ */
+ static QString homeAddressLabelLabel();
+
+ /**
+ Return translated label for businessAddressStreet field.
+ */
+ static QString businessAddressStreetLabel();
+
+ /**
+ Return translated label for businessAddressPostOfficeBox field.
+ */
+ static QString businessAddressPostOfficeBoxLabel();
+
+ /**
+ Return translated label for businessAddressLocality field.
+ */
+ static QString businessAddressLocalityLabel();
+
+ /**
+ Return translated label for businessAddressRegion field.
+ */
+ static QString businessAddressRegionLabel();
+
+ /**
+ Return translated label for businessAddressPostalCode field.
+ */
+ static QString businessAddressPostalCodeLabel();
+
+ /**
+ Return translated label for businessAddressCountry field.
+ */
+ static QString businessAddressCountryLabel();
+
+ /**
+ Return translated label for businessAddressLabel field.
+ */
+ static QString businessAddressLabelLabel();
+
+ /**
+ Return translated label for homePhone field.
+ */
+ static QString homePhoneLabel();
+
+ /**
+ Return translated label for businessPhone field.
+ */
+ static QString businessPhoneLabel();
+
+ /**
+ Return translated label for mobilePhone field.
+ */
+ static QString mobilePhoneLabel();
+
+ /**
+ Return translated label for homeFax field.
+ */
+ static QString homeFaxLabel();
+
+ /**
+ Return translated label for businessFax field.
+ */
+ static QString businessFaxLabel();
+
+ /**
+ Return translated label for carPhone field.
+ */
+ static QString carPhoneLabel();
+
+ /**
+ Return translated label for isdn field.
+ */
+ static QString isdnLabel();
+
+ /**
+ Return translated label for pager field.
+ */
+ static QString pagerLabel();
+
+ /**
+ Return translated label for email field.
+ */
+ static QString emailLabel();
+
+ /**
+ Set mail client.
+ */
+ void setMailer(const QString &mailer);
+
+ /**
+ Return mail client.
+ */
+ QString mailer() const;
+
+ /**
+ Return translated label for mailer field.
+ */
+ static QString mailerLabel();
+
+ /**
+ Set time zone.
+ */
+ void setTimeZone(const TimeZone &timeZone);
+
+ /**
+ Return time zone.
+ */
+ TimeZone timeZone() const;
+
+ /**
+ Return translated label for timeZone field.
+ */
+ static QString timeZoneLabel();
+
+ /**
+ Set geographic position.
+ */
+ void setGeo(const Geo &geo);
+
+ /**
+ Return geographic position.
+ */
+ Geo geo() const;
+
+ /**
+ Return translated label for geo field.
+ */
+ static QString geoLabel();
+
+ /**
+ Set title.
+ */
+ void setTitle(const QString &title);
+
+ /**
+ Return title.
+ */
+ QString title() const;
+
+ /**
+ Return translated label for title field.
+ */
+ static QString titleLabel();
+
+ /**
+ Set role.
+ */
+ void setRole(const QString &role);
+
+ /**
+ Return role.
+ */
+ QString role() const;
+
+ /**
+ Return translated label for role field.
+ */
+ static QString roleLabel();
+
+ /**
+ Set organization.
+ */
+ void setOrganization(const QString &organization);
+
+ /**
+ Return organization.
+ */
+ QString organization() const;
+
+ /**
+ Return translated label for organization field.
+ */
+ static QString organizationLabel();
+
+ /**
+ Set department.
+ */
+ void setDepartment(const QString &department);
+
+ /**
+ Return department.
+ */
+ QString department() const;
+
+ /**
+ Return translated label for department field.
+ */
+ static QString departmentLabel();
+
+ /**
+ Set note.
+ */
+ void setNote(const QString ¬e);
+
+ /**
+ Return note.
+ */
+ QString note() const;
+
+ /**
+ Return translated label for note field.
+ */
+ static QString noteLabel();
+
+ /**
+ Set product identifier.
+ */
+ void setProductId(const QString &productId);
+
+ /**
+ Return product identifier.
+ */
+ QString productId() const;
+
+ /**
+ Return translated label for productId field.
+ */
+ static QString productIdLabel();
+
+ /**
+ Set revision date.
+ */
+ void setRevision(const QDateTime &revision);
+
+ /**
+ Return revision date.
+ */
+ QDateTime revision() const;
+
+ /**
+ Return translated label for revision field.
+ */
+ static QString revisionLabel();
+
+ /**
+ Set sort string.
+ */
+ void setSortString(const QString &sortString);
+
+ /**
+ Return sort string.
+ */
+ QString sortString() const;
+
+ /**
+ Return translated label for sortString field.
+ */
+ static QString sortStringLabel();
+
+ /**
+ Set homepage.
+ */
+ void setUrl(const ResourceLocatorUrl &url);
+ void setUrl(const QUrl &url);
+
+ /**
+ Return homepage.
+ */
+ ResourceLocatorUrl url() const;
+
+ /**
+ Return translated label for url field.
+ */
+ static QString urlLabel();
+
+ /**
+ Set security class.
+ */
+ void setSecrecy(const Secrecy &secrecy);
+
+ /**
+ Return security class.
+ */
+ Secrecy secrecy() const;
+
+ /**
+ Return translated label for secrecy field.
+ */
+ static QString secrecyLabel();
+
+ /**
+ Set logo.
+ */
+ void setLogo(const Picture &logo);
+
+ /**
+ Return logo.
+ */
+ Picture logo() const;
+
+ /**
+ Return translated label for logo field.
+ */
+ static QString logoLabel();
+
+ /**
+ Set photo.
+ */
+ void setPhoto(const Picture &photo);
+
+ /**
+ Return photo.
+ */
+ Picture photo() const;
+
+ /**
+ Return translated label for photo field.
+ */
+ static QString photoLabel();
+
+ /**
+ Set sound.
+ */
+ void setSound(const Sound &sound);
+
+ /**
+ Return sound.
+ */
+ Sound sound() const;
+
+ /**
+ Return translated label for sound field.
+ */
+ static QString soundLabel();
+
+ /**
+ Set name fields by parsing the given string and trying to associate the
+ parts of the string with according fields. This function should probably
+ be a bit more clever.
+ */
+ void setNameFromString(const QString &s);
+
+ /**
+ Return the name of the addressee. This is calculated from all the name
+ fields.
+ */
+ QString realName() const;
+
+ /**
+ Return the name that consists of all name parts.
+ */
+ QString assembledName() const;
+
+ /**
+ Return email address including real name.
+
+ @param email Email address to be used to construct the full email string.
+ If this is QString() the preferred email address is used.
+ */
+ QString fullEmail(const QString &email = QString()) const;
+
+ /**
+ Insert an email address. If the email address already exists in this
+ addressee it is not duplicated.
+
+ @param email Email address
+ @param preferred Set to true, if this is the preferred email address of
+ the addressee.
+ */
+ void insertEmail(const QString &email, bool preferred = false, const QMap<QString, QStringList> ¶m = QMap<QString, QStringList>());
+
+ /**
+ Remove email address. If the email address doesn't exist, nothing happens.
+
+ @param email Email address to remove
+ */
+ void removeEmail(const QString &email);
+
+ /**
+ Return preferred email address. This is the first email address or the
+ last one added with insertEmail() with a set preferred parameter.
+ */
+ QString preferredEmail() const;
+
+ /**
+ Return list of all email addresses.
+ */
+ QStringList emails() const;
+
+ /**
+ Set the emails to @p list.
+ The first email address gets the preferred one!
+ @param list The list of email addresses.
+ */
+ void setEmails(const QStringList &list);
+
+ /**
+ Insert a phone number. If a phone number with the same id already exists
+ in this addressee it is not duplicated.
+
+ @param phoneNumber The telephone number to insert to the addressee
+ */
+ void insertPhoneNumber(const PhoneNumber &phoneNumber);
+
+ /**
+ Remove phone number. If no phone number with the given id exists for this
+ addresse nothing happens.
+
+ @param phoneNumber The telephone number to remove from the addressee
+ */
+ void removePhoneNumber(const PhoneNumber &phoneNumber);
+
+ /**
+ Return phone number, which matches the given type.
+
+ @param type The type of phone number to get
+ */
+ PhoneNumber phoneNumber(PhoneNumber::Type type) const;
+
+ /**
+ Return list of all phone numbers.
+ */
+ PhoneNumber::List phoneNumbers() const;
+
+ void setPhoneNumbers(const PhoneNumber::List &phoneNumbers);
+
+ /**
+ Return list of phone numbers with a special type.
+
+ @param type The type of phone number to get
+ */
+ PhoneNumber::List phoneNumbers(PhoneNumber::Type type) const;
+
+ /**
+ Return phone number with the given id.
+
+ @param id The identifier of the phone number to look for.
+ See PhoneNumber::id()
+ */
+ PhoneNumber findPhoneNumber(const QString &id) const;
+
+ /**
+ Insert a key. If a key with the same id already exists
+ in this addressee it is not duplicated.
+
+ @param key The key to insert
+ */
+ void insertKey(const Key &key);
+
+ /**
+ Remove a key. If no key with the given id exists for this
+ addresse nothing happens.
+
+ @param key The key to remove
+ */
+ void removeKey(const Key &key);
+
+ /**
+ Return key, which matches the given type.
+ If @p type == Key::Custom you can specify a string
+ that should match. If you leave the string empty, the first
+ key with a custom value is returned.
+
+ @param type The type of key to look for
+ @param customTypeString A string to match custom keys against when
+ @p type is @c Key::Custom
+ */
+ Key key(Key::Type type, const QString &customTypeString = QString()) const;
+
+ /**
+ Return list of all keys.
+ */
+ Key::List keys() const;
+
+ /**
+ Set the list of keys
+ @param keys The keys to be set.
+ */
+ void setKeys(const Key::List &keys);
+
+ /**
+ Return list of keys with a special type.
+ If @p type == Key::Custom you can specify a string
+ that should match. If you leave the string empty, all custom
+ keys will be returned.
+
+ @param type The type of key to look for
+ @param customTypeString A string to match custom keys against when
+ @p type is @c Key::Custom
+ */
+ Key::List keys(Key::Type type, const QString &customTypeString = QString()) const;
+
+ /**
+ Return key with the given id.
+
+ @param id The identifier of the key to look for. See Key::id()
+ */
+ Key findKey(const QString &id) const;
+
+ /**
+ Insert an address. If an address with the same id already exists
+ in this addressee it is not duplicated.
+
+ @param address The address to insert
+ */
+ void insertAddress(const Address &address);
+
+ /**
+ Remove address. If no address with the given id exists for this
+ addresse nothing happens.
+
+ @param address The address to remove
+ */
+ void removeAddress(const Address &address);
+
+ /**
+ Return address, which matches the given type.
+
+ @param type The type of address to look for
+ */
+ Address address(Address::Type type) const;
+
+ /**
+ Return list of all addresses.
+ */
+ Address::List addresses() const;
+
+ /**
+ Return list of addresses with a special type.
+
+ @param type The type of addresses to look for
+ */
+ Address::List addresses(Address::Type type) const;
+
+ /**
+ Return address with the given id.
+
+ @param id The identifier of the address to look for. See Address::id()
+ */
+ Address findAddress(const QString &id) const;
+
+ /**
+ Insert category. If the category already exists it is not duplicated.
+ */
+ void insertCategory(const QString &category);
+
+ /**
+ Remove category.
+ */
+ void removeCategory(const QString &category);
+
+ /**
+ Return, if addressee has the given category.
+ */
+ bool hasCategory(const QString &category) const;
+
+ /**
+ Set categories to given value.
+ */
+ void setCategories(const QStringList &category);
+
+ /**
+ Return list of all set categories.
+ */
+ QStringList categories() const;
+
+ /**
+ Insert custom entry. The entry is identified by the name of the inserting
+ application and a unique name. If an entry with the given app and name
+ already exists its value is replaced with the new given value.
+
+ An empty value isn't allowed (nothing happens if this is called with
+ any of the three arguments being empty)
+
+ @param app Name of the application inserting this custom entry
+ @param name Name of this application specific custom entry
+ @param value Value of this application specific custom entry
+ */
+ void insertCustom(const QString &app, const QString &name,
+ const QString &value);
+
+ /**
+ Remove custom entry.
+
+ @param app Name of the application which has inserted this custom entry
+ @param name Name of this application specific custom entry
+ */
+ void removeCustom(const QString &app, const QString &name);
+
+ /**
+ Return value of custom entry, identified by app and entry name.
+
+ @param app Name of the application which has inserted this custom entry
+ @param name Name of this application specific custom entry
+ */
+ QString custom(const QString &app, const QString &name) const;
+
+ /**
+ Set all custom entries.
+ */
+ void setCustoms(const QStringList &customs);
+
+ /**
+ Return list of all custom entries.
+
+ The format of the custom entries is 'app-key:value' and the list is sorted
+ alphabetically by 'app-key'.
+ */
+ QStringList customs() const;
+
+ /**
+ Parse full email address. The result is given back in fullName and email.
+
+ @param rawEmail The input string to parse for name and email
+ @param fullName The name part of the @p rawEmail input, if it contained one
+ @param email The email part of the @p rawEmail input, if it contained one
+ */
+ static void parseEmailAddress(const QString &rawEmail, QString &fullName,
+ QString &email);
+
+ /**
+ Returns string representation of the addressee.
+ */
+ QString toString() const;
+
+ /**
+ Mark addressee as changed.
+
+ @param value Sets the status indicating changed data
+ */
+ void setChanged(bool value);
+
+ /**
+ Return whether the addressee is changed.
+ */
+ bool changed() const;
+
+ /**
+ Sets the sort mode implementation.
+
+ Comparing to addressee objects is delegated to an instance
+ of a subclass of KContacts::SortMode.
+
+ @param mode The sort mode implementator to use
+ */
+ static void setSortMode(KContacts::SortMode *mode);
+
+ /**
+ Return whether this addressee is "less-than" a given one
+
+ @param addr The addressee object to compare with
+
+ @see setSortMode()
+ */
+ bool operator<(const Addressee &addr) const;
+
+ /**
+ Returns the MIME type used for Addressees
+ */
+ static QString mimeType();
+
+ KContacts::Email::List emailList() const;
+ void setEmailList(const Email::List &list);
+
+ /**
+ * Remove Language
+ * @brief removeLang
+ * @param language
+ */
+ void removeLang(const QString &language);
+ /**
+ * Insert Language
+ * @brief insertLang
+ * @param language
+ */
+ void insertLang(const Lang &language);
+ /**
+ * @brief langs
+ * @return List of lang
+ */
+ Lang::List langs() const;
+ void setLangs(const Lang::List &langs);
+
+ void setGender(const Gender &gender);
+ Gender gender() const;
+
+ QString kind() const;
+ void setKind(const QString &kind);
+
+ void insertCalendarUrl(const CalendarUrl &calendarUrl);
+ CalendarUrl::List calendarUrlList() const;
+
+ void insertExtraSound(const Sound &sound);
+ void setExtraSoundList(const Sound::List &soundList);
+ Sound::List extraSoundList() const;
+
+ void insertExtraPhoto(const Picture &picture);
+ void setExtraPhotoList(const Picture::List &pictureList);
+ Picture::List extraPhotoList() const;
+
+ void insertExtraLogo(const Picture &logo);
+ void setExtraLogoList(const Picture::List &logoList);
+ Picture::List extraLogoList() const;
+
+ ResourceLocatorUrl::List extraUrlList() const;
+ void setExtraUrlList(const ResourceLocatorUrl::List &urlList);
+ void insertExtraUrl(const ResourceLocatorUrl &url);
+
+ //Member
+ void insertMember(const QString &member);
+ void setMembers(const QStringList &c);
+ QStringList members() const;
+
+ //Relation
+ void insertRelationShip(const Related &related);
+ void setRelationShips(const Related::List &c);
+ Related::List relationShips() const;
+
+ //Source
+ void insertSourceUrl(const QUrl &url);
+ void setSourcesUrlList(const QVector<QUrl> &urlList);
+ QVector<QUrl> sourcesUrlList() const;
+
+ //Impp
+ Impp::List imppList() const;
+ void setImppList(const Impp::List &imppList);
+ void insertImpp(const Impp &impp);
+
+private:
+ class Private;
+ QSharedDataPointer<Private> d;
+};
+
+KCONTACTS_EXPORT QDataStream &operator<<(QDataStream &, const Addressee &);
+KCONTACTS_EXPORT QDataStream &operator>>(QDataStream &, Addressee &);
+
+}
+
+#define KCONTACTS_ADDRESSEE_METATYPE_DEFINED 1
+Q_DECLARE_METATYPE(KContacts::Addressee)
+
+#endif
--- /dev/null
+/*
+ This file is part of the KDE libraries
+ Copyright (C) 2003 Carsten Pfeiffer <pfeiffer@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation, version 2.
+
+ 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "addresseehelper.h"
+
+#include <kconfig.h>
+#include <klocalizedstring.h>
+#include <kconfiggroup.h>
+
+#include <QCoreApplication>
+
+using namespace KContacts;
+
+class Q_DECL_HIDDEN KContacts::AddresseeHelperPrivate
+{
+public:
+ QSet<QString> mTitles;
+ QSet<QString> mPrefixes;
+ QSet<QString> mSuffixes;
+ bool mTradeAsFamilyName;
+};
+
+Q_GLOBAL_STATIC(AddresseeHelper, s_self)
+
+// static
+AddresseeHelper *AddresseeHelper::self()
+{
+ return s_self;
+}
+
+AddresseeHelper::AddresseeHelper()
+ : QObject()
+ , d(new AddresseeHelperPrivate)
+{
+ initSettings();
+}
+
+AddresseeHelper::~AddresseeHelper()
+{
+}
+
+static void addToSet(const QStringList &list, QSet<QString> &container)
+{
+ QStringList::ConstIterator it;
+ QStringList::ConstIterator end(list.end());
+ for (it = list.begin(); it != end; ++it) {
+ if (!(*it).isEmpty()) {
+ container.insert(*it);
+ }
+ }
+}
+
+void AddresseeHelper::initSettings()
+{
+ d->mTitles.clear();
+ d->mSuffixes.clear();
+ d->mPrefixes.clear();
+
+ d->mTitles.insert(i18n("Dr."));
+ d->mTitles.insert(i18n("Miss"));
+ d->mTitles.insert(i18n("Mr."));
+ d->mTitles.insert(i18n("Mrs."));
+ d->mTitles.insert(i18n("Ms."));
+ d->mTitles.insert(i18n("Prof."));
+
+ d->mSuffixes.insert(i18n("I"));
+ d->mSuffixes.insert(i18n("II"));
+ d->mSuffixes.insert(i18n("III"));
+ d->mSuffixes.insert(i18n("Jr."));
+ d->mSuffixes.insert(i18n("Sr."));
+
+ d->mPrefixes.insert(QStringLiteral("van"));
+ d->mPrefixes.insert(QStringLiteral("von"));
+ d->mPrefixes.insert(QStringLiteral("de"));
+
+ KConfig _config(QStringLiteral("kabcrc"), KConfig::NoGlobals);
+ KConfigGroup config(&_config, "General");
+
+ addToSet(config.readEntry("Prefixes", QStringList()), d->mTitles);
+ addToSet(config.readEntry("Inclusions", QStringList()), d->mPrefixes);
+ addToSet(config.readEntry("Suffixes", QStringList()), d->mSuffixes);
+ d->mTradeAsFamilyName = config.readEntry("TradeAsFamilyName", true);
+}
+
+bool AddresseeHelper::containsTitle(const QString &title) const
+{
+ return d->mTitles.contains(title);
+}
+
+bool AddresseeHelper::containsPrefix(const QString &prefix) const
+{
+ return d->mPrefixes.contains(prefix);
+}
+
+bool AddresseeHelper::containsSuffix(const QString &suffix) const
+{
+ return d->mSuffixes.contains(suffix);
+}
+
+bool AddresseeHelper::tradeAsFamilyName() const
+{
+ return d->mTradeAsFamilyName;
+}
--- /dev/null
+/*
+ This file is part of the KDE libraries
+ Copyright (C) 2003 Carsten Pfeiffer <pfeiffer@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation, version 2.
+
+ 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KCONTACTS_ADDRESSEEHELPER_H
+#define KCONTACTS_ADDRESSEEHELPER_H
+
+#include "kcontacts_export.h"
+
+#include <QtCore/QObject>
+#include <QtCore/QStringList>
+#include <QtCore/QSet>
+
+namespace KContacts
+{
+class AddresseeHelperPrivate;
+
+/**
+ * This singleton class stores static data, which is shared
+ * by all Addressee objects. It maintains three lists of
+ * strings, which can be queried using this class:
+ *
+ * - a list of honoric prefixes, like "Mrs.", "Prof." etc,
+ * see containsTitle()
+ * - a list of inclusions, such as "van" or "de", see
+ * containsPrefix()
+ * - a list of honoric suffixes, such as "I" or "Jr.", see
+ * containsSuffix()
+ *
+ * All of these lists have a hardcoded and a configurable
+ * part. The configurable part is found in @c kabcrc, group
+ * @c General, fields @c Prefixes, @c Inclusions, and
+ * @c Suffixes.
+ *
+ * In addition to the above, this class stores one conveniece
+ * setting: it stores whether or not a single name component
+ * should be interpreted as a family name (see
+ * tradeAsFamilyName()). The corresponding configuration
+ * field is @c TradeAsFamilyName.
+ */
+class KCONTACTS_EXPORT AddresseeHelper : public QObject
+{
+ Q_OBJECT
+
+public:
+ /**
+ * Singleton interface to this class
+ *
+ * @return a pointer to the unique instance of this class.
+ */
+ static AddresseeHelper *self();
+
+ /**
+ * Queries the list of honoric prefixes.
+ *
+ * @param title the honoric prefix to search for
+ * @return @c true, if @p title was found in the list,
+ * @c false otherwise
+ */
+ bool containsTitle(const QString &title) const;
+
+ /**
+ * Queries the list of inclusions.
+ *
+ * @param prefix the inclusion to search for
+ * @return @c true, if @p prefix was found in the list,
+ * @c false otherwise
+ */
+ bool containsPrefix(const QString &prefix) const;
+
+ /**
+ * Queries the list of honoric suffixes.
+ *
+ * @param suffix the honoric suffix to search for
+ * @return @c true, if @p suffix was found in the list,
+ * @c false otherwise
+ */
+ bool containsSuffix(const QString &suffix) const;
+
+ /**
+ * Returns whether or not a single name component should
+ * be interpreted as a family name.
+ *
+ * @return @c true if single name component is a family name,
+ * @c false otherwise.
+ */
+ bool tradeAsFamilyName() const;
+
+ /** @internal */
+ AddresseeHelper();
+
+ ~AddresseeHelper();
+
+public Q_SLOTS:
+ /**
+ * Recreates the static data and reparses the configuration.
+ */
+ void initSettings();
+
+private:
+ QScopedPointer<AddresseeHelperPrivate> d;
+};
+
+}
+
+#endif
--- /dev/null
+/*
+ This file is part of the KContacts framework.
+ Copyright (c) 2002 Jost Schenck <jost@schenck.de>
+ 2003 Tobias Koenig <tokoe@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "addresseelist.h"
+#include "field.h"
+#include "sortmode.h"
+#include "kcontacts_debug.h"
+
+#include <QtCore/QSharedData>
+
+using namespace KContacts;
+
+//
+//
+// Traits
+//
+//
+
+SortingTraits::Uid::Uid()
+ : d(Q_NULLPTR)
+{
+}
+
+SortingTraits::Uid::~Uid()
+{
+}
+
+bool SortingTraits::Uid::eq(const Addressee &a1, const Addressee &a2)
+{
+ // locale awareness doesn't make sense sorting ids
+ return QString::compare(a1.uid(), a2.uid()) == 0;
+}
+
+bool SortingTraits::Uid::lt(const Addressee &a1, const Addressee &a2)
+{
+ // locale awareness doesn't make sense sorting ids
+ return QString::compare(a1.uid(), a2.uid()) < 0;
+}
+
+SortingTraits::Name::Name()
+ : d(Q_NULLPTR)
+{
+}
+
+SortingTraits::Name::~Name()
+{
+}
+
+bool SortingTraits::Name::eq(const Addressee &a1, const Addressee &a2)
+{
+ return QString::localeAwareCompare(a1.name(), a2.name()) == 0;
+}
+
+bool SortingTraits::Name::lt(const Addressee &a1, const Addressee &a2)
+{
+ return QString::localeAwareCompare(a1.name(), a2.name()) < 0;
+}
+
+SortingTraits::FormattedName::FormattedName()
+ : d(Q_NULLPTR)
+{
+}
+
+SortingTraits::FormattedName::~FormattedName()
+{
+}
+
+bool SortingTraits::FormattedName::eq(const Addressee &a1, const Addressee &a2)
+{
+ return QString::localeAwareCompare(a1.formattedName(), a2.formattedName()) == 0;
+}
+
+bool SortingTraits::FormattedName::lt(const Addressee &a1, const Addressee &a2)
+{
+ return QString::localeAwareCompare(a1.formattedName(), a2.formattedName()) < 0;
+}
+
+SortingTraits::FamilyName::FamilyName()
+ : d(Q_NULLPTR)
+{
+}
+
+SortingTraits::FamilyName::~FamilyName()
+{
+}
+
+bool SortingTraits::FamilyName::eq(const Addressee &a1, const Addressee &a2)
+{
+ return
+ QString::localeAwareCompare(a1.familyName(), a2.familyName()) == 0 &&
+ QString::localeAwareCompare(a1.givenName(), a2.givenName()) == 0;
+}
+
+bool SortingTraits::FamilyName::lt(const Addressee &a1, const Addressee &a2)
+{
+ int family = QString::localeAwareCompare(a1.familyName(), a2.familyName());
+ if (0 == family) {
+ return QString::localeAwareCompare(a1.givenName(), a2.givenName()) < 0;
+ } else {
+ return family < 0;
+ }
+}
+
+SortingTraits::GivenName::GivenName()
+ : d(Q_NULLPTR)
+{
+}
+
+SortingTraits::GivenName::~GivenName()
+{
+}
+
+bool SortingTraits::GivenName::eq(const Addressee &a1, const Addressee &a2)
+{
+ return
+ QString::localeAwareCompare(a1.givenName(), a2.givenName()) == 0 &&
+ QString::localeAwareCompare(a1.familyName(), a2.familyName()) == 0;
+}
+
+bool SortingTraits::GivenName::lt(const Addressee &a1, const Addressee &a2)
+{
+ int given = QString::localeAwareCompare(a1.givenName(), a2.givenName());
+ if (0 == given) {
+ return QString::localeAwareCompare(a1.familyName(), a2.familyName()) < 0;
+ } else {
+ return given < 0;
+ }
+}
+
+//
+//
+// AddresseeList
+//
+//
+
+static Field *sActiveField = Q_NULLPTR;
+
+class Q_DECL_HIDDEN AddresseeList::Private : public QSharedData
+{
+public:
+ Private()
+ : mReverseSorting(false)
+ , mActiveSortingCriterion(FormattedName)
+ {
+ }
+
+ Private(const Private &other)
+ : QSharedData(other)
+ {
+ mReverseSorting = other.mReverseSorting;
+ mActiveSortingCriterion = other.mActiveSortingCriterion;
+ }
+
+ bool mReverseSorting;
+ SortingCriterion mActiveSortingCriterion;
+};
+
+AddresseeList::AddresseeList()
+ : QVector<Addressee>()
+ , d(new Private)
+{
+}
+
+AddresseeList::~AddresseeList()
+{
+}
+
+AddresseeList::AddresseeList(const AddresseeList &other)
+ : QVector<Addressee>(other)
+ , d(other.d)
+{
+}
+
+AddresseeList::AddresseeList(const QVector<Addressee> &list)
+ : QVector<Addressee>(list)
+ , d(new Private)
+{
+}
+
+AddresseeList &AddresseeList::operator=(const AddresseeList &other)
+{
+ if (this != &other) {
+ QVector<Addressee>::operator=(other);
+ d = other.d;
+ }
+
+ return *this;
+}
+
+QString AddresseeList::toString() const
+{
+ QString str;
+
+ str += QLatin1String("AddresseeList {\n");
+ str += QStringLiteral(" Reverse Order: %1\n").arg(d->mReverseSorting ?
+ QStringLiteral("true") :
+ QStringLiteral("false"));
+
+ QString crit;
+ switch (d->mActiveSortingCriterion) {
+ case Uid:
+ crit = QStringLiteral("Uid");
+ break;
+ case Name:
+ crit = QStringLiteral("Name");
+ break;
+ case FormattedName:
+ crit = QStringLiteral("FormattedName");
+ break;
+ case FamilyName:
+ crit = QStringLiteral("FamilyName");
+ break;
+ case GivenName:
+ crit = QStringLiteral("GivenName");
+ break;
+ default:
+ crit = QStringLiteral("unknown -- update dump method");
+ break;
+ }
+
+ str += QStringLiteral(" Sorting criterion: %1\n").arg(crit);
+#if 0 //code commented in loop => comment it too
+ for (const_iterator it = begin(); it != end(); ++it) {
+// str += (*it).toString();
+ }
+#endif
+
+ str += QLatin1String("}\n");
+
+ return str;
+}
+
+void AddresseeList::setReverseSorting(bool reverseSorting)
+{
+ d->mReverseSorting = reverseSorting;
+}
+
+bool AddresseeList::reverseSorting() const
+{
+ return d->mReverseSorting;
+}
+
+void AddresseeList::sortBy(SortingCriterion c)
+{
+ d->mActiveSortingCriterion = c;
+ if (Uid == c) {
+ sortByTrait<SortingTraits::Uid>();
+ } else if (Name == c) {
+ sortByTrait<SortingTraits::Name>();
+ } else if (FormattedName == c) {
+ sortByTrait<SortingTraits::FormattedName>();
+ } else if (FamilyName == c) {
+ sortByTrait<SortingTraits::FamilyName>();
+ } else if (GivenName == c) {
+ sortByTrait<SortingTraits::GivenName>();
+ } else {
+ qCCritical(KCONTACTS_LOG) << "AddresseeList sorting criterion passed for which a trait is not known."
+ << "No sorting done.";
+ }
+}
+
+void AddresseeList::sort()
+{
+ sortBy(d->mActiveSortingCriterion);
+}
+
+template<class Trait>
+void AddresseeList::sortByTrait()
+{
+ // FIXME: better sorting algorithm, bubblesort is not acceptable for larger lists.
+ //
+ // for i := 1 to n - 1
+ // do for j := 1 to n - i
+ // do if A[j] > A[j+1]
+ // then temp := A[j]
+ // A[j] := A[j + 1]
+ // A[j + 1 ] := temp
+
+ iterator i1 = begin();
+ iterator endIt = end();
+ --endIt;
+ if (i1 == endIt) { // don't need sorting
+ return;
+ }
+
+ iterator i2 = endIt;
+ while (i1 != endIt) {
+ iterator j1 = begin();
+ iterator j2 = j1;
+ ++j2;
+ while (j1 != i2) {
+ if ((!d->mReverseSorting && Trait::lt(*j2, *j1)) ||
+ (d->mReverseSorting && Trait::lt(*j1, *j2))) {
+ qSwap(*j1, *j2);
+ }
+ ++j1;
+ ++j2;
+ }
+ ++i1;
+ --i2;
+ }
+}
+
+void AddresseeList::sortByField(Field *field)
+{
+ if (!field) {
+ qCWarning(KCONTACTS_LOG) << "sortByField called with no active sort field";
+ return;
+ }
+
+ sActiveField = field;
+
+ if (count() == 0) {
+ return;
+ }
+
+ KContacts::FieldSortMode *mode = new KContacts::FieldSortMode(sActiveField, !d->mReverseSorting);
+
+ KContacts::Addressee::setSortMode(mode);
+ qSort(*this);
+ KContacts::Addressee::setSortMode(Q_NULLPTR);
+
+ delete mode;
+}
+
+void AddresseeList::sortByMode(SortMode *mode)
+{
+ if (count() == 0) {
+ return;
+ }
+
+ KContacts::Addressee::setSortMode(mode);
+ qSort(*this);
+ KContacts::Addressee::setSortMode(Q_NULLPTR);
+}
+
+SortingCriterion AddresseeList::sortingCriterion() const
+{
+ return d->mActiveSortingCriterion;
+}
+
+Field *AddresseeList::sortingField() const
+{
+ return sActiveField;
+}
--- /dev/null
+/*
+ This file is part of the KContacts framework.
+ Copyright (c) 2002 Jost Schenck <jost@schenck.de>
+ 2003 Tobias Koenig <tokoe@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KCONTACTS_ADDRESSEELIST_H
+#define KCONTACTS_ADDRESSEELIST_H
+
+#include "kcontacts_export.h"
+#include <QtCore/QSharedDataPointer>
+#include <QtCore/QVector>
+
+namespace KContacts
+{
+
+class Field;
+class SortMode;
+class Addressee;
+
+/**
+ * Each trait must implement one static function for equality, one for "less
+ * than". Class name should be the field name. A trait does not necessarily
+ * have to stick to just one field: a trait sorting by family name can e.g.
+ * sort addressees with equal family name by given name.
+ *
+ * If you want to implement reverse sorting, you do not have to write another
+ * trait, as AddresseeList takes care of that.
+ */
+namespace SortingTraits
+{
+
+class KCONTACTS_EXPORT Uid
+{
+public:
+ /**
+ * Creates an instance.
+ */
+ Uid();
+
+ /**
+ * Destroys the instance.
+ */
+ ~Uid();
+
+ /**
+ * "Equal" compare method
+ *
+ * @return @c true if the first parameter is equal to the second
+ * when comparing the uid attribute.
+ *
+ * @see Addressee::uid()
+ * @see QString::compare()
+ */
+ static bool eq(const Addressee &a1, const Addressee &a2);
+
+ /**
+ * "Less-Than" compare method
+ *
+ * @return @c true if the first parameter is "less-than" the second
+ * when comparing the uid attribute.
+ *
+ * @see Addressee::uid()
+ * @see QString::compare()
+ */
+ static bool lt(const Addressee &a1, const Addressee &a2);
+
+private:
+ Q_DISABLE_COPY(Uid)
+ class Private;
+ Private *const d;
+};
+
+class KCONTACTS_EXPORT Name
+{
+public:
+ /**
+ * Creates an instance.
+ */
+ Name();
+
+ /**
+ * Destroys the instance.
+ */
+ ~Name();
+
+ /**
+ * "Equal" compare method
+ *
+ * @return @c true if the first parameter is equal to the second
+ * when comparing the name attribute.
+ *
+ * @see Addressee::name()
+ * @see QString::localeAwareCompare()
+ */
+ static bool eq(const Addressee &a1, const Addressee &a2);
+
+ /**
+ * "Less-Than" compare method
+ *
+ * @return @c true if the first parameter is "less-than" the second
+ * when comparing the name attribute.
+ *
+ * @see Addressee::name()
+ * @see QString::localeAwareCompare()
+ */
+ static bool lt(const Addressee &a1, const Addressee &a2);
+
+private:
+ Q_DISABLE_COPY(Name)
+ class Private;
+ Private *const d;
+};
+
+class KCONTACTS_EXPORT FormattedName
+{
+public:
+ /**
+ * Creates an instance.
+ */
+ FormattedName();
+
+ /**
+ * Destroys the instance.
+ */
+ ~FormattedName();
+
+ /**
+ * "Equal" compare method
+ *
+ * @return @c true if the first parameter is equal to the second
+ * when comparing the formatted name attribute.
+ *
+ * @see Addressee::formattedName()
+ * @see QString::localeAwareCompare()
+ */
+ static bool eq(const Addressee &a1, const Addressee &a2);
+
+ /**
+ * "Less-Than" compare method
+ *
+ * @return @c true if the first parameter is "less-than" the second
+ * when comparing the formatted name attribute.
+ *
+ * @see Addressee::formattedName()
+ * @see QString::localeAwareCompare()
+ */
+ static bool lt(const Addressee &a1, const Addressee &a2);
+
+private:
+ Q_DISABLE_COPY(FormattedName)
+ class Private;
+ Private *const d;
+};
+
+class KCONTACTS_EXPORT FamilyName // fallback to given name
+{
+public:
+ /**
+ * Creates an instance.
+ */
+ FamilyName();
+
+ /**
+ * Destroys the instance.
+ */
+ ~FamilyName();
+
+ /**
+ * "Equal" compare method
+ *
+ * @return @c true if the first parameter is equal to the second
+ * when comparing the family name and given name attributes.
+ *
+ * @see Addressee::familyName()
+ * @see Addressee::givenName()
+ * @see QString::localeAwareCompare()
+ */
+ static bool eq(const Addressee &a1, const Addressee &a2);
+
+ /**
+ * "Less-Than" compare method
+ *
+ * Falls back to comparing given name if equal
+ *
+ * @return @c true if the first parameter is "less-than" the second
+ * when comparing the family name attribute.
+ *
+ * @see Addressee::familyName()
+ * @see QString::localeAwareCompare()
+ */
+ static bool lt(const Addressee &a1, const Addressee &a2);
+
+private:
+ Q_DISABLE_COPY(FamilyName)
+ class Private;
+ Private *const d;
+};
+
+class KCONTACTS_EXPORT GivenName // fallback to family name
+{
+public:
+ /**
+ * Creates an instance.
+ */
+ GivenName();
+
+ /**
+ * Destroys the instance.
+ */
+ ~GivenName();
+
+ /**
+ * "Equal" compare method
+ *
+ * @return @c true if the first parameter is equal to the second
+ * when comparing the given name and family name attributes.
+ *
+ * @see Addressee::givenName()
+ * @see Addressee::familyName()
+ * @see QString::localeAwareCompare()
+ */
+ static bool eq(const Addressee &a1, const Addressee &a2);
+
+ /**
+ * "Less-Than" compare method
+ *
+ * Falls back to comparing family name if equal
+ *
+ * @return @c true if the first parameter is "less-than" the second
+ * when comparing the given name attribute.
+ *
+ * @see Addressee::givenName()
+ * @see QString::localeAwareCompare()
+ */
+ static bool lt(const Addressee &a1, const Addressee &a2);
+
+private:
+ Q_DISABLE_COPY(GivenName)
+ class Private;
+ Private *const d;
+};
+
+}
+
+/**
+ * Addressee attribute used for sorting.
+ */
+typedef enum {
+ Uid,
+ Name,
+ FormattedName,
+ FamilyName,
+ GivenName
+} SortingCriterion;
+
+/**
+ * @short a QValueList of Addressee, with sorting functionality
+ *
+ * This class extends the functionality of QValueList with
+ * sorting methods specific to the Addressee class. It can be used
+ * just like any other QValueList but is no template class.
+ *
+ * An AddresseeList does not automatically keep sorted when addressees
+ * are added or removed or the sorting order is changed, as this would
+ * slow down larger operations by sorting after every step. So after
+ * such operations you have to call {@link #sort} or {@link #sortBy} to
+ * create a defined order again.
+ *
+ * Iterator usage is inherited from QVector and extensively documented
+ * there. Please remember that the state of an iterator is undefined
+ * after any sorting operation.
+ *
+ * For the enumeration Type SortingCriterion, which specifies the
+ * field by the collection will be sorted, the following values exist:
+ * Uid, Name, FormattedName, FamilyName, GivenName.
+ *
+ * @author Jost Schenck jost@schenck.de
+ */
+class KCONTACTS_EXPORT AddresseeList : public QVector<Addressee>
+{
+public:
+ /**
+ * Creates a new addressee list.
+ */
+ AddresseeList();
+
+ /**
+ * Creates a new addressee list.
+ */
+ AddresseeList(const AddresseeList &other);
+
+ /**
+ * Creates a new addressee list.
+ */
+ AddresseeList(const QVector<Addressee> &list);
+
+ /**
+ * Destroys the addressee list.
+ */
+ ~AddresseeList();
+
+ /**
+ * Assignment operator.
+ *
+ * @param other the list to assign from
+ * @return a reference to @c this
+ */
+ AddresseeList &operator=(const AddresseeList &other);
+
+ /**
+ * Determines the direction of sorting. On change, the list
+ * will <em>not</em> automatically be resorted.
+ * @param reverseSorting <tt>true</tt> if sorting should be done reverse,
+ * <tt>false</tt> otherwise
+ */
+ void setReverseSorting(bool reverseSorting = true);
+
+ /**
+ * Returns the direction of sorting.
+ * @return <tt>true</tt> if sorting is done reverse, <tt>false</tt> otherwise
+ */
+ bool reverseSorting() const;
+
+ /**
+ * Sorts this list by a specific criterion.
+ * @param c the criterion by which should be sorted
+ */
+ void sortBy(SortingCriterion c);
+
+ /**
+ * Sorts this list by a specific field. If no parameter is given, the
+ * last used Field object will be used.
+ * @param field pointer to the Field object to be sorted by
+ */
+ void sortByField(Field *field = Q_NULLPTR);
+
+ /**
+ * Sorts this list by a specific sorting mode.
+ * @param mode pointer to the sorting mode object to be sorted by
+ */
+ void sortByMode(SortMode *mode = Q_NULLPTR);
+
+ /**
+ * Sorts this list by its active sorting criterion. This normally is the
+ * criterion of the last sortBy operation or <tt>FormattedName</tt> if up
+ * to now there has been no sortBy operation.
+ *
+ * Please note that the sorting trait of the last {@link #sortByTrait}
+ * method call is not remembered and thus the action can not be repeated
+ * by this method.
+ */
+ void sort();
+
+ /**
+ * Templated sort function. You normally will not want to use this but
+ * {@link #sortBy} and {@link #sort} instead as the existing sorting
+ * criteria completely suffice for most cases.
+ *
+ * However, if you do want to use some special sorting criterion, you can
+ * write a trait class that will be provided to this templated method.
+ * This trait class has to have a class declaration like the following:
+ * \code
+ * class MySortingTrait {
+ * public:
+ * // eq returns true if a1 and a2 are equal
+ * static bool eq(KContacts::Addressee a1, KContacts::Addressee a2);
+ * // lt returns true is a1 is "less than" a2
+ * static bool lt(KContacts::Addressee a1, KContacts::Addressee a2);
+ * };
+ * \endcode
+ * You can then pass this class to the sortByTrait method like this:
+ * \code
+ * myAddresseelist.sortByTrait<MySortingTrait>();
+ * \endcode
+ * Please note that the {@link #sort} method can not be used to repeat the
+ * sorting of the last <tt>sortByTrait</tt> action.
+ *
+ * Right now this method uses the bubble sort algorithm. This should be
+ * replaced for a better one when I have time.
+ */
+ template<class Trait> void sortByTrait();
+
+ /**
+ * Returns the active sorting criterion, ie the sorting criterion that
+ * will be used by a {@link #sort} call.
+ */
+ SortingCriterion sortingCriterion() const;
+
+ /**
+ * Returns the active sorting field, ie a pointer to the Field object
+ * which was used for the last {@link #sortByField} operation.
+ * This function returns the last GLOBAL sorting field, not
+ * the class specific one.
+ * You're a lot better off by keeping track of this locally.
+ */
+ Field *sortingField() const;
+
+ /**
+ * Returns a string representation of the addressee list.
+ */
+ QString toString() const;
+
+private:
+ class Private;
+ QSharedDataPointer<Private> d;
+};
+
+}
+
+#endif
--- /dev/null
+/*
+ This file is part of the KContacts framework.
+ Copyright (c) 2015 Laurent Montel <montel@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "calendarurl.h"
+
+#include <QMap>
+#include <QUrl>
+#include <QDataStream>
+#include <qstringlist.h>
+
+using namespace KContacts;
+
+class Q_DECL_HIDDEN CalendarUrl::Private : public QSharedData
+{
+public:
+ Private()
+ {
+ }
+
+ Private(const Private &other)
+ : QSharedData(other)
+ {
+ parameters = other.parameters;
+ type = other.type;
+ url = other.url;
+ }
+ static QString typeToString(CalendarUrl::CalendarType type);
+ QMap<QString, QStringList> parameters;
+ QUrl url;
+ CalendarUrl::CalendarType type;
+
+};
+
+QString CalendarUrl::Private::typeToString(CalendarUrl::CalendarType type)
+{
+ QString ret;
+ switch (type) {
+ case Unknown:
+ case EndCalendarType:
+ ret = QStringLiteral("Unknown");
+ break;
+ case FBUrl:
+ ret = QStringLiteral("FreeBusy");
+ break;
+ case CALUri:
+ ret = QStringLiteral("CalUri");
+ break;
+ case CALADRUri:
+ ret = QStringLiteral("Caladruri");
+ break;
+ }
+ return ret;
+}
+
+CalendarUrl::CalendarUrl()
+ : d(new Private)
+{
+ d->type = Unknown;
+}
+
+CalendarUrl::CalendarUrl(CalendarUrl::CalendarType type)
+ : d(new Private)
+{
+ d->type = type;
+}
+
+CalendarUrl::CalendarUrl(const CalendarUrl &other)
+ : d(other.d)
+{
+}
+
+CalendarUrl::~CalendarUrl()
+{
+
+}
+
+QMap<QString, QStringList> CalendarUrl::parameters() const
+{
+ return d->parameters;
+}
+
+bool CalendarUrl::operator==(const CalendarUrl &other) const
+{
+ return (d->parameters == other.parameters()) && (d->type == other.type()) && (d->url == other.url());
+}
+
+bool CalendarUrl::operator!=(const CalendarUrl &other) const
+{
+ return !(other == *this);
+}
+
+CalendarUrl &CalendarUrl::operator=(const CalendarUrl &other)
+{
+ if (this != &other) {
+ d = other.d;
+ }
+
+ return *this;
+}
+
+QString CalendarUrl::toString() const
+{
+ QString str;
+ str += QLatin1String("CalendarUrl {\n");
+ str += QStringLiteral(" url: %1\n").arg(d->url.toString());
+ str += QStringLiteral(" type: %1\n").arg(CalendarUrl::Private::typeToString(d->type));
+ if (!d->parameters.isEmpty()) {
+ QMapIterator<QString, QStringList> i(d->parameters);
+ QString param;
+ while (i.hasNext()) {
+ i.next();
+ param += QStringLiteral("%1 %2").arg(i.key(), i.value().join(QStringLiteral(",")));
+ }
+ str += QStringLiteral(" parameters: %1\n").arg(param);
+ }
+ str += QLatin1String("}\n");
+ return str;
+}
+
+void CalendarUrl::setParameters(const QMap<QString, QStringList> ¶ms)
+{
+ d->parameters = params;
+}
+
+bool CalendarUrl::isValid() const
+{
+ return (d->type != Unknown) && (d->url.isValid());
+}
+
+void CalendarUrl::setType(CalendarUrl::CalendarType type)
+{
+ d->type = type;
+}
+
+CalendarUrl::CalendarType CalendarUrl::type() const
+{
+ return d->type;
+}
+
+void CalendarUrl::setUrl(const QUrl &url)
+{
+ d->url = url;
+}
+
+QUrl CalendarUrl::url() const
+{
+ return d->url;
+}
+
+QDataStream &KContacts::operator<<(QDataStream &s, const CalendarUrl &calUrl)
+{
+ return s << calUrl.d->parameters << (uint)calUrl.d->type << calUrl.d->url;
+}
+
+QDataStream &KContacts::operator>>(QDataStream &s, CalendarUrl &calUrl)
+{
+ uint type;
+ s >> calUrl.d->parameters >> type >> calUrl.d->url;
+ calUrl.d->type = static_cast<CalendarUrl::CalendarType>(type);
+ return s;
+}
+
--- /dev/null
+/*
+ This file is part of the KContacts framework.
+ Copyright (c) 2015 Laurent Montel <montel@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef CALENDARURL_H
+#define CALENDARURL_H
+#include "kcontacts_export.h"
+
+#include <QtCore/QSharedDataPointer>
+#include <QtCore/QString>
+#include <QtCore/QMap>
+class QUrl;
+/** @short Class that holds a Calendar Url (FBURL/CALADRURI/CALURI)
+ * @since 4.14.6
+ */
+
+namespace KContacts
+{
+
+class KCONTACTS_EXPORT CalendarUrl
+{
+ friend KCONTACTS_EXPORT QDataStream &operator<<(QDataStream &, const CalendarUrl &);
+ friend KCONTACTS_EXPORT QDataStream &operator>>(QDataStream &, CalendarUrl &);
+public:
+ enum CalendarType {
+ Unknown = 0,
+ FBUrl,
+ CALUri,
+ CALADRUri,
+ EndCalendarType
+ };
+
+ CalendarUrl();
+ CalendarUrl(CalendarUrl::CalendarType type);
+ CalendarUrl(const CalendarUrl &other);
+
+ ~CalendarUrl();
+
+ typedef QVector<CalendarUrl> List;
+
+ bool isValid() const;
+
+ void setType(CalendarUrl::CalendarType type);
+ CalendarUrl::CalendarType type() const;
+
+ void setUrl(const QUrl &url);
+ QUrl url() const;
+
+ void setParameters(const QMap<QString, QStringList> ¶ms);
+ QMap<QString, QStringList> parameters() const;
+
+ bool operator==(const CalendarUrl &other) const;
+ bool operator!=(const CalendarUrl &other) const;
+
+ CalendarUrl &operator=(const CalendarUrl &other);
+
+ QString toString() const;
+private:
+ class Private;
+ QSharedDataPointer<Private> d;
+};
+
+KCONTACTS_EXPORT QDataStream &operator<<(QDataStream &stream, const CalendarUrl &object);
+
+KCONTACTS_EXPORT QDataStream &operator>>(QDataStream &stream, CalendarUrl &object);
+
+}
+Q_DECLARE_TYPEINFO(KContacts::CalendarUrl, Q_MOVABLE_TYPE);
+#endif // CALENDARURL_H
--- /dev/null
+/*
+ This file is part of the KContacts framework.
+ Copyright (c) 2008 Tobias Koenig <tokoe@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "contactgroup.h"
+
+#include <QtCore/QMap>
+#include <QtCore/QSharedData>
+#include <QtCore/QString>
+#include <QtCore/QUuid>
+
+using namespace KContacts;
+
+class Q_DECL_HIDDEN ContactGroup::ContactReference::ContactReferencePrivate : public QSharedData
+{
+public:
+ ContactReferencePrivate()
+ : QSharedData()
+ {
+ }
+
+ ContactReferencePrivate(const ContactReferencePrivate &other)
+ : QSharedData(other)
+ {
+ mUid = other.mUid;
+ mPreferredEmail = other.mPreferredEmail;
+ mCustoms = other.mCustoms;
+ }
+
+ QString mUid;
+ QString mGid;
+ QString mPreferredEmail;
+ QMap<QString, QString> mCustoms;
+};
+
+ContactGroup::ContactReference::ContactReference()
+ : d(new ContactReferencePrivate)
+{
+}
+
+ContactGroup::ContactReference::ContactReference(const ContactReference &other)
+ : d(other.d)
+{
+}
+
+ContactGroup::ContactReference::ContactReference(const QString &uid)
+ : d(new ContactReferencePrivate)
+{
+ d->mUid = uid;
+}
+
+ContactGroup::ContactReference::~ContactReference()
+{
+}
+
+void ContactGroup::ContactReference::setUid(const QString &uid)
+{
+ d->mUid = uid;
+}
+
+QString ContactGroup::ContactReference::uid() const
+{
+ return d->mUid;
+}
+
+void ContactGroup::ContactReference::setGid(const QString &gid)
+{
+ d->mGid = gid;
+}
+
+QString ContactGroup::ContactReference::gid() const
+{
+ return d->mGid;
+}
+
+void ContactGroup::ContactReference::setPreferredEmail(const QString &email)
+{
+ d->mPreferredEmail = email;
+}
+
+QString ContactGroup::ContactReference::preferredEmail() const
+{
+ return d->mPreferredEmail;
+}
+
+void ContactGroup::ContactReference::insertCustom(const QString &key, const QString &value)
+{
+ d->mCustoms.insert(key, value);
+}
+
+void ContactGroup::ContactReference::removeCustom(const QString &key)
+{
+ d->mCustoms.remove(key);
+}
+
+QString ContactGroup::ContactReference::custom(const QString &key) const
+{
+ return d->mCustoms.value(key);
+}
+
+ContactGroup::ContactReference &ContactGroup::ContactReference::operator=(
+ const ContactGroup::ContactReference &other)
+{
+ if (this != &other) {
+ d = other.d;
+ }
+
+ return *this;
+}
+
+bool ContactGroup::ContactReference::operator==(const ContactReference &other) const
+{
+ return d->mUid == other.d->mUid &&
+ d->mPreferredEmail == other.d->mPreferredEmail &&
+ d->mCustoms == other.d->mCustoms;
+}
+
+class Q_DECL_HIDDEN ContactGroup::ContactGroupReference::ContactGroupReferencePrivate : public QSharedData
+{
+public:
+ ContactGroupReferencePrivate()
+ : QSharedData()
+ {
+ }
+
+ ContactGroupReferencePrivate(const ContactGroupReferencePrivate &other)
+ : QSharedData(other)
+ {
+ mUid = other.mUid;
+ mCustoms = other.mCustoms;
+ }
+
+ QString mUid;
+ QMap<QString, QString> mCustoms;
+};
+
+ContactGroup::ContactGroupReference::ContactGroupReference()
+ : d(new ContactGroupReferencePrivate)
+{
+}
+
+ContactGroup::ContactGroupReference::ContactGroupReference(const ContactGroupReference &other)
+ : d(other.d)
+{
+}
+
+ContactGroup::ContactGroupReference::ContactGroupReference(const QString &uid)
+ : d(new ContactGroupReferencePrivate)
+{
+ d->mUid = uid;
+}
+
+ContactGroup::ContactGroupReference::~ContactGroupReference()
+{
+}
+
+void ContactGroup::ContactGroupReference::setUid(const QString &uid)
+{
+ d->mUid = uid;
+}
+
+QString ContactGroup::ContactGroupReference::uid() const
+{
+ return d->mUid;
+}
+
+void ContactGroup::ContactGroupReference::insertCustom(const QString &key, const QString &value)
+{
+ d->mCustoms.insert(key, value);
+}
+
+void ContactGroup::ContactGroupReference::removeCustom(const QString &key)
+{
+ d->mCustoms.remove(key);
+}
+
+QString ContactGroup::ContactGroupReference::custom(const QString &key) const
+{
+ return d->mCustoms.value(key);
+}
+
+ContactGroup::ContactGroupReference &ContactGroup::ContactGroupReference::operator=(
+ const ContactGroup::ContactGroupReference &other)
+{
+ if (this != &other) {
+ d = other.d;
+ }
+
+ return *this;
+}
+
+bool ContactGroup::ContactGroupReference::operator==(const ContactGroupReference &other) const
+{
+ return d->mUid == other.d->mUid &&
+ d->mCustoms == other.d->mCustoms;
+}
+
+class Q_DECL_HIDDEN ContactGroup::Data::DataPrivate : public QSharedData
+{
+public:
+ DataPrivate()
+ : QSharedData()
+ {
+ }
+
+ DataPrivate(const DataPrivate &other)
+ : QSharedData(other)
+ {
+ mName = other.mName;
+ mEmail = other.mEmail;
+ mCustoms = other.mCustoms;
+ }
+
+ QString mName;
+ QString mEmail;
+ QMap<QString, QString> mCustoms;
+};
+
+ContactGroup::Data::Data()
+ : d(new DataPrivate)
+{
+}
+
+ContactGroup::Data::Data(const Data &other)
+ : d(other.d)
+{
+}
+
+ContactGroup::Data::Data(const QString &name, const QString &email)
+ : d(new DataPrivate)
+{
+ d->mName = name;
+ d->mEmail = email;
+}
+
+ContactGroup::Data::~Data()
+{
+}
+
+void ContactGroup::Data::setName(const QString &name)
+{
+ d->mName = name;
+}
+
+QString ContactGroup::Data::name() const
+{
+ return d->mName;
+}
+
+void ContactGroup::Data::setEmail(const QString &email)
+{
+ d->mEmail = email;
+}
+
+QString ContactGroup::Data::email() const
+{
+ return d->mEmail;
+}
+
+void ContactGroup::Data::insertCustom(const QString &key, const QString &value)
+{
+ d->mCustoms.insert(key, value);
+}
+
+void ContactGroup::Data::removeCustom(const QString &key)
+{
+ d->mCustoms.remove(key);
+}
+
+QString ContactGroup::Data::custom(const QString &key) const
+{
+ return d->mCustoms.value(key);
+}
+
+ContactGroup::Data &ContactGroup::Data::operator=(const ContactGroup::Data &other)
+{
+ if (this != &other) {
+ d = other.d;
+ }
+
+ return *this;
+}
+
+bool ContactGroup::Data::operator==(const Data &other) const
+{
+ return d->mName == other.d->mName &&
+ d->mEmail == other.d->mEmail &&
+ d->mCustoms == other.d->mCustoms;
+}
+
+class Q_DECL_HIDDEN ContactGroup::Private : public QSharedData
+{
+public:
+ Private()
+ : QSharedData()
+ , mIdentifier(QUuid::createUuid().toString().mid(1, 36)) //We avoid the curly braces so the string is RFC4122 compliant and can be used as urn
+ {
+ }
+
+ Private(const Private &other)
+ : QSharedData(other)
+ {
+ mIdentifier = other.mIdentifier;
+ mName = other.mName;
+ mContactReferences = other.mContactReferences;
+ mContactGroupReferences = other.mContactGroupReferences;
+ mDataObjects = other.mDataObjects;
+ }
+
+ QString mIdentifier;
+ QString mName;
+ ContactGroup::ContactReference::List mContactReferences;
+ ContactGroup::ContactGroupReference::List mContactGroupReferences;
+ ContactGroup::Data::List mDataObjects;
+};
+
+ContactGroup::ContactGroup()
+ : d(new Private)
+{
+}
+
+ContactGroup::ContactGroup(const ContactGroup &other)
+ : d(other.d)
+{
+}
+
+ContactGroup::ContactGroup(const QString &name)
+ : d(new Private)
+{
+ d->mName = name;
+}
+
+ContactGroup::~ContactGroup()
+{
+}
+
+void ContactGroup::setName(const QString &name)
+{
+ d->mName = name;
+}
+
+QString ContactGroup::name() const
+{
+ return d->mName;
+}
+
+void ContactGroup::setId(const QString &id)
+{
+ d->mIdentifier = id;
+}
+
+QString ContactGroup::id() const
+{
+ return d->mIdentifier;
+}
+
+unsigned int ContactGroup::count() const
+{
+ return d->mContactReferences.count() + d->mDataObjects.count();
+}
+
+unsigned int ContactGroup::contactReferenceCount() const
+{
+ return d->mContactReferences.count();
+}
+
+unsigned int ContactGroup::contactGroupReferenceCount() const
+{
+ return d->mContactGroupReferences.count();
+}
+
+unsigned int ContactGroup::dataCount() const
+{
+ return d->mDataObjects.count();
+}
+
+ContactGroup::ContactReference &ContactGroup::contactReference(unsigned int index)
+{
+ Q_ASSERT_X(index < (unsigned int)d->mContactReferences.count(),
+ "contactReference()", "index out of range");
+
+ return d->mContactReferences[index];
+}
+
+const ContactGroup::ContactReference &ContactGroup::contactReference(unsigned int index) const
+{
+ Q_ASSERT_X(index < (unsigned int)d->mContactReferences.count(),
+ "contactReference()", "index out of range");
+
+ return d->mContactReferences[index];
+}
+
+ContactGroup::ContactGroupReference &ContactGroup::contactGroupReference(unsigned int index)
+{
+ Q_ASSERT_X(index < (unsigned int)d->mContactGroupReferences.count(),
+ "contactGroupReference()", "index out of range");
+
+ return d->mContactGroupReferences[index];
+}
+
+const ContactGroup::ContactGroupReference &ContactGroup::contactGroupReference(
+ unsigned int index) const
+{
+ Q_ASSERT_X(index < (unsigned int)d->mContactGroupReferences.count(),
+ "contactGroupReference()", "index out of range");
+
+ return d->mContactGroupReferences[index];
+}
+
+ContactGroup::Data &ContactGroup::data(unsigned int index)
+{
+ Q_ASSERT_X(index < (unsigned int)d->mDataObjects.count(), "data()", "index out of range");
+
+ return d->mDataObjects[index];
+}
+
+const ContactGroup::Data &ContactGroup::data(unsigned int index) const
+{
+ Q_ASSERT_X(index < (unsigned int)d->mDataObjects.count(), "data()", "index out of range");
+
+ return d->mDataObjects[index];
+}
+
+void ContactGroup::append(const ContactReference &reference)
+{
+ d->mContactReferences.append(reference);
+}
+
+void ContactGroup::append(const ContactGroupReference &reference)
+{
+ d->mContactGroupReferences.append(reference);
+}
+
+void ContactGroup::append(const Data &data)
+{
+ d->mDataObjects.append(data);
+}
+
+void ContactGroup::remove(const ContactReference &reference)
+{
+ d->mContactReferences.removeOne(reference);
+}
+
+void ContactGroup::remove(const ContactGroupReference &reference)
+{
+ d->mContactGroupReferences.removeOne(reference);
+}
+
+void ContactGroup::remove(const Data &data)
+{
+ d->mDataObjects.removeOne(data);
+}
+
+void ContactGroup::removeAllContactReferences()
+{
+ d->mContactReferences.clear();
+}
+
+void ContactGroup::removeAllContactGroupReferences()
+{
+ d->mContactGroupReferences.clear();
+}
+
+void ContactGroup::removeAllContactData()
+{
+ d->mDataObjects.clear();
+}
+
+ContactGroup &ContactGroup::operator=(const ContactGroup &other)
+{
+ if (this != &other) {
+ d = other.d;
+ }
+
+ return *this;
+}
+
+bool ContactGroup::operator==(const ContactGroup &other) const
+{
+ return d->mIdentifier == other.d->mIdentifier &&
+ d->mName == other.d->mName &&
+ d->mContactReferences == other.d->mContactReferences &&
+ d->mContactGroupReferences == other.d->mContactGroupReferences &&
+ d->mDataObjects == other.d->mDataObjects;
+}
+
+QString ContactGroup::mimeType()
+{
+ return QStringLiteral("application/x-vnd.kde.contactgroup");
+}
--- /dev/null
+/*
+ This file is part of the KContacts framework.
+ Copyright (c) 2008 Tobias Koenig <tokoe@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KCONTACTS_CONTACTGROUP_H
+#define KCONTACTS_CONTACTGROUP_H
+
+#include <QtCore/QVector>
+#include <QtCore/QSharedDataPointer>
+#include <QtCore/QMetaType>
+
+#include "kcontacts_export.h"
+
+class QString;
+
+namespace KContacts
+{
+
+/**
+ * @short This class represents a group of contacts.
+ *
+ * It can contain two types of contacts, either a reference
+ * or data.
+ * The reference entry is just an unique identifier which
+ * identifies the real contact in the system.
+ * The data entry contains a name and an email address.
+ *
+ * @author Tobias Koenig <tokoe@kde.org>
+ * @since 4.3
+ */
+class KCONTACTS_EXPORT ContactGroup
+{
+public:
+
+ /**
+ * This class represents a contact reference
+ */
+ class KCONTACTS_EXPORT ContactReference
+ {
+ public:
+ /**
+ * A list of contact references.
+ */
+ typedef QVector<ContactReference> List;
+
+ /**
+ * Creates an empty contact reference.
+ */
+ ContactReference();
+
+ /**
+ * Creates a contact reference from an @p other reference.
+ */
+ ContactReference(const ContactReference &other);
+
+ /**
+ * Creates a contact reference for the given contact @p uid.
+ */
+ ContactReference(const QString &uid);
+
+ /**
+ * Destroys the contact reference.
+ */
+ ~ContactReference();
+
+ /**
+ * Sets the contact uid of the contact reference.
+ * @param uid identifier of the contact to reference
+ * @note That is the Akonadi Item ID of the contact that
+ * is referenced here.
+ */
+ void setUid(const QString &uid);
+
+ /**
+ * Returns the contact uid of the contact reference.
+ *
+ * @note That is the Akonadi Item ID of the contact that
+ * is referenced here.
+ */
+ QString uid() const;
+
+ /**
+ * Sets the contact gid of the contact reference.
+ * @param gid globally unique identifier of the contact to reference
+ * @since 4.12
+ */
+ void setGid(const QString &gid);
+
+ /**
+ * Returns the contact GID of the contact reference.
+ * @since 4.12
+ */
+ QString gid() const;
+
+ /**
+ * Sets the preferred email address.
+ */
+ void setPreferredEmail(const QString &email);
+
+ /**
+ * Returns the preferred email address, or an empty string
+ * if no preferred email address is set.
+ */
+ QString preferredEmail() const;
+
+ /**
+ * Inserts a custom entry.
+ * If an entry with the same @p key already exists, it is
+ * overwritten.
+ *
+ * @param key The unique key.
+ * @param value The value.
+ */
+ void insertCustom(const QString &key, const QString &value);
+
+ /**
+ * Removes the custom entry with the given @p key.
+ */
+ void removeCustom(const QString &key);
+
+ /**
+ * Returns the value for the given @p key, or an empty string
+ * if the entry for that key does not exists.
+ */
+ QString custom(const QString &key) const;
+
+ /**
+ * @internal
+ */
+ ContactReference &operator=(const ContactReference &other);
+
+ /**
+ * @internal
+ */
+ bool operator==(const ContactReference &other) const;
+
+ private:
+ class ContactReferencePrivate;
+ QSharedDataPointer<ContactReferencePrivate> d;
+ };
+
+ /**
+ * This class represents a contact group reference
+ */
+ class KCONTACTS_EXPORT ContactGroupReference
+ {
+ public:
+ /**
+ * A list of contact group references.
+ */
+ typedef QVector<ContactGroupReference> List;
+
+ /**
+ * Creates an empty contact group reference.
+ */
+ ContactGroupReference();
+
+ /**
+ * Creates a contact group reference from an @p other reference.
+ */
+ ContactGroupReference(const ContactGroupReference &other);
+
+ /**
+ * Creates a contact group reference for the given contact group @p uid.
+ */
+ ContactGroupReference(const QString &uid);
+
+ /**
+ * Destroys the contact group reference.
+ */
+ ~ContactGroupReference();
+
+ /**
+ * Sets the contact group uid of the contact group reference.
+ */
+ void setUid(const QString &uid);
+
+ /**
+ * Returns the contact group uid of the contact group reference.
+ */
+ QString uid() const;
+
+ /**
+ * Inserts a custom entry.
+ * If an entry with the same @p key already exists, it is
+ * overwritten.
+ *
+ * @param key The unique key.
+ * @param value The value.
+ */
+ void insertCustom(const QString &key, const QString &value);
+
+ /**
+ * Removes the custom entry with the given @p key.
+ */
+ void removeCustom(const QString &key);
+
+ /**
+ * Returns the value for the given @p key, or an empty string
+ * if the entry for that key does not exists.
+ */
+ QString custom(const QString &key) const;
+
+ /**
+ * @internal
+ */
+ ContactGroupReference &operator=(const ContactGroupReference &other);
+
+ /**
+ * @internal
+ */
+ bool operator==(const ContactGroupReference &other) const;
+
+ private:
+ class ContactGroupReferencePrivate;
+ QSharedDataPointer<ContactGroupReferencePrivate> d;
+ };
+
+ /**
+ * This class represents a contact data object
+ */
+ class KCONTACTS_EXPORT Data
+ {
+ public:
+ /**
+ * A list of contact data.
+ */
+ typedef QVector<Data> List;
+
+ /**
+ * Creates an empty contact data object.
+ */
+ Data();
+
+ /**
+ * Creates a contact data object from an @p other data object.
+ */
+ Data(const Data &other);
+
+ /**
+ * Creates a contact data object with the given @p name and @p email address.
+ */
+ Data(const QString &name, const QString &email);
+
+ /**
+ * Destroys the contact data object.
+ */
+ ~Data();
+
+ /**
+ * Sets the @p name of the contact data object.
+ */
+ void setName(const QString &name);
+
+ /**
+ * Returns the name of the contact data object.
+ */
+ QString name() const;
+
+ /**
+ * Sets the @p email address of the contact data object.
+ */
+ void setEmail(const QString &email);
+
+ /**
+ * Returns the email address of the contact data object.
+ */
+ QString email() const;
+
+ /**
+ * Inserts a custom entry.
+ * If an entry with the same @p key already exists, it is
+ * overwritten.
+ *
+ * @param key The unique key.
+ * @param value The value.
+ */
+ void insertCustom(const QString &key, const QString &value);
+
+ /**
+ * Removes the custom entry with the given @p key.
+ */
+ void removeCustom(const QString &key);
+
+ /**
+ * Returns the value for the given @p key, or an empty string
+ * if the entry for that key does not exists.
+ */
+ QString custom(const QString &key) const;
+
+ /**
+ * @internal
+ */
+ Data &operator=(const Data &other);
+
+ /**
+ * @internal
+ */
+ bool operator==(const Data &other) const;
+
+ private:
+ class DataPrivate;
+ QSharedDataPointer<DataPrivate> d;
+ };
+
+ /**
+ * A list of contact groups.
+ */
+ typedef QVector<ContactGroup> List;
+
+ /**
+ * Creates an empty contact group.
+ */
+ ContactGroup();
+
+ /**
+ * Creates a contact group from an @p other group.
+ */
+ ContactGroup(const ContactGroup &other);
+
+ /**
+ * Creates a contact group with the given name.
+ */
+ ContactGroup(const QString &name);
+
+ /**
+ * Destroys the contact group.
+ */
+ ~ContactGroup();
+
+ /**
+ * Sets the unique @p id of the contact group.
+ */
+ void setId(const QString &id);
+
+ /**
+ * Returns the unique id of the contact group.
+ */
+ QString id() const;
+
+ /**
+ * Sets the i18n'd @p name of the contact group.
+ */
+ void setName(const QString &name);
+
+ /**
+ * Returns the i18n'd name of the contact group.
+ */
+ QString name() const;
+
+ /**
+ * Returns the number of contacts in this group.
+ * That includes the contact references and contact data.
+ */
+ unsigned int count() const;
+
+ /**
+ * Returns the number of contact references in this group.
+ */
+ unsigned int contactReferenceCount() const;
+
+ /**
+ * Returns the number of group references in this group.
+ */
+ unsigned int contactGroupReferenceCount() const;
+
+ /**
+ * Returns the number of contact data objects in this group.
+ */
+ unsigned int dataCount() const;
+
+ /**
+ * Returns the contact reference at the given @p index.
+ */
+ ContactReference &contactReference(unsigned int index);
+
+ /**
+ * Returns the contact reference at the given @p index.
+ */
+ const ContactReference &contactReference(unsigned int index) const;
+
+ /**
+ * Returns the contact group reference at the given @p index.
+ */
+ ContactGroupReference &contactGroupReference(unsigned int index);
+
+ /**
+ * Returns the contact group reference at the given @p index.
+ */
+ const ContactGroupReference &contactGroupReference(unsigned int index) const;
+
+ /**
+ * Returns the contact data object at the given @p index.
+ */
+ Data &data(unsigned int index);
+
+ /**
+ * Returns the contact data object at the given @p index.
+ */
+ const Data &data(unsigned int index) const;
+
+ /**
+ * Appends a new contact @p reference to the contact group.
+ */
+ void append(const ContactReference &reference);
+
+ /**
+ * Appends a new contact group @p reference to the contact group.
+ */
+ void append(const ContactGroupReference &reference);
+
+ /**
+ * Appends a new contact @p data object to the contact group.
+ */
+ void append(const Data &data);
+
+ /**
+ * Removes the given contact @p reference from the contact group.
+ */
+ void remove(const ContactReference &reference);
+
+ /**
+ * Removes the given contact group @p reference from the contact group.
+ */
+ void remove(const ContactGroupReference &reference);
+
+ /**
+ * Removes the given contact @p data object from the contact group.
+ */
+ void remove(const Data &data);
+
+ /**
+ * Removes all contact references from the contact group.
+ */
+ void removeAllContactReferences();
+
+ /**
+ * Removes all contact group references from the contact group.
+ */
+ void removeAllContactGroupReferences();
+
+ /**
+ * Removes all contact data from the contact group.
+ */
+ void removeAllContactData();
+
+ /**
+ * @internal
+ */
+ ContactGroup &operator=(const ContactGroup &other);
+
+ /**
+ * @internal
+ */
+ bool operator==(const ContactGroup &other) const;
+
+ /**
+ * Returns the MIME type used for Contact Groups
+ */
+ static QString mimeType();
+
+private:
+ class Private;
+ QSharedDataPointer<Private> d;
+};
+
+}
+Q_DECLARE_TYPEINFO(KContacts::ContactGroup::ContactGroupReference, Q_MOVABLE_TYPE);
+Q_DECLARE_TYPEINFO(KContacts::ContactGroup::ContactReference, Q_MOVABLE_TYPE);
+
+#define KCONTACTS_CONTACTGROUP_METATYPE_DEFINED
+Q_DECLARE_METATYPE(KContacts::ContactGroup)
+
+#endif
--- /dev/null
+<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+
+<!--
+ Copyright (C) 2007 Tobias Koenig <tokoe@kde.org>
+
+ This library is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Library General Public License as published by
+ the Free Software Foundation; either version 2 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 Library General Public
+ License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+-->
+
+ <!-- The root element of every ContactGroup document -->
+ <xsd:element name="contactGroup">
+ <xsd:complexType>
+ <!-- A list of contacts or contact references -->
+ <xsd:choice minOccurs="0" maxOccurs="unbound">
+ <xsd:element name="contactData" type="contactDataType"/>
+ <xsd:element name="contactReference" type="contactReferenceType"/>
+ </xsd:choice>
+
+ <!-- The unique identifier of this contact group -->
+ <xsd:attribute name="uid" type="xsd:string" use="required" />
+
+ <!-- The i18n'ed name of this contact group -->
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+
+ <!-- The type for inline contacts. -->
+ <xsd:complexType name="contactDataType">
+ <xsd:sequence>
+ <!-- The i18n'ed name of this contact -->
+ <xsd:element name="name" type="xsd:string" minOccurs="1" maxOccurs="1"/>
+
+ <!-- The plain email address (without the name) of this contact -->
+ <xsd:element name="email" type="xsd:string" minOccurs="1" maxOccurs="1"/>
+
+ <!-- A list of custom fields for this contact -->
+ <xsd:element name="custom" minOccurs="0" maxOccurs="unbound">
+ <xsd:complexType>
+ <xsd:attribute name="key" type="xsd:string" use="required" />
+ <xsd:attribute name="value" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ </xsd:complexType>
+
+ <xsd:complexType name="contactReferenceType">
+ <xsd:sequence>
+ <!-- The uid of the contact this entry references -->
+ <xsd:element name="uid" type="xsd:string" minOccurs="1" maxOccurs="1"/>
+
+ <!-- The preferred email address which shall be used for the contact -->
+ <xsd:element name="preferredEmail" type="xsd:string" minOccurs="0" maxOccurs="1"/>
+
+ <!-- A list of custom fields for this contact -->
+ <xsd:element name="custom" minOccurs="0" maxOccurs="unbound">
+ <xsd:complexType>
+ <xsd:attribute name="key" type="xsd:string" use="required" />
+ <xsd:attribute name="value" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ </xsd:complexType>
+
+</xsd:schema>
--- /dev/null
+/*
+ This file is part of the KContacts framework.
+ Copyright (c) 2008 Tobias Koenig <tokoe@kde.org>
+ Copyright (c) 2008 Kevin Krammer <kevin.krammer@gmx.at>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "contactgrouptool.h"
+#include "contactgroup.h"
+
+#include <QtCore/QIODevice>
+#include <QtCore/QString>
+#include <QtCore/QDebug>
+
+#include <QtCore/QXmlStreamReader>
+#include <QtCore/QXmlStreamWriter>
+
+using namespace KContacts;
+
+class XmlContactGroupWriter : public QXmlStreamWriter
+{
+public:
+ XmlContactGroupWriter();
+
+ void write(const ContactGroup &group, QIODevice *device);
+ void write(const QVector<ContactGroup> &groupLis, QIODevice *device);
+
+private:
+ void writeGroup(const ContactGroup &group);
+ void writeContactReference(const ContactGroup::ContactReference &reference);
+ void writeContactGroupReference(const ContactGroup::ContactGroupReference &reference);
+ void writeData(const ContactGroup::Data &data);
+};
+
+XmlContactGroupWriter::XmlContactGroupWriter()
+{
+ setAutoFormatting(true);
+}
+
+void XmlContactGroupWriter::write(const ContactGroup &group, QIODevice *device)
+{
+ setDevice(device);
+
+ writeStartDocument();
+
+ writeGroup(group);
+
+ writeEndDocument();
+}
+
+void XmlContactGroupWriter::write(const QVector<ContactGroup> &groupList, QIODevice *device)
+{
+ setDevice(device);
+
+ writeStartDocument();
+
+ writeStartElement(QStringLiteral("contactGroupList"));
+
+ foreach (const ContactGroup &group, groupList) {
+ writeGroup(group);
+ }
+
+ writeEndElement();
+
+ writeEndDocument();
+}
+
+void XmlContactGroupWriter::writeGroup(const ContactGroup &group)
+{
+ writeStartElement(QStringLiteral("contactGroup"));
+ writeAttribute(QStringLiteral("uid"), group.id());
+ writeAttribute(QStringLiteral("name"), group.name());
+
+ for (uint i = 0; i < group.contactReferenceCount(); ++i) {
+ writeContactReference(group.contactReference(i));
+ }
+
+ for (uint i = 0; i < group.contactGroupReferenceCount(); ++i) {
+ writeContactGroupReference(group.contactGroupReference(i));
+ }
+
+ for (uint i = 0; i < group.dataCount(); ++i) {
+ writeData(group.data(i));
+ }
+
+ writeEndElement();
+}
+
+void XmlContactGroupWriter::writeContactReference(const ContactGroup::ContactReference &reference)
+{
+ writeStartElement(QStringLiteral("contactReference"));
+ writeAttribute(QStringLiteral("uid"), reference.uid());
+ writeAttribute(QStringLiteral("gid"), reference.gid());
+ if (!reference.preferredEmail().isEmpty()) {
+ writeAttribute(QStringLiteral("preferredEmail"), reference.preferredEmail());
+ }
+
+ // TODO: customs
+
+ writeEndElement();
+}
+
+void XmlContactGroupWriter::writeContactGroupReference(
+ const ContactGroup::ContactGroupReference &reference)
+{
+ writeStartElement(QStringLiteral("contactGroupReference"));
+ writeAttribute(QStringLiteral("uid"), reference.uid());
+
+ // TODO: customs
+
+ writeEndElement();
+}
+
+void XmlContactGroupWriter::writeData(const ContactGroup::Data &data)
+{
+ writeStartElement(QStringLiteral("contactData"));
+ writeAttribute(QStringLiteral("name"), data.name());
+ writeAttribute(QStringLiteral("email"), data.email());
+
+ // TODO: customs
+
+ writeEndElement();
+}
+
+class XmlContactGroupReader : public QXmlStreamReader
+{
+public:
+ XmlContactGroupReader();
+
+ bool read(QIODevice *device, ContactGroup &group);
+ bool read(QIODevice *device, QVector<ContactGroup> &groupList);
+
+private:
+ bool readGroup(ContactGroup &group);
+ bool readContactReference(ContactGroup::ContactReference &reference);
+ bool readContactGroupReference(ContactGroup::ContactGroupReference &reference);
+ bool readData(ContactGroup::Data &data);
+};
+
+XmlContactGroupReader::XmlContactGroupReader()
+{
+}
+
+bool XmlContactGroupReader::read(QIODevice *device, ContactGroup &group)
+{
+ setDevice(device);
+
+ while (!atEnd()) {
+ readNext();
+ if (isStartElement()) {
+ if (name() == QLatin1String("contactGroup")) {
+ return readGroup(group);
+ } else {
+ raiseError(QStringLiteral("The document does not describe a ContactGroup"));
+ }
+ }
+ }
+
+ return error() == NoError;
+}
+
+bool XmlContactGroupReader::read(QIODevice *device, QVector<ContactGroup> &groupList)
+{
+ setDevice(device);
+
+ int depth = 0;
+
+ while (!atEnd()) {
+ readNext();
+ if (isStartElement()) {
+ ++depth;
+ if (depth == 1) {
+ if (name() == QLatin1String("contactGroupList")) {
+ continue;
+ } else {
+ raiseError(QStringLiteral("The document does not describe a list of ContactGroup"));
+ }
+ } else if (depth == 2) {
+ if (name() == QLatin1String("contactGroup")) {
+ ContactGroup group;
+ if (!readGroup(group)) {
+ return false;
+ }
+
+ groupList.append(group);
+ } else {
+ raiseError(QStringLiteral("The document does not describe a list of ContactGroup"));
+ }
+ }
+ }
+
+ if (isEndElement()) {
+ --depth;
+ }
+ }
+
+ return error() == NoError;
+}
+
+bool XmlContactGroupReader::readGroup(ContactGroup &group)
+{
+ const QXmlStreamAttributes elementAttributes = attributes();
+ const QStringRef uid = elementAttributes.value(QLatin1String("uid"));
+ if (uid.isEmpty()) {
+ raiseError(QStringLiteral("ContactGroup is missing a uid"));
+ return false;
+ }
+
+ const QStringRef groupName = elementAttributes.value(QLatin1String("name"));
+ if (groupName.isEmpty()) {
+ raiseError(QStringLiteral("ContactGroup is missing a name"));
+ return false;
+ }
+
+ group.setId(uid.toString());
+ group.setName(groupName.toString());
+
+ while (!atEnd()) {
+ readNext();
+ if (isStartElement()) {
+ if (name() == QLatin1String("contactData")) {
+ ContactGroup::Data data;
+ if (!readData(data)) {
+ return false;
+ }
+ group.append(data);
+ } else if (name() == QLatin1String("contactReference")) {
+ ContactGroup::ContactReference reference;
+ if (!readContactReference(reference)) {
+ return false;
+ }
+ group.append(reference);
+ } else if (name() == QLatin1String("contactGroupReference")) {
+ ContactGroup::ContactGroupReference reference;
+ if (!readContactGroupReference(reference)) {
+ return false;
+ }
+ group.append(reference);
+ } else {
+ raiseError(QStringLiteral("The document does not describe a ContactGroup"));
+ }
+ }
+
+ if (isEndElement()) {
+ if (name() == QLatin1String("contactGroup")) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+bool XmlContactGroupReader::readData(ContactGroup::Data &data)
+{
+ const QXmlStreamAttributes elementAttributes = attributes();
+ const QStringRef email = elementAttributes.value(QLatin1String("email"));
+ if (email.isEmpty()) {
+ raiseError(QStringLiteral("ContactData is missing an email address"));
+ return false;
+ }
+
+ const QStringRef name = elementAttributes.value(QLatin1String("name"));
+
+ data.setName(name.toString());
+ data.setEmail(email.toString());
+
+ return true;
+}
+
+bool XmlContactGroupReader::readContactReference(ContactGroup::ContactReference &reference)
+{
+ const QXmlStreamAttributes elementAttributes = attributes();
+ const QStringRef uid = elementAttributes.value(QLatin1String("uid"));
+ const QStringRef gid = elementAttributes.value(QLatin1String("gid"));
+ if (uid.isEmpty() && gid.isEmpty()) {
+ raiseError(QStringLiteral("ContactReference is missing both uid and gid"));
+ return false;
+ }
+ const QStringRef preferredEmail = elementAttributes.value(QLatin1String("preferredEmail"));
+
+ reference.setUid(uid.toString());
+ reference.setGid(gid.toString());
+ reference.setPreferredEmail(preferredEmail.toString());
+
+ return true;
+}
+
+bool XmlContactGroupReader::readContactGroupReference(
+ ContactGroup::ContactGroupReference &reference)
+{
+ const QXmlStreamAttributes elementAttributes = attributes();
+ const QStringRef uid = elementAttributes.value(QLatin1String("uid"));
+ if (uid.isEmpty()) {
+ raiseError(QStringLiteral("ContactGroupReference is missing a uid"));
+ return false;
+ }
+
+ reference.setUid(uid.toString());
+
+ return true;
+}
+
+bool ContactGroupTool::convertFromXml(QIODevice *device, ContactGroup &group,
+ QString *errorMessage)
+{
+ Q_UNUSED(errorMessage);
+
+ XmlContactGroupReader reader;
+
+ bool ok = reader.read(device, group);
+
+ if (!ok && errorMessage != Q_NULLPTR) {
+ *errorMessage = reader.errorString();
+ }
+
+ return ok;
+}
+
+bool ContactGroupTool::convertToXml(const ContactGroup &group, QIODevice *device,
+ QString *errorMessage)
+{
+ Q_UNUSED(errorMessage);
+
+ XmlContactGroupWriter writer;
+ writer.write(group, device);
+
+ return true;
+}
+
+bool ContactGroupTool::convertFromXml(QIODevice *device, QVector<ContactGroup> &groupList,
+ QString *errorMessage)
+{
+ Q_UNUSED(errorMessage);
+
+ XmlContactGroupReader reader;
+
+ bool ok = reader.read(device, groupList);
+
+ if (!ok && errorMessage != Q_NULLPTR) {
+ *errorMessage = reader.errorString();
+ }
+
+ return ok;
+}
+
+bool ContactGroupTool::convertToXml(const QVector<ContactGroup> &groupList,
+ QIODevice *device, QString *errorMessage)
+{
+ Q_UNUSED(errorMessage);
+
+ XmlContactGroupWriter writer;
+ writer.write(groupList, device);
+
+ return true;
+}
--- /dev/null
+/*
+ This file is part of the KContacts framework.
+ Copyright (c) 2008 Tobias Koenig <tokoe@kde.org>
+ Copyright (c) 2008 Kevin Krammer <kevin.krammer@gmx.at>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KCONTACTS_CONTACTGROUPTOOL_H
+#define KCONTACTS_CONTACTGROUPTOOL_H
+
+#include "kcontacts_export.h"
+#include <QString>
+class QIODevice;
+
+template <class T> class QList;
+
+namespace KContacts
+{
+
+class ContactGroup;
+
+/**
+ * Static methods for converting ContactGroup to XML format and vice versa.
+ *
+ * @author Kevin Krammer <kevin.krammer@gmx.at>
+ * @since 4.3
+ */
+namespace ContactGroupTool
+{
+
+/**
+ * Converts XML data coming from a @p device into a contact @p group.
+ * If an error occurs, @c false is returned and @p errorMessage is set.
+ */
+KCONTACTS_EXPORT bool convertFromXml(QIODevice *device, ContactGroup &group,
+ QString *errorMessage = Q_NULLPTR);
+
+/**
+ * Converts a contact @p group into XML data and writes them to a @p device.
+ * If an error occurs, @c false is returned and @p errorMessage is set.
+ */
+KCONTACTS_EXPORT bool convertToXml(const ContactGroup &group, QIODevice *device,
+ QString *errorMessage = Q_NULLPTR);
+
+/**
+ * Converts XML data coming from a @p device into a @p list of contact groups.
+ * If an error occurs, @c false is returned and @p errorMessage is set.
+ */
+KCONTACTS_EXPORT bool convertFromXml(QIODevice *device,
+ QVector<ContactGroup> &list,
+ QString *errorMessage = Q_NULLPTR);
+
+/**
+ * Converts a @p list of contact groups into XML data and writes them to a @p device.
+ * If an error occurs, @c false is returned and @p errorMessage is set.
+ */
+KCONTACTS_EXPORT bool convertToXml(const QVector<ContactGroup> &list,
+ QIODevice *device, QString *errorMessage = Q_NULLPTR);
+}
+
+}
+
+#endif
--- /dev/null
+ecm_generate_headers(KContacts_CamelCase_Converter_HEADERS
+ HEADER_NAMES
+ LDIFConverter
+ VCardConverter
+ PREFIX KContacts
+ REQUIRED_HEADERS KContacts_Converter_HEADERS
+)
+
+install(FILES
+ ${KContacts_CamelCase_Converter_HEADERS}
+ DESTINATION ${KDE_INSTALL_INCLUDEDIR_KF5}/KContacts/KContacts
+ COMPONENT Devel
+)
+
+
+install(FILES
+ ${KContacts_Converter_HEADERS}
+ DESTINATION ${KDE_INSTALL_INCLUDEDIR_KF5}/KContacts/kcontacts
+ COMPONENT Devel
+)
+
+
--- /dev/null
+/*
+ This file is part of the KContacts framework.
+ Copyright (c) 2003 Helge Deller <deller@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+/*
+ Useful links:
+ - http://tldp.org/HOWTO/LDAP-Implementation-HOWTO/schemas.html
+ - http://www.faqs.org/rfcs/rfc2849.html
+
+ Not yet handled items:
+ - objectclass microsoftaddressbook
+ - info,
+ - initials,
+ - otherfacsimiletelephonenumber,
+ - otherpager,
+ - physicaldeliveryofficename,
+*/
+
+#include "ldifconverter.h"
+#include "vcardconverter.h"
+#include "address.h"
+#include "addressee.h"
+#include "kcontacts_debug.h"
+
+#include "ldif_p.h"
+
+#include <klocalizedstring.h>
+
+#include <QtCore/QStringList>
+#include <QtCore/QTextCodec>
+#include <QtCore/QTextStream>
+
+using namespace KContacts;
+
+/* internal functions - do not use !! */
+
+namespace KContacts
+{
+/**
+ @internal
+
+ Evaluates @p fieldname and sets the @p value at the addressee or the address
+ objects when appropriate.
+
+ @param a The addressee to store information into
+ @param homeAddr The home address to store respective information into
+ @param workAddr The work address to store respective information into
+ @param fieldname LDIF field name to evaluate
+ @param value The value of the field addressed by @p fieldname
+*/
+void evaluatePair(Addressee &a, Address &homeAddr,
+ Address &workAddr,
+ QString &fieldname, QString &value,
+ int &birthday, int &birthmonth, int &birthyear, ContactGroup &contactGroup);
+}
+
+/* generate LDIF stream */
+
+static void ldif_out(QTextStream &t, const QString &formatStr,
+ const QString &value)
+{
+ if (value.isEmpty()) {
+ return;
+ }
+
+ const QByteArray txt = Ldif::assembleLine(formatStr, value, 72);
+
+ // write the string
+ t << QString::fromUtf8(txt) << "\n";
+}
+
+bool LDIFConverter::addresseeAndContactGroupToLDIF(const AddresseeList &addrList, const ContactGroup::List &contactGroupList, QString &str)
+{
+ bool result = addresseeToLDIF(addrList, str);
+ if (!contactGroupList.isEmpty()) {
+ result = contactGroupToLDIF(contactGroupList, str);
+ }
+ return result;
+}
+
+bool LDIFConverter::contactGroupToLDIF(const ContactGroup &contactGroup, QString &str)
+{
+ if (contactGroup.dataCount() <= 0) {
+ return false;
+ }
+ QTextStream t(&str, QIODevice::WriteOnly | QIODevice::Append);
+ t.setCodec(QTextCodec::codecForName("UTF-8"));
+ t << "objectclass: top\n";
+ t << "objectclass: groupOfNames\n";
+
+ for (unsigned int i = 0; i < contactGroup.dataCount(); ++i) {
+ ContactGroup::Data data = contactGroup.data(i);
+ const QString value = QStringLiteral("cn=%1,mail=%2").arg(data.name(), data.email());
+ ldif_out(t, QStringLiteral("member"), value);
+ }
+
+ t << "\n";
+ return true;
+}
+
+bool LDIFConverter::contactGroupToLDIF(const ContactGroup::List &contactGroupList, QString &str)
+{
+ ContactGroup::List::ConstIterator it;
+ ContactGroup::List::ConstIterator end(contactGroupList.constEnd());
+ for (it = contactGroupList.constBegin(); it != end; ++it) {
+ contactGroupToLDIF(*it, str);
+ }
+ return true;
+}
+
+bool LDIFConverter::addresseeToLDIF(const AddresseeList &addrList, QString &str)
+{
+ AddresseeList::ConstIterator it;
+ AddresseeList::ConstIterator end(addrList.constEnd());
+ for (it = addrList.constBegin(); it != end; ++it) {
+ addresseeToLDIF(*it, str);
+ }
+ return true;
+}
+
+bool LDIFConverter::addresseeToLDIF(const Addressee &addr, QString &str)
+{
+ if (addr.isEmpty()) {
+ return false;
+ }
+
+ QTextStream t(&str, QIODevice::WriteOnly | QIODevice::Append);
+ t.setCodec(QTextCodec::codecForName("UTF-8"));
+
+ const Address homeAddr = addr.address(Address::Home);
+ const Address workAddr = addr.address(Address::Work);
+
+ ldif_out(t, QStringLiteral("dn"), QStringLiteral("cn=%1,mail=%2").
+ arg(addr.formattedName().simplified(), addr.preferredEmail()));
+ t << "objectclass: top\n";
+ t << "objectclass: person\n";
+ t << "objectclass: organizationalPerson\n";
+
+ ldif_out(t, QStringLiteral("givenname"), addr.givenName());
+ ldif_out(t, QStringLiteral("sn"), addr.familyName());
+ ldif_out(t, QStringLiteral("cn"), addr.formattedName().simplified());
+ ldif_out(t, QStringLiteral("uid"), addr.uid());
+ ldif_out(t, QStringLiteral("nickname"), addr.nickName());
+ ldif_out(t, QStringLiteral("xmozillanickname"), addr.nickName());
+ ldif_out(t, QStringLiteral("mozillanickname"), addr.nickName());
+
+ ldif_out(t, QStringLiteral("mail"), addr.preferredEmail());
+ const QStringList emails = addr.emails();
+ const int numEmails = emails.count();
+ for (int i = 1; i < numEmails; ++i) {
+ if (i == 0) {
+ //nothing
+ } else if (i == 1) {
+ ldif_out(t, QStringLiteral("mozillasecondemail"), emails[1]);
+ } else {
+ ldif_out(t, QStringLiteral("othermailbox"), emails[i]);
+ }
+ }
+ //ldif_out( t, "mozilla_AIMScreenName: %1\n", "screen_name" );
+
+ ldif_out(t, QStringLiteral("telephonenumber"),
+ addr.phoneNumber(PhoneNumber::Work).number());
+ ldif_out(t, QStringLiteral("facsimiletelephonenumber"),
+ addr.phoneNumber(PhoneNumber::Fax).number());
+ ldif_out(t, QStringLiteral("homephone"),
+ addr.phoneNumber(PhoneNumber::Home).number());
+ ldif_out(t, QStringLiteral("mobile"),
+ addr.phoneNumber(PhoneNumber::Cell).number()); // Netscape 7
+ ldif_out(t, QStringLiteral("cellphone"),
+ addr.phoneNumber(PhoneNumber::Cell).number()); // Netscape 4.x
+ ldif_out(t, QStringLiteral("pager"),
+ addr.phoneNumber(PhoneNumber::Pager).number());
+ ldif_out(t, QStringLiteral("pagerphone"),
+ addr.phoneNumber(PhoneNumber::Pager).number());
+
+ ldif_out(t, QStringLiteral("streethomeaddress"), homeAddr.street());
+ ldif_out(t, QStringLiteral("postalcode"), workAddr.postalCode());
+ ldif_out(t, QStringLiteral("postofficebox"), workAddr.postOfficeBox());
+
+ QStringList streets = homeAddr.street().split(QLatin1Char('\n'));
+ const int numberOfStreets(streets.count());
+ if (numberOfStreets > 0) {
+ ldif_out(t, QStringLiteral("homepostaladdress"), streets.at(0)); // Netscape 7
+ }
+ if (numberOfStreets > 1) {
+ ldif_out(t, QStringLiteral("mozillahomepostaladdress2"), streets.at(1)); // Netscape 7
+ }
+ ldif_out(t, QStringLiteral("mozillahomelocalityname"), homeAddr.locality()); // Netscape 7
+ ldif_out(t, QStringLiteral("mozillahomestate"), homeAddr.region());
+ ldif_out(t, QStringLiteral("mozillahomepostalcode"), homeAddr.postalCode());
+ ldif_out(t, QStringLiteral("mozillahomecountryname"),
+ Address::ISOtoCountry(homeAddr.country()));
+ ldif_out(t, QStringLiteral("locality"), workAddr.locality());
+ ldif_out(t, QStringLiteral("streetaddress"), workAddr.street()); // Netscape 4.x
+
+ streets = workAddr.street().split(QLatin1Char('\n'));
+ if (streets.count() > 0) {
+ ldif_out(t, QStringLiteral("street"), streets.at(0));
+ }
+ if (streets.count() > 1) {
+ ldif_out(t, QStringLiteral("mozillaworkstreet2"), streets.at(1));
+ }
+ ldif_out(t, QStringLiteral("countryname"), Address::ISOtoCountry(workAddr.country()));
+ ldif_out(t, QStringLiteral("l"), workAddr.locality());
+ ldif_out(t, QStringLiteral("c"), Address::ISOtoCountry(workAddr.country()));
+ ldif_out(t, QStringLiteral("st"), workAddr.region());
+
+ ldif_out(t, QStringLiteral("title"), addr.title());
+ ldif_out(t, QStringLiteral("vocation"), addr.prefix());
+ ldif_out(t, QStringLiteral("ou"), addr.role());
+ ldif_out(t, QStringLiteral("o"), addr.organization());
+ ldif_out(t, QStringLiteral("organization"), addr.organization());
+ ldif_out(t, QStringLiteral("organizationname"), addr.organization());
+
+ // Compatibility with older kabc versions.
+ if (!addr.department().isEmpty()) {
+ ldif_out(t, QStringLiteral("department"), addr.department());
+ } else {
+ ldif_out(t, QStringLiteral("department"), addr.custom(QStringLiteral("KADDRESSBOOK"),
+ QStringLiteral("X-Department")));
+ }
+
+ ldif_out(t, QStringLiteral("workurl"), addr.url().url().toDisplayString());
+ ldif_out(t, QStringLiteral("homeurl"), addr.url().url().toDisplayString());
+ ldif_out(t, QStringLiteral("mozillahomeurl"), addr.url().url().toDisplayString());
+
+ ldif_out(t, QStringLiteral("description"), addr.note());
+ if (addr.revision().isValid()) {
+ ldif_out(t, QStringLiteral("modifytimestamp"), dateToVCardString(addr.revision()));
+ }
+
+ const QDateTime birthday = addr.birthday();
+ if (birthday.date().isValid()) {
+ const QDate date = birthday.date();
+ ldif_out(t, QStringLiteral("birthyear"), QString::number(date.year()));
+ ldif_out(t, QStringLiteral("birthmonth"), QString::number(date.month()));
+ ldif_out(t, QStringLiteral("birthday"), QString::number(date.day()));
+ }
+
+ t << "\n";
+
+ return true;
+}
+
+/* convert from LDIF stream */
+bool LDIFConverter::LDIFToAddressee(const QString &str, AddresseeList &addrList, ContactGroup::List &contactGroupList,
+ const QDateTime &dt)
+{
+ if (str.isEmpty()) {
+ return true;
+ }
+
+ bool endldif = false, end = false;
+ Ldif ldif;
+ Ldif::ParseValue ret;
+ Addressee a;
+ Address homeAddr, workAddr;
+ int birthday = -1;
+ int birthmonth = -1;
+ int birthyear = -1;
+ ContactGroup contactGroup;
+ ldif.setLdif(str.toLatin1());
+ QDateTime qdt = dt;
+ if (!qdt.isValid()) {
+ qdt = QDateTime::currentDateTime();
+ }
+ a.setRevision(qdt);
+ homeAddr = Address(Address::Home);
+ workAddr = Address(Address::Work);
+
+ do {
+ ret = ldif.nextItem();
+ switch (ret) {
+ case Ldif::Item: {
+ QString fieldname = ldif.attr().toLower();
+ QString value = QString::fromUtf8(ldif.value());
+ evaluatePair(a, homeAddr, workAddr, fieldname, value, birthday, birthmonth, birthyear, contactGroup);
+ break;
+ }
+ case Ldif::EndEntry: {
+ if (contactGroup.count() == 0) {
+ // if the new address is not empty, append it
+ QDateTime birthDate(QDate(birthyear, birthmonth, birthday));
+ if (birthDate.isValid()) {
+ a.setBirthday(birthDate);
+ }
+
+ if (!a.formattedName().isEmpty() || !a.name().isEmpty() ||
+ !a.familyName().isEmpty()) {
+ if (!homeAddr.isEmpty()) {
+ a.insertAddress(homeAddr);
+ }
+ if (!workAddr.isEmpty()) {
+ a.insertAddress(workAddr);
+ }
+ addrList.append(a);
+ }
+ } else {
+ contactGroupList.append(contactGroup);
+ }
+ a = Addressee();
+ contactGroup = ContactGroup();
+ a.setRevision(qdt);
+ homeAddr = Address(Address::Home);
+ workAddr = Address(Address::Work);
+ }
+ break;
+ case Ldif::MoreData: {
+ if (endldif) {
+ end = true;
+ } else {
+ ldif.endLdif();
+ endldif = true;
+ break;
+ }
+ }
+ default:
+ break;
+ }
+ } while (!end);
+
+ return true;
+}
+
+void KContacts::evaluatePair(Addressee &a, Address &homeAddr,
+ Address &workAddr,
+ QString &fieldname, QString &value,
+ int &birthday, int &birthmonth, int &birthyear, ContactGroup &contactGroup)
+{
+ if (fieldname == QLatin1String("dn")) { // ignore
+ return;
+ }
+
+ if (fieldname.startsWith(QLatin1Char('#'))) {
+ return;
+ }
+
+ if (fieldname.isEmpty() && !a.note().isEmpty()) {
+ // some LDIF export filters are borken and add additional
+ // comments on stand-alone lines. Just add them to the notes for now.
+ a.setNote(a.note() + QLatin1Char('\n') + value);
+ return;
+ }
+
+ if (fieldname == QLatin1String("givenname")) {
+ a.setGivenName(value);
+ return;
+ }
+
+ if (fieldname == QLatin1String("xmozillanickname") ||
+ fieldname == QLatin1String("nickname") ||
+ fieldname == QLatin1String("mozillanickname")) {
+ a.setNickName(value);
+ return;
+ }
+
+ if (fieldname == QLatin1String("sn")) {
+ a.setFamilyName(value);
+ return;
+ }
+
+ if (fieldname == QLatin1String("uid")) {
+ a.setUid(value);
+ return;
+ }
+ if (fieldname == QLatin1String("mail") ||
+ fieldname == QLatin1String("mozillasecondemail") /* mozilla */ ||
+ fieldname == QLatin1String("othermailbox") /*TheBat!*/) {
+ if (a.emails().indexOf(value) == -1) {
+ a.insertEmail(value);
+ }
+ return;
+ }
+
+ if (fieldname == QLatin1String("title")) {
+ a.setTitle(value);
+ return;
+ }
+
+ if (fieldname == QLatin1String("vocation")) {
+ a.setPrefix(value);
+ return;
+ }
+
+ if (fieldname == QLatin1String("cn")) {
+ a.setFormattedName(value);
+ return;
+ }
+
+ if (fieldname == QLatin1String("o") ||
+ fieldname == QLatin1String("organization") || // Exchange
+ fieldname == QLatin1String("organizationname")) { // Exchange
+ a.setOrganization(value);
+ return;
+ }
+
+ if (fieldname == QLatin1String("description") ||
+ fieldname == QLatin1String("mozillacustom1") ||
+ fieldname == QLatin1String("mozillacustom2") ||
+ fieldname == QLatin1String("mozillacustom3") ||
+ fieldname == QLatin1String("mozillacustom4") ||
+ fieldname == QLatin1String("custom1") ||
+ fieldname == QLatin1String("custom2") ||
+ fieldname == QLatin1String("custom3") ||
+ fieldname == QLatin1String("custom4")) {
+ if (!a.note().isEmpty()) {
+ a.setNote(a.note() + QLatin1Char('\n'));
+ }
+ a.setNote(a.note() + value);
+ return;
+ }
+
+ if (fieldname == QLatin1String("homeurl") ||
+ fieldname == QLatin1String("workurl") ||
+ fieldname == QLatin1String("mozillahomeurl")) {
+ if (a.url().url().isEmpty()) {
+ ResourceLocatorUrl url;
+ url.setUrl(QUrl(value));
+ a.setUrl(url);
+ return;
+ }
+ if (a.url().url().toDisplayString() == QUrl(value).toDisplayString()) {
+ return;
+ }
+ // TODO: current version of kabc only supports one URL.
+ // TODO: change this with KDE 4
+ }
+
+ if (fieldname == QLatin1String("homephone")) {
+ a.insertPhoneNumber(PhoneNumber(value, PhoneNumber::Home));
+ return;
+ }
+
+ if (fieldname == QLatin1String("telephonenumber")) {
+ a.insertPhoneNumber(PhoneNumber(value, PhoneNumber::Work));
+ return;
+ }
+ if (fieldname == QLatin1String("mobile") || /* mozilla/Netscape 7 */
+ fieldname == QLatin1String("cellphone")) {
+ a.insertPhoneNumber(PhoneNumber(value, PhoneNumber::Cell));
+ return;
+ }
+
+ if (fieldname == QLatin1String("pager") || // mozilla
+ fieldname == QLatin1String("pagerphone")) { // mozilla
+ a.insertPhoneNumber(PhoneNumber(value, PhoneNumber::Pager));
+ return;
+ }
+
+ if (fieldname == QLatin1String("facsimiletelephonenumber")) {
+ a.insertPhoneNumber(PhoneNumber(value, PhoneNumber::Fax));
+ return;
+ }
+
+ if (fieldname == QLatin1String("xmozillaanyphone")) { // mozilla
+ a.insertPhoneNumber(PhoneNumber(value, PhoneNumber::Work));
+ return;
+ }
+
+ if (fieldname == QLatin1String("streethomeaddress") ||
+ fieldname == QLatin1String("mozillahomestreet")) { // thunderbird
+ homeAddr.setStreet(value);
+ return;
+ }
+
+ if (fieldname == QLatin1String("street") ||
+ fieldname == QLatin1String("postaladdress")) { // mozilla
+ workAddr.setStreet(value);
+ return;
+ }
+ if (fieldname == QLatin1String("mozillapostaladdress2") ||
+ fieldname == QLatin1String("mozillaworkstreet2")) { // mozilla
+ workAddr.setStreet(workAddr.street() + QLatin1String("\n") + value);
+ return;
+ }
+
+ if (fieldname == QLatin1String("postalcode")) {
+ workAddr.setPostalCode(value);
+ return;
+ }
+
+ if (fieldname == QLatin1String("postofficebox")) {
+ workAddr.setPostOfficeBox(value);
+ return;
+ }
+
+ if (fieldname == QLatin1String("homepostaladdress")) { // Netscape 7
+ homeAddr.setStreet(value);
+ return;
+ }
+
+ if (fieldname == QLatin1String("mozillahomepostaladdress2")) { // mozilla
+ homeAddr.setStreet(homeAddr.street() + QLatin1String("\n") + value);
+ return;
+ }
+
+ if (fieldname == QLatin1String("mozillahomelocalityname")) { // mozilla
+ homeAddr.setLocality(value);
+ return;
+ }
+
+ if (fieldname == QLatin1String("mozillahomestate")) { // mozilla
+ homeAddr.setRegion(value);
+ return;
+ }
+
+ if (fieldname == QLatin1String("mozillahomepostalcode")) { // mozilla
+ homeAddr.setPostalCode(value);
+ return;
+ }
+
+ if (fieldname == QLatin1String("mozillahomecountryname")) { // mozilla
+ if (value.length() <= 2) {
+ value = Address::ISOtoCountry(value);
+ }
+ homeAddr.setCountry(value);
+ return;
+ }
+
+ if (fieldname == QLatin1String("locality")) {
+ workAddr.setLocality(value);
+ return;
+ }
+
+ if (fieldname == QLatin1String("streetaddress")) { // Netscape 4.x
+ workAddr.setStreet(value);
+ return;
+ }
+
+ if (fieldname == QLatin1String("countryname") ||
+ fieldname == QLatin1String("c")) { // mozilla
+ if (value.length() <= 2) {
+ value = Address::ISOtoCountry(value);
+ }
+ workAddr.setCountry(value);
+ return;
+ }
+
+ if (fieldname == QLatin1String("l")) { // mozilla
+ workAddr.setLocality(value);
+ return;
+ }
+
+ if (fieldname == QLatin1String("st")) {
+ workAddr.setRegion(value);
+ return;
+ }
+
+ if (fieldname == QLatin1String("ou")) {
+ a.setRole(value);
+ return;
+ }
+
+ if (fieldname == QLatin1String("department")) {
+ a.setDepartment(value);
+ return;
+ }
+
+ if (fieldname == QLatin1String("member")) {
+ // this is a mozilla list member (cn=xxx, mail=yyy)
+ QStringList list = value.split(QLatin1Char(','));
+ QString name, email;
+
+ QStringList::ConstIterator it;
+ QStringList::ConstIterator end(list.constEnd());
+ for (it = list.constBegin(); it != end; ++it) {
+ if ((*it).startsWith(QLatin1String("cn="))) {
+ name = (*it).mid(3).trimmed();
+ }
+ if ((*it).startsWith(QLatin1String("mail="))) {
+ email = (*it).mid(5).trimmed();
+ }
+ }
+ if (!name.isEmpty() && !email.isEmpty()) {
+ email = QLatin1String(" <") + email + QLatin1Char('>');
+ }
+ ContactGroup::Data data;
+ data.setEmail(email);
+ data.setName(name);
+ contactGroup.append(data);
+ return;
+ }
+
+ if (fieldname == QLatin1String("modifytimestamp")) {
+ if (value == QLatin1String("0Z")) { // ignore
+ return;
+ }
+ QDateTime dt = VCardStringToDate(value);
+ if (dt.isValid()) {
+ a.setRevision(dt);
+ return;
+ }
+ }
+
+ if (fieldname == QLatin1String("display-name")) {
+ contactGroup.setName(value);
+ return;
+ }
+
+ if (fieldname == QLatin1String("objectclass")) { // ignore
+ return;
+ }
+
+ if (fieldname == QLatin1String("birthyear")) {
+ birthyear = value.toInt();
+ return;
+ }
+ if (fieldname == QLatin1String("birthmonth")) {
+ birthmonth = value.toInt();
+ return;
+ }
+ if (fieldname == QLatin1String("birthday")) {
+ birthday = value.toInt();
+ return;
+ }
+ if (fieldname == QLatin1String("xbatbirthday")) {
+ QDate dt = QDate::fromString(value, QStringLiteral("yyyyMMdd"));
+ if (dt.isValid()) {
+ a.setBirthday(QDateTime(dt));
+ }
+ return;
+ }
+ qCWarning(KCONTACTS_LOG) << QStringLiteral("LDIFConverter: Unknown field for '%1': '%2=%3'\n").
+ arg(a.formattedName(), fieldname, value);
+
+ return;
+}
--- /dev/null
+/*
+ This file is part of the KContacts framework.
+ Copyright (c) 2003 Helge Deller <deller@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 only 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KCONTACTS_LDIFCONVERTER_H
+#define KCONTACTS_LDIFCONVERTER_H
+
+#include "addressee.h"
+#include "contactgroup.h"
+
+#include <QtCore/QDateTime>
+#include <QtCore/QString>
+
+namespace KContacts
+{
+
+/**
+ A set of functions to convert a string with LDIF information to addressees
+ and vice versa. It is useful for addressbook import- and exportfilters
+ and might be used to read and write Mozilla and Netscape addresssbooks.
+*/
+
+namespace LDIFConverter
+{
+
+/**
+ Converts a LDIF string to a list of addressees.
+
+ @param str The vcard string.
+ @param addrList The addresseelist.
+ @param contactGroupList the contactGroupList
+ @param dt The date & time value of the last modification (e.g. file modification time).
+*/
+KCONTACTS_EXPORT bool LDIFToAddressee(const QString &str, AddresseeList &addrList, QVector<KContacts::ContactGroup> &contactGroupList,
+ const QDateTime &dt = QDateTime::currentDateTime());
+
+/**
+ Converts a list of addressees to a LDIF string.
+
+ @param addrList The addresseelist.
+ @param str The LDIF string.
+*/
+KCONTACTS_EXPORT bool addresseeToLDIF(const AddresseeList &addrList, QString &str);
+
+/**
+ Converts a list of addressees and contactgrouplist to a LDIF string.
+
+ @param addrList The addresseelist.
+ @param contactGroupList The contact group list
+ @param str The LDIF string.
+
+*/
+KCONTACTS_EXPORT bool addresseeAndContactGroupToLDIF(const AddresseeList &addrList, const QVector<KContacts::ContactGroup> &contactGroupList, QString &str);
+/**
+ Converts an addressee to a LDIF string.
+
+ @param addr The addressee.
+ @param str The LDIF string.
+*/
+KCONTACTS_EXPORT bool addresseeToLDIF(const Addressee &addr, QString &str);
+
+/**
+ Converts a list of contact group to a LDIF string.
+
+ @param contactGroupList The contact group list
+ @param str The LDIF string.
+*/
+KCONTACTS_EXPORT bool contactGroupToLDIF(const ContactGroup::List &contactGroupList, QString &str);
+
+/**
+ Converts a contact group to a LDIF string.
+
+ @param contactGroup The contact group
+ @param str The LDIF string.
+*/
+KCONTACTS_EXPORT bool contactGroupToLDIF(const ContactGroup &contactGroup, QString &str);
+
+}
+
+}
+#endif
--- /dev/null
+/*
+ This file is part of the KContacts framework.
+ Copyright (c) 2002 Tobias Koenig <tokoe@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "vcardconverter.h"
+#include "vcardtool.h"
+
+using namespace KContacts;
+
+VCardConverter::VCardConverter()
+ : d(Q_NULLPTR)
+{
+}
+
+VCardConverter::~VCardConverter()
+{
+}
+
+QByteArray VCardConverter::exportVCard(const Addressee &addr, Version version) const
+{
+ Addressee::List list;
+ list.append(addr);
+
+ return exportVCards(list, version);
+}
+
+QByteArray VCardConverter::exportVCards(const Addressee::List &list, Version version) const
+{
+ VCardTool tool;
+ QByteArray returnValue;
+ switch (version) {
+ case v2_1:
+ returnValue = tool.exportVCards(list, VCard::v2_1);
+ break;
+ case v3_0:
+ returnValue = tool.exportVCards(list, VCard::v3_0);
+ break;
+ case v4_0:
+ returnValue = tool.exportVCards(list, VCard::v4_0);
+ break;
+ }
+
+ return returnValue;
+}
+
+QByteArray VCardConverter::createVCard(const Addressee &addr, Version version) const
+{
+ Addressee::List list;
+ list.append(addr);
+
+ return createVCards(list, version);
+}
+
+QByteArray VCardConverter::createVCards(const Addressee::List &list, Version version) const
+{
+ VCardTool tool;
+ QByteArray returnValue;
+ switch (version) {
+ case v2_1:
+ returnValue = tool.createVCards(list, VCard::v2_1);
+ break;
+ case v3_0:
+ returnValue = tool.createVCards(list, VCard::v3_0);
+ break;
+ case v4_0:
+ returnValue = tool.createVCards(list, VCard::v4_0);
+ break;
+ }
+
+ return returnValue;
+}
+
+Addressee VCardConverter::parseVCard(const QByteArray &vcard) const
+{
+ Addressee::List list = parseVCards(vcard);
+
+ return list.isEmpty() ? Addressee() : list[ 0 ];
+}
+
+Addressee::List VCardConverter::parseVCards(const QByteArray &vcard) const
+{
+ VCardTool tool;
+
+ return tool.parseVCards(vcard);
+}
+
+/* Helper functions */
+
+QString KContacts::dateToVCardString(const QDateTime &dateTime)
+{
+ return dateTime.toString(QStringLiteral("yyyyMMddThhmmssZ"));
+}
+
+QString KContacts::dateToVCardString(QDate date)
+{
+ return date.toString(QStringLiteral("yyyyMMdd"));
+}
+
+QDateTime KContacts::VCardStringToDate(const QString &dateString)
+{
+ QDate date;
+ QTime time;
+ QString d(dateString);
+
+ d = d.remove(QLatin1Char('-')).remove(QLatin1Char(':'));
+
+ if (d.length() >= 8) {
+ date = QDate(d.midRef(0, 4).toUInt(), d.midRef(4, 2).toUInt(), d.midRef(6, 2).toUInt());
+ }
+
+ if (d.length() > 9 && d[ 8 ].toUpper() == QLatin1Char('T')) {
+ time = QTime(d.midRef(9, 2).toUInt(), d.midRef(11, 2).toUInt(), d.midRef(13, 2).toUInt());
+ }
+
+ return QDateTime(date, time);
+}
+
+void KContacts::adaptIMAttributes(QByteArray &data)
+{
+ data.replace("X-messaging/aim-All", ("X-AIM"));
+ data.replace("X-messaging/icq-All", ("X-ICQ"));
+ data.replace("X-messaging/xmpp-All", ("X-JABBER"));
+ data.replace("X-messaging/msn-All", ("X-MSN"));
+ data.replace("X-messaging/yahoo-All", ("X-YAHOO"));
+ data.replace("X-messaging/gadu-All", ("X-GADUGADU"));
+ data.replace("X-messaging/skype-All", ("X-SKYPE"));
+ data.replace("X-messaging/groupwise-All", ("X-GROUPWISE"));
+ data.replace("X-messaging/sms-All", ("X-SMS"));
+ data.replace("X-messaging/meanwhile-All", ("X-MEANWHILE"));
+ data.replace("X-messaging/irc-All", ("X-IRC"));
+ data.replace("X-messaging/googletalk-All", ("X-GTALK"));
+}
--- /dev/null
+/*
+ This file is part of the KContacts framework.
+ Copyright (c) 2002 Tobias Koenig <tokoe@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KCONTACTS_VCARDCONVERTER_H
+#define KCONTACTS_VCARDCONVERTER_H
+
+#include "kcontacts_export.h"
+#include "kcontacts/addressee.h"
+#include <QtCore/QString>
+
+namespace KContacts
+{
+
+/**
+ @short Class to converting contact objects into vCard format and vice versa.
+
+ This class implements reading and writing of contact using from/to the
+ vCard format. Currently vCard version 2.1 and 3.0 is supported.
+
+ Example:
+
+ \code
+
+ QFile file( "myfile.vcf" );
+ file.open( QIODevice::ReadOnly );
+
+ QByteArray data = file.readAll();
+
+ VCardConverter converter;
+ Addressee::List list = converter.parseVCards( data );
+
+ // print formatted name of first contact
+ qDebug( "name=%s", list[ 0 ].formattedName().toLatin1() );
+
+ \endcode
+*/
+class KCONTACTS_EXPORT VCardConverter
+{
+public:
+
+ /**
+ @li v2_1 - VCard format version 2.1
+ @li v3_0 - VCard format version 3.0
+ @li v4_0 - VCard format version 4.0
+ */
+ enum Version {
+ v2_1,
+ v3_0,
+ v4_0
+ };
+
+ /**
+ Constructor.
+ */
+ VCardConverter();
+
+ /**
+ Destructor.
+ */
+ ~VCardConverter();
+
+ /**
+ Creates a string in vCard format which contains the given
+ contact.
+
+ @param addr The contact object
+ @param version The version of the generated vCard format
+ */
+ QByteArray createVCard(const Addressee &addr, Version version = v3_0) const;
+
+ /**
+ Creates a string in vCard format which contains the given
+ list of contact.
+
+ @param list The list of contact objects
+ @param version The version of the generated vCard format
+ */
+ // FIXME: Add error handling
+ QByteArray createVCards(const Addressee::List &list, Version version = v3_0) const;
+
+ /**
+ * @since 4.9.1
+ */
+ QByteArray exportVCard(const Addressee &addr, Version version) const;
+
+ /**
+ * @since 4.9.1
+ */
+ QByteArray exportVCards(const Addressee::List &list, Version version) const;
+
+ /**
+ Parses a string in vCard format and returns the first contact.
+ */
+ Addressee parseVCard(const QByteArray &vcard) const;
+
+ /**
+ Parses a string in vCard format and returns a list of contact objects.
+ */
+ // FIXME: Add error handling
+ Addressee::List parseVCards(const QByteArray &vcard) const;
+
+private:
+ Q_DISABLE_COPY(VCardConverter)
+ class VCardConverterPrivate;
+ VCardConverterPrivate *const d;
+};
+
+/**
+ Helper functions
+ */
+
+/**
+ * Converts a QDateTime to a date string as it is used in VCard and LDIF files.
+ * The return value is in the form "yyyyMMddThhmmssZ" (e.g. "20031201T120000Z")
+ * @param dateTime date and time to be converted
+ */
+KCONTACTS_EXPORT QString dateToVCardString(const QDateTime &dateTime);
+
+/**
+ * Converts a QDate to a short date string as it is used in VCard and LDIF files.
+ * The return value is in the form "yyyyMMdd" (e.g. "20031201")
+ * @param date date to be converted
+ */
+KCONTACTS_EXPORT QString dateToVCardString(QDate date);
+
+/**
+ * Converts a date string as it is used in VCard and LDIF files to a QDateTime value.
+ * If the date string does not contain a time value, it will be returned as 00:00:00.
+ * (e.g. "20031201T120000" will return a QDateTime for 2003-12-01 at 12:00)
+ * @param dateString string representing the date and time.
+ */
+KCONTACTS_EXPORT QDateTime VCardStringToDate(const QString &dateString);
+
+/**
+ * @brief adaptIMAttributes. Convert KAddressBook attribute to VCard IM Attribute
+ * @param data
+ */
+KCONTACTS_EXPORT void adaptIMAttributes(QByteArray &data);
+
+}
+#endif
--- /dev/null
+Andorra ad
+Андора ad
+Андора ad
+Andora ad
+ອີນເດີຍ ad
+Andora ad
+Андорра ad
+安道尔 ad
+United Arab Emirates ae
+Vereenigde Arabiese Emirate ae
+الإمارات العربية المتحدة ae
+Злучаныя Арабскія Эміраты ae
+Обединени Арабски Емирства ae
+Ujedinjeni arapski emirati ae
+Emirats Àrabs Units ae
+Spojené arabské emiráty ae
+Forenende Arabiske Emirater ae
+Vereinigte Arabische Emirate ae
+Ενωμένα Αραβικά Εμιράτα ae
+Emiratos árabes unidos ae
+Araabia Ühendemiraadid ae
+Arabiar Emirato Batuak ae
+امارات متحده عربی ae
+Yhdistyneet Arabiemiraatit ae
+Émirats Arabes Unis ae
+איחוד האמירויות הערביות ae
+Ujedinjeni arapski emirati ae
+Egyesült Arab Emirátusok ae
+Emirati arabi uniti ae
+アラブ首長国連邦 ae
+아랍 에미레이트 연합 ae
+ສະຫະລັດ ae
+Jungtiniai Arabų Emiratai ae
+Emirati Għarab Magħquda ae
+De forente arabiske emirater ae
+Verenigde Arabische Emiraten ae
+Dei sameinte arabiske emirata ae
+Di-Emirate tseo di Kopanego tsa Arab ae
+Zjednoczone Emiraty Arabskie ae
+Emiratos Árabes Unidos ae
+Emirados Árabes ae
+Emiratele Arabe Unite ae
+Объединенные Арабские Эмираты ae
+Spojené arabské emiráty ae
+Združeni arabski Emirati ae
+Förenade arabemiraten ae
+³ì¸¢Â «ÃÒ ¿¡Î¸û ae
+Birleşik Arap Emirlikleri ae
+Об'єднані Арабські Емірати ae
+Mashango o tangananaho a Emirates ae
+阿拉伯联合酋长国 ae
+阿拉伯聯合大公國 ae
+Izindawo zezinduna zase-United Arab ae
+Afghanistan af
+Афганістан af
+Афганистан af
+Afganistan af
+Afghanistán af
+Afganisztán af
+ລີທົ່ວເນີຍ af
+Afeganistão af
+Afganistan af
+Afganistan af
+Afganistan af
+Афганістан af
+阿富汗 af
+Antigua and Barbuda ag
+Antigue en Barbuda ag
+أنتيغوا و باربودا ag
+Antigua və Barbuda ag
+Антыгуа і Барбуда ag
+Антигуа и Барбадос ag
+Antigua ha Barbuda ag
+Antigua i Barbuda ag
+Antigua i Barbuda ag
+Antigua a Barbuda ag
+Antigua og Barbuda ag
+Antigua und Barbuda ag
+Antigua και Barbuda ag
+Antigvo kaj Barbudo ag
+Antigua y Barbuda ag
+Antigua ja Barbuda ag
+Antigua eta Barbuda ag
+آنتیگوا و باربودا ag
+Antigua ja Barbados ag
+Antigua og Barbuda ag
+Antigua et Barbuda ag
+Antiga e Barbuda ag
+אנטיגואה וברבודה ag
+Antigua i Barbuda ag
+Antigua és Barbuda ag
+Antigua dan Barbuda ag
+Antigúa og Barbúda ag
+Antigua e Barbuda ag
+アンティグアバーブーダ ag
+앤티가 바부다 ag
+Antikva ir Barbuda ag
+Antigva un Barbudas ag
+Antigwa u Barbuda ag
+Antigua og Barbuda ag
+Antigua en Barbuda ag
+Antigua og Barbuda ag
+Antigua le Barbuda ag
+Antigua e Barbuda ag
+Antigua i Barbuda ag
+Antigua e Barbuda ag
+Antigua e Barbuda ag
+Antigua şi Barbuda ag
+Антигуа и Барбадос ag
+Antigua a Barbuda ag
+Antigva in Barbuda ag
+Antigua i Barbuda ag
+I-Antigua kanye ne Barbuda ag
+Antigua och Barbuda ag
+¬ýÊÌÅ¡ & À¡÷Ò¼¡ ag
+Antigua ve Barbuda ag
+Трінідад та Тобаго ag
+Antigua và Barbuda ag
+Antigua eyet Barbuda ag
+Antigua ne Barbuda ag
+安地瓜岛和巴布达岛 ag
+安地瓜島和巴布達島 ag
+Antigua kanye ne-Barbuda ag
+Anguilla ai
+Ангуила ai
+ແພນວິນ ai
+Angvila ai
+Ангілья ai
+安圭拉 ai
+Albania al
+Альбанія al
+Албания al
+Albanija al
+Albanien al
+Albánia al
+ແອດແລນຕິກ al
+Albânia al
+Albánsko al
+Albanija al
+Albanien al
+Албанія al
+阿尔巴尼亚 al
+Armenia am
+Армэнія am
+Армения am
+Armenija am
+Armenien am
+Örményország am
+ອາເຈນຕິນາ am
+Armênia am
+Arménsko am
+Armenija am
+Armenien am
+Арменія am
+亚美尼亚 am
+Netherlands Antilles an
+Холандски Антили an
+Nizozemski Antili an
+Nederlandske antiller an
+Antillas holandesas an
+Antilla Holandarrak an
+Holland-Antillák an
+ເນເທີແລນ an
+Antilhas an
+Holandské Antily an
+Nizozemski Antili an
+Nederländska Antillerna an
+Голландські Антилли an
+荷属安的列斯群岛 an
+Angola ao
+Ангола ao
+Ангола ao
+ບັນແກເລີຍ ao
+Ангола ao
+安哥拉 ao
+Argentina ar
+Argentinië ar
+الأرجنتين ar
+Аргентына ar
+Аржентина ar
+Arc'hantina ar
+Argentinien ar
+Αργεντινή ar
+Argentino ar
+Argentiina ar
+آرژانتین ar
+Agentiina ar
+Argentine ar
+Arxentina ar
+ארגנטינה ar
+Argentína ar
+ArgentÃna ar
+アルゼンチン ar
+아르헨티나 ar
+ອາເຈນຕິນາ ar
+Argentīna ar
+Arġentina ar
+Argentinië ar
+Argentyna ar
+Аргентина ar
+Argentína ar
+I-Argentina ar
+¬÷¦º\83ýÊÉ¡ ar
+อาร์เจนตินา ar
+Arjantin ar
+Аргентина ar
+Agenthina ar
+Årdjintene ar
+阿根廷 ar
+阿根廷 ar
+American Samoa as
+Амэрыканскае Самоа as
+Американска Самоа as
+Američka Samoa as
+Samoa (USA) as
+Samoa americana as
+Amerikako Samoa as
+Amerikai Szamoa as
+ອາເມລິກາເຫນືອ as
+Samoa Americana as
+Americká Samoa as
+Ameriška Samoa as
+Amerikanska Samoa as
+Американське Самоа as
+美属萨摩亚群岛 as
+Austria at
+Oostenryk at
+النمسا at
+Avstriya at
+Аўстрыя at
+Австрия at
+Aostria at
+Austrija at
+Àustria at
+Rakousko at
+Østrig at
+Österreich at
+Αυστρία at
+Aŭstrio at
+اتریش at
+Itävalta at
+Eysturríki at
+Autriche at
+אוסטריה at
+Austrija at
+Ausztria at
+AusturrÃki at
+オーストリア at
+오스트리아 at
+ອອດສະເຕເລີຍ at
+Austrija at
+Austrija at
+Awtrija at
+Østerrike at
+Oostenrijk at
+Austerrike at
+Áustria at
+Áustria at
+Австрия at
+Rakúsko at
+Avstrija at
+Austrija at
+I-Austria at
+Österrike at
+¬Íò¾¢Ã¢Â¡ at
+ออสเตรีย at
+Avusturya at
+Австрія at
+Ositiria at
+A'o at
+Ôtriche at
+奥地利 at
+奧地利 at
+Australia au
+Australië au
+أستراليا au
+Avustralya au
+Аўстралія au
+Австралия au
+Aostralia au
+Australija au
+Austràlia au
+Austrálie au
+Australien au
+Australien au
+Αυστραλία au
+Aŭstralio au
+Austraalia au
+استرالیا au
+Australie au
+אוסטרליה au
+Australija au
+Ausztrália au
+Ã\81stralÃa au
+オーストラリア au
+오스트레일리아 au
+ອອດສະເຕເລີຍ au
+Australija au
+Austrālija au
+Awstralja au
+Australië au
+Austrália au
+Austrália au
+Австралия au
+Austrália au
+Avstralija au
+Australija au
+I-Australia au
+Australien au
+¬\8aÍò¾¢§ÃĢ¡ au
+ออสเตรเลีย au
+Avusturalya au
+Австралія au
+Ositiralia au
+U'c au
+Ôstraleye au
+澳大利亚 au
+澳大利亞 au
+Aruba aw
+Аруба aw
+ເກມໄັພ່ aw
+Аруба aw
+阿鲁巴岛 aw
+Azerbaijan az
+أذربيجان az
+Azərbaycan az
+Азэрбайджан az
+Азарбайджан az
+Azerbejdžan az
+Azerbaitjan az
+Ázerbajdžánský az
+Azerbajdjan az
+Aserbaidschan az
+Αζερμπαϊτζάν az
+Azerbajĝana az
+Azerbaiján az
+Aserbaidžaan az
+آذربایجان az
+Azerbaidzan az
+Aserbadsjan az
+אזרביג'ן az
+Azerbejdžan az
+Azerbajdzsán az
+Azerbaigian az
+アゼルバイジャン az
+아제르바이잔 az
+ອາເຊີໄບຈັນ az
+Azerbaidžanas az
+Azerbaidžāņu az
+Ażerbajġan az
+Aserbajdsjan az
+Azerbeidjan az
+Aserbajdsjan az
+Azerbejdżan az
+Azerbaijão az
+Turco az
+Azerbadjan az
+Азербайджан az
+Ázerbajdžánsky az
+Azerbajdžan az
+Azerbejdžan az
+I-Azerbaijan az
+«º÷¨Àº¡ý az
+อาร์เซอร์ไบจัน az
+Azerice az
+Азербайджан az
+Azerbaydjan az
+阿塞拜疆 az
+亞塞拜然 az
+Bosnia and Herzegovina ba
+Bosnië en Herzegovina ba
+البوسنا و الهرسك ba
+Босьнія і Герцагавіна ba
+Боснена и Херцеговина ba
+Bosna i Hercegovina ba
+Bòsnia i Hercegovina ba
+Bosna a Herzegovina ba
+Bosnien-Herzegovina ba
+Bosnien und Herzegowina ba
+Βοσνία και Ερζεγοβίνη ba
+Bosnio kaj Hercegovino ba
+Bosnia y Herzegovina ba
+Bosnia ja Hertsegovina ba
+Bosnia eta Herzegovina ba
+بوسنی و هرزگوین ba
+Bosnia ja Herzegovina ba
+Bosnia-Herzegovina ba
+Bosnie herzégovine ba
+בוסניה הרצגובינה ba
+Bosna i Hercegovina ba
+Bosznia-Hercegovina ba
+Bosnia e Erzegovina ba
+ボスニアヘルツェゴビナ ba
+보스니아어와 헤르체고비나 ba
+ບອສເນີຍ ແລະ ເຫີເຊີໂກວິນາ ba
+Bosnija ir Hercegovina ba
+Bosnija un Hercogovina ba
+Bożnia u Ħerżegovina ba
+Bosnia-Hercegovina ba
+Bosnië en Herzegovina ba
+Bosnia-Hercegovina ba
+Bosnia le Herzegovina ba
+Bośnia i Hercegowina ba
+Bósnia e Herzegovina ba
+Bósnia Herzegóvina ba
+Bosnia şi Herţegovina ba
+Босния и Герцеговина ba
+Bosna a Hercegovina ba
+Bosna in Hercegovina ba
+I-Bosnia kanye ne Herzegovina ba
+Bosnien och Herzegovina ba
+¦À¡Íɢ¡ ba
+บอสเนีย และ เฮอร์เซโกวินา ba
+Bosna Hersek ba
+Боснія та Герцеговина ba
+Mubosinia na Muhezegovina ba
+Bosneye ba
+Bosnia ne Herzegovina ba
+波斯尼亚和黑塞哥维那 ba
+波士尼亞與赫塞哥維納 ba
+Bosnia kanye ne-Herzegovina ba
+Barbados bb
+بربادوس bb
+Барбадос bb
+Барбадос bb
+Μπαρμπάντος bb
+Babadoso bb
+باربادوس bb
+Barbade bb
+ברבדוס bb
+バルバドス bb
+바르바도스 bb
+ບາລບາດອດສ bb
+Barbadosas bb
+Barbadosa bb
+Барбадос bb
+I-Barbados bb
+À¡÷§À¼¡Í bb
+บาร์บาดอส bb
+Барбадос bb
+Barbades bb
+巴巴多斯 bb
+巴貝多 bb
+Bangladesh bd
+بنغلاديش bd
+Banqladeş bd
+Банглядэш bd
+Бангладеш bd
+Bangladeš bd
+Bangladéš bd
+Bangladesch bd
+Μπαγκλαντές bd
+Bangladeŝo bd
+بنگلادش bd
+בנגלדש bd
+Bangladeš bd
+Banglades bd
+バングラデシュ bd
+방글라데시 bd
+ບັງຄະລາເທດ bd
+Bangladešas bd
+Bangladeša bd
+Bangladexx bd
+Bangladesz bd
+Banglade bd
+Бангладеш bd
+Bangladéš bd
+Bangladeš bd
+I-Bangladesh bd
+Àí¸Ç¡§¾Í bd
+บังคลาเทศ bd
+Bangladeş bd
+Бангладеш bd
+孟加拉 bd
+孟加拉 bd
+Belgium be
+België be
+بلجيكا be
+Belçika be
+Бэльгія be
+Белгия be
+Belgia be
+Belgija be
+Bèlgica be
+Belgie be
+Belgien be
+Belgien be
+Βέλγιο be
+Belgio be
+Bélgica be
+Belgia be
+Belgika be
+بلژیک be
+Belgia be
+Belgia be
+Belgique be
+Bélxica be
+בלגיה be
+Belgija be
+Belgia be
+BelgÃa be
+Belgio be
+ベルギー be
+벨기에 be
+ເບລຢ່ງມ be
+Belgija be
+Beļģija be
+Belġju be
+Belgia be
+België be
+Belgia be
+Bèlgica be
+Belgia be
+Bélgica be
+Bélgica be
+Belgia be
+Бельгия be
+Belgicko be
+Belgija be
+Belgija be
+I-Belgium be
+Belgien be
+¦Àøº¢Âõ be
+เบลเยียม be
+Belçika be
+Бельгія be
+Beljike be
+比利时 be
+比利時 be
+Burkina Faso bf
+Буркіна Фасо bf
+Буркина Фаско bf
+ຕຸລະກີ bf
+Буркіна Фасо bf
+布基纳法索 bf
+Bulgaria bg
+Bulgarye bg
+بلغاريا bg
+Bolgarıstan bg
+Баўгарыя bg
+България bg
+Bugarska bg
+Bulgària bg
+Bulharsko bg
+Bulgarien bg
+Bulgarien bg
+Βουλγαρία bg
+Bulgario bg
+Bulgaaria bg
+بلغارستان bg
+Bulgarie bg
+בולגריה bg
+Bugarska bg
+Bulgária bg
+BúlgarÃa bg
+ブルガリア bg
+불가리아 bg
+ບັນແກເລີຍ bg
+Bulgarija bg
+Bulgārija bg
+Bulgarija bg
+Bulgarije bg
+Bułgaria bg
+Bulgária bg
+Bulgária bg
+Болгария bg
+Bulharsko bg
+Bolgarija bg
+Bugarska bg
+I-Bulgaria bg
+Bulgarien bg
+Àø§¸Ã¢Â¡ bg
+บัลแกเรีย bg
+Bulgaristan bg
+Болгарія bg
+Baligaria bg
+Bulgåreye bg
+保加利亚 bg
+保加利亞 bg
+Bahrain bh
+البحرين bh
+Бахрэйн bh
+Бахрейн bh
+Bahrein bh
+Bahrajn bh
+Μπαχρέιν bh
+Bahrein bh
+Bahrein bh
+بحرین bh
+בחריין bh
+バーレーン bh
+바레인 bh
+ຖັກກ່ງວ bh
+Bahreinas bh
+Baħrain bh
+Baghrein bh
+Bahrajn bh
+Bahamas bh
+Bahrein bh
+Бахрейн bh
+Bahrajn bh
+Bahrajn bh
+I-Bahrain bh
+Bahrein bh
+À‹¨Ãý bh
+Bahreyn bh
+Бахрейн bh
+巴林 bh
+巴林 bh
+Burundi bi
+Бурундзі bi
+Бурунди bi
+ເຄອຣດ bi
+Бурунді bi
+布隆迪 bi
+Benin bj
+Бэнін bj
+Бенин bj
+ບອສເນີຍ bj
+Бенін bj
+贝宁 bj
+Bermuda bm
+Бэрмуды bm
+Бермуда bm
+ເຍລລະມັນ bm
+Bermudy bm
+Bermudi bm
+Бермуди bm
+百慕大 bm
+Brunei Darussalam bn
+Брунэй bn
+Бруней bn
+Brunei bn
+Brunei Szultánság bn
+ເບລາລັສເຊີຍ bn
+Brunei bn
+Brunei Darusalam bn
+Бруней Даруссалам bn
+Bolivia bo
+Bolivië bo
+بوليفيا bo
+Boliviya bo
+Балівія bo
+Боливия bo
+Bolivija bo
+Bolívia bo
+Bolívie bo
+Bolivien bo
+Βολιβία bo
+Bolivio bo
+Boliivia bo
+بولیوی bo
+Bolivie bo
+בוליביה bo
+Bolivija bo
+Bolívia bo
+BólivÃa bo
+ボリビア bo
+볼리비아 bo
+ໂບລີເວີຍ bo
+Bolivija bo
+Bolīvija bo
+Bolivja bo
+Boliwia bo
+Bolívia bo
+Bolívia bo
+Боливия bo
+Bolívia bo
+Bolivija bo
+Bolivija bo
+I-Bolivia bo
+¦À¡Ä¢Å¢Â¡ bo
+โบลิเวีย bo
+Bolivya bo
+Болівія bo
+Boliveye bo
+波利维亚 bo
+玻利維亞 bo
+Brazil br
+Brazilië br
+البرازيل br
+Braziliya br
+Бразылія br
+Бразилия br
+Brasil br
+Brazílie br
+Brasilien br
+Brasilien br
+Βραζιλία br
+Brazilo br
+Brasil br
+Brasiilia br
+Brasil br
+برزیل br
+Brasilia br
+Brésil br
+Brasil br
+ברזיל br
+Brazília br
+BrasilÃa br
+Brasile br
+ブラジル br
+브라질 br
+ບາຊີລ br
+Brazilija br
+Brazīlija br
+Brażil br
+Brasil br
+Brazilië br
+Brasil br
+Brasil br
+Brazylia br
+Brasil br
+Brasil br
+Brazilia br
+Бразилия br
+Brazília br
+Brazilija br
+I-Brazil br
+Brasilien br
+À¢§Ãº¢ø br
+บราซิล br
+Brezilya br
+Бразилія br
+Burazili br
+Braezi br
+巴西 br
+巴西 br
+Bahamas bs
+Багамы bs
+Бахами bs
+Bahami bs
+Bahamák bs
+ປານາມາ bs
+Bahamy bs
+Bahami bs
+Багами bs
+巴哈马 bs
+Bhutan bt
+Бутан bt
+Бутан bt
+Butan bt
+Bhután bt
+Bhután bt
+ຖັກກ່ງວ bt
+Butan bt
+Бутан bt
+不丹 bt
+Botswana bw
+Батсвана bw
+Боцвана bw
+Bocvana bw
+ບອດສເນີຍ bw
+Botsvana bw
+Ботсвана bw
+博茨瓦纳 bw
+Belarus by
+روسيا البيضاء by
+Беларусь by
+Беларус by
+Bjelorusija by
+Bělorusko by
+Hviderusland by
+Weißrussland by
+Bjelorusio by
+Valgevene by
+بلاروس by
+Valkovenäjä by
+Hvítarusland by
+Bélarus by
+בלרוס by
+Bjelorusija by
+Fehéroroszország by
+HvÃta-Rússland by
+Bielorussia by
+ベラルーシ by
+벨라루스 by
+ເບລາລັສ by
+Baltarusija by
+Baltkrievu by
+Hviterussland by
+Wit-Rusland by
+Kviterussland by
+Białoruś by
+Bielorússia by
+Bielorusso by
+Беларусь by
+Bielorusko by
+Belorusija by
+I-Belarus by
+Vitryssland by
+¦ÀÄ¡åÍ by
+เบลารัส by
+Білорусія by
+Belaruss by
+白俄罗斯 by
+白俄羅斯 by
+Belize bz
+Бэлізе bz
+Белиз bz
+ເບລຍ່ງມ bz
+Беліз bz
+伯利兹 bz
+Default C
+Verstek C
+افتراضي C
+Əsas C
+Па ўмаўчаньні C
+По подразбиране C
+Dre ziouer C
+Omissió C
+Výchozí C
+Standard C
+Standard C
+Προκαθορισμένο C
+Apriora C
+Predeterminado C
+Vaikimisi C
+Aurremugatua C
+پیشفرض C
+Oletus C
+Forsettur C
+Par défaut C
+Por Omisión C
+ברירת מחדל C
+Uobičajeno C
+Alapértelmezett C
+Standar C
+Sjálfgefið C
+Predefinito C
+標準 C
+기본 C
+ຄ່າປະລິຍາຍ C
+Nutylima C
+Noklusētais C
+Normali C
+Standard C
+Standaard C
+Standard C
+Thuso ya Tshoganetso C
+Omission C
+Domyślnie C
+Por Omissão C
+Padrão C
+Implicit C
+По умолчанию C
+Štandardný C
+Privzeto C
+Predefinisano C
+Förval C
+¦¸¡¼¡¿¢¨Ä C
+ค่าปริยาย C
+Öntanımlı C
+Типовий C
+Mặc định C
+Prémetou C
+Okwendalo C
+默认 C
+預設 C
+Okwendalo C
+Canada ca
+Kanada ca
+كندا ca
+Kanada ca
+Канада ca
+Канада ca
+Kanada ca
+Kanada ca
+Canadà ca
+Kanada ca
+Kanada ca
+Καναδάς ca
+Kanado ca
+Canadá ca
+Kanada ca
+Kanada ca
+کانادا ca
+Kanada ca
+Kanada ca
+Canadá ca
+קנדה ca
+Kanada ca
+Kanada ca
+Kanada ca
+Kanada ca
+カナダ ca
+캐나다 ca
+ແຄນາດາ ca
+Kanada ca
+Kanāda ca
+Kanada ca
+Kanada ca
+Canadá ca
+Canadá ca
+Канада ca
+Kanada ca
+Kanada ca
+Kanada ca
+I-Canada ca
+Kanada ca
+¸É¼¡ ca
+แคนาดา ca
+Kanada ca
+Канада ca
+加拿大 ca
+加拿大 ca
+Cocos (Keeling) Islands cc
+Кокосови Острови cc
+Kokosovo (Keeling) ostrvo cc
+Islas Cocos (Keeling) cc
+Koko Irlak cc
+Kókusz-szigetek (Keeling) cc
+Ilhas Cocos cc
+Kokosove Ostrovy cc
+Kokosovi (Keelingovi) otoki cc
+Kokosöarna cc
+Кокосові острови cc
+Congo, the democratic republic of the cd
+Дэмакратычная Рэспубліка Конга cd
+Конго cd
+Kongo, demokratska republika cd
+Congo, den demokratiske republik cd
+Congo, república democrática del cd
+Kongo, errepublika demokratikoa cd
+Kongói Demokratikus Köztársaság cd
+República Democrática do Congo cd
+Demokratická Republika Kongo cd
+Kongo, demokratična republika cd
+Demokratiska republiken Kongo cd
+刚果民主共和国 cd
+Central African Republic cf
+ЦАР cf
+Centralnoafrička Republika cf
+Central-afrikanske Republik cf
+República Centroafricana cf
+Afrika Erdiko Errepublika cf
+Közép-Afrikai Köztársaság cf
+ໂດມິນິກັນ cf
+República da África Central cf
+Stredoafrická Republika cf
+Centralnoafriška republika cf
+Centralafrikanska Republiken cf
+Центральноафриканська республіка cf
+中非共和国 cf
+Congo cg
+Конга cg
+Конго cg
+Kongo cg
+Kongo cg
+Kongó cg
+ຄອນໂໍຊລ cg
+Kongo cg
+Kongo cg
+Kongo cg
+Конго cg
+刚果 cg
+Switzerland ch
+Switserland ch
+سويسرا ch
+İsveçrə ch
+Швэйцарыя ch
+Швейцария ch
+Suis ch
+Švicarska ch
+Suïssa ch
+Švýcarsko ch
+Schweiz ch
+Schweiz ch
+Ελβετία ch
+Svislando ch
+Suiza ch
+Šveits ch
+Suitza ch
+سوییس ch
+Sveitsi ch
+Suisse ch
+Suíza ch
+שוייץ ch
+Švicarska ch
+Svájc ch
+Swiss ch
+Sviss ch
+Svizzera ch
+スイス ch
+스위스 ch
+ສະວິສເຊີແລນ ch
+Šveicarija ch
+Šveice ch
+Svizzera ch
+Sveits ch
+Zwitserland ch
+Sveits ch
+Suissa ch
+Szwajcaria ch
+Suíça ch
+Suíça ch
+Elveţia ch
+Швейцария ch
+Švajčiarsko ch
+Švica ch
+Švajcarska ch
+I-Switzerland ch
+Schweiz ch
+ÍÅ¢ðº÷Ä¡óÐ ch
+สวิสเซอร์แลนด์ ch
+İsviçre ch
+Швейцарія ch
+Thuỵ Sĩ ch
+Swisse ch
+瑞士 ch
+瑞士 ch
+Cote d'ivoire ci
+Бераг Слановай Косьці ci
+Кот'Дивоар ci
+Obala Slonovače ci
+Elfenbenskysten ci
+Costa de Marfil ci
+Elefántcsontpart ci
+ປ່ອຍຫມາກກະລອກ ci
+Slonokoščena obala ci
+Elfenbenskusten ci
+Кот д'Івуар ci
+Cook islands ck
+Kukova ostrva ck
+Cook-øerne ck
+Islas Cook ck
+Cook Irlak ck
+Cook-szigetek ck
+ຄຸກກີ້ ck
+Ilhas Cook ck
+Cookove ostrovy ck
+Cookovi otoki ck
+Cooköarna ck
+Острови Кука ck
+库克群岛 ck
+Chile cl
+Chilië cl
+تشيلي cl
+Şili cl
+Чылі cl
+Чили cl
+Čile cl
+Xile cl
+Χιλή cl
+Ĉilio cl
+Tšiili cl
+Txile cl
+شیلی cl
+Chili cl
+צ'ילה cl
+Čile cl
+Chili cl
+Cile cl
+チリ cl
+칠레 cl
+ຊີລີ cl
+Čilė cl
+Čīle cl
+Ċile cl
+Chili cl
+Cile cl
+Чили cl
+Čile cl
+Čile cl
+Čile cl
+I-Chile cl
+º¢Ä¢ cl
+ชิลี cl
+Şili cl
+Чилі cl
+Chi lê cl
+Tchili cl
+智利 cl
+智利 cl
+Cameroon cm
+Камэрун cm
+Камерун cm
+Kamerun cm
+Cameroun cm
+Camerún cm
+Kamerun cm
+Kamerun cm
+ຕາລາງງານ - K cm
+Camarões cm
+Komerun cm
+Kamerun cm
+Kamerun cm
+Камерун cm
+喀麦隆 cm
+China cn
+Sjina cn
+الصين cn
+Çin cn
+Кітай cn
+Китай cn
+Sina cn
+Kina cn
+Xina cn
+Čína cn
+Kina cn
+Κίνα cn
+Ĉinujo cn
+Hiina cn
+Txina cn
+چین cn
+Kiina cn
+Kina cn
+Chine cn
+סין cn
+Kina cn
+Kína cn
+Cina cn
+KÃna cn
+Cina cn
+中国 cn
+중국 cn
+ຈີນ cn
+Kinija cn
+Ķīna cn
+Ċina cn
+Kina cn
+Kina cn
+Xina cn
+Chiny cn
+Китай cn
+Čína cn
+Kitajska cn
+Kina cn
+I-China cn
+Kina cn
+º£É¡ cn
+จีน cn
+Çin cn
+Китай cn
+Trung Quốc cn
+Chine cn
+中国 cn
+中國 cn
+Colombia co
+Colombië co
+كولمبيا co
+Калюмбія co
+Колумбия co
+Kolumbija co
+Colòmbia co
+Kolumbie co
+Kolumbien co
+Κολομβία co
+Kolumbio co
+Kolumbia co
+Kolonbia co
+کلمبیا co
+Kolumbia co
+Colombie co
+קולומביה co
+Kolumbija co
+Kolumbia co
+コロンビア co
+콜롬비아 co
+ໂຄລຳເບີຍ co
+Kolumbija co
+Kolumbija co
+Kolumbja co
+Columbia co
+Kolumbia co
+Colômbia co
+Colômbia co
+Columbia co
+Колумбия co
+Kolumbia co
+Kolumbija co
+I-Colombia co
+¦¸¡ÄõÀ¢Â¡ co
+โคลัมเบีย co
+Kolombiya co
+Колумбія co
+Colombeye co
+Columbia co
+哥伦比亚 co
+哥倫比亞 co
+Costa Rica cr
+كوستاريكا cr
+Коста Рыка cr
+Коста Рика cr
+Kostarika cr
+Kostarika cr
+Κόστα Ρίκα cr
+کاستاریکا cr
+Kosta Rika cr
+קוסטה ריקה cr
+Costa rica cr
+コスタリカ cr
+코스타 리카 cr
+ໂຄເອເທີຍ cr
+Kosta Rika cr
+Kostaryka cr
+Коста-Рика cr
+Kostarika cr
+Kostarika cr
+I-Costa Rica cr
+§¸¡Š¼¡ ⸡ cr
+Kosta Rika cr
+Коста-Ріка cr
+哥斯达黎加 cr
+哥斯大黎加 cr
+Cuba cu
+Kuba cu
+كوبا cu
+Куба cu
+Куба cu
+Kuba cu
+Kuba cu
+Kuba cu
+Κούβα cu
+Kuuba cu
+Kuba cu
+کوبا cu
+Kuuba cu
+Kuba cu
+קובה cu
+Kuba cu
+キューバ cu
+쿠바 cu
+ເກມໄພ່ cu
+Kuba cu
+Kuba cu
+Kuba cu
+Куба cu
+Kuba cu
+Kuba cu
+I-Cuba cu
+Kuba cu
+¸¢ÔÀ¡ cu
+Küba cu
+Куба cu
+古巴 cu
+古巴 cu
+Cape Verde cv
+Капе Верде cv
+Zelenortska ostrva cv
+Kapverdiske øer cv
+Cabo Verde cv
+Cabo Verde cv
+Zöldfoki-szigetek cv
+ເກມໄພ່ cv
+Cabo Verde cv
+Kap Verde cv
+佛得角 cv
+Christmas Island cx
+Božično ostrvo cx
+Juleøen cx
+Islas Christmas cx
+Eguberri Irla cx
+Karácsony-szigetek cx
+ຄິດສະຕອລ cx
+Ilhas do Natal cx
+Vianočné Ostrovy cx
+Božični otok cx
+Julön cx
+Острів Різдва cx
+圣诞岛 cx
+Cyprus cy
+Кіпр cy
+Кипър cy
+Kipar cy
+Cypern cy
+Chipre cy
+Txipre cy
+Ciprus cy
+ບີບອັດ cy
+Chipre cy
+Ciper cy
+Cypern cy
+Кипр cy
+塞浦路斯 cy
+Czechia cz
+Czechië cz
+التشيك cz
+Çex Respublikası cz
+Чэхія cz
+Чехия cz
+Tchekia cz
+Češka cz
+Txèquia cz
+Česko cz
+Tjekkiet cz
+Tschechien cz
+Τσεχία cz
+Ĉeĥio cz
+República Checa cz
+Tšehhi cz
+Txekia cz
+چک cz
+Tsekki cz
+République tchèque cz
+Chequia cz
+צ'כיה cz
+Češka cz
+Csehország cz
+Tékkland cz
+Repubblica Ceca cz
+チェコ cz
+체코 cz
+Čekija cz
+Čehija cz
+Cżekia cz
+Tsjekkia cz
+Tsjechië cz
+Tsjekkia cz
+Chèquia cz
+Czechy cz
+República Checa cz
+República Tcheca cz
+Cehia cz
+Чехия cz
+Česko cz
+Češka cz
+Češka cz
+I-Czechia cz
+Tjeckien cz
+¦ºì¡ cz
+Çek Cumhuriyeti cz
+Чехія cz
+Séc cz
+Tchekeye cz
+捷克 cz
+捷克 cz
+Germany de
+Duitsland de
+ألمانيا de
+Almaniya de
+Нямеччына de
+Германия de
+Alamagn de
+Njemačka de
+Alemanya de
+Německo de
+Tyskland de
+Deutschland de
+Γερμανία de
+Germanio de
+Alemania de
+Saksamaa de
+Alemania de
+ آلمان de
+Saksa de
+Týskland de
+Allemagne de
+Alemaña de
+גרמניה de
+Njemačka de
+Németország de
+Jerman de
+Ã\9eýskaland de
+Germania de
+ドイツ de
+독일 de
+ເຍລລະມັນນີ de
+Vokietija de
+Vācija de
+Ġermanja de
+Tyskland de
+Duitsland de
+Tyskland de
+Alemanya de
+Niemcy de
+Alemanha de
+Alemanha de
+Germania de
+Германия de
+Nemecko de
+Nemčija de
+Nemačka de
+I-Germany de
+Tyskland de
+§º÷ÁÉ¢ de
+เยอรมันนี de
+Almanya de
+Німеччина de
+Đức de
+Almagne de
+德国 de
+德國 de
+IJalimani de
+Djibouti dj
+جيبوتي dj
+Джыбуці dj
+Джибути dj
+Đibuti dj
+Džibuti dj
+Dschibuti dj
+Τζιμπουτί dj
+جیبوتی dj
+ג'יבוטי dj
+Džibuti dj
+Dzsibuti dj
+ジブティ dj
+지부티 dj
+ພັດພາ dj
+Džibuti dj
+Dġibuti dj
+Dżibuti dj
+Djibuti dj
+Djibuti dj
+Джибути dj
+Džibuty dj
+Džibuti dj
+I-Djibouti dj
+Ê¢ƒ¢¦À¡Ê dj
+Cibuti dj
+Джібуті dj
+吉布提 dj
+吉布地 dj
+Denmark dk
+Denemarke dk
+الدنمارك dk
+Danimarka dk
+Данія dk
+Дания dk
+Danmark dk
+Danska dk
+Dinamarca dk
+Dánsko dk
+Danmark dk
+Dänemark dk
+Δανία dk
+Danlando dk
+Dinamarca dk
+Taani dk
+Danimarka dk
+دانمارک dk
+Tanska dk
+Danmark dk
+Danemark dk
+Dinamarca dk
+דנמרק dk
+Danska dk
+Dánia dk
+Danmörk dk
+Danimarca dk
+デンマーク dk
+덴마크 dk
+ເດນມາກ dk
+Danija dk
+Dānija dk
+Danimarka dk
+Danmark dk
+Denemarken dk
+Danmark dk
+Dinamarca dk
+Dania dk
+Dinamarca dk
+Dinamarca dk
+Danemarca dk
+Дания dk
+Dánsko dk
+Danska dk
+Danska dk
+I-Denmark dk
+Danmark dk
+¦¼ýÁ¡÷ì dk
+เดนมาร์ก dk
+Danimarka dk
+Данія dk
+Đan Mạch dk
+Daenmåtche dk
+丹麦 dk
+丹麥 dk
+Dominica dm
+Дамініка dm
+Доминика dm
+Dominika dm
+Dominika dm
+ໂລມາເນີຍ dm
+Dominicana dm
+Dominikánsko dm
+Dominikanska republika dm
+Домініка dm
+多米尼加 dm
+Dominican Republic do
+Dominikiese Republiek do
+جمهورية الدومينيكان do
+Dominik Respublikası do
+Дамініканская Рэспубліка do
+Доминиканска република do
+Republik Dominikan do
+Dominikanska Republika do
+República Dominicana do
+Dominikánská republika do
+Dominikanske Republik do
+Dominikanische Republik do
+Δομινικανή Δημοκρατία do
+Dominika Respubliko do
+República Dominicana do
+Dominikaani Vabariik do
+Dominikar Errepublika do
+جمهوری دامینیکن do
+Dominikaaninen tasavalta do
+République dominicaine do
+República Dominicana do
+הרפובליקה הדומיניקנית do
+Dominikanska Republika do
+Dominikai Köztársaság do
+Republik Dominika do
+DóminÃska Lýðveldið do
+Repubblica Dominicana do
+ドミニカ共和国 do
+도미니카 공화국 do
+ໂດມິນີກັນ do
+Dominikos Respublika do
+Dominikas Republika do
+Repubblika Dominikana do
+Den dominikanske republikk do
+Dominicaanse Republiek do
+Den dominikanske republikken do
+Republica Dominicana do
+Dominikana do
+República Dominicana do
+República Dominicana do
+Republica Dominicană do
+Доминиканская республика do
+Dominikánska republika do
+Dominikanska republika do
+Dominikanska republika do
+I-Dominican Republic do
+Dominikanska republiken do
+¦¼¡Á¢É¢ì¸ý ÌÊÂÃÍ do
+โดมินิกัน do
+Dominik Cumhuriyeti do
+Домініканська республіка do
+Muvhuso wa Dominican do
+Cộng hoà Dominican do
+Republike Dominikinne do
+IRepublic yeDominican do
+多米尼加共和国 do
+多明尼加共和國 do
+Algeria dz
+Algerië dz
+الجزائر dz
+Альжыр dz
+Алжир dz
+Alžir dz
+Algèria dz
+Alžírsko dz
+Algeriet dz
+Algerien dz
+Αλγερία dz
+Algerio dz
+Argelia dz
+Alžeeria dz
+ الجزیره dz
+Algérie dz
+אלג'יריה dz
+Alžir dz
+Algéria dz
+アルジェリア dz
+알제리 dz
+ບັນກາເລີຍ dz
+Alžyras dz
+Alġerija dz
+Algerie dz
+Algerije dz
+Algerie dz
+Algieria dz
+Argélia dz
+Argélia dz
+Алжир dz
+Alžírsko dz
+Alžirija dz
+I-Algeria dz
+Algeriet dz
+«øƒ¢Ã¢Â¡ dz
+Алжир dz
+Aldjereye dz
+阿尔及利亚 dz
+阿爾及利亞 dz
+Equador ec
+Ewenaar ec
+الإكوادور ec
+Ekvator ec
+Эквадор ec
+Еквадор ec
+Ecuador ec
+Ekvador ec
+Ekvádor ec
+Ecuador ec
+Ισημερινός ec
+Ekvadoro ec
+Ecuador ec
+Ekvador ec
+Ekuador ec
+اکوادور ec
+Équateur ec
+Ecuador ec
+אקוודור ec
+Ekvador ec
+Ecuador ec
+Ekvador ec
+Ecuador ec
+エクアドル ec
+에콰도르 ec
+ເອກໍດໍ ec
+Ekvadoras ec
+Ekvadora ec
+Ekwador ec
+Ecuador ec
+Ecuador ec
+Ekwador ec
+Ecuador ec
+Эквадор ec
+Ekvádor ec
+Ekvador ec
+Ekvador ec
+I-Equador ec
+®ì¦Å§¼¡÷ ec
+เอกวาดอร์ ec
+Ekvator ec
+Еквадор ec
+Ecwåteur ec
+厄瓜多尔 ec
+厄瓜多 ec
+Estonia ee
+Estlandies ee
+استونيا ee
+Estoniya ee
+Эстонія ee
+Естония ee
+Estonija ee
+Estònia ee
+Estonsko ee
+Estland ee
+Estland ee
+Εσθονία ee
+Estlando ee
+Eesti ee
+استونی ee
+Eesti ee
+Estonie ee
+אסטוניה ee
+Estonija ee
+Észtország ee
+Eistland ee
+エストニア ee
+에스토니아 ee
+ເອໂທເນີຍ ee
+Estija ee
+Igaunija ee
+Estonja ee
+Estland ee
+Estland ee
+Estland ee
+Estònia ee
+Estónia ee
+Estônia ee
+Эстония ee
+Estónsko ee
+Estonija ee
+Estonija ee
+I-Estonia ee
+Estland ee
+±Í§¼¡É¢Â¡ ee
+เอสโธเนีย ee
+Estonya ee
+Естонія ee
+Estoneye ee
+爱沙尼亚 ee
+愛沙尼亞 ee
+Egypt eg
+Egipte eg
+مصر eg
+Misir eg
+Эгіпэт eg
+Египет eg
+Egipat eg
+Egipte eg
+Egypten eg
+Ägypten eg
+Αίγυπτος eg
+Egiptujo eg
+Egipto eg
+Egiptus eg
+Egypto eg
+مصر eg
+Egypti eg
+Egyptaland eg
+Égypte eg
+מצרים eg
+Egipat eg
+Egyiptom eg
+Egyptaland eg
+Egitto eg
+エジプト eg
+이집트 eg
+ອີຢີບ eg
+Egiptas eg
+Ēģipte eg
+Eġittu eg
+Egypte eg
+Egepeta eg
+Egipt eg
+Egipto eg
+Egito eg
+Egipt eg
+Египет eg
+Egipt eg
+I-Egypt eg
+Egypten eg
+±¸¢ôÐ eg
+อียิปต์ eg
+Mısır eg
+Єгипет eg
+Edjipe eg
+埃及 eg
+埃及 eg
+Igibhithe eg
+Western Sahara eh
+Западна Сахара eh
+Zapadna Sahara eh
+Vestsahara eh
+Sahara occidental eh
+Mendebaldeko Sahara eh
+Nyugat-Szahara eh
+ພື້ນທີ່ທຳງານ eh
+Sahara eh
+Západna Sahara eh
+Zahodna Sahara eh
+Västsahara eh
+Західна Сахара eh
+西撒哈拉 eh
+Eritrea er
+Эрытрэя er
+Еритрея er
+Eritreja er
+ແກ້ໄຂແຟ້ມທຳງານ er
+Eritreja er
+Еритрея er
+厄立特里亚 er
+Spain es
+Spanje es
+أسبانيا es
+İspaniya es
+Гішпанія es
+Испания es
+Spagn es
+Španija es
+Espanya es
+Španělsko es
+Spanien es
+Spanien es
+Ισπανία es
+Hispanio es
+España es
+Hispaania es
+Espainia es
+اسپانیا es
+Espanja es
+Spania es
+Espagne es
+España es
+ספרד es
+Španjolska es
+Spanyolország es
+Spanyol es
+Spánn es
+Spagna es
+スペイン es
+스페인 es
+ສະເປັນ es
+Ispanija es
+Spānija es
+Spanja es
+Spania es
+Spanje es
+Spania es
+Espanha es
+Hiszpania es
+Espanha es
+Espanha es
+Spania es
+Испания es
+Španielsko es
+Španija es
+Španija es
+I-Spain es
+Spanien es
+ͦÀ¢ý es
+สเปน es
+İspanya es
+Іспанія es
+Tây Ban Nha es
+Sipagne es
+西班牙 es
+西班牙 es
+Ethiopia et
+Этыёпія et
+Етиопия et
+Etiopija et
+Ethiopien et
+Etiopía et
+Etiopia et
+Etiópia et
+ເອໂທເນີຍ et
+Etiópia et
+Etiópia et
+Etiopija et
+Etiopien et
+Ефіопія et
+埃塞俄比亚 et
+Finland fi
+فنلندا fi
+Finlandiya fi
+Фінляндыя fi
+Финландия fi
+Finska fi
+Finlàndia fi
+Finsko fi
+Finnland fi
+Φινλανδία fi
+Finlando fi
+Finlandia fi
+Soome fi
+Finlandia fi
+فنلاند fi
+Suomi fi
+Finnland fi
+Finlande fi
+Finlandia fi
+פינלנד fi
+Finska fi
+Finnország fi
+Finlandia fi
+Finnland fi
+Finlandia fi
+フィンランド fi
+핀란드 fi
+ຟີນແລນ fi
+Suomija fi
+Somija fi
+Finlandja fi
+Finlandia fi
+Finlandia fi
+Finlândia fi
+Finlândia fi
+Finlanda fi
+Финляндия fi
+Fínsko fi
+Finska fi
+Finska fi
+I-Finland fi
+À¢ýÄ¡óÐ fi
+ฟินแลนด์ fi
+Finlandiya fi
+Фінляндія fi
+Phần Lan fi
+Finlande fi
+芬兰 fi
+芬蘭 fi
+Fiji fj
+Фіджы fj
+Фиджи fj
+Fidži fj
+Fidzsi fj
+ມີດີ fj
+Ilhas Fiji fj
+Fidži fj
+Fidži fj
+Фіджі fj
+斐济 fj
+Falkland Islands (Malvinas) fk
+Фолклендски Острови fk
+Foklandska ostrva (Malvini) fk
+Falkland-øerne fk
+Islas Falkland (Malvinas) fk
+Falkland Irlak (Malvinak) fk
+Falkland-szigetek fk
+Ilhas Malvinas fk
+Falklandské Ostrovy (Malviny) fk
+Falklandski otoki (Malvini) fk
+Falklandsöarna fk
+福克兰岛 (马尔维纳斯) fk
+Micronesia, Federated states of fm
+Федэрацыя Мiкранэзіі fm
+Микронезия fm
+Mikronezija, Federalne države fm
+Mikronesien, de forenede stater af fm
+Micronesia, Estados federados de fm
+Mikronesia, Estatu Federatuak fm
+Mikronézia fm
+Estados Federados da Micronésia fm
+Spjoené štáty Mikronézie fm
+Mikronezija, Združene države fm
+Mikronesiska federationen fm
+密克罗尼西亚联邦 fm
+Faroe Islands fo
+Фареорски Острови fo
+Farska ostrva fo
+Færøerne fo
+islas Faroe fo
+Faroe Irlak fo
+Faroe-szigetek fo
+ໄອແລນ fo
+Ilhas Faroe fo
+Ostrovy Faroe fo
+Otoki Faroe fo
+Färöarna fo
+Фарерські острови fo
+France fr
+Frankryk fr
+فرنسا fr
+Fransa fr
+Францыя fr
+Франция fr
+Frañs fr
+Francuska fr
+França fr
+Francie fr
+Frankrig fr
+Frankreich fr
+Γαλλία fr
+Francio fr
+Francia fr
+Prantsusmaa fr
+Frantzia fr
+فرانسه fr
+Ranska fr
+Frakland fr
+Francia fr
+צרפת fr
+Francuska fr
+Franciaország fr
+Prancis fr
+Frakkland fr
+Francia fr
+フランス fr
+프랑스 fr
+ຝຣັ່ງ fr
+Prancūzija fr
+Francija fr
+Franza fr
+Frankrike fr
+Frankrijk fr
+Frankrike fr
+Fora fr
+França fr
+Francja fr
+França fr
+França fr
+Franţa fr
+Франция fr
+Francúzsko fr
+Francija fr
+Francuska fr
+I-France fr
+Frankrike fr
+À¢Ã¡ýÍ fr
+ฝรั่งเศส fr
+Fransa fr
+Франція fr
+Fura fr
+Pháp fr
+Fransi fr
+法国 fr
+法國 fr
+Gabon ga
+Габон ga
+Габон ga
+Gabón ga
+ແກລ່ງນ ga
+Gabão ga
+Габон ga
+加蓬 ga
+United Kingdom gb
+Vereenigde Koninkryk gb
+المملكة المتحدة gb
+Birləşmiş Krallıq gb
+Злучанае Каралеўства gb
+Великобритания gb
+Rouantelezh Unanet gb
+Velika Britanija gb
+Regne Unit gb
+Spojené království gb
+Storbritannien gb
+Großbritannien gb
+Ηνωμένο Βασίλειο gb
+Britio gb
+Reino Unido gb
+Ühendatud Kuningriigid gb
+Erreinu Batua gb
+بریتانیا gb
+Iso-Britannia gb
+Stórabretland gb
+Royaume Uni gb
+Reino Unido gb
+בריטניה gb
+Ujedinjeno Kraljevstvo gb
+Egyesült Királyság gb
+Inggris gb
+Stóra Bretland gb
+Regno Unito gb
+イギリス gb
+영국 gb
+ສະຫະລາດສະອານາຈັກ gb
+Jungtinė Karalystė gb
+Apvienotā Karaliste gb
+Renju Unit gb
+Storbritannia gb
+Verenigd Koninkrijk gb
+Storbritannia gb
+Regne Unit gb
+Wielka Brytania gb
+Reino Unido gb
+Reino Unido gb
+Anglia gb
+Великобритания gb
+Anglicko gb
+Združeno kraljestvo gb
+Velika Britanija gb
+I-United Kingdom gb
+Storbritannien gb
+³ì¸¢Â áÂõ gb
+สหราชอาณาจักร gb
+Birleşik Krallık gb
+Великобританія gb
+Anh gb
+United Kingdom gb
+联合王国 gb
+聯合王國 gb
+United Kingdom gb
+Grenada gd
+غرينادا gd
+Qrenada gd
+Грэнада gd
+Гренада gd
+Granada gd
+Γρενάδα gd
+Grenado gd
+Granada gd
+گرانادا gd
+Grenade gd
+Granada gd
+גרנדה gd
+Grænhöfðaeyjar gd
+Granada gd
+グラナダ gd
+그러네이다 gd
+ເກນາດາ gd
+Grenāda gd
+Granada gd
+Granada gd
+Granada gd
+Гренада gd
+I-Grenada gd
+¸¢¦Ãɼ¡ gd
+เกรนาดา gd
+Гренада gd
+格林纳达 gd
+格瑞那達 gd
+Georgia ge
+Грузія ge
+Грузия ge
+Gruzija ge
+Georgien ge
+Grúzia ge
+ເຊີເບີຍ ge
+Geórgia ge
+Gruzija ge
+Georgien ge
+Грузія ge
+格鲁吉亚 ge
+Ghana gh
+غانا gh
+Гана gh
+Гана gh
+Gana gh
+Γκάνα gh
+غنا gh
+גאנה gh
+ガーナ gh
+ຈີນ gh
+Gana gh
+Gana gh
+Gana gh
+Гана gh
+Gana gh
+I-Ghana gh
+¸¡É¡ gh
+Гана gh
+加纳 gh
+迦納 gh
+Gibraltar gi
+Гибралтар gi
+Gibraltár gi
+ມອລຕາ gi
+Гібралтар gi
+直布罗陀 gi
+Gambia gm
+Гамбія gm
+Гамбия gm
+Gambija gm
+ແກມມາ gm
+Gâmbia gm
+Gambija gm
+Гамбія gm
+冈比亚 gm
+Guinea gn
+Гвінэя gn
+Гвинея gn
+Gvineja gn
+ເຖາວັນ gn
+Guiné gn
+Gvineja gn
+Гвінея gn
+几内亚 gn
+Guadeloupe gp
+Гвадалупа gp
+Gvadalupe gp
+Guadalupe gp
+ເດີລຸກ gp
+Guadalupe gp
+Гваделупа gp
+瓜德罗普岛 gp
+Equatorial Guinea gq
+Экватарыяльная Гвінэя gq
+Екваториялна Гвинея gq
+Ekvatorijalna Gvineja gq
+Ækvatorial Guinea gq
+Guinea equatorial gq
+Ginea Ekuatoriala gq
+Egyenlítői Guinea gq
+ການສອນ gq
+Guiné Equatorial gq
+Rovníkova Guinea gq
+Ekvatorialna Gvineja gq
+Ekvatorialguinea gq
+Екваторіальна Гвінея gq
+赤道几内亚 gq
+Greece gr
+Griekeland gr
+اليونان gr
+Yunanıstan gr
+Грэцыя gr
+Гърция gr
+Gres gr
+Grčka gr
+Grècia gr
+Řecko gr
+Grækenland gr
+Griechenland gr
+Ελλάδα gr
+Grekujo gr
+Grecia gr
+Kreeka gr
+Grezia gr
+یونان gr
+Kreikka gr
+Grikkaland gr
+Grèce gr
+Grecia gr
+יוון gr
+Grčka gr
+Görögország gr
+Grikkland gr
+Grecia gr
+ギリシャ gr
+그리스 gr
+ກີຊ gr
+Graikija gr
+Grieķija gr
+Greċja gr
+Hellas gr
+Griekenland gr
+Hellas gr
+Grèça gr
+Grecja gr
+Grécia gr
+Grécia gr
+Grecia gr
+Греция gr
+Grécko gr
+Grčija gr
+Grčka gr
+I-Greece gr
+Grekland gr
+¸¢Ã£Í gr
+กรีซ gr
+Yunanistan gr
+Греція gr
+Hy Lạp gr
+Grece gr
+希腊 gr
+希臘 gr
+Guatemala gt
+Gautemala gt
+غواتيمالا gt
+Quatemala gt
+Гватэмала gt
+Гватемала gt
+Gvatemala gt
+Γουατεμάλα gt
+Gvatemalo gt
+Guatemaala gt
+گواتمالا gt
+גואטמלה gt
+Gvatemala gt
+カタロニア gt
+과테말라 gt
+ກັວເຕມາລາ gt
+Gvatemala gt
+Gvatemala gt
+Gwatemala gt
+Gwatemala gt
+Гватемала gt
+Gvatemala gt
+Gvatemala gt
+I-Guatemala gt
+ÌÅ¡ò¾Á¡Ä¡ gt
+กัวเตมาลา gt
+Гватемала gt
+Gwatemala gt
+瓜地马拉 gt
+瓜地馬拉 gt
+Guam gu
+Гуам gu
+ແກມມາ gu
+Гуам gu
+关岛 gu
+Guinea-Bissau gw
+Гвінэя-Бісаў gw
+Гвинея-Бисау gw
+Gvineja-Bisau gw
+Ginea-Bissau gw
+Bissau-Guinea gw
+ລັດເຊີຍ gw
+Guiné-Bissau gw
+Гвінея-Біссау gw
+几内亚比绍 gw
+Guyana gy
+Гвіяна gy
+Гуана gy
+Gvajana gy
+ຈີນ gy
+Guiana gy
+Gvajana gy
+Гаяна gy
+圭亚那 gy
+Hong Kong hk
+Ганконг hk
+Хонг Конг hk
+Hongkong hk
+ບໍ່ຮູ້ຈັກ hk
+Гонконг hk
+香港 hk
+Honduras hn
+هندوراس hn
+Гандурас hn
+Хондурас hn
+Hondures hn
+Ονδούρα hn
+Honduraso hn
+Honduuras hn
+هندوراس hn
+הונדורס hn
+ホンデュラス hn
+온두라스 hn
+ຫອນດູລັດ hn
+Hondūras hn
+Hondurasa hn
+Ħonduras hn
+Hondures hn
+Гондурас hn
+I-Honduras hn
+¬ñÎá\8aÍ hn
+ฮอนดูรัส hn
+Гондурас hn
+洪都拉斯 hn
+宏都拉斯 hn
+Croatia hr
+Kroatië hr
+كرواتيا hr
+Xırvatıstan hr
+Харватыя hr
+Хърватска hr
+Kroatia hr
+Hrvatska hr
+Croàcia hr
+Chorvatsko hr
+Kroatien hr
+Kroatien hr
+Κροατία hr
+Kroatio hr
+Croacia hr
+Horvaatia hr
+Kroazia hr
+کرواسی hr
+Kroatia hr
+Kroatia hr
+Croatie hr
+Croacia hr
+קרואטיה hr
+Hrvatska hr
+Horvátország hr
+Kroasia hr
+KróatÃa hr
+Croazia hr
+クロアチア hr
+크로아티아 hr
+ໂຄເອເທີຍ hr
+Kroatija hr
+Horvātija hr
+Kroazja hr
+Kroatia hr
+Kroatië hr
+Kroatia hr
+Croacia hr
+Chorwacja hr
+Croácia hr
+Croácia hr
+Croaţia hr
+Хорватия hr
+Chorvátsko hr
+Hrvaška hr
+Hrvatska hr
+I-Croatia hr
+Kroatien hr
+̦á§Åº¢Â¡ hr
+โครเอเธีย hr
+Hırvatistan hr
+Хорватія hr
+Crowåceye hr
+克罗地亚 hr
+克羅埃西亞 hr
+Haiti ht
+Гаіці ht
+Хаити ht
+Haití ht
+ວາດຮູບ - K ht
+Гаїті ht
+海地岛 ht
+Hungary hu
+Hongarye hu
+هنغاريا hu
+Macarıstan hu
+Вугоршчына hu
+Унгария hu
+Hungaria hu
+Mađarska hu
+Hongria hu
+Maďarsko hu
+Ungarn hu
+Ungarn hu
+Ουγγαρία hu
+Hungario hu
+Hungría hu
+Ungari hu
+Hungaria hu
+مجارستان hu
+Unkari hu
+Ungarn hu
+Hongrie hu
+Hungría hu
+הונגריה hu
+Mađjarska hu
+Magyarország hu
+Hungaria hu
+Ungverjaland hu
+Ungheria hu
+ハンガリー hu
+헝가리 hu
+ຫັງກາລີ hu
+Vengrija hu
+Ungārija hu
+Ungerija hu
+Ungarn hu
+Hongarije hu
+Ungarn hu
+Hongria hu
+Węgry hu
+Hungria hu
+Hungria hu
+Ungaria hu
+Венгрия hu
+Maďarsko hu
+Madžarska hu
+Mađarska hu
+I-Hungary hu
+Ungern hu
+¬í§¸Ã¢ hu
+ฮังการี hu
+Macaristan hu
+Угорщина hu
+Hongreye hu
+匈牙利 hu
+匈牙利 hu
+Indonesia id
+Indonesië id
+إندونيسيا id
+İndoneziya id
+Інданэзія id
+Индонезия id
+Indonezija id
+Indonèsia id
+Indonésie id
+Indonesien id
+Indonesien id
+Ινδονησία id
+Indonezio id
+Indoneesia id
+اندونزی id
+Indonésie id
+אינדונזיה id
+Indonezija id
+Indonézia id
+IndónesÃa id
+インドネシア id
+인도네시아 id
+ອີຍໂດນີເຊີຍ id
+Indonezija id
+Indonēzija id
+Indoneżja id
+Indonesië id
+Indonezja id
+Indonésia id
+Indonésia id
+Indonezia id
+Индонезия id
+Indonézia id
+Indonezija id
+I-Indonesia id
+Indonesien id
+󧾡ɣº¢Â¡ id
+อินโดนีเซีย id
+İndonezya id
+Індонезія id
+Indoneseye id
+印度尼西亚 id
+印尼 id
+Ireland ie
+Ierland ie
+أيرلندا ie
+İrlandiya ie
+Ірляндыя ie
+Ирландия ie
+Iwerzhon ie
+Irska ie
+Irlanda ie
+Irsko ie
+Irland ie
+Irland ie
+Ιρλανδία ie
+Islando ie
+Irlanda ie
+Island ie
+Irlanda ie
+ایرلند ie
+Irlanti ie
+Írland ie
+Irlande ie
+Irlanda ie
+אירלנד ie
+Irska ie
+Írország ie
+Irlandia ie
+Ã\8drland ie
+Irlanda ie
+アイスランド ie
+아일랜드 ie
+ໄອແລນ ie
+Airija ie
+Īrija ie
+Irlanda ie
+Irland ie
+Ierland ie
+Irland ie
+Irlanda ie
+Irlandia ie
+Irlanda ie
+Irlanda ie
+Irlanda ie
+Ирландия ie
+Írsko ie
+Irska ie
+Irska ie
+I-Ireland ie
+Irland ie
+«Â÷Ä¡óÐ ie
+ไอร์แลนด์ ie
+İrlanda ie
+Ірландія ie
+Irlande ie
+爱尔兰 ie
+愛爾蘭 ie
+Israel il
+اسرائيل il
+İzrail il
+Ізраіль il
+Израел il
+Izrael il
+Izrael il
+Ισραήλ il
+Israelo il
+Iisrael il
+اسراییل il
+Ísrael il
+Israël il
+ישראל il
+Izrael il
+Izrael il
+Ã\8dsrael il
+Israele il
+イスラエル il
+이스라엘 il
+ອິດສະລະເອລ il
+Izraelis il
+Izraēla il
+Iżrael il
+Izrael il
+Израиль il
+Izrael il
+Izrael il
+Izrael il
+I-Israel il
+Í§Ãø il
+อิสราเอล il
+İsrail il
+Ізраїль il
+Israyel il
+USirayeli il
+以色列 il
+以色列 il
+India in
+Indië in
+الهند in
+Hindistan in
+Індыя in
+Индия in
+Indija in
+Índia in
+Indie in
+Indien in
+Indien in
+Ινδία in
+Hindujo in
+هندوستان in
+Intia in
+Inde in
+הודו in
+Indija in
+Indland in
+インド in
+인도 in
+ອິນເດີຍ in
+Indija in
+Indija in
+Indja in
+Indie in
+Índia in
+Índia in
+Индия in
+Indija in
+I-India in
+Indien in
+ó¾¢Â¡ in
+อินเดีย in
+Hindistan in
+Індія in
+Inde in
+印度 in
+印度 in
+Endiya in
+Iraq iq
+Irak iq
+العراق iq
+İraq iq
+Ірак iq
+Ирак iq
+Irak iq
+Irák iq
+Irak iq
+Irak iq
+Ιράκ iq
+Irako iq
+Irak iq
+Iraak iq
+عراق iq
+Irak iq
+Irak iq
+Irak iq
+עירק iq
+Irak iq
+Irak iq
+Ã\8drak iq
+Irak iq
+イラク iq
+이라크 iq
+ອີລັກ iq
+Irakas iq
+Irāka iq
+Irak iq
+Irak iq
+Irak iq
+Irak iq
+Iraque iq
+Iraque iq
+Irak iq
+Ирак iq
+Irák iq
+Irak iq
+I-Iraq iq
+Irak iq
+®Ã¡ì iq
+อิรัค iq
+Irak iq
+Ірак iq
+Irak iq
+伊拉克 iq
+伊拉克 iq
+Iran ir
+أيران ir
+Іран ir
+Иран ir
+Írán ir
+Ιράν ir
+Iraan ir
+ایران ir
+אירן ir
+Irán ir
+イラン ir
+이란 ir
+ອີລັກ ir
+Iranas ir
+Irão ir
+Irã ir
+Иран ir
+Irán ir
+I-Iran ir
+®Ã¡ý ir
+İran ir
+Іран ir
+伊朗 ir
+伊朗 ir
+Iceland is
+Ysland is
+أيسلندا is
+İslandiya is
+Ісьляндыя is
+Исландия is
+Island is
+Island is
+Islàndia is
+Island is
+Island is
+Island is
+Ισλανδία is
+Islando is
+Islandia is
+Island is
+Islandia is
+ایسلند is
+Islanti is
+Ísland is
+Islande is
+Islandia is
+איסלנד is
+Island is
+Izland is
+Islandia is
+Ã\8dsland is
+Islanda is
+アイスランド is
+아이슬란드 is
+ໄອຊແລນ is
+Islandija is
+Islande is
+Islandja is
+Island is
+IJsland is
+Island is
+Islandia is
+Islandia is
+Islândia is
+Islândia is
+Islanda is
+Исландия is
+Island is
+Islandija is
+Island is
+I-Iceland is
+Island is
+³ÍÄ¡óÐ is
+ไอซ์แลนด์ is
+İzlanda is
+Ісландія is
+Izlande is
+冰岛 is
+冰島 is
+Icelandi is
+Italy it
+Italië it
+ايطاليا it
+İtalyia it
+Італія it
+Италия it
+Italia it
+Italija it
+Itàlia it
+Itálie it
+Italien it
+Italien it
+Ιταλία it
+Italio it
+Italia it
+Itaalia it
+Italia it
+ایتالیا it
+Italia it
+Italia it
+Italie it
+Italia it
+איטליה it
+Italija it
+Olaszország it
+Italia it
+Ã\8dtalÃa it
+Italia it
+イタリア it
+이탈리아 it
+ອີຕາລີ it
+Italija it
+Itālija it
+Italja it
+Italia it
+Italië it
+Italia it
+Italia it
+Włochy it
+Itália it
+Itália it
+Italia it
+Италия it
+Taliansko it
+Italija it
+Italija it
+I-Italy it
+Italien it
+ò¾¡Ä¢ it
+อิตาลี it
+İtalya it
+Італія it
+Itåleye it
+Ithali it
+意大利 it
+義大利 it
+Jamaica jm
+Jamaika jm
+جامايكا jm
+Yamayka jm
+Ямайка jm
+Ямайка jm
+Jamaika jm
+Jamajka jm
+Jamajka jm
+Jamaika jm
+Τζαμάικα jm
+Ĵamaiko jm
+Jamaika jm
+Jamaika jm
+جاماییکا jm
+Jamaika jm
+Jamaïque jm
+Xamaica jm
+ג'מייקה jm
+Jamajka jm
+Jamaika jm
+Jamaika jm
+Giamaica jm
+ジャマイカ jm
+자메이카 jm
+ຈາໄມກາ jm
+Jamaika jm
+Jamaika jm
+Ġamajka jm
+Jamajka jm
+Ямайка jm
+Jamajka jm
+Jamajka jm
+Jamajka jm
+I-Jamaica jm
+\83º¦Áö측 jm
+จาไมกา jm
+Jamaika jm
+Ямайка jm
+Djamayike jm
+牙买加 jm
+牙買加 jm
+Jordan jo
+Jordaan jo
+الأردن jo
+İordaniya jo
+Ярданія jo
+Йордания jo
+Jordania jo
+Jordán jo
+Jordanien jo
+Ιορδανία jo
+Jordanio jo
+Jordania jo
+اردن jo
+Jordania jo
+Jordanie jo
+ירדן jo
+Jordánia jo
+JórdanÃa jo
+Giordania jo
+ヨルダン jo
+요르단 jo
+ຈໍແດນ jo
+Jordanija jo
+Jordāna jo
+Ġordan jo
+Jordanië jo
+Jordania jo
+Jordânia jo
+Jordânia jo
+Iordania jo
+Иордания jo
+Jordánsko jo
+Jordanija jo
+I-Jordan jo
+Jordanien jo
+§Â¡÷¾¡ý jo
+จอร์แดน jo
+Ürdün jo
+Йорданія jo
+Djordaneye jo
+约旦 jo
+約旦 jo
+Ijolidani jo
+Japan jp
+اليابان jp
+Yaponiya jp
+Японія jp
+Япония jp
+Japó jp
+Japonsko jp
+Ιαπωνία jp
+Japanio jp
+Japón jp
+Jaapan jp
+Japonia jp
+ژاپن jp
+Japani jp
+Japon jp
+Xapón jp
+יפן jp
+Japán jp
+Jepang jp
+Giappone jp
+日本 jp
+일본 jp
+ຍີ່ປຸ່ນ jp
+Japonija jp
+Japāna jp
+Ġappun jp
+Japon jp
+Japonia jp
+Japão jp
+Japão jp
+Japonia jp
+Япония jp
+Japonsko jp
+Japonska jp
+I-Japan jp
+ºôÀ¡ý jp
+ญี่ปุ่น jp
+Japonya jp
+Японія jp
+Nhật bản jp
+Djapon jp
+日本 jp
+日本 jp
+Kenya ke
+Кенія ke
+Кения ke
+Kenija ke
+Kenia ke
+ເວນດາ ke
+Quênia ke
+Keňa ke
+Kenija ke
+Кенія ke
+肯尼亚 ke
+Kyrgyzstan kg
+Кыргызстан kg
+Киргистан kg
+Kirgistan kg
+Kirgizistan kg
+Kyrgyzstán kg
+Kirgizisztán kg
+ຄສິຕັລ kg
+Kirgizstan kg
+Kirgizistan kg
+Киргизстан kg
+吉尔吉斯坦 kg
+Cambodia kh
+Камбоджа kh
+Камбоджа kh
+Kambođa kh
+Kambodzsa kh
+ໂຄລຳເບີຍ kh
+Cambodja kh
+Kambodža kh
+Kambodža kh
+Kambodja kh
+Камбоджа kh
+柬埔寨 kh
+Kiribati ki
+Кiрыбацi ki
+Кирибати ki
+ແຟຄທັລ - K ki
+Кірібаті ki
+基里巴斯 ki
+Comoros km
+Каморы km
+Коморски km
+Komori km
+Comorerne km
+ສີ km
+Komori km
+Komorerna km
+Комори km
+科摩罗群岛 km
+St. Kitts and Nevis kn
+St. Kitts en Nevis kn
+سانت كيتس و نيفيس kn
+St. Kitts və Nevis kn
+Св. Кристоф и Невис kn
+S. Kitts ha Nevis kn
+St. Kitts i Nevis kn
+Sv. Kitts a Nevis kn
+St. Kitts-Nevis kn
+St. Kitts und Nevis kn
+St. Kitts και Nevis kn
+St. Kitts kaj Nevis kn
+St. Kitts y Nevis kn
+St. Kitts ja Nevis kn
+St. Kitts eta Nevis kn
+سن کیتس و نویس kn
+St. Kitts ja Nevis kn
+St Kitts et Nevis kn
+Saint Kitts e Nevis kn
+סנט קיטס ונביס kn
+St. Kitts és Nevis kn
+St. Kitts dan Nevis kn
+Ss. Kitts e Nevis kn
+セントキッツネヴィス kn
+세인트 키츠 네비스 kn
+Šv. Kitts ir Nevis kn
+St. Kitts un Nevis kn
+St. Kitts u Nevis kn
+St. Kitts og Nevis kn
+St. Kitts en Nevis kn
+St. Kitts og Nevis kn
+St. Kitts le Nevis kn
+St. Kitts e Nevis kn
+St. Kitts e Nevis kn
+St Kitts e Nevis kn
+Sf. Kitts şi Nevis kn
+о. Св. Кристофа и Невиса kn
+St. Kitts a Nevis kn
+St. Kitts in Nevis kn
+St. Kitts i Nevis kn
+I-St. Kitts and Nevis kn
+St. Kitts och Nevis kn
+¦ºÂ¢ý𠸢ðÍ & ¦¿Å¢Í kn
+St. Kitts ve Nevis kn
+Федерація Сент-Кітс і Невіс kn
+St. Kitts na Nevis kn
+St. Kitts neNevis kn
+圣基特和里维斯 kn
+聖克理斯多福及尼維斯 kn
+St. Kitts kanye no-Nevis kn
+North Korea kp
+Noord Korea kp
+كوريا الشمالية kp
+Şimali Koreya kp
+Паўночная Карэя kp
+Северна Корея kp
+Norzh-Korea kp
+Sjeverna Koreja kp
+Corea del Nord kp
+Severní Korea kp
+Nordkorea kp
+Nord-Korea kp
+Βόρεια Κορέα kp
+Nordkoreo kp
+Corea del Norte kp
+Põhja-Korea kp
+Ipar Korea kp
+کره شمالی kp
+Pohjois-Korea kp
+Norðurkorea kp
+Corée du nord kp
+Corea do Norte kp
+צפון קוריאה kp
+Sjeverna Koreja kp
+Észak-Korea kp
+Korea Utara kp
+Kórea - Norðurkórea kp
+Corea del Nord kp
+北朝鮮 kp
+조선민주주의 인민공화국 kp
+ເກົາລີເຫນືອ kp
+Šiaurės Korėja kp
+ZiemeļKoreja kp
+Korea ta' Fuq kp
+Nord-Korea kp
+Noord-Korea kp
+Nord-Korea kp
+Lebowa la Korea kp
+Corea dèu Nord kp
+Korea Północna kp
+Coreia do Norte kp
+Coréia do Norte kp
+Coreea de Nord kp
+Северная Корея kp
+severná Kórea kp
+Severna Koreja kp
+Severna Koreja kp
+I-North Korea kp
+Nordkorea kp
+ż ¦¸¡Ã¢Â¡ kp
+เกาหลีเหนือ kp
+Kuzey Kore kp
+Північна Корея kp
+Devhula ha Korea kp
+Bắc Triều Tiên kp
+Bijhe Coreye kp
+Umntla Korea kp
+朝鲜 kp
+北韓 kp
+Enyakatho ne-Korea kp
+South Korea kr
+Suid Korea kr
+كوريا الجنوبية kr
+Cənubi Koreya kr
+Паўднёвая Карэя kr
+Южна Корея kr
+Su-Korea kr
+Južna Koreja kr
+Corea del Sud kr
+Jižní Korea kr
+Sydkorea kr
+Süd-Korea kr
+Νότια Κορέα kr
+Sudkoreo kr
+Corea del Sur kr
+Lõuna-Korea kr
+Hego Korea kr
+کره جنوبی kr
+Etelä-Korea kr
+Suðurkorea kr
+Corée du sud kr
+Corea do Sur kr
+דרום קוריאה kr
+Južna Koreja kr
+Dél-Korea kr
+Korea Selatan kr
+Kórea - Suðurkórea kr
+Corea del Sud kr
+韓国 kr
+대한민국 kr
+ເກົາລີໃຕ້ kr
+Pietų Korėja kr
+DievidKoreja kr
+Korea t'Isfel kr
+Sør-Korea kr
+Zuid-Korea kr
+Sør-Korea kr
+Borwa bja Korea kr
+Corea dèu Sud kr
+Korea Południowa kr
+Coreia do Sul kr
+Coréia do Sul kr
+Coreea de Sud kr
+Южная Корея kr
+Južná Kórea kr
+Južna Koreja kr
+Južna Koreja kr
+I-South Korea kr
+Sydkorea kr
+¦¾ý ¦¸¡Ã¢Â¡ kr
+เกาหลีใต้ kr
+Güney Kore kr
+Південна Корея kr
+Korea tshipembe kr
+Hàn Quốc kr
+Nonne Coreye kr
+Umzantsi Korea kr
+韩国 kr
+南韓 kr
+Emzansi Korea kr
+Kuwait kw
+Kuwaït kw
+الكويت kw
+Кувэйт kw
+Кувейт kw
+Kuvajt kw
+Kuvajt kw
+Κουβέιτ kw
+Kuveit kw
+کویت kw
+Kuvait kw
+Kowait kw
+כווית kw
+Kuvajt kw
+Kuvait kw
+クェート kw
+쿠웨이트 kw
+ແຕ້ມຮູບ- K kw
+Kuveitas kw
+Koeweit kw
+Koweit kw
+Kuveit kw
+Кувейт kw
+Kuvajt kw
+Kuvajt kw
+I-Kuwait kw
+̨Åò kw
+KКувейт kw
+科威特 kw
+科威特 kw
+Cayman Islands ky
+Кайманови Острови ky
+Kajmanska ostrva ky
+Cayman-øerne ky
+Islas Caimán ky
+Kaiman Irlak ky
+Kajmán-szigetek ky
+ຄາຕາລັນ ky
+Ilhas Cayman ky
+Kajmanske Ostrovy ky
+Kajmanski otoki ky
+Caymanöarna ky
+Кайманські острови ky
+开曼群岛 ky
+Kazakhstan kz
+Казахстан kz
+Казахстан kz
+Kazahstan kz
+Kazakhstán kz
+Kazahsztán kz
+ແກແລກຕິກ - K kz
+Kazaquistão kz
+Kazachstan kz
+Kazahstan kz
+Kazakstan kz
+Казахстан kz
+哈萨克斯坦 kz
+Laos la
+Лаос la
+Лаос la
+Laosz la
+ລາວ la
+老挝 la
+Lebanon lb
+Libanon lb
+لبنان lb
+Ліван lb
+Ливан lb
+Liban lb
+Libanon lb
+Libanon lb
+Libanon lb
+Λίβανος lb
+Lebanono lb
+Líbano lb
+Liibanon lb
+لبنان lb
+Libanon lb
+Libanon lb
+Liban lb
+לבנון lb
+Libanon lb
+Libanon lb
+Libano lb
+レバノン lb
+레바논 lb
+ເດນ່ງນ lb
+Libanas lb
+Libanu lb
+Libanon lb
+Libanon lb
+Libanon lb
+Liban lb
+Líbano lb
+Líbano lb
+Liban lb
+Ливан lb
+Libanon lb
+Libanon lb
+I-Lebanon lb
+Libanon lb
+¦ÄÀÉ¡ý lb
+Ліван lb
+Liban lb
+黎巴嫩 lb
+黎巴嫩 lb
+St. Lucia lc
+سانت لوسيا lc
+Св. Люсиа lc
+S. Lucia lc
+Svatá Lucie lc
+Σάντα Λουτσία lc
+St. Lucio lc
+Santa Lucía lc
+سن لوسیا lc
+Sankta Lusia lc
+Sainte Lucie lc
+Santa Lucía lc
+סנטה לוסיה lc
+Santa Lucia lc
+セントルキア lc
+세인트 루시아 lc
+ເຊັນລູເຊີຍ lc
+Šv Liucija lc
+Sv. Lūcija lc
+St. Luċija lc
+Santa Lúcia lc
+Santa Lúcia lc
+Sf. Lucia lc
+о. Св. Люсии lc
+Sv. Júlia lc
+Sv. Lucija lc
+I-St. Lucia lc
+¦ºýð æº¢Â¡ lc
+เซนต์ลูเซีย lc
+Санта Лучія lc
+圣路西亚 lc
+聖露西亞 lc
+Liechtenstein li
+Ліхтэнштэйн li
+Лихтенщайн li
+Lihtenštajn li
+Liechtestein li
+ຟ້າແມບ li
+列支敦士登 li
+Sri Lanka lk
+Шры-Ланка lk
+Шри Ланка lk
+Šri Lanka lk
+ເຊີເບີຍ lk
+Šri Lanka lk
+斯里兰卡 lk
+Liberia lr
+Лібэрыя lr
+Либеря lr
+Liberija lr
+Libéria lr
+ລິຊາ lr
+Libéria lr
+Lýbia lr
+Liberija lr
+利比里亚 lr
+Lesotho ls
+Лесота ls
+Лесото ls
+Lesoto ls
+Lesoto ls
+ທົດສອບ ls
+Lesoto ls
+莱索托 ls
+Lithuania lt
+Lithuanië lt
+ليتوانيا lt
+Litvaniya lt
+Літва lt
+Литва lt
+Litvanija lt
+Lituània lt
+Litva lt
+Litauen lt
+Litauen lt
+Λιθουανία lt
+Litovio lt
+Lituania lt
+Leedu lt
+Lituania lt
+لیتوانی lt
+Liettua lt
+Lituanie lt
+ליטא lt
+Litva lt
+Litvánia lt
+Litháenska lt
+Lituania lt
+リトアニア lt
+리 투아니아 lt
+ລິທົ່ວເນີຍ lt
+Lietuva lt
+Lietuva lt
+Litwanja lt
+Litauen lt
+Litouwen lt
+Litauen lt
+Litwa lt
+Lituânia lt
+Lituânia lt
+Lituania lt
+Литва lt
+Litva lt
+Litva lt
+Litvanija lt
+I-Lithuania lt
+Litauen lt
+Ä¢òЧÅɢ¡ lt
+ลิธัวเนีย lt
+Litvanya lt
+Литва lt
+立陶宛 lt
+立陶宛 lt
+Luxembourg lu
+Luxenburg lu
+لوكسمبورغ lu
+Lüksemburq lu
+Люксэмбург lu
+Люксембург lu
+Luksemburg lu
+Luxemburg lu
+Lucembursko lu
+Luxemburg lu
+Λουξεμβούργο lu
+Luksemburgo lu
+Luxemburgo lu
+Luksemburg lu
+Luxemburg lu
+لوگزامبورگ lu
+Luxemburg lu
+Luksemborg lu
+לוקסמבורג lu
+Luksemburg lu
+Luxemburg lu
+Lúxemborg lu
+Lussemburgo lu
+ルクセンブルグ lu
+룩셈부르크 lu
+ລັກແຊມເບີກ lu
+Liuksemburgas lu
+Luksemburga lu
+Lussemburgu lu
+Luxemburg lu
+Luksemburg lu
+Luxemburgo lu
+Luxemburgo lu
+Luxemburg lu
+Люксембург lu
+Luxemburg lu
+Luksemburg lu
+Luksemburg lu
+I-Luxembourg lu
+Luxemburg lu
+Äìºõ§À¡÷ì lu
+ลักเซมเบอร์ก lu
+Lüksemburg lu
+Люксембург lu
+Lucsimbork lu
+卢森堡 lu
+盧森堡 lu
+Latvia lv
+لاتفيا lv
+Latviya lv
+Латвія lv
+Латвия lv
+Latvija lv
+Lotyšsko lv
+Letland lv
+Lettland lv
+Λιθουανία lv
+Latvio lv
+Letonia lv
+Läti lv
+لاتویا lv
+Lettonie lv
+לטביה lv
+Latvija lv
+Lettország lv
+Léttland lv
+Lettonia lv
+ラトビア lv
+라트비아 lv
+ລັດເວີຍ lv
+Latvija lv
+Latvija lv
+Latvja lv
+Letland lv
+Łotwa lv
+Letónia lv
+Латвия lv
+Lotyšsko lv
+Latvija lv
+Latvija lv
+I-Latvia lv
+Lettland lv
+ÄðŢ¡ lv
+ลัธเวีย lv
+Litvanya lv
+Латвія lv
+Lativia lv
+拉脱维亚 lv
+拉脫維亞 lv
+Libya ly
+Libië ly
+ليبيا ly
+Лівія ly
+Либия ly
+Libija ly
+Líbia ly
+Lýbie ly
+Libyen ly
+Libyen ly
+Λιβύη ly
+Libia ly
+Liibüa ly
+Libia ly
+لیبی ly
+Lybie ly
+לוב ly
+Líbia ly
+Libia ly
+リビア ly
+ລິຊາ ly
+Libija ly
+Libië ly
+Libia ly
+Líbia ly
+Líbia ly
+Ливия ly
+Lýbia ly
+Libija ly
+I-Libya ly
+Libyen ly
+Ä¢À¢Â¡ ly
+Лівія ly
+利比亚 ly
+利比亞 ly
+Morocco ma
+Morokko ma
+المغرب ma
+Марока ma
+Мароко ma
+Maroko ma
+Marroc ma
+Maroko ma
+Marokko ma
+Marokko ma
+Μαρόκο ma
+Moroko ma
+Marruecos ma
+Maroko ma
+Maroko ma
+مراکش ma
+Marokko ma
+Marokko ma
+Maroc ma
+מרוקו ma
+Maroko ma
+Marokkó ma
+Marocco ma
+モロッコ ma
+모로코 ma
+ເມົາລິ ma
+Marokas ma
+Marokk ma
+Marokko ma
+Marokko ma
+Marokko ma
+Maroko ma
+Marrocos ma
+Marrocos ma
+Maroc ma
+Марокко ma
+Maroko ma
+Maroko ma
+I-Morocco ma
+Marocko ma
+§Á¡Ã¡§¸¡ ma
+Марокко ma
+Marok ma
+摩洛哥 ma
+摩洛哥 ma
+Monaco mc
+Манака mc
+Монако mc
+Monako mc
+Mónaco mc
+ເມົາລິ mc
+Mônaco mc
+Monako mc
+Monako mc
+摩纳哥 mc
+Moldova md
+Малдова md
+Молдова md
+Moldavia md
+Moldavia md
+ສະໂລວັກ md
+Moldávsko md
+Moldavien md
+摩尔多瓦 md
+Madagascar mg
+Мадагаскар mg
+Мадагаскар mg
+Madagaskar mg
+Madagaszkár mg
+ຄາສະບາລ - K mg
+Madagaskar mg
+Madagaskar mg
+Madagaskar mg
+马达加斯加 mg
+Marshall Islands mh
+Маршаллавы астравы mh
+Маршалови Острови mh
+Maršalova ostrva mh
+Marshall-øerne mh
+Islas Marshall mh
+Marshall Irlak mh
+Marshall-szigetek mh
+ລາດສະອານາຈັກໄທຍ mh
+Ilhas Marshall mh
+Maršálove ostrovy mh
+Marshallovi otoki mh
+Marshallöarna mh
+马绍尔群岛 mh
+Macedonia mk
+Makedoniese mk
+مقدونيا mk
+Makedonya mk
+Македонія mk
+Македония mk
+Makedonia mk
+Makedonija mk
+Macedònia mk
+Makedonie mk
+Makedonien mk
+Makedonien mk
+Μακεδονία mk
+Macedonio mk
+Makedoonia mk
+Mazedonia mk
+مقدونیه mk
+Makedonia mk
+Macédoine mk
+מקדוניה mk
+Makedonija mk
+Macedónia mk
+Masedonia mk
+MakedónÃa mk
+マケドニア語 mk
+마케도니아 mk
+ມາເຊໂດເນີຍ mk
+Makedonija mk
+Maķedonija mk
+Maċedonja mk
+Makedonia mk
+Macedonië mk
+Makedonia mk
+Macedònian mk
+Macedónia mk
+Macedônia mk
+Македония mk
+Macedónsky mk
+Makedonija mk
+Makedonija mk
+I-Macedonia mk
+Makedonien mk
+Á¡º¢§¼¡É¢Â¡ mk
+มาเซโดเนีย mk
+Makedonya mk
+Македонія mk
+Masedonia mk
+马其顿 mk
+馬其頓 mk
+Mali ml
+Малі ml
+Мали ml
+ຈົດຫມາຍ ml
+马里 ml
+Myanmar mm
+М'янма mm
+Майнмар mm
+Mjanmar mm
+Burma mm
+Birmania mm
+ຕົວຮງກພີື້ນທີ່ທຳງານ - K mm
+Mjanmar mm
+缅甸 mm
+Mongolia mn
+Манголія mn
+Монголия mn
+Mongolija mn
+Mongoliet mn
+Mongólia mn
+ລອກອິນ mn
+Mongólia mn
+Mongolsko mn
+Mongolija mn
+Mongoliet mn
+蒙古 mn
+Macau mo
+Макао mo
+Makau mo
+Macao mo
+Makaó mo
+ມອລຕາ mo
+Makao mo
+Macao mo
+澳门 mo
+Martinique mq
+Мартиника mq
+Martinik mq
+Martinica mq
+ເມົາລິ mq
+Martinik mq
+马提尼克岛 mq
+Mauritania mr
+Маўрытанія mr
+Мавритания mr
+Mauritanija mr
+Mauretanien mr
+Mauritánia mr
+ລິທົວເນີຍ mr
+Mauritânia mr
+Mavretanija mr
+Mauretanien mr
+毛里塔尼亚 mr
+Montserrat ms
+Монсерат ms
+Monsera ms
+ຈໍພາບ ms
+蒙特塞拉特岛 ms
+Malta mt
+مالطة mt
+Мальта mt
+Малта mt
+Μάλτα mt
+Malto mt
+مالت mt
+Malte mt
+מלטה mt
+Málta mt
+マルタ mt
+왈타 mt
+ມອລຕາ mt
+Мальта mt
+I-Malta mt
+Á¡ø¼¡ mt
+มอลตา mt
+Мальта mt
+Male mt
+马耳他 mt
+馬爾他 mt
+Mauritius mu
+Маўрыцы mu
+Маурици mu
+Mauricijus mu
+Mauricio mu
+ພາທິຊັ້ນ mu
+Maurícius mu
+Mavricij mu
+毛里求斯 mu
+Maldives mv
+Мальдывы mv
+Малдиви mv
+Maldivi mv
+Maldiverne mv
+Maldivas mv
+Maldív-szigetek mv
+ມັລດິສ mv
+Maldivas mv
+Maldiv mv
+Maldiverna mv
+马尔代夫 mv
+Malawi mw
+Малаві mw
+Малави mw
+Malavi mw
+ມອລຕາ mw
+马拉维 mw
+Mexico mx
+Meksiko mx
+المكسيك mx
+Meksika mx
+Мэксыка mx
+Мексико mx
+Mec'hiko mx
+Meksiko mx
+Mèxic mx
+Mexiko mx
+Mexiko mx
+Μεξικό mx
+Meksikujo mx
+México mx
+Mehhiko mx
+Mexiko mx
+مکزیک mx
+Meksiko mx
+Meksiko mx
+Mexique mx
+México mx
+מקסיקו mx
+Meksiko mx
+Mexikó mx
+Meksiko mx
+MexÃkó mx
+Messico mx
+メキシコ mx
+멕시코 mx
+ເມັກຊີໂກ mx
+Meksika mx
+Meksika mx
+Messiku mx
+Mèxic mx
+Meksyk mx
+México mx
+México mx
+Mexic mx
+Мексика mx
+Mexiko mx
+Mehika mx
+Meksiko mx
+I-Mexico mx
+¦Á캢§¸¡ mx
+เม็กซิโก mx
+Meksika mx
+Мексика mx
+Mê hi cô mx
+Mecsike mx
+墨西哥 mx
+墨西哥 mx
+Malaysia my
+Малайзыя my
+Малайзия my
+Malezija my
+Malasia my
+Malasia my
+Malajzia my
+ມອລຕາ my
+Malásia my
+Malajzia my
+Malezija my
+马来西亚 my
+Mozambique mz
+Мазамбік mz
+Мозамбик mz
+Mozambik mz
+Mozambik mz
+ຫນ່ວຍຄວາມຈຳ mz
+Moçambique mz
+Mozambik mz
+Mozambik mz
+Moçambique mz
+莫桑比克 mz
+Namibia na
+Намібія na
+Намибия na
+Namibija na
+Namíbia na
+ຈາໄມກາ na
+Namíbia na
+Namíbia na
+Namibija na
+纳米比亚 na
+New Caledonia nc
+Нова Каледония nc
+Nova Kaledonija nc
+Ny Caledonien nc
+Nueva Caledonia nc
+Kaledonia Berria nc
+Új-Kaledónia nc
+ມາເຊໂດເນີຍ nc
+Nova Caledônia nc
+Nová Kaledónia nc
+Nova Kaledonija nc
+Nya Caledonien nc
+新喀里多尼亚 nc
+Niger ne
+Нігер ne
+Нигер ne
+ຕົວຮງກພື້ນທີ່ທຳງານ ne
+Nigéria ne
+Nigéria ne
+尼日尔 ne
+Norfolk Island nf
+Остров Норфолк nf
+Norfolk ostrvo nf
+Norfolk-øerne (Australien) nf
+Isla Norfolk nf
+Norfok Irla nf
+Norfolk-szigetek nf
+ໂປແລນ nf
+Ilhas Norfolk nf
+Ostrov Norfolk nf
+Otok Norfolk nf
+Norfolkön nf
+诺福克岛 nf
+Nigeria ng
+Нігерыя ng
+Нигерия ng
+Nigerija ng
+Nigéria ng
+ບັນແກເລີຍ ng
+Nigéria ng
+Nigéria ng
+Nigerija ng
+尼日利亚 ng
+Nicaragua ni
+Nikaragua ni
+نيكاراغوا ni
+Нікарагуа ni
+Никарагуа ni
+Nikaragva ni
+Nikaragua ni
+Νικαράγουα ni
+Nikaraagua ni
+نیکاراگویه ni
+Nikaragua ni
+Nikaragua ni
+ניקרגווה ni
+ニカラグア ni
+니카라과 ni
+ປາລາກກວຍ ni
+Nikaragua ni
+Nikaragwa ni
+Nikaragua ni
+Nicarágua ni
+Nicarágua ni
+Никарагуа ni
+Nikaragua ni
+Nikaragva ni
+I-Nicaragua ni
+¿¢¸Ã¡Ì§Å ni
+Nikaragua ni
+Нікарагуа ni
+尼加拉瓜 ni
+尼加拉瓜 ni
+Netherlands nl
+Nederland nl
+هولندا nl
+Hollandiya nl
+Галяндыя nl
+Холандия nl
+Izelvroioù nl
+Nizozemska nl
+Holanda nl
+Nizozemí nl
+Holland nl
+Niederlande nl
+Κάτω Χώρες nl
+Nederlando nl
+Países Bajos nl
+Holland nl
+Holanda nl
+هلند nl
+Alankomaat nl
+Háland nl
+Pays bas nl
+Países Baixos nl
+הולנד nl
+Nizozemska nl
+Hollandia nl
+Belanda nl
+Holland nl
+Paesi Bassi nl
+オランダ nl
+네덜란드 nl
+ເນເທີແລນ์ nl
+Olandija nl
+Nīderlande nl
+Nederland nl
+Nederland nl
+Nederland nl
+Holanda nl
+Holandia nl
+Países Baixos nl
+Holanda nl
+Olanda nl
+Нидерланды nl
+Holandsko nl
+Nizozemska nl
+Holandija nl
+I-Netherlands nl
+Nederländerna nl
+¦¿¾÷Ä¡óÐ nl
+เนเธอร์แลนด์ nl
+Hollanda nl
+Голландія nl
+Hà Lan nl
+荷兰 nl
+荷蘭 nl
+Norway no
+Noorweë no
+النرويج no
+Norveç no
+Нарвэгія no
+Норвегия no
+Norvegia no
+Norveška no
+Noruega no
+Norsko no
+Norge no
+Norwegen no
+Νορβηγία no
+Norvegio no
+Noruega no
+Norra no
+Norvegia no
+نروژ no
+Norja no
+Norra no
+Norvège no
+Noruega no
+נורבגיה no
+Norveška no
+Norvégia no
+Norwegia no
+Noregur no
+Norvegia no
+ノルウェー no
+노르웨이 no
+ນໍເວ no
+Norvegija no
+Norvēģija no
+Norveġja no
+Norge no
+Noorwegen no
+Noreg no
+Noruega no
+Norwegia no
+Noruega no
+Noruega no
+Norvegia no
+Норвегия no
+Nórsko no
+Norveška no
+Norveška no
+I-Norway no
+Norge no
+¿¡÷§Å no
+นอร์เวย์ no
+Norveç no
+Норвегія no
+Na uy no
+挪威 no
+挪威 no
+Nepal np
+Нэпал np
+Непал np
+Nepál np
+ເວນດາ np
+尼泊尔 np
+Nauru nr
+Науру nr
+Науру nr
+Naurú nr
+ປາລາກກວຍ nr
+瑙鲁 nr
+Niue nu
+Ниуе nu
+ເນ໊ຕ nu
+纽埃岛 nu
+New Zealand nz
+Nuwe Seeland nz
+نيوزيلاندا nz
+Yeni Zellandiya nz
+Новая Зэляндыя nz
+Нова Зеландия nz
+Zeland nevez nz
+Novi Zeland nz
+Nova Zelanda nz
+Nový Zéland nz
+Neuseeland nz
+Νέα Ζηλανδία nz
+Novzelando nz
+Nueva Zelanda nz
+Uus-Meremaa nz
+Zelanda Berria nz
+زلاندنو nz
+Uusi-Seelanti nz
+Nýsæland nz
+Nouvelle Zélande nz
+Nova Celandia nz
+ניו זילנד nz
+Novi Zeland nz
+Új-Zéland nz
+Selandia Baru nz
+Nýja Sjáland nz
+Nuova Zelanda nz
+ニュージーランド nz
+뉴질랜드 nz
+ນີວຊີແລນ nz
+Naujoji Zelandija nz
+JaunZēlande nz
+Nieuw Zeeland nz
+Navera Zelanda nz
+Nowa Zelandia nz
+Nova Zelândia nz
+Nova Zelândia nz
+Noua Zeelandă nz
+Новая Зеландия nz
+Nový Zéland nz
+Nova Zelandija nz
+Novi Zeland nz
+I-New Zealand nz
+Nya Zeeland nz
+¿¢äº¢Ä¡óÐ nz
+นิวซีแลนด์ nz
+Yeni Zelanda nz
+Нова Зеландія nz
+Nouve Zelande nz
+新西兰 nz
+紐西蘭 nz
+Oman om
+عُمان om
+Аман om
+Оман om
+Omán om
+Ομάν om
+Omano om
+Omán om
+Omaan om
+عمان om
+עומן om
+Omán om
+オマーン om
+오만 om
+ເຍີຍລະມັນ om
+Omanas om
+Omã om
+Оман om
+Omán om
+I-Oman om
+µÁý om
+Umman om
+Оман om
+ Oman om
+阿曼 om
+阿曼 om
+Panama pa
+بنما pa
+Панама pa
+Панама pa
+Panamà pa
+Παναμάς pa
+Panamo pa
+Panamá pa
+پاناما pa
+Panamá pa
+פנמה pa
+パナマ pa
+파나마 pa
+ປານາມາ pa
+Panamá pa
+Panamá pa
+Панама pa
+I-Panama pa
+ÀÉ¡Á¡ pa
+ปานามา pa
+Панама pa
+巴拿马 pa
+巴拿馬 pa
+Peru pe
+البيرو pe
+Пэру pe
+Перу pe
+Perou pe
+Perú pe
+Περού pe
+Peruo pe
+Perú pe
+Peruu pe
+پرو pe
+Pérou pe
+Perú pe
+פרו pe
+Perú pe
+Perù pe
+ペルー pe
+페루 pe
+ເປລູ pe
+Perū pe
+Pero pe
+Perú pe
+Перу pe
+I-Peru pe
+¦ÀÕ pe
+เปรู pe
+Перу pe
+Perou pe
+秘鲁 pe
+秘魯 pe
+French Polynesia pf
+Француская Палінэзія pf
+Френска Полинезия pf
+Francuska Polinezija pf
+Fransk Polynesien pf
+Polinesia francesa pf
+Polinesia Frantziarra pf
+Francia-Polinézia pf
+ຝຣັ່ງເສດ pf
+Polinésia Francesa pf
+Francúzska Polynézia pf
+Francoska Polinezija pf
+Franska Polynesien pf
+法属波利尼西亚 pf
+Papua New Guinea pg
+Папуа–Новая Гвінэя pg
+Папуа и Нова Гвинея pg
+Papua Nova Gvineja pg
+Papua Nueva Guinea pg
+Papua Ginea Berria pg
+Pápua Új-Guinea pg
+ເທົາອ່ອນ pg
+Nova Guiné Papua pg
+Papua Nová Guinea pg
+Papua Nova Gvineja pg
+Papua Nya Guinea pg
+巴布亚新几内亚 pg
+Philippines ph
+Філіпіны ph
+Филипини ph
+Filipini ph
+Filippinerne ph
+Filipinas ph
+Filipinak ph
+Fülöp-szigetek ph
+ອາລະປະໂຫຍດ ph
+Filipinas ph
+Filipíny ph
+Filipini ph
+Filippinerna ph
+菲律宾 ph
+Pakistan pk
+Пакістан pk
+Пакистан pk
+Pakisztán pk
+ລງບ pk
+Paquistão pk
+巴基斯坦 pk
+Poland pl
+Poolland pl
+بولندا pl
+Polşa pl
+Польшча pl
+Полша pl
+Polonia pl
+Poljska pl
+Polònia pl
+Polsko pl
+Polen pl
+Polen pl
+Πολωνία pl
+Pollando pl
+Polonia pl
+Poola pl
+Polonia pl
+لهستان pl
+Puola pl
+Pólland pl
+Pologne pl
+Polonia pl
+פולין pl
+Poljska pl
+Lengyelország pl
+Polandia pl
+Pólland pl
+Polonia pl
+ポーランド pl
+폴란드 pl
+ໂປແລນ pl
+Lenkija pl
+Polija pl
+Polonja pl
+Polen pl
+Polen pl
+Polen pl
+Polònia pl
+Polska pl
+Polónia pl
+Polônia pl
+Polonia pl
+Польша pl
+Poľsko pl
+Poljska pl
+Poljska pl
+I-Poland pl
+Polen pl
+§À¡Ä¡óÐ pl
+โปแลนด์ pl
+Polonya pl
+Польща pl
+Pholandi pl
+Ba Lan pl
+Pologne pl
+波兰 pl
+波蘭 pl
+Saint Pierre and Miquelon pm
+Sveti Pjer i Migelon pm
+Saint Pierre og Miquelon pm
+Saint Pierre y Miquelon pm
+Saint Pierre eta Miquelon pm
+Saint Pierre és Miquelon pm
+Saint Pierre e Miquelon pm
+Saint Pierre a Miquelon pm
+Sveti Pierre in Miquelon pm
+Saint Pierre och Miquelon pm
+圣皮埃尔和密克隆岛 pm
+Pitcairn pn
+Pitkern pn
+ລງບ pn
+Puerto Rico pr
+Пуерто Рико pr
+Portoriko pr
+ໂປຣໂຕຄອນ pr
+Porto Rico pr
+Portoriko pr
+波多尼各 pr
+Palestinian Territory ps
+Palesteinse Gebied ps
+السلطة الفلسطينية ps
+Палестынская тэрыторыя ps
+Палестина ps
+Palestinska teritorija ps
+Territori Palestí ps
+Palestinské území ps
+Palæstinensiske selvstyreområder ps
+Palästinensisches Gebiet ps
+Παλαιστίνη ps
+Palestinaj teritorioj ps
+Territorio palestino ps
+Palestiina territoorium ps
+Palestina ps
+فلسطین ps
+Palestiinalaisalue ps
+Palestinensiska økið ps
+Territoire palestinien ps
+השטחים הפלסטיניים ps
+Palestinski teritorij ps
+Palesztin területek ps
+Territori palestinesi ps
+パレスチナ自治区 ps
+팔레스타인 자치구 ps
+ການພິມຜິດພາດ ps
+Palestinos teritorija ps
+Palestina ps
+Palestinske territorier ps
+Palestijns territorium ps
+Palestinske territorium ps
+Bohwa bja Palestina ps
+Palestyna ps
+Território Palestiniano ps
+Território Palestino ps
+Teritoriul Palestinian ps
+Палестинские территории ps
+Palestínske územia ps
+Palestinski teritorij ps
+I-Palestinian Territory ps
+Palestina ps
+À¡Äо£É ¬¨½Âõ ps
+Filistin Bölgesi ps
+Палестинська територія ps
+Mukano wa maphalesitina ps
+Palestene ps
+Umhlaba wePalestina ps
+巴勒斯坦地区 ps
+巴勒斯坦領地 ps
+Indawo yama-Phalesitina ps
+Portugal pt
+البرتغال pt
+Portuqaliya pt
+Партугалія pt
+Португалия pt
+Portugalsko pt
+Πορτογαλία pt
+Portugalo pt
+پرتغال pt
+Portugali pt
+פורטוגל pt
+Portugália pt
+Portúgal pt
+Portogallo pt
+ポルトガル pt
+포르투갈 pt
+ໂປຣຕຸເກສ pt
+Portugalija pt
+Portugāle pt
+Portugall pt
+Portugalia pt
+Portugalia pt
+Португалия pt
+Portugalsko pt
+Portugalska pt
+I-Portugal pt
+§À¡÷òиø pt
+โปรตุเกส pt
+Portekiz pt
+Португалія pt
+BềEĐào Nha pt
+葡萄牙 pt
+葡萄牙 pt
+Palau pw
+Палау pw
+Палау pw
+ມອລຕາ pw
+帕劳群岛 pw
+Paraguay py
+Paraguaai py
+باراغواي py
+Paraqvay py
+Парагвай py
+Парагвай py
+Paragvaj py
+Paraguai py
+Παραγουάη py
+Paragvajo py
+Paraguai py
+پاراگویه py
+Paraguai py
+פרגואי py
+Paragvaj py
+パラグアイ py
+파라과이 py
+ປາລາກກວຍ py
+Paragvajus py
+Paragvaja py
+Paragwaj py
+Paraguai py
+Paragwaj py
+Paraguai py
+Paraguai py
+Paraguai py
+Парагвай py
+Portugalsko py
+Paragvaj py
+Paragvaj py
+I-Paraguay py
+Àá̧Špy
+ปารากวัย py
+Парагвай py
+Paragway py
+巴拉圭 py
+巴拉圭 py
+Qatar qa
+قطر qa
+Катар qa
+Катар qa
+Katar qa
+Katar qa
+Katar qa
+Κατάρ qa
+Kataro qa
+Katar qa
+قطر qa
+Katar qa
+קטר qa
+Katar qa
+Katar qa
+カタール qa
+카타르 qa
+ມອລຕາ qa
+Katar qa
+Катар qa
+Katar qa
+Katar qa
+I-Qatar qa
+¸¾¡÷ qa
+Katar qa
+Катар qa
+卡塔尔 qa
+卡達 qa
+Romania ro
+Romenië ro
+رومانيا ro
+Rumıniya ro
+Румынія ro
+Румъния ro
+Roumania ro
+Rumunija ro
+Rumunsko ro
+Rumænien ro
+Rumänien ro
+Ρουμανία ro
+Rumanio ro
+Rumanía ro
+Rumeenia ro
+Errumania ro
+رومانی ro
+Rumenia ro
+Roumanie ro
+Romanía ro
+רומניה ro
+Rumunjska ro
+Románia ro
+Rumania ro
+RúmenÃa ro
+ルーマニア ro
+루마니아 ro
+ໂລມາເນີຍ ro
+Rumunija ro
+Rumānija ro
+Rumanija ro
+Roemenië ro
+Rumunia ro
+Roménia ro
+Romênia ro
+Румыния ro
+Rumunsko ro
+Romunija ro
+Rumunija ro
+I-Romania ro
+Rumänien ro
+Õ§Áɢ¡ ro
+โรมาเนีย ro
+Romanya ro
+Румунія ro
+Ru ma ni ro
+Roumaneye ro
+罗马尼亚 ro
+羅馬尼亞 ro
+Russia ru
+Rusland ru
+روسيا ru
+Rusiya ru
+Расея ru
+Русия ru
+Rusia ru
+Rusija ru
+Rússia ru
+Rusko ru
+Rusland ru
+Russland ru
+Ρωσία ru
+Ruslando ru
+Rusia ru
+Venemaa ru
+Errusia ru
+روسیه ru
+Venäjä ru
+Russland ru
+Russie ru
+Rusia ru
+רוסיה ru
+Rusija ru
+Oroszország ru
+Rusia ru
+Rússland ru
+ロシア ru
+러시아 ru
+ລັດເຊີຍ ru
+Rusija ru
+Krievija ru
+Russja ru
+Russland ru
+Rusland ru
+Russland ru
+Rosja ru
+Rússia ru
+Rússia ru
+Rusia ru
+Россия ru
+Rusko ru
+Rusija ru
+Rusija ru
+I-Russia ru
+Ryssland ru
+ú¢Â¡ ru
+รัสเซีย ru
+Rusya ru
+Росія ru
+Rashia ru
+Nga ru
+Russeye ru
+Rashiya ru
+俄罗斯 ru
+俄羅斯 ru
+Rwanda rw
+Руанда rw
+Руанда rw
+Ruanda rw
+Ruanda rw
+Ruanda rw
+ແພນດ້າ rw
+Ruanda rw
+Ruanda rw
+卢旺达 rw
+Saudi Arabia sa
+Saudi Arabië sa
+السعودية sa
+Саудаўская Арабія sa
+Саудитска Арабия sa
+Saudijska Arabija sa
+Aràbia Saudí sa
+Saúdská Arábie sa
+Saudi Arabien sa
+Saudi-Arabien sa
+Σαουδική Αραβία sa
+Saŭdi-Arabio sa
+Arabia Saudí sa
+Saudi Araabia sa
+عربستان سعودی sa
+Saudi-Arabia sa
+Arabie Saoudite sa
+ערב הסעודית sa
+Saudijska Arabija sa
+Szaúd-Arábia sa
+Arabia saudita sa
+サウジアラビア sa
+사우디 아라비아 sa
+ອາລະບິກ sa
+Saudi Arabija sa
+Għarabja Sawdita sa
+Saudi-Arabia sa
+Saudi-Arabië sa
+Saudi-Arabia sa
+Arabia Saudyjska sa
+Arábia Saudita sa
+Arábia Saudita sa
+Arabia Saudită sa
+Саудовская Аравия sa
+Saudská arábia sa
+Saudova Arabija sa
+I-Saudi Arabia sa
+Saudiarabien sa
+º×¾¢ «§ÃÀ¢Â¡ sa
+Suudi Arabistan sa
+Саудівська Аравія sa
+沙特阿拉伯 sa
+沙烏地阿拉伯 sa
+Solomon Islands sb
+Саламонавы астравы sb
+Соломонови Острови sb
+Solomonska ostrva sb
+Salomon-øerne sb
+Islas Salomón sb
+Solomon Irlak sb
+Salamon-szigetek sb
+ສະໂລວະເນີຍ sb
+Ilhas Salomão sb
+Šalamúnove ostrovy sb
+Solomonovi otoki sb
+Salomonöarna sb
+所罗门群岛 sb
+Seychelles sc
+Сэйшэлы sc
+Сейшелски острови sc
+Sejšeli sc
+Seychellerne sc
+ເຊລ sc
+Sejšeli sc
+Seychellerna sc
+塞舌尔 sc
+Sudan sd
+السودان sd
+Судан sd
+Судан sd
+Sudán sd
+Σουδάν sd
+Sudano sd
+Sudán sd
+Sudaan sd
+سودان sd
+Sudania sd
+Soudan sd
+סודן sd
+Szudán sd
+Súdan sd
+スーダン sd
+수단 sd
+ຊູດານ sd
+Sudanas sd
+Sudāna sd
+Sudão sd
+Sudão sd
+Судан sd
+Sudán sd
+I-Sudan sd
+ݼ¡ý sd
+ซูดาน sd
+Судан sd
+Sudani sd
+Soudan sd
+苏丹 sd
+蘇丹 sd
+Sweden se
+Swede se
+السويد se
+İsveç se
+Швэцыя se
+Швеция se
+Sveden se
+Švedska se
+Suècia se
+Švédsko se
+Sverige se
+Schweden se
+Σουηδία se
+Svedio se
+Suecia se
+Rootsi se
+Suedia se
+سوید se
+Ruotsi se
+Svøriki se
+Suède se
+Suecia se
+שבדיה se
+Švedska se
+Svédország se
+Swedia se
+SvÃþjóð se
+Svezia se
+スウェーデン se
+스웨덴 se
+ສະວີເດນ se
+Švedija se
+Zviedrija se
+Svezja se
+Sverige se
+Zweden se
+Sverige se
+Suècia se
+Szwecja se
+Suécia se
+Suécia se
+Suedia se
+Швеция se
+Švédsko se
+Švedska se
+Švedska se
+I-Sweden se
+Sverige se
+ÍÅ£¼ý se
+สวีเดน se
+İsveç se
+Швеція se
+Swidene se
+Thuỵ Điển se
+瑞典 se
+瑞典 se
+Singapore sg
+Сынгапур sg
+Сингапур sg
+Singapur sg
+Singapur sg
+Szingapúr sg
+ໂຊນາ sg
+Singapura sg
+Singapur sg
+Singapur sg
+新加坡 sg
+Saint Helena sh
+Свети Елена sh
+Sveta Helena sh
+St. Helena sh
+Santa Helena sh
+Szent Heléna sh
+ຫົວເລື່ອງ sh
+Santa Helena sh
+Svätá Helena sh
+Sveta Helena sh
+圣赫勒拿岛 sh
+Slovenia si
+Slovenië si
+سلوفينيا si
+Sloveniya si
+Славенія si
+Словения si
+Slovenija si
+Eslovenia si
+Slovinsko si
+Slovenien si
+Slowenien si
+Σλοβενία si
+Slovenio si
+Eslovenia si
+Sloveenia si
+Eslovenia si
+اسلوانی si
+Slovénie si
+Eslovenia si
+סלובניה si
+Slovenija si
+Szlovénia si
+SlóvenÃa si
+スロベニア si
+슬로베니아 si
+ສະໂລວະເນີຍ si
+Slovėnija si
+Slovēnija si
+Slovenja si
+Slovenië si
+Eslovenia si
+Słowenia si
+Eslovénia si
+Eslovênia si
+Словения si
+Slovinsko si
+Slovenija si
+Slovenija si
+I-Slovenia si
+Slovenien si
+ͧġŢɢ¡ si
+สโลเวเนีย si
+Slovenya si
+Словенія si
+斯洛文尼亚 si
+斯洛維尼亞 si
+Slovakia sk
+Slovakië sk
+سلوفاكيا sk
+Slovakiya sk
+Славакія sk
+Словакия sk
+Slovačka sk
+Eslovaquia sk
+Slovensko sk
+Slovakiet sk
+Slowakien sk
+Σλοβακία sk
+Slovakujo sk
+Eslovaquia sk
+Slovakkia sk
+Eslovakia sk
+اسلواکی sk
+Slovaquie sk
+סלובקיה sk
+Slovačka sk
+Szlovákia sk
+SlóvakÃa sk
+Slovacchia sk
+スロバキア sk
+슬로바키아 sk
+ສະໂລວັກ sk
+Slovakija sk
+Slovākija sk
+Slovakja sk
+Slovakije sk
+Słowacja sk
+Eslováquia sk
+Eslováquia sk
+Slovacia sk
+Словакия sk
+Slovensko sk
+Slovaška sk
+I-Slovakia sk
+Slovakien sk
+ͧġš츢 sk
+สโลวัค sk
+Slovakya sk
+Словакія sk
+斯洛伐克 sk
+斯洛伐克 sk
+San Marino sm
+Сан-Марына sm
+Сан Марино sm
+ໂຊນາ sm
+圣马力诺 sm
+Senegal sn
+Сэнэгал sn
+Сенегал sn
+Szenegál sn
+ທົ່ວໄປ sn
+塞内加尔 sn
+Somalia so
+Somalië so
+صومال so
+Самалі so
+Сомалия so
+Somalija so
+Somàlia so
+Somálsko so
+Σομαλία so
+Somalio so
+Somaalia so
+سومالی so
+Somalie so
+סומליה so
+Somalija so
+Szomália so
+ソマリア so
+소말리아 so
+ໂລມາເນີຍ so
+Somalis so
+Somalija so
+Somalie so
+Somália so
+Somália so
+Сомали so
+Somálsko so
+Somalija so
+I-Somalia so
+§º¡Á¡Ä¢Â¡ so
+Somali so
+Сомалі so
+Somaleye so
+索马里 so
+索馬利亞 so
+Suriname sr
+Сурынам sr
+Суринам sr
+Surinam sr
+ເຊີເບີຍ sr
+Surinam sr
+Surinam sr
+Surinam sr
+Sao Tome and Principe st
+Сан Томе и Приницпе st
+Sao Tome i Principe st
+Sao Tomé og Principe st
+Sao Tome y Príncipe st
+Sao Tome eta Principe st
+Sao Tome és Principe st
+ບໍລິການ st
+São Tome e Príncipe st
+Sao Tome a Principe st
+Sao Tome in Principe st
+São Tomé och Príncipe st
+El Salvador sv
+السلفادور sv
+Сальвадор sv
+Ел Салвадор sv
+Salvador sv
+Salvador sv
+Ελ Σαλβαντόρ sv
+Elsalvadoro sv
+Salvador sv
+السالوادور sv
+Salvador sv
+O Salvador sv
+אל סלבדור sv
+Salvador sv
+エルサルバドル sv
+엘살바도르 sv
+ເອລຊັນວາດດໍ sv
+Salvadoras sv
+Salvadora sv
+Salwador sv
+Salvador sv
+Сальвадор sv
+Salvádor sv
+Salvador sv
+I-El Salvador sv
+±ø º¡øÅ§¼¡÷ sv
+เอลซัลวาดอร์ sv
+Ель-Сальвадор sv
+萨尔瓦多 sv
+薩爾瓦多 sv
+Syria sy
+Sirië sy
+سوريا sy
+Сырыя sy
+Сирия sy
+Sirija sy
+Síria sy
+Sýrie sy
+Syrien sy
+Syrien sy
+Συρία sy
+Sirio sy
+Siria sy
+Süüria sy
+Siria sy
+سوریه sy
+Syyria sy
+Syrie sy
+סוריה sy
+Sirija sy
+Szíria sy
+Siria sy
+シリア sy
+시리아 sy
+ເຊີເບີຍ sy
+Sirija sy
+Siria sy
+Syrië sy
+Síria sy
+Síria sy
+Siria sy
+Сирия sy
+Sýria sy
+Sirija sy
+I-Syria sy
+Syrien sy
+º¢Ã¢Â¡ sy
+Suriye sy
+Сирія sy
+叙利亚 sy
+敘利亞 sy
+Swaziland sz
+Свазылэнд sz
+Свазиленд sz
+Svazilend sz
+Swazilandia sz
+Swazilandia sz
+Szváziföld sz
+ລາດສະນາຈັກໄທຍ sz
+Suécia sz
+Swazijsko sz
+Svazi sz
+斯威士兰 sz
+Turks and Caicos Islands tc
+Turks i Kaikos ostrva tc
+Turks- og Caicosøerne tc
+Islas Turcos y Caicos tc
+Turks eta Caicos Irlak tc
+Turks- és Caicos-szigetek tc
+Ilhas Caicos e Turca tc
+Turks a Caicos ostrovy tc
+Otoka Turks in Caicos tc
+Turks- och Caicosöarna tc
+特克斯和凯科斯群岛 tc
+Chad td
+Чад td
+Чад td
+Čad td
+Tchad td
+Txad td
+Csád td
+ເກມໄພ່ td
+Čad td
+Čad td
+Tchad td
+乍得 td
+Togo tg
+Тога tg
+Того tg
+ຂອງເລ່ນສະນຸກ tg
+多哥 tg
+Thailand th
+تايلاند th
+Tayland th
+Тайлянд th
+Тайланд th
+Tajland th
+Tailàndia th
+Thajsko th
+Ταϊλάνδη th
+Tajlando th
+Tailandia th
+Tai th
+Thailandia th
+تایلند th
+Thaimaa th
+Tailand th
+Thaïlande th
+Tailandia th
+תאילנד th
+Tajland th
+Thaiföld th
+Tæland th
+Tailandia th
+タイ th
+태국 (타이) th
+ລາດສະນາຈັກໄທຍ th
+Tailandas th
+Taivāna th
+Tajlandja th
+Tailandia th
+Tajlandia th
+Tailândia th
+Tailândia th
+Tailanda th
+Таиланд th
+Thajsko th
+Tajska th
+Tajland th
+I-Thailand th
+¾¡öÄ¡óÐ th
+ราชอาณาจักรไทย th
+Tayland th
+Таїланд th
+Thái Lan th
+Taylande th
+泰国 th
+泰國 th
+Tajikistan tj
+Таджыкістан tj
+Таджикистан tj
+Tadžikistan tj
+Tajikistán tj
+Tadzsikisztán tj
+ໃຕ້ຫວັນ tj
+Tajiquistão tj
+Tadžikistan tj
+Tadžikistan tj
+Tadzjikistan tj
+塔吉克斯坦 tj
+Tokelau tk
+Токелао tk
+ເບລາລັສ tk
+Turkmenistan tm
+Туркмэністан tm
+Туркменистан tm
+Turkmenistán tm
+Türkmenisztán tm
+ຕຸລະກີ tm
+Turquia tm
+土库曼斯坦 tm
+Tunisia tn
+Tunisië tn
+تونس tn
+Туніс tn
+Тунис tn
+Tunis tn
+Tuníssia tn
+Tunisko tn
+Tunesien tn
+Tunesien tn
+Τυνησία tn
+Tunisio tn
+Túnez tn
+Tuneesia tn
+تونس tn
+Tunesia tn
+Tunisie tn
+תוניסיה tn
+Tunis tn
+Tunézia tn
+チュニジア tn
+튀니지 tn
+ລັດເຊີຍ tn
+Tunisas tn
+Tuneżija tn
+Tunisie tn
+Tunezja tn
+Tunísia tn
+Tunísia tn
+Тунис tn
+Tunisko tn
+Tunizija tn
+I-Tunisia tn
+Tunisien tn
+ÐÉ¢º¢Â¡ tn
+Tunus tn
+Туніс tn
+突尼斯 tn
+突尼西亞 tn
+Tonga to
+Тонга to
+Тонга to
+ໂຊນາ to
+汤加 to
+East Timor tp
+Источен Тимур tp
+Istočni Timor tp
+Østtimor tp
+Timor oriental tp
+Ekialdeko Timor tp
+Kelet-Timor tp
+ວັນແລະເວລາ tp
+Timor Leste tp
+Východný Timor tp
+Vzhodni Timor tp
+Östtimor tp
+东帝汶 tp
+Turkey tr
+Turkeye tr
+تركيا tr
+Türkiyə tr
+Турцыя tr
+Турция tr
+Turkia tr
+Turska tr
+Turquia tr
+Turecko tr
+Tyrkiet tr
+Türkei tr
+Τουρκία tr
+Turkujo tr
+Turquía tr
+Türgi tr
+Turkia tr
+ترکیه tr
+Turkki tr
+Turkaland tr
+Turquie tr
+Turquía tr
+טורקיה tr
+Turska tr
+Törökország tr
+Turki tr
+Tyrkland tr
+Turchia tr
+トルコ tr
+터키 tr
+ຕຸລະກີ tr
+Turkija tr
+Turcija tr
+Turkija tr
+Tyrkia tr
+Turkije tr
+Tyrkia tr
+Turquia tr
+Turcja tr
+Turquia tr
+Turquia tr
+Turcia tr
+Турция tr
+Turecko tr
+Turčija tr
+Turska tr
+I-Turkey tr
+Turkiet tr
+ÐÕ츢 tr
+ตุรกี tr
+Türkiye tr
+Туреччина tr
+ThềENhĩ Kì tr
+土耳其 tr
+土耳其 tr
+Trinidad and Tobago tt
+Trinidad en Tobago tt
+ترينيداد و توباغو tt
+Trinidad və Tabaqo tt
+Трынідад і Табага tt
+Тринидад и Тобаго tt
+Trinidad ha Tobago tt
+Trinidad i Tobago tt
+Trinidad i Tobago tt
+Trinidad a Tobago tt
+Trinidad og Tobago tt
+Trinidad und Tobago tt
+Τρίνινταντ και Τομπάγκο tt
+Trinidado kaj Tobago tt
+Trinidad y Tobago tt
+Trinidad ja Tobago tt
+Trinidad eta Tobago tt
+ترینیداد و تُباگو tt
+Trinidad ja Tobago tt
+Trinidad og Tobago tt
+Trinidad et Tobago tt
+Trindade e Tobago tt
+טרינידד וטובגו tt
+Trinidad i Tobago tt
+Trinidad és Tobago tt
+Trinidad dan Tobago tt
+Trinidad og Tobago tt
+Trinidad e Tobago tt
+トリニダードトバコ tt
+트리니다드토바고 tt
+ຕີນິແດດແລະໂທບາໂກ tt
+Trinidadas ir Tobagas tt
+Trinidada un Tobago tt
+Trinidad u Tobago tt
+Trinidad og Tobago tt
+Trinidad en Tobago tt
+Trinidad og Tobago tt
+Trinidad le Tobago tt
+Trinidad e Tobago tt
+Trinidad i Tobago tt
+Trinidade e Tobago tt
+Trinidad e Tobago tt
+Trinidad şi Tobago tt
+Тринидад и Тобаго tt
+Trinidad a Tobago tt
+Trinidad in Tabago tt
+Trinidad i Tobago tt
+I-Trinidad kanye neTobago tt
+Trinidad och Tobago tt
+ðâɢ¼¡ð & ¦¼¡À¡§¸¡ tt
+ตรีนิแดดและโทบาโก tt
+Trinidad veTabago tt
+Республіка Трінідад та Тобаго tt
+Trinidad na Tobago tt
+Trinidad và Tobago tt
+Trinidad ne Tobago tt
+特里尼达和多巴哥 tt
+千里達及托貝哥 tt
+Trinidad knaye ne-Tobago tt
+Tuvalu tv
+Тувалу tv
+Тували tv
+ຊູລູ tv
+图瓦卢 tv
+Taiwan tw
+تايوان tw
+Tayvan tw
+Тайвань tw
+Тайван tw
+Tajvan tw
+Ταϊβάν tw
+Tajvano tw
+Taiwán tw
+Taivan tw
+تایوان tw
+Taivan tw
+Taïwan tw
+Taiwán tw
+טיוואן tw
+Tajvan tw
+Tajvan tw
+台湾 tw
+대만 tw
+ໃຕ້ຫວັນ tw
+Taivanis tw
+Taivāna tw
+Tajwan tw
+Tajwan tw
+Formosa tw
+Тайвань tw
+Tajvan tw
+Tajvan tw
+I-Taiwan tw
+¾¡öÅ¡ý tw
+ได้หวัน tw
+Tayvan tw
+Тайвань tw
+Đài Loan tw
+中国台湾 tw
+台灣 tw
+Tanzania, United Republic of tz
+Злучаная Рэспубліка Танзанія tz
+Танзания tz
+Tanzanija, Ujedinjena Republika tz
+Tanzania tz
+Tanzania, Republica de tz
+Tanazia, Errepublika Batua tz
+Tanzánia tz
+ໂດມິນິກັນ tz
+República da Tanzânia tz
+Tanzánia, Spojená republika tz
+Tanzanija, Združena republika tz
+Förenade republiken Tanzania tz
+坦桑尼亚 tz
+Ukraine ua
+Ukraïne ua
+أوكرانيا ua
+Ukrayna ua
+Украіна ua
+Украйна ua
+Ukraina ua
+Ukrajina ua
+Ucraïna ua
+Ukrajina ua
+Ουκρανία ua
+Ukrainio ua
+Ucrania ua
+Ukraina ua
+Ukrania ua
+اکراین ua
+Ukraina ua
+Ukraina ua
+Ucraína ua
+אוקראינה ua
+Ukrajina ua
+Ukrajna ua
+Ukraina ua
+Ã\9akraÃna ua
+Ucraina ua
+ウクライナ ua
+우크라이나 ua
+ຍູເຄຣນ ua
+Ukraina ua
+Ukraina ua
+Ukranja ua
+Ukraina ua
+Oekraïne ua
+Ukraina ua
+Ucraina ua
+Ukraina ua
+Ucrânia ua
+Ucrânia ua
+Ucraina ua
+Украина ua
+Ukrajina ua
+Ukrajina ua
+Ukrajna ua
+I-Ukraine ua
+Ukraina ua
+¯ì¦Ãöý ua
+ยูเครน ua
+Ukrayna ua
+Україна ua
+Ukraina ua
+Ucrinne ua
+乌克兰 ua
+烏克蘭 ua
+Uganda ug
+Уганда ug
+Уганда ug
+ແພນດ້າ ug
+乌干达 ug
+United States of America us
+Vereenigde State van Amerika us
+الولايات المتحدة الأمريكية us
+Amerika Birləşmiş Ştatları us
+Злучаныя Штаты Амэрыкі us
+САЩ us
+Stadoù-Unanet Amerika us
+Sjedinjene Američke Države us
+Estats Units d'Amèrica us
+Spojené státy americké us
+USA us
+USA us
+Ην. Πολιτείες της Αμερικής us
+Usono us
+Estados Unidos de América us
+Ameerika Ühendriigid us
+Amerikako Estatu Batuak us
+ایالات متحدهی آمریکا us
+Yhdysvallat us
+Sambandsríki Amerika (USA) us
+États Unis d'Amérique us
+Estados Unidos de América us
+ארצות הברית us
+Sjedinjene Američke Države us
+Amerikai Egyesült Államok us
+Amerika Serikat us
+BandarÃki Norður AmerÃku us
+Stati Uniti d'America us
+アメリカ us
+미 합중국 us
+ສະຫະລັດອາເມລິກາ us
+Jungtinės Amerikos Valstijos us
+Amerikas Savienotās Valstis us
+Stati Uniti us
+USA us
+Verenigde Staten van Amerika us
+USA us
+Estats Units d'Amèrica us
+Stany Zjednoczone Ameryki us
+Estados Unidos da América us
+Estados Unidos us
+Statele Unite ale Americii us
+Соединенные Штаты Америки us
+USA us
+Združene države Amerike us
+Sjedinjene američke države us
+I-United States of America us
+Amerikas förenta stater us
+³ì¸¢Â «¦ÁÃ¢ì¸ ¿¡Î¸û us
+สหรัฐอเมริกา us
+Amerika Birleşik Devletleri us
+США us
+mashango o tangananaho a America us
+Mĩ us
+United States ye Melika us
+美利坚合众国 us
+美利堅合眾國 us
+Uruguay uy
+الأوروغواي uy
+Uruqvay uy
+Уругвай uy
+Уругвай uy
+Urugvaj uy
+Uruguai uy
+Ουρουγουάη uy
+Urugvajo uy
+Uruguai uy
+اروگویه uy
+Uruguai uy
+אורוגואי uy
+Urugvaj uy
+ウルグアイ uy
+우루과이 uy
+ອຸລຸກກວຍ uy
+Urugvajus uy
+Urugvaja uy
+Urugwaj uy
+Uruguai uy
+Urugwaj uy
+Uruguai uy
+Uruguai uy
+Uruguai uy
+Уругвай uy
+Uruguaj uy
+Urugvaj uy
+Urugvaj uy
+I-Uruguay uy
+¯Õ̧Šuy
+อุรุกวัย uy
+Уругвай uy
+Ourougway uy
+乌拉圭 uy
+烏拉圭 uy
+Uzbekistan uz
+Узбэкістан uz
+Узбекистан uz
+Uzbekistán uz
+Üzbegisztán uz
+ເດນ່ງນ uz
+Uzbequistão uz
+乌兹别克斯坦 uz
+Vatican City va
+Ватыкан va
+Ватикана va
+Vatikan va
+Vatikanstaten va
+Vaticano va
+Batikano Hiria va
+Vatikán va
+ລັດເວີຍ va
+Cidade do Vaticano va
+Vatikán va
+Vatikan va
+Vatikanstaten va
+梵蒂冈 va
+St. Vincent and the Grenadines vc
+St. Vincent en die Grenadene vc
+سانت فينسنت و الغرينادين vc
+St. Vincent və Grenadines vc
+Сент-Винсент и Гренадине vc
+S. Visant hag ar Grenadinez vc
+Sveti Vincent i Grenadini vc
+St. Vincent i les Granadines vc
+St. Vincent a Grenadiny vc
+St. Vincent og Grenadinerne vc
+St. Vincent und Grenadinen vc
+St. Vincent kaj la Grenadinoj vc
+San Vicente y las Granadinas vc
+St. Vincent ja Grenadines vc
+St. Vincent eta Grenadines vc
+سن وینسن و گرادینس vc
+St. Vincent ja Grenadiinit vc
+Sankta Vinsent og Grenadinoyggjar vc
+St Vincent et les Grenadines vc
+San Vicente e as Granadinas vc
+סנט וינסנט והגרנדינים vc
+St. Vincent és Grenadines vc
+St. Vincent dan the Grenadines vc
+St. Vincent og Grenadines vc
+S. Vincent e the Grenadines vc
+セントヴィンセントグレナディン vc
+세인트 빈센트 그레나딘 vc
+ເຊີນວິນແຊນ ແລະເກນາດີນ vc
+Šv. Vincentas ir Grenadinai vc
+Sv. Vincents un Grenadīnes vc
+St. Vinċenz u l-Grenadini vc
+St. Vincent og Grenadinene vc
+St. Vincent en de Grenadines vc
+St. Vincent og Grenadinane vc
+St. Vincent le Grenadines vc
+St. Vincent e les Granadines vc
+St. Vincent i Grenadyny vc
+São Vicente e Grenadinas vc
+São Vicente e Grenadines vc
+Sf. Vincent şi Grenadines vc
+Сент-Винсент и Гренадины vc
+St. Vincent a Grenadines vc
+Sv. Vincent in Grenadini vc
+St. Vincent i Grenadine vc
+I-St. Vincent and the Grenadines vc
+St. Vincent och Grenadinerna vc
+¦ºÂ¢ýð Å¢ý¦ºýð & ¸¢¦ÃÉËý¸û vc
+เซนต์วินเซนต์ และ เกรนาดีน vc
+St. Vincent ve Grenadines vc
+Сент-Вінсент і Гренадіни vc
+St. Vincent na Grenadines vc
+St. Vincent và Grenadines vc
+St. Vincent ne Grenadines vc
+圣文森特和格林那达 vc
+聖文森及格納那丁 vc
+I-St. Vincent kanye ne-Grenadines vc
+Venezuela ve
+فنزويلا ve
+Вэнэсуэла ve
+Венецуела ve
+Venecuela ve
+Βενεζουέλα ve
+Venezuelo ve
+Venetsueela ve
+ونزویلا ve
+Venesuela ve
+Vénézuela ve
+ונצואלה ve
+Venecuela ve
+ベネズェラ ve
+베네수엘라 ve
+ເວເນຊຸເອລາ ve
+Venesuela ve
+Venecuēla ve
+Veneżwela ve
+Wenezuela ve
+Венесуэла ve
+Venecuela ve
+I-Venezuela ve
+¦ÅÉ¢ÍÅÄ¡ ve
+เวเนซูเอลา ve
+Венесуела ve
+委内瑞拉 ve
+委內瑞拉 ve
+Virgin Islands, British vg
+Вирджински Острови, Британски vg
+Djevičanska ostrva, Britanska vg
+Britiske jomfruøer vg
+Islas Vírgenes Británicas vg
+Irla Birjinak, Britaniar vg
+Virgin-szigetek (brit) vg
+Ilhas Virgens, Inglaterra vg
+Panenské Ostrovy, Britské vg
+Deviški otoki, Britanski vg
+Brittiska Jungfruöarna vg
+维尔京群岛,英国 vg
+Virgin Islands, U.S. vi
+Вирджински Острови, Американски vi
+Djevičanska ostrva, Američka vi
+Jomfruøerne vi
+Islas Vírgenes Americanas vi
+Irla Birjinak, EE.BB. vi
+Virgin-szigetek (USA) vi
+Ilhas Virgens, EUA vi
+Panenské Ostrovy, Americké vi
+Deviški otoki, ZDA vi
+Amerikanska Jungfruöarna vi
+维尔京群岛,美国 vi
+Vietnam vn
+Viëtnam vn
+فييتنام vn
+Vyetnam vn
+Віетнам vn
+Виетнам vn
+Vijetnam vn
+Βιετνάμ vn
+Vjetnamo vn
+ویتنام vn
+וייטנאם vn
+Vijetnam vn
+VÃetnam vn
+ベトナム vn
+베트남 vn
+ຫວງດນາມ vn
+Vietnamas vn
+Vjetnama vn
+Vjetnam vn
+Viëtnam vn
+Wietnam vn
+Vietname vn
+Vietnã vn
+Вьетнам vn
+I-Vietnam vn
+เวียตนาม vn
+В'єтнам vn
+越南 vn
+越南 vn
+Vanuatu vu
+Вануату vu
+Ванути vu
+ຈີນ vu
+瓦努阿图 vu
+Wallis and Futuna wf
+Valis i Futuna wf
+Wallis- og Futuna-øerne wf
+Wallis y Futuna wf
+Wallis eta Futuna wf
+Wallis és Futuna wf
+ປັກອິນພາບ wf
+Wallis e Futuna wf
+Wallis a Futuna wf
+Wallis in Futuna wf
+Wallis och Futuna wf
+Samoa ws
+Самоа ws
+Самоя ws
+Szamoa ws
+ໂຊນາ ws
+萨摩亚群岛 ws
+Yemen ye
+اليمن ye
+Емен ye
+Йемен ye
+Jemen ye
+Iemen ye
+Jemen ye
+Jemen ye
+Υεμένη ye
+Jemeno ye
+Jeemen ye
+یمن ye
+Jemen ye
+Jemen ye
+תימן ye
+Jemen ye
+Jemen ye
+イエメン ye
+예멘 ye
+ເດມອນ ye
+Jemenas ye
+Jemen ye
+Jemen ye
+Jemen ye
+Jemen ye
+Jemen ye
+Iémen ye
+Йемен ye
+Jemen ye
+Jemen ye
+I-Yemen ye
+Jemen ye
+§ÂÁý ye
+Ємен ye
+也门 ye
+葉門 ye
+Yugoslavia yu
+Югаславія yu
+Югославия yu
+Jugoslavija yu
+Jugoslavien (Serbien/Montenegro) yu
+Jugoszlávia yu
+ໂບລິເວີຍ yu
+Iugoslávia yu
+Juhoslávia yu
+Jugoslavija yu
+Jugoslavien yu
+南斯拉夫 yu
+South Africa za
+Suid Afrika za
+جنوب أفريقيا za
+Cənubi Afrika za
+Паўднёвая Афрыка za
+Южна Африка za
+Suafrika za
+Južna Afrika za
+Sudàfrica za
+Jižní Afrika za
+Sydafrikanske republik za
+Südafrika za
+Νότια Αφρική za
+Sudafriko za
+Sudáfrica za
+Lõuna Aafrika za
+Hego Afrika za
+آفریقای جنوبی za
+Etelä-Afrikka za
+Suðurafrika za
+Afrique du sud za
+África do Sur za
+דרום אפריקה za
+Južna Afrika za
+Dél-Afrika za
+Afrika Selatan za
+Suður AfrÃka za
+Sud Africa za
+南アフリカ za
+남 아프리카 공화국 za
+ແອບພິກາໃຕ້ za
+Pietų Afrika za
+Dienvid Āfrika za
+Afrika t'Isfel za
+Sør-Afrika za
+Zuid-Afrika za
+Sør-Afrika za
+Afrika Borwa za
+Sudafrica za
+Afryka Południowa za
+Africa do Sul za
+África do Sul za
+Africa de Sud za
+Южная Африка za
+Južná Afrika za
+Južna Afrika za
+Južna Afrika za
+I-South Africa za
+Sydafrika za
+¦¾ý ¬ôâ측 za
+แอฟริกาใต้ za
+Güney Afrika za
+Південна Африка za
+Afurika tshipembe za
+Nam Phi za
+Mzantsi Afrika za
+南非 za
+南非 za
+Emzantsi Afrika za
+Zambia zm
+Замбія zm
+Замбия zm
+ຈາໄມກາ້ zm
+Zâmbia zm
+Zambija zm
+赞比亚 zm
+Zimbabwe zw
+Зымбабвэ zw
+Зимбабве zw
+Zimbabve zw
+ລິຊາ zw
+Zimbabve zw
+津巴布韦 zw
--- /dev/null
+/*
+ This file is part of the KContacts framework.
+ Copyright (c) 2015 Laurent Montel <montel@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "email.h"
+
+#include <QMap>
+#include <qstringlist.h>
+#include <QDataStream>
+
+using namespace KContacts;
+
+class Q_DECL_HIDDEN Email::Private : public QSharedData
+{
+public:
+ Private()
+ {
+ }
+
+ Private(const Private &other)
+ : QSharedData(other)
+ {
+ parameters = other.parameters;
+ mail = other.mail;
+ }
+ QMap<QString, QStringList> parameters;
+ QString mail;
+};
+
+Email::Email()
+ : d(new Private)
+{
+
+}
+
+Email::Email(const QString &mail)
+ : d(new Private)
+{
+ d->mail = mail;
+}
+
+Email::Email(const Email &other)
+ : d(other.d)
+{
+}
+
+Email::~Email()
+{
+
+}
+
+QMap<QString, QStringList> Email::parameters() const
+{
+ return d->parameters;
+}
+
+bool Email::operator==(const Email &other) const
+{
+ return (d->parameters == other.parameters()) && (d->mail == other.mail());
+}
+
+bool Email::operator!=(const Email &other) const
+{
+ return !(other == *this);
+}
+
+Email &Email::operator=(const Email &other)
+{
+ if (this != &other) {
+ d = other.d;
+ }
+
+ return *this;
+}
+
+QString Email::toString() const
+{
+ QString str;
+ str += QLatin1String("Email {\n");
+ str += QStringLiteral(" mail: %1\n").arg(d->mail);
+ if (!d->parameters.isEmpty()) {
+ QMapIterator<QString, QStringList> i(d->parameters);
+ QString param;
+ while (i.hasNext()) {
+ i.next();
+ param += QStringLiteral("%1 %2").arg(i.key(), i.value().join(QStringLiteral(",")));
+ }
+ str += QStringLiteral(" parameters: %1\n").arg(param);
+ }
+ str += QLatin1String("}\n");
+ return str;
+}
+
+void Email::setParameters(const QMap<QString, QStringList> ¶ms)
+{
+ d->parameters = params;
+}
+
+void Email::setEmail(const QString &mail)
+{
+ d->mail = mail;
+}
+
+QString Email::mail() const
+{
+ return d->mail;
+}
+
+bool Email::isValid() const
+{
+ return !d->mail.isEmpty();
+}
+
+QDataStream &KContacts::operator<<(QDataStream &s, const Email &email)
+{
+ return s << email.d->parameters << email.d->mail;
+}
+
+QDataStream &KContacts::operator>>(QDataStream &s, Email &email)
+{
+ s >> email.d->parameters >> email.d->mail;
+ return s;
+}
+
--- /dev/null
+/*
+ This file is part of the KContacts framework.
+ Copyright (c) 2015 Laurent Montel <montel@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef EMAIL_H
+#define EMAIL_H
+
+#include "kcontacts_export.h"
+#include <QtCore/QSharedDataPointer>
+#include <QtCore/QString>
+#include <QtCore/QMap>
+
+/** @short Class that holds a Email for a contact.
+ * @since 4.14.5
+ */
+
+namespace KContacts
+{
+
+class KCONTACTS_EXPORT Email
+{
+ friend KCONTACTS_EXPORT QDataStream &operator<<(QDataStream &, const Email &);
+ friend KCONTACTS_EXPORT QDataStream &operator>>(QDataStream &, Email &);
+public:
+ /**
+ * Creates an empty email object.
+ */
+ Email();
+ Email(const Email &other);
+ Email(const QString &mail);
+
+ ~Email();
+
+ typedef QVector<Email> List;
+
+ void setEmail(const QString &mail);
+ QString mail() const;
+
+ bool isValid() const;
+
+ void setParameters(const QMap<QString, QStringList> ¶ms);
+ QMap<QString, QStringList> parameters() const;
+
+ bool operator==(const Email &other) const;
+ bool operator!=(const Email &other) const;
+
+ Email &operator=(const Email &other);
+
+ QString toString() const;
+private:
+ class Private;
+ QSharedDataPointer<Private> d;
+};
+
+KCONTACTS_EXPORT QDataStream &operator<<(QDataStream &stream, const Email &object);
+
+KCONTACTS_EXPORT QDataStream &operator>>(QDataStream &stream, Email &object);
+
+}
+Q_DECLARE_TYPEINFO(KContacts::Email, Q_MOVABLE_TYPE);
+#endif // EMAIL_H
--- /dev/null
+/*
+ This file is part of the KContacts framework.
+ Copyright (c) 2002 Cornelius Schumacher <schumacher@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <klocalizedstring.h>
+#include <kconfig.h>
+
+#include <kconfiggroup.h>
+#include <KSharedConfig>
+#include "field.h"
+
+using namespace KContacts;
+
+class Q_DECL_HIDDEN Field::Private
+{
+public:
+ Private(int fieldId, int category = 0,
+ const QString &label = QString(),
+ const QString &key = QString(),
+ const QString &app = QString())
+ : mFieldId(fieldId), mCategory(category), mLabel(label),
+ mKey(key), mApp(app) {}
+
+ enum FieldId {
+ CustomField,
+ FormattedName,
+ FamilyName,
+ GivenName,
+ AdditionalName,
+ Prefix,
+ Suffix,
+ NickName,
+ Birthday,
+ HomeAddressStreet,
+ HomeAddressPostOfficeBox,
+ HomeAddressLocality,
+ HomeAddressRegion,
+ HomeAddressPostalCode,
+ HomeAddressCountry,
+ HomeAddressLabel,
+ BusinessAddressStreet,
+ BusinessAddressPostOfficeBox,
+ BusinessAddressLocality,
+ BusinessAddressRegion,
+ BusinessAddressPostalCode,
+ BusinessAddressCountry,
+ BusinessAddressLabel,
+ HomePhone,
+ BusinessPhone,
+ MobilePhone,
+ HomeFax,
+ BusinessFax,
+ CarPhone,
+ Isdn,
+ Pager,
+ Email,
+ Mailer,
+ Title,
+ Role,
+ Organization,
+ Department,
+ Note,
+ Url
+ };
+
+ int fieldId() const
+ {
+ return mFieldId;
+ }
+ int category() const
+ {
+ return mCategory;
+ }
+
+ QString label() const
+ {
+ return mLabel;
+ }
+ QString key() const
+ {
+ return mKey;
+ }
+ QString app() const
+ {
+ return mApp;
+ }
+
+ static Field::List mAllFields;
+ static Field::List mDefaultFields;
+ static Field::List mCustomFields;
+
+private:
+ int mFieldId;
+ int mCategory;
+
+ QString mLabel;
+ QString mKey;
+ QString mApp;
+};
+
+Field::List Field::Private::mAllFields;
+Field::List Field::Private::mDefaultFields;
+Field::List Field::Private::mCustomFields;
+
+Field::Field(Private *p)
+ : d(p)
+{
+}
+
+Field::~Field()
+{
+ delete d;
+}
+
+QString Field::label()
+{
+ switch (d->fieldId()) {
+ case Private::FormattedName:
+ return Addressee::formattedNameLabel();
+ case Private::FamilyName:
+ return Addressee::familyNameLabel();
+ case Private::GivenName:
+ return Addressee::givenNameLabel();
+ case Private::AdditionalName:
+ return Addressee::additionalNameLabel();
+ case Private::Prefix:
+ return Addressee::prefixLabel();
+ case Private::Suffix:
+ return Addressee::suffixLabel();
+ case Private::NickName:
+ return Addressee::nickNameLabel();
+ case Private::Birthday:
+ return Addressee::birthdayLabel();
+ case Private::HomeAddressStreet:
+ return Addressee::homeAddressStreetLabel();
+ case Private::HomeAddressPostOfficeBox:
+ return Addressee::homeAddressPostOfficeBoxLabel();
+ case Private::HomeAddressLocality:
+ return Addressee::homeAddressLocalityLabel();
+ case Private::HomeAddressRegion:
+ return Addressee::homeAddressRegionLabel();
+ case Private::HomeAddressPostalCode:
+ return Addressee::homeAddressPostalCodeLabel();
+ case Private::HomeAddressCountry:
+ return Addressee::homeAddressCountryLabel();
+ case Private::HomeAddressLabel:
+ return Addressee::homeAddressLabelLabel();
+ case Private::BusinessAddressStreet:
+ return Addressee::businessAddressStreetLabel();
+ case Private::BusinessAddressPostOfficeBox:
+ return Addressee::businessAddressPostOfficeBoxLabel();
+ case Private::BusinessAddressLocality:
+ return Addressee::businessAddressLocalityLabel();
+ case Private::BusinessAddressRegion:
+ return Addressee::businessAddressRegionLabel();
+ case Private::BusinessAddressPostalCode:
+ return Addressee::businessAddressPostalCodeLabel();
+ case Private::BusinessAddressCountry:
+ return Addressee::businessAddressCountryLabel();
+ case Private::BusinessAddressLabel:
+ return Addressee::businessAddressLabelLabel();
+ case Private::HomePhone:
+ return Addressee::homePhoneLabel();
+ case Private::BusinessPhone:
+ return Addressee::businessPhoneLabel();
+ case Private::MobilePhone:
+ return Addressee::mobilePhoneLabel();
+ case Private::HomeFax:
+ return Addressee::homeFaxLabel();
+ case Private::BusinessFax:
+ return Addressee::businessFaxLabel();
+ case Private::CarPhone:
+ return Addressee::carPhoneLabel();
+ case Private::Isdn:
+ return Addressee::isdnLabel();
+ case Private::Pager:
+ return Addressee::pagerLabel();
+ case Private::Email:
+ return Addressee::emailLabel();
+ case Private::Mailer:
+ return Addressee::mailerLabel();
+ case Private::Title:
+ return Addressee::titleLabel();
+ case Private::Role:
+ return Addressee::roleLabel();
+ case Private::Organization:
+ return Addressee::organizationLabel();
+ case Private::Department:
+ return Addressee::departmentLabel();
+ case Private::Note:
+ return Addressee::noteLabel();
+ case Private::Url:
+ return Addressee::urlLabel();
+ case Private::CustomField:
+ return d->label();
+ default:
+ return i18n("Unknown Field");
+ }
+}
+
+int Field::category()
+{
+ return d->category();
+}
+
+QString Field::categoryLabel(int category)
+{
+ switch (category) {
+ case All:
+ return i18n("All");
+ case Frequent:
+ return i18n("Frequent");
+ case Address:
+ return i18nc("street/postal", "Address");
+ case Email:
+ return i18n("Email");
+ case Personal:
+ return i18n("Personal");
+ case Organization:
+ return i18n("Organization");
+ case CustomCategory:
+ return i18n("Custom");
+ default:
+ return i18n("Undefined");
+ }
+}
+
+QString Field::value(const KContacts::Addressee &a)
+{
+ switch (d->fieldId()) {
+ case Private::FormattedName:
+ return a.formattedName();
+ case Private::FamilyName:
+ return a.familyName();
+ case Private::GivenName:
+ return a.givenName();
+ case Private::AdditionalName:
+ return a.additionalName();
+ case Private::Prefix:
+ return a.prefix();
+ case Private::Suffix:
+ return a.suffix();
+ case Private::NickName:
+ return a.nickName();
+ case Private::Mailer:
+ return a.mailer();
+ case Private::Title:
+ return a.title();
+ case Private::Role:
+ return a.role();
+ case Private::Organization:
+ return a.organization();
+ case Private::Department:
+ return a.department();
+ case Private::Note:
+ return a.note();
+ case Private::Email:
+ return a.preferredEmail();
+ case Private::Birthday:
+ if (a.birthday().isValid()) {
+ return a.birthday().date().toString(Qt::ISODate);
+ } else {
+ return QString();
+ }
+ case Private::Url:
+ return a.url().url().toDisplayString();
+ case Private::HomePhone: {
+ PhoneNumber::List::ConstIterator it;
+
+ {
+ // check for preferred number
+ const PhoneNumber::List list = a.phoneNumbers(PhoneNumber::Home | PhoneNumber::Pref);
+ PhoneNumber::List::ConstIterator end(list.end());
+ for (it = list.begin(); it != end; ++it) {
+ if (((*it).type() & ~(PhoneNumber::Pref)) == PhoneNumber::Home) {
+ return (*it).number();
+ }
+ }
+ }
+
+ {
+ // check for normal home number
+ const PhoneNumber::List list = a.phoneNumbers(PhoneNumber::Home);
+ PhoneNumber::List::ConstIterator end(list.end());
+ for (it = list.begin(); it != end; ++it) {
+ if (((*it).type() & ~(PhoneNumber::Pref)) == PhoneNumber::Home) {
+ return (*it).number();
+ }
+ }
+ }
+
+ return QString();
+ }
+ case Private::BusinessPhone: {
+ PhoneNumber::List::ConstIterator it;
+
+ {
+ // check for preferred number
+ const PhoneNumber::List list = a.phoneNumbers(PhoneNumber::Work | PhoneNumber::Pref);
+ PhoneNumber::List::ConstIterator end(list.end());
+ for (it = list.begin(); it != end; ++it) {
+ if (((*it).type() & ~(PhoneNumber::Pref)) == PhoneNumber::Work) {
+ return (*it).number();
+ }
+ }
+ }
+
+ {
+ // check for normal work number
+ const PhoneNumber::List list = a.phoneNumbers(PhoneNumber::Work);
+ for (it = list.begin(); it != list.end(); ++it) {
+ if (((*it).type() & ~(PhoneNumber::Pref)) == PhoneNumber::Work) {
+ return (*it).number();
+ }
+ }
+ }
+
+ return QString();
+ }
+ case Private::MobilePhone:
+ return a.phoneNumber(PhoneNumber::Cell).number();
+ case Private::HomeFax:
+ return a.phoneNumber(PhoneNumber::Home | PhoneNumber::Fax).number();
+ case Private::BusinessFax:
+ return a.phoneNumber(PhoneNumber::Work | PhoneNumber::Fax).number();
+ case Private::CarPhone:
+ return a.phoneNumber(PhoneNumber::Car).number();
+ case Private::Isdn:
+ return a.phoneNumber(PhoneNumber::Isdn).number();
+ case Private::Pager:
+ return a.phoneNumber(PhoneNumber::Pager).number();
+ case Private::HomeAddressStreet:
+ return a.address(Address::Home).street();
+ case Private::HomeAddressPostOfficeBox:
+ return a.address(Address::Home).postOfficeBox();
+ case Private::HomeAddressLocality:
+ return a.address(Address::Home).locality();
+ case Private::HomeAddressRegion:
+ return a.address(Address::Home).region();
+ case Private::HomeAddressPostalCode:
+ return a.address(Address::Home).postalCode();
+ case Private::HomeAddressCountry:
+ return a.address(Address::Home).country();
+ case Private::BusinessAddressStreet:
+ return a.address(Address::Work).street();
+ case Private::BusinessAddressPostOfficeBox:
+ return a.address(Address::Work).postOfficeBox();
+ case Private::BusinessAddressLocality:
+ return a.address(Address::Work).locality();
+ case Private::BusinessAddressRegion:
+ return a.address(Address::Work).region();
+ case Private::BusinessAddressPostalCode:
+ return a.address(Address::Work).postalCode();
+ case Private::BusinessAddressCountry:
+ return a.address(Address::Work).country();
+ case Private::CustomField:
+ return a.custom(d->app(), d->key());
+ default:
+ return QString();
+ }
+}
+
+bool Field::setValue(KContacts::Addressee &a, const QString &value)
+{
+ switch (d->fieldId()) {
+ case Private::FormattedName:
+ a.setFormattedName(value);
+ return true;
+ case Private::FamilyName:
+ a.setFamilyName(value);
+ return true;
+ case Private::GivenName:
+ a.setGivenName(value);
+ return true;
+ case Private::AdditionalName:
+ a.setAdditionalName(value);
+ return true;
+ case Private::Prefix:
+ a.setPrefix(value);
+ return true;
+ case Private::Suffix:
+ a.setSuffix(value);
+ return true;
+ case Private::NickName:
+ a.setNickName(value);
+ return true;
+ case Private::Mailer:
+ a.setMailer(value);
+ return true;
+ case Private::Title:
+ a.setTitle(value);
+ return true;
+ case Private::Role:
+ a.setRole(value);
+ return true;
+ case Private::Organization:
+ a.setOrganization(value);
+ return true;
+ case Private::Department:
+ a.setDepartment(value);
+ return true;
+ case Private::Note:
+ a.setNote(value);
+ return true;
+ case Private::Birthday:
+ a.setBirthday(QDateTime::fromString(value, Qt::ISODate));
+ return true;
+ case Private::CustomField:
+ a.insertCustom(d->app(), d->key(), value);
+ return true;
+ default:
+ return false;
+ }
+}
+
+QString Field::sortKey(const KContacts::Addressee &a)
+{
+ switch (d->fieldId()) {
+ case Private::FormattedName:
+ return a.formattedName();
+ case Private::FamilyName:
+ return a.familyName();
+ case Private::GivenName:
+ return a.givenName();
+ case Private::AdditionalName:
+ return a.additionalName();
+ case Private::Prefix:
+ return a.prefix();
+ case Private::Suffix:
+ return a.suffix();
+ case Private::NickName:
+ return a.nickName();
+ case Private::Mailer:
+ return a.mailer();
+ case Private::Title:
+ return a.title();
+ case Private::Role:
+ return a.role();
+ case Private::Organization:
+ return a.organization();
+ case Private::Department:
+ return a.department();
+ case Private::Note:
+ return a.note();
+ case Private::Birthday:
+ if (a.birthday().isValid()) {
+ QDate date = a.birthday().date();
+ QString key;
+ key.sprintf("%02d-%02d", date.month(), date.day());
+ return key;
+ } else {
+ return QStringLiteral("00-00");
+ }
+ default:
+ return value(a).toLower();
+ }
+}
+
+bool Field::isCustom()
+{
+ return d->fieldId() == Private::CustomField;
+}
+
+Field::List Field::allFields()
+{
+ if (Private::mAllFields.isEmpty()) {
+ createField(Private::FormattedName, Frequent);
+ createField(Private::FamilyName, Frequent);
+ createField(Private::GivenName, Frequent);
+ createField(Private::AdditionalName);
+ createField(Private::Prefix);
+ createField(Private::Suffix);
+ createField(Private::NickName, Personal);
+ createField(Private::Birthday, Personal);
+ createField(Private::HomeAddressStreet, Address | Personal);
+ createField(Private::HomeAddressPostOfficeBox, Address | Personal);
+ createField(Private::HomeAddressLocality, Address | Personal);
+ createField(Private::HomeAddressRegion, Address | Personal);
+ createField(Private::HomeAddressPostalCode, Address | Personal);
+ createField(Private::HomeAddressCountry, Address | Personal);
+ createField(Private::HomeAddressLabel, Address | Personal);
+ createField(Private::BusinessAddressStreet, Address | Organization);
+ createField(Private::BusinessAddressPostOfficeBox, Address | Organization);
+ createField(Private::BusinessAddressLocality, Address | Organization);
+ createField(Private::BusinessAddressRegion, Address | Organization);
+ createField(Private::BusinessAddressPostalCode, Address | Organization);
+ createField(Private::BusinessAddressCountry, Address | Organization);
+ createField(Private::BusinessAddressLabel, Address | Organization);
+ createField(Private::HomePhone, Personal | Frequent);
+ createField(Private::BusinessPhone, Organization | Frequent);
+ createField(Private::MobilePhone, Frequent);
+ createField(Private::HomeFax);
+ createField(Private::BusinessFax);
+ createField(Private::CarPhone);
+ createField(Private::Isdn);
+ createField(Private::Pager);
+ createField(Private::Email, Email | Frequent);
+ createField(Private::Mailer, Email);
+ createField(Private::Title, Organization);
+ createField(Private::Role, Organization);
+ createField(Private::Organization, Organization);
+ createField(Private::Department, Organization);
+ createField(Private::Note);
+ createField(Private::Url);
+ }
+
+ return Private::mAllFields;
+}
+
+Field::List Field::defaultFields()
+{
+ if (Private::mDefaultFields.isEmpty()) {
+ createDefaultField(Private::FormattedName);
+ createDefaultField(Private::Email);
+ }
+
+ return Private::mDefaultFields;
+}
+
+void Field::createField(int id, int category)
+{
+ Private::mAllFields.append(new Field(new Private(id, category)));
+}
+
+void Field::createDefaultField(int id, int category)
+{
+ Private::mDefaultFields.append(new Field(new Private(id, category)));
+}
+
+void Field::deleteFields()
+{
+ Field::List::ConstIterator it;
+
+ for (it = Private::mAllFields.constBegin(); it != Private::mAllFields.constEnd(); ++it) {
+ delete(*it);
+ }
+ Private::mAllFields.clear();
+
+ for (it = Private::mDefaultFields.constBegin(); it != Private::mDefaultFields.constEnd(); ++it) {
+ delete(*it);
+ }
+ Private::mDefaultFields.clear();
+
+ for (it = Private::mCustomFields.constBegin(); it != Private::mCustomFields.constEnd(); ++it) {
+ delete(*it);
+ }
+ Private::mCustomFields.clear();
+}
+
+void Field::saveFields(const QString &identifier,
+ const Field::List &fields)
+{
+ KConfigGroup cg(KSharedConfig::openConfig(), "KABCFields");
+
+ saveFields(cg, identifier, fields);
+}
+
+void Field::saveFields(KConfigGroup &cfg, const QString &identifier,
+ const Field::List &fields)
+{
+ QList<int> fieldIds;
+
+ int custom = 0;
+ Field::List::ConstIterator it;
+ fieldIds.reserve(fields.count());
+ for (it = fields.begin(); it != fields.end(); ++it) {
+ fieldIds.append((*it)->d->fieldId());
+ if ((*it)->isCustom()) {
+ QStringList customEntry;
+ customEntry << (*it)->d->label();
+ customEntry << (*it)->d->key();
+ customEntry << (*it)->d->app();
+ cfg.writeEntry(QLatin1String("KCONTACTS_CustomEntry_") + identifier + QLatin1Char('_') +
+ QString::number(custom++), customEntry);
+ }
+ }
+
+ cfg.writeEntry(identifier, fieldIds);
+}
+
+Field::List Field::restoreFields(const QString &identifier)
+{
+ KConfigGroup cg(KSharedConfig::openConfig(), "KABCFields");
+
+ return restoreFields(cg, identifier);
+}
+
+Field::List Field::restoreFields(const KConfigGroup &cfg, const QString &identifier)
+{
+ const QList<int> fieldIds = cfg.readEntry(identifier, QList<int>());
+
+ Field::List fields;
+
+ int custom = 0;
+ QList<int>::ConstIterator it;
+ fields.reserve(fieldIds.count());
+ for (it = fieldIds.begin(); it != fieldIds.end(); ++it) {
+ Private *f = Q_NULLPTR;
+ if ((*it) == Private::CustomField) {
+ QStringList customEntry = cfg.readEntry(QLatin1String("KCONTACTS_CustomEntry_") +
+ identifier + QLatin1Char('_') +
+ QString::number(custom++), QStringList());
+ f = new Private(*it, CustomCategory, customEntry[ 0 ],
+ customEntry[ 1 ], customEntry[ 2 ]);
+ } else {
+ f = new Private(*it);
+ }
+ fields.append(new Field(f));
+ }
+
+ return fields;
+}
+
+bool Field::equals(Field *field)
+{
+ bool sameId = (d->fieldId() == field->d->fieldId());
+
+ if (!sameId) {
+ return false;
+ }
+
+ if (d->fieldId() != Private::CustomField) {
+ return true;
+ }
+
+ return d->key() == field->d->key();
+}
+
+Field *Field::createCustomField(const QString &label, int category,
+ const QString &key, const QString &app)
+{
+ Field *field = new Field(new Private(Private::CustomField,
+ category | CustomCategory,
+ label, key, app));
+ Private::mCustomFields.append(field);
+
+ return field;
+}
--- /dev/null
+/*
+ This file is part of the KContacts framework.
+ Copyright (c) 2002 Cornelius Schumacher <schumacher@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KCONTACTS_FIELD_H
+#define KCONTACTS_FIELD_H
+
+#include "addressee.h"
+#include <QtCore/QString>
+
+class KConfigGroup;
+
+namespace KContacts
+{
+
+/**
+ * @short Represents a field in the Addressbook
+ *
+ * This class represents a field in the Addressbook database.
+ * It provides methods for accessing meta-information about
+ * the field (such as label() or category()) as well as
+ * getting or setting the field's value in an instance of
+ * Addressee (value(), setValue()).
+ *
+ * Furthermore, some static methods are provided for getting
+ * a list of all fields (allFields(), defaultFields()), for
+ * creating new fields (createCustomField()) and for saving
+ * or loading fields to/from a config file (saveFields(),
+ * restoreFields()).
+ */
+class KCONTACTS_EXPORT Field
+{
+public:
+ /**
+ * This type is used for a list of fields.
+ */
+ typedef QList<Field *> List;
+
+ /**
+ * Represents the category a field belongs to.
+ */
+ enum FieldCategory {
+ /**
+ * All fields
+ */
+ All = 0x0,
+ /**
+ * Frequently used fields
+ */
+ Frequent = 0x01,
+ /**
+ * Fields which belong to the address, such as Street, City, Zip, etc.
+ */
+ Address = 0x02,
+ /**
+ * Fields which store information about the e-mail contact, such as
+ * e-mail address or mail client
+ */
+ Email = 0x04,
+ /**
+ * Personal fields, such as Birthday, Home Address fields, IM Address, etc.
+ */
+ Personal = 0x08,
+ /**
+ * Fields about the organization, such as Business Address fields, Department,
+ * Profession, etc.
+ */
+ Organization = 0x10,
+ /**
+ * Custom (user-defined) fields
+ */
+ CustomCategory = 0x20
+ };
+
+ /**
+ * Returns the translated label for this field.
+ */
+ virtual QString label();
+
+ /**
+ * Returns the ored categories the field belongs to.
+ */
+ virtual int category();
+
+ /**
+ * Returns the translated label for @p category.
+ *
+ * @param category the category of type FieldCategory
+ * @return the translated label
+ */
+ static QString categoryLabel(int category);
+
+ /**
+ * Returns a string representation of the value the field has in the given
+ * Addressee.
+ *
+ * @return the string representation of the value or QString(), if it
+ * is not possible to convert the value to a string.
+ */
+ virtual QString value(const KContacts::Addressee &addressee);
+
+ /**
+ * Sets the value of the field in the given Addressee.
+ *
+ * @return @c true on success or @c false, if the given string couldn't
+ * be converted to a valid value.
+ */
+ virtual bool setValue(KContacts::Addressee &addressee, const QString &value);
+
+ /**
+ * Returns a string, that can be used for sorting.
+ */
+ QString sortKey(const KContacts::Addressee &addressee);
+
+ /**
+ * Returns, if the field is a user-defined field.
+ *
+ * @return @c true if this is a custom field, @c false otherwise
+ */
+ virtual bool isCustom();
+
+ /**
+ * Returns, if the field is equal with @p field.
+ *
+ * @param field the field to compare this field to
+ * @return @c true if the fields are equal, @c false otherwise
+ */
+ virtual bool equals(Field *field);
+
+ /**
+ * Returns a list of all fields.
+ */
+ static Field::List allFields();
+
+ /**
+ * Returns a list of the default fields.
+ */
+ static Field::List defaultFields();
+
+ /**
+ * Creates a custom field.
+ *
+ * @param label The label for this field
+ * @param category The category of this field
+ * @param key Unique key for this field
+ * @param app Unique app name for this field
+ */
+ static Field *createCustomField(const QString &label, int category,
+ const QString &key, const QString &app);
+
+ /**
+ * Delete all fields from list.
+ */
+ static void deleteFields();
+
+ /**
+ * Save the field settings to a config file.
+ *
+ * @param cfg The config file object
+ * @param identifier The unique identifier
+ * @param fields The list of the fields
+ */
+ static void saveFields(KConfigGroup &cfg, const QString &identifier,
+ const Field::List &fields);
+ /**
+ * @overload
+ *
+ * Here, the list is stored in KSharedConfig::openConfig() in group "KABCFields".
+ *
+ * @param identifier The unique identifier
+ * @param fields The list of the fields
+ */
+ static void saveFields(const QString &identifier,
+ const Field::List &fields);
+
+ /**
+ * Load the field settings from a config file.
+ *
+ * @param cfg The config file object
+ * @param identifier The unique identifier
+ */
+ static Field::List restoreFields(const KConfigGroup &cfg, const QString &identifier);
+
+ /**
+ * @overload
+ *
+ * Here, the list is loaded from KSharedConfig::openConfig() from group "KABCFields".
+ *
+ * @param identifier The unique identifier
+ */
+ static Field::List restoreFields(const QString &identifier);
+
+protected:
+ /**
+ * @internal
+ *
+ * Creates a field and appends it to the general list of fields.
+ *
+ * @param id The identifier for the field
+ * @param category The optional category for the field
+ */
+ static void createField(int id, int category = 0);
+
+ /**
+ * @internal
+ *
+ * Creates a field and appends it to the list of default fields.
+ *
+ * @param id The identifier for the field
+ * @param category The optional category for the field
+ */
+ static void createDefaultField(int id, int category = 0);
+
+private:
+ class Private;
+
+ Field(Private *p);
+ virtual ~Field();
+
+ Private *const d;
+};
+
+}
+#endif
--- /dev/null
+/*
+ This file is part of the KContacts framework.
+ Copyright (c) 2015 Laurent Montel <montel@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "gender.h"
+
+#include <QMap>
+#include <qstringlist.h>
+
+using namespace KContacts;
+
+class Q_DECL_HIDDEN Gender::Private : public QSharedData
+{
+public:
+ Private()
+ {
+ }
+
+ Private(const Private &other)
+ : QSharedData(other)
+ {
+ comment = other.comment;
+ gender = other.gender;
+ }
+ QString gender;
+ QString comment;
+};
+
+Gender::Gender()
+ : d(new Private)
+{
+
+}
+
+Gender::Gender(const QString &gender)
+ : d(new Private)
+{
+ d->gender = gender;
+}
+
+Gender::Gender(const Gender &other)
+ : d(other.d)
+{
+}
+
+Gender::~Gender()
+{
+
+}
+
+bool Gender::operator==(const Gender &other) const
+{
+ return (d->comment == other.comment()) && (d->gender == other.gender());
+}
+
+bool Gender::operator!=(const Gender &other) const
+{
+ return !(other == *this);
+}
+
+Gender &Gender::operator=(const Gender &other)
+{
+ if (this != &other) {
+ d = other.d;
+ }
+
+ return *this;
+}
+
+QString Gender::toString() const
+{
+ QString str;
+ str += QLatin1String("Gender {\n");
+ str += QStringLiteral(" gender: %1\n").arg(d->gender);
+ str += QStringLiteral(" comment: %1\n").arg(d->comment);
+ str += QLatin1String("}\n");
+ return str;
+}
+
+void Gender::setGender(const QString &gender)
+{
+ d->gender = gender;
+}
+
+QString Gender::gender() const
+{
+ return d->gender;
+}
+
+void Gender::setComment(const QString &comment)
+{
+ d->comment = comment;
+}
+
+QString Gender::comment() const
+{
+ return d->comment;
+}
+
+bool Gender::isValid() const
+{
+ return !d->gender.isEmpty() || !d->comment.isEmpty();
+}
+
+QDataStream &KContacts::operator<<(QDataStream &s, const Gender &gender)
+{
+ return s << gender.d->comment << gender.d->gender;
+}
+
+QDataStream &KContacts::operator>>(QDataStream &s, Gender &gender)
+{
+ s >> gender.d->comment >> gender.d->gender;
+ return s;
+}
+
--- /dev/null
+/*
+ This file is part of the KContacts framework.
+ Copyright (c) 2015 Laurent Montel <montel@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef GENDER_H
+#define GENDER_H
+#include "kcontacts_export.h"
+#include <QtCore/QSharedDataPointer>
+#include <QtCore/QString>
+
+/** @short Class that holds a Gender for a contact.
+ * @since 4.14.5
+ */
+
+namespace KContacts
+{
+
+class KCONTACTS_EXPORT Gender
+{
+ friend KCONTACTS_EXPORT QDataStream &operator<<(QDataStream &, const Gender &);
+ friend KCONTACTS_EXPORT QDataStream &operator>>(QDataStream &, Gender &);
+public:
+ /**
+ * Creates an empty Gender object.
+ */
+ Gender();
+ Gender(const Gender &other);
+ Gender(const QString &gender);
+
+ ~Gender();
+
+ void setGender(const QString &gender);
+ QString gender() const;
+
+ void setComment(const QString &comment);
+ QString comment() const;
+
+ bool isValid() const;
+
+ bool operator==(const Gender &other) const;
+ bool operator!=(const Gender &other) const;
+
+ Gender &operator=(const Gender &other);
+
+ QString toString() const;
+private:
+ class Private;
+ QSharedDataPointer<Private> d;
+};
+
+KCONTACTS_EXPORT QDataStream &operator<<(QDataStream &stream, const Gender &object);
+
+KCONTACTS_EXPORT QDataStream &operator>>(QDataStream &stream, Gender &object);
+}
+Q_DECLARE_TYPEINFO(KContacts::Gender, Q_MOVABLE_TYPE);
+#endif // GENDER_H
--- /dev/null
+/*
+ This file is part of the KContacts framework.
+ Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "geo.h"
+
+#include <QtCore/QDataStream>
+#include <QtCore/QSharedData>
+
+using namespace KContacts;
+
+class Q_DECL_HIDDEN Geo::Private : public QSharedData
+{
+public:
+ Private()
+ : mLatitude(91), mLongitude(181),
+ mValidLatitude(false), mValidLongitude(false)
+ {
+ }
+
+ Private(const Private &other)
+ : QSharedData(other)
+ {
+ mLatitude = other.mLatitude;
+ mLongitude = other.mLongitude;
+ mValidLatitude = other.mValidLatitude;
+ mValidLongitude = other.mValidLongitude;
+ }
+
+ float mLatitude;
+ float mLongitude;
+
+ bool mValidLatitude;
+ bool mValidLongitude;
+};
+
+Geo::Geo()
+ : d(new Private)
+{
+}
+
+Geo::Geo(float latitude, float longitude)
+ : d(new Private)
+{
+ setLatitude(latitude);
+ setLongitude(longitude);
+}
+
+Geo::Geo(const Geo &other)
+ : d(other.d)
+{
+}
+
+Geo::~Geo()
+{
+}
+
+void Geo::setLatitude(float latitude)
+{
+ if (latitude >= -90 && latitude <= 90) {
+ d->mLatitude = latitude;
+ d->mValidLatitude = true;
+ } else {
+ d->mLatitude = 91;
+ d->mValidLatitude = false;
+ }
+}
+
+float Geo::latitude() const
+{
+ return d->mLatitude;
+}
+
+void Geo::setLongitude(float longitude)
+{
+ if (longitude >= -180 && longitude <= 180) {
+ d->mLongitude = longitude;
+ d->mValidLongitude = true;
+ } else {
+ d->mLongitude = 181;
+ d->mValidLongitude = false;
+ }
+}
+
+float Geo::longitude() const
+{
+ return d->mLongitude;
+}
+
+bool Geo::isValid() const
+{
+ return d->mValidLatitude && d->mValidLongitude;
+}
+
+bool Geo::operator==(const Geo &other) const
+{
+ if (!other.isValid() && !isValid()) {
+ return true;
+ }
+
+ if (!other.isValid() || !isValid()) {
+ return false;
+ }
+
+ if (other.d->mLatitude == d->mLatitude && other.d->mLongitude == d->mLongitude) {
+ return true;
+ }
+
+ return false;
+}
+
+bool Geo::operator!=(const Geo &other) const
+{
+ return !(*this == other);
+}
+
+Geo &Geo::operator=(const Geo &other)
+{
+ if (this != &other) {
+ d = other.d;
+ }
+
+ return *this;
+}
+
+QString Geo::toString() const
+{
+ QString str;
+
+ str += QLatin1String("Geo {\n");
+ str += QStringLiteral(" Valid: %1\n").
+ arg(isValid() ? QStringLiteral("true") : QStringLiteral("false"));
+ str += QStringLiteral(" Latitude: %1\n").arg(d->mLatitude);
+ str += QStringLiteral(" Longitude: %1\n").arg(d->mLongitude);
+ str += QLatin1String("}\n");
+
+ return str;
+}
+
+void Geo::clear()
+{
+ d->mValidLatitude = false;
+ d->mValidLongitude = false;
+}
+
+QDataStream &KContacts::operator<<(QDataStream &s, const Geo &geo)
+{
+ return s << geo.d->mLatitude << geo.d->mValidLatitude
+ << geo.d->mLongitude << geo.d->mValidLongitude;
+}
+
+QDataStream &KContacts::operator>>(QDataStream &s, Geo &geo)
+{
+ s >> geo.d->mLatitude >> geo.d->mValidLatitude
+ >> geo.d->mLongitude >> geo.d->mValidLongitude;
+
+ return s;
+}
--- /dev/null
+/*
+ This file is part of the KContacts framework.
+ Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KCONTACTS_GEO_H
+#define KCONTACTS_GEO_H
+
+#include "kcontacts_export.h"
+#include <QtCore/QSharedDataPointer>
+#include <QtCore/QString>
+
+namespace KContacts
+{
+
+/**
+ * @short Geographic position
+ *
+ * This class represents a geographic position.
+ */
+class KCONTACTS_EXPORT Geo
+{
+ friend KCONTACTS_EXPORT QDataStream &operator<<(QDataStream &, const Geo &);
+ friend KCONTACTS_EXPORT QDataStream &operator>>(QDataStream &, Geo &);
+
+public:
+ /**
+ * Creates an invalid geographics position object.
+ */
+ Geo();
+
+ /**
+ * Creates a geographics position object.
+ *
+ * @param latitude Geographical latitude
+ * @param longitude Geographical longitude
+ */
+ Geo(float latitude, float longitude);
+
+ /**
+ * Copy constructor.
+ */
+ Geo(const Geo &other);
+
+ /**
+ * Destroys the geographics position object.
+ */
+ ~Geo();
+
+ /**
+ * Sets the @p latitude.
+ *
+ * @param latitude The location's latitude coordinate
+ */
+ void setLatitude(float latitude);
+
+ /**
+ * Returns the latitude.
+ */
+ float latitude() const;
+
+ /**
+ * Sets the @p longitude.
+ *
+ * @param longitude The location's longitude coordinate
+ */
+ void setLongitude(float longitude);
+
+ /**
+ * Returns the longitude.
+ */
+ float longitude() const;
+
+ /**
+ * Returns, whether this object contains a valid geographical position.
+ */
+ bool isValid() const;
+
+ /**
+ * Equality operator.
+ *
+ * @note Two invalid Geo instance will return @c true
+ */
+ bool operator==(const Geo &other) const;
+
+ /**
+ * Not-Equal operator.
+ */
+ bool operator!=(const Geo &other) const;
+
+ /**
+ * Assignment operator.
+ *
+ * @param other The Geo instance to assign to @c this
+ */
+ Geo &operator=(const Geo &other);
+
+ /**
+ * Returns string representation of geographical position.
+ */
+ QString toString() const;
+
+ /**
+ * Clears the class, marking it as invalid.
+ *
+ * @since 5.6
+ */
+ void clear();
+
+private:
+ class Private;
+ QSharedDataPointer<Private> d;
+};
+
+/**
+ * Serializes the geographical position @p object into the @p stream.
+ */
+KCONTACTS_EXPORT QDataStream &operator<<(QDataStream &stream, const Geo &object);
+
+/**
+ * Initializes the geographical position @p object from the @p stream.
+ */
+KCONTACTS_EXPORT QDataStream &operator>>(QDataStream &stream, Geo &object);
+}
+Q_DECLARE_TYPEINFO(KContacts::Geo, Q_MOVABLE_TYPE);
+#endif
--- /dev/null
+/*
+ This file is part of libkabc.
+ Copyright (c) 2015 Laurent Montel <montel@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "impp.h"
+
+#include <QMap>
+#include <qstringlist.h>
+#include <QDataStream>
+#include "kcontacts_debug.h"
+
+using namespace KContacts;
+
+class Q_DECL_HIDDEN Impp::Private : public QSharedData
+{
+public:
+ Private()
+ : type(KContacts::Impp::Unknown)
+ {
+ }
+
+ Private(const Private &other)
+ : QSharedData(other)
+ {
+ parameters = other.parameters;
+ type = other.type;
+ }
+ QMap<QString, QStringList> parameters;
+ QString address;
+ ImppType type;
+};
+
+Impp::Impp()
+ : d(new Private)
+{
+
+}
+
+Impp::Impp(const Impp &other)
+ : d(other.d)
+{
+}
+
+Impp::Impp(const QString &address)
+ : d(new Private)
+{
+ d->address = address;
+}
+
+Impp::~Impp()
+{
+
+}
+
+bool Impp::isValid() const
+{
+ return !d->address.isEmpty() && (d->type != Unknown);
+}
+
+Impp::ImppType Impp::type() const
+{
+ return d->type;
+}
+
+void Impp::setType(Impp::ImppType type)
+{
+ d->type = type;
+}
+
+void Impp::setAddress(const QString &address)
+{
+ d->address = address;
+}
+
+QString Impp::address() const
+{
+ return d->address;
+}
+
+void Impp::setParameters(const QMap<QString, QStringList> ¶ms)
+{
+ d->parameters = params;
+}
+
+QMap<QString, QStringList> Impp::parameters() const
+{
+ return d->parameters;
+}
+
+bool Impp::operator==(const Impp &other) const
+{
+ return (d->parameters == other.parameters()) && (d->address == other.address()) && (d->type == other.type());
+}
+
+bool Impp::operator!=(const Impp &other) const
+{
+ return !(other == *this);
+}
+
+Impp &Impp::operator=(const Impp &other)
+{
+ if (this != &other) {
+ d = other.d;
+ }
+
+ return *this;
+}
+
+QString Impp::toString() const
+{
+ QString str;
+ str += QLatin1String("Impp {\n");
+ str += QStringLiteral(" type: %1\n").arg(typeToString(d->type));
+ str += QStringLiteral(" address: %1\n").arg(d->address);
+ if (!d->parameters.isEmpty()) {
+ QMapIterator<QString, QStringList> i(d->parameters);
+ QString param;
+ while (i.hasNext()) {
+ i.next();
+ param += QStringLiteral("%1 %2").arg(i.key(), i.value().join(QStringLiteral(",")));
+ }
+ str += QStringLiteral(" parameters: %1\n").arg(param);
+ }
+ str += QLatin1String("}\n");
+ return str;
+}
+
+QString Impp::typeToString(ImppType type)
+{
+ switch (type) {
+ case Unknown:
+ case EndList:
+ qCWarning(KCONTACTS_LOG) << "Invalid type requested";
+ break;
+ case Skype:
+ return QStringLiteral("skype");
+ case Xmpp:
+ return QStringLiteral("xmpp");
+ case Jabber:
+ return QStringLiteral("jabber");
+ case Sip:
+ return QStringLiteral("sip");
+ case Aim:
+ return QStringLiteral("aim");
+ case Msn:
+ return QStringLiteral("msn");
+ case Twitter:
+ return QStringLiteral("twitter");
+ case GoogleTalk:
+ return QStringLiteral("googletalk");
+ case Yahoo:
+ return QStringLiteral("yahoo");
+ case Qq:
+ return QStringLiteral("qq");
+ case GaduGadu:
+ return QStringLiteral("gadugadu");
+ case Ownclound:
+ return QStringLiteral("owncloud-handle");
+ case Facebook:
+ return QStringLiteral("facebook");
+ case Icq:
+ return QStringLiteral("icq");
+ }
+ return QString();
+}
+
+QDataStream &KContacts::operator<<(QDataStream &s, const Impp &impp)
+{
+ return s << impp.d->parameters << impp.d->address << impp.d->type;
+}
+
+QDataStream &KContacts::operator>>(QDataStream &s, Impp &impp)
+{
+ int i;
+ s >> impp.d->parameters >> impp.d->address >> i;
+ impp.d->type = static_cast<Impp::ImppType>(i);
+ return s;
+}
+
--- /dev/null
+/*
+ This file is part of libkabc.
+ Copyright (c) 2015 Laurent Montel <montel@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef IMPP_H
+#define IMPP_H
+
+#include "kcontacts_export.h"
+#include <QtCore/QSharedDataPointer>
+#include <QtCore/QString>
+#include <QtCore/QMap>
+
+/** @short Class that holds a IMPP for a contact.
+ * @since 4.14.5
+ */
+namespace KContacts
+{
+class KCONTACTS_EXPORT Impp
+{
+ friend KCONTACTS_EXPORT QDataStream &operator<<(QDataStream &, const Impp &);
+ friend KCONTACTS_EXPORT QDataStream &operator>>(QDataStream &, Impp &);
+public:
+ Impp();
+ Impp(const Impp &other);
+ Impp(const QString &address);
+
+ ~Impp();
+
+ typedef QVector<Impp> List;
+ enum ImppType {
+ Unknown = 0,
+ Skype = 1,
+ Xmpp = 2,
+ Jabber = 3,
+ Sip = 4,
+ Aim = 5,
+ Msn = 6,
+ Twitter = 7,
+ GoogleTalk = 8,
+ Yahoo = 9,
+ Qq = 10,
+ GaduGadu = 11,
+ Ownclound = 12,
+ Icq = 13,
+ Facebook = 14,
+ EndList
+ };
+ bool isValid() const;
+
+ ImppType type() const;
+ void setType(ImppType type);
+
+ void setAddress(const QString &address);
+ QString address() const;
+
+ void setParameters(const QMap<QString, QStringList> ¶ms);
+ QMap<QString, QStringList> parameters() const;
+
+ bool operator==(const Impp &other) const;
+ bool operator!=(const Impp &other) const;
+
+ Impp &operator=(const Impp &other);
+
+ QString toString() const;
+
+ static QString typeToString(ImppType type);
+
+private:
+ class Private;
+ QSharedDataPointer<Private> d;
+};
+
+KCONTACTS_EXPORT QDataStream &operator<<(QDataStream &stream, const Impp &object);
+
+KCONTACTS_EXPORT QDataStream &operator>>(QDataStream &stream, Impp &object);
+
+}
+
+Q_DECLARE_TYPEINFO(KContacts::Impp, Q_MOVABLE_TYPE);
+#endif // IMPP_H
--- /dev/null
+/*
+ This file is part of the KContacts framework.
+ Copyright (c) 2002 Tobias Koenig <tokoe@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "key.h"
+
+#include <klocalizedstring.h>
+#include <krandom.h>
+
+#include <QtCore/QDataStream>
+#include <QtCore/QSharedData>
+
+using namespace KContacts;
+
+class Q_DECL_HIDDEN Key::Private : public QSharedData
+{
+public:
+ Private()
+ : mId(KRandom::randomString(8))
+ {
+ }
+
+ Private(const Private &other)
+ : QSharedData(other)
+ {
+ mId = other.mId;
+ mBinaryData = other.mBinaryData;
+ mTextData = other.mTextData;
+ mCustomTypeString = other.mCustomTypeString;
+ mIsBinary = other.mIsBinary;
+ mType = other.mType;
+ }
+
+ QString mId;
+ QByteArray mBinaryData;
+ QString mTextData;
+ QString mCustomTypeString;
+
+ Type mType;
+ bool mIsBinary;
+};
+
+Key::Key(const QString &text, Type type)
+ : d(new Private)
+{
+ d->mTextData = text;
+ d->mIsBinary = false;
+ d->mType = type;
+}
+
+Key::Key(const Key &other)
+ : d(other.d)
+{
+}
+
+Key::~Key()
+{
+}
+
+bool Key::operator==(const Key &other) const
+{
+ if (d->mId != other.d->mId) {
+ return false;
+ }
+
+ if (d->mType != other.d->mType) {
+ return false;
+ }
+
+ if (d->mIsBinary != other.d->mIsBinary) {
+ return false;
+ }
+
+ if (d->mIsBinary) {
+ if (d->mBinaryData != other.d->mBinaryData) {
+ return false;
+ }
+ } else {
+ if (d->mTextData != other.d->mTextData) {
+ return false;
+ }
+ }
+
+ if (d->mCustomTypeString != other.d->mCustomTypeString) {
+ return false;
+ }
+
+ return true;
+}
+
+bool Key::operator!=(const Key &other) const
+{
+ return !(*this == other);
+}
+
+Key &Key::operator=(const Key &other)
+{
+ if (this != &other) {
+ d = other.d;
+ }
+
+ return *this;
+}
+
+void Key::setId(const QString &id)
+{
+ d->mId = id;
+}
+
+QString Key::id() const
+{
+ return d->mId;
+}
+
+void Key::setBinaryData(const QByteArray &binary)
+{
+ d->mBinaryData = binary;
+ d->mIsBinary = true;
+}
+
+QByteArray Key::binaryData() const
+{
+ return d->mBinaryData;
+}
+
+void Key::setTextData(const QString &text)
+{
+ d->mTextData = text;
+ d->mIsBinary = false;
+}
+
+QString Key::textData() const
+{
+ return d->mTextData;
+}
+
+bool Key::isBinary() const
+{
+ return d->mIsBinary;
+}
+
+void Key::setType(Type type)
+{
+ d->mType = type;
+}
+
+void Key::setCustomTypeString(const QString &custom)
+{
+ d->mCustomTypeString = custom;
+}
+
+Key::Type Key::type() const
+{
+ return d->mType;
+}
+
+QString Key::customTypeString() const
+{
+ return d->mCustomTypeString;
+}
+
+QString Key::toString() const
+{
+ QString str;
+
+ str += QLatin1String("Key {\n");
+ str += QStringLiteral(" Id: %1\n").arg(d->mId);
+ str += QStringLiteral(" Type: %1\n").arg(typeLabel(d->mType));
+ if (d->mType == Custom) {
+ str += QStringLiteral(" CustomType: %1\n").arg(d->mCustomTypeString);
+ }
+ str += QStringLiteral(" IsBinary: %1\n").
+ arg(d->mIsBinary ? QStringLiteral("true") : QStringLiteral("false"));
+ if (d->mIsBinary) {
+ str += QStringLiteral(" Binary: %1\n").
+ arg(QString::fromLatin1(d->mBinaryData.toBase64()));
+ } else {
+ str += QStringLiteral(" Text: %1\n").arg(d->mTextData);
+ }
+ str += QLatin1String("}\n");
+
+ return str;
+}
+
+Key::TypeList Key::typeList()
+{
+ static TypeList list;
+
+ if (list.isEmpty()) {
+ list << X509 << PGP << Custom;
+ }
+
+ return list;
+}
+
+QString Key::typeLabel(Type type)
+{
+ switch (type) {
+ case X509:
+ return i18nc("X.509 public key", "X509");
+ break;
+ case PGP:
+ return i18nc("Pretty Good Privacy key", "PGP");
+ break;
+ case Custom:
+ return i18nc("A custom key", "Custom");
+ break;
+ default:
+ return i18nc("another type of encryption key", "Unknown type");
+ break;
+ }
+}
+
+QDataStream &KContacts::operator<<(QDataStream &s, const Key &key)
+{
+ return s << key.d->mId << key.d->mType << key.d->mIsBinary << key.d->mBinaryData
+ << key.d->mTextData << key.d->mCustomTypeString;
+}
+
+QDataStream &KContacts::operator>>(QDataStream &s, Key &key)
+{
+ uint type;
+ s >> key.d->mId >> type >> key.d->mIsBinary >> key.d->mBinaryData >> key.d->mTextData
+ >> key.d->mCustomTypeString;
+
+ key.d->mType = Key::Type(type);
+
+ return s;
+}
--- /dev/null
+/*
+ This file is part of the KContacts framework.
+ Copyright (c) 2002 Tobias Koenig <tokoe@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KCONTACTS_KEY_H
+#define KCONTACTS_KEY_H
+
+#include "kcontacts_export.h"
+
+#include <QtCore/QDataStream>
+#include <QtCore/QSharedDataPointer>
+
+namespace KContacts
+{
+
+/**
+ * @short A class to store an encryption key.
+ */
+class KCONTACTS_EXPORT Key
+{
+ friend KCONTACTS_EXPORT QDataStream &operator<<(QDataStream &, const Key &);
+ friend KCONTACTS_EXPORT QDataStream &operator>>(QDataStream &, Key &);
+
+public:
+ /**
+ List of keys.
+ */
+ typedef QVector<Key> List;
+
+ /**
+ Key types
+ */
+ enum Type {
+ X509, /**< X509 key */
+ PGP, /**< Pretty Good Privacy key */
+ Custom /**< Custom or IANA conform key */
+ };
+
+ /**
+ List of key types.
+ */
+ typedef QList<Type> TypeList;
+
+ /**
+ Creates a new key.
+
+ @param text The text data.
+ @param type The key type, see Types.
+ */
+ explicit Key(const QString &text = QString(), Type type = PGP);
+
+ /**
+ Copy constructor.
+ */
+ Key(const Key &other);
+
+ /**
+ Destroys the key.
+ */
+ ~Key();
+
+ /**
+ Equality operator.
+ */
+ bool operator==(const Key &other) const;
+
+ /**
+ Not-equal operator.
+ */
+ bool operator!=(const Key &other) const;
+
+ /**
+ Assignment operator.
+
+ @param other The Key instance to assign to @c this
+ */
+ Key &operator=(const Key &other);
+
+ /**
+ Sets the unique @p identifier.
+ */
+ void setId(const QString &identifier);
+
+ /**
+ Returns the unique identifier.
+ */
+ QString id() const;
+
+ /**
+ Sets binary @p data.
+ */
+ void setBinaryData(const QByteArray &data);
+
+ /**
+ Returns the binary data.
+ */
+ QByteArray binaryData() const;
+
+ /**
+ Sets text @p data.
+ */
+ void setTextData(const QString &data);
+
+ /**
+ Returns the text data.
+ */
+ QString textData() const;
+
+ /**
+ Returns whether the key contains binary or text data.
+ */
+ bool isBinary() const;
+
+ /**
+ Sets the @p type.
+
+ @param type The type of the key
+
+ @see Type
+ */
+ void setType(Type type);
+
+ /**
+ Sets custom @p type string.
+ */
+ void setCustomTypeString(const QString &type);
+
+ /**
+ Returns the type, see Type.
+ */
+ Type type() const;
+
+ /**
+ Returns the custom type string.
+ */
+ QString customTypeString() const;
+
+ /**
+ Returns a string representation of the key.
+ */
+ QString toString() const;
+
+ /**
+ Returns a list of all available key types.
+ */
+ static TypeList typeList();
+
+ /**
+ Returns a translated label for a given key @p type.
+ */
+ static QString typeLabel(Type type);
+
+private:
+ class Private;
+ QSharedDataPointer<Private> d;
+};
+
+/**
+ Serializes the @p key object into the @p stream.
+*/
+KCONTACTS_EXPORT QDataStream &operator<<(QDataStream &stream, const Key &key);
+
+/**
+ Initializes the @p key object from the @p stream.
+*/
+KCONTACTS_EXPORT QDataStream &operator>>(QDataStream &stream, Key &key);
+
+}
+Q_DECLARE_TYPEINFO(KContacts::Key, Q_MOVABLE_TYPE);
+#endif
--- /dev/null
+/*
+ This file is part of the KContacts framework.
+ Copyright (c) 2015 Laurent Montel <montel@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "lang.h"
+#include <QMap>
+#include <qstringlist.h>
+#include <QDataStream>
+
+using namespace KContacts;
+
+class Q_DECL_HIDDEN Lang::Private : public QSharedData
+{
+public:
+ Private()
+ {
+ }
+
+ Private(const Private &other)
+ : QSharedData(other)
+ {
+ parameters = other.parameters;
+ language = other.language;
+ }
+ QMap<QString, QStringList> parameters;
+ QString language;
+};
+
+Lang::Lang()
+ : d(new Private)
+{
+
+}
+
+Lang::Lang(const Lang &other)
+ : d(other.d)
+{
+
+}
+
+Lang::Lang(const QString &language)
+ : d(new Private)
+{
+ d->language = language;
+}
+
+Lang::~Lang()
+{
+
+}
+
+void Lang::setLanguage(const QString &lang)
+{
+ d->language = lang;
+}
+
+QString Lang::language() const
+{
+ return d->language;
+}
+
+bool Lang::isValid() const
+{
+ return !d->language.isEmpty();
+}
+
+void Lang::setParameters(const QMap<QString, QStringList> ¶ms)
+{
+ d->parameters = params;
+}
+
+QMap<QString, QStringList> Lang::parameters() const
+{
+ return d->parameters;
+}
+
+bool Lang::operator==(const Lang &other) const
+{
+ return (d->parameters == other.parameters()) && (d->language == other.language());
+}
+
+bool Lang::operator!=(const Lang &other) const
+{
+ return !(other == *this);
+}
+
+Lang &Lang::operator=(const Lang &other)
+{
+ if (this != &other) {
+ d = other.d;
+ }
+
+ return *this;
+}
+
+QString Lang::toString() const
+{
+ QString str;
+ str += QLatin1String("Lang {\n");
+ str += QStringLiteral(" language: %1\n").arg(d->language);
+ if (!d->parameters.isEmpty()) {
+ QMapIterator<QString, QStringList> i(d->parameters);
+ QString param;
+ while (i.hasNext()) {
+ i.next();
+ param += QStringLiteral("%1 %2").arg(i.key(), i.value().join(QStringLiteral(",")));
+ }
+ str += QStringLiteral(" parameters: %1\n").arg(param);
+ }
+ str += QLatin1String("}\n");
+ return str;
+}
+
+QDataStream &KContacts::operator<<(QDataStream &s, const Lang &lang)
+{
+ return s << lang.d->parameters << lang.d->language;
+}
+
+QDataStream &KContacts::operator>>(QDataStream &s, Lang &lang)
+{
+ s >> lang.d->parameters >> lang.d->language;
+ return s;
+}
--- /dev/null
+/*
+ This file is part of the KContacts framework.
+ Copyright (c) 2015 Laurent Montel <montel@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef LANG_H
+#define LANG_H
+
+#include "kcontacts_export.h"
+#include <QtCore/QSharedDataPointer>
+#include <QtCore/QString>
+#include <QtCore/QMap>
+
+/** @short Class that holds a Language for a contact.
+ * @since 4.14.5
+ */
+namespace KContacts
+{
+class KCONTACTS_EXPORT Lang
+{
+ friend KCONTACTS_EXPORT QDataStream &operator<<(QDataStream &, const Lang &);
+ friend KCONTACTS_EXPORT QDataStream &operator>>(QDataStream &, Lang &);
+public:
+ Lang();
+ Lang(const Lang &other);
+ Lang(const QString &language);
+
+ ~Lang();
+
+ typedef QVector<Lang> List;
+
+ void setLanguage(const QString &lang);
+ QString language() const;
+
+ bool isValid() const;
+
+ void setParameters(const QMap<QString, QStringList> ¶ms);
+ QMap<QString, QStringList> parameters() const;
+
+ bool operator==(const Lang &other) const;
+ bool operator!=(const Lang &other) const;
+
+ Lang &operator=(const Lang &other);
+
+ QString toString() const;
+private:
+ class Private;
+ QSharedDataPointer<Private> d;
+};
+KCONTACTS_EXPORT QDataStream &operator<<(QDataStream &stream, const Lang &object);
+
+KCONTACTS_EXPORT QDataStream &operator>>(QDataStream &stream, Lang &object);
+
+}
+Q_DECLARE_TYPEINFO(KContacts::Lang, Q_MOVABLE_TYPE);
+#endif // LANG_H
--- /dev/null
+/*
+ A temporary copy to break dependency to KLDAP
+
+ This file is part of libkldap.
+ Copyright (c) 2006 Sean Harmer <sh@theharmers.co.uk>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "ldapdn_p.h"
+
+#include <algorithm>
+
+#include "kcontacts_debug.h"
+
+class Q_DECL_HIDDEN LdapDN::LdapDNPrivate
+{
+public:
+ LdapDNPrivate() : m_dn() {}
+ ~LdapDNPrivate() {}
+
+ bool isValidRDNString(const QString &rdn) const;
+ QStringList splitOnNonEscapedChar(const QString &rdn, QChar ch) const;
+
+ QString m_dn;
+};
+
+bool LdapDN::LdapDNPrivate::isValidRDNString(const QString &rdn) const
+{
+ qCDebug(KCONTACTS_LOG) << "Testing rdn:" << rdn;
+
+ // If it is a muli-valued rdn, split it into its constituent parts
+ QStringList rdnParts = splitOnNonEscapedChar(rdn, QLatin1Char('+'));
+ if (rdnParts.size() > 1) {
+ for (int i = 0; i < rdnParts.size(); i++) {
+ if (!isValidRDNString(rdnParts.at(i))) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ // Split the rdn into the attribute name and value parts
+ const QStringList components = rdn.split(QLatin1Char('='));
+
+ // We should have exactly two parts
+ if (components.size() != 2) {
+ return false;
+ }
+
+ return true;
+}
+
+QStringList LdapDN::LdapDNPrivate::splitOnNonEscapedChar(const QString &str, QChar ch) const
+{
+ QStringList strParts;
+ int index = 0;
+ int searchFrom = 0;
+ int strPartStartIndex = 0;
+ while ((index = str.indexOf(ch, searchFrom)) != -1) {
+ const QChar prev = str[std::max(0, index - 1)];
+ if (prev != QLatin1Char('\\')) {
+ // Found a component of a multi-valued RDN
+ //qCDebug(KCONTACTS_LOG) << "Found" << ch << "at index" << index;
+ QString tmp = str.mid(strPartStartIndex, index - strPartStartIndex);
+ //qCDebug(KCONTACTS_LOG) << "Adding part:" << tmp;
+ strParts.append(tmp);
+ strPartStartIndex = index + 1;
+ }
+
+ searchFrom = index + 1;
+ }
+
+ // Add on the part after the last found delimeter
+ QString tmp = str.mid(strPartStartIndex);
+ //qCDebug(KCONTACTS_LOG) << "Adding part:" << tmp;
+ strParts.append(tmp);
+
+ return strParts;
+}
+
+LdapDN::LdapDN()
+ : d(new LdapDNPrivate)
+{
+
+}
+
+LdapDN::LdapDN(const QString &dn)
+ : d(new LdapDNPrivate)
+{
+ d->m_dn = dn;
+}
+
+LdapDN::LdapDN(const LdapDN &that)
+ : d(new LdapDNPrivate)
+{
+ *d = *that.d;
+}
+
+LdapDN &LdapDN::operator=(const LdapDN &that)
+{
+ if (this == &that) {
+ return *this;
+ }
+
+ *d = *that.d;
+ return *this;
+}
+
+LdapDN::~LdapDN()
+{
+ delete d;
+}
+
+void LdapDN::clear()
+{
+ d->m_dn.clear();
+}
+
+bool LdapDN::isEmpty() const
+{
+ return d->m_dn.isEmpty();
+}
+
+QString LdapDN::toString() const
+{
+ return d->m_dn;
+}
+
+QString LdapDN::toString(int depth) const
+{
+ QStringList rdns = d->splitOnNonEscapedChar(d->m_dn, QLatin1Char(','));
+ if (depth >= rdns.size()) {
+ return QString();
+ }
+
+ // Construct a DN down to the requested depth
+ QString dn;
+ for (int i = depth; i >= 0; i--) {
+ dn += rdns.at(rdns.size() - 1 - i) + QLatin1Char(',');
+ qCDebug(KCONTACTS_LOG) << "dn =" << dn;
+ }
+ dn = dn.left(dn.length() - 1); // Strip off the extraneous comma
+
+ return dn;
+}
+
+QString LdapDN::rdnString() const
+{
+ /** \TODO We should move this into the d pointer as we calculate rdns quite a lot */
+ QStringList rdns = d->splitOnNonEscapedChar(d->m_dn, QLatin1Char(','));
+ return rdns.at(0);
+}
+
+QString LdapDN::rdnString(int depth) const
+{
+ QStringList rdns = d->splitOnNonEscapedChar(d->m_dn, QLatin1Char(','));
+ if (depth >= rdns.size()) {
+ return QString();
+ }
+ return rdns.at(rdns.size() - 1 - depth);
+}
+
+bool LdapDN::isValid() const
+{
+ qCDebug(KCONTACTS_LOG) << "Testing dn:" << d->m_dn;
+
+ // Break the string into rdn's
+ QStringList rdns = d->splitOnNonEscapedChar(d->m_dn, QLatin1Char(','));
+
+ // Test to see if each rdn is valid
+ for (int i = 0; i < rdns.size(); i++) {
+ if (!d->isValidRDNString(rdns.at(i))) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+int LdapDN::depth() const
+{
+ QStringList rdns = d->splitOnNonEscapedChar(d->m_dn, QLatin1Char(','));
+ return rdns.size();
+}
+
+bool LdapDN::operator == (const LdapDN &rhs) const
+{
+ return d->m_dn == rhs.d->m_dn;
+}
+
+bool LdapDN::operator != (const LdapDN &rhs) const
+{
+ return d->m_dn != rhs.d->m_dn;
+}
--- /dev/null
+/*
+ A temporary copy to break dependency to KLDAP
+
+ This file is part of libkldap.
+ Copyright (c) 2006 Sean Harmer <sh@theharmers.co.uk>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef LDAPDN_P_H
+#define LDAPDN_P_H
+
+#include <QtCore/QStringList>
+
+class LdapDN
+{
+public:
+ explicit LdapDN();
+ explicit LdapDN(const QString &dn);
+
+ LdapDN(const LdapDN &that);
+ LdapDN &operator=(const LdapDN &that);
+
+ ~LdapDN();
+
+ void clear();
+
+ bool isEmpty() const;
+
+ /**
+ * \returns A QString representing the DN.
+ */
+ QString toString() const;
+
+ /**
+ * \param depth The depth of the DN to return using a zero-based index.
+ * \returns A QString representing the DN levels deep in the directory.
+ */
+ QString toString(int depth) const;
+
+ /**
+ * \returns A QString representing the RDN of this DN.
+ */
+ QString rdnString() const;
+
+ /**
+ * \param depth The depth of the RDN to return using a zero-based index.
+ * \returns A QString representing the RDN levels deep in the directory.
+ */
+ QString rdnString(int depth) const;
+
+ /**
+ * \returns True if this is a valid DN, false otherwise.
+ */
+ bool isValid() const;
+
+ /**
+ * \returns The depth of this DN in the directory.
+ */
+ int depth() const;
+
+ bool operator==(const LdapDN &rhs) const;
+
+ bool operator!=(const LdapDN &rhs) const;
+
+private:
+ class LdapDNPrivate;
+ LdapDNPrivate *const d;
+};
+
+#endif
--- /dev/null
+/*
+ A temporary copy to break dependency to KLDAP
+
+ This file is part of libkldap.
+ Copyright (c) 2004-2006 Szombathelyi György <gyurco@freemail.hu>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "ldif_p.h"
+
+#include "kcontacts_debug.h"
+
+class Q_DECL_HIDDEN Ldif::LdifPrivate
+{
+public:
+ int mModType;
+ bool mDelOldRdn, mUrl;
+ LdapDN mDn;
+ QString mAttr, mNewRdn, mNewSuperior, mOid;
+ QByteArray mLdif, mValue;
+ EntryType mEntryType;
+
+ bool mIsNewLine, mIsComment, mCritical;
+ ParseValue mLastParseValue;
+ uint mPos, mLineNumber;
+ QByteArray mLine;
+};
+
+Ldif::Ldif() : d(new LdifPrivate)
+{
+ startParsing();
+}
+
+Ldif::Ldif(const Ldif &that) : d(new LdifPrivate)
+{
+ *d = *that.d;
+
+ startParsing();
+}
+
+Ldif &Ldif::operator=(const Ldif &that)
+{
+ if (this == &that) {
+ return *this;
+ }
+
+ *d = *that.d;
+
+ return *this;
+}
+
+Ldif::~Ldif()
+{
+ delete d;
+}
+
+QByteArray Ldif::assembleLine(const QString &fieldname,
+ const QByteArray &value,
+ uint linelen, bool url)
+{
+ bool safe = false;
+ bool isDn;
+ QByteArray result;
+
+ if (url) {
+ result = fieldname.toUtf8() + ":< " + value;
+ } else {
+ isDn = fieldname.toLower() == QLatin1String("dn");
+ //SAFE-INIT-CHAR
+ if (value.size() > 0 && value[0] > 0 && value[0] != '\n' &&
+ value[0] != '\r' && value[0] != ':' && value[0] != '<') {
+ safe = true;
+ }
+
+ //SAFE-CHAR
+ if (safe) {
+ for (int i = 1; i < value.size(); ++i) {
+ //allow utf-8 in Distinguished Names
+ if ((isDn && value[i] == 0) ||
+ (!isDn && value[i] <= 0) ||
+ value[i] == '\r' || value[i] == '\n') {
+ safe = false;
+ break;
+ }
+ }
+ }
+
+ if (value.size() == 0) {
+ safe = true;
+ }
+
+ if (safe) {
+ result = fieldname.toUtf8() + ": " + value;
+ } else {
+ result = fieldname.toUtf8() + ":: " + value.toBase64();
+ }
+
+ if (linelen > 0) {
+ int i = (uint)(fieldname.length() + 2) > linelen ? fieldname.length() + 2 : linelen;
+ while (i < result.length()) {
+ result.insert(i, "\n ");
+ i += linelen + 2;
+ }
+ }
+ }
+ return result;
+}
+
+QByteArray Ldif::assembleLine(const QString &fieldname, const QString &value,
+ uint linelen, bool url)
+{
+ return assembleLine(fieldname, value.toUtf8(), linelen, url);
+}
+
+bool Ldif::splitLine(const QByteArray &line, QString &fieldname, QByteArray &value)
+{
+ int position;
+ QByteArray tmp;
+ int linelen;
+
+// qCDebug(KCONTACTS_LOG) << "line:" << QString::fromUtf8(line);
+
+ position = line.indexOf(":");
+ if (position == -1) {
+ // strange: we did not find a fieldname
+ fieldname = QLatin1String("");
+ value = line.trimmed();
+// qCDebug(KCONTACTS_LOG) << "value :" << value[0];
+ return false;
+ }
+
+ linelen = line.size();
+ fieldname = QString::fromUtf8(line.left(position).trimmed());
+
+ if (linelen > (position + 1) && line[ position + 1 ] == ':') {
+ // String is BASE64 encoded -> decode it now.
+ if (linelen <= (position + 3)) {
+ value.resize(0);
+ return false;
+ }
+ value = QByteArray::fromBase64(line.mid(position + 3));
+ return false;
+ }
+
+ if (linelen > (position + 1) && line[ position + 1 ] == '<') {
+ // String is an URL.
+ if (linelen <= (position + 3)) {
+ value.resize(0);
+ return false;
+ }
+ value = QByteArray::fromBase64(line.mid(position + 3));
+ return true;
+ }
+
+ if (linelen <= (position + 2)) {
+ value.resize(0);
+ return false;
+ }
+ value = line.mid(position + 2);
+ return false;
+}
+
+bool Ldif::splitControl(const QByteArray &line, QString &oid, bool &critical,
+ QByteArray &value)
+{
+ QString tmp;
+ critical = false;
+ bool url = splitLine(line, tmp, value);
+
+ qCDebug(KCONTACTS_LOG) << "value:" << QString::fromUtf8(value);
+ if (tmp.isEmpty()) {
+ tmp = QString::fromUtf8(value);
+ value.resize(0);
+ }
+ if (tmp.endsWith(QLatin1String("true"))) {
+ critical = true;
+ tmp.truncate(tmp.length() - 5);
+ } else if (tmp.endsWith(QLatin1String("false"))) {
+ critical = false;
+ tmp.truncate(tmp.length() - 6);
+ }
+ oid = tmp;
+ return url;
+}
+
+Ldif::ParseValue Ldif::processLine()
+{
+
+ if (d->mIsComment) {
+ return None;
+ }
+
+ ParseValue retval = None;
+ if (d->mLastParseValue == EndEntry) {
+ d->mEntryType = Entry_None;
+ }
+
+ d->mUrl = splitLine(d->mLine, d->mAttr, d->mValue);
+
+ QString attrLower = d->mAttr.toLower();
+
+ switch (d->mEntryType) {
+ case Entry_None:
+ if (attrLower == QLatin1String("version")) {
+ if (!d->mDn.isEmpty()) {
+ retval = Err;
+ }
+ } else if (attrLower == QLatin1String("dn")) {
+ qCDebug(KCONTACTS_LOG) << "ldapentry dn:" << QString::fromUtf8(d->mValue);
+ d->mDn = LdapDN(QString::fromUtf8(d->mValue));
+ d->mModType = Mod_None;
+ retval = NewEntry;
+ } else if (attrLower == QLatin1String("changetype")) {
+ if (d->mDn.isEmpty()) {
+ retval = Err;
+ } else {
+ QString tmpval = QString::fromUtf8(d->mValue);
+ qCDebug(KCONTACTS_LOG) << "changetype:" << tmpval;
+ if (tmpval == QLatin1String("add")) {
+ d->mEntryType = Entry_Add;
+ } else if (tmpval == QLatin1String("delete")) {
+ d->mEntryType = Entry_Del;
+ } else if (tmpval == QLatin1String("modrdn") || tmpval == QLatin1String("moddn")) {
+ d->mNewRdn = QLatin1String("");
+ d->mNewSuperior = QLatin1String("");
+ d->mDelOldRdn = true;
+ d->mEntryType = Entry_Modrdn;
+ } else if (tmpval == QLatin1String("modify")) {
+ d->mEntryType = Entry_Mod;
+ } else {
+ retval = Err;
+ }
+ }
+ } else if (attrLower == QLatin1String("control")) {
+ d->mUrl = splitControl(d->mValue, d->mOid, d->mCritical, d->mValue);
+ retval = Control;
+ } else if (!d->mAttr.isEmpty() && d->mValue.size() > 0) {
+ d->mEntryType = Entry_Add;
+ retval = Item;
+ }
+ break;
+ case Entry_Add:
+ if (d->mAttr.isEmpty() && d->mValue.size() == 0) {
+ retval = EndEntry;
+ } else {
+ retval = Item;
+ }
+ break;
+ case Entry_Del:
+ if (d->mAttr.isEmpty() && d->mValue.size() == 0) {
+ retval = EndEntry;
+ } else {
+ retval = Err;
+ }
+ break;
+ case Entry_Mod:
+ if (d->mModType == Mod_None) {
+ qCDebug(KCONTACTS_LOG) << "new modtype" << d->mAttr;
+ if (d->mAttr.isEmpty() && d->mValue.size() == 0) {
+ retval = EndEntry;
+ } else if (attrLower == QLatin1String("add")) {
+ d->mModType = Mod_Add;
+ } else if (attrLower == QLatin1String("replace")) {
+ d->mModType = Mod_Replace;
+ d->mAttr = QString::fromUtf8(d->mValue);
+ d->mValue = QByteArray();
+ retval = Item;
+ } else if (attrLower == QLatin1String("delete")) {
+ d->mModType = Mod_Del;
+ d->mAttr = QString::fromUtf8(d->mValue);
+ d->mValue = QByteArray();
+ retval = Item;
+ } else {
+ retval = Err;
+ }
+ } else {
+ if (d->mAttr.isEmpty()) {
+ if (QString::fromUtf8(d->mValue) == QLatin1String("-")) {
+ d->mModType = Mod_None;
+ } else if (d->mValue.size() == 0) {
+ retval = EndEntry;
+ } else {
+ retval = Err;
+ }
+ } else {
+ retval = Item;
+ }
+ }
+ break;
+ case Entry_Modrdn:
+ if (d->mAttr.isEmpty() && d->mValue.size() == 0) {
+ retval = EndEntry;
+ } else if (attrLower == QLatin1String("newrdn")) {
+ d->mNewRdn = QString::fromUtf8(d->mValue);
+ } else if (attrLower == QLatin1String("newsuperior")) {
+ d->mNewSuperior = QString::fromUtf8(d->mValue);
+ } else if (attrLower == QLatin1String("deleteoldrdn")) {
+ if (d->mValue.size() > 0 && d->mValue[0] == '0') {
+ d->mDelOldRdn = false;
+ } else if (d->mValue.size() > 0 && d->mValue[0] == '1') {
+ d->mDelOldRdn = true;
+ } else {
+ retval = Err;
+ }
+ } else {
+ retval = Err;
+ }
+ break;
+ }
+ return retval;
+}
+
+Ldif::ParseValue Ldif::nextItem()
+{
+ ParseValue retval = None;
+ char c = 0;
+
+ while (retval == None) {
+ if (d->mPos < (uint)d->mLdif.size()) {
+ c = d->mLdif[d->mPos];
+ d->mPos++;
+ if (d->mIsNewLine && c == '\r') {
+ continue; //handle \n\r line end
+ }
+ if (d->mIsNewLine && (c == ' ' || c == '\t')) { //line folding
+ d->mIsNewLine = false;
+ continue;
+ }
+ if (d->mIsNewLine) {
+ d->mIsNewLine = false;
+ retval = processLine();
+ d->mLastParseValue = retval;
+ d->mLine.resize(0);
+ d->mIsComment = (c == '#');
+ }
+ if (c == '\n' || c == '\r') {
+ d->mLineNumber++;
+ d->mIsNewLine = true;
+ continue;
+ }
+ } else {
+ retval = MoreData;
+ break;
+ }
+
+ if (!d->mIsComment) {
+ d->mLine += c;
+ }
+ }
+ return retval;
+}
+
+void Ldif::endLdif()
+{
+ QByteArray tmp(3, '\n');
+ d->mLdif = tmp;
+ d->mPos = 0;
+}
+
+void Ldif::startParsing()
+{
+ d->mPos = d->mLineNumber = 0;
+ d->mDelOldRdn = false;
+ d->mEntryType = Entry_None;
+ d->mModType = Mod_None;
+ d->mDn = LdapDN();
+ d->mNewRdn.clear();
+ d->mNewSuperior.clear();
+ d->mLine = QByteArray();
+ d->mIsNewLine = false;
+ d->mIsComment = false;
+ d->mLastParseValue = None;
+}
+
+void Ldif::setLdif(const QByteArray &ldif)
+{
+ d->mLdif = ldif;
+ d->mPos = 0;
+}
+
+Ldif::EntryType Ldif::entryType() const
+{
+ return d->mEntryType;
+}
+
+int Ldif::modType() const
+{
+ return d->mModType;
+}
+
+LdapDN Ldif::dn() const
+{
+ return d->mDn;
+}
+
+QString Ldif::newRdn() const
+{
+ return d->mNewRdn;
+}
+
+QString Ldif::newSuperior() const
+{
+ return d->mNewSuperior;
+}
+
+bool Ldif::delOldRdn() const
+{
+ return d->mDelOldRdn;
+}
+
+QString Ldif::attr() const
+{
+ return d->mAttr;
+}
+
+QByteArray Ldif::value() const
+{
+ return d->mValue;
+}
+
+bool Ldif::isUrl() const
+{
+ return d->mUrl;
+}
+
+bool Ldif::isCritical() const
+{
+ return d->mCritical;
+}
+
+QString Ldif::oid() const
+{
+ return d->mOid;
+}
+
+uint Ldif::lineNumber() const
+{
+ return d->mLineNumber;
+}
--- /dev/null
+/*
+ A temporary copy to break dependency to KLDAP
+
+ This file is part of libkldap.
+ Copyright (c) 2004-2006 Szombathelyi György <gyurco@freemail.hu>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef LDIF_P_H
+#define LDIF_P_H
+
+#include <QtCore/QString>
+#include <QtCore/QByteArray>
+
+#include "ldapdn_p.h"
+
+/**
+ * Ldif
+ *
+ * Ldif implements an RFC 2849 compliant Ldif parser. Ldif files are used to
+ * represent directory information on LDAP-based servers, or to describe a set
+ * of changes which are to be applied to a directory.
+ */
+class Ldif
+{
+public:
+
+ typedef enum {
+ None, NewEntry, EndEntry, Item, Control, Err, MoreData
+ } ParseValue;
+
+ typedef enum {
+ Entry_None, Entry_Add, Entry_Del, Entry_Mod, Entry_Modrdn
+ } EntryType;
+
+ typedef enum {
+ Mod_None, Mod_Add, Mod_Replace, Mod_Del
+ } ModType;
+
+ Ldif();
+
+ Ldif(const Ldif &that);
+ Ldif &operator=(const Ldif &that);
+
+ virtual ~Ldif();
+
+ /**
+ * Assembles fieldname and value into a valid Ldif line, BASE64 encodes the
+ * value if necessary and optionally splits into more lines.
+ * @param fieldname The name of the entry.
+ * @param value The value of the entry.
+ * @param linelen Maximum length of the lines in the result.
+ * @param url If true, encode value as url ( use :< ).
+ */
+ static QByteArray assembleLine(const QString &fieldname,
+ const QByteArray &value, uint linelen = 0,
+ bool url = false);
+ /**
+ * This is the same as the above function, the only difference that
+ * this accepts QString as the value.
+ */
+ static QByteArray assembleLine(const QString &fieldname,
+ const QString &value, uint linelen = 0,
+ bool url = false);
+
+ /**
+ * Splits one line from an Ldif file to attribute and value components.
+ * @return true if value is an URL, false otherwise
+ */
+ static bool splitLine(const QByteArray &line, QString &fieldname,
+ QByteArray &value);
+
+ /**
+ * Splits a control specification (without the "control:" directive)
+ * @param line is the control directive
+ * @param oid will contain the OID
+ * @param critical will contain the criticality of control
+ * @param value is the control value
+ */
+ static bool splitControl(const QByteArray &line, QString &oid,
+ bool &critical, QByteArray &value);
+
+ /**
+ * Starts the parsing of a new Ldif
+ */
+ void startParsing();
+
+ /**
+ * Process one Ldif line
+ */
+ ParseValue processLine();
+
+ /**
+ * Process the Ldif until a complete item can be returned
+ * @return NewEntry if a new DN encountered, Item if a new item returned,
+ * Err if the Ldif contains error, EndEntry if the parser reached the end
+ * of the current entry and MoreData if the parser encountered the end of
+ * the current chunk of the Ldif.
+ *
+ * If you want to finish the parsing after receiving MoreData, then call
+ * endLdif(), so the parser can safely flush the current entry.
+ */
+ ParseValue nextItem();
+
+ /**
+ * Sets a chunk of Ldif. Call before startParsing(), or if nextItem()
+ * returned MoreData.
+ */
+ void setLdif(const QByteArray &ldif);
+
+ /**
+ * Indicates the end of the Ldif file/stream. Call if nextItem() returned
+ * MoreData, but actually you don't have more data.
+ */
+ void endLdif();
+
+ /**
+ * Returns the requested LDAP operation extracted from the current entry.
+ */
+ EntryType entryType() const;
+
+ /**
+ * Returns the LDAP modify request type if entryType() returned Entry_Mod.
+ */
+ int modType() const;
+
+ /**
+ * Returns the Distinguished Name of the current entry.
+ */
+ LdapDN dn() const;
+
+ /**
+ * Returns the new Relative Distinguished Name if modType() returned
+ * Entry_Modrdn.
+ */
+ QString newRdn() const;
+
+ /**
+ * Returns the new parent of the entry if modType() returned Entry_Modrdn.
+ */
+ QString newSuperior() const;
+
+ /**
+ * Returns if the delete of the old RDN is required.
+ */
+ bool delOldRdn() const;
+
+ /**
+ * Returns the attribute name.
+ */
+ QString attr() const;
+
+ /**
+ * Returns the attribute value.
+ */
+ QByteArray value() const;
+
+ /**
+ * Returns if val() is an url
+ */
+ bool isUrl() const;
+
+ /**
+ * Returns the criticality level when modType() returned Control.
+ */
+ bool isCritical() const;
+
+ /**
+ * Returns the OID when modType() returned Control.
+ */
+ QString oid() const;
+
+ /**
+ * Returns the line number which the parser processes.
+ */
+ uint lineNumber() const;
+
+private:
+ class LdifPrivate;
+ LdifPrivate *const d;
+};
+
+#endif
--- /dev/null
+/*
+ This file is part of the KContacts framework.
+ Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "phonenumber.h"
+
+#include <klocalizedstring.h>
+#include <krandom.h>
+
+#include <QtCore/QDataStream>
+#include <QtCore/QSharedData>
+
+using namespace KContacts;
+
+static QString cleanupNumber(const QString &input)
+{
+ return input.simplified();
+}
+
+class Q_DECL_HIDDEN PhoneNumber::Private : public QSharedData
+{
+public:
+ Private(Type type)
+ : mId(KRandom::randomString(8)), mType(type)
+ {
+ }
+
+ Private(const Private &other)
+ : QSharedData(other)
+ {
+ mId = other.mId;
+ mType = other.mType;
+ mNumber = other.mNumber;
+ }
+
+ QString mId;
+ QString mNumber;
+ Type mType;
+};
+
+PhoneNumber::PhoneNumber()
+ : d(new Private(Home))
+{
+}
+
+PhoneNumber::PhoneNumber(const QString &number, Type type)
+ : d(new Private(type))
+{
+ d->mNumber = cleanupNumber(number);
+}
+
+PhoneNumber::PhoneNumber(const PhoneNumber &other)
+ : d(other.d)
+{
+}
+
+PhoneNumber::~PhoneNumber()
+{
+}
+
+bool PhoneNumber::operator==(const PhoneNumber &other) const
+{
+ if (d->mId != other.d->mId) {
+ return false;
+ }
+
+ if (d->mNumber != other.d->mNumber) {
+ return false;
+ }
+
+ if (d->mType != other.d->mType) {
+ return false;
+ }
+
+ return true;
+}
+
+bool PhoneNumber::operator!=(const PhoneNumber &other) const
+{
+ return !(other == *this);
+}
+
+PhoneNumber &PhoneNumber::operator=(const PhoneNumber &other)
+{
+ if (this != &other) {
+ d = other.d;
+ }
+
+ return *this;
+}
+
+bool PhoneNumber::isEmpty() const
+{
+ return d->mNumber.isEmpty();
+}
+
+void PhoneNumber::setId(const QString &id)
+{
+ d->mId = id;
+}
+
+QString PhoneNumber::id() const
+{
+ return d->mId;
+}
+
+void PhoneNumber::setNumber(const QString &number)
+{
+ d->mNumber = cleanupNumber(number);
+}
+
+QString PhoneNumber::number() const
+{
+ return d->mNumber;
+}
+
+void PhoneNumber::setType(Type type)
+{
+ d->mType = type;
+}
+
+PhoneNumber::Type PhoneNumber::type() const
+{
+ return d->mType;
+}
+
+QString PhoneNumber::typeLabel() const
+{
+ return typeLabel(type());
+}
+
+PhoneNumber::TypeList PhoneNumber::typeList()
+{
+ static TypeList list;
+
+ if (list.isEmpty()) {
+ list << Home << Work << Msg << Pref << Voice << Fax << Cell << Video
+ << Bbs << Modem << Car << Isdn << Pcs << Pager << Undefined;
+ }
+
+ return list;
+}
+
+QString PhoneNumber::typeFlagLabel(TypeFlag type)
+{
+ switch (type) {
+ case Undefined:
+ return i18nc("Undefined phone type", "Telephone number");
+ case Home:
+ return i18nc("Home phone", "Home");
+ case Work:
+ return i18nc("Work phone", "Work");
+ case Msg:
+ return i18n("Messenger");
+ case Pref:
+ return i18nc("Preferred phone", "Preferred");
+ case Voice:
+ return i18n("Voice");
+ case Fax:
+ return i18n("Fax");
+ case Cell:
+ return i18nc("Mobile Phone", "Mobile");
+ case Video:
+ return i18nc("Video phone", "Video");
+ case Bbs:
+ return i18n("Mailbox");
+ case Modem:
+ return i18n("Modem");
+ case Car:
+ return i18nc("Car Phone", "Car");
+ case Isdn:
+ return i18n("ISDN");
+ case Pcs:
+ return i18n("PCS");
+ case Pager:
+ return i18n("Pager");
+ default:
+ return i18nc("another type of phone", "Other");
+ }
+}
+
+QString PhoneNumber::typeLabel(Type type)
+{
+ QString label;
+ bool first = true;
+
+ // special cases
+ // Pref stand alone -> Preferred Number
+ // Home+Fax or Work+Fax -> combine as initial string
+ if (type == Pref) {
+ return i18n("Preferred Number");
+ }
+
+ if (type & Fax) {
+ if (type & Home) {
+ label = i18n("Home Fax");
+ first = false;
+ type &= ~Fax;
+ type &= ~Home;
+ } else if (type & Work) {
+ label = i18n("Work Fax");
+ first = false;
+ type &= ~Fax;
+ type &= ~Work;
+ }
+ }
+
+ const TypeList list = typeList();
+
+ TypeList::ConstIterator it;
+ TypeList::ConstIterator end(list.end());
+ for (it = list.begin(); it != end; ++it) {
+ // these are actually flags
+ const TypeFlag flag = static_cast<TypeFlag>(static_cast<int>(*it));
+ if (type & flag) {
+ if (!first) {
+ label.append(QLatin1Char('/'));
+ }
+
+ label.append(typeFlagLabel(flag));
+
+ if (first) {
+ first = false;
+ }
+ }
+ }
+
+ return label;
+}
+
+QString PhoneNumber::toString() const
+{
+ QString str;
+
+ str += QLatin1String("PhoneNumber {\n");
+ str += QStringLiteral(" Id: %1\n").arg(d->mId);
+ str += QStringLiteral(" Type: %1\n").arg(typeLabel(d->mType));
+ str += QStringLiteral(" Number: %1\n").arg(d->mNumber);
+ str += QLatin1String("}\n");
+
+ return str;
+}
+
+QDataStream &KContacts::operator<<(QDataStream &s, const PhoneNumber &phone)
+{
+ return s << phone.d->mId << (uint)phone.d->mType << phone.d->mNumber;
+}
+
+QDataStream &KContacts::operator>>(QDataStream &s, PhoneNumber &phone)
+{
+ uint type;
+ s >> phone.d->mId >> type >> phone.d->mNumber;
+ phone.d->mType = PhoneNumber::Type(type);
+
+ return s;
+}
--- /dev/null
+/*
+ This file is part of the KContacts framework.
+ Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KCONTACTS_PHONENUMBER_H
+#define KCONTACTS_PHONENUMBER_H
+
+#include "kcontacts_export.h"
+
+#include <QtCore/QSharedDataPointer>
+#include <QtCore/QString>
+#include <QtCore/QVector>
+
+namespace KContacts
+{
+
+/**
+ * @short Phonenumber information.
+ *
+ * This class provides phone number information. A phone number is classified by
+ * a type. The following types are available, it's possible to use multiple types
+ * Types for a number by combining them through a logical or.
+*/
+class KCONTACTS_EXPORT PhoneNumber
+{
+ friend KCONTACTS_EXPORT QDataStream &operator<<(QDataStream &, const PhoneNumber &);
+ friend KCONTACTS_EXPORT QDataStream &operator>>(QDataStream &, PhoneNumber &);
+
+public:
+ /**
+ Phone number types.
+ */
+ enum TypeFlag {
+ Home = 1, /**< Home number */
+ Work = 2, /**< Office number */
+ Msg = 4, /**< Messaging */
+ Pref = 8, /**< Preferred number */
+ Voice = 16, /**< Voice */
+ Fax = 32, /**< Fax machine */
+ Cell = 64, /**< Cell phone */
+ Video = 128, /**< Video phone */
+ Bbs = 256, /**< Mailbox */
+ Modem = 512, /**< Modem */
+ Car = 1024, /**< Car phone */
+ Isdn = 2048, /**< ISDN connection */
+ Pcs = 4096, /**< Personal Communication Service*/
+ Pager = 8192, /**< Pager */
+ Undefined = 16384 /** Undefined number type */
+ };
+
+ Q_DECLARE_FLAGS(Type, TypeFlag)
+
+ /**
+ * List of phone number types.
+ */
+ typedef QVector<TypeFlag> TypeList;
+
+ /**
+ * List of phone numbers.
+ */
+ typedef QVector<PhoneNumber> List;
+
+ /**
+ * Creates an empty phone number object.
+ */
+ PhoneNumber();
+
+ /**
+ * Creates a phone number object.
+ *
+ * @param number Number
+ * @param type Type as defined in enum. Multiple types can be
+ * specified by combining them by a logical or.
+ */
+ PhoneNumber(const QString &number, Type type = Home); //krazy:exclude=explicit
+
+ /**
+ * Copy constructor.
+ *
+ * Fast operation, PhoneNumber's data is implicitly shared.
+ *
+ * @param other The PhoneNumber object to copy from
+ */
+ PhoneNumber(const PhoneNumber &other);
+
+ /**
+ * Destroys the phone number.
+ */
+ ~PhoneNumber();
+
+ /**
+ * Equality operator.
+ *
+ * @return @c true if number, type and identifier are equal,
+ * otherwise @c false
+ */
+ bool operator==(const PhoneNumber &other) const;
+
+ /**
+ * Not-Equal operator.
+ */
+ bool operator!=(const PhoneNumber &other) const;
+
+ /**
+ * Assignment operator.
+ *
+ * Fast operation, PhoneNumber's data is implicitly shared.
+ *
+ * @param other The PhoneNumber object to asssign to @c this
+ */
+ PhoneNumber &operator=(const PhoneNumber &other);
+
+ /**
+ * Returns true, if the phone number is empty.
+ */
+ bool isEmpty() const;
+
+ /**
+ * Sets the unique @p identifier.
+ */
+ void setId(const QString &identifier);
+
+ /**
+ * Returns the unique identifier.
+ */
+ QString id() const;
+
+ /**
+ * Sets the phone @p number.
+ */
+ void setNumber(const QString &number);
+
+ /**
+ * Returns the phone number.
+ */
+ QString number() const;
+
+ /**
+ * Sets the @p type.
+ * Multiple types can be specified by combining them by a logical or.
+ *
+ * @param type The #Type of the phone number
+ */
+ void setType(Type type);
+
+ /**
+ * Returns the type. Can be a multiple types combined by a logical or.
+ *
+ * @see #TypeFlag
+ * @see typeLabel()
+ */
+ Type type() const;
+
+ /**
+ * Returns a translated string of the address' type.
+ */
+ QString typeLabel() const;
+
+ /**
+ * Returns a list of all available types
+ */
+ static TypeList typeList();
+
+ /**
+ * Returns the translated label for phone number @p type.
+ *
+ * In opposite to typeFlagLabel( TypeFlag type ), it returns all types
+ * of the phone number concatenated by '/'.
+ *
+ * @param type An OR'ed combination of #TypeFlag
+ *
+ * @see type()
+ */
+ static QString typeLabel(Type type);
+
+ /**
+ * Returns the translated label for phone number @p type.
+ *
+ * @param type An OR'ed combination of #TypeFlag
+ *
+ * @see typeLabel()
+ * @since 4.5
+ */
+ static QString typeFlagLabel(TypeFlag type);
+
+ /**
+ * Returns a string representation of the phone number.
+ */
+ QString toString() const;
+
+private:
+ class Private;
+ QSharedDataPointer<Private> d;
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(PhoneNumber::Type)
+
+/**
+ * Serializes the phone @p number object into the @p stream.
+ *
+ * @param stream The stream to write into
+ * @param number The phone number object to serialize
+ */
+KCONTACTS_EXPORT QDataStream &operator<<(QDataStream &stream, const PhoneNumber &number);
+
+/**
+ * Initializes the phone @p number object from the @p stream.
+ *
+ * @param stream The stream to read from
+ * @param number The phone number object to deserialize into
+ */
+KCONTACTS_EXPORT QDataStream &operator>>(QDataStream &stream, const PhoneNumber &number);
+
+}
+Q_DECLARE_TYPEINFO(KContacts::PhoneNumber, Q_MOVABLE_TYPE);
+#endif
--- /dev/null
+/*
+ This file is part of the KContacts framework.
+ Copyright (c) 2002 Tobias Koenig <tokoe@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "picture.h"
+
+#include <QtCore/QBuffer>
+#include <QtCore/QSharedData>
+
+namespace KContacts
+{
+
+class PicturePrivate : public QSharedData
+{
+public:
+ PicturePrivate()
+ : mIntern(false)
+ {
+ }
+
+ PicturePrivate(const PicturePrivate &other)
+ : QSharedData(other)
+ {
+ mUrl = other.mUrl;
+ mType = other.mType;
+ mData = other.mData;
+ mIntern = other.mIntern;
+ }
+
+ QString mUrl;
+ QString mType;
+ mutable QImage mData;
+ mutable QByteArray mRawData;
+
+ bool mIntern;
+};
+
+}
+
+Q_GLOBAL_STATIC_WITH_ARGS(QSharedDataPointer<KContacts::PicturePrivate>, s_sharedEmpty, (new KContacts::PicturePrivate))
+
+using namespace KContacts;
+
+Picture::Picture()
+ : d(*s_sharedEmpty())
+{
+}
+
+Picture::Picture(const QString &url)
+ : d(new PicturePrivate)
+{
+ d->mUrl = url;
+}
+
+Picture::Picture(const QImage &data)
+ : d(new PicturePrivate)
+{
+ setData(data);
+}
+
+Picture::Picture(const Picture &other)
+ : d(other.d)
+{
+}
+
+Picture::~Picture()
+{
+}
+
+Picture &Picture::operator=(const Picture &other)
+{
+ if (this != &other) {
+ d = other.d;
+ }
+
+ return *this;
+}
+
+bool Picture::operator==(const Picture &p) const
+{
+ if (d->mIntern != p.d->mIntern) {
+ return false;
+ }
+
+ if (d->mType != p.d->mType) {
+ return false;
+ }
+
+ if (d->mIntern) {
+ if (!d->mData.isNull() && !p.d->mData.isNull()) {
+ if (d->mData != p.d->mData) {
+ return false;
+ }
+ } else if (!d->mRawData.isEmpty() && !p.d->mRawData.isEmpty()) {
+ if (d->mRawData != p.d->mRawData) {
+ return false;
+ }
+ } else if ((!d->mData.isNull() || !d->mRawData.isEmpty()) &&
+ (!p.d->mData.isNull() || !p.d->mRawData.isEmpty())) {
+ if (data() != p.data()) {
+ return false;
+ }
+ } else {
+ // if one picture is empty and the other is not
+ return false;
+ }
+ } else {
+ if (d->mUrl != p.d->mUrl) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool Picture::operator!=(const Picture &p) const
+{
+ return !(p == *this);
+}
+
+bool Picture::isEmpty() const
+{
+ return
+ ((d->mIntern == false && d->mUrl.isEmpty()) ||
+ (d->mIntern == true && d->mData.isNull() && d->mRawData.isEmpty()));
+}
+
+void Picture::setUrl(const QString &url)
+{
+ d->mUrl = url;
+ d->mType.clear();
+ d->mIntern = false;
+}
+
+void Picture::setUrl(const QString &url, const QString &type)
+{
+ d->mUrl = url;
+ d->mType = type;
+ d->mIntern = false;
+}
+
+void Picture::setData(const QImage &data)
+{
+ d->mRawData.clear();
+ d->mData = data;
+ d->mIntern = true;
+
+// set the type, the raw data will have when accessed through Picture::rawData()
+ if (!d->mData.hasAlphaChannel()) {
+ d->mType = QStringLiteral("jpeg");
+ } else {
+ d->mType = QStringLiteral("png");
+ }
+}
+
+void Picture::setRawData(const QByteArray &rawData, const QString &type)
+{
+ d->mRawData = rawData;
+ d->mType = type;
+ d->mData = QImage();
+ d->mIntern = true;
+}
+
+void Picture::setType(const QString &type)
+{
+ d->mType = type;
+}
+
+bool Picture::isIntern() const
+{
+ return d->mIntern;
+}
+
+QString Picture::url() const
+{
+ return d->mUrl;
+}
+
+QImage Picture::data() const
+{
+ if (d->mData.isNull() && !d->mRawData.isEmpty()) {
+ d->mData.loadFromData(d->mRawData);
+ }
+
+ return d->mData;
+}
+
+QByteArray Picture::rawData() const
+{
+ if (d->mRawData.isEmpty() && !d->mData.isNull()) {
+ QBuffer buffer(&d->mRawData);
+ buffer.open(QIODevice::WriteOnly);
+
+ // d->mType was already set accordingly by Picture::setData()
+ d->mData.save(&buffer, d->mType.toUpper().toLatin1().data());
+ }
+
+ return d->mRawData;
+}
+
+QString Picture::type() const
+{
+ return d->mType;
+}
+
+QString Picture::toString() const
+{
+ QString str;
+
+ str += QLatin1String("Picture {\n");
+ str += QStringLiteral(" Type: %1\n").arg(d->mType);
+ str += QStringLiteral(" IsIntern: %1\n").
+ arg(d->mIntern ? QStringLiteral("true") : QStringLiteral("false"));
+ if (d->mIntern) {
+ str += QStringLiteral(" Data: %1\n").arg(QString::fromLatin1(rawData().toBase64()));
+ } else {
+ str += QStringLiteral(" Url: %1\n").arg(d->mUrl);
+ }
+ str += QLatin1String("}\n");
+
+ return str;
+}
+
+QDataStream &KContacts::operator<<(QDataStream &s, const Picture &picture)
+{
+ return s << picture.d->mIntern << picture.d->mUrl << picture.d->mType << picture.data();
+}
+
+QDataStream &KContacts::operator>>(QDataStream &s, Picture &picture)
+{
+ s >> picture.d->mIntern >> picture.d->mUrl >> picture.d->mType >> picture.d->mData;
+
+ return s;
+}
--- /dev/null
+/*
+ This file is part of the KContacts framework.
+ Copyright (c) 2002 Tobias Koenig <tokoe@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KCONTACTS_PICTURE_H
+#define KCONTACTS_PICTURE_H
+
+#include "kcontacts_export.h"
+
+#include <QtCore/QDataStream>
+#include <QtCore/QString>
+#include <QtCore/QSharedDataPointer>
+#include <QImage>
+
+namespace KContacts
+{
+
+class PicturePrivate;
+
+/**
+ A class to store a picture of an addressee. It can store the data directly or
+ an url reference to a picture.
+*/
+class KCONTACTS_EXPORT Picture
+{
+ friend KCONTACTS_EXPORT QDataStream &operator<<(QDataStream &, const Picture &);
+ friend KCONTACTS_EXPORT QDataStream &operator>>(QDataStream &, Picture &);
+
+public:
+ /**
+ * Creates an empty picture.
+ */
+ Picture();
+
+ /**
+ * Creates a picture which points to the given url.
+ *
+ * @param url A URL that describes the location of the picture file.
+ */
+ Picture(const QString &url);
+
+ /**
+ * Creates a picture with the given data.
+ *
+ * @param data The raw data of the picture.
+ */
+ Picture(const QImage &data);
+
+ /**
+ * Copy constructor.
+ *
+ * Fast operation, Picture's data is implicitly shared.
+ *
+ * @param picture The Picture instance to copy from
+ */
+ Picture(const Picture &picture);
+
+ /**
+ * Destructor.
+ */
+ ~Picture();
+
+ typedef QVector<Picture> List;
+ /**
+ * Assignment operator
+ *
+ * Fast operation, Picture's data is implicitly shared.
+ *
+ * @param other The Picture instance to assign to @c this
+ */
+ Picture &operator=(const Picture &other);
+
+ /**
+ * Equality operator.
+ */
+ bool operator==(const Picture &other) const;
+
+ /**
+ * Not-Equal operator.
+ */
+ bool operator!=(const Picture &other) const;
+
+ /**
+ * Returns true, if the picture is empty.
+ */
+ bool isEmpty() const;
+
+ /**
+ * Sets a URL for the location of the picture file. When using this
+ * function, isIntern() will return 'false' until you use
+ * setData().
+ * This also clears the type, as it is unknown.
+ *
+ * @param url The location URL of the picture file.
+ */
+ void setUrl(const QString &url);
+
+ /**
+ * Sets a URL for the location of the picture file. When using this
+ * function, isIntern() will return 'false' until you use
+ * setData().
+ *
+ * @param url The location URL of the picture file.
+ * @param type The encoding format of the image, e.g. jpeg or png
+ * @since 4.10
+ */
+ void setUrl(const QString &url, const QString &type);
+
+ /**
+ * Sets the image data of the picture. When using this function,
+ * isIntern() will return 'true' until you use setUrl().
+ * This also sets type to "png" or "jpeg" depending
+ * on whether the image has an alpha channel or not.
+ *
+ * @param data The image data of the picture.
+ */
+ void setData(const QImage &data);
+
+ /**
+ * Sets the raw data of the picture. When using this function,
+ * isIntern() will return 'true' until you use setUrl().
+ *
+ * @param rawData The raw data of the picture.
+ * @param type The encoding format of the image, e.g. jpeg or png
+ * @since 4.10
+ */
+ void setRawData(const QByteArray &rawData, const QString &type);
+
+ /**
+ * Sets the type of the picture.
+ * @param type the picture's data type
+ * @deprecated type should only be set along with setRawData()
+ */
+ void KCONTACTS_DEPRECATED setType(const QString &type);
+
+ /**
+ * Returns whether the picture is described by a URL (extern) or
+ * by the raw data (intern).
+ * When this method returns 'true' you can use data() to
+ * get the raw data. Otherwise you can request the URL of this
+ * picture by url() and load the raw data from that location.
+ */
+ bool isIntern() const;
+
+ /**
+ * Returns the location URL of this picture.
+ */
+ QString url() const;
+
+ /**
+ * Returns the image data of this picture.
+ */
+ QImage data() const;
+
+ /**
+ * Returns the raw data of this picture.
+ *
+ * @since 4.10
+ */
+ QByteArray rawData() const;
+
+ /**
+ * Returns the type of this picture.
+ */
+ QString type() const;
+
+ /**
+ * Returns string representation of the picture.
+ */
+ QString toString() const;
+
+private:
+ QSharedDataPointer<PicturePrivate> d;
+};
+
+/**
+ * Serializes the @p picture object into the @p stream.
+ */
+KCONTACTS_EXPORT QDataStream &operator<<(QDataStream &stream, const Picture &picture);
+
+/**
+ * Initializes the @p picture object from the @p stream.
+ */
+KCONTACTS_EXPORT QDataStream &operator>>(QDataStream &stream, Picture &picture);
+
+}
+Q_DECLARE_TYPEINFO(KContacts::Picture, Q_MOVABLE_TYPE);
+#endif
--- /dev/null
+/*
+ This file is part of the KContacts framework.
+ Copyright (c) 2015 Laurent Montel <montel@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "related.h"
+#include <QMap>
+#include <qstringlist.h>
+#include <QDataStream>
+
+using namespace KContacts;
+
+class Q_DECL_HIDDEN Related::Private : public QSharedData
+{
+public:
+ Private()
+ {
+ }
+
+ Private(const Private &other)
+ : QSharedData(other)
+ {
+ parameters = other.parameters;
+ relatedTo = other.relatedTo;
+ }
+ QMap<QString, QStringList> parameters;
+ QString relatedTo;
+};
+
+Related::Related()
+ : d(new Private)
+{
+
+}
+
+Related::Related(const Related &other)
+ : d(other.d)
+{
+
+}
+
+Related::Related(const QString &relatedTo)
+ : d(new Private)
+{
+ d->relatedTo = relatedTo;
+}
+
+Related::~Related()
+{
+
+}
+
+void Related::setRelated(const QString &relatedTo)
+{
+ d->relatedTo = relatedTo;
+}
+
+QString Related::related() const
+{
+ return d->relatedTo;
+}
+
+bool Related::isValid() const
+{
+ return !d->relatedTo.isEmpty();
+}
+
+void Related::setParameters(const QMap<QString, QStringList> ¶ms)
+{
+ d->parameters = params;
+}
+
+QMap<QString, QStringList> Related::parameters() const
+{
+ return d->parameters;
+}
+
+bool Related::operator==(const Related &other) const
+{
+ return (d->parameters == other.parameters()) && (d->relatedTo == other.related());
+}
+
+bool Related::operator!=(const Related &other) const
+{
+ return !(other == *this);
+}
+
+Related &Related::operator=(const Related &other)
+{
+ if (this != &other) {
+ d = other.d;
+ }
+
+ return *this;
+}
+
+QString Related::toString() const
+{
+ QString str;
+ str += QLatin1String("Related {\n");
+ str += QStringLiteral(" relatedTo: %1\n").arg(d->relatedTo);
+ if (!d->parameters.isEmpty()) {
+ QMapIterator<QString, QStringList> i(d->parameters);
+ QString param;
+ while (i.hasNext()) {
+ i.next();
+ param += QStringLiteral("%1 %2").arg(i.key(), i.value().join(QStringLiteral(",")));
+ }
+ str += QStringLiteral(" parameters: %1\n").arg(param);
+ }
+ str += QLatin1String("}\n");
+ return str;
+}
+
+QDataStream &KContacts::operator<<(QDataStream &s, const Related &related)
+{
+ return s << related.d->parameters << related.d->relatedTo;
+}
+
+QDataStream &KContacts::operator>>(QDataStream &s, Related &related)
+{
+ s >> related.d->parameters >> related.d->relatedTo;
+ return s;
+}
--- /dev/null
+/*
+ This file is part of the KContacts framework.
+ Copyright (c) 2015 Laurent Montel <montel@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef RELATED_H
+#define RELATED_H
+
+#include "kcontacts_export.h"
+#include <QtCore/QSharedDataPointer>
+#include <QtCore/QString>
+#include <QtCore/QMap>
+
+namespace KContacts
+{
+class KCONTACTS_EXPORT Related
+{
+ friend KCONTACTS_EXPORT QDataStream &operator<<(QDataStream &, const Related &);
+ friend KCONTACTS_EXPORT QDataStream &operator>>(QDataStream &, Related &);
+public:
+ Related();
+ Related(const Related &other);
+ Related(const QString &related);
+
+ ~Related();
+
+ typedef QVector<Related> List;
+
+ void setRelated(const QString &relatedTo);
+ QString related() const;
+
+ bool isValid() const;
+
+ void setParameters(const QMap<QString, QStringList> ¶ms);
+ QMap<QString, QStringList> parameters() const;
+
+ bool operator==(const Related &other) const;
+ bool operator!=(const Related &other) const;
+
+ Related &operator=(const Related &other);
+
+ QString toString() const;
+private:
+ class Private;
+ QSharedDataPointer<Private> d;
+};
+KCONTACTS_EXPORT QDataStream &operator<<(QDataStream &stream, const Related &object);
+
+KCONTACTS_EXPORT QDataStream &operator>>(QDataStream &stream, Related &object);
+
+}
+Q_DECLARE_TYPEINFO(KContacts::Related, Q_MOVABLE_TYPE);
+#endif // LANG_H
--- /dev/null
+/*
+ This file is part of the KContacts framework.
+ Copyright (c) 2015 Laurent Montel <montel@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "resourcelocatorurl.h"
+#include <QMap>
+#include <QUrl>
+#include <QDataStream>
+#include <qstringlist.h>
+
+using namespace KContacts;
+
+class Q_DECL_HIDDEN ResourceLocatorUrl::Private : public QSharedData
+{
+public:
+ Private()
+ {
+ }
+
+ Private(const Private &other)
+ : QSharedData(other)
+ {
+ parameters = other.parameters;
+ url = other.url;
+ }
+ QMap<QString, QStringList> parameters;
+ QUrl url;
+};
+
+ResourceLocatorUrl::ResourceLocatorUrl()
+ : d(new Private)
+{
+}
+
+ResourceLocatorUrl::ResourceLocatorUrl(const ResourceLocatorUrl &other)
+ : d(other.d)
+{
+}
+
+ResourceLocatorUrl::~ResourceLocatorUrl()
+{
+
+}
+
+QMap<QString, QStringList> ResourceLocatorUrl::parameters() const
+{
+ return d->parameters;
+}
+
+bool ResourceLocatorUrl::operator==(const ResourceLocatorUrl &other) const
+{
+ return (d->parameters == other.parameters()) && (d->url == other.url());
+}
+
+bool ResourceLocatorUrl::operator!=(const ResourceLocatorUrl &other) const
+{
+ return !(other == *this);
+}
+
+ResourceLocatorUrl &ResourceLocatorUrl::operator=(const ResourceLocatorUrl &other)
+{
+ if (this != &other) {
+ d = other.d;
+ }
+
+ return *this;
+}
+
+QString ResourceLocatorUrl::toString() const
+{
+ QString str;
+ str += QLatin1String("ResourceLocatorUrl {\n");
+ str += QStringLiteral(" url: %1\n").arg(d->url.toString());
+ if (!d->parameters.isEmpty()) {
+ QMapIterator<QString, QStringList> i(d->parameters);
+ QString param;
+ while (i.hasNext()) {
+ i.next();
+ param += QStringLiteral("%1 %2").arg(i.key(), i.value().join(QStringLiteral(",")));
+ }
+ str += QStringLiteral(" parameters: %1\n").arg(param);
+ }
+ str += QLatin1String("}\n");
+ return str;
+}
+
+void ResourceLocatorUrl::setParameters(const QMap<QString, QStringList> ¶ms)
+{
+ d->parameters = params;
+}
+
+bool ResourceLocatorUrl::isValid() const
+{
+ return (d->url.isValid());
+}
+
+void ResourceLocatorUrl::setUrl(const QUrl &url)
+{
+ d->url = url;
+}
+
+QUrl ResourceLocatorUrl::url() const
+{
+ return d->url;
+}
+
+QDataStream &KContacts::operator<<(QDataStream &s, const ResourceLocatorUrl &calUrl)
+{
+ return s << calUrl.d->parameters << calUrl.d->url;
+}
+
+QDataStream &KContacts::operator>>(QDataStream &s, ResourceLocatorUrl &calUrl)
+{
+ s >> calUrl.d->parameters >> calUrl.d->url;
+ return s;
+}
+
--- /dev/null
+/*
+ This file is part of the KContacts framework.
+ Copyright (c) 2015 Laurent Montel <montel@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef RESOURCELOCATORURL_H
+#define RESOURCELOCATORURL_H
+
+#include "kcontacts_export.h"
+
+#include <QtCore/QSharedDataPointer>
+#include <QtCore/QString>
+#include <QtCore/QMap>
+class QUrl;
+/** @short Class that holds a Resource Locator
+ * @since 5.0
+ */
+
+namespace KContacts
+{
+
+class KCONTACTS_EXPORT ResourceLocatorUrl
+{
+ friend KCONTACTS_EXPORT QDataStream &operator<<(QDataStream &, const ResourceLocatorUrl &);
+ friend KCONTACTS_EXPORT QDataStream &operator>>(QDataStream &, ResourceLocatorUrl &);
+public:
+
+ ResourceLocatorUrl();
+ ResourceLocatorUrl(const ResourceLocatorUrl &other);
+
+ ~ResourceLocatorUrl();
+
+ typedef QVector<ResourceLocatorUrl> List;
+
+ bool isValid() const;
+
+ void setUrl(const QUrl &url);
+ QUrl url() const;
+
+ void setParameters(const QMap<QString, QStringList> ¶ms);
+ QMap<QString, QStringList> parameters() const;
+
+ bool operator==(const ResourceLocatorUrl &other) const;
+ bool operator!=(const ResourceLocatorUrl &other) const;
+
+ ResourceLocatorUrl &operator=(const ResourceLocatorUrl &other);
+
+ QString toString() const;
+private:
+ class Private;
+ QSharedDataPointer<Private> d;
+};
+
+KCONTACTS_EXPORT QDataStream &operator<<(QDataStream &stream, const ResourceLocatorUrl &object);
+
+KCONTACTS_EXPORT QDataStream &operator>>(QDataStream &stream, ResourceLocatorUrl &object);
+
+}
+Q_DECLARE_TYPEINFO(KContacts::ResourceLocatorUrl, Q_MOVABLE_TYPE);
+
+#endif // RESOURCELOCATORURL_H
--- /dev/null
+/*
+ This file is part of the KContacts framework.
+ Copyright (c) 2002 Tobias Koenig <tokoe@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "secrecy.h"
+
+#include <klocalizedstring.h>
+
+#include <QtCore/QDataStream>
+#include <QtCore/QSharedData>
+
+using namespace KContacts;
+
+class Q_DECL_HIDDEN Secrecy::PrivateData : public QSharedData
+{
+public:
+ PrivateData()
+ : mType(Secrecy::Invalid)
+ {
+ }
+
+ PrivateData(const PrivateData &other)
+ : QSharedData(other)
+ {
+ mType = other.mType;
+ }
+
+ Type mType;
+};
+
+Secrecy::Secrecy(Type type)
+ : d(new PrivateData)
+{
+ d->mType = type;
+}
+
+Secrecy::Secrecy(const Secrecy &other)
+ : d(other.d)
+{
+}
+
+Secrecy::~Secrecy()
+{
+}
+
+Secrecy &Secrecy::operator=(const Secrecy &other)
+{
+ if (this != &other) {
+ d = other.d;
+ }
+
+ return *this;
+}
+
+bool Secrecy::operator==(const Secrecy &other) const
+{
+ return d->mType == other.d->mType;
+}
+
+bool Secrecy::operator!=(const Secrecy &other) const
+{
+ return !(*this == other);
+}
+
+bool Secrecy::isValid() const
+{
+ return d->mType != Invalid;
+}
+
+void Secrecy::setType(Type type)
+{
+ d->mType = type;
+}
+
+Secrecy::Type Secrecy::type() const
+{
+ return d->mType;
+}
+
+Secrecy::TypeList Secrecy::typeList()
+{
+ static TypeList list;
+
+ if (list.isEmpty()) {
+ list << Public << Private << Confidential;
+ }
+
+ return list;
+}
+
+QString Secrecy::typeLabel(Type type)
+{
+ switch (type) {
+ case Public:
+ return i18nc("access is for everyone", "Public");
+ break;
+ case Private:
+ return i18nc("access is by owner only", "Private");
+ break;
+ case Confidential:
+ return i18nc("access is by owner and a controlled group", "Confidential");
+ break;
+ default:
+ return i18nc("unknown secrecy type", "Unknown type");
+ break;
+ }
+}
+
+QString Secrecy::toString() const
+{
+ QString str;
+
+ str += QLatin1String("Secrecy {\n");
+ str += QStringLiteral(" Type: %1\n").arg(typeLabel(d->mType));
+ str += QLatin1String("}\n");
+
+ return str;
+}
+
+QDataStream &KContacts::operator<<(QDataStream &s, const Secrecy &secrecy)
+{
+ return s << (uint)secrecy.d->mType;
+}
+
+QDataStream &KContacts::operator>>(QDataStream &s, Secrecy &secrecy)
+{
+ uint type;
+ s >> type;
+
+ switch (type) {
+ case 0:
+ secrecy.d->mType = Secrecy::Public;
+ break;
+ case 1:
+ secrecy.d->mType = Secrecy::Private;
+ break;
+ case 2:
+ secrecy.d->mType = Secrecy::Confidential;
+ break;
+ default:
+ secrecy.d->mType = Secrecy::Invalid;
+ break;
+ }
+
+ return s;
+}
--- /dev/null
+/*
+ This file is part of the KContacts framework.
+ Copyright (c) 2002 Tobias Koenig <tokoe@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KCONTACTS_SECRECY_H
+#define KCONTACTS_SECRECY_H
+
+#include "kcontacts_export.h"
+#include <QtCore/QVector>
+#include <QtCore/QSharedDataPointer>
+
+namespace KContacts
+{
+
+class KCONTACTS_EXPORT Secrecy
+{
+ friend KCONTACTS_EXPORT QDataStream &operator<<(QDataStream &, const Secrecy &);
+ friend KCONTACTS_EXPORT QDataStream &operator>>(QDataStream &, Secrecy &);
+
+public:
+ /**
+ * Secrecy types
+ *
+ * @li Public - for public access
+ * @li Private - only private access
+ * @li Confidential - access for confidential persons
+ */
+ enum Type {
+ Public,
+ Private,
+ Confidential,
+ Invalid
+ };
+
+ /**
+ * List of secrecy types.
+ */
+ typedef QVector<Type> TypeList;
+
+ /**
+ * Creates a new secrecy of the given type.
+ *
+ * @param type The secrecy type. @see Type
+ */
+ Secrecy(Type type = Invalid);
+
+ /**
+ * Copy constructor.
+ */
+ Secrecy(const Secrecy &other);
+
+ /**
+ * Destroys the secrecy.
+ */
+ ~Secrecy();
+
+ Secrecy &operator=(const Secrecy &other);
+
+ bool operator==(const Secrecy &other) const;
+ bool operator!=(const Secrecy &other) const;
+
+ /**
+ * Returns if the Secrecy object has a valid value.
+ */
+ bool isValid() const;
+
+ /**
+ * Sets the @p type.
+ *
+ * @param type The #Type of secrecy
+ */
+ void setType(Type type);
+
+ /**
+ * Returns the type.
+ */
+ Type type() const;
+
+ /**
+ * Returns a list of all available secrecy types.
+ */
+ static TypeList typeList();
+
+ /**
+ * Returns a translated label for a given secrecy @p type.
+ */
+ static QString typeLabel(Type type);
+
+ /**
+ * Returns a string representation of the secrecy.
+ */
+ QString toString() const;
+
+private:
+ class PrivateData;
+ QSharedDataPointer<PrivateData> d;
+};
+
+/**
+ * Serializes the @p secrecy object into the @p stream.
+ */
+KCONTACTS_EXPORT QDataStream &operator<<(QDataStream &stream, const Secrecy &secrecy);
+
+/**
+ * Initializes the @p secrecy object from the @p stream.
+ */
+KCONTACTS_EXPORT QDataStream &operator>>(QDataStream &stream, Secrecy &secrecy);
+
+}
+Q_DECLARE_TYPEINFO(KContacts::Secrecy, Q_MOVABLE_TYPE);
+#endif
--- /dev/null
+/*
+ This file is part of the KContacts framework.
+ Copyright (c) 2004 Tobias Koenig <tokoe@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "sortmode.h"
+#include "field.h"
+
+using namespace KContacts;
+
+SortMode::~SortMode()
+{
+}
+
+class Q_DECL_HIDDEN NameSortMode::Private
+{
+public:
+ NameType mNameType;
+ bool mAscendingOrder;
+};
+
+NameSortMode::NameSortMode()
+ : d(new Private)
+{
+ d->mNameType = FormattedName;
+ d->mAscendingOrder = true;
+}
+
+NameSortMode::NameSortMode(NameType type, bool ascending)
+ : d(new Private)
+{
+ d->mNameType = type;
+ d->mAscendingOrder = ascending;
+}
+
+NameSortMode::~NameSortMode()
+{
+ delete d;
+}
+
+bool NameSortMode::lesser(const KContacts::Addressee &first, const KContacts::Addressee &second) const
+{
+ bool lesser = false;
+
+ switch (d->mNameType) {
+ case FormattedName:
+ lesser = QString::localeAwareCompare(first.formattedName(), second.formattedName()) < 0;
+ break;
+ case FamilyName:
+ lesser = QString::localeAwareCompare(first.familyName(), second.familyName()) < 0;
+ break;
+ case GivenName:
+ lesser = QString::localeAwareCompare(first.givenName(), second.givenName()) < 0;
+ break;
+ default:
+ lesser = false;
+ break;
+ }
+
+ if (!d->mAscendingOrder) {
+ lesser = !lesser;
+ }
+
+ return lesser;
+}
+
+class Q_DECL_HIDDEN FieldSortMode::Private
+{
+public:
+ KContacts::Field *mField;
+ bool mAscendingOrder;
+};
+
+FieldSortMode::FieldSortMode(KContacts::Field *field, bool ascending)
+ : d(new Private)
+{
+ d->mField = field;
+ d->mAscendingOrder = ascending;
+}
+
+FieldSortMode::~FieldSortMode()
+{
+ delete d;
+}
+
+bool FieldSortMode::lesser(const KContacts::Addressee &first, const KContacts::Addressee &second) const
+{
+ if (!d->mField) {
+ return false;
+ } else {
+ bool lesser =
+ QString::localeAwareCompare(d->mField->value(first), d->mField->value(second)) < 0;
+ if (!d->mAscendingOrder) {
+ lesser = !lesser;
+ }
+
+ return lesser;
+ }
+}
--- /dev/null
+/*
+ This file is part of the KContacts framework.
+ Copyright (c) 2004 Tobias Koenig <tokoe@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KCONTACTS_SORTMODE_H
+#define KCONTACTS_SORTMODE_H
+
+#include "kcontacts_export.h"
+#include "addressee.h"
+
+namespace KContacts
+{
+
+class Field;
+
+/**
+ @short Sort method for sorting an addressee list.
+
+ This interface should be reimplemented by classes which shall act as
+ SortModes for KContacts::AddresseeList.
+*/
+class KCONTACTS_EXPORT SortMode
+{
+public:
+ virtual ~SortMode();
+
+ /**
+ Reimplement this method and return whether the first contact is 'smaller'
+ than the second.
+ */
+ virtual bool lesser(const KContacts::Addressee &first, const KContacts::Addressee &second) const = 0;
+};
+
+/**
+ @short Implements comparison by name.
+
+ This class implements a comparison of two Addressee objects by name.
+ */
+class KCONTACTS_EXPORT NameSortMode : public SortMode
+{
+public:
+ /**
+ Specifies which parts of the name are used for comparison.
+ */
+ enum NameType {
+ FormattedName, /**< use the formatted name, e.g. "John Doe" */
+ FamilyName, /**< use the last name, e.g. "Doe" */
+ GivenName /**< use the first name, e.g. "John" */
+ };
+
+ /**
+ Constructor.
+
+ Creates a NameSortMethod with FormattedName as name type set.
+ */
+ NameSortMode();
+
+ /**
+ Constructor.
+
+ Creates a NameSortMethod with the specified name type.
+
+ @param type The name type.
+ @param ascending if @c true, Addressee object are sorted in
+ ascending order; if @c false, objects are sorted in
+ descending order
+ */
+ explicit NameSortMode(NameType type, bool ascending = true);
+
+ virtual ~NameSortMode();
+
+ /**
+ Returns whether the first contact is 'smaller' then the second.
+ */
+ bool lesser(const KContacts::Addressee &first, const KContacts::Addressee &second) const Q_DECL_OVERRIDE;
+
+private:
+ class Private;
+ Private *const d;
+
+ Q_DISABLE_COPY(NameSortMode)
+};
+
+/**
+ @short Implements comparison by an arbitrary field.
+
+ This class implements a comparison of two Addressee objects by the
+ value of an arbitrary field.
+ */
+class KCONTACTS_EXPORT FieldSortMode : public SortMode
+{
+public:
+ /**
+ Constructor.
+
+ Creates a FieldSortMethod with the specified @p field.
+
+ @param field The field.
+ @param ascending if @c true, Addressee object are sorted in
+ ascending order; if @c false, objects are sorted in
+ descending order
+ */
+ explicit FieldSortMode(KContacts::Field *field, bool ascending = true);
+
+ virtual ~FieldSortMode();
+
+ /**
+ Returns whether the first contact is 'smaller' then the second.
+ */
+ bool lesser(const KContacts::Addressee &first, const KContacts::Addressee &second) const Q_DECL_OVERRIDE;
+
+private:
+ class Private;
+ Private *const d;
+
+ Q_DISABLE_COPY(FieldSortMode)
+};
+
+}
+
+#endif
--- /dev/null
+/*
+ This file is part of the KContacts framework.
+ Copyright (c) 2002 Tobias Koenig <tokoe@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "sound.h"
+
+#include <QtCore/QDataStream>
+#include <QtCore/QSharedData>
+
+using namespace KContacts;
+
+class Q_DECL_HIDDEN Sound::Private : public QSharedData
+{
+public:
+ Private()
+ : mIntern(false)
+ {
+ }
+
+ Private(const Private &other)
+ : QSharedData(other)
+ {
+ mUrl = other.mUrl;
+ mData = other.mData;
+ mIntern = other.mIntern;
+ }
+
+ QString mUrl;
+ QByteArray mData;
+
+ bool mIntern;
+};
+
+Sound::Sound()
+ : d(new Private)
+{
+}
+
+Sound::Sound(const QString &url)
+ : d(new Private)
+{
+ d->mUrl = url;
+}
+
+Sound::Sound(const QByteArray &data)
+ : d(new Private)
+{
+ d->mIntern = true;
+ d->mData = data;
+}
+
+Sound::Sound(const Sound &other)
+ : d(other.d)
+{
+}
+
+Sound::~Sound()
+{
+}
+
+Sound &Sound::operator=(const Sound &other)
+{
+ if (this != &other) {
+ d = other.d;
+ }
+
+ return *this;
+}
+
+bool Sound::operator==(const Sound &other) const
+{
+ if (d->mIntern != other.d->mIntern) {
+ return false;
+ }
+
+ if (d->mIntern) {
+ if (d->mData != other.d->mData) {
+ return false;
+ }
+ } else {
+ if (d->mUrl != other.d->mUrl) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool Sound::operator!=(const Sound &other) const
+{
+ return !(other == *this);
+}
+
+void Sound::setUrl(const QString &url)
+{
+ d->mIntern = false;
+ d->mUrl = url;
+}
+
+void Sound::setData(const QByteArray &data)
+{
+ d->mIntern = true;
+ d->mData = data;
+}
+
+bool Sound::isIntern() const
+{
+ return d->mIntern;
+}
+
+bool Sound::isEmpty() const
+{
+ return
+ ((d->mIntern && d->mData.isEmpty()) || (!d->mIntern && d->mUrl.isEmpty()));
+}
+
+QString Sound::url() const
+{
+ return d->mUrl;
+}
+
+QByteArray Sound::data() const
+{
+ return d->mData;
+}
+
+QString Sound::toString() const
+{
+ QString str;
+
+ str += QLatin1String("Sound {\n");
+ str += QStringLiteral(" IsIntern: %1\n").
+ arg(d->mIntern ? QStringLiteral("true") : QStringLiteral("false"));
+ if (d->mIntern) {
+ str += QStringLiteral(" Data: %1\n").
+ arg(QString::fromLatin1(d->mData.toBase64()));
+ } else {
+ str += QStringLiteral(" Url: %1\n").arg(d->mUrl);
+ }
+ str += QLatin1String("}\n");
+
+ return str;
+}
+
+QDataStream &KContacts::operator<<(QDataStream &s, const Sound &sound)
+{
+ return s << sound.d->mIntern << sound.d->mUrl << sound.d->mData;
+}
+
+QDataStream &KContacts::operator>>(QDataStream &s, Sound &sound)
+{
+ s >> sound.d->mIntern >> sound.d->mUrl >> sound.d->mData;
+
+ return s;
+}
--- /dev/null
+/*
+ This file is part of the KContacts framework.
+ Copyright (c) 2002 Tobias Koenig <tokoe@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KCONTACTS_SOUND_H
+#define KCONTACTS_SOUND_H
+
+#include "kcontacts_export.h"
+#include <QtCore/QString>
+#include <QtCore/QSharedDataPointer>
+
+namespace KContacts
+{
+
+/** @short Class that holds a Sound clip for a contact.
+ *
+ * The sound can be played doing something like this:
+ *
+ * \code
+ * KTempFile tmp;
+ * if ( sound.isIntern() ) {
+ * tmp.file()->write( sound.data() );
+ * tmp.close();
+ * KAudioPlayer::play( tmp.name() );
+ * } else if( !sound.url().isEmpty() ) {
+ * QString tmpFile;
+ * if ( !KIO::NetAccess::download( QUrl( themeURL.url() ), tmpFile, 0 ) ) {
+ * KMessageBox::error( 0,
+ * KIO::NetAccess::lastErrorString(),
+ * i18n( "Failed to download sound file" ),
+ * KMessageBox::Notify
+ * );
+ * return;
+ * }
+ * KAudioPlayer::play( tmpFile );
+ * }
+ * \endcode
+ *
+ * Unfortunately, KAudioPlayer::play is ASync, so to delete the temporary file
+ * the best you can really do is set a timer.
+ *
+ */
+class KCONTACTS_EXPORT Sound
+{
+ friend KCONTACTS_EXPORT QDataStream &operator<<(QDataStream &, const Sound &);
+ friend KCONTACTS_EXPORT QDataStream &operator>>(QDataStream &, Sound &);
+
+public:
+
+ /**
+ * Creates an empty sound object.
+ */
+ Sound();
+
+ /**
+ * Creates a sound object for the given url.
+ *
+ * @param url A url that describes the position of the sound file.
+ */
+ Sound(const QString &url);
+
+ /**
+ * Creates a sound object for the given data.
+ *
+ * @param data The raw data of the sound.
+ */
+ Sound(const QByteArray &data);
+
+ /**
+ * Copy constructor.
+ */
+ Sound(const Sound &other);
+
+ /**
+ * Destroys the sound object.
+ */
+ ~Sound();
+
+ typedef QVector<Sound> List;
+ /**
+ * Assignment operator.
+ *
+ * @param other The sound object to assign to @c this
+ */
+ Sound &operator=(const Sound &other);
+
+ /**
+ * Equality operator.
+ *
+ * @param other The object to compare with
+ *
+ * @return @c true if the two objects are equal, otherwise @c false
+ */
+ bool operator==(const Sound &other) const;
+
+ /**
+ * Not-Equal operator.
+ *
+ * @param other The object to compare with
+ *
+ * @return @c true if the two objects are not equal, otherwise @c false
+ */
+ bool operator!=(const Sound &other) const;
+
+ /**
+ * Sets a URL for the location of the sound file. When using this
+ * function, isIntern() will return 'false' until you use
+ * setData().
+ *
+ * @param url The location URL of the sound file.
+ */
+ void setUrl(const QString &url);
+
+ /**
+ * Returns true, if the sound object is empty.
+ */
+ bool isEmpty() const;
+
+ /**
+ * Sets the raw data of the sound. When using this function,
+ * isIntern() will return 'true' until you use setUrl().
+ *
+ * @param data The raw data of the sound.
+ */
+ void setData(const QByteArray &data);
+
+ /**
+ * Returns whether the sound is described by a URL (extern) or
+ * by the raw data (intern).
+ * When this method returns 'true' you can use data() to
+ * get the raw data. Otherwise you can request the URL of this
+ * sound by url() and load the raw data from that location.
+ */
+ bool isIntern() const;
+
+ /**
+ * Returns the location URL of this sound.
+ */
+ QString url() const;
+
+ /**
+ * Returns the raw data of this sound.
+ */
+ QByteArray data() const;
+
+ /**
+ * Returns string representation of the sound.
+ */
+ QString toString() const;
+
+private:
+ class Private;
+ QSharedDataPointer<Private> d;
+};
+
+/**
+ * Serializes the @p sound object into the @p stream.
+ */
+KCONTACTS_EXPORT QDataStream &operator<<(QDataStream &stream, const Sound &sound);
+
+/**
+ * Initializes the @p sound object from the @p stream.
+ */
+KCONTACTS_EXPORT QDataStream &operator>>(QDataStream &stream, Sound &sound);
+
+}
+Q_DECLARE_TYPEINFO(KContacts::Sound, Q_MOVABLE_TYPE);
+#endif
--- /dev/null
+/*
+ This file is part of the KContacts framework.
+ Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "timezone.h"
+
+#include <QtCore/QDataStream>
+#include <QtCore/QSharedData>
+
+using namespace KContacts;
+
+class Q_DECL_HIDDEN TimeZone::Private : public QSharedData
+{
+public:
+ Private(int offset = 0, bool valid = false)
+ : mOffset(offset), mValid(valid)
+ {
+ }
+
+ Private(const Private &other)
+ : QSharedData(other)
+ {
+ mOffset = other.mOffset;
+ mValid = other.mValid;
+ }
+
+ int mOffset;
+ bool mValid;
+};
+
+TimeZone::TimeZone()
+ : d(new Private)
+{
+}
+
+TimeZone::TimeZone(int offset)
+ : d(new Private(offset, true))
+{
+}
+
+TimeZone::TimeZone(const TimeZone &other)
+ : d(other.d)
+{
+}
+
+TimeZone::~TimeZone()
+{
+}
+
+void TimeZone::setOffset(int offset)
+{
+ d->mOffset = offset;
+ d->mValid = true;
+}
+
+int TimeZone::offset() const
+{
+ return d->mOffset;
+}
+
+bool TimeZone::isValid() const
+{
+ return d->mValid;
+}
+
+bool TimeZone::operator==(const TimeZone &t) const
+{
+ if (!t.isValid() && !isValid()) {
+ return true;
+ }
+
+ if (!t.isValid() || !isValid()) {
+ return false;
+ }
+
+ if (t.d->mOffset == d->mOffset) {
+ return true;
+ }
+
+ return false;
+}
+
+bool TimeZone::operator!=(const TimeZone &t) const
+{
+ return !(*this == t);
+}
+
+TimeZone &TimeZone::operator=(const TimeZone &other)
+{
+ if (this != &other) {
+ d = other.d;
+ }
+
+ return *this;
+}
+
+QString TimeZone::toString() const
+{
+ QString str;
+
+ str += QLatin1String("TimeZone {\n");
+ str += QStringLiteral(" Offset: %1\n").arg(d->mOffset);
+ str += QLatin1String("}\n");
+
+ return str;
+}
+
+QDataStream &KContacts::operator<<(QDataStream &s, const TimeZone &zone)
+{
+ return s << zone.d->mOffset << zone.d->mValid;
+}
+
+QDataStream &KContacts::operator>>(QDataStream &s, TimeZone &zone)
+{
+ s >> zone.d->mOffset >> zone.d->mValid;
+
+ return s;
+}
--- /dev/null
+/*
+ This file is part of the KContacts framework.
+ Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KCONTACTS_TIMEZONE_H
+#define KCONTACTS_TIMEZONE_H
+
+#include "kcontacts_export.h"
+#include <QtCore/QSharedDataPointer>
+#include <QtCore/QString>
+
+namespace KContacts
+{
+
+/**
+ * @short Time zone information.
+ *
+ * This class stores information about a time zone.
+ */
+class KCONTACTS_EXPORT TimeZone
+{
+ friend KCONTACTS_EXPORT QDataStream &operator<<(QDataStream &, const TimeZone &);
+ friend KCONTACTS_EXPORT QDataStream &operator>>(QDataStream &, TimeZone &);
+
+public:
+ /**
+ * Construct invalid time zone.
+ */
+ TimeZone();
+
+ /**
+ * Construct time zone.
+ *
+ * @param offset Offset in minutes relative to UTC.
+ */
+ TimeZone(int offset);
+
+ /**
+ * Copy constructor.
+ */
+ TimeZone(const TimeZone &other);
+
+ /**
+ * Destroys the time zone.
+ */
+ ~TimeZone();
+
+ /**
+ * Set time zone offset relative to UTC.
+ *
+ * @param offset Offset in minutes.
+ */
+ void setOffset(int offset);
+
+ /**
+ * Return offset in minutes relative to UTC.
+ */
+ int offset() const;
+
+ /**
+ * Return, if this time zone object is valid.
+ */
+ bool isValid() const;
+
+ bool operator==(const TimeZone &other) const;
+ bool operator!=(const TimeZone &other) const;
+ TimeZone &operator=(const TimeZone &other);
+
+ /**
+ * Return string representation of time zone offset.
+ */
+ QString toString() const;
+
+private:
+ class Private;
+ QSharedDataPointer<Private> d;
+};
+
+/**
+ * Serializes the @p timezone object into the @p stream.
+ */
+KCONTACTS_EXPORT QDataStream &operator<<(QDataStream &stream, const TimeZone &timeZone);
+
+/**
+ * Initializes the @p timezone object from the @p stream.
+ */
+KCONTACTS_EXPORT QDataStream &operator>>(QDataStream &stream, TimeZone &timeZone);
+
+}
+Q_DECLARE_TYPEINFO(KContacts::TimeZone, Q_MOVABLE_TYPE);
+
+#endif
--- /dev/null
+/*
+ This file is part of the KContacts framework.
+
+ Copyright (c) 2002 Tobias Koenig <tokoe@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "vcarddrag.h"
+
+#include "converter/vcardconverter.h"
+
+#include <QMimeData>
+#include <QMimeDatabase>
+
+using namespace KContacts;
+
+static QString findCompatibleMimeType(const QMimeData *md)
+{
+ // check the canonical MIME type first
+ if (md->hasFormat(KContacts::Addressee::mimeType())) {
+ return KContacts::Addressee::mimeType();
+ }
+
+ const QStringList mimeTypeOffers = md->formats();
+ const QMimeDatabase db;
+ Q_FOREACH (const QString &mimeType, mimeTypeOffers) {
+ const QMimeType mimeTypePtr = db.mimeTypeForName(mimeType);
+ if (mimeTypePtr.isValid() && mimeTypePtr.inherits(KContacts::Addressee::mimeType())) {
+ return mimeType;
+ }
+ }
+
+ return QString();
+}
+
+bool VCardDrag::populateMimeData(QMimeData *md, const QByteArray &content)
+{
+ md->setData(KContacts::Addressee::mimeType(), content);
+ return true;
+}
+
+bool VCardDrag::populateMimeData(QMimeData *md, const KContacts::Addressee::List &addressees)
+{
+ KContacts::VCardConverter converter;
+ const QByteArray vcards = converter.createVCards(addressees);
+ if (!vcards.isEmpty()) {
+ return populateMimeData(md, vcards);
+ } else {
+ return false;
+ }
+}
+
+bool VCardDrag::canDecode(const QMimeData *md)
+{
+ return !findCompatibleMimeType(md).isEmpty();
+}
+
+bool VCardDrag::fromMimeData(const QMimeData *md, QByteArray &content)
+{
+ const QString mimeOffer = findCompatibleMimeType(md);
+ if (mimeOffer.isEmpty()) {
+ return false;
+ }
+ content = md->data(mimeOffer);
+ return !content.isEmpty();
+}
+
+bool VCardDrag::fromMimeData(const QMimeData *md, KContacts::Addressee::List &addressees)
+{
+ const QString mimeOffer = findCompatibleMimeType(md);
+ if (mimeOffer.isEmpty()) {
+ return false;
+ }
+ addressees = KContacts::VCardConverter().parseVCards(md->data(mimeOffer));
+ return !addressees.isEmpty();
+}
+
--- /dev/null
+/*
+ This file is part of the KContacts framework.
+
+ Copyright (c) 2002-2010 Tobias Koenig <tokoe@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KCONTACTS_VCARDDRAG_H
+#define KCONTACTS_VCARDDRAG_H
+
+#include "kcontacts_export.h"
+
+#include <kcontacts/addressee.h>
+#include <QMimeData>
+
+namespace KContacts
+{
+
+/**
+ @brief Utility function for implementing drag&drop for vCards
+
+ See the Qt drag'n'drop documentation.
+
+ @since 4.5
+*/
+namespace VCardDrag
+{
+
+/**
+ Adds the vCard representation as data of the drag object.
+
+ @param md the object to set the data on
+ @param content the vCard data to set
+
+ @return Always @c true
+*/
+KCONTACTS_EXPORT bool populateMimeData(QMimeData *md, const QByteArray &content);
+
+/**
+ Adds the vCard representation as data of the drag object.
+
+ @param md the object to set the data on
+ @param contacts list of Addressee objects to serialize to vCard
+
+ @return @c true if serializing of the given list worked, otherwise @c false
+
+ @see VCardConverter::createVCards()
+*/
+KCONTACTS_EXPORT bool populateMimeData(QMimeData *md, const KContacts::Addressee::List &contacts);
+
+/**
+ Returns if drag&drop object can be decoded to vCard.
+
+ @param md the object to check for vCard data
+
+ @return @c true if the given data object contains a vCard MIME type, otherwise @c false
+*/
+KCONTACTS_EXPORT bool canDecode(const QMimeData *md);
+
+/**
+ Decodes the drag&drop object to vCard component @p content.
+
+ @param md the object to check for vCard data
+ @param content where to put the vCard data from @p md
+
+ @return @c true if there was data for the vCard MIME type, otherwise @c false
+
+ @see canDecode()
+*/
+KCONTACTS_EXPORT bool fromMimeData(const QMimeData *md, QByteArray &content);
+
+/**
+ Decodes the MIME data @p md and puts the resulting vCard into @p contactss.
+
+ @param md the object to check for vCard data
+ @param contacts where to put the parsed vCards from @p md
+
+ @return @c true if there was data for the vCard MIME type and it could be parsed successfully,
+ otherwise @c false
+
+ @see canDecode()
+*/
+KCONTACTS_EXPORT bool fromMimeData(const QMimeData *md, KContacts::Addressee::List &contacts);
+}
+
+}
+
+#endif // VCARDDRAG_H
--- /dev/null
+
+
+########### install files ###############
+install(
+ FILES
+ vcard.h
+ vcardline.h
+ vcardparser.h
+ DESTINATION ${KDE_INSTALL_INCLUDEDIR_KF5}/kcontacts COMPONENT Devel
+)
--- /dev/null
+/*
+ This file is part of the KContacts framework.
+ Copyright (c) 2003 Tobias Koenig <tokoe@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "vcard.h"
+#include <QVector>
+
+using namespace KContacts;
+
+VCard::VCard()
+{
+}
+
+VCard::VCard(const VCard &vcard)
+{
+ mLineMap = vcard.mLineMap;
+}
+
+VCard::~VCard()
+{
+}
+
+VCard &VCard::operator=(const VCard &vcard)
+{
+ if (&vcard == this) {
+ return *this;
+ }
+
+ mLineMap = vcard.mLineMap;
+
+ return *this;
+}
+
+void VCard::clear()
+{
+ mLineMap.clear();
+}
+
+QStringList VCard::identifiers() const
+{
+ return mLineMap.keys();
+}
+
+void VCard::addLine(const VCardLine &line)
+{
+ mLineMap[ line.identifier() ].append(line);
+}
+
+VCardLine::List VCard::lines(const QString &identifier) const
+{
+ LineMap::ConstIterator it = mLineMap.find(identifier);
+ if (it == mLineMap.end()) {
+ return VCardLine::List();
+ }
+
+ return *it;
+}
+
+VCardLine VCard::line(const QString &identifier) const
+{
+ LineMap::ConstIterator it = mLineMap.find(identifier);
+ if (it == mLineMap.end()) {
+ return VCardLine();
+ }
+
+ if ((*it).isEmpty()) {
+ return VCardLine();
+ } else {
+ return (*it).first();
+ }
+}
+
+void VCard::setVersion(Version version)
+{
+ mLineMap.remove(QStringLiteral("VERSION"));
+
+ VCardLine line;
+ line.setIdentifier(QStringLiteral("VERSION"));
+ if (version == v2_1) {
+ line.setIdentifier(QStringLiteral("2.1"));
+ } else if (version == v3_0) {
+ line.setIdentifier(QStringLiteral("3.0"));
+ } else if (version == v4_0) {
+ line.setIdentifier(QStringLiteral("4.0"));
+ }
+
+ mLineMap[ QStringLiteral("VERSION") ].append(line);
+}
+
+VCard::Version VCard::version() const
+{
+ LineMap::ConstIterator versionEntry = mLineMap.find(QStringLiteral("VERSION"));
+ if (versionEntry == mLineMap.end()) {
+ return v3_0;
+ }
+
+ VCardLine line = (*versionEntry)[ 0 ];
+ if (line.value() == QLatin1String("2.1")) {
+ return v2_1;
+ } else if (line.value() == QLatin1String("3.0")) {
+ return v3_0;
+ } else {
+ return v4_0;
+ }
+}
--- /dev/null
+/*
+ This file is part of the KContacts framework.
+ Copyright (c) 2003 Tobias Koenig <tokoe@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef VCARDPARSER_VCARD_H
+#define VCARDPARSER_VCARD_H
+
+#include <QtCore/QMap>
+#include <QtCore/QStringList>
+
+#include "vcardline.h"
+
+namespace KContacts
+{
+
+class VCard
+{
+public:
+ typedef QVector<VCard> List;
+ typedef QMap<QString, VCardLine::List> LineMap;
+
+ enum Version {
+ v2_1,
+ v3_0,
+ v4_0
+ };
+
+ VCard();
+ VCard(const VCard &card);
+
+ ~VCard();
+
+ VCard &operator=(const VCard &card);
+
+ /**
+ * Removes all lines from the vCard.
+ */
+ void clear();
+
+ /**
+ * Returns a list of all identifiers that exists in the vCard.
+ */
+ QStringList identifiers() const;
+
+ /**
+ * Adds a VCardLine to the VCard
+ */
+ void addLine(const VCardLine &line);
+
+ /**
+ * Returns all lines of the vcard with a special identifier.
+ */
+ VCardLine::List lines(const QString &identifier) const;
+
+ /**
+ * Returns only the first line of the vcard with a special identifier.
+ */
+ VCardLine line(const QString &identifier) const;
+
+ /**
+ * Set the version of the vCard.
+ */
+ void setVersion(Version version);
+
+ /**
+ * Returns the version of this vCard.
+ */
+ Version version() const;
+
+private:
+ LineMap mLineMap;
+};
+
+}
+
+#endif
--- /dev/null
+/*
+ This file is part of the KContacts framework.
+ Copyright (c) 2003 Tobias Koenig <tokoe@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "vcardline.h"
+
+using namespace KContacts;
+
+VCardLine::VCardLine()
+{
+}
+
+VCardLine::VCardLine(const QString &identifier)
+{
+ mIdentifier = identifier;
+}
+
+VCardLine::VCardLine(const QString &identifier, const QVariant &value)
+{
+ mIdentifier = identifier;
+ mValue = value;
+}
+
+VCardLine::VCardLine(const VCardLine &line)
+{
+ mParamMap = line.mParamMap;
+ mValue = line.mValue;
+ mIdentifier = line.mIdentifier;
+}
+
+VCardLine::~VCardLine()
+{
+}
+
+VCardLine &VCardLine::operator=(const VCardLine &line)
+{
+ if (&line == this) {
+ return *this;
+ }
+
+ mParamMap = line.mParamMap;
+ mValue = line.mValue;
+ mIdentifier = line.mIdentifier;
+
+ return *this;
+}
+
+void VCardLine::setIdentifier(const QString &identifier)
+{
+ mIdentifier = identifier;
+}
+
+QString VCardLine::identifier() const
+{
+ return mIdentifier;
+}
+
+void VCardLine::setValue(const QVariant &value)
+{
+ mValue = value;
+}
+
+QVariant VCardLine::value() const
+{
+ return mValue;
+}
+
+void VCardLine::setGroup(const QString &group)
+{
+ mGroup = group;
+}
+
+QString VCardLine::group() const
+{
+ return mGroup;
+}
+
+bool VCardLine::hasGroup() const
+{
+ return !mGroup.isEmpty();
+}
+
+QStringList VCardLine::parameterList() const
+{
+ return mParamMap.keys();
+}
+
+void VCardLine::addParameter(const QString ¶m, const QString &value)
+{
+ QStringList &list = mParamMap[ param ];
+ if (!list.contains(value)) { // not included yet
+ list.append(value);
+ }
+}
+
+QStringList VCardLine::parameters(const QString ¶m) const
+{
+ ParamMap::ConstIterator it = mParamMap.find(param);
+ if (it == mParamMap.end()) {
+ return QStringList();
+ } else {
+ return *it;
+ }
+}
+
+QString VCardLine::parameter(const QString ¶m) const
+{
+ ParamMap::ConstIterator it = mParamMap.find(param);
+ if (it == mParamMap.end()) {
+ return QString();
+ } else {
+ if ((*it).isEmpty()) {
+ return QString();
+ } else {
+ return (*it).first();
+ }
+ }
+}
+
+VCardLine::ParamMap VCardLine::parameterMap() const
+{
+ return mParamMap;
+}
--- /dev/null
+/*
+ This file is part of the KContacts framework.
+ Copyright (c) 2003 Tobias Koenig <tokoe@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef VCARDLINE_H
+#define VCARDLINE_H
+
+#include <QtCore/QMap>
+#include <QtCore/QString>
+#include <QtCore/QStringList>
+#include <QtCore/QVariant>
+
+namespace KContacts
+{
+
+class VCardLine
+{
+public:
+ typedef QVector<VCardLine> List;
+ typedef QMap<QString, QStringList> ParamMap;
+
+ VCardLine();
+ VCardLine(const QString &identifier);
+ VCardLine(const QString &identifier, const QVariant &value);
+ VCardLine(const VCardLine &line);
+
+ ~VCardLine();
+
+ VCardLine &operator=(const VCardLine &line);
+
+ /**
+ * Sets the identifier of this line e.g. UID, FN, CLASS
+ *
+ * @param identifier The VCard identifier of this line
+ */
+ void setIdentifier(const QString &identifier);
+
+ /**
+ * Returns the identifier of this line.
+ */
+ QString identifier() const;
+
+ /**
+ * Sets the value of of this line.
+ */
+ void setValue(const QVariant &value);
+
+ /**
+ * Returns the value of this line.
+ */
+ QVariant value() const;
+
+ /**
+ * Sets the group the line belongs to.
+ */
+ void setGroup(const QString &group);
+
+ /**
+ * Returns the group the line belongs to.
+ */
+ QString group() const;
+
+ /**
+ * Returns whether the line belongs to a group.
+ */
+ bool hasGroup() const;
+
+ /**
+ * Returns all parameters.
+ */
+ QStringList parameterList() const;
+
+ /**
+ * Add a new parameter to the line.
+ *
+ * @param param Name of the parameter to insert
+ * @param value Value of the parameter to insert
+ */
+ void addParameter(const QString ¶m, const QString &value);
+
+ /**
+ * Returns the values of a special parameter.
+ * You can get a list of all parameters with paramList().
+ *
+ * @param param Name of the parameter to look for
+ */
+ QStringList parameters(const QString ¶m) const;
+
+ /**
+ * Returns only the first value of a special parameter.
+ * You can get a list of all parameters with paramList().
+ *
+ * @param param Name of the parameter to look for
+ */
+ QString parameter(const QString ¶m) const;
+
+ /**
+ * Returns all parameters
+ * @since 4.14.5
+ */
+ ParamMap parameterMap() const;
+
+private:
+ ParamMap mParamMap;
+ QString mIdentifier;
+ QString mGroup;
+ QVariant mValue;
+};
+
+}
+
+#endif
--- /dev/null
+/*
+ This file is part of the KContacts framework.
+ Copyright (c) 2003 Tobias Koenig <tokoe@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "vcardparser.h"
+#include <kcodecs.h>
+#include "kcontacts_debug.h"
+#include <QtCore/QTextCodec>
+
+class StringCache
+{
+public:
+ QString fromLatin1(const QByteArray &value)
+ {
+ if (value.isEmpty()) {
+ return QString();
+ }
+
+ QHash<QByteArray, QString>::const_iterator it = m_values.constFind(value);
+ if (it != m_values.constEnd()) {
+ return it.value();
+ }
+
+ QString string = QString::fromLatin1(value);
+ m_values.insert(value, string);
+ return string;
+ }
+
+private:
+ QHash<QByteArray, QString> m_values;
+};
+
+#define FOLD_WIDTH 75
+
+using namespace KContacts;
+
+static void addEscapes(QByteArray &str, bool excludeEscapteComma)
+{
+ str.replace('\\', (char *)"\\\\");
+ if (!excludeEscapteComma) {
+ str.replace(',', (char *)"\\,");
+ }
+ str.replace('\r', (char *)"\\r");
+ str.replace('\n', (char *)"\\n");
+}
+
+static void removeEscapes(QByteArray &str)
+{
+ str.replace((char *)"\\n", "\n");
+ str.replace((char *)"\\N", "\n");
+ str.replace((char *)"\\r", "\r");
+ str.replace((char *)"\\,", ",");
+ str.replace((char *)"\\\\", "\\");
+}
+
+VCardParser::VCardParser()
+ : d(Q_NULLPTR)
+{
+}
+
+VCardParser::~VCardParser()
+{
+}
+
+VCard::List VCardParser::parseVCards(const QByteArray &text)
+{
+ VCard currentVCard;
+ VCard::List vCardList;
+ QByteArray currentLine;
+
+ QList<QByteArray> lines = text.split('\n');
+
+ bool inVCard = false;
+ QList<QByteArray>::Iterator it(lines.begin());
+ QList<QByteArray>::Iterator linesEnd(lines.end());
+
+ StringCache cache;
+
+ for (; it != linesEnd; ++it) {
+ // remove the trailing \r, left from \r\n
+ if ((*it).endsWith('\r')) {
+ (*it).chop(1);
+ }
+
+ if ((*it).startsWith(' ') ||
+ (*it).startsWith('\t')) { //folded line => append to previous
+ currentLine.append((*it).mid(1));
+ continue;
+ } else {
+ if ((*it).trimmed().isEmpty()) { // empty line
+ continue;
+ }
+ if (inVCard && !currentLine.isEmpty()) { // now parse the line
+ int colon = currentLine.indexOf(':');
+ if (colon == -1) { // invalid line
+ currentLine = (*it);
+ continue;
+ }
+
+ VCardLine vCardLine;
+ const QByteArray key = currentLine.left(colon).trimmed();
+ QByteArray value = currentLine.mid(colon + 1);
+
+ QList<QByteArray> params = key.split(';');
+
+ // check for group
+ int groupPos = params[ 0 ].indexOf('.');
+ if (groupPos != -1) {
+ vCardLine.setGroup(cache.fromLatin1(params[ 0 ].left(groupPos)));
+ vCardLine.setIdentifier(cache.fromLatin1(params[ 0 ].mid(groupPos + 1)));
+ } else {
+ vCardLine.setIdentifier(cache.fromLatin1(params[ 0 ]));
+ }
+
+ if (params.count() > 1) { // find all parameters
+ QList<QByteArray>::ConstIterator paramIt(params.constBegin());
+ for (++paramIt; paramIt != params.constEnd(); ++paramIt) {
+ QList<QByteArray> pair = (*paramIt).split('=');
+ if (pair.count() == 1) {
+ // correct the fucking 2.1 'standard'
+ if (pair[ 0 ].toLower() == "quoted-printable") {
+ pair[ 0 ] = "encoding";
+ pair.append("quoted-printable");
+ } else if (pair[ 0 ].toLower() == "base64") {
+ pair[ 0 ] = "encoding";
+ pair.append("base64");
+ } else {
+ pair.prepend("type");
+ }
+ }
+ if (pair[ 1 ].indexOf(',') != -1) { // parameter in type=x,y,z format
+ const QList<QByteArray> args = pair[ 1 ].split(',');
+ QList<QByteArray>::ConstIterator argIt;
+ QList<QByteArray>::ConstIterator argEnd(args.constEnd());
+ for (argIt = args.constBegin(); argIt != argEnd; ++argIt) {
+ vCardLine.addParameter(cache.fromLatin1(pair[ 0 ].toLower()),
+ cache.fromLatin1(*argIt));
+ }
+ } else {
+ vCardLine.addParameter(cache.fromLatin1(pair[ 0 ].toLower()),
+ cache.fromLatin1(pair[ 1 ]));
+ }
+ }
+ }
+
+ removeEscapes(value);
+
+ QByteArray output;
+ bool wasBase64Encoded = false;
+
+ if (vCardLine.parameterList().contains(QStringLiteral("encoding"))) {
+ const QString encoding = vCardLine.parameter(QStringLiteral("encoding")).toLower();
+
+ // have to decode the data
+ if (encoding == QLatin1String("b") || encoding == QLatin1String("base64")) {
+ output = QByteArray::fromBase64(value);
+ wasBase64Encoded = true;
+ } else if (encoding == QLatin1String("quoted-printable")) {
+ // join any qp-folded lines
+ while (value.endsWith('=') && it != linesEnd) {
+ value.chop(1); // remove the '='
+ value.append(*it);
+ ++it;
+ // remove the trailing \r, left from \r\n
+ if ((*it).endsWith('\r')) {
+ (*it).chop(1);
+ }
+ }
+ KCodecs::quotedPrintableDecode(value, output);
+ } else if (encoding == QLatin1String("8bit")) {
+ output = value;
+ } else {
+ qDebug("Unknown vcard encoding type!");
+ }
+ } else {
+ output = value;
+ }
+
+ if (vCardLine.parameterList().contains(QStringLiteral("charset"))) {
+ // have to convert the data
+ QTextCodec *codec = QTextCodec::codecForName(
+ vCardLine.parameter(QStringLiteral("charset")).toLatin1());
+ if (codec) {
+ vCardLine.setValue(codec->toUnicode(output));
+ } else {
+ vCardLine.setValue(QString::fromUtf8(output));
+ }
+ } else if (wasBase64Encoded) {
+ vCardLine.setValue(output);
+ } else {
+ vCardLine.setValue(QString::fromUtf8(output));
+ }
+
+ currentVCard.addLine(vCardLine);
+ }
+
+ // we do not save the start and end tag as vcardline
+ if ((*it).toLower().startsWith("begin:vcard")) { //krazy:exclude=strings
+ inVCard = true;
+ currentLine.clear();
+ currentVCard.clear(); // flush vcard
+ continue;
+ }
+
+ if ((*it).toLower().startsWith("end:vcard")) { //krazy:exclude=strings
+ inVCard = false;
+ vCardList.append(currentVCard);
+ currentLine.clear();
+ currentVCard.clear(); // flush vcard
+ continue;
+ }
+
+ currentLine = (*it);
+ }
+ }
+
+ return vCardList;
+}
+
+QByteArray VCardParser::createVCards(const VCard::List &list)
+{
+ QByteArray text;
+ QByteArray textLine;
+ QString encodingType;
+ QStringList idents;
+ QStringList params;
+ QStringList values;
+ QStringList::ConstIterator identIt;
+ QStringList::Iterator paramIt;
+ QStringList::ConstIterator valueIt;
+
+ VCardLine::List lines;
+ VCardLine::List::ConstIterator lineIt;
+ VCard::List::ConstIterator cardIt;
+
+ bool hasEncoding;
+
+ text.reserve(list.size() * 300); // reserve memory to be more efficient
+
+ // iterate over the cards
+ VCard::List::ConstIterator listEnd(list.end());
+ for (cardIt = list.begin(); cardIt != listEnd; ++cardIt) {
+ text.append("BEGIN:VCARD\r\n");
+
+ idents = (*cardIt).identifiers();
+ //VERSION must be first
+ if (idents.contains(QStringLiteral("VERSION"))) {
+ const QString str = idents.takeAt(idents.indexOf(QStringLiteral("VERSION")));
+ idents.prepend(str);
+ }
+
+ for (identIt = idents.constBegin(); identIt != idents.constEnd(); ++identIt) {
+ lines = (*cardIt).lines((*identIt));
+
+ // iterate over the lines
+ for (lineIt = lines.constBegin(); lineIt != lines.constEnd(); ++lineIt) {
+ QVariant val = (*lineIt).value();
+ if (val.isValid()) {
+ if ((*lineIt).hasGroup()) {
+ textLine = (*lineIt).group().toLatin1() + '.' + (*lineIt).identifier().toLatin1();
+ } else {
+ textLine = (*lineIt).identifier().toLatin1();
+ }
+
+ params = (*lineIt).parameterList();
+ hasEncoding = false;
+ if (!params.isEmpty()) { // we have parameters
+ for (paramIt = params.begin(); paramIt != params.end(); ++paramIt) {
+ if ((*paramIt) == QLatin1String("encoding")) {
+ hasEncoding = true;
+ encodingType = (*lineIt).parameter(QStringLiteral("encoding")).toLower();
+ }
+
+ values = (*lineIt).parameters(*paramIt);
+ for (valueIt = values.constBegin(); valueIt != values.constEnd(); ++valueIt) {
+ textLine.append(';' + (*paramIt).toLatin1().toUpper());
+ if (!(*valueIt).isEmpty()) {
+ textLine.append('=' + (*valueIt).toLatin1());
+ }
+ }
+ }
+ }
+
+ QByteArray input, output;
+ bool checkMultibyte = false; // avoid splitting a multibyte character
+
+ // handle charset
+ if ((*lineIt).parameterList().contains(QStringLiteral("charset"))) {
+ // have to convert the data
+ const QString value = (*lineIt).value().toString();
+ QTextCodec *codec = QTextCodec::codecForName(
+ (*lineIt).parameter(QStringLiteral("charset")).toLatin1());
+ if (codec) {
+ input = codec->fromUnicode(value);
+ } else {
+ checkMultibyte = true;
+ input = value.toUtf8();
+ }
+ } else if ((*lineIt).value().type() == QVariant::ByteArray) {
+ input = (*lineIt).value().toByteArray();
+ } else {
+ checkMultibyte = true;
+ input = (*lineIt).value().toString().toUtf8();
+ }
+
+ // handle encoding
+ if (hasEncoding) { // have to encode the data
+ if (encodingType == QLatin1String("b")) {
+ checkMultibyte = false;
+ output = input.toBase64();
+ } else if (encodingType == QLatin1String("quoted-printable")) {
+ checkMultibyte = false;
+ KCodecs::quotedPrintableEncode(input, output, false);
+ }
+ } else {
+ output = input;
+ }
+ addEscapes(output, ((*lineIt).identifier() == QLatin1String("CATEGORIES") || (*lineIt).identifier() == QLatin1String("GEO")));
+
+ if (!output.isEmpty()) {
+ textLine.append(':' + output);
+
+ if (textLine.length() > FOLD_WIDTH) { // we have to fold the line
+ if (checkMultibyte) {
+ // RFC 6350: Multi-octet characters MUST remain contiguous.
+ // we know that textLine contains UTF-8 encoded characters
+ int lineLength = 0;
+ for (int i = 0; i < textLine.length(); ++i) {
+ if ((textLine[i] & 0xC0) == 0xC0) { // a multibyte sequence follows
+ int sequenceLength = 2;
+ if ((textLine[i] & 0xE0) == 0xE0) {
+ sequenceLength = 3;
+ } else if ((textLine[i] & 0xF0) == 0xF0) {
+ sequenceLength = 4;
+ }
+ if ((lineLength + sequenceLength) > FOLD_WIDTH) {
+ // the current line would be too long. fold it
+ text += "\r\n " + textLine.mid(i, sequenceLength);
+ lineLength = 1 + sequenceLength; // incl. leading space
+ } else {
+ text += textLine.mid(i, sequenceLength);
+ lineLength += sequenceLength;
+ }
+ i += sequenceLength - 1;
+ } else {
+ text += textLine[i];
+ ++lineLength;
+ }
+ if ((lineLength == FOLD_WIDTH) && (i < (textLine.length() - 1))) {
+ text += "\r\n ";
+ lineLength = 1; // leading space
+ }
+ }
+ text += "\r\n";
+ } else {
+ for (int i = 0; i <= (textLine.length() / FOLD_WIDTH); ++i) {
+ text.append(
+ (i == 0 ? "" : " ") + textLine.mid(i * FOLD_WIDTH, FOLD_WIDTH) + "\r\n");
+ }
+ }
+ } else {
+ text.append(textLine + "\r\n");
+ }
+ }
+ }
+ }
+ }
+
+ text.append("END:VCARD\r\n");
+ text.append("\r\n");
+ }
+
+ return text;
+}
--- /dev/null
+/*
+ This file is part of the KContacts framework.
+ Copyright (c) 2003 Tobias Koenig <tokoe@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef VCARDPARSER_H
+#define VCARDPARSER_H
+
+#include "vcard.h"
+#include <QtCore/QByteArray>
+
+namespace KContacts
+{
+
+class VCardParser
+{
+public:
+ VCardParser();
+ ~VCardParser();
+
+ static VCard::List parseVCards(const QByteArray &text);
+ static QByteArray createVCards(const VCard::List &list);
+
+private:
+ Q_DISABLE_COPY(VCardParser)
+ class VCardParserPrivate;
+ VCardParserPrivate *d;
+};
+
+}
+
+#endif
--- /dev/null
+/*
+ This file is part of the KContacts framework.
+ Copyright (c) 2003 Tobias Koenig <tokoe@kde.org>
+ Copyright (c) 2015 Laurent Montel <montel@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "vcardtool.h"
+#include "key.h"
+#include "picture.h"
+#include "secrecy.h"
+#include "sound.h"
+#include "lang.h"
+#include "gender.h"
+#include "related.h"
+#include <QtCore/QString>
+#include <QtCore/QBuffer>
+#include <QDebug>
+
+using namespace KContacts;
+
+static bool needsEncoding(const QString &value)
+{
+ uint length = value.length();
+ for (uint i = 0; i < length; ++i) {
+ char c = value.at(i).toLatin1();
+ if ((c < 33 || c > 126) && c != ' ' && c != '=') {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+VCardTool::VCardTool()
+{
+ mAddressTypeMap.insert(QStringLiteral("dom"), Address::Dom);
+ mAddressTypeMap.insert(QStringLiteral("intl"), Address::Intl);
+ mAddressTypeMap.insert(QStringLiteral("postal"), Address::Postal);
+ mAddressTypeMap.insert(QStringLiteral("parcel"), Address::Parcel);
+ mAddressTypeMap.insert(QStringLiteral("home"), Address::Home);
+ mAddressTypeMap.insert(QStringLiteral("work"), Address::Work);
+ mAddressTypeMap.insert(QStringLiteral("pref"), Address::Pref);
+
+ mPhoneTypeMap.insert(QStringLiteral("HOME"), PhoneNumber::Home);
+ mPhoneTypeMap.insert(QStringLiteral("WORK"), PhoneNumber::Work);
+ mPhoneTypeMap.insert(QStringLiteral("MSG"), PhoneNumber::Msg);
+ mPhoneTypeMap.insert(QStringLiteral("PREF"), PhoneNumber::Pref);
+ mPhoneTypeMap.insert(QStringLiteral("VOICE"), PhoneNumber::Voice);
+ mPhoneTypeMap.insert(QStringLiteral("FAX"), PhoneNumber::Fax);
+ mPhoneTypeMap.insert(QStringLiteral("CELL"), PhoneNumber::Cell);
+ mPhoneTypeMap.insert(QStringLiteral("VIDEO"), PhoneNumber::Video);
+ mPhoneTypeMap.insert(QStringLiteral("BBS"), PhoneNumber::Bbs);
+ mPhoneTypeMap.insert(QStringLiteral("MODEM"), PhoneNumber::Modem);
+ mPhoneTypeMap.insert(QStringLiteral("CAR"), PhoneNumber::Car);
+ mPhoneTypeMap.insert(QStringLiteral("ISDN"), PhoneNumber::Isdn);
+ mPhoneTypeMap.insert(QStringLiteral("PCS"), PhoneNumber::Pcs);
+ mPhoneTypeMap.insert(QStringLiteral("PAGER"), PhoneNumber::Pager);
+}
+
+VCardTool::~VCardTool()
+{
+}
+
+QByteArray VCardTool::exportVCards(const Addressee::List &list, VCard::Version version) const
+{
+ return createVCards(list, version, true /*export vcard*/);
+}
+
+QByteArray VCardTool::createVCards(const Addressee::List &list, VCard::Version version) const
+{
+ return createVCards(list, version, false /*don't export*/);
+}
+
+void VCardTool::addParameter(VCardLine &line, VCard::Version version, const QString &key, const QStringList &valueStringList) const
+{
+ if (version == VCard::v2_1) {
+ Q_FOREACH (const QString &valueStr, valueStringList) {
+ line.addParameter(valueStr, QString());
+ }
+ } else {
+ line.addParameter(key, valueStringList.join(QStringLiteral(",")));
+ }
+}
+
+QByteArray VCardTool::createVCards(const Addressee::List &list,
+ VCard::Version version, bool exportVcard) const
+{
+ VCard::List vCardList;
+
+ Addressee::List::ConstIterator addrIt;
+ Addressee::List::ConstIterator listEnd(list.constEnd());
+ for (addrIt = list.constBegin(); addrIt != listEnd; ++addrIt) {
+ VCard card;
+ QStringList::ConstIterator strIt;
+ // VERSION
+ if (version == VCard::v2_1) {
+ card.addLine(VCardLine(QStringLiteral("VERSION"), QLatin1String("2.1")));
+ } else if (version == VCard::v3_0) {
+ card.addLine(VCardLine(QStringLiteral("VERSION"), QLatin1String("3.0")));
+ } else if (version == VCard::v4_0) {
+ card.addLine(VCardLine(QStringLiteral("VERSION"), QLatin1String("4.0")));
+ }
+
+ // ADR + LABEL
+ const Address::List addresses = (*addrIt).addresses();
+ for (Address::List::ConstIterator it = addresses.begin(); it != addresses.end(); ++it) {
+ QStringList address;
+
+ const bool isEmpty = ((*it).postOfficeBox().isEmpty() &&
+ (*it).extended().isEmpty() &&
+ (*it).street().isEmpty() &&
+ (*it).locality().isEmpty() &&
+ (*it).region().isEmpty() &&
+ (*it).postalCode().isEmpty() &&
+ (*it).country().isEmpty());
+
+ address.append((*it).postOfficeBox().replace(QLatin1Char(';'),
+ QLatin1String("\\;")));
+
+ address.append((*it).extended().replace(QLatin1Char(';'),
+ QLatin1String("\\;")));
+
+ address.append((*it).street().replace(QLatin1Char(';'),
+ QLatin1String("\\;")));
+
+ address.append((*it).locality().replace(QLatin1Char(';'),
+ QLatin1String("\\;")));
+
+ address.append((*it).region().replace(QLatin1Char(';'),
+ QLatin1String("\\;")));
+
+ address.append((*it).postalCode().replace(QLatin1Char(';'),
+ QLatin1String("\\;")));
+
+ address.append((*it).country().replace(QLatin1Char(';'),
+ QLatin1String("\\;")));
+
+ VCardLine adrLine(QStringLiteral("ADR"), address.join(QStringLiteral(";")));
+ if (version == VCard::v2_1 && needsEncoding(address.join(QStringLiteral(";")))) {
+ adrLine.addParameter(QStringLiteral("charset"), QStringLiteral("UTF-8"));
+ adrLine.addParameter(QStringLiteral("encoding"), QStringLiteral("QUOTED-PRINTABLE"));
+ }
+
+ VCardLine labelLine(QStringLiteral("LABEL"), (*it).label());
+ if (version == VCard::v2_1 && needsEncoding((*it).label())) {
+ labelLine.addParameter(QStringLiteral("charset"), QStringLiteral("UTF-8"));
+ labelLine.addParameter(QStringLiteral("encoding"), QStringLiteral("QUOTED-PRINTABLE"));
+ }
+
+ const bool hasLabel = !(*it).label().isEmpty();
+ QMap<QString, Address::TypeFlag>::ConstIterator typeIt;
+ QStringList addreLineType;
+ QStringList labelLineType;
+ for (typeIt = mAddressTypeMap.constBegin();
+ typeIt != mAddressTypeMap.constEnd(); ++typeIt) {
+ if (typeIt.value() & (*it).type()) {
+ addreLineType << typeIt.key();
+ if (hasLabel) {
+ labelLineType << typeIt.key();
+ }
+ }
+ }
+
+ if (!isEmpty) {
+ addParameter(adrLine, version, QStringLiteral("TYPE"), addreLineType);
+ card.addLine(adrLine);
+ }
+ if (hasLabel) {
+ addParameter(labelLine, version, QStringLiteral("TYPE"), labelLineType);
+ card.addLine(labelLine);
+ }
+ }
+
+ // BDAY
+ card.addLine(VCardLine(QStringLiteral("BDAY"), createDateTime((*addrIt).birthday(), version)));
+
+ //Laurent: 31 Jan 2015. Not necessary to export it. When Categories were changes as AkonadiTag nobody thought that it was break categorie support...
+ //=> not necessary to export just tag...
+ // CATEGORIES only > 2.1
+ if (!exportVcard) {
+ if (version != VCard::v2_1) {
+ QStringList categories = (*addrIt).categories();
+ QStringList::Iterator catIt;
+ QStringList::Iterator catEnd(categories.end());
+ for (catIt = categories.begin(); catIt != catEnd; ++catIt) {
+ (*catIt).replace(QLatin1Char(','), QLatin1String("\\,"));
+ }
+
+ VCardLine catLine(QStringLiteral("CATEGORIES"), categories.join(QStringLiteral(",")));
+ card.addLine(catLine);
+ }
+ }
+ // MEMBER (only in 4.0)
+ if (version == VCard::v4_0) {
+ // The KIND property must be set to "group" in order to use this property.
+ if ((*addrIt).kind().toLower() == QLatin1String("group")) {
+ Q_FOREACH (const QString &member, (*addrIt).members()) {
+ VCardLine line(QStringLiteral("MEMBER"), member);
+ card.addLine(line);
+ }
+ }
+ }
+ // SOURCE
+ Q_FOREACH (const QUrl &url, (*addrIt).sourcesUrlList()) {
+ VCardLine line = VCardLine(QStringLiteral("SOURCE"), url.url());
+ card.addLine(line);
+ }
+
+ if (version == VCard::v4_0) {
+ const Related::List relatedList = (*addrIt).relationShips();
+ Related::List::ConstIterator relatedIt;
+ Related::List::ConstIterator relatedEnd(relatedList.end());
+ for (relatedIt = relatedList.begin(); relatedIt != relatedEnd; ++relatedIt) {
+ VCardLine line(QStringLiteral("RELATED"), (*relatedIt).related());
+ QMapIterator<QString, QStringList> i((*relatedIt).parameters());
+ while (i.hasNext()) {
+ i.next();
+ line.addParameter(i.key(), i.value().join(QStringLiteral(",")));
+ }
+ card.addLine(line);
+ }
+ }
+ // CLASS only for version == 3.0
+ if (version == VCard::v3_0) {
+ card.addLine(createSecrecy((*addrIt).secrecy()));
+ }
+ // LANG only for version == 4.0
+ if (version == VCard::v4_0) {
+ const Lang::List langList = (*addrIt).langs();
+ Lang::List::ConstIterator langIt;
+ Lang::List::ConstIterator langEnd(langList.end());
+ for (langIt = langList.begin(); langIt != langEnd; ++langIt) {
+ VCardLine line(QStringLiteral("LANG"), (*langIt).language());
+ QMapIterator<QString, QStringList> i((*langIt).parameters());
+ while (i.hasNext()) {
+ i.next();
+ line.addParameter(i.key(), i.value().join(QStringLiteral(",")));
+ }
+ card.addLine(line);
+ }
+ }
+ // EMAIL
+ const Email::List emailList = (*addrIt).emailList();
+ Email::List::ConstIterator emailIt;
+ Email::List::ConstIterator emailEnd(emailList.end());
+ for (emailIt = emailList.begin(); emailIt != emailEnd; ++emailIt) {
+ VCardLine line(QStringLiteral("EMAIL"), (*emailIt).mail());
+ QMapIterator<QString, QStringList> i((*emailIt).parameters());
+ while (i.hasNext()) {
+ i.next();
+ if (version == VCard::v2_1) {
+ if (i.key().toLower() == QLatin1String("type")) {
+ QStringList valueStringList = i.value();
+ bool hasPreferred = false;
+ if (valueStringList.contains(QStringLiteral("PREF"))) {
+ valueStringList.removeAll(QStringLiteral("PREF"));
+ hasPreferred = true;
+ }
+ if (!valueStringList.isEmpty()) {
+ addParameter(line, version, i.key(), valueStringList);
+ }
+ if (hasPreferred) {
+ line.addParameter(QStringLiteral("PREF"), QString());
+ }
+ } else {
+ line.addParameter(i.key(), i.value().join(QStringLiteral(",")));
+ }
+ } else {
+ line.addParameter(i.key(), i.value().join(QStringLiteral(",")));
+ }
+ }
+ card.addLine(line);
+ }
+
+ // FN required for only version > 2.1
+ VCardLine fnLine(QStringLiteral("FN"), (*addrIt).formattedName());
+ if (version == VCard::v2_1 && needsEncoding((*addrIt).formattedName())) {
+ fnLine.addParameter(QStringLiteral("charset"), QStringLiteral("UTF-8"));
+ fnLine.addParameter(QStringLiteral("encoding"), QStringLiteral("QUOTED-PRINTABLE"));
+ }
+ card.addLine(fnLine);
+
+ // GEO
+ const Geo geo = (*addrIt).geo();
+ if (geo.isValid()) {
+ QString str;
+ if (version == VCard::v4_0) {
+ str.sprintf("geo:%.6f,%.6f", geo.latitude(), geo.longitude());
+ } else {
+ str.sprintf("%.6f;%.6f", geo.latitude(), geo.longitude());
+ }
+ card.addLine(VCardLine(QStringLiteral("GEO"), str));
+ }
+
+ // KEY
+ const Key::List keys = (*addrIt).keys();
+ Key::List::ConstIterator keyIt;
+ Key::List::ConstIterator keyEnd(keys.end());
+ for (keyIt = keys.begin(); keyIt != keyEnd; ++keyIt) {
+ card.addLine(createKey(*keyIt, version));
+ }
+
+ // LOGO
+ card.addLine(createPicture(QStringLiteral("LOGO"), (*addrIt).logo(), version));
+ Q_FOREACH (const Picture &logo, (*addrIt).extraLogoList()) {
+ card.addLine(createPicture(QStringLiteral("LOGO"), logo, version));
+ }
+
+ // MAILER only for version < 4.0
+ if (version != VCard::v4_0) {
+ VCardLine mailerLine(QStringLiteral("MAILER"), (*addrIt).mailer());
+ if (version == VCard::v2_1 && needsEncoding((*addrIt).mailer())) {
+ mailerLine.addParameter(QStringLiteral("charset"), QStringLiteral("UTF-8"));
+ mailerLine.addParameter(QStringLiteral("encoding"), QStringLiteral("QUOTED-PRINTABLE"));
+ }
+ card.addLine(mailerLine);
+ }
+
+ // N required for only version < 4.0
+ QStringList name;
+ name.append((*addrIt).familyName().replace(QLatin1Char(';'),
+ QLatin1String("\\;")));
+
+ name.append((*addrIt).givenName().replace(QLatin1Char(';'),
+ QLatin1String("\\;")));
+
+ name.append((*addrIt).additionalName().replace(QLatin1Char(';'),
+ QLatin1String("\\;")));
+
+ name.append((*addrIt).prefix().replace(QLatin1Char(';'),
+ QLatin1String("\\;")));
+
+ name.append((*addrIt).suffix().replace(QLatin1Char(';'),
+ QLatin1String("\\;")));
+
+ VCardLine nLine(QStringLiteral("N"), name.join(QStringLiteral(";")));
+ if (version == VCard::v2_1 && needsEncoding(name.join(QStringLiteral(";")))) {
+ nLine.addParameter(QStringLiteral("charset"), QStringLiteral("UTF-8"));
+ nLine.addParameter(QStringLiteral("encoding"), QStringLiteral("QUOTED-PRINTABLE"));
+ }
+ if (version == VCard::v4_0 && !(*addrIt).sortString().isEmpty()) {
+ nLine.addParameter(QStringLiteral("SORT-AS"), (*addrIt).sortString());
+ }
+
+ card.addLine(nLine);
+
+ // NAME only for version < 4.0
+ if (version != VCard::v4_0) {
+ VCardLine nameLine(QStringLiteral("NAME"), (*addrIt).name());
+ if (version == VCard::v2_1 && needsEncoding((*addrIt).name())) {
+ nameLine.addParameter(QStringLiteral("charset"), QStringLiteral("UTF-8"));
+ nameLine.addParameter(QStringLiteral("encoding"), QStringLiteral("QUOTED-PRINTABLE"));
+ }
+ card.addLine(nameLine);
+ }
+
+ // NICKNAME only for version > 2.1
+ if (version != VCard::v2_1) {
+ card.addLine(VCardLine(QStringLiteral("NICKNAME"), (*addrIt).nickName()));
+ }
+
+ // NOTE
+ VCardLine noteLine(QStringLiteral("NOTE"), (*addrIt).note());
+ if (version == VCard::v2_1 && needsEncoding((*addrIt).note())) {
+ noteLine.addParameter(QStringLiteral("charset"), QStringLiteral("UTF-8"));
+ noteLine.addParameter(QStringLiteral("encoding"), QStringLiteral("QUOTED-PRINTABLE"));
+ }
+ card.addLine(noteLine);
+
+ // ORG
+ QStringList organization;
+ organization.append((*addrIt).organization().replace(QLatin1Char(';'),
+ QLatin1String("\\;")));
+ if (!(*addrIt).department().isEmpty()) {
+ organization.append((*addrIt).department().replace(QLatin1Char(';'),
+ QLatin1String("\\;")));
+ }
+ VCardLine orgLine(QStringLiteral("ORG"), organization.join(QStringLiteral(";")));
+ if (version == VCard::v2_1 && needsEncoding(organization.join(QStringLiteral(";")))) {
+ orgLine.addParameter(QStringLiteral("charset"), QStringLiteral("UTF-8"));
+ orgLine.addParameter(QStringLiteral("encoding"), QStringLiteral("QUOTED-PRINTABLE"));
+ }
+ card.addLine(orgLine);
+
+ // PHOTO
+ card.addLine(createPicture(QStringLiteral("PHOTO"), (*addrIt).photo(), version));
+ Q_FOREACH (const Picture &photo, (*addrIt).extraPhotoList()) {
+ card.addLine(createPicture(QStringLiteral("PHOTO"), photo, version));
+ }
+
+ // PROID only for version > 2.1
+ if (version != VCard::v2_1) {
+ card.addLine(VCardLine(QStringLiteral("PRODID"), (*addrIt).productId()));
+ }
+
+ // REV
+ card.addLine(VCardLine(QStringLiteral("REV"), createDateTime((*addrIt).revision(), version)));
+
+ // ROLE
+ VCardLine roleLine(QStringLiteral("ROLE"), (*addrIt).role());
+ if (version == VCard::v2_1 && needsEncoding((*addrIt).role())) {
+ roleLine.addParameter(QStringLiteral("charset"), QStringLiteral("UTF-8"));
+ roleLine.addParameter(QStringLiteral("encoding"), QStringLiteral("QUOTED-PRINTABLE"));
+ }
+ card.addLine(roleLine);
+
+ // SORT-STRING
+ if (version == VCard::v3_0) {
+ card.addLine(VCardLine(QStringLiteral("SORT-STRING"), (*addrIt).sortString()));
+ }
+
+ // SOUND
+ card.addLine(createSound((*addrIt).sound(), version));
+ Q_FOREACH (const Sound &sound, (*addrIt).extraSoundList()) {
+ card.addLine(createSound(sound, version));
+ }
+
+ // TEL
+ const PhoneNumber::List phoneNumbers = (*addrIt).phoneNumbers();
+ PhoneNumber::List::ConstIterator phoneIt;
+ PhoneNumber::List::ConstIterator phoneEnd(phoneNumbers.end());
+ for (phoneIt = phoneNumbers.begin(); phoneIt != phoneEnd; ++phoneIt) {
+ VCardLine line(QStringLiteral("TEL"), (*phoneIt).number());
+
+ QMap<QString, PhoneNumber::TypeFlag>::ConstIterator typeIt;
+ QMap<QString, PhoneNumber::TypeFlag>::ConstIterator typeEnd(mPhoneTypeMap.constEnd());
+ QStringList lst;
+ for (typeIt = mPhoneTypeMap.constBegin(); typeIt != typeEnd; ++typeIt) {
+ if (typeIt.value() & (*phoneIt).type()) {
+ lst << typeIt.key();
+
+ }
+ }
+ if (!lst.isEmpty()) {
+ addParameter(line, version, QStringLiteral("TYPE"), lst);
+ }
+ card.addLine(line);
+ }
+
+ // TITLE
+ VCardLine titleLine(QStringLiteral("TITLE"), (*addrIt).title());
+ if (version == VCard::v2_1 && needsEncoding((*addrIt).title())) {
+ titleLine.addParameter(QStringLiteral("charset"), QStringLiteral("UTF-8"));
+ titleLine.addParameter(QStringLiteral("encoding"), QStringLiteral("QUOTED-PRINTABLE"));
+ }
+ card.addLine(titleLine);
+
+ // TZ
+ // TODO Add vcard4.0 support
+ const TimeZone timeZone = (*addrIt).timeZone();
+ if (timeZone.isValid()) {
+ QString str;
+
+ int neg = 1;
+ if (timeZone.offset() < 0) {
+ neg = -1;
+ }
+
+ str.sprintf("%c%02d:%02d", (timeZone.offset() >= 0 ? '+' : '-'),
+ (timeZone.offset() / 60) * neg,
+ (timeZone.offset() % 60) * neg);
+
+ card.addLine(VCardLine(QStringLiteral("TZ"), str));
+ }
+
+ // UID
+ card.addLine(VCardLine(QStringLiteral("UID"), (*addrIt).uid()));
+
+ // URL
+ Q_FOREACH (const ResourceLocatorUrl &url, (*addrIt).extraUrlList()) {
+ VCardLine line(QStringLiteral("URL"), url.url());
+ QMapIterator<QString, QStringList> i(url.parameters());
+ while (i.hasNext()) {
+ i.next();
+ line.addParameter(i.key(), i.value().join(QStringLiteral(",")));
+ }
+ card.addLine(line);
+ }
+ if (version == VCard::v4_0) {
+ // GENDER
+ const Gender gender = (*addrIt).gender();
+ if (gender.isValid()) {
+ QString genderStr;
+ if (!gender.gender().isEmpty()) {
+ genderStr = gender.gender();
+ }
+ if (!gender.comment().isEmpty()) {
+ genderStr += QLatin1Char(';') + gender.comment();
+ }
+ VCardLine line(QStringLiteral("GENDER"), genderStr);
+ card.addLine(line);
+ }
+ // KIND
+ if (!(*addrIt).kind().isEmpty()) {
+ VCardLine line(QStringLiteral("KIND"), (*addrIt).kind());
+ card.addLine(line);
+ }
+ }
+ // From vcard4.
+ if (version == VCard::v4_0) {
+ Q_FOREACH (const CalendarUrl &url, (*addrIt).calendarUrlList()) {
+ if (url.isValid()) {
+ QString type;
+ switch (url.type()) {
+ case CalendarUrl::Unknown:
+ case CalendarUrl::EndCalendarType:
+ break;
+ case CalendarUrl::FBUrl:
+ type = QStringLiteral("FBURL");
+ break;
+ case CalendarUrl::CALUri:
+ type = QStringLiteral("CALURI");
+ break;
+ case CalendarUrl::CALADRUri:
+ type = QStringLiteral("CALADRURI");
+ break;
+
+ }
+ if (!type.isEmpty()) {
+ VCardLine line(type, url.url().toDisplayString());
+ QMapIterator<QString, QStringList> i(url.parameters());
+ while (i.hasNext()) {
+ i.next();
+ line.addParameter(i.key(), i.value().join(QStringLiteral(",")));
+ }
+ card.addLine(line);
+ }
+ }
+ }
+ }
+ // IMPP (supported in vcard 3 too)
+ Q_FOREACH (const Impp &impp, (*addrIt).imppList()) {
+ VCardLine line(QStringLiteral("IMPP"), impp.address());
+ line.addParameter(QStringLiteral("X-SERVICE-TYPE"), Impp::typeToString(impp.type()));
+ QMapIterator<QString, QStringList> i(impp.parameters());
+ while (i.hasNext()) {
+ i.next();
+ if (i.key().toLower() != QStringLiteral("x-service-type")) {
+ line.addParameter(i.key(), i.value().join(QStringLiteral(",")));
+ }
+ }
+ card.addLine(line);
+ }
+
+ // X-
+ const QStringList customs = (*addrIt).customs();
+ for (strIt = customs.begin(); strIt != customs.end(); ++strIt) {
+ QString identifier = QLatin1String("X-") +
+ (*strIt).left((*strIt).indexOf(QLatin1Char(':')));
+ const QString value = (*strIt).mid((*strIt).indexOf(QLatin1Char(':')) + 1);
+ if (value.isEmpty()) {
+ continue;
+ }
+ //Convert to standard identifier
+ if (exportVcard) {
+ if (identifier == QLatin1String("X-messaging/aim-All")) {
+ identifier = QStringLiteral("X-AIM");
+ } else if (identifier == QLatin1String("X-messaging/icq-All")) {
+ identifier = QStringLiteral("X-ICQ");
+ } else if (identifier == QLatin1String("X-messaging/xmpp-All")) {
+ identifier = QStringLiteral("X-JABBER");
+ } else if (identifier == QLatin1String("X-messaging/msn-All")) {
+ identifier = QStringLiteral("X-MSN");
+ } else if (identifier == QLatin1String("X-messaging/yahoo-All")) {
+ identifier = QStringLiteral("X-YAHOO");
+ } else if (identifier == QLatin1String("X-messaging/gadu-All")) {
+ identifier = QStringLiteral("X-GADUGADU");
+ } else if (identifier == QLatin1String("X-messaging/skype-All")) {
+ identifier = QStringLiteral("X-SKYPE");
+ } else if (identifier == QLatin1String("X-messaging/groupwise-All")) {
+ identifier = QStringLiteral("X-GROUPWISE");
+ } else if (identifier == QLatin1String("X-messaging/sms-All")) {
+ identifier = QStringLiteral("X-SMS");
+ } else if (identifier == QLatin1String("X-messaging/meanwhile-All")) {
+ identifier = QStringLiteral("X-MEANWHILE");
+ } else if (identifier == QLatin1String("X-messaging/irc-All")) {
+ identifier = QStringLiteral("X-IRC"); //Not defined by rfc but need for fixing #300869
+ } else if (identifier == QLatin1String("X-messaging/googletalk-All")) {
+ //Not defined by rfc but need for fixing #300869
+ identifier = QStringLiteral("X-GTALK");
+ } else if (identifier == QLatin1String("X-messaging/twitter-All")) {
+ identifier = QStringLiteral("X-TWITTER");
+ }
+ }
+ if (identifier.toLower() == QLatin1String("x-kaddressbook-x-anniversary") && version == VCard::v4_0) {
+ // ANNIVERSARY
+ if (!value.isEmpty()) {
+ const QDate date = QDate::fromString(value, Qt::ISODate);
+ QDateTime dt = QDateTime(date);
+ dt.setTime(QTime());
+ card.addLine(VCardLine(QStringLiteral("ANNIVERSARY"), createDateTime(dt, version)));
+ }
+ } else {
+ VCardLine line(identifier, value);
+ if (version == VCard::v2_1 && needsEncoding(value)) {
+ line.addParameter(QStringLiteral("charset"), QStringLiteral("UTF-8"));
+ line.addParameter(QStringLiteral("encoding"), QStringLiteral("QUOTED-PRINTABLE"));
+ }
+ card.addLine(line);
+ }
+ }
+
+ vCardList.append(card);
+ }
+
+ return VCardParser::createVCards(vCardList);
+}
+
+Addressee::List VCardTool::parseVCards(const QByteArray &vcard) const
+{
+ static const QLatin1Char semicolonSep(';');
+ static const QLatin1Char commaSep(',');
+ QString identifier;
+
+ Addressee::List addrList;
+ const VCard::List vCardList = VCardParser::parseVCards(vcard);
+
+ VCard::List::ConstIterator cardIt;
+ VCard::List::ConstIterator listEnd(vCardList.end());
+ for (cardIt = vCardList.begin(); cardIt != listEnd; ++cardIt) {
+ Addressee addr;
+
+ const QStringList idents = (*cardIt).identifiers();
+ QStringList::ConstIterator identIt;
+ QStringList::ConstIterator identEnd(idents.end());
+ for (identIt = idents.begin(); identIt != identEnd; ++identIt) {
+ const VCardLine::List lines = (*cardIt).lines((*identIt));
+ VCardLine::List::ConstIterator lineIt;
+
+ // iterate over the lines
+ for (lineIt = lines.begin(); lineIt != lines.end(); ++lineIt) {
+ identifier = (*lineIt).identifier().toLower();
+ // ADR
+ if (identifier == QLatin1String("adr")) {
+ Address address;
+ const QStringList addrParts = splitString(semicolonSep, (*lineIt).value().toString());
+ if (addrParts.count() > 0) {
+ address.setPostOfficeBox(addrParts.at(0));
+ }
+ if (addrParts.count() > 1) {
+ address.setExtended(addrParts.at(1));
+ }
+ if (addrParts.count() > 2) {
+ address.setStreet(addrParts.at(2));
+ }
+ if (addrParts.count() > 3) {
+ address.setLocality(addrParts.at(3));
+ }
+ if (addrParts.count() > 4) {
+ address.setRegion(addrParts.at(4));
+ }
+ if (addrParts.count() > 5) {
+ address.setPostalCode(addrParts.at(5));
+ }
+ if (addrParts.count() > 6) {
+ address.setCountry(addrParts.at(6));
+ }
+
+ Address::Type type;
+
+ const QStringList types = (*lineIt).parameters(QStringLiteral("type"));
+ QStringList::ConstIterator end(types.end());
+ for (QStringList::ConstIterator it = types.begin(); it != end; ++it) {
+ type |= mAddressTypeMap[(*it).toLower() ];
+ }
+
+ address.setType(type);
+ if (!(*lineIt).parameter(QStringLiteral("label")).isEmpty()) {
+ address.setLabel((*lineIt).parameter(QStringLiteral("label")));
+ }
+ addr.insertAddress(address);
+ }
+ // ANNIVERSARY
+ else if (identifier == QLatin1String("anniversary")) {
+ const QString t = (*lineIt).value().toString();
+ const QDateTime dt(parseDateTime(t));
+ addr.insertCustom(QStringLiteral("KADDRESSBOOK"), QStringLiteral("X-Anniversary"), dt.date().toString(Qt::ISODate));
+ }
+ // BDAY
+ else if (identifier == QLatin1String("bday")) {
+ addr.setBirthday(parseDateTime((*lineIt).value().toString()));
+ }
+
+ // CATEGORIES
+ else if (identifier == QLatin1String("categories")) {
+ const QStringList categories = splitString(commaSep, (*lineIt).value().toString());
+ addr.setCategories(categories);
+ }
+ // FBURL
+ else if (identifier == QLatin1String("fburl")) {
+ CalendarUrl calurl;
+ calurl.setType(CalendarUrl::FBUrl);
+ const QUrl url = QUrl((*lineIt).value().toString());
+ calurl.setUrl(url);
+ calurl.setParameters((*lineIt).parameterMap());
+ addr.insertCalendarUrl(calurl);
+ }
+ // CALADRURI
+ else if (identifier == QLatin1String("caladruri")) {
+ CalendarUrl calurl;
+ calurl.setType(CalendarUrl::CALADRUri);
+ const QUrl url = QUrl((*lineIt).value().toString());
+ calurl.setUrl(url);
+ calurl.setParameters((*lineIt).parameterMap());
+ addr.insertCalendarUrl(calurl);
+ }
+ // CALURI
+ else if (identifier == QLatin1String("caluri")) {
+ CalendarUrl calurl;
+ calurl.setType(CalendarUrl::CALUri);
+ const QUrl url = QUrl((*lineIt).value().toString());
+ calurl.setUrl(url);
+ calurl.setParameters((*lineIt).parameterMap());
+ addr.insertCalendarUrl(calurl);
+ }
+ //IMPP
+ else if (identifier == QLatin1String("impp")) {
+ QString imppStr = (*lineIt).value().toString();
+ Impp impp;
+ impp.setAddress(imppStr);
+ impp.setParameters((*lineIt).parameterMap());
+ if (!(*lineIt).parameter(QStringLiteral("x-service-type")).isEmpty()) {
+ const QString serviceType = (*lineIt).parameter(QStringLiteral("x-service-type")).toLower();
+ if (serviceType == QLatin1String("facebook")) {
+ impp.setType(KContacts::Impp::Facebook);
+ } else if (serviceType == QLatin1String("jabber")) {
+ impp.setType(KContacts::Impp::Jabber);
+ } else if (serviceType == QLatin1String("sip")) {
+ impp.setType(KContacts::Impp::Sip);
+ } else if (serviceType == QLatin1String("aim")) {
+ impp.setType(KContacts::Impp::Aim);
+ } else if (serviceType == QLatin1String("msn")) {
+ impp.setType(KContacts::Impp::Msn);
+ } else if (serviceType == QLatin1String("twitter")) {
+ impp.setType(KContacts::Impp::Twitter);
+ } else if (serviceType == QLatin1String("googletalk")) {
+ impp.setType(KContacts::Impp::GoogleTalk);
+ } else if (serviceType == QLatin1String("xmpp")) {
+ impp.setType(KContacts::Impp::Xmpp);
+ } else if (serviceType == QLatin1String("icq")) {
+ impp.setType(KContacts::Impp::Icq);
+ } else if (serviceType == QLatin1String("yahoo")) {
+ impp.setType(KContacts::Impp::Yahoo);
+ } else if (serviceType == QLatin1String("qq")) {
+ impp.setType(KContacts::Impp::Qq);
+ } else if (serviceType == QLatin1String("gadugadu")) {
+ impp.setType(KContacts::Impp::GaduGadu);
+ } else if (serviceType == QLatin1String("owncloud-handle")) {
+ impp.setType(KContacts::Impp::Ownclound);
+ } else if (serviceType == QLatin1String("skype")) {
+ impp.setType(KContacts::Impp::Skype);
+ } else {
+ qDebug() << "unknown service type " << serviceType;
+ }
+ }
+ addr.insertImpp(impp);
+ }
+ // CLASS
+ else if (identifier == QLatin1String("class")) {
+ addr.setSecrecy(parseSecrecy(*lineIt));
+ }
+ // GENDER
+ else if (identifier == QLatin1String("gender")) {
+ QString genderStr = (*lineIt).value().toString();
+ if (!genderStr.isEmpty()) {
+ Gender gender;
+ if (genderStr.at(0) != QLatin1Char(';')) {
+ gender.setGender(genderStr.at(0));
+ if (genderStr.length() > 2 && (genderStr.at(1) == QLatin1Char(';'))) {
+ gender.setComment(genderStr.right(genderStr.length() - 2));
+ }
+ } else {
+ gender.setComment(genderStr.right(genderStr.length() - 1));
+ }
+ addr.setGender(gender);
+ }
+ }
+ // LANG
+ else if (identifier == QLatin1String("lang")) {
+ Lang lang;
+ lang.setLanguage((*lineIt).value().toString());
+ lang.setParameters((*lineIt).parameterMap());
+ addr.insertLang(lang);
+ }
+ // EMAIL
+ else if (identifier == QLatin1String("email")) {
+ const QStringList types = (*lineIt).parameters(QStringLiteral("type"));
+ addr.insertEmail((*lineIt).value().toString(),
+ types.contains(QStringLiteral("PREF")), (*lineIt).parameterMap());
+ }
+ // KIND
+ else if (identifier == QLatin1String("kind")) {
+ addr.setKind((*lineIt).value().toString());
+ }
+ // FN
+ else if (identifier == QLatin1String("fn")) {
+ addr.setFormattedName((*lineIt).value().toString());
+ }
+
+ // GEO
+ else if (identifier == QLatin1String("geo")) {
+ Geo geo;
+ QString lineStr = (*lineIt).value().toString();
+ if (lineStr.startsWith(QLatin1String("geo:"))) { //VCard 4.0
+ lineStr.remove(QStringLiteral("geo:"));
+ const QStringList geoParts =
+ lineStr.split(QLatin1Char(','), QString::KeepEmptyParts);
+ if (geoParts.size() >= 2) {
+ geo.setLatitude(geoParts.at(0).toFloat());
+ geo.setLongitude(geoParts.at(1).toFloat());
+ addr.setGeo(geo);
+ }
+ } else {
+ const QStringList geoParts =
+ lineStr.split(QLatin1Char(';'), QString::KeepEmptyParts);
+ if (geoParts.size() >= 2) {
+ geo.setLatitude(geoParts.at(0).toFloat());
+ geo.setLongitude(geoParts.at(1).toFloat());
+ addr.setGeo(geo);
+ }
+ }
+ }
+
+ // KEY
+ else if (identifier == QLatin1String("key")) {
+ addr.insertKey(parseKey(*lineIt));
+ }
+
+ // LABEL
+ else if (identifier == QLatin1String("label")) {
+ Address::Type type;
+
+ const QStringList types = (*lineIt).parameters(QStringLiteral("type"));
+ QStringList::ConstIterator end(types.end());
+ for (QStringList::ConstIterator it = types.begin(); it != end; ++it) {
+ type |= mAddressTypeMap[(*it).toLower() ];
+ }
+
+ bool available = false;
+ KContacts::Address::List addressList = addr.addresses();
+ for (KContacts::Address::List::Iterator it = addressList.begin();
+ it != addressList.end(); ++it) {
+ if ((*it).type() == type) {
+ (*it).setLabel((*lineIt).value().toString());
+ addr.insertAddress(*it);
+ available = true;
+ break;
+ }
+ }
+
+ if (!available) { // a standalone LABEL tag
+ KContacts::Address address(type);
+ address.setLabel((*lineIt).value().toString());
+ addr.insertAddress(address);
+ }
+ }
+
+ // LOGO
+ else if (identifier == QLatin1String("logo")) {
+ Picture picture = parsePicture(*lineIt);
+ if (addr.logo().isEmpty()) {
+ addr.setLogo(picture);
+ } else {
+ addr.insertExtraLogo(picture);
+ }
+ }
+
+ // MAILER
+ else if (identifier == QLatin1String("mailer")) {
+ addr.setMailer((*lineIt).value().toString());
+ }
+
+ // N
+ else if (identifier == QLatin1String("n")) {
+ const QStringList nameParts = splitString(semicolonSep, (*lineIt).value().toString());
+ const int numberOfParts(nameParts.count());
+ if (numberOfParts > 0) {
+ addr.setFamilyName(nameParts.at(0));
+ }
+ if (numberOfParts > 1) {
+ addr.setGivenName(nameParts.at(1));
+ }
+ if (numberOfParts > 2) {
+ addr.setAdditionalName(nameParts.at(2));
+ }
+ if (numberOfParts > 3) {
+ addr.setPrefix(nameParts.at(3));
+ }
+ if (numberOfParts > 4) {
+ addr.setSuffix(nameParts.at(4));
+ }
+ if (!(*lineIt).parameter(QStringLiteral("sort-as")).isEmpty()) {
+ addr.setSortString((*lineIt).parameter(QStringLiteral("sort-as")));
+ }
+ }
+
+ // NAME
+ else if (identifier == QLatin1String("name")) {
+ addr.setName((*lineIt).value().toString());
+ }
+
+ // NICKNAME
+ else if (identifier == QLatin1String("nickname")) {
+ addr.setNickName((*lineIt).value().toString());
+ }
+
+ // NOTE
+ else if (identifier == QLatin1String("note")) {
+ addr.setNote((*lineIt).value().toString());
+ }
+
+ // ORGANIZATION
+ else if (identifier == QLatin1String("org")) {
+ const QStringList orgParts = splitString(semicolonSep, (*lineIt).value().toString());
+ if (orgParts.count() > 0) {
+ addr.setOrganization(orgParts.at(0));
+ }
+ if (orgParts.count() > 1) {
+ addr.setDepartment(orgParts.at(1));
+ }
+ if (!(*lineIt).parameter(QStringLiteral("sort-as")).isEmpty()) {
+ addr.setSortString((*lineIt).parameter(QStringLiteral("sort-as")));
+ }
+ }
+
+ // PHOTO
+ else if (identifier == QLatin1String("photo")) {
+ Picture picture = parsePicture(*lineIt);
+ if (addr.photo().isEmpty()) {
+ addr.setPhoto(picture);
+ } else {
+ addr.insertExtraPhoto(picture);
+ }
+ }
+
+ // PROID
+ else if (identifier == QLatin1String("prodid")) {
+ addr.setProductId((*lineIt).value().toString());
+ }
+
+ // REV
+ else if (identifier == QLatin1String("rev")) {
+ addr.setRevision(parseDateTime((*lineIt).value().toString()));
+ }
+
+ // ROLE
+ else if (identifier == QLatin1String("role")) {
+ addr.setRole((*lineIt).value().toString());
+ }
+
+ // SORT-STRING
+ else if (identifier == QLatin1String("sort-string")) {
+ addr.setSortString((*lineIt).value().toString());
+ }
+
+ // SOUND
+ else if (identifier == QLatin1String("sound")) {
+ Sound sound = parseSound(*lineIt);
+ if (addr.sound().isEmpty()) {
+ addr.setSound(sound);
+ } else {
+ addr.insertExtraSound(sound);
+ }
+ }
+
+ // TEL
+ else if (identifier == QLatin1String("tel")) {
+ PhoneNumber phone;
+ phone.setNumber((*lineIt).value().toString());
+
+ PhoneNumber::Type type;
+ bool foundType = false;
+ const QStringList types = (*lineIt).parameters(QStringLiteral("type"));
+ QStringList::ConstIterator typeEnd(types.end());
+ for (QStringList::ConstIterator it = types.begin(); it != typeEnd; ++it) {
+ type |= mPhoneTypeMap[(*it).toUpper()];
+ foundType = true;
+ }
+ phone.setType(foundType ? type : PhoneNumber::Undefined);
+
+ addr.insertPhoneNumber(phone);
+ }
+
+ // TITLE
+ else if (identifier == QLatin1String("title")) {
+ addr.setTitle((*lineIt).value().toString());
+ }
+
+ // TZ
+ else if (identifier == QLatin1String("tz")) {
+ TimeZone tz;
+ const QString date = (*lineIt).value().toString();
+
+ if (!date.isEmpty()) {
+ int hours = date.midRef(1, 2).toInt();
+ int minutes = date.midRef(4, 2).toInt();
+ int offset = (hours * 60) + minutes;
+ offset = offset * (date[ 0 ] == QLatin1Char('+') ? 1 : -1);
+
+ tz.setOffset(offset);
+ addr.setTimeZone(tz);
+ }
+ }
+
+ // UID
+ else if (identifier == QLatin1String("uid")) {
+ addr.setUid((*lineIt).value().toString());
+ }
+
+ // URL
+ else if (identifier == QLatin1String("url")) {
+ const QUrl url = QUrl((*lineIt).value().toString());
+ ResourceLocatorUrl resourceLocatorUrl;
+ resourceLocatorUrl.setUrl(url);
+ resourceLocatorUrl.setParameters((*lineIt).parameterMap());
+ addr.insertExtraUrl(resourceLocatorUrl);
+ }
+ // SOURCE
+ else if (identifier == QLatin1String("source")) {
+ const QUrl url = QUrl((*lineIt).value().toString());
+ addr.insertSourceUrl(url);
+ }
+ // MEMBER (vcard 4.0)
+ else if (identifier == QLatin1String("member")) {
+ addr.insertMember((*lineIt).value().toString());
+ }
+ // RELATED (vcard 4.0)
+ else if (identifier == QLatin1String("related")) {
+ Related related;
+ related.setRelated((*lineIt).value().toString());
+ related.setParameters((*lineIt).parameterMap());
+ addr.insertRelationShip(related);
+ }
+ // X-
+ //TODO import X-GENDER
+ else if (identifier.startsWith(QLatin1String("x-"))) {
+ QString ident = (*lineIt).identifier();
+ //X-Evolution
+ if (identifier == QLatin1String("x-evolution-spouse") ||
+ identifier == QLatin1String("x-spouse")) {
+ ident = QStringLiteral("X-KADDRESSBOOK-X-SpousesName");
+ } else if (identifier == QLatin1String("x-evolution-blog-url")) {
+ ident = QStringLiteral("X-KADDRESSBOOK-BlogFeed");
+ } else if (identifier == QLatin1String("x-evolution-assistant") ||
+ identifier == QLatin1String("x-assistant")) {
+ ident = QStringLiteral("X-KADDRESSBOOK-X-AssistantsName");
+ } else if (identifier == QLatin1String("x-evolution-anniversary") ||
+ identifier == QLatin1String("x-anniversary")) {
+ ident = QStringLiteral("X-KADDRESSBOOK-X-Anniversary");
+ } else if (identifier == QLatin1String("x-evolution-manager") ||
+ identifier == QLatin1String("x-manager")) {
+ ident = QStringLiteral("X-KADDRESSBOOK-X-ManagersName");
+ } else if (identifier == QLatin1String("x-aim")) {
+ ident = QStringLiteral("X-messaging/aim-All");
+ } else if (identifier == QLatin1String("x-icq")) {
+ ident = QStringLiteral("X-messaging/icq-All");
+ } else if (identifier == QLatin1String("x-jabber")) {
+ ident = QStringLiteral("X-messaging/xmpp-All");
+ } else if (identifier == QLatin1String("x-jabber")) {
+ ident = QStringLiteral("X-messaging/xmpp-All");
+ } else if (identifier == QLatin1String("x-msn")) {
+ ident = QStringLiteral("X-messaging/msn-All");
+ } else if (identifier == QLatin1String("x-yahoo")) {
+ ident = QStringLiteral("X-messaging/yahoo-All");
+ } else if (identifier == QLatin1String("x-gadugadu")) {
+ ident = QStringLiteral("X-messaging/gadu-All");
+ } else if (identifier == QLatin1String("x-skype")) {
+ ident = QStringLiteral("X-messaging/skype-All");
+ } else if (identifier == QLatin1String("x-groupwise")) {
+ ident = QStringLiteral("X-messaging/groupwise-All");
+ } else if (identifier == QLatin1String("x-sms")) {
+ ident = QStringLiteral("X-messaging/sms-All");
+ } else if (identifier == QLatin1String("x-meanwhile")) {
+ ident = QStringLiteral("X-messaging/meanwhile-All");
+ } else if (identifier == QLatin1String("x-irc")) {
+ ident = QStringLiteral("X-messaging/irc-All");
+ } else if (identifier == QLatin1String("x-gtalk")) {
+ ident = QStringLiteral("X-messaging/googletalk-All");
+ } else if (identifier == QLatin1String("x-twitter")) {
+ ident = QStringLiteral("X-messaging/twitter-All");
+ }
+
+ const QString key = ident.mid(2);
+ const int dash = key.indexOf(QLatin1Char('-'));
+ addr.insertCustom(key.left(dash), key.mid(dash + 1),
+ (*lineIt).value().toString());
+ }
+ }
+ }
+
+ addrList.append(addr);
+ }
+
+ return addrList;
+}
+
+QDateTime VCardTool::parseDateTime(const QString &str) const
+{
+ QDate date;
+ QTime time;
+
+ if (str.indexOf(QLatin1Char('-')) == -1) { // is base format (yyyymmdd)
+ date = QDate(str.leftRef(4).toInt(), str.midRef(4, 2).toInt(),
+ str.midRef(6, 2).toInt());
+ } else { // is extended format yyyy-mm-dd
+ date = QDate(str.leftRef(4).toInt(), str.midRef(5, 2).toInt(),
+ str.midRef(8, 2).toInt());
+ }
+
+ // does it also contain a time ? (Note: mm, ss are optional according ISO-8601)
+ int timeStart = str.indexOf(QLatin1Char('T'));
+ if (timeStart >= 0) {
+ int hour = 0, minute = 0, second = 0;
+
+ hour = str.midRef(timeStart + 1, 2).toInt(); // hour must always be given
+
+ if (str.indexOf(QLatin1Char(':'), timeStart + 1) > 0) { // extended format (hh:mm:ss)
+ if (str.length() >= (timeStart + 5)) {
+ minute = str.midRef(timeStart + 4, 2).toInt();
+ if (str.length() >= (timeStart + 8)) {
+ second = str.midRef(timeStart + 7, 2).toInt();
+ }
+ }
+ } else { // basic format (hhmmss)
+ if (str.length() >= (timeStart + 4)) {
+ minute = str.midRef(timeStart + 3, 2).toInt();
+ if (str.length() >= (timeStart + 6)) {
+ second = str.midRef(timeStart + 5, 2).toInt();
+ }
+ }
+ }
+
+ time = QTime(hour, minute, second);
+ }
+
+ Qt::TimeSpec spec = (str.right(1) == QLatin1String("Z")) ? Qt::UTC : Qt::LocalTime;
+
+ QDateTime dateTime(date);
+
+ if (time.isValid()) {
+ dateTime.setTime(time);
+ }
+
+ dateTime.setTimeSpec(spec);
+ return dateTime;
+}
+
+QString VCardTool::createDateTime(const QDateTime &dateTime, VCard::Version version) const
+{
+ QString str;
+ if (version == VCard::v4_0) {
+ if (dateTime.date().isValid()) {
+ str.sprintf("%4d%02d%02d", dateTime.date().year(), dateTime.date().month(),
+ dateTime.date().day());
+ if (dateTime.time().isValid()) {
+ QString tmp;
+ tmp.sprintf("T%02d%02d%02d", dateTime.time().hour(), dateTime.time().minute(),
+ dateTime.time().second());
+ str += tmp;
+
+ if (dateTime.timeSpec() == Qt::UTC) {
+ str += QLatin1Char('Z');
+ }
+ }
+ }
+
+ } else {
+ if (dateTime.date().isValid()) {
+ str.sprintf("%4d-%02d-%02d", dateTime.date().year(), dateTime.date().month(),
+ dateTime.date().day());
+ if (dateTime.time().isValid()) {
+ QString tmp;
+ tmp.sprintf("T%02d:%02d:%02d", dateTime.time().hour(), dateTime.time().minute(),
+ dateTime.time().second());
+ str += tmp;
+
+ if (dateTime.timeSpec() == Qt::UTC) {
+ str += QLatin1Char('Z');
+ }
+ }
+ }
+ }
+ return str;
+}
+
+Picture VCardTool::parsePicture(const VCardLine &line) const
+{
+ Picture pic;
+
+ const QStringList params = line.parameterList();
+ QString type;
+ if (params.contains(QStringLiteral("type"))) {
+ type = line.parameter(QStringLiteral("type"));
+ }
+ if (params.contains(QStringLiteral("encoding"))) {
+ pic.setRawData(line.value().toByteArray(), type);
+ } else if (params.contains(QStringLiteral("value"))) {
+ if (line.parameter(QStringLiteral("value")).toLower() == QLatin1String("uri")) {
+ pic.setUrl(line.value().toString());
+ }
+ }
+
+ return pic;
+}
+
+VCardLine VCardTool::createPicture(const QString &identifier, const Picture &pic, VCard::Version version) const
+{
+ VCardLine line(identifier);
+
+ if (pic.isEmpty()) {
+ return line;
+ }
+
+ if (pic.isIntern()) {
+ line.setValue(pic.rawData());
+ if (version == VCard::v2_1) {
+ line.addParameter(QStringLiteral("ENCODING"), QStringLiteral("BASE64"));
+ line.addParameter(pic.type(), QString());
+ } else {
+ line.addParameter(QStringLiteral("encoding"), QStringLiteral("b"));
+ line.addParameter(QStringLiteral("type"), pic.type());
+ }
+ } else {
+ line.setValue(pic.url());
+ line.addParameter(QStringLiteral("value"), QStringLiteral("URI"));
+ }
+
+ return line;
+}
+
+Sound VCardTool::parseSound(const VCardLine &line) const
+{
+ Sound snd;
+
+ const QStringList params = line.parameterList();
+ if (params.contains(QStringLiteral("encoding"))) {
+ snd.setData(line.value().toByteArray());
+ } else if (params.contains(QStringLiteral("value"))) {
+ if (line.parameter(QStringLiteral("value")).toLower() == QLatin1String("uri")) {
+ snd.setUrl(line.value().toString());
+ }
+ }
+
+ /* TODO: support sound types
+ if ( params.contains( "type" ) )
+ snd.setType( line.parameter( "type" ) );
+ */
+
+ return snd;
+}
+
+VCardLine VCardTool::createSound(const Sound &snd, VCard::Version version) const
+{
+ Q_UNUSED(version);
+ VCardLine line(QStringLiteral("SOUND"));
+
+ if (snd.isIntern()) {
+ if (!snd.data().isEmpty()) {
+ line.setValue(snd.data());
+ if (version == VCard::v2_1) {
+ line.addParameter(QStringLiteral("ENCODING"), QStringLiteral("BASE64"));
+ } else {
+ line.addParameter(QStringLiteral("encoding"), QStringLiteral("b"));
+ }
+ // TODO: need to store sound type!!!
+ }
+ } else if (!snd.url().isEmpty()) {
+ line.setValue(snd.url());
+ line.addParameter(QStringLiteral("value"), QStringLiteral("URI"));
+ }
+
+ return line;
+}
+
+Key VCardTool::parseKey(const VCardLine &line) const
+{
+ Key key;
+
+ const QStringList params = line.parameterList();
+ if (params.contains(QStringLiteral("encoding"))) {
+ key.setBinaryData(line.value().toByteArray());
+ } else {
+ key.setTextData(line.value().toString());
+ }
+
+ if (params.contains(QStringLiteral("type"))) {
+ if (line.parameter(QStringLiteral("type")).toLower() == QLatin1String("x509")) {
+ key.setType(Key::X509);
+ } else if (line.parameter(QStringLiteral("type")).toLower() == QLatin1String("pgp")) {
+ key.setType(Key::PGP);
+ } else {
+ key.setType(Key::Custom);
+ key.setCustomTypeString(line.parameter(QStringLiteral("type")));
+ }
+ }
+
+ return key;
+}
+
+VCardLine VCardTool::createKey(const Key &key, VCard::Version version) const
+{
+ VCardLine line(QStringLiteral("KEY"));
+
+ if (key.isBinary()) {
+ if (!key.binaryData().isEmpty()) {
+ line.setValue(key.binaryData());
+ if (version == VCard::v2_1) {
+ line.addParameter(QStringLiteral("ENCODING"), QStringLiteral("BASE64"));
+ } else {
+ line.addParameter(QStringLiteral("encoding"), QStringLiteral("b"));
+ }
+ }
+ } else if (!key.textData().isEmpty()) {
+ line.setValue(key.textData());
+ }
+
+ if (key.type() == Key::X509) {
+ line.addParameter(QStringLiteral("type"), QStringLiteral("X509"));
+ } else if (key.type() == Key::PGP) {
+ line.addParameter(QStringLiteral("type"), QStringLiteral("PGP"));
+ } else if (key.type() == Key::Custom) {
+ line.addParameter(QStringLiteral("type"), key.customTypeString());
+ }
+
+ return line;
+}
+
+Secrecy VCardTool::parseSecrecy(const VCardLine &line) const
+{
+ Secrecy secrecy;
+
+ const QString value = line.value().toString().toLower();
+ if (value == QLatin1String("public")) {
+ secrecy.setType(Secrecy::Public);
+ } else if (value == QLatin1String("private")) {
+ secrecy.setType(Secrecy::Private);
+ } else if (value == QLatin1String("confidential")) {
+ secrecy.setType(Secrecy::Confidential);
+ }
+
+ return secrecy;
+}
+
+VCardLine VCardTool::createSecrecy(const Secrecy &secrecy) const
+{
+ VCardLine line(QStringLiteral("CLASS"));
+
+ int type = secrecy.type();
+
+ if (type == Secrecy::Public) {
+ line.setValue(QLatin1String("PUBLIC"));
+ } else if (type == Secrecy::Private) {
+ line.setValue(QLatin1String("PRIVATE"));
+ } else if (type == Secrecy::Confidential) {
+ line.setValue(QLatin1String("CONFIDENTIAL"));
+ }
+
+ return line;
+}
+
+QStringList VCardTool::splitString(QChar sep, const QString &str) const
+{
+ QStringList list;
+ QString value(str);
+
+ int start = 0;
+ int pos = value.indexOf(sep, start);
+
+ while (pos != -1) {
+ if (pos == 0 || value[ pos - 1 ] != QLatin1Char('\\')) {
+ if (pos > start && pos <= (int)value.length()) {
+ list << value.mid(start, pos - start);
+ } else {
+ list << QString();
+ }
+
+ start = pos + 1;
+ pos = value.indexOf(sep, start);
+ } else {
+ value.replace(pos - 1, 2, sep);
+ pos = value.indexOf(sep, pos);
+ }
+ }
+
+ int l = value.length() - 1;
+ const QString mid = value.mid(start, l - start + 1);
+ if (!mid.isEmpty()) {
+ list << mid;
+ } else {
+ list << QString();
+ }
+
+ return list;
+}
--- /dev/null
+/*
+ This file is part of the KContacts framework.
+ Copyright (c) 2003 Tobias Koenig <tokoe@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KCONTACTS_VCARDTOOL_H
+#define KCONTACTS_VCARDTOOL_H
+
+#include "kcontacts_export.h"
+#include "addressee.h"
+#include "vcardparser/vcardparser.h"
+
+class QDateTime;
+
+namespace KContacts
+{
+
+class Key;
+class Picture;
+class Secrecy;
+class Sound;
+
+class KCONTACTS_EXPORT VCardTool
+{
+public:
+ VCardTool();
+ ~VCardTool();
+
+ /**
+ Creates a string that contains the addressees from the list in
+ the vCard format.
+ */
+ QByteArray createVCards(const Addressee::List &list,
+ VCard::Version version = VCard::v3_0) const;
+
+ /**
+ * @since 4.9.1
+ */
+ QByteArray exportVCards(const Addressee::List &list,
+ VCard::Version version = VCard::v3_0) const;
+ /**
+ Parses the string and returns a list of addressee objects.
+ */
+ Addressee::List parseVCards(const QByteArray &vcard) const;
+
+private:
+
+ QByteArray createVCards(const Addressee::List &list,
+ VCard::Version version, bool exportVcard) const;
+
+ /**
+ Split a string and replaces escaped separators on the fly with
+ unescaped ones.
+ */
+ QStringList splitString(QChar sep, const QString &value) const;
+
+ QDateTime parseDateTime(const QString &str) const;
+ QString createDateTime(const QDateTime &dateTime, VCard::Version version) const;
+
+ Picture parsePicture(const VCardLine &line) const;
+ VCardLine createPicture(const QString &identifier, const Picture &pic, VCard::Version version) const;
+
+ Sound parseSound(const VCardLine &line) const;
+ VCardLine createSound(const Sound &snd, VCard::Version version) const;
+
+ Key parseKey(const VCardLine &line) const;
+ VCardLine createKey(const Key &key, VCard::Version version) const;
+
+ Secrecy parseSecrecy(const VCardLine &line) const;
+ VCardLine createSecrecy(const Secrecy &secrecy) const;
+
+ void addParameter(VCardLine &line, VCard::Version version, const QString &key, const QStringList &valueStringList) const;
+
+ QMap<QString, Address::TypeFlag> mAddressTypeMap;
+ QMap<QString, PhoneNumber::TypeFlag> mPhoneTypeMap;
+
+ Q_DISABLE_COPY(VCardTool)
+ class VCardToolPrivate;
+ VCardToolPrivate *d;
+};
+
+}
+
+#endif
--- /dev/null
+# FIXME: Make it build with this flag
+remove_definitions(-DQT_NO_CAST_FROM_BYTEARRAY)
+
+include(ECMMarkAsTest)
+
+########### next target ###############
+
+# FIXME: Build fails
+set(testread_SRCS testread.cpp)
+add_executable(testread ${testread_SRCS})
+target_link_libraries(testread KF5Contacts KF5::I18n Qt5::Gui)
+
+########### next target ###############
+
+# FIXME: Build fails
+set(testwrite_SRCS testwrite.cpp)
+add_executable(testwrite ${testwrite_SRCS})
+target_link_libraries(testwrite KF5Contacts Qt5::Gui KF5::I18n)
+
+########### next target ###############
+
+set(testread2_SRCS testread2.cpp testutils.cpp)
+add_executable(testread2 ${testread2_SRCS})
+target_link_libraries(testread2 KF5Contacts Qt5::Gui)
--- /dev/null
+For testing the vcardparser there are some test files and a small testsuite
+automatically checking for regressions. The tests directory contains some vCard
+files and correpsonding reference output files (with an additional ".ref"
+suffix). For running the geression test do "./testroundtrip" or simply run "ctest".
+
+For creating a new test put a vCard file to be parsed into the tests directory.
+Create a reference file by running "testread" on the test file. It will put out
+the parsed data as vCard again on stdout. Carefully check the output, manually
+correct any errors and save the result as reference file in the tests directory.
+Now add the filename to the testroundtrip.qrc resource file and run
+"make && ./roundtriptest" If the check fails adapt the reference file or fix the bugs
+in the parser, whatever is appropriate.
--- /dev/null
+#!/usr/bin/perl
+
+if ( @ARGV != 1 ) {
+ print STDERR "Missing arg: filename\n";
+ system "touch FAILED";
+ exit 1;
+}
+
+$file = $ARGV[0];
+
+if ( !open( IN, "$file" ) ) {
+ print STDERR "Unable to open '$file'\n";
+ system "touch FAILED";
+ exit 1;
+}
+
+while( <IN> ) {
+ if (/^VERSION:(.*)$/ ) {
+ $version = $1;
+ if ( $version eq "2.1" ) { $options = "--vcard21"; }
+ }
+}
+
+close IN;
+
+$ref = "$file.ref";
+
+if ( !open( REF, "$ref" ) ) {
+ print STDERR "Unable to open $ref\n";
+ system "touch FAILED";
+ exit 1;
+}
+
+while( <REF> ) {
+ push @ref, $_;
+}
+
+close REF;
+
+if ( !open( READ, "./testread $file $options 2> /dev/null |" ) ) {
+ print STDERR "Unable to open testread\n";
+ system "touch FAILED";
+ exit 1;
+}
+
+print "Checking '$file':\n";
+
+$gotsomething = 0;
+$error = 0;
+$i = 0;
+while( <READ> ) {
+ $gotsomething = 1;
+ $out = $_;
+ $ref = @ref[$i++];
+
+ if ( $out ne $ref ) {
+ if ( $ref =~ /^UID/ && $out =~ /^UID/ ) { next; }
+ $error++;
+ print " Expected : $ref";
+ print " Parser output : $out";
+ }
+}
+
+close READ;
+
+if ( $gotsomething == 0 ) {
+ print "\n FAILED: testread didn't output anything\n";
+ system "touch FAILED";
+ exit 1;
+}
+if ( $error > 0 ) {
+ print "\n FAILED: $error errors found.\n";
+ system "touch FAILED";
+ exit 1;
+} else {
+ print " OK\n";
+}
+
+exit 0;
--- /dev/null
+/*
+ This file is part of the KContacts framework.
+ Copyright (c) 2007 KDE-PIM team <kde-pim@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <iostream>
+#include <stdlib.h>
+
+#include <QtCore/QFile>
+
+#include <qdebug.h>
+#include <KAboutData>
+#include <QCoreApplication>
+#include <klocalizedstring.h>
+#include <QCommandLineParser>
+#include <QCommandLineOption>
+
+#include "converter/kcontacts/vcardconverter.h"
+#include "vcard.h"
+
+int main(int argc, char **argv)
+{
+ KAboutData aboutData(QStringLiteral("testread"), i18n("vCard test reader"), QStringLiteral("0.1"));
+ aboutData.addAuthor(i18n("Cornelius Schumacher"), QString(), QStringLiteral("schumacher@kde.org"));
+
+ QCoreApplication app(argc, argv);
+ QCommandLineParser parser;
+ parser.addOption(QCommandLineOption(QStringList() << QStringLiteral("vcard21"), i18n("vCard 2.1")));
+ parser.addOption(QCommandLineOption(QStringList() << QStringLiteral("+inputfile"), i18n("Input file")));
+
+ KAboutData::setApplicationData(aboutData);
+ parser.addVersionOption();
+ parser.addHelpOption();
+ aboutData.setupCommandLine(&parser);
+ parser.process(app);
+ aboutData.processCommandLine(&parser);
+
+ if (parser.positionalArguments().count() != 1) {
+ std::cerr << "Missing argument" << std::endl;
+ return 1;
+ }
+
+ QString inputFile(parser.positionalArguments().at(0));
+
+ QFile file(inputFile);
+ if (!file.open(QIODevice::ReadOnly)) {
+ qDebug("Unable to open file '%s' for reading!", qPrintable(file.fileName()));
+ return 1;
+ }
+
+ QByteArray text = file.readAll();
+ file.close();
+
+ KContacts::VCardConverter converter;
+ KContacts::Addressee::List list = converter.parseVCards(text);
+
+ if (parser.isSet(QStringLiteral("vcard21"))) {
+ text = converter.createVCards(list, KContacts::VCardConverter::v2_1); // uses version 2.1
+ } else {
+ text = converter.createVCards(list); // uses version 3.0
+ }
+
+ std::cout << text.data();
+
+ return 0;
+}
--- /dev/null
+/*
+ This file is part of the KContacts framework.
+ Copyright (c) 2007 KDE-PIM team <kde-pim@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "testutils.h"
+#include <kcontacts/addressee.h>
+#include <converter/kcontacts/vcardconverter.h>
+#include <qdebug.h>
+
+using namespace KContacts;
+
+int main()
+{
+ Addressee::List l = vCardsAsAddresseeList();
+ QByteArray vcards = vCardsAsText();
+
+ VCardConverter vct;
+
+ Addressee::List parsed = vct.parseVCards(vcards);
+
+ if (l.size() != parsed.size()) {
+ qDebug() << "\tSize - FAILED :" << l.size() << "vs. parsed" << parsed.size();
+ } else {
+ qDebug() << "\tSize - PASSED";
+ }
+
+ Addressee::List::iterator itr1;
+ Addressee::List::iterator itr2;
+ for (itr1 = l.begin(), itr2 = parsed.begin();
+ itr1 != l.end() && itr2 != parsed.end(); ++itr1, ++itr2) {
+ if ((*itr1).fullEmail() == (*itr2).fullEmail() &&
+ (*itr1).organization() == (*itr2).organization() &&
+ (*itr1).phoneNumbers() == (*itr2).phoneNumbers() &&
+ (*itr1).emails() == (*itr2).emails() &&
+ (*itr1).role() == (*itr2).role()) {
+ qDebug() << "\tAddressee - PASSED";
+ qDebug() << "\t\t" << (*itr1).fullEmail() << "VS." << (*itr2).fullEmail();
+ } else {
+ qDebug() << "\tAddressee - FAILED";
+ qDebug() << (*itr1).toString();
+ qDebug() << (*itr2).toString();
+ //qDebug()<<"\t\t"<< (*itr1).fullEmail() << "VS." << (*itr2).fullEmail();
+ }
+ }
+}
--- /dev/null
+/*
+ This file is part of the KContacts framework.
+ Copyright (c) 2007 KDE-PIM team <kde-pim@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <QtCore/QFile>
+
+#include <kcontacts/addressee.h>
+
+#include "vcardparser.h"
+
+using namespace KContacts;
+
+Addressee vcard1()
+{
+ Addressee addr;
+
+ addr.setName(QStringLiteral("Frank Dawson"));
+ addr.setOrganization(QStringLiteral("Lotus Development Corporation"));
+ KContacts::ResourceLocatorUrl url;
+ url.setUrl(QUrl(QStringLiteral("http://home.earthlink.net/~fdawson")));
+ addr.setUrl(url);
+ addr.insertEmail(QStringLiteral("fdawson@earthlink.net"));
+ addr.insertEmail(QStringLiteral("Frank_Dawson@Lotus.com"), true);
+ addr.insertPhoneNumber(PhoneNumber(QStringLiteral("+1-919-676-9515"),
+ PhoneNumber::Voice | PhoneNumber::Msg | PhoneNumber::Work));
+ addr.insertPhoneNumber(PhoneNumber(QStringLiteral("+1-919-676-9564"),
+ PhoneNumber::Fax | PhoneNumber::Work));
+ Address a(Address::Work | Address::Postal | Address::Parcel);
+ a.setStreet(QStringLiteral("6544 Battleford Drive"));
+ a.setLocality(QStringLiteral("Raleigh"));
+ a.setRegion(QStringLiteral("NC"));
+ a.setPostalCode(QStringLiteral("27613-3502"));
+ a.setCountry(QStringLiteral("U.S.A."));
+ addr.insertAddress(a);
+ return addr;
+}
+
+Addressee vcard2()
+{
+ Addressee addr;
+
+ addr.setName(QStringLiteral("Tim Howes"));
+ addr.setOrganization(QStringLiteral("Netscape Communications Corp."));
+ addr.insertEmail(QStringLiteral("howes@netscape.com"));
+ addr.insertPhoneNumber(PhoneNumber(QStringLiteral("+1-415-937-3419"),
+ PhoneNumber::Voice | PhoneNumber::Msg | PhoneNumber::Work));
+ addr.insertPhoneNumber(PhoneNumber(QStringLiteral("+1-415-528-4164"),
+ PhoneNumber::Fax | PhoneNumber::Work));
+ Address a(Address::Work);
+ a.setStreet(QStringLiteral("501 E. Middlefield Rd."));
+ a.setLocality(QStringLiteral("Mountain View"));
+ a.setRegion(QStringLiteral("CA"));
+ a.setPostalCode(QStringLiteral("94043"));
+ a.setCountry(QStringLiteral("U.S.A."));
+ addr.insertAddress(a);
+ return addr;
+}
+
+Addressee vcard3()
+{
+ Addressee addr;
+
+ addr.setName(QStringLiteral("ian geiser"));
+ addr.setOrganization(QStringLiteral("Source eXtreme"));
+ addr.insertEmail(QStringLiteral("geiseri@yahoo.com"));
+ addr.setTitle(QStringLiteral("VP of Engineering"));
+ return addr;
+}
+
+QByteArray vcardAsText(const QString &location)
+{
+ QByteArray text;
+
+ QFile file(location);
+ if (file.open(QIODevice::ReadOnly)) {
+ text = file.readAll();
+ file.close();
+ }
+
+ return text;
+}
+
+Addressee::List vCardsAsAddresseeList()
+{
+ Addressee::List l;
+
+ l.append(vcard1());
+ l.append(vcard2());
+ l.append(vcard3());
+
+ return l;
+}
+
+QByteArray vCardsAsText()
+{
+ QByteArray vcards = vcardAsText(QStringLiteral("tests/vcard1.vcf"));
+ vcards += vcardAsText(QStringLiteral("tests/vcard2.vcf"));
+ vcards += vcardAsText(QStringLiteral("tests/vcard3.vcf"));
+
+ return vcards;
+}
--- /dev/null
+/*
+ This file is part of the KContacts framework.
+ Copyright (c) 2007 KDE-PIM team <kde-pim@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef TESTUTILS_H
+#define TESTUTILS_H
+
+#include <QtCore/QByteArray>
+#include <QtCore/QString>
+
+#include <kcontacts/addressee.h>
+
+KContacts::Addressee vcard1();
+KContacts::Addressee vcard2();
+KContacts::Addressee vcard3();
+KContacts::Addressee::List vCardsAsAddresseeList();
+QByteArray vCardAsText(const QString &location);
+QByteArray vCardsAsText();
+
+#endif
--- /dev/null
+/*
+ This file is part of the KContacts framework.
+ Copyright (c) 2007 KDE-PIM team <kde-pim@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <QtCore/QFile>
+
+#include <kaboutdata.h>
+#include <klocalizedstring.h>
+
+#include <QCoreApplication>
+#include <KAboutData>
+#include <QCommandLineParser>
+
+#include "kcontacts/addressee.h"
+#include "kcontacts/phonenumber.h"
+#include "kcontacts/address.h"
+#include "kcontacts/key.h"
+#include "kcontacts/picture.h"
+#include "kcontacts/sound.h"
+#include "kcontacts/secrecy.h"
+#include "converter/kcontacts/vcardconverter.h"
+
+int main(int argc, char **argv)
+{
+ KAboutData aboutData(QLatin1String("testwrite"), i18n("vCard test writer"), QLatin1String("0.1"));
+
+ QCoreApplication app(argc, argv);
+ QCommandLineParser parser;
+ KAboutData::setApplicationData(aboutData);
+ parser.addVersionOption();
+ parser.addHelpOption();
+ aboutData.setupCommandLine(&parser);
+ parser.process(app);
+ aboutData.processCommandLine(&parser);
+
+ KContacts::Addressee addressee;
+
+ addressee.setNameFromString(QLatin1String("Mr. Tobias Koenig Jr."));
+ addressee.setNickName(QLatin1String("tokoe"));
+ addressee.setBirthday(QDateTime(QDate(1982, 7, 19)));
+ addressee.setMailer(QLatin1String("mutt1.2"));
+ addressee.setTimeZone(KContacts::TimeZone(+2));
+
+ KContacts::Geo geo;
+ geo.setLatitude(30);
+ geo.setLongitude(51);
+ addressee.setGeo(geo);
+
+ addressee.setTitle(QLatin1String("nerd"));
+ addressee.setRole(QLatin1String("Maintainer"));
+ addressee.setOrganization(QLatin1String("KDE"));
+ addressee.setNote(QLatin1String("nerver\ntouch a running system"));
+ addressee.setProductId(QLatin1String("testId"));
+ addressee.setRevision(QDateTime::currentDateTime());
+ addressee.setSortString(QLatin1String("koenig"));
+ KContacts::ResourceLocatorUrl url;
+ url.setUrl(QUrl(QLatin1String("http://wgess16.dyndns.org")));
+ addressee.setUrl(url);
+ addressee.setSecrecy(KContacts::Secrecy(KContacts::Secrecy::Confidential));
+
+ addressee.insertEmail(QLatin1String("tokoe@kde.org"), true);
+ addressee.insertEmail(QLatin1String("tokoe82@yahoo.de"), true);
+
+ KContacts::PhoneNumber phone1(QLatin1String("3541523475"),
+ KContacts::PhoneNumber::Pref | KContacts::PhoneNumber::Home);
+ KContacts::PhoneNumber phone2(QLatin1String("+46745673475"),
+ KContacts::PhoneNumber::Work);
+ addressee.insertPhoneNumber(phone1);
+ addressee.insertPhoneNumber(phone2);
+
+ KContacts::Key key(QLatin1String("secret key"), KContacts::Key::X509);
+ addressee.insertKey(key);
+
+ QStringList categories;
+ categories << QLatin1String("Friends") << QLatin1String("School") << QLatin1String("KDE");
+ addressee.setCategories(categories);
+
+ KContacts::Address a(KContacts::Address::Work | KContacts::Address::Postal | KContacts::Address::Parcel);
+ a.setStreet(QLatin1String("6544 Battleford Drive"));
+ a.setLocality(QLatin1String("Raleigh"));
+ a.setRegion(QLatin1String("NC"));
+ a.setPostalCode(QLatin1String("27613-3502"));
+ a.setCountry(QLatin1String("U.S.A."));
+ addressee.insertAddress(a);
+
+ addressee.insertCustom(QLatin1String("1hsdf"), QLatin1String("ertuer"),
+ QLatin1String("iurt"));
+ addressee.insertCustom(QLatin1String("2hsdf"), QLatin1String("ertuer"),
+ QLatin1String("iurt"));
+ addressee.insertCustom(QLatin1String("3hsdf"), QLatin1String("ertuer"),
+ QLatin1String("iurt"));
+
+ KContacts::Addressee::List list;
+ for (int i = 0; i < 1000; ++i) {
+ KContacts::Addressee addr = addressee;
+ addr.setUid(QString::number(i));
+ list.append(addr);
+ }
+
+ KContacts::VCardConverter converter;
+ QByteArray txt = converter.createVCards(list);
+
+ QFile file(QLatin1String("out.vcf"));
+ if (!file.open(QIODevice::WriteOnly)) {
+ qDebug("Can't open file '%s' fro writing", qPrintable(file.fileName()));
+ return 1;
+ }
+
+ file.write(txt);
+ file.close();
+
+ return 0;
+}