--- /dev/null
+# Ignore the following files
+*~
+*.[oa]
+*.diff
+*.kate-swp
+*.kdev4
+.kdev_include_paths
+*.kdevelop.pcs
+*.moc
+*.moc.cpp
+*.orig
+*.user
+.*.swp
+.swp.*
+Doxyfile
+Makefile
+/build*/
+.cmake/
+CMakeLists.txt.user*
+*.unc-backup*
+/.clang-format
+/compile_commands.json
+.clangd
+.idea
+/cmake-build*
+.cache
--- /dev/null
+# SPDX-FileCopyrightText: 2020 Volker Krause <vkrause@kde.org>
+# SPDX-License-Identifier: CC0-1.0
+
+include:
+ - https://invent.kde.org/sysadmin/ci-utilities/raw/master/gitlab-templates/linux.yml
+ - https://invent.kde.org/sysadmin/ci-utilities/raw/master/gitlab-templates/android.yml
+ - https://invent.kde.org/sysadmin/ci-utilities/raw/master/gitlab-templates/freebsd.yml
+ - https://invent.kde.org/sysadmin/ci-utilities/raw/master/gitlab-templates/linux-qt6.yml
+ - https://invent.kde.org/sysadmin/ci-utilities/raw/master/gitlab-templates/android-qt6.yml
+ - https://invent.kde.org/sysadmin/ci-utilities/raw/master/gitlab-templates/windows.yml
+ - https://invent.kde.org/sysadmin/ci-utilities/raw/master/gitlab-templates/freebsd-qt6.yml
+ - https://invent.kde.org/sysadmin/ci-utilities/raw/master/gitlab-templates/windows-qt6.yml
--- /dev/null
+Dependencies:
+- 'on': ['@all']
+ 'require':
+ 'frameworks/extra-cmake-modules': '@same'
+ 'frameworks/kio' : '@same'
+
+Options:
+ test-before-installing: True
+ require-passing-tests-on: [ 'Linux', 'FreeBSD' ]
--- /dev/null
+cmake_minimum_required(VERSION 3.16)
+
+set(KF_VERSION "5.102.0") # handled by release scripts
+set(KF_DEP_VERSION "5.102.0") # handled by release scripts
+
+project(libkdav VERSION ${KF_VERSION})
+
+find_package(ECM 5.102.0 CONFIG REQUIRED)
+set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH})
+
+include(KDEInstallDirs)
+include(KDECMakeSettings)
+include(KDEGitCommitHooks)
+include(KDEFrameworkCompilerSettings NO_POLICY_SCOPE)
+
+include(CMakeFindDependencyMacro)
+include(ECMSetupVersion)
+include(GenerateExportHeader)
+include(ECMGenerateHeaders)
+include(ECMGeneratePriFile)
+include(FeatureSummary)
+include(ECMAddQch)
+include(ECMAddTests)
+include(ECMInstallIcons)
+include(ECMQtDeclareLoggingCategory)
+include(ECMDeprecationSettings)
+
+
+set(REQUIRED_QT_VERSION 5.15.2)
+find_package(Qt${QT_MAJOR_VERSION} ${REQUIRED_QT_VERSION} CONFIG REQUIRED Core Gui Test)
+
+find_package(KF5 ${KF_DEP_VERSION} REQUIRED CoreAddons KIO I18n)
+
+# setup lib
+
+option(BUILD_QCH "Build API documentation in QCH format (for e.g. Qt Assistant, Qt Creator & KDevelop)" OFF)
+add_feature_info(QCH ${BUILD_QCH} "API documentation in QCH format (for e.g. Qt Assistant, Qt Creator & KDevelop)")
+
+ecm_set_disabled_deprecation_versions(
+ QT 5.15.2
+ KF 5.95
+)
+
+ecm_setup_version(PROJECT VARIABLE_PREFIX KDAV
+ VERSION_HEADER "${CMAKE_CURRENT_BINARY_DIR}/kdav_version.h"
+ PACKAGE_VERSION_FILE "${CMAKE_CURRENT_BINARY_DIR}/KF5DAVConfigVersion.cmake"
+ SOVERSION 5
+ )
+
+ki18n_install(po)
+
+add_subdirectory(src)
+if(BUILD_TESTING)
+ add_subdirectory(autotests)
+ add_subdirectory(test)
+endif()
+
+set(CMAKECONFIG_INSTALL_DIR "${KDE_INSTALL_CMAKEPACKAGEDIR}/KF5DAV")
+
+if (BUILD_QCH)
+ ecm_install_qch_export(
+ TARGETS KF5DAV_QCH
+ FILE KF5DAVQchTargets.cmake
+ DESTINATION "${CMAKECONFIG_INSTALL_DIR}"
+ COMPONENT Devel
+ )
+ set(PACKAGE_INCLUDE_QCHTARGETS "include(\"\${CMAKE_CURRENT_LIST_DIR}/KF5DAVQchTargets.cmake\")")
+endif()
+
+configure_package_config_file(
+ "${CMAKE_CURRENT_SOURCE_DIR}/KF5DAVConfig.cmake.in"
+ "${CMAKE_CURRENT_BINARY_DIR}/KF5DAVConfig.cmake"
+ INSTALL_DESTINATION ${CMAKECONFIG_INSTALL_DIR}
+ )
+
+install(FILES
+ "${CMAKE_CURRENT_BINARY_DIR}/KF5DAVConfig.cmake"
+ "${CMAKE_CURRENT_BINARY_DIR}/KF5DAVConfigVersion.cmake"
+ DESTINATION "${CMAKECONFIG_INSTALL_DIR}"
+ COMPONENT Devel
+ )
+
+install(EXPORT KF5DAVTargets DESTINATION "${CMAKECONFIG_INSTALL_DIR}" FILE KF5DAVTargets.cmake NAMESPACE KF5::)
+
+install(FILES
+ ${CMAKE_CURRENT_BINARY_DIR}/kdav_version.h
+ DESTINATION ${KDE_INSTALL_INCLUDEDIR_KF}/KDAV COMPONENT Devel
+ )
+
+
+feature_summary(WHAT ALL
+ INCLUDE_QUIET_PACKAGES
+ FATAL_ON_MISSING_REQUIRED_PACKAGES
+)
+
+kde_configure_git_pre_commit_hook(CHECKS CLANG_FORMAT)
--- /dev/null
+@PACKAGE_INIT@
+
+include(CMakeFindDependencyMacro)
+find_dependency(KF5CoreAddons "@KF_DEP_VERSION@")
+
+include("${CMAKE_CURRENT_LIST_DIR}/KF5DAVTargets.cmake")
+@PACKAGE_INCLUDE_QCHTARGETS@
--- /dev/null
+Creative Commons Legal Code
+
+CC0 1.0 Universal
+
+ CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
+ LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN
+ ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
+ INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
+ REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS
+ PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM
+ THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED
+ HEREUNDER.
+
+Statement of Purpose
+
+The laws of most jurisdictions throughout the world automatically confer
+exclusive Copyright and Related Rights (defined below) upon the creator
+and subsequent owner(s) (each and all, an "owner") of an original work of
+authorship and/or a database (each, a "Work").
+
+Certain owners wish to permanently relinquish those rights to a Work for
+the purpose of contributing to a commons of creative, cultural and
+scientific works ("Commons") that the public can reliably and without fear
+of later claims of infringement build upon, modify, incorporate in other
+works, reuse and redistribute as freely as possible in any form whatsoever
+and for any purposes, including without limitation commercial purposes.
+These owners may contribute to the Commons to promote the ideal of a free
+culture and the further production of creative, cultural and scientific
+works, or to gain reputation or greater distribution for their Work in
+part through the use and efforts of others.
+
+For these and/or other purposes and motivations, and without any
+expectation of additional consideration or compensation, the person
+associating CC0 with a Work (the "Affirmer"), to the extent that he or she
+is an owner of Copyright and Related Rights in the Work, voluntarily
+elects to apply CC0 to the Work and publicly distribute the Work under its
+terms, with knowledge of his or her Copyright and Related Rights in the
+Work and the meaning and intended legal effect of CC0 on those rights.
+
+1. Copyright and Related Rights. A Work made available under CC0 may be
+protected by copyright and related or neighboring rights ("Copyright and
+Related Rights"). Copyright and Related Rights include, but are not
+limited to, the following:
+
+ i. the right to reproduce, adapt, distribute, perform, display,
+ communicate, and translate a Work;
+ ii. moral rights retained by the original author(s) and/or performer(s);
+iii. publicity and privacy rights pertaining to a person's image or
+ likeness depicted in a Work;
+ iv. rights protecting against unfair competition in regards to a Work,
+ subject to the limitations in paragraph 4(a), below;
+ v. rights protecting the extraction, dissemination, use and reuse of data
+ in a Work;
+ vi. database rights (such as those arising under Directive 96/9/EC of the
+ European Parliament and of the Council of 11 March 1996 on the legal
+ protection of databases, and under any national implementation
+ thereof, including any amended or successor version of such
+ directive); and
+vii. other similar, equivalent or corresponding rights throughout the
+ world based on applicable law or treaty, and any national
+ implementations thereof.
+
+2. Waiver. To the greatest extent permitted by, but not in contravention
+of, applicable law, Affirmer hereby overtly, fully, permanently,
+irrevocably and unconditionally waives, abandons, and surrenders all of
+Affirmer's Copyright and Related Rights and associated claims and causes
+of action, whether now known or unknown (including existing as well as
+future claims and causes of action), in the Work (i) in all territories
+worldwide, (ii) for the maximum duration provided by applicable law or
+treaty (including future time extensions), (iii) in any current or future
+medium and for any number of copies, and (iv) for any purpose whatsoever,
+including without limitation commercial, advertising or promotional
+purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each
+member of the public at large and to the detriment of Affirmer's heirs and
+successors, fully intending that such Waiver shall not be subject to
+revocation, rescission, cancellation, termination, or any other legal or
+equitable action to disrupt the quiet enjoyment of the Work by the public
+as contemplated by Affirmer's express Statement of Purpose.
+
+3. Public License Fallback. Should any part of the Waiver for any reason
+be judged legally invalid or ineffective under applicable law, then the
+Waiver shall be preserved to the maximum extent permitted taking into
+account Affirmer's express Statement of Purpose. In addition, to the
+extent the Waiver is so judged Affirmer hereby grants to each affected
+person a royalty-free, non transferable, non sublicensable, non exclusive,
+irrevocable and unconditional license to exercise Affirmer's Copyright and
+Related Rights in the Work (i) in all territories worldwide, (ii) for the
+maximum duration provided by applicable law or treaty (including future
+time extensions), (iii) in any current or future medium and for any number
+of copies, and (iv) for any purpose whatsoever, including without
+limitation commercial, advertising or promotional purposes (the
+"License"). The License shall be deemed effective as of the date CC0 was
+applied by Affirmer to the Work. Should any part of the License for any
+reason be judged legally invalid or ineffective under applicable law, such
+partial invalidity or ineffectiveness shall not invalidate the remainder
+of the License, and in such case Affirmer hereby affirms that he or she
+will not (i) exercise any of his or her remaining Copyright and Related
+Rights in the Work or (ii) assert any associated claims and causes of
+action with respect to the Work, in either case contrary to Affirmer's
+express Statement of Purpose.
+
+4. Limitations and Disclaimers.
+
+ a. No trademark or patent rights held by Affirmer are waived, abandoned,
+ surrendered, licensed or otherwise affected by this document.
+ b. Affirmer offers the Work as-is and makes no representations or
+ warranties of any kind concerning the Work, express, implied,
+ statutory or otherwise, including without limitation warranties of
+ title, merchantability, fitness for a particular purpose, non
+ infringement, or the absence of latent or other defects, accuracy, or
+ the present or absence of errors, whether or not discoverable, all to
+ the greatest extent permissible under applicable law.
+ c. Affirmer disclaims responsibility for clearing rights of other persons
+ that may apply to the Work or any use thereof, including without
+ limitation any person's Copyright and Related Rights in the Work.
+ Further, Affirmer disclaims responsibility for obtaining any necessary
+ consents, permissions or other rights required for any use of the
+ Work.
+ d. Affirmer understands and acknowledges that Creative Commons is not a
+ party to this document and has no duty or obligation with respect to
+ this CC0 or use of the Work.
--- /dev/null
+GNU GENERAL PUBLIC LICENSE
+
+Version 2, June 1991
+
+Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+
+Everyone is permitted to copy and distribute verbatim copies of this license
+document, but changing it is not allowed.
+
+Preamble
+
+The licenses for most software are designed to take away your freedom to share
+and change it. By contrast, the GNU General Public License is intended to
+guarantee your freedom to share and change free software--to make sure the
+software is free for all its users. This General Public License applies to
+most of the Free Software Foundation's software and to any other program whose
+authors commit to using it. (Some other Free Software Foundation software
+is covered by the GNU Lesser General Public License instead.) You can apply
+it to your programs, too.
+
+When we speak of free software, we are referring to freedom, 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 or use pieces of it in new free programs; and that
+you know you can do these things.
+
+To protect your rights, we need to make restrictions that forbid anyone to
+deny you these rights or to ask you to surrender the rights. These restrictions
+translate to certain responsibilities for you if you distribute copies of
+the software, or if you modify it.
+
+For example, if you distribute copies of such a program, whether gratis or
+for a fee, you must give the recipients all the rights that you have. You
+must make sure that they, too, receive or can get the source code. And you
+must show them these terms so they know their rights.
+
+We protect your rights with two steps: (1) copyright the software, and (2)
+offer you this license which gives you legal permission to copy, distribute
+and/or modify the software.
+
+Also, for each author's protection and ours, we want to make certain that
+everyone understands that there is no warranty for this free software. If
+the software is modified by someone else and passed on, we want its recipients
+to know that what they have is not the original, so that any problems introduced
+by others will not reflect on the original authors' reputations.
+
+Finally, any free program is threatened constantly by software patents. We
+wish to avoid the danger that redistributors of a free program will individually
+obtain patent licenses, in effect making the program proprietary. To prevent
+this, we have made it clear that any patent must be licensed for everyone's
+free use or not licensed at all.
+
+The precise terms and conditions for copying, distribution and modification
+follow.
+
+TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+0. This License applies to any program or other work which contains a notice
+placed by the copyright holder saying it may be distributed under the terms
+of this General Public License. The "Program", below, refers to any such program
+or work, and a "work based on the Program" means either the Program or any
+derivative work under copyright law: that is to say, a work containing the
+Program or a portion of it, either verbatim or with modifications and/or translated
+into another language. (Hereinafter, translation is included without limitation
+in the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not covered
+by this License; they are outside its scope. The act of running the Program
+is not restricted, and the output from the Program is covered only if its
+contents constitute a work based on the Program (independent of having been
+made by running the Program). Whether that is true depends on what the Program
+does.
+
+1. You may copy and distribute verbatim copies of the Program's 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 give any other recipients of the Program a copy of this
+License along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and you
+may at your option offer warranty protection in exchange for a fee.
+
+2. You may modify your copy or copies of the Program or any portion of it,
+thus forming a work based on the Program, 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) You must cause the modified files to carry prominent notices stating that
+you changed the files and the date of any change.
+
+b) You must cause any work that you distribute or publish, that in whole or
+in part contains or is derived from the Program or any part thereof, to be
+licensed as a whole at no charge to all third parties under the terms of this
+License.
+
+c) If the modified program normally reads commands interactively when run,
+you must cause it, when started running for such interactive use in the most
+ordinary way, to print or display an announcement including an appropriate
+copyright notice and a notice that there is no warranty (or else, saying that
+you provide a warranty) and that users may redistribute the program under
+these conditions, and telling the user how to view a copy of this License.
+(Exception: if the Program itself is interactive but does not normally print
+such an announcement, your work based on the Program is not required to print
+an announcement.)
+
+These requirements apply to the modified work as a whole. If identifiable
+sections of that work are not derived from the Program, 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 Program, 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 Program.
+
+In addition, mere aggregation of another work not based on the Program with
+the Program (or with a work based on the Program) on a volume of a storage
+or distribution medium does not bring the other work under the scope of this
+License.
+
+3. You may copy and distribute the Program (or a work based on it, under Section
+2) in object code or executable form under the terms of Sections 1 and 2 above
+provided that you also do one of the following:
+
+a) 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; or,
+
+b) Accompany it with a written offer, valid for at least three years, to give
+any third party, for a charge no more than your cost of physically performing
+source distribution, a complete machine-readable copy of the corresponding
+source code, to be distributed under the terms of Sections 1 and 2 above on
+a medium customarily used for software interchange; or,
+
+c) Accompany it with the information you received as to the offer to distribute
+corresponding source code. (This alternative is allowed only for noncommercial
+distribution and only if you received the program in object code or executable
+form with such an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for making
+modifications to it. For an executable work, 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 executable. However, as a special exception, the source code 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.
+
+If distribution of executable or 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 counts as distribution of the source code,
+even though third parties are not compelled to copy the source along with
+the object code.
+
+4. You may not copy, modify, sublicense, or distribute the Program except
+as expressly provided under this License. Any attempt otherwise to copy, modify,
+sublicense or distribute the Program 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.
+
+5. 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
+Program or its derivative works. These actions are prohibited by law if you
+do not accept this License. Therefore, by modifying or distributing the Program
+(or any work based on the Program), you indicate your acceptance of this License
+to do so, and all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+6. Each time you redistribute the Program (or any work based on the Program),
+the recipient automatically receives a license from the original licensor
+to copy, distribute or modify the Program 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 to this License.
+
+7. 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 Program at all. For example, if a
+patent license would not permit royalty-free redistribution of the Program
+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 Program.
+
+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.
+
+8. If the distribution and/or use of the Program is restricted in certain
+countries either by patents or by copyrighted interfaces, the original copyright
+holder who places the Program 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.
+
+9. The Free Software Foundation may publish revised and/or new versions of
+the 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 Program 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
+Program does not specify a version number of this License, you may choose
+any version ever published by the Free Software Foundation.
+
+10. If you wish to incorporate parts of the Program into other free programs
+whose distribution conditions are different, 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
+
+11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR
+THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE
+STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM
+"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 PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+12. 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 PROGRAM 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 PROGRAM (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 PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH
+HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+END OF TERMS AND CONDITIONS
+
+How to Apply These Terms to Your New Programs
+
+If you develop a new program, and you want it to be of the greatest possible
+use to the public, the best way to achieve this is to make it free software
+which everyone can redistribute and change under these terms.
+
+To do so, attach the following notices to the program. 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 program's name and an idea of what it does.>
+
+Copyright (C) <yyyy> <name of author>
+
+This program is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free Software
+Foundation; either version 2 of the License, or (at your option) any later
+version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
+Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this when
+it starts in an interactive mode:
+
+Gnomovision version 69, Copyright (C) year name of author Gnomovision comes
+with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software,
+and you are welcome to redistribute it under certain conditions; type `show
+c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may be
+called something other than `show w' and `show c'; they could even be mouse-clicks
+or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your school,
+if any, to sign a "copyright disclaimer" for the program, if necessary. Here
+is a sample; alter the names:
+
+Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision'
+(which makes passes at compilers) written by James Hacker.
+
+<signature of Ty Coon>, 1 April 1989 Ty Coon, President of Vice This General
+Public License does not permit incorporating your program into proprietary
+programs. If your program is a subroutine library, you may consider it more
+useful to permit linking proprietary applications with the library. If this
+is what you want to do, use the GNU Lesser General Public License instead
+of this License.
--- /dev/null
+GNU LIBRARY GENERAL PUBLIC LICENSE
+
+Version 2, June 1991 Copyright (C) 1991 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 library GPL. It is numbered 2 because
+it goes with version 2 of the ordinary GPL.]
+
+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 Library General Public License, applies to some specially
+designated Free Software Foundation software, and to any other libraries whose
+authors decide to use it. You can use it for your libraries, too.
+
+When we speak of free software, we are referring to freedom, 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 or use pieces of it in new free programs; and that
+you know you can do these things.
+
+To protect your rights, we need to make restrictions that forbid anyone to
+deny you these rights or to ask you to surrender the 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
+a program 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.
+
+Our method of protecting your rights has two steps: (1) copyright the library,
+and (2) offer you this license which gives you legal permission to copy, distribute
+and/or modify the library.
+
+Also, for each distributor's protection, we want to make certain that everyone
+understands that there is no warranty for this free library. If the library
+is modified by someone else and passed on, we want its recipients to know
+that what they have is not the original version, so that any problems introduced
+by others will not reflect on the original authors' reputations.
+
+Finally, any free program is threatened constantly by software patents. We
+wish to avoid the danger that companies distributing free software will individually
+obtain patent licenses, thus in effect transforming the program into proprietary
+software. To prevent this, we have made it clear that any patent must be licensed
+for everyone's free use or not licensed at all.
+
+Most GNU software, including some libraries, is covered by the ordinary GNU
+General Public License, which was designed for utility programs. This license,
+the GNU Library General Public License, applies to certain designated libraries.
+This license is quite different from the ordinary one; be sure to read it
+in full, and don't assume that anything in it is the same as in the ordinary
+license.
+
+The reason we have a separate public license for some libraries is that they
+blur the distinction we usually make between modifying or adding to a program
+and simply using it. Linking a program with a library, without changing the
+library, is in some sense simply using the library, and is analogous to running
+a utility program or application program. However, in a textual and legal
+sense, the linked executable is a combined work, a derivative of the original
+library, and the ordinary General Public License treats it as such.
+
+Because of this blurred distinction, using the ordinary General Public License
+for libraries did not effectively promote software sharing, because most developers
+did not use the libraries. We concluded that weaker conditions might promote
+sharing better.
+
+However, unrestricted linking of non-free programs would deprive the users
+of those programs of all benefit from the free status of the libraries themselves.
+This Library General Public License is intended to permit developers of non-free
+programs to use free libraries, while preserving your freedom as a user of
+such programs to change the free libraries that are incorporated in them.
+(We have not seen how to achieve this as regards changes in header files,
+but we have achieved it as regards changes in the actual functions of the
+Library.) The hope is that this will lead to faster development of free libraries.
+
+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, while the latter only works together with the library.
+
+Note that it is possible for a library to be covered by the ordinary General
+Public License rather than by this special one.
+
+TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+0. This License Agreement applies to any software library which contains a
+notice placed by the copyright holder or other authorized party saying it
+may be distributed under the terms of this Library General Public License
+(also called "this License"). Each licensee is addressed as "you".
+
+A "library" means a collection of software functions and/or data prepared
+so as to be conveniently linked with application programs (which use some
+of those functions and data) to form executables.
+
+The "Library", below, refers to any such software library or work which has
+been distributed under these terms. A "work based on the Library" means either
+the Library or any derivative work under copyright law: that is to say, a
+work containing the Library or a portion of it, either verbatim or with modifications
+and/or translated straightforwardly into another language. (Hereinafter, translation
+is included without limitation in the term "modification".)
+
+"Source code" for a work means the preferred form of the work for making modifications
+to it. For a library, complete source code means all the source code for all
+modules it contains, plus any associated interface definition files, plus
+the scripts used to control compilation and installation of the library.
+
+Activities other than copying, distribution and modification are not covered
+by this License; they are outside its scope. The act of running a program
+using the Library is not restricted, and output from such a program is covered
+only if its contents constitute a work based on the Library (independent of
+the use of the Library in a tool for writing it). Whether that is true depends
+on what the Library does and what the program that uses the Library does.
+
+1. You may copy and distribute verbatim copies of the Library's complete source
+code as you receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice and disclaimer
+of warranty; keep intact all the notices that refer to this License and to
+the absence of any warranty; and distribute a copy of this License along with
+the Library.
+
+You may charge a fee for the physical act of transferring a copy, and you
+may at your option offer warranty protection in exchange for a fee.
+
+2. You may modify your copy or copies of the Library or any portion of it,
+thus forming a work based on the Library, and copy and distribute such modifications
+or work under the terms of Section 1 above, provided that you also meet all
+of these conditions:
+
+ a) The modified work must itself be a software library.
+
+b) You must cause the files modified to carry prominent notices stating that
+you changed the files and the date of any change.
+
+c) You must cause the whole of the work to be licensed at no charge to all
+third parties under the terms of this License.
+
+d) If a facility in the modified Library refers to a function or a table of
+data to be supplied by an application program that uses the facility, other
+than as an argument passed when the facility is invoked, then you must make
+a good faith effort to ensure that, in the event an application does not supply
+such function or table, the facility still operates, and performs whatever
+part of its purpose remains meaningful.
+
+(For example, a function in a library to compute square roots has a purpose
+that is entirely well-defined independent of the application. Therefore, Subsection
+2d requires that any application-supplied function or table used by this function
+must be optional: if the application does not supply it, the square root function
+must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If identifiable
+sections of that work are not derived from the Library, and can be reasonably
+considered independent and separate works in themselves, then this License,
+and its terms, do not apply to those sections when you distribute them as
+separate works. But when you distribute the same sections as part of a whole
+which is a work based on the Library, the distribution of the whole must be
+on the terms of this License, whose permissions for other licensees extend
+to the entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest your
+rights to work written entirely by you; rather, the intent is to exercise
+the right to control the distribution of derivative or collective works based
+on the Library.
+
+In addition, mere aggregation of another work not based on the Library with
+the Library (or with a work based on the Library) on a volume of a storage
+or distribution medium does not bring the other work under the scope of this
+License.
+
+3. You may opt to apply the terms of the ordinary GNU General Public License
+instead of this License to a given copy of the Library. To do this, you must
+alter all the notices that refer to this License, so that they refer to the
+ordinary GNU General Public License, version 2, instead of to this License.
+(If a newer version than version 2 of the ordinary GNU General Public License
+has appeared, then you can specify that version instead if you wish.) Do not
+make any other change in these notices.
+
+Once this change is made in a given copy, it is irreversible for that copy,
+so the ordinary GNU General Public License applies to all subsequent copies
+and derivative works made from that copy.
+
+This option is useful when you wish to copy part of the code of the Library
+into a program that is not a library.
+
+4. You may copy and distribute the Library (or a portion or derivative of
+it, under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you accompany it with the complete corresponding
+machine-readable source code, which must be distributed under the terms of
+Sections 1 and 2 above on a medium customarily used for software interchange.
+
+If distribution of object code is made by offering access to copy from a designated
+place, then offering equivalent access to copy the source code from the same
+place satisfies the requirement to distribute the source code, even though
+third parties are not compelled to copy the source along with the object code.
+
+5. A program that contains no derivative of any portion of the Library, but
+is designed to work with the Library by being compiled or linked with it,
+is called a "work that uses the Library". Such a work, in isolation, is not
+a derivative work of the Library, and therefore falls outside the scope of
+this License.
+
+However, linking a "work that uses the Library" with the Library creates an
+executable that is a derivative of the Library (because it contains portions
+of the Library), rather than a "work that uses the library". The executable
+is therefore covered by this License. Section 6 states terms for distribution
+of such executables.
+
+When a "work that uses the Library" uses material from a header file that
+is part of the Library, the object code for the work may be a derivative work
+of the Library even though the source code is not. Whether this is true is
+especially significant if the work can be linked without the Library, or if
+the work is itself a library. The threshold for this to be true is not precisely
+defined by law.
+
+If such an object file uses only numerical parameters, data structure layouts
+and accessors, and small macros and small inline functions (ten lines or less
+in length), then the use of the object file is unrestricted, regardless of
+whether it is legally a derivative work. (Executables containing this object
+code plus portions of the Library will still fall under Section 6.)
+
+Otherwise, if the work is a derivative of the Library, you may distribute
+the object code for the work under the terms of Section 6. Any executables
+containing that work also fall under Section 6, whether or not they are linked
+directly with the Library itself.
+
+6. As an exception to the Sections above, you may also compile 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) 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.
+
+c) 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.
+
+d) 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 source code distributed need
+not include anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the operating
+system on which the executable runs, unless that component itself accompanies
+the executable.
+
+It may happen that this requirement contradicts the license restrictions of
+other proprietary libraries that do not normally accompany the operating system.
+Such a contradiction means you cannot use both them and the Library together
+in an executable that you distribute.
+
+7. You may place library facilities that are a work based on the Library side-by-side
+in a single library together with other library facilities not covered by
+this License, and distribute such a combined library, provided that the separate
+distribution of the work based on the Library and of the other library facilities
+is otherwise permitted, and provided that you do these two things:
+
+a) Accompany the combined library with a copy of the same work based on the
+Library, uncombined with any other library facilities. This must be distributed
+under the terms of the Sections above.
+
+b) Give prominent notice with the combined library of the fact that part of
+it is a work based on the Library, and explaining where to find the accompanying
+uncombined form of the same work.
+
+8. You may not copy, modify, sublicense, link with, or distribute the Library
+except as expressly provided under this License. Any attempt otherwise to
+copy, modify, sublicense, link with, or distribute the Library is void, and
+will automatically terminate your rights under this License. However, parties
+who have received copies, or rights, from you under this License will not
+have their licenses terminated so long as such parties remain in full compliance.
+
+9. You are not required to accept this License, since you have not signed
+it. However, nothing else grants you permission to modify or distribute the
+Library or its derivative works. These actions are prohibited by law if you
+do not accept this License. Therefore, by modifying or distributing the Library
+(or any work based on the Library), you indicate your acceptance of this License
+to do so, and all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+10. Each time you redistribute the Library (or any work based on the Library),
+the recipient automatically receives a license from the original licensor
+to copy, distribute, link with or modify the Library subject to these terms
+and conditions. You may not impose any further restrictions on the recipients'
+exercise of the rights granted herein. You are not responsible for enforcing
+compliance by third parties to this License.
+
+11. If, as a consequence of a court judgment or allegation of patent infringement
+or for any other reason (not limited to patent issues), conditions are imposed
+on you (whether by court order, agreement or otherwise) that contradict the
+conditions of this License, they do not excuse you from the conditions of
+this License. If you cannot distribute so as to satisfy simultaneously your
+obligations under this License and any other pertinent obligations, then as
+a consequence you may not distribute the Library at all. For example, if a
+patent license would not permit royalty-free redistribution of the Library
+by all those who receive copies directly or indirectly through you, then the
+only way you could satisfy both it and this License would be to refrain entirely
+from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any patents
+or other property right claims or to contest validity of any such claims;
+this section has the sole purpose of protecting the integrity of the free
+software distribution system which is implemented by public license practices.
+Many people have made generous contributions to the wide range of software
+distributed through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing to
+distribute software through any other system and a licensee cannot impose
+that choice.
+
+This section is intended to make thoroughly clear what is believed to be a
+consequence of the rest of this License.
+
+12. If the distribution and/or use of the Library is restricted in certain
+countries either by patents or by copyrighted interfaces, the original copyright
+holder who places the Library under this License may add an explicit geographical
+distribution limitation excluding those countries, so that distribution is
+permitted only in or among countries not thus excluded. In such case, this
+License incorporates the limitation as if written in the body of this License.
+
+13. The Free Software Foundation may publish revised and/or new versions of
+the Library General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to address
+new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library specifies
+a version number of this License which applies to it and "any later version",
+you have the option of following the terms and conditions either of that version
+or of any later version published by the Free Software Foundation. If the
+Library does not specify a license version number, you may choose any version
+ever published by the Free Software Foundation.
+
+14. If you wish to incorporate parts of the Library into other free programs
+whose distribution conditions are incompatible with these, write to the author
+to ask for permission. For software which is copyrighted by the Free Software
+Foundation, write to the Free Software Foundation; we sometimes make exceptions
+for this. Our decision will be guided by the two goals of preserving the free
+status of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+ NO WARRANTY
+
+15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR
+THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE
+STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY
+"AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE
+OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE
+THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE
+OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA
+OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES
+OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH
+HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+END OF TERMS AND CONDITIONS
+
+How to Apply These Terms to Your New Libraries
+
+If you develop a new library, and you want it to be of the greatest possible
+use to the public, we recommend making it free software that everyone can
+redistribute and change. You can do so by permitting redistribution under
+these terms (or, alternatively, under the terms of the ordinary General Public
+License).
+
+To apply these terms, attach the following notices to the library. It is safest
+to attach them to the start of each source file to most effectively convey
+the exclusion of warranty; and each file should have at least the "copyright"
+line and a pointer to where the full notice is found.
+
+one line to give the library's name and an 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 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; 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
+# KDAV
+
+## Introduction
+
+This is an DAV protocol implementation with KJobs.
+
+Calendars and todos are supported, using either GroupDAV
+or CalDAV, and contacts are supported using GroupDAV or
+CardDAV.
+
+
+## Usage
+
+It should be pretty straightforward. The URL to use should be, if possible,
+the principals URL for your server (CalDAV / CardDAV) or the parent
+collection of your calendars to allow discovery.
+
+
+## Tested with / known bugs
+
+Here is a list of servers tested with this resource with the URLs used.
+Feel free to contact the author(s) if you successfully tested a configuration
+not listed here.
+
+* Egroupware (1.6.002)
+ https://host/groupdav.php
+ - GroupDAV working.
+ - CalDAV working.
+ - CardDAV working.
+
+* SOGo (version 1.0.4, 1.1.0 and version at http://sogo-demo.inverse.ca/)
+ https://host/SOGo/dav/<USER>/Calendar and https://host/SOGo/dav/<USER>/Contacts
+ - GroupDAV calendar working, but the timezone data in the ICalendar
+ generated by KCal seems misinterpreted by SOGo : every event is
+ shifted by the timezone offset (at least test with TZ Europe/Paris,
+ feel free to send your results to the author(s). This seems resolved
+ with the demo version made available by Inverse.ca.
+ - CalDAV working, with the same bug.
+ - CardDAV working.
+
+* Davical (version 0.9.7.6)
+ https://host/caldav.php/principals/users/<USER>
+ - CalDAV working.
+
+* Zimbra Open-Source edition (version 5.0.18),
+ https://host/principals/users/<USER>
+ - Caldav mostly working : retrieval of shared calendars that contain a lot
+ of events fails with a 500 server error.
+
+* Google calendar
+ https://www.google.com/calendar/dav/<CALENDAR_ID>/events
+ - CalDAV working.
+
+* iCloud
+ https://caldav.icloud.com/
+ - CalDAV working ([App-specific password required](https://support.apple.com/en-us/HT204397)).
\ No newline at end of file
--- /dev/null
+set(EXECUTABLE_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR})
+add_definitions(-DAUTOTEST_DATA_DIR="${CMAKE_CURRENT_SOURCE_DIR}/data")
+
+ecm_add_test(davcollectiontest.cpp davcollectiontest.h
+ TEST_NAME davcollection
+ NAME_PREFIX "kdav-"
+ LINK_LIBRARIES KF5::DAV Qt${QT_MAJOR_VERSION}::Test Qt${QT_MAJOR_VERSION}::Core Qt${QT_MAJOR_VERSION}::Gui
+)
+
+ecm_add_test(davitemtest.cpp davitemtest.h
+ TEST_NAME davitem
+ NAME_PREFIX "kdav-"
+ LINK_LIBRARIES KF5::DAV Qt${QT_MAJOR_VERSION}::Test Qt${QT_MAJOR_VERSION}::Core
+)
+
+ecm_add_test(davurltest.cpp davurltest.h
+ TEST_NAME davurl
+ NAME_PREFIX "kdav-"
+ LINK_LIBRARIES KF5::DAV Qt${QT_MAJOR_VERSION}::Test Qt${QT_MAJOR_VERSION}::Core
+)
+
+ecm_add_test(davcollectionsmultifetchjobtest.cpp fakeserver.cpp davcollectionsmultifetchjobtest.h fakeserver.h
+ TEST_NAME davcollectionsmultifetchjobtest
+ NAME_PREFIX "kdav-"
+ LINK_LIBRARIES KF5::DAV Qt${QT_MAJOR_VERSION}::Test Qt${QT_MAJOR_VERSION}::Core Qt${QT_MAJOR_VERSION}::Network
+)
+
+ecm_add_test(davitemfetchjobtest.cpp fakeserver.cpp davitemfetchjobtest.h fakeserver.h
+ TEST_NAME davitemfetchjob
+ NAME_PREFIX "kdav-"
+ LINK_LIBRARIES KF5::DAV Qt${QT_MAJOR_VERSION}::Test Qt${QT_MAJOR_VERSION}::Core Qt${QT_MAJOR_VERSION}::Network
+)
+
+ecm_add_test(davitemslistjobtest.cpp fakeserver.cpp davitemslistjobtest.h fakeserver.h
+ TEST_NAME davitemslistjob
+ NAME_PREFIX "kdav-"
+ LINK_LIBRARIES KF5::DAV Qt${QT_MAJOR_VERSION}::Test Qt${QT_MAJOR_VERSION}::Core Qt${QT_MAJOR_VERSION}::Network
+)
--- /dev/null
+C: GET /item HTTP/1.1
+C: User-Agent: KDE DAV groupware client
+S: HTTP/1.0 200 OK
+S: Date: Wed, 04 Jan 2017 18:26:48 GMT
+S: Last-Modified: Wed, 04 Jan 2017 18:26:47 GMT
+S: ETag: 7a33141f192d904d-47
+S: Content-Type: text/x-vcard; charset=utf-8
+D: BEGIN:VCARD
+D: VERSION:3.0
+D: PRODID:-//Kolab//iRony DAV Server 0.3.1//Sabre//Sabre VObject 2.1.7//EN
+D: UID:12345678-1234-1234-1234-123456789abc
+D: FN:John2 Doe
+D: N:Doe;John2;;;
+D: EMAIL;TYPE=INTERNET;TYPE=HOME:john2.doe@example.com
+D: REV;VALUE=DATE-TIME:20170104T182647Z
+D: END:VCARD
+X
--- /dev/null
+C: PROPFIND /caldav/dfaure%40example.com/ HTTP/1.1
+S: HTTP/1.1 207 Multi-Status
+S: Date: Wed, 04 Jan 2017 18:26:48 GMT
+S: Last-Modified: Wed, 04 Jan 2017 18:26:47 GMT
+S: DAV: 1, 3, extended-mkcol, access-control, calendarserver-principal-property-search, calendar-access, calendar-proxy, calendar-schedule, calendar-auto-schedule, addressbook, 2
+S: Content-Type: application/xml; charset=utf-8
+D: <?xml version="1.0" encoding="utf-8" ?>
+D: <multistatus xmlns="DAV:" xmlns:C="urn:ietf:params:xml:ns:caldav">
+D: <response xmlns="DAV:">
+D: <href xmlns="DAV:">/caldav.php/test1.user/home/</href>
+D: <propstat xmlns="DAV:">
+D: <prop xmlns="DAV:">
+D: <C:supported-calendar-component-set xmlns:C="urn:ietf:params:xml:ns:caldav">
+D: <C:comp xmlns:C="urn:ietf:params:xml:ns:caldav" name="VEVENT"/>
+D: <C:comp xmlns:C="urn:ietf:params:xml:ns:caldav" name="VTODO"/>
+D: <C:comp xmlns:C="urn:ietf:params:xml:ns:caldav" name="VJOURNAL"/>
+D: <C:comp xmlns:C="urn:ietf:params:xml:ns:caldav" name="VTIMEZONE"/>
+D: <C:comp xmlns:C="urn:ietf:params:xml:ns:caldav" name="VFREEBUSY"/>
+D: </C:supported-calendar-component-set>
+D: <resourcetype xmlns="DAV:">
+D: <collection xmlns="DAV:"/>
+D: <C:calendar xmlns:C="urn:ietf:params:xml:ns:caldav"/>
+D: <C:schedule-calendar xmlns:C="urn:ietf:params:xml:ns:caldav"/>
+D: </resourcetype>
+D: <displayname xmlns="DAV:">Test1 User</displayname>
+D: <current-user-privilege-set xmlns="DAV:">
+D: <privilege xmlns="DAV:">
+D: <read xmlns="DAV:"/>
+D: </privilege>
+D: </current-user-privilege-set>
+D: <getctag xmlns="http://calendarserver.org/ns/">12345</getctag>
+D: </prop>
+D: <status xmlns="DAV:">HTTP/1.1 200 OK</status>
+D: </propstat>
+D: </response>
+D: </multistatus>
+X
--- /dev/null
+C: PROPFIND /caldav HTTP/1.1
+S: HTTP/1.1 207 Multi-Status
+S: Date: Wed, 04 Jan 2017 18:26:48 GMT
+S: Last-Modified: Wed, 04 Jan 2017 18:26:47 GMT
+S: DAV: 1, 3, extended-mkcol, access-control, calendarserver-principal-property-search, calendar-access, calendar-proxy, calendar-schedule, calendar-auto-schedule, addressbook, 2
+S: Content-Type: application/xml; charset=utf-8
+D: <?xml version="1.0" encoding="utf-8" ?>
+D: <multistatus xmlns="DAV:" xmlns:C="urn:ietf:params:xml:ns:caldav">
+D: <response>
+D: <href>/principals/users/dfaure%40example.com/</href>
+D: <propstat>
+D: <prop>
+D: <C:calendar-home-set>
+D: <href>/caldav/dfaure%40example.com/</href>
+D: </C:calendar-home-set>
+D: </prop>
+D: <status>HTTP/1.1 200 OK</status>
+D: </propstat>
+D: </response>
+D: </multistatus>
+X
--- /dev/null
+C: PROPFIND /carddav/dfaure%40example.com/ HTTP/1.1
+S: HTTP/1.1 207 Multi-Status
+S: Date: Wed, 04 Jan 2017 18:26:48 GMT
+S: Last-Modified: Wed, 04 Jan 2017 18:26:47 GMT
+S: DAV: 1, 3, extended-mkcol, access-control, calendarserver-principal-property-search, calendar-access, calendar-proxy, calendar-schedule, calendar-auto-schedule, addressbook, 2
+S: Content-Type: application/xml; charset=utf-8
+D: <?xml version="1.0" encoding="utf-8" ?>
+D: <multistatus xmlns="DAV:" xmlns:C="urn:ietf:params:xml:ns:carddav">
+D: <response xmlns="DAV:">
+D: <href xmlns="DAV:">/carddav.php/test1.user/home/</href>
+D: <propstat xmlns="DAV:">
+D: <prop xmlns="DAV:">
+D: <resourcetype xmlns="DAV:">
+D: <collection xmlns="DAV:"/>
+D: <C:addressbook xmlns:C="urn:ietf:params:xml:ns:carddav"/>
+D: </resourcetype>
+D: <displayname xmlns="DAV:">My Address Book</displayname>
+D: <getctag xmlns="http://calendarserver.org/ns/">3145</getctag>
+D: </prop>
+D: <status xmlns="DAV:">HTTP/1.1 200 OK</status>
+D: </propstat>
+D: </response>
+D: </multistatus>
+X
--- /dev/null
+C: PROPFIND /carddav HTTP/1.1
+S: HTTP/1.1 207 Multi-Status
+S: Date: Wed, 04 Jan 2017 18:26:48 GMT
+S: Last-Modified: Wed, 04 Jan 2017 18:26:47 GMT
+S: DAV: 1, 3, extended-mkcol, access-control, calendarserver-principal-property-search, calendar-access, calendar-proxy, calendar-schedule, calendar-auto-schedule, addressbook, 2
+S: Content-Type: application/xml; charset=utf-8
+D: <?xml version="1.0" encoding="utf-8" ?>
+D: <multistatus xmlns="DAV:" xmlns:C="urn:ietf:params:xml:ns:carddav">
+D: <response>
+D: <href>/principals/users/dfaure%40example.com/</href>
+D: <propstat>
+D: <prop>
+D: <C:addressbook-home-set>
+D: <href>/carddav/dfaure%40example.com/</href>
+D: </C:addressbook-home-set>
+D: </prop>
+D: <status>HTTP/1.1 200 OK</status>
+D: </propstat>
+D: </response>
+D: </multistatus>
+X
--- /dev/null
+C: PROPFIND /does_not_exist HTTP/1.1
+S: HTTP/1.1 404 Not found
+X
--- /dev/null
+/*
+ SPDX-FileCopyrightText: 2020 David Faure <faure@kde.org>
+
+ SPDX-License-Identifier: LGPL-2.0-or-later
+*/
+
+#include "davcollectionsmultifetchjobtest.h"
+#include "fakeserver.h"
+
+#include <KDAV/DavCollectionsMultiFetchJob>
+
+#include <QSignalSpy>
+#include <QTest>
+
+using KDAV::DavCollection;
+Q_DECLARE_METATYPE(KDAV::Protocol)
+
+void DavCollectionsMultiFetchJobTest::initTestCase()
+{
+ // To let ctest exit, we shouldn't start kio_http_cache_cleaner
+ qputenv("KIO_DISABLE_CACHE_CLEANER", "yes");
+
+ qRegisterMetaType<KDAV::Protocol>();
+}
+
+void DavCollectionsMultiFetchJobTest::runSuccessfullTest()
+{
+ FakeServer fakeServer(5990);
+ QUrl url(QStringLiteral("http://localhost/caldav"));
+ url.setPort(fakeServer.port());
+ KDAV::DavUrl davUrl1(url, KDAV::CalDav);
+ QUrl url2(url);
+ url2.setPath(QStringLiteral("/carddav"));
+ KDAV::DavUrl davUrl2(url2, KDAV::CardDav);
+
+ auto job = new KDAV::DavCollectionsMultiFetchJob({davUrl1, davUrl2});
+
+ QSignalSpy spy(job, &KDAV::DavCollectionsMultiFetchJob::collectionDiscovered);
+
+ fakeServer.addScenarioFromFile(QLatin1String(AUTOTEST_DATA_DIR) + QStringLiteral("/dataitemmultifetchjob-caldav.txt"));
+ fakeServer.addScenarioFromFile(QLatin1String(AUTOTEST_DATA_DIR) + QStringLiteral("/dataitemmultifetchjob-caldav-collections.txt"));
+ fakeServer.addScenarioFromFile(QLatin1String(AUTOTEST_DATA_DIR) + QStringLiteral("/dataitemmultifetchjob-carddav.txt"));
+ fakeServer.addScenarioFromFile(QLatin1String(AUTOTEST_DATA_DIR) + QStringLiteral("/dataitemmultifetchjob-carddav-collections.txt"));
+ fakeServer.startAndWait();
+ job->exec();
+
+ QVERIFY(fakeServer.isAllScenarioDone());
+ QCOMPARE(job->error(), 0);
+
+ const KDAV::DavCollection::List collections = job->collections();
+ QCOMPARE(collections.count(), 2);
+ int calDavIdx = 0;
+ int cardDavIdx = 1;
+ if (collections.at(0).contentTypes() == DavCollection::Contacts) { // put things in a defined order
+ std::swap(calDavIdx, cardDavIdx);
+ }
+
+ const KDAV::DavCollection calendar = collections.at(calDavIdx);
+ QCOMPARE(calendar.displayName(), QStringLiteral("Test1 User"));
+ QCOMPARE(calendar.contentTypes(), DavCollection::Events | DavCollection::Todos | DavCollection::FreeBusy | DavCollection::Journal);
+ QCOMPARE(calendar.url().url().path(), QStringLiteral("/caldav.php/test1.user/home/"));
+ QCOMPARE(calendar.CTag(), QStringLiteral("12345"));
+ QCOMPARE(calendar.privileges(), KDAV::Read);
+
+ const KDAV::DavCollection addressbook = collections.at(cardDavIdx);
+ QCOMPARE(addressbook.displayName(), QStringLiteral("My Address Book"));
+ QCOMPARE(addressbook.contentTypes(), DavCollection::Contacts);
+ QCOMPARE(addressbook.url().url().path(), QStringLiteral("/carddav.php/test1.user/home/"));
+ QCOMPARE(addressbook.CTag(), QStringLiteral("3145"));
+ QCOMPARE(addressbook.privileges(), KDAV::All);
+
+ QCOMPARE(spy.count(), 2);
+ QCOMPARE(int(spy.at(calDavIdx).at(0).value<KDAV::Protocol>()), int(KDAV::CalDav));
+ QCOMPARE(spy.at(calDavIdx).at(1).toString(), calendar.url().url().toString());
+ QCOMPARE(spy.at(calDavIdx).at(2).toString(), url.toString());
+
+ QCOMPARE(int(spy.at(cardDavIdx).at(0).value<KDAV::Protocol>()), int(KDAV::CardDav));
+ QCOMPARE(spy.at(cardDavIdx).at(1).toString(), addressbook.url().url().toString());
+ QCOMPARE(spy.at(cardDavIdx).at(2).toString(), url2.toString());
+}
+
+void DavCollectionsMultiFetchJobTest::shouldFailOnError()
+{
+ FakeServer fakeServer(5990);
+ QUrl url(QStringLiteral("http://localhost/caldav"));
+ url.setPort(fakeServer.port());
+ KDAV::DavUrl davUrl1(url, KDAV::CalDav);
+ QUrl urlError(url);
+ urlError.setPath(QStringLiteral("/does_not_exist"));
+ KDAV::DavUrl davUrlError(urlError, KDAV::CalDav);
+
+ auto job = new KDAV::DavCollectionsMultiFetchJob({davUrl1, davUrlError});
+
+ fakeServer.addScenarioFromFile(QLatin1String(AUTOTEST_DATA_DIR) + QStringLiteral("/dataitemmultifetchjob-caldav.txt"));
+ fakeServer.addScenarioFromFile(QLatin1String(AUTOTEST_DATA_DIR) + QStringLiteral("/dataitemmultifetchjob-caldav-collections.txt"));
+ fakeServer.addScenarioFromFile(QLatin1String(AUTOTEST_DATA_DIR) + QStringLiteral("/dataitemmultifetchjob-error.txt"));
+ fakeServer.startAndWait();
+ job->exec();
+
+ QVERIFY(fakeServer.isAllScenarioDone());
+ QCOMPARE(job->error(), 300);
+}
+
+QTEST_MAIN(DavCollectionsMultiFetchJobTest)
--- /dev/null
+/*
+ SPDX-FileCopyrightText: 2020 David Faure <faure@kde.org>
+
+ SPDX-License-Identifier: LGPL-2.0-or-later
+*/
+
+#ifndef DAVITEMFETCHJOB_TEST_H
+#define DAVITEMFETCHJOB_TEST_H
+
+#include <QObject>
+
+class DavCollectionsMultiFetchJobTest : public QObject
+{
+ Q_OBJECT
+
+private Q_SLOTS:
+ void initTestCase();
+ void runSuccessfullTest();
+ void shouldFailOnError();
+};
+
+#endif
--- /dev/null
+/*
+ SPDX-FileCopyrightText: 2017 Sandro Knauß <sknauss@kde.org>
+
+ SPDX-License-Identifier: LGPL-2.0-or-later
+*/
+
+#include "davcollectiontest.h"
+
+#include <KDAV/DavCollection>
+#include <KDAV/DavUrl>
+
+#include <QColor>
+#include <QTest>
+
+void DavCollectionTest::createEmpty()
+{
+ KDAV::DavCollection davCollection;
+
+ QCOMPARE(davCollection.url().protocol(), KDAV::CalDav);
+ QCOMPARE(davCollection.CTag(), QString());
+ QCOMPARE(davCollection.displayName(), QString());
+ QCOMPARE(davCollection.color(), QColor());
+ QCOMPARE(davCollection.contentTypes(), KDAV::DavCollection::ContentTypes());
+ QCOMPARE(davCollection.privileges(), KDAV::Privileges());
+}
+
+void DavCollectionTest::storeTest()
+{
+ QUrl url(QStringLiteral("test://me:pw@test"));
+ KDAV::DavUrl davUrl(url, KDAV::CardDav);
+ KDAV::DavCollection davCollection(davUrl, QStringLiteral("myname"), KDAV::DavCollection::Events | KDAV::DavCollection::Todos);
+
+ QCOMPARE(davCollection.url().protocol(), KDAV::CardDav);
+ QCOMPARE(davCollection.url().url(), url);
+ QCOMPARE(davCollection.CTag(), QString());
+ QCOMPARE(davCollection.displayName(), QStringLiteral("myname"));
+ QCOMPARE(davCollection.color(), QColor());
+ QCOMPARE(davCollection.contentTypes(), KDAV::DavCollection::Events | KDAV::DavCollection::Todos);
+ QCOMPARE(davCollection.privileges(), KDAV::All);
+}
+
+void DavCollectionTest::setTest()
+{
+ QUrl url(QStringLiteral("test://me:pw@test"));
+ KDAV::DavUrl davUrl(url, KDAV::CardDav);
+ KDAV::DavCollection davCollection;
+
+ davCollection.setUrl(davUrl);
+ davCollection.setCTag(QStringLiteral("ctag"));
+ davCollection.setDisplayName(QStringLiteral("myname"));
+ davCollection.setColor(QColor(1, 2, 3));
+ davCollection.setContentTypes(KDAV::DavCollection::Events | KDAV::DavCollection::Todos);
+ davCollection.setPrivileges(KDAV::Read | KDAV::Write);
+
+ QCOMPARE(davCollection.url().protocol(), KDAV::CardDav);
+ QCOMPARE(davCollection.url().url(), url);
+ QCOMPARE(davCollection.CTag(), QStringLiteral("ctag"));
+ QCOMPARE(davCollection.displayName(), QStringLiteral("myname"));
+ QCOMPARE(davCollection.color(), QColor(1, 2, 3));
+ QCOMPARE(davCollection.contentTypes(), KDAV::DavCollection::Events | KDAV::DavCollection::Todos);
+ QCOMPARE(davCollection.privileges(), KDAV::Read | KDAV::Write);
+}
+
+void DavCollectionTest::copyTest()
+{
+ KDAV::DavCollection davCollection;
+
+ QUrl url(QStringLiteral("test://me:pw@test"));
+ KDAV::DavUrl davUrl(url, KDAV::CardDav);
+
+ davCollection.setUrl(davUrl);
+ davCollection.setCTag(QStringLiteral("ctag"));
+ davCollection.setDisplayName(QStringLiteral("myname"));
+ davCollection.setColor(QColor(1, 2, 3));
+ davCollection.setContentTypes(KDAV::DavCollection::Events | KDAV::DavCollection::Todos);
+ davCollection.setPrivileges(KDAV::Read | KDAV::Write);
+
+ KDAV::DavCollection copy1(davCollection);
+ QCOMPARE(copy1.url().protocol(), davCollection.url().protocol());
+ QCOMPARE(copy1.url().url(), davCollection.url().url());
+ QCOMPARE(copy1.CTag(), davCollection.CTag());
+ QCOMPARE(copy1.displayName(), davCollection.displayName());
+ QCOMPARE(copy1.color(), davCollection.color());
+ QCOMPARE(copy1.contentTypes(), davCollection.contentTypes());
+ QCOMPARE(copy1.privileges(), davCollection.privileges());
+
+ KDAV::DavCollection copy2;
+ copy2 = davCollection;
+
+ QCOMPARE(copy2.url().protocol(), davCollection.url().protocol());
+ QCOMPARE(copy2.url().url(), davCollection.url().url());
+ QCOMPARE(copy2.CTag(), davCollection.CTag());
+ QCOMPARE(copy2.displayName(), davCollection.displayName());
+ QCOMPARE(copy2.color(), davCollection.color());
+ QCOMPARE(copy2.contentTypes(), davCollection.contentTypes());
+ QCOMPARE(copy2.privileges(), davCollection.privileges());
+}
+
+QTEST_MAIN(DavCollectionTest)
--- /dev/null
+/*
+ SPDX-FileCopyrightText: 2017 Sandro Knauß <sknauss@kde.org>
+
+ SPDX-License-Identifier: LGPL-2.0-or-later
+*/
+
+#ifndef DAVCOLLECTION_TEST_H
+#define DAVCOLLECTION_TEST_H
+
+#include <QObject>
+
+class DavCollectionTest : public QObject
+{
+ Q_OBJECT
+
+private Q_SLOTS:
+ void createEmpty();
+ void storeTest();
+ void setTest();
+ void copyTest();
+};
+
+#endif
--- /dev/null
+/*
+ SPDX-FileCopyrightText: 2017 Sandro Knauß <sknauss@kde.org>
+
+ SPDX-License-Identifier: LGPL-2.0-or-later
+*/
+
+#include "davitemfetchjobtest.h"
+#include "fakeserver.h"
+
+#include <KDAV/DavItemFetchJob>
+
+#include <QTest>
+
+void DavItemFetchJobTest::initTestCase()
+{
+ // To let ctest exit, we shouldn't start kio_http_cache_cleaner
+ qputenv("KIO_DISABLE_CACHE_CLEANER", "yes");
+}
+
+void DavItemFetchJobTest::runSuccessfullTest()
+{
+ FakeServer fakeServer(5989);
+ QUrl url(QStringLiteral("http://localhost/item"));
+ url.setPort(fakeServer.port());
+ KDAV::DavUrl davUrl(url, KDAV::CardDav);
+
+ KDAV::DavItem item(davUrl, QString(), QByteArray(), QString());
+
+ auto job = new KDAV::DavItemFetchJob(item);
+
+ fakeServer.addScenarioFromFile(QLatin1String(AUTOTEST_DATA_DIR) + QStringLiteral("/dataitemfetchjob.txt"));
+ fakeServer.startAndWait();
+ job->exec();
+
+ QVERIFY(fakeServer.isAllScenarioDone());
+ QCOMPARE(job->error(), 0);
+
+ QCOMPARE(item.data(), QByteArray());
+ QCOMPARE(item.etag(), QString());
+ QCOMPARE(item.contentType(), QString());
+
+ item = job->item();
+ QByteArray data(
+ "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Kolab//iRony DAV Server 0.3.1//Sabre//Sabre VObject "
+ "2.1.7//EN\r\nUID:12345678-1234-1234-1234-123456789abc\r\nFN:John2 "
+ "Doe\r\nN:Doe;John2;;;\r\nEMAIL;TYPE=INTERNET;TYPE=HOME:john2.doe@example.com\r\nREV;VALUE=DATE-TIME:20170104T182647Z\r\nEND:VCARD\r\n");
+ QCOMPARE(item.data(), data);
+ QCOMPARE(item.etag(), QStringLiteral("7a33141f192d904d-47"));
+ QCOMPARE(item.contentType(), QStringLiteral("text/x-vcard"));
+}
+
+QTEST_MAIN(DavItemFetchJobTest)
--- /dev/null
+/*
+ SPDX-FileCopyrightText: 2017 Sandro Knauß <sknauss@kde.org>
+
+ SPDX-License-Identifier: LGPL-2.0-or-later
+*/
+
+#ifndef DAVITEMFETCHJOB_TEST_H
+#define DAVITEMFETCHJOB_TEST_H
+
+#include <QObject>
+
+class DavItemFetchJobTest : public QObject
+{
+ Q_OBJECT
+
+private Q_SLOTS:
+ void initTestCase();
+ void runSuccessfullTest();
+};
+
+#endif
--- /dev/null
+/*
+ SPDX-FileCopyrightText: 2017 Sandro Knauß <sknauss@kde.org>
+
+ SPDX-License-Identifier: LGPL-2.0-or-later
+*/
+
+#include "davitemslistjobtest.h"
+#include "fakeserver.h"
+
+#include <KDAV/DavError>
+#include <KDAV/DavItemsListJob>
+#include <KDAV/DavUrl>
+#include <KDAV/EtagCache>
+
+#include <QTest>
+
+void DavItemsListJobTest::noMatchingMimetype()
+{
+ std::shared_ptr<KDAV::EtagCache> cache(new KDAV::EtagCache());
+
+ QUrl url(QStringLiteral("http://localhost/collection"));
+ KDAV::DavUrl davUrl(url, KDAV::CardDav);
+ KDAV::Error error(KDAV::ErrorNumber::ERR_ITEMLIST_NOMIMETYPE, 0, QString(), 0);
+
+ auto job = new KDAV::DavItemsListJob(davUrl, cache);
+ job->setContentMimeTypes(QStringList() << QStringLiteral("mime/invalid1") << QStringLiteral("mime/invalid2"));
+ job->exec();
+
+ QCOMPARE(job->error(), static_cast<int>(KDAV::ErrorNumber::ERR_ITEMLIST_NOMIMETYPE));
+ QCOMPARE(job->errorText(), error.errorText());
+}
+
+QTEST_MAIN(DavItemsListJobTest)
--- /dev/null
+/*
+ SPDX-FileCopyrightText: 2017 Sandro Knauß <sknauss@kde.org>
+
+ SPDX-License-Identifier: LGPL-2.0-or-later
+*/
+
+#ifndef DAVITEMSLISTJOB_TEST_H
+#define DAVITEMSLISTJOB_TEST_H
+
+#include <QObject>
+
+class DavItemsListJobTest : public QObject
+{
+ Q_OBJECT
+
+private Q_SLOTS:
+ void noMatchingMimetype();
+};
+
+#endif
--- /dev/null
+/*
+ SPDX-FileCopyrightText: 2017 Sandro Knauß <sknauss@kde.org>
+
+ SPDX-License-Identifier: LGPL-2.0-or-later
+*/
+
+#include "davitemtest.h"
+
+#include <KDAV/DavItem>
+#include <KDAV/DavUrl>
+
+#include <QDataStream>
+#include <QTest>
+
+void DavItemTest::createEmpty()
+{
+ KDAV::DavItem davItem;
+
+ QCOMPARE(davItem.url().toDisplayString(), QString());
+ QCOMPARE(davItem.contentType(), QString());
+ QCOMPARE(davItem.data(), QByteArray());
+ QCOMPARE(davItem.etag(), QString());
+}
+
+void DavItemTest::storeTest()
+{
+ QUrl url(QStringLiteral("test://me:pw@test"));
+ KDAV::DavUrl davUrl(url, KDAV::CardDav);
+ KDAV::DavItem davItem(davUrl, QStringLiteral("text/test"), QByteArray("data"), QStringLiteral("991233434-234345"));
+
+ QCOMPARE(davItem.url().protocol(), KDAV::CardDav);
+ QCOMPARE(davItem.contentType(), QStringLiteral("text/test"));
+ QCOMPARE(davItem.data(), QByteArray("data"));
+ QCOMPARE(davItem.etag(), QStringLiteral("991233434-234345"));
+}
+
+void DavItemTest::setTest()
+{
+ QUrl url(QStringLiteral("test://me:pw@test"));
+ KDAV::DavUrl davUrl(url, KDAV::CardDav);
+ KDAV::DavItem davItem;
+
+ davItem.setUrl(davUrl);
+ davItem.setContentType(QStringLiteral("text/test"));
+ davItem.setData(QByteArray("data"));
+ davItem.setEtag(QStringLiteral("991233434-234345"));
+
+ QCOMPARE(davItem.url().protocol(), KDAV::CardDav);
+ QCOMPARE(davItem.contentType(), QStringLiteral("text/test"));
+ QCOMPARE(davItem.data(), QByteArray("data"));
+ QCOMPARE(davItem.etag(), QStringLiteral("991233434-234345"));
+}
+
+void DavItemTest::copyTest()
+{
+ QUrl url(QStringLiteral("test://me:pw@test"));
+ KDAV::DavUrl davUrl(url, KDAV::CardDav);
+ KDAV::DavItem davItem(davUrl, QStringLiteral("text/test"), QByteArray("data"), QStringLiteral("991233434-234345"));
+
+ KDAV::DavItem davItemCopy1(davItem);
+ QCOMPARE(davItemCopy1.url().protocol(), davItem.url().protocol());
+ QCOMPARE(davItemCopy1.url().url(), davItem.url().url());
+ QCOMPARE(davItemCopy1.contentType(), davItem.contentType());
+ QCOMPARE(davItemCopy1.data(), davItem.data());
+ QCOMPARE(davItemCopy1.etag(), davItem.etag());
+
+ KDAV::DavItem davItemCopy2;
+ davItemCopy2 = davItem;
+ QCOMPARE(davItemCopy2.url().protocol(), davItem.url().protocol());
+ QCOMPARE(davItemCopy2.url().url(), davItem.url().url());
+ QCOMPARE(davItemCopy2.contentType(), davItem.contentType());
+ QCOMPARE(davItemCopy2.data(), davItem.data());
+ QCOMPARE(davItemCopy2.etag(), davItem.etag());
+}
+
+void DavItemTest::serializeTest()
+{
+ KDAV::DavItem davItem1;
+ KDAV::DavItem davItem2;
+
+ QUrl url(QStringLiteral("test://me:pw@test"));
+ KDAV::DavUrl davUrl(url, KDAV::CardDav);
+
+ davItem1.setUrl(davUrl);
+ davItem1.setContentType(QStringLiteral("text/test"));
+ davItem1.setData(QByteArray("data"));
+ davItem1.setEtag(QStringLiteral("991233434-234345"));
+
+ QByteArray data;
+ QDataStream s(&data, QIODevice::WriteOnly);
+ s << davItem1;
+
+ QDataStream t(&data, QIODevice::ReadOnly);
+ t >> davItem2;
+
+ QCOMPARE(davItem2.url().protocol(), davItem1.url().protocol());
+ QCOMPARE(davItem2.url().url(), davItem1.url().url());
+ QCOMPARE(davItem2.contentType(), davItem1.contentType());
+ QCOMPARE(davItem2.data(), davItem1.data());
+ QCOMPARE(davItem2.etag(), davItem1.etag());
+}
+
+QTEST_MAIN(DavItemTest)
--- /dev/null
+/*
+ SPDX-FileCopyrightText: 2017 Sandro Knauß <sknauss@kde.org>
+
+ SPDX-License-Identifier: LGPL-2.0-or-later
+*/
+
+#ifndef DAVITEM_TEST_H
+#define DAVITEM_TEST_H
+
+#include <QObject>
+
+class DavItemTest : public QObject
+{
+ Q_OBJECT
+
+private Q_SLOTS:
+ void createEmpty();
+ void storeTest();
+ void setTest();
+ void copyTest();
+
+ void serializeTest();
+};
+
+#endif
--- /dev/null
+/*
+ SPDX-FileCopyrightText: 2017 Sandro Knauß <sknauss@kde.org>
+
+ SPDX-License-Identifier: LGPL-2.0-or-later
+*/
+
+#include "davurltest.h"
+
+#include <KDAV/DavUrl>
+
+#include <QDataStream>
+#include <QTest>
+
+void DavUrlTest::createEmpty()
+{
+ KDAV::DavUrl davUrl;
+
+ QCOMPARE(davUrl.protocol(), KDAV::CalDav);
+ QCOMPARE(davUrl.url(), QUrl());
+}
+
+void DavUrlTest::storeTest()
+{
+ QUrl url(QStringLiteral("test://me:pw@test"));
+ KDAV::DavUrl davUrl(url, KDAV::CardDav);
+
+ QCOMPARE(davUrl.protocol(), KDAV::CardDav);
+ QCOMPARE(davUrl.url(), url);
+ QCOMPARE(davUrl.toDisplayString(), QStringLiteral("test://test"));
+}
+
+void DavUrlTest::setTest()
+{
+ QUrl url(QStringLiteral("test://me:pw@test"));
+ KDAV::DavUrl davUrl;
+
+ davUrl.setProtocol(KDAV::CardDav);
+ davUrl.setUrl(url);
+
+ QCOMPARE(davUrl.protocol(), KDAV::CardDav);
+ QCOMPARE(davUrl.url(), url);
+ QCOMPARE(davUrl.toDisplayString(), QStringLiteral("test://test"));
+}
+
+void DavUrlTest::serializeTest()
+{
+ KDAV::DavUrl davUrl1;
+ KDAV::DavUrl davUrl2;
+
+ QUrl url(QStringLiteral("test://me:pw@test"));
+ davUrl1.setProtocol(KDAV::CardDav);
+ davUrl1.setUrl(url);
+
+ QByteArray data;
+ QDataStream s(&data, QIODevice::WriteOnly);
+ s << davUrl1;
+
+ QDataStream t(&data, QIODevice::ReadOnly);
+ t >> davUrl2;
+
+ QCOMPARE(davUrl2.protocol(), davUrl1.protocol());
+ QCOMPARE(davUrl2.url(), davUrl1.url());
+}
+
+QTEST_MAIN(DavUrlTest)
--- /dev/null
+/*
+ SPDX-FileCopyrightText: 2017 Sandro Knauß <sknauss@kde.org>
+
+ SPDX-License-Identifier: LGPL-2.0-or-later
+*/
+
+#ifndef DAVURL_TEST_H
+#define DAVURL_TEST_H
+
+#include <QObject>
+
+class DavUrlTest : public QObject
+{
+ Q_OBJECT
+
+private Q_SLOTS:
+ void createEmpty();
+ void storeTest();
+ void setTest();
+
+ void serializeTest();
+};
+
+#endif
--- /dev/null
+/*
+ SPDX-FileCopyrightText: 2008 Omat Holding B .V. <info@omat.nl>
+ SPDX-FileCopyrightText: 2010 Klarälvdalens Datakonsult AB , a KDAB Group company <info@kdab.com>
+ SPDX-FileContributor: Kevin Ottens <kevin@kdab.com>
+ SPDX-FileCopyrightText: 2017 Sandro Kanuß <knauss@kde.org>
+
+ SPDX-License-Identifier: GPL-2.0-or-later
+*/
+
+// Own
+#include "fakeserver.h"
+
+// Qt
+#include <QDebug>
+#include <QFile>
+#include <QTest>
+
+FakeServer::FakeServer(int port, QObject *parent)
+ : QObject(parent)
+ , m_thread(new QThread)
+ , m_port(port)
+{
+ moveToThread(m_thread);
+}
+
+FakeServer::~FakeServer()
+{
+ QMetaObject::invokeMethod(this, &FakeServer::cleanup);
+ m_thread->quit();
+ m_thread->wait();
+ delete m_thread;
+}
+
+void FakeServer::startAndWait()
+{
+ m_thread->start();
+ // this will block until the init code happens and the event queue starts
+ QMetaObject::invokeMethod(this, &FakeServer::init, Qt::BlockingQueuedConnection);
+}
+
+void FakeServer::dataAvailable()
+{
+ QMutexLocker locker(&m_mutex);
+
+ QTcpSocket *socket = qobject_cast<QTcpSocket *>(sender());
+ Q_ASSERT(socket != nullptr);
+
+ int scenarioNumber = -1;
+ readClientPart(socket, &scenarioNumber);
+ if (scenarioNumber >= 0) {
+ Q_ASSERT(scenarioNumber < m_scenarios.count());
+ writeServerPart(socket, scenarioNumber);
+ }
+}
+
+void FakeServer::newConnection()
+{
+ QMutexLocker locker(&m_mutex);
+
+ m_clientSockets << m_tcpServer->nextPendingConnection();
+ connect(m_clientSockets.last(), &QTcpSocket::readyRead, this, &FakeServer::dataAvailable);
+}
+
+void FakeServer::init()
+{
+ m_tcpServer = new QTcpServer();
+
+ if (!m_tcpServer->listen(QHostAddress(QHostAddress::LocalHost), m_port)) {
+ qFatal("Unable to start the server");
+ }
+
+ connect(m_tcpServer, &QTcpServer::newConnection, this, &FakeServer::newConnection);
+}
+
+void FakeServer::cleanup()
+{
+ qDeleteAll(m_clientSockets);
+ delete m_tcpServer;
+}
+
+void FakeServer::setScenario(const QList<QByteArray> &scenario)
+{
+ QMutexLocker locker(&m_mutex);
+
+ m_scenarios.clear();
+ m_scenarios << scenario;
+}
+
+void FakeServer::addScenario(const QList<QByteArray> &scenario)
+{
+ QMutexLocker locker(&m_mutex);
+
+ m_scenarios << scenario;
+}
+
+void FakeServer::addScenarioFromFile(const QString &fileName)
+{
+ QFile file(fileName);
+ file.open(QIODevice::ReadOnly | QIODevice::Text);
+
+ QList<QByteArray> scenario;
+
+ while (!file.atEnd()) {
+ scenario << file.readLine().trimmed();
+ }
+
+ file.close();
+
+ addScenario(scenario);
+}
+
+bool FakeServer::isScenarioDone(int scenarioNumber) const
+{
+ QMutexLocker locker(&m_mutex);
+
+ if (scenarioNumber < m_scenarios.size()) {
+ return m_scenarios[scenarioNumber].isEmpty();
+ } else {
+ return true; // Non existent hence empty, right?
+ }
+}
+
+bool FakeServer::isAllScenarioDone() const
+{
+ QMutexLocker locker(&m_mutex);
+
+ for (const QList<QByteArray> &scenario : std::as_const(m_scenarios)) {
+ if (!scenario.isEmpty()) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+void FakeServer::writeServerPart(QTcpSocket *clientSocket, int scenarioNumber)
+{
+ QList<QByteArray> scenario = m_scenarios[scenarioNumber];
+
+ while (!scenario.isEmpty() && scenario.first().startsWith("S: ")) {
+ QByteArray rule = scenario.takeFirst();
+
+ QByteArray payload = rule.mid(3);
+ clientSocket->write(payload + "\r\n");
+ }
+
+ QByteArray data;
+
+ while (!scenario.isEmpty() && scenario.first().startsWith("D: ")) {
+ QByteArray rule = scenario.takeFirst();
+
+ QByteArray payload = rule.mid(3);
+ data.append(payload + "\r\n");
+ }
+
+ clientSocket->write(QStringLiteral("Content-Length: %1\r\n\r\n").arg(data.length()).toLatin1());
+ clientSocket->write(data);
+
+ if (!scenario.isEmpty() && scenario.first().startsWith("X")) {
+ scenario.takeFirst();
+ clientSocket->close();
+ }
+
+ if (!scenario.isEmpty()) {
+ QVERIFY(scenario.first().startsWith("C: "));
+ }
+
+ m_scenarios[scenarioNumber] = scenario;
+}
+
+void FakeServer::readClientPart(QTcpSocket *socket, int *scenarioNumber)
+{
+ QByteArray line = socket->readLine();
+ qDebug() << "Read client request" << line;
+ const auto it = std::find_if(m_scenarios.begin(), m_scenarios.end(), [&](const QList<QByteArray> &scenario) {
+ return !scenario.isEmpty() && scenario.at(0).mid(3) + "\r\n" == line;
+ });
+ if (it == m_scenarios.end()) {
+ qWarning() << "No server response available for" << line;
+ QFAIL("Unexpected request");
+ return;
+ }
+ QList<QByteArray> scenario = *it;
+ QVector<QByteArray> header;
+
+ while (line != "\r\n") {
+ header << line;
+ if (socket->bytesAvailable() == 0 && !socket->waitForReadyRead()) {
+ qDebug() << header;
+ QFAIL("could not read all headers");
+ return;
+ }
+ line = socket->readLine();
+ }
+
+ while (!scenario.isEmpty() && scenario.first().startsWith("C: ")) {
+ QByteArray expected = scenario.takeFirst().mid(3) + "\r\n";
+
+ if (!header.contains(expected)) {
+ qWarning() << expected << "not found in header. Here's what we got:";
+ qWarning() << header;
+ QVERIFY(false);
+ break;
+ }
+ }
+
+ if (!scenario.isEmpty()) {
+ QVERIFY(scenario.first().startsWith("S: "));
+ }
+
+ *it = scenario;
+ *scenarioNumber = std::distance(m_scenarios.begin(), it);
+ QVERIFY(*scenarioNumber < m_scenarios.count());
+}
+
+int FakeServer::port() const
+{
+ return m_port;
+}
--- /dev/null
+/*
+ SPDX-FileCopyrightText: 2008 Omat Holding B .V. <info@omat.nl>
+ SPDX-FileCopyrightText: 2010 Klarälvdalens Datakonsult AB , a KDAB Group company <info@kdab.com>
+ SPDX-FileContributor: Kevin Ottens <kevin@kdab.com>
+ SPDX-FileCopyrightText: 2017 Sandro Kanuß <knauss@kde.org>
+
+ SPDX-License-Identifier: GPL-2.0-or-later
+*/
+
+#ifndef FAKESERVER_H
+#define FAKESERVER_H
+
+#include <QMutex>
+#include <QTcpServer>
+#include <QTcpSocket>
+#include <QThread>
+
+Q_DECLARE_METATYPE(QList<QByteArray>)
+
+/**
+ * Pretends to be an DAV server for the purposes of unit tests.
+ *
+ * FakeServer does not really understand the DAV protocol. Instead,
+ * you give it a script, or scenario, that lists how an DAV session
+ * exchange should go. When it receives the client parts of the
+ * scenario, it will respond with the following server parts.
+ *
+ * The server can be furnished with several scenarios. The first
+ * scenario will be played out to the first client that connects, the
+ * second scenario to the second client connection and so on.
+ *
+ * The fake server runs as a separate thread in the same process it
+ * is started from, and listens for connections (see port() method) on the
+ * local machine.
+ *
+ * Scenarios are in the form of protocol messages, with a tag at the
+ * start to indicate whether it is message that will be sent by the
+ * client ("C: ") or a response that should be sent by the server
+ * ("S: "). Or ("D: ") for the exchanged data. Content-length header is added
+ * automatically with the current length and also the empty line between Header
+ * and Content. For example:
+ * @code
+ * C: GET /item HTTP/1.1
+ * S: HTTP/1.0 200 OK
+ * D: much data
+ * D: more data
+ * X
+ * @endcode
+ *
+ * A line starting with X indicates that the connection should be
+ * closed by the server. This should be the last line in the
+ * scenario.
+
+ * A typical usage is something like
+ * @code
+ * QList<QByteArray> scenario;
+ * scenario << "C: GET /item HTTP/1.1"
+ * << "S: HTTP/1.0 200 OK"
+ * << "D: much data"
+ * << "D: more data"
+ * << "X";
+ *
+ * FakeServer fakeServer;
+ * fakeServer.setScenario(scenario);
+ * fakeServer.startAndWait();
+ *
+ * QUrl url(QStringLiteral("http://localhost/item"));
+ * url.setPort(fakeServer.port());
+ * KDAV::DavUrl davUrl(url, KDAV::CardDav);
+ * KDAV::DavItem item(davUrl, QString(), QByteArray(), QString());
+ *
+ * auto job = new KDAV::DavItemFetchJob(item);
+ * job->exec();
+ * fakeServer.quit();
+ * QVERIFY(fakeServer.isAllScenarioDone());
+ * @endcode
+ */
+
+class FakeServer : public QObject
+{
+ Q_OBJECT
+
+public:
+ /**
+ * Each unittest should use a different port so that they can be run in parallel
+ */
+ FakeServer(int port = 5989, QObject *parent = nullptr);
+ ~FakeServer() override;
+
+ /**
+ * Starts the server and waits for it to be ready
+ *
+ * You should use this instead of start() to avoid race conditions.
+ */
+ void startAndWait();
+
+ /**
+ * Removes any previously-added scenarios, and adds a new one
+ *
+ * After this, there will only be one scenario, and so the fake
+ * server will only be able to service a single request. More
+ * scenarios can be added with addScenario, though.
+ *
+ * @see addScenario()\n
+ * addScenarioFromFile()
+ */
+ void setScenario(const QList<QByteArray> &scenario);
+
+ /**
+ * Adds a new scenario
+ *
+ * Note that scenarios will be used in the order that clients
+ * connect. If this is the 5th scenario that has been added
+ * (bearing in mind that setScenario() resets the scenario
+ * count), it will be used to service the 5th client that
+ * connects.
+ *
+ * @see addScenarioFromFile()
+ *
+ * @param scenario the scenario as a list of messages
+ */
+ void addScenario(const QList<QByteArray> &scenario);
+ /**
+ * Adds a new scenario from a local file
+ *
+ * Note that scenarios will be used in the order that clients
+ * connect. If this is the 5th scenario that has been added
+ * (bearing in mind that setScenario() resets the scenario
+ * count), it will be used to service the 5th client that
+ * connects.
+ *
+ * @see addScenario()
+ *
+ * @param fileName the name of the file that contains the
+ * scenario; it will be split at line
+ * boundaries, and excess whitespace will
+ * be trimmed from the start and end of lines
+ */
+ void addScenarioFromFile(const QString &fileName);
+
+ /**
+ * Checks whether a particular scenario has completed
+ *
+ * @param scenarioNumber the number of the scenario to check,
+ * in order of addition/client connection
+ */
+ bool isScenarioDone(int scenarioNumber) const;
+ /**
+ * Whether all the scenarios that were added to the fake
+ * server have been completed.
+ */
+ bool isAllScenarioDone() const;
+
+ /**
+ * Returns the port where the fake server is listening.
+ */
+ int port() const;
+
+private Q_SLOTS:
+ void newConnection();
+ void dataAvailable();
+ void init();
+ void cleanup();
+
+private:
+ void writeServerPart(QTcpSocket *clientSocket, int scenarioNumber);
+ void readClientPart(QTcpSocket *socket, int *scenarioNumber);
+
+ QList<QList<QByteArray>> m_scenarios;
+ QTcpServer *m_tcpServer = nullptr;
+ mutable QMutex m_mutex;
+ QList<QTcpSocket *> m_clientSockets;
+ QThread *m_thread;
+ int m_port;
+};
+
+#endif
--- /dev/null
+maintainer:
+fancyname: KDAV
+description: An DAV protocol implementation with KJobs
+tier: 3
+type: functional
+platforms:
+ - name: All
+portingAid: false
+deprecated: false
+release: true
+libraries:
+ - qmake: KDAV
+ cmake: "KF5::DAV"
+cmakename: KF5DAV
+
+public_lib: true
+group: Frameworks
+subgroup: Tier 3
--- /dev/null
+# Copyright (C) YEAR This_file_is_part_of_KDE
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Safa Alfulaij <safa1996alfulaij@gmail.com>, 2018.
+msgid ""
+msgstr ""
+"Project-Id-Version: \n"
+"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
+"POT-Creation-Date: 2021-03-09 02:40+0100\n"
+"PO-Revision-Date: 2018-01-31 22:49+0300\n"
+"Last-Translator: Safa Alfulaij <safa1996alfulaij@gmail.com>\n"
+"Language-Team: Arabic <doc@arabeyes.org>\n"
+"Language: ar\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 "
+"&& n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;\n"
+"X-Generator: Lokalize 2.0\n"
+
+#: common/daverror.cpp:88
+#, kde-format
+msgid "Invalid username/password"
+msgstr "اسم المستخدم/كلمة السّرّ غير صالحة"
+
+#: common/daverror.cpp:90
+#, kde-format
+msgid "Access forbidden"
+msgstr "النّفاذ ممنوع"
+
+#: common/daverror.cpp:92
+#, kde-format
+msgid "Resource not found"
+msgstr "لم يُعثر على المورد"
+
+#: common/daverror.cpp:94
+#, kde-format
+msgid "HTTP error"
+msgstr "خطأ HTTP"
+
+#: common/daverror.cpp:96
+#, kde-format
+msgid ""
+"There was a problem with the request.\n"
+"%1 (%2)."
+msgstr ""
+"حدثت مشكلة بالطّلب.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:99
+#, kde-format
+msgid "Protocol for the collection does not support MULTIGET"
+msgstr "لا يدعم ميفاق التّجميعات MULTIGET"
+
+#: common/daverror.cpp:102
+#, kde-format
+msgid ""
+"The server encountered an error that prevented it from completing your "
+"request: %1 (%2)"
+msgstr "واجه الخادوم خطأً منعه من إكمال الطّلب: %1 (%2)"
+
+#: common/daverror.cpp:105
+#, kde-format
+msgid ""
+"There was a problem with the request. The collection has not been deleted "
+"from the server.\n"
+"%1 (%2)."
+msgstr ""
+"حدثت مشكلة بالطّلب. لم تُحذف التّجميعة من الخادوم.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:108
+#, kde-format
+msgid "Invalid responses from backend"
+msgstr "ردود غير صالحة من السّند"
+
+#: common/daverror.cpp:111
+#, kde-format
+msgid "Error setting focus for XQuery"
+msgstr "خطأ في ضبط التّركيز على XQuery"
+
+#: common/daverror.cpp:114
+#, kde-format
+msgid "Invalid XQuery submitted by DAV implementation"
+msgstr "أرسل تنفيذ DAV استعلام XQuery غير صالح"
+
+#: common/daverror.cpp:118
+#, kde-format
+msgid ""
+"There was a problem with the request. The collection has not been modified "
+"on the server.\n"
+"%1 (%2)."
+msgstr ""
+"حدثت مشكلة بالطّلب. لم تُعدّل التّجميعة في الخادوم.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:124
+#, kde-format
+msgid "No properties to change or remove"
+msgstr "لا خصائص لتغييرها أو إزالتها"
+
+#: common/daverror.cpp:127
+#, kde-format
+msgid "There was an error when modifying the properties"
+msgstr "حدث خطأ أثناء تعديل الخصائص"
+
+#: common/daverror.cpp:129
+#, kde-format
+msgid ""
+"\n"
+"The server returned more information:\n"
+"%1"
+msgstr ""
+"\n"
+"أعاد الخادوم معلومات أكثر:\n"
+"%1"
+
+#: common/daverror.cpp:133
+#, kde-format
+msgid ""
+"There was a problem with the request. The item has not been created on the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+"حدثت مشكلة بالطّلب. لم يُنشأ العنصر في الخادوم.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:136
+#, kde-format
+msgid ""
+"There was a problem with the request. The item has not been deleted from the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+"حدثت مشكلة بالطّلب. لم يُحذف العنصر من الخادوم.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:139
+#, kde-format
+msgid ""
+"There was a problem with the request. The item was not modified on the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+"حدثت مشكلة بالطّلب. لم يُعدّل العنصر في الخادوم.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:142
+#, kde-format
+msgid "There was a problem with the request."
+msgstr "حدثت مشكلة بالطّلب."
+
+#: common/daverror.cpp:146
+#, kde-format
+msgid ""
+"There was a problem with the request. The requested MIME types are not "
+"supported."
+msgstr "حدثت مشكلة بالطّلب. أنواع MIME المطلوبة غير مدعومة."
--- /dev/null
+# Copyright (C) YEAR This file is copyright:
+# This file is distributed under the same license as the kdav package.
+#
+# Kheyyam Gojayev <xxmn77@gmail.com>, 2021.
+msgid ""
+msgstr ""
+"Project-Id-Version: kdav\n"
+"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
+"POT-Creation-Date: 2021-03-09 02:40+0100\n"
+"PO-Revision-Date: 2021-02-08 17:35+0400\n"
+"Last-Translator: Kheyyam Gojayev <xxmn77@gmail.com>\n"
+"Language-Team: Azerbaijani <kde-i18n-doc@kde.org>\n"
+"Language: az\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Generator: Lokalize 20.12.2\n"
+
+#: common/daverror.cpp:88
+#, kde-format
+msgid "Invalid username/password"
+msgstr "İstifadəçi adı və ya şifrə səhvdir"
+
+#: common/daverror.cpp:90
+#, kde-format
+msgid "Access forbidden"
+msgstr "Giriş qadağandır"
+
+#: common/daverror.cpp:92
+#, kde-format
+msgid "Resource not found"
+msgstr "Resurs tapılmadı"
+
+#: common/daverror.cpp:94
+#, kde-format
+msgid "HTTP error"
+msgstr "HTTP xətası"
+
+#: common/daverror.cpp:96
+#, kde-format
+msgid ""
+"There was a problem with the request.\n"
+"%1 (%2)."
+msgstr ""
+"Tələb ilə bağlı problem var.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:99
+#, kde-format
+msgid "Protocol for the collection does not support MULTIGET"
+msgstr "Kolleksiya üçün protokol MULTIGET dəstəkləmir"
+
+#: common/daverror.cpp:102
+#, kde-format
+msgid ""
+"The server encountered an error that prevented it from completing your "
+"request: %1 (%2)"
+msgstr ""
+"Server, sorğunuzun yerinə yetirməsinə mane olan bir səhvlə qarşılaşdı: %1 "
+"(%2)"
+
+#: common/daverror.cpp:105
+#, kde-format
+msgid ""
+"There was a problem with the request. The collection has not been deleted "
+"from the server.\n"
+"%1 (%2)."
+msgstr ""
+"Tələb ilə bağlı problem var. Bu kolleksiya serverdən silinə bilmədi\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:108
+#, kde-format
+msgid "Invalid responses from backend"
+msgstr "Server tərəfdən səhv cavablar"
+
+#: common/daverror.cpp:111
+#, kde-format
+msgid "Error setting focus for XQuery"
+msgstr "XQuery üçün fokus qurulmasında xəta"
+
+#: common/daverror.cpp:114
+#, kde-format
+msgid "Invalid XQuery submitted by DAV implementation"
+msgstr "DAV tətbiqi tərəfindən göndərilən etibarsız XQuery"
+
+#: common/daverror.cpp:118
+#, kde-format
+msgid ""
+"There was a problem with the request. The collection has not been modified "
+"on the server.\n"
+"%1 (%2)."
+msgstr ""
+"Tələb ilə bağlı problem var. Bu kolleksiya serverdə dəyişdirilə bilmədi\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:124
+#, kde-format
+msgid "No properties to change or remove"
+msgstr "Dəyişdirmək və silmək xüsusiyyətlərinə malik deyil"
+
+#: common/daverror.cpp:127
+#, kde-format
+msgid "There was an error when modifying the properties"
+msgstr "Xüsusiyyətləri dəyişdirərkən xəta baş verdi"
+
+#: common/daverror.cpp:129
+#, kde-format
+msgid ""
+"\n"
+"The server returned more information:\n"
+"%1"
+msgstr ""
+"\n"
+"Server daha çox məlumat qaytardı:\n"
+"%1"
+
+#: common/daverror.cpp:133
+#, kde-format
+msgid ""
+"There was a problem with the request. The item has not been created on the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+"Tələb ilə bağlı problem var. Bu kolleksiya serverdə yaradıla bilmədi\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:136
+#, kde-format
+msgid ""
+"There was a problem with the request. The item has not been deleted from the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+"Tələb ilə bağlı problem var. Bu element serverdən silinə bilmədi\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:139
+#, kde-format
+msgid ""
+"There was a problem with the request. The item was not modified on the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+"Tələb ilə bağlı problem var. Bu element serverdə dəyişdirilə bilmədi\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:142
+#, kde-format
+msgid "There was a problem with the request."
+msgstr "Tələb ilə bağlı problem var."
+
+#: common/daverror.cpp:146
+#, kde-format
+msgid ""
+"There was a problem with the request. The requested MIME types are not "
+"supported."
+msgstr "Tələb ilə bağlı problem var. Tələb olunnan MİME növləri dəstəklənmədi."
--- /dev/null
+# Mincho Kondarev <mkondarev@yahoo.de>, 2022.
+msgid ""
+msgstr ""
+"Project-Id-Version: \n"
+"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
+"POT-Creation-Date: 2021-03-09 02:40+0100\n"
+"PO-Revision-Date: 2022-05-20 18:59+0200\n"
+"Last-Translator: Mincho Kondarev <mkondarev@yahoo.de>\n"
+"Language-Team: Bulgarian <kde-i18n-doc@kde.org>\n"
+"Language: bg\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: Lokalize 22.04.0\n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+
+#: common/daverror.cpp:88
+#, kde-format
+msgid "Invalid username/password"
+msgstr "Невалидно потребителско име/парола"
+
+#: common/daverror.cpp:90
+#, kde-format
+msgid "Access forbidden"
+msgstr "Достъпът е забранен"
+
+#: common/daverror.cpp:92
+#, kde-format
+msgid "Resource not found"
+msgstr "Ресурсът не е намерен"
+
+#: common/daverror.cpp:94
+#, kde-format
+msgid "HTTP error"
+msgstr "HTTP грешка"
+
+#: common/daverror.cpp:96
+#, kde-format
+msgid ""
+"There was a problem with the request.\n"
+"%1 (%2)."
+msgstr ""
+"Имаше проблем със заявката.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:99
+#, kde-format
+msgid "Protocol for the collection does not support MULTIGET"
+msgstr "Протоколът за колекцията не поддържа MULTIGET"
+
+#: common/daverror.cpp:102
+#, kde-format
+msgid ""
+"The server encountered an error that prevented it from completing your "
+"request: %1 (%2)"
+msgstr ""
+"Сървърът срещна грешка, която му попречи да завърши вашата заявка: %1 (%2)"
+
+#: common/daverror.cpp:105
+#, kde-format
+msgid ""
+"There was a problem with the request. The collection has not been deleted "
+"from the server.\n"
+"%1 (%2)."
+msgstr ""
+"Имаше проблем със заявката. Колекцията не е изтрита от сървъра.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:108
+#, kde-format
+msgid "Invalid responses from backend"
+msgstr "Невалидни отговори от бекенда"
+
+#: common/daverror.cpp:111
+#, kde-format
+msgid "Error setting focus for XQuery"
+msgstr "Грешка при задаване на фокуса за XQuery"
+
+#: common/daverror.cpp:114
+#, kde-format
+msgid "Invalid XQuery submitted by DAV implementation"
+msgstr "Невалиден XQuery, изпратен от внедряването на DAV"
+
+#: common/daverror.cpp:118
+#, kde-format
+msgid ""
+"There was a problem with the request. The collection has not been modified "
+"on the server.\n"
+"%1 (%2)."
+msgstr ""
+"Имаше проблем със заявката. Колекцията не е модифицирана на сървъра.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:124
+#, kde-format
+msgid "No properties to change or remove"
+msgstr "Няма свойства за промяна или премахване"
+
+#: common/daverror.cpp:127
+#, kde-format
+msgid "There was an error when modifying the properties"
+msgstr "При промяна на свойствата възникна грешка"
+
+#: common/daverror.cpp:129
+#, kde-format
+msgid ""
+"\n"
+"The server returned more information:\n"
+"%1"
+msgstr ""
+"\n"
+"Сървърът върна повече информация:\n"
+"%1"
+
+#: common/daverror.cpp:133
+#, kde-format
+msgid ""
+"There was a problem with the request. The item has not been created on the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+"Имаше проблем със заявката. Елементът не е създаден в сървър.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:136
+#, kde-format
+msgid ""
+"There was a problem with the request. The item has not been deleted from the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+"Имаше проблем със заявката. Елементът не е изтрит от сървър.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:139
+#, kde-format
+msgid ""
+"There was a problem with the request. The item was not modified on the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+"Имаше проблем със заявката. Артикулът не е модифициран на сървър.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:142
+#, kde-format
+msgid "There was a problem with the request."
+msgstr "Имаше проблем със заявката."
+
+#: common/daverror.cpp:146
+#, kde-format
+msgid ""
+"There was a problem with the request. The requested MIME types are not "
+"supported."
+msgstr "Имаше проблем със заявката. Исканите MIME типове не се поддържат."
--- /dev/null
+# Translation of libkdav.po to Catalan
+# Copyright (C) 2009-2017 This_file_is_part_of_KDE
+# This file is distributed under the license LGPL version 2.1 or
+# version 3 or later versions approved by the membership of KDE e.V.
+#
+# Manuel Tortosa Moreno <manutortosa@gmail.com>, 2009, 2010.
+# Josep M. Ferrer <txemaq@gmail.com>, 2010, 2011, 2012, 2015, 2017.
+# Antoni Bella Pérez <antonibella5@yahoo.com>, 2012, 2013, 2014, 2015, 2016, 2017.
+msgid ""
+msgstr ""
+"Project-Id-Version: kdav\n"
+"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
+"POT-Creation-Date: 2021-03-09 02:40+0100\n"
+"PO-Revision-Date: 2017-12-12 12:17+0100\n"
+"Last-Translator: Antoni Bella Pérez <antonibella5@yahoo.com>\n"
+"Language-Team: Catalan <kde-i18n-ca@kde.org>\n"
+"Language: ca\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: Lokalize 2.0\n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+"X-Accelerator-Marker: &\n"
+
+#: common/daverror.cpp:88
+#, kde-format
+msgid "Invalid username/password"
+msgstr "Nom d'usuari o contrasenya no vàlids"
+
+#: common/daverror.cpp:90
+#, kde-format
+msgid "Access forbidden"
+msgstr "Accés prohibit"
+
+#: common/daverror.cpp:92
+#, kde-format
+msgid "Resource not found"
+msgstr "No s'ha trobat el recurs"
+
+#: common/daverror.cpp:94
+#, kde-format
+msgid "HTTP error"
+msgstr "Error d'HTTP"
+
+#: common/daverror.cpp:96
+#, kde-format
+msgid ""
+"There was a problem with the request.\n"
+"%1 (%2)."
+msgstr ""
+"S'ha produït un problema amb la sol·licitud.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:99
+#, kde-format
+msgid "Protocol for the collection does not support MULTIGET"
+msgstr "El protocol per a la col·lecció no permet MULTIGET"
+
+#: common/daverror.cpp:102
+#, kde-format
+msgid ""
+"The server encountered an error that prevented it from completing your "
+"request: %1 (%2)"
+msgstr ""
+"El servidor ha trobat un error que impedeix completar la vostra sol·licitud: "
+"%1 (%2)"
+
+#: common/daverror.cpp:105
+#, kde-format
+msgid ""
+"There was a problem with the request. The collection has not been deleted "
+"from the server.\n"
+"%1 (%2)."
+msgstr ""
+"S'ha produït un problema amb la sol·licitud. La col·lecció no ha estat "
+"eliminada del servidor.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:108
+#, kde-format
+msgid "Invalid responses from backend"
+msgstr "Respostes no vàlides del dorsal"
+
+#: common/daverror.cpp:111
+#, kde-format
+msgid "Error setting focus for XQuery"
+msgstr "Error en establir el focus a XQuery"
+
+#: common/daverror.cpp:114
+#, kde-format
+msgid "Invalid XQuery submitted by DAV implementation"
+msgstr "XQuery no vàlida enviada per la implementació DAV"
+
+#: common/daverror.cpp:118
+#, kde-format
+msgid ""
+"There was a problem with the request. The collection has not been modified "
+"on the server.\n"
+"%1 (%2)."
+msgstr ""
+"S'ha produït un problema amb la sol·licitud. La col·lecció no ha estat "
+"modificada en el servidor.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:124
+#, kde-format
+msgid "No properties to change or remove"
+msgstr "No hi ha cap propietat a canviar o eliminar"
+
+#: common/daverror.cpp:127
+#, kde-format
+msgid "There was an error when modifying the properties"
+msgstr "S'ha produït un error en modificar les propietats"
+
+#: common/daverror.cpp:129
+#, kde-format
+msgid ""
+"\n"
+"The server returned more information:\n"
+"%1"
+msgstr ""
+"\n"
+"El servidor ha retornat més informació:\n"
+"%1"
+
+#: common/daverror.cpp:133
+#, kde-format
+msgid ""
+"There was a problem with the request. The item has not been created on the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+"S'ha produït un problema amb la sol·licitud. L'element no ha estat creat en "
+"el servidor.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:136
+#, kde-format
+msgid ""
+"There was a problem with the request. The item has not been deleted from the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+"S'ha produït un problema amb la sol·licitud. L'element no ha estat eliminat "
+"del servidor.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:139
+#, kde-format
+msgid ""
+"There was a problem with the request. The item was not modified on the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+"S'ha produït un problema amb la sol·licitud. L'element no ha estat modificat "
+"en el servidor.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:142
+#, kde-format
+msgid "There was a problem with the request."
+msgstr "S'ha produït un problema amb la sol·licitud."
+
+#: common/daverror.cpp:146
+#, kde-format
+msgid ""
+"There was a problem with the request. The requested MIME types are not "
+"supported."
+msgstr ""
+"S'ha produït un problema amb la sol·licitud. Els tipus MIME requerits no "
+"estan implementats."
--- /dev/null
+# Translation of libkdav.po to Catalan (Valencian)
+# Copyright (C) 2009-2017 This_file_is_part_of_KDE
+# This file is distributed under the license LGPL version 2.1 or
+# version 3 or later versions approved by the membership of KDE e.V.
+#
+# Manuel Tortosa Moreno <manutortosa@gmail.com>, 2009, 2010.
+# Josep M. Ferrer <txemaq@gmail.com>, 2010, 2011, 2012, 2015, 2017.
+# Antoni Bella Pérez <antonibella5@yahoo.com>, 2012, 2013, 2014, 2015, 2016, 2017.
+msgid ""
+msgstr ""
+"Project-Id-Version: kdav\n"
+"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
+"POT-Creation-Date: 2021-03-09 02:40+0100\n"
+"PO-Revision-Date: 2017-12-12 12:17+0100\n"
+"Last-Translator: Antoni Bella Pérez <antonibella5@yahoo.com>\n"
+"Language-Team: Catalan <kde-i18n-ca@kde.org>\n"
+"Language: ca@valencia\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: Lokalize 2.0\n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+"X-Accelerator-Marker: &\n"
+
+#: common/daverror.cpp:88
+#, kde-format
+msgid "Invalid username/password"
+msgstr "Nom d'usuari o contrasenya no vàlids"
+
+#: common/daverror.cpp:90
+#, kde-format
+msgid "Access forbidden"
+msgstr "Accés prohibit"
+
+#: common/daverror.cpp:92
+#, kde-format
+msgid "Resource not found"
+msgstr "No s'ha trobat el recurs"
+
+#: common/daverror.cpp:94
+#, kde-format
+msgid "HTTP error"
+msgstr "S'ha produït un error d'HTTP"
+
+#: common/daverror.cpp:96
+#, kde-format
+msgid ""
+"There was a problem with the request.\n"
+"%1 (%2)."
+msgstr ""
+"S'ha produït un problema amb la sol·licitud.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:99
+#, kde-format
+msgid "Protocol for the collection does not support MULTIGET"
+msgstr "El protocol per a la col·lecció no permet MULTIGET"
+
+#: common/daverror.cpp:102
+#, kde-format
+msgid ""
+"The server encountered an error that prevented it from completing your "
+"request: %1 (%2)"
+msgstr ""
+"El servidor ha trobat un error que impedix completar la vostra sol·licitud: "
+"%1 (%2)"
+
+#: common/daverror.cpp:105
+#, kde-format
+msgid ""
+"There was a problem with the request. The collection has not been deleted "
+"from the server.\n"
+"%1 (%2)."
+msgstr ""
+"S'ha produït un problema amb la sol·licitud. La col·lecció no ha sigut "
+"eliminada del servidor.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:108
+#, kde-format
+msgid "Invalid responses from backend"
+msgstr "Respostes no vàlides del dorsal"
+
+#: common/daverror.cpp:111
+#, kde-format
+msgid "Error setting focus for XQuery"
+msgstr "S'ha produït un error en establir el focus a XQuery"
+
+#: common/daverror.cpp:114
+#, kde-format
+msgid "Invalid XQuery submitted by DAV implementation"
+msgstr "XQuery no vàlida enviada per la implementació DAV"
+
+#: common/daverror.cpp:118
+#, kde-format
+msgid ""
+"There was a problem with the request. The collection has not been modified "
+"on the server.\n"
+"%1 (%2)."
+msgstr ""
+"S'ha produït un problema amb la sol·licitud. La col·lecció no ha sigut "
+"modificada en el servidor.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:124
+#, kde-format
+msgid "No properties to change or remove"
+msgstr "No hi ha cap propietat que calga canviar o eliminar"
+
+#: common/daverror.cpp:127
+#, kde-format
+msgid "There was an error when modifying the properties"
+msgstr "S'ha produït un error en modificar les propietats"
+
+#: common/daverror.cpp:129
+#, kde-format
+msgid ""
+"\n"
+"The server returned more information:\n"
+"%1"
+msgstr ""
+"\n"
+"El servidor ha retornat més informació:\n"
+"%1"
+
+#: common/daverror.cpp:133
+#, kde-format
+msgid ""
+"There was a problem with the request. The item has not been created on the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+"S'ha produït un problema amb la sol·licitud. L'element no ha sigut creat en "
+"el servidor.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:136
+#, kde-format
+msgid ""
+"There was a problem with the request. The item has not been deleted from the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+"S'ha produït un problema amb la sol·licitud. L'element no ha sigut eliminat "
+"del servidor.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:139
+#, kde-format
+msgid ""
+"There was a problem with the request. The item was not modified on the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+"S'ha produït un problema amb la sol·licitud. L'element no ha sigut modificat "
+"en el servidor.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:142
+#, kde-format
+msgid "There was a problem with the request."
+msgstr "S'ha produït un problema amb la sol·licitud."
+
+#: common/daverror.cpp:146
+#, kde-format
+msgid ""
+"There was a problem with the request. The requested MIME types are not "
+"supported."
+msgstr ""
+"S'ha produït un problema amb la sol·licitud. Els tipus MIME requerits no "
+"estan implementats."
--- /dev/null
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# Vít Pelčák <vit@pelcak.org>, 2010, 2011, 2013, 2016, 2017, 2018.
+# Tomáš Chvátal <tomas.chvatal@gmail.com>, 2012.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: \n"
+"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
+"POT-Creation-Date: 2021-03-09 02:40+0100\n"
+"PO-Revision-Date: 2017-02-27 13:49+0100\n"
+"Last-Translator: Vít Pelčák <vit@pelcak.org>\n"
+"Language-Team: Czech <kde-i18n-doc@kde.org>\n"
+"Language: cs\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n"
+"X-Generator: Lokalize 2.0\n"
+
+#: common/daverror.cpp:88
+#, kde-format
+msgid "Invalid username/password"
+msgstr "Neplatné uživatelské jméno nebo heslo"
+
+#: common/daverror.cpp:90
+#, kde-format
+msgid "Access forbidden"
+msgstr "Přístup zakázán"
+
+#: common/daverror.cpp:92
+#, kde-format
+msgid "Resource not found"
+msgstr "Zdroj nebyl nalezen"
+
+#: common/daverror.cpp:94
+#, kde-format
+msgid "HTTP error"
+msgstr "Chyba HTTP"
+
+#: common/daverror.cpp:96
+#, kde-format
+msgid ""
+"There was a problem with the request.\n"
+"%1 (%2)."
+msgstr ""
+
+#: common/daverror.cpp:99
+#, kde-format
+msgid "Protocol for the collection does not support MULTIGET"
+msgstr ""
+
+#: common/daverror.cpp:102
+#, kde-format
+msgid ""
+"The server encountered an error that prevented it from completing your "
+"request: %1 (%2)"
+msgstr ""
+
+#: common/daverror.cpp:105
+#, kde-format
+msgid ""
+"There was a problem with the request. The collection has not been deleted "
+"from the server.\n"
+"%1 (%2)."
+msgstr ""
+
+#: common/daverror.cpp:108
+#, kde-format
+msgid "Invalid responses from backend"
+msgstr ""
+
+#: common/daverror.cpp:111
+#, kde-format
+msgid "Error setting focus for XQuery"
+msgstr ""
+
+#: common/daverror.cpp:114
+#, kde-format
+msgid "Invalid XQuery submitted by DAV implementation"
+msgstr ""
+
+#: common/daverror.cpp:118
+#, kde-format
+msgid ""
+"There was a problem with the request. The collection has not been modified "
+"on the server.\n"
+"%1 (%2)."
+msgstr ""
+
+#: common/daverror.cpp:124
+#, kde-format
+msgid "No properties to change or remove"
+msgstr ""
+
+#: common/daverror.cpp:127
+#, kde-format
+msgid "There was an error when modifying the properties"
+msgstr ""
+
+#: common/daverror.cpp:129
+#, kde-format
+msgid ""
+"\n"
+"The server returned more information:\n"
+"%1"
+msgstr ""
+"\n"
+"Server navrátil více informací:\n"
+"%1"
+
+#: common/daverror.cpp:133
+#, kde-format
+msgid ""
+"There was a problem with the request. The item has not been created on the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+
+#: common/daverror.cpp:136
+#, kde-format
+msgid ""
+"There was a problem with the request. The item has not been deleted from the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+
+#: common/daverror.cpp:139
+#, kde-format
+msgid ""
+"There was a problem with the request. The item was not modified on the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+
+#: common/daverror.cpp:142
+#, kde-format
+msgid "There was a problem with the request."
+msgstr "V požadavku nastal problém."
+
+#: common/daverror.cpp:146
+#, kde-format
+msgid ""
+"There was a problem with the request. The requested MIME types are not "
+"supported."
+msgstr ""
--- /dev/null
+# Burkhard Lück <lueck@hube-lueck.de>, 2009, 2011, 2013, 2014, 2015, 2017, 2018, 2020, 2021.
+# Frederik Schwarzer <schwarzer@kde.org>, 2010, 2011, 2016, 2020.
+# Panagiotis Papadopoulos <pano_90@gmx.net>, 2010.
+# Peter Rüthemann <peter.ruethemann@gmx.ch>, 2010.
+# Torbjörn Klatt <opensource@torbjoern-klatt.de>, 2011.
+# Rolf Eike Beer <kde@opensource.sf-tec.de>, 2011.
+msgid ""
+msgstr ""
+"Project-Id-Version: akonadi_davgroupware_resource\n"
+"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
+"POT-Creation-Date: 2021-03-09 02:40+0100\n"
+"PO-Revision-Date: 2021-05-31 15:13+0200\n"
+"Last-Translator: Burkhard Lück <lueck@hube-lueck.de>\n"
+"Language-Team: German <kde-i18n-de@kde.org>\n"
+"Language: de\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+
+#: common/daverror.cpp:88
+#, kde-format
+msgid "Invalid username/password"
+msgstr "Ungültiger Benutzername/Passwort"
+
+#: common/daverror.cpp:90
+#, kde-format
+msgid "Access forbidden"
+msgstr "Zugriff unzulässig"
+
+#: common/daverror.cpp:92
+#, kde-format
+msgid "Resource not found"
+msgstr "Die Ressource wurde nicht gefunden"
+
+#: common/daverror.cpp:94
+#, kde-format
+msgid "HTTP error"
+msgstr "HTTP-Fehler"
+
+#: common/daverror.cpp:96
+#, kde-format
+msgid ""
+"There was a problem with the request.\n"
+"%1 (%2)."
+msgstr ""
+"Bei der Abfrage ist ein Problem aufgetreten\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:99
+#, kde-format
+msgid "Protocol for the collection does not support MULTIGET"
+msgstr "Das Protokoll für die Sammlung unterstützt MULTIGET nicht."
+
+#: common/daverror.cpp:102
+#, kde-format
+msgid ""
+"The server encountered an error that prevented it from completing your "
+"request: %1 (%2)"
+msgstr ""
+"Der Server hat einen Fehler festgestellt, der die Fertigstellung Ihrer "
+"Abfrage verhindert: %1 (%2)"
+
+#: common/daverror.cpp:105
+#, kde-format
+msgid ""
+"There was a problem with the request. The collection has not been deleted "
+"from the server.\n"
+"%1 (%2)."
+msgstr ""
+"Bei der Abfrage ist ein Problem aufgetreten. Die Sammlung wurde nicht vom "
+"Server gelöscht.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:108
+#, kde-format
+msgid "Invalid responses from backend"
+msgstr "Ungültige Antwort des Treibers"
+
+#: common/daverror.cpp:111
+#, kde-format
+msgid "Error setting focus for XQuery"
+msgstr "Fehler beim Bestimmen des Fokus für XQuery"
+
+#: common/daverror.cpp:114
+#, kde-format
+msgid "Invalid XQuery submitted by DAV implementation"
+msgstr "DAV-Implementation hat ungültige XQuery übermittelt"
+
+#: common/daverror.cpp:118
+#, kde-format
+msgid ""
+"There was a problem with the request. The collection has not been modified "
+"on the server.\n"
+"%1 (%2)."
+msgstr ""
+"Bei der Abfrage ist ein Problem aufgetreten. Die Sammlung wurde auf dem "
+"Server nicht verändert.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:124
+#, kde-format
+msgid "No properties to change or remove"
+msgstr ""
+"Keine Eigenschaften vorhanden, die verändert oder gelöscht werden können."
+
+#: common/daverror.cpp:127
+#, kde-format
+msgid "There was an error when modifying the properties"
+msgstr "Problem beim Anpassen der Eigenschaften"
+
+#: common/daverror.cpp:129
+#, kde-format
+msgid ""
+"\n"
+"The server returned more information:\n"
+"%1"
+msgstr ""
+"\n"
+"Der Server hat weitere Informationen zurückgegeben:\n"
+"%1"
+
+#: common/daverror.cpp:133
+#, kde-format
+msgid ""
+"There was a problem with the request. The item has not been created on the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+"Bei der Abfrage ist ein Problem aufgetreten. Der Eintrag wurde auf dem "
+"Server nicht erstellt\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:136
+#, kde-format
+msgid ""
+"There was a problem with the request. The item has not been deleted from the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+"Bei der Abfrage ist ein Problem aufgetreten. Der Eintrag wurde nicht vom "
+"Server gelöscht\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:139
+#, kde-format
+msgid ""
+"There was a problem with the request. The item was not modified on the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+"Bei der Abfrage ist ein Problem aufgetreten. Der Eintrag wurde auf dem "
+"Server nicht verändert\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:142
+#, kde-format
+msgid "There was a problem with the request."
+msgstr "Bei der Abfrage ist ein Problem aufgetreten"
+
+#: common/daverror.cpp:146
+#, kde-format
+msgid ""
+"There was a problem with the request. The requested MIME types are not "
+"supported."
+msgstr ""
+"Bei der Abfrage ist ein Problem aufgetreten. Die angeforderte MIME-Typen "
+"werden nicht unterstützt."
--- /dev/null
+# Copyright (C) YEAR This file is copyright:
+# This file is distributed under the same license as the kdav package.
+#
+# Stelios <sstavra@gmail.com>, 2020.
+msgid ""
+msgstr ""
+"Project-Id-Version: kdav\n"
+"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
+"POT-Creation-Date: 2021-03-09 02:40+0100\n"
+"PO-Revision-Date: 2020-09-13 16:21+0300\n"
+"Last-Translator: Stelios <sstavra@gmail.com>\n"
+"Language-Team: Greek <kde-i18n-el@kde.org>\n"
+"Language: el\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+"X-Generator: Lokalize 20.04.2\n"
+
+#: common/daverror.cpp:88
+#, kde-format
+msgid "Invalid username/password"
+msgstr "Μη έγκυρα όνομα χρήστη ή κωδικός πρόσβασης"
+
+#: common/daverror.cpp:90
+#, kde-format
+msgid "Access forbidden"
+msgstr "Η πρόσβαση απαγορεύεται"
+
+#: common/daverror.cpp:92
+#, kde-format
+msgid "Resource not found"
+msgstr "Ο πόρος δε βρέθηκε"
+
+#: common/daverror.cpp:94
+#, kde-format
+msgid "HTTP error"
+msgstr "HTTP σφάλμα"
+
+#: common/daverror.cpp:96
+#, kde-format
+msgid ""
+"There was a problem with the request.\n"
+"%1 (%2)."
+msgstr ""
+"Παρουσιάστηκε κάποιο πρόβλημα με την αίτηση.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:99
+#, kde-format
+msgid "Protocol for the collection does not support MULTIGET"
+msgstr "Το πρωτόκολλο για τη συλλογή δεν υποστηρίζει MULTIGET"
+
+#: common/daverror.cpp:102
+#, kde-format
+msgid ""
+"The server encountered an error that prevented it from completing your "
+"request: %1 (%2)"
+msgstr ""
+"Ο εξυπηρετητής αντιμετώπισε κάποιο σφάλμα που τον εμπόδισε να ολοκληρώσει "
+"την αίτησή σας: %1 (%2)"
+
+#: common/daverror.cpp:105
+#, kde-format
+msgid ""
+"There was a problem with the request. The collection has not been deleted "
+"from the server.\n"
+"%1 (%2)."
+msgstr ""
+"Υπήρξε πρόβλημα με την αίτηση. Η συλλογή δεν έχει διαγραφεί από τον "
+"εξυπηρετητή.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:108
+#, kde-format
+msgid "Invalid responses from backend"
+msgstr "Μη έγκυρες αποκρίσεις από το σύστημα υποστήριξης"
+
+#: common/daverror.cpp:111
+#, kde-format
+msgid "Error setting focus for XQuery"
+msgstr "Σφάλμα ρύθμισης της εστίασης για το XQuery"
+
+#: common/daverror.cpp:114
+#, kde-format
+msgid "Invalid XQuery submitted by DAV implementation"
+msgstr "Μη έγκυρο XQuery υποβλήθηκε από DAV υλοποίηση"
+
+#: common/daverror.cpp:118
+#, kde-format
+msgid ""
+"There was a problem with the request. The collection has not been modified "
+"on the server.\n"
+"%1 (%2)."
+msgstr ""
+"Υπήρξε πρόβλημα με την αίτηση. Η συλλογή δεν έχει τροποποιηθεί στον "
+"εξυπηρετητή.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:124
+#, kde-format
+msgid "No properties to change or remove"
+msgstr "Δεν υπάρχουν ιδιότητες για αλλαγή ή διαγραφή"
+
+#: common/daverror.cpp:127
+#, kde-format
+msgid "There was an error when modifying the properties"
+msgstr "Παρουσιάστηκε σφάλμα κατά την τροποποίηση των ιδιοτήτων"
+
+#: common/daverror.cpp:129
+#, kde-format
+msgid ""
+"\n"
+"The server returned more information:\n"
+"%1"
+msgstr ""
+"\n"
+"Ο εξυπηρετητής επίστρεψε και άλλη πληροφορία:\n"
+"%1"
+
+#: common/daverror.cpp:133
+#, kde-format
+msgid ""
+"There was a problem with the request. The item has not been created on the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+"Υπήρξε πρόβλημα με την αίτηση. Το αντικείμενο δεν έχει δημιουργηθεί στον "
+"εξυπηρετητή.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:136
+#, kde-format
+msgid ""
+"There was a problem with the request. The item has not been deleted from the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+"Υπήρξε πρόβλημα με την αίτηση. Το αντικείμενο δεν έχει διαγραφεί από τον "
+"εξυπηρετητή.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:139
+#, kde-format
+msgid ""
+"There was a problem with the request. The item was not modified on the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+"Υπήρξε πρόβλημα με την αίτηση. Το αντικείμενο δεν έχει τροποποιηθεί στον "
+"εξυπηρετητή.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:142
+#, kde-format
+msgid "There was a problem with the request."
+msgstr "Υπήρξε πρόβλημα με την αίτηση."
+
+#: common/daverror.cpp:146
+#, kde-format
+msgid ""
+"There was a problem with the request. The requested MIME types are not "
+"supported."
+msgstr ""
+"Υπήρξε πρόβλημα με την αίτηση. Οι αιτούμενοι τύποι MIME δεν υποστηρίζονται."
--- /dev/null
+# Copyright (C) YEAR This_file_is_part_of_KDE
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Steve Allewell <steve.allewell@gmail.com>, 2017.
+msgid ""
+msgstr ""
+"Project-Id-Version: \n"
+"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
+"POT-Creation-Date: 2021-03-09 02:40+0100\n"
+"PO-Revision-Date: 2017-12-22 15:41+0000\n"
+"Last-Translator: Steve Allewell <steve.allewell@gmail.com>\n"
+"Language-Team: British English <kde-l10n-en_gb@kde.org>\n"
+"Language: en_GB\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+"X-Generator: Lokalize 2.0\n"
+
+#: common/daverror.cpp:88
+#, kde-format
+msgid "Invalid username/password"
+msgstr "Invalid username/password"
+
+#: common/daverror.cpp:90
+#, kde-format
+msgid "Access forbidden"
+msgstr "Access forbidden"
+
+#: common/daverror.cpp:92
+#, kde-format
+msgid "Resource not found"
+msgstr "Resource not found"
+
+#: common/daverror.cpp:94
+#, kde-format
+msgid "HTTP error"
+msgstr "HTTP error"
+
+#: common/daverror.cpp:96
+#, kde-format
+msgid ""
+"There was a problem with the request.\n"
+"%1 (%2)."
+msgstr ""
+"There was a problem with the request.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:99
+#, kde-format
+msgid "Protocol for the collection does not support MULTIGET"
+msgstr "Protocol for the collection does not support MULTIGET"
+
+#: common/daverror.cpp:102
+#, kde-format
+msgid ""
+"The server encountered an error that prevented it from completing your "
+"request: %1 (%2)"
+msgstr ""
+"The server encountered an error that prevented it from completing your "
+"request: %1 (%2)"
+
+#: common/daverror.cpp:105
+#, kde-format
+msgid ""
+"There was a problem with the request. The collection has not been deleted "
+"from the server.\n"
+"%1 (%2)."
+msgstr ""
+"There was a problem with the request. The collection has not been deleted "
+"from the server.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:108
+#, kde-format
+msgid "Invalid responses from backend"
+msgstr "Invalid responses from backend"
+
+#: common/daverror.cpp:111
+#, kde-format
+msgid "Error setting focus for XQuery"
+msgstr "Error setting focus for XQuery"
+
+#: common/daverror.cpp:114
+#, kde-format
+msgid "Invalid XQuery submitted by DAV implementation"
+msgstr "Invalid XQuery submitted by DAV implementation"
+
+#: common/daverror.cpp:118
+#, kde-format
+msgid ""
+"There was a problem with the request. The collection has not been modified "
+"on the server.\n"
+"%1 (%2)."
+msgstr ""
+"There was a problem with the request. The collection has not been modified "
+"on the server.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:124
+#, kde-format
+msgid "No properties to change or remove"
+msgstr "No properties to change or remove"
+
+#: common/daverror.cpp:127
+#, kde-format
+msgid "There was an error when modifying the properties"
+msgstr "There was an error when modifying the properties"
+
+#: common/daverror.cpp:129
+#, kde-format
+msgid ""
+"\n"
+"The server returned more information:\n"
+"%1"
+msgstr ""
+"\n"
+"The server returned more information:\n"
+"%1"
+
+#: common/daverror.cpp:133
+#, kde-format
+msgid ""
+"There was a problem with the request. The item has not been created on the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+"There was a problem with the request. The item has not been created on the "
+"server.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:136
+#, kde-format
+msgid ""
+"There was a problem with the request. The item has not been deleted from the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+"There was a problem with the request. The item has not been deleted from the "
+"server.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:139
+#, kde-format
+msgid ""
+"There was a problem with the request. The item was not modified on the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+"There was a problem with the request. The item was not modified on the "
+"server.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:142
+#, kde-format
+msgid "There was a problem with the request."
+msgstr "There was a problem with the request."
+
+#: common/daverror.cpp:146
+#, kde-format
+msgid ""
+"There was a problem with the request. The requested MIME types are not "
+"supported."
+msgstr ""
+"There was a problem with the request. The requested MIME types are not "
+"supported."
--- /dev/null
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR This_file_is_part_of_KDE
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: \n"
+"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
+"POT-Creation-Date: 2021-03-09 02:40+0100\n"
+"PO-Revision-Date: 2017-12-14 09:10+0100\n"
+"Last-Translator: Javier Viñal <fjvinal@gmail.com>\n"
+"Language-Team: Spanish <l10n-kde-es@kde.org>\n"
+"Language: es\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: Poedit 2.0.3\n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+
+#: common/daverror.cpp:88
+#, kde-format
+msgid "Invalid username/password"
+msgstr "Usuario/contraseña inválidos"
+
+#: common/daverror.cpp:90
+#, kde-format
+msgid "Access forbidden"
+msgstr "Acceso prohíbido"
+
+#: common/daverror.cpp:92
+#, kde-format
+msgid "Resource not found"
+msgstr "Recurso no encontrado"
+
+#: common/daverror.cpp:94
+#, kde-format
+msgid "HTTP error"
+msgstr "Error HTTP"
+
+#: common/daverror.cpp:96
+#, kde-format
+msgid ""
+"There was a problem with the request.\n"
+"%1 (%2)."
+msgstr ""
+"Ha habido un problema con la petición.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:99
+#, kde-format
+msgid "Protocol for the collection does not support MULTIGET"
+msgstr "El protocolo para la colección no implementa MULTIGET"
+
+#: common/daverror.cpp:102
+#, kde-format
+msgid ""
+"The server encountered an error that prevented it from completing your "
+"request: %1 (%2)"
+msgstr ""
+"El servidor encontró un error que le impide completar la petición: %1 (%2)"
+
+#: common/daverror.cpp:105
+#, kde-format
+msgid ""
+"There was a problem with the request. The collection has not been deleted "
+"from the server.\n"
+"%1 (%2)."
+msgstr ""
+"Ha habido un problema con la petición. La colección no se ha borrado del "
+"servidor.\n"
+"%1 (%2)"
+
+#: common/daverror.cpp:108
+#, kde-format
+msgid "Invalid responses from backend"
+msgstr "Respuesta inválida desde el motor"
+
+#: common/daverror.cpp:111
+#, kde-format
+msgid "Error setting focus for XQuery"
+msgstr "Error al establecer el foco para XQuery"
+
+#: common/daverror.cpp:114
+#, kde-format
+msgid "Invalid XQuery submitted by DAV implementation"
+msgstr "XQuery inválido enviado por la implementación de DAV"
+
+#: common/daverror.cpp:118
+#, kde-format
+msgid ""
+"There was a problem with the request. The collection has not been modified "
+"on the server.\n"
+"%1 (%2)."
+msgstr ""
+"Ha habido un problema con la petición. La colección no se ha modificado del "
+"servidor.\n"
+"%1 (%2)"
+
+#: common/daverror.cpp:124
+#, kde-format
+msgid "No properties to change or remove"
+msgstr "Ninguna propiedad que cambiar o eliminar"
+
+#: common/daverror.cpp:127
+#, kde-format
+msgid "There was an error when modifying the properties"
+msgstr "Ha habido un error al modificar las propiedades"
+
+#: common/daverror.cpp:129
+#, kde-format
+msgid ""
+"\n"
+"The server returned more information:\n"
+"%1"
+msgstr ""
+"\n"
+"El servidor ha devuelto más información:\n"
+"%1"
+
+#: common/daverror.cpp:133
+#, kde-format
+msgid ""
+"There was a problem with the request. The item has not been created on the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+"Ha habido un problema con la petición. El elemento no se ha creado en el "
+"servidor.\n"
+"%1 (%2)"
+
+#: common/daverror.cpp:136
+#, kde-format
+msgid ""
+"There was a problem with the request. The item has not been deleted from the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+"Ha habido un problema con la petición. El elemento no se ha borrado desde el "
+"servidor.\n"
+"%1 (%2)"
+
+#: common/daverror.cpp:139
+#, kde-format
+msgid ""
+"There was a problem with the request. The item was not modified on the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+"Ha habido un problema con la petición. El elemento no se ha modificado en el "
+"servidor.\n"
+"%1 (%2)"
+
+#: common/daverror.cpp:142
+#, kde-format
+msgid "There was a problem with the request."
+msgstr "Ha habido un problema con la petición."
+
+#: common/daverror.cpp:146
+#, kde-format
+msgid ""
+"There was a problem with the request. The requested MIME types are not "
+"supported."
+msgstr ""
+"Ha habido un problema con la petición. El tipo MIME solicitado no está "
+"implementado."
--- /dev/null
+# Copyright (C) YEAR This file is copyright:
+# This file is distributed under the same license as the kdav package.
+#
+# Marek Laane <qiilaq69@gmail.com>, 2019.
+msgid ""
+msgstr ""
+"Project-Id-Version: kdav\n"
+"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
+"POT-Creation-Date: 2021-03-09 02:40+0100\n"
+"PO-Revision-Date: 2019-11-16 21:51+0200\n"
+"Last-Translator: Marek Laane <qiilaq69@gmail.com>\n"
+"Language-Team: Estonian <kde-et@lists.linux.ee>\n"
+"Language: et\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+"X-Generator: Lokalize 19.08.1\n"
+
+#: common/daverror.cpp:88
+#, kde-format
+msgid "Invalid username/password"
+msgstr "Vigane kasutajanimi/parool"
+
+#: common/daverror.cpp:90
+#, kde-format
+msgid "Access forbidden"
+msgstr "Juurdepääs keelatud"
+
+#: common/daverror.cpp:92
+#, kde-format
+msgid "Resource not found"
+msgstr "Ressurssi ei leitud"
+
+#: common/daverror.cpp:94
+#, kde-format
+msgid "HTTP error"
+msgstr "HTTP tõrge"
+
+#: common/daverror.cpp:96
+#, kde-format
+msgid ""
+"There was a problem with the request.\n"
+"%1 (%2)."
+msgstr ""
+"Päringuga tekkis probleem.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:99
+#, kde-format
+msgid "Protocol for the collection does not support MULTIGET"
+msgstr "Kogumise protokollis ei ole MULTIGET toetatud"
+
+#: common/daverror.cpp:102
+#, kde-format
+msgid ""
+"The server encountered an error that prevented it from completing your "
+"request: %1 (%2)"
+msgstr "Serveris tekkis tõrge, mis takistas sinu päringu täitmist: %1 (%2)"
+
+#: common/daverror.cpp:105
+#, kde-format
+msgid ""
+"There was a problem with the request. The collection has not been deleted "
+"from the server.\n"
+"%1 (%2)."
+msgstr ""
+"Päringuga tekkis probleem. Kogu ei ole serverist kustutatud.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:108
+#, kde-format
+msgid "Invalid responses from backend"
+msgstr "Vigased vastused taustaprogrammilt"
+
+#: common/daverror.cpp:111
+#, kde-format
+msgid "Error setting focus for XQuery"
+msgstr "Tõrge fookuse määramisel XQueryle"
+
+#: common/daverror.cpp:114
+#, kde-format
+msgid "Invalid XQuery submitted by DAV implementation"
+msgstr "DAV-i teostus edastas vigase XQuery"
+
+#: common/daverror.cpp:118
+#, kde-format
+msgid ""
+"There was a problem with the request. The collection has not been modified "
+"on the server.\n"
+"%1 (%2)."
+msgstr ""
+"Päringuga tekkis probleem. Kogu ei oldud serveris muudetud.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:124
+#, kde-format
+msgid "No properties to change or remove"
+msgstr "Pole omadusi, mida muuta või eemaldada"
+
+#: common/daverror.cpp:127
+#, kde-format
+msgid "There was an error when modifying the properties"
+msgstr "Omaduste muutmisel tekkis tõrge"
+
+#: common/daverror.cpp:129
+#, kde-format
+msgid ""
+"\n"
+"The server returned more information:\n"
+"%1"
+msgstr ""
+"\n"
+"Server tagastas rohkem teavet:\n"
+"%1"
+
+#: common/daverror.cpp:133
+#, kde-format
+msgid ""
+"There was a problem with the request. The item has not been created on the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+"Päringuga tekkis probleem. Elementi ei ole serveris loodud.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:136
+#, kde-format
+msgid ""
+"There was a problem with the request. The item has not been deleted from the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+"Päringuga tekkis probleem. Elementi ei ole serverist kustutatud.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:139
+#, kde-format
+msgid ""
+"There was a problem with the request. The item was not modified on the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+"Päringuga tekkis probleem. Elementi ei oldud serveris muudetud.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:142
+#, kde-format
+msgid "There was a problem with the request."
+msgstr "Päringuga tekkis probleem."
+
+#: common/daverror.cpp:146
+#, kde-format
+msgid ""
+"There was a problem with the request. The requested MIME types are not "
+"supported."
+msgstr "Päringuga tekkis probleem. Nõutavad MIME tüübid ei ole toetatud."
--- /dev/null
+# Translation for libkdav.po to Euskara/Basque (eu).
+# Copyright (C) 2021, This file is copyright:
+# This file is distributed under the same license as the kdav package.
+# KDE euskaratzeko proiektuko arduraduna <xalba@ni.eus>.
+#
+# Translators:
+# Iñigo Salvador Azurmendi <xalba@ni.eus>, 2021.
+msgid ""
+msgstr ""
+"Project-Id-Version: kdav\n"
+"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
+"POT-Creation-Date: 2021-03-09 02:40+0100\n"
+"PO-Revision-Date: 2021-07-30 21:09+0200\n"
+"Last-Translator: Iñigo Salvador Azurmendi <xalba@ni.eus>\n"
+"Language-Team: Basque <kde-i18n-eu@kde.org>\n"
+"Language: eu\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Generator: Lokalize 21.04.3\n"
+
+#: common/daverror.cpp:88
+#, kde-format
+msgid "Invalid username/password"
+msgstr "Erabiltzaile-izen/pasahitz baliogabea"
+
+#: common/daverror.cpp:90
+#, kde-format
+msgid "Access forbidden"
+msgstr "Sarrera debekatua"
+
+#: common/daverror.cpp:92
+#, kde-format
+msgid "Resource not found"
+msgstr "Baliabidea ez da aurkitu"
+
+#: common/daverror.cpp:94
+#, kde-format
+msgid "HTTP error"
+msgstr "HTTP errorea"
+
+#: common/daverror.cpp:96
+#, kde-format
+msgid ""
+"There was a problem with the request.\n"
+"%1 (%2)."
+msgstr ""
+"Eskaerarekin arazo bat egon da.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:99
+#, kde-format
+msgid "Protocol for the collection does not support MULTIGET"
+msgstr "Bildumarako protokoloak ez du MULTIGET onartzen"
+
+#: common/daverror.cpp:102
+#, kde-format
+msgid ""
+"The server encountered an error that prevented it from completing your "
+"request: %1 (%2)"
+msgstr ""
+"Zerbitzariak zure eskaria betetzea eragozten duen errore bat aurkitu du: %1 "
+"(%2)"
+
+#: common/daverror.cpp:105
+#, kde-format
+msgid ""
+"There was a problem with the request. The collection has not been deleted "
+"from the server.\n"
+"%1 (%2)."
+msgstr ""
+"Eskaerarekin arazo bat egon da. Bilduma ez da zerbitzaritik ezabatu.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:108
+#, kde-format
+msgid "Invalid responses from backend"
+msgstr "Bizkarraldekoaren erantzun baliogabeak"
+
+#: common/daverror.cpp:111
+#, kde-format
+msgid "Error setting focus for XQuery"
+msgstr "«XQuery»rako arreta ezartzeko errorea"
+
+#: common/daverror.cpp:114
+#, kde-format
+msgid "Invalid XQuery submitted by DAV implementation"
+msgstr "DAV inplementazioak «XQuery» baliogabea bidali du "
+
+#: common/daverror.cpp:118
+#, kde-format
+msgid ""
+"There was a problem with the request. The collection has not been modified "
+"on the server.\n"
+"%1 (%2)."
+msgstr ""
+"Eskaerarekin arazo bat egon da. Bilduma ez da aldatu zerbitzarian.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:124
+#, kde-format
+msgid "No properties to change or remove"
+msgstr "Ez dago aldatzeko edo kentzeko propietaterik"
+
+#: common/daverror.cpp:127
+#, kde-format
+msgid "There was an error when modifying the properties"
+msgstr "Errore bat gertatu da propietateak aldatzean"
+
+#: common/daverror.cpp:129
+#, kde-format
+msgid ""
+"\n"
+"The server returned more information:\n"
+"%1"
+msgstr ""
+"\n"
+"Zerbitzariak informazio gehiago itzuli du:\n"
+"%1"
+
+#: common/daverror.cpp:133
+#, kde-format
+msgid ""
+"There was a problem with the request. The item has not been created on the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+"Eskaerarekin arazo bat egon da. Elementua ez da sortu zerbitzarian.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:136
+#, kde-format
+msgid ""
+"There was a problem with the request. The item has not been deleted from the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+"Eskaerarekin arazo bat egon da. Elementua ez da zerbitzaritik ezabatu.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:139
+#, kde-format
+msgid ""
+"There was a problem with the request. The item was not modified on the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+"Eskaerarekin arazo bat egon da. Elementua ez da aldatu zerbitzarian.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:142
+#, kde-format
+msgid "There was a problem with the request."
+msgstr "Eskaerarekin arazo bat egon da."
+
+#: common/daverror.cpp:146
+#, kde-format
+msgid ""
+"There was a problem with the request. The requested MIME types are not "
+"supported."
+msgstr ""
+"Eskaerarekin arazo bat egon da. Eskatutako MIME-motak ez dira onartzen."
--- /dev/null
+# Copyright © 2011, 2012 This_file_is_part_of_KDE
+# This file is distributed under the same license as the kdepim-runtime package.
+# Tommi Nieminen <translator@legisign.org>, 2011, 2012, 2013, 2015, 2016, 2017.
+# Lasse Liehu <lasse.liehu@gmail.com>, 2012, 2013, 2014, 2015.
+# Jiri Grönroos <jiri.gronroos+kde@iki.fi>, 2012.
+#
+# KDE Finnish translation sprint participants:
+# Author: Artnay
+# Author: Lliehu
+msgid ""
+msgstr ""
+"Project-Id-Version: akonadi_davgroupware_resource\n"
+"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
+"POT-Creation-Date: 2021-03-09 02:40+0100\n"
+"PO-Revision-Date: 2017-12-25 20:33+0200\n"
+"Last-Translator: Tommi Nieminen <translator@legisign.org>\n"
+"Language-Team: Finnish <kde-i18n-doc@kde.org>\n"
+"Language: fi\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-POT-Import-Date: 2012-12-01 22:24:46+0000\n"
+"X-Generator: Lokalize 2.0\n"
+
+#: common/daverror.cpp:88
+#, kde-format
+msgid "Invalid username/password"
+msgstr "Virheellinen käyttäjätunnus tai salasana"
+
+#: common/daverror.cpp:90
+#, kde-format
+msgid "Access forbidden"
+msgstr "Saanti estetty"
+
+#: common/daverror.cpp:92
+#, kde-format
+msgid "Resource not found"
+msgstr "Resurssia ei löydy"
+
+#: common/daverror.cpp:94
+#, kde-format
+msgid "HTTP error"
+msgstr "HTTP-virhe"
+
+#: common/daverror.cpp:96
+#, kde-format
+msgid ""
+"There was a problem with the request.\n"
+"%1 (%2)."
+msgstr ""
+"Pyynnössä oli ongelmia.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:99
+#, kde-format
+msgid "Protocol for the collection does not support MULTIGET"
+msgstr "Kokoelman yhteyskäytäntö ei tue MULTIGETiä"
+
+#: common/daverror.cpp:102
+#, kde-format
+msgid ""
+"The server encountered an error that prevented it from completing your "
+"request: %1 (%2)"
+msgstr ""
+"Palvelin kohtasi virheen, joka esti sitä toteuttamasta pyyntöäsi: %1 (%2)"
+
+#: common/daverror.cpp:105
+#, kde-format
+msgid ""
+"There was a problem with the request. The collection has not been deleted "
+"from the server.\n"
+"%1 (%2)."
+msgstr ""
+"Pyynnössä oli ongelmia eikä kokoelmaa poistettu palvelimelta.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:108
+#, kde-format
+msgid "Invalid responses from backend"
+msgstr "Taustaosa vastaa virheellisesti"
+
+#: common/daverror.cpp:111
+#, kde-format
+msgid "Error setting focus for XQuery"
+msgstr "Virhe asetettaessa XQueryn kohdistusta"
+
+#: common/daverror.cpp:114
+#, kde-format
+msgid "Invalid XQuery submitted by DAV implementation"
+msgstr "DAV-toteutus lähetti virheellisen XQueryn"
+
+#: common/daverror.cpp:118
+#, kde-format
+msgid ""
+"There was a problem with the request. The collection has not been modified "
+"on the server.\n"
+"%1 (%2)."
+msgstr ""
+"Pyynnössä oli ongelmia eikä kokoelmaa muutettu palvelimella.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:124
+#, kde-format
+msgid "No properties to change or remove"
+msgstr "Ei muutettavia tai poistettavia ominaisuuksia"
+
+#: common/daverror.cpp:127
+#, kde-format
+msgid "There was an error when modifying the properties"
+msgstr "Ominaisuuksia muutettaessa sattui virhe"
+
+#: common/daverror.cpp:129
+#, kde-format
+msgid ""
+"\n"
+"The server returned more information:\n"
+"%1"
+msgstr ""
+"\n"
+"Palvelin palautti lisätietoa:\n"
+"%1"
+
+#: common/daverror.cpp:133
+#, kde-format
+msgid ""
+"There was a problem with the request. The item has not been created on the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+"Pyynnössä oli ongelmia eikä merkintää luotu palvelimeen.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:136
+#, kde-format
+msgid ""
+"There was a problem with the request. The item has not been deleted from the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+"Pyynnössä oli ongelmia eikä merkintää poistettu palvelimelta.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:139
+#, kde-format
+msgid ""
+"There was a problem with the request. The item was not modified on the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+"Pyynnössä oli ongelmia eikä merkintää muutettu palvelimella.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:142
+#, kde-format
+msgid "There was a problem with the request."
+msgstr "Pyynnössä oli ongelmia."
+
+#: common/daverror.cpp:146
+#, kde-format
+msgid ""
+"There was a problem with the request. The requested MIME types are not "
+"supported."
+msgstr "Pyynnössä oli ongelmia: pyydettyjä MIME-tyyppejä ei tueta."
--- /dev/null
+# translation of akonadi_davgroupware_resource.po to Français
+# Copyright (C) YEAR This_file_is_part_of_KDE
+# This file is distributed under the same license as the PACKAGE package.
+# Guillaume Pujol <guill.p@gmail.com>, 2009, 2010.
+# Geoffray Levasseur <geoffray.levasseurbrandin@numericable.fr>, 2012, 2013, 2014.
+# xavier <xavier.besnard@neuf.fr>, 2013.
+# Joëlle Cornavin <jcornavin@laposte.net>, 2011.
+# Sebastien Renard <renard@kde.org>, 2013.
+# Vincent Pinon <vpinon@kde.org>, 2017, 2018.
+#
+# Xavier BESNARD <xavier.besnard]neuf.fr>, 2023.
+msgid ""
+msgstr ""
+"Project-Id-Version: akonadi_davgroupware_resource\n"
+"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
+"POT-Creation-Date: 2021-03-09 02:40+0100\n"
+"PO-Revision-Date: 2023-01-05 08:57+0100\n"
+"Last-Translator: Xavier BESNARD <xavier.besnard]neuf.fr>\n"
+"Language-Team: fr\n"
+"Language: fr\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n > 1);\n"
+"X-Generator: Lokalize 22.12.0\n"
+"X-Environment: kde\n"
+"X-Accelerator-Marker: &\n"
+"X-Text-Markup: kde4\n"
+
+#: common/daverror.cpp:88
+#, kde-format
+msgid "Invalid username/password"
+msgstr "Nom d'utilisateur ou mot de passe non valable"
+
+#: common/daverror.cpp:90
+#, kde-format
+msgid "Access forbidden"
+msgstr "Accès refusé"
+
+#: common/daverror.cpp:92
+#, kde-format
+msgid "Resource not found"
+msgstr "Impossible de trouver la ressource"
+
+#: common/daverror.cpp:94
+#, kde-format
+msgid "HTTP error"
+msgstr "Erreur « HTTP »"
+
+#: common/daverror.cpp:96
+#, kde-format
+msgid ""
+"There was a problem with the request.\n"
+"%1 (%2)."
+msgstr ""
+"Il y a eu un problème avec la requête.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:99
+#, kde-format
+msgid "Protocol for the collection does not support MULTIGET"
+msgstr "Le protocole pour la collection ne prend pas en charge « MULTIGET »."
+
+#: common/daverror.cpp:102
+#, kde-format
+msgid ""
+"The server encountered an error that prevented it from completing your "
+"request: %1 (%2)"
+msgstr ""
+"Le serveur a rencontré une erreur l'empêchant de mener à bien votre "
+"requête : %1 (%2)"
+
+#: common/daverror.cpp:105
+#, kde-format
+msgid ""
+"There was a problem with the request. The collection has not been deleted "
+"from the server.\n"
+"%1 (%2)."
+msgstr ""
+"Il y a eu un problème avec la requête. La collection n'a pas été supprimée "
+"du serveur.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:108
+#, kde-format
+msgid "Invalid responses from backend"
+msgstr "Réponses non valables provenant du moteur"
+
+#: common/daverror.cpp:111
+#, kde-format
+msgid "Error setting focus for XQuery"
+msgstr "Problème lors de la définition du focus pour « XQuery »"
+
+#: common/daverror.cpp:114
+#, kde-format
+msgid "Invalid XQuery submitted by DAV implementation"
+msgstr "« XQuery » non valable soumise par l'implémentation de « DAV »"
+
+#: common/daverror.cpp:118
+#, kde-format
+msgid ""
+"There was a problem with the request. The collection has not been modified "
+"on the server.\n"
+"%1 (%2)."
+msgstr ""
+"Il y a eu un problème avec la requête. La collection n'a pas été modifié sur "
+"le serveur.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:124
+#, kde-format
+msgid "No properties to change or remove"
+msgstr "Aucune propriété à modifier ou supprimer"
+
+#: common/daverror.cpp:127
+#, kde-format
+msgid "There was an error when modifying the properties"
+msgstr "Une erreur est survenue lors de la modification des propriétés"
+
+#: common/daverror.cpp:129
+#, kde-format
+msgid ""
+"\n"
+"The server returned more information:\n"
+"%1"
+msgstr ""
+"\n"
+"Le serveur a retourné plus d'informations :\n"
+"%1"
+
+#: common/daverror.cpp:133
+#, kde-format
+msgid ""
+"There was a problem with the request. The item has not been created on the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+"Il y a eu un problème avec la requête. L'élément n'a pas été créé sur le "
+"serveur.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:136
+#, kde-format
+msgid ""
+"There was a problem with the request. The item has not been deleted from the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+"Il y a eu un problème avec la requête. L'élément n'a pas été supprimé du "
+"serveur.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:139
+#, kde-format
+msgid ""
+"There was a problem with the request. The item was not modified on the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+"Il y a eu un problème avec la requête. L'élément n'a pas été modifié sur le "
+"serveur.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:142
+#, kde-format
+msgid "There was a problem with the request."
+msgstr "Il y a eu un problème avec la requête."
+
+#: common/daverror.cpp:146
+#, kde-format
+msgid ""
+"There was a problem with the request. The requested MIME types are not "
+"supported."
+msgstr ""
+"Il y a eu un problème avec la requête. Les types MIME demandés ne sont pas "
+"pris en charge."
--- /dev/null
+# Copyright (C) YEAR This_file_is_part_of_KDE
+# This file is distributed under the same license as the PACKAGE package.
+# Xosé <xosecalvo@gmail.com>, 2009, 2010, 2013.
+# Adrian Chaves Fernandez <adriyetichaves@gmail.com>, 2013, 2015, 2017.
+# Marce Villarino <mvillarino@kde-espana.org>, 2014.
+# Adrián Chaves (Gallaecio) <adrian@chaves.io>, 2017, 2018, 2019.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: \n"
+"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
+"POT-Creation-Date: 2021-03-09 02:40+0100\n"
+"PO-Revision-Date: 2019-03-16 19:40+0100\n"
+"Last-Translator: Adrián Chaves (Gallaecio) <adrian@chaves.io>\n"
+"Language-Team: Galician <kde-i18n-doc@kde.org>\n"
+"Language: gl\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+
+#: common/daverror.cpp:88
+#, kde-format
+msgid "Invalid username/password"
+msgstr "O nome de usuario ou o contrasinal son incorrectos"
+
+#: common/daverror.cpp:90
+#, kde-format
+msgid "Access forbidden"
+msgstr "Denegouse o acceso"
+
+#: common/daverror.cpp:92
+#, kde-format
+msgid "Resource not found"
+msgstr "Non se atopou o recurso."
+
+#: common/daverror.cpp:94
+#, kde-format
+msgid "HTTP error"
+msgstr "Erro de HTTP"
+
+#: common/daverror.cpp:96
+#, kde-format
+msgid ""
+"There was a problem with the request.\n"
+"%1 (%2)."
+msgstr ""
+"Houbo un problema coa solicitude.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:99
+#, kde-format
+msgid "Protocol for the collection does not support MULTIGET"
+msgstr "O protocolo da colección non admite MULTIGET"
+
+#: common/daverror.cpp:102
+#, kde-format
+msgid ""
+"The server encountered an error that prevented it from completing your "
+"request: %1 (%2)"
+msgstr ""
+"O servidor atopouse cun erro que evitou que realizase a súa solicitude: %1 "
+"(%2)"
+
+#: common/daverror.cpp:105
+#, kde-format
+msgid ""
+"There was a problem with the request. The collection has not been deleted "
+"from the server.\n"
+"%1 (%2)."
+msgstr ""
+"Produciuse un problema coa solicitude. A colección non se eliminou do "
+"servidor.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:108
+#, kde-format
+msgid "Invalid responses from backend"
+msgstr "Responsas incorrectas da infraestrutura"
+
+#: common/daverror.cpp:111
+#, kde-format
+msgid "Error setting focus for XQuery"
+msgstr "Produciuse un erro ao configurar o foco de XQuery"
+
+#: common/daverror.cpp:114
+#, kde-format
+msgid "Invalid XQuery submitted by DAV implementation"
+msgstr "A realización de DAV enviou unha XQuery incorrecta"
+
+#: common/daverror.cpp:118
+#, kde-format
+msgid ""
+"There was a problem with the request. The collection has not been modified "
+"on the server.\n"
+"%1 (%2)."
+msgstr ""
+"Houbo un problema coa solicitude. A colección non se modificou no servidor.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:124
+#, kde-format
+msgid "No properties to change or remove"
+msgstr "Non hai propiedades que cambiar ou retirar"
+
+#: common/daverror.cpp:127
+#, kde-format
+msgid "There was an error when modifying the properties"
+msgstr "Produciuse un erro ao modificar as propiedades."
+
+#: common/daverror.cpp:129
+#, kde-format
+msgid ""
+"\n"
+"The server returned more information:\n"
+"%1"
+msgstr ""
+"\n"
+"O servidor devolveu máis información:\n"
+"%1"
+
+#: common/daverror.cpp:133
+#, kde-format
+msgid ""
+"There was a problem with the request. The item has not been created on the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+"Houbo un problema coa solicitude. O elemento non se creou no servidor.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:136
+#, kde-format
+msgid ""
+"There was a problem with the request. The item has not been deleted from the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+"Houbo un problema coa solicitude. O elemento non se eliminou do servidor.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:139
+#, kde-format
+msgid ""
+"There was a problem with the request. The item was not modified on the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+"Houbo un problema coa solicitude. O elemento non se modificou no servidor.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:142
+#, kde-format
+msgid "There was a problem with the request."
+msgstr "Houbo un problema coa solicitude."
+
+#: common/daverror.cpp:146
+#, kde-format
+msgid ""
+"There was a problem with the request. The requested MIME types are not "
+"supported."
+msgstr ""
+"Houbo un problema coa solicitude. O tipos MIME solicitados non son "
+"compatíbeis."
--- /dev/null
+# Copyright (C) YEAR This file is copyright:
+# This file is distributed under the same license as the kdav package.
+#
+# Sameer Singh <lumarzeli30@gmail.com>, 2021.
+# Raghavendra Kamath <raghu@raghukamath.com>, 2021.
+msgid ""
+msgstr ""
+"Project-Id-Version: kdav\n"
+"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
+"POT-Creation-Date: 2021-03-09 02:40+0100\n"
+"PO-Revision-Date: 2021-06-27 10:10+0530\n"
+"Last-Translator: Raghavendra Kamath <raghu@raghukamath.com>\n"
+"Language-Team: kde-hindi\n"
+"Language: hi\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n!=1);\n"
+"X-Generator: Lokalize 21.04.2\n"
+
+#: common/daverror.cpp:88
+#, kde-format
+msgid "Invalid username/password"
+msgstr "अवैध उपयोक्ता नाम/कूटशब्द"
+
+#: common/daverror.cpp:90
+#, kde-format
+msgid "Access forbidden"
+msgstr "प्रवेश निषेध"
+
+#: common/daverror.cpp:92
+#, kde-format
+msgid "Resource not found"
+msgstr "कोई संसाधन नहीं मिला"
+
+#: common/daverror.cpp:94
+#, kde-format
+msgid "HTTP error"
+msgstr "एचटीटीपी त्रुटि"
+
+#: common/daverror.cpp:96
+#, kde-format
+msgid ""
+"There was a problem with the request.\n"
+"%1 (%2)."
+msgstr ""
+"याचिका में कोई समस्या थी।\n"
+"%1 (%2) ।"
+
+#: common/daverror.cpp:99
+#, kde-format
+msgid "Protocol for the collection does not support MULTIGET"
+msgstr "संग्रह का प्रोटोकॉल मल्टीगेट का समर्थन नहीं करता है।"
+
+#: common/daverror.cpp:102
+#, kde-format
+msgid ""
+"The server encountered an error that prevented it from completing your "
+"request: %1 (%2)"
+msgstr "सर्वर किसी समस्या के कारण आपकी याचिका को पूरा नहीं कर सका: %1 (%2)"
+
+#: common/daverror.cpp:105
+#, kde-format
+msgid ""
+"There was a problem with the request. The collection has not been deleted "
+"from the server.\n"
+"%1 (%2)."
+msgstr ""
+"याचिका में कोई समस्या थी। संग्रह को सर्वर से हटा दिया गया है।\n"
+"%1 (%2)।"
+
+#: common/daverror.cpp:108
+#, kde-format
+msgid "Invalid responses from backend"
+msgstr "पृष्ठभाग से अवैध उत्तर"
+
+#: common/daverror.cpp:111
+#, kde-format
+msgid "Error setting focus for XQuery"
+msgstr "एक्सक्वैरी में फ़ोकस सेट करने में त्रुटि"
+
+#: common/daverror.cpp:114
+#, kde-format
+msgid "Invalid XQuery submitted by DAV implementation"
+msgstr "डीएवी कार्यान्वयन ने अवैध एक्सक्वैरी प्रस्तुत की"
+
+#: common/daverror.cpp:118
+#, kde-format
+msgid ""
+"There was a problem with the request. The collection has not been modified "
+"on the server.\n"
+"%1 (%2)."
+msgstr ""
+"याचिका में कोई समस्या थी। सर्वर में संग्रह का परिवर्तिन नहीं किया गया है।\n"
+"%1 (%2)।"
+
+#: common/daverror.cpp:124
+#, kde-format
+msgid "No properties to change or remove"
+msgstr "कोई गुण परिवर्तिन या हटाने के लिए नहीं है"
+
+#: common/daverror.cpp:127
+#, kde-format
+msgid "There was an error when modifying the properties"
+msgstr "गुणों को परिवर्तित करते समय त्रुटि हुई"
+
+#: common/daverror.cpp:129
+#, kde-format
+msgid ""
+"\n"
+"The server returned more information:\n"
+"%1"
+msgstr ""
+"\n"
+"सर्वर नें अतिरिक्त जानकारी प्रदान की है:\n"
+"%1"
+
+#: common/daverror.cpp:133
+#, kde-format
+msgid ""
+"There was a problem with the request. The item has not been created on the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+"याचिका में कोई समस्या थी। वस्तु सर्वर में सृजित नहीं की गई।\n"
+"%1 (%2)।"
+
+#: common/daverror.cpp:136
+#, kde-format
+msgid ""
+"There was a problem with the request. The item has not been deleted from the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+"याचिका में कोई समस्या थी। वस्तु सर्वर से हटाई नहीं गई।\n"
+"%1 (%2)।"
+
+#: common/daverror.cpp:139
+#, kde-format
+msgid ""
+"There was a problem with the request. The item was not modified on the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+"याचिका में कोई समस्या थी। वस्तु सर्वर में परिवर्तित नहीं हुई।\n"
+"%1 (%2)।"
+
+#: common/daverror.cpp:142
+#, kde-format
+msgid "There was a problem with the request."
+msgstr "याचिका में कोई समस्या थी।"
+
+#: common/daverror.cpp:146
+#, kde-format
+msgid ""
+"There was a problem with the request. The requested MIME types are not "
+"supported."
+msgstr "याचिका में कोई समस्या थी। प्राथित माईम प्रकार समर्थित नहीं हैं।"
--- /dev/null
+# Copyright (C) YEAR This file is copyright:
+# This file is distributed under the same license as the kdav package.
+#
+# giovanni <g.sora@tiscali.it>, 2020.
+msgid ""
+msgstr ""
+"Project-Id-Version: kdav\n"
+"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
+"POT-Creation-Date: 2021-03-09 02:40+0100\n"
+"PO-Revision-Date: 2020-02-12 14:05+0100\n"
+"Last-Translator: giovanni <g.sora@tiscali.it>\n"
+"Language-Team: Interlingua <kde-i18n-it@kde.org>\n"
+"Language: ia\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+"X-Generator: Lokalize 18.12.3\n"
+
+#: common/daverror.cpp:88
+#, kde-format
+msgid "Invalid username/password"
+msgstr "Invalide nomine de usator / contrasigno"
+
+#: common/daverror.cpp:90
+#, kde-format
+msgid "Access forbidden"
+msgstr "Accesso prohibite"
+
+#: common/daverror.cpp:92
+#, kde-format
+msgid "Resource not found"
+msgstr "Il non trovava ressource"
+
+#: common/daverror.cpp:94
+#, kde-format
+msgid "HTTP error"
+msgstr "Error HTTP"
+
+#: common/daverror.cpp:96
+#, kde-format
+msgid ""
+"There was a problem with the request.\n"
+"%1 (%2)."
+msgstr ""
+"Il habeva un problema con le requesta.\n"
+" %1(%2)."
+
+#: common/daverror.cpp:99
+#, kde-format
+msgid "Protocol for the collection does not support MULTIGET"
+msgstr "Le protocollo pro le collection non supporta MULTIGET"
+
+#: common/daverror.cpp:102
+#, kde-format
+msgid ""
+"The server encountered an error that prevented it from completing your "
+"request: %1 (%2)"
+msgstr ""
+"Le servitor incontrava un error que impediva ex completar tu requesta: %1 "
+"(%2)"
+
+#: common/daverror.cpp:105
+#, kde-format
+msgid ""
+"There was a problem with the request. The collection has not been deleted "
+"from the server.\n"
+"%1 (%2)."
+msgstr ""
+"Il habeva un problema con le requesta. Le collection non ha essite delite ex "
+"le servitor.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:108
+#, kde-format
+msgid "Invalid responses from backend"
+msgstr "Responsas invalide ex retro-administration"
+
+#: common/daverror.cpp:111
+#, kde-format
+msgid "Error setting focus for XQuery"
+msgstr "Error durante que il fixava foco per XQuery"
+
+#: common/daverror.cpp:114
+#, kde-format
+msgid "Invalid XQuery submitted by DAV implementation"
+msgstr "XQuery invalide submittite per implementation de DAV"
+
+#: common/daverror.cpp:118
+#, kde-format
+msgid ""
+"There was a problem with the request. The collection has not been modified "
+"on the server.\n"
+"%1 (%2)."
+msgstr ""
+"Il habeva un problema con le requesta. Le collection non ha essite "
+"modificate sur le servitor \n"
+" %1 (%2)"
+
+#: common/daverror.cpp:124
+#, kde-format
+msgid "No properties to change or remove"
+msgstr "Nulle proprietates de modificar o remover"
+
+#: common/daverror.cpp:127
+#, kde-format
+msgid "There was an error when modifying the properties"
+msgstr "Il haveba un error durante que on modificava le proprietates"
+
+#: common/daverror.cpp:129
+#, kde-format
+msgid ""
+"\n"
+"The server returned more information:\n"
+"%1"
+msgstr ""
+"\n"
+"Le servitor retornava plure de information:\n"
+"%1"
+
+#: common/daverror.cpp:133
+#, kde-format
+msgid ""
+"There was a problem with the request. The item has not been created on the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+"Il habeva un problema con le requesta. Le elemento non ha essite create sur "
+"le servitor.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:136
+#, kde-format
+msgid ""
+"There was a problem with the request. The item has not been deleted from the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+"Il habeva un problema con le requesta. Le elemento non ha essite delite ex "
+"le servitor.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:139
+#, kde-format
+msgid ""
+"There was a problem with the request. The item was not modified on the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+"Il habeva un problema con le requesta. Le elemento non esseva modificate sur "
+"le servitor.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:142
+#, kde-format
+msgid "There was a problem with the request."
+msgstr "Il habeva un problema con le requesta."
+
+#: common/daverror.cpp:146
+#, kde-format
+msgid ""
+"There was a problem with the request. The requested MIME types are not "
+"supported."
+msgstr ""
+"Il habeva un problema con le requesta. Le requirite typos MIME non es "
+"supportate."
--- /dev/null
+# translation of akonadi_davgroupware_resource.po to Italian
+#
+# Vincenzo Reale <smart2128vr@gmail.com>, 2009, 2010.
+# Nicola Ruggero <nicola@nxnt.org>, 2010, 2011.
+# Luigi Toscano <luigi.toscano@tiscali.it>, 2012, 2013, 2014, 2015, 2016, 2017.
+msgid ""
+msgstr ""
+"Project-Id-Version: akonadi_davgroupware_resource\n"
+"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
+"POT-Creation-Date: 2021-03-09 02:40+0100\n"
+"PO-Revision-Date: 2017-12-14 21:04+0100\n"
+"Last-Translator: Luigi Toscano <luigi.toscano@tiscali.it>\n"
+"Language-Team: Italian <kde-i18n-it@kde.org>\n"
+"Language: it\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Generator: Lokalize 2.0\n"
+
+#: common/daverror.cpp:88
+#, kde-format
+msgid "Invalid username/password"
+msgstr "Username o password non validi"
+
+#: common/daverror.cpp:90
+#, kde-format
+msgid "Access forbidden"
+msgstr "Accesso vietato"
+
+#: common/daverror.cpp:92
+#, kde-format
+msgid "Resource not found"
+msgstr "Risorsa non trovata"
+
+#: common/daverror.cpp:94
+#, kde-format
+msgid "HTTP error"
+msgstr "Errore HTTP"
+
+#: common/daverror.cpp:96
+#, kde-format
+msgid ""
+"There was a problem with the request.\n"
+"%1 (%2)."
+msgstr ""
+"Problema con la richiesta.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:99
+#, kde-format
+msgid "Protocol for the collection does not support MULTIGET"
+msgstr "Il protocollo della collezione non supporta MULTIGET"
+
+#: common/daverror.cpp:102
+#, kde-format
+msgid ""
+"The server encountered an error that prevented it from completing your "
+"request: %1 (%2)"
+msgstr "Errore nel server. Impossibile completare la richiesta: %1 (%2)"
+
+#: common/daverror.cpp:105
+#, kde-format
+msgid ""
+"There was a problem with the request. The collection has not been deleted "
+"from the server.\n"
+"%1 (%2)."
+msgstr ""
+"Problema con la richiesta. La collezione non è stata eliminata dal server.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:108
+#, kde-format
+msgid "Invalid responses from backend"
+msgstr "Risposta non valida dal backend"
+
+#: common/daverror.cpp:111
+#, kde-format
+msgid "Error setting focus for XQuery"
+msgstr "Errore impostando il fuoco su XQuery"
+
+#: common/daverror.cpp:114
+#, kde-format
+msgid "Invalid XQuery submitted by DAV implementation"
+msgstr "XQuery non valida inviata dall'implementazione DAV"
+
+#: common/daverror.cpp:118
+#, kde-format
+msgid ""
+"There was a problem with the request. The collection has not been modified "
+"on the server.\n"
+"%1 (%2)."
+msgstr ""
+"Problema con la richiesta. La collezione non è stata modificata sul server.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:124
+#, kde-format
+msgid "No properties to change or remove"
+msgstr "Nessuna proprietà da cambiare o rimuovere"
+
+#: common/daverror.cpp:127
+#, kde-format
+msgid "There was an error when modifying the properties"
+msgstr "Errore nella modifica delle proprietà"
+
+#: common/daverror.cpp:129
+#, kde-format
+msgid ""
+"\n"
+"The server returned more information:\n"
+"%1"
+msgstr ""
+"\n"
+"Il server ha fornito ulteriori informazioni:\n"
+"%1"
+
+#: common/daverror.cpp:133
+#, kde-format
+msgid ""
+"There was a problem with the request. The item has not been created on the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+"Problema con la richiesta. L'elemento non è stato creato sul server.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:136
+#, kde-format
+msgid ""
+"There was a problem with the request. The item has not been deleted from the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+"Problema con la richiesta. L'elemento non è stato eliminato dal server.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:139
+#, kde-format
+msgid ""
+"There was a problem with the request. The item was not modified on the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+"Problema con la richiesta. L'elemento non è stato modificato sul server.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:142
+#, kde-format
+msgid "There was a problem with the request."
+msgstr "Problema con la richiesta."
+
+#: common/daverror.cpp:146
+#, kde-format
+msgid ""
+"There was a problem with the request. The requested MIME types are not "
+"supported."
+msgstr "Problema con la richiesta. I tipi MIME richiesti non sono supportati."
--- /dev/null
+msgid ""
+msgstr ""
+"Project-Id-Version: akonadi_davcalendar_resource\n"
+"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
+"POT-Creation-Date: 2021-03-09 02:40+0100\n"
+"PO-Revision-Date: 2009-11-04 20:48+0900\n"
+"Last-Translator: Japanese KDE translation team <kde-jp@kde.org>\n"
+"Language-Team: Japanese <kde-jp@kde.org>\n"
+"Language: ja\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+"X-Accelerator-Marker: &\n"
+"X-Text-Markup: kde4\n"
+
+#: common/daverror.cpp:88
+#, kde-format
+msgid "Invalid username/password"
+msgstr ""
+
+#: common/daverror.cpp:90
+#, kde-format
+msgid "Access forbidden"
+msgstr ""
+
+#: common/daverror.cpp:92
+#, kde-format
+msgid "Resource not found"
+msgstr ""
+
+#: common/daverror.cpp:94
+#, kde-format
+msgid "HTTP error"
+msgstr ""
+
+#: common/daverror.cpp:96
+#, kde-format
+msgid ""
+"There was a problem with the request.\n"
+"%1 (%2)."
+msgstr ""
+
+#: common/daverror.cpp:99
+#, kde-format
+msgid "Protocol for the collection does not support MULTIGET"
+msgstr ""
+
+#: common/daverror.cpp:102
+#, kde-format
+msgid ""
+"The server encountered an error that prevented it from completing your "
+"request: %1 (%2)"
+msgstr ""
+
+#: common/daverror.cpp:105
+#, kde-format
+msgid ""
+"There was a problem with the request. The collection has not been deleted "
+"from the server.\n"
+"%1 (%2)."
+msgstr ""
+
+#: common/daverror.cpp:108
+#, kde-format
+msgid "Invalid responses from backend"
+msgstr ""
+
+#: common/daverror.cpp:111
+#, kde-format
+msgid "Error setting focus for XQuery"
+msgstr ""
+
+#: common/daverror.cpp:114
+#, kde-format
+msgid "Invalid XQuery submitted by DAV implementation"
+msgstr ""
+
+#: common/daverror.cpp:118
+#, kde-format
+msgid ""
+"There was a problem with the request. The collection has not been modified "
+"on the server.\n"
+"%1 (%2)."
+msgstr ""
+
+#: common/daverror.cpp:124
+#, kde-format
+msgid "No properties to change or remove"
+msgstr ""
+
+#: common/daverror.cpp:127
+#, kde-format
+msgid "There was an error when modifying the properties"
+msgstr ""
+
+#: common/daverror.cpp:129
+#, kde-format
+msgid ""
+"\n"
+"The server returned more information:\n"
+"%1"
+msgstr ""
+
+#: common/daverror.cpp:133
+#, kde-format
+msgid ""
+"There was a problem with the request. The item has not been created on the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+
+#: common/daverror.cpp:136
+#, kde-format
+msgid ""
+"There was a problem with the request. The item has not been deleted from the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+
+#: common/daverror.cpp:139
+#, kde-format
+msgid ""
+"There was a problem with the request. The item was not modified on the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+
+#: common/daverror.cpp:142
+#, kde-format
+msgid "There was a problem with the request."
+msgstr ""
+
+#: common/daverror.cpp:146
+#, kde-format
+msgid ""
+"There was a problem with the request. The requested MIME types are not "
+"supported."
+msgstr ""
--- /dev/null
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR This file is copyright:
+# This file is distributed under the same license as the kdav package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: kdav\n"
+"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
+"POT-Creation-Date: 2021-03-09 02:40+0100\n"
+"PO-Revision-Date: 2022-05-22 06:20+0200\n"
+"Last-Translator: Temuri Doghonadze <temuri.doghonadze@gmail.com>\n"
+"Language-Team: Georgian <kde-i18n-doc@kde.org>\n"
+"Language: ka\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Generator: Poedit 3.0.1\n"
+
+#: common/daverror.cpp:88
+#, kde-format
+msgid "Invalid username/password"
+msgstr "მომხმარებელი ან პაროლი არასწორია"
+
+#: common/daverror.cpp:90
+#, kde-format
+msgid "Access forbidden"
+msgstr "წვდომა აკრძალულია"
+
+#: common/daverror.cpp:92
+#, kde-format
+msgid "Resource not found"
+msgstr "რესურსი ნაპოვნი არაა"
+
+#: common/daverror.cpp:94
+#, kde-format
+msgid "HTTP error"
+msgstr "HTTP შეცდომა"
+
+#: common/daverror.cpp:96
+#, kde-format
+msgid ""
+"There was a problem with the request.\n"
+"%1 (%2)."
+msgstr ""
+"მოთხოვნის პრობლემა.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:99
+#, kde-format
+msgid "Protocol for the collection does not support MULTIGET"
+msgstr "კოლექციის პროტოკოლს MULTIGET-ს მხარდაჭერა არ გააჩნია"
+
+#: common/daverror.cpp:102
+#, kde-format
+msgid ""
+"The server encountered an error that prevented it from completing your "
+"request: %1 (%2)"
+msgstr "სერვერის შეცდომა. შედეგად მოთხოვნა არ შესრულებულა: %1 (%2)"
+
+#: common/daverror.cpp:105
+#, kde-format
+msgid ""
+"There was a problem with the request. The collection has not been deleted "
+"from the server.\n"
+"%1 (%2)."
+msgstr ""
+"მოთხოვნის პრობლემა. კოლექცია სერვერიდან არ წაშლილა.\n"
+"%1 (%2)"
+
+#: common/daverror.cpp:108
+#, kde-format
+msgid "Invalid responses from backend"
+msgstr "უკანაბოლოს არასწორი პასუხი"
+
+#: common/daverror.cpp:111
+#, kde-format
+msgid "Error setting focus for XQuery"
+msgstr "XQuery-ის ფოკუსის დაყენების შეცდომა"
+
+#: common/daverror.cpp:114
+#, kde-format
+msgid "Invalid XQuery submitted by DAV implementation"
+msgstr "DAV-ის იმპლემენტაციის მიერ გადმოცემული XQuery არასწორია"
+
+#: common/daverror.cpp:118
+#, kde-format
+msgid ""
+"There was a problem with the request. The collection has not been modified "
+"on the server.\n"
+"%1 (%2)."
+msgstr ""
+"მოთხოვნის პრობლემა. კოლექცია სერვერზე არ შეცვლილა.\n"
+"%1 (%2)"
+
+#: common/daverror.cpp:124
+#, kde-format
+msgid "No properties to change or remove"
+msgstr "შესაცვლელი ან წასაშლელი თვსებები ნაპოვნი არაა"
+
+#: common/daverror.cpp:127
+#, kde-format
+msgid "There was an error when modifying the properties"
+msgstr "შეცდომა თვისებების შეცვლისას"
+
+#: common/daverror.cpp:129
+#, kde-format
+msgid ""
+"\n"
+"The server returned more information:\n"
+"%1"
+msgstr ""
+"\n"
+"მეტი ინფორმაციისთვის იხილეთ:\n"
+"%1"
+
+#: common/daverror.cpp:133
+#, kde-format
+msgid ""
+"There was a problem with the request. The item has not been created on the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+"მოთხოვნის პრობლემა. სერვერზე ჩანაწერი არ გაკეთებულა.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:136
+#, kde-format
+msgid ""
+"There was a problem with the request. The item has not been deleted from the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+"მოთხოვნის პრობლემა. ჩანაწერი სერვერიდან არ წაშლილა.\n"
+"%1 (%2)"
+
+#: common/daverror.cpp:139
+#, kde-format
+msgid ""
+"There was a problem with the request. The item was not modified on the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+"მოთხოვნის პრობლემა. სერვერზე ჩანაწერი არ შეცვლილა.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:142
+#, kde-format
+msgid "There was a problem with the request."
+msgstr "მოთხოვნის პრობლემა."
+
+#: common/daverror.cpp:146
+#, kde-format
+msgid ""
+"There was a problem with the request. The requested MIME types are not "
+"supported."
+msgstr "მოთხოვნის პრობლემა. მითითებული MIME ტიპები მხარდაჭერილი არაა."
--- /dev/null
+# Copyright (C) YEAR This_file_is_part_of_KDE
+# This file is distributed under the same license as the PACKAGE package.
+# Shinjo Park <kde@peremen.name>, 2013, 2014, 2015, 2016, 2017, 2018.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: \n"
+"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
+"POT-Creation-Date: 2021-03-09 02:40+0100\n"
+"PO-Revision-Date: 2018-08-15 12:26+0100\n"
+"Last-Translator: Shinjo Park <kde@peremen.name>\n"
+"Language-Team: Korean <kde-kr@kde.org>\n"
+"Language: ko\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+"X-Generator: Lokalize 2.0\n"
+
+#: common/daverror.cpp:88
+#, kde-format
+msgid "Invalid username/password"
+msgstr "잘못된 사용자 이름 및 암호"
+
+#: common/daverror.cpp:90
+#, kde-format
+msgid "Access forbidden"
+msgstr "접근 거부됨"
+
+#: common/daverror.cpp:92
+#, kde-format
+msgid "Resource not found"
+msgstr "자원을 찾을 수 없음"
+
+#: common/daverror.cpp:94
+#, kde-format
+msgid "HTTP error"
+msgstr "HTTP 오류"
+
+#: common/daverror.cpp:96
+#, kde-format
+msgid ""
+"There was a problem with the request.\n"
+"%1 (%2)."
+msgstr ""
+"요청에 문제가 있습니다.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:99
+#, kde-format
+msgid "Protocol for the collection does not support MULTIGET"
+msgstr "모음집에 대한 프로토콜이 MULTIGET을 지원하지 않음"
+
+#: common/daverror.cpp:102
+#, kde-format
+msgid ""
+"The server encountered an error that prevented it from completing your "
+"request: %1 (%2)"
+msgstr "서버에서 요청을 처리할 수 없는 오류가 발생했습니다: %1(%2)"
+
+#: common/daverror.cpp:105
+#, kde-format
+msgid ""
+"There was a problem with the request. The collection has not been deleted "
+"from the server.\n"
+"%1 (%2)."
+msgstr ""
+"요청에 문제가 있습니다. 서버에서 모음집이 삭제되지 않았습니다:\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:108
+#, kde-format
+msgid "Invalid responses from backend"
+msgstr "백엔드에서 잘못된 응답이 돌아옴"
+
+#: common/daverror.cpp:111
+#, kde-format
+msgid "Error setting focus for XQuery"
+msgstr "XQuery 초점 설정 오류"
+
+#: common/daverror.cpp:114
+#, kde-format
+msgid "Invalid XQuery submitted by DAV implementation"
+msgstr "DAV 구현에서 잘못된 XQuery를 보냄"
+
+#: common/daverror.cpp:118
+#, kde-format
+msgid ""
+"There was a problem with the request. The collection has not been modified "
+"on the server.\n"
+"%1 (%2)."
+msgstr ""
+"요청에 문제가 있습니다. 서버에서 모음집이 수정되지 않았습니다:\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:124
+#, kde-format
+msgid "No properties to change or remove"
+msgstr "변경하거나 삭제할 속성 없음"
+
+#: common/daverror.cpp:127
+#, kde-format
+msgid "There was an error when modifying the properties"
+msgstr "속성을 수정하는 중 오류가 발생함"
+
+#: common/daverror.cpp:129
+#, kde-format
+msgid ""
+"\n"
+"The server returned more information:\n"
+"%1"
+msgstr ""
+"\n"
+"서버에서 부가 정보를 돌려 줌:\n"
+"%1"
+
+#: common/daverror.cpp:133
+#, kde-format
+msgid ""
+"There was a problem with the request. The item has not been created on the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+"요청에 문제가 있습니다. 서버에서 모음집이 생성되지 않았습니다:\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:136
+#, kde-format
+msgid ""
+"There was a problem with the request. The item has not been deleted from the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+"요청에 문제가 있습니다. 서버에서 항목이 삭제되지 않았습니다:\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:139
+#, kde-format
+msgid ""
+"There was a problem with the request. The item was not modified on the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+"요청에 문제가 있습니다. 서버에서 항목이 수정되지 않았습니다:\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:142
+#, kde-format
+msgid "There was a problem with the request."
+msgstr "요청에 문제가 있습니다."
+
+#: common/daverror.cpp:146
+#, kde-format
+msgid ""
+"There was a problem with the request. The requested MIME types are not "
+"supported."
+msgstr "요청에 문제가 있습니다. 지정한 MIME 형식을 지원하지 않습니다."
--- /dev/null
+# Lithuanian translations for kdav package.
+# Copyright (C) 2019 This file is copyright:
+# This file is distributed under the same license as the kdav package.
+# Automatically generated, 2019.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: kdav\n"
+"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
+"POT-Creation-Date: 2021-03-09 02:40+0100\n"
+"PO-Revision-Date: 2018-08-16 09:12+0200\n"
+"Last-Translator: Automatically generated\n"
+"Language-Team: lt\n"
+"Language: lt\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=4; plural=(n==1 ? 0 : n%10>=2 && (n%100<10 || n"
+"%100>=20) ? 1 : n%10==0 || (n%100>10 && n%100<20) ? 2 : 3);\n"
+
+#: common/daverror.cpp:88
+#, kde-format
+msgid "Invalid username/password"
+msgstr ""
+
+#: common/daverror.cpp:90
+#, kde-format
+msgid "Access forbidden"
+msgstr ""
+
+#: common/daverror.cpp:92
+#, kde-format
+msgid "Resource not found"
+msgstr ""
+
+#: common/daverror.cpp:94
+#, kde-format
+msgid "HTTP error"
+msgstr ""
+
+#: common/daverror.cpp:96
+#, kde-format
+msgid ""
+"There was a problem with the request.\n"
+"%1 (%2)."
+msgstr ""
+
+#: common/daverror.cpp:99
+#, kde-format
+msgid "Protocol for the collection does not support MULTIGET"
+msgstr ""
+
+#: common/daverror.cpp:102
+#, kde-format
+msgid ""
+"The server encountered an error that prevented it from completing your "
+"request: %1 (%2)"
+msgstr ""
+
+#: common/daverror.cpp:105
+#, kde-format
+msgid ""
+"There was a problem with the request. The collection has not been deleted "
+"from the server.\n"
+"%1 (%2)."
+msgstr ""
+
+#: common/daverror.cpp:108
+#, kde-format
+msgid "Invalid responses from backend"
+msgstr ""
+
+#: common/daverror.cpp:111
+#, kde-format
+msgid "Error setting focus for XQuery"
+msgstr ""
+
+#: common/daverror.cpp:114
+#, kde-format
+msgid "Invalid XQuery submitted by DAV implementation"
+msgstr ""
+
+#: common/daverror.cpp:118
+#, kde-format
+msgid ""
+"There was a problem with the request. The collection has not been modified "
+"on the server.\n"
+"%1 (%2)."
+msgstr ""
+
+#: common/daverror.cpp:124
+#, kde-format
+msgid "No properties to change or remove"
+msgstr ""
+
+#: common/daverror.cpp:127
+#, kde-format
+msgid "There was an error when modifying the properties"
+msgstr ""
+
+#: common/daverror.cpp:129
+#, kde-format
+msgid ""
+"\n"
+"The server returned more information:\n"
+"%1"
+msgstr ""
+
+#: common/daverror.cpp:133
+#, kde-format
+msgid ""
+"There was a problem with the request. The item has not been created on the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+
+#: common/daverror.cpp:136
+#, kde-format
+msgid ""
+"There was a problem with the request. The item has not been deleted from the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+
+#: common/daverror.cpp:139
+#, kde-format
+msgid ""
+"There was a problem with the request. The item was not modified on the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+
+#: common/daverror.cpp:142
+#, kde-format
+msgid "There was a problem with the request."
+msgstr ""
+
+#: common/daverror.cpp:146
+#, kde-format
+msgid ""
+"There was a problem with the request. The requested MIME types are not "
+"supported."
+msgstr ""
--- /dev/null
+# Translation of libkdav to Norwegian Bokmål
+#
+# Bjørn Steensrud <bjornst@skogkatt.homelinux.org>, 2010, 2011, 2013, 2014.
+msgid ""
+msgstr ""
+"Project-Id-Version: \n"
+"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
+"POT-Creation-Date: 2021-03-09 02:40+0100\n"
+"PO-Revision-Date: 2014-09-19 22:47+0200\n"
+"Last-Translator: Bjørn Steensrud <bjornst@skogkatt.homelinux.org>\n"
+"Language-Team: Norwegian Bokmål <l10n-no@lister.huftis.org>\n"
+"Language: nb\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: Lokalize 1.5\n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+"X-Environment: kde\n"
+"X-Accelerator-Marker: &\n"
+"X-Text-Markup: kde4\n"
+
+#: common/daverror.cpp:88
+#, kde-format
+msgid "Invalid username/password"
+msgstr "Ugyldig brukernavn/passord"
+
+#: common/daverror.cpp:90
+#, kde-format
+msgid "Access forbidden"
+msgstr "Adgang forbudt"
+
+#: common/daverror.cpp:92
+#, kde-format
+msgid "Resource not found"
+msgstr "Fant ikke ressurs"
+
+#: common/daverror.cpp:94
+#, kde-format
+msgid "HTTP error"
+msgstr "HTTP-feil"
+
+#: common/daverror.cpp:96
+#, kde-format
+msgid ""
+"There was a problem with the request.\n"
+"%1 (%2)."
+msgstr ""
+"Det var et problem med forespørselen.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:99
+#, kde-format
+msgid "Protocol for the collection does not support MULTIGET"
+msgstr "Protokollen for samlingen støtter ikke MULTIGET"
+
+#: common/daverror.cpp:102
+#, kde-format
+msgid ""
+"The server encountered an error that prevented it from completing your "
+"request: %1 (%2)"
+msgstr ""
+
+#: common/daverror.cpp:105
+#, kde-format
+msgid ""
+"There was a problem with the request. The collection has not been deleted "
+"from the server.\n"
+"%1 (%2)."
+msgstr ""
+"Det var et problem med forespørselen. Samlingen er ikke slettet fra "
+"tjeneren.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:108
+#, kde-format
+msgid "Invalid responses from backend"
+msgstr "Ugyldige svar fra bakgrunnsmotor"
+
+#: common/daverror.cpp:111
+#, kde-format
+msgid "Error setting focus for XQuery"
+msgstr "Feil ved fokussetting for XQuery"
+
+#: common/daverror.cpp:114
+#, kde-format
+msgid "Invalid XQuery submitted by DAV implementation"
+msgstr "Ugyldig XQuery sendt inn av DAV-implementasjon"
+
+#: common/daverror.cpp:118
+#, kde-format
+msgid ""
+"There was a problem with the request. The collection has not been modified "
+"on the server.\n"
+"%1 (%2)."
+msgstr ""
+
+#: common/daverror.cpp:124
+#, kde-format
+msgid "No properties to change or remove"
+msgstr "Ingen egenskaper som skal endres eller fjernes"
+
+#: common/daverror.cpp:127
+#, kde-format
+msgid "There was an error when modifying the properties"
+msgstr "Det oppsto en feil ved endring av egenskapene"
+
+#: common/daverror.cpp:129
+#, kde-format
+msgid ""
+"\n"
+"The server returned more information:\n"
+"%1"
+msgstr ""
+
+#: common/daverror.cpp:133
+#, kde-format
+msgid ""
+"There was a problem with the request. The item has not been created on the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+"Det var et problem med forespørselen. Elementet er ikke opprettet på "
+"tjeneren.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:136
+#, kde-format
+msgid ""
+"There was a problem with the request. The item has not been deleted from the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+"Det var et problem med forespørselen. Elementet er ikke slettet fra "
+"tjeneren.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:139
+#, kde-format
+msgid ""
+"There was a problem with the request. The item was not modified on the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+"Det var et problem med forespørselen. Elementet ble ikke endret på "
+"tjeneren.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:142
+#, kde-format
+msgid "There was a problem with the request."
+msgstr ""
+
+#: common/daverror.cpp:146
+#, kde-format
+msgid ""
+"There was a problem with the request. The requested MIME types are not "
+"supported."
+msgstr ""
--- /dev/null
+# Copyright (C) YEAR This_file_is_part_of_KDE
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Freek de Kruijf <freekdekruijf@kde.nl>, 2017.
+msgid ""
+msgstr ""
+"Project-Id-Version: \n"
+"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
+"POT-Creation-Date: 2021-03-09 02:40+0100\n"
+"PO-Revision-Date: 2017-12-12 22:49+0100\n"
+"Last-Translator: Freek de Kruijf <freekdekruijf@kde.nl>\n"
+"Language-Team: Dutch <kde-i18n-nl@kde.org>\n"
+"Language: nl\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+"X-Generator: Lokalize 2.0\n"
+
+#: common/daverror.cpp:88
+#, kde-format
+msgid "Invalid username/password"
+msgstr "Ongeldige gebruikersnaam/wachtwoord"
+
+#: common/daverror.cpp:90
+#, kde-format
+msgid "Access forbidden"
+msgstr "Toegang verboden"
+
+#: common/daverror.cpp:92
+#, kde-format
+msgid "Resource not found"
+msgstr "Hulpbron niet gevonden"
+
+#: common/daverror.cpp:94
+#, kde-format
+msgid "HTTP error"
+msgstr "HTTP-fout"
+
+#: common/daverror.cpp:96
+#, kde-format
+msgid ""
+"There was a problem with the request.\n"
+"%1 (%2)."
+msgstr ""
+"Er was een probleem met het verzoek.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:99
+#, kde-format
+msgid "Protocol for the collection does not support MULTIGET"
+msgstr "Protocol voor de verzameling ondersteunt geen MULTIGET"
+
+#: common/daverror.cpp:102
+#, kde-format
+msgid ""
+"The server encountered an error that prevented it from completing your "
+"request: %1 (%2)"
+msgstr ""
+"De server kwam een fout tegen, waardoor deze uw verzoek niet kon afhandelen: "
+"%1 (%2)"
+
+#: common/daverror.cpp:105
+#, kde-format
+msgid ""
+"There was a problem with the request. The collection has not been deleted "
+"from the server.\n"
+"%1 (%2)."
+msgstr ""
+"Er was een probleem met het verzoek. De verzameling is niet van de server "
+"verwijderd.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:108
+#, kde-format
+msgid "Invalid responses from backend"
+msgstr "Ongeldige antwoorden van backend"
+
+#: common/daverror.cpp:111
+#, kde-format
+msgid "Error setting focus for XQuery"
+msgstr "Fout bij het instellen van de focus voor XQuery"
+
+#: common/daverror.cpp:114
+#, kde-format
+msgid "Invalid XQuery submitted by DAV implementation"
+msgstr "Ongeldige Xquery ingediend door DAV-implementatie"
+
+#: common/daverror.cpp:118
+#, kde-format
+msgid ""
+"There was a problem with the request. The collection has not been modified "
+"on the server.\n"
+"%1 (%2)."
+msgstr ""
+"Er was een probleem met het verzoek. De verzameling is niet gewijzigd op de "
+"server.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:124
+#, kde-format
+msgid "No properties to change or remove"
+msgstr "Er zijn geen eigenschappen te wijzigen of te verwijderen"
+
+#: common/daverror.cpp:127
+#, kde-format
+msgid "There was an error when modifying the properties"
+msgstr "Er trad een fout op bij het wijzigen van de eigenschappen"
+
+#: common/daverror.cpp:129
+#, kde-format
+msgid ""
+"\n"
+"The server returned more information:\n"
+"%1"
+msgstr ""
+"\n"
+"De server gaf meer informatie terug:\n"
+"%1"
+
+#: common/daverror.cpp:133
+#, kde-format
+msgid ""
+"There was a problem with the request. The item has not been created on the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+"Er was een probleem met het verzoek. Het item is niet aangemaakt op de "
+"server\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:136
+#, kde-format
+msgid ""
+"There was a problem with the request. The item has not been deleted from the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+"Er was een probleem met het verzoek. Het item is niet van de server "
+"verwijderd.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:139
+#, kde-format
+msgid ""
+"There was a problem with the request. The item was not modified on the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+"Er was een probleem met het verzoek. Het item is niet gewijzigd op de "
+"server.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:142
+#, kde-format
+msgid "There was a problem with the request."
+msgstr "Er was een probleem met het verzoek."
+
+#: common/daverror.cpp:146
+#, kde-format
+msgid ""
+"There was a problem with the request. The requested MIME types are not "
+"supported."
+msgstr ""
+"Er was een probleem met het verzoek. De gevraagde MIME-typen worden niet "
+"ondersteund."
--- /dev/null
+# Translation of libkdav to Norwegian Nynorsk
+#
+# Karl Ove Hufthammer <karl@huftis.org>, 2020.
+msgid ""
+msgstr ""
+"Project-Id-Version: kdepim-runtime\n"
+"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
+"POT-Creation-Date: 2021-03-09 02:40+0100\n"
+"PO-Revision-Date: 2020-10-24 14:20+0200\n"
+"Last-Translator: Karl Ove Hufthammer <karl@huftis.org>\n"
+"Language-Team: Norwegian Nynorsk <l10n-no@lister.huftis.org>\n"
+"Language: nn\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+"X-Generator: Lokalize 20.08.2\n"
+"X-Environment: kde\n"
+"X-Accelerator-Marker: &\n"
+"X-Text-Markup: kde4\n"
+
+#: common/daverror.cpp:88
+#, kde-format
+msgid "Invalid username/password"
+msgstr "Ugyldig brukarnamn/passord"
+
+#: common/daverror.cpp:90
+#, kde-format
+msgid "Access forbidden"
+msgstr "Nekta tilgang"
+
+#: common/daverror.cpp:92
+#, kde-format
+msgid "Resource not found"
+msgstr "Fann ikkje ressursen"
+
+#: common/daverror.cpp:94
+#, kde-format
+msgid "HTTP error"
+msgstr "HTTP-feil"
+
+#: common/daverror.cpp:96
+#, kde-format
+msgid ""
+"There was a problem with the request.\n"
+"%1 (%2)."
+msgstr ""
+"Det var problem med førespurnaden.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:99
+#, kde-format
+msgid "Protocol for the collection does not support MULTIGET"
+msgstr "Protokoll for samlinga støttar ikkje MULTIGET"
+
+#: common/daverror.cpp:102
+#, kde-format
+msgid ""
+"The server encountered an error that prevented it from completing your "
+"request: %1 (%2)"
+msgstr ""
+"Tenaren støytte på ein feil som hindra han i å fullføra førespurnaden: %1 "
+"(%2)"
+
+#: common/daverror.cpp:105
+#, kde-format
+msgid ""
+"There was a problem with the request. The collection has not been deleted "
+"from the server.\n"
+"%1 (%2)."
+msgstr ""
+"Det var problem med førespurnaden. Samlinga er ikkje sletta frå tenaren.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:108
+#, kde-format
+msgid "Invalid responses from backend"
+msgstr "Ugyldig svar frå bakgrunnsmotoren"
+
+#: common/daverror.cpp:111
+#, kde-format
+msgid "Error setting focus for XQuery"
+msgstr "Feil ved fokusval for XQuery"
+
+#: common/daverror.cpp:114
+#, kde-format
+msgid "Invalid XQuery submitted by DAV implementation"
+msgstr "Ugyldig XQuery send av DAV-implementasjon"
+
+#: common/daverror.cpp:118
+#, kde-format
+msgid ""
+"There was a problem with the request. The collection has not been modified "
+"on the server.\n"
+"%1 (%2)."
+msgstr ""
+"Det var problem med førespurnaden. Samlinga er ikkje endra på tenaren.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:124
+#, kde-format
+msgid "No properties to change or remove"
+msgstr "Ingen eigenskapar å endra eller fjerna"
+
+#: common/daverror.cpp:127
+#, kde-format
+msgid "There was an error when modifying the properties"
+msgstr "Det oppstod ein feil ved endring av eigenskapar"
+
+#: common/daverror.cpp:129
+#, kde-format
+msgid ""
+"\n"
+"The server returned more information:\n"
+"%1"
+msgstr ""
+"\n"
+"Tenaren returnerte meir informasjon:\n"
+"%1"
+
+#: common/daverror.cpp:133
+#, kde-format
+msgid ""
+"There was a problem with the request. The item has not been created on the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+"Det var problem med førespurnaden. Elementet er ikkje oppretta på tenaren.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:136
+#, kde-format
+msgid ""
+"There was a problem with the request. The item has not been deleted from the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+"Det var problem med førespurnaden. Elementet er ikkje sletta frå tenaren.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:139
+#, kde-format
+msgid ""
+"There was a problem with the request. The item was not modified on the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+"Det var problem med førespurnaden. Elementet er ikkje endra på tenaren.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:142
+#, kde-format
+msgid "There was a problem with the request."
+msgstr "Det var problem med førespurnaden."
+
+#: common/daverror.cpp:146
+#, kde-format
+msgid ""
+"There was a problem with the request. The requested MIME types are not "
+"supported."
+msgstr ""
+"Det var problem med førespurnaden. Dei førespurde MIME-typane er ikkje "
+"støtta."
--- /dev/null
+# Copyright (C) YEAR This_file_is_part_of_KDE
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Łukasz Wojniłowicz <lukasz.wojnilowicz@gmail.com>, 2018.
+msgid ""
+msgstr ""
+"Project-Id-Version: \n"
+"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
+"POT-Creation-Date: 2021-03-09 02:40+0100\n"
+"PO-Revision-Date: 2018-01-28 06:08+0100\n"
+"Last-Translator: Łukasz Wojniłowicz <lukasz.wojnilowicz@gmail.com>\n"
+"Language-Team: Polish <kde-i18n-doc@kde.org>\n"
+"Language: pl\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 "
+"|| n%100>=20) ? 1 : 2);\n"
+"X-Generator: Lokalize 2.0\n"
+
+#: common/daverror.cpp:88
+#, kde-format
+msgid "Invalid username/password"
+msgstr "Nieprawidłowa nazwa użytkownika/hasło"
+
+#: common/daverror.cpp:90
+#, kde-format
+msgid "Access forbidden"
+msgstr "Dostęp wzbroniony"
+
+#: common/daverror.cpp:92
+#, kde-format
+msgid "Resource not found"
+msgstr "Nie znaleziono zasobu"
+
+#: common/daverror.cpp:94
+#, kde-format
+msgid "HTTP error"
+msgstr "Błąd HTTP"
+
+#: common/daverror.cpp:96
+#, kde-format
+msgid ""
+"There was a problem with the request.\n"
+"%1 (%2)."
+msgstr ""
+"Wystąpił problem z żądaniem\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:99
+#, kde-format
+msgid "Protocol for the collection does not support MULTIGET"
+msgstr "Protokół dla zbioru nie obsługuje MULTIGET"
+
+#: common/daverror.cpp:102
+#, kde-format
+msgid ""
+"The server encountered an error that prevented it from completing your "
+"request: %1 (%2)"
+msgstr ""
+"Serwer napotkał błąd który uniemożliwił spełnienie twojego żądania: %1 (%2)"
+
+#: common/daverror.cpp:105
+#, kde-format
+msgid ""
+"There was a problem with the request. The collection has not been deleted "
+"from the server.\n"
+"%1 (%2)."
+msgstr ""
+"Wystąpił problem z żądaniem. Zbiór nie został usunięty z serwera.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:108
+#, kde-format
+msgid "Invalid responses from backend"
+msgstr "Nieprawidłowa odpowiedź z modułu obsługi"
+
+#: common/daverror.cpp:111
+#, kde-format
+msgid "Error setting focus for XQuery"
+msgstr "Błąd ustawiania ostrości dla XQuery"
+
+#: common/daverror.cpp:114
+#, kde-format
+msgid "Invalid XQuery submitted by DAV implementation"
+msgstr "Nieprawidłowe XQuery wykonane przez DAV"
+
+#: common/daverror.cpp:118
+#, kde-format
+msgid ""
+"There was a problem with the request. The collection has not been modified "
+"on the server.\n"
+"%1 (%2)."
+msgstr ""
+"Wystąpił problem z żądaniem. Zbiór nie został zmieniony na serwerze.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:124
+#, kde-format
+msgid "No properties to change or remove"
+msgstr "Nie ma właściwości, aby zmienić lub usunąć"
+
+#: common/daverror.cpp:127
+#, kde-format
+msgid "There was an error when modifying the properties"
+msgstr "Wystąpił błąd w trakcje zmiany właściwości"
+
+#: common/daverror.cpp:129
+#, kde-format
+msgid ""
+"\n"
+"The server returned more information:\n"
+"%1"
+msgstr ""
+"\n"
+"Serwer zwrócił więcej informacji:\n"
+"%1"
+
+#: common/daverror.cpp:133
+#, kde-format
+msgid ""
+"There was a problem with the request. The item has not been created on the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+"Wystąpił problem z żądaniem. Element nie został stworzona na serwerze.\n"
+" %1 (%2)."
+
+#: common/daverror.cpp:136
+#, kde-format
+msgid ""
+"There was a problem with the request. The item has not been deleted from the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+"Wystąpił problem z żądaniem. Element nie został usunięty na serwerze.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:139
+#, kde-format
+msgid ""
+"There was a problem with the request. The item was not modified on the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+"Wystąpił problem z żądaniem. Element nie został zmieniony na serwerze.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:142
+#, kde-format
+msgid "There was a problem with the request."
+msgstr "Wystąpił problem z żądaniem."
+
+#: common/daverror.cpp:146
+#, kde-format
+msgid ""
+"There was a problem with the request. The requested MIME types are not "
+"supported."
+msgstr "Wystąpił problem z żądaniem. Żądane typy MIME nie są obsługiwane."
--- /dev/null
+msgid ""
+msgstr ""
+"Project-Id-Version: libkdav\n"
+"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
+"POT-Creation-Date: 2021-03-09 02:40+0100\n"
+"PO-Revision-Date: 2017-12-04 11:32+0000\n"
+"Last-Translator: José Nuno Coelho Pires <zepires@gmail.com>\n"
+"Language-Team: Portuguese <kde-i18n-pt@kde.org>\n"
+"Language: pt\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-POFile-SpellExtra: XQuery MULTIGET DAV\n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+
+#: common/daverror.cpp:88
+#, kde-format
+msgid "Invalid username/password"
+msgstr "Utilizador/senha inválidos"
+
+#: common/daverror.cpp:90
+#, kde-format
+msgid "Access forbidden"
+msgstr "Acesso proibido"
+
+#: common/daverror.cpp:92
+#, kde-format
+msgid "Resource not found"
+msgstr "Recurso não encontrado"
+
+#: common/daverror.cpp:94
+#, kde-format
+msgid "HTTP error"
+msgstr "Erro de HTTP"
+
+#: common/daverror.cpp:96
+#, kde-format
+msgid ""
+"There was a problem with the request.\n"
+"%1 (%2)."
+msgstr ""
+"Ocorreu um problema com o pedido.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:99
+#, kde-format
+msgid "Protocol for the collection does not support MULTIGET"
+msgstr "O protocolo da colecção não suporta o MULTIGET"
+
+#: common/daverror.cpp:102
+#, kde-format
+msgid ""
+"The server encountered an error that prevented it from completing your "
+"request: %1 (%2)"
+msgstr ""
+"O servidor encontrou um erro que o impediu de terminar o seu pedido: %1 (%2)"
+
+#: common/daverror.cpp:105
+#, kde-format
+msgid ""
+"There was a problem with the request. The collection has not been deleted "
+"from the server.\n"
+"%1 (%2)."
+msgstr ""
+"Ocorreu um problema com o pedido. A colecção não foi apagada no servidor.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:108
+#, kde-format
+msgid "Invalid responses from backend"
+msgstr "Foi obtida uma resposta inválida da infra-estrutura"
+
+#: common/daverror.cpp:111
+#, kde-format
+msgid "Error setting focus for XQuery"
+msgstr "Ocorreu um erro na atribuição do XQuery"
+
+#: common/daverror.cpp:114
+#, kde-format
+msgid "Invalid XQuery submitted by DAV implementation"
+msgstr "Foi enviado um pedido de XQuery inválido pela implementação do DAV"
+
+#: common/daverror.cpp:118
+#, kde-format
+msgid ""
+"There was a problem with the request. The collection has not been modified "
+"on the server.\n"
+"%1 (%2)."
+msgstr ""
+"Ocorreu um problema com o pedido. A colecção não foi modificada no "
+"servidor.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:124
+#, kde-format
+msgid "No properties to change or remove"
+msgstr "Não existem propriedades para alterar ou remover"
+
+#: common/daverror.cpp:127
+#, kde-format
+msgid "There was an error when modifying the properties"
+msgstr "Ocorreu um erro ao modificar as propriedades"
+
+#: common/daverror.cpp:129
+#, kde-format
+msgid ""
+"\n"
+"The server returned more information:\n"
+"%1"
+msgstr ""
+"\n"
+"O servidor devolveu mais informações:\n"
+"%1"
+
+#: common/daverror.cpp:133
+#, kde-format
+msgid ""
+"There was a problem with the request. The item has not been created on the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+"Ocorreu um problema com o pedido - O item não foi criado no servidor.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:136
+#, kde-format
+msgid ""
+"There was a problem with the request. The item has not been deleted from the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+"Ocorreu um problema com o pedido - o item não foi apagado no servidor.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:139
+#, kde-format
+msgid ""
+"There was a problem with the request. The item was not modified on the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+"Ocorreu um problema com o pedido. O item não foi modificado no servidor.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:142
+#, kde-format
+msgid "There was a problem with the request."
+msgstr "Ocorreu um problema com o pedido."
+
+#: common/daverror.cpp:146
+#, kde-format
+msgid ""
+"There was a problem with the request. The requested MIME types are not "
+"supported."
+msgstr ""
+"Ocorreu um problema com o pedido. Os tipos MIME pedidos não são suportados."
--- /dev/null
+# Translation of libkdav.po to Brazilian Portuguese
+# Copyright (C) 2018 This_file_is_part_of_KDE
+# This file is distributed under the same license as the PACKAGE package.
+#
+# André Marcelo Alvarenga <alvarenga@kde.org>, 2018.
+msgid ""
+msgstr ""
+"Project-Id-Version: libkdav\n"
+"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
+"POT-Creation-Date: 2021-03-09 02:40+0100\n"
+"PO-Revision-Date: 2018-07-24 22:45-0300\n"
+"Last-Translator: André Marcelo Alvarenga <alvarenga@kde.org>\n"
+"Language-Team: Brazilian Portuguese <kde-i18n-pt_br@kde.org>\n"
+"Language: pt_BR\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n > 1);\n"
+"X-Generator: Lokalize 2.0\n"
+
+#: common/daverror.cpp:88
+#, kde-format
+msgid "Invalid username/password"
+msgstr "Usuário/senha inválidos"
+
+#: common/daverror.cpp:90
+#, kde-format
+msgid "Access forbidden"
+msgstr "Acesso proibido"
+
+#: common/daverror.cpp:92
+#, kde-format
+msgid "Resource not found"
+msgstr "Recurso não encontrado"
+
+#: common/daverror.cpp:94
+#, kde-format
+msgid "HTTP error"
+msgstr "Erro de HTTP"
+
+#: common/daverror.cpp:96
+#, kde-format
+msgid ""
+"There was a problem with the request.\n"
+"%1 (%2)."
+msgstr ""
+"Ocorreu um problema com a solicitação.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:99
+#, kde-format
+msgid "Protocol for the collection does not support MULTIGET"
+msgstr "O protocolo da coleção não tem suporte ao MULTIGET"
+
+#: common/daverror.cpp:102
+#, kde-format
+msgid ""
+"The server encountered an error that prevented it from completing your "
+"request: %1 (%2)"
+msgstr ""
+"O servidor encontrou um erro que o impediu de concluir a sua solicitação: %1 "
+"(%2)"
+
+#: common/daverror.cpp:105
+#, kde-format
+msgid ""
+"There was a problem with the request. The collection has not been deleted "
+"from the server.\n"
+"%1 (%2)."
+msgstr ""
+"Ocorreu um problema com a solicitação. A coleção não foi excluída no "
+"servidor.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:108
+#, kde-format
+msgid "Invalid responses from backend"
+msgstr "Foi obtida uma resposta inválida da infraestrutura"
+
+#: common/daverror.cpp:111
+#, kde-format
+msgid "Error setting focus for XQuery"
+msgstr "Ocorreu um erro na configuração do XQuery"
+
+#: common/daverror.cpp:114
+#, kde-format
+msgid "Invalid XQuery submitted by DAV implementation"
+msgstr ""
+"Foi enviada uma solicitação de XQuery inválida pela implementação do DAV"
+
+#: common/daverror.cpp:118
+#, kde-format
+msgid ""
+"There was a problem with the request. The collection has not been modified "
+"on the server.\n"
+"%1 (%2)."
+msgstr ""
+"Ocorreu um problema com a solicitação. A coleção não foi modificada no "
+"servidor.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:124
+#, kde-format
+msgid "No properties to change or remove"
+msgstr "Nenhuma propriedade para alterar ou remover"
+
+#: common/daverror.cpp:127
+#, kde-format
+msgid "There was an error when modifying the properties"
+msgstr "Ocorreu um erro ao modificar as propriedades"
+
+#: common/daverror.cpp:129
+#, kde-format
+msgid ""
+"\n"
+"The server returned more information:\n"
+"%1"
+msgstr ""
+"\n"
+"O servidor retornou mais informações:\n"
+"%1"
+
+#: common/daverror.cpp:133
+#, kde-format
+msgid ""
+"There was a problem with the request. The item has not been created on the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+"Ocorreu um problema com a solicitação. O item não foi criado no servidor.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:136
+#, kde-format
+msgid ""
+"There was a problem with the request. The item has not been deleted from the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+"Ocorreu um problema com a solicitação. O item não foi excluído no servidor.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:139
+#, kde-format
+msgid ""
+"There was a problem with the request. The item was not modified on the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+"Ocorreu um problema com a solicitação. O item não foi modificado no "
+"servidor.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:142
+#, kde-format
+msgid "There was a problem with the request."
+msgstr "Ocorreu um problema com a solicitação."
+
+#: common/daverror.cpp:146
+#, kde-format
+msgid ""
+"There was a problem with the request. The requested MIME types are not "
+"supported."
+msgstr ""
+"Ocorreu um problema com a solicitação. Não há suporte para os tipos MIME "
+"solicitados."
--- /dev/null
+# Copyright (C) YEAR This file is copyright:
+# This file is distributed under the same license as the kdepim-runtime package.
+# Sergiu Bivol <sergiu@cip.md>, 2020.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: kdepim-runtime\n"
+"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
+"POT-Creation-Date: 2021-03-09 02:40+0100\n"
+"PO-Revision-Date: 2020-09-27 12:44+0100\n"
+"Last-Translator: Sergiu Bivol <sergiu@cip.md>\n"
+"Language-Team: Romanian\n"
+"Language: ro\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=3; plural=n==1 ? 0 : (n==0 || (n%100 > 0 && n%100 < "
+"20)) ? 1 : 2;\n"
+"X-Generator: Lokalize 19.12.3\n"
+
+#: common/daverror.cpp:88
+#, kde-format
+msgid "Invalid username/password"
+msgstr "Utilizator/parolă nevalide"
+
+#: common/daverror.cpp:90
+#, kde-format
+msgid "Access forbidden"
+msgstr "Acces interzis"
+
+#: common/daverror.cpp:92
+#, kde-format
+msgid "Resource not found"
+msgstr "Resursa nu a fost găsită"
+
+#: common/daverror.cpp:94
+#, kde-format
+msgid "HTTP error"
+msgstr "Eroare HTTP"
+
+#: common/daverror.cpp:96
+#, kde-format
+msgid ""
+"There was a problem with the request.\n"
+"%1 (%2)."
+msgstr ""
+"A apărut o problemă cu cererea.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:99
+#, kde-format
+msgid "Protocol for the collection does not support MULTIGET"
+msgstr "Protocolul pentru colecție nu susține MULTIGET"
+
+#: common/daverror.cpp:102
+#, kde-format
+msgid ""
+"The server encountered an error that prevented it from completing your "
+"request: %1 (%2)"
+msgstr ""
+"Serverul a întâmpinat o eroare ce l-a împiedicat să vă completeze cererea: "
+"%1 (%2)"
+
+#: common/daverror.cpp:105
+#, kde-format
+msgid ""
+"There was a problem with the request. The collection has not been deleted "
+"from the server.\n"
+"%1 (%2)."
+msgstr ""
+"A apărut o problemă cu cererea. Colecția nu a fost ștearsă de pe server.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:108
+#, kde-format
+msgid "Invalid responses from backend"
+msgstr "Răspunsuri nevalide de la platformă"
+
+#: common/daverror.cpp:111
+#, kde-format
+msgid "Error setting focus for XQuery"
+msgstr "Eroare la stabilirea focalizării pentru XQuery"
+
+#: common/daverror.cpp:114
+#, kde-format
+msgid "Invalid XQuery submitted by DAV implementation"
+msgstr "XQuery nevalid transmis de implementarea DAV"
+
+#: common/daverror.cpp:118
+#, kde-format
+msgid ""
+"There was a problem with the request. The collection has not been modified "
+"on the server.\n"
+"%1 (%2)."
+msgstr ""
+"A apărut o problemă cu cererea. Colecția nu a fost modificată pe server.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:124
+#, kde-format
+msgid "No properties to change or remove"
+msgstr "Nu sunt proprietăți de schimbat sau eliminat"
+
+#: common/daverror.cpp:127
+#, kde-format
+msgid "There was an error when modifying the properties"
+msgstr "A apărut o eroare la modificarea proprietăților"
+
+#: common/daverror.cpp:129
+#, kde-format
+msgid ""
+"\n"
+"The server returned more information:\n"
+"%1"
+msgstr ""
+"\n"
+"Serverul a întors mai multă informație:\n"
+"%1"
+
+#: common/daverror.cpp:133
+#, kde-format
+msgid ""
+"There was a problem with the request. The item has not been created on the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+"A apărut o problemă cu cererea. Elementul nu a fost creat pe server.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:136
+#, kde-format
+msgid ""
+"There was a problem with the request. The item has not been deleted from the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+"A apărut o problemă cu cererea. Elementul nu a fost șters de pe server.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:139
+#, kde-format
+msgid ""
+"There was a problem with the request. The item was not modified on the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+"A apărut o problemă cu cererea. Elementul nu a fost modificat pe server.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:142
+#, kde-format
+msgid "There was a problem with the request."
+msgstr "A apărut o problemă cu cererea."
+
+#: common/daverror.cpp:146
+#, kde-format
+msgid ""
+"There was a problem with the request. The requested MIME types are not "
+"supported."
+msgstr ""
+"A apărut o problemă cu cererea. Tipurile MIME cerute nu sunt susținute."
--- /dev/null
+# Copyright (C) YEAR This_file_is_part_of_KDE
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Alexander Potashev <aspotashev@gmail.com>, 2017.
+# Alexander Yavorsky <kekcuha@gmail.com>, 2018.
+msgid ""
+msgstr ""
+"Project-Id-Version: \n"
+"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
+"POT-Creation-Date: 2021-03-09 02:40+0100\n"
+"PO-Revision-Date: 2018-07-16 21:52+0300\n"
+"Last-Translator: Alexander Yavorsky <kekcuha@gmail.com>\n"
+"Language-Team: Russian <kde-russian@lists.kde.ru>\n"
+"Language: ru\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=4; plural=n==1 ? 3 : n%10==1 && n%100!=11 ? 0 : n"
+"%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
+"X-Generator: Lokalize 2.0\n"
+
+#: common/daverror.cpp:88
+#, kde-format
+msgid "Invalid username/password"
+msgstr "Неправильное имя пользователя или пароль"
+
+#: common/daverror.cpp:90
+#, kde-format
+msgid "Access forbidden"
+msgstr "Доступ запрещён"
+
+#: common/daverror.cpp:92
+#, kde-format
+msgid "Resource not found"
+msgstr "Ресурс не найден"
+
+#: common/daverror.cpp:94
+#, kde-format
+msgid "HTTP error"
+msgstr "Ошибка HTTP"
+
+#: common/daverror.cpp:96
+#, kde-format
+msgid ""
+"There was a problem with the request.\n"
+"%1 (%2)."
+msgstr ""
+"При выполнении запроса произошла ошибка.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:99
+#, kde-format
+msgid "Protocol for the collection does not support MULTIGET"
+msgstr "Протокол для этой коллекции не поддерживает MULTIGET."
+
+#: common/daverror.cpp:102
+#, kde-format
+msgid ""
+"The server encountered an error that prevented it from completing your "
+"request: %1 (%2)"
+msgstr ""
+"На сервере произошла ошибка, из-за чего он не смог завершить выполнение "
+"запроса: %1 (%2)"
+
+#: common/daverror.cpp:105
+#, kde-format
+msgid ""
+"There was a problem with the request. The collection has not been deleted "
+"from the server.\n"
+"%1 (%2)."
+msgstr ""
+"При выполнении запроса произошла ошибка. Коллекция не была удалена с "
+"сервера.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:108
+#, kde-format
+msgid "Invalid responses from backend"
+msgstr "Неверный ответ сервера"
+
+#: common/daverror.cpp:111
+#, kde-format
+msgid "Error setting focus for XQuery"
+msgstr "Ошибка установки фокуса для XQuery"
+
+#: common/daverror.cpp:114
+#, kde-format
+msgid "Invalid XQuery submitted by DAV implementation"
+msgstr "Неверный XQuery, представленный реализацией DAV"
+
+#: common/daverror.cpp:118
+#, kde-format
+msgid ""
+"There was a problem with the request. The collection has not been modified "
+"on the server.\n"
+"%1 (%2)."
+msgstr ""
+"При выполнении запроса произошла ошибка. Коллекция не была изменена на "
+"сервере.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:124
+#, kde-format
+msgid "No properties to change or remove"
+msgstr "Нет свойств для изменения или удаления"
+
+#: common/daverror.cpp:127
+#, kde-format
+msgid "There was an error when modifying the properties"
+msgstr "При изменении свойств произошла ошибка"
+
+#: common/daverror.cpp:129
+#, kde-format
+msgid ""
+"\n"
+"The server returned more information:\n"
+"%1"
+msgstr ""
+"\n"
+"Сервер вернул расширенные сведения:\n"
+"%1"
+
+#: common/daverror.cpp:133
+#, kde-format
+msgid ""
+"There was a problem with the request. The item has not been created on the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+"При выполнении запроса произошла ошибка. Объект не был создан на сервере.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:136
+#, kde-format
+msgid ""
+"There was a problem with the request. The item has not been deleted from the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+"При выполнении запроса произошла ошибка. Объект не был удалён с сервера.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:139
+#, kde-format
+msgid ""
+"There was a problem with the request. The item was not modified on the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+"При выполнении запроса произошла ошибка. Объект не был изменён на сервере.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:142
+#, kde-format
+msgid "There was a problem with the request."
+msgstr "При выполнении запроса произошла ошибка."
+
+#: common/daverror.cpp:146
+#, kde-format
+msgid ""
+"There was a problem with the request. The requested MIME types are not "
+"supported."
+msgstr ""
+"При выполнении запроса произошла ошибка. Запрошенные типы MIME не "
+"поддерживаются."
--- /dev/null
+# translation of libkdav.po to Slovak
+# Roman Paholík <wizzardsk@gmail.com>, 2017.
+# Matej Mrenica <matejm98mthw@gmail.com>, 2022.
+msgid ""
+msgstr ""
+"Project-Id-Version: libkdav\n"
+"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
+"POT-Creation-Date: 2021-03-09 02:40+0100\n"
+"PO-Revision-Date: 2022-02-14 19:47+0100\n"
+"Last-Translator: Matej Mrenica <matejm98mthw@gmail.com>\n"
+"Language-Team: Slovak <kde-i18n-doc@kde.org>\n"
+"Language: sk\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: Lokalize 21.12.2\n"
+"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n"
+
+#: common/daverror.cpp:88
+#, kde-format
+msgid "Invalid username/password"
+msgstr "Neplatné užívateľské meno/heslo"
+
+#: common/daverror.cpp:90
+#, kde-format
+msgid "Access forbidden"
+msgstr "Prístup zamietnutý"
+
+#: common/daverror.cpp:92
+#, kde-format
+msgid "Resource not found"
+msgstr "Zdroj nenájdený"
+
+#: common/daverror.cpp:94
+#, kde-format
+msgid "HTTP error"
+msgstr "HTTP chyba"
+
+#: common/daverror.cpp:96
+#, kde-format
+msgid ""
+"There was a problem with the request.\n"
+"%1 (%2)."
+msgstr ""
+"Bol problém s požiadavkou.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:99
+#, kde-format
+msgid "Protocol for the collection does not support MULTIGET"
+msgstr "Protokol pre kolekciu nepodporuje MULTIGET"
+
+#: common/daverror.cpp:102
+#, kde-format
+msgid ""
+"The server encountered an error that prevented it from completing your "
+"request: %1 (%2)"
+msgstr ""
+"Nastala chyba servera, ktorá znemožnila vykonať vašu požiadavku: %1 (%2)"
+
+#: common/daverror.cpp:105
+#, kde-format
+msgid ""
+"There was a problem with the request. The collection has not been deleted "
+"from the server.\n"
+"%1 (%2)."
+msgstr ""
+"Nastala chyba s požiadavkou. Kolekcia nebola vymazaná zo servera.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:108
+#, kde-format
+msgid "Invalid responses from backend"
+msgstr "Neplatná odpoveď z backendu"
+
+#: common/daverror.cpp:111
+#, kde-format
+msgid "Error setting focus for XQuery"
+msgstr "Chyba nastavenia zamerania na XQuery"
+
+#: common/daverror.cpp:114
+#, kde-format
+msgid "Invalid XQuery submitted by DAV implementation"
+msgstr "Neplatná XQuery poslaná implementáciou DAV"
+
+#: common/daverror.cpp:118
+#, kde-format
+msgid ""
+"There was a problem with the request. The collection has not been modified "
+"on the server.\n"
+"%1 (%2)."
+msgstr ""
+"Nastala chyba s požiadavkou. Položka nebola zmenená na serveri.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:124
+#, kde-format
+msgid "No properties to change or remove"
+msgstr "Žiadne vlastnosti na zmenu alebo odstránenie"
+
+#: common/daverror.cpp:127
+#, kde-format
+msgid "There was an error when modifying the properties"
+msgstr "Nastala chyba počas zmeny vlastností"
+
+#: common/daverror.cpp:129
+#, kde-format
+msgid ""
+"\n"
+"The server returned more information:\n"
+"%1"
+msgstr ""
+"\n"
+"Server vrátil viac informácií:\n"
+"%1"
+
+#: common/daverror.cpp:133
+#, kde-format
+msgid ""
+"There was a problem with the request. The item has not been created on the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+"Nastala chyba s požiadavkou. Položka nebola vytvorená na serveri.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:136
+#, kde-format
+msgid ""
+"There was a problem with the request. The item has not been deleted from the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+"Nastala chyba s požiadavkou. Položka nebola vymazaná zo servera.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:139
+#, kde-format
+msgid ""
+"There was a problem with the request. The item was not modified on the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+"Nastala chyba s požiadavkou. Položka nebola zmenená na serveri.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:142
+#, kde-format
+msgid "There was a problem with the request."
+msgstr "Bol problém s požiadavkou."
+
+#: common/daverror.cpp:146
+#, kde-format
+msgid ""
+"There was a problem with the request. The requested MIME types are not "
+"supported."
+msgstr ""
+"Vyskytol sa problém so žiadosťou. Požadované typy MIME nie sú podporované."
--- /dev/null
+# Copyright (C) YEAR This file is copyright:
+# This file is distributed under the same license as the kdav package.
+#
+# Matjaž Jeran <matjaz.jeran@amis.net>, 2020.
+msgid ""
+msgstr ""
+"Project-Id-Version: kdav\n"
+"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
+"POT-Creation-Date: 2021-03-09 02:40+0100\n"
+"PO-Revision-Date: 2020-06-09 07:29+0200\n"
+"Last-Translator: Matjaž Jeran <matjaz.jeran@amis.net>\n"
+"Language-Team: Slovenian <lugos-slo@lugos.si>\n"
+"Language: sl\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: Lokalize 19.12.2\n"
+"Plural-Forms: nplurals=4; plural=(n%100==1 ? 1 : n%100==2 ? 2 : n%100==3 || n"
+"%100==4 ? 3 : 0);\n"
+
+#: common/daverror.cpp:88
+#, kde-format
+msgid "Invalid username/password"
+msgstr "Neveljavno uporabniško ime/geslo"
+
+#: common/daverror.cpp:90
+#, kde-format
+msgid "Access forbidden"
+msgstr "Dostop prepovedan"
+
+#: common/daverror.cpp:92
+#, kde-format
+msgid "Resource not found"
+msgstr "Vira ni mogoče najti"
+
+#: common/daverror.cpp:94
+#, kde-format
+msgid "HTTP error"
+msgstr "Napaka HTTP"
+
+#: common/daverror.cpp:96
+#, kde-format
+msgid ""
+"There was a problem with the request.\n"
+"%1 (%2)."
+msgstr ""
+"Problem pri zahtevku.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:99
+#, kde-format
+msgid "Protocol for the collection does not support MULTIGET"
+msgstr "Protokol za zbiranje ne podpira MULTIGET"
+
+#: common/daverror.cpp:102
+#, kde-format
+msgid ""
+"The server encountered an error that prevented it from completing your "
+"request: %1 (%2)"
+msgstr ""
+"Strežnik je naletel na napako, ki mu je preprečila dokončanje vašega "
+"zahtevka: %1 (%2)"
+
+#: common/daverror.cpp:105
+#, kde-format
+msgid ""
+"There was a problem with the request. The collection has not been deleted "
+"from the server.\n"
+"%1 (%2)."
+msgstr ""
+"Pri zahtevku je prišlo do težave. Zbirka ni bila izbrisana s strežnika.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:108
+#, kde-format
+msgid "Invalid responses from backend"
+msgstr "Neveljavni odzivi iz zaledja"
+
+#: common/daverror.cpp:111
+#, kde-format
+msgid "Error setting focus for XQuery"
+msgstr "Napaka pri postavitvi osredotočenja na XQuery"
+
+#: common/daverror.cpp:114
+#, kde-format
+msgid "Invalid XQuery submitted by DAV implementation"
+msgstr "Neveljavna poizvedba XQuery, poslana iz implementacije DAV"
+
+#: common/daverror.cpp:118
+#, kde-format
+msgid ""
+"There was a problem with the request. The collection has not been modified "
+"on the server.\n"
+"%1 (%2)."
+msgstr ""
+"Pri zahtevku je prišlo do težave. Zbirka ni na strežniku bila spremenjena.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:124
+#, kde-format
+msgid "No properties to change or remove"
+msgstr "Ni lastnosti za spremembo ali odstranitev"
+
+#: common/daverror.cpp:127
+#, kde-format
+msgid "There was an error when modifying the properties"
+msgstr "Pri spreminjanju lastnosti je prišlo do napake"
+
+#: common/daverror.cpp:129
+#, kde-format
+msgid ""
+"\n"
+"The server returned more information:\n"
+"%1"
+msgstr ""
+"\n"
+"Strežnik je vrnil več informacij:\n"
+"%1"
+
+#: common/daverror.cpp:133
+#, kde-format
+msgid ""
+"There was a problem with the request. The item has not been created on the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+"Pri zahtevku je prišlo do težave. Na strežniku ni bilo ustvarjenega "
+"elementa.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:136
+#, kde-format
+msgid ""
+"There was a problem with the request. The item has not been deleted from the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+"Pri zahtevku je prišlo do težave. Na strežniku element ni bil izbrisan.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:139
+#, kde-format
+msgid ""
+"There was a problem with the request. The item was not modified on the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+"Pri zahtevku je prišlo do težave. Na strežniku element ni bil spremenjen.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:142
+#, kde-format
+msgid "There was a problem with the request."
+msgstr "Pri zahtevku je prišlo do težave."
+
+#: common/daverror.cpp:146
+#, kde-format
+msgid ""
+"There was a problem with the request. The requested MIME types are not "
+"supported."
+msgstr "Pri zahtevku je prišlo do težave. Zahtevane vrste Mime niso podprte."
--- /dev/null
+# Translation of libkdav.po into Serbian.
+# Chusslove Illich <caslav.ilic@gmx.net>, 2011, 2013, 2014, 2015, 2016, 2017.
+msgid ""
+msgstr ""
+"Project-Id-Version: libkdav\n"
+"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
+"POT-Creation-Date: 2020-04-06 03:29+0200\n"
+"PO-Revision-Date: 2017-12-17 18:01+0100\n"
+"Last-Translator: Chusslove Illich <caslav.ilic@gmx.net>\n"
+"Language-Team: Serbian <kde-i18n-sr@kde.org>\n"
+"Language: sr\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=4; plural=n==1 ? 3 : n%10==1 && n%100!=11 ? 0 : n"
+"%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
+"X-Accelerator-Marker: &\n"
+"X-Text-Markup: kde4\n"
+"X-Environment: kde\n"
+
+#: common/daverror.cpp:87
+#, kde-format
+msgid "Invalid username/password"
+msgstr "Лоше корисничко име или лозинка"
+
+#: common/daverror.cpp:89
+#, kde-format
+msgid "Access forbidden"
+msgstr "Приступ забрањен"
+
+#: common/daverror.cpp:91
+#, kde-format
+msgid "Resource not found"
+msgstr "Ресурс није нађен"
+
+#: common/daverror.cpp:93
+#, kde-format
+msgid "HTTP error"
+msgstr "ХТТП грешка"
+
+#: common/daverror.cpp:95
+#, kde-format
+msgid ""
+"There was a problem with the request.\n"
+"%1 (%2)."
+msgstr ""
+"Дошло је до проблема са захтевом.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:99
+#, kde-format
+msgid "Protocol for the collection does not support MULTIGET"
+msgstr "Протокол за збирке не подржава MULTIGET."
+
+#: common/daverror.cpp:102
+#, kde-format
+msgid ""
+"The server encountered an error that prevented it from completing your "
+"request: %1 (%2)"
+msgstr ""
+"Сервер је наишао на грешку која га је спречила да доврши ваш захтев: %1 (%2)"
+
+#: common/daverror.cpp:105
+#, kde-format
+msgid ""
+"There was a problem with the request. The collection has not been deleted "
+"from the server.\n"
+"%1 (%2)."
+msgstr ""
+"Дошло је до проблема са захтевом. Збирка није обрисана са сервера.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:109
+#, kde-format
+msgid "Invalid responses from backend"
+msgstr "Неисправни одговори из позадине."
+
+#: common/daverror.cpp:112
+#, kde-format
+msgid "Error setting focus for XQuery"
+msgstr "Грешка у постављању фокуса за икс‑упит."
+
+#: common/daverror.cpp:115
+#, kde-format
+msgid "Invalid XQuery submitted by DAV implementation"
+msgstr "Изведба ДАВ‑а предала је лош икс‑упит."
+
+#: common/daverror.cpp:118
+#, kde-format
+msgid ""
+"There was a problem with the request. The collection has not been modified "
+"on the server.\n"
+"%1 (%2)."
+msgstr ""
+"Дошло је до проблема са захтевом. Збирка није измењена на серверу.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:122
+#, kde-format
+msgid "No properties to change or remove"
+msgstr "Нема својстава за мењање или уклањање."
+
+#: common/daverror.cpp:125
+#, kde-format
+msgid "There was an error when modifying the properties"
+msgstr "Грешка при мењању својстава."
+
+#: common/daverror.cpp:127
+#, kde-format
+msgid ""
+"\n"
+"The server returned more information:\n"
+"%1"
+msgstr ""
+"\n"
+"Сервер је вратио још података:\n"
+"%1"
+
+#: common/daverror.cpp:131
+#, kde-format
+msgid ""
+"There was a problem with the request. The item has not been created on the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+"Дошло је до проблема са захтевом. Ставка није створена на серверу.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:135
+#, kde-format
+msgid ""
+"There was a problem with the request. The item has not been deleted from the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+"Дошло је до проблема са захтевом. Ставка није обрисана са сервера.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:139
+#, kde-format
+msgid ""
+"There was a problem with the request. The item was not modified on the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+"Дошло је до проблема са захтевом, ставка није измењена на серверу.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:144
+#, kde-format
+msgid "There was a problem with the request."
+msgstr "Дошло је до проблема са захтевом."
+
+#: common/daverror.cpp:148
+#, kde-format
+msgid ""
+"There was a problem with the request. The requested MIME types are not "
+"supported."
+msgstr "Дошло је до проблема са захтевом. Тражени МИМЕ типови нису подржани."
--- /dev/null
+# Translation of libkdav.po into Serbian.
+# Chusslove Illich <caslav.ilic@gmx.net>, 2011, 2013, 2014, 2015, 2016, 2017.
+msgid ""
+msgstr ""
+"Project-Id-Version: libkdav\n"
+"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
+"POT-Creation-Date: 2020-04-06 03:29+0200\n"
+"PO-Revision-Date: 2017-12-17 18:01+0100\n"
+"Last-Translator: Chusslove Illich <caslav.ilic@gmx.net>\n"
+"Language-Team: Serbian <kde-i18n-sr@kde.org>\n"
+"Language: sr@ijekavian\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=4; plural=n==1 ? 3 : n%10==1 && n%100!=11 ? 0 : n"
+"%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
+"X-Accelerator-Marker: &\n"
+"X-Text-Markup: kde4\n"
+"X-Environment: kde\n"
+
+#: common/daverror.cpp:87
+#, kde-format
+msgid "Invalid username/password"
+msgstr "Лоше корисничко име или лозинка"
+
+#: common/daverror.cpp:89
+#, kde-format
+msgid "Access forbidden"
+msgstr "Приступ забрањен"
+
+#: common/daverror.cpp:91
+#, kde-format
+msgid "Resource not found"
+msgstr "Ресурс није нађен"
+
+#: common/daverror.cpp:93
+#, kde-format
+msgid "HTTP error"
+msgstr "ХТТП грешка"
+
+#: common/daverror.cpp:95
+#, kde-format
+msgid ""
+"There was a problem with the request.\n"
+"%1 (%2)."
+msgstr ""
+"Дошло је до проблема са захтевом.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:99
+#, kde-format
+msgid "Protocol for the collection does not support MULTIGET"
+msgstr "Протокол за збирке не подржава MULTIGET."
+
+#: common/daverror.cpp:102
+#, kde-format
+msgid ""
+"The server encountered an error that prevented it from completing your "
+"request: %1 (%2)"
+msgstr ""
+"Сервер је наишао на грешку која га је спречила да доврши ваш захтев: %1 (%2)"
+
+#: common/daverror.cpp:105
+#, kde-format
+msgid ""
+"There was a problem with the request. The collection has not been deleted "
+"from the server.\n"
+"%1 (%2)."
+msgstr ""
+"Дошло је до проблема са захтевом. Збирка није обрисана са сервера.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:109
+#, kde-format
+msgid "Invalid responses from backend"
+msgstr "Неисправни одговори из позадине."
+
+#: common/daverror.cpp:112
+#, kde-format
+msgid "Error setting focus for XQuery"
+msgstr "Грешка у постављању фокуса за икс‑упит."
+
+#: common/daverror.cpp:115
+#, kde-format
+msgid "Invalid XQuery submitted by DAV implementation"
+msgstr "Изведба ДАВ‑а предала је лош икс‑упит."
+
+#: common/daverror.cpp:118
+#, kde-format
+msgid ""
+"There was a problem with the request. The collection has not been modified "
+"on the server.\n"
+"%1 (%2)."
+msgstr ""
+"Дошло је до проблема са захтевом. Збирка није измењена на серверу.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:122
+#, kde-format
+msgid "No properties to change or remove"
+msgstr "Нема својстава за мењање или уклањање."
+
+#: common/daverror.cpp:125
+#, kde-format
+msgid "There was an error when modifying the properties"
+msgstr "Грешка при мењању својстава."
+
+#: common/daverror.cpp:127
+#, kde-format
+msgid ""
+"\n"
+"The server returned more information:\n"
+"%1"
+msgstr ""
+"\n"
+"Сервер је вратио још података:\n"
+"%1"
+
+#: common/daverror.cpp:131
+#, kde-format
+msgid ""
+"There was a problem with the request. The item has not been created on the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+"Дошло је до проблема са захтевом. Ставка није створена на серверу.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:135
+#, kde-format
+msgid ""
+"There was a problem with the request. The item has not been deleted from the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+"Дошло је до проблема са захтевом. Ставка није обрисана са сервера.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:139
+#, kde-format
+msgid ""
+"There was a problem with the request. The item was not modified on the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+"Дошло је до проблема са захтевом, ставка није измењена на серверу.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:144
+#, kde-format
+msgid "There was a problem with the request."
+msgstr "Дошло је до проблема са захтевом."
+
+#: common/daverror.cpp:148
+#, kde-format
+msgid ""
+"There was a problem with the request. The requested MIME types are not "
+"supported."
+msgstr "Дошло је до проблема са захтевом. Тражени МИМЕ типови нису подржани."
--- /dev/null
+# Translation of libkdav.po into Serbian.
+# Chusslove Illich <caslav.ilic@gmx.net>, 2011, 2013, 2014, 2015, 2016, 2017.
+msgid ""
+msgstr ""
+"Project-Id-Version: libkdav\n"
+"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
+"POT-Creation-Date: 2020-04-06 03:29+0200\n"
+"PO-Revision-Date: 2017-12-17 18:01+0100\n"
+"Last-Translator: Chusslove Illich <caslav.ilic@gmx.net>\n"
+"Language-Team: Serbian <kde-i18n-sr@kde.org>\n"
+"Language: sr@ijekavianlatin\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=4; plural=n==1 ? 3 : n%10==1 && n%100!=11 ? 0 : n"
+"%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
+"X-Accelerator-Marker: &\n"
+"X-Text-Markup: kde4\n"
+"X-Environment: kde\n"
+
+#: common/daverror.cpp:87
+#, kde-format
+msgid "Invalid username/password"
+msgstr "Loše korisničko ime ili lozinka"
+
+#: common/daverror.cpp:89
+#, kde-format
+msgid "Access forbidden"
+msgstr "Pristup zabranjen"
+
+#: common/daverror.cpp:91
+#, kde-format
+msgid "Resource not found"
+msgstr "Resurs nije nađen"
+
+#: common/daverror.cpp:93
+#, kde-format
+msgid "HTTP error"
+msgstr "HTTP greška"
+
+#: common/daverror.cpp:95
+#, kde-format
+msgid ""
+"There was a problem with the request.\n"
+"%1 (%2)."
+msgstr ""
+"Došlo je do problema sa zahtevom.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:99
+#, kde-format
+msgid "Protocol for the collection does not support MULTIGET"
+msgstr "Protokol za zbirke ne podržava MULTIGET."
+
+#: common/daverror.cpp:102
+#, kde-format
+msgid ""
+"The server encountered an error that prevented it from completing your "
+"request: %1 (%2)"
+msgstr ""
+"Server je naišao na grešku koja ga je sprečila da dovrši vaš zahtev: %1 (%2)"
+
+#: common/daverror.cpp:105
+#, kde-format
+msgid ""
+"There was a problem with the request. The collection has not been deleted "
+"from the server.\n"
+"%1 (%2)."
+msgstr ""
+"Došlo je do problema sa zahtevom. Zbirka nije obrisana sa servera.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:109
+#, kde-format
+msgid "Invalid responses from backend"
+msgstr "Neispravni odgovori iz pozadine."
+
+#: common/daverror.cpp:112
+#, kde-format
+msgid "Error setting focus for XQuery"
+msgstr "Greška u postavljanju fokusa za XQuery."
+
+#: common/daverror.cpp:115
+#, kde-format
+msgid "Invalid XQuery submitted by DAV implementation"
+msgstr "Izvedba DAV‑a predala je loš XQuery."
+
+#: common/daverror.cpp:118
+#, kde-format
+msgid ""
+"There was a problem with the request. The collection has not been modified "
+"on the server.\n"
+"%1 (%2)."
+msgstr ""
+"Došlo je do problema sa zahtevom. Zbirka nije izmenjena na serveru.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:122
+#, kde-format
+msgid "No properties to change or remove"
+msgstr "Nema svojstava za menjanje ili uklanjanje."
+
+#: common/daverror.cpp:125
+#, kde-format
+msgid "There was an error when modifying the properties"
+msgstr "Greška pri menjanju svojstava."
+
+#: common/daverror.cpp:127
+#, kde-format
+msgid ""
+"\n"
+"The server returned more information:\n"
+"%1"
+msgstr ""
+"\n"
+"Server je vratio još podataka:\n"
+"%1"
+
+#: common/daverror.cpp:131
+#, kde-format
+msgid ""
+"There was a problem with the request. The item has not been created on the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+"Došlo je do problema sa zahtevom. Stavka nije stvorena na serveru.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:135
+#, kde-format
+msgid ""
+"There was a problem with the request. The item has not been deleted from the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+"Došlo je do problema sa zahtevom. Stavka nije obrisana sa servera.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:139
+#, kde-format
+msgid ""
+"There was a problem with the request. The item was not modified on the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+"Došlo je do problema sa zahtevom, stavka nije izmenjena na serveru.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:144
+#, kde-format
+msgid "There was a problem with the request."
+msgstr "Došlo je do problema sa zahtevom."
+
+#: common/daverror.cpp:148
+#, kde-format
+msgid ""
+"There was a problem with the request. The requested MIME types are not "
+"supported."
+msgstr "Došlo je do problema sa zahtevom. Traženi MIME tipovi nisu podržani."
--- /dev/null
+# Translation of libkdav.po into Serbian.
+# Chusslove Illich <caslav.ilic@gmx.net>, 2011, 2013, 2014, 2015, 2016, 2017.
+msgid ""
+msgstr ""
+"Project-Id-Version: libkdav\n"
+"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
+"POT-Creation-Date: 2020-04-06 03:29+0200\n"
+"PO-Revision-Date: 2017-12-17 18:01+0100\n"
+"Last-Translator: Chusslove Illich <caslav.ilic@gmx.net>\n"
+"Language-Team: Serbian <kde-i18n-sr@kde.org>\n"
+"Language: sr@latin\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=4; plural=n==1 ? 3 : n%10==1 && n%100!=11 ? 0 : n"
+"%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
+"X-Accelerator-Marker: &\n"
+"X-Text-Markup: kde4\n"
+"X-Environment: kde\n"
+
+#: common/daverror.cpp:87
+#, kde-format
+msgid "Invalid username/password"
+msgstr "Loše korisničko ime ili lozinka"
+
+#: common/daverror.cpp:89
+#, kde-format
+msgid "Access forbidden"
+msgstr "Pristup zabranjen"
+
+#: common/daverror.cpp:91
+#, kde-format
+msgid "Resource not found"
+msgstr "Resurs nije nađen"
+
+#: common/daverror.cpp:93
+#, kde-format
+msgid "HTTP error"
+msgstr "HTTP greška"
+
+#: common/daverror.cpp:95
+#, kde-format
+msgid ""
+"There was a problem with the request.\n"
+"%1 (%2)."
+msgstr ""
+"Došlo je do problema sa zahtevom.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:99
+#, kde-format
+msgid "Protocol for the collection does not support MULTIGET"
+msgstr "Protokol za zbirke ne podržava MULTIGET."
+
+#: common/daverror.cpp:102
+#, kde-format
+msgid ""
+"The server encountered an error that prevented it from completing your "
+"request: %1 (%2)"
+msgstr ""
+"Server je naišao na grešku koja ga je sprečila da dovrši vaš zahtev: %1 (%2)"
+
+#: common/daverror.cpp:105
+#, kde-format
+msgid ""
+"There was a problem with the request. The collection has not been deleted "
+"from the server.\n"
+"%1 (%2)."
+msgstr ""
+"Došlo je do problema sa zahtevom. Zbirka nije obrisana sa servera.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:109
+#, kde-format
+msgid "Invalid responses from backend"
+msgstr "Neispravni odgovori iz pozadine."
+
+#: common/daverror.cpp:112
+#, kde-format
+msgid "Error setting focus for XQuery"
+msgstr "Greška u postavljanju fokusa za XQuery."
+
+#: common/daverror.cpp:115
+#, kde-format
+msgid "Invalid XQuery submitted by DAV implementation"
+msgstr "Izvedba DAV‑a predala je loš XQuery."
+
+#: common/daverror.cpp:118
+#, kde-format
+msgid ""
+"There was a problem with the request. The collection has not been modified "
+"on the server.\n"
+"%1 (%2)."
+msgstr ""
+"Došlo je do problema sa zahtevom. Zbirka nije izmenjena na serveru.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:122
+#, kde-format
+msgid "No properties to change or remove"
+msgstr "Nema svojstava za menjanje ili uklanjanje."
+
+#: common/daverror.cpp:125
+#, kde-format
+msgid "There was an error when modifying the properties"
+msgstr "Greška pri menjanju svojstava."
+
+#: common/daverror.cpp:127
+#, kde-format
+msgid ""
+"\n"
+"The server returned more information:\n"
+"%1"
+msgstr ""
+"\n"
+"Server je vratio još podataka:\n"
+"%1"
+
+#: common/daverror.cpp:131
+#, kde-format
+msgid ""
+"There was a problem with the request. The item has not been created on the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+"Došlo je do problema sa zahtevom. Stavka nije stvorena na serveru.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:135
+#, kde-format
+msgid ""
+"There was a problem with the request. The item has not been deleted from the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+"Došlo je do problema sa zahtevom. Stavka nije obrisana sa servera.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:139
+#, kde-format
+msgid ""
+"There was a problem with the request. The item was not modified on the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+"Došlo je do problema sa zahtevom, stavka nije izmenjena na serveru.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:144
+#, kde-format
+msgid "There was a problem with the request."
+msgstr "Došlo je do problema sa zahtevom."
+
+#: common/daverror.cpp:148
+#, kde-format
+msgid ""
+"There was a problem with the request. The requested MIME types are not "
+"supported."
+msgstr "Došlo je do problema sa zahtevom. Traženi MIME tipovi nisu podržani."
--- /dev/null
+# Copyright (C) YEAR This_file_is_part_of_KDE
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Stefan Asserhäll <stefan.asserhall@bredband.net>, 2017.
+msgid ""
+msgstr ""
+"Project-Id-Version: \n"
+"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
+"POT-Creation-Date: 2021-03-09 02:40+0100\n"
+"PO-Revision-Date: 2017-12-12 19:37+0100\n"
+"Last-Translator: Stefan Asserhäll <stefan.asserhall@bredband.net>\n"
+"Language-Team: Swedish <kde-i18n-doc@kde.org>\n"
+"Language: sv\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+"X-Generator: Lokalize 2.0\n"
+
+#: common/daverror.cpp:88
+#, kde-format
+msgid "Invalid username/password"
+msgstr "Ogiltigt användarnamn eller lösenord"
+
+#: common/daverror.cpp:90
+#, kde-format
+msgid "Access forbidden"
+msgstr "Åtkomst nekas"
+
+#: common/daverror.cpp:92
+#, kde-format
+msgid "Resource not found"
+msgstr "Resurs hittades inte"
+
+#: common/daverror.cpp:94
+#, kde-format
+msgid "HTTP error"
+msgstr "HTTP-fel"
+
+#: common/daverror.cpp:96
+#, kde-format
+msgid ""
+"There was a problem with the request.\n"
+"%1 (%2)."
+msgstr ""
+"Ett problem uppstod med begäran.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:99
+#, kde-format
+msgid "Protocol for the collection does not support MULTIGET"
+msgstr "Protokoll för samlingen stöder inte MULTIGET"
+
+#: common/daverror.cpp:102
+#, kde-format
+msgid ""
+"The server encountered an error that prevented it from completing your "
+"request: %1 (%2)"
+msgstr ""
+"Servern råkade ut för ett fel som förhindrade den att färdigställa din "
+"begäran: %1 (%2)"
+
+#: common/daverror.cpp:105
+#, kde-format
+msgid ""
+"There was a problem with the request. The collection has not been deleted "
+"from the server.\n"
+"%1 (%2)."
+msgstr ""
+"Ett problem uppstod med begäran. Samlingen har inte tagits bort från "
+"servern.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:108
+#, kde-format
+msgid "Invalid responses from backend"
+msgstr "Felaktigt svar från gränssnitt"
+
+#: common/daverror.cpp:111
+#, kde-format
+msgid "Error setting focus for XQuery"
+msgstr "Fel när fokus skulle ställas in för XQuery"
+
+#: common/daverror.cpp:114
+#, kde-format
+msgid "Invalid XQuery submitted by DAV implementation"
+msgstr "Felaktig XQuery skickades av DAV-implementering"
+
+#: common/daverror.cpp:118
+#, kde-format
+msgid ""
+"There was a problem with the request. The collection has not been modified "
+"on the server.\n"
+"%1 (%2)."
+msgstr ""
+"Ett problem uppstod med begäran. Samlingen har inte ändrats på servern.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:124
+#, kde-format
+msgid "No properties to change or remove"
+msgstr "Inga egenskaper att ändra eller ta bort"
+
+#: common/daverror.cpp:127
+#, kde-format
+msgid "There was an error when modifying the properties"
+msgstr "Ett fel uppstod när egenskaperna skulle ändras"
+
+#: common/daverror.cpp:129
+#, kde-format
+msgid ""
+"\n"
+"The server returned more information:\n"
+"%1"
+msgstr ""
+"\n"
+"Servern returnerade mer information:\n"
+"%1"
+
+#: common/daverror.cpp:133
+#, kde-format
+msgid ""
+"There was a problem with the request. The item has not been created on the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+"Ett problem uppstod med begäran. Objektet har inte skapats på servern.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:136
+#, kde-format
+msgid ""
+"There was a problem with the request. The item has not been deleted from the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+"Ett problem uppstod med begäran. Objektet har inte tagits bort från "
+"servern.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:139
+#, kde-format
+msgid ""
+"There was a problem with the request. The item was not modified on the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+"Ett problem uppstod med begäran. Objektet ändrades inte på servern.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:142
+#, kde-format
+msgid "There was a problem with the request."
+msgstr "Ett problem uppstod med begäran."
+
+#: common/daverror.cpp:146
+#, kde-format
+msgid ""
+"There was a problem with the request. The requested MIME types are not "
+"supported."
+msgstr "Ett problem uppstod med begäran. De begärda Mime-typerna stöds inte."
--- /dev/null
+# Copyright (C) YEAR This file is copyright:
+# This file is distributed under the same license as the kdav package.
+#
+# Emir SARI <emir_sari@icloud.com>, 2022.
+msgid ""
+msgstr ""
+"Project-Id-Version: kdav\n"
+"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
+"POT-Creation-Date: 2021-03-09 02:40+0100\n"
+"PO-Revision-Date: 2022-03-18 23:21+0300\n"
+"Last-Translator: Emir SARI <emir_sari@icloud.com>\n"
+"Language-Team: Turkish <kde-l10n-tr@kde.org>\n"
+"Language: tr\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n > 1);\n"
+"X-Generator: Lokalize 21.12.3\n"
+
+#: common/daverror.cpp:88
+#, kde-format
+msgid "Invalid username/password"
+msgstr "Geçersiz kullanıcı adı/parola"
+
+#: common/daverror.cpp:90
+#, kde-format
+msgid "Access forbidden"
+msgstr "Erişim engellendi"
+
+#: common/daverror.cpp:92
+#, kde-format
+msgid "Resource not found"
+msgstr "Özkaynak bulunamadı"
+
+#: common/daverror.cpp:94
+#, kde-format
+msgid "HTTP error"
+msgstr "HTTP hatası"
+
+#: common/daverror.cpp:96
+#, kde-format
+msgid ""
+"There was a problem with the request.\n"
+"%1 (%2)."
+msgstr ""
+"İstekte bir sorun oluştu.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:99
+#, kde-format
+msgid "Protocol for the collection does not support MULTIGET"
+msgstr "Koleksiyon protokolü MULTIGET desteklemiyor"
+
+#: common/daverror.cpp:102
+#, kde-format
+msgid ""
+"The server encountered an error that prevented it from completing your "
+"request: %1 (%2)"
+msgstr ""
+"Sunucu, isteğinizin tamamlanmasını engelleyen bir hatayla karşılaştı: %1 (%2)"
+
+#: common/daverror.cpp:105
+#, kde-format
+msgid ""
+"There was a problem with the request. The collection has not been deleted "
+"from the server.\n"
+"%1 (%2)."
+msgstr ""
+"İstekte bir sorun oluştu. Koleksiyon sunucudan silinmedi.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:108
+#, kde-format
+msgid "Invalid responses from backend"
+msgstr "Arka uçtan geçersiz yanıt"
+
+#: common/daverror.cpp:111
+#, kde-format
+msgid "Error setting focus for XQuery"
+msgstr "XQuery için odak ayarlanırken hata"
+
+#: common/daverror.cpp:114
+#, kde-format
+msgid "Invalid XQuery submitted by DAV implementation"
+msgstr "DAV uygulaması tarafından sağlanan geçersiz XQuery"
+
+#: common/daverror.cpp:118
+#, kde-format
+msgid ""
+"There was a problem with the request. The collection has not been modified "
+"on the server.\n"
+"%1 (%2)."
+msgstr ""
+"İstekte bir sorun oluştu. Koleksiyon, sunucuda değiştirilmedi.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:124
+#, kde-format
+msgid "No properties to change or remove"
+msgstr "Değiştirilecek veya kaldırılacak özellik yok"
+
+#: common/daverror.cpp:127
+#, kde-format
+msgid "There was an error when modifying the properties"
+msgstr "Özellikleri değiştirirken bir hata oluştu"
+
+#: common/daverror.cpp:129
+#, kde-format
+msgid ""
+"\n"
+"The server returned more information:\n"
+"%1"
+msgstr ""
+"\n"
+"Sunucu ek bilgi döndürdü:\n"
+"%1"
+
+#: common/daverror.cpp:133
+#, kde-format
+msgid ""
+"There was a problem with the request. The item has not been created on the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+"İstekte bir sorun oluştu. Öge, sunucuda oluşturulmadı.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:136
+#, kde-format
+msgid ""
+"There was a problem with the request. The item has not been deleted from the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+"İstekte bir sorun oluştu. Öge, sunucuda silinmedi.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:139
+#, kde-format
+msgid ""
+"There was a problem with the request. The item was not modified on the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+"İstekte bir sorun oluştu. Öge, sunucuda değiştirilmedi.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:142
+#, kde-format
+msgid "There was a problem with the request."
+msgstr "İstekte bir sorun oluştu."
+
+#: common/daverror.cpp:146
+#, kde-format
+msgid ""
+"There was a problem with the request. The requested MIME types are not "
+"supported."
+msgstr "İstekte bir sorun oluştu. İstenen MIME türleri desteklenmiyor."
--- /dev/null
+# Translation of libkdav.po to Ukrainian
+# Copyright (C) 2017 This_file_is_part_of_KDE
+# This file is distributed under the license LGPL version 2.1 or
+# version 3 or later versions approved by the membership of KDE e.V.
+#
+# Yuri Chornoivan <yurchor@ukr.net>, 2017.
+msgid ""
+msgstr ""
+"Project-Id-Version: libkdav\n"
+"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
+"POT-Creation-Date: 2021-03-09 02:40+0100\n"
+"PO-Revision-Date: 2017-12-12 08:38+0200\n"
+"Last-Translator: Yuri Chornoivan <yurchor@ukr.net>\n"
+"Language-Team: Ukrainian <kde-i18n-uk@kde.org>\n"
+"Language: uk\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=4; plural=n==1 ? 3 : n%10==1 && n%100!=11 ? 0 : n"
+"%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
+"X-Generator: Lokalize 2.0\n"
+
+#: common/daverror.cpp:88
+#, kde-format
+msgid "Invalid username/password"
+msgstr "Некоректне ім’я користувача чи пароль"
+
+#: common/daverror.cpp:90
+#, kde-format
+msgid "Access forbidden"
+msgstr "Доступ заборонено"
+
+#: common/daverror.cpp:92
+#, kde-format
+msgid "Resource not found"
+msgstr "Ресурс не знайдено"
+
+#: common/daverror.cpp:94
+#, kde-format
+msgid "HTTP error"
+msgstr "Помилка HTTP"
+
+#: common/daverror.cpp:96
+#, kde-format
+msgid ""
+"There was a problem with the request.\n"
+"%1 (%2)."
+msgstr ""
+"Під час виконання запиту виникла проблема.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:99
+#, kde-format
+msgid "Protocol for the collection does not support MULTIGET"
+msgstr "У протоколі для роботи з цією збіркою не передбачено команди MULTIGET"
+
+#: common/daverror.cpp:102
+#, kde-format
+msgid ""
+"The server encountered an error that prevented it from completing your "
+"request: %1 (%2)"
+msgstr ""
+"На сервері сталася помилка, через яку він не зміг завершити виконання вашого "
+"запиту: %1 (%2)"
+
+#: common/daverror.cpp:105
+#, kde-format
+msgid ""
+"There was a problem with the request. The collection has not been deleted "
+"from the server.\n"
+"%1 (%2)."
+msgstr ""
+"Під час виконання запиту виникла проблема. Збірку на сервері не було "
+"вилучено.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:108
+#, kde-format
+msgid "Invalid responses from backend"
+msgstr "Отримано некоректні відповіді сервера"
+
+#: common/daverror.cpp:111
+#, kde-format
+msgid "Error setting focus for XQuery"
+msgstr "Помилка під час спроби встановлення фокусу для XQuery"
+
+#: common/daverror.cpp:114
+#, kde-format
+msgid "Invalid XQuery submitted by DAV implementation"
+msgstr "Реалізацією DAV було надіслано некоректні дані XQuery"
+
+#: common/daverror.cpp:118
+#, kde-format
+msgid ""
+"There was a problem with the request. The collection has not been modified "
+"on the server.\n"
+"%1 (%2)."
+msgstr ""
+"Під час виконання запиту виникла проблема. Збірку на сервері не було "
+"змінено.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:124
+#, kde-format
+msgid "No properties to change or remove"
+msgstr "Немає властивостей для зміни або вилучення"
+
+#: common/daverror.cpp:127
+#, kde-format
+msgid "There was an error when modifying the properties"
+msgstr "Під час спроби зміни властивостей сталася помилка"
+
+#: common/daverror.cpp:129
+#, kde-format
+msgid ""
+"\n"
+"The server returned more information:\n"
+"%1"
+msgstr ""
+"\n"
+"Сервером було повернуто додаткову інформацію:\n"
+"%1"
+
+#: common/daverror.cpp:133
+#, kde-format
+msgid ""
+"There was a problem with the request. The item has not been created on the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+"Під час виконання запиту виникла проблема. Запис на сервері не було "
+"створено.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:136
+#, kde-format
+msgid ""
+"There was a problem with the request. The item has not been deleted from the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+"Під час виконання запиту виникла проблема. Запис на сервері не було "
+"вилучено.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:139
+#, kde-format
+msgid ""
+"There was a problem with the request. The item was not modified on the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+"Під час виконання запиту виникла проблема. Запис на сервері не було "
+"змінено.\n"
+"%1 (%2)."
+
+#: common/daverror.cpp:142
+#, kde-format
+msgid "There was a problem with the request."
+msgstr "Під час виконання запиту виникла проблема."
+
+#: common/daverror.cpp:146
+#, kde-format
+msgid ""
+"There was a problem with the request. The requested MIME types are not "
+"supported."
+msgstr ""
+"Під час виконання запиту виникла проблема. Підтримки потрібних вам типів "
+"MIME не передбачено."
--- /dev/null
+msgid ""
+msgstr ""
+"Project-Id-Version: kdeorg\n"
+"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
+"POT-Creation-Date: 2021-03-09 02:40+0100\n"
+"PO-Revision-Date: 2023-01-02 07:11\n"
+"Last-Translator: \n"
+"Language-Team: Chinese Simplified\n"
+"Language: zh_CN\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+"X-Crowdin-Project: kdeorg\n"
+"X-Crowdin-Project-ID: 269464\n"
+"X-Crowdin-Language: zh-CN\n"
+"X-Crowdin-File: /kf5-trunk/messages/kdav/libkdav.pot\n"
+"X-Crowdin-File-ID: 6689\n"
+
+#: common/daverror.cpp:88
+#, kde-format
+msgid "Invalid username/password"
+msgstr "无效的用户名或密码"
+
+#: common/daverror.cpp:90
+#, kde-format
+msgid "Access forbidden"
+msgstr "禁止访问"
+
+#: common/daverror.cpp:92
+#, kde-format
+msgid "Resource not found"
+msgstr "找不到资源"
+
+#: common/daverror.cpp:94
+#, kde-format
+msgid "HTTP error"
+msgstr "HTTP 错误"
+
+#: common/daverror.cpp:96
+#, kde-format
+msgid ""
+"There was a problem with the request.\n"
+"%1 (%2)."
+msgstr "请求出错。\\n%1 (%2)。"
+
+#: common/daverror.cpp:99
+#, kde-format
+msgid "Protocol for the collection does not support MULTIGET"
+msgstr "集合的协议不支持 MULTIGET"
+
+#: common/daverror.cpp:102
+#, kde-format
+msgid ""
+"The server encountered an error that prevented it from completing your "
+"request: %1 (%2)"
+msgstr "服务器出现错误,无法完成您的请求:%1 (%2)"
+
+#: common/daverror.cpp:105
+#, kde-format
+msgid ""
+"There was a problem with the request. The collection has not been deleted "
+"from the server.\n"
+"%1 (%2)."
+msgstr ""
+"请求出错。服务器上的项目未删除。\n"
+"%1 (%2)。"
+
+#: common/daverror.cpp:108
+#, kde-format
+msgid "Invalid responses from backend"
+msgstr "无效的后端应答"
+
+#: common/daverror.cpp:111
+#, kde-format
+msgid "Error setting focus for XQuery"
+msgstr "设置 XQuery 焦点时发生错误"
+
+#: common/daverror.cpp:114
+#, kde-format
+msgid "Invalid XQuery submitted by DAV implementation"
+msgstr "DAV 实现提交了无效的 XQuery"
+
+#: common/daverror.cpp:118
+#, kde-format
+msgid ""
+"There was a problem with the request. The collection has not been modified "
+"on the server.\n"
+"%1 (%2)."
+msgstr ""
+"请求出错。服务器上的项目未修改。\n"
+"%1 (%2)。"
+
+#: common/daverror.cpp:124
+#, kde-format
+msgid "No properties to change or remove"
+msgstr "没有要更改或删除的属性"
+
+#: common/daverror.cpp:127
+#, kde-format
+msgid "There was an error when modifying the properties"
+msgstr "修改属性时出错"
+
+#: common/daverror.cpp:129
+#, kde-format
+msgid ""
+"\n"
+"The server returned more information:\n"
+"%1"
+msgstr ""
+"\n"
+"服务器返回更多信息:\n"
+"%1"
+
+#: common/daverror.cpp:133
+#, kde-format
+msgid ""
+"There was a problem with the request. The item has not been created on the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+"请求出错。服务器上的项目未创建。\n"
+"%1 (%2)。"
+
+#: common/daverror.cpp:136
+#, kde-format
+msgid ""
+"There was a problem with the request. The item has not been deleted from the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+"请求出错。服务器上的项目未删除。\n"
+"%1 (%2)。"
+
+#: common/daverror.cpp:139
+#, kde-format
+msgid ""
+"There was a problem with the request. The item was not modified on the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+"请求出错。服务器上的项目未修改。\n"
+"%1 (%2)。"
+
+#: common/daverror.cpp:142
+#, kde-format
+msgid "There was a problem with the request."
+msgstr "请求出错。"
+
+#: common/daverror.cpp:146
+#, kde-format
+msgid ""
+"There was a problem with the request. The requested MIME types are not "
+"supported."
+msgstr "请求出错。服务器上的项目未创建。"
--- /dev/null
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR This file is copyright:
+# This file is distributed under the same license as the kdav package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: kdav\n"
+"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
+"POT-Creation-Date: 2021-03-09 02:40+0100\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: Chinese <kde-i18n-doc@kde.org>\n"
+"Language: zh_TW\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+
+#: common/daverror.cpp:88
+#, kde-format
+msgid "Invalid username/password"
+msgstr ""
+
+#: common/daverror.cpp:90
+#, kde-format
+msgid "Access forbidden"
+msgstr ""
+
+#: common/daverror.cpp:92
+#, kde-format
+msgid "Resource not found"
+msgstr ""
+
+#: common/daverror.cpp:94
+#, kde-format
+msgid "HTTP error"
+msgstr ""
+
+#: common/daverror.cpp:96
+#, kde-format
+msgid ""
+"There was a problem with the request.\n"
+"%1 (%2)."
+msgstr ""
+
+#: common/daverror.cpp:99
+#, kde-format
+msgid "Protocol for the collection does not support MULTIGET"
+msgstr ""
+
+#: common/daverror.cpp:102
+#, kde-format
+msgid ""
+"The server encountered an error that prevented it from completing your "
+"request: %1 (%2)"
+msgstr ""
+
+#: common/daverror.cpp:105
+#, kde-format
+msgid ""
+"There was a problem with the request. The collection has not been deleted "
+"from the server.\n"
+"%1 (%2)."
+msgstr ""
+
+#: common/daverror.cpp:108
+#, kde-format
+msgid "Invalid responses from backend"
+msgstr ""
+
+#: common/daverror.cpp:111
+#, kde-format
+msgid "Error setting focus for XQuery"
+msgstr ""
+
+#: common/daverror.cpp:114
+#, kde-format
+msgid "Invalid XQuery submitted by DAV implementation"
+msgstr ""
+
+#: common/daverror.cpp:118
+#, kde-format
+msgid ""
+"There was a problem with the request. The collection has not been modified "
+"on the server.\n"
+"%1 (%2)."
+msgstr ""
+
+#: common/daverror.cpp:124
+#, kde-format
+msgid "No properties to change or remove"
+msgstr ""
+
+#: common/daverror.cpp:127
+#, kde-format
+msgid "There was an error when modifying the properties"
+msgstr ""
+
+#: common/daverror.cpp:129
+#, kde-format
+msgid ""
+"\n"
+"The server returned more information:\n"
+"%1"
+msgstr ""
+
+#: common/daverror.cpp:133
+#, kde-format
+msgid ""
+"There was a problem with the request. The item has not been created on the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+
+#: common/daverror.cpp:136
+#, kde-format
+msgid ""
+"There was a problem with the request. The item has not been deleted from the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+
+#: common/daverror.cpp:139
+#, kde-format
+msgid ""
+"There was a problem with the request. The item was not modified on the "
+"server.\n"
+"%1 (%2)."
+msgstr ""
+
+#: common/daverror.cpp:142
+#, kde-format
+msgid "There was a problem with the request."
+msgstr ""
+
+#: common/daverror.cpp:146
+#, kde-format
+msgid ""
+"There was a problem with the request. The requested MIME types are not "
+"supported."
+msgstr ""
--- /dev/null
+add_definitions(-DTRANSLATION_DOMAIN=\"libkdav\")
+
+set(KDAV_INSTALL_INCLUDEDIR "${KDE_INSTALL_INCLUDEDIR_KF}/KDAV")
+
+add_library(KF5DAV)
+add_library(KF5::DAV ALIAS KF5DAV)
+
+set_target_properties(KF5DAV PROPERTIES
+ VERSION ${KDAV_VERSION}
+ SOVERSION ${KDAV_SOVERSION}
+ EXPORT_NAME DAV
+)
+
+target_sources(KF5DAV PRIVATE
+ common/davcollection.cpp
+ common/davcollectiondeletejob.cpp
+ common/davcollectiondeletejob.h
+ common/davcollection.h
+ common/davcollectionmodifyjob.cpp
+ common/davcollectionmodifyjob.h
+ common/davcollectionsfetchjob.cpp
+ common/davcollectionsfetchjob.h
+ common/davcollectionsmultifetchjob.cpp
+ common/davcollectionsmultifetchjob.h
+ common/daverror.cpp
+ common/daverror.h
+ common/davitem.cpp
+ common/davitemcreatejob.cpp
+ common/davitemcreatejob.h
+ common/davitemdeletejob.cpp
+ common/davitemdeletejob.h
+ common/davitemfetchjob.cpp
+ common/davitemfetchjob.h
+ common/davitem.h
+ common/davitemmodifyjob.cpp
+ common/davitemmodifyjob.h
+ common/davitemsfetchjob.cpp
+ common/davitemsfetchjob.h
+ common/davitemslistjob.cpp
+ common/davitemslistjob.h
+ common/davjobbase.cpp
+ common/davjobbase.h
+ common/davjobbase_p.h
+ common/davmanager.cpp
+ common/davmanager_p.h
+ common/davmultigetprotocol.cpp
+ common/davmultigetprotocol_p.h
+ common/davprincipalhomesetsfetchjob.cpp
+ common/davprincipalhomesetsfetchjob.h
+ common/davprincipalsearchjob.cpp
+ common/davprincipalsearchjob.h
+ common/davprotocolbase.cpp
+ common/davprotocolbase_p.h
+ common/davurl.cpp
+ common/davurl.h
+ common/enums.h
+ common/etagcache.cpp
+ common/etagcache.h
+ common/protocolinfo.cpp
+ common/protocolinfo.h
+ common/utils.cpp
+ common/utils_p.h
+
+ protocols/groupdavprotocol.cpp
+ protocols/groupdavprotocol_p.h
+
+ #KContacts
+ protocols/carddavprotocol.cpp
+ protocols/carddavprotocol_p.h
+
+ #KCalCore
+ protocols/caldavprotocol.cpp
+ protocols/caldavprotocol_p.h
+ )
+
+
+ecm_generate_headers(KDAV_Camelcase_HEADERS
+ HEADER_NAMES
+ DavJobBase
+ DavCollection
+ DavCollectionDeleteJob
+ DavCollectionsFetchJob
+ DavCollectionModifyJob
+ DavCollectionsMultiFetchJob
+ DavError
+ DavItem
+ DavItemCreateJob
+ DavItemDeleteJob
+ DavItemFetchJob
+ DavItemModifyJob
+ DavItemsFetchJob
+ DavItemsListJob
+ DavPrincipalHomesetsFetchJob
+ DavPrincipalSearchJob
+ DavUrl
+ Enums
+ EtagCache
+ ProtocolInfo
+ REQUIRED_HEADERS KDAV_HEADERS
+ PREFIX KDAV
+ RELATIVE common
+ )
+
+install(FILES
+ ${KDAV_Camelcase_HEADERS}
+ DESTINATION ${KDAV_INSTALL_INCLUDEDIR}/KDAV # for C++ namespace KDAV
+ COMPONENT Devel
+ )
+
+install(FILES
+ ${KDAV_HEADERS}
+ ${CMAKE_CURRENT_BINARY_DIR}/kdav_export.h
+
+ DESTINATION ${KDAV_INSTALL_INCLUDEDIR}/kdav # for C++ namespace KDAV
+ COMPONENT Devel
+ )
+
+ecm_qt_declare_logging_category(KF5DAV
+ HEADER libkdav_debug.h
+ IDENTIFIER KDAV_LOG
+ CATEGORY_NAME kf.dav
+ OLD_CATEGORY_NAMES org.kde.pim.kdav
+ DESCRIPTION "KDAV"
+ EXPORT KDAV
+)
+
+generate_export_header(KF5DAV BASE_NAME kdav)
+
+target_include_directories(KF5DAV PRIVATE
+ common
+ protocols
+)
+
+target_link_libraries(KF5DAV
+PUBLIC
+ KF5::CoreAddons
+PRIVATE
+ Qt${QT_MAJOR_VERSION}::Xml
+ Qt${QT_MAJOR_VERSION}::Gui
+ KF5::KIOCore
+ KF5::I18n
+ )
+
+
+install(TARGETS
+ KF5DAV
+ EXPORT KF5DAVTargets
+ ${KF_INSTALL_TARGETS_DEFAULT_ARGS}
+ )
+
+ecm_generate_pri_file(BASE_NAME KDAV
+ LIB_NAME KF5DAV
+ DEPS "KCoreAddons"
+ FILENAME_VAR PRI_FILENAME INCLUDE_INSTALL_DIR ${KDAV_INSTALL_INCLUDEDIR}
+ )
+
+install(FILES
+ ${PRI_FILENAME}
+ DESTINATION ${ECM_MKSPECS_INSTALL_DIR}
+ )
+
+target_include_directories(KF5DAV INTERFACE "$<INSTALL_INTERFACE:${KDAV_INSTALL_INCLUDEDIR}>")
+
+ecm_qt_install_logging_categories(EXPORT KDAV FILE kdav.categories DESTINATION ${KDE_INSTALL_LOGGINGCATEGORIESDIR})
+
+if (BUILD_QCH)
+ ecm_add_qch(
+ KF5DAV_QCH
+ NAME KDAV
+ BASE_NAME KF5DAV
+ VERSION ${KF_VERSION}
+ ORG_DOMAIN org.kde
+ SOURCES # using only public headers, to cover only public API
+ ${KDAV_HEADERS}
+ MD_MAINPAGE "${CMAKE_SOURCE_DIR}/README.md"
+ LINK_QCHS
+ Qt5Gui_QCH
+ KF5CoreAddons_QCH
+ INCLUDE_DIRS
+ ${CMAKE_CURRENT_BINARY_DIR}
+ BLANK_MACROS
+ KDAV_EXPORT
+ KDAV_DEPRECATED_EXPORT
+ KDAV_DEPRECATED
+ "KDAV_DEPRECATED_VERSION(x, y, t)"
+ TAGFILE_INSTALL_DESTINATION ${KDE_INSTALL_QTQCHDIR}
+ QCH_INSTALL_DESTINATION ${KDE_INSTALL_QTQCHDIR}
+ COMPONENT Devel
+ )
+endif()
--- /dev/null
+#! /bin/sh
+$XGETTEXT `find . -name "*.cpp" -o -name "*.h" | grep -v '/tests/'` -o $podir/libkdav.pot
--- /dev/null
+/*
+ SPDX-FileCopyrightText: 2009 Grégory Oestreicher <greg@kamago.net>
+
+ SPDX-License-Identifier: LGPL-2.0-or-later
+*/
+
+#include "davcollection.h"
+
+#include "davurl.h"
+
+#include <QColor>
+
+using namespace KDAV;
+
+class DavCollectionPrivate : public QSharedData
+{
+public:
+ DavCollection::ContentTypes mContentTypes;
+ QString mCTag;
+ DavUrl mUrl;
+ QString mDisplayName;
+ QColor mColor;
+ Privileges mPrivileges;
+};
+
+DavCollection::DavCollection()
+ : d(new DavCollectionPrivate)
+{
+}
+
+DavCollection::DavCollection(const DavUrl &url, const QString &displayName, ContentTypes contentTypes)
+ : d(new DavCollectionPrivate)
+{
+ d->mUrl = url;
+ d->mDisplayName = displayName;
+ d->mContentTypes = contentTypes;
+ d->mPrivileges = KDAV::All;
+}
+
+DavCollection::DavCollection(const DavCollection &other) = default;
+DavCollection::DavCollection(DavCollection &&) = default;
+DavCollection &DavCollection::operator=(const DavCollection &other) = default;
+DavCollection &DavCollection::operator=(DavCollection &&) = default;
+DavCollection::~DavCollection() = default;
+
+void DavCollection::setCTag(const QString &ctag)
+{
+ d->mCTag = ctag;
+}
+
+QString DavCollection::CTag() const
+{
+ return d->mCTag;
+}
+
+void DavCollection::setUrl(const DavUrl &url)
+{
+ d->mUrl = url;
+}
+
+DavUrl DavCollection::url() const
+{
+ return d->mUrl;
+}
+
+void DavCollection::setDisplayName(const QString &displayName)
+{
+ d->mDisplayName = displayName;
+}
+
+QString DavCollection::displayName() const
+{
+ return d->mDisplayName;
+}
+
+void DavCollection::setColor(const QColor &color)
+{
+ d->mColor = color;
+}
+
+QColor DavCollection::color() const
+{
+ return d->mColor;
+}
+
+void DavCollection::setContentTypes(ContentTypes contentTypes)
+{
+ d->mContentTypes = contentTypes;
+}
+
+DavCollection::ContentTypes DavCollection::contentTypes() const
+{
+ return d->mContentTypes;
+}
+
+void DavCollection::setPrivileges(Privileges privs)
+{
+ d->mPrivileges = privs;
+}
+
+Privileges DavCollection::privileges() const
+{
+ return d->mPrivileges;
+}
--- /dev/null
+/*
+ SPDX-FileCopyrightText: 2009 Grégory Oestreicher <greg@kamago.net>
+
+ SPDX-License-Identifier: LGPL-2.0-or-later
+*/
+
+#ifndef KDAV_DAVCOLLECTION_H
+#define KDAV_DAVCOLLECTION_H
+
+#include "kdav_export.h"
+
+#include "enums.h"
+
+#include <QSharedDataPointer>
+#include <QString>
+#include <QVector>
+
+class QColor;
+
+class DavCollectionPrivate;
+
+namespace KDAV
+{
+class DavUrl;
+}
+
+namespace KDAV
+{
+/**
+ * @class DavCollection davcollection.h <KDAV/DavCollection>
+ *
+ * @short A helper class to store information about DAV collection.
+ *
+ * This class is used as container to transfer information about DAV
+ * collections between the Akonadi resource and the DAV jobs.
+ */
+class KDAV_EXPORT DavCollection
+{
+public:
+ /**
+ * Defines a list of DAV collection objects.
+ */
+ typedef QVector<DavCollection> List;
+
+ /**
+ * Describes the possible content type of the DAV collection.
+ */
+ enum ContentType {
+ Events = 1, ///< The collection can contain event DAV resources.
+ Todos = 2, ///< The collection can contain todo DAV resources.
+ Contacts = 4, ///< The collection can contain contact DAV resources.
+ FreeBusy = 8, ///< The collection can contain free/busy information.
+ Journal = 16, ///< The collection can contain journal DAV resources.
+ Calendar = 32, ///< The collection can contain anything calendar-related.
+ };
+ Q_DECLARE_FLAGS(ContentTypes, ContentType)
+
+ /**
+ * Creates an empty DAV collection.
+ */
+ DavCollection();
+
+ /**
+ * Creates a new DAV collection.
+ *
+ * @param url The URL that identifies the collection.
+ * @param displayName The display name of the collection.
+ * @param contentTypes The possible content types of the collection.
+ */
+ DavCollection(const DavUrl &url, const QString &displayName, ContentTypes contentTypes);
+
+ DavCollection(const DavCollection &other);
+ DavCollection(DavCollection &&);
+ DavCollection &operator=(const DavCollection &other);
+ DavCollection &operator=(DavCollection &&);
+
+ ~DavCollection();
+
+ /**
+ * Sets this collection CTag.
+ * @see https://github.com/apple/ccs-calendarserver/blob/master/doc/Extensions/caldav-ctag.txt
+ */
+ void setCTag(const QString &ctag);
+
+ /**
+ * Returns this collection CTag. The returned value will be empty
+ * if no CTag was found.
+ * @see https://github.com/apple/ccs-calendarserver/blob/master/doc/Extensions/caldav-ctag.txt
+ */
+ Q_REQUIRED_RESULT QString CTag() const;
+
+ /**
+ * Sets the @p url that identifies the collection.
+ */
+ void setUrl(const DavUrl &url);
+
+ /**
+ * Returns the URL that identifies the collection.
+ */
+ Q_REQUIRED_RESULT DavUrl url() const;
+
+ /**
+ * Sets the display @p name of the collection.
+ */
+ void setDisplayName(const QString &name);
+
+ /**
+ * Returns the display name of the collection.
+ */
+ Q_REQUIRED_RESULT QString displayName() const;
+
+ /**
+ * Sets the color for this collection
+ */
+ void setColor(const QColor &color);
+
+ /**
+ * Return the color of the collection, or an empty string if
+ * none was provided by the backend.
+ */
+ Q_REQUIRED_RESULT QColor color() const;
+
+ /**
+ * Sets the possible content @p types of the collection.
+ */
+ void setContentTypes(ContentTypes types);
+
+ /**
+ * Returns the possible content types of the collection.
+ */
+ Q_REQUIRED_RESULT ContentTypes contentTypes() const;
+
+ /**
+ * Sets the privileges on this collection.
+ */
+ void setPrivileges(Privileges privs);
+
+ /**
+ * Returns the privileges on this collection.
+ */
+ Q_REQUIRED_RESULT Privileges privileges() const;
+
+private:
+ QSharedDataPointer<DavCollectionPrivate> d;
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(DavCollection::ContentTypes)
+
+}
+
+Q_DECLARE_TYPEINFO(KDAV::DavCollection, Q_MOVABLE_TYPE);
+
+#endif
--- /dev/null
+/*
+ SPDX-FileCopyrightText: 2010 Grégory Oestreicher <greg@kamago.net>
+
+ SPDX-License-Identifier: LGPL-2.0-or-later
+*/
+
+#include "davcollectiondeletejob.h"
+#include "davjobbase_p.h"
+
+#include "daverror.h"
+
+#include <KIO/DeleteJob>
+#include <KIO/Job>
+
+using namespace KDAV;
+
+namespace KDAV
+{
+class DavCollectionDeleteJobPrivate : public DavJobBasePrivate
+{
+public:
+ void davJobFinished(KJob *job);
+
+ DavUrl mUrl;
+};
+}
+
+DavCollectionDeleteJob::DavCollectionDeleteJob(const DavUrl &url, QObject *parent)
+ : DavJobBase(new DavCollectionDeleteJobPrivate, parent)
+{
+ Q_D(DavCollectionDeleteJob);
+ d->mUrl = url;
+}
+
+void DavCollectionDeleteJob::start()
+{
+ Q_D(DavCollectionDeleteJob);
+ KIO::DeleteJob *job = KIO::del(d->mUrl.url(), KIO::HideProgressInfo | KIO::DefaultFlags);
+ job->addMetaData(QStringLiteral("PropagateHttpHeader"), QStringLiteral("true"));
+ job->addMetaData(QStringLiteral("cookies"), QStringLiteral("none"));
+ job->addMetaData(QStringLiteral("no-auth-prompt"), QStringLiteral("true"));
+
+ connect(job, &KIO::DeleteJob::result, this, [d](KJob *job) {
+ d->davJobFinished(job);
+ });
+}
+
+void DavCollectionDeleteJobPrivate::davJobFinished(KJob *job)
+{
+ KIO::DeleteJob *deleteJob = qobject_cast<KIO::DeleteJob *>(job);
+
+ if (deleteJob->error() && deleteJob->error() != KIO::ERR_NO_CONTENT) {
+ const int responseCode = deleteJob->queryMetaData(QStringLiteral("responsecode")).isEmpty() //
+ ? 0
+ : deleteJob->queryMetaData(QStringLiteral("responsecode")).toInt();
+
+ setLatestResponseCode(responseCode);
+ setError(ERR_COLLECTIONDELETE);
+ setJobErrorText(deleteJob->errorText());
+ setJobError(deleteJob->error());
+ setErrorTextFromDavError();
+ }
+
+ emitResult();
+}
--- /dev/null
+/*
+ SPDX-FileCopyrightText: 2010 Grégory Oestreicher <greg@kamago.net>
+
+ SPDX-License-Identifier: LGPL-2.0-or-later
+*/
+
+#ifndef KDAV_DAVCOLLECTIONDELETEJOB_H
+#define KDAV_DAVCOLLECTIONDELETEJOB_H
+
+#include "kdav_export.h"
+
+#include "davjobbase.h"
+#include "davurl.h"
+
+namespace KDAV
+{
+class DavCollectionDeleteJobPrivate;
+
+/**
+ * @class DavCollectionDeleteJob davcollectiondeletejob.h <KDAV/DavCollectionDeleteJob>
+ *
+ * @short A job that deletes a DAV collection.
+ *
+ * This job is used to delete a DAV collection at a certain URL.
+ */
+class KDAV_EXPORT DavCollectionDeleteJob : public DavJobBase
+{
+ Q_OBJECT
+
+public:
+ /**
+ * Creates a new DAV collection delete job.
+ *
+ * @param url The DAV URL of the collection to delete
+ * @param parent The parent object.
+ */
+ explicit DavCollectionDeleteJob(const DavUrl &url, QObject *parent = nullptr);
+
+ /**
+ * Starts the job.
+ */
+ void start() override;
+
+private:
+ Q_DECLARE_PRIVATE(DavCollectionDeleteJob)
+};
+}
+
+#endif
--- /dev/null
+/*
+ SPDX-FileCopyrightText: 2010 Grégory Oestreicher <greg@kamago.net>
+
+ SPDX-License-Identifier: LGPL-2.0-or-later
+*/
+
+#include "davcollectionmodifyjob.h"
+#include "davjobbase_p.h"
+#include "davmanager_p.h"
+
+#include "daverror.h"
+#include "utils_p.h"
+
+#include <KIO/DavJob>
+#include <KIO/Job>
+
+using namespace KDAV;
+
+namespace KDAV
+{
+class DavCollectionModifyJobPrivate : public DavJobBasePrivate
+{
+public:
+ void davJobFinished(KJob *job);
+
+ DavUrl mUrl;
+ QDomDocument mQuery;
+
+ QVector<QDomElement> mSetProperties;
+ QVector<QDomElement> mRemoveProperties;
+};
+}
+
+DavCollectionModifyJob::DavCollectionModifyJob(const DavUrl &url, QObject *parent)
+ : DavJobBase(new DavCollectionModifyJobPrivate, parent)
+{
+ Q_D(DavCollectionModifyJob);
+ d->mUrl = url;
+}
+
+void DavCollectionModifyJob::setProperty(const QString &prop, const QString &value, const QString &ns)
+{
+ Q_D(DavCollectionModifyJob);
+ QDomElement propElement;
+
+ if (ns.isEmpty()) {
+ propElement = d->mQuery.createElement(prop);
+ } else {
+ propElement = d->mQuery.createElementNS(ns, prop);
+ }
+
+ const QDomText textElement = d->mQuery.createTextNode(value);
+ propElement.appendChild(textElement);
+
+ d->mSetProperties << propElement;
+}
+
+void DavCollectionModifyJob::removeProperty(const QString &prop, const QString &ns)
+{
+ Q_D(DavCollectionModifyJob);
+ QDomElement propElement;
+
+ if (ns.isEmpty()) {
+ propElement = d->mQuery.createElement(prop);
+ } else {
+ propElement = d->mQuery.createElementNS(ns, prop);
+ }
+
+ d->mRemoveProperties << propElement;
+}
+
+void DavCollectionModifyJob::start()
+{
+ Q_D(DavCollectionModifyJob);
+ if (d->mSetProperties.isEmpty() && d->mRemoveProperties.isEmpty()) {
+ setError(ERR_COLLECTIONMODIFY_NO_PROPERITES);
+ d->setErrorTextFromDavError();
+ emitResult();
+ return;
+ }
+
+ QDomDocument mQuery;
+ QDomElement propertyUpdateElement = mQuery.createElementNS(QStringLiteral("DAV:"), QStringLiteral("propertyupdate"));
+ mQuery.appendChild(propertyUpdateElement);
+
+ if (!d->mSetProperties.isEmpty()) {
+ QDomElement setElement = mQuery.createElementNS(QStringLiteral("DAV:"), QStringLiteral("set"));
+ propertyUpdateElement.appendChild(setElement);
+
+ QDomElement propElement = mQuery.createElementNS(QStringLiteral("DAV:"), QStringLiteral("prop"));
+ setElement.appendChild(propElement);
+
+ for (const QDomElement &element : std::as_const(d->mSetProperties)) {
+ propElement.appendChild(element);
+ }
+ }
+
+ if (!d->mRemoveProperties.isEmpty()) {
+ QDomElement removeElement = mQuery.createElementNS(QStringLiteral("DAV:"), QStringLiteral("remove"));
+ propertyUpdateElement.appendChild(removeElement);
+
+ QDomElement propElement = mQuery.createElementNS(QStringLiteral("DAV:"), QStringLiteral("prop"));
+ removeElement.appendChild(propElement);
+
+ for (const QDomElement &element : std::as_const(d->mSetProperties)) {
+ propElement.appendChild(element);
+ }
+ }
+
+ KIO::DavJob *job = DavManager::self()->createPropPatchJob(d->mUrl.url(), mQuery.toString());
+ job->addMetaData(QStringLiteral("PropagateHttpHeader"), QStringLiteral("true"));
+ connect(job, &KIO::DavJob::result, this, [d](KJob *job) {
+ d->davJobFinished(job);
+ });
+}
+
+void DavCollectionModifyJobPrivate::davJobFinished(KJob *job)
+{
+ KIO::DavJob *davJob = qobject_cast<KIO::DavJob *>(job);
+ const QString responseCodeStr = davJob->queryMetaData(QStringLiteral("responsecode"));
+ const int responseCode = responseCodeStr.isEmpty() ? 0 : responseCodeStr.toInt();
+
+ // KIO::DavJob does not set error() even if the HTTP status code is a 4xx or a 5xx
+ if (davJob->error() || (responseCode >= 400 && responseCode < 600)) {
+ setLatestResponseCode(responseCode);
+ setError(ERR_COLLECTIONMODIFY);
+ setJobErrorText(davJob->errorText());
+ setJobError(davJob->error());
+ setErrorTextFromDavError();
+ emitResult();
+ return;
+ }
+
+ QDomDocument response;
+ response.setContent(davJob->responseData(), true);
+ QDomElement responseElement = Utils::firstChildElementNS(response.documentElement(), QStringLiteral("DAV:"), QStringLiteral("response"));
+
+ bool hasError = false;
+
+ // parse all propstats answers to get the eventual errors
+ const QDomNodeList propstats = responseElement.elementsByTagNameNS(QStringLiteral("DAV:"), QStringLiteral("propstat"));
+ for (int i = 0; i < propstats.length(); ++i) {
+ const QDomElement propstatElement = propstats.item(i).toElement();
+ const QDomElement statusElement = Utils::firstChildElementNS(propstatElement, QStringLiteral("DAV:"), QStringLiteral("status"));
+
+ const QString statusText = statusElement.text();
+ if (statusText.contains(QLatin1String("200"))) {
+ continue;
+ } else {
+ // Generic error
+ hasError = true;
+ break;
+ }
+ }
+
+ if (hasError) {
+ setError(ERR_COLLECTIONMODIFY_RESPONSE);
+
+ // Trying to get more information about the error
+ const QDomElement responseDescriptionElement =
+ Utils::firstChildElementNS(responseElement, QStringLiteral("DAV:"), QStringLiteral("responsedescription"));
+ if (!responseDescriptionElement.isNull()) {
+ setJobErrorText(responseDescriptionElement.text());
+ }
+ setErrorTextFromDavError();
+ }
+
+ emitResult();
+}
--- /dev/null
+/*
+ SPDX-FileCopyrightText: 2010 Grégory Oestreicher <greg@kamago.net>
+
+ SPDX-License-Identifier: LGPL-2.0-or-later
+*/
+
+#ifndef KDAV_DAVCOLLECTIONMODIFYJOB_H
+#define KDAV_DAVCOLLECTIONMODIFYJOB_H
+
+#include "kdav_export.h"
+
+#include "davjobbase.h"
+#include "davurl.h"
+
+namespace KDAV
+{
+class DavCollectionModifyJobPrivate;
+
+/**
+ * @class DavCollectionModifyJob davcollectionmodifyjob.h <KDAV/DavCollectionModifyJob>
+ *
+ * @short A job that modifies a DAV collection.
+ *
+ * This job is used to modify a property of a DAV collection
+ * on the DAV server.
+ */
+class KDAV_EXPORT DavCollectionModifyJob : public DavJobBase
+{
+ Q_OBJECT
+
+public:
+ /**
+ * Creates a new DAV collection modify job.
+ *
+ * @param url The DAV URL that identifies the collection.
+ * @param parent The parent object.
+ */
+ explicit DavCollectionModifyJob(const DavUrl &url, QObject *parent = nullptr);
+
+ /**
+ * Sets the property that shall be modified by the job.
+ *
+ * @param property The name of the property.
+ * @param value The value of the property.
+ * @param ns The XML namespace that shall be used for the property name.
+ */
+ void setProperty(const QString &property, const QString &value, const QString &ns = QString());
+
+ /**
+ * Sets the property that shall be removed by the job.
+ *
+ * @param property The name of the property.
+ * @param ns The XML namespace that shall be used for the property name.
+ */
+ void removeProperty(const QString &property, const QString &ns);
+
+ /**
+ * Starts the job.
+ */
+ void start() override;
+
+private:
+ Q_DECLARE_PRIVATE(DavCollectionModifyJob)
+};
+}
+
+#endif
--- /dev/null
+/*
+ SPDX-FileCopyrightText: 2010 Tobias Koenig <tokoe@kde.org>
+
+ SPDX-License-Identifier: LGPL-2.0-or-later
+*/
+
+#include "davcollectionsfetchjob.h"
+#include "davjobbase_p.h"
+
+#include "daverror.h"
+#include "davmanager_p.h"
+#include "davprincipalhomesetsfetchjob.h"
+#include "davprotocolbase_p.h"
+#include "utils_p.h"
+
+#include "libkdav_debug.h"
+#include <KIO/DavJob>
+#include <KIO/Job>
+
+#include <QBuffer>
+#include <QColor>
+
+using namespace KDAV;
+
+namespace KDAV
+{
+class DavCollectionsFetchJobPrivate : public DavJobBasePrivate
+{
+public:
+ void principalFetchFinished(KJob *job);
+ void collectionsFetchFinished(KJob *job);
+ void doCollectionsFetch(const QUrl &url);
+ void subjobFinished();
+
+ DavUrl mUrl;
+ DavCollection::List mCollections;
+ uint mSubJobCount = 0;
+
+ Q_DECLARE_PUBLIC(DavCollectionsFetchJob)
+};
+}
+
+DavCollectionsFetchJob::DavCollectionsFetchJob(const DavUrl &url, QObject *parent)
+ : DavJobBase(new DavCollectionsFetchJobPrivate, parent)
+{
+ Q_D(DavCollectionsFetchJob);
+ d->mUrl = url;
+}
+
+void DavCollectionsFetchJob::start()
+{
+ Q_D(DavCollectionsFetchJob);
+ if (DavManager::davProtocol(d->mUrl.protocol())->supportsPrincipals()) {
+ DavPrincipalHomeSetsFetchJob *job = new DavPrincipalHomeSetsFetchJob(d->mUrl);
+ connect(job, &DavPrincipalHomeSetsFetchJob::result, this, [d](KJob *job) {
+ d->principalFetchFinished(job);
+ });
+ job->start();
+ } else {
+ d->doCollectionsFetch(d->mUrl.url());
+ }
+}
+
+DavCollection::List DavCollectionsFetchJob::collections() const
+{
+ Q_D(const DavCollectionsFetchJob);
+ return d->mCollections;
+}
+
+DavUrl DavCollectionsFetchJob::davUrl() const
+{
+ Q_D(const DavCollectionsFetchJob);
+ return d->mUrl;
+}
+
+void DavCollectionsFetchJobPrivate::doCollectionsFetch(const QUrl &url)
+{
+ ++mSubJobCount;
+
+ const QDomDocument collectionQuery = DavManager::davProtocol(mUrl.protocol())->collectionsQuery()->buildQuery();
+
+ KIO::DavJob *job = DavManager::self()->createPropFindJob(url, collectionQuery.toString());
+ QObject::connect(job, &KIO::DavJob::result, q_ptr, [this](KJob *job) {
+ collectionsFetchFinished(job);
+ });
+ job->addMetaData(QStringLiteral("PropagateHttpHeader"), QStringLiteral("true"));
+}
+
+void DavCollectionsFetchJobPrivate::principalFetchFinished(KJob *job)
+{
+ const DavPrincipalHomeSetsFetchJob *davJob = qobject_cast<DavPrincipalHomeSetsFetchJob *>(job);
+
+ if (davJob->error()) {
+ if (davJob->latestResponseCode()) {
+ // If we have a HTTP response code then this may mean that
+ // the URL was not a principal URL. Retry as if it were a calendar URL.
+ qCDebug(KDAV_LOG) << job->errorText();
+ doCollectionsFetch(mUrl.url());
+ } else {
+ // Just give up here.
+ setDavError(davJob->davError());
+ setErrorTextFromDavError();
+ emitResult();
+ }
+
+ return;
+ }
+
+ const QStringList homeSets = davJob->homeSets();
+ qCDebug(KDAV_LOG) << "Found" << homeSets.size() << "homesets";
+ qCDebug(KDAV_LOG) << homeSets;
+
+ if (homeSets.isEmpty()) {
+ // Same as above, retry as if it were a calendar URL.
+ doCollectionsFetch(mUrl.url());
+ return;
+ }
+
+ for (const QString &homeSet : homeSets) {
+ QUrl url = mUrl.url();
+
+ if (homeSet.startsWith(QLatin1Char('/'))) {
+ // homeSet is only a path, use request url to complete
+ url.setPath(homeSet, QUrl::TolerantMode);
+ } else {
+ // homeSet is a complete url
+ QUrl tmpUrl(homeSet);
+ tmpUrl.setUserName(url.userName());
+ tmpUrl.setPassword(url.password());
+ url = tmpUrl;
+ }
+
+ doCollectionsFetch(url);
+ }
+}
+
+void DavCollectionsFetchJobPrivate::collectionsFetchFinished(KJob *job)
+{
+ Q_Q(DavCollectionsFetchJob);
+ KIO::DavJob *davJob = qobject_cast<KIO::DavJob *>(job);
+ const QString responseCodeStr = davJob->queryMetaData(QStringLiteral("responsecode"));
+ const int responseCode = responseCodeStr.isEmpty() ? 0 : responseCodeStr.toInt();
+
+ // KIO::DavJob does not set error() even if the HTTP status code is a 4xx or a 5xx
+ if (davJob->error() || (responseCode >= 400 && responseCode < 600)) {
+ if (davJob->url() != mUrl.url()) {
+ // Retry as if the initial URL was a calendar URL.
+ // We can end up here when retrieving a homeset on
+ // which a PROPFIND resulted in an error
+ doCollectionsFetch(mUrl.url());
+ --mSubJobCount;
+ return;
+ }
+
+ setLatestResponseCode(responseCode);
+ setError(ERR_PROBLEM_WITH_REQUEST);
+ setJobErrorText(davJob->errorText());
+ setJobError(davJob->error());
+ setErrorTextFromDavError();
+ } else {
+ // For use in the collectionDiscovered() signal
+ QUrl _jobUrl = mUrl.url();
+ _jobUrl.setUserInfo(QString());
+ const QString jobUrl = _jobUrl.toDisplayString();
+
+ // Validate that we got a valid PROPFIND response
+ QDomDocument response;
+ response.setContent(davJob->responseData(), true);
+ QDomElement rootElement = response.documentElement();
+ if (rootElement.tagName().compare(QLatin1String("multistatus"), Qt::CaseInsensitive) != 0) {
+ setError(ERR_COLLECTIONFETCH);
+ setErrorTextFromDavError();
+ subjobFinished();
+ return;
+ }
+
+ QByteArray resp = davJob->responseData();
+ QDomDocument document;
+ if (!document.setContent(resp, true)) {
+ setError(ERR_COLLECTIONFETCH);
+ setErrorTextFromDavError();
+ subjobFinished();
+ return;
+ }
+
+ if (!q->error()) {
+ /*
+ * Extract information from a document like the following:
+ *
+ * <responses>
+ * <response xmlns="DAV:">
+ * <href xmlns="DAV:">/caldav.php/test1.user/home/</href>
+ * <propstat xmlns="DAV:">
+ * <prop xmlns="DAV:">
+ * <C:supported-calendar-component-set xmlns:C="urn:ietf:params:xml:ns:caldav">
+ * <C:comp xmlns:C="urn:ietf:params:xml:ns:caldav" name="VEVENT"/>
+ * <C:comp xmlns:C="urn:ietf:params:xml:ns:caldav" name="VTODO"/>
+ * <C:comp xmlns:C="urn:ietf:params:xml:ns:caldav" name="VJOURNAL"/>
+ * <C:comp xmlns:C="urn:ietf:params:xml:ns:caldav" name="VTIMEZONE"/>
+ * <C:comp xmlns:C="urn:ietf:params:xml:ns:caldav" name="VFREEBUSY"/>
+ * </C:supported-calendar-component-set>
+ * <resourcetype xmlns="DAV:">
+ * <collection xmlns="DAV:"/>
+ * <C:calendar xmlns:C="urn:ietf:params:xml:ns:caldav"/>
+ * <C:schedule-calendar xmlns:C="urn:ietf:params:xml:ns:caldav"/>
+ * </resourcetype>
+ * <displayname xmlns="DAV:">Test1 User</displayname>
+ * <current-user-privilege-set xmlns="DAV:">
+ * <privilege xmlns="DAV:">
+ * <read xmlns="DAV:"/>
+ * </privilege>
+ * </current-user-privilege-set>
+ * <getctag xmlns="http://calendarserver.org/ns/">12345</getctag>
+ * </prop>
+ * <status xmlns="DAV:">HTTP/1.1 200 OK</status>
+ * </propstat>
+ * </response>
+ * </responses>
+ */
+
+ const QDomElement responsesElement = document.documentElement();
+
+ QDomElement responseElement = Utils::firstChildElementNS(responsesElement, QStringLiteral("DAV:"), QStringLiteral("response"));
+ while (!responseElement.isNull()) {
+ QDomElement propstatElement;
+
+ // check for the valid propstat, without giving up on first error
+ {
+ const QDomNodeList propstats = responseElement.elementsByTagNameNS(QStringLiteral("DAV:"), QStringLiteral("propstat"));
+ for (int i = 0; i < propstats.length(); ++i) {
+ const QDomElement propstatCandidate = propstats.item(i).toElement();
+ const QDomElement statusElement = Utils::firstChildElementNS(propstatCandidate, QStringLiteral("DAV:"), QStringLiteral("status"));
+ if (statusElement.text().contains(QLatin1String("200"))) {
+ propstatElement = propstatCandidate;
+ }
+ }
+ }
+
+ if (propstatElement.isNull()) {
+ responseElement = Utils::nextSiblingElementNS(responseElement, QStringLiteral("DAV:"), QStringLiteral("response"));
+ continue;
+ }
+
+ // extract url
+ const QDomElement hrefElement = Utils::firstChildElementNS(responseElement, QStringLiteral("DAV:"), QStringLiteral("href"));
+ if (hrefElement.isNull()) {
+ responseElement = Utils::nextSiblingElementNS(responseElement, QStringLiteral("DAV:"), QStringLiteral("response"));
+ continue;
+ }
+
+ QString href = hrefElement.text();
+ if (!href.endsWith(QLatin1Char('/'))) {
+ href.append(QLatin1Char('/'));
+ }
+
+ QUrl url = davJob->url();
+ url.setUserInfo(QString());
+ if (href.startsWith(QLatin1Char('/'))) {
+ // href is only a path, use request url to complete
+ url.setPath(href, QUrl::TolerantMode);
+ } else {
+ // href is a complete url
+ url = QUrl::fromUserInput(href);
+ }
+
+ // don't add this resource if it has already been detected
+ bool alreadySeen = false;
+ for (const DavCollection &seen : std::as_const(mCollections)) {
+ if (seen.url().toDisplayString() == url.toDisplayString()) {
+ alreadySeen = true;
+ }
+ }
+ if (alreadySeen) {
+ responseElement = Utils::nextSiblingElementNS(responseElement, QStringLiteral("DAV:"), QStringLiteral("response"));
+ continue;
+ }
+
+ // extract display name
+ const QDomElement propElement = Utils::firstChildElementNS(propstatElement, QStringLiteral("DAV:"), QStringLiteral("prop"));
+ if (!DavManager::davProtocol(mUrl.protocol())->containsCollection(propElement)) {
+ responseElement = Utils::nextSiblingElementNS(responseElement, QStringLiteral("DAV:"), QStringLiteral("response"));
+ continue;
+ }
+ const QDomElement displaynameElement = Utils::firstChildElementNS(propElement, QStringLiteral("DAV:"), QStringLiteral("displayname"));
+ const QString displayName = displaynameElement.text();
+
+ // Extract CTag
+ const QDomElement CTagElement = Utils::firstChildElementNS(propElement, //
+ QStringLiteral("http://calendarserver.org/ns/"),
+ QStringLiteral("getctag"));
+ QString CTag;
+ if (!CTagElement.isNull()) {
+ CTag = CTagElement.text();
+ }
+
+ // extract calendar color if provided
+ const QDomElement colorElement = Utils::firstChildElementNS(propElement, //
+ QStringLiteral("http://apple.com/ns/ical/"),
+ QStringLiteral("calendar-color"));
+ QColor color;
+ if (!colorElement.isNull()) {
+ QString colorValue = colorElement.text();
+ if (QColor::isValidColor(colorValue)) {
+ // Color is either #RRGGBBAA or #RRGGBB but QColor expects #AARRGGBB
+ // so we put the AA in front if the string's length is 9.
+ if (colorValue.size() == 9) {
+ QString fixedColorValue = QStringLiteral("#") + colorValue.mid(7, 2) + colorValue.mid(1, 6);
+ color.setNamedColor(fixedColorValue);
+ } else {
+ color.setNamedColor(colorValue);
+ }
+ }
+ }
+
+ // extract allowed content types
+ const DavCollection::ContentTypes contentTypes = DavManager::davProtocol(mUrl.protocol())->collectionContentTypes(propstatElement);
+
+ auto _url = url;
+ _url.setUserInfo(mUrl.url().userInfo());
+ DavCollection collection(DavUrl(_url, mUrl.protocol()), displayName, contentTypes);
+
+ collection.setCTag(CTag);
+ if (color.isValid()) {
+ collection.setColor(color);
+ }
+
+ // extract privileges
+ const QDomElement currentPrivsElement = Utils::firstChildElementNS(propElement, //
+ QStringLiteral("DAV:"),
+ QStringLiteral("current-user-privilege-set"));
+ if (currentPrivsElement.isNull()) {
+ // Assume that we have all privileges
+ collection.setPrivileges(KDAV::All);
+ } else {
+ Privileges privileges = Utils::extractPrivileges(currentPrivsElement);
+ collection.setPrivileges(privileges);
+ }
+
+ qCDebug(KDAV_LOG) << url.toDisplayString() << "PRIVS: " << collection.privileges();
+ mCollections << collection;
+ Q_EMIT q->collectionDiscovered(mUrl.protocol(), url.toDisplayString(), jobUrl);
+
+ responseElement = Utils::nextSiblingElementNS(responseElement, QStringLiteral("DAV:"), QStringLiteral("response"));
+ }
+ }
+ }
+
+ subjobFinished();
+}
+
+void DavCollectionsFetchJobPrivate::subjobFinished()
+{
+ if (--mSubJobCount == 0) {
+ emitResult();
+ }
+}
--- /dev/null
+/*
+ SPDX-FileCopyrightText: 2010 Tobias Koenig <tokoe@kde.org>
+
+ SPDX-License-Identifier: LGPL-2.0-or-later
+*/
+
+#ifndef KDAV_DAVCOLLECTIONSFETCHJOB_H
+#define KDAV_DAVCOLLECTIONSFETCHJOB_H
+
+#include "kdav_export.h"
+
+#include "davcollection.h"
+#include "davjobbase.h"
+#include "davurl.h"
+
+namespace KDAV
+{
+class DavCollectionsFetchJobPrivate;
+
+/**
+ * @class DavCollectionsFetchJob davcollectionsfetchjob.h <KDAV/DavCollectionsFetchJob>
+ *
+ * @short A job that fetches all DAV collection.
+ *
+ * This job is used to fetch all DAV collection that are available
+ * under a certain DAV URL.
+ */
+class KDAV_EXPORT DavCollectionsFetchJob : public DavJobBase
+{
+ Q_OBJECT
+
+public:
+ /**
+ * Creates a new DAV collections fetch job.
+ *
+ * @param url The DAV URL of the DAV collection whose sub collections shall be fetched.
+ * @param parent The parent object.
+ */
+ explicit DavCollectionsFetchJob(const DavUrl &url, QObject *parent = nullptr);
+
+ /**
+ * Starts the job.
+ */
+ void start() override;
+
+ /**
+ * Returns the list of fetched DAV collections.
+ */
+ Q_REQUIRED_RESULT DavCollection::List collections() const;
+
+ /**
+ * Return the DavUrl used by this job
+ */
+ Q_REQUIRED_RESULT DavUrl davUrl() const;
+
+Q_SIGNALS:
+ /**
+ * This signal is emitted every time a new collection has been discovered.
+ *
+ * @param collectionUrl The URL of the discovered collection
+ * @param configuredUrl The URL given to the job
+ */
+ void collectionDiscovered(KDAV::Protocol protocol, const QString &collectionUrl, const QString &configuredUrl);
+
+private:
+ Q_DECLARE_PRIVATE(DavCollectionsFetchJob)
+};
+}
+
+#endif
--- /dev/null
+/*
+ SPDX-FileCopyrightText: 2010 Tobias Koenig <tokoe@kde.org>
+
+ SPDX-License-Identifier: LGPL-2.0-or-later
+*/
+
+#include "davcollectionsmultifetchjob.h"
+
+#include "davcollectionsfetchjob.h"
+
+using namespace KDAV;
+
+namespace KDAV
+{
+class DavCollectionsMultiFetchJobPrivate
+{
+public:
+ DavCollection::List mCollections;
+};
+}
+
+DavCollectionsMultiFetchJob::DavCollectionsMultiFetchJob(const DavUrl::List &urls, QObject *parent)
+ : KCompositeJob(parent)
+ , d(new DavCollectionsMultiFetchJobPrivate)
+{
+ for (const DavUrl &url : std::as_const(urls)) {
+ DavCollectionsFetchJob *job = new DavCollectionsFetchJob(url, this);
+ connect(job, &DavCollectionsFetchJob::collectionDiscovered, this, &DavCollectionsMultiFetchJob::collectionDiscovered);
+ addSubjob(job);
+ }
+}
+
+DavCollectionsMultiFetchJob::~DavCollectionsMultiFetchJob() = default;
+
+void DavCollectionsMultiFetchJob::start()
+{
+ if (!hasSubjobs()) {
+ emitResult();
+ } else {
+ for (KJob *job : subjobs()) {
+ job->start();
+ }
+ }
+}
+
+DavCollection::List DavCollectionsMultiFetchJob::collections() const
+{
+ return d->mCollections;
+}
+
+void DavCollectionsMultiFetchJob::slotResult(KJob *job)
+{
+ // If we use KCompositeJob::slotResult(job) we end up with behaviour that's very
+ // hard to unittest: the valid URLs might or might not get processed.
+ // Let's wait until all subjobs are done before emitting result.
+
+ if (job->error() && !error()) {
+ // Store error only if first error
+ setError(job->error());
+ setErrorText(job->errorText());
+ }
+ if (!job->error()) {
+ DavCollectionsFetchJob *fetchJob = qobject_cast<DavCollectionsFetchJob *>(job);
+ d->mCollections << fetchJob->collections();
+ }
+ removeSubjob(job);
+ if (!hasSubjobs()) {
+ emitResult();
+ }
+}
--- /dev/null
+/*
+ SPDX-FileCopyrightText: 2010 Tobias Koenig <tokoe@kde.org>
+
+ SPDX-License-Identifier: LGPL-2.0-or-later
+*/
+
+#ifndef KDAV_DAVCOLLECTIONSMULTIFETCHJOB_H
+#define KDAV_DAVCOLLECTIONSMULTIFETCHJOB_H
+
+#include "kdav_export.h"
+
+#include "davcollection.h"
+#include "davurl.h"
+
+#include <KCompositeJob>
+
+#include <memory>
+
+namespace KDAV
+{
+class DavCollectionsMultiFetchJobPrivate;
+
+/**
+ * @class DavCollectionsMultiFetchJob davcollectionsmultifetchjob.h <KDAV/DavCollectionsMultiFetchJob>
+ *
+ * @short A job that fetches all DAV collection.
+ *
+ * This job is used to fetch all DAV collection that are available
+ * under a certain list of DAV URLs.
+ *
+ * @note This class just combines multiple calls of DavCollectionsFetchJob
+ * into one job.
+ */
+class KDAV_EXPORT DavCollectionsMultiFetchJob : public KCompositeJob
+{
+ Q_OBJECT
+
+public:
+ /**
+ * Creates a new DAV collections multi fetch job.
+ *
+ * @param urls The list of DAV URLs whose sub collections shall be fetched.
+ * @param parent The parent object.
+ */
+ explicit DavCollectionsMultiFetchJob(const DavUrl::List &urls, QObject *parent = nullptr);
+ ~DavCollectionsMultiFetchJob() override;
+
+ /**
+ * Starts the job.
+ */
+ void start() override;
+
+ /**
+ * Returns the list of fetched DAV collections.
+ */
+ Q_REQUIRED_RESULT DavCollection::List collections() const;
+
+Q_SIGNALS:
+ /**
+ * This signal is emitted every time a new collection has been discovered.
+ *
+ * @param collectionUrl The URL of the discovered collection
+ * @param configuredUrl The URL given to the job
+ */
+ void collectionDiscovered(KDAV::Protocol protocol, const QString &collectionUrl, const QString &configuredUrl);
+
+private:
+ void slotResult(KJob *) override;
+
+ const std::unique_ptr<DavCollectionsMultiFetchJobPrivate> d;
+};
+}
+
+#endif
--- /dev/null
+/*
+ SPDX-FileCopyrightText: 2016 Sandro Knauß <sknauss@kde.org>
+
+ SPDX-License-Identifier: LGPL-2.0-or-later
+*/
+
+#include "daverror.h"
+#include <KLocalizedString>
+
+#include <KIO/Global>
+#include <KIO/Job>
+
+using namespace KDAV;
+
+namespace KDAV
+{
+class ErrorPrivate : public QSharedData
+{
+public:
+ ErrorNumber mErrorNumber = NO_ERR;
+ int mResponseCode = 0;
+ int mJobErrorCode = 0;
+ QString mErrorText;
+};
+}
+
+Error::Error()
+ : d(new ErrorPrivate)
+{
+}
+
+Error::Error(ErrorNumber errNo, int responseCode, const QString &errorText, int jobErrorCode)
+ : d(new ErrorPrivate)
+{
+ d->mErrorNumber = errNo;
+ d->mResponseCode = responseCode;
+ d->mErrorText = errorText;
+ d->mJobErrorCode = jobErrorCode;
+}
+
+Error::Error(const Error &) = default;
+Error::Error(Error &&) = default;
+Error::~Error() = default;
+Error &Error::operator=(const Error &) = default;
+Error &Error::operator=(Error &&) = default;
+
+ErrorNumber Error::errorNumber() const
+{
+ return d->mErrorNumber;
+}
+
+QString Error::internalErrorText() const
+{
+ return d->mErrorText;
+}
+
+int Error::jobErrorCode() const
+{
+ return d->mJobErrorCode;
+}
+
+int Error::responseCode() const
+{
+ return d->mResponseCode;
+}
+
+QString KDAV::Error::translatedJobError() const
+{
+ QString err;
+ if (d->mJobErrorCode > 0 && d->mJobErrorCode != KIO::ERR_WORKER_DEFINED) {
+ err = KIO::buildErrorString(d->mJobErrorCode, d->mErrorText);
+ } else {
+ err = d->mErrorText;
+ }
+ return err;
+}
+
+QString Error::errorText() const
+{
+ QString result;
+
+ QString err = translatedJobError();
+
+ switch (d->mErrorNumber) {
+ case ERR_PROBLEM_WITH_REQUEST:
+ // User-side error
+ if (d->mResponseCode == 401) {
+ err = i18n("Invalid username/password");
+ } else if (d->mResponseCode == 403) {
+ err = i18n("Access forbidden");
+ } else if (d->mResponseCode == 404) {
+ err = i18n("Resource not found");
+ } else {
+ err = i18n("HTTP error");
+ }
+ result = i18n("There was a problem with the request.\n%1 (%2).", err, d->mResponseCode);
+ break;
+ case ERR_NO_MULTIGET:
+ result = i18n("Protocol for the collection does not support MULTIGET");
+ break;
+ case ERR_SERVER_UNRECOVERABLE:
+ result = i18n("The server encountered an error that prevented it from completing your request: %1 (%2)", err, d->mResponseCode);
+ break;
+ case ERR_COLLECTIONDELETE:
+ result = i18n("There was a problem with the request. The collection has not been deleted from the server.\n%1 (%2).", err, d->mResponseCode);
+ break;
+ case ERR_COLLECTIONFETCH:
+ result = i18n("Invalid responses from backend");
+ break;
+ case ERR_COLLECTIONFETCH_XQUERY_SETFOCUS:
+ result = i18n("Error setting focus for XQuery");
+ break;
+ case ERR_COLLECTIONFETCH_XQUERY_INVALID:
+ result = i18n("Invalid XQuery submitted by DAV implementation");
+ break;
+ case ERR_COLLECTIONMODIFY:
+ result = i18n(
+ "There was a problem with the request. The collection has not been modified on the server.\n"
+ "%1 (%2).",
+ err,
+ d->mResponseCode);
+ break;
+ case ERR_COLLECTIONMODIFY_NO_PROPERITES:
+ result = i18n("No properties to change or remove");
+ break;
+ case ERR_COLLECTIONMODIFY_RESPONSE:
+ result = i18n("There was an error when modifying the properties");
+ if (!d->mErrorText.isEmpty()) {
+ result.append(i18n("\nThe server returned more information:\n%1", d->mErrorText));
+ }
+ break;
+ case ERR_ITEMCREATE:
+ result = i18n("There was a problem with the request. The item has not been created on the server.\n%1 (%2).", err, d->mResponseCode);
+ break;
+ case ERR_ITEMDELETE:
+ result = i18n("There was a problem with the request. The item has not been deleted from the server.\n%1 (%2).", err, d->mResponseCode);
+ break;
+ case ERR_ITEMMODIFY:
+ result = i18n("There was a problem with the request. The item was not modified on the server.\n%1 (%2).", err, d->mResponseCode);
+ break;
+ case ERR_ITEMLIST: {
+ result = i18n("There was a problem with the request.");
+ break;
+ };
+ case ERR_ITEMLIST_NOMIMETYPE:
+ result = i18n("There was a problem with the request. The requested MIME types are not supported.");
+ break;
+ case NO_ERR:
+ break;
+ }
+ return result;
+}
--- /dev/null
+/*
+ SPDX-FileCopyrightText: 2016 Sandro Knauß <sknauss@kde.org>
+
+ SPDX-License-Identifier: LGPL-2.0-or-later
+*/
+
+#ifndef KDAV_DAVERROR_H
+#define KDAV_DAVERROR_H
+
+#include "kdav_export.h"
+
+#include <KJob>
+
+#include <QSharedDataPointer>
+#include <QString>
+
+namespace KDAV
+{
+/** DAV operation error codes. */
+enum ErrorNumber {
+ NO_ERR = 0,
+ ERR_PROBLEM_WITH_REQUEST = KJob::UserDefinedError + 200, // it would be better to request KIO about uts UserDefinedError space.
+ ERR_NO_MULTIGET,
+ ERR_SERVER_UNRECOVERABLE,
+ ERR_COLLECTIONDELETE = ERR_PROBLEM_WITH_REQUEST + 10,
+ ERR_COLLECTIONFETCH = ERR_PROBLEM_WITH_REQUEST + 20,
+ ERR_COLLECTIONFETCH_XQUERY_SETFOCUS,
+ ERR_COLLECTIONFETCH_XQUERY_INVALID,
+ ERR_COLLECTIONMODIFY = ERR_PROBLEM_WITH_REQUEST + 30,
+ ERR_COLLECTIONMODIFY_NO_PROPERITES,
+ ERR_COLLECTIONMODIFY_RESPONSE,
+ ERR_ITEMCREATE = ERR_PROBLEM_WITH_REQUEST + 100,
+ ERR_ITEMDELETE = ERR_PROBLEM_WITH_REQUEST + 110,
+ ERR_ITEMMODIFY = ERR_PROBLEM_WITH_REQUEST + 120,
+ ERR_ITEMLIST = ERR_PROBLEM_WITH_REQUEST + 130,
+ ERR_ITEMLIST_NOMIMETYPE,
+};
+
+class ErrorPrivate;
+
+/**
+ * @class Error daverror.h <KDAV/DavError>
+ *
+ * DAV operation error.
+ */
+class KDAV_EXPORT Error
+{
+public:
+ explicit Error();
+ explicit Error(ErrorNumber errNo, int responseCode, const QString &errorText, int jobErrorCode);
+ Error(const Error &);
+ Error(Error &&);
+ ~Error();
+ Error &operator=(const Error &);
+ Error &operator=(Error &&);
+
+ Q_REQUIRED_RESULT ErrorNumber errorNumber() const;
+ Q_REQUIRED_RESULT int responseCode() const;
+ Q_REQUIRED_RESULT QString internalErrorText() const;
+ Q_REQUIRED_RESULT int jobErrorCode() const;
+ Q_REQUIRED_RESULT QString translatedJobError() const;
+ Q_REQUIRED_RESULT QString errorText() const;
+
+private:
+ QSharedDataPointer<ErrorPrivate> d;
+};
+}
+
+#endif
--- /dev/null
+/*
+ SPDX-FileCopyrightText: 2009 Grégory Oestreicher <greg@kamago.net>
+
+ SPDX-License-Identifier: LGPL-2.0-or-later
+*/
+
+#include "davitem.h"
+
+#include "davurl.h"
+
+using namespace KDAV;
+
+class DavItemPrivate : public QSharedData
+{
+public:
+ DavUrl mUrl;
+ QString mContentType;
+ QByteArray mData;
+ QString mEtag;
+};
+
+DavItem::DavItem()
+ : d(new DavItemPrivate)
+{
+}
+
+DavItem::DavItem(const DavUrl &url, const QString &contentType, const QByteArray &data, const QString &etag)
+ : d(new DavItemPrivate)
+{
+ d->mUrl = url;
+ d->mContentType = contentType;
+ d->mData = data;
+ d->mEtag = etag;
+}
+
+DavItem::DavItem(const DavItem &other) = default;
+DavItem::DavItem(DavItem &&) = default;
+DavItem &DavItem::operator=(const DavItem &other) = default;
+DavItem &DavItem::operator=(DavItem &&) = default;
+DavItem::~DavItem() = default;
+
+void DavItem::setUrl(const DavUrl &url)
+{
+ d->mUrl = url;
+}
+
+DavUrl DavItem::url() const
+{
+ return d->mUrl;
+}
+
+void DavItem::setContentType(const QString &contentType)
+{
+ d->mContentType = contentType;
+}
+
+QString DavItem::contentType() const
+{
+ return d->mContentType;
+}
+
+void DavItem::setData(const QByteArray &data)
+{
+ d->mData = data;
+}
+
+QByteArray DavItem::data() const
+{
+ return d->mData;
+}
+
+void DavItem::setEtag(const QString &etag)
+{
+ d->mEtag = etag;
+}
+
+QString DavItem::etag() const
+{
+ return d->mEtag;
+}
+
+QDataStream &KDAV::operator<<(QDataStream &stream, const DavItem &item)
+{
+ stream << item.url();
+ stream << item.contentType();
+ stream << item.data();
+ stream << item.etag();
+
+ return stream;
+}
+
+QDataStream &KDAV::operator>>(QDataStream &stream, DavItem &item)
+{
+ QString contentType;
+ QString etag;
+ DavUrl url;
+ QByteArray data;
+
+ stream >> url;
+ stream >> contentType;
+ stream >> data;
+ stream >> etag;
+
+ item = DavItem(url, contentType, data, etag);
+
+ return stream;
+}
--- /dev/null
+/*
+ SPDX-FileCopyrightText: 2009 Grégory Oestreicher <greg@kamago.net>
+
+ SPDX-License-Identifier: LGPL-2.0-or-later
+*/
+
+#ifndef KDAV_DAVITEM_H
+#define KDAV_DAVITEM_H
+
+#include "kdav_export.h"
+
+#include <QByteArray>
+#include <QDataStream>
+#include <QSharedDataPointer>
+#include <QString>
+#include <QVector>
+
+class DavItemPrivate;
+
+namespace KDAV
+{
+class DavUrl;
+}
+
+namespace KDAV
+{
+/**
+ * @class DavItem davitem.h <KDAV/DavItem>
+ *
+ * @short A helper class to store information about DAV resources.
+ *
+ * This class is used as container to transfer information about DAV
+ * resources between the Akonadi resource and the DAV jobs.
+ *
+ * @note While the DAV RFC names them DAV resource we call them items
+ * to comply to Akonadi terminology.
+ */
+class KDAV_EXPORT DavItem
+{
+public:
+ /**
+ * Defines a list of DAV item objects.
+ */
+ typedef QVector<DavItem> List;
+
+ /**
+ * Creates an empty DAV item.
+ */
+ DavItem();
+
+ /**
+ * Creates a new DAV item.
+ *
+ * @param url The URL that identifies the item.
+ * @param contentType The content type of the item.
+ * @param data The actual raw content data of the item.
+ * @param etag The ETag of the item.
+ */
+ DavItem(const DavUrl &url, const QString &contentType, const QByteArray &data, const QString &etag);
+
+ DavItem(const DavItem &other);
+ DavItem(DavItem &&);
+ DavItem &operator=(const DavItem &other);
+ DavItem &operator=(DavItem &&);
+
+ ~DavItem();
+
+ /**
+ * Sets the @p url that identifies the item.
+ */
+ void setUrl(const DavUrl &url);
+
+ /**
+ * Returns the URL that identifies the item.
+ */
+ Q_REQUIRED_RESULT DavUrl url() const;
+
+ /**
+ * Sets the content @p type of the item.
+ */
+ void setContentType(const QString &type);
+
+ /**
+ * Returns the content type of the item.
+ */
+ Q_REQUIRED_RESULT QString contentType() const;
+
+ /**
+ * Sets the raw content @p data of the item.
+ */
+ void setData(const QByteArray &data);
+
+ /**
+ * Returns the raw content data of the item.
+ */
+ Q_REQUIRED_RESULT QByteArray data() const;
+
+ /**
+ * Sets the @p etag of the item.
+ * @see https://tools.ietf.org/html/rfc4918#section-8.6
+ */
+ void setEtag(const QString &etag);
+
+ /**
+ * Returns the ETag of the item.
+ * @see https://tools.ietf.org/html/rfc4918#section-8.6
+ */
+ Q_REQUIRED_RESULT QString etag() const;
+
+private:
+ QSharedDataPointer<DavItemPrivate> d;
+};
+
+KDAV_EXPORT QDataStream &operator<<(QDataStream &out, const DavItem &item);
+KDAV_EXPORT QDataStream &operator>>(QDataStream &in, DavItem &item);
+}
+
+Q_DECLARE_TYPEINFO(KDAV::DavItem, Q_MOVABLE_TYPE);
+
+#endif
--- /dev/null
+/*
+ SPDX-FileCopyrightText: 2010 Tobias Koenig <tokoe@kde.org>
+
+ SPDX-License-Identifier: LGPL-2.0-or-later
+*/
+
+#include "davitemcreatejob.h"
+#include "davjobbase_p.h"
+
+#include "daverror.h"
+#include "davitemfetchjob.h"
+
+#include <KIO/DavJob>
+#include <KIO/Job>
+
+using namespace KDAV;
+
+namespace KDAV
+{
+class DavItemCreateJobPrivate : public DavJobBasePrivate
+{
+public:
+ void davJobFinished(KJob *job);
+ void itemRefreshed(KJob *job);
+
+ DavItem mItem;
+ int mRedirectCount = 0;
+
+ Q_DECLARE_PUBLIC(DavItemCreateJob)
+};
+}
+
+DavItemCreateJob::DavItemCreateJob(const DavItem &item, QObject *parent)
+ : DavJobBase(new DavItemCreateJobPrivate, parent)
+{
+ Q_D(DavItemCreateJob);
+ d->mItem = item;
+}
+
+void DavItemCreateJob::start()
+{
+ Q_D(DavItemCreateJob);
+ QString headers = QStringLiteral("Content-Type: ");
+ headers += d->mItem.contentType();
+ headers += QLatin1String("\r\n");
+ headers += QLatin1String("If-None-Match: *");
+
+ KIO::StoredTransferJob *job = KIO::storedPut(d->mItem.data(), itemUrl(), -1, KIO::HideProgressInfo | KIO::DefaultFlags);
+ job->addMetaData(QStringLiteral("PropagateHttpHeader"), QStringLiteral("true"));
+ job->addMetaData(QStringLiteral("customHTTPHeader"), headers);
+ job->addMetaData(QStringLiteral("cookies"), QStringLiteral("none"));
+ job->addMetaData(QStringLiteral("no-auth-prompt"), QStringLiteral("true"));
+ job->setRedirectionHandlingEnabled(false);
+
+ connect(job, &KIO::StoredTransferJob::result, this, [d](KJob *job) {
+ d->davJobFinished(job);
+ });
+}
+
+DavItem DavItemCreateJob::item() const
+{
+ Q_D(const DavItemCreateJob);
+ return d->mItem;
+}
+
+QUrl DavItemCreateJob::itemUrl() const
+{
+ Q_D(const DavItemCreateJob);
+ return d->mItem.url().url();
+}
+
+void DavItemCreateJobPrivate::davJobFinished(KJob *job)
+{
+ Q_Q(DavItemCreateJob);
+ KIO::StoredTransferJob *storedJob = qobject_cast<KIO::StoredTransferJob *>(job);
+ const QString responseCodeStr = storedJob->queryMetaData(QStringLiteral("responsecode"));
+ const int responseCode = responseCodeStr.isEmpty() ? 0 : responseCodeStr.toInt();
+ if (storedJob->error()) {
+ setLatestResponseCode(responseCode);
+ setError(ERR_ITEMCREATE);
+ setJobErrorText(storedJob->errorText());
+ setJobError(storedJob->error());
+ setErrorTextFromDavError();
+
+ emitResult();
+ return;
+ }
+
+ // The 'Location:' HTTP header is used to indicate the new URL
+ const QStringList allHeaders = storedJob->queryMetaData(QStringLiteral("HTTP-Headers")).split(QLatin1Char('\n'));
+ QString location;
+ for (const QString &header : allHeaders) {
+ if (header.startsWith(QLatin1String("location:"), Qt::CaseInsensitive)) {
+ location = header.section(QLatin1Char(' '), 1);
+ }
+ }
+
+ QUrl url;
+ if (location.isEmpty()) {
+ url = storedJob->url();
+ } else if (location.startsWith(QLatin1Char('/'))) {
+ url = storedJob->url();
+ url.setPath(location, QUrl::TolerantMode);
+ } else {
+ url = QUrl::fromUserInput(location);
+ }
+
+ if (responseCode == 301 || responseCode == 302 || responseCode == 307 || responseCode == 308) {
+ if (mRedirectCount > 4) {
+ setLatestResponseCode(responseCode);
+ setError(DavItemCreateJob::UserDefinedError + responseCode);
+ emitResult();
+ } else {
+ QUrl _itemUrl(url);
+ _itemUrl.setUserInfo(q->itemUrl().userInfo());
+ mItem.setUrl(DavUrl(_itemUrl, mItem.url().protocol()));
+
+ ++mRedirectCount;
+ q->start();
+ }
+
+ return;
+ }
+
+ url.setUserInfo(q->itemUrl().userInfo());
+ mItem.setUrl(DavUrl(url, mItem.url().protocol()));
+
+ DavItemFetchJob *fetchJob = new DavItemFetchJob(mItem);
+ QObject::connect(fetchJob, &DavItemFetchJob::result, q, [this](KJob *job) {
+ itemRefreshed(job);
+ });
+ fetchJob->start();
+}
+
+void DavItemCreateJobPrivate::itemRefreshed(KJob *job)
+{
+ if (!job->error()) {
+ DavItemFetchJob *fetchJob = qobject_cast<DavItemFetchJob *>(job);
+ mItem.setEtag(fetchJob->item().etag());
+ }
+ emitResult();
+}
--- /dev/null
+/*
+ SPDX-FileCopyrightText: 2010 Tobias Koenig <tokoe@kde.org>
+
+ SPDX-License-Identifier: LGPL-2.0-or-later
+*/
+
+#ifndef KDAV_DAVITEMCREATEJOB_H
+#define KDAV_DAVITEMCREATEJOB_H
+
+#include "kdav_export.h"
+
+#include "davitem.h"
+#include "davjobbase.h"
+#include "davurl.h"
+
+namespace KDAV
+{
+class DavItemCreateJobPrivate;
+
+/**
+ * @class DavItemCreateJob davitemcreatejob.h <KDAV/DavItemCreateJob>
+ *
+ * @short A job to create a DAV item on the DAV server.
+ */
+class KDAV_EXPORT DavItemCreateJob : public DavJobBase
+{
+ Q_OBJECT
+
+public:
+ /**
+ * Creates a new DAV item create job.
+ *
+ * @param item The item that shall be created.
+ * @param parent The parent object.
+ */
+ explicit DavItemCreateJob(const DavItem &item, QObject *parent = nullptr);
+
+ /**
+ * Starts the job.
+ */
+ void start() override;
+
+ /**
+ * Returns the created DAV item including the correct identifier URL
+ * and current ETag information.
+ */
+ Q_REQUIRED_RESULT DavItem item() const;
+
+ Q_REQUIRED_RESULT QUrl itemUrl() const;
+
+private:
+ Q_DECLARE_PRIVATE(DavItemCreateJob)
+};
+}
+
+#endif
--- /dev/null
+/*
+ SPDX-FileCopyrightText: 2010 Tobias Koenig <tokoe@kde.org>
+
+ SPDX-License-Identifier: LGPL-2.0-or-later
+*/
+
+#include "davitemdeletejob.h"
+#include "davjobbase_p.h"
+
+#include "daverror.h"
+#include "davitemfetchjob.h"
+#include "davmanager_p.h"
+
+#include <KIO/DeleteJob>
+#include <KIO/Job>
+
+using namespace KDAV;
+
+namespace KDAV
+{
+class DavItemDeleteJobPrivate : public DavJobBasePrivate
+{
+public:
+ void davJobFinished(KJob *job);
+ void conflictingItemFetched(KJob *job);
+
+ DavItem mItem;
+ DavItem mFreshItem;
+ int mFreshResponseCode = -1;
+};
+}
+
+DavItemDeleteJob::DavItemDeleteJob(const DavItem &item, QObject *parent)
+ : DavJobBase(new DavItemDeleteJobPrivate, parent)
+{
+ Q_D(DavItemDeleteJob);
+ d->mItem = item;
+}
+
+void DavItemDeleteJob::start()
+{
+ Q_D(DavItemDeleteJob);
+ KIO::DeleteJob *job = KIO::del(d->mItem.url().url(), KIO::HideProgressInfo | KIO::DefaultFlags);
+ job->addMetaData(QStringLiteral("PropagateHttpHeader"), QStringLiteral("true"));
+ job->addMetaData(QStringLiteral("customHTTPHeader"), QStringLiteral("If-Match: ") + d->mItem.etag());
+ job->addMetaData(QStringLiteral("cookies"), QStringLiteral("none"));
+ job->addMetaData(QStringLiteral("no-auth-prompt"), QStringLiteral("true"));
+
+ connect(job, &KIO::DeleteJob::result, this, [d](KJob *job) {
+ d->davJobFinished(job);
+ });
+}
+
+DavItem DavItemDeleteJob::freshItem() const
+{
+ Q_D(const DavItemDeleteJob);
+ return d->mFreshItem;
+}
+
+int DavItemDeleteJob::freshResponseCode() const
+{
+ Q_D(const DavItemDeleteJob);
+ return d->mFreshResponseCode;
+}
+
+void DavItemDeleteJobPrivate::davJobFinished(KJob *job)
+{
+ KIO::DeleteJob *deleteJob = qobject_cast<KIO::DeleteJob *>(job);
+
+ if (deleteJob->error() && deleteJob->error() != KIO::ERR_NO_CONTENT) {
+ const int responseCode = deleteJob->queryMetaData(QStringLiteral("responsecode")).isEmpty() //
+ ? 0
+ : deleteJob->queryMetaData(QStringLiteral("responsecode")).toInt();
+
+ if (responseCode != 404 && responseCode != 410) {
+ setLatestResponseCode(responseCode);
+ setError(ERR_ITEMDELETE);
+ setJobErrorText(deleteJob->errorText());
+ setJobError(deleteJob->error());
+ setErrorTextFromDavError();
+ }
+
+ if (q_ptr->hasConflict()) {
+ DavItemFetchJob *fetchJob = new DavItemFetchJob(mItem);
+ QObject::connect(fetchJob, &DavItemFetchJob::result, q_ptr, [this](KJob *job) {
+ conflictingItemFetched(job);
+ });
+ fetchJob->start();
+ return;
+ }
+ }
+
+ emitResult();
+}
+
+void DavItemDeleteJobPrivate::conflictingItemFetched(KJob *job)
+{
+ DavItemFetchJob *fetchJob = qobject_cast<DavItemFetchJob *>(job);
+ mFreshResponseCode = fetchJob->latestResponseCode();
+
+ if (!job->error()) {
+ mFreshItem = fetchJob->item();
+ }
+
+ emitResult();
+}
--- /dev/null
+/*
+ SPDX-FileCopyrightText: 2010 Tobias Koenig <tokoe@kde.org>
+
+ SPDX-License-Identifier: LGPL-2.0-or-later
+*/
+
+#ifndef KDAV_DAVITEMDELETEJOB_H
+#define KDAV_DAVITEMDELETEJOB_H
+
+#include "kdav_export.h"
+
+#include "davitem.h"
+#include "davjobbase.h"
+#include "davurl.h"
+
+namespace KDAV
+{
+class DavItemDeleteJobPrivate;
+
+/**
+ * @class DavItemDeleteJob davitemdeletejob.h <KDAV/DavItemDeleteJob>
+ *
+ * @short A job to delete a DAV item on the DAV server.
+ */
+class KDAV_EXPORT DavItemDeleteJob : public DavJobBase
+{
+ Q_OBJECT
+
+public:
+ /**
+ * Creates a new DAV item delete job.
+ *
+ * @param item The item that shall be deleted.
+ * @param parent The parent object.
+ */
+ explicit DavItemDeleteJob(const DavItem &item, QObject *parent = nullptr);
+
+ /**
+ * Starts the job.
+ */
+ void start() override;
+
+ /**
+ * Returns the item that triggered the conflict, if any.
+ */
+ Q_REQUIRED_RESULT DavItem freshItem() const;
+
+ /**
+ * Returns the response code we got when fetching the fresh item.
+ */
+ Q_REQUIRED_RESULT int freshResponseCode() const;
+
+private:
+ Q_DECLARE_PRIVATE(DavItemDeleteJob)
+};
+}
+
+#endif
--- /dev/null
+/*
+ SPDX-FileCopyrightText: 2010 Tobias Koenig <tokoe@kde.org>
+
+ SPDX-License-Identifier: LGPL-2.0-or-later
+*/
+
+#include "davitemfetchjob.h"
+#include "davjobbase_p.h"
+
+#include "daverror.h"
+
+#include <KIO/DavJob>
+#include <KIO/Job>
+
+using namespace KDAV;
+namespace KDAV
+{
+class DavItemFetchJobPrivate : public DavJobBasePrivate
+{
+public:
+ void davJobFinished(KJob *job);
+
+ DavUrl mUrl;
+ DavItem mItem;
+};
+}
+
+static QString etagFromHeaders(const QString &headers)
+{
+ const QStringList allHeaders = headers.split(QLatin1Char('\n'));
+
+ QString etag;
+ for (const QString &header : allHeaders) {
+ if (header.startsWith(QLatin1String("etag:"), Qt::CaseInsensitive)) {
+ etag = header.section(QLatin1Char(' '), 1);
+ }
+ }
+
+ return etag;
+}
+
+DavItemFetchJob::DavItemFetchJob(const DavItem &item, QObject *parent)
+ : DavJobBase(new DavItemFetchJobPrivate, parent)
+{
+ Q_D(DavItemFetchJob);
+ d->mItem = item;
+}
+
+void DavItemFetchJob::start()
+{
+ Q_D(DavItemFetchJob);
+ KIO::StoredTransferJob *job = KIO::storedGet(d->mItem.url().url(), KIO::Reload, KIO::HideProgressInfo | KIO::DefaultFlags);
+ job->addMetaData(QStringLiteral("PropagateHttpHeader"), QStringLiteral("true"));
+ // Work around a strange bug in Zimbra (seen at least on CE 5.0.18) : if the user-agent
+ // contains "Mozilla", some strange debug data is displayed in the shared calendars.
+ // This kinda mess up the events parsing...
+ job->addMetaData(QStringLiteral("UserAgent"), QStringLiteral("KDE DAV groupware client"));
+ job->addMetaData(QStringLiteral("cookies"), QStringLiteral("none"));
+ job->addMetaData(QStringLiteral("no-auth-prompt"), QStringLiteral("true"));
+
+ connect(job, &KIO::StoredTransferJob::result, this, [d](KJob *job) {
+ d->davJobFinished(job);
+ });
+}
+
+DavItem DavItemFetchJob::item() const
+{
+ Q_D(const DavItemFetchJob);
+ return d->mItem;
+}
+
+void DavItemFetchJobPrivate::davJobFinished(KJob *job)
+{
+ KIO::StoredTransferJob *storedJob = qobject_cast<KIO::StoredTransferJob *>(job);
+ const QString responseCodeStr = storedJob->queryMetaData(QStringLiteral("responsecode"));
+ const int responseCode = responseCodeStr.isEmpty() ? 0 : responseCodeStr.toInt();
+
+ setLatestResponseCode(responseCode);
+
+ if (storedJob->error()) {
+ setLatestResponseCode(responseCode);
+ setError(ERR_PROBLEM_WITH_REQUEST);
+ setJobErrorText(storedJob->errorText());
+ setJobError(storedJob->error());
+ setErrorTextFromDavError();
+ } else {
+ mItem.setData(storedJob->data());
+ mItem.setContentType(storedJob->queryMetaData(QStringLiteral("content-type")));
+ mItem.setEtag(etagFromHeaders(storedJob->queryMetaData(QStringLiteral("HTTP-Headers"))));
+ }
+
+ emitResult();
+}
--- /dev/null
+/*
+ SPDX-FileCopyrightText: 2010 Tobias Koenig <tokoe@kde.org>
+
+ SPDX-License-Identifier: LGPL-2.0-or-later
+*/
+
+#ifndef KDAV_DAVITEMFETCHJOB_H
+#define KDAV_DAVITEMFETCHJOB_H
+
+#include "kdav_export.h"
+
+#include "davitem.h"
+#include "davjobbase.h"
+#include "davurl.h"
+
+namespace KDAV
+{
+class DavItemFetchJobPrivate;
+
+/**
+ * @class DavItemFetchJob davitemfetchjob.h <KDAV/DavItemFetchJob>
+ *
+ * @short A job that fetches a DAV item from the DAV server.
+ */
+class KDAV_EXPORT DavItemFetchJob : public DavJobBase
+{
+ Q_OBJECT
+
+public:
+ /**
+ * Creates a new DAV item fetch job.
+ *
+ * @param item The item that shall be fetched.
+ * @param parent The parent object.
+ */
+ explicit DavItemFetchJob(const DavItem &item, QObject *parent = nullptr);
+
+ /**
+ * Starts the job.
+ */
+ void start() override;
+
+ /**
+ * Returns the fetched item including current ETag information.
+ */
+ Q_REQUIRED_RESULT DavItem item() const;
+
+private:
+ Q_DECLARE_PRIVATE(DavItemFetchJob)
+};
+}
+
+#endif
--- /dev/null
+/*
+ SPDX-FileCopyrightText: 2010 Tobias Koenig <tokoe@kde.org>
+
+ SPDX-License-Identifier: LGPL-2.0-or-later
+*/
+
+#include "davitemmodifyjob.h"
+#include "davjobbase_p.h"
+
+#include "daverror.h"
+#include "davitemfetchjob.h"
+
+#include <KIO/Job>
+
+using namespace KDAV;
+namespace KDAV
+{
+class DavItemModifyJobPrivate : public DavJobBasePrivate
+{
+public:
+ void davJobFinished(KJob *job);
+ void itemRefreshed(KJob *job);
+ void conflictingItemFetched(KJob *job);
+
+ DavItem mItem;
+ DavItem mFreshItem;
+ int mFreshResponseCode = 0;
+
+ Q_DECLARE_PUBLIC(DavItemModifyJob)
+};
+}
+
+DavItemModifyJob::DavItemModifyJob(const DavItem &item, QObject *parent)
+ : DavJobBase(new DavItemModifyJobPrivate, parent)
+{
+ Q_D(DavItemModifyJob);
+ d->mItem = item;
+}
+
+void DavItemModifyJob::start()
+{
+ Q_D(DavItemModifyJob);
+ QString headers = QStringLiteral("Content-Type: ");
+ headers += d->mItem.contentType();
+ headers += QLatin1String("\r\n");
+ headers += QLatin1String("If-Match: ") + d->mItem.etag();
+
+ KIO::StoredTransferJob *job = KIO::storedPut(d->mItem.data(), itemUrl(), -1, KIO::HideProgressInfo | KIO::DefaultFlags);
+ job->addMetaData(QStringLiteral("PropagateHttpHeader"), QStringLiteral("true"));
+ job->addMetaData(QStringLiteral("customHTTPHeader"), headers);
+ job->addMetaData(QStringLiteral("cookies"), QStringLiteral("none"));
+ job->addMetaData(QStringLiteral("no-auth-prompt"), QStringLiteral("true"));
+
+ connect(job, &KIO::StoredTransferJob::result, this, [d](KJob *job) {
+ d->davJobFinished(job);
+ });
+}
+
+DavItem DavItemModifyJob::item() const
+{
+ Q_D(const DavItemModifyJob);
+ return d->mItem;
+}
+
+DavItem DavItemModifyJob::freshItem() const
+{
+ Q_D(const DavItemModifyJob);
+ return d->mFreshItem;
+}
+
+int DavItemModifyJob::freshResponseCode() const
+{
+ Q_D(const DavItemModifyJob);
+ return d->mFreshResponseCode;
+}
+
+QUrl DavItemModifyJob::itemUrl() const
+{
+ Q_D(const DavItemModifyJob);
+ return d->mItem.url().url();
+}
+
+void DavItemModifyJobPrivate::davJobFinished(KJob *job)
+{
+ Q_Q(DavItemModifyJob);
+ KIO::StoredTransferJob *storedJob = qobject_cast<KIO::StoredTransferJob *>(job);
+
+ if (storedJob->error()) {
+ const int responseCode = storedJob->queryMetaData(QStringLiteral("responsecode")).isEmpty() //
+ ? 0
+ : storedJob->queryMetaData(QStringLiteral("responsecode")).toInt();
+
+ setLatestResponseCode(responseCode);
+ setError(ERR_ITEMMODIFY);
+ setJobErrorText(storedJob->errorText());
+ setJobError(storedJob->error());
+ setErrorTextFromDavError();
+
+ if (q->hasConflict()) {
+ DavItemFetchJob *fetchJob = new DavItemFetchJob(mItem);
+ QObject::connect(fetchJob, &DavItemFetchJob::result, q, [this](KJob *job) {
+ conflictingItemFetched(job);
+ });
+ fetchJob->start();
+ } else {
+ emitResult();
+ }
+
+ return;
+ }
+
+ // The 'Location:' HTTP header is used to indicate the new URL
+ const QStringList allHeaders = storedJob->queryMetaData(QStringLiteral("HTTP-Headers")).split(QLatin1Char('\n'));
+ QString location;
+ for (const QString &header : allHeaders) {
+ if (header.startsWith(QLatin1String("location:"), Qt::CaseInsensitive)) {
+ location = header.section(QLatin1Char(' '), 1);
+ }
+ }
+
+ QUrl url;
+ if (location.isEmpty()) {
+ url = storedJob->url();
+ } else if (location.startsWith(QLatin1Char('/'))) {
+ url = storedJob->url();
+ url.setPath(location, QUrl::TolerantMode);
+ } else {
+ url = QUrl::fromUserInput(location);
+ }
+
+ url.setUserInfo(q->itemUrl().userInfo());
+ mItem.setUrl(DavUrl(url, mItem.url().protocol()));
+
+ DavItemFetchJob *fetchJob = new DavItemFetchJob(mItem);
+ QObject::connect(fetchJob, &DavItemFetchJob::result, q, [this](KJob *job) {
+ itemRefreshed(job);
+ });
+ fetchJob->start();
+}
+
+void DavItemModifyJobPrivate::itemRefreshed(KJob *job)
+{
+ if (!job->error()) {
+ DavItemFetchJob *fetchJob = qobject_cast<DavItemFetchJob *>(job);
+ mItem.setEtag(fetchJob->item().etag());
+ } else {
+ mItem.setEtag(QString());
+ }
+ emitResult();
+}
+
+void DavItemModifyJobPrivate::conflictingItemFetched(KJob *job)
+{
+ DavItemFetchJob *fetchJob = qobject_cast<DavItemFetchJob *>(job);
+ mFreshResponseCode = fetchJob->latestResponseCode();
+
+ if (!job->error()) {
+ mFreshItem = fetchJob->item();
+ }
+
+ emitResult();
+}
--- /dev/null
+/*
+ SPDX-FileCopyrightText: 2010 Tobias Koenig <tokoe@kde.org>
+
+ SPDX-License-Identifier: LGPL-2.0-or-later
+*/
+
+#ifndef KDAV_DAVITEMMODIFYJOB_H
+#define KDAV_DAVITEMMODIFYJOB_H
+
+#include "kdav_export.h"
+
+#include "davitem.h"
+#include "davjobbase.h"
+#include "davurl.h"
+
+namespace KDAV
+{
+class DavItemModifyJobPrivate;
+
+/**
+ * @class DavItemModifyJob davitemmodifyjob.h <KDAV/DavItemModifyJob>
+ *
+ * @short A job that modifies a DAV item on the DAV server.
+ */
+class KDAV_EXPORT DavItemModifyJob : public DavJobBase
+{
+ Q_OBJECT
+
+public:
+ /**
+ * Creates a new DAV item modify job.
+ *
+ * @param item The item that shall be modified.
+ * @param parent The parent object.
+ */
+ explicit DavItemModifyJob(const DavItem &item, QObject *parent = nullptr);
+
+ /**
+ * Starts the job.
+ */
+ void start() override;
+
+ /**
+ * Returns the modified item including the updated ETag information.
+ */
+ Q_REQUIRED_RESULT DavItem item() const;
+
+ Q_REQUIRED_RESULT QUrl itemUrl() const;
+
+ /**
+ * Returns the item that triggered the conflict, if any.
+ */
+ Q_REQUIRED_RESULT DavItem freshItem() const;
+
+ /**
+ * Returns the response code we got when fetching the fresh item.
+ */
+ Q_REQUIRED_RESULT int freshResponseCode() const;
+
+private:
+ Q_DECLARE_PRIVATE(DavItemModifyJob)
+};
+}
+
+#endif
--- /dev/null
+/*
+ SPDX-FileCopyrightText: 2010 Grégory Oestreicher <greg@kamago.net>
+
+ Based on DavItemsListJob:
+ SPDX-FileCopyrightText: 2010 Tobias Koenig <tokoe@kde.org>
+
+ SPDX-License-Identifier: LGPL-2.0-or-later
+*/
+
+#include "davitemsfetchjob.h"
+#include "davjobbase_p.h"
+
+#include "daverror.h"
+#include "davmanager_p.h"
+#include "davmultigetprotocol_p.h"
+#include "utils_p.h"
+
+#include <KIO/DavJob>
+#include <KIO/Job>
+
+using namespace KDAV;
+
+namespace KDAV
+{
+class DavItemsFetchJobPrivate : public DavJobBasePrivate
+{
+public:
+ void davJobFinished(KJob *job);
+
+ DavUrl mCollectionUrl;
+ QStringList mUrls;
+ QMap<QString, DavItem> mItems;
+};
+}
+
+DavItemsFetchJob::DavItemsFetchJob(const DavUrl &collectionUrl, const QStringList &urls, QObject *parent)
+ : DavJobBase(new DavItemsFetchJobPrivate, parent)
+{
+ Q_D(DavItemsFetchJob);
+ d->mCollectionUrl = collectionUrl;
+ d->mUrls = urls;
+}
+
+void DavItemsFetchJob::start()
+{
+ Q_D(DavItemsFetchJob);
+ const DavMultigetProtocol *protocol = dynamic_cast<const DavMultigetProtocol *>(DavManager::davProtocol(d->mCollectionUrl.protocol()));
+ if (!protocol) {
+ setError(ERR_NO_MULTIGET);
+ d->setErrorTextFromDavError();
+ emitResult();
+ return;
+ }
+
+ const QDomDocument report = protocol->itemsReportQuery(d->mUrls)->buildQuery();
+ KIO::DavJob *job = DavManager::self()->createReportJob(d->mCollectionUrl.url(), report.toString(), QStringLiteral("0"));
+ job->addMetaData(QStringLiteral("PropagateHttpHeader"), QStringLiteral("true"));
+ connect(job, &KIO::DavJob::result, this, [d](KJob *job) {
+ d->davJobFinished(job);
+ });
+}
+
+DavItem::List DavItemsFetchJob::items() const
+{
+ Q_D(const DavItemsFetchJob);
+ DavItem::List values;
+ values.reserve(d->mItems.size());
+ for (const auto &value : std::as_const(d->mItems)) {
+ values << value;
+ }
+ return values;
+}
+
+DavItem DavItemsFetchJob::item(const QString &url) const
+{
+ Q_D(const DavItemsFetchJob);
+ return d->mItems.value(url);
+}
+
+void DavItemsFetchJobPrivate::davJobFinished(KJob *job)
+{
+ KIO::DavJob *davJob = qobject_cast<KIO::DavJob *>(job);
+ const QString responseCodeStr = davJob->queryMetaData(QStringLiteral("responsecode"));
+ const int responseCode = responseCodeStr.isEmpty() ? 0 : responseCodeStr.toInt();
+
+ // KIO::DavJob does not set error() even if the HTTP status code is a 4xx or a 5xx
+ if (davJob->error() || (responseCode >= 400 && responseCode < 600)) {
+ setLatestResponseCode(responseCode);
+ setError(ERR_PROBLEM_WITH_REQUEST);
+ setJobErrorText(davJob->errorText());
+ setJobError(davJob->error());
+ setErrorTextFromDavError();
+
+ emitResult();
+ return;
+ }
+
+ const DavMultigetProtocol *protocol = static_cast<const DavMultigetProtocol *>(DavManager::davProtocol(mCollectionUrl.protocol()));
+
+ QDomDocument document;
+ document.setContent(davJob->responseData(), true);
+ const QDomElement documentElement = document.documentElement();
+
+ QDomElement responseElement = Utils::firstChildElementNS(documentElement, QStringLiteral("DAV:"), QStringLiteral("response"));
+
+ while (!responseElement.isNull()) {
+ QDomElement propstatElement = Utils::firstChildElementNS(responseElement, QStringLiteral("DAV:"), QStringLiteral("propstat"));
+
+ if (propstatElement.isNull()) {
+ responseElement = Utils::nextSiblingElementNS(responseElement, QStringLiteral("DAV:"), QStringLiteral("response"));
+ continue;
+ }
+
+ // Check for errors
+ const QDomElement statusElement = Utils::firstChildElementNS(propstatElement, QStringLiteral("DAV:"), QStringLiteral("status"));
+ if (!statusElement.text().contains(QLatin1String("200"))) {
+ responseElement = Utils::nextSiblingElementNS(responseElement, QStringLiteral("DAV:"), QStringLiteral("response"));
+ continue;
+ }
+
+ const QDomElement propElement = Utils::firstChildElementNS(propstatElement, QStringLiteral("DAV:"), QStringLiteral("prop"));
+
+ DavItem item;
+
+ // extract path
+ const QDomElement hrefElement = Utils::firstChildElementNS(responseElement, QStringLiteral("DAV:"), QStringLiteral("href"));
+ const QString href = hrefElement.text();
+
+ QUrl url = davJob->url();
+ if (href.startsWith(QLatin1Char('/'))) {
+ // href is only a path, use request url to complete
+ url.setPath(href, QUrl::TolerantMode);
+ } else {
+ // href is a complete url
+ url = QUrl::fromUserInput(href);
+ }
+
+ auto _url = url;
+ _url.setUserInfo(mCollectionUrl.url().userInfo());
+ item.setUrl(DavUrl(_url, mCollectionUrl.protocol()));
+
+ // extract ETag
+ const QDomElement getetagElement = Utils::firstChildElementNS(propElement, QStringLiteral("DAV:"), QStringLiteral("getetag"));
+ item.setEtag(getetagElement.text());
+
+ // extract content
+ const QDomElement dataElement = Utils::firstChildElementNS(propElement, protocol->responseNamespace(), protocol->dataTagName());
+
+ if (dataElement.isNull()) {
+ responseElement = Utils::nextSiblingElementNS(responseElement, QStringLiteral("DAV:"), QStringLiteral("response"));
+ continue;
+ }
+
+ const QByteArray data = dataElement.firstChild().toText().data().toUtf8();
+ if (data.isEmpty()) {
+ responseElement = Utils::nextSiblingElementNS(responseElement, QStringLiteral("DAV:"), QStringLiteral("response"));
+ continue;
+ }
+
+ item.setData(data);
+
+ mItems.insert(item.url().toDisplayString(), item);
+ responseElement = Utils::nextSiblingElementNS(responseElement, QStringLiteral("DAV:"), QStringLiteral("response"));
+ }
+
+ emitResult();
+}
--- /dev/null
+/*
+ SPDX-FileCopyrightText: 2010 Grégory Oestreicher <greg@kamago.net>
+
+ Based on DavItemsListJob:
+ SPDX-FileCopyrightText: 2010 Tobias Koenig <tokoe@kde.org>
+
+ SPDX-License-Identifier: LGPL-2.0-or-later
+*/
+
+#ifndef KDAV_DAVITEMSFETCHJOB_H
+#define KDAV_DAVITEMSFETCHJOB_H
+
+#include "kdav_export.h"
+
+#include "davitem.h"
+#include "davjobbase.h"
+#include "davurl.h"
+
+#include <QStringList>
+
+namespace KDAV
+{
+class DavItemsFetchJobPrivate;
+
+/**
+ * @class DavItemsFetchJob davitemsfetchjob.h <KDAV/DavItemsFetchJob>
+ *
+ * @short A job that fetches a list of items from a DAV server using a MULTIGET query.
+ */
+class KDAV_EXPORT DavItemsFetchJob : public DavJobBase
+{
+ Q_OBJECT
+
+public:
+ /**
+ * Creates a new items fetch job.
+ *
+ * @param collectionUrl The DAV collection on which to run the query
+ * @param urls The list of URLs to fetch
+ * @param parent The parent object
+ */
+ DavItemsFetchJob(const DavUrl &collectionUrl, const QStringList &urls, QObject *parent = nullptr);
+
+ /**
+ * Starts the job.
+ */
+ void start() override;
+
+ /**
+ * Returns the list of fetched items
+ */
+ Q_REQUIRED_RESULT DavItem::List items() const;
+
+ /**
+ * Return the item found at @p url
+ */
+ Q_REQUIRED_RESULT DavItem item(const QString &url) const;
+
+private:
+ Q_DECLARE_PRIVATE(DavItemsFetchJob)
+};
+}
+
+#endif
--- /dev/null
+/*
+ SPDX-FileCopyrightText: 2010 Tobias Koenig <tokoe@kde.org>
+
+ SPDX-License-Identifier: LGPL-2.0-or-later
+*/
+
+#include "davitemslistjob.h"
+#include "davjobbase_p.h"
+
+#include "daverror.h"
+#include "davmanager_p.h"
+#include "davprotocolbase_p.h"
+#include "davurl.h"
+#include "etagcache.h"
+#include "utils_p.h"
+
+#include <KIO/DavJob>
+#include <KIO/Job>
+
+#include <set>
+
+using namespace KDAV;
+
+namespace KDAV
+{
+class DavItemsListJobPrivate : public DavJobBasePrivate
+{
+public:
+ void davJobFinished(KJob *job);
+
+ DavUrl mUrl;
+ std::shared_ptr<EtagCache> mEtagCache;
+ QStringList mMimeTypes;
+ QString mRangeStart;
+ QString mRangeEnd;
+ DavItem::List mItems;
+ std::set<QString> mSeenUrls; // to prevent events duplication with some servers
+ DavItem::List mChangedItems;
+ QStringList mDeletedItems;
+ uint mSubJobCount = 0;
+};
+}
+
+DavItemsListJob::DavItemsListJob(const DavUrl &url, const std::shared_ptr<EtagCache> &cache, QObject *parent)
+ : DavJobBase(new DavItemsListJobPrivate, parent)
+{
+ Q_D(DavItemsListJob);
+ d->mUrl = url;
+ d->mEtagCache = cache;
+}
+
+DavItemsListJob::~DavItemsListJob() = default;
+
+void DavItemsListJob::setContentMimeTypes(const QStringList &types)
+{
+ Q_D(DavItemsListJob);
+ d->mMimeTypes = types;
+}
+
+void DavItemsListJob::setTimeRange(const QString &start, const QString &end)
+{
+ Q_D(DavItemsListJob);
+ d->mRangeStart = start;
+ d->mRangeEnd = end;
+}
+
+void DavItemsListJob::start()
+{
+ Q_D(DavItemsListJob);
+ const DavProtocolBase *protocol = DavManager::davProtocol(d->mUrl.protocol());
+ Q_ASSERT(protocol);
+
+ const auto queries = protocol->itemsQueries();
+ for (XMLQueryBuilder::Ptr builder : queries) {
+ if (!d->mRangeStart.isEmpty()) {
+ builder->setParameter(QStringLiteral("start"), d->mRangeStart);
+ }
+ if (!d->mRangeEnd.isEmpty()) {
+ builder->setParameter(QStringLiteral("end"), d->mRangeEnd);
+ }
+
+ const QDomDocument props = builder->buildQuery();
+ const QString mimeType = builder->mimeType();
+
+ if (d->mMimeTypes.isEmpty() || d->mMimeTypes.contains(mimeType)) {
+ ++d->mSubJobCount;
+ if (protocol->useReport()) {
+ KIO::DavJob *job = DavManager::self()->createReportJob(d->mUrl.url(), props.toString());
+ job->addMetaData(QStringLiteral("PropagateHttpHeader"), QStringLiteral("true"));
+ job->setProperty("davType", QStringLiteral("report"));
+ job->setProperty("itemsMimeType", mimeType);
+ connect(job, &KIO::DavJob::result, this, [d](KJob *job) {
+ d->davJobFinished(job);
+ });
+ } else {
+ KIO::DavJob *job = DavManager::self()->createPropFindJob(d->mUrl.url(), props.toString());
+ job->addMetaData(QStringLiteral("PropagateHttpHeader"), QStringLiteral("true"));
+ job->setProperty("davType", QStringLiteral("propFind"));
+ job->setProperty("itemsMimeType", mimeType);
+ connect(job, &KIO::DavJob::result, this, [d](KJob *job) {
+ d->davJobFinished(job);
+ });
+ }
+ }
+ }
+
+ if (d->mSubJobCount == 0) {
+ setError(ERR_ITEMLIST_NOMIMETYPE);
+ d->setErrorTextFromDavError();
+ emitResult();
+ }
+}
+
+DavItem::List DavItemsListJob::items() const
+{
+ Q_D(const DavItemsListJob);
+ return d->mItems;
+}
+
+DavItem::List DavItemsListJob::changedItems() const
+{
+ Q_D(const DavItemsListJob);
+ return d->mChangedItems;
+}
+
+QStringList DavItemsListJob::deletedItems() const
+{
+ Q_D(const DavItemsListJob);
+ return d->mDeletedItems;
+}
+
+void DavItemsListJobPrivate::davJobFinished(KJob *job)
+{
+ KIO::DavJob *davJob = qobject_cast<KIO::DavJob *>(job);
+ const int responseCode = davJob->queryMetaData(QStringLiteral("responsecode")).isEmpty() //
+ ? 0
+ : davJob->queryMetaData(QStringLiteral("responsecode")).toInt();
+
+ // KIO::DavJob does not set error() even if the HTTP status code is a 4xx or a 5xx
+ if (davJob->error() || (responseCode >= 400 && responseCode < 600)) {
+ setLatestResponseCode(responseCode);
+ setError(ERR_PROBLEM_WITH_REQUEST);
+ setJobErrorText(davJob->errorText());
+ setJobError(davJob->error());
+ setErrorTextFromDavError();
+ } else {
+ /*
+ * Extract data from a document like the following:
+ *
+ * <multistatus xmlns="DAV:">
+ * <response xmlns="DAV:">
+ * <href xmlns="DAV:">/caldav.php/test1.user/home/KOrganizer-166749289.780.ics</href>
+ * <propstat xmlns="DAV:">
+ * <prop xmlns="DAV:">
+ * <getetag xmlns="DAV:">"b4bbea0278f4f63854c4167a7656024a"</getetag>
+ * </prop>
+ * <status xmlns="DAV:">HTTP/1.1 200 OK</status>
+ * </propstat>
+ * </response>
+ * <response xmlns="DAV:">
+ * <href xmlns="DAV:">/caldav.php/test1.user/home/KOrganizer-399416366.464.ics</href>
+ * <propstat xmlns="DAV:">
+ * <prop xmlns="DAV:">
+ * <getetag xmlns="DAV:">"52eb129018398a7da4f435b2bc4c6cd5"</getetag>
+ * </prop>
+ * <status xmlns="DAV:">HTTP/1.1 200 OK</status>
+ * </propstat>
+ * </response>
+ * </multistatus>
+ */
+
+ const QString itemsMimeType = job->property("itemsMimeType").toString();
+ QDomDocument document;
+ document.setContent(davJob->responseData(), true);
+ const QDomElement documentElement = document.documentElement();
+
+ QDomElement responseElement = Utils::firstChildElementNS(documentElement, QStringLiteral("DAV:"), QStringLiteral("response"));
+ while (!responseElement.isNull()) {
+ QDomElement propstatElement;
+
+ // check for the valid propstat, without giving up on first error
+ {
+ const QDomNodeList propstats = responseElement.elementsByTagNameNS(QStringLiteral("DAV:"), QStringLiteral("propstat"));
+ for (int i = 0; i < propstats.length(); ++i) {
+ const QDomElement propstatCandidate = propstats.item(i).toElement();
+ const QDomElement statusElement = Utils::firstChildElementNS(propstatCandidate, QStringLiteral("DAV:"), QStringLiteral("status"));
+ if (statusElement.text().contains(QLatin1String("200"))) {
+ propstatElement = propstatCandidate;
+ }
+ }
+ }
+
+ if (propstatElement.isNull()) {
+ responseElement = Utils::nextSiblingElementNS(responseElement, QStringLiteral("DAV:"), QStringLiteral("response"));
+ continue;
+ }
+
+ const QDomElement propElement = Utils::firstChildElementNS(propstatElement, QStringLiteral("DAV:"), QStringLiteral("prop"));
+
+ // check whether it is a DAV collection ...
+ const QDomElement resourcetypeElement = Utils::firstChildElementNS(propElement, QStringLiteral("DAV:"), QStringLiteral("resourcetype"));
+ if (!resourcetypeElement.isNull()) {
+ const QDomElement collectionElement = Utils::firstChildElementNS(resourcetypeElement, QStringLiteral("DAV:"), QStringLiteral("collection"));
+ if (!collectionElement.isNull()) {
+ responseElement = Utils::nextSiblingElementNS(responseElement, QStringLiteral("DAV:"), QStringLiteral("response"));
+ continue;
+ }
+ }
+
+ // ... if not it is an item
+ DavItem item;
+ item.setContentType(itemsMimeType);
+
+ // extract path
+ const QDomElement hrefElement = Utils::firstChildElementNS(responseElement, QStringLiteral("DAV:"), QStringLiteral("href"));
+ const QString href = hrefElement.text();
+
+ QUrl url = davJob->url();
+ url.setUserInfo(QString());
+ if (href.startsWith(QLatin1Char('/'))) {
+ // href is only a path, use request url to complete
+ url.setPath(href, QUrl::TolerantMode);
+ } else {
+ // href is a complete url
+ url = QUrl::fromUserInput(href);
+ }
+
+ const QString itemUrl = url.toDisplayString();
+ const auto [it, isInserted] = mSeenUrls.insert(itemUrl);
+ if (!isInserted) {
+ responseElement = Utils::nextSiblingElementNS(responseElement, QStringLiteral("DAV:"), QStringLiteral("response"));
+ continue;
+ }
+
+ auto _url = url;
+ _url.setUserInfo(mUrl.url().userInfo());
+ item.setUrl(DavUrl(_url, mUrl.protocol()));
+
+ // extract ETag
+ const QDomElement getetagElement = Utils::firstChildElementNS(propElement, QStringLiteral("DAV:"), QStringLiteral("getetag"));
+
+ item.setEtag(getetagElement.text());
+
+ mItems << item;
+
+ if (mEtagCache->etagChanged(itemUrl, item.etag())) {
+ mChangedItems << item;
+ }
+
+ responseElement = Utils::nextSiblingElementNS(responseElement, QStringLiteral("DAV:"), QStringLiteral("response"));
+ }
+ }
+
+ mDeletedItems.clear();
+
+ const auto map = mEtagCache->etagCacheMap();
+ for (auto it = map.cbegin(); it != map.cend(); ++it) {
+ const QString remoteId = it.key();
+ if (mSeenUrls.find(remoteId) == mSeenUrls.cend()) {
+ mDeletedItems.append(remoteId);
+ }
+ }
+
+ if (--mSubJobCount == 0) {
+ emitResult();
+ }
+}
--- /dev/null
+/*
+ SPDX-FileCopyrightText: 2010 Tobias Koenig <tokoe@kde.org>
+
+ SPDX-License-Identifier: LGPL-2.0-or-later
+*/
+
+#ifndef KDAV_DAVITEMSLISTJOB_H
+#define KDAV_DAVITEMSLISTJOB_H
+
+#include "kdav_export.h"
+
+#include "davitem.h"
+#include "davjobbase.h"
+
+#include <memory>
+
+#include <QStringList>
+
+namespace KDAV
+{
+class EtagCache;
+class DavUrl;
+class DavItemsListJobPrivate;
+
+/**
+ * @class DavItemsListJob davitemslistjob.h <KDAV/DavItemsListJob>
+ *
+ * @short A job that lists all DAV items inside a DAV collection.
+ */
+class KDAV_EXPORT DavItemsListJob : public DavJobBase
+{
+ Q_OBJECT
+
+public:
+ /**
+ * Creates a new DAV items list job.
+ *
+ * @param url The URL of the DAV collection.
+ * @param parent The parent object.
+ */
+ DavItemsListJob(const DavUrl &url, const std::shared_ptr<EtagCache> &cache, QObject *parent = nullptr);
+
+ ~DavItemsListJob() override;
+
+ /**
+ * Limits the mime types of the items requested.
+ *
+ * If no mime type is given then all will be requested.
+ *
+ * @param types The list of mime types to include
+ */
+ void setContentMimeTypes(const QStringList &types);
+
+ /**
+ * Sets the start and end time to list items for.
+ *
+ * @param start The range start, in format "date with UTC time"
+ * @param end The range end, in format "date with UTC time"
+ */
+ void setTimeRange(const QString &start, const QString &end);
+
+ /**
+ * Starts the job.
+ */
+ void start() override;
+
+ /**
+ * Returns the list of items seen including identifier URL and ETag information.
+ */
+ Q_REQUIRED_RESULT DavItem::List items() const;
+
+ /**
+ * Returns the list of items that were changed on the server.
+ */
+ Q_REQUIRED_RESULT DavItem::List changedItems() const;
+
+ /**
+ * Returns the list of items URLs that were not seen in the backend.
+ * As this is based on the ETag cache this may contain dependent items.
+ */
+ Q_REQUIRED_RESULT QStringList deletedItems() const;
+
+private:
+ Q_DECLARE_PRIVATE(DavItemsListJob)
+};
+}
+
+#endif
--- /dev/null
+/*
+ SPDX-FileCopyrightText: 2014 Gregory Oestreicher <greg@kamago.net>
+
+ SPDX-License-Identifier: LGPL-2.0-or-later
+*/
+
+#include "davjobbase.h"
+#include "davjobbase_p.h"
+
+#include "daverror.h"
+
+using namespace KDAV;
+
+DavJobBase::DavJobBase(QObject *parent)
+ : KJob(parent)
+ , d_ptr(new DavJobBasePrivate())
+{
+ d_ptr->q_ptr = this;
+}
+
+DavJobBase::DavJobBase(DavJobBasePrivate *dd, QObject *parent)
+ : KJob(parent)
+ , d_ptr(dd)
+{
+ d_ptr->q_ptr = this;
+}
+
+DavJobBase::~DavJobBase() = default;
+
+int DavJobBase::latestResponseCode() const
+{
+ return d_ptr->mLatestResponseCode;
+}
+
+bool DavJobBase::canRetryLater() const
+{
+ bool ret = false;
+
+ // Be explicit and readable by splitting the if/else if clauses
+
+ if (latestResponseCode() == 0 && error()) {
+ // Likely a timeout or a connection failure.
+ ret = true;
+ } else if (latestResponseCode() == 401) {
+ // Authentication required
+ ret = true;
+ } else if (latestResponseCode() == 402) {
+ // Payment required
+ ret = true;
+ } else if (latestResponseCode() == 407) {
+ // Proxy authentication required
+ ret = true;
+ } else if (latestResponseCode() == 408) {
+ // Request timeout
+ ret = true;
+ } else if (latestResponseCode() == 423) {
+ // Locked
+ ret = true;
+ } else if (latestResponseCode() == 429) {
+ // Too many requests
+ ret = true;
+ } else if (latestResponseCode() >= 501 && latestResponseCode() <= 504) {
+ // Various server-side errors
+ ret = true;
+ } else if (latestResponseCode() == 507) {
+ // Insufficient storage
+ ret = true;
+ } else if (latestResponseCode() == 511) {
+ // Network authentication required
+ ret = true;
+ }
+
+ return ret;
+}
+
+bool DavJobBase::hasConflict() const
+{
+ return latestResponseCode() == 412;
+}
+
+void DavJobBasePrivate::setLatestResponseCode(int code)
+{
+ mLatestResponseCode = code;
+}
+
+Error DavJobBase::davError() const
+{
+ return Error(static_cast<KDAV::ErrorNumber>(error()), d_ptr->mLatestResponseCode, d_ptr->mInternalErrorText, d_ptr->mJobErrorCode);
+}
+
+void DavJobBasePrivate::setJobErrorText(const QString &errorText)
+{
+ mInternalErrorText = errorText;
+}
+
+void DavJobBasePrivate::setJobError(int jobErrorCode)
+{
+ mJobErrorCode = jobErrorCode;
+}
+
+void DavJobBasePrivate::setErrorTextFromDavError()
+{
+ q_ptr->setErrorText(q_ptr->davError().errorText());
+}
+
+void DavJobBasePrivate::setDavError(const Error &error)
+{
+ q_ptr->setError(error.errorNumber());
+ setLatestResponseCode(error.responseCode());
+ setJobErrorText(error.internalErrorText());
+ setJobError(error.jobErrorCode());
+}
+
+void DavJobBasePrivate::setError(int errorCode)
+{
+ q_ptr->setError(errorCode);
+}
+
+void DavJobBasePrivate::setErrorText(const QString &errorText)
+{
+ q_ptr->setErrorText(errorText);
+}
+
+void DavJobBasePrivate::emitResult()
+{
+ q_ptr->emitResult();
+}
--- /dev/null
+/*
+ SPDX-FileCopyrightText: 2014 Gregory Oestreicher <greg@kamago.net>
+
+ SPDX-License-Identifier: LGPL-2.0-or-later
+*/
+
+#ifndef KDAV_DAVJOBBASE_H
+#define KDAV_DAVJOBBASE_H
+
+#include "kdav_export.h"
+
+#include <KJob>
+
+#include <memory>
+
+namespace KDAV
+{
+class DavJobBasePrivate;
+class Error;
+
+/**
+ * @class DavJobBase davjobbase.h <KDAV/DavJobBase>
+ *
+ * @short base class for the jobs used by the resource.
+ */
+class KDAV_EXPORT DavJobBase : public KJob
+{
+ Q_OBJECT
+
+public:
+ explicit DavJobBase(QObject *parent = nullptr);
+ ~DavJobBase() override;
+
+ /**
+ * Get the latest response code.
+ *
+ * If no response code has been set then 0 will be returned, but will
+ * be meaningless unless error() is non-zero. In that case this means
+ * that the latest error was not at the HTTP level.
+ */
+ Q_REQUIRED_RESULT int latestResponseCode() const;
+
+ /**
+ * Check if the job can be retried later.
+ *
+ * This will return true for transient errors, i.e. if the response code
+ * is either zero and error() is set or if the HTTP response code hints
+ * at a temporary error.
+ *
+ * The HTTP response codes considered retryable are:
+ * - 401
+ * - 402
+ * - 407
+ * - 408
+ * - 423
+ * - 429
+ * - 501 to 504, inclusive
+ * - 507
+ * - 511
+ */
+ Q_REQUIRED_RESULT bool canRetryLater() const;
+
+ /**
+ * Check if the job failed because of a conflict
+ */
+ Q_REQUIRED_RESULT bool hasConflict() const;
+
+ /**
+ * Returns a instance of the KDAV:Error to be able to translate the error
+ */
+ Q_REQUIRED_RESULT Error davError() const;
+
+protected:
+ Q_DECL_HIDDEN explicit DavJobBase(DavJobBasePrivate *dd, QObject *parent = nullptr);
+ std::unique_ptr<DavJobBasePrivate> d_ptr;
+
+private:
+ Q_DECLARE_PRIVATE(DavJobBase)
+};
+}
+
+#endif
--- /dev/null
+/*
+ SPDX-FileCopyrightText: 2014 Gregory Oestreicher <greg@kamago.net>
+
+ SPDX-License-Identifier: LGPL-2.0-or-later
+*/
+
+#ifndef KDAV_DAVJOBBASE_P_H
+#define KDAV_DAVJOBBASE_P_H
+
+#include <QString>
+
+#include <memory>
+
+namespace KDAV
+{
+class DavJobBase;
+
+class DavJobBasePrivate
+{
+public:
+ virtual ~DavJobBasePrivate() = default;
+
+ /**
+ * Sets the latest response code received.
+ *
+ * Only really useful in case of error, though success codes can
+ * also be set.
+ *
+ * @param code The code to set, should be a valid HTTP response code or zero.
+ */
+ void setLatestResponseCode(int code);
+
+ void setJobErrorText(const QString &errorText);
+ void setJobError(int jobErrorCode);
+ void setErrorTextFromDavError();
+ void setDavError(const Error &error);
+
+ // forwarded protected KJob API, so we can use this from subclasses of this
+ void setError(int errorCode);
+ void setErrorText(const QString &errorText);
+ void emitResult();
+
+ DavJobBase *q_ptr = nullptr;
+ int mLatestResponseCode = 0;
+ int mJobErrorCode = 0;
+ QString mInternalErrorText;
+};
+
+}
+
+#endif
--- /dev/null
+/*
+ SPDX-FileCopyrightText: 2010 Tobias Koenig <tokoe@kde.org>
+
+ SPDX-License-Identifier: LGPL-2.0-or-later
+*/
+
+#include "davmanager_p.h"
+
+#include "protocols/caldavprotocol_p.h"
+#include "protocols/carddavprotocol_p.h"
+#include "protocols/groupdavprotocol_p.h"
+
+#include <KIO/DavJob>
+
+#include "libkdav_debug.h"
+
+#include <QUrl>
+
+using namespace KDAV;
+
+DavManager::DavManager() = default;
+DavManager::~DavManager() = default;
+
+DavManager *DavManager::self()
+{
+ static DavManager sSelf;
+ return &sSelf;
+}
+
+KIO::DavJob *DavManager::createPropFindJob(const QUrl &url, const QString &document, const QString &depth) const
+{
+ KIO::DavJob *job = KIO::davPropFind(url, document, depth, KIO::HideProgressInfo | KIO::DefaultFlags);
+
+ job->addMetaData(QStringLiteral("cookies"), QStringLiteral("none"));
+ job->addMetaData(QStringLiteral("no-auth-prompt"), QStringLiteral("true"));
+ job->setProperty("davDepth", QVariant::fromValue(depth));
+
+ return job;
+}
+
+KIO::DavJob *DavManager::createReportJob(const QUrl &url, const QString &document, const QString &depth) const
+{
+ KIO::DavJob *job = KIO::davReport(url, document, depth, KIO::HideProgressInfo | KIO::DefaultFlags);
+
+ job->addMetaData(QStringLiteral("cookies"), QStringLiteral("none"));
+ job->addMetaData(QStringLiteral("no-auth-prompt"), QStringLiteral("true"));
+ job->setProperty("davDepth", QVariant::fromValue(depth));
+
+ return job;
+}
+
+KIO::DavJob *DavManager::createPropPatchJob(const QUrl &url, const QString &document) const
+{
+ KIO::DavJob *job = KIO::davPropPatch(url, document, KIO::HideProgressInfo | KIO::DefaultFlags);
+ const QString header = QStringLiteral("Content-Type: text/xml");
+ job->addMetaData(QStringLiteral("customHTTPHeader"), header);
+ job->addMetaData(QStringLiteral("cookies"), QStringLiteral("none"));
+ job->addMetaData(QStringLiteral("no-auth-prompt"), QStringLiteral("true"));
+ return job;
+}
+
+const DavProtocolBase *DavManager::davProtocol(Protocol protocol)
+{
+ const auto d = DavManager::self();
+ if (!d->mProtocols[protocol]) {
+ switch (protocol) {
+ case KDAV::CalDav:
+ d->mProtocols[KDAV::CalDav].reset(new CaldavProtocol());
+ break;
+ case KDAV::CardDav:
+ d->mProtocols[KDAV::CardDav].reset(new CarddavProtocol());
+ break;
+ case KDAV::GroupDav:
+ d->mProtocols[KDAV::GroupDav].reset(new GroupdavProtocol());
+ break;
+ default:
+ qCCritical(KDAV_LOG) << "Unknown protocol: " << static_cast<int>(protocol);
+ return nullptr;
+ }
+ }
+
+ return d->mProtocols[protocol].get();
+}
--- /dev/null
+/*
+ SPDX-FileCopyrightText: 2010 Tobias Koenig <tokoe@kde.org>
+
+ SPDX-License-Identifier: LGPL-2.0-or-later
+*/
+
+#ifndef KDAV_DAVMANAGER_P_H
+#define KDAV_DAVMANAGER_P_H
+
+#include "enums.h"
+
+#include <QString>
+
+#include <memory>
+
+namespace KIO
+{
+class DavJob;
+}
+
+class QUrl;
+
+/** CalDav/CardDav protocol implementation. */
+namespace KDAV
+{
+class DavProtocolBase;
+
+/**
+ * @short A factory class for handling DAV jobs.
+ *
+ * This class provides factory methods to create preconfigured
+ * low-level DAV jobs and has access to the global DAV protocol dialect
+ * objects which abstract the access to the various DAV protocol dialects.
+ */
+class DavManager
+{
+public:
+ /**
+ * Destroys the DAV manager.
+ */
+ ~DavManager();
+
+ /**
+ * Returns the global instance of the DAV manager.
+ */
+ static DavManager *self();
+
+ /**
+ * Returns a preconfigured DAV PROPFIND job.
+ *
+ * @param url The target URL of the job.
+ * @param document The query XML document.
+ * @param depth The Depth: value to send in the HTTP request
+ */
+ KIO::DavJob *createPropFindJob(const QUrl &url, const QString &document, const QString &depth = QStringLiteral("1")) const;
+
+ /**
+ * Returns a preconfigured DAV REPORT job.
+ *
+ * @param url The target URL of the job.
+ * @param document The query XML document.
+ * @param depth The Depth: value to send in the HTTP request
+ */
+ KIO::DavJob *createReportJob(const QUrl &url, const QString &document, const QString &depth = QStringLiteral("1")) const;
+
+ /**
+ * Returns a preconfigured DAV PROPPATCH job.
+ *
+ * @param url The target URL of the job.
+ * @param document The query XML document.
+ */
+ KIO::DavJob *createPropPatchJob(const QUrl &url, const QString &document) const;
+
+ /**
+ * Returns the DAV protocol dialect object for the given DAV @p protocol.
+ */
+ static const DavProtocolBase *davProtocol(Protocol protocol);
+
+private:
+ /**
+ * Creates a new DAV manager.
+ */
+ DavManager();
+
+ std::unique_ptr<DavProtocolBase> mProtocols[3];
+};
+}
+
+#endif
--- /dev/null
+/*
+ SPDX-FileCopyrightText: 2010 Grégory Oestreicher <greg@kamago.net>
+
+ SPDX-License-Identifier: LGPL-2.0-or-later
+*/
+
+#include "davmultigetprotocol_p.h"
+
+using namespace KDAV;
+
+DavMultigetProtocol::~DavMultigetProtocol()
+{
+}
--- /dev/null
+/*
+ SPDX-FileCopyrightText: 2010 Grégory Oestreicher <greg@kamago.net>
+
+ SPDX-License-Identifier: LGPL-2.0-or-later
+*/
+
+#ifndef KDAV_DAVMULTIGETPROTOCOL_H
+#define KDAV_DAVMULTIGETPROTOCOL_H
+
+#include "kdav_export.h"
+
+#include "davprotocolbase_p.h"
+
+namespace KDAV
+{
+/**
+ * @short Base class for protocols that implement MULTIGET capabilities
+ */
+class DavMultigetProtocol : public DavProtocolBase
+{
+public:
+ /**
+ * Destroys the DAV protocol
+ */
+ ~DavMultigetProtocol() override;
+
+ /**
+ * Returns the XML document that represents a MULTIGET DAV query to
+ * list all DAV resources with the given @p urls.
+ */
+ virtual XMLQueryBuilder::Ptr itemsReportQuery(const QStringList &urls) const = 0;
+
+ /**
+ * Returns the namespace used by protocol-specific elements found in responses.
+ */
+ virtual QString responseNamespace() const = 0;
+
+ /**
+ * Returns the tag name of data elements found in responses.
+ */
+ virtual QString dataTagName() const = 0;
+};
+}
+
+#endif
--- /dev/null
+/*
+ SPDX-FileCopyrightText: 2010 Grégory Oestreicher <greg@kamago.net>
+
+ SPDX-License-Identifier: LGPL-2.0-or-later
+*/
+
+#include "davprincipalhomesetsfetchjob.h"
+#include "davjobbase_p.h"
+
+#include "daverror.h"
+#include "davmanager_p.h"
+#include "davprotocolbase_p.h"
+#include "protocolinfo.h"
+#include "utils_p.h"
+
+#include <KIO/DavJob>
+#include <KIO/Job>
+
+using namespace KDAV;
+
+namespace KDAV
+{
+class DavPrincipalHomeSetsFetchJobPrivate : public DavJobBasePrivate
+{
+public:
+ void davJobFinished(KJob *job);
+ /**
+ * Start the fetch process.
+ *
+ * There may be two rounds necessary if the first request
+ * does not returns the home sets, but only the current-user-principal
+ * or the principal-URL. The bool flag is here to prevent requesting
+ * those last two on each request, as they are only fetched in
+ * the first round.
+ *
+ * @param fetchHomeSetsOnly If set to true the request will not include
+ * the current-user-principal and principal-URL props.
+ */
+ void fetchHomeSets(bool fetchHomeSetsOnly);
+
+ DavUrl mUrl;
+ QStringList mHomeSets;
+};
+}
+
+DavPrincipalHomeSetsFetchJob::DavPrincipalHomeSetsFetchJob(const DavUrl &url, QObject *parent)
+ : DavJobBase(new DavPrincipalHomeSetsFetchJobPrivate, parent)
+{
+ Q_D(DavPrincipalHomeSetsFetchJob);
+ d->mUrl = url;
+}
+
+void DavPrincipalHomeSetsFetchJob::start()
+{
+ Q_D(DavPrincipalHomeSetsFetchJob);
+ d->fetchHomeSets(false);
+}
+
+void DavPrincipalHomeSetsFetchJobPrivate::fetchHomeSets(bool homeSetsOnly)
+{
+ QDomDocument document;
+
+ QDomElement propfindElement = document.createElementNS(QStringLiteral("DAV:"), QStringLiteral("propfind"));
+ document.appendChild(propfindElement);
+
+ QDomElement propElement = document.createElementNS(QStringLiteral("DAV:"), QStringLiteral("prop"));
+ propfindElement.appendChild(propElement);
+
+ const QString homeSet = ProtocolInfo::principalHomeSet(mUrl.protocol());
+ const QString homeSetNS = ProtocolInfo::principalHomeSetNS(mUrl.protocol());
+ propElement.appendChild(document.createElementNS(homeSetNS, homeSet));
+
+ if (!homeSetsOnly) {
+ propElement.appendChild(document.createElementNS(QStringLiteral("DAV:"), QStringLiteral("current-user-principal")));
+ propElement.appendChild(document.createElementNS(QStringLiteral("DAV:"), QStringLiteral("principal-URL")));
+ }
+
+ KIO::DavJob *job = DavManager::self()->createPropFindJob(mUrl.url(), document.toString(), QStringLiteral("0"));
+ job->addMetaData(QStringLiteral("PropagateHttpHeader"), QStringLiteral("true"));
+ QObject::connect(job, &KIO::DavJob::result, q_ptr, [this](KJob *job) {
+ davJobFinished(job);
+ });
+}
+
+QStringList DavPrincipalHomeSetsFetchJob::homeSets() const
+{
+ Q_D(const DavPrincipalHomeSetsFetchJob);
+ return d->mHomeSets;
+}
+
+void DavPrincipalHomeSetsFetchJobPrivate::davJobFinished(KJob *job)
+{
+ KIO::DavJob *davJob = qobject_cast<KIO::DavJob *>(job);
+ const QString responseCodeStr = davJob->queryMetaData(QStringLiteral("responsecode"));
+ const int responseCode = responseCodeStr.isEmpty() ? 0 : responseCodeStr.toInt();
+
+ // KIO::DavJob does not set error() even if the HTTP status code is a 4xx or a 5xx
+ if (davJob->error() || (responseCode >= 400 && responseCode < 600)) {
+ QString err;
+ if (davJob->error() && davJob->error() != KIO::ERR_WORKER_DEFINED) {
+ err = KIO::buildErrorString(davJob->error(), davJob->errorText());
+ } else {
+ err = davJob->errorText();
+ }
+
+ setLatestResponseCode(responseCode);
+ setError(ERR_PROBLEM_WITH_REQUEST);
+ setJobErrorText(davJob->errorText());
+ setJobError(davJob->error());
+ setErrorTextFromDavError();
+
+ emitResult();
+ return;
+ }
+
+ /*
+ * Extract information from a document like the following (if no homeset is defined) :
+ *
+ * <D:multistatus xmlns:D="DAV:">
+ * <D:response xmlns:D="DAV:">
+ * <D:href xmlns:D="DAV:">/dav/</D:href>
+ * <D:propstat xmlns:D="DAV:">
+ * <D:status xmlns:D="DAV:">HTTP/1.1 200 OK</D:status>
+ * <D:prop xmlns:D="DAV:">
+ * <D:current-user-principal xmlns:D="DAV:">
+ * <D:href xmlns:D="DAV:">/principals/users/gdacoin/</D:href>
+ * </D:current-user-principal>
+ * </D:prop>
+ * </D:propstat>
+ * <D:propstat xmlns:D="DAV:">
+ * <D:status xmlns:D="DAV:">HTTP/1.1 404 Not Found</D:status>
+ * <D:prop xmlns:D="DAV:">
+ * <principal-URL xmlns="DAV:"/>
+ * <calendar-home-set xmlns="urn:ietf:params:xml:ns:caldav"/>
+ * </D:prop>
+ * </D:propstat>
+ * </D:response>
+ * </D:multistatus>
+ *
+ * Or like this (if the homeset is defined):
+ *
+ * <?xml version="1.0" encoding="utf-8" ?>
+ * <multistatus xmlns="DAV:" xmlns:C="urn:ietf:params:xml:ns:caldav">
+ * <response>
+ * <href>/principals/users/greg%40kamago.net/</href>
+ * <propstat>
+ * <prop>
+ * <C:calendar-home-set>
+ * <href>/greg%40kamago.net/</href>
+ * </C:calendar-home-set>
+ * </prop>
+ * <status>HTTP/1.1 200 OK</status>
+ * </propstat>
+ * </response>
+ * </multistatus>
+ */
+
+ const QString homeSet = ProtocolInfo::principalHomeSet(mUrl.protocol());
+ const QString homeSetNS = ProtocolInfo::principalHomeSetNS(mUrl.protocol());
+ QString nextRoundHref; // The content of the href element that will be used if no homeset was found.
+ // This is either given by current-user-principal or by principal-URL.
+
+ QDomDocument document;
+ document.setContent(davJob->responseData(), true);
+ const QDomElement multistatusElement = document.documentElement();
+
+ QDomElement responseElement = Utils::firstChildElementNS(multistatusElement, QStringLiteral("DAV:"), QStringLiteral("response"));
+ while (!responseElement.isNull()) {
+ QDomElement propstatElement;
+
+ // check for the valid propstat, without giving up on first error
+ {
+ const QDomNodeList propstats = responseElement.elementsByTagNameNS(QStringLiteral("DAV:"), QStringLiteral("propstat"));
+ for (int i = 0; i < propstats.length(); ++i) {
+ const QDomElement propstatCandidate = propstats.item(i).toElement();
+ const QDomElement statusElement = Utils::firstChildElementNS(propstatCandidate, QStringLiteral("DAV:"), QStringLiteral("status"));
+ if (statusElement.text().contains(QLatin1String("200"))) {
+ propstatElement = propstatCandidate;
+ }
+ }
+ }
+
+ if (propstatElement.isNull()) {
+ responseElement = Utils::nextSiblingElementNS(responseElement, QStringLiteral("DAV:"), QStringLiteral("response"));
+ continue;
+ }
+
+ // extract home sets
+ const QDomElement propElement = Utils::firstChildElementNS(propstatElement, QStringLiteral("DAV:"), QStringLiteral("prop"));
+ const QDomElement homeSetElement = Utils::firstChildElementNS(propElement, homeSetNS, homeSet);
+
+ if (!homeSetElement.isNull()) {
+ QDomElement hrefElement = Utils::firstChildElementNS(homeSetElement, QStringLiteral("DAV:"), QStringLiteral("href"));
+
+ while (!hrefElement.isNull()) {
+ const QString href = hrefElement.text();
+ if (!mHomeSets.contains(href)) {
+ mHomeSets << href;
+ }
+
+ hrefElement = Utils::nextSiblingElementNS(hrefElement, QStringLiteral("DAV:"), QStringLiteral("href"));
+ }
+ } else {
+ // Trying to get the principal url, given either by current-user-principal or principal-URL
+ QDomElement urlHolder = Utils::firstChildElementNS(propElement, QStringLiteral("DAV:"), QStringLiteral("current-user-principal"));
+ if (urlHolder.isNull()) {
+ urlHolder = Utils::firstChildElementNS(propElement, QStringLiteral("DAV:"), QStringLiteral("principal-URL"));
+ }
+
+ if (!urlHolder.isNull()) {
+ // Getting the href that will be used for the next round
+ QDomElement hrefElement = Utils::firstChildElementNS(urlHolder, QStringLiteral("DAV:"), QStringLiteral("href"));
+ if (!hrefElement.isNull()) {
+ nextRoundHref = hrefElement.text();
+ }
+ }
+ }
+
+ responseElement = Utils::nextSiblingElementNS(responseElement, QStringLiteral("DAV:"), QStringLiteral("response"));
+ }
+
+ /*
+ * Now either we got one or more homesets, or we got an href for the next round
+ * or nothing can be found by this job.
+ * If we have homesets, we're done here and can notify the caller.
+ * Else we must ensure that we have an href for the next round.
+ */
+ if (!mHomeSets.isEmpty() || nextRoundHref.isEmpty()) {
+ emitResult();
+ } else {
+ QUrl nextRoundUrl(mUrl.url());
+
+ if (nextRoundHref.startsWith(QLatin1Char('/'))) {
+ // nextRoundHref is only a path, use request url to complete
+ nextRoundUrl.setPath(nextRoundHref, QUrl::TolerantMode);
+ } else {
+ // href is a complete url
+ nextRoundUrl = QUrl::fromUserInput(nextRoundHref);
+ nextRoundUrl.setUserName(mUrl.url().userName());
+ nextRoundUrl.setPassword(mUrl.url().password());
+ }
+
+ mUrl.setUrl(nextRoundUrl);
+ // And one more round, fetching only homesets
+ fetchHomeSets(true);
+ }
+}
--- /dev/null
+/*
+ SPDX-FileCopyrightText: 2010 Grégory Oestreicher <greg@kamago.net>
+
+ SPDX-License-Identifier: LGPL-2.0-or-later
+*/
+
+#ifndef KDAV_DAVPRINCIPALHOMESETSFETCHJOB_H
+#define KDAV_DAVPRINCIPALHOMESETSFETCHJOB_H
+
+#include "kdav_export.h"
+
+#include "davjobbase.h"
+#include "davurl.h"
+
+#include <QStringList>
+
+namespace KDAV
+{
+class DavPrincipalHomeSetsFetchJobPrivate;
+
+/**
+ * @class DavPrincipalHomeSetsFetchJob davprincipalhomesetsfetchjob.h <KDAV/DavPrincipalHomeSetsFetchJob>
+ *
+ * @short A job that fetches home sets for a principal.
+ */
+class KDAV_EXPORT DavPrincipalHomeSetsFetchJob : public DavJobBase
+{
+ Q_OBJECT
+
+public:
+ /**
+ * Creates a new DAV principals home sets fetch job.
+ *
+ * @param url The DAV URL of the DAV principal.
+ * @param parent The parent object.
+ */
+ explicit DavPrincipalHomeSetsFetchJob(const DavUrl &url, QObject *parent = nullptr);
+
+ /**
+ * Starts the job.
+ */
+ void start() override;
+
+ /**
+ * Returns the found home sets.
+ */
+ Q_REQUIRED_RESULT QStringList homeSets() const;
+
+private:
+ Q_DECLARE_PRIVATE(DavPrincipalHomeSetsFetchJob)
+};
+}
+
+#endif
--- /dev/null
+/*
+ SPDX-FileCopyrightText: 2011 Grégory Oestreicher <greg@kamago.net>
+
+ SPDX-License-Identifier: LGPL-2.0-or-later
+*/
+
+#include "davprincipalsearchjob.h"
+#include "davjobbase_p.h"
+
+#include "daverror.h"
+#include "davmanager_p.h"
+#include "utils_p.h"
+
+#include <KIO/DavJob>
+#include <KIO/Job>
+
+#include <QUrl>
+
+using namespace KDAV;
+
+namespace KDAV
+{
+class DavPrincipalSearchJobPrivate : public DavJobBasePrivate
+{
+public:
+ void buildReportQuery(QDomDocument &query) const;
+ void principalCollectionSetSearchFinished(KJob *job);
+ void principalPropertySearchFinished(KJob *job);
+
+ DavUrl mUrl;
+ DavPrincipalSearchJob::FilterType mType;
+ QString mFilter;
+ int mPrincipalPropertySearchSubJobCount = 0;
+ bool mPrincipalPropertySearchSubJobSuccessful = false;
+ struct PropertyInfo {
+ QString propNS;
+ QString propName;
+ };
+ std::vector<PropertyInfo> mFetchProperties;
+ QVector<DavPrincipalSearchJob::Result> mResults;
+};
+}
+
+DavPrincipalSearchJob::DavPrincipalSearchJob(const DavUrl &url, DavPrincipalSearchJob::FilterType type, const QString &filter, QObject *parent)
+ : DavJobBase(new DavPrincipalSearchJobPrivate, parent)
+{
+ Q_D(DavPrincipalSearchJob);
+ d->mUrl = url;
+ d->mType = type;
+ d->mFilter = filter;
+}
+
+void DavPrincipalSearchJob::fetchProperty(const QString &name, const QString &ns)
+{
+ Q_D(DavPrincipalSearchJob);
+ d->mFetchProperties.push_back({!ns.isEmpty() ? ns : QStringLiteral("DAV:"), name});
+}
+
+DavUrl DavPrincipalSearchJob::davUrl() const
+{
+ Q_D(const DavPrincipalSearchJob);
+ return d->mUrl;
+}
+
+void DavPrincipalSearchJob::start()
+{
+ Q_D(DavPrincipalSearchJob);
+ /*
+ * The first step is to try to locate the URL that contains the principals.
+ * This is done with a PROPFIND request and a XML like this:
+ * <?xml version="1.0" encoding="utf-8" ?>
+ * <D:propfind xmlns:D="DAV:">
+ * <D:prop>
+ * <D:principal-collection-set/>
+ * </D:prop>
+ * </D:propfind>
+ */
+ QDomDocument query;
+
+ QDomElement propfind = query.createElementNS(QStringLiteral("DAV:"), QStringLiteral("propfind"));
+ query.appendChild(propfind);
+
+ QDomElement prop = query.createElementNS(QStringLiteral("DAV:"), QStringLiteral("prop"));
+ propfind.appendChild(prop);
+
+ QDomElement principalCollectionSet = query.createElementNS(QStringLiteral("DAV:"), QStringLiteral("principal-collection-set"));
+ prop.appendChild(principalCollectionSet);
+
+ KIO::DavJob *job = DavManager::self()->createPropFindJob(d->mUrl.url(), query.toString());
+ job->addMetaData(QStringLiteral("PropagateHttpHeader"), QStringLiteral("true"));
+ connect(job, &KIO::DavJob::result, this, [d](KJob *job) {
+ d->principalCollectionSetSearchFinished(job);
+ });
+ job->start();
+}
+
+void DavPrincipalSearchJobPrivate::principalCollectionSetSearchFinished(KJob *job)
+{
+ KIO::DavJob *davJob = qobject_cast<KIO::DavJob *>(job);
+ const QString responseCodeStr = davJob->queryMetaData(QStringLiteral("responsecode"));
+ const int responseCode = responseCodeStr.isEmpty() ? 0 : responseCodeStr.toInt();
+ // KIO::DavJob does not set error() even if the HTTP status code is a 4xx or a 5xx
+ if (davJob->error() || (responseCode >= 400 && responseCode < 600)) {
+ setLatestResponseCode(responseCode);
+ setError(ERR_PROBLEM_WITH_REQUEST);
+ setJobErrorText(davJob->errorText());
+ setJobError(davJob->error());
+ setErrorTextFromDavError();
+
+ emitResult();
+ return;
+ }
+
+ if (job->error()) {
+ setError(job->error());
+ setErrorText(job->errorText());
+ emitResult();
+ return;
+ }
+
+ /*
+ * Extract information from a document like the following:
+ *
+ * <?xml version="1.0" encoding="utf-8" ?>
+ * <D:multistatus xmlns:D="DAV:">
+ * <D:response>
+ * <D:href>http://www.example.com/papers/</D:href>
+ * <D:propstat>
+ * <D:prop>
+ * <D:principal-collection-set>
+ * <D:href>http://www.example.com/acl/users/</D:href>
+ * <D:href>http://www.example.com/acl/groups/</D:href>
+ * </D:principal-collection-set>
+ * </D:prop>
+ * <D:status>HTTP/1.1 200 OK</D:status>
+ * </D:propstat>
+ * </D:response>
+ * </D:multistatus>
+ */
+
+ QDomDocument document;
+ document.setContent(davJob->responseData(), true);
+ QDomElement documentElement = document.documentElement();
+
+ QDomElement responseElement = Utils::firstChildElementNS(documentElement, QStringLiteral("DAV:"), QStringLiteral("response"));
+ if (responseElement.isNull()) {
+ emitResult();
+ return;
+ }
+
+ // check for the valid propstat, without giving up on first error
+ QDomElement propstatElement;
+ {
+ const QDomNodeList propstats = responseElement.elementsByTagNameNS(QStringLiteral("DAV:"), QStringLiteral("propstat"));
+ for (int i = 0; i < propstats.length(); ++i) {
+ const QDomElement propstatCandidate = propstats.item(i).toElement();
+ const QDomElement statusElement = Utils::firstChildElementNS(propstatCandidate, QStringLiteral("DAV:"), QStringLiteral("status"));
+ if (statusElement.text().contains(QLatin1String("200"))) {
+ propstatElement = propstatCandidate;
+ }
+ }
+ }
+
+ if (propstatElement.isNull()) {
+ emitResult();
+ return;
+ }
+
+ QDomElement propElement = Utils::firstChildElementNS(propstatElement, QStringLiteral("DAV:"), QStringLiteral("prop"));
+ if (propElement.isNull()) {
+ emitResult();
+ return;
+ }
+
+ QDomElement principalCollectionSetElement = Utils::firstChildElementNS(propElement, QStringLiteral("DAV:"), QStringLiteral("principal-collection-set"));
+ if (principalCollectionSetElement.isNull()) {
+ emitResult();
+ return;
+ }
+
+ QDomNodeList hrefNodes = principalCollectionSetElement.elementsByTagNameNS(QStringLiteral("DAV:"), QStringLiteral("href"));
+ for (int i = 0; i < hrefNodes.size(); ++i) {
+ QDomElement hrefElement = hrefNodes.at(i).toElement();
+ QString href = hrefElement.text();
+
+ QUrl url = mUrl.url();
+ if (href.startsWith(QLatin1Char('/'))) {
+ // href is only a path, use request url to complete
+ url.setPath(href, QUrl::TolerantMode);
+ } else {
+ // href is a complete url
+ QUrl tmpUrl(href);
+ tmpUrl.setUserName(url.userName());
+ tmpUrl.setPassword(url.password());
+ url = tmpUrl;
+ }
+
+ QDomDocument principalPropertySearchQuery;
+ buildReportQuery(principalPropertySearchQuery);
+ KIO::DavJob *reportJob = DavManager::self()->createReportJob(url, principalPropertySearchQuery.toString());
+ reportJob->addMetaData(QStringLiteral("PropagateHttpHeader"), QStringLiteral("true"));
+ QObject::connect(reportJob, &KIO::DavJob::result, q_ptr, [this](KJob *job) {
+ principalPropertySearchFinished(job);
+ });
+ ++mPrincipalPropertySearchSubJobCount;
+ reportJob->start();
+ }
+}
+
+void DavPrincipalSearchJobPrivate::principalPropertySearchFinished(KJob *job)
+{
+ --mPrincipalPropertySearchSubJobCount;
+
+ if (job->error() && !mPrincipalPropertySearchSubJobSuccessful) {
+ setError(job->error());
+ setErrorText(job->errorText());
+ if (mPrincipalPropertySearchSubJobCount == 0) {
+ emitResult();
+ }
+ return;
+ }
+
+ KIO::DavJob *davJob = qobject_cast<KIO::DavJob *>(job);
+
+ const int responseCode = davJob->queryMetaData(QStringLiteral("responsecode")).toInt();
+
+ if (responseCode > 499 && responseCode < 600 && !mPrincipalPropertySearchSubJobSuccessful) {
+ // Server-side error, unrecoverable
+ setLatestResponseCode(responseCode);
+ setError(ERR_SERVER_UNRECOVERABLE);
+ setJobErrorText(davJob->errorText());
+ setJobError(davJob->error());
+ setErrorTextFromDavError();
+ if (mPrincipalPropertySearchSubJobCount == 0) {
+ emitResult();
+ }
+ return;
+ } else if (responseCode > 399 && responseCode < 500 && !mPrincipalPropertySearchSubJobSuccessful) {
+ setLatestResponseCode(responseCode);
+ setError(ERR_PROBLEM_WITH_REQUEST);
+ setJobErrorText(davJob->errorText());
+ setJobError(davJob->error());
+ setErrorTextFromDavError();
+
+ if (mPrincipalPropertySearchSubJobCount == 0) {
+ emitResult();
+ }
+ return;
+ }
+
+ if (!mPrincipalPropertySearchSubJobSuccessful) {
+ setError(0); // nope, everything went fine
+ mPrincipalPropertySearchSubJobSuccessful = true;
+ }
+
+ /*
+ * Extract infos from a document like the following:
+ * <?xml version="1.0" encoding="utf-8" ?>
+ * <D:multistatus xmlns:D="DAV:" xmlns:B="http://BigCorp.com/ns/">
+ * <D:response>
+ * <D:href>http://www.example.com/users/jdoe</D:href>
+ * <D:propstat>
+ * <D:prop>
+ * <D:displayname>John Doe</D:displayname>
+ * </D:prop>
+ * <D:status>HTTP/1.1 200 OK</D:status>
+ * </D:propstat>
+ * </D:multistatus>
+ */
+
+ QDomDocument document;
+ document.setContent(davJob->responseData(), true);
+ const QDomElement documentElement = document.documentElement();
+
+ QDomElement responseElement = Utils::firstChildElementNS(documentElement, QStringLiteral("DAV:"), QStringLiteral("response"));
+ if (responseElement.isNull()) {
+ if (mPrincipalPropertySearchSubJobCount == 0) {
+ emitResult();
+ }
+ return;
+ }
+
+ // check for the valid propstat, without giving up on first error
+ QDomElement propstatElement;
+ {
+ const QDomNodeList propstats = responseElement.elementsByTagNameNS(QStringLiteral("DAV:"), QStringLiteral("propstat"));
+ const int propStatsEnd(propstats.length());
+ for (int i = 0; i < propStatsEnd; ++i) {
+ const QDomElement propstatCandidate = propstats.item(i).toElement();
+ const QDomElement statusElement = Utils::firstChildElementNS(propstatCandidate, QStringLiteral("DAV:"), QStringLiteral("status"));
+ if (statusElement.text().contains(QLatin1String("200"))) {
+ propstatElement = propstatCandidate;
+ }
+ }
+ }
+
+ if (propstatElement.isNull()) {
+ if (mPrincipalPropertySearchSubJobCount == 0) {
+ emitResult();
+ }
+ return;
+ }
+
+ QDomElement propElement = Utils::firstChildElementNS(propstatElement, QStringLiteral("DAV:"), QStringLiteral("prop"));
+ if (propElement.isNull()) {
+ if (mPrincipalPropertySearchSubJobCount == 0) {
+ emitResult();
+ }
+ return;
+ }
+
+ // All requested properties are now under propElement, so let's find them
+ for (const auto &[propNS, propName] : mFetchProperties) {
+ const QDomNodeList fetchNodes = propElement.elementsByTagNameNS(propNS, propName);
+ mResults.reserve(mResults.size() + fetchNodes.size());
+ for (int i = 0; i < fetchNodes.size(); ++i) {
+ const QDomElement fetchElement = fetchNodes.at(i).toElement();
+ mResults.push_back({propNS, propName, fetchElement.text()});
+ }
+ }
+
+ if (mPrincipalPropertySearchSubJobCount == 0) {
+ emitResult();
+ }
+}
+
+QVector<DavPrincipalSearchJob::Result> DavPrincipalSearchJob::results() const
+{
+ Q_D(const DavPrincipalSearchJob);
+ return d->mResults;
+}
+
+void DavPrincipalSearchJobPrivate::buildReportQuery(QDomDocument &query) const
+{
+ /*
+ * Build a document like the following, where XXX will
+ * be replaced by the properties the user want to fetch:
+ *
+ * <?xml version="1.0" encoding="utf-8" ?>
+ * <D:principal-property-search xmlns:D="DAV:">
+ * <D:property-search>
+ * <D:prop>
+ * <D:displayname/>
+ * </D:prop>
+ * <D:match>FILTER</D:match>
+ * </D:property-search>
+ * <D:prop>
+ * XXX
+ * </D:prop>
+ * </D:principal-property-search>
+ */
+
+ QDomElement principalPropertySearch = query.createElementNS(QStringLiteral("DAV:"), QStringLiteral("principal-property-search"));
+ query.appendChild(principalPropertySearch);
+
+ QDomElement propertySearch = query.createElementNS(QStringLiteral("DAV:"), QStringLiteral("property-search"));
+ principalPropertySearch.appendChild(propertySearch);
+
+ QDomElement prop = query.createElementNS(QStringLiteral("DAV:"), QStringLiteral("prop"));
+ propertySearch.appendChild(prop);
+
+ if (mType == DavPrincipalSearchJob::DisplayName) {
+ QDomElement displayName = query.createElementNS(QStringLiteral("DAV:"), QStringLiteral("displayname"));
+ prop.appendChild(displayName);
+ } else if (mType == DavPrincipalSearchJob::EmailAddress) {
+ QDomElement calendarUserAddressSet =
+ query.createElementNS(QStringLiteral("urn:ietf:params:xml:ns:caldav"), QStringLiteral("calendar-user-address-set"));
+ prop.appendChild(calendarUserAddressSet);
+ // QDomElement hrefElement = query.createElementNS( "DAV:", "href" );
+ // prop.appendChild( hrefElement );
+ }
+
+ QDomElement match = query.createElementNS(QStringLiteral("DAV:"), QStringLiteral("match"));
+ propertySearch.appendChild(match);
+
+ QDomText propFilter = query.createTextNode(mFilter);
+ match.appendChild(propFilter);
+
+ prop = query.createElementNS(QStringLiteral("DAV:"), QStringLiteral("prop"));
+ principalPropertySearch.appendChild(prop);
+
+ for (const auto &[propNS, propName] : mFetchProperties) {
+ QDomElement elem = query.createElementNS(propNS, propName);
+ prop.appendChild(elem);
+ }
+}
--- /dev/null
+/*
+ SPDX-FileCopyrightText: 2011 Grégory Oestreicher <greg@kamago.net>
+
+ SPDX-License-Identifier: LGPL-2.0-or-later
+*/
+
+#ifndef KDAV_DAVPRINCIPALSEARCHJOB_H
+#define KDAV_DAVPRINCIPALSEARCHJOB_H
+
+#include "kdav_export.h"
+
+#include "davjobbase.h"
+#include "davurl.h"
+
+#include <QString>
+
+namespace KDAV
+{
+class DavPrincipalSearchJobPrivate;
+
+/**
+ * @class DavPrincipalSearchJob davprincipalsearchjob.h <KDAV/DavPrincipalSearchJob>
+ *
+ * @short A job that search a DAV principal on a server
+ *
+ * This job is used to search a principal on a server
+ * that implement the dav-property-search REPORT (RFC3744).
+ *
+ * The properties to fetch are set with @ref fetchProperty().
+ */
+class KDAV_EXPORT DavPrincipalSearchJob : public DavJobBase
+{
+ Q_OBJECT
+
+public:
+ /**
+ * Types of search that are supported by this job.
+ * DisplayName will match on the DAV displayname property.
+ * EmailAddress will match on the CalDav calendar-user-address-set property.
+ */
+ enum FilterType {
+ DisplayName,
+ EmailAddress,
+ };
+
+ /**
+ * Simple struct to hold the search job results
+ */
+ struct Result {
+ QString propertyNamespace;
+ QString property;
+ QString value;
+ };
+
+ /**
+ * Creates a new DAV principal search job
+ *
+ * @param url The URL to use in the REPORT query.
+ * @param type The type that the filter will match.
+ * @param filter The filter that will be used to match the displayname attribute.
+ * @param parent The parent object.
+ */
+ explicit DavPrincipalSearchJob(const DavUrl &url, FilterType type, const QString &filter, QObject *parent = nullptr);
+
+ /**
+ * Add a new property to fetch from the server.
+ *
+ * @param name The name of the property.
+ * @param ns The namespace of this property, defaults to 'DAV:'.
+ */
+ void fetchProperty(const QString &name, const QString &ns = QString());
+
+ /**
+ * Starts the job
+ */
+ void start() override;
+
+ /**
+ * Return the DavUrl used by this job
+ */
+ Q_REQUIRED_RESULT DavUrl davUrl() const;
+
+ /**
+ * Get the job results.
+ */
+ Q_REQUIRED_RESULT QVector<Result> results() const;
+
+private:
+ Q_DECLARE_PRIVATE(DavPrincipalSearchJob)
+};
+}
+
+Q_DECLARE_TYPEINFO(KDAV::DavPrincipalSearchJob::Result, Q_MOVABLE_TYPE);
+#endif
--- /dev/null
+/*
+ SPDX-FileCopyrightText: 2009 Grégory Oestreicher <greg@kamago.net>
+
+ SPDX-License-Identifier: LGPL-2.0-or-later
+*/
+
+#include "davprotocolbase_p.h"
+
+#include <QVariant>
+
+using namespace KDAV;
+
+XMLQueryBuilder::~XMLQueryBuilder()
+{
+}
+
+void XMLQueryBuilder::setParameter(const QString &key, const QVariant &value)
+{
+ mParameters[key] = value;
+}
+
+QVariant XMLQueryBuilder::parameter(const QString &key) const
+{
+ QVariant ret;
+ if (mParameters.contains(key)) {
+ ret = mParameters.value(key);
+ }
+ return ret;
+}
+
+DavProtocolBase::~DavProtocolBase()
+{
+}
+
+QString DavProtocolBase::principalHomeSet() const
+{
+ return QString();
+}
+
+QString DavProtocolBase::principalHomeSetNS() const
+{
+ return QString();
+}
--- /dev/null
+/*
+ SPDX-FileCopyrightText: 2009 Grégory Oestreicher <greg@kamago.net>
+
+ SPDX-License-Identifier: LGPL-2.0-or-later
+*/
+
+#ifndef KDAV_DAVPROTOCOLBASE_H
+#define KDAV_DAVPROTOCOLBASE_H
+
+#include "kdav_export.h"
+
+#include "davcollection.h"
+
+#include <QDomDocument>
+#include <QMap>
+#include <QVariant>
+#include <memory>
+
+namespace KDAV
+{
+/**
+ * @short Base class for XML query builders
+ */
+class XMLQueryBuilder
+{
+public:
+ typedef std::shared_ptr<XMLQueryBuilder> Ptr;
+
+ virtual ~XMLQueryBuilder();
+
+ virtual QDomDocument buildQuery() const = 0;
+ virtual QString mimeType() const = 0;
+
+ void setParameter(const QString &key, const QVariant &value);
+ QVariant parameter(const QString &key) const;
+
+private:
+ QMap<QString, QVariant> mParameters;
+};
+
+/**
+ * @short Base class for various DAV groupware dialects.
+ *
+ * This class provides an interface to query the DAV dialect
+ * specific features and abstract them.
+ *
+ * The functionality is implemented in:
+ * @li CaldavProtocol
+ * @li CarddavProtocol
+ * @li GroupdavProtocol
+ */
+class DavProtocolBase
+{
+public:
+ /**
+ * Destroys the DAV protocol base.
+ */
+ virtual ~DavProtocolBase();
+
+ /**
+ * Returns whether the DAV protocol dialect supports principal
+ * queries. If true, it must return the home set it provides
+ * access to with principalHomeSet() and the home set namespace
+ * with principalHomeSetNS();
+ */
+ virtual bool supportsPrincipals() const = 0;
+
+ /**
+ * Returns whether the DAV protocol dialect supports the REPORT
+ * command to query all resources of a collection.
+ * If not, PROPFIND command will be used instead.
+ */
+ virtual bool useReport() const = 0;
+
+ /**
+ * Returns whether the DAV protocol dialect supports the MULTIGET command.
+ *
+ * If MULTIGET is supported, the content of all DAV resources
+ * can be fetched in Akonadi::ResourceBase::retrieveItems() already and
+ * there is no need to call Akonadi::ResourceBase::retrieveItem() for every single
+ * DAV resource.
+ *
+ * Protocols that have MULTIGET capabilities must inherit from
+ * DavMultigetProtocol instead of this class.
+ */
+ virtual bool useMultiget() const = 0;
+
+ /**
+ * Returns the home set that this protocol supports.
+ */
+ virtual QString principalHomeSet() const;
+
+ /**
+ * Returns the namespace of the home set.
+ */
+ virtual QString principalHomeSetNS() const;
+
+ /**
+ * Returns the XML document that represents the DAV query to
+ * list all available DAV collections.
+ */
+ virtual XMLQueryBuilder::Ptr collectionsQuery() const = 0;
+
+ /**
+ * Returns @c true if the given <prop> element of a multistatus response contains a
+ * valid collection for this protocol.
+ */
+ virtual bool containsCollection(const QDomElement &propElem) const = 0;
+
+ /**
+ * Returns a list of XML documents that represent DAV queries to
+ * list all available DAV resources inside a specific DAV collection.
+ */
+ virtual QVector<XMLQueryBuilder::Ptr> itemsQueries() const = 0;
+
+ /**
+ * Returns the possible content types for the collection that
+ * is described by the passed @p propstat element of a PROPFIND result.
+ */
+ virtual DavCollection::ContentTypes collectionContentTypes(const QDomElement &propstat) const = 0;
+};
+}
+
+#endif
--- /dev/null
+/*
+ SPDX-FileCopyrightText: 2010 Tobias Koenig <tokoe@kde.org>
+
+ SPDX-License-Identifier: LGPL-2.0-or-later
+*/
+
+#include "davurl.h"
+
+
+using namespace KDAV;
+
+namespace KDAV
+{
+class DavUrlPrivate : public QSharedData
+{
+public:
+ Protocol mProtocol = KDAV::CalDav;
+ QUrl mUrl;
+};
+}
+
+DavUrl::DavUrl()
+ : d(new DavUrlPrivate)
+{
+}
+
+DavUrl::DavUrl(const QUrl &url, Protocol protocol)
+ : d(new DavUrlPrivate)
+{
+ d->mUrl = url;
+ d->mProtocol = protocol;
+}
+
+DavUrl::DavUrl(const DavUrl &) = default;
+DavUrl::DavUrl(DavUrl &&) = default;
+DavUrl::~DavUrl() = default;
+DavUrl &DavUrl::operator=(const DavUrl &) = default;
+DavUrl &DavUrl::operator=(DavUrl &&) = default;
+
+void DavUrl::setUrl(const QUrl &url)
+{
+ d->mUrl = url;
+}
+
+QUrl DavUrl::url() const
+{
+ return d->mUrl;
+}
+
+void DavUrl::setProtocol(Protocol protocol)
+{
+ d->mProtocol = protocol;
+}
+
+Protocol DavUrl::protocol() const
+{
+ return d->mProtocol;
+}
+
+QString DavUrl::toDisplayString() const
+{
+ auto url = d->mUrl;
+ url.setUserInfo(QString());
+ return url.toDisplayString();
+}
+
+QDataStream &KDAV::operator<<(QDataStream &stream, const DavUrl &url)
+{
+ stream << QString::number(url.protocol());
+ stream << url.url();
+
+ return stream;
+}
+
+QDataStream &KDAV::operator>>(QDataStream &stream, DavUrl &davUrl)
+{
+ QUrl url;
+ QString p;
+
+ stream >> p;
+ stream >> url;
+
+ davUrl = DavUrl(url, static_cast<Protocol>(p.toInt()));
+
+ return stream;
+}
--- /dev/null
+/*
+ SPDX-FileCopyrightText: 2010 Tobias Koenig <tokoe@kde.org>
+
+ SPDX-License-Identifier: LGPL-2.0-or-later
+*/
+
+#ifndef KDAV_DAVURL_H
+#define KDAV_DAVURL_H
+
+#include "kdav_export.h"
+
+#include "enums.h"
+
+#include <QSharedDataPointer>
+#include <QUrl>
+#include <QVector>
+
+namespace KDAV
+{
+class DavUrlPrivate;
+/**
+ * @class DavUrl davurl.h <KDAV/DavUrl>
+ *
+ * @short A helper class to combine URL and protocol of a DAV URL.
+ */
+class KDAV_EXPORT DavUrl
+{
+public:
+ /**
+ * Defines a list of DAV URL objects.
+ */
+ typedef QVector<DavUrl> List;
+
+ /**
+ * Creates an empty DAV URL.
+ */
+ DavUrl();
+ DavUrl(const DavUrl &);
+ DavUrl(DavUrl &&);
+ ~DavUrl();
+ DavUrl &operator=(const DavUrl &);
+ DavUrl &operator=(DavUrl &&);
+
+ /**
+ * Creates a new DAV URL.
+ *
+ * @param url The URL that identifies the DAV object.
+ * @param protocol The DAV protocol dialect that is used to retrieve the DAV object.
+ */
+ DavUrl(const QUrl &url, Protocol protocol);
+
+ /**
+ * Sets the @p url that identifies the DAV object.
+ */
+ void setUrl(const QUrl &url);
+
+ /**
+ * Returns the URL that identifies the DAV object.
+ */
+ Q_REQUIRED_RESULT QUrl url() const;
+
+ /**
+ * Returns the URL in a user-friendly way without login information.
+ */
+ Q_REQUIRED_RESULT QString toDisplayString() const;
+
+ /**
+ * Sets the DAV @p protocol dialect that is used to retrieve the DAV object.
+ */
+ void setProtocol(Protocol protocol);
+
+ /**
+ * Returns the DAV protocol dialect that is used to retrieve the DAV object.
+ */
+ Q_REQUIRED_RESULT Protocol protocol() const;
+
+private:
+ QSharedDataPointer<DavUrlPrivate> d;
+};
+
+KDAV_EXPORT QDataStream &operator<<(QDataStream &out, const DavUrl &url);
+KDAV_EXPORT QDataStream &operator>>(QDataStream &in, DavUrl &url);
+}
+
+Q_DECLARE_TYPEINFO(KDAV::DavUrl, Q_MOVABLE_TYPE);
+
+#endif
--- /dev/null
+/*
+ SPDX-FileCopyrightText: 2010 Tobias Koenig <tokoe@kde.org>
+
+ SPDX-License-Identifier: LGPL-2.0-or-later
+*/
+
+#ifndef KDAV_ENUMS_H
+#define KDAV_ENUMS_H
+
+#include <QFlags>
+
+/**
+ * The KDAV namespace.
+ */
+namespace KDAV
+{
+/**
+ * Describes the DAV protocol dialect.
+ */
+enum Protocol {
+ CalDav = 0, ///< The CalDav protocol as defined in https://devguide.calconnect.org/CalDAV
+ CardDav, ///< The CardDav protocol as defined in https://devguide.calconnect.org/CardDAV
+ GroupDav, ///< The GroupDav protocol as defined in http://www.groupdav.org
+};
+
+/**
+ * Describes the DAV privileges on a resource (see RFC3744)
+ */
+enum Privilege {
+ None = 0x0,
+ Read = 0x1,
+ Write = 0x2,
+ WriteProperties = 0x4,
+ WriteContent = 0x8,
+ Unlock = 0x10,
+ ReadAcl = 0x20,
+ ReadCurrentUserPrivilegeSet = 0x40,
+ WriteAcl = 0x80,
+ Bind = 0x100,
+ Unbind = 0x200,
+ All = 0x400,
+};
+Q_DECLARE_FLAGS(Privileges, Privilege)
+Q_DECLARE_OPERATORS_FOR_FLAGS(Privileges)
+}
+
+#endif
--- /dev/null
+/*
+ SPDX-FileCopyrightText: 2010 Grégory Oestreicher <greg@kamago.net>
+
+ SPDX-License-Identifier: LGPL-2.0-or-later
+*/
+
+#include "etagcache.h"
+
+#include <QMap>
+#include <QSet>
+
+using namespace KDAV;
+
+namespace KDAV
+{
+class EtagCachePrivate
+{
+public:
+ QMap<QString, QString> mCache;
+ QSet<QString> mChangedRemoteIds;
+};
+}
+
+EtagCache::EtagCache(QObject *parent)
+ : QObject(parent)
+ , d(new EtagCachePrivate)
+{
+}
+
+EtagCache::~EtagCache() = default;
+
+void EtagCache::setEtag(const QString &remoteId, const QString &etag)
+{
+ setEtagInternal(remoteId, etag);
+
+ d->mChangedRemoteIds.remove(remoteId);
+}
+
+void EtagCache::setEtagInternal(const QString &remoteId, const QString &etag)
+{
+ d->mCache[remoteId] = etag;
+}
+
+bool EtagCache::contains(const QString &remoteId) const
+{
+ return d->mCache.contains(remoteId);
+}
+
+bool EtagCache::etagChanged(const QString &remoteId, const QString &refEtag) const
+{
+ if (!contains(remoteId)) {
+ return true;
+ }
+ return d->mCache.value(remoteId) != refEtag;
+}
+
+void EtagCache::markAsChanged(const QString &remoteId)
+{
+ d->mChangedRemoteIds.insert(remoteId);
+}
+
+bool EtagCache::isOutOfDate(const QString &remoteId) const
+{
+ return d->mChangedRemoteIds.contains(remoteId);
+}
+
+void EtagCache::removeEtag(const QString &remoteId)
+{
+ d->mChangedRemoteIds.remove(remoteId);
+ d->mCache.remove(remoteId);
+}
+
+QMap<QString, QString> EtagCache::etagCacheMap() const
+{
+ return d->mCache;
+}
+
+QStringList EtagCache::urls() const
+{
+ return d->mCache.keys();
+}
+
+QStringList EtagCache::changedRemoteIds() const
+{
+ return d->mChangedRemoteIds.values();
+}
--- /dev/null
+/*
+ SPDX-FileCopyrightText: 2010 Grégory Oestreicher <greg@kamago.net>
+
+ SPDX-License-Identifier: LGPL-2.0-or-later
+*/
+
+#ifndef KDAV_ETAGCACHE_H
+#define KDAV_ETAGCACHE_H
+
+#include "kdav_export.h"
+
+#include <QObject>
+#include <QStringList>
+
+#include <memory>
+
+namespace KDAV
+{
+class EtagCachePrivate;
+
+/**
+ * @class EtagCache etagcache.h <KDAV/EtagCache>
+ *
+ * @short A helper class to cache ETags.
+ *
+ * The EtagCache caches the remote ids and ETags of all items
+ * in a given collection. This cache is needed to find
+ * out which items have been changed in the backend and have to
+ * be refetched on the next call of Akonadi::ResourceBase::retrieveItems()
+ */
+class KDAV_EXPORT EtagCache : public QObject
+{
+ Q_OBJECT
+
+public:
+ /**
+ * Creates a new ETag cache and populates it with the ETags
+ * of items found in @p collection.
+ */
+ explicit EtagCache(QObject *parent = nullptr);
+ ~EtagCache() override;
+
+ /**
+ * Sets the ETag for the remote ID. If the remote ID is marked as
+ * changed (is contained in the return of changedRemoteIds), remove
+ * it from the changed list.
+ */
+ void setEtag(const QString &remoteId, const QString &etag);
+
+ /**
+ * Checks if the given item is in the cache
+ */
+ Q_REQUIRED_RESULT bool contains(const QString &remoteId) const;
+
+ /**
+ * Check if the known ETag for the remote ID is equal to @p refEtag.
+ */
+ Q_REQUIRED_RESULT bool etagChanged(const QString &remoteId, const QString &refEtag) const;
+
+ /**
+ * Mark an item as changed in the backend.
+ */
+ void markAsChanged(const QString &remoteId);
+
+ /**
+ * Returns true if the remote ID is marked as changed (is contained in the
+ * return of changedRemoteIds)
+ */
+ Q_REQUIRED_RESULT bool isOutOfDate(const QString &remoteId) const;
+
+ /**
+ * Removes the entry for item with remote ID @p remoteId.
+ */
+ void removeEtag(const QString &remoteId);
+
+ /**
+ * Returns the list of all items URLs.
+ */
+ Q_REQUIRED_RESULT QStringList urls() const;
+
+ /**
+ * Returns the list of remote ids of items that have been changed
+ * in the backend.
+ */
+ Q_REQUIRED_RESULT QStringList changedRemoteIds() const;
+
+protected:
+ /**
+ * Sets the ETag for the remote ID.
+ */
+ void setEtagInternal(const QString &remoteId, const QString &etag);
+
+private:
+ const std::unique_ptr<EtagCachePrivate> d;
+
+ friend class DavItemsListJobPrivate;
+ // @internal
+ // Returns a map of remote Id and corresponding etag string key/value pairs.
+ // Only used by DavItemsListJobPrivate
+ Q_DECL_HIDDEN QMap<QString, QString> etagCacheMap() const;
+};
+}
+
+#endif
--- /dev/null
+/*
+ SPDX-FileCopyrightText: 2010 Tobias Koenig <tokoe@kde.org>
+
+ SPDX-License-Identifier: LGPL-2.0-or-later
+*/
+
+#include "protocolinfo.h"
+#include "davmanager_p.h"
+#include "davprotocolbase_p.h"
+#include "libkdav_debug.h"
+
+using namespace KDAV;
+
+bool ProtocolInfo::useMultiget(KDAV::Protocol protocol)
+{
+ return DavManager::davProtocol(protocol)->useMultiget();
+}
+
+QString ProtocolInfo::principalHomeSet(KDAV::Protocol protocol)
+{
+ return DavManager::davProtocol(protocol)->principalHomeSet();
+}
+
+QString ProtocolInfo::principalHomeSetNS(KDAV::Protocol protocol)
+{
+ return DavManager::davProtocol(protocol)->principalHomeSetNS();
+}
+
+QString ProtocolInfo::protocolName(KDAV::Protocol protocol)
+{
+ switch (protocol) {
+ case KDAV::CalDav:
+ return QStringLiteral("CalDav");
+ case KDAV::CardDav:
+ return QStringLiteral("CardDav");
+ case KDAV::GroupDav:
+ return QStringLiteral("GroupDav");
+ }
+ return {};
+}
+
+KDAV::Protocol ProtocolInfo::protocolByName(const QString &name)
+{
+ Protocol protocol = KDAV::CalDav;
+
+ if (name == QLatin1String("CalDav")) {
+ protocol = KDAV::CalDav;
+ } else if (name == QLatin1String("CardDav")) {
+ protocol = KDAV::CardDav;
+ } else if (name == QLatin1String("GroupDav")) {
+ protocol = KDAV::GroupDav;
+ } else {
+ qCCritical(KDAV_LOG) << "Unexpected protocol name : " << name;
+ }
+
+ return protocol;
+}
+
+QString ProtocolInfo::contactsMimeType(KDAV::Protocol protocol)
+{
+ QString ret;
+
+ if (protocol == KDAV::CardDav) {
+ ret = QStringLiteral("text/vcard");
+ } else if (protocol == KDAV::GroupDav) {
+ ret = QStringLiteral("text/x-vcard");
+ }
+
+ return ret;
+}
--- /dev/null
+/*
+ SPDX-FileCopyrightText: 2019 Volker Krause <vkrause@kde.org>
+
+ SPDX-License-Identifier: LGPL-2.0-or-later
+*/
+
+#ifndef KDAV_PROTOCOLINFO_H
+#define KDAV_PROTOCOLINFO_H
+
+#include "enums.h"
+#include "kdav_export.h"
+
+namespace KDAV
+{
+/** Information about a DAV protocol. */
+namespace ProtocolInfo
+{
+/**
+ * Returns whether the @p protocol dialect supports the MULTIGET command.
+ *
+ * If MULTIGET is supported, the content of all DAV resources
+ * can be fetched in Akonadi::ResourceBase::retrieveItems() already and
+ * there is no need to call Akonadi::ResourceBase::retrieveItem() for every single
+ * DAV resource.
+ */
+Q_REQUIRED_RESULT KDAV_EXPORT bool useMultiget(KDAV::Protocol protocol);
+
+/** Returns the principal home set of @p protocol. */
+Q_REQUIRED_RESULT KDAV_EXPORT QString principalHomeSet(KDAV::Protocol protocol);
+
+/** Returns the principal home set namespace of @p protocol. */
+Q_REQUIRED_RESULT KDAV_EXPORT QString principalHomeSetNS(KDAV::Protocol protocol);
+
+/**
+ * Returns the untranslated name of the given DAV @p protocol dialect.
+ */
+Q_REQUIRED_RESULT KDAV_EXPORT QString protocolName(KDAV::Protocol protocol);
+
+/**
+ * Returns the protocol matching the given name. This is the opposite of
+ * ProtocolInfo::protocolName().
+ */
+Q_REQUIRED_RESULT KDAV_EXPORT KDAV::Protocol protocolByName(const QString &name);
+
+/**
+ * Returns the mimetype that shall be used for contact DAV resources using @p protocol.
+ */
+Q_REQUIRED_RESULT KDAV_EXPORT QString contactsMimeType(KDAV::Protocol protocol);
+}
+
+}
+
+#endif // KDAV_PROTOCOLINFO_H
--- /dev/null
+/*
+ SPDX-FileCopyrightText: 2010 Tobias Koenig <tokoe@kde.org>
+
+ SPDX-License-Identifier: LGPL-2.0-or-later
+*/
+
+#include "utils_p.h"
+
+#include "enums.h"
+
+#include <QString>
+
+using namespace KDAV;
+
+QDomElement Utils::firstChildElementNS(const QDomElement &parent, const QString &namespaceUri, const QString &tagName)
+{
+ for (QDomNode child = parent.firstChild(); !child.isNull(); child = child.nextSibling()) {
+ if (child.isElement()) {
+ const QDomElement elt = child.toElement();
+ if (tagName.isEmpty() || (elt.tagName() == tagName && elt.namespaceURI() == namespaceUri)) {
+ return elt;
+ }
+ }
+ }
+
+ return QDomElement();
+}
+
+QDomElement Utils::nextSiblingElementNS(const QDomElement &element, const QString &namespaceUri, const QString &tagName)
+{
+ for (QDomNode sib = element.nextSibling(); !sib.isNull(); sib = sib.nextSibling()) {
+ if (sib.isElement()) {
+ const QDomElement elt = sib.toElement();
+ if (tagName.isEmpty() || (elt.tagName() == tagName && elt.namespaceURI() == namespaceUri)) {
+ return elt;
+ }
+ }
+ }
+
+ return QDomElement();
+}
+
+Privileges Utils::extractPrivileges(const QDomElement &element)
+{
+ Privileges final = None;
+ QDomElement privElement = firstChildElementNS(element, QStringLiteral("DAV:"), QStringLiteral("privilege"));
+
+ while (!privElement.isNull()) {
+ QDomElement child = privElement.firstChildElement();
+
+ while (!child.isNull()) {
+ final |= parsePrivilege(child);
+ child = child.nextSiblingElement();
+ }
+
+ privElement = Utils::nextSiblingElementNS(privElement, QStringLiteral("DAV:"), QStringLiteral("privilege"));
+ }
+
+ return final;
+}
+
+Privileges Utils::parsePrivilege(const QDomElement &element)
+{
+ Privileges final = None;
+
+ if (!element.childNodes().isEmpty()) {
+ // This is an aggregate privilege, parse each of its children
+ QDomElement child = element.firstChildElement();
+ while (!child.isNull()) {
+ final |= parsePrivilege(child);
+ child = child.nextSiblingElement();
+ }
+ } else {
+ // This is a normal privilege
+ const QString privname = element.localName();
+
+ if (privname == QLatin1String("read")) {
+ final |= KDAV::Read;
+ } else if (privname == QLatin1String("write")) {
+ final |= KDAV::Write;
+ } else if (privname == QLatin1String("write-properties")) {
+ final |= KDAV::WriteProperties;
+ } else if (privname == QLatin1String("write-content")) {
+ final |= KDAV::WriteContent;
+ } else if (privname == QLatin1String("unlock")) {
+ final |= KDAV::Unlock;
+ } else if (privname == QLatin1String("read-acl")) {
+ final |= KDAV::ReadAcl;
+ } else if (privname == QLatin1String("read-current-user-privilege-set")) {
+ final |= KDAV::ReadCurrentUserPrivilegeSet;
+ } else if (privname == QLatin1String("write-acl")) {
+ final |= KDAV::WriteAcl;
+ } else if (privname == QLatin1String("bind")) {
+ final |= KDAV::Bind;
+ } else if (privname == QLatin1String("unbind")) {
+ final |= KDAV::Unbind;
+ } else if (privname == QLatin1String("all")) {
+ final |= KDAV::All;
+ }
+ }
+
+ return final;
+}
--- /dev/null
+/*
+ SPDX-FileCopyrightText: 2010 Tobias Koenig <tokoe@kde.org>
+
+ SPDX-License-Identifier: LGPL-2.0-or-later
+*/
+
+#ifndef KDAV_DAVUTILS_P_H
+#define KDAV_DAVUTILS_P_H
+
+#include "enums.h"
+
+#include <QDomElement>
+
+namespace KDAV
+{
+namespace Utils
+{
+/**
+ * Returns the first child element of @p parent that has the given @p tagName and is part of the @p namespaceUri.
+ */
+Q_REQUIRED_RESULT QDomElement firstChildElementNS(const QDomElement &parent, const QString &namespaceUri, const QString &tagName);
+
+/**
+ * Returns the next sibling element of @p element that has the given @p tagName and is part of the @p namespaceUri.
+ */
+Q_REQUIRED_RESULT QDomElement nextSiblingElementNS(const QDomElement &element, const QString &namespaceUri, const QString &tagName);
+
+/**
+ * Extracts privileges from @p element. The <privilege/> tags are expected to be first level children of @p element.
+ */
+Q_REQUIRED_RESULT Privileges extractPrivileges(const QDomElement &element);
+
+/**
+ * Parses a single <privilege/> tag and returns the final Privileges.
+ */
+Q_REQUIRED_RESULT Privileges parsePrivilege(const QDomElement &element);
+
+}
+}
+
+#endif
--- /dev/null
+/*
+ SPDX-FileCopyrightText: 2009 Grégory Oestreicher <greg@kamago.net>
+
+ SPDX-License-Identifier: LGPL-2.0-or-later
+*/
+
+#include "caldavprotocol_p.h"
+#include "common/utils_p.h"
+
+#include <QDomDocument>
+#include <QStringList>
+#include <QUrl>
+
+using namespace KDAV;
+
+class CaldavCollectionQueryBuilder : public XMLQueryBuilder
+{
+public:
+ QDomDocument buildQuery() const override
+ {
+ QDomDocument document;
+
+ QDomElement propfindElement = document.createElementNS(QStringLiteral("DAV:"), QStringLiteral("propfind"));
+ document.appendChild(propfindElement);
+
+ QDomElement propElement = document.createElementNS(QStringLiteral("DAV:"), QStringLiteral("prop"));
+ propfindElement.appendChild(propElement);
+
+ propElement.appendChild(document.createElementNS(QStringLiteral("DAV:"), QStringLiteral("displayname")));
+ propElement.appendChild(document.createElementNS(QStringLiteral("DAV:"), QStringLiteral("resourcetype")));
+ propElement.appendChild(document.createElementNS(QStringLiteral("http://apple.com/ns/ical/"), QStringLiteral("calendar-color")));
+ propElement.appendChild(document.createElementNS(QStringLiteral("urn:ietf:params:xml:ns:caldav"), QStringLiteral("supported-calendar-component-set")));
+ propElement.appendChild(document.createElementNS(QStringLiteral("DAV:"), QStringLiteral("current-user-privilege-set")));
+ propElement.appendChild(document.createElementNS(QStringLiteral("http://calendarserver.org/ns/"), QStringLiteral("getctag")));
+
+ return document;
+ }
+
+ QString mimeType() const override
+ {
+ return QString();
+ }
+};
+
+class CaldavListEventQueryBuilder : public XMLQueryBuilder
+{
+public:
+ QDomDocument buildQuery() const override
+ {
+ QString startTime = parameter(QStringLiteral("start")).toString();
+ QString endTime = parameter(QStringLiteral("end")).toString();
+ QDomDocument document;
+
+ QDomElement queryElement = document.createElementNS(QStringLiteral("urn:ietf:params:xml:ns:caldav"), QStringLiteral("calendar-query"));
+ document.appendChild(queryElement);
+
+ QDomElement propElement = document.createElementNS(QStringLiteral("DAV:"), QStringLiteral("prop"));
+ queryElement.appendChild(propElement);
+
+ QDomElement getetagElement = document.createElementNS(QStringLiteral("DAV:"), QStringLiteral("getetag"));
+ propElement.appendChild(getetagElement);
+
+ QDomElement getRTypeElement = document.createElementNS(QStringLiteral("DAV:"), QStringLiteral("resourcetype"));
+ propElement.appendChild(getRTypeElement);
+
+ QDomElement filterElement = document.createElementNS(QStringLiteral("urn:ietf:params:xml:ns:caldav"), QStringLiteral("filter"));
+ queryElement.appendChild(filterElement);
+
+ QDomElement compfilterElement = document.createElementNS(QStringLiteral("urn:ietf:params:xml:ns:caldav"), QStringLiteral("comp-filter"));
+
+ QDomAttr nameAttribute = document.createAttribute(QStringLiteral("name"));
+ nameAttribute.setValue(QStringLiteral("VCALENDAR"));
+ compfilterElement.setAttributeNode(nameAttribute);
+ filterElement.appendChild(compfilterElement);
+
+ QDomElement subcompfilterElement = document.createElementNS(QStringLiteral("urn:ietf:params:xml:ns:caldav"), QStringLiteral("comp-filter"));
+ nameAttribute = document.createAttribute(QStringLiteral("name"));
+ nameAttribute.setValue(QStringLiteral("VEVENT"));
+ subcompfilterElement.setAttributeNode(nameAttribute);
+
+ if (!startTime.isEmpty() || !endTime.isEmpty()) {
+ QDomElement timeRangeElement = document.createElementNS(QStringLiteral("urn:ietf:params:xml:ns:caldav"), QStringLiteral("time-range"));
+
+ if (!startTime.isEmpty()) {
+ QDomAttr startAttribute = document.createAttribute(QStringLiteral("start"));
+ startAttribute.setValue(startTime);
+ timeRangeElement.setAttributeNode(startAttribute);
+ }
+
+ if (!endTime.isEmpty()) {
+ QDomAttr endAttribute = document.createAttribute(QStringLiteral("end"));
+ endAttribute.setValue(endTime);
+ timeRangeElement.setAttributeNode(endAttribute);
+ }
+
+ subcompfilterElement.appendChild(timeRangeElement);
+ }
+
+ compfilterElement.appendChild(subcompfilterElement);
+
+ return document;
+ }
+
+ QString mimeType() const override
+ {
+ return QStringLiteral("application/x-vnd.akonadi.calendar.event");
+ }
+};
+
+class CaldavListTodoQueryBuilder : public XMLQueryBuilder
+{
+public:
+ QDomDocument buildQuery() const override
+ {
+ QString startTime = parameter(QStringLiteral("start")).toString();
+ QString endTime = parameter(QStringLiteral("end")).toString();
+ QDomDocument document;
+
+ QDomElement queryElement = document.createElementNS(QStringLiteral("urn:ietf:params:xml:ns:caldav"), QStringLiteral("calendar-query"));
+ document.appendChild(queryElement);
+
+ QDomElement propElement = document.createElementNS(QStringLiteral("DAV:"), QStringLiteral("prop"));
+ queryElement.appendChild(propElement);
+
+ QDomElement getetagElement = document.createElementNS(QStringLiteral("DAV:"), QStringLiteral("getetag"));
+ propElement.appendChild(getetagElement);
+
+ QDomElement getRTypeElement = document.createElementNS(QStringLiteral("DAV:"), QStringLiteral("resourcetype"));
+ propElement.appendChild(getRTypeElement);
+
+ QDomElement filterElement = document.createElementNS(QStringLiteral("urn:ietf:params:xml:ns:caldav"), QStringLiteral("filter"));
+ queryElement.appendChild(filterElement);
+
+ QDomElement compfilterElement = document.createElementNS(QStringLiteral("urn:ietf:params:xml:ns:caldav"), QStringLiteral("comp-filter"));
+
+ QDomAttr nameAttribute = document.createAttribute(QStringLiteral("name"));
+ nameAttribute.setValue(QStringLiteral("VCALENDAR"));
+ compfilterElement.setAttributeNode(nameAttribute);
+ filterElement.appendChild(compfilterElement);
+
+ QDomElement subcompfilterElement = document.createElementNS(QStringLiteral("urn:ietf:params:xml:ns:caldav"), QStringLiteral("comp-filter"));
+ nameAttribute = document.createAttribute(QStringLiteral("name"));
+ nameAttribute.setValue(QStringLiteral("VTODO"));
+ subcompfilterElement.setAttributeNode(nameAttribute);
+
+ if (!startTime.isEmpty() || !endTime.isEmpty()) {
+ QDomElement timeRangeElement = document.createElementNS(QStringLiteral("urn:ietf:params:xml:ns:caldav"), QStringLiteral("time-range"));
+
+ if (!startTime.isEmpty()) {
+ QDomAttr startAttribute = document.createAttribute(QStringLiteral("start"));
+ startAttribute.setValue(startTime);
+ timeRangeElement.setAttributeNode(startAttribute);
+ }
+
+ if (!endTime.isEmpty()) {
+ QDomAttr endAttribute = document.createAttribute(QStringLiteral("end"));
+ endAttribute.setValue(endTime);
+ timeRangeElement.setAttributeNode(endAttribute);
+ }
+
+ subcompfilterElement.appendChild(timeRangeElement);
+ }
+
+ compfilterElement.appendChild(subcompfilterElement);
+
+ return document;
+ }
+
+ QString mimeType() const override
+ {
+ return QStringLiteral("application/x-vnd.akonadi.calendar.todo");
+ }
+};
+
+class CaldavListJournalQueryBuilder : public XMLQueryBuilder
+{
+public:
+ QDomDocument buildQuery() const override
+ {
+ QString startTime = parameter(QStringLiteral("start")).toString();
+ QString endTime = parameter(QStringLiteral("end")).toString();
+ QDomDocument document;
+
+ QDomElement queryElement = document.createElementNS(QStringLiteral("urn:ietf:params:xml:ns:caldav"), QStringLiteral("calendar-query"));
+ document.appendChild(queryElement);
+
+ QDomElement propElement = document.createElementNS(QStringLiteral("DAV:"), QStringLiteral("prop"));
+ queryElement.appendChild(propElement);
+
+ QDomElement getetagElement = document.createElementNS(QStringLiteral("DAV:"), QStringLiteral("getetag"));
+ propElement.appendChild(getetagElement);
+
+ QDomElement getRTypeElement = document.createElementNS(QStringLiteral("DAV:"), QStringLiteral("resourcetype"));
+ propElement.appendChild(getRTypeElement);
+
+ QDomElement filterElement = document.createElementNS(QStringLiteral("urn:ietf:params:xml:ns:caldav"), QStringLiteral("filter"));
+ queryElement.appendChild(filterElement);
+
+ QDomElement compfilterElement = document.createElementNS(QStringLiteral("urn:ietf:params:xml:ns:caldav"), QStringLiteral("comp-filter"));
+
+ QDomAttr nameAttribute = document.createAttribute(QStringLiteral("name"));
+ nameAttribute.setValue(QStringLiteral("VCALENDAR"));
+ compfilterElement.setAttributeNode(nameAttribute);
+ filterElement.appendChild(compfilterElement);
+
+ QDomElement subcompfilterElement = document.createElementNS(QStringLiteral("urn:ietf:params:xml:ns:caldav"), QStringLiteral("comp-filter"));
+ nameAttribute = document.createAttribute(QStringLiteral("name"));
+ nameAttribute.setValue(QStringLiteral("VJOURNAL"));
+ subcompfilterElement.setAttributeNode(nameAttribute);
+
+ if (!startTime.isEmpty() || !endTime.isEmpty()) {
+ QDomElement timeRangeElement = document.createElementNS(QStringLiteral("urn:ietf:params:xml:ns:caldav"), QStringLiteral("time-range"));
+
+ if (!startTime.isEmpty()) {
+ QDomAttr startAttribute = document.createAttribute(QStringLiteral("start"));
+ startAttribute.setValue(startTime);
+ timeRangeElement.setAttributeNode(startAttribute);
+ }
+
+ if (!endTime.isEmpty()) {
+ QDomAttr endAttribute = document.createAttribute(QStringLiteral("end"));
+ endAttribute.setValue(endTime);
+ timeRangeElement.setAttributeNode(endAttribute);
+ }
+
+ subcompfilterElement.appendChild(timeRangeElement);
+ }
+
+ compfilterElement.appendChild(subcompfilterElement);
+
+ return document;
+ }
+
+ QString mimeType() const override
+ {
+ return QStringLiteral("application/x-vnd.akonadi.calendar.journal");
+ }
+};
+
+class CaldavMultigetQueryBuilder : public XMLQueryBuilder
+{
+public:
+ QDomDocument buildQuery() const override
+ {
+ QDomDocument document;
+ const QStringList urls = parameter(QStringLiteral("urls")).toStringList();
+ if (urls.isEmpty()) {
+ return document;
+ }
+
+ QDomElement multigetElement = document.createElementNS(QStringLiteral("urn:ietf:params:xml:ns:caldav"), QStringLiteral("calendar-multiget"));
+ document.appendChild(multigetElement);
+
+ QDomElement propElement = document.createElementNS(QStringLiteral("DAV:"), QStringLiteral("prop"));
+ multigetElement.appendChild(propElement);
+
+ propElement.appendChild(document.createElementNS(QStringLiteral("DAV:"), QStringLiteral("getetag")));
+ propElement.appendChild(document.createElementNS(QStringLiteral("urn:ietf:params:xml:ns:caldav"), QStringLiteral("calendar-data")));
+
+ for (const QString &url : urls) {
+ QDomElement hrefElement = document.createElementNS(QStringLiteral("DAV:"), QStringLiteral("href"));
+ const QUrl pathUrl = QUrl::fromUserInput(url);
+ const QDomText textNode = document.createTextNode(pathUrl.path());
+ hrefElement.appendChild(textNode);
+
+ multigetElement.appendChild(hrefElement);
+ }
+
+ return document;
+ }
+
+ QString mimeType() const override
+ {
+ return QString();
+ }
+};
+
+CaldavProtocol::CaldavProtocol()
+{
+}
+
+bool CaldavProtocol::supportsPrincipals() const
+{
+ return true;
+}
+
+bool CaldavProtocol::useReport() const
+{
+ return true;
+}
+
+bool CaldavProtocol::useMultiget() const
+{
+ return true;
+}
+
+QString CaldavProtocol::principalHomeSet() const
+{
+ return QStringLiteral("calendar-home-set");
+}
+
+QString CaldavProtocol::principalHomeSetNS() const
+{
+ return QStringLiteral("urn:ietf:params:xml:ns:caldav");
+}
+
+XMLQueryBuilder::Ptr CaldavProtocol::collectionsQuery() const
+{
+ return XMLQueryBuilder::Ptr(new CaldavCollectionQueryBuilder());
+}
+
+bool CaldavProtocol::containsCollection(const QDomElement &propElem) const
+{
+ return !propElem.elementsByTagNameNS(QStringLiteral("urn:ietf:params:xml:ns:caldav"), QStringLiteral("calendar")).isEmpty();
+}
+
+QVector<XMLQueryBuilder::Ptr> CaldavProtocol::itemsQueries() const
+{
+ QVector<XMLQueryBuilder::Ptr> ret;
+ ret << XMLQueryBuilder::Ptr(new CaldavListEventQueryBuilder());
+ ret << XMLQueryBuilder::Ptr(new CaldavListTodoQueryBuilder());
+ ret << XMLQueryBuilder::Ptr(new CaldavListJournalQueryBuilder());
+ return ret;
+}
+
+XMLQueryBuilder::Ptr CaldavProtocol::itemsReportQuery(const QStringList &urls) const
+{
+ XMLQueryBuilder::Ptr ret(new CaldavMultigetQueryBuilder());
+ ret->setParameter(QStringLiteral("urls"), urls);
+ return ret;
+}
+
+QString CaldavProtocol::responseNamespace() const
+{
+ return QStringLiteral("urn:ietf:params:xml:ns:caldav");
+}
+
+QString CaldavProtocol::dataTagName() const
+{
+ return QStringLiteral("calendar-data");
+}
+
+DavCollection::ContentTypes CaldavProtocol::collectionContentTypes(const QDomElement &propstatElement) const
+{
+ /*
+ * Extract the content type information from a propstat like the following
+ * <propstat xmlns="DAV:">
+ * <prop xmlns="DAV:">
+ * <C:supported-calendar-component-set xmlns:C="urn:ietf:params:xml:ns:caldav">
+ * <C:comp xmlns:C="urn:ietf:params:xml:ns:caldav" name="VEVENT"/>
+ * <C:comp xmlns:C="urn:ietf:params:xml:ns:caldav" name="VTODO"/>
+ * <C:comp xmlns:C="urn:ietf:params:xml:ns:caldav" name="VJOURNAL"/>
+ * <C:comp xmlns:C="urn:ietf:params:xml:ns:caldav" name="VTIMEZONE"/>
+ * <C:comp xmlns:C="urn:ietf:params:xml:ns:caldav" name="VFREEBUSY"/>
+ * </C:supported-calendar-component-set>
+ * <resourcetype xmlns="DAV:">
+ * <collection xmlns="DAV:"/>
+ * <C:calendar xmlns:C="urn:ietf:params:xml:ns:caldav"/>
+ * <C:schedule-calendar xmlns:C="urn:ietf:params:xml:ns:caldav"/>
+ * </resourcetype>
+ * <displayname xmlns="DAV:">Test1 User</displayname>
+ * </prop>
+ * <status xmlns="DAV:">HTTP/1.1 200 OK</status>
+ * </propstat>
+ */
+
+ const QDomElement propElement = Utils::firstChildElementNS(propstatElement, QStringLiteral("DAV:"), QStringLiteral("prop"));
+ const QDomElement supportedcomponentElement = Utils::firstChildElementNS(propElement, //
+ QStringLiteral("urn:ietf:params:xml:ns:caldav"),
+ QStringLiteral("supported-calendar-component-set"));
+
+ DavCollection::ContentTypes contentTypes;
+ QDomElement compElement = Utils::firstChildElementNS(supportedcomponentElement, QStringLiteral("urn:ietf:params:xml:ns:caldav"), QStringLiteral("comp"));
+
+ /*
+ * Assign the content-type if the server didn't return anything.
+ * According to RFC4791, §5.2.3:
+ * In the absence of this property, the server MUST accept all
+ * component types, and the client can assume that all component
+ * types are accepted.
+ */
+ if (compElement.isNull()) {
+ contentTypes |= DavCollection::Calendar;
+ contentTypes |= DavCollection::Events;
+ contentTypes |= DavCollection::Todos;
+ contentTypes |= DavCollection::FreeBusy;
+ contentTypes |= DavCollection::Journal;
+ }
+
+ while (!compElement.isNull()) {
+ const QString type = compElement.attribute(QStringLiteral("name")).toLower();
+ if (type == QLatin1String("vcalendar")) {
+ contentTypes |= DavCollection::Calendar;
+ } else if (type == QLatin1String("vevent")) {
+ contentTypes |= DavCollection::Events;
+ } else if (type == QLatin1String("vtodo")) {
+ contentTypes |= DavCollection::Todos;
+ } else if (type == QLatin1String("vfreebusy")) {
+ contentTypes |= DavCollection::FreeBusy;
+ } else if (type == QLatin1String("vjournal")) {
+ contentTypes |= DavCollection::Journal;
+ }
+
+ compElement = Utils::nextSiblingElementNS(compElement, QStringLiteral("urn:ietf:params:xml:ns:caldav"), QStringLiteral("comp"));
+ }
+
+ return contentTypes;
+}
--- /dev/null
+/*
+ SPDX-FileCopyrightText: 2009 Grégory Oestreicher <greg@kamago.net>
+
+ SPDX-License-Identifier: LGPL-2.0-or-later
+*/
+
+#ifndef KDAV_CALDAVPROTOCOL_H
+#define KDAV_CALDAVPROTOCOL_H
+
+#include "common/davmultigetprotocol_p.h"
+
+class CaldavProtocol : public KDAV::DavMultigetProtocol
+{
+public:
+ CaldavProtocol();
+ Q_REQUIRED_RESULT bool supportsPrincipals() const override;
+ Q_REQUIRED_RESULT bool useReport() const override;
+ Q_REQUIRED_RESULT bool useMultiget() const override;
+ Q_REQUIRED_RESULT QString principalHomeSet() const override;
+ Q_REQUIRED_RESULT QString principalHomeSetNS() const override;
+ Q_REQUIRED_RESULT KDAV::XMLQueryBuilder::Ptr collectionsQuery() const override;
+ Q_REQUIRED_RESULT bool containsCollection(const QDomElement &propElem) const override;
+ Q_REQUIRED_RESULT QVector<KDAV::XMLQueryBuilder::Ptr> itemsQueries() const override;
+ Q_REQUIRED_RESULT KDAV::XMLQueryBuilder::Ptr itemsReportQuery(const QStringList &urls) const override;
+ Q_REQUIRED_RESULT QString responseNamespace() const override;
+ Q_REQUIRED_RESULT QString dataTagName() const override;
+
+ Q_REQUIRED_RESULT KDAV::DavCollection::ContentTypes collectionContentTypes(const QDomElement &propstat) const override;
+};
+
+#endif
--- /dev/null
+/*
+ SPDX-FileCopyrightText: 2010 Tobias Koenig <tokoe@kde.org>
+
+ SPDX-License-Identifier: LGPL-2.0-or-later
+*/
+
+#include "carddavprotocol_p.h"
+
+#include <QDomDocument>
+#include <QStringList>
+#include <QUrl>
+
+using namespace KDAV;
+
+class CarddavCollectionQueryBuilder : public XMLQueryBuilder
+{
+public:
+ QDomDocument buildQuery() const override
+ {
+ QDomDocument document;
+
+ QDomElement propfindElement = document.createElementNS(QStringLiteral("DAV:"), QStringLiteral("propfind"));
+ document.appendChild(propfindElement);
+
+ QDomElement propElement = document.createElementNS(QStringLiteral("DAV:"), QStringLiteral("prop"));
+ propfindElement.appendChild(propElement);
+
+ propElement.appendChild(document.createElementNS(QStringLiteral("DAV:"), QStringLiteral("displayname")));
+ propElement.appendChild(document.createElementNS(QStringLiteral("DAV:"), QStringLiteral("resourcetype")));
+ propElement.appendChild(document.createElementNS(QStringLiteral("http://calendarserver.org/ns/"), QStringLiteral("getctag")));
+
+ return document;
+ }
+
+ QString mimeType() const override
+ {
+ return QString();
+ }
+};
+
+class CarddavListItemsQueryBuilder : public XMLQueryBuilder
+{
+public:
+ QDomDocument buildQuery() const override
+ {
+ QDomDocument document;
+
+ QDomElement propfindElement = document.createElementNS(QStringLiteral("DAV:"), QStringLiteral("propfind"));
+ document.appendChild(propfindElement);
+
+ QDomElement propElement = document.createElementNS(QStringLiteral("DAV:"), QStringLiteral("prop"));
+ propfindElement.appendChild(propElement);
+
+ propElement.appendChild(document.createElementNS(QStringLiteral("DAV:"), QStringLiteral("displayname")));
+ propElement.appendChild(document.createElementNS(QStringLiteral("DAV:"), QStringLiteral("resourcetype")));
+ propElement.appendChild(document.createElementNS(QStringLiteral("DAV:"), QStringLiteral("getetag")));
+
+ return document;
+ }
+
+ QString mimeType() const override
+ {
+ return QStringLiteral("text/directory");
+ }
+};
+
+class CarddavMultigetQueryBuilder : public XMLQueryBuilder
+{
+public:
+ QDomDocument buildQuery() const override
+ {
+ QDomDocument document;
+ const QStringList urls = parameter(QStringLiteral("urls")).toStringList();
+ if (urls.isEmpty()) {
+ return document;
+ }
+
+ QDomElement multigetElement = document.createElementNS(QStringLiteral("urn:ietf:params:xml:ns:carddav"), QStringLiteral("addressbook-multiget"));
+ document.appendChild(multigetElement);
+
+ QDomElement propElement = document.createElementNS(QStringLiteral("DAV:"), QStringLiteral("prop"));
+ multigetElement.appendChild(propElement);
+
+ propElement.appendChild(document.createElementNS(QStringLiteral("DAV:"), QStringLiteral("getetag")));
+ QDomElement addressDataElement = document.createElementNS(QStringLiteral("urn:ietf:params:xml:ns:carddav"), QStringLiteral("address-data"));
+ addressDataElement.appendChild(document.createElementNS(QStringLiteral("DAV:"), QStringLiteral("allprop")));
+ propElement.appendChild(addressDataElement);
+
+ for (const QString &url : urls) {
+ QDomElement hrefElement = document.createElementNS(QStringLiteral("DAV:"), QStringLiteral("href"));
+ const QUrl pathUrl = QUrl::fromUserInput(url);
+ const QDomText textNode = document.createTextNode(pathUrl.toString());
+ hrefElement.appendChild(textNode);
+
+ multigetElement.appendChild(hrefElement);
+ }
+
+ return document;
+ }
+
+ QString mimeType() const override
+ {
+ return QString();
+ }
+};
+
+CarddavProtocol::CarddavProtocol()
+{
+}
+
+bool CarddavProtocol::supportsPrincipals() const
+{
+ return true;
+}
+
+bool CarddavProtocol::useReport() const
+{
+ return false;
+}
+
+bool CarddavProtocol::useMultiget() const
+{
+ return true;
+}
+
+QString CarddavProtocol::principalHomeSet() const
+{
+ return QStringLiteral("addressbook-home-set");
+}
+
+QString CarddavProtocol::principalHomeSetNS() const
+{
+ return QStringLiteral("urn:ietf:params:xml:ns:carddav");
+}
+
+XMLQueryBuilder::Ptr CarddavProtocol::collectionsQuery() const
+{
+ return XMLQueryBuilder::Ptr(new CarddavCollectionQueryBuilder());
+}
+
+bool CarddavProtocol::containsCollection(const QDomElement &propElem) const
+{
+ return !propElem.elementsByTagNameNS(QStringLiteral("urn:ietf:params:xml:ns:carddav"), QStringLiteral("addressbook")).isEmpty();
+}
+
+QVector<XMLQueryBuilder::Ptr> CarddavProtocol::itemsQueries() const
+{
+ QVector<XMLQueryBuilder::Ptr> ret;
+ ret << XMLQueryBuilder::Ptr(new CarddavListItemsQueryBuilder());
+ return ret;
+}
+
+XMLQueryBuilder::Ptr CarddavProtocol::itemsReportQuery(const QStringList &urls) const
+{
+ XMLQueryBuilder::Ptr ret(new CarddavMultigetQueryBuilder());
+ ret->setParameter(QStringLiteral("urls"), urls);
+ return ret;
+}
+
+QString CarddavProtocol::responseNamespace() const
+{
+ return QStringLiteral("urn:ietf:params:xml:ns:carddav");
+}
+
+QString CarddavProtocol::dataTagName() const
+{
+ return QStringLiteral("address-data");
+}
+
+DavCollection::ContentTypes CarddavProtocol::collectionContentTypes(const QDomElement &) const
+{
+ return DavCollection::Contacts;
+}
--- /dev/null
+/*
+ SPDX-FileCopyrightText: 2010 Tobias Koenig <tokoe@kde.org>
+
+ SPDX-License-Identifier: LGPL-2.0-or-later
+*/
+
+#ifndef KDAV_CARDDAVPROTOCOL_H
+#define KDAV_CARDDAVPROTOCOL_H
+
+#include "common/davmultigetprotocol_p.h"
+
+class CarddavProtocol : public KDAV::DavMultigetProtocol
+{
+public:
+ CarddavProtocol();
+ Q_REQUIRED_RESULT bool supportsPrincipals() const override;
+ Q_REQUIRED_RESULT bool useReport() const override;
+ Q_REQUIRED_RESULT bool useMultiget() const override;
+ Q_REQUIRED_RESULT QString principalHomeSet() const override;
+ Q_REQUIRED_RESULT QString principalHomeSetNS() const override;
+ Q_REQUIRED_RESULT KDAV::XMLQueryBuilder::Ptr collectionsQuery() const override;
+ Q_REQUIRED_RESULT bool containsCollection(const QDomElement &propElem) const override;
+ Q_REQUIRED_RESULT QVector<KDAV::XMLQueryBuilder::Ptr> itemsQueries() const override;
+ Q_REQUIRED_RESULT KDAV::XMLQueryBuilder::Ptr itemsReportQuery(const QStringList &urls) const override;
+ Q_REQUIRED_RESULT QString responseNamespace() const override;
+ Q_REQUIRED_RESULT QString dataTagName() const override;
+
+ Q_REQUIRED_RESULT KDAV::DavCollection::ContentTypes collectionContentTypes(const QDomElement &propstat) const override;
+};
+
+#endif
--- /dev/null
+/*
+ SPDX-FileCopyrightText: 2009 Grégory Oestreicher <greg@kamago.net>
+
+ SPDX-License-Identifier: LGPL-2.0-or-later
+*/
+
+#include "groupdavprotocol_p.h"
+
+#include "common/utils_p.h"
+
+#include <QDomDocument>
+
+using namespace KDAV;
+
+class GroupdavCollectionQueryBuilder : public XMLQueryBuilder
+{
+public:
+ QDomDocument buildQuery() const override
+ {
+ QDomDocument document;
+
+ QDomElement propfindElement = document.createElementNS(QStringLiteral("DAV:"), QStringLiteral("propfind"));
+ document.appendChild(propfindElement);
+
+ QDomElement propElement = document.createElementNS(QStringLiteral("DAV:"), QStringLiteral("prop"));
+ propfindElement.appendChild(propElement);
+
+ propElement.appendChild(document.createElementNS(QStringLiteral("DAV:"), QStringLiteral("displayname")));
+ propElement.appendChild(document.createElementNS(QStringLiteral("DAV:"), QStringLiteral("resourcetype")));
+
+ return document;
+ }
+
+ QString mimeType() const override
+ {
+ return QString();
+ }
+};
+
+class GroupdavItemQueryBuilder : public XMLQueryBuilder
+{
+public:
+ QDomDocument buildQuery() const override
+ {
+ QDomDocument document;
+
+ QDomElement propfindElement = document.createElementNS(QStringLiteral("DAV:"), QStringLiteral("propfind"));
+ document.appendChild(propfindElement);
+
+ QDomElement propElement = document.createElementNS(QStringLiteral("DAV:"), QStringLiteral("prop"));
+ propfindElement.appendChild(propElement);
+
+ propElement.appendChild(document.createElementNS(QStringLiteral("DAV:"), QStringLiteral("displayname")));
+ propElement.appendChild(document.createElementNS(QStringLiteral("DAV:"), QStringLiteral("resourcetype")));
+ propElement.appendChild(document.createElementNS(QStringLiteral("DAV:"), QStringLiteral("getetag")));
+
+ return document;
+ }
+
+ QString mimeType() const override
+ {
+ return QString();
+ }
+};
+
+GroupdavProtocol::GroupdavProtocol()
+{
+}
+
+bool GroupdavProtocol::supportsPrincipals() const
+{
+ return false;
+}
+
+bool GroupdavProtocol::useReport() const
+{
+ return false;
+}
+
+bool GroupdavProtocol::useMultiget() const
+{
+ return false;
+}
+
+XMLQueryBuilder::Ptr GroupdavProtocol::collectionsQuery() const
+{
+ return XMLQueryBuilder::Ptr(new GroupdavCollectionQueryBuilder());
+}
+
+bool GroupdavProtocol::containsCollection(const QDomElement &propElem) const
+{
+ return !propElem.elementsByTagNameNS(QStringLiteral("http://groupdav.org/"), QStringLiteral("vevent-collection")).isEmpty()
+ || !propElem.elementsByTagNameNS(QStringLiteral("http://groupdav.org/"), QStringLiteral("vtodo-collection")).isEmpty()
+ || !propElem.elementsByTagNameNS(QStringLiteral("http://groupdav.org/"), QStringLiteral("vcard-collection")).isEmpty();
+}
+
+QVector<XMLQueryBuilder::Ptr> GroupdavProtocol::itemsQueries() const
+{
+ QVector<XMLQueryBuilder::Ptr> ret;
+ ret << XMLQueryBuilder::Ptr(new GroupdavItemQueryBuilder());
+ return ret;
+}
+
+DavCollection::ContentTypes GroupdavProtocol::collectionContentTypes(const QDomElement &propstatElement) const
+{
+ /*
+ * Extract the content type information from a propstat like the following
+ *
+ * <propstat>
+ * <status>HTTP/1.1 200 OK</status>
+ * <prop>
+ * <displayname>Tasks</displayname>
+ * <resourcetype>
+ * <collection/>
+ * <G:vtodo-collection xmlns:G="http://groupdav.org/"/>
+ * </resourcetype>
+ * <getlastmodified>Sat, 30 Jan 2010 17:52:41 -0100</getlastmodified>
+ * </prop>
+ * </propstat>
+ */
+
+ const QDomElement propElement = Utils::firstChildElementNS(propstatElement, QStringLiteral("DAV:"), QStringLiteral("prop"));
+ const QDomElement resourcetypeElement = Utils::firstChildElementNS(propElement, QStringLiteral("DAV:"), QStringLiteral("resourcetype"));
+
+ DavCollection::ContentTypes contentTypes;
+
+ if (!Utils::firstChildElementNS(resourcetypeElement, QStringLiteral("http://groupdav.org/"), QStringLiteral("vevent-collection")).isNull()) {
+ contentTypes |= DavCollection::Events;
+ }
+
+ if (!Utils::firstChildElementNS(resourcetypeElement, QStringLiteral("http://groupdav.org/"), QStringLiteral("vtodo-collection")).isNull()) {
+ contentTypes |= DavCollection::Todos;
+ }
+
+ if (!Utils::firstChildElementNS(resourcetypeElement, QStringLiteral("http://groupdav.org/"), QStringLiteral("vcard-collection")).isNull()) {
+ contentTypes |= DavCollection::Contacts;
+ }
+
+ return contentTypes;
+}
--- /dev/null
+/*
+ SPDX-FileCopyrightText: 2009 Grégory Oestreicher <greg@kamago.net>
+
+ SPDX-License-Identifier: LGPL-2.0-or-later
+*/
+
+#ifndef GROUPDAVPROTOCOL_H
+#define GROUPDAVPROTOCOL_H
+
+#include "common/davprotocolbase_p.h"
+
+class GroupdavProtocol : public KDAV::DavProtocolBase
+{
+public:
+ GroupdavProtocol();
+ Q_REQUIRED_RESULT bool supportsPrincipals() const override;
+ Q_REQUIRED_RESULT bool useReport() const override;
+ Q_REQUIRED_RESULT bool useMultiget() const override;
+ Q_REQUIRED_RESULT KDAV::XMLQueryBuilder::Ptr collectionsQuery() const override;
+ Q_REQUIRED_RESULT bool containsCollection(const QDomElement &propElem) const override;
+ Q_REQUIRED_RESULT QVector<KDAV::XMLQueryBuilder::Ptr> itemsQueries() const override;
+
+ Q_REQUIRED_RESULT KDAV::DavCollection::ContentTypes collectionContentTypes(const QDomElement &propstat) const override;
+};
+
+#endif
--- /dev/null
+kde_enable_exceptions()
+set(EXECUTABLE_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR})
+
+add_executable(testserver testserver.cpp)
+
+target_link_libraries(testserver
+ Qt${QT_MAJOR_VERSION}::Core
+ KF5::DAV
+ Qt${QT_MAJOR_VERSION}::Xml
+ )
+
--- /dev/null
+/*
+ SPDX-FileCopyrightText: 2016 Sandro Knauß <sknauss@kde.org>
+
+ SPDX-License-Identifier: LGPL-2.0-or-later
+*/
+
+#include <KDAV/DavCollectionDeleteJob>
+#include <KDAV/DavCollectionModifyJob>
+#include <KDAV/DavCollectionsFetchJob>
+#include <KDAV/DavItemCreateJob>
+#include <KDAV/DavItemDeleteJob>
+#include <KDAV/DavItemFetchJob>
+#include <KDAV/DavItemModifyJob>
+#include <KDAV/DavItemsFetchJob>
+#include <KDAV/DavItemsListJob>
+#include <KDAV/EtagCache>
+
+#include <QCoreApplication>
+#include <QDebug>
+#include <QStringList>
+
+int main(int argc, char **argv)
+{
+ QCoreApplication app(argc, argv);
+
+ QUrl mainUrl(QStringLiteral("https://apps.kolabnow.com/addressbooks/test1%40kolab.org"));
+ mainUrl.setUserName(QStringLiteral("test1@kolab.org"));
+ mainUrl.setPassword(QStringLiteral("Welcome2KolabSystems"));
+ KDAV::DavUrl davUrl(mainUrl, KDAV::CardDav);
+
+ auto *job = new KDAV::DavCollectionsFetchJob(davUrl);
+ job->exec();
+
+ const auto collections = job->collections();
+ for (const auto &collection : collections) {
+ qDebug() << collection.displayName() << "PRIVS: " << collection.privileges();
+ auto collectionUrl = collection.url();
+ std::shared_ptr<KDAV::EtagCache> cache(new KDAV::EtagCache());
+ int anz = -1;
+ // Get all items in a collection add them to cache and make sure, that afterward no item is changed
+ {
+ auto itemListJob = new KDAV::DavItemsListJob(collectionUrl, cache);
+ itemListJob->exec();
+ anz = itemListJob->items().size();
+ qDebug() << "items:" << itemListJob->items().size();
+ qDebug() << "changed Items:" << itemListJob->changedItems().size();
+ qDebug() << "deleted Items:" << itemListJob->deletedItems();
+ const auto changedItems = itemListJob->changedItems();
+ for (const auto &item : changedItems) {
+ qDebug() << item.url().url() << item.contentType() << item.data();
+ auto itemFetchJob = new KDAV::DavItemFetchJob(item);
+ itemFetchJob->exec();
+ const auto fetchedItem = itemFetchJob->item();
+ qDebug() << fetchedItem.contentType() << fetchedItem.data();
+
+ auto itemsFetchJob = new KDAV::DavItemsFetchJob(collectionUrl, QStringList() << item.url().toDisplayString());
+ itemsFetchJob->exec();
+ if (itemsFetchJob->item(item.url().toDisplayString()).contentType() != fetchedItem.contentType()) { // itemsfetchjob do not get contentType
+ qDebug() << "Fetched same item but got different contentType:" << itemsFetchJob->item(item.url().toDisplayString()).contentType();
+ }
+
+ if (itemsFetchJob->item(item.url().toDisplayString()).data() != fetchedItem.data()) {
+ qDebug() << "Fetched same item but got different data:" << itemsFetchJob->item(item.url().toDisplayString()).data();
+ }
+
+ cache->setEtag(item.url().toDisplayString(), item.etag());
+ }
+ cache->setEtag(QStringLiteral("invalid"), QStringLiteral("invalid"));
+ }
+ {
+ qDebug() << "second run: (should be empty).";
+ auto itemListJob = new KDAV::DavItemsListJob(collectionUrl, cache);
+ itemListJob->exec();
+ if (itemListJob->items().size() != anz) {
+ qDebug() << "Items have added/deleted on server.";
+ }
+ if (itemListJob->changedItems().size() != 0) {
+ qDebug() << "Items have changed on server.";
+ }
+ if (itemListJob->deletedItems() != QStringList() << QStringLiteral("invalid")) {
+ qDebug() << "more items deleted:" << itemListJob->deletedItems();
+ }
+ }
+ }
+
+ {
+ QUrl url(QStringLiteral("https://apps.kolabnow.com/addressbooks/test1%40kolab.org/cbbf386d-7e9b-4e72-947d-0b813ea9b347/"));
+ url.setUserInfo(mainUrl.userInfo());
+ KDAV::DavUrl collectionUrl(url, KDAV::CardDav);
+ auto collectionDeleteJob = new KDAV::DavCollectionDeleteJob(collectionUrl);
+ collectionDeleteJob->exec();
+ if (collectionDeleteJob->error()) {
+ qDebug() << collectionDeleteJob->errorString();
+ }
+ }
+
+ {
+ QUrl url(QStringLiteral("https://apps.kolabnow.com/addressbooks/test1%40kolab.org/9290e784-c876-412f-8385-be292d64b2c6/"));
+ url.setUserInfo(mainUrl.userInfo());
+ KDAV::DavUrl testCollectionUrl(url, KDAV::CardDav);
+ auto collectionModifyJob = new KDAV::DavCollectionModifyJob(testCollectionUrl);
+ collectionModifyJob->setProperty(QStringLiteral("displayname"), QStringLiteral("test234"));
+ collectionModifyJob->exec();
+ if (collectionModifyJob->error()) {
+ qDebug() << collectionModifyJob->errorString();
+ }
+ }
+
+ // create element with "wrong put url" test if we get the correct url back
+ {
+ QUrl url(QStringLiteral("https://apps.kolabnow.com/addressbooks/test1%40kolab.org/9290e784-c876-412f-8385-be292d64b2c6/xxx.vcf"));
+ url.setUserInfo(mainUrl.userInfo());
+ KDAV::DavUrl testItemUrl(url, KDAV::CardDav);
+ QByteArray data =
+ "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Kolab//iRony DAV Server 0.3.1//Sabre//Sabre VObject "
+ "2.1.7//EN\r\nUID:12345678-1234-1234-1234-123456789abc\r\nFN:John "
+ "Doe\r\nN:Doe;John;;;\r\nEMAIL;TYPE=INTERNET;TYPE=HOME:john.doe@example.com\r\nREV;VALUE=DATE-TIME:20161221T145611Z\r\nEND:VCARD\r\n";
+ KDAV::DavItem item(testItemUrl, QStringLiteral("text/x-vcard"), data, QString());
+ auto createJob = new KDAV::DavItemCreateJob(item);
+ createJob->exec();
+ if (createJob->error()) {
+ qDebug() << createJob->errorString();
+ }
+ if (createJob->item().url().toDisplayString()
+ != QLatin1String(
+ "https://apps.kolabnow.com/addressbooks/test1%40kolab.org/9290e784-c876-412f-8385-be292d64b2c6/12345678-1234-1234-1234-123456789abc.vcf")) {
+ qDebug() << "unexpected url" << createJob->item().url().url();
+ }
+ }
+
+ {
+ QUrl url(QStringLiteral(
+ "https://apps.kolabnow.com/addressbooks/test1%40kolab.org/9290e784-c876-412f-8385-be292d64b2c6/12345678-1234-1234-1234-123456789abc.vcf"));
+ url.setUserInfo(mainUrl.userInfo());
+ KDAV::DavUrl testItemUrl(url, KDAV::CardDav);
+ QByteArray data =
+ "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Kolab//iRony DAV Server 0.3.1//Sabre//Sabre VObject "
+ "2.1.7//EN\r\nUID:12345678-1234-1234-1234-123456789abc\r\nFN:John2 "
+ "Doe\r\nN:Doe;John2;;;\r\nEMAIL;TYPE=INTERNET;TYPE=HOME:john2.doe@example.com\r\nREV;VALUE=DATE-TIME:20161221T145611Z\r\nEND:VCARD\r\n";
+ KDAV::DavItem item(testItemUrl, QStringLiteral("text/x-vcard"), data, QString());
+ auto modifyJob = new KDAV::DavItemModifyJob(item);
+ modifyJob->exec();
+ if (modifyJob->error()) {
+ qDebug() << modifyJob->errorString();
+ }
+ }
+
+ {
+ QUrl url(QStringLiteral(
+ "https://apps.kolabnow.com/addressbooks/test1%40kolab.org/9290e784-c876-412f-8385-be292d64b2c6/12345678-1234-1234-1234-123456789abc.vcf"));
+ url.setUserInfo(mainUrl.userInfo());
+ KDAV::DavUrl testItemUrl(url, KDAV::CardDav);
+ QByteArray data =
+ "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Kolab//iRony DAV Server 0.3.1//Sabre//Sabre VObject "
+ "2.1.7//EN\r\nUID:12345678-1234-1234-1234-123456789abc\r\nFN:John2 "
+ "Doe\r\nN:Doe;John2;;;\r\nEMAIL;TYPE=INTERNET;TYPE=HOME:john2.doe@example.com\r\nREV;VALUE=DATE-TIME:20161221T145611Z\r\nEND:VCARD\r\n";
+ KDAV::DavItem item(testItemUrl, QStringLiteral("text/x-vcard"), data, QString());
+ auto deleteJob = new KDAV::DavItemDeleteJob(item);
+ deleteJob->exec();
+ if (deleteJob->error()) {
+ qDebug() << deleteJob->errorString();
+ }
+ }
+}