Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
KDE:Unstable:Applications
kimap
_service:obs_scm:kimap-VERSIONgit.20240930T1854...
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File _service:obs_scm:kimap-VERSIONgit.20240930T185424~db1f697.obscpio of Package kimap
07070100000000000081A400000000000000000000000166FAD7C000000071000000000000000000000000000000000000003600000000kimap-VERSIONgit.20240930T185424~db1f697/.codespellrc[codespell] skip = ./build*,.git,*.notifyrc,*.desktop,*.json,*.xml interactive = 3 ignore-words-list = accessort 07070100000001000081A400000000000000000000000166FAD7C000000067000000000000000000000000000000000000003E00000000kimap-VERSIONgit.20240930T185424~db1f697/.codespellrc.license# SPDX-FileCopyrightText: 2022-2024 Laurent Montel <montel@kde.org> # SPDX-License-Identifier: CC0-1.0 07070100000002000081A400000000000000000000000166FAD7C0000000A3000000000000000000000000000000000000004000000000kimap-VERSIONgit.20240930T185424~db1f697/.git-blame-ignore-revs# SPDX-License-Identifier: CC0-1.0 # SPDX-FileCopyrightText: none # clang-format dab484f8cf3ba7809a134e8589690c9bed6b45d5 5ffbc07640fc932ebf7b87928bb1f8d6405e1b96 07070100000003000081A400000000000000000000000166FAD7C000000172000000000000000000000000000000000000003400000000kimap-VERSIONgit.20240930T185424~db1f697/.gitignore# SPDX-License-Identifier: CC0-1.0 # SPDX-FileCopyrightText: none # 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* compile_commands.json .clang-format .clangd .idea /cmake-build* .cache Testing/ /.vscode/ 07070100000004000081A400000000000000000000000166FAD7C0000001BE000000000000000000000000000000000000003800000000kimap-VERSIONgit.20240930T185424~db1f697/.gitlab-ci.yml# SPDX-FileCopyrightText: 2020-2024 Laurent Montel <montel@kde.org> # SPDX-License-Identifier: CC0-1.0 include: - project: sysadmin/ci-utilities file: - /gitlab-templates/linux-qt6.yml - /gitlab-templates/freebsd-qt6.yml - /gitlab-templates/windows-qt6.yml - /gitlab-templates/reuse-lint.yml - /gitlab-templates/cppcheck.yml - /gitlab-templates/clang-format.yml - /gitlab-templates/alpine-qt6.yml 07070100000005000081A400000000000000000000000166FAD7C000000187000000000000000000000000000000000000003500000000kimap-VERSIONgit.20240930T185424~db1f697/.kde-ci.yml# SPDX-FileCopyrightText: None # SPDX-License-Identifier: CC0-1.0 Dependencies: - 'on': ['Linux', 'FreeBSD', 'Windows'] 'require': 'frameworks/extra-cmake-modules': '@latest-kf6' 'pim/kmime' : '@same' 'frameworks/kcoreaddons': '@latest-kf6' 'frameworks/ki18n': '@latest-kf6' 'frameworks/kio': '@latest-kf6' Options: require-passing-tests-on: [ 'Linux', 'FreeBSD' ] 07070100000006000081A400000000000000000000000166FAD7C00000000D000000000000000000000000000000000000003000000000kimap-VERSIONgit.20240930T185424~db1f697/.krazySKIP /tests/ 07070100000007000081A400000000000000000000000166FAD7C00000003E000000000000000000000000000000000000003800000000kimap-VERSIONgit.20240930T185424~db1f697/.krazy.licenseSPDX-FileCopyrightText: none SPDX-License-Identifier: CC0-1.0 07070100000008000081A400000000000000000000000166FAD7C000000ED5000000000000000000000000000000000000003800000000kimap-VERSIONgit.20240930T185424~db1f697/CMakeLists.txt# SPDX-FileCopyrightText: none # SPDX-License-Identifier: BSD-3-Clause cmake_minimum_required(VERSION 3.16 FATAL_ERROR) set(PIM_VERSION "6.2.40") project(KIMAP VERSION ${PIM_VERSION}) # ECM setup set(KF_MIN_VERSION "6.6.0") set(QT_REQUIRED_VERSION "6.7.0") find_package(ECM ${KF_MIN_VERSION} CONFIG REQUIRED) set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH}) include(KDEInstallDirs) include(KDECMakeSettings) include(KDECompilerSettings NO_POLICY_SCOPE) include(ECMGenerateExportHeader) include(ECMGenerateHeaders) include(ECMSetupVersion) include(FeatureSummary) include(KDEGitCommitHooks) include(KDEClangFormat) file(GLOB_RECURSE ALL_CLANG_FORMAT_SOURCE_FILES *.cpp *.h *.c) kde_clang_format(${ALL_CLANG_FORMAT_SOURCE_FILES}) include(ECMQtDeclareLoggingCategory) include(ECMDeprecationSettings) include(ECMFeatureSummary) include(ECMAddQch) include(ECMCheckOutboundLicense) file(GLOB_RECURSE ALL_SOURCE_FILES src/*.cpp src/*.h tests/*.cpp tests/*.h autotests/*.cpp autotests/*.h ) ecm_check_outbound_license(LICENSES GPL-2.0-only FILES ${ALL_SOURCE_FILES}) set(KIMAP_LIB_VERSION ${PIM_VERSION}) set(KMIME_LIBS_VERSION "6.2.40") ecm_setup_version(PROJECT VARIABLE_PREFIX KIMAP VERSION_HEADER "${CMAKE_CURRENT_BINARY_DIR}/src/kimap_version.h" PACKAGE_VERSION_FILE "${CMAKE_CURRENT_BINARY_DIR}/KPim6IMAPConfigVersion.cmake" SOVERSION 6 ) 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)") ########### Find packages ########### find_package(Sasl2) set_package_properties(Sasl2 PROPERTIES TYPE REQUIRED) find_package(KF6CoreAddons ${KF_MIN_VERSION} CONFIG REQUIRED) find_package(KF6I18n ${KF_MIN_VERSION} CONFIG REQUIRED) find_package(KF6KIO ${KF_MIN_VERSION} CONFIG REQUIRED) find_package(KPim6Mime ${KMIME_LIBS_VERSION} CONFIG REQUIRED) ########### CMake Config Files ########### set(CMAKECONFIG_INSTALL_DIR "${KDE_INSTALL_CMAKEPACKAGEDIR}/KPim6IMAP") add_definitions(-DTRANSLATION_DOMAIN=\"libkimap6\") ecm_set_disabled_deprecation_versions(QT 6.7.2 KF 6.7.0 ) add_definitions(-DQT_NO_EMIT) option(USE_UNITY_CMAKE_SUPPORT "Use UNITY cmake support (speedup compile time)" OFF) set(COMPILE_WITH_UNITY_CMAKE_SUPPORT OFF) if(USE_UNITY_CMAKE_SUPPORT) set(COMPILE_WITH_UNITY_CMAKE_SUPPORT ON) endif() ########### Targets ########### add_subdirectory(src) if(BUILD_TESTING) find_package(Qt6 ${QT_REQUIRED_VERSION} CONFIG REQUIRED Test) add_subdirectory(autotests) add_subdirectory(tests) endif() ########### Install Files ########### install(FILES "${CMAKE_CURRENT_BINARY_DIR}/KPim6IMAPConfig.cmake" "${CMAKE_CURRENT_BINARY_DIR}/KPim6IMAPConfigVersion.cmake" DESTINATION "${CMAKECONFIG_INSTALL_DIR}" COMPONENT Devel ) install(EXPORT KPim6IMAPTargets DESTINATION "${CMAKECONFIG_INSTALL_DIR}" FILE KPim6IMAPTargets.cmake NAMESPACE KPim6::) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/src/kimap_version.h DESTINATION ${KDE_INSTALL_INCLUDEDIR}/KPim6/KIMAP/ COMPONENT Devel ) if(BUILD_QCH) ecm_install_qch_export( TARGETS KPim6Imap_QCH FILE KPim6ImapQchTargets.cmake DESTINATION "${CMAKECONFIG_INSTALL_DIR}" COMPONENT Devel ) set(PACKAGE_INCLUDE_QCHTARGETS "include(\"\${CMAKE_CURRENT_LIST_DIR}/KPim6ImapQchTargets.cmake\")") endif() configure_package_config_file( "${CMAKE_CURRENT_SOURCE_DIR}/KPimIMAPConfig.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/KPim6IMAPConfig.cmake" INSTALL_DESTINATION ${CMAKECONFIG_INSTALL_DIR} ) kde_configure_git_pre_commit_hook(CHECKS CLANG_FORMAT) ki18n_install(po) ecm_feature_summary(WHAT ALL FATAL_ON_MISSING_REQUIRED_PACKAGES) 07070100000009000081A400000000000000000000000166FAD7C000001AB2000000000000000000000000000000000000003B00000000kimap-VERSIONgit.20240930T185424~db1f697/CMakePresets.json{ "version": 3, "configurePresets": [ { "name": "base", "displayName": "base preset", "generator": "Ninja", "binaryDir": "${sourceDir}/build-${presetName}", "installDir": "$env{KF6}", "hidden": true, "cacheVariables": { "BUILD_QCH": "ON" } }, { "name": "dev-mold", "displayName": "Build as debug + using mold linker", "cacheVariables": { "CMAKE_BUILD_TYPE": "Debug", "CMAKE_EXPORT_COMPILE_COMMANDS": "ON", "CMAKE_SHARED_LINKER_FLAGS": "-fuse-ld=mold" }, "inherits": [ "base" ] }, { "name": "dev", "displayName": "Build as debug", "cacheVariables": { "CMAKE_BUILD_TYPE": "Debug", "CMAKE_EXPORT_COMPILE_COMMANDS": "ON" }, "inherits": [ "base" ] }, { "name": "asan", "displayName": "Build with Asan support.", "cacheVariables": { "CMAKE_BUILD_TYPE": "Debug", "ECM_ENABLE_SANITIZERS" : "'address;undefined'" }, "inherits": [ "base" ] }, { "name": "dev-clang", "displayName": "dev-clang", "cacheVariables": { "CMAKE_BUILD_TYPE": "Debug", "CMAKE_EXPORT_COMPILE_COMMANDS": "ON" }, "environment": { "CXX": "clang++", "CCACHE_DISABLE": "ON" }, "inherits": [ "base" ] }, { "name": "unity", "displayName": "Build with CMake unity support.", "cacheVariables": { "CMAKE_BUILD_TYPE": "Debug", "USE_UNITY_CMAKE_SUPPORT": "ON" }, "inherits": [ "base" ] }, { "name": "release", "displayName": "Build as release mode.", "cacheVariables": { "CMAKE_BUILD_TYPE": "Release", "BUILD_TESTING": "OFF" }, "inherits": [ "base" ] }, { "name": "profile", "displayName": "profile", "cacheVariables": { "CMAKE_BUILD_TYPE": "RelWithDebInfo" }, "inherits": [ "base" ] }, { "name": "coverage", "displayName": "coverage", "cacheVariables": { "CMAKE_BUILD_TYPE": "Debug", "USE_UNITY_CMAKE_SUPPORT": "OFF", "BUILD_COVERAGE": "ON" }, "inherits": [ "base" ] }, { "name": "clazy", "displayName": "clazy", "cacheVariables": { "CMAKE_BUILD_TYPE": "Debug" }, "environment": { "CXX": "clazy", "CCACHE_DISABLE": "ON" }, "inherits": [ "base" ] }, { "name": "pch", "displayName": "pch", "cacheVariables": { "CMAKE_BUILD_TYPE": "Debug", "USE_PRECOMPILED_HEADERS": "ON", "BUILD_COVERAGE": "ON" }, "inherits": [ "base" ] }, { "name": "ftime-trace", "displayName": "ftime-trace", "cacheVariables": { "CMAKE_BUILD_TYPE": "Debug", "USE_DEVELOPER_MODE": "ON", "CMAKE_C_FLAGS_INIT": "-ftime-trace", "CMAKE_CXX_FLAGS_INIT": "-ftime-trace" }, "environment": { "CC": "/usr/bin/clang", "CXX": "/usr/bin/clang++", "CCACHE_DISABLE": "ON" }, "inherits": [ "base" ] } ], "buildPresets": [ { "name": "dev", "configurePreset": "dev" }, { "name": "ftime-trace", "configurePreset": "ftime-trace" }, { "name": "dev-mold", "configurePreset": "dev-mold" }, { "name": "dev-clang", "configurePreset": "dev-clang" }, { "name": "pch", "configurePreset": "pch" }, { "name": "release", "configurePreset": "release" }, { "name": "unity", "configurePreset": "unity" }, { "name": "coverage", "configurePreset": "coverage" }, { "name": "asan", "configurePreset": "asan" }, { "name": "clazy", "configurePreset": "clazy", "environment": { "CLAZY_CHECKS" : "level0,level1,detaching-member,ifndef-define-typo,isempty-vs-count,qrequiredresult-candidates,reserve-candidates,signal-with-return-value,unneeded-cast,function-args-by-ref,function-args-by-value,returning-void-expression,no-ctor-missing-parent-argument,isempty-vs-count,qhash-with-char-pointer-key,raw-environment-function,qproperty-type-mismatch,old-style-connect,qstring-allocations,container-inside-loop,heap-allocated-small-trivial-type,inefficient-qlist,qstring-varargs,level2,detaching-member,heap-allocated-small-trivial-type,isempty-vs-count,qstring-varargs,qvariant-template-instantiation,raw-environment-function,reserve-candidates,signal-with-return-value,thread-with-slots,no-ctor-missing-parent-argument,no-missing-typeinfo", "CCACHE_DISABLE" : "ON" } } ], "testPresets": [ { "name": "dev", "configurePreset": "dev", "output": {"outputOnFailure": true}, "execution": {"noTestsAction": "error", "stopOnFailure": false} }, { "name": "asan", "configurePreset": "asan", "output": {"outputOnFailure": true}, "execution": {"noTestsAction": "error", "stopOnFailure": true} }, { "name": "unity", "configurePreset": "unity", "output": {"outputOnFailure": true}, "execution": {"noTestsAction": "error", "stopOnFailure": true} }, { "name": "coverage", "configurePreset": "coverage", "output": {"outputOnFailure": true}, "execution": {"noTestsAction": "error", "stopOnFailure": true} } ] } 0707010000000A000081A400000000000000000000000166FAD7C00000006C000000000000000000000000000000000000004300000000kimap-VERSIONgit.20240930T185424~db1f697/CMakePresets.json.license# SPDX-FileCopyrightText: 2021-2024 Laurent Montel <montel@kde.org> # SPDX-License-Identifier: BSD-3-Clause 0707010000000B000081A400000000000000000000000166FAD7C0000001ED000000000000000000000000000000000000004100000000kimap-VERSIONgit.20240930T185424~db1f697/KPimIMAPConfig.cmake.in# SPDX-FileCopyrightText: 2017-2019 Christophe Giboudeaux <christophe@krop.fr> # SPDX-FileCopyrightText: 2017-2024 Laurent Montel <montel.org> # SPDX-License-Identifier: BSD-3-Clause @PACKAGE_INIT@ set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR} ${CMAKE_MODULE_PATH}) include(CMakeFindDependencyMacro) find_dependency(KF6CoreAddons "@KF_MIN_VERSION@") find_dependency(KPim6Mime "@KMIME_LIBS_VERSION@") include("${CMAKE_CURRENT_LIST_DIR}/KPim6IMAPTargets.cmake") @PACKAGE_INCLUDE_QCHTARGETS@ 0707010000000C000041ED00000000000000000000000266FAD7C000000000000000000000000000000000000000000000003200000000kimap-VERSIONgit.20240930T185424~db1f697/LICENSES0707010000000D000081A400000000000000000000000166FAD7C0000005C8000000000000000000000000000000000000004300000000kimap-VERSIONgit.20240930T185424~db1f697/LICENSES/BSD-3-Clause.txtCopyright (c) <year> <owner>. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 0707010000000E000081A400000000000000000000000166FAD7C000001B04000000000000000000000000000000000000003E00000000kimap-VERSIONgit.20240930T185424~db1f697/LICENSES/CC0-1.0.txtCreative 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. 0707010000000F000081A400000000000000000000000166FAD7C0000044D6000000000000000000000000000000000000004700000000kimap-VERSIONgit.20240930T185424~db1f697/LICENSES/GPL-2.0-or-later.txtGNU 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. 07070100000010000081A400000000000000000000000166FAD7C0000060C6000000000000000000000000000000000000004400000000kimap-VERSIONgit.20240930T185424~db1f697/LICENSES/LGPL-2.0-only.txtGNU 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! 07070100000011000081A400000000000000000000000166FAD7C0000060C6000000000000000000000000000000000000004800000000kimap-VERSIONgit.20240930T185424~db1f697/LICENSES/LGPL-2.0-or-later.txtGNU 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! 07070100000012000081A400000000000000000000000166FAD7C00000024D000000000000000000000000000000000000003300000000kimap-VERSIONgit.20240930T185424~db1f697/README.md# KIMAP # This library provides a job-based API for interacting with an IMAP4rev1 server. It manages connections, encryption and parameter quoting and encoding, but otherwise provides quite a low-level interface to the protocol. This library does not implement an IMAP client; it merely makes it easier to do so. Users should be familiar with [RFC 3501](https://tools.ietf.org/html/rfc3501 "IMAP 4rev1") as well as [other related RFCs](https://www.iana.org/assignments/imap4-capabilities) although the library hides some of the nastier details like the encoding and quoting of strings. 07070100000013000081A400000000000000000000000166FAD7C00000003E000000000000000000000000000000000000003B00000000kimap-VERSIONgit.20240930T185424~db1f697/README.md.licenseSPDX-FileCopyrightText: none SPDX-License-Identifier: CC0-1.0 07070100000014000081A400000000000000000000000166FAD7C000000199000000000000000000000000000000000000003400000000kimap-VERSIONgit.20240930T185424~db1f697/REUSE.toml# SPDX-FileCopyrightText: none # SPDX-License-Identifier: CC0-1.0 version = 1 SPDX-PackageName = "kimap" SPDX-PackageSupplier = "Montel Laurent <montel@kde.org>" SPDX-PackageDownloadLocation = "https://invent.kde.org/pim/kimap" [[annotations]] path = ["autotests/fakeserverscenario.log", "readme-build-ftime.txt"] precedence = "aggregate" SPDX-FileCopyrightText = "none" SPDX-License-Identifier = "CC0-1.0" 07070100000015000041ED00000000000000000000000366FAD7C000000000000000000000000000000000000000000000003300000000kimap-VERSIONgit.20240930T185424~db1f697/autotests07070100000016000081A400000000000000000000000166FAD7C000000493000000000000000000000000000000000000004200000000kimap-VERSIONgit.20240930T185424~db1f697/autotests/CMakeLists.txt# SPDX-FileCopyrightText: none # SPDX-License-Identifier: BSD-3-Clause kde_enable_exceptions() include(ECMMarkAsTest) add_subdirectory(kimaptest) macro(KIMAP_UNIT_TESTS) foreach(_testname ${ARGN}) add_executable(${_testname} ${_testname}.cpp) add_test(NAME ${_testname} COMMAND ${_testname}) ecm_mark_as_test(${_testname}) target_link_libraries(${_testname} KPim6IMAP Qt::Test kimaptest6 Qt::Network) set_target_properties(${_testname} PROPERTIES COMPILE_FLAGS -DTEST_DATA="\\"${CMAKE_CURRENT_SOURCE_DIR}\\"") set_tests_properties(${_testname} PROPERTIES RUN_SERIAL TRUE) endforeach() endmacro() ########### automated tests ############### KIMAP_UNIT_TESTS( fakeservertest testrfccodecs testsession loginjobtest logoutjobtest capabilitiesjobtest closejobtest selectjobtest createjobtest deletejobtest enablejobtest expungejobtest fetchjobtest renamejobtest subscribejobtest unsubscribejobtest listjobtest storejobtest imapsettest idjobtest idlejobtest quotarootjobtest searchjobtest getmetadatajobtest streamparsertest setmetadatajobtest appendjobtest statusjobtest movejobtest ) 07070100000017000081A400000000000000000000000166FAD7C000000D2C000000000000000000000000000000000000004500000000kimap-VERSIONgit.20240930T185424~db1f697/autotests/appendjobtest.cpp/* SPDX-FileCopyrightText: 2013 Christian Mollekopf <mollekopf@kolabsys.com> SPDX-License-Identifier: GPL-2.0-or-later */ #include <QTest> #include "kimap/appendjob.h" #include "kimap/session.h" #include "kimaptest/fakeserver.h" #include <QDateTime> #include <QTest> class AppendJobTest : public QObject { Q_OBJECT private Q_SLOTS: void testAppend_data() { QTest::addColumn<QString>("mailbox"); QTest::addColumn<QList<QByteArray>>("scenario"); QTest::addColumn<QList<QByteArray>>("flags"); QTest::addColumn<QDateTime>("internaldate"); QTest::addColumn<QByteArray>("content"); QTest::addColumn<qint64>("uid"); QList<QByteArray> flags; flags << QByteArray("\\Seen"); { QList<QByteArray> scenario; scenario << FakeServer::preauth() << "C: A000001 APPEND \"INBOX\" (\\Seen) {7}\r\ncontent" << "S: A000001 OK APPEND completed. [ APPENDUID 492 2671 ]"; QTest::newRow("good") << "INBOX" << scenario << flags << QDateTime() << QByteArray("content") << qint64(2671); } { QList<QByteArray> scenario; scenario << FakeServer::preauth() << "C: A000001 APPEND \"INBOX\" (\\Seen) \"26-Feb-2014 12:38:00 +0000\" {7}\r\ncontent" << "S: A000001 OK APPEND completed. [ APPENDUID 493 2672 ]"; QTest::newRow("good, with internalDate set") << "INBOX" << scenario << flags << QDateTime::fromString(QStringLiteral("2014-02-26T12:38:00Z"), Qt::ISODate) << QByteArray("content") << qint64(2672); } { QList<QByteArray> scenario; scenario << FakeServer::preauth() << "C: A000001 APPEND \"INBOX\" (\\Seen) {7}\r\ncontent" << "S: BYE" << "X"; QTest::newRow("bad") << "INBOX" << scenario << flags << QDateTime() << QByteArray("content") << qint64(0); } { QList<QByteArray> scenario; scenario << FakeServer::preauth() << "C: A000001 APPEND \"INBOX\" (\\Seen) {7}\r\ncontent" << "S: " << "X"; QTest::newRow("Don't crash on empty response") << "INBOX" << scenario << flags << QDateTime() << QByteArray("content") << qint64(0); } } void testAppend() { QFETCH(QString, mailbox); QFETCH(QList<QByteArray>, scenario); QFETCH(QList<QByteArray>, flags); QFETCH(QDateTime, internaldate); QFETCH(QByteArray, content); QFETCH(qint64, uid); FakeServer fakeServer; fakeServer.setScenario(scenario); fakeServer.startAndWait(); KIMAP::Session session(QStringLiteral("127.0.0.1"), 5989); auto job = new KIMAP::AppendJob(&session); job->setContent(content); job->setFlags(flags); job->setInternalDate(internaldate); job->setMailBox(mailbox); const bool result = job->exec(); QEXPECT_FAIL("bad", "Expected failure on connection abort", Continue); QEXPECT_FAIL("Don't crash on empty response", "Expected failure on connection abort", Continue); QVERIFY(result); QCOMPARE(job->uid(), uid); fakeServer.quit(); } }; QTEST_GUILESS_MAIN(AppendJobTest) #include "appendjobtest.moc" 07070100000018000081A400000000000000000000000166FAD7C0000009EF000000000000000000000000000000000000004B00000000kimap-VERSIONgit.20240930T185424~db1f697/autotests/capabilitiesjobtest.cpp/* SPDX-FileCopyrightText: 2009 Andras Mantia <amantia@kde.org> SPDX-FileCopyrightText: 2010 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com> SPDX-FileContributor: Kevin Ottens <kevin@kdab.com> SPDX-License-Identifier: GPL-2.0-or-later */ #include <QTest> #include "kimap/capabilitiesjob.h" #include "kimap/session.h" #include "kimaptest/fakeserver.h" #include <QTest> class CapabilitiesJobTest : public QObject { Q_OBJECT private Q_SLOTS: void testCapabilities_data() { QTest::addColumn<QList<QByteArray>>("scenario"); QTest::addColumn<QStringList>("capabilities"); QList<QByteArray> scenario; scenario << "S: * PREAUTH" << "C: A000001 CAPABILITY" << "S: * CAPABILITY IMAP4rev1 STARTTLS AUTH=GSSAPI" << "S: A000001 OK CAPABILITY completed"; QStringList capabilities; capabilities << QStringLiteral("IMAP4REV1") << QStringLiteral("STARTTLS") << QStringLiteral("AUTH=GSSAPI"); QTest::newRow("good") << scenario << capabilities; scenario.clear(); capabilities.clear(); scenario << "S: * PREAUTH" << "C: A000001 CAPABILITY" << "S: A000001 BAD command unknown or arguments invalid"; QTest::newRow("bad") << scenario << capabilities; scenario.clear(); capabilities.clear(); scenario << "S: * PREAUTH" << "C: A000001 CAPABILITY" << "S: * CAPABILITY IMAP4rev1 STARTTLS AUTH=PLAIN" << "S: * some response" << "S: A000001 OK CAPABILITY completed"; capabilities << QStringLiteral("IMAP4REV1") << QStringLiteral("STARTTLS") << QStringLiteral("AUTH=PLAIN"); QTest::newRow("extra-untagged") << scenario << capabilities; } void testCapabilities() { QFETCH(QList<QByteArray>, scenario); QFETCH(QStringList, capabilities); FakeServer fakeServer; fakeServer.setScenario(scenario); fakeServer.startAndWait(); KIMAP::Session session(QStringLiteral("127.0.0.1"), 5989); auto job = new KIMAP::CapabilitiesJob(&session); bool result = job->exec(); QEXPECT_FAIL("bad", "Expected failure on BAD response", Continue); QVERIFY(result); if (result) { QCOMPARE(job->capabilities(), capabilities); } fakeServer.quit(); } }; QTEST_GUILESS_MAIN(CapabilitiesJobTest) #include "capabilitiesjobtest.moc" 07070100000019000081A400000000000000000000000166FAD7C0000006D7000000000000000000000000000000000000004400000000kimap-VERSIONgit.20240930T185424~db1f697/autotests/closejobtest.cpp/* SPDX-FileCopyrightText: 2020 Daniel Vrátil <dvratil@kde.org> SPDX-License-Identifier: GPL-2.0-or-later */ #include <QTest> #include "kimap/closejob.h" #include "kimap/session.h" #include "kimaptest/fakeserver.h" #include <QTest> class CloseJobTest : public QObject { Q_OBJECT private Q_SLOTS: void testClose_data() { QTest::addColumn<QList<QByteArray>>("scenario"); QTest::addColumn<quint64>("highestModSeq"); QList<QByteArray> scenario; scenario << FakeServer::preauth() << "C: A000001 CLOSE" << "S: A000001 OK Closed"; QTest::newRow("good") << scenario << 0ULL; scenario.clear(); scenario << FakeServer::preauth() << "C: A000001 CLOSE" << "S: A000001 BAD No mailbox selected"; QTest::newRow("bad") << scenario << 0ULL; scenario.clear(); scenario << FakeServer::preauth() << "C: A000001 CLOSE" << "S: A000001 OK [HIGHESTMODSEQ 123456789] Closed."; QTest::newRow("qresync") << scenario << 123456789ULL; } void testClose() { QFETCH(QList<QByteArray>, scenario); QFETCH(quint64, highestModSeq); FakeServer fakeServer; fakeServer.setScenario(scenario); fakeServer.startAndWait(); KIMAP::Session session(QStringLiteral("127.0.0.1"), 5989); auto job = new KIMAP::CloseJob(&session); bool result = job->exec(); QEXPECT_FAIL("bad", "Expected failure on BAD response", Continue); QVERIFY(result); if (result) { QCOMPARE(job->newHighestModSeq(), highestModSeq); } fakeServer.quit(); } }; QTEST_GUILESS_MAIN(CloseJobTest) #include "closejobtest.moc" 0707010000001A000081A400000000000000000000000166FAD7C000000A87000000000000000000000000000000000000004500000000kimap-VERSIONgit.20240930T185424~db1f697/autotests/createjobtest.cpp/* SPDX-FileCopyrightText: 2009 Andras Mantia <amantia@kde.org> SPDX-FileCopyrightText: 2010 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com> SPDX-FileContributor: Kevin Ottens <kevin@kdab.com> SPDX-License-Identifier: GPL-2.0-or-later */ #include <QTest> #include "kimap/createjob.h" #include "kimap/session.h" #include "kimaptest/fakeserver.h" #include <QTest> class CreateJobTest : public QObject { Q_OBJECT private Q_SLOTS: void testCreate_data() { QTest::addColumn<QString>("mailbox"); QTest::addColumn<QList<QByteArray>>("scenario"); QList<QByteArray> scenario; scenario << FakeServer::preauth() << "C: A000001 CREATE \"INBOX\"" << "S: A000001 OK CREATE completed"; QTest::newRow("good") << "INBOX" << scenario; scenario.clear(); scenario << FakeServer::preauth() << "C: A000001 CREATE \"INBOX-FAIL-BAD\"" << "S: A000001 BAD command unknown or arguments invalid"; QTest::newRow("bad") << "INBOX-FAIL-BAD" << scenario; scenario.clear(); scenario << FakeServer::preauth() << "C: A000001 CREATE \"INBOX-FAIL-NO\"" << "S: A000001 NO create failure"; QTest::newRow("no") << "INBOX-FAIL-NO" << scenario; scenario.clear(); scenario << FakeServer::preauth() << "C: A000001 CREATE \"INBOX-FAIL-IGNOREDCODE\"" << "S: A000001 NO create failure [IGNOREDCODE]"; QTest::newRow("ignoredcode") << "INBOX-FAIL-IGNOREDCODE" << scenario; scenario.clear(); scenario << FakeServer::preauth() << "C: A000001 CREATE \"INBOX-ALREADYEXISTS\"" << "S: A000001 NO create failure [ALREADYEXISTS]"; QTest::newRow("alreadyexists") << "INBOX-ALREADYEXISTS" << scenario; } void testCreate() { QFETCH(QString, mailbox); QFETCH(QList<QByteArray>, scenario); FakeServer fakeServer; fakeServer.setScenario(scenario); fakeServer.startAndWait(); KIMAP::Session session(QStringLiteral("127.0.0.1"), 5989); auto job = new KIMAP::CreateJob(&session); job->setMailBox(mailbox); bool result = job->exec(); QEXPECT_FAIL("bad", "Expected failure on BAD response", Continue); QEXPECT_FAIL("no", "Expected failure on NO response", Continue); QEXPECT_FAIL("ignoredcode", "Expected failure on NO response with ignored response code", Continue); QVERIFY(result); if (result) { QCOMPARE(job->mailBox(), mailbox); } fakeServer.quit(); } }; QTEST_GUILESS_MAIN(CreateJobTest) #include "createjobtest.moc" 0707010000001B000081A400000000000000000000000166FAD7C000000B73000000000000000000000000000000000000004500000000kimap-VERSIONgit.20240930T185424~db1f697/autotests/deletejobtest.cpp/* SPDX-FileCopyrightText: 2009 Andras Mantia <amantia@kde.org> SPDX-FileCopyrightText: 2010 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com> SPDX-FileContributor: Kevin Ottens <kevin@kdab.com> SPDX-License-Identifier: GPL-2.0-or-later */ #include <QTest> #include "kimap/deletejob.h" #include "kimap/session.h" #include "kimaptest/fakeserver.h" #include <QTest> class DeleteJobTest : public QObject { Q_OBJECT private Q_SLOTS: void testDelete_data() { QTest::addColumn<QString>("mailbox"); QTest::addColumn<QList<QByteArray>>("scenario"); QList<QByteArray> scenario; scenario << FakeServer::preauth() << "C: A000001 DELETE \"foo\"" << "S: A000001 OK DELETE completed"; QTest::newRow("good") << "foo" << scenario; scenario.clear(); scenario << FakeServer::preauth() << "C: A000001 DELETE \"foo-BAD\"" << "S: A000001 BAD command unknown or arguments invalid"; QTest::newRow("bad") << "foo-BAD" << scenario; scenario.clear(); scenario << FakeServer::preauth() << "C: A000001 DELETE \"foo\"" << "S: A000001 Name \"foo\" has inferior hierarchical names"; QTest::newRow("no") << "foo" << scenario; scenario.clear(); scenario << FakeServer::preauth() << "C: A000001 DELETE \"foo-IGNOREDCODE\"" << "S: A000001 NO Name \"foo-IGNOREDCODE\" does not exist [IGNOREDCODE]"; QTest::newRow("ignoredcode") << "foo-IGNOREDCODE" << scenario; scenario.clear(); scenario << FakeServer::preauth() << "C: A000001 DELETE \"foo-NONEXISTENT\"" << "S: A000001 NO Name \"foo-NONEXISTENT\" does not exist [NONEXISTENT]"; QTest::newRow("nonexistent") << "foo-NONEXISTENT" << scenario; scenario.clear(); scenario << FakeServer::preauth() << "C: A000001 DELETE \"foo/bar\"" << "S: A000001 OK DELETE completed"; QTest::newRow("hierarchical") << "foo/bar" << scenario; } void testDelete() { QFETCH(QString, mailbox); QFETCH(QList<QByteArray>, scenario); FakeServer fakeServer; fakeServer.setScenario(scenario); fakeServer.startAndWait(); KIMAP::Session session(QStringLiteral("127.0.0.1"), 5989); auto job = new KIMAP::DeleteJob(&session); job->setMailBox(mailbox); bool result = job->exec(); QEXPECT_FAIL("bad", "Expected failure on BAD response", Continue); QEXPECT_FAIL("no", "Expected failure on NO response", Continue); QEXPECT_FAIL("ignoredcode", "Expected failure on NO response with ignored response code", Continue); QVERIFY(result); if (result) { QCOMPARE(job->mailBox(), mailbox); } fakeServer.quit(); } }; QTEST_GUILESS_MAIN(DeleteJobTest) #include "deletejobtest.moc" 0707010000001C000081A400000000000000000000000166FAD7C000000871000000000000000000000000000000000000004500000000kimap-VERSIONgit.20240930T185424~db1f697/autotests/enablejobtest.cpp/* SPDX-FileCopyrightText: 2020 Daniel Vrátil <dvratil@kde.org> SPDX-License-Identifier: GPL-2.0-or-later */ #include <QTest> #include "kimap/enablejob.h" #include "kimap/session.h" #include "kimaptest/fakeserver.h" #include <QTest> Q_DECLARE_METATYPE(QList<QList<QByteArray>>) class EnableJobTest : public QObject { Q_OBJECT private Q_SLOTS: void testEnable_data() { QTest::addColumn<QList<QByteArray>>("scenario"); QTest::addColumn<QStringList>("reqCapabilities"); QTest::addColumn<QStringList>("supportedCaps"); QList<QByteArray> scenario; scenario << FakeServer::preauth() << "C: A000001 ENABLE CONDSTORE X-GOOD-IDEA" << "S: * ENABLED X-GOOD-IDEA" << "S: A000001 OK Enabled"; QStringList reqCapabilities = {QStringLiteral("CONDSTORE"), QStringLiteral("X-GOOD-IDEA")}; QStringList supportedCaps = {QStringLiteral("X-GOOD-IDEA")}; QTest::newRow("one feature") << scenario << reqCapabilities << supportedCaps; scenario.clear(); scenario << FakeServer::preauth() << "C: A000001 ENABLE FEATURE1 FEATURE2" << "S: * ENABLED FEATURE1 FEATURE2" << "S: A000001 OK Enabled"; reqCapabilities = QStringList{QStringLiteral("FEATURE1"), QStringLiteral("FEATURE2")}; supportedCaps = QStringList{QStringLiteral("FEATURE1"), QStringLiteral("FEATURE2")}; QTest::newRow("both features") << scenario << reqCapabilities << supportedCaps; } void testEnable() { QFETCH(QList<QByteArray>, scenario); QFETCH(QStringList, reqCapabilities); QFETCH(QStringList, supportedCaps); FakeServer fakeServer; fakeServer.setScenario(scenario); fakeServer.startAndWait(); KIMAP::Session session(QStringLiteral("127.0.0.1"), 5989); auto job = new KIMAP::EnableJob(&session); job->setCapabilities(reqCapabilities); QVERIFY(job->exec()); QCOMPARE(job->enabledCapabilities(), supportedCaps); fakeServer.quit(); } }; QTEST_GUILESS_MAIN(EnableJobTest) #include "enablejobtest.moc" 0707010000001D000081A400000000000000000000000166FAD7C000000B64000000000000000000000000000000000000004600000000kimap-VERSIONgit.20240930T185424~db1f697/autotests/expungejobtest.cpp/* SPDX-FileCopyrightText: 2016 Daniel Vrátil <dvratil@kde.org> SPDX-License-Identifier: GPL-2.0-or-later */ #include <QTest> #include "imapset.h" #include "kimap/expungejob.h" #include "kimap/session.h" #include "kimaptest/fakeserver.h" #include <QTest> class ExpungeJobTest : public QObject { Q_OBJECT private Q_SLOTS: void testDelete_data() { QTest::addColumn<QList<QByteArray>>("scenario"); QTest::addColumn<KIMAP::ImapSet>("vanishedSet"); QTest::addColumn<quint64>("highestModSeq"); QList<QByteArray> scenario; scenario << FakeServer::preauth() << "C: A000001 EXPUNGE" << "S: * 1 EXPUNGE" << "S: * 2 EXPUNGE" << "S: * 3 EXPUNGE" << "S: A000001 OK EXPUNGE completed"; QTest::newRow("good") << scenario << KIMAP::ImapSet{} << 0ULL; scenario.clear(); scenario << FakeServer::preauth() << "C: A000001 EXPUNGE" << "S: * 1" // missing EXPUNGE word << "S: A000001 OK EXPUNGE completed"; QTest::newRow("non-standard response") << scenario << KIMAP::ImapSet{} << 0ULL; scenario.clear(); scenario << FakeServer::preauth() << "C: A000001 EXPUNGE" << "S: A000001 BAD command unknown or arguments invalid"; QTest::newRow("bad") << scenario << KIMAP::ImapSet{} << 0ULL; scenario.clear(); scenario << FakeServer::preauth() << "C: A000001 EXPUNGE" << "S: A000001 NO access denied"; QTest::newRow("no") << scenario << KIMAP::ImapSet{} << 0ULL; scenario.clear(); scenario << FakeServer::preauth() << "C: A000001 EXPUNGE" << "S: * VANISHED 405,407,410:420" << "S: A000001 OK [HIGHESTMODSEQ 123456789] Expunged."; KIMAP::ImapSet vanishedSet; vanishedSet.add(QList<qint64>{405, 407}); vanishedSet.add(KIMAP::ImapInterval{410, 420}); QTest::newRow("qresync") << scenario << vanishedSet << 123456789ULL; } void testDelete() { QFETCH(QList<QByteArray>, scenario); QFETCH(KIMAP::ImapSet, vanishedSet); QFETCH(quint64, highestModSeq); FakeServer fakeServer; fakeServer.setScenario(scenario); fakeServer.startAndWait(); KIMAP::Session session(QStringLiteral("127.0.0.1"), 5989); auto job = new KIMAP::ExpungeJob(&session); bool result = job->exec(); QEXPECT_FAIL("bad", "Expected failure on BAD response", Continue); QEXPECT_FAIL("no", "Expected failure on NO response", Continue); QVERIFY(result); if (result) { QCOMPARE(job->vanishedMessages(), vanishedSet); QCOMPARE(job->newHighestModSeq(), highestModSeq); } fakeServer.quit(); } }; QTEST_GUILESS_MAIN(ExpungeJobTest) #include "expungejobtest.moc" 0707010000001E000081A400000000000000000000000166FAD7C00000010D000000000000000000000000000000000000004A00000000kimap-VERSIONgit.20240930T185424~db1f697/autotests/fakeserverscenario.logC: A000001 LIST "" * S: * LIST ( \HasChildren ) / INBOX S: * LIST ( \HasNoChildren ) / INBOX/&AOQ- &APY- &APw- @ &IKw- S: * LIST ( \HasChildren ) / INBOX/lost+found S: * LIST ( \HasNoChildren ) / "INBOX/lost+found/Calendar Public-20080128" S: A000001 OK LIST completed 0707010000001F000081A400000000000000000000000166FAD7C00000065D000000000000000000000000000000000000004600000000kimap-VERSIONgit.20240930T185424~db1f697/autotests/fakeservertest.cpp/* SPDX-FileCopyrightText: 2010 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com> SPDX-FileContributor: Kevin Ottens <kevin@kdab.com> SPDX-License-Identifier: GPL-2.0-or-later */ #include <QTest> #include "kimap/listjob.h" #include "kimap/session.h" #include "kimaptest/fakeserver.h" #include <QTest> class FakeServerTest : public QObject { Q_OBJECT private Q_SLOTS: void testLoadScenario() { KIMAP::MailBoxDescriptor descriptor; QList<KIMAP::MailBoxDescriptor> listresult; descriptor.separator = QLatin1Char('/'); descriptor.name = QStringLiteral("INBOX"); listresult << descriptor; descriptor.separator = QLatin1Char('/'); descriptor.name = QString::fromUtf8("INBOX/ä ö ü @ €"); listresult << descriptor; descriptor.separator = QLatin1Char('/'); descriptor.name = QStringLiteral("INBOX/lost+found"); listresult << descriptor; descriptor.separator = QLatin1Char('/'); descriptor.name = QStringLiteral("INBOX/lost+found/Calendar Public-20080128"); listresult << descriptor; FakeServer fakeServer; fakeServer.addScenarioFromFile(QStringLiteral(TEST_DATA) + QStringLiteral("/fakeserverscenario.log")); fakeServer.startAndWait(); KIMAP::Session session(QStringLiteral("127.0.0.1"), 5989); auto job = new KIMAP::ListJob(&session); job->setOption(KIMAP::ListJob::IncludeUnsubscribed); QVERIFY(job->exec()); fakeServer.quit(); } }; QTEST_GUILESS_MAIN(FakeServerTest) #include "fakeservertest.moc" 07070100000020000081A400000000000000000000000166FAD7C00000498D000000000000000000000000000000000000004400000000kimap-VERSIONgit.20240930T185424~db1f697/autotests/fetchjobtest.cpp/* SPDX-FileCopyrightText: 2010 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com> SPDX-FileContributor: Kevin Ottens <kevin@kdab.com> SPDX-License-Identifier: GPL-2.0-or-later */ #include <QTest> #include "kimap/fetchjob.h" #include "kimap/session.h" #include "kimaptest/fakeserver.h" #include <QSignalSpy> #include <QTest> Q_DECLARE_METATYPE(KIMAP::FetchJob::FetchScope) class FetchJobTest : public QObject { Q_OBJECT public: FetchJobTest() { qRegisterMetaType<KIMAP::ImapSet>(); } private: QStringList m_signals; QMap<qint64, qint64> m_uids; QMap<qint64, qint64> m_sizes; QMap<qint64, KIMAP::MessageFlags> m_flags; QMap<qint64, KIMAP::MessagePtr> m_messages; QMap<qint64, KIMAP::MessageParts> m_parts; QMap<qint64, KIMAP::MessageAttribute> m_attrs; QMap<qint64, KIMAP::Message> m_msgs; public Q_SLOTS: void onHeadersReceived(const QString & /*mailBox*/, const QMap<qint64, qint64> &uids, const QMap<qint64, qint64> &sizes, const QMap<qint64, KIMAP::MessageAttribute> &attrs, const QMap<qint64, KIMAP::MessageFlags> &flags, const QMap<qint64, KIMAP::MessagePtr> &messages) { m_signals << QStringLiteral("headersReceived"); m_uids.insert(uids); m_sizes.insert(sizes); m_flags.insert(flags); m_messages.insert(messages); m_attrs.insert(attrs); } void onMessagesReceived(const QString & /*mailbox*/, const QMap<qint64, qint64> &uids, const QMap<qint64, KIMAP::MessageAttribute> &attrs, const QMap<qint64, KIMAP::MessagePtr> &messages) { m_signals << QStringLiteral("messagesReceived"); m_uids.insert(uids); m_messages.insert(messages); m_attrs.insert(attrs); } void onPartsReceived(const QString & /*mailbox*/, const QMap<qint64, qint64> & /*uids*/, const QMap<qint64, KIMAP::MessageAttribute> &attrs, const QMap<qint64, KIMAP::MessageParts> &parts) { m_signals << QStringLiteral("partsReceived"); m_attrs.insert(attrs); m_parts.insert(parts); } void onMessagesAvailable(const QMap<qint64, KIMAP::Message> &messages) { m_signals << QStringLiteral("messagesAvailable"); m_msgs.insert(messages); } private Q_SLOTS: void testFetch_data() { qRegisterMetaType<KIMAP::FetchJob::FetchScope>(); QTest::addColumn<bool>("uidBased"); QTest::addColumn<KIMAP::ImapSet>("set"); QTest::addColumn<int>("expectedMessageCount"); QTest::addColumn<QList<QByteArray>>("scenario"); QTest::addColumn<KIMAP::FetchJob::FetchScope>("scope"); QTest::addColumn<KIMAP::ImapSet>("expectedVanished"); KIMAP::FetchJob::FetchScope scope; scope.mode = KIMAP::FetchJob::FetchScope::Flags; scope.changedSince = 123456789; QList<QByteArray> scenario; scenario << FakeServer::preauth() << "C: A000001 FETCH 1:4 (FLAGS UID) (CHANGEDSINCE 123456789)" << "S: * 1 FETCH ( FLAGS () UID 1 )" << "S: * 2 FETCH ( FLAGS () UID 2 )" << "S: * 3 FETCH ( FLAGS () UID 3 )" << "S: * 4 FETCH ( FLAGS () UID 4 )" << "S: A000001 OK fetch done"; QTest::newRow("messages have empty flags (with changedsince)") << false << KIMAP::ImapSet(1, 4) << 4 << scenario << scope << KIMAP::ImapSet{}; scenario.clear(); scope.changedSince = 0; scenario << FakeServer::preauth() << "C: A000001 FETCH 1:4 (FLAGS UID)" << "S: * 1 FETCH ( FLAGS () UID 1 )" << "S: * 2 FETCH ( FLAGS () UID 2 )" << "S: * 3 FETCH ( FLAGS () UID 3 )" << "S: * 4 FETCH ( FLAGS () UID 4 )" << "S: A000001 OK fetch done"; QTest::newRow("messages have empty flags") << false << KIMAP::ImapSet(1, 4) << 4 << scenario << scope << KIMAP::ImapSet{}; scenario.clear(); // kill the connection part-way through a list, with carriage returns at end // BUG 253619 // this should fail, but it shouldn't crash scenario << FakeServer::preauth() << "C: A000001 FETCH 11 (RFC822.SIZE INTERNALDATE BODY.PEEK[HEADER.FIELDS (TO FROM MESSAGE-ID REFERENCES IN-REPLY-TO SUBJECT DATE)] FLAGS UID)" << "S: * 11 FETCH (RFC822.SIZE 770 INTERNALDATE \"11-Oct-2010 03:33:50 +0100\" BODY[HEADER.FIELDS (TO FROM MESSAGE-ID REFERENCES IN-REPLY-TO " "SUBJECT DATE)] {246}" << "S: From: John Smith <jonathanr.smith@foobarbaz.com>\r\nTo: " "\"amagicemailaddress@foobarbazbarfoo.com\"\r\n\t<amagicemailaddress@foobarbazbarfoo.com>\r\nDate: Mon, 11 Oct 2010 03:34:48 " "+0100\r\nSubject: unsubscribe\r\nMessage-ID: <ASDFFDSASDFFDS@foobarbaz.com>\r\n\r\n" << "X"; scope.mode = KIMAP::FetchJob::FetchScope::Headers; QTest::newRow("connection drop") << false << KIMAP::ImapSet(11, 11) << 1 << scenario << scope << KIMAP::ImapSet{}; scenario.clear(); // Important bit here if "([127.0.0.1])" which used to crash the stream parser scenario << FakeServer::preauth() << "C: A000001 FETCH 11 (RFC822.SIZE INTERNALDATE BODY.PEEK[HEADER.FIELDS (TO FROM MESSAGE-ID REFERENCES IN-REPLY-TO SUBJECT DATE)] FLAGS UID)" << "S: * 11 FETCH (RFC822.SIZE 770 INTERNALDATE \"11-Oct-2010 03:33:50 +0100\" BODY[HEADER.FIELDS (TO FROM MESSAGE-ID REFERENCES IN-REPLY-TO " "SUBJECT DATE)] {246}" << "S: ([127.0.0.1])\r\nDate: Mon, 11 Oct 2010 03:34:48 +0100\r\nSubject: unsubscribe\r\nMessage-ID: <ASDFFDSASDFFDS@foobarbaz.com>\r\n\r\n" << "X"; scope.mode = KIMAP::FetchJob::FetchScope::Headers; QTest::newRow("buffer overwrite") << false << KIMAP::ImapSet(11, 11) << 1 << scenario << scope << KIMAP::ImapSet{}; scenario.clear(); // We're assuming a buffer overwrite here which made us miss the opening parenthesis // for the properties list scenario << FakeServer::preauth() << "C: A000001 FETCH 11 (RFC822.SIZE INTERNALDATE BODY.PEEK[HEADER.FIELDS (TO FROM MESSAGE-ID REFERENCES IN-REPLY-TO SUBJECT DATE)] FLAGS UID)" << "S: * 11 FETCH {10}doh!\r\n\r\n\r\n)\r\n" << "X"; scope.mode = KIMAP::FetchJob::FetchScope::Headers; QTest::newRow("buffer overwrite 2") << false << KIMAP::ImapSet(11, 11) << 1 << scenario << scope << KIMAP::ImapSet{}; scenario.clear(); scenario << FakeServer::preauth() << "C: A000001 FETCH 11 (RFC822.SIZE INTERNALDATE BODY.PEEK[HEADER] FLAGS UID) (CHANGEDSINCE 123456789)" << "S: * 11 FETCH (UID 123 RFC822.SIZE 770 INTERNALDATE \"11-Oct-2010 03:33:50 +0100\" BODY[HEADER] {245}" << "S: From: John Smith <jonathanr.smith@foobarbaz.com>\r\nTo: " "\"amagicemailaddress@foobarbazbarfoo.com\"\r\n\t<amagicemailaddress@foobarbazbarfoo.com>\r\nDate: Mon, 11 Oct 2010 03:34:48 " "+0100\r\nSubject: unsubscribe\r\nMessage-ID: <ASDFFDSASDFFDS@foobarbaz.com>\r\n\r\n FLAGS ())" << "S: A000001 OK fetch done"; scope.mode = KIMAP::FetchJob::FetchScope::FullHeaders; scope.changedSince = 123456789; QTest::newRow("fetch full headers") << false << KIMAP::ImapSet(11, 11) << 1 << scenario << scope << KIMAP::ImapSet{}; scenario.clear(); scenario << FakeServer::preauth() << "C: A000001 UID FETCH 300:500 (FLAGS UID) (CHANGEDSINCE 12345 VANISHED)" << "S: * VANISHED (EARLIER) 300:310,405,411" << "S: * 1 FETCH (UID 404 MODSEQ (65402) FLAGS (\\Seen))" << "S: * 2 FETCH (UID 406 MODSEQ (75403) FLAGS (\\Deleted))" << "S: * 4 FETCH (UID 408 MODSEQ (29738) FLAGS ($Nojunk $AutoJunk $MDNSent))" << "S: A000001 OK Fetch completed"; scope.mode = KIMAP::FetchJob::FetchScope::Flags; scope.changedSince = 12345; scope.qresync = true; KIMAP::ImapSet vanished; vanished.add(KIMAP::ImapInterval{300, 310}); vanished.add(QList<qint64>{405, 411}); QTest::newRow("qresync") << true << KIMAP::ImapSet(300, 500) << 3 << scenario << scope << vanished; } void testFetch() { QFETCH(bool, uidBased); QFETCH(KIMAP::ImapSet, set); QFETCH(int, expectedMessageCount); QFETCH(QList<QByteArray>, scenario); QFETCH(KIMAP::FetchJob::FetchScope, scope); QFETCH(KIMAP::ImapSet, expectedVanished); FakeServer fakeServer; fakeServer.setScenario(scenario); fakeServer.startAndWait(); KIMAP::Session session(QStringLiteral("127.0.0.1"), 5989); auto job = new KIMAP::FetchJob(&session); job->setUidBased(uidBased); job->setSequenceSet(set); job->setScope(scope); connect(job, SIGNAL(headersReceived(QString, QMap<qint64, qint64>, QMap<qint64, qint64>, QMap<qint64, KIMAP::MessageAttribute>, QMap<qint64, KIMAP::MessageFlags>, QMap<qint64, KIMAP::MessagePtr>)), this, SLOT(onHeadersReceived(QString, QMap<qint64, qint64>, QMap<qint64, qint64>, QMap<qint64, KIMAP::MessageAttribute>, QMap<qint64, KIMAP::MessageFlags>, QMap<qint64, KIMAP::MessagePtr>))); connect(job, &KIMAP::FetchJob::messagesAvailable, this, &FetchJobTest::onMessagesAvailable); QSignalSpy vanishedSpy(job, &KIMAP::FetchJob::messagesVanished); QVERIFY(vanishedSpy.isValid()); bool result = job->exec(); QEXPECT_FAIL("connection drop", "Expected failure on connection drop", Continue); QEXPECT_FAIL("buffer overwrite", "Expected failure on confused list", Continue); QEXPECT_FAIL("buffer overwrite 2", "Expected beginning of message missing", Continue); QVERIFY(result); if (result) { QVERIFY(m_signals.count() > 0); QCOMPARE(m_uids.count(), expectedMessageCount); QCOMPARE(m_msgs.count(), expectedMessageCount); if (scope.qresync) { QCOMPARE(vanishedSpy.size(), 1); QCOMPARE(vanishedSpy.at(0).at(0).value<KIMAP::ImapSet>(), expectedVanished); } } QVERIFY(fakeServer.isAllScenarioDone()); fakeServer.quit(); m_signals.clear(); m_uids.clear(); m_sizes.clear(); m_flags.clear(); m_messages.clear(); m_parts.clear(); m_attrs.clear(); m_msgs.clear(); } void testFetchStructure() { QList<QByteArray> scenario; scenario << FakeServer::preauth() << "C: A000001 FETCH 1:2 (BODYSTRUCTURE UID)" << R"(S: * 1 FETCH (UID 10 BODYSTRUCTURE ("TEXT" "PLAIN" ("CHARSET" "ISO-8859-1") NIL NIL "7BIT" 5 1 NIL NIL NIL)))" << R"(S: * 2 FETCH (UID 20 BODYSTRUCTURE (((("TEXT" "PLAIN" ("CHARSET" "ISO-8859-1") NIL NIL "7BIT" 72 4 NIL NIL NIL)("TEXT" "HTML" ("CHARSET" "ISO-8859-1") NIL NIL "QUOTED-PRINTABLE" 281 5 NIL NIL NIL) "ALTERNATIVE" ("BOUNDARY" "0001") NIL NIL)("IMAGE" "GIF" ("NAME" "B56.gif") "<B56@goomoji.gmail>" NIL "BASE64" 528 NIL NIL NIL) "RELATED" ("BOUNDARY" "0002") NIL NIL)("IMAGE" "JPEG" ("NAME" "photo.jpg") NIL NIL "BASE64" 53338 NIL ("ATTACHMENT" ("FILENAME" "photo.jpg")) NIL) "MIXED" ("BOUNDARY" "0003") NIL NIL)))" << "S: A000001 OK fetch done"; KIMAP::FetchJob::FetchScope scope; scope.mode = KIMAP::FetchJob::FetchScope::Structure; FakeServer fakeServer; fakeServer.setScenario(scenario); fakeServer.startAndWait(); KIMAP::Session session(QStringLiteral("127.0.0.1"), 5989); auto job = new KIMAP::FetchJob(&session); job->setUidBased(false); job->setSequenceSet(KIMAP::ImapSet(1, 2)); job->setScope(scope); connect(job, SIGNAL(messagesReceived(QString, QMap<qint64, qint64>, QMap<qint64, KIMAP::MessageAttribute>, QMap<qint64, KIMAP::MessagePtr>)), this, SLOT(onMessagesReceived(QString, QMap<qint64, qint64>, QMap<qint64, KIMAP::MessageAttribute>, QMap<qint64, KIMAP::MessagePtr>))); connect(job, &KIMAP::FetchJob::messagesAvailable, this, &FetchJobTest::onMessagesAvailable); bool result = job->exec(); QVERIFY(result); QVERIFY(m_signals.count() > 0); QCOMPARE(m_uids.count(), 2); QCOMPARE(m_messages[1]->attachments().count(), 0); QCOMPARE(m_messages[2]->attachments().count(), 1); QCOMPARE(m_messages[2]->contents().size(), 2); QCOMPARE(m_messages[2]->contents()[0]->contents().size(), 2); QCOMPARE(m_messages[2]->attachments().at(0)->contentDisposition()->filename(), QStringLiteral("photo.jpg")); QCOMPARE(m_msgs.count(), 2); QCOMPARE(m_msgs[1].message->attachments().count(), 0); QCOMPARE(m_msgs[2].message->attachments().count(), 1); QCOMPARE(m_msgs[2].message->contents().size(), 2); QCOMPARE(m_msgs[2].message->contents()[0]->contents().size(), 2); QCOMPARE(m_msgs[2].message->attachments().at(0)->contentDisposition()->filename(), QStringLiteral("photo.jpg")); fakeServer.quit(); m_signals.clear(); m_uids.clear(); m_sizes.clear(); m_flags.clear(); m_messages.clear(); m_parts.clear(); m_attrs.clear(); m_msgs.clear(); } void testFetchParts() { QList<QByteArray> scenario; scenario << FakeServer::preauth() << "C: A000001 FETCH 2 (BODY.PEEK[HEADER.FIELDS (TO FROM MESSAGE-ID REFERENCES IN-REPLY-TO SUBJECT DATE)] BODY.PEEK[1.1.1.MIME] " "BODY.PEEK[1.1.1] FLAGS UID)" << "S: * 2 FETCH (UID 20 FLAGS (\\Seen) BODY[HEADER.FIELDS (TO FROM MESSAGE-ID REFERENCES IN-REPLY-TO SUBJECT DATE)] {154}\r\nFrom: Joe Smith " "<smith@example.com>\r\nDate: Wed, 2 Mar 2011 11:33:24 +0700\r\nMessage-ID: <1234@example.com>\r\nSubject: hello\r\nTo: Jane " "<jane@example.com>\r\n\r\n BODY[1.1.1] {28}\r\nHi Jane, nice to meet you!\r\n BODY[1.1.1.MIME] {48}\r\nContent-Type: text/plain; " "charset=ISO-8859-1\r\n\r\n)\r\n" << "S: A000001 OK fetch done"; KIMAP::FetchJob::FetchScope scope; scope.mode = KIMAP::FetchJob::FetchScope::HeaderAndContent; scope.parts.clear(); scope.parts.append("1.1.1"); FakeServer fakeServer; fakeServer.setScenario(scenario); fakeServer.startAndWait(); KIMAP::Session session(QStringLiteral("127.0.0.1"), 5989); auto job = new KIMAP::FetchJob(&session); job->setUidBased(false); job->setSequenceSet(KIMAP::ImapSet(2, 2)); job->setScope(scope); connect(job, SIGNAL(headersReceived(QString, QMap<qint64, qint64>, QMap<qint64, qint64>, QMap<qint64, KIMAP::MessageAttribute>, QMap<qint64, KIMAP::MessageFlags>, QMap<qint64, KIMAP::MessagePtr>)), this, SLOT(onHeadersReceived(QString, QMap<qint64, qint64>, QMap<qint64, qint64>, QMap<qint64, KIMAP::MessageAttribute>, QMap<qint64, KIMAP::MessageFlags>, QMap<qint64, KIMAP::MessagePtr>))); connect(job, SIGNAL(partsReceived(QString, QMap<qint64, qint64>, QMap<qint64, KIMAP::MessageAttribute>, QMap<qint64, KIMAP::MessageParts>)), this, SLOT(onPartsReceived(QString, QMap<qint64, qint64>, QMap<qint64, KIMAP::MessageAttribute>, QMap<qint64, KIMAP::MessageParts>))); connect(job, &KIMAP::FetchJob::messagesAvailable, this, &FetchJobTest::onMessagesAvailable); bool result = job->exec(); QVERIFY(result); QVERIFY(m_signals.count() > 0); QCOMPARE(m_uids.count(), 1); QCOMPARE(m_parts.count(), 1); QCOMPARE(m_attrs.count(), 0); QCOMPARE(m_msgs.count(), 1); // Check that we received the message header QCOMPARE(m_messages[2]->messageID()->identifier(), QByteArray("1234@example.com")); QCOMPARE(m_msgs[2].message->messageID()->identifier(), QByteArray("1234@example.com")); // Check that we received the flags QMap<qint64, KIMAP::MessageFlags> expectedFlags; expectedFlags.insert(2, KIMAP::MessageFlags() << "\\Seen"); QCOMPARE(m_flags, expectedFlags); QCOMPARE(m_msgs[2].flags, expectedFlags[2]); // Check that we didn't received the full message body, since we only requested a specific part QCOMPARE(m_messages[2]->decodedText().length(), 0); QCOMPARE(m_messages[2]->attachments().count(), 0); QCOMPARE(m_msgs[2].message->decodedText().length(), 0); QCOMPARE(m_msgs[2].message->attachments().count(), 0); // Check that we received the part we requested QByteArray partId = m_parts[2].keys().first(); QString text = m_parts[2].value(partId)->decodedText(true, true); QCOMPARE(partId, QByteArray("1.1.1")); QCOMPARE(text, QStringLiteral("Hi Jane, nice to meet you!")); QCOMPARE(m_msgs[2].parts.keys().first(), QByteArray("1.1.1")); QCOMPARE(m_msgs[2].parts.value(partId)->decodedText(true, true), QStringLiteral("Hi Jane, nice to meet you!")); fakeServer.quit(); m_signals.clear(); m_uids.clear(); m_sizes.clear(); m_flags.clear(); m_messages.clear(); m_parts.clear(); m_attrs.clear(); m_msgs.clear(); } }; QTEST_GUILESS_MAIN(FetchJobTest) #include "fetchjobtest.moc" 07070100000021000081A400000000000000000000000166FAD7C000003F18000000000000000000000000000000000000004A00000000kimap-VERSIONgit.20240930T185424~db1f697/autotests/getmetadatajobtest.cpp/* SPDX-FileCopyrightText: 2013 Christian Mollekopf <mollekopf@kolabsys.com> SPDX-License-Identifier: GPL-2.0-or-later */ #include <QTest> #include "kimap/getmetadatajob.h" #include "kimap/session.h" #include "kimaptest/fakeserver.h" #include <QDebug> #include <QTest> using MAP = QMap<QByteArray, QByteArray>; Q_DECLARE_METATYPE(MAP) class GetMetadataJobTest : public QObject { Q_OBJECT private Q_SLOTS: void metadata_data() { QTest::addColumn<QList<QByteArray>>("scenario"); QTest::addColumn<QString>("mailbox"); QTest::addColumn<QMap<QByteArray, QByteArray>>("expectedAnnotations"); { // FIXME requesting /shared and getting /private back doesn't make sense => fix scenario QList<QByteArray> scenario; scenario << FakeServer::preauth() << "C: A000001 GETMETADATA (DEPTH infinity) \"Folder1\" (/shared)" << R"(S: * METADATA "Folder1" (/shared/comment "Shared comment"))" << R"(S: * METADATA "Folder1" (/private/comment "My own comment"))" << "S: A000001 OK GETMETADATA complete"; QMap<QByteArray, QByteArray> expected; expected.insert("/shared/comment", "Shared comment"); expected.insert("/private/comment", "My own comment"); QTest::newRow("normal") << scenario << "Folder1" << expected; } { QList<QByteArray> scenario; scenario << FakeServer::preauth() << "C: A000001 GETMETADATA (DEPTH infinity) \"Folder1\" (/shared)" << R"(S: * METADATA "Folder1" (/shared/comment "Shared comment" /private/comment "My own comment"))" << "S: A000001 OK GETMETADATA complete"; QMap<QByteArray, QByteArray> expected; expected.insert("/shared/comment", "Shared comment"); expected.insert("/private/comment", "My own comment"); QTest::newRow("combined response") << scenario << "Folder1" << expected; } { QList<QByteArray> scenario; scenario << FakeServer::preauth() << "C: A000001 GETMETADATA (DEPTH infinity) \"Folder1\" (/shared)" << R"(S: * METADATA "Folder1" (/shared/comment "NIL" /private/comment "NIL"))" << "S: A000001 OK GETMETADATA complete"; QMap<QByteArray, QByteArray> expected; expected.insert("/shared/comment", ""); expected.insert("/private/comment", ""); QTest::newRow("NIL response") << scenario << "Folder1" << expected; } } void metadata() { QFETCH(QList<QByteArray>, scenario); QFETCH(QString, mailbox); QFETCH(MAP, expectedAnnotations); FakeServer fakeServer; fakeServer.setScenario(scenario); fakeServer.startAndWait(); KIMAP::Session session(QLatin1StringView("127.0.0.1"), 5989); auto getMetadataJob = new KIMAP::GetMetaDataJob(&session); getMetadataJob->setServerCapability(KIMAP::MetaDataJobBase::Metadata); getMetadataJob->setMailBox(mailbox); getMetadataJob->setDepth(KIMAP::GetMetaDataJob::AllLevels); getMetadataJob->addRequestedEntry("/shared"); QVERIFY(getMetadataJob->exec()); QCOMPARE(getMetadataJob->allMetaData(mailbox).size(), expectedAnnotations.size()); const QMap<QByteArray, QByteArray> &allMetaData = getMetadataJob->allMetaData(); QCOMPARE(allMetaData.size(), expectedAnnotations.size()); const auto keys = expectedAnnotations.keys(); for (const QByteArray &entry : keys) { QCOMPARE(getMetadataJob->metaData(mailbox, entry), expectedAnnotations.value(entry)); QCOMPARE(getMetadataJob->metaData(entry), expectedAnnotations.value(entry)); QCOMPARE(allMetaData.value(entry), expectedAnnotations.value(entry)); } fakeServer.quit(); } void testMetadataParameter() { FakeServer fakeServer; QList<QByteArray> scenario; scenario << FakeServer::preauth() << "C: A000001 GETMETADATA \"Folder1\" (/shared)" << "S: A000001 OK GETMETADATA complete" << "C: A000002 GETMETADATA (DEPTH 1) \"Folder1\" (/shared)" << "S: A000002 OK GETMETADATA complete" << "C: A000003 GETMETADATA (MAXSIZE 1234) \"Folder1\" (/shared)" << "S: A000003 OK GETMETADATA complete" << "C: A000004 GETMETADATA (DEPTH 1 MAXSIZE 1234) \"Folder1\" (/shared)" << "S: A000004 OK GETMETADATA complete" << "C: A000005 GETMETADATA (DEPTH 1 MAXSIZE 1234) \"Folder1\" (/shared /shared2)" << "S: A000005 OK GETMETADATA complete" << "C: A000006 GETMETADATA (DEPTH 1 MAXSIZE 1234) \"Folder1\"" << "S: A000006 OK GETMETADATA complete" << "C: A000007 GETMETADATA (DEPTH 1) \"Folder1\"" << "S: A000007 OK GETMETADATA complete" << "C: A000008 GETMETADATA (MAXSIZE 1234) \"Folder1\"" << "S: A000008 OK GETMETADATA complete" << "C: A000009 GETMETADATA \"Folder1\"" << "S: A000009 OK GETMETADATA complete" << "C: A000010 GETMETADATA \"\"" << "S: A000010 OK GETMETADATA complete"; fakeServer.setScenario(scenario); fakeServer.startAndWait(); KIMAP::Session session(QStringLiteral("127.0.0.1"), 5989); // C: A000001 GETMETADATA "Folder1" (/shared) auto getMetadataJob = new KIMAP::GetMetaDataJob(&session); getMetadataJob->setServerCapability(KIMAP::MetaDataJobBase::Metadata); getMetadataJob->setMailBox(QStringLiteral("Folder1")); getMetadataJob->addRequestedEntry("/shared"); getMetadataJob->setDepth(KIMAP::GetMetaDataJob::NoDepth); QVERIFY(getMetadataJob->exec()); QCOMPARE(getMetadataJob->allMetaData(QLatin1StringView("Folder1")).size(), 0); // C: A000002 GETMETADATA "Folder1" (DEPTH 1) (/shared) getMetadataJob = new KIMAP::GetMetaDataJob(&session); getMetadataJob->setServerCapability(KIMAP::MetaDataJobBase::Metadata); getMetadataJob->setMailBox(QStringLiteral("Folder1")); getMetadataJob->addRequestedEntry("/shared"); getMetadataJob->setDepth(KIMAP::GetMetaDataJob::OneLevel); QVERIFY(getMetadataJob->exec()); // C: A000003 GETMETADATA "Folder1" (MAXSIZE 1234) (/shared) getMetadataJob = new KIMAP::GetMetaDataJob(&session); getMetadataJob->setServerCapability(KIMAP::MetaDataJobBase::Metadata); getMetadataJob->setMailBox(QStringLiteral("Folder1")); getMetadataJob->addRequestedEntry("/shared"); getMetadataJob->setDepth(KIMAP::GetMetaDataJob::NoDepth); getMetadataJob->setMaximumSize(1234); QVERIFY(getMetadataJob->exec()); // C: A000004 GETMETADATA "Folder1" (DEPTH 1) (MAXSIZE 1234) (/shared) getMetadataJob = new KIMAP::GetMetaDataJob(&session); getMetadataJob->setServerCapability(KIMAP::MetaDataJobBase::Metadata); getMetadataJob->setMailBox(QStringLiteral("Folder1")); getMetadataJob->addRequestedEntry("/shared"); getMetadataJob->setDepth(KIMAP::GetMetaDataJob::OneLevel); getMetadataJob->setMaximumSize(1234); QVERIFY(getMetadataJob->exec()); // C: A000005 GETMETADATA "Folder1" (DEPTH 1) (MAXSIZE 1234) (/shared /shared2) getMetadataJob = new KIMAP::GetMetaDataJob(&session); getMetadataJob->setServerCapability(KIMAP::MetaDataJobBase::Metadata); getMetadataJob->setMailBox(QStringLiteral("Folder1")); getMetadataJob->addRequestedEntry("/shared"); getMetadataJob->addRequestedEntry("/shared2"); getMetadataJob->setDepth(KIMAP::GetMetaDataJob::OneLevel); getMetadataJob->setMaximumSize(1234); QVERIFY(getMetadataJob->exec()); // C: A000006 GETMETADATA "Folder1" (DEPTH 1) (MAXSIZE 1234) getMetadataJob = new KIMAP::GetMetaDataJob(&session); getMetadataJob->setServerCapability(KIMAP::MetaDataJobBase::Metadata); getMetadataJob->setMailBox(QStringLiteral("Folder1")); getMetadataJob->setDepth(KIMAP::GetMetaDataJob::OneLevel); getMetadataJob->setMaximumSize(1234); QVERIFY(getMetadataJob->exec()); // C: A000007 GETMETADATA "Folder1" (DEPTH 1) getMetadataJob = new KIMAP::GetMetaDataJob(&session); getMetadataJob->setServerCapability(KIMAP::MetaDataJobBase::Metadata); getMetadataJob->setMailBox(QStringLiteral("Folder1")); getMetadataJob->setDepth(KIMAP::GetMetaDataJob::OneLevel); QVERIFY(getMetadataJob->exec()); // C: A000008 GETMETADATA "Folder1" (MAXSIZE 1234) getMetadataJob = new KIMAP::GetMetaDataJob(&session); getMetadataJob->setServerCapability(KIMAP::MetaDataJobBase::Metadata); getMetadataJob->setMailBox(QStringLiteral("Folder1")); getMetadataJob->setDepth(KIMAP::GetMetaDataJob::NoDepth); getMetadataJob->setMaximumSize(1234); QVERIFY(getMetadataJob->exec()); // C: A000009 GETMETADATA "Folder1" getMetadataJob = new KIMAP::GetMetaDataJob(&session); getMetadataJob->setServerCapability(KIMAP::MetaDataJobBase::Metadata); getMetadataJob->setMailBox(QStringLiteral("Folder1")); getMetadataJob->setDepth(KIMAP::GetMetaDataJob::NoDepth); QVERIFY(getMetadataJob->exec()); // C: A000010 GETMETADATA "" getMetadataJob = new KIMAP::GetMetaDataJob(&session); getMetadataJob->setServerCapability(KIMAP::MetaDataJobBase::Metadata); getMetadataJob->setMailBox(QLatin1StringView("")); getMetadataJob->setDepth(KIMAP::GetMetaDataJob::NoDepth); QVERIFY(getMetadataJob->exec()); QVERIFY(fakeServer.isAllScenarioDone()); fakeServer.quit(); } void annotatemore_data() { QTest::addColumn<QList<QByteArray>>("scenario"); QTest::addColumn<QString>("mailbox"); QTest::addColumn<QMap<QByteArray, QByteArray>>("expectedAnnotations"); QTest::addColumn<QByteArray>("entry"); { QList<QByteArray> scenario; scenario << FakeServer::preauth() << R"(C: A000001 GETANNOTATION "Folder1" "*" "value.shared")" << "S: * ANNOTATION Folder1 /comment (value.shared \"Shared comment\")" << "S: * ANNOTATION Folder1 /comment (value.priv \"My own comment\")" << "S: A000001 OK annotations retrieved"; QMap<QByteArray, QByteArray> expected; expected.insert("/shared/comment", "Shared comment"); expected.insert("/private/comment", "My own comment"); QTest::newRow("get all") << scenario << "Folder1" << expected << QByteArray("/shared*"); } { QList<QByteArray> scenario; scenario << FakeServer::preauth() << R"(C: A000001 GETANNOTATION "Folder1" "/comment" "value.shared")" << "S: * ANNOTATION Folder1 /comment (value.shared \"Shared comment\")" << "S: * ANNOTATION Folder1 /comment (value.priv \"My own comment\")" << "S: A000001 OK annotations retrieved"; QMap<QByteArray, QByteArray> expected; expected.insert("/shared/comment", "Shared comment"); expected.insert("/private/comment", "My own comment"); QTest::newRow("get single") << scenario << "Folder1" << expected << QByteArray("/shared/comment"); } } void annotatemore() { QFETCH(QList<QByteArray>, scenario); QFETCH(QString, mailbox); QFETCH(MAP, expectedAnnotations); QFETCH(QByteArray, entry); FakeServer fakeServer; fakeServer.setScenario(scenario); fakeServer.startAndWait(); KIMAP::Session session(QStringLiteral("127.0.0.1"), 5989); auto getMetadataJob = new KIMAP::GetMetaDataJob(&session); getMetadataJob->setServerCapability(KIMAP::MetaDataJobBase::Annotatemore); getMetadataJob->setMailBox(mailbox); getMetadataJob->addRequestedEntry(entry); QVERIFY(getMetadataJob->exec()); // qDebug() << getMetadataJob->allMetaData(mailbox); qDebug() << getMetadataJob->allMetaData(); const QMap<QByteArray, QByteArray> &allMetaData = getMetadataJob->allMetaData(); QCOMPARE(allMetaData.size(), expectedAnnotations.size()); const auto keys = expectedAnnotations.keys(); for (const QByteArray &e : keys) { QCOMPARE(getMetadataJob->metaData(e), expectedAnnotations.value(e)); QCOMPARE(allMetaData.value(e), expectedAnnotations.value(e)); } fakeServer.quit(); } void testAnnotateEntires() { FakeServer fakeServer; QList<QByteArray> scenario; scenario << FakeServer::preauth() << "C: A000001 GETANNOTATION \"Folder1\"" << "S: A000001 OK annotations retrieved" << R"(C: A000002 GETANNOTATION "Folder1" ("/comment" "/motd") ("value.priv" "value.shared"))" << "S: A000002 OK annotations retrieved"; fakeServer.setScenario(scenario); fakeServer.startAndWait(); KIMAP::Session session(QStringLiteral("127.0.0.1"), 5989); // C: A000001 GETANNOTATION "Folder1" auto getMetadataJob = new KIMAP::GetMetaDataJob(&session); getMetadataJob->setServerCapability(KIMAP::MetaDataJobBase::Annotatemore); getMetadataJob->setMailBox(QStringLiteral("Folder1")); QVERIFY(getMetadataJob->exec()); QCOMPARE(getMetadataJob->allMetaData(QLatin1StringView("Folder1")).size(), 0); // C: A000002 GETANNOTATION "Folder1" ("/comment" "/motd") ("value.shared" "value.priv") getMetadataJob = new KIMAP::GetMetaDataJob(&session); getMetadataJob->setServerCapability(KIMAP::MetaDataJobBase::Annotatemore); getMetadataJob->setMailBox(QStringLiteral("Folder1")); getMetadataJob->addRequestedEntry("/shared/comment"); getMetadataJob->addRequestedEntry("/private/motd"); QVERIFY(getMetadataJob->exec()); QVERIFY(fakeServer.isAllScenarioDone()); fakeServer.quit(); } void testAnnotateMutiple() { // Do not double same parts of the request FakeServer fakeServer; QList<QByteArray> scenario; scenario << FakeServer::preauth() << R"(C: A000001 GETANNOTATION "Folder1" ("/comment" "/motd") "value.shared")" << "S: A000001 OK annotations retrieved" << R"(C: A000002 GETANNOTATION "Folder1" "/comment" ("value.priv" "value.shared"))" << "S: A000002 OK annotations retrieved"; fakeServer.setScenario(scenario); fakeServer.startAndWait(); KIMAP::Session session(QStringLiteral("127.0.0.1"), 5989); // C: A000001 GETANNOTATION "Folder1" ("/comment" "/motd") "value.shared" auto getMetadataJob = new KIMAP::GetMetaDataJob(&session); getMetadataJob->setServerCapability(KIMAP::MetaDataJobBase::Annotatemore); getMetadataJob->setMailBox(QStringLiteral("Folder1")); getMetadataJob->addRequestedEntry("/shared/comment"); getMetadataJob->addRequestedEntry("/shared/motd"); QVERIFY(getMetadataJob->exec()); // C: A000002 GETANNOTATION "Folder1" ("/comment") ("value.shared" "value.priv") getMetadataJob = new KIMAP::GetMetaDataJob(&session); getMetadataJob->setServerCapability(KIMAP::MetaDataJobBase::Annotatemore); getMetadataJob->setMailBox(QStringLiteral("Folder1")); getMetadataJob->addRequestedEntry("/shared/comment"); getMetadataJob->addRequestedEntry("/private/comment"); QVERIFY(getMetadataJob->exec()); QVERIFY(fakeServer.isAllScenarioDone()); fakeServer.quit(); } }; QTEST_GUILESS_MAIN(GetMetadataJobTest) #include "getmetadatajobtest.moc" 07070100000022000081A400000000000000000000000166FAD7C0000005C9000000000000000000000000000000000000004100000000kimap-VERSIONgit.20240930T185424~db1f697/autotests/idjobtest.cpp/* SPDX-FileCopyrightText: 2015 Christian Mollekopf <mollekopf@kolabsys.com> SPDX-License-Identifier: GPL-2.0-or-later */ #include "kimap/idjob.h" #include "kimap/session.h" #include "kimaptest/fakeserver.h" #include <QTest> using ArrayMap = QMap<QByteArray, QByteArray>; Q_DECLARE_METATYPE(ArrayMap) class IdJobTest : public QObject { Q_OBJECT private Q_SLOTS: void testId_data() { QTest::addColumn<QList<QByteArray>>("scenario"); QTest::addColumn<ArrayMap>("values"); QList<QByteArray> scenario; scenario << "S: * PREAUTH" << R"(C: A000001 ID ("name" "clientid"))" << "S: * ID NIL" << "S: A000001 OK ID completed"; ArrayMap values; values.insert("name", "clientid"); QTest::newRow("good") << scenario << values; } void testId() { QFETCH(QList<QByteArray>, scenario); QFETCH(ArrayMap, values); FakeServer fakeServer; fakeServer.setScenario(scenario); fakeServer.startAndWait(); KIMAP::Session session(QStringLiteral("127.0.0.1"), 5989); auto job = new KIMAP::IdJob(&session); const auto keys = values.keys(); for (const QByteArray &key : keys) { job->setField(key, values.value(key)); } bool result = job->exec(); QVERIFY(result); fakeServer.quit(); } }; QTEST_GUILESS_MAIN(IdJobTest) #include "idjobtest.moc" 07070100000023000081A400000000000000000000000166FAD7C000002478000000000000000000000000000000000000004300000000kimap-VERSIONgit.20240930T185424~db1f697/autotests/idlejobtest.cpp/* SPDX-FileCopyrightText: 2010 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com> SPDX-FileContributor: Kevin Ottens <kevin@kdab.com> SPDX-License-Identifier: GPL-2.0-or-later */ #include <QTest> #include "kimap/idlejob.h" #include "kimap/selectjob.h" #include "kimap/session.h" #include "kimaptest/fakeserver.h" #include <QSignalSpy> #include <QTest> Q_DECLARE_METATYPE(QList<int>) Q_DECLARE_METATYPE(QList<qint64>) Q_DECLARE_METATYPE(KIMAP::IdleJob *) class IdleJobTest : public QObject { Q_OBJECT public: explicit IdleJobTest(QObject *parent = nullptr) : QObject(parent) { qRegisterMetaType<KIMAP::IdleJob *>(); } private Q_SLOTS: void shouldReactToIdle_data() { QTest::addColumn<QList<QByteArray>>("scenario"); QTest::addColumn<QString>("expectedMailBox"); QTest::addColumn<QList<int>>("expectedMessageCounts"); QTest::addColumn<QList<int>>("expectedRecentCounts"); QTest::addColumn<QList<qint64>>("expectedFlagsNotifications"); QList<QByteArray> scenario; QString expectedMailBox; QList<int> expectedMessageCounts; QList<int> expectedRecentCounts; QList<qint64> expectedFlagsNotifications; scenario.clear(); scenario << FakeServer::preauth() << "C: A000001 SELECT \"INBOX/Foo\"" << "S: A000001 OK SELECT done" << "C: A000002 IDLE" << "S: + OK" << "S: * 0 RECENT" << "S: * 1 EXISTS" << "S: * 1 RECENT" << "S: * 2 EXISTS" << "S: A000002 OK done idling"; expectedMailBox = QStringLiteral("INBOX/Foo"); expectedMessageCounts.clear(); expectedRecentCounts.clear(); expectedMessageCounts << 1 << 2; expectedRecentCounts << 0 << 1; QTest::newRow("normal") << scenario << expectedMailBox << expectedMessageCounts << expectedRecentCounts << expectedFlagsNotifications; scenario.clear(); scenario << FakeServer::preauth() << "C: A000001 SELECT \"INBOX/Foo\"" << "S: A000001 OK SELECT done" << "C: A000002 IDLE" << "S: + OK" << "S: * 0 RECENT" << "S: * 1 RECENT" << "S: A000002 OK done idling"; expectedMailBox = QStringLiteral("INBOX/Foo"); expectedMessageCounts.clear(); expectedRecentCounts.clear(); expectedMessageCounts << -1 << -1; expectedRecentCounts << 0 << 1; QTest::newRow("only RECENT") << scenario << expectedMailBox << expectedMessageCounts << expectedRecentCounts << expectedFlagsNotifications; scenario.clear(); scenario << FakeServer::preauth() << "C: A000001 SELECT \"INBOX/Foo\"" << "S: A000001 OK SELECT done" << "C: A000002 IDLE" << "S: + OK" << "S: * 1 EXISTS" << "S: * 2 EXISTS" << "S: A000002 OK done idling"; expectedMailBox = QStringLiteral("INBOX/Foo"); expectedMessageCounts.clear(); expectedRecentCounts.clear(); expectedMessageCounts << 1 << 2; expectedRecentCounts << -1 << -1; QTest::newRow("only EXISTS") << scenario << expectedMailBox << expectedMessageCounts << expectedRecentCounts << expectedFlagsNotifications; scenario.clear(); scenario << FakeServer::preauth() << "C: A000001 SELECT \"INBOX/Foo\"" << "S: A000001 OK SELECT done" << "C: A000002 IDLE" << "S: + OK" << "S: * 2 EXISTS" << "W: 150" << "S: * 1 RECENT" << "S: A000002 OK done idling"; expectedMailBox = QStringLiteral("INBOX/Foo"); expectedMessageCounts.clear(); expectedRecentCounts.clear(); expectedMessageCounts << 2; expectedRecentCounts << 1; QTest::newRow("under 200ms, same notification") << scenario << expectedMailBox << expectedMessageCounts << expectedRecentCounts << expectedFlagsNotifications; scenario.clear(); scenario << FakeServer::preauth() << "C: A000001 SELECT \"INBOX/Foo\"" << "S: A000001 OK SELECT done" << "C: A000002 IDLE" << "S: + OK" << "S: * 2 EXISTS" << "W: 250" << "S: * 1 RECENT" << "S: A000002 OK done idling"; expectedMailBox = QStringLiteral("INBOX/Foo"); expectedMessageCounts.clear(); expectedRecentCounts.clear(); expectedMessageCounts << 2 << -1; expectedRecentCounts << -1 << 1; QTest::newRow("above 200ms, two notifications") << scenario << expectedMailBox << expectedMessageCounts << expectedRecentCounts << expectedFlagsNotifications; scenario.clear(); scenario << FakeServer::preauth() << "C: A000001 SELECT \"INBOX/Foo\"" << "S: A000001 OK SELECT done" << "C: A000002 IDLE" << "S: + OK" << "S: * 1 FETCH (FLAGS ())" << "W: 200" << "S: * 2 FETCH (FLAGS (\\Seen))" << "S: A000002 OK done idling"; expectedMailBox = QStringLiteral("INBOX/Foo"); expectedMessageCounts.clear(); expectedRecentCounts.clear(); expectedFlagsNotifications << 1 << 2; QTest::newRow("2 flags change notifications") << scenario << expectedMailBox << expectedMessageCounts << expectedRecentCounts << expectedFlagsNotifications; } void shouldReactToIdle() { QFETCH(QList<QByteArray>, scenario); QFETCH(QString, expectedMailBox); QFETCH(QList<int>, expectedMessageCounts); QFETCH(QList<int>, expectedRecentCounts); QFETCH(QList<qint64>, expectedFlagsNotifications); QVERIFY(expectedMessageCounts.size() == expectedRecentCounts.size()); FakeServer fakeServer; fakeServer.setScenario(scenario); fakeServer.startAndWait(); KIMAP::Session session(QStringLiteral("127.0.0.1"), 5989); auto select = new KIMAP::SelectJob(&session); select->setMailBox(expectedMailBox); QVERIFY(select->exec()); auto idle = new KIMAP::IdleJob(&session); QSignalSpy statsSpy(idle, &KIMAP::IdleJob::mailBoxStats); QSignalSpy flagsSpy(idle, &KIMAP::IdleJob::mailBoxMessageFlagsChanged); bool result = idle->exec(); if (result) { QCOMPARE(statsSpy.count(), expectedMessageCounts.size()); QCOMPARE(flagsSpy.count(), expectedFlagsNotifications.size()); for (int i = 0; i < statsSpy.count(); i++) { const KIMAP::IdleJob *job = statsSpy.at(i).at(0).value<KIMAP::IdleJob *>(); const QString mailBox = statsSpy.at(i).at(1).toString(); const int messageCount = statsSpy.at(i).at(2).toInt(); const int recentCount = statsSpy.at(i).at(3).toInt(); QCOMPARE(job, idle); QCOMPARE(mailBox, expectedMailBox); QCOMPARE(messageCount, expectedMessageCounts.at(i)); QCOMPARE(recentCount, expectedRecentCounts.at(i)); } for (int i = 0; i < flagsSpy.count(); i++) { const KIMAP::IdleJob *job = flagsSpy.at(i).at(0).value<KIMAP::IdleJob *>(); const qint64 uid = flagsSpy.at(i).at(1).toLongLong(); QCOMPARE(job, idle); QCOMPARE(uid, expectedFlagsNotifications.at(i)); } } fakeServer.quit(); } void shouldResetTimeout_data() { QTest::addColumn<QList<QByteArray>>("scenario"); { QList<QByteArray> scenario; scenario << FakeServer::preauth() << "C: A000001 SELECT \"INBOX\"" << "S: A000001 OK SELECT done" << "C: A000002 IDLE" << "S: + OK" << "S: A000002 OK done idling"; QTest::newRow("good") << scenario; } { QList<QByteArray> scenario; scenario << FakeServer::preauth() << "C: A000001 SELECT \"INBOX\"" << "S: A000001 OK SELECT done" << "C: A000002 IDLE" << "S: + OK" << "X"; QTest::newRow("bad") << scenario; } } void shouldResetTimeout() { QFETCH(QList<QByteArray>, scenario); FakeServer fakeServer; fakeServer.setScenario(scenario); fakeServer.startAndWait(); KIMAP::Session session(QStringLiteral("127.0.0.1"), 5989); const int originalTimeout = session.timeout(); auto select = new KIMAP::SelectJob(&session); select->setMailBox(QStringLiteral("INBOX")); QVERIFY(select->exec()); auto idle = new KIMAP::IdleJob(&session); idle->exec(); QCOMPARE(session.timeout(), originalTimeout); fakeServer.quit(); } }; QTEST_GUILESS_MAIN(IdleJobTest) #include "idlejobtest.moc" 07070100000024000081A400000000000000000000000166FAD7C0000016BE000000000000000000000000000000000000004300000000kimap-VERSIONgit.20240930T185424~db1f697/autotests/imapsettest.cpp/* SPDX-FileCopyrightText: 2009 Kevin Ottens <ervin@kde.org> SPDX-License-Identifier: GPL-2.0-or-later */ #include <QTest> #include "kimap/imapset.h" #include <QDebug> #include <QTest> using namespace KIMAP; QByteArray operator""_ba(const char *str, std::size_t len) { return QByteArray{str, static_cast<int>(len)}; } class ImapSetTest : public QObject { Q_OBJECT private Q_SLOTS: void shouldConvertToAndFromByteArray_data() { ImapSet set; QTest::addColumn<ImapSet>("imapSet"); QTest::addColumn<QByteArray>("byteArray"); QTest::newRow("empty set") << ImapSet() << QByteArray(); QTest::newRow("unique value") << ImapSet(7) << QByteArray("7"); QTest::newRow("single interval") << ImapSet(7, 10) << QByteArray("7:10"); QTest::newRow("single interval with no upper bound") << ImapSet(1, 0) << QByteArray("1:*"); set = ImapSet(7, 10); set.add(ImapInterval(12, 14)); QTest::newRow("two intervals") << set << QByteArray("7:10,12:14"); set = ImapSet(7, 10); set.add(ImapInterval(12)); QTest::newRow("two intervals with an infinite one") << set << QByteArray("7:10,12:*"); set = ImapSet(7, 10); set.add(5); QTest::newRow("one interval and a value") << set << QByteArray("7:10,5"); set = ImapSet(7, 10); set.add(QList<ImapSet::Id>() << 5 << 3); QTest::newRow("one interval and two values") << set << QByteArray("7:10,3,5"); } void shouldConvertToAndFromByteArray() { QFETCH(ImapSet, imapSet); QFETCH(QByteArray, byteArray); QCOMPARE(QString::fromUtf8(imapSet.toImapSequenceSet()), QString::fromUtf8(byteArray)); // qDebug() << "Expects" << imapSet << "got" << ImapSet::fromImapSequenceSet( byteArray ); QCOMPARE(ImapSet::fromImapSequenceSet(byteArray), imapSet); } void testOptimize_data() { QTest::addColumn<ImapSet>("imapSet"); QTest::addColumn<QByteArray>("originalString"); QTest::addColumn<QByteArray>("expectedString"); { ImapSet imapSet; for (int i = 1; i <= 10; ++i) { imapSet.add(i); } QTest::newRow("Neighbouring numbers") << imapSet << "1,2,3,4,5,6,7,8,9,10"_ba << "1:10"_ba; } { ImapSet imapSet; imapSet.add(ImapInterval{1, 3}); imapSet.add(ImapInterval{5, 7}); QTest::newRow("Neighbouring intervals with a gap") << imapSet << "1:3,5:7"_ba << "1:3,5:7"_ba; } { ImapSet imapSet; for (int i : {5, 8, 3, 1, 9, 2, 7, 4, 6}) { imapSet.add(i); } QTest::newRow("Random order") << imapSet << "5,8,3,1,9,2,7,4,6"_ba << "1:9"_ba; } { ImapSet imapSet; imapSet.add(ImapInterval{1, 3}); imapSet.add(ImapInterval{2, 4}); QTest::newRow("Overlapping") << imapSet << "1:3,2:4"_ba << "1:4"_ba; } { ImapSet imapSet; imapSet.add(ImapInterval{2, 4}); imapSet.add(ImapInterval{1, 3}); imapSet.add(4); imapSet.add(ImapInterval{7, 8}); imapSet.add(ImapInterval{8, 9}); QTest::newRow("Multiple overlapping with a gap") << imapSet << "2:4,1:3,4,7:8,8:9"_ba << "1:4,7:9"_ba; } { ImapSet imapSet; imapSet.add(5); imapSet.add(8); imapSet.add(10); imapSet.add(ImapInterval{0, 20}); QTest::newRow("Overlapping multiple intervals") << imapSet << "5,8,10,0:20"_ba << "0:20"_ba; } { ImapSet imapSet; imapSet.add(1); imapSet.add(ImapInterval{3, 5}); imapSet.add(ImapInterval{4, 0}); QTest::newRow("Open end overlap") << imapSet << "1,3:5,4:*"_ba << "1,3:*"_ba; } { ImapSet imapSet; imapSet.add(ImapInterval{1, 4}); imapSet.add(3); QTest::newRow("Value within interval") << imapSet << "1:4,3"_ba << "1:4"_ba; } { ImapSet imapSet; imapSet.add(ImapInterval{1, 0}); imapSet.add(ImapInterval{3, 0}); imapSet.add(5); QTest::newRow("Multiple open end intervals") << imapSet << "1:*,3:*,5"_ba << "1:*"_ba; } { ImapSet imapSet; for (ImapSet::Id id : {1, 2, 3, 5, 6, 8, 9, 10, 15, 16, 19, 20, 21, 23}) { imapSet.add(id); } QTest::newRow("Merge single values") << imapSet << "1,2,3,5,6,8,9,10,15,16,19,20,21,23"_ba << "1:3,5:6,8:10,15:16,19:21,23"_ba; } } void testOptimize() { QFETCH(ImapSet, imapSet); QFETCH(QByteArray, originalString); QFETCH(QByteArray, expectedString); QCOMPARE(imapSet.intervals().size(), originalString.count(",") + 1); QCOMPARE(imapSet.toImapSequenceSet(), originalString); imapSet.optimize(); QCOMPARE(imapSet.intervals().size(), expectedString.count(",") + 1); QCOMPARE(imapSet.toImapSequenceSet(), expectedString); } }; QTEST_GUILESS_MAIN(ImapSetTest) #include "imapsettest.moc" 07070100000025000041ED00000000000000000000000266FAD7C000000000000000000000000000000000000000000000003D00000000kimap-VERSIONgit.20240930T185424~db1f697/autotests/kimaptest07070100000026000081A400000000000000000000000166FAD7C00000037C000000000000000000000000000000000000004C00000000kimap-VERSIONgit.20240930T185424~db1f697/autotests/kimaptest/CMakeLists.txt# SPDX-FileCopyrightText: none # SPDX-License-Identifier: BSD-3-Clause kde_enable_exceptions() set(kimaptest_SRCS fakeserver.cpp mockjob.cpp sslserver.cpp ) add_library(kimaptest6 STATIC ${kimaptest_SRCS}) if(COMPILE_WITH_UNITY_CMAKE_SUPPORT) set_target_properties(kimaptest6 PROPERTIES UNITY_BUILD ON) endif() generate_export_header(kimaptest6) add_library(KPim6::kimaptest ALIAS kimaptest6) target_include_directories(KPim6IMAP INTERFACE "$<INSTALL_INTERFACE:${KDE_INSTALL_INCLUDEDIR}/KPim6/KIMAPTest>") target_link_libraries(kimaptest6 KPim6IMAP Qt::Test Qt::Network Qt::Core KF6::CoreAddons KF6::KIOCore KF6::I18n) install(TARGETS kimaptest6 EXPORT KPim6IMAPTargets ${KDE_INSTALL_TARGETS_DEFAULT_ARGS}) ########### install files ############### install(FILES fakeserver.h mockjob.h DESTINATION ${KDE_INSTALL_INCLUDEDIR}/KPim6/KIMAPTest/kimaptest COMPONENT Devel) 07070100000027000081A400000000000000000000000166FAD7C000001841000000000000000000000000000000000000004C00000000kimap-VERSIONgit.20240930T185424~db1f697/autotests/kimaptest/fakeserver.cpp/* 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-License-Identifier: GPL-2.0-or-later */ // Own #include "fakeserver.h" #include "sslserver.h" // Qt #include <QDebug> #include <QFile> #include <QTcpServer> #include <QTcpSocket> #include <QTest> #include "imapstreamparser.h" QByteArray FakeServer::preauth() { return "S: * PREAUTH localhost Test Library server ready"; } QByteArray FakeServer::greeting() { return "S: * OK localhost Test Library server ready"; } FakeServer::FakeServer(QObject *parent) : QThread(parent) , m_encrypted(false) , m_starttls(false) { moveToThread(this); } FakeServer::~FakeServer() { quit(); wait(); } void FakeServer::startAndWait() { start(); // this will block until the event queue starts QMetaObject::invokeMethod(this, &FakeServer::started, Qt::BlockingQueuedConnection); } void FakeServer::dataAvailable() { QMutexLocker locker(&m_mutex); auto socket = qobject_cast<QTcpSocket *>(sender()); QVERIFY(socket); int scenarioNumber = m_clientSockets.indexOf(socket); if (m_scenarios[scenarioNumber].isEmpty()) { KIMAP::ImapStreamParser *clientParser = m_clientParsers[scenarioNumber]; QByteArray received = "C: " + clientParser->readUntilCommandEnd().trimmed(); qWarning() << "Scenario" << scenarioNumber << "finished, but we got command" << received; QVERIFY(false); } readClientPart(scenarioNumber); writeServerPart(scenarioNumber); if (m_starttls) { m_starttls = false; qDebug() << "start tls"; static_cast<QSslSocket *>(socket)->startServerEncryption(); } } void FakeServer::newConnection() { QMutexLocker locker(&m_mutex); m_clientSockets << m_tcpServer->nextPendingConnection(); connect(m_clientSockets.last(), &QTcpSocket::readyRead, this, &FakeServer::dataAvailable); m_clientParsers << new KIMAP::ImapStreamParser(m_clientSockets.last(), true); QVERIFY(m_clientSockets.size() <= m_scenarios.size()); writeServerPart(m_clientSockets.size() - 1); } void FakeServer::setEncrypted(QSsl::SslProtocol protocol) { m_encrypted = true; m_sslProtocol = protocol; } void FakeServer::setWaitForStartTls(bool wait) { m_waitForStartTls = wait; } void FakeServer::run() { if (m_encrypted) { m_tcpServer = new SslServer(m_sslProtocol, m_waitForStartTls); } else { m_tcpServer = new QTcpServer(); } if (!m_tcpServer->listen(QHostAddress(QHostAddress::LocalHost), 5989)) { qFatal("Unable to start the server"); } connect(m_tcpServer, &QTcpServer::newConnection, this, &FakeServer::newConnection); exec(); qDeleteAll(m_clientParsers); qDeleteAll(m_clientSockets); delete m_tcpServer; } void FakeServer::started() { // do nothing: this is a dummy slot used by startAndWait() } 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(QFile::ReadOnly); QList<QByteArray> scenario; // When loading from files we never have the authentication phase // force jumping directly to authenticated state. scenario << preauth(); 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(int scenarioNumber) { QList<QByteArray> scenario = m_scenarios[scenarioNumber]; QTcpSocket *clientSocket = m_clientSockets[scenarioNumber]; while (!scenario.isEmpty() && (scenario.first().startsWith("S: ") || scenario.first().startsWith("W: "))) { QByteArray rule = scenario.takeFirst(); if (rule.startsWith("S: ")) { QByteArray payload = rule.mid(3); clientSocket->write(payload + "\r\n"); } else { int timeout = rule.mid(3).toInt(); QTest::qWait(timeout); } } 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::compareReceived(const QByteArray &received, const QByteArray &expected) const { QCOMPARE(QString::fromUtf8(received), QString::fromUtf8(expected)); QCOMPARE(received, expected); } void FakeServer::readClientPart(int scenarioNumber) { QList<QByteArray> scenario = m_scenarios[scenarioNumber]; KIMAP::ImapStreamParser *clientParser = m_clientParsers[scenarioNumber]; while (!scenario.isEmpty() && scenario.first().startsWith("C: ")) { QByteArray received = "C: " + clientParser->readUntilCommandEnd().trimmed(); QByteArray expected = scenario.takeFirst(); if (expected.contains("C: SKIP")) { continue; } compareReceived(received, expected); if (received.contains("STARTTLS")) { m_starttls = true; } } if (!scenario.isEmpty()) { QVERIFY(scenario.first().startsWith("S: ") || scenario.first().startsWith("X")); } m_scenarios[scenarioNumber] = scenario; } #include "moc_fakeserver.cpp" 07070100000028000081A400000000000000000000000166FAD7C000001B6A000000000000000000000000000000000000004A00000000kimap-VERSIONgit.20240930T185424~db1f697/autotests/kimaptest/fakeserver.h/* 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-License-Identifier: GPL-2.0-or-later */ #pragma once #include <QMutex> #include <QSsl> #include <QThread> class QTcpSocket; class QTcpServer; namespace KIMAP { class ImapStreamParser; } Q_DECLARE_METATYPE(QList<QByteArray>) /** * Pretends to be an IMAP server for the purposes of unit tests. * * FakeServer does not really understand the IMAP protocol. Instead, * you give it a script, or scenario, that lists how an IMAP 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 on port 5989 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:"). For example: * @code * C: A000001 LIST "" * * S: * LIST ( \HasChildren ) / INBOX * S: * LIST ( \HasNoChildren ) / INBOX/&AOQ- &APY- &APw- @ &IKw- * S: * LIST ( \HasChildren ) / INBOX/lost+found * S: * LIST ( \HasNoChildren ) / "INBOX/lost+found/Calendar Public-20080128" * S: A000001 OK LIST completed * @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. For example, the following simulates the server closing * the connection after receiving too many bad commands: * @code * C: A000001 madhatter * S: A000001 BAD Command madhatter * X * @endcode * * FakeServer::preauth() and FakeServer::greeting() provide standard * PREAUTH and OK responses, respectively, that can be used (unmodified) * as the first line of a scenario. * * A typical usage is something like * @code * QList<QByteArray> scenario; * scenario << FakeServer::preauth() * << "C: A000001 CAPABILITY" * << "S: * CAPABILITY IMAP4rev1 STARTTLS AUTH=GSSAPI" * << "S: A000001 OK CAPABILITY completed"; * * FakeServer fakeServer; * fakeServer.setScenario( scenario ); * fakeServer.startAndWait(); * * KIMAP::Session session( QStringLiteral("127.0.0.1"), 5989 ); * KIMAP::CapabilitiesJob *job = new KIMAP::CapabilitiesJob(&session); * QVERIFY( job->exec() ); * // check the returned capabilities * * fakeServer.quit(); * @endcode */ class FakeServer : public QThread { Q_OBJECT public: /** * Get the default PREAUTH response * * This is the initial PREAUTH message that the server * sends at the start of a session to indicate that the * user is already authenticated by some other mechanism. * * Can be used as the first line in a scenario where * you want to skip the LOGIN stage of the protocol. */ static QByteArray preauth(); /** * Get the default greeting * * This is the initial OK message that the server sends at the * start of a session to indicate that a LOGIN is required. * * Can be used as the first line in a scenario where * you want to use the LOGIN command. */ static QByteArray greeting(); explicit FakeServer(QObject *parent = nullptr); ~FakeServer() override; /** * Sets the encryption mode used by the server socket. */ void setEncrypted(QSsl::SslProtocol protocol); /** * Won't start encryption until client sends STARTTLS */ void setWaitForStartTls(bool wait); /** * Starts the server and waits for it to be ready * * You should use this instead of start() to avoid race conditions. */ void startAndWait(); /** * Starts the fake IMAP server * * You should not call this directly. Use start() instead. * * @reimp */ void run() override; /** * 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; protected: /** * Whether the received content is the same as the expected. * Use QCOMPARE, if creating subclasses. */ virtual void compareReceived(const QByteArray &received, const QByteArray &expected) const; private Q_SLOTS: void newConnection(); void dataAvailable(); void started(); private: void writeServerPart(int scenarioNumber); void readClientPart(int scenarioNumber); QList<QList<QByteArray>> m_scenarios; QTcpServer *m_tcpServer; mutable QMutex m_mutex; QList<QTcpSocket *> m_clientSockets; QList<KIMAP::ImapStreamParser *> m_clientParsers; bool m_encrypted; bool m_starttls; bool m_waitForStartTls = false; QSsl::SslProtocol m_sslProtocol; }; 07070100000029000081A400000000000000000000000166FAD7C00000065E000000000000000000000000000000000000004900000000kimap-VERSIONgit.20240930T185424~db1f697/autotests/kimaptest/mockjob.cpp/* This file is part of the KDE project SPDX-FileCopyrightText: 2008 Kevin Ottens <ervin@kde.org> SPDX-FileCopyrightText: 2010 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com> SPDX-FileContributor: Kevin Ottens <kevin@kdab.com> SPDX-License-Identifier: LGPL-2.0-or-later */ #include "mockjob.h" #include "job_p.h" #include "session.h" #include "session_p.h" #include <KLocalizedString> #include <QTimer> class MockJobPrivate : public KIMAP::JobPrivate { public: MockJobPrivate(KIMAP::Session *session, const QString &name) : KIMAP::JobPrivate(session, name) , timeout(10) { } ~MockJobPrivate() { } QByteArray command; int timeout; }; MockJob::MockJob(KIMAP::Session *session) : KIMAP::Job(*new MockJobPrivate(session, i18n("Mock"))) { } void MockJob::doStart() { Q_D(MockJob); if (isNull()) { QTimer::singleShot(d->timeout, this, SLOT(done())); } else { d->sessionInternal()->setSocketTimeout(d->timeout); d->tags << d->sessionInternal()->sendCommand(d->command); } } void MockJob::done() { emitResult(); } void MockJob::setCommand(const QByteArray &command) { Q_D(MockJob); d->command = command; } QByteArray MockJob::command() const { Q_D(const MockJob); return d->command; } void MockJob::setTimeout(int timeout) { Q_D(MockJob); d->timeout = timeout; } int MockJob::timeout() const { Q_D(const MockJob); return d->timeout; } bool MockJob::isNull() const { Q_D(const MockJob); return d->command.isEmpty(); } #include "moc_mockjob.cpp" 0707010000002A000081A400000000000000000000000166FAD7C00000056C000000000000000000000000000000000000004700000000kimap-VERSIONgit.20240930T185424~db1f697/autotests/kimaptest/mockjob.h/* This file is part of the KDE project SPDX-FileCopyrightText: 2008 Kevin Ottens <ervin@kde.org> SPDX-FileCopyrightText: 2010 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com> SPDX-FileContributor: Kevin Ottens <kevin@kdab.com> SPDX-License-Identifier: LGPL-2.0-or-later */ #pragma once #include "kimap/job.h" class MockJobPrivate; /** * Provides an easy way to send an arbitrary IMAP client command. */ class MockJob : public KIMAP::Job { Q_OBJECT Q_DECLARE_PRIVATE(MockJob) public: MockJob(KIMAP::Session *session); /** * Sets the command to execute. * * This should not include the command tag. */ void setCommand(const QByteArray &command); /** * The command that will be sent. */ QByteArray command() const; /** * Sets the timeout before the job completes. */ void setTimeout(int timeout); /** * The timeout used by the job. */ int timeout() const; /** * Whether the command is empty. * * Equivalent to command().isEmpty(). * * @return @c true if no command is set, @c false otherwise */ bool isNull() const; /** * Starts the job. * * Do not call this directly. Use start() instead. * * @reimp */ void doStart() override; private Q_SLOTS: void done(); }; 0707010000002B000081A400000000000000000000000166FAD7C0000014E8000000000000000000000000000000000000004B00000000kimap-VERSIONgit.20240930T185424~db1f697/autotests/kimaptest/sslserver.cpp/* SPDX-FileCopyrightText: 2013 Christian Mollekopf <mollekopf@kolabsys.com> SPDX-License-Identifier: GPL-2.0-or-later */ #include "sslserver.h" #include <QDebug> #include <QSslConfiguration> #include <QSslKey> // Generated on 2020-10-07 using command: // openssl req -nodes -new -x509 -keyout key.pem -out cert.pem -days 36500 // // The cert should be valid until 2120. static QByteArray staticCert() { // a dummy certificate return QByteArray( "-----BEGIN CERTIFICATE-----\n\ MIIDZzCCAk+gAwIBAgIUQoBjjbd//7DD9zWfru/epnVT2vAwDQYJKoZIhvcNAQEL\n\ BQAwQjELMAkGA1UEBhMCWFgxFTATBgNVBAcMDERlZmF1bHQgQ2l0eTEcMBoGA1UE\n\ CgwTRGVmYXVsdCBDb21wYW55IEx0ZDAgFw0yMDEwMDcxMzMxMTJaGA8yMTIwMDkx\n\ MzEzMzExMlowQjELMAkGA1UEBhMCWFgxFTATBgNVBAcMDERlZmF1bHQgQ2l0eTEc\n\ MBoGA1UECgwTRGVmYXVsdCBDb21wYW55IEx0ZDCCASIwDQYJKoZIhvcNAQEBBQAD\n\ ggEPADCCAQoCggEBAMIu0Osija2bIINdCjuP0T+tdlQOI8l52J+z/dI45MxecEn5\n\ LAsYWhqanpgZSM5tFf4xqWaX/1/TVDB5JiLx3voWOODTtNKzFVFCzfKHuH6cBboE\n\ E4TZ+H6hTq+YyMKUDN7XqRtBIf1FBf0lMhalWdtEDtlXcsuoaGXkr671JwR34+EU\n\ 6YH/8kbBQQBoL640/gxtgevGmpqfqLW0/hogF5pOhMOfwVlYo28IqaPScUGEpopf\n\ zqL+z6NwdEsNLygwq21kU0hhRnx2UgdPcZNX3dc7sUkZjxn53t6XPeVvgGXCte1o\n\ Ad6L0rMunlda+Tj02FXn7jo6G7ELj05Bg8JNB8sCAwEAAaNTMFEwHQYDVR0OBBYE\n\ FLi6xsBAkbc06veA7t+8slAUCVebMB8GA1UdIwQYMBaAFLi6xsBAkbc06veA7t+8\n\ slAUCVebMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAFpcIzOl\n\ iqMK/kre/xJyE+S1UoS85rmegZDkNdEXUS6zCozL+eO2NxHxumxfD3qrdwLvXfn0\n\ y30xUlNecB30/egXrel9z7Xop70sVCfgfb/vfMmQ5KSUZC8968rgHPl5qPmjZk6X\n\ z0M9hktTRpIk43DPuz5k1qD+LsmrKzI7twGu00EenwVZa4eLN36Ju4ZRg3I0h2zH\n\ vAnuAku0F0JU9GXdbjOW/248k+jhMP1noDaLqwVkkjgzaJwHxFNiKxnG3f7anneK\n\ HxybczmNl3a6IsZN0CSUSwLfvr1Wezk2Mb7dwzhPbycP5icB/KXWgApkRZ3MKfLN\n\ aBvBMCfr7GXmLQk=\n\ -----END CERTIFICATE-----"); } static QByteArray staticKey() { // a dummy key without password return QByteArray( "-----BEGIN PRIVATE KEY-----\n\ MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDCLtDrIo2tmyCD\n\ XQo7j9E/rXZUDiPJedifs/3SOOTMXnBJ+SwLGFoamp6YGUjObRX+Malml/9f01Qw\n\ eSYi8d76Fjjg07TSsxVRQs3yh7h+nAW6BBOE2fh+oU6vmMjClAze16kbQSH9RQX9\n\ JTIWpVnbRA7ZV3LLqGhl5K+u9ScEd+PhFOmB//JGwUEAaC+uNP4MbYHrxpqan6i1\n\ tP4aIBeaToTDn8FZWKNvCKmj0nFBhKaKX86i/s+jcHRLDS8oMKttZFNIYUZ8dlIH\n\ T3GTV93XO7FJGY8Z+d7elz3lb4BlwrXtaAHei9KzLp5XWvk49NhV5+46OhuxC49O\n\ QYPCTQfLAgMBAAECggEAFdV/xkCfX5rmv/6RLPtR0vAlMvRYD8p0khiB/MZK67Pe\n\ umKbEjBNyVoDZSTKq/NWGrvoyVFj9JlliQHGSP2bTdF72cPUPDDIv9dcIt4h35KZ\n\ jj3xF+oOZ+apW1M5l69f9xqWuCrNsJW3Q6yQAj3baa0wYj3T+ZRZEMPzASAtn/HM\n\ 8r/ToZ9jzObVeNAKoHy30bn5a5NwUcpdOfj84l/qJalXEMtR05FTOa+UEjbqpxjM\n\ +HR9RhlLyxXoFkBjtBowEWZcJSik7t5Vpk4brhUZTVxR1bC5zAXxtnDg2SmR9bKO\n\ 4wttLEtTTrXeTkxpYMTZWt7FplUmP92RdcW8PCbe2QKBgQDl+QYUhaQdmRC1ylny\n\ 2XP0lvPBHQr7jIHYcsGgit7XKMu6wSq/NGuLNT7WL1A9UDWBCdsdqXBFjR3rwhzh\n\ krbymy1H6PGPYYMQg0DeoAG7I1YTYhrp25bO0WTXVyYrhbZiQkFontUFYIbqu+Rf\n\ glVnhEXXN6wXBjY1F0qM4KjydQKBgQDYKNspAaxX/GxnydtlxXTXWSKD/kMlbAeu\n\ +AI9PRn6LckT7pKEE4Qd/gHnrlnxlqgLTJDcGgTeNutHmaHToQNSWiNltr7igzsU\n\ nABUwlNpl2NwUqttCvsGcyxhabDIjO6Iw+jbnLsWwyMzwf/5YaP8wwmznWYDGn6Y\n\ UXbyXn5JPwKBgQCzHM/qfefDkaqdG/wQk+KnFkbFGnyqTNX4ofBCvMYwp7p9OuOz\n\ Rf2Yz6CgKvuAtY7mcKmzIXuq/+zU6TubSKyqqceLoVc6iAUPgFquycpvWWc584fo\n\ qjl73USAH4VAEoVpZBcTh9l7taF/A1YsORORa0kGBXtH93OSyBAtRvDu3QKBgHZm\n\ 2rU5f2eqks6/GPhEEl4rKubWDX2gEQ1cOA3HPEV3ct8CHStPbVzoV67KJ+ZXObEG\n\ vYpyjhwSRQoxMx0y4xjm2uDKGwEEFQaS9PN4hiweio9qGRBfpWTBDZxGQll4KOit\n\ Nw2kai5rsQqWx1mYjDTVuKi0HL6ycomIhfj4nYANAoGATXXc8Ekg+w7hfzLS3BTV\n\ SovH/d6/fC5B7nD5+wB7s0dD8NqqOUKvRm/HPRzMWejSOMXWQzpWSAGTheaFArTw\n\ 2k6FDQ7S1lEt6jbVBtS189LtaZBnEWZQfyjKl8h6lJyVU2kBfaYoEOO31T8n20sG\n\ NdkmACeCyNMs5V3yq1vAeN4=\n\ -----END PRIVATE KEY-----"); } SslServer::SslServer(QSsl::SslProtocol protocol, bool waitForStartTls) : QTcpServer() , mProtocol(protocol) , mWaitForStartTls(waitForStartTls) { } void SslServer::incomingConnection(qintptr handle) { auto socket = new QSslSocket(); socket->setSocketDescriptor(handle); socket->setProtocol(mProtocol); QSslKey ssl_key(staticKey(), QSsl::Rsa); QSslCertificate ssl_cert(staticCert()); Q_ASSERT(QDateTime::currentDateTime() >= ssl_cert.effectiveDate()); Q_ASSERT(QDateTime::currentDateTime() <= ssl_cert.expiryDate()); Q_ASSERT(!ssl_cert.isBlacklisted()); socket->setPrivateKey(ssl_key); socket->setLocalCertificate(ssl_cert); socket->sslConfiguration().addCaCertificates(QList<QSslCertificate>() << ssl_cert); socket->setPeerVerifyMode(QSslSocket::VerifyNone); socket->ignoreSslErrors(); connect(socket, &QSslSocket::sslErrors, this, &SslServer::sslErrors); connect(socket, &QAbstractSocket::errorOccurred, this, &SslServer::error); if (!mWaitForStartTls) { socket->startServerEncryption(); } addPendingConnection(socket); } void SslServer::sslErrors(const QList<QSslError> &errors) { for (const QSslError &error : errors) { qWarning() << "Received ssl error: " << error.errorString(); } auto socket = qobject_cast<QSslSocket *>(QObject::sender()); if (socket) { socket->disconnectFromHost(); } } void SslServer::error(QAbstractSocket::SocketError error) { auto socket = qobject_cast<QSslSocket *>(QObject::sender()); if (socket) { qWarning() << socket->errorString(); } qWarning() << error; } #include "moc_sslserver.cpp" 0707010000002C000081A400000000000000000000000166FAD7C000000243000000000000000000000000000000000000004900000000kimap-VERSIONgit.20240930T185424~db1f697/autotests/kimaptest/sslserver.h/* SPDX-FileCopyrightText: 2013 Christian Mollekopf <mollekopf@kolabsys.com> SPDX-License-Identifier: GPL-2.0-or-later */ #pragma once #include <QSslSocket> #include <QTcpServer> class SslServer : public QTcpServer { Q_OBJECT public: SslServer(QSsl::SslProtocol, bool waitForStartTls); void incomingConnection(qintptr handle) override; private Q_SLOTS: void sslErrors(const QList<QSslError> &errors); void error(QAbstractSocket::SocketError); private: QSsl::SslProtocol mProtocol; QSslSocket mSocket; bool mWaitForStartTls = false; }; 0707010000002D000081A400000000000000000000000166FAD7C00000219E000000000000000000000000000000000000004300000000kimap-VERSIONgit.20240930T185424~db1f697/autotests/listjobtest.cpp/* SPDX-FileCopyrightText: 2009 Andras Mantia <amantia@kde.org> SPDX-FileCopyrightText: 2010 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com> SPDX-FileContributor: Kevin Ottens <kevin@kdab.com> SPDX-License-Identifier: GPL-2.0-or-later */ #include <QTest> #include "kimap/listjob.h" #include "kimap/session.h" #include "kimaptest/fakeserver.h" #include <QDebug> #include <QSignalSpy> #include <QTest> Q_DECLARE_METATYPE(QList<KIMAP::MailBoxDescriptor>) Q_DECLARE_METATYPE(QList<QList<QByteArray>>) class ListJobTest : public QObject { Q_OBJECT private Q_SLOTS: void testList_data() { QTest::addColumn<bool>("unsubscribed"); QTest::addColumn<QList<QByteArray>>("scenario"); QTest::addColumn<QList<KIMAP::MailBoxDescriptor>>("listresult"); QList<QByteArray> scenario; scenario << FakeServer::preauth() << "C: A000001 LIST \"\" *" << "S: * LIST ( \\HasChildren ) / INBOX" << "S: * LIST ( \\HasNoChildren ) / INBOX/&AOQ- &APY- &APw- @ &IKw-" << "S: * LIST ( \\HasChildren ) / INBOX/lost+found" << R"(S: * LIST ( \HasNoChildren ) / "INBOX/lost+found/Calendar Public-20080128")" << "S: A000001 OK LIST completed"; KIMAP::MailBoxDescriptor descriptor; QList<KIMAP::MailBoxDescriptor> listresult; descriptor.separator = QLatin1Char('/'); descriptor.name = QStringLiteral("INBOX"); listresult << descriptor; descriptor.separator = QLatin1Char('/'); descriptor.name = QString::fromUtf8("INBOX/ä ö ü @ €"); listresult << descriptor; descriptor.separator = QLatin1Char('/'); descriptor.name = QStringLiteral("INBOX/lost+found"); listresult << descriptor; descriptor.separator = QLatin1Char('/'); descriptor.name = QStringLiteral("INBOX/lost+found/Calendar Public-20080128"); listresult << descriptor; QTest::newRow("normal") << true << scenario << listresult; scenario.clear(); scenario << FakeServer::preauth() << "C: A000001 LIST \"\" *" << "S: * LIST ( \\HasChildren ) / Inbox" << "S: * LIST ( \\HasNoChildren ) / Inbox/&AOQ- &APY- &APw- @ &IKw-" << "S: * LIST ( \\HasChildren ) / Inbox/lost+found" << R"(S: * LIST ( \HasNoChildren ) / "Inbox/lost+found/Calendar Public-20080128")" << "S: A000001 OK LIST completed"; listresult.clear(); descriptor.separator = QLatin1Char('/'); descriptor.name = QStringLiteral("INBOX"); listresult << descriptor; descriptor.separator = QLatin1Char('/'); descriptor.name = QString::fromUtf8("INBOX/ä ö ü @ €"); listresult << descriptor; descriptor.separator = QLatin1Char('/'); descriptor.name = QStringLiteral("INBOX/lost+found"); listresult << descriptor; descriptor.separator = QLatin1Char('/'); descriptor.name = QStringLiteral("INBOX/lost+found/Calendar Public-20080128"); listresult << descriptor; QTest::newRow("lowercase Inbox") << true << scenario << listresult; scenario.clear(); scenario << FakeServer::preauth() << "C: A000001 LSUB \"\" *" << "S: * LSUB ( \\HasChildren ) / INBOX" << "S: * LSUB ( ) / INBOX/Calendar/3196" << "S: * LSUB ( \\HasChildren ) / INBOX/Calendar/ff" << "S: * LSUB ( ) / INBOX/Calendar/ff/hgh" << "S: * LSUB ( ) / user/test2/Calendar" << "S: A000001 OK LSUB completed"; listresult.clear(); descriptor.separator = QLatin1Char('/'); descriptor.name = QStringLiteral("INBOX"); listresult << descriptor; descriptor.separator = QLatin1Char('/'); descriptor.name = QStringLiteral("INBOX/Calendar/3196"); listresult << descriptor; descriptor.separator = QLatin1Char('/'); descriptor.name = QStringLiteral("INBOX/Calendar/ff"); listresult << descriptor; descriptor.separator = QLatin1Char('/'); descriptor.name = QStringLiteral("INBOX/Calendar/ff/hgh"); listresult << descriptor; descriptor.separator = QLatin1Char('/'); descriptor.name = QStringLiteral("user/test2/Calendar"); listresult << descriptor; QTest::newRow("subscribed") << false << scenario << listresult; scenario.clear(); scenario << FakeServer::preauth() << "C: A000001 LSUB \"\" *" << "S: * LSUB ( \\HasChildren ) / Inbox" << "S: * LSUB ( ) / Inbox/Calendar/3196" << "S: * LSUB ( \\HasChildren ) / Inbox/Calendar/ff" << "S: * LSUB ( ) / Inbox/Calendar/ff/hgh" << "S: * LSUB ( ) / user/test2/Calendar" << "S: A000001 OK LSUB completed"; listresult.clear(); descriptor.separator = QLatin1Char('/'); descriptor.name = QStringLiteral("INBOX"); listresult << descriptor; descriptor.separator = QLatin1Char('/'); descriptor.name = QStringLiteral("INBOX/Calendar/3196"); listresult << descriptor; descriptor.separator = QLatin1Char('/'); descriptor.name = QStringLiteral("INBOX/Calendar/ff"); listresult << descriptor; descriptor.separator = QLatin1Char('/'); descriptor.name = QStringLiteral("INBOX/Calendar/ff/hgh"); listresult << descriptor; descriptor.separator = QLatin1Char('/'); descriptor.name = QStringLiteral("user/test2/Calendar"); listresult << descriptor; QTest::newRow("subscribed, lowercase Inbox") << false << scenario << listresult; scenario.clear(); scenario << FakeServer::preauth() << "C: A000001 LIST \"\" *" << "S: * LIST ( \\HasNoChildren ) / INBOX/lost+found/Calendar Public-20080128" << "S: A000001 OK LIST completed"; listresult.clear(); descriptor.separator = QLatin1Char('/'); descriptor.name = QStringLiteral("INBOX/lost+found/Calendar Public-20080128"); listresult << descriptor; QTest::newRow("unquoted-space") << true << scenario << listresult; scenario.clear(); scenario << FakeServer::preauth() << "C: A000001 LIST \"\" *" << "S: * LIST ( \\NoInferiors ) ( ) INBOX" << "S: A000001 OK LIST completed"; listresult.clear(); descriptor.separator = QLatin1Char('/'); descriptor.name = QStringLiteral("INBOX"); listresult << descriptor; QTest::newRow("separator is empty list") << true << scenario << listresult; scenario.clear(); scenario << FakeServer::preauth() << "C: A000001 LIST \"\" *" << "S: A000001 BAD command unknown or arguments invalid"; listresult.clear(); QTest::newRow("bad") << true << scenario << listresult; scenario.clear(); scenario << FakeServer::preauth() << "C: A000001 LIST \"\" *" << "S: A000001 NO list failure"; QTest::newRow("no") << true << scenario << listresult; } void testList() { QFETCH(bool, unsubscribed); QFETCH(QList<QByteArray>, scenario); QFETCH(QList<KIMAP::MailBoxDescriptor>, listresult); FakeServer fakeServer; fakeServer.setScenario(scenario); fakeServer.startAndWait(); KIMAP::Session session(QStringLiteral("127.0.0.1"), 5989); auto job = new KIMAP::ListJob(&session); job->setOption(unsubscribed ? KIMAP::ListJob::IncludeUnsubscribed : KIMAP::ListJob::NoOption); QSignalSpy spy(job, &KIMAP::ListJob::mailBoxesReceived); bool result = job->exec(); QEXPECT_FAIL("bad", "Expected failure on BAD response", Continue); QEXPECT_FAIL("no", "Expected failure on NO response", Continue); QVERIFY(result); if (result) { QVERIFY(spy.count() > 0); QList<KIMAP::MailBoxDescriptor> mailBoxes; for (int i = 0; i < spy.count(); ++i) { mailBoxes += spy.at(i).at(0).value<QList<KIMAP::MailBoxDescriptor>>(); } // qDebug() << mailBoxes.first().name; // qDebug() << listresult.first().name; QCOMPARE(mailBoxes, listresult); } // QCOMPARE(job->mailBox(), mailbox); fakeServer.quit(); } }; QTEST_GUILESS_MAIN(ListJobTest) #include "listjobtest.moc" 0707010000002E000081A400000000000000000000000166FAD7C0000024FE000000000000000000000000000000000000004400000000kimap-VERSIONgit.20240930T185424~db1f697/autotests/loginjobtest.cpp/* SPDX-FileCopyrightText: 2009 Andras Mantia <amantia@kde.org> SPDX-FileCopyrightText: 2010 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com> SPDX-FileContributor: Kevin Ottens <kevin@kdab.com> SPDX-License-Identifier: GPL-2.0-or-later */ #include <QTest> #include "kimap/loginjob.h" #include "kimap/session.h" #include "kimaptest/fakeserver.h" #include <QTest> class TestUiProxy : public KIMAP::SessionUiProxy { bool ignoreSslError(const KSslErrorUiData &) override { return true; } }; class LoginJobTest : public QObject { Q_OBJECT private Q_SLOTS: void shouldHandleLogin_data() { QTest::addColumn<QString>("user"); QTest::addColumn<QString>("password"); QTest::addColumn<QList<QByteArray>>("scenario"); QList<QByteArray> scenario; scenario << FakeServer::greeting() << "C: A000001 LOGIN \"user\" \"password\"" << "S: A000001 OK User logged in"; QTest::newRow("success") << QStringLiteral("user") << QStringLiteral("password") << scenario; scenario.clear(); scenario << FakeServer::greeting() << "C: A000001 LOGIN \"user_bad\" \"password\"" << "S: A000001 NO Login failed: authentication failure"; QTest::newRow("wrong login") << "user_bad" << QStringLiteral("password") << scenario; scenario.clear(); scenario << FakeServer::greeting() << "C: A000001 LOGIN \"user\" \"aa\\\"bb\\\\cc[dd ee\"" << "S: A000001 OK User logged in"; QTest::newRow("special chars") << QStringLiteral("user") << "aa\"bb\\cc[dd ee" << scenario; scenario.clear(); scenario << FakeServer::preauth(); QTest::newRow("already authenticated") << QStringLiteral("user") << QStringLiteral("password") << scenario; } void shouldHandleLogin() { QFETCH(QString, user); QFETCH(QString, password); QFETCH(QList<QByteArray>, scenario); FakeServer fakeServer; fakeServer.setScenario(scenario); fakeServer.startAndWait(); KIMAP::Session *session = new KIMAP::Session(QStringLiteral("127.0.0.1"), 5989); KIMAP::LoginJob *login = new KIMAP::LoginJob(session); login->setUserName(user); login->setPassword(password); bool result = login->exec(); QEXPECT_FAIL("wrong login", "Login with bad user name", Continue); QEXPECT_FAIL("already authenticated", "Trying to log on an already authenticated session", Continue); QVERIFY(result); fakeServer.quit(); delete session; } void shouldHandleProxyLogin_data() { QTest::addColumn<QString>("user"); QTest::addColumn<QString>("proxy"); QTest::addColumn<QString>("password"); QTest::addColumn<QList<QByteArray>>("scenario"); QList<QByteArray> scenario; scenario << FakeServer::greeting() << "C: A000001 AUTHENTICATE PLAIN" << "S: A000001 OK (success)" << "C: A000001 LOGIN \"proxy\" \"user\" \"password\"" << "S: A000001 OK User logged in"; QTest::newRow("success") << QStringLiteral("user") << "proxy" << QStringLiteral("password") << scenario; } void shouldHandleProxyLogin() { QFETCH(QString, user); QFETCH(QString, proxy); QFETCH(QString, password); QFETCH(QList<QByteArray>, scenario); FakeServer fakeServer; fakeServer.setScenario(scenario); fakeServer.startAndWait(); KIMAP::Session *session = new KIMAP::Session(QStringLiteral("127.0.0.1"), 5989); KIMAP::LoginJob *login = new KIMAP::LoginJob(session); login->setAuthenticationMode(KIMAP::LoginJob::Plain); login->setUserName(user); login->setAuthorizationName(proxy); login->setPassword(password); bool result = login->exec(); QVERIFY(result); fakeServer.quit(); delete session; } void shouldSaveServerGreeting_data() { QTest::addColumn<QString>("greeting"); QTest::addColumn<QList<QByteArray>>("scenario"); QList<QByteArray> scenario; scenario << FakeServer::greeting() << "C: A000001 LOGIN \"user\" \"password\"" << "S: A000001 OK Welcome John Smith"; QTest::newRow("greeting") << "Welcome John Smith" << scenario; scenario.clear(); scenario << FakeServer::greeting() << "C: A000001 LOGIN \"user\" \"password\"" << "S: A000001 OK Welcome John Smith (last login: Feb 21, 2010)"; QTest::newRow("greeting with parenthesis") << "Welcome John Smith (last login: Feb 21, 2010)" << scenario; scenario.clear(); scenario << FakeServer::greeting() << "C: A000001 LOGIN \"user\" \"password\"" << "S: A000001 OK"; QTest::newRow("no greeting") << "" << scenario; scenario.clear(); scenario << FakeServer::greeting() << "C: A000001 LOGIN \"user\" \"password\"" << "S: A000001 NO Login failed: authentication failure"; QTest::newRow("login failed") << "" << scenario; } void shouldSaveServerGreeting() { QFETCH(QString, greeting); QFETCH(QList<QByteArray>, scenario); FakeServer fakeServer; fakeServer.setScenario(scenario); fakeServer.startAndWait(); KIMAP::Session *session = new KIMAP::Session(QStringLiteral("127.0.0.1"), 5989); KIMAP::LoginJob *login = new KIMAP::LoginJob(session); login->setUserName(QStringLiteral("user")); login->setPassword(QStringLiteral("password")); login->exec(); QCOMPARE(login->serverGreeting(), greeting); fakeServer.quit(); delete session; } void shouldUseSsl_data() { QTest::addColumn<QList<QByteArray>>("scenario"); QTest::addColumn<int>("serverEncryption"); { QList<QByteArray> scenario; scenario << FakeServer::greeting() << "C: A000001 CAPABILITY" << "S: A000001 OK" << "C: A000002 LOGIN \"user\" \"password\"" << "S: A000002 OK"; // AnySslVersion doesn't mean the server can force a specific version (e.g. openssl always starts with a tls12 hello) QTest::newRow("any protocol with anyssl version") << scenario << static_cast<int>(QSsl::AnyProtocol); QTest::newRow("tlsv12") << scenario << static_cast<int>(QSsl::TlsV1_2); QTest::newRow("tlsv13") << scenario << static_cast<int>(QSsl::TlsV1_3); } } void shouldUseSsl() { QFETCH(QList<QByteArray>, scenario); QFETCH(int, serverEncryption); FakeServer fakeServer; fakeServer.setEncrypted(static_cast<QSsl::SslProtocol>(serverEncryption)); fakeServer.setScenario(scenario); fakeServer.startAndWait(); KIMAP::Session *session = new KIMAP::Session(QStringLiteral("127.0.0.1"), 5989); KIMAP::SessionUiProxy::Ptr uiProxy(new TestUiProxy); session->setUiProxy(uiProxy); KIMAP::LoginJob *login = new KIMAP::LoginJob(session); login->setUserName(QStringLiteral("user")); login->setPassword(QStringLiteral("password")); login->setEncryptionMode(KIMAP::LoginJob::SSLorTLS); QVERIFY(login->exec()); fakeServer.quit(); delete session; } void shouldUseStartTls_data() { QTest::addColumn<QList<QByteArray>>("scenario"); QTest::addColumn<bool>("success"); { QList<QByteArray> scenario; scenario << FakeServer::greeting() << "C: A000001 CAPABILITY" << "S: * CAPABILITY IMAP4rev1 STARTTLS" << "S: A000001 OK CAPABILITY completed" << "C: A000002 STARTTLS" << "S: A000002 OK" << "C: A000003 CAPABILITY" << "S: * CAPABILITY IMAP4rev1" << "S: A000003 OK CAPABILITY completed" << "C: A000004 LOGIN \"user\" \"password\"" << "S: A000004 OK"; QTest::newRow("STARTTLS supported") << scenario << true; } { QList<QByteArray> scenario; scenario << FakeServer::greeting() << "C: A000001 CAPABILITY" << "S: * CAPABILITY IMAP4rev1" << "S: A000001 OK CAPABILITY completed"; QTest::newRow("STARTTLS not supported") << scenario << false; } } void shouldUseStartTls() { QFETCH(QList<QByteArray>, scenario); QFETCH(bool, success); FakeServer fakeServer; fakeServer.setEncrypted(QSsl::AnyProtocol); fakeServer.setWaitForStartTls(true); fakeServer.setScenario(scenario); fakeServer.startAndWait(); KIMAP::Session session(QStringLiteral("127.0.0.1"), 5989); KIMAP::SessionUiProxy::Ptr uiProxy(new TestUiProxy); session.setUiProxy(uiProxy); KIMAP::LoginJob login(&session); login.setUserName(QStringLiteral("user")); login.setPassword(QStringLiteral("password")); login.setEncryptionMode(KIMAP::LoginJob::STARTTLS); QCOMPARE(login.exec(), success); fakeServer.quit(); } }; QTEST_GUILESS_MAIN(LoginJobTest) #include "loginjobtest.moc" 0707010000002F000081A400000000000000000000000166FAD7C000000688000000000000000000000000000000000000004500000000kimap-VERSIONgit.20240930T185424~db1f697/autotests/logoutjobtest.cpp/* SPDX-FileCopyrightText: 2009 Andras Mantia <amantia@kde.org> SPDX-FileCopyrightText: 2010 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com> SPDX-FileContributor: Kevin Ottens <kevin@kdab.com> SPDX-License-Identifier: GPL-2.0-or-later */ #include <QTest> #include "kimap/loginjob.h" #include "kimap/logoutjob.h" #include "kimap/session.h" #include "kimaptest/fakeserver.h" #include <QTest> class LogoutJobTest : public QObject { Q_OBJECT private Q_SLOTS: void testLogout() { FakeServer fakeServer; fakeServer.setScenario(QList<QByteArray>() << FakeServer::preauth() << "C: A000001 LOGOUT" << "S: A000001 OK LOGOUT completed"); fakeServer.startAndWait(); auto session = new KIMAP::Session(QStringLiteral("127.0.0.1"), 5989); auto logout = new KIMAP::LogoutJob(session); QVERIFY(logout->exec()); fakeServer.quit(); delete session; } void testLogoutUntagged() { FakeServer fakeServer; fakeServer.setScenario(QList<QByteArray>() << FakeServer::preauth() << "C: A000001 LOGOUT" << "S: * some untagged response" << "S: A000001 OK LOGOUT completed"); fakeServer.startAndWait(); auto session = new KIMAP::Session(QStringLiteral("127.0.0.1"), 5989); auto logout = new KIMAP::LogoutJob(session); QVERIFY(logout->exec()); fakeServer.quit(); delete session; } }; QTEST_GUILESS_MAIN(LogoutJobTest) #include "logoutjobtest.moc" 07070100000030000081A400000000000000000000000166FAD7C0000007F2000000000000000000000000000000000000004300000000kimap-VERSIONgit.20240930T185424~db1f697/autotests/movejobtest.cpp/* SPDX-FileCopyrightText: 2016 Daniel Vrátil <dvratil@kde.org> SPDX-License-Identifier: GPL-2.0-or-later */ #include <QTest> #include "../src/movejob.h" #include "kimap/imapset.h" #include "kimap/session.h" #include "kimaptest/fakeserver.h" #include <QTest> class MoveJobTest : public QObject { Q_OBJECT private Q_SLOTS: void testMove_data() { QTest::addColumn<bool>("uidBased"); QTest::addColumn<qint64>("id"); QTest::addColumn<qint64>("resultUid"); QTest::addColumn<QString>("mailbox"); QTest::addColumn<QList<QByteArray>>("scenario"); QList<QByteArray> scenario; scenario << FakeServer::preauth() << "C: A000001 MOVE 3 \"foo\"" << "S: * OK [COPYUID 12345 3 7]" << "S: A000001 OK MOVE completed"; QTest::newRow("not uid based") << false << qint64(3) << qint64(7) << QStringLiteral("foo") << scenario; scenario.clear(); scenario << FakeServer::preauth() << "C: A000001 UID MOVE 1024 \"bar\"" << "S: * OK [COPYUID 12346 4 2048]" << "S: A000001 OK MOVE completed"; QTest::newRow("uid based") << true << qint64(1024) << qint64(2048) << QStringLiteral("bar") << scenario; } void testMove() { QFETCH(bool, uidBased); QFETCH(qint64, id); QFETCH(qint64, resultUid); QFETCH(QString, mailbox); QFETCH(QList<QByteArray>, scenario); FakeServer fakeServer; fakeServer.setScenario(scenario); fakeServer.startAndWait(); KIMAP::Session session(QStringLiteral("127.0.0.1"), 5989); auto job = new KIMAP::MoveJob(&session); job->setMailBox(mailbox); job->setUidBased(uidBased); job->setSequenceSet(KIMAP::ImapSet(id)); bool result = job->exec(); QVERIFY(result); QCOMPARE(job->resultingUids(), KIMAP::ImapSet(resultUid)); fakeServer.quit(); } }; QTEST_GUILESS_MAIN(MoveJobTest) #include "movejobtest.moc" 07070100000031000081A400000000000000000000000166FAD7C000001873000000000000000000000000000000000000004800000000kimap-VERSIONgit.20240930T185424~db1f697/autotests/quotarootjobtest.cpp/* SPDX-FileCopyrightText: 2011 Andras Mantia <amantia@kde.org> SPDX-License-Identifier: GPL-2.0-or-later */ #include <QTest> #include "kimap/getquotarootjob.h" #include "kimap/session.h" #include "kimaptest/fakeserver.h" #include <QTest> Q_DECLARE_METATYPE(QList<qint64>) class QuotaRootJobTest : public QObject { Q_OBJECT private Q_SLOTS: void testGetQuotaRoot_data() { QTest::addColumn<QString>("mailbox"); QTest::addColumn<QList<QByteArray>>("roots"); QTest::addColumn<QList<QByteArray>>("resources"); QTest::addColumn<QList<qint64>>("usages"); QTest::addColumn<QList<qint64>>("limits"); QTest::addColumn<QList<QByteArray>>("scenario"); QList<QByteArray> roots; QList<QByteArray> resources; QList<qint64> usages; QList<qint64> limits; QList<QByteArray> scenario; roots << ""; resources << "STORAGE"; limits << 512; usages << 10; scenario << FakeServer::preauth() << "C: A000001 GETQUOTAROOT \"INBOX\"" << "S: * QUOTAROOT INBOX \"\" " << "S: * QUOTA \"\" (STORAGE 10 512)" << "S: A000001 OK GETQUOTA completed"; QTest::newRow("one root, one resource") << "INBOX" << roots << resources << usages << limits << scenario; roots.clear(); resources.clear(); usages.clear(); limits.clear(); scenario.clear(); roots << ""; resources << "STORAGE" << "MESSAGE"; usages << 10 << 8221; limits << 512 << 20000; scenario << FakeServer::preauth() << "C: A000001 GETQUOTAROOT \"INBOX\"" << "S: * QUOTAROOT INBOX \"\" " << "S: * QUOTA \"\" (STORAGE 10 512)" << "S: * QUOTA \"\" ( MESSAGE 8221 20000 ) " << "S: A000001 OK GETQUOTA completed"; QTest::newRow("one root, multiple resource") << "INBOX" << roots << resources << usages << limits << scenario; roots.clear(); resources.clear(); usages.clear(); limits.clear(); scenario.clear(); roots << "root1" << "root2"; resources << "STORAGE" << "MESSAGE"; usages << 10 << 8221 << 30 << 100; limits << 512 << 20000 << 5124 << 120000; scenario << FakeServer::preauth() << "C: A000001 GETQUOTAROOT \"INBOX\"" << "S: * QUOTAROOT INBOX \"root1\" root2 " << "S: * QUOTA \"root1\" (STORAGE 10 512)" << "S: * QUOTA \"root1\" ( MESSAGE 8221 20000 ) " << "S: * QUOTA \"root2\" ( MESSAGE 100 120000 ) " << "S: * QUOTA \"root2\" (STORAGE 30 5124)" << "S: A000001 OK GETQUOTA completed"; QTest::newRow("multiple roots, multiple resource") << "INBOX" << roots << resources << usages << limits << scenario; roots.clear(); resources.clear(); usages.clear(); limits.clear(); scenario.clear(); roots << ""; resources << "STORAGE" << "MESSAGE"; usages << 10 << 8221; limits << 512 << 20000; scenario << FakeServer::preauth() << "C: A000001 GETQUOTAROOT \"INBOX\"" << "S: * QUOTAROOT INBOX" << "S: * QUOTA (STORAGE 10 512)" << "S: * QUOTA ( MESSAGE 8221 20000 ) " << "S: A000001 OK GETQUOTA completed"; QTest::newRow("no rootname, multiple resource") << "INBOX" << roots << resources << usages << limits << scenario; roots.clear(); resources.clear(); usages.clear(); limits.clear(); scenario.clear(); roots << ""; resources << "STORAGE"; limits << 512; usages << 10; scenario << FakeServer::preauth() << "C: A000001 GETQUOTAROOT \"INBOX\"" << "S: * QUOTAROOT INBOX \"\" " << "S: * QUOTA (STORAGE 10 512)" << "S: A000001 OK GETQUOTA completed"; QTest::newRow("no rootname in QUOTA, one resource") << "INBOX" << roots << resources << usages << limits << scenario; roots.clear(); resources.clear(); usages.clear(); limits.clear(); scenario.clear(); roots << ""; resources << "STORAGE"; limits << 512; usages << 10; scenario << FakeServer::preauth() << "C: A000001 GETQUOTAROOT \"INBOX\"" << "S: * QUOTAROOT INBOX \"root1\" " << "S: * QUOTA \"root2\" (STORAGE 10 512)" << "S: A000001 OK GETQUOTA completed"; QTest::newRow("rootname mismatch") << "INBOX" << roots << resources << usages << limits << scenario; } void testGetQuotaRoot() { QFETCH(QString, mailbox); QFETCH(QList<QByteArray>, roots); QFETCH(QList<QByteArray>, resources); QFETCH(QList<qint64>, usages); QFETCH(QList<qint64>, limits); QFETCH(QList<QByteArray>, scenario); FakeServer fakeServer; fakeServer.setScenario(scenario); fakeServer.startAndWait(); KIMAP::Session session(QStringLiteral("127.0.0.1"), 5989); auto job = new KIMAP::GetQuotaRootJob(&session); job->setMailBox(mailbox); bool result = job->exec(); QEXPECT_FAIL("bad", "Expected failure on BAD response", Continue); QEXPECT_FAIL("no", "Expected failure on NO response", Continue); QVERIFY(result); QEXPECT_FAIL("rootname mismatch", "Expected failure on rootname mismatch in QUOTAROOT and QUOTA response", Abort); QCOMPARE(job->roots(), roots); for (int rootIdx = 0; rootIdx < roots.size(); rootIdx++) { const QByteArray &root = roots[rootIdx]; for (int i = 0; i < resources.size(); i++) { int idx = i + rootIdx * roots.size(); QByteArray resource = resources[i]; QCOMPARE(job->limit(root, resource), limits[idx]); QCOMPARE(job->usage(root, resource), usages[idx]); } } fakeServer.quit(); } }; QTEST_GUILESS_MAIN(QuotaRootJobTest) #include "quotarootjobtest.moc" 07070100000032000081A400000000000000000000000166FAD7C000000957000000000000000000000000000000000000004500000000kimap-VERSIONgit.20240930T185424~db1f697/autotests/renamejobtest.cpp/* SPDX-FileCopyrightText: 2009 Andras Mantia <amantia@kde.org> SPDX-FileCopyrightText: 2010 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com> SPDX-FileContributor: Kevin Ottens <kevin@kdab.com> SPDX-License-Identifier: GPL-2.0-or-later */ #include <QTest> #include "kimap/renamejob.h" #include "kimap/session.h" #include "kimaptest/fakeserver.h" #include <QTest> class RenameJobTest : public QObject { Q_OBJECT private Q_SLOTS: void testRename_data() { QTest::addColumn<QString>("mailbox"); QTest::addColumn<QString>("newname"); QTest::addColumn<QList<QByteArray>>("scenario"); QList<QByteArray> scenario; scenario << FakeServer::preauth() << R"(C: A000001 RENAME "INBOX" "oldmail")" << "S: A000001 OK RENAME completed"; QTest::newRow("good") << "INBOX" << "oldmail" << scenario; scenario.clear(); scenario << FakeServer::preauth() << R"(C: A000001 RENAME "INBOX-FAIL-BAD" "oldmail-bad")" << "S: A000001 BAD command unknown or arguments invalid"; QTest::newRow("bad") << "INBOX-FAIL-BAD" << "oldmail-bad" << scenario; scenario.clear(); scenario << FakeServer::preauth() << R"(C: A000001 RENAME "INBOX-FAIL-NO" "oldmail-no")" << "S: A000001 NO rename failure"; QTest::newRow("no") << "INBOX-FAIL-NO" << "oldmail-no" << scenario; } void testRename() { QFETCH(QString, mailbox); QFETCH(QString, newname); QFETCH(QList<QByteArray>, scenario); FakeServer fakeServer; fakeServer.setScenario(scenario); fakeServer.startAndWait(); KIMAP::Session session(QStringLiteral("127.0.0.1"), 5989); auto job = new KIMAP::RenameJob(&session); job->setSourceMailBox(mailbox); job->setDestinationMailBox(newname); bool result = job->exec(); QEXPECT_FAIL("bad", "Expected failure on BAD response", Continue); QEXPECT_FAIL("no", "Expected failure on NO response", Continue); QVERIFY(result); QCOMPARE(job->sourceMailBox(), mailbox); QCOMPARE(job->destinationMailBox(), newname); fakeServer.quit(); } }; QTEST_GUILESS_MAIN(RenameJobTest) #include "renamejobtest.moc" 07070100000033000081A400000000000000000000000166FAD7C000001EF4000000000000000000000000000000000000004500000000kimap-VERSIONgit.20240930T185424~db1f697/autotests/searchjobtest.cpp/* * SPDX-FileCopyrightText: 2013 Daniel Vrátil <dvratil@redhat.com> * * SPDX-License-Identifier: GPL-2.0-or-later * */ #include <QTest> #include "kimap/loginjob.h" #include "kimap/searchjob.h" #include "kimap/session.h" #include "kimaptest/fakeserver.h" #include <QTest> using SearchCriteriaValuePair = QPair<KIMAP::SearchJob::SearchCriteria, QByteArray>; Q_DECLARE_METATYPE(QList<SearchCriteriaValuePair>) Q_DECLARE_METATYPE(KIMAP::SearchJob::SearchLogic) Q_DECLARE_METATYPE(KIMAP::Term) #define searchPair(a, b) qMakePair<KIMAP::SearchJob::SearchCriteria, QByteArray>(a, b) class SearchJobTest : public QObject { Q_OBJECT private Q_SLOTS: void testSearch_data() { QTest::addColumn<QList<QByteArray>>("scenario"); QTest::addColumn<bool>("uidbased"); QTest::addColumn<int>("expectedResultsCount"); QTest::addColumn<KIMAP::SearchJob::SearchLogic>("searchLogic"); QTest::addColumn<QList<SearchCriteriaValuePair>>("searchCriteria"); QList<QByteArray> scenario; QList<SearchCriteriaValuePair> criteria; scenario << FakeServer::preauth() << "C: A000001 UID SEARCH HEADER Message-Id <12345678@mail.box>" << "S: * SEARCH 10 12" << "S: A000001 OK search done"; criteria << searchPair(KIMAP::SearchJob::Header, "Message-Id <12345678@mail.box>"); QTest::newRow("uidbased header search") << scenario << true << 2 << KIMAP::SearchJob::And << criteria; scenario.clear(); criteria.clear(); scenario << FakeServer::preauth() << "C: A000001 SEARCH OR (NEW) (HEADER Message-Id <12345678@mail.box>)" << "S: * SEARCH" << "S: A000001 OK search done"; criteria << searchPair(KIMAP::SearchJob::New, QByteArray()) << searchPair(KIMAP::SearchJob::Header, "Message-Id <12345678@mail.box>"); QTest::newRow("OR search with no results") << scenario << false << 0 << KIMAP::SearchJob::Or << criteria; scenario.clear(); criteria.clear(); scenario << FakeServer::preauth() << "C: A000001 SEARCH TO {25}\r\n<testuser@kde.testserver>" << "S: * SEARCH 1" << "S: A000001 OK search done"; criteria << searchPair(KIMAP::SearchJob::To, "<testuser@kde.testserver>"); QTest::newRow("literal data search") << scenario << false << 1 << KIMAP::SearchJob::And << criteria; scenario.clear(); criteria.clear(); scenario << FakeServer::preauth() << "C: A000001 UID SEARCH NOT (NEW)" << "S: * SEARCH 1 2 3 4 5 6" << "S: A000001 OK search done"; criteria << searchPair(KIMAP::SearchJob::New, QByteArray()); QTest::newRow("uidbased NOT NEW search") << scenario << true << 6 << KIMAP::SearchJob::Not << criteria; } void testSearch() { QFETCH(QList<QByteArray>, scenario); QFETCH(bool, uidbased); QFETCH(int, expectedResultsCount); QFETCH(KIMAP::SearchJob::SearchLogic, searchLogic); QFETCH(QList<SearchCriteriaValuePair>, searchCriteria); FakeServer fakeServer; fakeServer.setScenario(scenario); fakeServer.startAndWait(); KIMAP::Session session(QStringLiteral("127.0.0.1"), 5989); auto job = new KIMAP::SearchJob(&session); job->setUidBased(uidbased); job->setSearchLogic(searchLogic); for (const SearchCriteriaValuePair &pair : std::as_const(searchCriteria)) { if (pair.second.isEmpty()) { job->addSearchCriteria(pair.first); } else { job->addSearchCriteria(pair.first, pair.second); } } bool result = job->exec(); QVERIFY(result); if (result) { QList<qint64> foundItems = job->results(); QCOMPARE(foundItems.size(), expectedResultsCount); } fakeServer.quit(); } void testSearchTerm_data() { QTest::addColumn<QList<QByteArray>>("scenario"); QTest::addColumn<bool>("uidbased"); QTest::addColumn<int>("expectedResultsCount"); QTest::addColumn<KIMAP::Term>("searchTerm"); { QList<QByteArray> scenario; scenario << FakeServer::preauth() << "C: A000001 UID SEARCH HEADER Message-Id \"<12345678@mail.box>\"" << "S: * SEARCH 10 12" << "S: A000001 OK search done"; QTest::newRow("uidbased header search") << scenario << true << 2 << KIMAP::Term(QStringLiteral("Message-Id"), QStringLiteral("<12345678@mail.box>")); } { QList<QByteArray> scenario; scenario << FakeServer::preauth() << "C: A000001 SEARCH OR NEW HEADER Message-Id \"<12345678@mail.box>\"" << "S: * SEARCH" << "S: A000001 OK search done"; QTest::newRow("OR search with no results") << scenario << false << 0 << KIMAP::Term(KIMAP::Term::Or, QList<KIMAP::Term>() << KIMAP::Term(KIMAP::Term::New) << KIMAP::Term(QStringLiteral("Message-Id"), QStringLiteral("<12345678@mail.box>"))); } { QList<QByteArray> scenario; scenario << FakeServer::preauth() << "C: A000001 SEARCH TO \"<testuser@kde.testserver>\"" << "S: * SEARCH 1" << "S: A000001 OK search done"; QTest::newRow("literal data search") << scenario << false << 1 << KIMAP::Term(KIMAP::Term::To, QStringLiteral("<testuser@kde.testserver>")); } { QList<QByteArray> scenario; scenario << FakeServer::preauth() << "C: A000001 UID SEARCH NOT NEW" << "S: * SEARCH 1 2 3 4 5 6" << "S: A000001 OK search done"; QTest::newRow("uidbased NOT NEW search") << scenario << true << 6 << KIMAP::Term(KIMAP::Term::New).setNegated(true); } { QList<QByteArray> scenario; scenario << FakeServer::preauth() << R"(C: A000001 UID SEARCH OR HEADER Message-Id "<1234567@mail.box>" (OR HEADER Message-Id "<7654321@mail.box>" (OR HEADER Message-Id "<abcdefg@mail.box>" HEADER Message-Id "<gfedcba@mail.box>")))" << "S: * SEARCH 1 2 3 4" << "S: A000001 OK search done"; KIMAP::Term term{KIMAP::Term::Or, {KIMAP::Term{QStringLiteral("Message-Id"), QStringLiteral("<1234567@mail.box>")}, KIMAP::Term{QStringLiteral("Message-Id"), QStringLiteral("<7654321@mail.box>")}, KIMAP::Term{QStringLiteral("Message-Id"), QStringLiteral("<abcdefg@mail.box>")}, KIMAP::Term{QStringLiteral("Message-Id"), QStringLiteral("<gfedcba@mail.box>")}}}; QTest::newRow("OR with multiple subterms") << scenario << true << 4 << term; } } void testSearchTerm() { QFETCH(QList<QByteArray>, scenario); QFETCH(bool, uidbased); QFETCH(int, expectedResultsCount); QFETCH(KIMAP::Term, searchTerm); FakeServer fakeServer; fakeServer.setScenario(scenario); fakeServer.startAndWait(); KIMAP::Session session(QStringLiteral("127.0.0.1"), 5989); auto job = new KIMAP::SearchJob(&session); job->setUidBased(uidbased); job->setTerm(searchTerm); bool result = job->exec(); QVERIFY(result); if (result) { QList<qint64> foundItems = job->results(); QCOMPARE(foundItems.size(), expectedResultsCount); } fakeServer.quit(); } }; QTEST_GUILESS_MAIN(SearchJobTest) #include "searchjobtest.moc" 07070100000034000081A400000000000000000000000166FAD7C000002C60000000000000000000000000000000000000004500000000kimap-VERSIONgit.20240930T185424~db1f697/autotests/selectjobtest.cpp/* SPDX-FileCopyrightText: 2009 Andras Mantia <amantia@kde.org> SPDX-FileCopyrightText: 2010 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com> SPDX-FileContributor: Kevin Ottens <kevin@kdab.com> SPDX-License-Identifier: GPL-2.0-or-later */ #include <QTest> #include "kimap/loginjob.h" #include "kimap/selectjob.h" #include "kimap/session.h" #include "kimaptest/fakeserver.h" #include <QSignalSpy> #include <QTest> using Messages = QMap<qint64, KIMAP::Message>; Q_DECLARE_METATYPE(KIMAP::Message) Q_DECLARE_METATYPE(Messages) class SelectJobTest : public QObject { Q_OBJECT public: explicit SelectJobTest() { qRegisterMetaType<KIMAP::ImapSet>(); qRegisterMetaType<KIMAP::Message>(); qRegisterMetaType<QMap<qint64, KIMAP::Message>>("QMap<qint64,KIMAP::Message>"); } private Q_SLOTS: void testSingleSelect_data() { QTest::addColumn<QList<QByteArray>>("scenario"); QTest::addColumn<QList<QByteArray>>("flags"); QTest::addColumn<QList<QByteArray>>("permanentflags"); QTest::addColumn<int>("messagecount"); QTest::addColumn<int>("recentcount"); QTest::addColumn<int>("firstUnseenIndex"); QTest::addColumn<qint64>("uidValidity"); QTest::addColumn<qint64>("nextUid"); QTest::addColumn<quint64>("highestmodseq"); QTest::addColumn<bool>("condstoreEnabled"); QTest::addColumn<bool>("readonly"); QTest::addColumn<qint64>("lastUidvalidity"); QTest::addColumn<quint64>("lastModseq"); QTest::addColumn<KIMAP::ImapSet>("vanished"); QTest::addColumn<Messages>("modified"); QList<QByteArray> scenario; QList<QByteArray> flags; QList<QByteArray> permanentflags; scenario << FakeServer::preauth() << "C: A000001 SELECT \"INBOX\" (CONDSTORE)" << "S: * 172 EXISTS" << "S: * 1 RECENT" << "S: * OK [UNSEEN 12] Message 12 is first unseen" << "S: * OK [UIDVALIDITY 3857529045] UIDs valid" << "S: * OK [UIDNEXT 4392] Predicted next UID" << "S: * OK [HIGHESTMODSEQ 123456789]" << R"(S: * FLAGS (\Answered \Flagged \Deleted \Seen \Draft))" << R"(S: * OK [PERMANENTFLAGS (\Deleted \Seen \*)] Limited)" << "S: A000001 OK [READ-WRITE] SELECT completed"; flags << "\\Answered" << "\\Flagged" << "\\Deleted" << "\\Seen" << "\\Draft"; permanentflags << "\\Deleted" << "\\Seen" << "\\*"; QTest::newRow("good") << scenario << flags << permanentflags << 172 << 1 << 12 << 3857529045LL << 4392LL << 123456789ULL << true << false << -1LL << 0ULL << KIMAP::ImapSet{} << Messages{}; scenario.clear(); flags.clear(); permanentflags.clear(); scenario << FakeServer::preauth() << "C: A000001 SELECT \"INBOX\"" << "S: A000001 BAD command unknown or arguments invalid"; QTest::newRow("bad") << scenario << flags << permanentflags << 0 << 0 << 0 << 0LL << 0LL << 0ULL << false << false << -1LL << 0ULL << KIMAP::ImapSet{} << Messages{}; scenario.clear(); flags.clear(); permanentflags.clear(); scenario << FakeServer::preauth() << "C: A000001 SELECT \"INBOX\"" << "S: A000001 NO select failure"; QTest::newRow("no") << scenario << flags << permanentflags << 0 << 0 << 0 << 0LL << 0LL << 0ULL << false << false << -1LL << 0ULL << KIMAP::ImapSet{} << Messages{}; scenario.clear(); scenario << FakeServer::preauth() << "C: A000001 SELECT \"INBOX\" (QRESYNC (67890007 90060115194045000))" << "S: * 314 EXISTS" << "S: * 15 RECENT" << "S: * OK [UIDVALIDITY 67890007] UIDVALIDITY" << "S: * OK [UIDNEXT 567] Predicted next UID" << "S: * OK [HIGHESTMODSEQ 90060115205545359]" << "S: * OK [UNSEEN 7] There are some unseen messages in the mailbox" << R"(S: * FLAGS (\Answered \Flagged \Draft \Deleted \Seen))" << R"(S: * OK [PERMANENTFLAGS (\Answered \Flagged \Draft \Deleted \Seen \*)] Permanent flags)" << "S: * VANISHED (EARLIER) 41,43:116,118,120:211,214:540" << "S: * 49 FETCH (UID 117 FLAGS (\\Seen \\Answered) MODSEQ (90060115194045001))" << "S: * 50 FETCH (UID 119 FLAGS (\\Draft $MDNSent) MODSEQ (90060115194045308))" << "S: * 100 FETCH (UID 541 FLAGS (\\Seen $Forwarded) MODSEQ (90060115194045001))" << "S: A000001 OK [READ-WRITE] mailbox selected"; permanentflags = {"\\Answered", "\\Flagged", "\\Draft", "\\Deleted", "\\Seen", "\\*"}; flags = {"\\Answered", "\\Flagged", "\\Draft", "\\Deleted", "\\Seen"}; KIMAP::ImapSet vanished; vanished.add(41); vanished.add(KIMAP::ImapInterval{43, 116}); vanished.add(118); vanished.add(KIMAP::ImapInterval{120, 211}); vanished.add(KIMAP::ImapInterval{214, 540}); Messages modified = {{49, KIMAP::Message{117, 0, {"\\Seen", "\\Answered"}, {{"MODSEQ", QVariant{90060115194045001ULL}}}, {}, {}}}, {50, KIMAP::Message{119, 0, {"\\Draft", "$MDNSent"}, {{"MODSEQ", QVariant{90060115194045308ULL}}}, {}, {}}}, {100, KIMAP::Message{541, 0, {"\\Seen", "$Forwarded"}, {{"MODSEQ", QVariant{90060115194045001ULL}}}, {}, {}}}}; QTest::newRow("QResync") << scenario << flags << permanentflags << 314 << 15 << 7 << 67890007LL << 567LL << 90060115205545359ULL << false << false << 67890007LL << 90060115194045000ULL << vanished << modified; } void testSingleSelect() { QFETCH(QList<QByteArray>, scenario); QFETCH(QList<QByteArray>, flags); QFETCH(QList<QByteArray>, permanentflags); QFETCH(int, messagecount); QFETCH(int, recentcount); QFETCH(int, firstUnseenIndex); QFETCH(qint64, uidValidity); QFETCH(qint64, nextUid); QFETCH(quint64, highestmodseq); QFETCH(bool, condstoreEnabled); QFETCH(qint64, lastUidvalidity); QFETCH(quint64, lastModseq); QFETCH(KIMAP::ImapSet, vanished); QFETCH(Messages, modified); FakeServer fakeServer; fakeServer.setScenario(scenario); fakeServer.startAndWait(); KIMAP::Session session(QStringLiteral("127.0.0.1"), 5989); auto job = new KIMAP::SelectJob(&session); job->setCondstoreEnabled(condstoreEnabled); job->setMailBox(QStringLiteral("INBOX")); if (lastUidvalidity > -1 && lastModseq > 0) { job->setQResync(lastUidvalidity, lastModseq); } QSignalSpy vanishedSpy(job, &KIMAP::SelectJob::vanished); QVERIFY(vanishedSpy.isValid()); QSignalSpy modifiedSpy(job, &KIMAP::SelectJob::modified); QVERIFY(modifiedSpy.isValid()); bool result = job->exec(); QEXPECT_FAIL("bad", "Expected failure on BAD scenario", Continue); QEXPECT_FAIL("no", "Expected failure on NO scenario", Continue); QVERIFY(result); if (result) { QCOMPARE(job->flags(), flags); QCOMPARE(job->permanentFlags(), permanentflags); QCOMPARE(job->messageCount(), messagecount); QCOMPARE(job->recentCount(), recentcount); QCOMPARE(job->firstUnseenIndex(), firstUnseenIndex); QCOMPARE(job->uidValidity(), uidValidity); QCOMPARE(job->nextUid(), nextUid); QCOMPARE(job->highestModSequence(), highestmodseq); if (!vanished.isEmpty()) { QCOMPARE(vanishedSpy.size(), 1); QCOMPARE(vanishedSpy.at(0).at(0).value<KIMAP::ImapSet>(), vanished); } if (!modified.isEmpty()) { Messages collectedModified; for (const auto &modifiedSpyCatch : modifiedSpy) { const auto msgs = modifiedSpyCatch.at(0).value<Messages>(); for (auto it = msgs.begin(); it != msgs.end(); ++it) { collectedModified.insert(it.key(), it.value()); } } QCOMPARE(collectedModified, modified); } } fakeServer.quit(); } void testSeveralSelect() { FakeServer fakeServer; fakeServer.setScenario(QList<QByteArray>() << FakeServer::preauth() << "C: A000001 SELECT \"INBOX\"" << "S: A000001 OK [READ-WRITE] SELECT completed" << "C: A000002 SELECT \"INBOX/Foo\"" << "S: A000002 OK [READ-WRITE] SELECT completed"); fakeServer.startAndWait(); KIMAP::Session session(QStringLiteral("127.0.0.1"), 5989); auto job = new KIMAP::SelectJob(&session); job->setMailBox(QStringLiteral("INBOX")); QVERIFY(job->exec()); job = new KIMAP::SelectJob(&session); job->setMailBox(QStringLiteral("INBOX/Foo")); QVERIFY(job->exec()); } void testReadOnlySelect_data() { QTest::addColumn<QList<QByteArray>>("scenario"); QTest::addColumn<bool>("examine"); QTest::addColumn<bool>("isReadOnly"); { QList<QByteArray> scenario; scenario << FakeServer::preauth() << "C: A000001 SELECT \"INBOX\"" << "S: A000001 OK [READ-WRITE] SELECT ok"; QTest::newRow("SELECT rw") << scenario << false << false; } { QList<QByteArray> scenario; scenario << FakeServer::preauth() << "C: A000001 SELECT \"INBOX\"" << "S: A000001 OK SELECT ok"; QTest::newRow("SELECT rw (without code)") << scenario << false << false; } { QList<QByteArray> scenario; scenario << FakeServer::preauth() << "C: A000001 SELECT \"INBOX\"" << "S: A000001 OK [READ-ONLY] SELECT ok"; QTest::newRow("SELECT ro") << scenario << false << true; } { QList<QByteArray> scenario; scenario << FakeServer::preauth() << "C: A000001 EXAMINE \"INBOX\"" << "S: A000001 OK [READ-ONLY] EXAMINE ok"; QTest::newRow("EXAMINE ro") << scenario << true << true; } } void testReadOnlySelect() { QFETCH(QList<QByteArray>, scenario); QFETCH(bool, examine); QFETCH(bool, isReadOnly); FakeServer fakeServer; fakeServer.setScenario(scenario); fakeServer.startAndWait(); KIMAP::Session session(QStringLiteral("127.0.0.1"), 5989); KIMAP::SelectJob select(&session); select.setOpenReadOnly(examine); select.setMailBox(QStringLiteral("INBOX")); QVERIFY(select.exec()); QCOMPARE(select.isOpenReadOnly(), isReadOnly); } }; QTEST_GUILESS_MAIN(SelectJobTest) #include "selectjobtest.moc" 07070100000035000081A400000000000000000000000166FAD7C000001702000000000000000000000000000000000000004A00000000kimap-VERSIONgit.20240930T185424~db1f697/autotests/setmetadatajobtest.cpp/* SPDX-FileCopyrightText: 2013 Christian Mollekopf <mollekopf@kolabsys.com> SPDX-License-Identifier: GPL-2.0-or-later */ #include <QTest> #include "kimap/session.h" #include "kimap/setmetadatajob.h" #include "kimaptest/fakeserver.h" #include <QTest> using MAP = QMap<QByteArray, QByteArray>; Q_DECLARE_METATYPE(MAP) class SetMetadataJobTest : public QObject { Q_OBJECT private Q_SLOTS: void metadata_data() { QTest::addColumn<QList<QByteArray>>("scenario"); QTest::addColumn<QString>("mailbox"); QTest::addColumn<QMap<QByteArray, QByteArray>>("annotations"); { QList<QByteArray> scenario; scenario << FakeServer::preauth() << R"(C: A000001 SETMETADATA "Folder1" ("/public/comment" "comment2" "/shared/comment" "Shared comment"))" << "S: A000001 OK SETMETADATA complete"; QMap<QByteArray, QByteArray> annotations; annotations.insert("/public/comment", "comment2"); annotations.insert("/shared/comment", "Shared comment"); QTest::newRow("normal") << scenario << "Folder1" << annotations; } { QList<QByteArray> scenario; scenario << FakeServer::preauth() << "C: A000001 SETMETADATA \"Folder1\" (\"/public/comment\" {8}\r\ncomment2 \"/shared/comment\" {14}\r\nShared\ncomment)" << "S: A000001 OK SETMETADATA complete"; QMap<QByteArray, QByteArray> annotations; annotations.insert("/shared/comment", "Shared\ncomment"); annotations.insert("/public/comment", "comment2"); QTest::newRow("newline") << scenario << "Folder1" << annotations; } { QList<QByteArray> scenario; scenario << FakeServer::preauth() << R"(C: A000001 SETMETADATA "Folder1" ("/shared/comment" NIL))" << "S: A000001 OK SETMETADATA complete"; QMap<QByteArray, QByteArray> annotations; annotations.insert("/shared/comment", ""); QTest::newRow("newline") << scenario << "Folder1" << annotations; } { QList<QByteArray> scenario; scenario << FakeServer::preauth() << "C: A000001 SETMETADATA \"Folder1\" (\"/public/comment\" {12}\r\ncomment\ntest \"/shared/comment\" {3}\r\nNIL)" << "S: A000001 OK SETMETADATA complete"; QMap<QByteArray, QByteArray> annotations; annotations.insert("/shared/comment", ""); annotations.insert("/public/comment", "comment\ntest"); QTest::newRow("newline2") << scenario << "Folder1" << annotations; } { QList<QByteArray> scenario; scenario << FakeServer::preauth() << "C: A000001 SETMETADATA \"Folder1\" (\"/public/comment\" {3}\r\nNIL \"/shared/comment\" {12}\r\ncomment\ntest)" << "S: A000001 OK SETMETADATA complete"; QMap<QByteArray, QByteArray> annotations; annotations.insert("/shared/comment", "comment\ntest"); annotations.insert("/public/comment", ""); QTest::newRow("newline2") << scenario << "Folder1" << annotations; } } void metadata() { QFETCH(QList<QByteArray>, scenario); QFETCH(QString, mailbox); QFETCH(MAP, annotations); FakeServer fakeServer; fakeServer.setScenario(scenario); fakeServer.startAndWait(); KIMAP::Session session(QStringLiteral("127.0.0.1"), 5989); auto setMetadataJob = new KIMAP::SetMetaDataJob(&session); setMetadataJob->setServerCapability(KIMAP::MetaDataJobBase::Metadata); setMetadataJob->setMailBox(mailbox); const auto keys = annotations.keys(); for (const QByteArray &entry : keys) { setMetadataJob->addMetaData(entry, annotations[entry]); } QVERIFY(setMetadataJob->exec()); fakeServer.quit(); } void annotatemore_data() { QTest::addColumn<QList<QByteArray>>("scenario"); QTest::addColumn<QString>("mailbox"); QTest::addColumn<QMap<QByteArray, QByteArray>>("annotations"); QTest::addColumn<bool>("legacyMode"); { QList<QByteArray> scenario; scenario << FakeServer::preauth() << R"(C: A000001 SETANNOTATION "Folder1" "/comment" ("value.shared" "Shared comment"))" << "S: A000001 OK annotations changed"; QMap<QByteArray, QByteArray> annotations; annotations.insert("/comment", "Shared comment"); QTest::newRow("normal") << scenario << "Folder1" << annotations << false; QTest::newRow("legacy") << scenario << "Folder1" << annotations << true; } } void annotatemore() { QFETCH(QList<QByteArray>, scenario); QFETCH(QString, mailbox); QFETCH(MAP, annotations); QFETCH(bool, legacyMode); FakeServer fakeServer; fakeServer.setScenario(scenario); fakeServer.startAndWait(); KIMAP::Session session(QStringLiteral("127.0.0.1"), 5989); auto setMetadataJob = new KIMAP::SetMetaDataJob(&session); setMetadataJob->setServerCapability(KIMAP::MetaDataJobBase::Annotatemore); setMetadataJob->setMailBox(mailbox); const auto keys = annotations.keys(); for (const QByteArray &entry : keys) { if (legacyMode) { setMetadataJob->setEntry(entry); setMetadataJob->addMetaData("value.shared", annotations[entry]); } else { setMetadataJob->addMetaData(QByteArray("/shared") + entry, annotations[entry]); } } QVERIFY(setMetadataJob->exec()); fakeServer.quit(); } }; QTEST_GUILESS_MAIN(SetMetadataJobTest) #include "setmetadatajobtest.moc" 07070100000036000081A400000000000000000000000166FAD7C000000F0A000000000000000000000000000000000000004500000000kimap-VERSIONgit.20240930T185424~db1f697/autotests/statusjobtest.cpp/* SPDX-FileCopyrightText: 2016 Daniel Vrátil <dvratil@kde.org> SPDX-License-Identifier: LGPL-2.0-or-later */ #include <QTest> #include "kimap/loginjob.h" #include "kimap/session.h" #include "kimap/statusjob.h" #include "kimaptest/fakeserver.h" using StatusMap = QList<QPair<QByteArray, qint64>>; Q_DECLARE_METATYPE(StatusMap) class StatusJobTest : public QObject { Q_OBJECT private Q_SLOTS: void testStatus_data() { QTest::addColumn<QList<QByteArray>>("scenario"); QTest::addColumn<QList<QByteArray>>("dataItems"); QTest::addColumn<StatusMap>("results"); QList<QByteArray> scenario; QList<QByteArray> dataItems; StatusMap results; scenario << FakeServer::preauth() << "C: A000001 STATUS \"INBOX\" (MESSAGES RECENT UIDNEXT UIDVALIDITY UNSEEN)" << "S: * STATUS \"INBOX\" (MESSAGES 294 RECENT 1 UIDNEXT 295 UIDVALIDITY 458587604 UNSEEN 181)" << "S: A000001 OK STATUS Completed"; dataItems = {"MESSAGES", "RECENT", "UIDNEXT", "UIDVALIDITY", "UNSEEN"}; results = {{"MESSAGES", 294}, {"RECENT", 1}, {"UIDNEXT", 295}, {"UIDVALIDITY", 458587604}, {"UNSEEN", 181}}; QTest::newRow("good") << scenario << dataItems << results; scenario.clear(); results.clear(); scenario << FakeServer::preauth() << "C: A000001 STATUS \"INBOX\" (MESSAGES UIDNEXT HIGHESTMODSEQ)" << "S: * STATUS \"INBOX\" (MESSAGES 294 UIDNEXT 295)" << "S: A000001 OK STATUS Completed"; dataItems = {"MESSAGES", "UIDNEXT", "HIGHESTMODSEQ"}; results = {{"MESSAGES", 294}, {"UIDNEXT", 295}}; QTest::newRow("incomplete") << scenario << dataItems << results; scenario.clear(); results.clear(); scenario << FakeServer::preauth() << "C: A000001 STATUS \"INBOX\" (HIGHESTMODSEQ)" << "S: * STATUS \"INBOX\" ()" << "S: A000001 OK STATUS Completed"; dataItems = {"HIGHESTMODSEQ"}; QTest::newRow("empty response") << scenario << dataItems << results; scenario.clear(); results.clear(); scenario << FakeServer::preauth() << "C: A000001 STATUS \"INBOX\" (MESSAGES HIGHESTMODSEQ)" << "S: A000001 NO status failure"; dataItems = {"MESSAGES", "HIGHESTMODSEQ"}; results.clear(); QTest::newRow("no") << scenario << dataItems << results; scenario.clear(); results.clear(); scenario << FakeServer::preauth() << "C: A000001 STATUS \"INBOX\" (UIDNEXT)" << "S: A000001 NO bad command"; dataItems = {"UIDNEXT"}; QTest::newRow("bad") << scenario << dataItems << results; } void testStatus() { QFETCH(QList<QByteArray>, scenario); QFETCH(QList<QByteArray>, dataItems); QFETCH(StatusMap, results); FakeServer fakeServer; fakeServer.setScenario(scenario); fakeServer.startAndWait(); KIMAP::Session session(QStringLiteral("127.0.0.1"), 5989); auto job = new KIMAP::StatusJob(&session); job->setMailBox(QStringLiteral("INBOX")); job->setDataItems(dataItems); bool result = job->exec(); QEXPECT_FAIL("bad", "Expected failure on BAD scenario", Continue); QEXPECT_FAIL("no", "Expected failure on NO scenario", Continue); QVERIFY(result); if (result) { const StatusMap status = job->status(); QCOMPARE(status.count(), results.count()); for (int i = 0; i < results.count(); ++i) { QCOMPARE(results[i].first, status[i].first); QCOMPARE(results[i].second, status[i].second); } } fakeServer.quit(); } }; QTEST_GUILESS_MAIN(StatusJobTest) #include "statusjobtest.moc" 07070100000037000081A400000000000000000000000166FAD7C000000A93000000000000000000000000000000000000004400000000kimap-VERSIONgit.20240930T185424~db1f697/autotests/storejobtest.cpp/* SPDX-FileCopyrightText: 2009 Kevin Ottens <ervin@kde.org> SPDX-FileCopyrightText: 2010 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com> SPDX-FileContributor: Kevin Ottens <kevin@kdab.com> SPDX-License-Identifier: GPL-2.0-or-later */ #include <QTest> #include "kimap/session.h" #include "kimap/storejob.h" #include "kimaptest/fakeserver.h" #include <QTest> class StoreJobTest : public QObject { Q_OBJECT private Q_SLOTS: void testStore_data() { QTest::addColumn<bool>("uidBased"); QTest::addColumn<qint64>("id"); QTest::addColumn<qint64>("uid"); QTest::addColumn<QList<QByteArray>>("flags"); QTest::addColumn<QList<QByteArray>>("scenario"); QList<QByteArray> scenario; scenario << FakeServer::preauth() << "C: A000001 STORE 3 FLAGS (\\Seen \\Foo)" << "S: * 3 FETCH (FLAGS (\\Seen \\Foo) UID 1096)" << "S: A000001 OK STORE completed"; QTest::newRow("not uid based") << false << qint64(3) << qint64(1096) << (QList<QByteArray>() << "\\Seen" << "\\Foo") << scenario; scenario.clear(); scenario << FakeServer::preauth() << "C: A000001 UID STORE 1096 FLAGS (\\Seen \\Foo)" << "S: * 3 FETCH (FLAGS (\\Seen \\Foo) UID 1096)" << "S: A000001 OK STORE completed"; QTest::newRow("uid based") << true << qint64(3) << qint64(1096) << (QList<QByteArray>() << "\\Seen" << "\\Foo") << scenario; } void testStore() { QFETCH(bool, uidBased); QFETCH(qint64, id); QFETCH(qint64, uid); QFETCH(QList<QByteArray>, flags); QFETCH(QList<QByteArray>, scenario); FakeServer fakeServer; fakeServer.setScenario(scenario); fakeServer.startAndWait(); KIMAP::Session session(QStringLiteral("127.0.0.1"), 5989); auto job = new KIMAP::StoreJob(&session); job->setUidBased(uidBased); job->setSequenceSet(KIMAP::ImapSet(uidBased ? uid : id)); job->setFlags(flags); job->setMode(KIMAP::StoreJob::SetFlags); bool result = job->exec(); QVERIFY(result); if (uidBased) { QVERIFY(job->resultingFlags().contains(uid)); } else { QVERIFY(job->resultingFlags().contains(id)); } fakeServer.quit(); } }; QTEST_GUILESS_MAIN(StoreJobTest) #include "storejobtest.moc" 07070100000038000081A400000000000000000000000166FAD7C000001431000000000000000000000000000000000000004800000000kimap-VERSIONgit.20240930T185424~db1f697/autotests/streamparsertest.cpp/* SPDX-FileCopyrightText: 2013 Christian Mollekopf <mollekopf@kolabsys.com> SPDX-License-Identifier: GPL-2.0-or-later */ #include <QTest> #include "imapstreamparser.h" #include "response_p.h" #include <QBuffer> #include <QTest> using namespace KIMAP; class StreamParserTest : public QObject { Q_OBJECT QByteArray part1; QByteArray part2; QByteArray part3; QByteArray part4; QByteArray completeResponse; QList<QByteArray> expectedList; private Q_SLOTS: void init() { part1 = "* 230 FETCH (FLAGS (\\Recent \\Seen) UID 230 INTERNALDATE \" 1-Nov-2013 13:31:17 +0100\" RFC822.SIZE 37 BODY[] {37}\r"; part2 = "\nDate: Fri, 01 Nov 2013 12:31:13 +0000\n"; part3 = "body\n"; part4 = ")\n\r"; completeResponse = part1 + part2 + part3 + part4; expectedList.clear(); expectedList << "FLAGS"; expectedList << "(\\Recent \\Seen)"; expectedList << "UID"; expectedList << "230"; expectedList << "INTERNALDATE"; expectedList << " 1-Nov-2013 13:31:17 +0100"; expectedList << "RFC822.SIZE"; expectedList << "37"; expectedList << "BODY[]"; expectedList << "Date: Fri, 01 Nov 2013 12:31:13 +0000"; expectedList << "body"; } /** * Test parsing of the example command if the complete command is in the buffer */ void testParse() { QByteArray buffer; QBuffer socket(&buffer); socket.open(QBuffer::WriteOnly); QVERIFY(socket.write(completeResponse) != -1); QBuffer readSocket(&buffer); readSocket.open(QBuffer::ReadOnly); ImapStreamParser parser(&readSocket); QVERIFY(parser.availableDataSize() != 0); Response message; QList<Response::Part> *payload = &message.content; QVERIFY(!parser.atCommandEnd()); QVERIFY(parser.hasString()); *payload << Response::Part(parser.readString()); //* QVERIFY(parser.hasString()); *payload << Response::Part(parser.readString()); // 230 QVERIFY(parser.hasString()); *payload << Response::Part(parser.readString()); // FETCH QVERIFY(parser.hasList()); *payload << Response::Part(parser.readParenthesizedList()); QVERIFY(parser.atCommandEnd()); QCOMPARE(message.content.last().toList(), expectedList); } void testLeadingNewline() { /** * Test a the special case when the CRLF after the string octet count, is separated and not initially loaded into the buffer. */ QByteArray buffer; QBuffer socket(&buffer); socket.open(QBuffer::WriteOnly); QVERIFY(socket.write(part1) != -1); QBuffer readSocket(&buffer); readSocket.open(QBuffer::ReadOnly); ImapStreamParser parser(&readSocket); QVERIFY(parser.availableDataSize() != 0); Response message; QList<Response::Part> *payload = &message.content; QVERIFY(!parser.atCommandEnd()); // We wait with writing part2 until the first part is already loaded into the buffer QVERIFY(socket.write(part2) != -1); QVERIFY(parser.hasString()); *payload << Response::Part(parser.readString()); //* QVERIFY(parser.hasString()); *payload << Response::Part(parser.readString()); // 230 QVERIFY(parser.hasString()); *payload << Response::Part(parser.readString()); // FETCH QVERIFY(socket.write(part3) != -1); QVERIFY(socket.write(part4) != -1); QVERIFY(parser.hasList()); *payload << Response::Part(parser.readParenthesizedList()); QVERIFY(parser.atCommandEnd()); } void testNewLineInString() { QByteArray command2; command2 = "* 33 FETCH (FLAGS (\\Recent \\Seen) UID 33 INTERNALDATE \" 1-Nov-2013 18:43:34 +0100\" RFC822.SIZE 1203 BODY[HEADER.FIELDS (TO FROM MESSAGE-ID " "REFERENCES IN-REPLY-TO SUBJECT DATE)] {54}\r\n"; command2 += "Date: Fri, 01 Nov 2013 17:43:29 +0000\n"; command2 += "Subject: uid32\n"; command2 += "\n"; command2 += ")\n\r"; QByteArray buffer; QBuffer socket(&buffer); socket.open(QBuffer::WriteOnly); QVERIFY(socket.write(command2) != -1); QBuffer readSocket(&buffer); readSocket.open(QBuffer::ReadOnly); ImapStreamParser parser(&readSocket); QVERIFY(parser.availableDataSize() != 0); Response message; QList<Response::Part> *payload = &message.content; QVERIFY(!parser.atCommandEnd()); QVERIFY(parser.hasString()); *payload << Response::Part(parser.readString()); //* QVERIFY(parser.hasString()); *payload << Response::Part(parser.readString()); // 33 QVERIFY(parser.hasString()); *payload << Response::Part(parser.readString()); // FETCH QVERIFY(parser.hasList()); *payload << Response::Part(parser.readParenthesizedList()); QVERIFY(parser.atCommandEnd()); } }; QTEST_GUILESS_MAIN(StreamParserTest) #include "streamparsertest.moc" 07070100000039000081A400000000000000000000000166FAD7C000000814000000000000000000000000000000000000004800000000kimap-VERSIONgit.20240930T185424~db1f697/autotests/subscribejobtest.cpp/* SPDX-FileCopyrightText: 2009 Andras Mantia <amantia@kde.org> SPDX-FileCopyrightText: 2010 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com> SPDX-FileContributor: Kevin Ottens <kevin@kdab.com> SPDX-License-Identifier: GPL-2.0-or-later */ #include <QTest> #include "kimap/session.h" #include "kimap/subscribejob.h" #include "kimaptest/fakeserver.h" #include <QTest> class SubscribeJobTest : public QObject { Q_OBJECT private Q_SLOTS: void testSubscribe_data() { QTest::addColumn<QString>("mailbox"); QTest::addColumn<QList<QByteArray>>("scenario"); QList<QByteArray> scenario; scenario << FakeServer::preauth() << "C: A000001 SUBSCRIBE \"INBOX/foo\"" << "S: A000001 OK CREATE completed"; QTest::newRow("good") << "INBOX/foo" << scenario; scenario.clear(); scenario << FakeServer::preauth() << "C: A000001 SUBSCRIBE \"INBOX-FAIL-BAD\"" << "S: A000001 BAD command unknown or arguments invalid"; QTest::newRow("bad") << "INBOX-FAIL-BAD" << scenario; scenario.clear(); scenario << FakeServer::preauth() << "C: A000001 SUBSCRIBE \"INBOX-FAIL-NO\"" << "S: A000001 NO subscribe failure"; QTest::newRow("no") << "INBOX-FAIL-NO" << scenario; } void testSubscribe() { QFETCH(QString, mailbox); QFETCH(QList<QByteArray>, scenario); FakeServer fakeServer; fakeServer.setScenario(scenario); fakeServer.startAndWait(); KIMAP::Session session(QStringLiteral("127.0.0.1"), 5989); auto job = new KIMAP::SubscribeJob(&session); job->setMailBox(mailbox); bool result = job->exec(); QEXPECT_FAIL("bad", "Expected failure on BAD scenario", Continue); QEXPECT_FAIL("no", "Expected failure on NO scenario", Continue); QVERIFY(result); QCOMPARE(job->mailBox(), mailbox); fakeServer.quit(); } }; QTEST_GUILESS_MAIN(SubscribeJobTest) #include "subscribejobtest.moc" 0707010000003A000081A400000000000000000000000166FAD7C000000B4C000000000000000000000000000000000000004500000000kimap-VERSIONgit.20240930T185424~db1f697/autotests/testrfccodecs.cpp/* This file is part of the kimap library. SPDX-FileCopyrightText: 2007 Tom Albers <tomalbers@kde.nl> SPDX-FileCopyrightText: 2007 Allen Winter <winter@kde.org> SPDX-License-Identifier: LGPL-2.0-only */ #include <QTest> #include "testrfccodecs.h" QTEST_GUILESS_MAIN(RFCCodecsTest) #include "rfccodecs.h" using namespace KIMAP; void RFCCodecsTest::testIMAPEncoding() { QString encoded; QString decoded; QByteArray bEncoded; QByteArray bDecoded; encoded = encodeImapFolderName(QString::fromUtf8("Test.Frode Rønning")); QCOMPARE(encoded, QString::fromUtf8("Test.Frode R&APg-nning")); bEncoded = encodeImapFolderName(QString::fromUtf8("Test.Frode Rønning").toUtf8()); QCOMPARE(bEncoded, QString::fromUtf8("Test.Frode R&APg-nning").toUtf8()); decoded = decodeImapFolderName(QString::fromLatin1("Test.Frode R&APg-nning")); QCOMPARE(decoded, QString::fromUtf8("Test.Frode Rønning")); bDecoded = decodeImapFolderName(QString::fromUtf8("Test.Frode Rønning").toUtf8()); QCOMPARE(bDecoded, QString::fromUtf8("Test.Frode Rønning").toUtf8()); encoded = encodeImapFolderName(QString::fromUtf8("Test.tom & jerry")); QCOMPARE(encoded, QString::fromUtf8("Test.tom &- jerry")); bEncoded = encodeImapFolderName(QString::fromUtf8("Test.tom & jerry").toUtf8()); QCOMPARE(bEncoded, QString::fromUtf8("Test.tom &- jerry").toUtf8()); decoded = decodeImapFolderName(QString::fromUtf8("Test.tom &- jerry")); QCOMPARE(decoded, QString::fromUtf8("Test.tom & jerry")); bDecoded = decodeImapFolderName(QString::fromUtf8("Test.tom &- jerry").toUtf8()); QCOMPARE(bDecoded, QString::fromUtf8("Test.tom & jerry").toUtf8()); // Try to feed already encoded encoded = encodeImapFolderName(QString::fromUtf8("Test.Cl&AOE-udio")); QCOMPARE(encoded, QString::fromUtf8("Test.Cl&-AOE-udio")); bEncoded = encodeImapFolderName(QString::fromUtf8("Test.Cl&AOE-udio").toUtf8()); QCOMPARE(bEncoded, QString::fromUtf8("Test.Cl&-AOE-udio").toUtf8()); decoded = decodeImapFolderName(QString::fromUtf8("Test.Cl&-AOE-udio")); QCOMPARE(decoded, QString::fromUtf8("Test.Cl&AOE-udio")); bDecoded = decodeImapFolderName(QString::fromUtf8("Test.Cl&-AOE-udio").toUtf8()); QCOMPARE(bDecoded, QString::fromUtf8("Test.Cl&AOE-udio").toUtf8()); // With UTF8 characters bEncoded = "INBOX/&AOQ- &APY- &APw- @ &IKw-"; QCOMPARE(decodeImapFolderName(bEncoded), QByteArray("INBOX/ä ö ü @ €")); } void RFCCodecsTest::testQuotes() { QString test(QStringLiteral("tom\"allen")); QCOMPARE(quoteIMAP(test), QString::fromLatin1("tom\\\"allen")); test = QStringLiteral("tom\'allen"); QCOMPARE(quoteIMAP(test), QString::fromLatin1("tom\'allen")); test = QStringLiteral("tom\\allen"); QCOMPARE(quoteIMAP(test), QString::fromLatin1("tom\\\\allen")); } #include "moc_testrfccodecs.cpp" 0707010000003B000081A400000000000000000000000166FAD7C000000141000000000000000000000000000000000000004300000000kimap-VERSIONgit.20240930T185424~db1f697/autotests/testrfccodecs.h/* This file is part of the kimap library. SPDX-FileCopyrightText: 2007 Allen Winter <winter@kde.org> SPDX-License-Identifier: LGPL-2.0-or-later */ #pragma once #include <QObject> class RFCCodecsTest : public QObject { Q_OBJECT private Q_SLOTS: void testIMAPEncoding(); void testQuotes(); }; 0707010000003C000081A400000000000000000000000166FAD7C000002E55000000000000000000000000000000000000004300000000kimap-VERSIONgit.20240930T185424~db1f697/autotests/testsession.cpp/* This file is part of the KDE project SPDX-FileCopyrightText: 2008 Kevin Ottens <ervin@kde.org> SPDX-FileCopyrightText: 2010 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com> SPDX-FileContributor: Kevin Ottens <kevin@kdab.com> SPDX-License-Identifier: LGPL-2.0-or-later */ #include <QEventLoop> #include <QObject> #include <QSignalSpy> #include <QTest> #include "job.h" #include "kimaptest/fakeserver.h" #include "kimaptest/mockjob.h" #include "session.h" Q_DECLARE_METATYPE(KIMAP::Session::State) Q_DECLARE_METATYPE(KJob *) class SessionTest : public QObject { Q_OBJECT private Q_SLOTS: void initTestCase() { qRegisterMetaType<KIMAP::Session::State>(); } void shouldStartDisconnected() { FakeServer fakeServer; fakeServer.setScenario(QList<QByteArray>() << FakeServer::greeting()); fakeServer.startAndWait(); KIMAP::Session s(QStringLiteral("127.0.0.1"), 5989); QSignalSpy spy(&s, &KIMAP::Session::stateChanged); QCOMPARE((int)s.state(), (int)KIMAP::Session::Disconnected); QTest::qWait(600); QCOMPARE((int)s.state(), (int)KIMAP::Session::NotAuthenticated); QCOMPARE(spy.count(), 1); // NotAuthenticated QList<QVariant> arguments = spy.takeFirst(); QCOMPARE((int)qvariant_cast<KIMAP::Session::State>(arguments.at(0)), (int)KIMAP::Session::NotAuthenticated); QCOMPARE((int)qvariant_cast<KIMAP::Session::State>(arguments.at(1)), (int)KIMAP::Session::Disconnected); } void shouldFailForInvalidHosts() { KIMAP::Session s(QStringLiteral("0.0.0.0"), 1234); s.setTimeout(1); // 1 second timeout QSignalSpy spyFail(&s, &KIMAP::Session::connectionFailed); QSignalSpy spyLost(&s, &KIMAP::Session::connectionLost); QSignalSpy spyState(&s, &KIMAP::Session::stateChanged); QCOMPARE((int)s.state(), (int)KIMAP::Session::Disconnected); QTest::qWait(500); QCOMPARE((int)s.state(), (int)KIMAP::Session::Disconnected); QCOMPARE(spyFail.count(), 1); QCOMPARE(spyLost.count(), 0); QCOMPARE(spyState.count(), 0); // Wait 800ms more. So now it's 1.3 seconds, check that the socket timeout has correctly been // disabled, and that it hadn't fired unexpectedly. QTest::qWait(800); QCOMPARE(spyFail.count(), 1); } /** Checks that the timeout works when the connection succeeds, but the server doesn't sends anything back to the client. This could happen for example if we connected to a non-IMAP server. */ void shouldTimeoutOnNoGreeting() { FakeServer fakeServer; fakeServer.setScenario(QList<QByteArray>()); fakeServer.startAndWait(); KIMAP::Session s(QStringLiteral("127.0.0.1"), 5989); s.setTimeout(2); QSignalSpy spyFail(&s, &KIMAP::Session::connectionFailed); QSignalSpy spyLost(&s, &KIMAP::Session::connectionLost); QSignalSpy spyState(&s, &KIMAP::Session::stateChanged); QCOMPARE((int)s.state(), (int)KIMAP::Session::Disconnected); // Wait 1.8 second. Since the timeout is set to 2 seconds, the socket should be still // disconnected at this point, yet the connectionFailed() signal shouldn't have been emitted. QTest::qWait(1800); QCOMPARE((int)s.state(), (int)KIMAP::Session::Disconnected); QCOMPARE(spyFail.count(), 0); QCOMPARE(spyLost.count(), 0); QCOMPARE(spyState.count(), 0); // Wait 0.5 second more. Now we are at 2.3 seconds, the socket should have timed out, and the // connectionFailed() signal should have been emitted. QTest::qWait(500); QCOMPARE((int)s.state(), (int)KIMAP::Session::Disconnected); QCOMPARE(spyFail.count(), 0); QCOMPARE(spyLost.count(), 1); QCOMPARE(spyState.count(), 0); } void shouldSupportPreauth() { FakeServer fakeServer; fakeServer.setScenario(QList<QByteArray>() << FakeServer::preauth()); fakeServer.startAndWait(); KIMAP::Session s(QStringLiteral("127.0.0.1"), 5989); QSignalSpy spy(&s, &KIMAP::Session::stateChanged); QCOMPARE((int)s.state(), (int)KIMAP::Session::Disconnected); QTest::qWait(500); QCOMPARE((int)s.state(), (int)KIMAP::Session::Authenticated); QCOMPARE(spy.count(), 1); // Authenticated QList<QVariant> arguments = spy.takeFirst(); QCOMPARE((int)qvariant_cast<KIMAP::Session::State>(arguments.at(0)), (int)KIMAP::Session::Authenticated); QCOMPARE((int)qvariant_cast<KIMAP::Session::State>(arguments.at(1)), (int)KIMAP::Session::Disconnected); } void shouldRespectStartOrder() { FakeServer fakeServer; fakeServer.setScenario(QList<QByteArray>() << FakeServer::greeting()); fakeServer.startAndWait(); KIMAP::Session s(QStringLiteral("127.0.0.1"), 5989); auto j1 = new MockJob(&s); connect(j1, &KJob::result, this, &SessionTest::jobDone); auto j2 = new MockJob(&s); connect(j2, &KJob::result, this, &SessionTest::jobDone); auto j3 = new MockJob(&s); connect(j3, &KJob::result, this, &SessionTest::jobDone); auto j4 = new MockJob(&s); connect(j4, &KJob::result, this, &SessionTest::jobDone); j4->start(); j2->start(); j3->start(); j1->start(); m_expectedCalls = 4; m_eventLoop.exec(); QCOMPARE(m_jobs.size(), 4); QCOMPARE(m_jobs[0], j4); QCOMPARE(m_jobs[1], j2); QCOMPARE(m_jobs[2], j3); QCOMPARE(m_jobs[3], j1); } void shouldManageQueueSize() { FakeServer fakeServer; fakeServer.setScenario(QList<QByteArray>() << FakeServer::greeting()); fakeServer.startAndWait(); KIMAP::Session s(QStringLiteral("127.0.0.1"), 5989); QSignalSpy queueSpy(&s, &KIMAP::Session::jobQueueSizeChanged); QCOMPARE(s.jobQueueSize(), 0); auto j1 = new MockJob(&s); auto j2 = new MockJob(&s); auto j3 = new MockJob(&s); auto j4 = new MockJob(&s); connect(j4, &KJob::result, &m_eventLoop, &QEventLoop::quit); QCOMPARE(s.jobQueueSize(), 0); j1->start(); QCOMPARE(s.jobQueueSize(), 1); QCOMPARE(queueSpy.size(), 1); QCOMPARE(queueSpy.at(0).at(0).toInt(), 1); j2->start(); QCOMPARE(s.jobQueueSize(), 2); QCOMPARE(queueSpy.size(), 2); QCOMPARE(queueSpy.at(1).at(0).toInt(), 2); j3->start(); QCOMPARE(s.jobQueueSize(), 3); QCOMPARE(queueSpy.size(), 3); QCOMPARE(queueSpy.at(2).at(0).toInt(), 3); j4->start(); QCOMPARE(s.jobQueueSize(), 4); QCOMPARE(queueSpy.size(), 4); QCOMPARE(queueSpy.at(3).at(0).toInt(), 4); queueSpy.clear(); m_eventLoop.exec(); QCOMPARE(s.jobQueueSize(), 0); QCOMPARE(queueSpy.at(0).at(0).toInt(), 3); QCOMPARE(queueSpy.at(1).at(0).toInt(), 2); QCOMPARE(queueSpy.at(2).at(0).toInt(), 1); QCOMPARE(queueSpy.at(3).at(0).toInt(), 0); } void shouldTimeoutOnNoReply() { FakeServer fakeServer; fakeServer.setScenario(QList<QByteArray>() << FakeServer::preauth() << "C: A000001 DUMMY" << "S: * DUMMY" << "S: * DUMMY" << "S: * DUMMY" << "S: * DUMMY" << "S: * DUMMY" << "S: * DUMMY" << "S: * DUMMY" << "S: * DUMMY" << "S: * DUMMY" << "S: * DUMMY" << "S: * DUMMY" << "S: * DUMMY" << "S: * DUMMY" // We never get a OK or anything, so the job can't normally complete ); fakeServer.startAndWait(); KIMAP::Session s(QStringLiteral("127.0.0.1"), 5989); QSignalSpy spyFail(&s, &KIMAP::Session::connectionFailed); QSignalSpy spyLost(&s, &KIMAP::Session::connectionLost); QSignalSpy spyState(&s, &KIMAP::Session::stateChanged); auto mock = new MockJob(&s); mock->setCommand("DUMMY"); mock->exec(); // We expect to get an error here due to some timeout QVERIFY(mock->error() != 0); QCOMPARE(spyFail.count(), 0); QCOMPARE(spyLost.count(), 1); QCOMPARE(spyState.count(), 2); // Authenticated, Disconnected } void shouldFailFirstJobOnConnectionFailed() { qRegisterMetaType<KJob *>(); FakeServer fakeServer; fakeServer.setScenario(QList<QByteArray>()); fakeServer.startAndWait(); KIMAP::Session s(QStringLiteral("127.0.0.1"), 5989); s.setTimeout(1); auto j1 = new MockJob(&s); QSignalSpy spyResult1(j1, &KJob::result); QSignalSpy spyDestroyed1(j1, &QObject::destroyed); auto j2 = new MockJob(&s); QSignalSpy spyResult2(j2, &KJob::result); QSignalSpy spyDestroyed2(j2, &QObject::destroyed); auto j3 = new MockJob(&s); QSignalSpy spyResult3(j3, &KJob::result); QSignalSpy spyDestroyed3(j3, &QObject::destroyed); j1->start(); j2->start(); j3->start(); QCOMPARE(s.jobQueueSize(), 3); QTest::qWait(1100); // Check that only the first job has emitted it's result QCOMPARE(spyResult1.count(), 1); QCOMPARE(spyResult2.count(), 0); QCOMPARE(spyResult3.count(), 0); // Check that all jobs have been deleted QCOMPARE(spyDestroyed1.count(), 1); QCOMPARE(spyDestroyed2.count(), 1); QCOMPARE(spyDestroyed3.count(), 1); QCOMPARE(s.jobQueueSize(), 0); } void shouldCloseOnInconsistency() { for (int count = 0; count < 10; count++) { FakeServer fakeServer; fakeServer.setScenario(QList<QByteArray>() << FakeServer::preauth() << "C: A000001 DUMMY" << "S: * DUMMY %" << "S: DUMMY)"); fakeServer.startAndWait(); KIMAP::Session s(QStringLiteral("127.0.0.1"), 5989); QSignalSpy spyFail(&s, &KIMAP::Session::connectionFailed); QSignalSpy spyLost(&s, &KIMAP::Session::connectionLost); QSignalSpy spyState(&s, &KIMAP::Session::stateChanged); auto mock = new MockJob(&s); mock->setTimeout(5000); mock->setCommand("DUMMY"); mock->setAutoDelete(false); mock->start(); QTest::qWait(250); // Should be plenty // We expect to get an error here due to the inconsistency QVERIFY(mock->error() != 0); QCOMPARE(spyFail.count(), 0); QCOMPARE(spyLost.count(), 1); QCOMPARE(spyState.count(), 2); // Authenticated, Disconnected delete mock; } } public Q_SLOTS: void jobDone(KJob *job) { m_jobs << job; if (m_expectedCalls == m_jobs.size()) { m_eventLoop.quit(); } } private: QEventLoop m_eventLoop; int m_expectedCalls; QList<KJob *> m_jobs; }; QTEST_GUILESS_MAIN(SessionTest) #include "testsession.moc" 0707010000003D000081A400000000000000000000000166FAD7C000000845000000000000000000000000000000000000004A00000000kimap-VERSIONgit.20240930T185424~db1f697/autotests/unsubscribejobtest.cpp/* SPDX-FileCopyrightText: 2009 Andras Mantia <amantia@kde.org> SPDX-FileCopyrightText: 2010 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com> SPDX-FileContributor: Kevin Ottens <kevin@kdab.com> SPDX-License-Identifier: GPL-2.0-or-later */ #include <QTest> #include "kimap/session.h" #include "kimap/unsubscribejob.h" #include "kimaptest/fakeserver.h" #include <QTest> class UnsubscribeJobTest : public QObject { Q_OBJECT private Q_SLOTS: void testUnsubscribe_data() { QTest::addColumn<QString>("mailbox"); QTest::addColumn<QList<QByteArray>>("scenario"); QList<QByteArray> scenario; scenario << FakeServer::preauth() << "C: A000001 UNSUBSCRIBE \"#news.comp.mail.mime\"" << "S: A000001 OK UNSUBSCRIBE completed"; QTest::newRow("good") << "#news.comp.mail.mime" << scenario; scenario.clear(); scenario << FakeServer::preauth() << "C: A000001 UNSUBSCRIBE \"INBOX-FAIL-BAD\"" << "S: A000001 BAD command unknown or arguments invalid"; QTest::newRow("bad") << "INBOX-FAIL-BAD" << scenario; scenario.clear(); scenario << FakeServer::preauth() << "C: A000001 UNSUBSCRIBE \"INBOX-FAIL-NO\"" << "S: A000001 NO unsubscribe failure"; QTest::newRow("no") << "INBOX-FAIL-NO" << scenario; } void testUnsubscribe() { QFETCH(QString, mailbox); QFETCH(QList<QByteArray>, scenario); FakeServer fakeServer; fakeServer.setScenario(scenario); fakeServer.startAndWait(); KIMAP::Session session(QStringLiteral("127.0.0.1"), 5989); auto job = new KIMAP::UnsubscribeJob(&session); job->setMailBox(mailbox); bool result = job->exec(); QEXPECT_FAIL("bad", "Expected failure on BAD scenario", Continue); QEXPECT_FAIL("no", "Expected failure on NO scenario", Continue); QVERIFY(result); QCOMPARE(job->mailBox(), mailbox); fakeServer.quit(); } }; QTEST_GUILESS_MAIN(UnsubscribeJobTest) #include "unsubscribejobtest.moc" 0707010000003E000081A400000000000000000000000166FAD7C00000017D000000000000000000000000000000000000003700000000kimap-VERSIONgit.20240930T185424~db1f697/metainfo.yamlfancyname: KIMAP maintainer: dvratil description: A job-based API for interacting with IMAP servers tier: 3 type: functional platforms: - name: Linux - name: FreeBSD - name: Windows - name: macOS portingAid: false deprecated: false release: false libraries: - cmake: "KPim6::Imap" cmakename: KPim6Imap public_lib: true group: kdepim platforms: - name: Linux 0707010000003F000081A400000000000000000000000166FAD7C00000003E000000000000000000000000000000000000003F00000000kimap-VERSIONgit.20240930T185424~db1f697/metainfo.yaml.licenseSPDX-FileCopyrightText: none SPDX-License-Identifier: CC0-1.0 07070100000040000041ED00000000000000000000003866FAD7C000000000000000000000000000000000000000000000002C00000000kimap-VERSIONgit.20240930T185424~db1f697/po07070100000041000041ED00000000000000000000000266FAD7C000000000000000000000000000000000000000000000002F00000000kimap-VERSIONgit.20240930T185424~db1f697/po/ar07070100000042000081A400000000000000000000000166FAD7C000001639000000000000000000000000000000000000003C00000000kimap-VERSIONgit.20240930T185424~db1f697/po/ar/libkimap6.po# Copyright (C) YEAR This file is copyright: # This file is distributed under the same license as the kimap package. # # Zayed Al-Saidi <zayed.alsaidi@gmail.com>, 2022. msgid "" msgstr "" "Project-Id-Version: kimap\n" "Report-Msgid-Bugs-To: https://bugs.kde.org\n" "POT-Creation-Date: 2022-05-11 00:45+0000\n" "PO-Revision-Date: 2022-02-17 19:06+0400\n" "Last-Translator: Zayed Al-Saidi <zayed.alsaidi@gmail.com>\n" "Language-Team: Arabic <kde-l10n-ar@kde.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" #: acljobbase.cpp:56 #, kde-format msgid "AclJobBase" msgstr "AclJobBase" #: appendjob.cpp:40 #, kde-format msgid "Append" msgstr "الإلحاق" #: capabilitiesjob.cpp:35 #, kde-format msgid "Capabilities" msgstr "الإمكانيات" #: closejob.cpp:32 #, kde-format msgid "Close" msgstr "أغلق" #: copyjob.cpp:41 #, kde-format msgid "Copy" msgstr "انسخ" #: createjob.cpp:36 #, kde-format msgid "Create" msgstr "أنشئ" #: deleteacljob.cpp:37 #, kde-format msgid "DeleteAclJob" msgstr "DeleteAclJob" #: deletejob.cpp:36 #, kde-format msgid "Delete" msgstr "احذف" #: enablejob.cpp:31 #, kde-format msgid "Enable" msgstr "مكّن" #: expungejob.cpp:37 #, kde-format msgid "Expunge" msgstr "اشَطَب" #: fetchjob.cpp:97 #, kde-format msgid "Fetch" msgstr "اجلب" #: getacljob.cpp:37 #, kde-format msgid "GetAcl" msgstr "GetAcl" #: getmetadatajob.cpp:43 #, kde-format msgid "GetMetaData" msgstr "GetMetaData" #: getmetadatajob.cpp:66 #, kde-format msgid "GetAnnotation" msgstr "GetAnnotation" #: getquotajob.cpp:35 #, kde-format msgid "GetQuota" msgstr "GetQuota" #: getquotarootjob.cpp:38 #, kde-format msgid "GetQuotaRoot" msgstr "GetQuotaRoot" #: idjob.cpp:35 #, kde-format msgid "Id" msgstr "المعرّف" #: idlejob.cpp:65 #, kde-format msgctxt "name of the idle job" msgid "Idle" msgstr "خاملة" #: job.cpp:19 #, kde-format msgid "Job" msgstr "وظيفة" #: job.cpp:54 loginjob.cpp:574 #, kde-format msgid "Connection to server lost." msgstr "فُقد الاتّصال بالخادوم." #: job.cpp:65 loginjob.cpp:403 setmetadatajob.cpp:126 #, kde-format msgid "%1 failed, malformed reply from the server." msgstr "فشل %1 ، الرد مشوه من الخادم." #: job.cpp:68 loginjob.cpp:277 setmetadatajob.cpp:109 setmetadatajob.cpp:129 #, kde-format msgid "%1 failed, server replied: %2" msgstr "فشل %1، رد الخادم: %2" #: listjob.cpp:59 #, kde-format msgid "List" msgstr "قائمة" #: listrightsjob.cpp:38 #, kde-format msgid "ListRights" msgstr "ListRights" #: loginjob.cpp:129 loginjob.cpp:233 #, kde-format msgid "Login" msgstr "ولوج" #: loginjob.cpp:184 #, kde-format msgid "IMAP session in the wrong state for authentication" msgstr "جلسة IMAP في حالة خاطئة للمصادقة" #: loginjob.cpp:235 #, kde-format msgid "Capability" msgstr "الإمكانية" #: loginjob.cpp:237 #, kde-format msgid "StartTls" msgstr "StartTls" #: loginjob.cpp:340 #, kde-format msgid "STARTTLS is not supported by the server, try using SSL/TLS instead." msgstr "لا يدعم الخادم STARTTLS ، حاول استخدام SSL / TLS بدلاً من ذلك." #: loginjob.cpp:353 #, kde-format msgid "Internal error, tried to login before encryption" msgstr "خطأ داخلي، حاول الولوج قبل التشفير" #: loginjob.cpp:362 #, kde-format msgid "Login failed, plain login is disabled by the server." msgstr "فشل الولوج ، عُطل الولوج البسيط بواسطة الخادم." #: loginjob.cpp:383 #, kde-format msgid "Login failed, authentication mode %1 is not supported by the server." msgstr "فشل الولوج، وضع المصادقة %1 غير معتمد من قبل الخادم." #: loginjob.cpp:413 #, kde-format msgid "Login failed, client cannot initialize the SASL library." msgstr "فشل الولوج، تعذّر على العميل بدء مكتبة SASL." #: loginjob.cpp:512 #, kde-format msgid "Login failed, TLS negotiation failed." msgstr "فشل الولوج، فشل تفاوض SSL." #: loginjob.cpp:570 #, kde-format msgid "SSL handshake failed." msgstr "فشلت عملية تبادل الإشارات SSL." #: logoutjob.cpp:33 #, kde-format msgid "Logout" msgstr "اخرج" #: metadatajobbase.cpp:53 #, kde-format msgid "MetaDataJobBase" msgstr "MetaDataJobBase" #: movejob.cpp:42 #, kde-format msgid "Move" msgstr "انقل" #: myrightsjob.cpp:37 #, kde-format msgid "MyRights" msgstr "MyRights" #: namespacejob.cpp:68 #, kde-format msgid "Namespace" msgstr "نطاق الأسماء" #: quotajobbase.cpp:34 #, kde-format msgid "QuotaJobBase" msgstr "QuotaJobBase" #: renamejob.cpp:37 #, kde-format msgid "Rename" msgstr "غيّر الاسم" #: searchjob.cpp:361 #, kde-format msgctxt "Name of the search job" msgid "Search" msgstr "ابحث" #: selectjob.cpp:73 #, kde-format msgctxt "name of the select job" msgid "Select" msgstr "اختر" #: setacljob.cpp:34 #, kde-format msgid "SetAcl" msgstr "SetAcl" #: setmetadatajob.cpp:43 #, kde-format msgid "SetMetaData" msgstr "SetMetaData" #: setquotajob.cpp:37 #, kde-format msgid "SetQuota" msgstr "SetQuota" #: statusjob.cpp:40 #, kde-format msgctxt "name of the status job" msgid "Status" msgstr "الحالة" #: storejob.cpp:70 #, kde-format msgid "Store" msgstr "احفظ" #: subscribejob.cpp:36 #, kde-format msgid "Subscribe" msgstr "اشترك" #: unsubscribejob.cpp:36 #, kde-format msgid "Unsubscribe" msgstr "أزل الاشتراك" 07070100000043000041ED00000000000000000000000266FAD7C000000000000000000000000000000000000000000000003000000000kimap-VERSIONgit.20240930T185424~db1f697/po/ast07070100000044000081A400000000000000000000000166FAD7C000001180000000000000000000000000000000000000003D00000000kimap-VERSIONgit.20240930T185424~db1f697/po/ast/libkimap6.po# Copyright (C) 2023 This file is copyright: # This file is distributed under the same license as the kimap package. # # SPDX-FileCopyrightText: 2023 Enol P. <enolp@softastur.org> msgid "" msgstr "" "Project-Id-Version: kimap\n" "Report-Msgid-Bugs-To: https://bugs.kde.org\n" "POT-Creation-Date: 2022-05-11 00:45+0000\n" "PO-Revision-Date: 2023-10-25 13:04+0200\n" "Last-Translator: Enol P. <enolp@softastur.org>\n" "Language-Team: \n" "Language: ast\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 23.08.2\n" #: acljobbase.cpp:56 #, kde-format msgid "AclJobBase" msgstr "" #: appendjob.cpp:40 #, kde-format msgid "Append" msgstr "" #: capabilitiesjob.cpp:35 #, kde-format msgid "Capabilities" msgstr "" #: closejob.cpp:32 #, kde-format msgid "Close" msgstr "" #: copyjob.cpp:41 #, kde-format msgid "Copy" msgstr "" #: createjob.cpp:36 #, kde-format msgid "Create" msgstr "" #: deleteacljob.cpp:37 #, kde-format msgid "DeleteAclJob" msgstr "" #: deletejob.cpp:36 #, kde-format msgid "Delete" msgstr "" #: enablejob.cpp:31 #, kde-format msgid "Enable" msgstr "" #: expungejob.cpp:37 #, kde-format msgid "Expunge" msgstr "" #: fetchjob.cpp:97 #, kde-format msgid "Fetch" msgstr "" #: getacljob.cpp:37 #, kde-format msgid "GetAcl" msgstr "" #: getmetadatajob.cpp:43 #, kde-format msgid "GetMetaData" msgstr "" #: getmetadatajob.cpp:66 #, kde-format msgid "GetAnnotation" msgstr "" #: getquotajob.cpp:35 #, kde-format msgid "GetQuota" msgstr "" #: getquotarootjob.cpp:38 #, kde-format msgid "GetQuotaRoot" msgstr "" #: idjob.cpp:35 #, kde-format msgid "Id" msgstr "" #: idlejob.cpp:65 #, kde-format msgctxt "name of the idle job" msgid "Idle" msgstr "" #: job.cpp:19 #, kde-format msgid "Job" msgstr "" #: job.cpp:54 loginjob.cpp:574 #, kde-format msgid "Connection to server lost." msgstr "" #: job.cpp:65 loginjob.cpp:403 setmetadatajob.cpp:126 #, kde-format msgid "%1 failed, malformed reply from the server." msgstr "" #: job.cpp:68 loginjob.cpp:277 setmetadatajob.cpp:109 setmetadatajob.cpp:129 #, kde-format msgid "%1 failed, server replied: %2" msgstr "" #: listjob.cpp:59 #, kde-format msgid "List" msgstr "" #: listrightsjob.cpp:38 #, kde-format msgid "ListRights" msgstr "" #: loginjob.cpp:129 loginjob.cpp:233 #, kde-format msgid "Login" msgstr "" #: loginjob.cpp:184 #, kde-format msgid "IMAP session in the wrong state for authentication" msgstr "" #: loginjob.cpp:235 #, kde-format msgid "Capability" msgstr "" #: loginjob.cpp:237 #, kde-format msgid "StartTls" msgstr "" #: loginjob.cpp:340 #, kde-format msgid "STARTTLS is not supported by the server, try using SSL/TLS instead." msgstr "" #: loginjob.cpp:353 #, kde-format msgid "Internal error, tried to login before encryption" msgstr "" #: loginjob.cpp:362 #, kde-format msgid "Login failed, plain login is disabled by the server." msgstr "" #: loginjob.cpp:383 #, kde-format msgid "Login failed, authentication mode %1 is not supported by the server." msgstr "" #: loginjob.cpp:413 #, kde-format msgid "Login failed, client cannot initialize the SASL library." msgstr "" #: loginjob.cpp:512 #, kde-format msgid "Login failed, TLS negotiation failed." msgstr "" #: loginjob.cpp:570 #, kde-format msgid "SSL handshake failed." msgstr "" #: logoutjob.cpp:33 #, kde-format msgid "Logout" msgstr "" #: metadatajobbase.cpp:53 #, kde-format msgid "MetaDataJobBase" msgstr "" #: movejob.cpp:42 #, kde-format msgid "Move" msgstr "" #: myrightsjob.cpp:37 #, kde-format msgid "MyRights" msgstr "" #: namespacejob.cpp:68 #, kde-format msgid "Namespace" msgstr "" #: quotajobbase.cpp:34 #, kde-format msgid "QuotaJobBase" msgstr "" #: renamejob.cpp:37 #, kde-format msgid "Rename" msgstr "" #: searchjob.cpp:361 #, kde-format msgctxt "Name of the search job" msgid "Search" msgstr "" #: selectjob.cpp:73 #, kde-format msgctxt "name of the select job" msgid "Select" msgstr "" #: setacljob.cpp:34 #, kde-format msgid "SetAcl" msgstr "" #: setmetadatajob.cpp:43 #, kde-format msgid "SetMetaData" msgstr "" #: setquotajob.cpp:37 #, kde-format msgid "SetQuota" msgstr "" #: statusjob.cpp:40 #, kde-format msgctxt "name of the status job" msgid "Status" msgstr "" #: storejob.cpp:70 #, kde-format msgid "Store" msgstr "" #: subscribejob.cpp:36 #, kde-format msgid "Subscribe" msgstr "" #: unsubscribejob.cpp:36 #, kde-format msgid "Unsubscribe" msgstr "" 07070100000045000041ED00000000000000000000000266FAD7C000000000000000000000000000000000000000000000002F00000000kimap-VERSIONgit.20240930T185424~db1f697/po/bs07070100000046000081A400000000000000000000000166FAD7C0000015ED000000000000000000000000000000000000003C00000000kimap-VERSIONgit.20240930T185424~db1f697/po/bs/libkimap6.po# Bosnian translation for kdepimlibs # Copyright (c) 2010 Rosetta Contributors and Canonical Ltd 2010 # This file is distributed under the same license as the kdepimlibs package. # FIRST AUTHOR <EMAIL@ADDRESS>, 2010. # msgid "" msgstr "" "Project-Id-Version: kdepimlibs\n" "Report-Msgid-Bugs-To: https://bugs.kde.org\n" "POT-Creation-Date: 2022-05-11 00:45+0000\n" "PO-Revision-Date: 2012-10-05 17:12+0000\n" "Last-Translator: Launchpad Translations Administrators <Unknown>\n" "Language-Team: Bosnian <bs@li.org>\n" "Language: bs\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Launchpad-Export-Date: 2013-10-19 05:20+0000\n" "X-Generator: Launchpad (build 16807)\n" "Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" "%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" #: acljobbase.cpp:56 #, kde-format msgid "AclJobBase" msgstr "AclJobBase" #: appendjob.cpp:40 #, kde-format msgid "Append" msgstr "Nadodaj" #: capabilitiesjob.cpp:35 #, kde-format msgid "Capabilities" msgstr "Mogućnosti" #: closejob.cpp:32 #, kde-format msgid "Close" msgstr "Zatvori" #: copyjob.cpp:41 #, kde-format msgid "Copy" msgstr "Kopiraj" #: createjob.cpp:36 #, kde-format msgid "Create" msgstr "Kreiraj" #: deleteacljob.cpp:37 #, kde-format msgid "DeleteAclJob" msgstr "DeleteAclJob" #: deletejob.cpp:36 #, kde-format msgid "Delete" msgstr "Obriši" #: enablejob.cpp:31 #, kde-format msgid "Enable" msgstr "" #: expungejob.cpp:37 #, kde-format msgid "Expunge" msgstr "Expunge" #: fetchjob.cpp:97 #, kde-format msgid "Fetch" msgstr "Dobavi" #: getacljob.cpp:37 #, kde-format msgid "GetAcl" msgstr "GetAcl" #: getmetadatajob.cpp:43 #, kde-format msgid "GetMetaData" msgstr "GetMetaData" #: getmetadatajob.cpp:66 #, kde-format msgid "GetAnnotation" msgstr "GetAnnotation" #: getquotajob.cpp:35 #, kde-format msgid "GetQuota" msgstr "GetQuota" #: getquotarootjob.cpp:38 #, kde-format msgid "GetQuotaRoot" msgstr "GetQuotaRoot" #: idjob.cpp:35 #, fuzzy, kde-format #| msgctxt "name of the idle job" #| msgid "Idle" msgid "Id" msgstr "Neaktivan" #: idlejob.cpp:65 #, kde-format msgctxt "name of the idle job" msgid "Idle" msgstr "Neaktivan" #: job.cpp:19 #, kde-format msgid "Job" msgstr "Posao" #: job.cpp:54 loginjob.cpp:574 #, kde-format msgid "Connection to server lost." msgstr "Spajanje na server se izgubilo." #: job.cpp:65 loginjob.cpp:403 setmetadatajob.cpp:126 #, kde-format msgid "%1 failed, malformed reply from the server." msgstr "%1nije uspio, neispravan odgovor od servera." #: job.cpp:68 loginjob.cpp:277 setmetadatajob.cpp:109 setmetadatajob.cpp:129 #, kde-format msgid "%1 failed, server replied: %2" msgstr "%1 nije uspjela, serverj je odgovorio: %2" #: listjob.cpp:59 #, kde-format msgid "List" msgstr "Lista" #: listrightsjob.cpp:38 #, kde-format msgid "ListRights" msgstr "ListRights" #: loginjob.cpp:129 loginjob.cpp:233 #, kde-format msgid "Login" msgstr "Prijava" #: loginjob.cpp:184 #, kde-format msgid "IMAP session in the wrong state for authentication" msgstr "IMAP sesijai u krivom stanju za provjeru autentičnosti" #: loginjob.cpp:235 #, kde-format msgid "Capability" msgstr "Sposobnost" #: loginjob.cpp:237 #, kde-format msgid "StartTls" msgstr "StartTls" #: loginjob.cpp:340 #, kde-format msgid "STARTTLS is not supported by the server, try using SSL/TLS instead." msgstr "" #: loginjob.cpp:353 #, kde-format msgid "Internal error, tried to login before encryption" msgstr "" #: loginjob.cpp:362 #, kde-format msgid "Login failed, plain login is disabled by the server." msgstr "" "Prijava nije uspjela, običan prijava je onemogućena od strane poslužitelja." #: loginjob.cpp:383 #, kde-format msgid "Login failed, authentication mode %1 is not supported by the server." msgstr "" "Prijava nije uspjela, režim provjere autentičnosti %1 nije podržan od " "strane poslužitelja." #: loginjob.cpp:413 #, kde-format msgid "Login failed, client cannot initialize the SASL library." msgstr "Prijava nije uspjela, klijent ne može inicijalizirati SASL biblioteku." #: loginjob.cpp:512 #, kde-format msgid "Login failed, TLS negotiation failed." msgstr "Prijava nije uspjela, TLS pregovaranje nije uspjelo." #: loginjob.cpp:570 #, kde-format msgid "SSL handshake failed." msgstr "" #: logoutjob.cpp:33 #, kde-format msgid "Logout" msgstr "Odjava" #: metadatajobbase.cpp:53 #, kde-format msgid "MetaDataJobBase" msgstr "MetaDataJobBase" #: movejob.cpp:42 #, kde-format msgid "Move" msgstr "" #: myrightsjob.cpp:37 #, kde-format msgid "MyRights" msgstr "MyRights" #: namespacejob.cpp:68 #, kde-format msgid "Namespace" msgstr "Imenski prostor" #: quotajobbase.cpp:34 #, kde-format msgid "QuotaJobBase" msgstr "QuotaJobBase" #: renamejob.cpp:37 #, kde-format msgid "Rename" msgstr "Preimenuj" #: searchjob.cpp:361 #, kde-format msgctxt "Name of the search job" msgid "Search" msgstr "Traži" #: selectjob.cpp:73 #, kde-format msgctxt "name of the select job" msgid "Select" msgstr "Odaberi" #: setacljob.cpp:34 #, kde-format msgid "SetAcl" msgstr "SetAcl" #: setmetadatajob.cpp:43 #, kde-format msgid "SetMetaData" msgstr "SetMetaData" #: setquotajob.cpp:37 #, kde-format msgid "SetQuota" msgstr "SetQuota" #: statusjob.cpp:40 #, kde-format msgctxt "name of the status job" msgid "Status" msgstr "" #: storejob.cpp:70 #, kde-format msgid "Store" msgstr "Pohrani" #: subscribejob.cpp:36 #, kde-format msgid "Subscribe" msgstr "Pretplati se" #: unsubscribejob.cpp:36 #, kde-format msgid "Unsubscribe" msgstr "Otkaži pretplatu" #~ msgid "SetAnnotation" #~ msgstr "SetAnnotation" 07070100000047000041ED00000000000000000000000266FAD7C000000000000000000000000000000000000000000000002F00000000kimap-VERSIONgit.20240930T185424~db1f697/po/ca07070100000048000081A400000000000000000000000166FAD7C00000170E000000000000000000000000000000000000003C00000000kimap-VERSIONgit.20240930T185424~db1f697/po/ca/libkimap6.po# Translation of libkimap6.po to Catalan # Copyright (C) 2009-2022 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. # # Josep M. Ferrer <txemaq@gmail.com>, 2009, 2014, 2016, 2020, 2022. # Manuel Tortosa Moreno <manutortosa@gmail.com>, 2009, 2010. # Antoni Bella Pérez <antonibella5@yahoo.com>, 2014, 2016, 2018, 2020. msgid "" msgstr "" "Project-Id-Version: kimap\n" "Report-Msgid-Bugs-To: https://bugs.kde.org\n" "POT-Creation-Date: 2022-05-11 00:45+0000\n" "PO-Revision-Date: 2022-01-28 09:30+0100\n" "Last-Translator: Josep M. Ferrer <txemaq@gmail.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 20.12.0\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" "X-Accelerator-Marker: &\n" #: acljobbase.cpp:56 #, kde-format msgid "AclJobBase" msgstr "TascaAclBase" #: appendjob.cpp:40 #, kde-format msgid "Append" msgstr "Addició" #: capabilitiesjob.cpp:35 #, kde-format msgid "Capabilities" msgstr "Capacitats" #: closejob.cpp:32 #, kde-format msgid "Close" msgstr "Tanca" #: copyjob.cpp:41 #, kde-format msgid "Copy" msgstr "Copia" #: createjob.cpp:36 #, kde-format msgid "Create" msgstr "Crea" #: deleteacljob.cpp:37 #, kde-format msgid "DeleteAclJob" msgstr "SuprimeixTascaAcl" #: deletejob.cpp:36 #, kde-format msgid "Delete" msgstr "Suprimeix" #: enablejob.cpp:31 #, kde-format msgid "Enable" msgstr "Habilita" #: expungejob.cpp:37 #, kde-format msgid "Expunge" msgstr "Expurga" #: fetchjob.cpp:97 #, kde-format msgid "Fetch" msgstr "Recupera" #: getacljob.cpp:37 #, kde-format msgid "GetAcl" msgstr "ObténAcl" #: getmetadatajob.cpp:43 #, kde-format msgid "GetMetaData" msgstr "ObténMetaDades" #: getmetadatajob.cpp:66 #, kde-format msgid "GetAnnotation" msgstr "ObténAnotació" #: getquotajob.cpp:35 #, kde-format msgid "GetQuota" msgstr "ObténQuota" #: getquotarootjob.cpp:38 #, kde-format msgid "GetQuotaRoot" msgstr "ObténQuotaArrel" #: idjob.cpp:35 #, kde-format msgid "Id" msgstr "ID" #: idlejob.cpp:65 #, kde-format msgctxt "name of the idle job" msgid "Idle" msgstr "Inactiva" #: job.cpp:19 #, kde-format msgid "Job" msgstr "Tasca" #: job.cpp:54 loginjob.cpp:574 #, kde-format msgid "Connection to server lost." msgstr "S'ha perdut la connexió amb el servidor." #: job.cpp:65 loginjob.cpp:403 setmetadatajob.cpp:126 #, kde-format msgid "%1 failed, malformed reply from the server." msgstr "%1 ha fallat, resposta amb format incorrecte des del servidor." #: job.cpp:68 loginjob.cpp:277 setmetadatajob.cpp:109 setmetadatajob.cpp:129 #, kde-format msgid "%1 failed, server replied: %2" msgstr "%1 ha fallat, el servidor ha contestat: %2" #: listjob.cpp:59 #, kde-format msgid "List" msgstr "Llista" #: listrightsjob.cpp:38 #, kde-format msgid "ListRights" msgstr "LlistaDrets" #: loginjob.cpp:129 loginjob.cpp:233 #, kde-format msgid "Login" msgstr "Entrada" #: loginjob.cpp:184 #, kde-format msgid "IMAP session in the wrong state for authentication" msgstr "Sessió IMAP en estat erroni per autenticació" #: loginjob.cpp:235 #, kde-format msgid "Capability" msgstr "Funcionalitats" #: loginjob.cpp:237 #, kde-format msgid "StartTls" msgstr "IniciaTls" #: loginjob.cpp:340 #, kde-format msgid "STARTTLS is not supported by the server, try using SSL/TLS instead." msgstr "STARTTLS no està acceptat pel servidor, proveu amb SSL/TLS." #: loginjob.cpp:353 #, kde-format msgid "Internal error, tried to login before encryption" msgstr "Error intern, s'ha intentat l'entrada abans de l'encriptatge" #: loginjob.cpp:362 #, kde-format msgid "Login failed, plain login is disabled by the server." msgstr "" "Ha fallat l'inici de la sessió, el servidor té desactivada l'entrada " "senzilla." #: loginjob.cpp:383 #, kde-format msgid "Login failed, authentication mode %1 is not supported by the server." msgstr "" "Ha fallat l'inici de la sessió, el servidor té desactivat el mode " "d'autenticació %1." #: loginjob.cpp:413 #, kde-format msgid "Login failed, client cannot initialize the SASL library." msgstr "" "Ha fallat l'inici de la sessió, el client no ha pogut inicialitzar la " "biblioteca SASL." #: loginjob.cpp:512 #, kde-format msgid "Login failed, TLS negotiation failed." msgstr "Ha fallat l'inici de la sessió, ha fallat la negociació TLS." #: loginjob.cpp:570 #, kde-format msgid "SSL handshake failed." msgstr "El protocol inicial de SSL ha fallat." #: logoutjob.cpp:33 #, kde-format msgid "Logout" msgstr "Sortida" #: metadatajobbase.cpp:53 #, kde-format msgid "MetaDataJobBase" msgstr "TascaMetaDadesBase" #: movejob.cpp:42 #, kde-format msgid "Move" msgstr "Mou" #: myrightsjob.cpp:37 #, kde-format msgid "MyRights" msgstr "ElsMeusDrets" # skip-rule: kct-namespace #: namespacejob.cpp:68 #, kde-format msgid "Namespace" msgstr "EspaiDeNom" #: quotajobbase.cpp:34 #, kde-format msgid "QuotaJobBase" msgstr "TascaQuotaBase" #: renamejob.cpp:37 #, kde-format msgid "Rename" msgstr "Reanomena" #: searchjob.cpp:361 #, kde-format msgctxt "Name of the search job" msgid "Search" msgstr "Cerca" #: selectjob.cpp:73 #, kde-format msgctxt "name of the select job" msgid "Select" msgstr "Selecciona" #: setacljob.cpp:34 #, kde-format msgid "SetAcl" msgstr "EstableixAcl" #: setmetadatajob.cpp:43 #, kde-format msgid "SetMetaData" msgstr "EstableixMetaDades" #: setquotajob.cpp:37 #, kde-format msgid "SetQuota" msgstr "EstableixQuota" #: statusjob.cpp:40 #, kde-format msgctxt "name of the status job" msgid "Status" msgstr "Estat" #: storejob.cpp:70 #, kde-format msgid "Store" msgstr "Emmagatzema" #: subscribejob.cpp:36 #, kde-format msgid "Subscribe" msgstr "Subscriu" #: unsubscribejob.cpp:36 #, kde-format msgid "Unsubscribe" msgstr "Cancel·la la subscripció" 07070100000049000041ED00000000000000000000000266FAD7C000000000000000000000000000000000000000000000003800000000kimap-VERSIONgit.20240930T185424~db1f697/po/ca@valencia0707010000004A000081A400000000000000000000000166FAD7C000001754000000000000000000000000000000000000004500000000kimap-VERSIONgit.20240930T185424~db1f697/po/ca@valencia/libkimap6.po# Translation of libkimap6.po to Catalan (Valencian) # Copyright (C) 2009-2022 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. # # Josep M. Ferrer <txemaq@gmail.com>, 2009, 2014, 2016, 2020, 2022. # Manuel Tortosa Moreno <manutortosa@gmail.com>, 2009, 2010. # Antoni Bella Pérez <antonibella5@yahoo.com>, 2014, 2016, 2018, 2020. msgid "" msgstr "" "Project-Id-Version: kimap\n" "Report-Msgid-Bugs-To: https://bugs.kde.org\n" "POT-Creation-Date: 2022-05-11 00:45+0000\n" "PO-Revision-Date: 2022-01-28 09:30+0100\n" "Last-Translator: Josep M. Ferrer <txemaq@gmail.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 20.12.0\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" "X-Accelerator-Marker: &\n" #: acljobbase.cpp:56 #, kde-format msgid "AclJobBase" msgstr "TascaAclBase" #: appendjob.cpp:40 #, kde-format msgid "Append" msgstr "Addició" #: capabilitiesjob.cpp:35 #, kde-format msgid "Capabilities" msgstr "Capacitats" #: closejob.cpp:32 #, kde-format msgid "Close" msgstr "Tanca" #: copyjob.cpp:41 #, kde-format msgid "Copy" msgstr "Copia" #: createjob.cpp:36 #, kde-format msgid "Create" msgstr "Crea" #: deleteacljob.cpp:37 #, kde-format msgid "DeleteAclJob" msgstr "SuprimeixTascaAcl" #: deletejob.cpp:36 #, kde-format msgid "Delete" msgstr "Suprimix" #: enablejob.cpp:31 #, kde-format msgid "Enable" msgstr "Habilita" #: expungejob.cpp:37 #, kde-format msgid "Expunge" msgstr "Expurga" #: fetchjob.cpp:97 #, kde-format msgid "Fetch" msgstr "Recupera" #: getacljob.cpp:37 #, kde-format msgid "GetAcl" msgstr "ObténAcl" #: getmetadatajob.cpp:43 #, kde-format msgid "GetMetaData" msgstr "ObténMetaDades" #: getmetadatajob.cpp:66 #, kde-format msgid "GetAnnotation" msgstr "ObténAnotació" #: getquotajob.cpp:35 #, kde-format msgid "GetQuota" msgstr "ObténQuota" #: getquotarootjob.cpp:38 #, kde-format msgid "GetQuotaRoot" msgstr "ObténQuotaArrel" #: idjob.cpp:35 #, kde-format msgid "Id" msgstr "ID" #: idlejob.cpp:65 #, kde-format msgctxt "name of the idle job" msgid "Idle" msgstr "Inactiva" #: job.cpp:19 #, kde-format msgid "Job" msgstr "Tasca" #: job.cpp:54 loginjob.cpp:574 #, kde-format msgid "Connection to server lost." msgstr "S'ha perdut la connexió amb el servidor." #: job.cpp:65 loginjob.cpp:403 setmetadatajob.cpp:126 #, kde-format msgid "%1 failed, malformed reply from the server." msgstr "%1 ha fallat, resposta amb format incorrecte des del servidor." #: job.cpp:68 loginjob.cpp:277 setmetadatajob.cpp:109 setmetadatajob.cpp:129 #, kde-format msgid "%1 failed, server replied: %2" msgstr "%1 ha fallat, el servidor ha contestat: %2" #: listjob.cpp:59 #, kde-format msgid "List" msgstr "Llista" #: listrightsjob.cpp:38 #, kde-format msgid "ListRights" msgstr "LlistaDrets" #: loginjob.cpp:129 loginjob.cpp:233 #, kde-format msgid "Login" msgstr "Entrada" #: loginjob.cpp:184 #, kde-format msgid "IMAP session in the wrong state for authentication" msgstr "Sessió IMAP en estat erroni per autenticació" #: loginjob.cpp:235 #, kde-format msgid "Capability" msgstr "Funcionalitats" #: loginjob.cpp:237 #, kde-format msgid "StartTls" msgstr "IniciaTls" #: loginjob.cpp:340 #, kde-format msgid "STARTTLS is not supported by the server, try using SSL/TLS instead." msgstr "STARTTLS no està acceptat pel servidor, proveu amb SSL/TLS." #: loginjob.cpp:353 #, kde-format msgid "Internal error, tried to login before encryption" msgstr "" "S'ha produït un error intern, s'ha intentat l'entrada abans de l'encriptació" #: loginjob.cpp:362 #, kde-format msgid "Login failed, plain login is disabled by the server." msgstr "" "No s'ha pogut fer l'inici de la sessió, el servidor té desactivada l'entrada " "senzilla." #: loginjob.cpp:383 #, kde-format msgid "Login failed, authentication mode %1 is not supported by the server." msgstr "" "No s'ha pogut fer l'inici de la sessió, el servidor té desactivat el mode " "d'autenticació %1." #: loginjob.cpp:413 #, kde-format msgid "Login failed, client cannot initialize the SASL library." msgstr "" "No s'ha pogut fer l'inici de la sessió, el client no ha pogut restablir la " "biblioteca SASL." #: loginjob.cpp:512 #, kde-format msgid "Login failed, TLS negotiation failed." msgstr "No s'ha pogut fer l'inici de la sessió, ha fallat la negociació TLS." #: loginjob.cpp:570 #, kde-format msgid "SSL handshake failed." msgstr "El protocol inicial de SSL ha fallat." #: logoutjob.cpp:33 #, kde-format msgid "Logout" msgstr "Eixida" #: metadatajobbase.cpp:53 #, kde-format msgid "MetaDataJobBase" msgstr "TascaMetaDadesBase" #: movejob.cpp:42 #, kde-format msgid "Move" msgstr "Mou" #: myrightsjob.cpp:37 #, kde-format msgid "MyRights" msgstr "ElsMeusDrets" # skip-rule: kct-namespace #: namespacejob.cpp:68 #, kde-format msgid "Namespace" msgstr "EspaiDeNom" #: quotajobbase.cpp:34 #, kde-format msgid "QuotaJobBase" msgstr "TascaQuotaBase" #: renamejob.cpp:37 #, kde-format msgid "Rename" msgstr "Canvia el nom" #: searchjob.cpp:361 #, kde-format msgctxt "Name of the search job" msgid "Search" msgstr "Busca" #: selectjob.cpp:73 #, kde-format msgctxt "name of the select job" msgid "Select" msgstr "Selecciona" #: setacljob.cpp:34 #, kde-format msgid "SetAcl" msgstr "EstablixAcl" #: setmetadatajob.cpp:43 #, kde-format msgid "SetMetaData" msgstr "EstablixMetaDades" #: setquotajob.cpp:37 #, kde-format msgid "SetQuota" msgstr "EstablixQuota" #: statusjob.cpp:40 #, kde-format msgctxt "name of the status job" msgid "Status" msgstr "Estat" #: storejob.cpp:70 #, kde-format msgid "Store" msgstr "Emmagatzema" #: subscribejob.cpp:36 #, kde-format msgid "Subscribe" msgstr "Subscriu" #: unsubscribejob.cpp:36 #, kde-format msgid "Unsubscribe" msgstr "Cancel·la la subscripció" 0707010000004B000041ED00000000000000000000000266FAD7C000000000000000000000000000000000000000000000002F00000000kimap-VERSIONgit.20240930T185424~db1f697/po/cs0707010000004C000081A400000000000000000000000166FAD7C0000015B1000000000000000000000000000000000000003C00000000kimap-VERSIONgit.20240930T185424~db1f697/po/cs/libkimap6.po# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # Lukáš Tinkl <ltinkl@redhat.com>, 2010. # Vít Pelčák <vit@pelcak.org>, 2011, 2014, 2016. # Vit Pelcak <vit@pelcak.org>, 2022. # msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: https://bugs.kde.org\n" "POT-Creation-Date: 2022-05-11 00:45+0000\n" "PO-Revision-Date: 2022-01-31 16:34+0100\n" "Last-Translator: Vit Pelcak <vpelcak@suse.cz>\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 21.12.1\n" #: acljobbase.cpp:56 #, kde-format msgid "AclJobBase" msgstr "AclJobBase" #: appendjob.cpp:40 #, kde-format msgid "Append" msgstr "Přidání" #: capabilitiesjob.cpp:35 #, kde-format msgid "Capabilities" msgstr "Možnosti" #: closejob.cpp:32 #, kde-format msgid "Close" msgstr "Zavřít" #: copyjob.cpp:41 #, kde-format msgid "Copy" msgstr "Kopírovat" #: createjob.cpp:36 #, kde-format msgid "Create" msgstr "Vytvořit" #: deleteacljob.cpp:37 #, kde-format msgid "DeleteAclJob" msgstr "DeleteAclJob" #: deletejob.cpp:36 #, kde-format msgid "Delete" msgstr "Smazat" #: enablejob.cpp:31 #, kde-format msgid "Enable" msgstr "Povolit" #: expungejob.cpp:37 #, kde-format msgid "Expunge" msgstr "Zničit" #: fetchjob.cpp:97 #, kde-format msgid "Fetch" msgstr "Stáhnout" #: getacljob.cpp:37 #, kde-format msgid "GetAcl" msgstr "GetAcl" #: getmetadatajob.cpp:43 #, kde-format msgid "GetMetaData" msgstr "GetMetaData" #: getmetadatajob.cpp:66 #, kde-format msgid "GetAnnotation" msgstr "GetAnnotation" #: getquotajob.cpp:35 #, kde-format msgid "GetQuota" msgstr "GetQuota" #: getquotarootjob.cpp:38 #, kde-format msgid "GetQuotaRoot" msgstr "GetQuotaRoot" #: idjob.cpp:35 #, kde-format msgid "Id" msgstr "Id" #: idlejob.cpp:65 #, kde-format msgctxt "name of the idle job" msgid "Idle" msgstr "Nečinný" #: job.cpp:19 #, kde-format msgid "Job" msgstr "Úloha" #: job.cpp:54 loginjob.cpp:574 #, kde-format msgid "Connection to server lost." msgstr "Spojení se serverem bylo ztraceno." #: job.cpp:65 loginjob.cpp:403 setmetadatajob.cpp:126 #, kde-format msgid "%1 failed, malformed reply from the server." msgstr "Metoda '%1' selhala, chybná odpověď ze serveru." #: job.cpp:68 loginjob.cpp:277 setmetadatajob.cpp:109 setmetadatajob.cpp:129 #, kde-format msgid "%1 failed, server replied: %2" msgstr "Metoda '%1' selhala, server odpověděl: %2" #: listjob.cpp:59 #, kde-format msgid "List" msgstr "Seznam" #: listrightsjob.cpp:38 #, kde-format msgid "ListRights" msgstr "ListRights" #: loginjob.cpp:129 loginjob.cpp:233 #, kde-format msgid "Login" msgstr "Přihlášení" #: loginjob.cpp:184 #, kde-format msgid "IMAP session in the wrong state for authentication" msgstr "Sezení IMAP v neplatném stavu ověření" #: loginjob.cpp:235 #, kde-format msgid "Capability" msgstr "Možnost" #: loginjob.cpp:237 #, kde-format msgid "StartTls" msgstr "StartTls" #: loginjob.cpp:340 #, kde-format msgid "STARTTLS is not supported by the server, try using SSL/TLS instead." msgstr "Server nepodporuje STARTTLS. Zkuste použít SSL/TLS." #: loginjob.cpp:353 #, kde-format msgid "Internal error, tried to login before encryption" msgstr "Vnitřní chyba. Pokus o přihlášení před šifrováním" #: loginjob.cpp:362 #, kde-format msgid "Login failed, plain login is disabled by the server." msgstr "Přihlášení selhalo, přihlášení prostým textem je na serveru zakázáno." #: loginjob.cpp:383 #, kde-format msgid "Login failed, authentication mode %1 is not supported by the server." msgstr "Přihlášení selhalo, ověřovací režim %1 není serverem podporován." #: loginjob.cpp:413 #, kde-format msgid "Login failed, client cannot initialize the SASL library." msgstr "Přihlášení selhalo, klient nemůže inicializovat SASL knihovnu." #: loginjob.cpp:512 #, kde-format msgid "Login failed, TLS negotiation failed." msgstr "Přihlášení selhalo, komunikace v TLS selhala." #: loginjob.cpp:570 #, kde-format msgid "SSL handshake failed." msgstr "Handshake SSL selhal." #: logoutjob.cpp:33 #, kde-format msgid "Logout" msgstr "Odhlášení" #: metadatajobbase.cpp:53 #, kde-format msgid "MetaDataJobBase" msgstr "MetaDataJobBase" #: movejob.cpp:42 #, kde-format msgid "Move" msgstr "Přesunout" #: myrightsjob.cpp:37 #, kde-format msgid "MyRights" msgstr "MyRights" #: namespacejob.cpp:68 #, kde-format msgid "Namespace" msgstr "Jmenný prostor" #: quotajobbase.cpp:34 #, kde-format msgid "QuotaJobBase" msgstr "QuotaJobBase" #: renamejob.cpp:37 #, kde-format msgid "Rename" msgstr "Přejmenovat" #: searchjob.cpp:361 #, kde-format msgctxt "Name of the search job" msgid "Search" msgstr "Vyhledat" #: selectjob.cpp:73 #, kde-format msgctxt "name of the select job" msgid "Select" msgstr "Vybrat" #: setacljob.cpp:34 #, kde-format msgid "SetAcl" msgstr "SetAcl" #: setmetadatajob.cpp:43 #, kde-format msgid "SetMetaData" msgstr "SetMetaData" #: setquotajob.cpp:37 #, kde-format msgid "SetQuota" msgstr "SetQuota" #: statusjob.cpp:40 #, kde-format msgctxt "name of the status job" msgid "Status" msgstr "Stav" #: storejob.cpp:70 #, kde-format msgid "Store" msgstr "Uložit" #: subscribejob.cpp:36 #, kde-format msgid "Subscribe" msgstr "Zaregistrovat" #: unsubscribejob.cpp:36 #, kde-format msgid "Unsubscribe" msgstr "Odhlásit se" 0707010000004D000041ED00000000000000000000000266FAD7C000000000000000000000000000000000000000000000002F00000000kimap-VERSIONgit.20240930T185424~db1f697/po/da0707010000004E000081A400000000000000000000000166FAD7C0000016AA000000000000000000000000000000000000003C00000000kimap-VERSIONgit.20240930T185424~db1f697/po/da/libkimap6.po# Copyright (C) YEAR This_file_is_part_of_KDE # This file is distributed under the same license as the PACKAGE package. # # Martin Schlander <mschlander@opensuse.org>, 2009, 2010, 2014, 2016, 2017, 2020, 2022. msgid "" msgstr "" "Project-Id-Version: libkimap\n" "Report-Msgid-Bugs-To: https://bugs.kde.org\n" "POT-Creation-Date: 2022-05-11 00:45+0000\n" "PO-Revision-Date: 2022-02-08 19:44+0100\n" "Last-Translator: Martin Schlander <mschlander@opensuse.org>\n" "Language-Team: Danish <kde-i18n-doc@kde.org>\n" "Language: da\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Generator: Lokalize 20.04.2\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" #: acljobbase.cpp:56 #, kde-format msgid "AclJobBase" msgstr "AclJobBase" #: appendjob.cpp:40 #, kde-format msgid "Append" msgstr "Tilføj" #: capabilitiesjob.cpp:35 #, kde-format msgid "Capabilities" msgstr "Kapabiliteter" #: closejob.cpp:32 #, kde-format msgid "Close" msgstr "Luk" #: copyjob.cpp:41 #, kde-format msgid "Copy" msgstr "Kopiér" #: createjob.cpp:36 #, kde-format msgid "Create" msgstr "Opret" #: deleteacljob.cpp:37 #, kde-format msgid "DeleteAclJob" msgstr "DeleteAclJob" #: deletejob.cpp:36 #, kde-format msgid "Delete" msgstr "Slet" #: enablejob.cpp:31 #, kde-format msgid "Enable" msgstr "Aktivér" #: expungejob.cpp:37 #, kde-format msgid "Expunge" msgstr "Udslet" #: fetchjob.cpp:97 #, kde-format msgid "Fetch" msgstr "Hent" #: getacljob.cpp:37 #, kde-format msgid "GetAcl" msgstr "GetAcl" #: getmetadatajob.cpp:43 #, kde-format msgid "GetMetaData" msgstr "GetMetaData" #: getmetadatajob.cpp:66 #, kde-format msgid "GetAnnotation" msgstr "GetAnnotation" #: getquotajob.cpp:35 #, kde-format msgid "GetQuota" msgstr "GetQuota" #: getquotarootjob.cpp:38 #, kde-format msgid "GetQuotaRoot" msgstr "GetQuotaRoot" #: idjob.cpp:35 #, kde-format msgid "Id" msgstr "Id" #: idlejob.cpp:65 #, kde-format msgctxt "name of the idle job" msgid "Idle" msgstr "Inaktiv" #: job.cpp:19 #, kde-format msgid "Job" msgstr "Job" #: job.cpp:54 loginjob.cpp:574 #, kde-format msgid "Connection to server lost." msgstr "Mistede forbindelse til serveren." #: job.cpp:65 loginjob.cpp:403 setmetadatajob.cpp:126 #, kde-format msgid "%1 failed, malformed reply from the server." msgstr "%1 mislykkedes, ukorrekt svar fra serveren." #: job.cpp:68 loginjob.cpp:277 setmetadatajob.cpp:109 setmetadatajob.cpp:129 #, kde-format msgid "%1 failed, server replied: %2" msgstr "%1 mislykkedes, serveren svarede: %2" #: listjob.cpp:59 #, kde-format msgid "List" msgstr "Liste" #: listrightsjob.cpp:38 #, kde-format msgid "ListRights" msgstr "ListRights" #: loginjob.cpp:129 loginjob.cpp:233 #, kde-format msgid "Login" msgstr "Login" #: loginjob.cpp:184 #, kde-format msgid "IMAP session in the wrong state for authentication" msgstr "IMAP-session i forkert tilstand til autentificering" #: loginjob.cpp:235 #, kde-format msgid "Capability" msgstr "Kapabilitet" #: loginjob.cpp:237 #, kde-format msgid "StartTls" msgstr "StartTls" #: loginjob.cpp:340 #, kde-format msgid "STARTTLS is not supported by the server, try using SSL/TLS instead." msgstr "" "STARTTLS understøttes ikke af serveren, prøv at bruge SSL/TLS i stedet." #: loginjob.cpp:353 #, kde-format msgid "Internal error, tried to login before encryption" msgstr "Intern fejl, prøvede at logge ind før kryptering" #: loginjob.cpp:362 #, kde-format msgid "Login failed, plain login is disabled by the server." msgstr "Login mislykkedes, almindeligt login er deaktiveret af serveren." #: loginjob.cpp:383 #, kde-format msgid "Login failed, authentication mode %1 is not supported by the server." msgstr "" "Login mislykkedes, godkendelsestilstanden %1 er ikke understøttet af " "serveren." #: loginjob.cpp:413 #, kde-format msgid "Login failed, client cannot initialize the SASL library." msgstr "Login mislykkedes, klienten kan ikke initialisers SASL-biblioteket." #: loginjob.cpp:512 #, kde-format msgid "Login failed, TLS negotiation failed." msgstr "Login mislykkedes, TLS-forhandling mislykkedes." #: loginjob.cpp:570 #, kde-format msgid "SSL handshake failed." msgstr "SSL-håndtryk mislykkedes." #: logoutjob.cpp:33 #, kde-format msgid "Logout" msgstr "Log af" #: metadatajobbase.cpp:53 #, kde-format msgid "MetaDataJobBase" msgstr "MetaDataJobBase" #: movejob.cpp:42 #, kde-format msgid "Move" msgstr "Flyt" #: myrightsjob.cpp:37 #, kde-format msgid "MyRights" msgstr "MyRights" #: namespacejob.cpp:68 #, kde-format msgid "Namespace" msgstr "Navnerum" #: quotajobbase.cpp:34 #, kde-format msgid "QuotaJobBase" msgstr "QuotaJobBase" #: renamejob.cpp:37 #, kde-format msgid "Rename" msgstr "Omdøb" #: searchjob.cpp:361 #, kde-format msgctxt "Name of the search job" msgid "Search" msgstr "Søg" #: selectjob.cpp:73 #, kde-format msgctxt "name of the select job" msgid "Select" msgstr "Vælg" #: setacljob.cpp:34 #, kde-format msgid "SetAcl" msgstr "SetAcl" #: setmetadatajob.cpp:43 #, kde-format msgid "SetMetaData" msgstr "SetMetaData" #: setquotajob.cpp:37 #, kde-format msgid "SetQuota" msgstr "SetQuota" #: statusjob.cpp:40 #, kde-format msgctxt "name of the status job" msgid "Status" msgstr "Status" #: storejob.cpp:70 #, kde-format msgid "Store" msgstr "Opbevar" #: subscribejob.cpp:36 #, kde-format msgid "Subscribe" msgstr "Abonnér" #: unsubscribejob.cpp:36 #, kde-format msgid "Unsubscribe" msgstr "Afmeld" #~ msgid "SetAnnotation" #~ msgstr "SetAnnotation" #~ msgctxt "NAME OF TRANSLATORS" #~ msgid "Your names" #~ msgstr "Martin Schlander" #~ msgctxt "EMAIL OF TRANSLATORS" #~ msgid "Your emails" #~ msgstr "mschlander@opensuse.org" #, fuzzy #~| msgid "Create" #~ msgctxt "Authentication method" #~ msgid "Clear text" #~ msgstr "Opret" #~ msgid "Check" #~ msgstr "Tjek" 0707010000004F000041ED00000000000000000000000266FAD7C000000000000000000000000000000000000000000000002F00000000kimap-VERSIONgit.20240930T185424~db1f697/po/de07070100000050000081A400000000000000000000000166FAD7C0000017E5000000000000000000000000000000000000003C00000000kimap-VERSIONgit.20240930T185424~db1f697/po/de/libkimap6.po# Burkhard Lück <lueck@hube-lueck.de>, 2009, 2013, 2016, 2018, 2021. # Frederik Schwarzer <schwarzer@kde.org>, 2009, 2010, 2011, 2016, 2022. # Thomas Reitelbach <tr@erdfunkstelle.de>, 2009. # Johannes Obermayr <johannesobermayr@gmx.de>, 2010. msgid "" msgstr "" "Project-Id-Version: libkimap6\n" "Report-Msgid-Bugs-To: https://bugs.kde.org\n" "POT-Creation-Date: 2022-05-11 00:45+0000\n" "PO-Revision-Date: 2022-06-15 11:31+0200\n" "Last-Translator: Frederik Schwarzer <schwarzer@kde.org>\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" "X-Generator: Lokalize 22.04.1\n" #: acljobbase.cpp:56 #, kde-format msgid "AclJobBase" msgstr "AclJobBase" #: appendjob.cpp:40 #, kde-format msgid "Append" msgstr "Anhängen" #: capabilitiesjob.cpp:35 #, kde-format msgid "Capabilities" msgstr "Fähigkeiten" #: closejob.cpp:32 #, kde-format msgid "Close" msgstr "Schließen" #: copyjob.cpp:41 #, kde-format msgid "Copy" msgstr "Kopieren" #: createjob.cpp:36 #, kde-format msgid "Create" msgstr "Erstellen" #: deleteacljob.cpp:37 #, kde-format msgid "DeleteAclJob" msgstr "DeleteAclJob" #: deletejob.cpp:36 #, kde-format msgid "Delete" msgstr "Löschen" #: enablejob.cpp:31 #, kde-format msgid "Enable" msgstr "Aktivieren" #: expungejob.cpp:37 #, kde-format msgid "Expunge" msgstr "Löschen" #: fetchjob.cpp:97 #, kde-format msgid "Fetch" msgstr "Abholen" #: getacljob.cpp:37 #, kde-format msgid "GetAcl" msgstr "GetAcl" #: getmetadatajob.cpp:43 #, kde-format msgid "GetMetaData" msgstr "GetMetaData" #: getmetadatajob.cpp:66 #, kde-format msgid "GetAnnotation" msgstr "GetAnnotation" #: getquotajob.cpp:35 #, kde-format msgid "GetQuota" msgstr "GetQuota" #: getquotarootjob.cpp:38 #, kde-format msgid "GetQuotaRoot" msgstr "GetQuotaRoot" #: idjob.cpp:35 #, kde-format msgid "Id" msgstr "Kennung" #: idlejob.cpp:65 #, kde-format msgctxt "name of the idle job" msgid "Idle" msgstr "Leerlauf" #: job.cpp:19 #, kde-format msgid "Job" msgstr "Job" #: job.cpp:54 loginjob.cpp:574 #, kde-format msgid "Connection to server lost." msgstr "Die Verbindung zum Server ist abgebrochen." #: job.cpp:65 loginjob.cpp:403 setmetadatajob.cpp:126 #, kde-format msgid "%1 failed, malformed reply from the server." msgstr "%1 fehlgeschlagen, fehlerhafte Antwort vom Server erhalten." #: job.cpp:68 loginjob.cpp:277 setmetadatajob.cpp:109 setmetadatajob.cpp:129 #, kde-format msgid "%1 failed, server replied: %2" msgstr "%1 fehlgeschlagen, die Serverantwort lautet: %2" #: listjob.cpp:59 #, kde-format msgid "List" msgstr "Liste" #: listrightsjob.cpp:38 #, kde-format msgid "ListRights" msgstr "ListRights" #: loginjob.cpp:129 loginjob.cpp:233 #, kde-format msgid "Login" msgstr "Anmeldung" #: loginjob.cpp:184 #, kde-format msgid "IMAP session in the wrong state for authentication" msgstr "" "Die IMAP-Sitzung befindet sich in einem unzulässigen Status für die " "Authentifizierung." #: loginjob.cpp:235 #, kde-format msgid "Capability" msgstr "Fähigkeiten" #: loginjob.cpp:237 #, kde-format msgid "StartTls" msgstr "StartTls" #: loginjob.cpp:340 #, kde-format msgid "STARTTLS is not supported by the server, try using SSL/TLS instead." msgstr "" "STARTTLS wird vom Server nicht unterstützt, benutzen Sie stattdessen SSL/TLS." #: loginjob.cpp:353 #, kde-format msgid "Internal error, tried to login before encryption" msgstr "Interner Fehler. Anmeldeversuch vor Verschlüsselung." #: loginjob.cpp:362 #, kde-format msgid "Login failed, plain login is disabled by the server." msgstr "" "Anmeldung fehlgeschlagen, PLAIN-Anmeldung wird von diesem Server abgelehnt." #: loginjob.cpp:383 #, kde-format msgid "Login failed, authentication mode %1 is not supported by the server." msgstr "" "Anmeldung fehlgeschlagen, die Authentifizierungsmethode %1 wird vom Server " "nicht unterstützt." #: loginjob.cpp:413 #, kde-format msgid "Login failed, client cannot initialize the SASL library." msgstr "" "Anmeldung fehlgeschlagen, die SASL-Bibliothek kann nicht initialisiert " "werden." #: loginjob.cpp:512 #, kde-format msgid "Login failed, TLS negotiation failed." msgstr "Anmeldung fehlgeschlagen, TLS-Aushandlung fehlgeschlagen." #: loginjob.cpp:570 #, kde-format msgid "SSL handshake failed." msgstr "SSL-Protokollaushandlung ist fehlgeschlagen." #: logoutjob.cpp:33 #, kde-format msgid "Logout" msgstr "Abmelden" #: metadatajobbase.cpp:53 #, kde-format msgid "MetaDataJobBase" msgstr "MetaDataJobBase" #: movejob.cpp:42 #, kde-format msgid "Move" msgstr "Verschieben" #: myrightsjob.cpp:37 #, kde-format msgid "MyRights" msgstr "MyRights" #: namespacejob.cpp:68 #, kde-format msgid "Namespace" msgstr "Namensraum" #: quotajobbase.cpp:34 #, kde-format msgid "QuotaJobBase" msgstr "QuotaJobBase" #: renamejob.cpp:37 #, kde-format msgid "Rename" msgstr "Umbenennen" #: searchjob.cpp:361 #, kde-format msgctxt "Name of the search job" msgid "Search" msgstr "Suche" #: selectjob.cpp:73 #, kde-format msgctxt "name of the select job" msgid "Select" msgstr "Auswählen" #: setacljob.cpp:34 #, kde-format msgid "SetAcl" msgstr "SetAcl" #: setmetadatajob.cpp:43 #, kde-format msgid "SetMetaData" msgstr "SetMetaData" #: setquotajob.cpp:37 #, kde-format msgid "SetQuota" msgstr "SetQuota" #: statusjob.cpp:40 #, kde-format msgctxt "name of the status job" msgid "Status" msgstr "Status" #: storejob.cpp:70 #, kde-format msgid "Store" msgstr "Speichern" #: subscribejob.cpp:36 #, kde-format msgid "Subscribe" msgstr "Abonnieren" #: unsubscribejob.cpp:36 #, kde-format msgid "Unsubscribe" msgstr "Kündigen" #~ msgid "SetAnnotation" #~ msgstr "SetAnnotation" #~ msgctxt "NAME OF TRANSLATORS" #~ msgid "Your names" #~ msgstr "Thomas Reitelbach" #~ msgctxt "EMAIL OF TRANSLATORS" #~ msgid "Your emails" #~ msgstr "tr@erdfunkstelle.de" #~ msgctxt "Authentication method" #~ msgid "Clear text" #~ msgstr "Klartext" #~ msgctxt "Authentication method" #~ msgid "Anonymous" #~ msgstr "Anonymer Login" #~ msgid "Check" #~ msgstr "Prüfen" 07070100000051000041ED00000000000000000000000266FAD7C000000000000000000000000000000000000000000000002F00000000kimap-VERSIONgit.20240930T185424~db1f697/po/el07070100000052000081A400000000000000000000000166FAD7C000001B2A000000000000000000000000000000000000003C00000000kimap-VERSIONgit.20240930T185424~db1f697/po/el/libkimap6.po# Copyright (C) YEAR This_file_is_part_of_KDE # This file is distributed under the same license as the PACKAGE package. # # Toussis Manolis <manolis@koppermind.homelinux.org>, 2009. # Stelios <sstavra@gmail.com>, 2012, 2020, 2021. # Dimitrios Glentadakis <dglent@gmail.com>, 2012. # Dimitris Kardarakos <dimkard@gmail.com>, 2014. msgid "" msgstr "" "Project-Id-Version: libkimap\n" "Report-Msgid-Bugs-To: https://bugs.kde.org\n" "POT-Creation-Date: 2022-05-11 00:45+0000\n" "PO-Revision-Date: 2021-06-16 18:08+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" #: acljobbase.cpp:56 #, kde-format msgid "AclJobBase" msgstr "AclJobBase" #: appendjob.cpp:40 #, kde-format msgid "Append" msgstr "Εισαγωγή" #: capabilitiesjob.cpp:35 #, kde-format msgid "Capabilities" msgstr "Δυνατότητες" #: closejob.cpp:32 #, kde-format msgid "Close" msgstr "Κλείσιμο" #: copyjob.cpp:41 #, kde-format msgid "Copy" msgstr "Αντιγραφή" #: createjob.cpp:36 #, kde-format msgid "Create" msgstr "Δημιουργία" #: deleteacljob.cpp:37 #, kde-format msgid "DeleteAclJob" msgstr "DeleteAclJob" #: deletejob.cpp:36 #, kde-format msgid "Delete" msgstr "Διαγραφή" #: enablejob.cpp:31 #, kde-format msgid "Enable" msgstr "Ενεργοποίηση" #: expungejob.cpp:37 #, kde-format msgid "Expunge" msgstr "Σβήσιμο" #: fetchjob.cpp:97 #, kde-format msgid "Fetch" msgstr "Ανάκτηση" #: getacljob.cpp:37 #, kde-format msgid "GetAcl" msgstr "GetAcl" #: getmetadatajob.cpp:43 #, kde-format msgid "GetMetaData" msgstr "Λήψη μεταδεδομένων" #: getmetadatajob.cpp:66 #, kde-format msgid "GetAnnotation" msgstr "Λήψη σημείωσης" #: getquotajob.cpp:35 #, kde-format msgid "GetQuota" msgstr "Λήψη Quota" #: getquotarootjob.cpp:38 #, kde-format msgid "GetQuotaRoot" msgstr "Λήψη βάσης Quota" #: idjob.cpp:35 #, kde-format msgid "Id" msgstr "Id" #: idlejob.cpp:65 #, kde-format msgctxt "name of the idle job" msgid "Idle" msgstr "Αδρανής" #: job.cpp:19 #, kde-format msgid "Job" msgstr "Εργασία" #: job.cpp:54 loginjob.cpp:574 #, kde-format msgid "Connection to server lost." msgstr "Η σύνδεση με τον εξυπηρετητή έχει χαθεί." #: job.cpp:65 loginjob.cpp:403 setmetadatajob.cpp:126 #, kde-format msgid "%1 failed, malformed reply from the server." msgstr "Αποτυχία %1, μη έγκυρη απάντηση από τον εξυπηρετητή." #: job.cpp:68 loginjob.cpp:277 setmetadatajob.cpp:109 setmetadatajob.cpp:129 #, kde-format msgid "%1 failed, server replied: %2" msgstr "Αποτυχία %1, απάντηση εξυπηρετητή: %2" #: listjob.cpp:59 #, kde-format msgid "List" msgstr "Λίστα" #: listrightsjob.cpp:38 #, kde-format msgid "ListRights" msgstr "Λίστα δικαιωμάτων" #: loginjob.cpp:129 loginjob.cpp:233 #, kde-format msgid "Login" msgstr "Σύνδεση" #: loginjob.cpp:184 #, kde-format msgid "IMAP session in the wrong state for authentication" msgstr "IMAP συνεδρία σε λάθος κατάσταση για την ταυτοποίηση" #: loginjob.cpp:235 #, kde-format msgid "Capability" msgstr "Δυνατότητα" #: loginjob.cpp:237 #, kde-format msgid "StartTls" msgstr "StartTls" #: loginjob.cpp:340 #, kde-format msgid "STARTTLS is not supported by the server, try using SSL/TLS instead." msgstr "" "Το STARTTLS δεν υποστηρίζεται από τον εξυπηρετητή, δοκιμάστε το SSL/TLS." #: loginjob.cpp:353 #, kde-format msgid "Internal error, tried to login before encryption" msgstr "" #: loginjob.cpp:362 #, kde-format msgid "Login failed, plain login is disabled by the server." msgstr "" "Αποτυχία σύνδεσης, η σύνδεση απλού κειμένου είναι απενεργοποιημένη από τον " "εξυπηρετητή." #: loginjob.cpp:383 #, kde-format msgid "Login failed, authentication mode %1 is not supported by the server." msgstr "" "Αποτυχία σύνδεσης, η μέθοδος ταυτοποίησης %1 δεν υποστηρίζεται από τον " "εξυπηρετητή." #: loginjob.cpp:413 #, kde-format msgid "Login failed, client cannot initialize the SASL library." msgstr "" "Αποτυχία σύνδεσης, ο πελάτης δεν μπορεί να αρχικοποιήσει τη βιβλιοθήκη SASL." #: loginjob.cpp:512 #, kde-format msgid "Login failed, TLS negotiation failed." msgstr "Αποτυχία σύνδεσης, αποτυχία διαπραγμάτευσης TLS." #: loginjob.cpp:570 #, kde-format msgid "SSL handshake failed." msgstr "Αποτυχία χειραψίας SSL." #: logoutjob.cpp:33 #, kde-format msgid "Logout" msgstr "Αποσύνδεση" #: metadatajobbase.cpp:53 #, kde-format msgid "MetaDataJobBase" msgstr "MetaDataJobBase" #: movejob.cpp:42 #, kde-format msgid "Move" msgstr "Μετακίνηση" #: myrightsjob.cpp:37 #, kde-format msgid "MyRights" msgstr "Τα δικαιώματά μου" #: namespacejob.cpp:68 #, kde-format msgid "Namespace" msgstr "Χώρος ονομάτων" #: quotajobbase.cpp:34 #, kde-format msgid "QuotaJobBase" msgstr "QuotaJobBase" #: renamejob.cpp:37 #, kde-format msgid "Rename" msgstr "Μετονομασία" #: searchjob.cpp:361 #, kde-format msgctxt "Name of the search job" msgid "Search" msgstr "Αναζήτηση" #: selectjob.cpp:73 #, kde-format msgctxt "name of the select job" msgid "Select" msgstr "Επιλογή" #: setacljob.cpp:34 #, kde-format msgid "SetAcl" msgstr "ΟρισμόςAcl" #: setmetadatajob.cpp:43 #, kde-format msgid "SetMetaData" msgstr "Ορισμός μεταδεδομένων" #: setquotajob.cpp:37 #, kde-format msgid "SetQuota" msgstr "ΟρισμόςQuota" #: statusjob.cpp:40 #, kde-format msgctxt "name of the status job" msgid "Status" msgstr "Κατάσταση" #: storejob.cpp:70 #, kde-format msgid "Store" msgstr "Αποθήκευση" #: subscribejob.cpp:36 #, kde-format msgid "Subscribe" msgstr "Εγγραφή" #: unsubscribejob.cpp:36 #, kde-format msgid "Unsubscribe" msgstr "Διαγραφή" #~ msgid "SetAnnotation" #~ msgstr "Ορισμός σημείωσης" #~ msgid "Mock" #~ msgstr "Mock" #~ msgctxt "NAME OF TRANSLATORS" #~ msgid "Your names" #~ msgstr "Τούσης Μανώλης" #~ msgctxt "EMAIL OF TRANSLATORS" #~ msgid "Your emails" #~ msgstr "manolis@koppermind.homelinux.org" #, fuzzy #~| msgid "Create" #~ msgctxt "Authentication method" #~ msgid "Clear text" #~ msgstr "Δημιουργία" #~ msgid "Check" #~ msgstr "Έλεγχος" #~ msgid "Noop" #~ msgstr "Καμία λειτουργία" 07070100000053000041ED00000000000000000000000266FAD7C000000000000000000000000000000000000000000000003200000000kimap-VERSIONgit.20240930T185424~db1f697/po/en_GB07070100000054000081A400000000000000000000000166FAD7C000001538000000000000000000000000000000000000003F00000000kimap-VERSIONgit.20240930T185424~db1f697/po/en_GB/libkimap6.po# 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>, 2014, 2016, 2018, 2020, 2022. msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: https://bugs.kde.org\n" "POT-Creation-Date: 2022-05-11 00:45+0000\n" "PO-Revision-Date: 2022-02-19 11:52+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 21.12.1\n" #: acljobbase.cpp:56 #, kde-format msgid "AclJobBase" msgstr "AclJobBase" #: appendjob.cpp:40 #, kde-format msgid "Append" msgstr "Append" #: capabilitiesjob.cpp:35 #, kde-format msgid "Capabilities" msgstr "Capabilities" #: closejob.cpp:32 #, kde-format msgid "Close" msgstr "Close" #: copyjob.cpp:41 #, kde-format msgid "Copy" msgstr "Copy" #: createjob.cpp:36 #, kde-format msgid "Create" msgstr "Create" #: deleteacljob.cpp:37 #, kde-format msgid "DeleteAclJob" msgstr "DeleteAclJob" #: deletejob.cpp:36 #, kde-format msgid "Delete" msgstr "Delete" #: enablejob.cpp:31 #, kde-format msgid "Enable" msgstr "Enable" #: expungejob.cpp:37 #, kde-format msgid "Expunge" msgstr "Expunge" #: fetchjob.cpp:97 #, kde-format msgid "Fetch" msgstr "Fetch" #: getacljob.cpp:37 #, kde-format msgid "GetAcl" msgstr "GetAcl" #: getmetadatajob.cpp:43 #, kde-format msgid "GetMetaData" msgstr "GetMetaData" #: getmetadatajob.cpp:66 #, kde-format msgid "GetAnnotation" msgstr "GetAnnotation" #: getquotajob.cpp:35 #, kde-format msgid "GetQuota" msgstr "GetQuota" #: getquotarootjob.cpp:38 #, kde-format msgid "GetQuotaRoot" msgstr "GetQuotaRoot" #: idjob.cpp:35 #, kde-format msgid "Id" msgstr "ID" #: idlejob.cpp:65 #, kde-format msgctxt "name of the idle job" msgid "Idle" msgstr "Idle" #: job.cpp:19 #, kde-format msgid "Job" msgstr "Job" #: job.cpp:54 loginjob.cpp:574 #, kde-format msgid "Connection to server lost." msgstr "Connection to server lost." #: job.cpp:65 loginjob.cpp:403 setmetadatajob.cpp:126 #, kde-format msgid "%1 failed, malformed reply from the server." msgstr "%1 failed, malformed reply from the server." #: job.cpp:68 loginjob.cpp:277 setmetadatajob.cpp:109 setmetadatajob.cpp:129 #, kde-format msgid "%1 failed, server replied: %2" msgstr "%1 failed, server replied: %2" #: listjob.cpp:59 #, kde-format msgid "List" msgstr "List" #: listrightsjob.cpp:38 #, kde-format msgid "ListRights" msgstr "ListRights" #: loginjob.cpp:129 loginjob.cpp:233 #, kde-format msgid "Login" msgstr "Login" #: loginjob.cpp:184 #, kde-format msgid "IMAP session in the wrong state for authentication" msgstr "IMAP session in the wrong state for authentication" #: loginjob.cpp:235 #, kde-format msgid "Capability" msgstr "Capability" #: loginjob.cpp:237 #, kde-format msgid "StartTls" msgstr "StartTls" #: loginjob.cpp:340 #, kde-format msgid "STARTTLS is not supported by the server, try using SSL/TLS instead." msgstr "STARTTLS is not supported by the server, try using SSL/TLS instead." #: loginjob.cpp:353 #, kde-format msgid "Internal error, tried to login before encryption" msgstr "Internal error, tried to login before encryption" #: loginjob.cpp:362 #, kde-format msgid "Login failed, plain login is disabled by the server." msgstr "Login failed, plain login is disabled by the server." #: loginjob.cpp:383 #, kde-format msgid "Login failed, authentication mode %1 is not supported by the server." msgstr "Login failed, authentication mode %1 is not supported by the server." #: loginjob.cpp:413 #, kde-format msgid "Login failed, client cannot initialize the SASL library." msgstr "Login failed, client cannot initialise the SASL library." #: loginjob.cpp:512 #, kde-format msgid "Login failed, TLS negotiation failed." msgstr "Login failed, TLS negotiation failed." #: loginjob.cpp:570 #, kde-format msgid "SSL handshake failed." msgstr "SSL handshake failed." #: logoutjob.cpp:33 #, kde-format msgid "Logout" msgstr "Logout" #: metadatajobbase.cpp:53 #, kde-format msgid "MetaDataJobBase" msgstr "MetaDataJobBase" #: movejob.cpp:42 #, kde-format msgid "Move" msgstr "Move" #: myrightsjob.cpp:37 #, kde-format msgid "MyRights" msgstr "MyRights" #: namespacejob.cpp:68 #, kde-format msgid "Namespace" msgstr "Namespace" #: quotajobbase.cpp:34 #, kde-format msgid "QuotaJobBase" msgstr "QuotaJobBase" #: renamejob.cpp:37 #, kde-format msgid "Rename" msgstr "Rename" #: searchjob.cpp:361 #, kde-format msgctxt "Name of the search job" msgid "Search" msgstr "Search" #: selectjob.cpp:73 #, kde-format msgctxt "name of the select job" msgid "Select" msgstr "Select" #: setacljob.cpp:34 #, kde-format msgid "SetAcl" msgstr "SetAcl" #: setmetadatajob.cpp:43 #, kde-format msgid "SetMetaData" msgstr "SetMetaData" #: setquotajob.cpp:37 #, kde-format msgid "SetQuota" msgstr "SetQuota" #: statusjob.cpp:40 #, kde-format msgctxt "name of the status job" msgid "Status" msgstr "Status" #: storejob.cpp:70 #, kde-format msgid "Store" msgstr "Store" #: subscribejob.cpp:36 #, kde-format msgid "Subscribe" msgstr "Subscribe" #: unsubscribejob.cpp:36 #, kde-format msgid "Unsubscribe" msgstr "Unsubscribe" #~ msgid "SetAnnotation" #~ msgstr "SetAnnotation" #~ msgid "Mock" #~ msgstr "Mock" 07070100000055000041ED00000000000000000000000266FAD7C000000000000000000000000000000000000000000000002F00000000kimap-VERSIONgit.20240930T185424~db1f697/po/eo07070100000056000081A400000000000000000000000166FAD7C000001554000000000000000000000000000000000000003C00000000kimap-VERSIONgit.20240930T185424~db1f697/po/eo/libkimap6.po# Translation of libkimap into esperanto. # mesaĝoj por "kimap" # Copyright (C) 2009 Free Software Foundation, Inc. # Axel Rousseau <axel@esperanto-jeunes.org>, 2009. # Oliver Kellogg <olivermkellogg@gmail.com>, 2023. # msgid "" msgstr "" "Project-Id-Version: libkimap\n" "Report-Msgid-Bugs-To: https://bugs.kde.org\n" "POT-Creation-Date: 2022-05-11 00:45+0000\n" "PO-Revision-Date: 2023-09-23 12:31+0100\n" "Last-Translator: Oliver Kellogg <olivermkellogg@gmail.com>\n" "Language-Team: esperanto <kde-i18n-eo@kde.org>\n" "Language: eo\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Generator: pology\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" #: acljobbase.cpp:56 #, kde-format msgid "AclJobBase" msgstr "AclJobBase" #: appendjob.cpp:40 #, kde-format msgid "Append" msgstr "Aldoni" #: capabilitiesjob.cpp:35 #, kde-format msgid "Capabilities" msgstr "Kapabloj" #: closejob.cpp:32 #, kde-format msgid "Close" msgstr "Fermi" #: copyjob.cpp:41 #, kde-format msgid "Copy" msgstr "Kopii" #: createjob.cpp:36 #, kde-format msgid "Create" msgstr "Krei" #: deleteacljob.cpp:37 #, kde-format msgid "DeleteAclJob" msgstr "DeleteAclJob" #: deletejob.cpp:36 #, kde-format msgid "Delete" msgstr "Forigi" #: enablejob.cpp:31 #, kde-format msgid "Enable" msgstr "Ebligi" #: expungejob.cpp:37 #, kde-format msgid "Expunge" msgstr "Forigi" #: fetchjob.cpp:97 #, kde-format msgid "Fetch" msgstr "Elŝuti" #: getacljob.cpp:37 #, kde-format msgid "GetAcl" msgstr "GetAcl" #: getmetadatajob.cpp:43 #, kde-format msgid "GetMetaData" msgstr "GetMetaData" #: getmetadatajob.cpp:66 #, kde-format msgid "GetAnnotation" msgstr "GetAnnotation" #: getquotajob.cpp:35 #, kde-format msgid "GetQuota" msgstr "GetQuota" #: getquotarootjob.cpp:38 #, kde-format msgid "GetQuotaRoot" msgstr "GetQuotaRoot" #: idjob.cpp:35 #, kde-format msgid "Id" msgstr "Id" #: idlejob.cpp:65 #, kde-format msgctxt "name of the idle job" msgid "Idle" msgstr "Senokupa" #: job.cpp:19 #, kde-format msgid "Job" msgstr "Tasko" #: job.cpp:54 loginjob.cpp:574 #, kde-format msgid "Connection to server lost." msgstr "Perdis konekton al servilo." #: job.cpp:65 loginjob.cpp:403 setmetadatajob.cpp:126 #, kde-format msgid "%1 failed, malformed reply from the server." msgstr "%1 malsukcesis, misformita respondo de servilo." #: job.cpp:68 loginjob.cpp:277 setmetadatajob.cpp:109 setmetadatajob.cpp:129 #, kde-format msgid "%1 failed, server replied: %2" msgstr "%1 malsukcesis, servilo respondis: %2" #: listjob.cpp:59 #, kde-format msgid "List" msgstr "Listo" #: listrightsjob.cpp:38 #, kde-format msgid "ListRights" msgstr "ListPermesoj" #: loginjob.cpp:129 loginjob.cpp:233 #, kde-format msgid "Login" msgstr "Ensaluto" #: loginjob.cpp:184 #, kde-format msgid "IMAP session in the wrong state for authentication" msgstr "IMAP-seanco estas en la malĝusta stato por aŭtentigo" #: loginjob.cpp:235 #, kde-format msgid "Capability" msgstr "Kapablo" #: loginjob.cpp:237 #, kde-format msgid "StartTls" msgstr "StartTls" #: loginjob.cpp:340 #, kde-format msgid "STARTTLS is not supported by the server, try using SSL/TLS instead." msgstr "" "STARTTLS ne estas subtenata fare de la servilo, provu uzi SSL/TLS anstataŭe." #: loginjob.cpp:353 #, kde-format msgid "Internal error, tried to login before encryption" msgstr "Interna eraro, provis ensaluti antaŭ ĉifrado" #: loginjob.cpp:362 #, kde-format msgid "Login failed, plain login is disabled by the server." msgstr "Ensaluto malsukcesis, plata ensaluto estas malŝaltita de la servilo" #: loginjob.cpp:383 #, kde-format msgid "Login failed, authentication mode %1 is not supported by the server." msgstr "" "Ensaluto malsukcesis, aŭtentiga reĝimo %1 ne estas subtenata de la servilo." #: loginjob.cpp:413 #, kde-format msgid "Login failed, client cannot initialize the SASL library." msgstr "" "Ensaluto malsukcesis, kliento ne povas pravalorigi la SASL-bibliotekon." #: loginjob.cpp:512 #, kde-format msgid "Login failed, TLS negotiation failed." msgstr "Ensaluto malsukcesis, TLS-intertraktado malsukcesis." #: loginjob.cpp:570 #, kde-format msgid "SSL handshake failed." msgstr "SSL-kvitanco malsukcesis." #: logoutjob.cpp:33 #, kde-format msgid "Logout" msgstr "Elsaluti" #: metadatajobbase.cpp:53 #, kde-format msgid "MetaDataJobBase" msgstr "MetaDataJobBase" #: movejob.cpp:42 #, kde-format msgid "Move" msgstr "Movi" #: myrightsjob.cpp:37 #, kde-format msgid "MyRights" msgstr "MiajPermesoj" #: namespacejob.cpp:68 #, kde-format msgid "Namespace" msgstr "Nomospaco" #: quotajobbase.cpp:34 #, kde-format msgid "QuotaJobBase" msgstr "QuotaJobBase" #: renamejob.cpp:37 #, kde-format msgid "Rename" msgstr "Alinomi" #: searchjob.cpp:361 #, kde-format msgctxt "Name of the search job" msgid "Search" msgstr "Serĉi" #: selectjob.cpp:73 #, kde-format msgctxt "name of the select job" msgid "Select" msgstr "Elekti" #: setacljob.cpp:34 #, kde-format msgid "SetAcl" msgstr "SetAcl" #: setmetadatajob.cpp:43 #, kde-format msgid "SetMetaData" msgstr "SetMetaData" #: setquotajob.cpp:37 #, kde-format msgid "SetQuota" msgstr "SetQuota" #: statusjob.cpp:40 #, kde-format msgctxt "name of the status job" msgid "Status" msgstr "Stato" #: storejob.cpp:70 #, kde-format msgid "Store" msgstr "Konservi" #: subscribejob.cpp:36 #, kde-format msgid "Subscribe" msgstr "Subskribi" #: unsubscribejob.cpp:36 #, kde-format msgid "Unsubscribe" msgstr "Malaboni" 07070100000057000041ED00000000000000000000000266FAD7C000000000000000000000000000000000000000000000002F00000000kimap-VERSIONgit.20240930T185424~db1f697/po/es07070100000058000081A400000000000000000000000166FAD7C000001715000000000000000000000000000000000000003C00000000kimap-VERSIONgit.20240930T185424~db1f697/po/es/libkimap6.po# translation of libkimap.po to Spanish # Copyright (C) YEAR This_file_is_part_of_KDE # This file is distributed under the same license as the PACKAGE package. # # Dario Andres Rodriguez <andresbajotierra@gmail.com>, 2009. # Eloy Cuadra <ecuadra@eloihr.net>, 2009, 2010, 2020, 2022. # Cristina Yenyxe Gonzalez Garcia <the.blue.valkyrie@gmail.com>, 2009. # Adrián Martínez <sfxgt3@gmail.com>, 2010. # Javier Vinal <fjvinal@gmail.com>, 2011, 2012, 2013, 2014, 2016, 2018. msgid "" msgstr "" "Project-Id-Version: libkimap\n" "Report-Msgid-Bugs-To: https://bugs.kde.org\n" "POT-Creation-Date: 2022-05-11 00:45+0000\n" "PO-Revision-Date: 2022-01-28 23:55+0100\n" "Last-Translator: Eloy Cuadra <ecuadra@eloihr.net>\n" "Language-Team: Spanish <kde-l10n-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: Lokalize 21.12.1\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" #: acljobbase.cpp:56 #, kde-format msgid "AclJobBase" msgstr "AclJobBase" #: appendjob.cpp:40 #, kde-format msgid "Append" msgstr "Añadir" #: capabilitiesjob.cpp:35 #, kde-format msgid "Capabilities" msgstr "Capacidades" #: closejob.cpp:32 #, kde-format msgid "Close" msgstr "Cerrar" #: copyjob.cpp:41 #, kde-format msgid "Copy" msgstr "Copiar" #: createjob.cpp:36 #, kde-format msgid "Create" msgstr "Crear" #: deleteacljob.cpp:37 #, kde-format msgid "DeleteAclJob" msgstr "DeleteAclJob" #: deletejob.cpp:36 #, kde-format msgid "Delete" msgstr "Borrar" #: enablejob.cpp:31 #, kde-format msgid "Enable" msgstr "Activar" #: expungejob.cpp:37 #, kde-format msgid "Expunge" msgstr "Expurgar" #: fetchjob.cpp:97 #, kde-format msgid "Fetch" msgstr "Obtener" #: getacljob.cpp:37 #, kde-format msgid "GetAcl" msgstr "GetAcl" #: getmetadatajob.cpp:43 #, kde-format msgid "GetMetaData" msgstr "GetMetaData" #: getmetadatajob.cpp:66 #, kde-format msgid "GetAnnotation" msgstr "GetAnnotation" #: getquotajob.cpp:35 #, kde-format msgid "GetQuota" msgstr "GetQuota" #: getquotarootjob.cpp:38 #, kde-format msgid "GetQuotaRoot" msgstr "GetQuotaRoot" #: idjob.cpp:35 #, kde-format msgid "Id" msgstr "Id" #: idlejob.cpp:65 #, kde-format msgctxt "name of the idle job" msgid "Idle" msgstr "Inactivo" #: job.cpp:19 #, kde-format msgid "Job" msgstr "Trabajo" #: job.cpp:54 loginjob.cpp:574 #, kde-format msgid "Connection to server lost." msgstr "Se ha perdido la conexión con el servidor." #: job.cpp:65 loginjob.cpp:403 setmetadatajob.cpp:126 #, kde-format msgid "%1 failed, malformed reply from the server." msgstr "%1 ha fallado: respuesta no válida del servidor." #: job.cpp:68 loginjob.cpp:277 setmetadatajob.cpp:109 setmetadatajob.cpp:129 #, kde-format msgid "%1 failed, server replied: %2" msgstr "%1 ha fallado. El servidor ha respondido: %2" #: listjob.cpp:59 #, kde-format msgid "List" msgstr "Lista" #: listrightsjob.cpp:38 #, kde-format msgid "ListRights" msgstr "ListRights" #: loginjob.cpp:129 loginjob.cpp:233 #, kde-format msgid "Login" msgstr "Iniciar sesión" #: loginjob.cpp:184 #, kde-format msgid "IMAP session in the wrong state for authentication" msgstr "La sesión IMAP no está en estado correcto para autenticarse" #: loginjob.cpp:235 #, kde-format msgid "Capability" msgstr "Capacidad" #: loginjob.cpp:237 #, kde-format msgid "StartTls" msgstr "StartTls" #: loginjob.cpp:340 #, kde-format msgid "STARTTLS is not supported by the server, try using SSL/TLS instead." msgstr "" "STARTTLS no está implementado en el servidor: intente usar SSL/TLS en su " "lugar." #: loginjob.cpp:353 #, kde-format msgid "Internal error, tried to login before encryption" msgstr "Error interno: se ha intentado iniciar sesión antes de cifrar." #: loginjob.cpp:362 #, kde-format msgid "Login failed, plain login is disabled by the server." msgstr "" "El inicio de sesión ha fallado: el inicio de sesión sencillo está " "desactivado en este servidor." #: loginjob.cpp:383 #, kde-format msgid "Login failed, authentication mode %1 is not supported by the server." msgstr "" "El inicio de sesión ha fallado: el servidor no permite el modo de " "autenticación %1." #: loginjob.cpp:413 #, kde-format msgid "Login failed, client cannot initialize the SASL library." msgstr "" "El inicio de sesión ha fallado: el cliente no ha podido inicializar la " "biblioteca SASL." #: loginjob.cpp:512 #, kde-format msgid "Login failed, TLS negotiation failed." msgstr "El inicio de sesión ha fallado: la negociación TLS ha fallado." #: loginjob.cpp:570 #, kde-format msgid "SSL handshake failed." msgstr "El diálogo SSL ha fallado." #: logoutjob.cpp:33 #, kde-format msgid "Logout" msgstr "Cerrar sesión" #: metadatajobbase.cpp:53 #, kde-format msgid "MetaDataJobBase" msgstr "MetaDataJobBase" #: movejob.cpp:42 #, kde-format msgid "Move" msgstr "Mover" #: myrightsjob.cpp:37 #, kde-format msgid "MyRights" msgstr "MyRights" #: namespacejob.cpp:68 #, kde-format msgid "Namespace" msgstr "Espacio de nombres" #: quotajobbase.cpp:34 #, kde-format msgid "QuotaJobBase" msgstr "QuotaJobBase" #: renamejob.cpp:37 #, kde-format msgid "Rename" msgstr "Cambiar de nombre" #: searchjob.cpp:361 #, kde-format msgctxt "Name of the search job" msgid "Search" msgstr "Buscar" #: selectjob.cpp:73 #, kde-format msgctxt "name of the select job" msgid "Select" msgstr "Seleccionar" #: setacljob.cpp:34 #, kde-format msgid "SetAcl" msgstr "SetAcl" #: setmetadatajob.cpp:43 #, kde-format msgid "SetMetaData" msgstr "SetMetaData" #: setquotajob.cpp:37 #, kde-format msgid "SetQuota" msgstr "SetQuota" #: statusjob.cpp:40 #, kde-format msgctxt "name of the status job" msgid "Status" msgstr "Estado" #: storejob.cpp:70 #, kde-format msgid "Store" msgstr "Almacenar" #: subscribejob.cpp:36 #, kde-format msgid "Subscribe" msgstr "Suscribirse" #: unsubscribejob.cpp:36 #, kde-format msgid "Unsubscribe" msgstr "Cancelar suscripción" 07070100000059000041ED00000000000000000000000266FAD7C000000000000000000000000000000000000000000000002F00000000kimap-VERSIONgit.20240930T185424~db1f697/po/et0707010000005A000081A400000000000000000000000166FAD7C000001676000000000000000000000000000000000000003C00000000kimap-VERSIONgit.20240930T185424~db1f697/po/et/libkimap6.po# translation of libkimap.po to Estonian # Copyright (C) YEAR This_file_is_part_of_KDE # This file is distributed under the same license as the PACKAGE package. # # Marek Laane <bald@smail.ee>, 2009, 2010, 2014, 2016, 2019. msgid "" msgstr "" "Project-Id-Version: libkimap\n" "Report-Msgid-Bugs-To: https://bugs.kde.org\n" "POT-Creation-Date: 2022-05-11 00:45+0000\n" "PO-Revision-Date: 2019-11-17 00:57+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" "X-Generator: Lokalize 19.08.1\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" #: acljobbase.cpp:56 #, kde-format msgid "AclJobBase" msgstr "AclJobBase" #: appendjob.cpp:40 #, kde-format msgid "Append" msgstr "Lisa" #: capabilitiesjob.cpp:35 #, kde-format msgid "Capabilities" msgstr "Omadused" #: closejob.cpp:32 #, kde-format msgid "Close" msgstr "Sulge" #: copyjob.cpp:41 #, kde-format msgid "Copy" msgstr "Kopeeri" #: createjob.cpp:36 #, kde-format msgid "Create" msgstr "Loo" #: deleteacljob.cpp:37 #, kde-format msgid "DeleteAclJob" msgstr "DeleteAclJob" #: deletejob.cpp:36 #, kde-format msgid "Delete" msgstr "Kustuta" #: enablejob.cpp:31 #, kde-format msgid "Enable" msgstr "" #: expungejob.cpp:37 #, kde-format msgid "Expunge" msgstr "Eemalda" #: fetchjob.cpp:97 #, kde-format msgid "Fetch" msgstr "Tõmba" #: getacljob.cpp:37 #, kde-format msgid "GetAcl" msgstr "GetAcl" #: getmetadatajob.cpp:43 #, kde-format msgid "GetMetaData" msgstr "GetMetaData" #: getmetadatajob.cpp:66 #, kde-format msgid "GetAnnotation" msgstr "GetAnnotation" #: getquotajob.cpp:35 #, kde-format msgid "GetQuota" msgstr "GetQuota" #: getquotarootjob.cpp:38 #, kde-format msgid "GetQuotaRoot" msgstr "GetQuotaRoot" #: idjob.cpp:35 #, kde-format msgid "Id" msgstr "ID" #: idlejob.cpp:65 #, kde-format msgctxt "name of the idle job" msgid "Idle" msgstr "Jõude" #: job.cpp:19 #, kde-format msgid "Job" msgstr "Töö" #: job.cpp:54 loginjob.cpp:574 #, kde-format msgid "Connection to server lost." msgstr "Ühendus serveriga kadus." #: job.cpp:65 loginjob.cpp:403 setmetadatajob.cpp:126 #, kde-format msgid "%1 failed, malformed reply from the server." msgstr "%1 nurjus, serverist saadi vigane vastus." #: job.cpp:68 loginjob.cpp:277 setmetadatajob.cpp:109 setmetadatajob.cpp:129 #, kde-format msgid "%1 failed, server replied: %2" msgstr "%1 nurjus, server vastas: %2" #: listjob.cpp:59 #, kde-format msgid "List" msgstr "Nimekiri" #: listrightsjob.cpp:38 #, kde-format msgid "ListRights" msgstr "ListRights" #: loginjob.cpp:129 loginjob.cpp:233 #, kde-format msgid "Login" msgstr "Sisselogimine" #: loginjob.cpp:184 #, kde-format msgid "IMAP session in the wrong state for authentication" msgstr "IMAP seanss on autentimiseks vales olekus" #: loginjob.cpp:235 #, kde-format msgid "Capability" msgstr "Omadus" #: loginjob.cpp:237 #, kde-format msgid "StartTls" msgstr "StartTls" #: loginjob.cpp:340 #, kde-format msgid "STARTTLS is not supported by the server, try using SSL/TLS instead." msgstr "STARTTLS ei ole serveris toetatud, selle asemel kasutatakse SSL/TLS." #: loginjob.cpp:353 #, kde-format msgid "Internal error, tried to login before encryption" msgstr "" #: loginjob.cpp:362 #, kde-format msgid "Login failed, plain login is disabled by the server." msgstr "Sisselogimine nurjus, server keelab lihttekstiga sisselogimise." #: loginjob.cpp:383 #, kde-format msgid "Login failed, authentication mode %1 is not supported by the server." msgstr "Sisselogimine nurjus, server ei toeta autentimisrežiim %1." #: loginjob.cpp:413 #, kde-format msgid "Login failed, client cannot initialize the SASL library." msgstr "Sisselogimine nurjus, klient ei suutnud initsialiseerida SASL teeki." #: loginjob.cpp:512 #, kde-format msgid "Login failed, TLS negotiation failed." msgstr "Sisselogimine nurjus, TLS läbirääkimised nurjusid." #: loginjob.cpp:570 #, kde-format msgid "SSL handshake failed." msgstr "SSL-käepigistus nurjus." #: logoutjob.cpp:33 #, kde-format msgid "Logout" msgstr "Väljalogimine" #: metadatajobbase.cpp:53 #, kde-format msgid "MetaDataJobBase" msgstr "MetaDataJobBase" #: movejob.cpp:42 #, kde-format msgid "Move" msgstr "Liiguta" #: myrightsjob.cpp:37 #, kde-format msgid "MyRights" msgstr "MyRights" #: namespacejob.cpp:68 #, kde-format msgid "Namespace" msgstr "Nimeruum" #: quotajobbase.cpp:34 #, kde-format msgid "QuotaJobBase" msgstr "QuotaJobBase" #: renamejob.cpp:37 #, kde-format msgid "Rename" msgstr "Nimeta ümber" #: searchjob.cpp:361 #, kde-format msgctxt "Name of the search job" msgid "Search" msgstr "Otsing" #: selectjob.cpp:73 #, kde-format msgctxt "name of the select job" msgid "Select" msgstr "Valimine" #: setacljob.cpp:34 #, kde-format msgid "SetAcl" msgstr "SetAcl" #: setmetadatajob.cpp:43 #, kde-format msgid "SetMetaData" msgstr "SetMetaData" #: setquotajob.cpp:37 #, kde-format msgid "SetQuota" msgstr "SetQuota" #: statusjob.cpp:40 #, kde-format msgctxt "name of the status job" msgid "Status" msgstr "Olek" #: storejob.cpp:70 #, kde-format msgid "Store" msgstr "Salvesta" #: subscribejob.cpp:36 #, kde-format msgid "Subscribe" msgstr "Telli" #: unsubscribejob.cpp:36 #, kde-format msgid "Unsubscribe" msgstr "Tühista tellimus" #~ msgid "SetAnnotation" #~ msgstr "SetAnnotation" #~ msgctxt "NAME OF TRANSLATORS" #~ msgid "Your names" #~ msgstr "Marek Laane" #~ msgctxt "EMAIL OF TRANSLATORS" #~ msgid "Your emails" #~ msgstr "bald@smail.ee" #, fuzzy #~| msgid "Create" #~ msgctxt "Authentication method" #~ msgid "Clear text" #~ msgstr "Loo" #~ msgid "Check" #~ msgstr "Kontrolli" #~ msgid "Noop" #~ msgstr "Noop" 0707010000005B000041ED00000000000000000000000266FAD7C000000000000000000000000000000000000000000000002F00000000kimap-VERSIONgit.20240930T185424~db1f697/po/eu0707010000005C000081A400000000000000000000000166FAD7C00000163E000000000000000000000000000000000000003C00000000kimap-VERSIONgit.20240930T185424~db1f697/po/eu/libkimap6.po# Translation for libkimap5.po to Euskara/Basque (eu). # Copyright (C) 2023 This file is copyright: # This file is distributed under the same license as the kimap package. # KDE euskaratzeko proiektuko arduraduna <xalba@ni.eus>. # # Translators: # Iñigo Salvador Azurmendi <xalba@ni.eus>, 2023. msgid "" msgstr "" "Project-Id-Version: kimap\n" "Report-Msgid-Bugs-To: https://bugs.kde.org\n" "POT-Creation-Date: 2022-05-11 00:45+0000\n" "PO-Revision-Date: 2023-01-03 09:03+0100\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 22.12.0\n" #: acljobbase.cpp:56 #, kde-format msgid "AclJobBase" msgstr "AclAtazaOinarria" #: appendjob.cpp:40 #, kde-format msgid "Append" msgstr "Erantsi" #: capabilitiesjob.cpp:35 #, kde-format msgid "Capabilities" msgstr "Gaitasunak" #: closejob.cpp:32 #, kde-format msgid "Close" msgstr "Itxi" #: copyjob.cpp:41 #, kde-format msgid "Copy" msgstr "Kopiatu" #: createjob.cpp:36 #, kde-format msgid "Create" msgstr "Sortu" #: deleteacljob.cpp:37 #, kde-format msgid "DeleteAclJob" msgstr "EzabatuAclAtaza" #: deletejob.cpp:36 #, kde-format msgid "Delete" msgstr "Ezabatu" #: enablejob.cpp:31 #, kde-format msgid "Enable" msgstr "Gaitu" #: expungejob.cpp:37 #, kde-format msgid "Expunge" msgstr "Desagerrarazi" #: fetchjob.cpp:97 #, kde-format msgid "Fetch" msgstr "Ekarri" #: getacljob.cpp:37 #, kde-format msgid "GetAcl" msgstr "LortuAcl" #: getmetadatajob.cpp:43 #, kde-format msgid "GetMetaData" msgstr "LortuMetaDatuak" #: getmetadatajob.cpp:66 #, kde-format msgid "GetAnnotation" msgstr "LortuIdatzoharra" #: getquotajob.cpp:35 #, kde-format msgid "GetQuota" msgstr "LortuKuota" #: getquotarootjob.cpp:38 #, kde-format msgid "GetQuotaRoot" msgstr "LortuKuotaErroa" #: idjob.cpp:35 #, kde-format msgid "Id" msgstr "ID" #: idlejob.cpp:65 #, kde-format msgctxt "name of the idle job" msgid "Idle" msgstr "Inaktibo" #: job.cpp:19 #, kde-format msgid "Job" msgstr "Ataza" #: job.cpp:54 loginjob.cpp:574 #, kde-format msgid "Connection to server lost." msgstr "Zerbitzarirako konexioa galdu da." #: job.cpp:65 loginjob.cpp:403 setmetadatajob.cpp:126 #, kde-format msgid "%1 failed, malformed reply from the server." msgstr "%1 huts egin du, gaizki eratutako erantzuna zerbitzaritik." #: job.cpp:68 loginjob.cpp:277 setmetadatajob.cpp:109 setmetadatajob.cpp:129 #, kde-format msgid "%1 failed, server replied: %2" msgstr "%1 huts egin du, zerbitzariak erantzun du: %2" #: listjob.cpp:59 #, kde-format msgid "List" msgstr "Zerrenda" #: listrightsjob.cpp:38 #, kde-format msgid "ListRights" msgstr "ZerrendatuEskubideak" #: loginjob.cpp:129 loginjob.cpp:233 #, kde-format msgid "Login" msgstr "Saio-hasiera" #: loginjob.cpp:184 #, kde-format msgid "IMAP session in the wrong state for authentication" msgstr "IMAP saioa autentifikazioa egiteko okerreko egoeran" #: loginjob.cpp:235 #, kde-format msgid "Capability" msgstr "Gaitasuna" #: loginjob.cpp:237 #, kde-format msgid "StartTls" msgstr "StartTls" #: loginjob.cpp:340 #, kde-format msgid "STARTTLS is not supported by the server, try using SSL/TLS instead." msgstr "" "Zerbitzariak ez du STARTTLS onartzen, saiatu horren ordez SSL/TLS erabiltzen." #: loginjob.cpp:353 #, kde-format msgid "Internal error, tried to login before encryption" msgstr "Barneko errorea, zifratzearen aurretik saio-hasten saiatu da" #: loginjob.cpp:362 #, kde-format msgid "Login failed, plain login is disabled by the server." msgstr "" "Saio-hastea huts egin du, zerbitzariak ageriko saio-hasiera ezgaitu du." #: loginjob.cpp:383 #, kde-format msgid "Login failed, authentication mode %1 is not supported by the server." msgstr "" "Saio-hastea huts egin du, zerbitzariak ez du %1 autentifikazio moduaren " "euskarririk." #: loginjob.cpp:413 #, kde-format msgid "Login failed, client cannot initialize the SASL library." msgstr "Saio-hastea huts egin du, ezin du SASL liburutegia hasieratu." #: loginjob.cpp:512 #, kde-format msgid "Login failed, TLS negotiation failed." msgstr "Saio-hastea huts egin du, TLS negoziazioak huts egin du." #: loginjob.cpp:570 #, kde-format msgid "SSL handshake failed." msgstr "SSL bostekoa estutzea huts egin du." #: logoutjob.cpp:33 #, kde-format msgid "Logout" msgstr "Saio-ixtea" #: metadatajobbase.cpp:53 #, kde-format msgid "MetaDataJobBase" msgstr "MetaDatuenOinarriAtaza" #: movejob.cpp:42 #, kde-format msgid "Move" msgstr "Mugitu" #: myrightsjob.cpp:37 #, kde-format msgid "MyRights" msgstr "NireEskubideak" #: namespacejob.cpp:68 #, kde-format msgid "Namespace" msgstr "Izen-tartea" #: quotajobbase.cpp:34 #, kde-format msgid "QuotaJobBase" msgstr "KuotaAtazaOinarria" #: renamejob.cpp:37 #, kde-format msgid "Rename" msgstr "Berrizendatu" #: searchjob.cpp:361 #, kde-format msgctxt "Name of the search job" msgid "Search" msgstr "Bilatu" #: selectjob.cpp:73 #, kde-format msgctxt "name of the select job" msgid "Select" msgstr "Hautatu" #: setacljob.cpp:34 #, kde-format msgid "SetAcl" msgstr "EzarriAcl" #: setmetadatajob.cpp:43 #, kde-format msgid "SetMetaData" msgstr "EzarriMetaDatuak" #: setquotajob.cpp:37 #, kde-format msgid "SetQuota" msgstr "EzarriKuota" #: statusjob.cpp:40 #, kde-format msgctxt "name of the status job" msgid "Status" msgstr "Egoera" #: storejob.cpp:70 #, kde-format msgid "Store" msgstr "Biltegiratu" #: subscribejob.cpp:36 #, kde-format msgid "Subscribe" msgstr "Harpidetu" #: unsubscribejob.cpp:36 #, kde-format msgid "Unsubscribe" msgstr "Harpidetza kendu" 0707010000005D000041ED00000000000000000000000266FAD7C000000000000000000000000000000000000000000000002F00000000kimap-VERSIONgit.20240930T185424~db1f697/po/fi0707010000005E000081A400000000000000000000000166FAD7C0000027FC000000000000000000000000000000000000003C00000000kimap-VERSIONgit.20240930T185424~db1f697/po/fi/libkimap6.po# Finnish translation for libkimap # Copyright © 2010 Rosetta Contributors and Canonical Ltd 2010 # This file is distributed under the same license as the libkimap package. # Tommi Nieminen <translator@legisign.org>, 2012, 2016, 2018, 2021, 2022. # Lasse Liehu <lasse.liehu@gmail.com>, 2013, 2014, 2016. # # KDE Finnish translation sprint participants: # Jiri Grönroos <Unknown>, 2010. msgid "" msgstr "" "Project-Id-Version: libkimap\n" "Report-Msgid-Bugs-To: https://bugs.kde.org\n" "POT-Creation-Date: 2022-05-11 00:45+0000\n" "PO-Revision-Date: 2022-02-12 19:14+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:25:20+0000\n" "X-Generator: Lokalize 20.04.2\n" # ”AclJobBase” tarkoittaa käytännössä jotain ACL:ään liittyvää työtä, josta ei tiedetä tarkemmin. #: acljobbase.cpp:56 #, kde-format msgid "AclJobBase" msgstr "Tuntematon ACL-työ" # Tämä on jätetty suomentamatta, koska on IMAP-komennon nimi. Parempi alkuteksti saadaan toivottavasti pian. #: appendjob.cpp:40 #, kde-format msgid "Append" msgstr "Append" # Tämä on jätetty suomentamatta, koska on IMAP-komennon nimi. Parempi alkuteksti saadaan toivottavasti pian. #: capabilitiesjob.cpp:35 #, kde-format msgid "Capabilities" msgstr "Capabilities" # Tämä on jätetty suomentamatta, koska on IMAP-komennon nimi. Parempi alkuteksti saadaan toivottavasti pian. #: closejob.cpp:32 #, kde-format msgid "Close" msgstr "Close" # Tämä on jätetty suomentamatta, koska on IMAP-komennon nimi. Parempi alkuteksti saadaan toivottavasti pian. #: copyjob.cpp:41 #, kde-format msgid "Copy" msgstr "Copy" # Tämä on jätetty suomentamatta, koska on IMAP-komennon nimi. Parempi alkuteksti saadaan toivottavasti pian. #: createjob.cpp:36 #, kde-format msgid "Create" msgstr "Create" # ”DeleteAclJob” tarkoittaa työtä, joka vastaa IMAP-komentoa ”DELETEACL”. IMAP-komento on jätetty tarkoituksella suomentamatta. Parempi alkuteksti saadaan toivottavasti pian. #: deleteacljob.cpp:37 #, kde-format msgid "DeleteAclJob" msgstr "DeleteAcl" # Tämä on jätetty suomentamatta, koska on IMAP-komennon nimi. Parempi alkuteksti saadaan toivottavasti pian. #: deletejob.cpp:36 #, kde-format msgid "Delete" msgstr "Delete" #: enablejob.cpp:31 #, kde-format msgid "Enable" msgstr "Käytä" # Tämä on jätetty suomentamatta, koska on IMAP-komennon nimi. Parempi alkuteksti saadaan toivottavasti pian. #: expungejob.cpp:37 #, kde-format msgid "Expunge" msgstr "Expunge" # Tämä on jätetty suomentamatta, koska on IMAP-komennon nimi. Parempi alkuteksti saadaan toivottavasti pian. #: fetchjob.cpp:97 #, kde-format msgid "Fetch" msgstr "Fetch" # Tämä on jätetty suomentamatta, koska on IMAP-komennon nimi. Parempi alkuteksti saadaan toivottavasti pian. #: getacljob.cpp:37 #, kde-format msgid "GetAcl" msgstr "GetAcl" # Tämä on jätetty suomentamatta, koska on IMAP-komennon nimi. Parempi alkuteksti saadaan toivottavasti pian. #: getmetadatajob.cpp:43 #, kde-format msgid "GetMetaData" msgstr "GetMetaData" # Tämä on jätetty suomentamatta, koska on IMAP-komennon nimi. Parempi alkuteksti saadaan toivottavasti pian. #: getmetadatajob.cpp:66 #, kde-format msgid "GetAnnotation" msgstr "GetAnnotation" # Tämä on jätetty suomentamatta, koska on IMAP-komennon nimi. Parempi alkuteksti saadaan toivottavasti pian. #: getquotajob.cpp:35 #, kde-format msgid "GetQuota" msgstr "GetQuota" # Tämä on jätetty suomentamatta, koska on IMAP-komennon nimi. Parempi alkuteksti saadaan toivottavasti pian. #: getquotarootjob.cpp:38 #, kde-format msgid "GetQuotaRoot" msgstr "GetQuotaRoot" # Tämä on jätetty suomentamatta, koska on IMAP-komennon nimi. Parempi alkuteksti saadaan toivottavasti pian. #: idjob.cpp:35 #, kde-format msgid "Id" msgstr "Id" # Tämä on jätetty suomentamatta, koska on IMAP-komennon nimi. Parempi alkuteksti saadaan toivottavasti pian. #: idlejob.cpp:65 #, kde-format msgctxt "name of the idle job" msgid "Idle" msgstr "Idle" #: job.cpp:19 #, kde-format msgid "Job" msgstr "Työ" #: job.cpp:54 loginjob.cpp:574 #, kde-format msgid "Connection to server lost." msgstr "Yhteys palvelimeen menetetty." #: job.cpp:65 loginjob.cpp:403 setmetadatajob.cpp:126 #, kde-format msgid "%1 failed, malformed reply from the server." msgstr "%1 epäonnistui, virheellinen vastaus palvelimelta." #: job.cpp:68 loginjob.cpp:277 setmetadatajob.cpp:109 setmetadatajob.cpp:129 #, kde-format msgid "%1 failed, server replied: %2" msgstr "%1 epäonnistui, palvelimen vastaus: %2" # Tämä on jätetty suomentamatta, koska on IMAP-komennon nimi. Parempi alkuteksti saadaan toivottavasti pian. #: listjob.cpp:59 #, kde-format msgid "List" msgstr "List" # Tämä on jätetty suomentamatta, koska on IMAP-komennon nimi. Parempi alkuteksti saadaan toivottavasti pian. #: listrightsjob.cpp:38 #, kde-format msgid "ListRights" msgstr "ListRights" # Tämä on jätetty suomentamatta, koska on IMAP-komennon nimi. Parempi alkuteksti saadaan toivottavasti pian. #: loginjob.cpp:129 loginjob.cpp:233 #, kde-format msgid "Login" msgstr "Login" #: loginjob.cpp:184 #, kde-format msgid "IMAP session in the wrong state for authentication" msgstr "IMAP-istunto väärässä tilassa tunnistautumista varten" # Tämä on jätetty suomentamatta, koska on IMAP-komennon nimi. Parempi alkuteksti saadaan toivottavasti pian. #: loginjob.cpp:235 #, kde-format msgid "Capability" msgstr "Capability" # Tämä on jätetty suomentamatta, koska on IMAP-komennon nimi. Parempi alkuteksti saadaan toivottavasti pian. #: loginjob.cpp:237 #, kde-format msgid "StartTls" msgstr "StartTls" #: loginjob.cpp:340 #, kde-format msgid "STARTTLS is not supported by the server, try using SSL/TLS instead." msgstr "Palvelin ei tue STARTTLS:ää, yritä käyttää sen sijaan SSL/TLS:ää." #: loginjob.cpp:353 #, kde-format msgid "Internal error, tried to login before encryption" msgstr "Sisäinen virhe: yritettiin kirjautua ennen salausta" #: loginjob.cpp:362 #, kde-format msgid "Login failed, plain login is disabled by the server." msgstr "" "Kirjautuminen epäonnistui: palvelin on poistanut käytöstä " "raakatekstikirjautumisen." #: loginjob.cpp:383 #, kde-format msgid "Login failed, authentication mode %1 is not supported by the server." msgstr "Kirjautuminen epäonnistui: palvelin ei tue tunnistautumistapaa %1." #: loginjob.cpp:413 #, kde-format msgid "Login failed, client cannot initialize the SASL library." msgstr "Kirjautuminen epäonnistui: ohjelma ei saa SASL-kirjastoa alustetuksi." #: loginjob.cpp:512 #, kde-format msgid "Login failed, TLS negotiation failed." msgstr "Kirjautuminen epäonnistui: TLS-neuvottelu epäonnistui." #: loginjob.cpp:570 #, kde-format msgid "SSL handshake failed." msgstr "SSL-kättely epäonnistui." # Tämä on jätetty suomentamatta, koska on IMAP-komennon nimi. Parempi alkuteksti saadaan toivottavasti pian. #: logoutjob.cpp:33 #, kde-format msgid "Logout" msgstr "Logout" # ”MetaDataJobBase” tarkoittaa työtä, joka liittyy jotenkin metatietoihin, mutta josta ei tiedetä tarkemmin. MetaData on jätetty suomentamatta, koska muitakaan IMAP-komentojen nimiä ei ole tässä suomennettu. #: metadatajobbase.cpp:53 #, kde-format msgid "MetaDataJobBase" msgstr "Tuntematon MetaData-työ" #: movejob.cpp:42 #, kde-format msgid "Move" msgstr "Siirrä" # Tämä on jätetty suomentamatta, koska on IMAP-komennon nimi. Parempi alkuteksti saadaan toivottavasti pian. #: myrightsjob.cpp:37 #, kde-format msgid "MyRights" msgstr "MyRights" # Tämä on jätetty suomentamatta, koska on IMAP-komennon nimi. Parempi alkuteksti saadaan toivottavasti pian. #: namespacejob.cpp:68 #, kde-format msgid "Namespace" msgstr "Namespace" # ”MetaDataJobBase” tarkoittaa työtä, joka liittyy jotenkin quotaan, mutta josta ei tiedetä tarkemmin. Quota on jätetty suomentamatta, koska muitakaan IMAP-komentojen nimiä ei ole tässä suomennettu. #: quotajobbase.cpp:34 #, kde-format msgid "QuotaJobBase" msgstr "Tuntematon Quota-työ" # Tämä on jätetty suomentamatta, koska on IMAP-komennon nimi. Parempi alkuteksti saadaan toivottavasti pian. #: renamejob.cpp:37 #, kde-format msgid "Rename" msgstr "Rename" # Tämä on jätetty suomentamatta, koska on IMAP-komennon nimi. Parempi alkuteksti saadaan toivottavasti pian. #: searchjob.cpp:361 #, kde-format msgctxt "Name of the search job" msgid "Search" msgstr "Search" # Tämä on jätetty suomentamatta, koska on IMAP-komennon nimi. Parempi alkuteksti saadaan toivottavasti pian. #: selectjob.cpp:73 #, kde-format msgctxt "name of the select job" msgid "Select" msgstr "Select" # Tämä on jätetty suomentamatta, koska on IMAP-komennon nimi. Parempi alkuteksti saadaan toivottavasti pian. #: setacljob.cpp:34 #, kde-format msgid "SetAcl" msgstr "SetAcl" # Tämä on jätetty suomentamatta, koska on IMAP-komennon nimi. Parempi alkuteksti saadaan toivottavasti pian. #: setmetadatajob.cpp:43 #, kde-format msgid "SetMetaData" msgstr "SetMetaData" # Tämä on jätetty suomentamatta, koska on IMAP-komennon nimi. Parempi alkuteksti saadaan toivottavasti pian. #: setquotajob.cpp:37 #, kde-format msgid "SetQuota" msgstr "SetQuota" #: statusjob.cpp:40 #, kde-format msgctxt "name of the status job" msgid "Status" msgstr "Status" # Tämä on jätetty suomentamatta, koska on IMAP-komennon nimi. Parempi alkuteksti saadaan toivottavasti pian. #: storejob.cpp:70 #, kde-format msgid "Store" msgstr "Store" # Tämä on jätetty suomentamatta, koska on IMAP-komennon nimi. Parempi alkuteksti saadaan toivottavasti pian. #: subscribejob.cpp:36 #, kde-format msgid "Subscribe" msgstr "Subscribe" # Tämä on jätetty suomentamatta, koska on IMAP-komennon nimi. Parempi alkuteksti saadaan toivottavasti pian. #: unsubscribejob.cpp:36 #, kde-format msgid "Unsubscribe" msgstr "Unsubscribe" # Tämä on jätetty suomentamatta, koska on IMAP-komennon nimi. Parempi alkuteksti saadaan toivottavasti pian. #~ msgid "SetAnnotation" #~ msgstr "SetAnnotation" #~ msgid "Mock" #~ msgstr "Mock" 0707010000005F000041ED00000000000000000000000266FAD7C000000000000000000000000000000000000000000000002F00000000kimap-VERSIONgit.20240930T185424~db1f697/po/fr07070100000060000081A400000000000000000000000166FAD7C000001938000000000000000000000000000000000000003C00000000kimap-VERSIONgit.20240930T185424~db1f697/po/fr/libkimap6.po# translation of libkimap.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. # Geoffray Levasseur <jeff.brandin@gmail.com>, 2009. # Sebastien Renard <Sebastien.Renard@digitalfox.org>, 2009. # Geoffray Levasseur <geoffray.levasseurbrandin@numericable.fr>, 2009, 2010, 2014. # SPDX-FileCopyrightText: 2012, 2013, 2020, 2022, 2024 Xavier Besnard <xavier.besnard@kde.org> # Vincent Pinon <vpinon@kde.org>, 2017. # Simon Depiets <sdepiets@gmail.com>, 2018. # Xavier Besnard <xavier.besnard@kde.org>, 2023. # msgid "" msgstr "" "Project-Id-Version: libkimap\n" "Report-Msgid-Bugs-To: https://bugs.kde.org\n" "POT-Creation-Date: 2022-05-11 00:45+0000\n" "PO-Revision-Date: 2024-04-26 15:58+0200\n" "Last-Translator: Xavier Besnard <xavier.besnard@kde.org>\n" "Language-Team: French <French <kde-francophone@kde.org>>\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 23.08.5\n" "X-Environment: kde\n" "X-Accelerator-Marker: &\n" "X-Text-Markup: kde4\n" #: acljobbase.cpp:56 #, kde-format msgid "AclJobBase" msgstr "AclJobBase" #: appendjob.cpp:40 #, kde-format msgid "Append" msgstr "Fusionner" #: capabilitiesjob.cpp:35 #, kde-format msgid "Capabilities" msgstr "Capacités" #: closejob.cpp:32 #, kde-format msgid "Close" msgstr "Fermer" #: copyjob.cpp:41 #, kde-format msgid "Copy" msgstr "Copier" #: createjob.cpp:36 #, kde-format msgid "Create" msgstr "Créer" #: deleteacljob.cpp:37 #, kde-format msgid "DeleteAclJob" msgstr "DeleteAclJob" #: deletejob.cpp:36 #, kde-format msgid "Delete" msgstr "Supprimer" #: enablejob.cpp:31 #, kde-format msgid "Enable" msgstr "Activer" #: expungejob.cpp:37 #, kde-format msgid "Expunge" msgstr "Purger" #: fetchjob.cpp:97 #, kde-format msgid "Fetch" msgstr "Rechercher" #: getacljob.cpp:37 #, kde-format msgid "GetAcl" msgstr "GetAcl" #: getmetadatajob.cpp:43 #, kde-format msgid "GetMetaData" msgstr "GetMetaData" #: getmetadatajob.cpp:66 #, kde-format msgid "GetAnnotation" msgstr "GetAnnotation" #: getquotajob.cpp:35 #, kde-format msgid "GetQuota" msgstr "GetQuota" #: getquotarootjob.cpp:38 #, kde-format msgid "GetQuotaRoot" msgstr "GetQuotaRoot" #: idjob.cpp:35 #, kde-format msgid "Id" msgstr "Identifiant" #: idlejob.cpp:65 #, kde-format msgctxt "name of the idle job" msgid "Idle" msgstr "Inactif" #: job.cpp:19 #, kde-format msgid "Job" msgstr "Tâche" #: job.cpp:54 loginjob.cpp:574 #, kde-format msgid "Connection to server lost." msgstr "Interruption de la connexion au serveur." #: job.cpp:65 loginjob.cpp:403 setmetadatajob.cpp:126 #, kde-format msgid "%1 failed, malformed reply from the server." msgstr "Échec de %1. Réponse incorrecte du serveur." #: job.cpp:68 loginjob.cpp:277 setmetadatajob.cpp:109 setmetadatajob.cpp:129 #, kde-format msgid "%1 failed, server replied: %2" msgstr "Échec de %1. Le serveur a répondu : %2" #: listjob.cpp:59 #, kde-format msgid "List" msgstr "Liste" #: listrightsjob.cpp:38 #, kde-format msgid "ListRights" msgstr "ListRights" #: loginjob.cpp:129 loginjob.cpp:233 #, kde-format msgid "Login" msgstr "Connexion" #: loginjob.cpp:184 #, kde-format msgid "IMAP session in the wrong state for authentication" msgstr "" "La session « IMAP » est dans un état incorrect pour une authentification" #: loginjob.cpp:235 #, kde-format msgid "Capability" msgstr "Capacité" #: loginjob.cpp:237 #, kde-format msgid "StartTls" msgstr "STARTTLS" #: loginjob.cpp:340 #, kde-format msgid "STARTTLS is not supported by the server, try using SSL/TLS instead." msgstr "" "STARTTLS n'est pas pris en charge par le serveur, veuillez essayer avec SSL/" "TLS." #: loginjob.cpp:353 #, kde-format msgid "Internal error, tried to login before encryption" msgstr "Erreur interne, tentative de connexion avant le chiffrement" #: loginjob.cpp:362 #, kde-format msgid "Login failed, plain login is disabled by the server." msgstr "" "La connexion a échoué. La connexion non chiffrée est désactivée par le " "serveur." #: loginjob.cpp:383 #, kde-format msgid "Login failed, authentication mode %1 is not supported by the server." msgstr "" "La connexion a échoué. Le mode d'authentification « %1 » n'est pas pris en " "charge par le serveur." #: loginjob.cpp:413 #, kde-format msgid "Login failed, client cannot initialize the SASL library." msgstr "" "La connexion a échoué. Le client ne peut initialiser la bibliothèque " "« SASL »." #: loginjob.cpp:512 #, kde-format msgid "Login failed, TLS negotiation failed." msgstr "La connexion a échoué. La négociation « TLS » a échoué." #: loginjob.cpp:570 #, kde-format msgid "SSL handshake failed." msgstr "Échec de la transaction SSL." #: logoutjob.cpp:33 #, kde-format msgid "Logout" msgstr "Déconnexion" #: metadatajobbase.cpp:53 #, kde-format msgid "MetaDataJobBase" msgstr "MetaDataJobBase" #: movejob.cpp:42 #, kde-format msgid "Move" msgstr "Déplacer" #: myrightsjob.cpp:37 #, kde-format msgid "MyRights" msgstr "MyRights" #: namespacejob.cpp:68 #, kde-format msgid "Namespace" msgstr "Namespace" #: quotajobbase.cpp:34 #, kde-format msgid "QuotaJobBase" msgstr "QuotaJobBase" #: renamejob.cpp:37 #, kde-format msgid "Rename" msgstr "Renommer" #: searchjob.cpp:361 #, kde-format msgctxt "Name of the search job" msgid "Search" msgstr "Rechercher" #: selectjob.cpp:73 #, kde-format msgctxt "name of the select job" msgid "Select" msgstr "Sélectionner" #: setacljob.cpp:34 #, kde-format msgid "SetAcl" msgstr "SetAcl" #: setmetadatajob.cpp:43 #, kde-format msgid "SetMetaData" msgstr "SetMetaData" #: setquotajob.cpp:37 #, kde-format msgid "SetQuota" msgstr "SetQuota" #: statusjob.cpp:40 #, kde-format msgctxt "name of the status job" msgid "Status" msgstr "État" #: storejob.cpp:70 #, kde-format msgid "Store" msgstr "Enregistrer" #: subscribejob.cpp:36 #, kde-format msgid "Subscribe" msgstr "S'inscrire" #: unsubscribejob.cpp:36 #, kde-format msgid "Unsubscribe" msgstr "Se désinscrire" #~ msgid "SetAnnotation" #~ msgstr "SetAnnotation" #~ msgctxt "NAME OF TRANSLATORS" #~ msgid "Your names" #~ msgstr "Geoffray Levasseur" #~ msgctxt "EMAIL OF TRANSLATORS" #~ msgid "Your emails" #~ msgstr "jeff.levasseur@free.fr" #, fuzzy #~| msgid "Create" #~ msgctxt "Authentication method" #~ msgid "Clear text" #~ msgstr "Créer" 07070100000061000041ED00000000000000000000000266FAD7C000000000000000000000000000000000000000000000002F00000000kimap-VERSIONgit.20240930T185424~db1f697/po/ga07070100000062000081A400000000000000000000000166FAD7C00000167B000000000000000000000000000000000000003C00000000kimap-VERSIONgit.20240930T185424~db1f697/po/ga/libkimap6.po# Irish translation of libkimap # Copyright (C) 2009 This_file_is_part_of_KDE # This file is distributed under the same license as the libkimap package. # Kevin Scannell <kscanne@gmail.com>, 2009. msgid "" msgstr "" "Project-Id-Version: libkimap\n" "Report-Msgid-Bugs-To: https://bugs.kde.org\n" "POT-Creation-Date: 2022-05-11 00:45+0000\n" "PO-Revision-Date: 2009-12-24 06:59-0500\n" "Last-Translator: Kevin Scannell <kscanne@gmail.com>\n" "Language-Team: Irish <gaeilge-gnulinux@lists.sourceforge.net>\n" "Language: ga\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=5; plural=n==1 ? 0 : n==2 ? 1 : n<7 ? 2 : n < 11 ? " "3 : 4\n" #: acljobbase.cpp:56 #, kde-format msgid "AclJobBase" msgstr "AclJobBase" #: appendjob.cpp:40 #, kde-format msgid "Append" msgstr "Iarcheangail" #: capabilitiesjob.cpp:35 #, kde-format msgid "Capabilities" msgstr "Ábaltachtaí" #: closejob.cpp:32 #, kde-format msgid "Close" msgstr "Dún" #: copyjob.cpp:41 #, kde-format msgid "Copy" msgstr "Cóipeáil" #: createjob.cpp:36 #, kde-format msgid "Create" msgstr "Cruthaigh" #: deleteacljob.cpp:37 #, kde-format msgid "DeleteAclJob" msgstr "DeleteAclJob" #: deletejob.cpp:36 #, kde-format msgid "Delete" msgstr "Scrios" #: enablejob.cpp:31 #, kde-format msgid "Enable" msgstr "" #: expungejob.cpp:37 #, kde-format msgid "Expunge" msgstr "Glan" #: fetchjob.cpp:97 #, kde-format msgid "Fetch" msgstr "Gabh" #: getacljob.cpp:37 #, kde-format msgid "GetAcl" msgstr "FaighAcl" #: getmetadatajob.cpp:43 #, kde-format msgid "GetMetaData" msgstr "FaighMeiteashonraí" #: getmetadatajob.cpp:66 #, kde-format msgid "GetAnnotation" msgstr "FaighAnótáil" #: getquotajob.cpp:35 #, kde-format msgid "GetQuota" msgstr "FaighCuóta" #: getquotarootjob.cpp:38 #, kde-format msgid "GetQuotaRoot" msgstr "GetQuotaRoot" #: idjob.cpp:35 #, fuzzy, kde-format #| msgctxt "name of the idle job" #| msgid "Idle" msgid "Id" msgstr "Díomhaoin" #: idlejob.cpp:65 #, kde-format msgctxt "name of the idle job" msgid "Idle" msgstr "Díomhaoin" #: job.cpp:19 #, kde-format msgid "Job" msgstr "Jab" #: job.cpp:54 loginjob.cpp:574 #, kde-format msgid "Connection to server lost." msgstr "Cailleadh an ceangal leis an bhfreastalaí." #: job.cpp:65 loginjob.cpp:403 setmetadatajob.cpp:126 #, kde-format msgid "%1 failed, malformed reply from the server." msgstr "Theip ar %1, fuarthas freagra míchumtha ón bhfreastalaí." #: job.cpp:68 loginjob.cpp:277 setmetadatajob.cpp:109 setmetadatajob.cpp:129 #, kde-format msgid "%1 failed, server replied: %2" msgstr "Theip ar %1, freagra ón bhfreastalaí: %2" #: listjob.cpp:59 #, kde-format msgid "List" msgstr "Liosta" #: listrightsjob.cpp:38 #, kde-format msgid "ListRights" msgstr "ListRights" #: loginjob.cpp:129 loginjob.cpp:233 #, kde-format msgid "Login" msgstr "Logáil isteach" #: loginjob.cpp:184 #, kde-format msgid "IMAP session in the wrong state for authentication" msgstr "Tá seisiún IMAP sa staid mhícheart le haghaidh fíordheimhnithe" #: loginjob.cpp:235 #, kde-format msgid "Capability" msgstr "Ábaltacht" #: loginjob.cpp:237 #, kde-format msgid "StartTls" msgstr "StartTls" #: loginjob.cpp:340 #, kde-format msgid "STARTTLS is not supported by the server, try using SSL/TLS instead." msgstr "" #: loginjob.cpp:353 #, kde-format msgid "Internal error, tried to login before encryption" msgstr "" #: loginjob.cpp:362 #, kde-format msgid "Login failed, plain login is disabled by the server." msgstr "" "Theip ar logáil isteach, dhíchumasaigh an freastalaí gnáthlogáil isteach." #: loginjob.cpp:383 #, kde-format msgid "Login failed, authentication mode %1 is not supported by the server." msgstr "" "Theip ar logáil isteach, ní thacaíonn an freastalaí le mód fíordheimhnithe " "%1." #: loginjob.cpp:413 #, kde-format msgid "Login failed, client cannot initialize the SASL library." msgstr "" "Theip ar logáil isteach, ní féidir leis an gcliant an leabharlann SASL a " "thúsú." #: loginjob.cpp:512 #, kde-format msgid "Login failed, TLS negotiation failed." msgstr "Theip ar logáil isteach, theip ar idirbheartaíocht TLS." #: loginjob.cpp:570 #, kde-format msgid "SSL handshake failed." msgstr "" #: logoutjob.cpp:33 #, kde-format msgid "Logout" msgstr "Logáil Amach" #: metadatajobbase.cpp:53 #, kde-format msgid "MetaDataJobBase" msgstr "MetaDataJobBase" #: movejob.cpp:42 #, kde-format msgid "Move" msgstr "" #: myrightsjob.cpp:37 #, kde-format msgid "MyRights" msgstr "MoChuidCearta" #: namespacejob.cpp:68 #, kde-format msgid "Namespace" msgstr "Ainmspás" #: quotajobbase.cpp:34 #, kde-format msgid "QuotaJobBase" msgstr "QuotaJobBase" #: renamejob.cpp:37 #, kde-format msgid "Rename" msgstr "Athainmnigh" #: searchjob.cpp:361 #, kde-format msgctxt "Name of the search job" msgid "Search" msgstr "Cuardach" #: selectjob.cpp:73 #, kde-format msgctxt "name of the select job" msgid "Select" msgstr "Roghnú" #: setacljob.cpp:34 #, kde-format msgid "SetAcl" msgstr "SocraighAcl" #: setmetadatajob.cpp:43 #, kde-format msgid "SetMetaData" msgstr "SocraighMeiteashonraí" #: setquotajob.cpp:37 #, kde-format msgid "SetQuota" msgstr "SocraighCuóta" #: statusjob.cpp:40 #, kde-format msgctxt "name of the status job" msgid "Status" msgstr "" #: storejob.cpp:70 #, kde-format msgid "Store" msgstr "Stóráil" #: subscribejob.cpp:36 #, kde-format msgid "Subscribe" msgstr "Liostáil" #: unsubscribejob.cpp:36 #, kde-format msgid "Unsubscribe" msgstr "Díliostáil" #~ msgid "SetAnnotation" #~ msgstr "SocraighAnótáil" #~ msgctxt "NAME OF TRANSLATORS" #~ msgid "Your names" #~ msgstr "Kevin Scannell" #~ msgctxt "EMAIL OF TRANSLATORS" #~ msgid "Your emails" #~ msgstr "kscanne@gmail.com" 07070100000063000041ED00000000000000000000000266FAD7C000000000000000000000000000000000000000000000002F00000000kimap-VERSIONgit.20240930T185424~db1f697/po/gl07070100000064000081A400000000000000000000000166FAD7C0000016B0000000000000000000000000000000000000003C00000000kimap-VERSIONgit.20240930T185424~db1f697/po/gl/libkimap6.po# translation of libkimap.po to galician # Copyright (C) YEAR This_file_is_part_of_KDE # This file is distributed under the same license as the PACKAGE package. # Marce Villarino <mvillarino@users.sourceforge.net>, 2009, 2014. # Xosé <xosecalvo@gmail.com>, 2009. # Xosé <xosecalvo@edu.xunta.es>, 2009, 2011. # Adrián Chaves Fernández (Gallaecio) <adriyetichaves@gmail.com>, 2016, 2017. # Adrián Chaves (Gallaecio) <adrian@chaves.io>, 2017, 2018, 2023. # msgid "" msgstr "" "Project-Id-Version: libkimap\n" "Report-Msgid-Bugs-To: https://bugs.kde.org\n" "POT-Creation-Date: 2022-05-11 00:45+0000\n" "PO-Revision-Date: 2023-04-24 07:05+0200\n" "Last-Translator: Adrián Chaves (Gallaecio) <adrian@chaves.io>\n" "Language-Team: Galician <proxecto@trasno.gal>\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" "X-Generator: Lokalize 22.12.3\n" #: acljobbase.cpp:56 #, kde-format msgid "AclJobBase" msgstr "AclJobBase" #: appendjob.cpp:40 #, kde-format msgid "Append" msgstr "Amecer" #: capabilitiesjob.cpp:35 #, kde-format msgid "Capabilities" msgstr "Capacidades" #: closejob.cpp:32 #, kde-format msgid "Close" msgstr "Pechar" #: copyjob.cpp:41 #, kde-format msgid "Copy" msgstr "Copiar" #: createjob.cpp:36 #, kde-format msgid "Create" msgstr "Crear" #: deleteacljob.cpp:37 #, kde-format msgid "DeleteAclJob" msgstr "DeleteAclJob" #: deletejob.cpp:36 #, kde-format msgid "Delete" msgstr "Eliminar" #: enablejob.cpp:31 #, kde-format msgid "Enable" msgstr "Activar" #: expungejob.cpp:37 #, kde-format msgid "Expunge" msgstr "Suprimir" #: fetchjob.cpp:97 #, kde-format msgid "Fetch" msgstr "Obter" #: getacljob.cpp:37 #, kde-format msgid "GetAcl" msgstr "GetAcl" #: getmetadatajob.cpp:43 #, kde-format msgid "GetMetaData" msgstr "GetMetaData" #: getmetadatajob.cpp:66 #, kde-format msgid "GetAnnotation" msgstr "GetAnnotation" #: getquotajob.cpp:35 #, kde-format msgid "GetQuota" msgstr "GetQuota" #: getquotarootjob.cpp:38 #, kde-format msgid "GetQuotaRoot" msgstr "GetQuotaRoot" #: idjob.cpp:35 #, kde-format msgid "Id" msgstr "Identificador" #: idlejob.cpp:65 #, kde-format msgctxt "name of the idle job" msgid "Idle" msgstr "Inactivo" #: job.cpp:19 #, kde-format msgid "Job" msgstr "Tarefa" #: job.cpp:54 loginjob.cpp:574 #, kde-format msgid "Connection to server lost." msgstr "Perdeuse a conexión co servidor." #: job.cpp:65 loginjob.cpp:403 setmetadatajob.cpp:126 #, kde-format msgid "%1 failed, malformed reply from the server." msgstr "Fallou %1; recibiuse unha resposta incorrecta do servidor." #: job.cpp:68 loginjob.cpp:277 setmetadatajob.cpp:109 setmetadatajob.cpp:129 #, kde-format msgid "%1 failed, server replied: %2" msgstr "Fallou %1; o servidor respondeu: %2" #: listjob.cpp:59 #, kde-format msgid "List" msgstr "Lista" #: listrightsjob.cpp:38 #, kde-format msgid "ListRights" msgstr "ListRights" #: loginjob.cpp:129 loginjob.cpp:233 #, kde-format msgid "Login" msgstr "Identificación" #: loginjob.cpp:184 #, kde-format msgid "IMAP session in the wrong state for authentication" msgstr "A sesión de IMAP está no estado equivocado para a autenticación" #: loginjob.cpp:235 #, kde-format msgid "Capability" msgstr "Capacidade" #: loginjob.cpp:237 #, kde-format msgid "StartTls" msgstr "StartTls" #: loginjob.cpp:340 #, kde-format msgid "STARTTLS is not supported by the server, try using SSL/TLS instead." msgstr "O servidor non é compatíbel con STARTTLS, probe a usar SSL/TLS." #: loginjob.cpp:353 #, kde-format msgid "Internal error, tried to login before encryption" msgstr "Erro interno, intentouse a identificación antes da cifraxe" #: loginjob.cpp:362 #, kde-format msgid "Login failed, plain login is disabled by the server." msgstr "Fallou o acceso; o acceso simple está desactivado no servidor." #: loginjob.cpp:383 #, kde-format msgid "Login failed, authentication mode %1 is not supported by the server." msgstr "Fallou o acceso; o servidor non admite o modo de autenticación %1." #: loginjob.cpp:413 #, kde-format msgid "Login failed, client cannot initialize the SASL library." msgstr "Fallou o acceso; o cliente non pode inicializar a biblioteca SASL." #: loginjob.cpp:512 #, kde-format msgid "Login failed, TLS negotiation failed." msgstr "Fallou o acceso; fallou a negociación TLS." #: loginjob.cpp:570 #, kde-format msgid "SSL handshake failed." msgstr "Fallou a negociación de SSL." #: logoutjob.cpp:33 #, kde-format msgid "Logout" msgstr "Saída" #: metadatajobbase.cpp:53 #, kde-format msgid "MetaDataJobBase" msgstr "MetaDataJobBase" #: movejob.cpp:42 #, kde-format msgid "Move" msgstr "Mover" #: myrightsjob.cpp:37 #, kde-format msgid "MyRights" msgstr "MyRights" #: namespacejob.cpp:68 #, kde-format msgid "Namespace" msgstr "Espazo de nomes" #: quotajobbase.cpp:34 #, kde-format msgid "QuotaJobBase" msgstr "QuotaJobBase" #: renamejob.cpp:37 #, kde-format msgid "Rename" msgstr "Renomear" #: searchjob.cpp:361 #, kde-format msgctxt "Name of the search job" msgid "Search" msgstr "Buscar" #: selectjob.cpp:73 #, kde-format msgctxt "name of the select job" msgid "Select" msgstr "Seleccionar" #: setacljob.cpp:34 #, kde-format msgid "SetAcl" msgstr "SetAcl" #: setmetadatajob.cpp:43 #, kde-format msgid "SetMetaData" msgstr "SetMetaData" #: setquotajob.cpp:37 #, kde-format msgid "SetQuota" msgstr "SetQuota" #: statusjob.cpp:40 #, kde-format msgctxt "name of the status job" msgid "Status" msgstr "Estado" #: storejob.cpp:70 #, kde-format msgid "Store" msgstr "Gardar" #: subscribejob.cpp:36 #, kde-format msgid "Subscribe" msgstr "Subscribirse" #: unsubscribejob.cpp:36 #, kde-format msgid "Unsubscribe" msgstr "Anular a subscrición" #~ msgid "SetAnnotation" #~ msgstr "SetAnnotation" 07070100000065000041ED00000000000000000000000266FAD7C000000000000000000000000000000000000000000000002F00000000kimap-VERSIONgit.20240930T185424~db1f697/po/he07070100000066000081A400000000000000000000000166FAD7C0000016F7000000000000000000000000000000000000003C00000000kimap-VERSIONgit.20240930T185424~db1f697/po/he/libkimap6.po# Copyright (C) 2024 This file is copyright: # This file is distributed under the same license as the kimap package. # # SPDX-FileCopyrightText: 2024 Yaron Shahrabani <sh.yaron@gmail.com> msgid "" msgstr "" "Project-Id-Version: kimap\n" "Report-Msgid-Bugs-To: https://bugs.kde.org\n" "POT-Creation-Date: 2022-05-11 00:45+0000\n" "PO-Revision-Date: 2024-04-07 00:15+0300\n" "Last-Translator: Yaron Shahrabani <sh.yaron@gmail.com>\n" "Language-Team: צוות התרגום של KDE ישראל\n" "Language: he\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 == 2) ? 1 : ((n > 10 && " "n % 10 == 0) ? 2 : 3));\n" "X-Generator: Lokalize 23.08.5\n" #: acljobbase.cpp:56 #, kde-format msgid "AclJobBase" msgstr "בסיס_משימת_ACL" #: appendjob.cpp:40 #, kde-format msgid "Append" msgstr "הוספה" #: capabilitiesjob.cpp:35 #, kde-format msgid "Capabilities" msgstr "יכולות" #: closejob.cpp:32 #, kde-format msgid "Close" msgstr "סגירה" #: copyjob.cpp:41 #, kde-format msgid "Copy" msgstr "העתקה" #: createjob.cpp:36 #, kde-format msgid "Create" msgstr "יצירה" #: deleteacljob.cpp:37 #, kde-format msgid "DeleteAclJob" msgstr "מחיקת_משימת_ACL" #: deletejob.cpp:36 #, kde-format msgid "Delete" msgstr "מחיקה" #: enablejob.cpp:31 #, kde-format msgid "Enable" msgstr "הפעלה" #: expungejob.cpp:37 #, kde-format msgid "Expunge" msgstr "ניפוי" #: fetchjob.cpp:97 #, kde-format msgid "Fetch" msgstr "משיכה" #: getacljob.cpp:37 #, kde-format msgid "GetAcl" msgstr "משיכת_ACL" #: getmetadatajob.cpp:43 #, kde-format msgid "GetMetaData" msgstr "משיכת_נתוני_על" #: getmetadatajob.cpp:66 #, kde-format msgid "GetAnnotation" msgstr "קבלת_הסבר" #: getquotajob.cpp:35 #, kde-format msgid "GetQuota" msgstr "קבלת_מכסה" #: getquotarootjob.cpp:38 #, kde-format msgid "GetQuotaRoot" msgstr "קבלת_מכסת_שורש" #: idjob.cpp:35 #, kde-format msgid "Id" msgstr "מזהה" #: idlejob.cpp:65 #, kde-format msgctxt "name of the idle job" msgid "Idle" msgstr "בהמתנה" #: job.cpp:19 #, kde-format msgid "Job" msgstr "משימה" #: job.cpp:54 loginjob.cpp:574 #, kde-format msgid "Connection to server lost." msgstr "החיבור לשרת אבד." #: job.cpp:65 loginjob.cpp:403 setmetadatajob.cpp:126 #, kde-format msgid "%1 failed, malformed reply from the server." msgstr "%1 נכשל, תשובה פגומה מהשרת." #: job.cpp:68 loginjob.cpp:277 setmetadatajob.cpp:109 setmetadatajob.cpp:129 #, kde-format msgid "%1 failed, server replied: %2" msgstr "%1 נכשל, תגובת השרת: %2" #: listjob.cpp:59 #, kde-format msgid "List" msgstr "הצגה" #: listrightsjob.cpp:38 #, kde-format msgid "ListRights" msgstr "הצגת_זכויות" #: loginjob.cpp:129 loginjob.cpp:233 #, kde-format msgid "Login" msgstr "כניסה" #: loginjob.cpp:184 #, kde-format msgid "IMAP session in the wrong state for authentication" msgstr "הפעלת ה־IMAP במצב השגוי לאימות" #: loginjob.cpp:235 #, kde-format msgid "Capability" msgstr "יכולת" #: loginjob.cpp:237 #, kde-format msgid "StartTls" msgstr "StartTls" #: loginjob.cpp:340 #, kde-format msgid "STARTTLS is not supported by the server, try using SSL/TLS instead." msgstr "השרת לא תומך ב־STARTTLS, כדאי לנסות להשתמש ב־SSL/TLS במקום." #: loginjob.cpp:353 #, kde-format msgid "Internal error, tried to login before encryption" msgstr "שגיאה פנימית, התבצע ניסיון להיכנס לפני ההצפנה" #: loginjob.cpp:362 #, kde-format msgid "Login failed, plain login is disabled by the server." msgstr "הכניסה נכשלה, כניסה במצב פשוט הושבתה על ידי השרת." #: loginjob.cpp:383 #, kde-format msgid "Login failed, authentication mode %1 is not supported by the server." msgstr "הכניסה נכשלה, מצב האימות %1 לא נתמך על ידי השרת." #: loginjob.cpp:413 #, kde-format msgid "Login failed, client cannot initialize the SASL library." msgstr "הכניסה נכשלה, הלקוח לא יכול להפעיל את ספריית ה־SASL." #: loginjob.cpp:512 #, kde-format msgid "Login failed, TLS negotiation failed." msgstr "הכניסה נכשלה, משא ומתן על TLS נכשל." #: loginjob.cpp:570 #, kde-format msgid "SSL handshake failed." msgstr "לחיצת יד ה־SSL נכשלה." #: logoutjob.cpp:33 #, kde-format msgid "Logout" msgstr "יציאה" #: metadatajobbase.cpp:53 #, kde-format msgid "MetaDataJobBase" msgstr "בסיס_משימת_נתוני_על" #: movejob.cpp:42 #, kde-format msgid "Move" msgstr "העברה" #: myrightsjob.cpp:37 #, kde-format msgid "MyRights" msgstr "הזכויות_שלי" #: namespacejob.cpp:68 #, kde-format msgid "Namespace" msgstr "מרחב_שם" #: quotajobbase.cpp:34 #, kde-format msgid "QuotaJobBase" msgstr "בסיס_משימות_מכסה" #: renamejob.cpp:37 #, kde-format msgid "Rename" msgstr "שינוי_שם" #: searchjob.cpp:361 #, kde-format msgctxt "Name of the search job" msgid "Search" msgstr "חיפוש" #: selectjob.cpp:73 #, kde-format msgctxt "name of the select job" msgid "Select" msgstr "בחירה" #: setacljob.cpp:34 #, kde-format msgid "SetAcl" msgstr "הגדרת_ACL" #: setmetadatajob.cpp:43 #, kde-format msgid "SetMetaData" msgstr "הגדרת_נתוני_על" #: setquotajob.cpp:37 #, kde-format msgid "SetQuota" msgstr "הגדרת_מכסה" #: statusjob.cpp:40 #, kde-format msgctxt "name of the status job" msgid "Status" msgstr "מצב" #: storejob.cpp:70 #, kde-format msgid "Store" msgstr "אחסון" #: subscribejob.cpp:36 #, kde-format msgid "Subscribe" msgstr "מינוי" #: unsubscribejob.cpp:36 #, kde-format msgid "Unsubscribe" msgstr "ביטול_מינוי" 07070100000067000041ED00000000000000000000000266FAD7C000000000000000000000000000000000000000000000002F00000000kimap-VERSIONgit.20240930T185424~db1f697/po/hu07070100000068000081A400000000000000000000000166FAD7C0000018B3000000000000000000000000000000000000003C00000000kimap-VERSIONgit.20240930T185424~db1f697/po/hu/libkimap6.po# Copyright (C) YEAR This_file_is_part_of_KDE # This file is distributed under the same license as the PACKAGE package. # # Tamas Szanto <tszanto@interware.hu>, 2009. # Kristóf Kiszel <ulysses@kubuntu.org>, 2011, 2012, 2014. # Balázs Úr <urbalazs@gmail.com>, 2014. # Kristof Kiszel <ulysses@fsf.hu>, 2022. msgid "" msgstr "" "Project-Id-Version: KDE 4.3\n" "Report-Msgid-Bugs-To: https://bugs.kde.org\n" "POT-Creation-Date: 2022-05-11 00:45+0000\n" "PO-Revision-Date: 2022-02-08 09:29+0100\n" "Last-Translator: Kristof Kiszel <ulysses@fsf.hu>\n" "Language-Team: Hungarian <kde-l10n-hu@kde.org>\n" "Language: hu\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.07.70\n" #: acljobbase.cpp:56 #, kde-format msgid "AclJobBase" msgstr "AclFeladatAlap" #: appendjob.cpp:40 #, kde-format msgid "Append" msgstr "Hozzáfűzés" #: capabilitiesjob.cpp:35 #, kde-format msgid "Capabilities" msgstr "Képességek" #: closejob.cpp:32 #, kde-format msgid "Close" msgstr "Bezárás" #: copyjob.cpp:41 #, kde-format msgid "Copy" msgstr "Másolás" #: createjob.cpp:36 #, kde-format msgid "Create" msgstr "Létrehozás" #: deleteacljob.cpp:37 #, kde-format msgid "DeleteAclJob" msgstr "TörlésAclFeladat" #: deletejob.cpp:36 #, kde-format msgid "Delete" msgstr "Törlés" #: enablejob.cpp:31 #, kde-format msgid "Enable" msgstr "Engedélyezés" #: expungejob.cpp:37 #, kde-format msgid "Expunge" msgstr "Eltávolítás" #: fetchjob.cpp:97 #, kde-format msgid "Fetch" msgstr "Lekérdezés" #: getacljob.cpp:37 #, kde-format msgid "GetAcl" msgstr "LekérdezAcl" #: getmetadatajob.cpp:43 #, kde-format msgid "GetMetaData" msgstr "LekérMetaAdat" #: getmetadatajob.cpp:66 #, kde-format msgid "GetAnnotation" msgstr "LekérMegjegyzés" #: getquotajob.cpp:35 #, kde-format msgid "GetQuota" msgstr "LekérKvóta" #: getquotarootjob.cpp:38 #, kde-format msgid "GetQuotaRoot" msgstr "LekérKvótaGyökér" #: idjob.cpp:35 #, kde-format msgid "Id" msgstr "Azonosító" #: idlejob.cpp:65 #, kde-format msgctxt "name of the idle job" msgid "Idle" msgstr "Inaktív" #: job.cpp:19 #, kde-format msgid "Job" msgstr "Feladat" #: job.cpp:54 loginjob.cpp:574 #, kde-format msgid "Connection to server lost." msgstr "Megszakadt a kapcsolat a kiszolgálóval." #: job.cpp:65 loginjob.cpp:403 setmetadatajob.cpp:126 #, kde-format msgid "%1 failed, malformed reply from the server." msgstr "%1 nem sikerült, hibás válasz érkezett a kiszolgálótól." #: job.cpp:68 loginjob.cpp:277 setmetadatajob.cpp:109 setmetadatajob.cpp:129 #, kde-format msgid "%1 failed, server replied: %2" msgstr "%1 nem sikerült, a kiszolgáló válasza: %2" #: listjob.cpp:59 #, kde-format msgid "List" msgstr "Listázás" #: listrightsjob.cpp:38 #, kde-format msgid "ListRights" msgstr "Jogosultságlista" #: loginjob.cpp:129 loginjob.cpp:233 #, kde-format msgid "Login" msgstr "Bejelentkezés" #: loginjob.cpp:184 #, kde-format msgid "IMAP session in the wrong state for authentication" msgstr "Az IMAP munkamenet rossz állapotban van a hitelesítéshez" #: loginjob.cpp:235 #, kde-format msgid "Capability" msgstr "Képesség" #: loginjob.cpp:237 #, kde-format msgid "StartTls" msgstr "TlsIndítás" #: loginjob.cpp:340 #, kde-format msgid "STARTTLS is not supported by the server, try using SSL/TLS instead." msgstr "" "A kiszolgáló nem támogatja a STARTTLS-t, használjon SSL/TLS-t helyette." #: loginjob.cpp:353 #, kde-format msgid "Internal error, tried to login before encryption" msgstr "Belső hiba, próbáljon bejelentkezni titkosítás előtt" #: loginjob.cpp:362 #, kde-format msgid "Login failed, plain login is disabled by the server." msgstr "" "A bejelentkezés nem sikerült, a kiszolgáló nem engedélyez egyszerű szöveges " "bejelentkezést." #: loginjob.cpp:383 #, kde-format msgid "Login failed, authentication mode %1 is not supported by the server." msgstr "" "A bejelentkezés nem sikerült, a kiszolgáló nem támogatja ezt a " "felhasználóazonosítási módot: %1." #: loginjob.cpp:413 #, kde-format msgid "Login failed, client cannot initialize the SASL library." msgstr "" "A bejelentkezés nem sikerült, a kliens nem tudta inicializálni az SASL-" "programkönyvtárat." #: loginjob.cpp:512 #, kde-format msgid "Login failed, TLS negotiation failed." msgstr "" "A bejelentkezés nem sikerült, a TLS kommunikációt nem sikerült beállítani." #: loginjob.cpp:570 #, kde-format msgid "SSL handshake failed." msgstr "Az SSH kézfogás nem sikerült." #: logoutjob.cpp:33 #, kde-format msgid "Logout" msgstr "Kijelentkezés" #: metadatajobbase.cpp:53 #, kde-format msgid "MetaDataJobBase" msgstr "MetaAdatokFeladatAlap" #: movejob.cpp:42 #, kde-format msgid "Move" msgstr "Áthelyezés" #: myrightsjob.cpp:37 #, kde-format msgid "MyRights" msgstr "SajátJogosultság" #: namespacejob.cpp:68 #, kde-format msgid "Namespace" msgstr "Névtér" #: quotajobbase.cpp:34 #, kde-format msgid "QuotaJobBase" msgstr "KvótaFeladatAlap" #: renamejob.cpp:37 #, kde-format msgid "Rename" msgstr "Átnevezés" #: searchjob.cpp:361 #, kde-format msgctxt "Name of the search job" msgid "Search" msgstr "Keresés" #: selectjob.cpp:73 #, kde-format msgctxt "name of the select job" msgid "Select" msgstr "Kijelölés" #: setacljob.cpp:34 #, kde-format msgid "SetAcl" msgstr "BeállítAcl" #: setmetadatajob.cpp:43 #, kde-format msgid "SetMetaData" msgstr "BeállítMetaAdat" #: setquotajob.cpp:37 #, kde-format msgid "SetQuota" msgstr "BeállítKvóta" #: statusjob.cpp:40 #, kde-format msgctxt "name of the status job" msgid "Status" msgstr "Állapot" #: storejob.cpp:70 #, kde-format msgid "Store" msgstr "Eltárolás" #: subscribejob.cpp:36 #, kde-format msgid "Subscribe" msgstr "Előfizetés" #: unsubscribejob.cpp:36 #, kde-format msgid "Unsubscribe" msgstr "Előfizetés lemondása" #~ msgid "SetAnnotation" #~ msgstr "BeállítMegjegyzés" #~ msgid "Mock" #~ msgstr "Utánzás" #~ msgctxt "NAME OF TRANSLATORS" #~ msgid "Your names" #~ msgstr "Szántó Tamás" #~ msgctxt "EMAIL OF TRANSLATORS" #~ msgid "Your emails" #~ msgstr "tszanto@interware.hu" #, fuzzy #~| msgid "Create" #~ msgctxt "Authentication method" #~ msgid "Clear text" #~ msgstr "Létrehozás" 07070100000069000041ED00000000000000000000000266FAD7C000000000000000000000000000000000000000000000002F00000000kimap-VERSIONgit.20240930T185424~db1f697/po/ia0707010000006A000081A400000000000000000000000166FAD7C00000162E000000000000000000000000000000000000003C00000000kimap-VERSIONgit.20240930T185424~db1f697/po/ia/libkimap6.po# Copyright (C) YEAR This_file_is_part_of_KDE # This file is distributed under the same license as the PACKAGE package. # # g.sora <g.sora@tiscali.it>, 2011, 2012, 2013, 2020, 2022. msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: https://bugs.kde.org\n" "POT-Creation-Date: 2022-05-11 00:45+0000\n" "PO-Revision-Date: 2022-01-29 22:42+0100\n" "Last-Translator: giovanni <g.sora@tiscali.it>\n" "Language-Team: Interlingua <kde-i18n-doc@kde.org>\n" "Language: ia\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Generator: Lokalize 21.12.1\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" #: acljobbase.cpp:56 #, kde-format msgid "AclJobBase" msgstr "AclJobBase (Carga Basic de Acl)" #: appendjob.cpp:40 #, kde-format msgid "Append" msgstr "Adjunge" #: capabilitiesjob.cpp:35 #, kde-format msgid "Capabilities" msgstr "Capabilitates" #: closejob.cpp:32 #, kde-format msgid "Close" msgstr "Claude" #: copyjob.cpp:41 #, kde-format msgid "Copy" msgstr "Copia" #: createjob.cpp:36 #, kde-format msgid "Create" msgstr "Crea" #: deleteacljob.cpp:37 #, kde-format msgid "DeleteAclJob" msgstr "Dele Carga ACL" #: deletejob.cpp:36 #, kde-format msgid "Delete" msgstr "Dele" #: enablejob.cpp:31 #, kde-format msgid "Enable" msgstr "Habilita" #: expungejob.cpp:37 #, kde-format msgid "Expunge" msgstr "Elimina" #: fetchjob.cpp:97 #, kde-format msgid "Fetch" msgstr "Reporta" #: getacljob.cpp:37 #, kde-format msgid "GetAcl" msgstr "Obtene Acl" #: getmetadatajob.cpp:43 #, kde-format msgid "GetMetaData" msgstr "Obtene MetaDatos" #: getmetadatajob.cpp:66 #, kde-format msgid "GetAnnotation" msgstr "Obtene annotation" #: getquotajob.cpp:35 #, kde-format msgid "GetQuota" msgstr "Obtene quota" #: getquotarootjob.cpp:38 #, kde-format msgid "GetQuotaRoot" msgstr "Obtene Radice de quota" #: idjob.cpp:35 #, kde-format msgid "Id" msgstr "id" #: idlejob.cpp:65 #, kde-format msgctxt "name of the idle job" msgid "Idle" msgstr "Inactive" #: job.cpp:19 #, kde-format msgid "Job" msgstr "Carga" #: job.cpp:54 loginjob.cpp:574 #, kde-format msgid "Connection to server lost." msgstr "Connexion a servitor perdite." #: job.cpp:65 loginjob.cpp:403 setmetadatajob.cpp:126 #, kde-format msgid "%1 failed, malformed reply from the server." msgstr "%1 falleva, responsa de mal formato ex le servitor." #: job.cpp:68 loginjob.cpp:277 setmetadatajob.cpp:109 setmetadatajob.cpp:129 #, kde-format msgid "%1 failed, server replied: %2" msgstr "%1 falleva, servitor respondeva: %2" #: listjob.cpp:59 #, kde-format msgid "List" msgstr "Lista" #: listrightsjob.cpp:38 #, kde-format msgid "ListRights" msgstr "Lista Derectos" #: loginjob.cpp:129 loginjob.cpp:233 #, kde-format msgid "Login" msgstr "Accesso de identification" #: loginjob.cpp:184 #, kde-format msgid "IMAP session in the wrong state for authentication" msgstr "Session de IMAP in le stato errate pro authentication" #: loginjob.cpp:235 #, kde-format msgid "Capability" msgstr "Capacitate" #: loginjob.cpp:237 #, kde-format msgid "StartTls" msgstr "Initia Tls" #: loginjob.cpp:340 #, kde-format msgid "STARTTLS is not supported by the server, try using SSL/TLS instead." msgstr "" "STARTTLS non es supportate per le servitor, essaya usante SSL/TLS plus " "tosto." #: loginjob.cpp:353 #, kde-format msgid "Internal error, tried to login before encryption" msgstr "Error interne, essayava authenticar se ante cryptation" #: loginjob.cpp:362 #, kde-format msgid "Login failed, plain login is disabled by the server." msgstr "" "Il falleva accesso de authentication, accesso plan es dishabilitate per le " "servitor." #: loginjob.cpp:383 #, kde-format msgid "Login failed, authentication mode %1 is not supported by the server." msgstr "" "Autorisation fallite, modo de authentication %1 non es supportate per le " "servitor." #: loginjob.cpp:413 #, kde-format msgid "Login failed, client cannot initialize the SASL library." msgstr "" "Authentication falleva, il cliente non pote initialisar le libreria SASL." #: loginjob.cpp:512 #, kde-format msgid "Login failed, TLS negotiation failed." msgstr "Authentication falleva, il falleva negotiation TLS." #: loginjob.cpp:570 #, kde-format msgid "SSL handshake failed." msgstr "Il falleva le handshake de SSL." #: logoutjob.cpp:33 #, kde-format msgid "Logout" msgstr "Clausura de session" #: metadatajobbase.cpp:53 #, kde-format msgid "MetaDataJobBase" msgstr "MetaDataJobBase (carga basic de metadata)" #: movejob.cpp:42 #, kde-format msgid "Move" msgstr "Move" #: myrightsjob.cpp:37 #, kde-format msgid "MyRights" msgstr "MiDerectos" #: namespacejob.cpp:68 #, kde-format msgid "Namespace" msgstr "Nomine de spatio" #: quotajobbase.cpp:34 #, kde-format msgid "QuotaJobBase" msgstr "QuotaJobBase(Carga basic de quota)" #: renamejob.cpp:37 #, kde-format msgid "Rename" msgstr "Renomina" #: searchjob.cpp:361 #, kde-format msgctxt "Name of the search job" msgid "Search" msgstr "Cerca" #: selectjob.cpp:73 #, kde-format msgctxt "name of the select job" msgid "Select" msgstr "Selige" #: setacljob.cpp:34 #, kde-format msgid "SetAcl" msgstr "Fixa Acl" #: setmetadatajob.cpp:43 #, kde-format msgid "SetMetaData" msgstr "Fixa Metadata" #: setquotajob.cpp:37 #, kde-format msgid "SetQuota" msgstr "Fixa Quota" #: statusjob.cpp:40 #, kde-format msgctxt "name of the status job" msgid "Status" msgstr "Stato" #: storejob.cpp:70 #, kde-format msgid "Store" msgstr "Immagazina" #: subscribejob.cpp:36 #, kde-format msgid "Subscribe" msgstr "Subscribe" #: unsubscribejob.cpp:36 #, kde-format msgid "Unsubscribe" msgstr "De-subscribe" #~ msgid "SetAnnotation" #~ msgstr "Fixa Annotation" 0707010000006B000041ED00000000000000000000000266FAD7C000000000000000000000000000000000000000000000002F00000000kimap-VERSIONgit.20240930T185424~db1f697/po/it0707010000006C000081A400000000000000000000000166FAD7C000001675000000000000000000000000000000000000003C00000000kimap-VERSIONgit.20240930T185424~db1f697/po/it/libkimap6.po# translation of libkimap.po to Italian # Copyright (C) YEAR This_file_is_part_of_KDE # This file is distributed under the same license as the PACKAGE package. # Nicola Ruggero <nicola@nxnt.org>, 2009, 2010. # Luigi Toscano <luigi.toscano@tiscali.it>, 2016, 2018, 2022. # msgid "" msgstr "" "Project-Id-Version: libkimap\n" "Report-Msgid-Bugs-To: https://bugs.kde.org\n" "POT-Creation-Date: 2022-05-11 00:45+0000\n" "PO-Revision-Date: 2022-01-29 00:26+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 21.08.0\n" #: acljobbase.cpp:56 #, kde-format msgid "AclJobBase" msgstr "AclJobBase" #: appendjob.cpp:40 #, kde-format msgid "Append" msgstr "Append" #: capabilitiesjob.cpp:35 #, kde-format msgid "Capabilities" msgstr "Capabilities" #: closejob.cpp:32 #, kde-format msgid "Close" msgstr "Close" #: copyjob.cpp:41 #, kde-format msgid "Copy" msgstr "Copy" #: createjob.cpp:36 #, kde-format msgid "Create" msgstr "Create" #: deleteacljob.cpp:37 #, kde-format msgid "DeleteAclJob" msgstr "DeleteAclJob" #: deletejob.cpp:36 #, kde-format msgid "Delete" msgstr "Delete" #: enablejob.cpp:31 #, kde-format msgid "Enable" msgstr "Abilita" #: expungejob.cpp:37 #, kde-format msgid "Expunge" msgstr "Expunge" #: fetchjob.cpp:97 #, kde-format msgid "Fetch" msgstr "Fetch" #: getacljob.cpp:37 #, kde-format msgid "GetAcl" msgstr "GetAcl" #: getmetadatajob.cpp:43 #, kde-format msgid "GetMetaData" msgstr "GetMetaData" #: getmetadatajob.cpp:66 #, kde-format msgid "GetAnnotation" msgstr "GetAnnotation" #: getquotajob.cpp:35 #, kde-format msgid "GetQuota" msgstr "GetQuota" #: getquotarootjob.cpp:38 #, kde-format msgid "GetQuotaRoot" msgstr "GetQuotaRoot" #: idjob.cpp:35 #, kde-format msgid "Id" msgstr "ID" #: idlejob.cpp:65 #, kde-format msgctxt "name of the idle job" msgid "Idle" msgstr "Idle" #: job.cpp:19 #, kde-format msgid "Job" msgstr "Job" #: job.cpp:54 loginjob.cpp:574 #, kde-format msgid "Connection to server lost." msgstr "Connessione al server perduta." #: job.cpp:65 loginjob.cpp:403 setmetadatajob.cpp:126 #, kde-format msgid "%1 failed, malformed reply from the server." msgstr "%1 non riuscito, risposta dal server mal definita." #: job.cpp:68 loginjob.cpp:277 setmetadatajob.cpp:109 setmetadatajob.cpp:129 #, kde-format msgid "%1 failed, server replied: %2" msgstr "%1 non riuscito, il server ha risposto: %2" #: listjob.cpp:59 #, kde-format msgid "List" msgstr "List" #: listrightsjob.cpp:38 #, kde-format msgid "ListRights" msgstr "ListRights" #: loginjob.cpp:129 loginjob.cpp:233 #, kde-format msgid "Login" msgstr "Login" #: loginjob.cpp:184 #, kde-format msgid "IMAP session in the wrong state for authentication" msgstr "Sessione IMAP in uno stato di autenticazione non valido" #: loginjob.cpp:235 #, kde-format msgid "Capability" msgstr "Capability" #: loginjob.cpp:237 #, kde-format msgid "StartTls" msgstr "StartTls" #: loginjob.cpp:340 #, kde-format msgid "STARTTLS is not supported by the server, try using SSL/TLS instead." msgstr "STARTTLS non è supportato dal server, prova in alternativa SSL/TLS." #: loginjob.cpp:353 #, kde-format msgid "Internal error, tried to login before encryption" msgstr "Errore interno, tentativo di login prima della cifratura" #: loginjob.cpp:362 #, kde-format msgid "Login failed, plain login is disabled by the server." msgstr "Accesso non riuscito, l'accesso semplice è disabilitato dal server." #: loginjob.cpp:383 #, kde-format msgid "Login failed, authentication mode %1 is not supported by the server." msgstr "" "Accesso non riuscito, la modalità di autenticazione %1 non è supportata dal " "server." #: loginjob.cpp:413 #, kde-format msgid "Login failed, client cannot initialize the SASL library." msgstr "Accesso non riuscito, impossibile inizializzare la libreria SASL." #: loginjob.cpp:512 #, kde-format msgid "Login failed, TLS negotiation failed." msgstr "Accesso non riuscito, negoziazione TLS non riuscita." #: loginjob.cpp:570 #, kde-format msgid "SSL handshake failed." msgstr "Negoziazione SSL non riuscita." #: logoutjob.cpp:33 #, kde-format msgid "Logout" msgstr "Logout" #: metadatajobbase.cpp:53 #, kde-format msgid "MetaDataJobBase" msgstr "MetaDataJobBase" #: movejob.cpp:42 #, kde-format msgid "Move" msgstr "Sposta" #: myrightsjob.cpp:37 #, kde-format msgid "MyRights" msgstr "MyRights" #: namespacejob.cpp:68 #, kde-format msgid "Namespace" msgstr "Namespace" #: quotajobbase.cpp:34 #, kde-format msgid "QuotaJobBase" msgstr "QuotaJobBase" #: renamejob.cpp:37 #, kde-format msgid "Rename" msgstr "Rename" #: searchjob.cpp:361 #, kde-format msgctxt "Name of the search job" msgid "Search" msgstr "Search" #: selectjob.cpp:73 #, kde-format msgctxt "name of the select job" msgid "Select" msgstr "Select" #: setacljob.cpp:34 #, kde-format msgid "SetAcl" msgstr "SetAcl" #: setmetadatajob.cpp:43 #, kde-format msgid "SetMetaData" msgstr "SetMetaData" #: setquotajob.cpp:37 #, kde-format msgid "SetQuota" msgstr "SetQuota" #: statusjob.cpp:40 #, kde-format msgctxt "name of the status job" msgid "Status" msgstr "Stato" #: storejob.cpp:70 #, kde-format msgid "Store" msgstr "Store" #: subscribejob.cpp:36 #, kde-format msgid "Subscribe" msgstr "Subscribe" #: unsubscribejob.cpp:36 #, kde-format msgid "Unsubscribe" msgstr "Unsubscribe" #~ msgid "SetAnnotation" #~ msgstr "SetAnnotation" #~ msgctxt "NAME OF TRANSLATORS" #~ msgid "Your names" #~ msgstr "Nicola Ruggero" #~ msgctxt "EMAIL OF TRANSLATORS" #~ msgid "Your emails" #~ msgstr "nicola@nxnt.org" 0707010000006D000041ED00000000000000000000000266FAD7C000000000000000000000000000000000000000000000002F00000000kimap-VERSIONgit.20240930T185424~db1f697/po/ja0707010000006E000081A400000000000000000000000166FAD7C000001284000000000000000000000000000000000000003C00000000kimap-VERSIONgit.20240930T185424~db1f697/po/ja/libkimap6.po# Daniel E. Moctezuma <democtezuma@gmail.com>, 2010. msgid "" msgstr "" "Project-Id-Version: libkimap\n" "Report-Msgid-Bugs-To: https://bugs.kde.org\n" "POT-Creation-Date: 2022-05-11 00:45+0000\n" "PO-Revision-Date: 2010-09-25 20:01-0700\n" "Last-Translator: Fumiaki Okushi <okushi@kde.gr.jp>\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=1; plural=0;\n" "X-Accelerator-Marker: &\n" "X-Text-Markup: kde4\n" "X-Generator: Lokalize 1.0\n" #: acljobbase.cpp:56 #, kde-format msgid "AclJobBase" msgstr "" #: appendjob.cpp:40 #, kde-format msgid "Append" msgstr "" #: capabilitiesjob.cpp:35 #, kde-format msgid "Capabilities" msgstr "" #: closejob.cpp:32 #, kde-format msgid "Close" msgstr "閉じる" #: copyjob.cpp:41 #, kde-format msgid "Copy" msgstr "コピー" #: createjob.cpp:36 #, kde-format msgid "Create" msgstr "作成" #: deleteacljob.cpp:37 #, kde-format msgid "DeleteAclJob" msgstr "" #: deletejob.cpp:36 #, kde-format msgid "Delete" msgstr "削除" #: enablejob.cpp:31 #, kde-format msgid "Enable" msgstr "" #: expungejob.cpp:37 #, kde-format msgid "Expunge" msgstr "" #: fetchjob.cpp:97 #, kde-format msgid "Fetch" msgstr "フェッチ" #: getacljob.cpp:37 #, kde-format msgid "GetAcl" msgstr "" #: getmetadatajob.cpp:43 #, kde-format msgid "GetMetaData" msgstr "" #: getmetadatajob.cpp:66 #, kde-format msgid "GetAnnotation" msgstr "" #: getquotajob.cpp:35 #, kde-format msgid "GetQuota" msgstr "" #: getquotarootjob.cpp:38 #, kde-format msgid "GetQuotaRoot" msgstr "" #: idjob.cpp:35 #, kde-format msgid "Id" msgstr "" #: idlejob.cpp:65 #, kde-format msgctxt "name of the idle job" msgid "Idle" msgstr "" #: job.cpp:19 #, kde-format msgid "Job" msgstr "ジョブ" #: job.cpp:54 loginjob.cpp:574 #, kde-format msgid "Connection to server lost." msgstr "サーバへの接続が失われました。" #: job.cpp:65 loginjob.cpp:403 setmetadatajob.cpp:126 #, kde-format msgid "%1 failed, malformed reply from the server." msgstr "%1 に失敗、サーバから不正な応答がありました。" #: job.cpp:68 loginjob.cpp:277 setmetadatajob.cpp:109 setmetadatajob.cpp:129 #, kde-format msgid "%1 failed, server replied: %2" msgstr "%1 に失敗、サーバの返信: %2" #: listjob.cpp:59 #, kde-format msgid "List" msgstr "リスト" #: listrightsjob.cpp:38 #, kde-format msgid "ListRights" msgstr "" #: loginjob.cpp:129 loginjob.cpp:233 #, kde-format msgid "Login" msgstr "ログイン" #: loginjob.cpp:184 #, kde-format msgid "IMAP session in the wrong state for authentication" msgstr "" #: loginjob.cpp:235 #, kde-format msgid "Capability" msgstr "能力" #: loginjob.cpp:237 #, kde-format msgid "StartTls" msgstr "" #: loginjob.cpp:340 #, kde-format msgid "STARTTLS is not supported by the server, try using SSL/TLS instead." msgstr "" #: loginjob.cpp:353 #, kde-format msgid "Internal error, tried to login before encryption" msgstr "" #: loginjob.cpp:362 #, kde-format msgid "Login failed, plain login is disabled by the server." msgstr "" #: loginjob.cpp:383 #, kde-format msgid "Login failed, authentication mode %1 is not supported by the server." msgstr "" #: loginjob.cpp:413 #, kde-format msgid "Login failed, client cannot initialize the SASL library." msgstr "" #: loginjob.cpp:512 #, kde-format msgid "Login failed, TLS negotiation failed." msgstr "" #: loginjob.cpp:570 #, kde-format msgid "SSL handshake failed." msgstr "" #: logoutjob.cpp:33 #, kde-format msgid "Logout" msgstr "ログアウト" #: metadatajobbase.cpp:53 #, kde-format msgid "MetaDataJobBase" msgstr "" #: movejob.cpp:42 #, kde-format msgid "Move" msgstr "" #: myrightsjob.cpp:37 #, kde-format msgid "MyRights" msgstr "" #: namespacejob.cpp:68 #, kde-format msgid "Namespace" msgstr "ネームスペース" #: quotajobbase.cpp:34 #, kde-format msgid "QuotaJobBase" msgstr "" #: renamejob.cpp:37 #, kde-format msgid "Rename" msgstr "名前を変更" #: searchjob.cpp:361 #, kde-format msgctxt "Name of the search job" msgid "Search" msgstr "検索" #: selectjob.cpp:73 #, kde-format msgctxt "name of the select job" msgid "Select" msgstr "選択" #: setacljob.cpp:34 #, kde-format msgid "SetAcl" msgstr "" #: setmetadatajob.cpp:43 #, kde-format msgid "SetMetaData" msgstr "" #: setquotajob.cpp:37 #, kde-format msgid "SetQuota" msgstr "" #: statusjob.cpp:40 #, kde-format msgctxt "name of the status job" msgid "Status" msgstr "" #: storejob.cpp:70 #, kde-format msgid "Store" msgstr "保存" #: subscribejob.cpp:36 #, kde-format msgid "Subscribe" msgstr "購読" #: unsubscribejob.cpp:36 #, kde-format msgid "Unsubscribe" msgstr "購読中止" 0707010000006F000041ED00000000000000000000000266FAD7C000000000000000000000000000000000000000000000002F00000000kimap-VERSIONgit.20240930T185424~db1f697/po/ka07070100000070000081A400000000000000000000000166FAD7C0000019E9000000000000000000000000000000000000003C00000000kimap-VERSIONgit.20240930T185424~db1f697/po/ka/libkimap6.po# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR This file is copyright: # This file is distributed under the same license as the kimap package. # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. # msgid "" msgstr "" "Project-Id-Version: kimap\n" "Report-Msgid-Bugs-To: https://bugs.kde.org\n" "POT-Creation-Date: 2022-05-11 00:45+0000\n" "PO-Revision-Date: 2022-11-27 11:29+0100\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.2\n" #: acljobbase.cpp:56 #, kde-format msgid "AclJobBase" msgstr "AclJobBase" #: appendjob.cpp:40 #, kde-format msgid "Append" msgstr "მიმატება" #: capabilitiesjob.cpp:35 #, kde-format msgid "Capabilities" msgstr "შესაძლებლობები" #: closejob.cpp:32 #, kde-format msgid "Close" msgstr "დახურვა" #: copyjob.cpp:41 #, kde-format msgid "Copy" msgstr "კოპირება" #: createjob.cpp:36 #, kde-format msgid "Create" msgstr "შექმნა" #: deleteacljob.cpp:37 #, kde-format msgid "DeleteAclJob" msgstr "DeleteAclJob" #: deletejob.cpp:36 #, kde-format msgid "Delete" msgstr "წაშლა" #: enablejob.cpp:31 #, kde-format msgid "Enable" msgstr "ჩართვა" #: expungejob.cpp:37 #, kde-format msgid "Expunge" msgstr "Expunge" #: fetchjob.cpp:97 #, kde-format msgid "Fetch" msgstr "გამოთხოვა" #: getacljob.cpp:37 #, kde-format msgid "GetAcl" msgstr "GetAcl" #: getmetadatajob.cpp:43 #, kde-format msgid "GetMetaData" msgstr "GetMetaData" #: getmetadatajob.cpp:66 #, kde-format msgid "GetAnnotation" msgstr "GetAnnotation" #: getquotajob.cpp:35 #, kde-format msgid "GetQuota" msgstr "GetQuota" #: getquotarootjob.cpp:38 #, kde-format msgid "GetQuotaRoot" msgstr "GetQuotaRoot" #: idjob.cpp:35 #, kde-format msgid "Id" msgstr "Id" #: idlejob.cpp:65 #, kde-format msgctxt "name of the idle job" msgid "Idle" msgstr "უმოქმედო" #: job.cpp:19 #, kde-format msgid "Job" msgstr "დავალება" #: job.cpp:54 loginjob.cpp:574 #, kde-format msgid "Connection to server lost." msgstr "სერვერთან კავშირი დაკარგულია." #: job.cpp:65 loginjob.cpp:403 setmetadatajob.cpp:126 #, kde-format msgid "%1 failed, malformed reply from the server." msgstr "%1-ის შეცდომა. სერვერის პასუხი არასწორია." #: job.cpp:68 loginjob.cpp:277 setmetadatajob.cpp:109 setmetadatajob.cpp:129 #, kde-format msgid "%1 failed, server replied: %2" msgstr "%1-ის შეცდომა. სერვერის პასუხია: %2" #: listjob.cpp:59 #, kde-format msgid "List" msgstr "სია" #: listrightsjob.cpp:38 #, kde-format msgid "ListRights" msgstr "ListRights" #: loginjob.cpp:129 loginjob.cpp:233 #, kde-format msgid "Login" msgstr "შესვლა" #: loginjob.cpp:184 #, kde-format msgid "IMAP session in the wrong state for authentication" msgstr "IMAP-ის სესია ავთენტიკაციისთვის არასწორ მდგომარეობაშია" #: loginjob.cpp:235 #, kde-format msgid "Capability" msgstr "შესაძლებლობა" #: loginjob.cpp:237 #, kde-format msgid "StartTls" msgstr "StartTls" #: loginjob.cpp:340 #, kde-format msgid "STARTTLS is not supported by the server, try using SSL/TLS instead." msgstr "STARTTLS მხარდაუჭერელია სერვერის მიერ. სცადეთ SSL/TLS გამოიყენოთ." #: loginjob.cpp:353 #, kde-format msgid "Internal error, tried to login before encryption" msgstr "შიდა შეცდომა. შესვლის მცდელობა დაშიფვრის ჩართვამდე" #: loginjob.cpp:362 #, kde-format msgid "Login failed, plain login is disabled by the server." msgstr "შესვლის შეცდომა. დაუშიფრავი შესვლა გათიშულია." #: loginjob.cpp:383 #, kde-format msgid "Login failed, authentication mode %1 is not supported by the server." msgstr "შესვლის შეცდომა. ავთენტიკაციის რეჟიმი %1 მხარდაუჭერელია სერვერის მიერ." #: loginjob.cpp:413 #, kde-format msgid "Login failed, client cannot initialize the SASL library." msgstr "შესვლის შეცდომა. კლიენტს SASL ბიბლიოთეკის ინიციალიზაცია არ შეუძლია." #: loginjob.cpp:512 #, kde-format msgid "Login failed, TLS negotiation failed." msgstr "შესვლის შეცდომა TLS მიმოცვლის შეცდომა." #: loginjob.cpp:570 #, kde-format msgid "SSL handshake failed." msgstr "SSL მიმოცვლის შეცდომა." #: logoutjob.cpp:33 #, kde-format msgid "Logout" msgstr "გასვლა" #: metadatajobbase.cpp:53 #, kde-format msgid "MetaDataJobBase" msgstr "MetaDataJobBase" #: movejob.cpp:42 #, kde-format msgid "Move" msgstr "გადატანა" #: myrightsjob.cpp:37 #, kde-format msgid "MyRights" msgstr "MyRights" #: namespacejob.cpp:68 #, kde-format msgid "Namespace" msgstr "სახელების სივრცე" #: quotajobbase.cpp:34 #, kde-format msgid "QuotaJobBase" msgstr "QuotaJobBase" #: renamejob.cpp:37 #, kde-format msgid "Rename" msgstr "სახელის გადარქმევა" #: searchjob.cpp:361 #, kde-format msgctxt "Name of the search job" msgid "Search" msgstr "ძებნა" #: selectjob.cpp:73 #, kde-format msgctxt "name of the select job" msgid "Select" msgstr "აირჩიეთ" #: setacljob.cpp:34 #, kde-format msgid "SetAcl" msgstr "SetAcl" #: setmetadatajob.cpp:43 #, kde-format msgid "SetMetaData" msgstr "SetMetaData" #: setquotajob.cpp:37 #, kde-format msgid "SetQuota" msgstr "SetQuota" #: statusjob.cpp:40 #, kde-format msgctxt "name of the status job" msgid "Status" msgstr "მდგომარეობა" #: storejob.cpp:70 #, kde-format msgid "Store" msgstr "მაღაზია" #: subscribejob.cpp:36 #, kde-format msgid "Subscribe" msgstr "ხელმოწერა" #: unsubscribejob.cpp:36 #, kde-format msgid "Unsubscribe" msgstr "გამოწერის გაუქმება" 07070100000071000041ED00000000000000000000000266FAD7C000000000000000000000000000000000000000000000002F00000000kimap-VERSIONgit.20240930T185424~db1f697/po/kk07070100000072000081A400000000000000000000000166FAD7C0000016DA000000000000000000000000000000000000003C00000000kimap-VERSIONgit.20240930T185424~db1f697/po/kk/libkimap6.po# Copyright (C) YEAR This_file_is_part_of_KDE # This file is distributed under the same license as the PACKAGE package. # # Sairan Kikkarin <sairan@computer.org>, 2011. msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: https://bugs.kde.org\n" "POT-Creation-Date: 2022-05-11 00:45+0000\n" "PO-Revision-Date: 2011-02-18 06:48+0600\n" "Last-Translator: Sairan Kikkarin <sairan@computer.org>\n" "Language-Team: Kazakh <kde-i18n-doc@kde.org>\n" "Language: kk\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Generator: Lokalize 1.0\n" "Plural-Forms: nplurals=1; plural=0;\n" #: acljobbase.cpp:56 #, kde-format msgid "AclJobBase" msgstr "AclJobBase" #: appendjob.cpp:40 #, kde-format msgid "Append" msgstr "Жалғау" #: capabilitiesjob.cpp:35 #, kde-format msgid "Capabilities" msgstr "Мүмкіндіктері" #: closejob.cpp:32 #, kde-format msgid "Close" msgstr "Жабу" #: copyjob.cpp:41 #, kde-format msgid "Copy" msgstr "Көшіріп алу" #: createjob.cpp:36 #, kde-format msgid "Create" msgstr "Құрып алу" #: deleteacljob.cpp:37 #, kde-format msgid "DeleteAclJob" msgstr "DeleteAclJob" #: deletejob.cpp:36 #, kde-format msgid "Delete" msgstr "Өшіру" #: enablejob.cpp:31 #, kde-format msgid "Enable" msgstr "" #: expungejob.cpp:37 #, kde-format msgid "Expunge" msgstr "Тазалап шығу" #: fetchjob.cpp:97 #, kde-format msgid "Fetch" msgstr "Алу" #: getacljob.cpp:37 #, kde-format msgid "GetAcl" msgstr "GetAcl" #: getmetadatajob.cpp:43 #, kde-format msgid "GetMetaData" msgstr "GetMetaData" #: getmetadatajob.cpp:66 #, kde-format msgid "GetAnnotation" msgstr "GetAnnotation" #: getquotajob.cpp:35 #, kde-format msgid "GetQuota" msgstr "GetQuota" #: getquotarootjob.cpp:38 #, kde-format msgid "GetQuotaRoot" msgstr "GetQuotaRoot" #: idjob.cpp:35 #, fuzzy, kde-format #| msgctxt "name of the idle job" #| msgid "Idle" msgid "Id" msgstr "Іссіз" #: idlejob.cpp:65 #, kde-format msgctxt "name of the idle job" msgid "Idle" msgstr "Іссіз" #: job.cpp:19 #, kde-format msgid "Job" msgstr "Тапсырма" #: job.cpp:54 loginjob.cpp:574 #, kde-format msgid "Connection to server lost." msgstr "Серверімен байланыс үзілген." #: job.cpp:65 loginjob.cpp:403 setmetadatajob.cpp:126 #, kde-format msgid "%1 failed, malformed reply from the server." msgstr "%1 жаңылысы, серверінен жарамсыз жауап келді." #: job.cpp:68 loginjob.cpp:277 setmetadatajob.cpp:109 setmetadatajob.cpp:129 #, kde-format msgid "%1 failed, server replied: %2" msgstr "%1 жаңылысы, серверінің жауабы: %2" #: listjob.cpp:59 #, kde-format msgid "List" msgstr "Тізім" #: listrightsjob.cpp:38 #, kde-format msgid "ListRights" msgstr "ListRights" #: loginjob.cpp:129 loginjob.cpp:233 #, kde-format msgid "Login" msgstr "Кіру" #: loginjob.cpp:184 #, kde-format msgid "IMAP session in the wrong state for authentication" msgstr "IMAP сеансы аутентификацияны өткізуге лайық күйде емес" #: loginjob.cpp:235 #, kde-format msgid "Capability" msgstr "Мүмкіндіктері" #: loginjob.cpp:237 #, kde-format msgid "StartTls" msgstr "StartTls" #: loginjob.cpp:340 #, kde-format msgid "STARTTLS is not supported by the server, try using SSL/TLS instead." msgstr "" #: loginjob.cpp:353 #, kde-format msgid "Internal error, tried to login before encryption" msgstr "" #: loginjob.cpp:362 #, kde-format msgid "Login failed, plain login is disabled by the server." msgstr "" "Кіру жаңылысы, бұл сервер й (шифрланбаған) паролімен кіруді қабылдамайды" #: loginjob.cpp:383 #, kde-format msgid "Login failed, authentication mode %1 is not supported by the server." msgstr "Кіру жаңылысы, сервері %1 аутентификация режімін танымайды." #: loginjob.cpp:413 #, kde-format msgid "Login failed, client cannot initialize the SASL library." msgstr "" "Кіру жаңылысы, клиент-бағдарламасы SASL жиын файлын.бастау күйіне келтіре " "алмады." #: loginjob.cpp:512 #, kde-format msgid "Login failed, TLS negotiation failed." msgstr "Кіру жаңылысы, TLS - келісу қатесі." #: loginjob.cpp:570 #, kde-format msgid "SSL handshake failed." msgstr "" #: logoutjob.cpp:33 #, kde-format msgid "Logout" msgstr "Шығып кету" #: metadatajobbase.cpp:53 #, kde-format msgid "MetaDataJobBase" msgstr "MetaDataJobBase" #: movejob.cpp:42 #, kde-format msgid "Move" msgstr "" #: myrightsjob.cpp:37 #, kde-format msgid "MyRights" msgstr "MyRights" #: namespacejob.cpp:68 #, kde-format msgid "Namespace" msgstr "Атаулар кеңістігі" #: quotajobbase.cpp:34 #, kde-format msgid "QuotaJobBase" msgstr "QuotaJobBase" #: renamejob.cpp:37 #, kde-format msgid "Rename" msgstr "Атауын өзгерту" #: searchjob.cpp:361 #, kde-format msgctxt "Name of the search job" msgid "Search" msgstr "Іздеу" #: selectjob.cpp:73 #, kde-format msgctxt "name of the select job" msgid "Select" msgstr "Таңдау" #: setacljob.cpp:34 #, kde-format msgid "SetAcl" msgstr "SetAcl" #: setmetadatajob.cpp:43 #, kde-format msgid "SetMetaData" msgstr "SetMetaData" #: setquotajob.cpp:37 #, kde-format msgid "SetQuota" msgstr "SetQuota" #: statusjob.cpp:40 #, kde-format msgctxt "name of the status job" msgid "Status" msgstr "" #: storejob.cpp:70 #, kde-format msgid "Store" msgstr "Сақтау" #: subscribejob.cpp:36 #, kde-format msgid "Subscribe" msgstr "Жазылу" #: unsubscribejob.cpp:36 #, kde-format msgid "Unsubscribe" msgstr "Жазылудан айну" #~ msgid "SetAnnotation" #~ msgstr "SetAnnotation" 07070100000073000041ED00000000000000000000000266FAD7C000000000000000000000000000000000000000000000002F00000000kimap-VERSIONgit.20240930T185424~db1f697/po/km07070100000074000081A400000000000000000000000166FAD7C000001B2C000000000000000000000000000000000000003C00000000kimap-VERSIONgit.20240930T185424~db1f697/po/km/libkimap6.po# translation of libkimap.po to Khmer # Copyright (C) YEAR This_file_is_part_of_KDE # This file is distributed under the same license as the PACKAGE package. # # Khoem Sokhem <khoemsokhem@khmeros.info>, 2009, 2010. # Morn Met, 2010. msgid "" msgstr "" "Project-Id-Version: libkimap\n" "Report-Msgid-Bugs-To: https://bugs.kde.org\n" "POT-Creation-Date: 2022-05-11 00:45+0000\n" "PO-Revision-Date: 2010-06-24 15:47+0700\n" "Last-Translator: Khoem Sokhem <khoemsokhem@khmeros.info>\n" "Language-Team: Khmer <support@khmeros.info>\n" "Language: km\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Generator: KBabel 1.11.4\n" "Plural-Forms: nplurals=1; plural=0;\n" #: acljobbase.cpp:56 #, kde-format msgid "AclJobBase" msgstr "AclJobBase" #: appendjob.cpp:40 #, kde-format msgid "Append" msgstr "បន្ថែមខាងចុង" #: capabilitiesjob.cpp:35 #, kde-format msgid "Capabilities" msgstr "សមត្ថភាព" #: closejob.cpp:32 #, kde-format msgid "Close" msgstr "បិទ" #: copyjob.cpp:41 #, kde-format msgid "Copy" msgstr "ចម្លង" #: createjob.cpp:36 #, kde-format msgid "Create" msgstr "បង្កើត" #: deleteacljob.cpp:37 #, kde-format msgid "DeleteAclJob" msgstr "DeleteAclJob" #: deletejob.cpp:36 #, kde-format msgid "Delete" msgstr "លុប" #: enablejob.cpp:31 #, kde-format msgid "Enable" msgstr "" #: expungejob.cpp:37 #, kde-format msgid "Expunge" msgstr "Expunge" #: fetchjob.cpp:97 #, kde-format msgid "Fetch" msgstr "ទៅយក" #: getacljob.cpp:37 #, kde-format msgid "GetAcl" msgstr "GetAcl" #: getmetadatajob.cpp:43 #, kde-format msgid "GetMetaData" msgstr "GetMetaData" #: getmetadatajob.cpp:66 #, kde-format msgid "GetAnnotation" msgstr "GetAnnotation" #: getquotajob.cpp:35 #, kde-format msgid "GetQuota" msgstr "GetQuota" #: getquotarootjob.cpp:38 #, kde-format msgid "GetQuotaRoot" msgstr "GetQuotaRoot" #: idjob.cpp:35 #, fuzzy, kde-format #| msgctxt "name of the idle job" #| msgid "Idle" msgid "Id" msgstr "ទំនេរ" #: idlejob.cpp:65 #, kde-format msgctxt "name of the idle job" msgid "Idle" msgstr "ទំនេរ" #: job.cpp:19 #, kde-format msgid "Job" msgstr "ការងារ" #: job.cpp:54 loginjob.cpp:574 #, kde-format msgid "Connection to server lost." msgstr "បាត់ការតភ្ជាប់ទៅកាន់ម៉ាស៊ីនបម្រើ ។" #: job.cpp:65 loginjob.cpp:403 setmetadatajob.cpp:126 #, kde-format msgid "%1 failed, malformed reply from the server." msgstr "%1 បានបរាជ័យ ការឆ្លើយតបមិនត្រឹមត្រូវពីម៉ាស៊ីនបម្រើ ។" #: job.cpp:68 loginjob.cpp:277 setmetadatajob.cpp:109 setmetadatajob.cpp:129 #, kde-format msgid "%1 failed, server replied: %2" msgstr "%1 បានបរាជ័យ ម៉ាស៊ីនបម្រើបានឆ្លើយតប ៖ %2" #: listjob.cpp:59 #, kde-format msgid "List" msgstr "បញ្ជី" #: listrightsjob.cpp:38 #, kde-format msgid "ListRights" msgstr "ListRights" #: loginjob.cpp:129 loginjob.cpp:233 #, kde-format msgid "Login" msgstr "ចូល" #: loginjob.cpp:184 #, kde-format msgid "IMAP session in the wrong state for authentication" msgstr "សម័យ IMAP ក្នុងភាពមិនត្រឹមត្រូវសម្រាប់ការផ្ទៀងផ្ទាត់ភាពត្រឹមត្រូវ" #: loginjob.cpp:235 #, kde-format msgid "Capability" msgstr "សមត្ថភាព" #: loginjob.cpp:237 #, kde-format msgid "StartTls" msgstr "StartTls" #: loginjob.cpp:340 #, kde-format msgid "STARTTLS is not supported by the server, try using SSL/TLS instead." msgstr "" #: loginjob.cpp:353 #, kde-format msgid "Internal error, tried to login before encryption" msgstr "" #: loginjob.cpp:362 #, kde-format msgid "Login failed, plain login is disabled by the server." msgstr "បានបរាជ័យក្នុងការចូល ចូលធម្មត្រូវបានបិទដោយម៉ាស៊ីនបម្រើ ។" #: loginjob.cpp:383 #, kde-format msgid "Login failed, authentication mode %1 is not supported by the server." msgstr "បានបរាជ័យក្នុងការចូល របៀបផ្ទៀងផ្ទាត់ភាពត្រឹមត្រូវ %1 មិនត្រូវបានគាំទ្រដោយម៉ាស៊ីនបម្រើទេ ។" #: loginjob.cpp:413 #, kde-format msgid "Login failed, client cannot initialize the SASL library." msgstr "បានបរាជ័យក្នុងការចូល ម៉ាស៊ីនភ្ញៀវមិនអាចចាប់ផ្ដើមបណ្ណាល័យ SASL បានទេ ។" #: loginjob.cpp:512 #, kde-format msgid "Login failed, TLS negotiation failed." msgstr "បានបរាជ័យក្នុងការចូល បានបរាជ័យក្នុងការចរចាររបស់ TLS ។" #: loginjob.cpp:570 #, kde-format msgid "SSL handshake failed." msgstr "" #: logoutjob.cpp:33 #, kde-format msgid "Logout" msgstr "ចេញ" #: metadatajobbase.cpp:53 #, kde-format msgid "MetaDataJobBase" msgstr "MetaDataJobBase" #: movejob.cpp:42 #, kde-format msgid "Move" msgstr "" #: myrightsjob.cpp:37 #, kde-format msgid "MyRights" msgstr "MyRights" #: namespacejob.cpp:68 #, kde-format msgid "Namespace" msgstr "Namespace" #: quotajobbase.cpp:34 #, kde-format msgid "QuotaJobBase" msgstr "QuotaJobBase" #: renamejob.cpp:37 #, kde-format msgid "Rename" msgstr "ប្ដូរឈ្មោះ" #: searchjob.cpp:361 #, kde-format msgctxt "Name of the search job" msgid "Search" msgstr "ស្វែងរក" #: selectjob.cpp:73 #, kde-format msgctxt "name of the select job" msgid "Select" msgstr "ជ្រើស" #: setacljob.cpp:34 #, kde-format msgid "SetAcl" msgstr "SetAcl" #: setmetadatajob.cpp:43 #, kde-format msgid "SetMetaData" msgstr "SetMetaData" #: setquotajob.cpp:37 #, kde-format msgid "SetQuota" msgstr "SetQuota" #: statusjob.cpp:40 #, kde-format msgctxt "name of the status job" msgid "Status" msgstr "" #: storejob.cpp:70 #, kde-format msgid "Store" msgstr "ទុក" #: subscribejob.cpp:36 #, kde-format msgid "Subscribe" msgstr "ជាវ" #: unsubscribejob.cpp:36 #, kde-format msgid "Unsubscribe" msgstr "ឈប់ជាវ" #~ msgid "SetAnnotation" #~ msgstr "SetAnnotation" #~ msgctxt "NAME OF TRANSLATORS" #~ msgid "Your names" #~ msgstr "ខឹម សុខែម,អេង វណ្ណៈ, អោក ពិសិដ្ឋ" #~ msgctxt "EMAIL OF TRANSLATORS" #~ msgid "Your emails" #~ msgstr "khoemsokhem@khmeros.info,vannak@khmeros.info,piseth_dv@khmeros.info" 07070100000075000041ED00000000000000000000000266FAD7C000000000000000000000000000000000000000000000002F00000000kimap-VERSIONgit.20240930T185424~db1f697/po/ko07070100000076000081A400000000000000000000000166FAD7C000001677000000000000000000000000000000000000003C00000000kimap-VERSIONgit.20240930T185424~db1f697/po/ko/libkimap6.po# 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>, 2015, 2016, 2018, 2021, 2022. # msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: https://bugs.kde.org\n" "POT-Creation-Date: 2022-05-11 00:45+0000\n" "PO-Revision-Date: 2022-02-20 22:18+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 21.08.1\n" #: acljobbase.cpp:56 #, kde-format msgid "AclJobBase" msgstr "권한 작업 기반" #: appendjob.cpp:40 #, kde-format msgid "Append" msgstr "덧붙이기" #: capabilitiesjob.cpp:35 #, kde-format msgid "Capabilities" msgstr "사용 가능한 기능" #: closejob.cpp:32 #, kde-format msgid "Close" msgstr "닫기" #: copyjob.cpp:41 #, kde-format msgid "Copy" msgstr "복사" #: createjob.cpp:36 #, kde-format msgid "Create" msgstr "만들기" #: deleteacljob.cpp:37 #, kde-format msgid "DeleteAclJob" msgstr "권한 작업 삭제" #: deletejob.cpp:36 #, kde-format msgid "Delete" msgstr "삭제" #: enablejob.cpp:31 #, kde-format msgid "Enable" msgstr "활성화" #: expungejob.cpp:37 #, kde-format msgid "Expunge" msgstr "비우기" #: fetchjob.cpp:97 #, kde-format msgid "Fetch" msgstr "가져오기" #: getacljob.cpp:37 #, kde-format msgid "GetAcl" msgstr "권한 가져오기" #: getmetadatajob.cpp:43 #, kde-format msgid "GetMetaData" msgstr "메타데이터 가져오기" #: getmetadatajob.cpp:66 #, kde-format msgid "GetAnnotation" msgstr "주석 가져오기" #: getquotajob.cpp:35 #, kde-format msgid "GetQuota" msgstr "할당량 가져오기" #: getquotarootjob.cpp:38 #, kde-format msgid "GetQuotaRoot" msgstr "할당량 루트 가져오기" #: idjob.cpp:35 #, kde-format msgid "Id" msgstr "ID" #: idlejob.cpp:65 #, kde-format msgctxt "name of the idle job" msgid "Idle" msgstr "대기" #: job.cpp:19 #, kde-format msgid "Job" msgstr "작업" #: job.cpp:54 loginjob.cpp:574 #, kde-format msgid "Connection to server lost." msgstr "서버와의 연결이 끊어졌습니다." #: job.cpp:65 loginjob.cpp:403 setmetadatajob.cpp:126 #, kde-format msgid "%1 failed, malformed reply from the server." msgstr "%1 실패. 서버에서 잘못된 응답이 돌아왔습니다." #: job.cpp:68 loginjob.cpp:277 setmetadatajob.cpp:109 setmetadatajob.cpp:129 #, kde-format msgid "%1 failed, server replied: %2" msgstr "%1 실패. 서버 응답: %2" #: listjob.cpp:59 #, kde-format msgid "List" msgstr "목록" #: listrightsjob.cpp:38 #, kde-format msgid "ListRights" msgstr "권한 목록" #: loginjob.cpp:129 loginjob.cpp:233 #, kde-format msgid "Login" msgstr "로그인" #: loginjob.cpp:184 #, kde-format msgid "IMAP session in the wrong state for authentication" msgstr "IMAP 세션이 잘못된 인증 상태에 있음" #: loginjob.cpp:235 #, kde-format msgid "Capability" msgstr "기능" #: loginjob.cpp:237 #, kde-format msgid "StartTls" msgstr "StartTls" #: loginjob.cpp:340 #, kde-format msgid "STARTTLS is not supported by the server, try using SSL/TLS instead." msgstr "서버에서 STARTTLS를 사용할 수 없습니다. SSL/TLS를 사용하십시오." #: loginjob.cpp:353 #, kde-format msgid "Internal error, tried to login before encryption" msgstr "내부 오류, 암호화 전에 로그인을 시도함" #: loginjob.cpp:362 #, kde-format msgid "Login failed, plain login is disabled by the server." msgstr "로그인 실패. 서버에서 로그인을 지원하지 않습니다." #: loginjob.cpp:383 #, kde-format msgid "Login failed, authentication mode %1 is not supported by the server." msgstr "로그인 실패. 서버에서 인증 모드 %1을(를) 지원하지 않습니다." #: loginjob.cpp:413 #, kde-format msgid "Login failed, client cannot initialize the SASL library." msgstr "로그인 실패. 클라이언트가 SASL 라이브러리를 초기화할 수 없습니다." #: loginjob.cpp:512 #, kde-format msgid "Login failed, TLS negotiation failed." msgstr "로그인 실패. TLS 협상이 실패했습니다." #: loginjob.cpp:570 #, kde-format msgid "SSL handshake failed." msgstr "SSL 악수가 실패했습니다." #: logoutjob.cpp:33 #, kde-format msgid "Logout" msgstr "로그아웃" #: metadatajobbase.cpp:53 #, kde-format msgid "MetaDataJobBase" msgstr "메타데이터 작업 기반" #: movejob.cpp:42 #, kde-format msgid "Move" msgstr "이동" #: myrightsjob.cpp:37 #, kde-format msgid "MyRights" msgstr "내 권한" #: namespacejob.cpp:68 #, kde-format msgid "Namespace" msgstr "네임스페이스" #: quotajobbase.cpp:34 #, kde-format msgid "QuotaJobBase" msgstr "할당량 작업 기본" #: renamejob.cpp:37 #, kde-format msgid "Rename" msgstr "이름 바꾸기" #: searchjob.cpp:361 #, kde-format msgctxt "Name of the search job" msgid "Search" msgstr "찾기" #: selectjob.cpp:73 #, kde-format msgctxt "name of the select job" msgid "Select" msgstr "선택" #: setacljob.cpp:34 #, kde-format msgid "SetAcl" msgstr "접근 권한 설정" #: setmetadatajob.cpp:43 #, kde-format msgid "SetMetaData" msgstr "메타데이터 설정" #: setquotajob.cpp:37 #, kde-format msgid "SetQuota" msgstr "할당량 설정" #: statusjob.cpp:40 #, kde-format msgctxt "name of the status job" msgid "Status" msgstr "상태" #: storejob.cpp:70 #, kde-format msgid "Store" msgstr "저장" #: subscribejob.cpp:36 #, kde-format msgid "Subscribe" msgstr "구독" #: unsubscribejob.cpp:36 #, kde-format msgid "Unsubscribe" msgstr "구독해제" #~ msgid "SetAnnotation" #~ msgstr "주석 설정" #~ msgid "Mock" #~ msgstr "가짜" 07070100000077000041ED00000000000000000000000266FAD7C000000000000000000000000000000000000000000000002F00000000kimap-VERSIONgit.20240930T185424~db1f697/po/lt07070100000078000081A400000000000000000000000166FAD7C0000015DA000000000000000000000000000000000000003C00000000kimap-VERSIONgit.20240930T185424~db1f697/po/lt/libkimap6.po# Lithuanian translations for libkimap package. # This file is distributed under the same license as the libkimap package. # # Remigijus Jarmalavičius <remigijus@jarmalavicius.lt>, 2011. # Liudas Ališauskas <liudas@aksioma.lt>, 2014, 2015. msgid "" msgstr "" "Project-Id-Version: libkimap\n" "Report-Msgid-Bugs-To: https://bugs.kde.org\n" "POT-Creation-Date: 2022-05-11 00:45+0000\n" "PO-Revision-Date: 2015-08-30 15:56+0200\n" "Last-Translator: Liudas Ališauskas <liudas@akmc.lt>\n" "Language-Team: Lithuanian <kde-i18n-lt@kde.org>\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" "X-Generator: Lokalize 2.0\n" #: acljobbase.cpp:56 #, kde-format msgid "AclJobBase" msgstr "AclJobBase" #: appendjob.cpp:40 #, kde-format msgid "Append" msgstr "Papildyti" #: capabilitiesjob.cpp:35 #, kde-format msgid "Capabilities" msgstr "Galimybės" #: closejob.cpp:32 #, kde-format msgid "Close" msgstr "Užverti" #: copyjob.cpp:41 #, kde-format msgid "Copy" msgstr "Kopijuoti" #: createjob.cpp:36 #, kde-format msgid "Create" msgstr "Sukurti" #: deleteacljob.cpp:37 #, kde-format msgid "DeleteAclJob" msgstr "DeleteAclJob" #: deletejob.cpp:36 #, kde-format msgid "Delete" msgstr "Trinti" #: enablejob.cpp:31 #, kde-format msgid "Enable" msgstr "" #: expungejob.cpp:37 #, kde-format msgid "Expunge" msgstr "Išvalyti" #: fetchjob.cpp:97 #, kde-format msgid "Fetch" msgstr "Gauti" #: getacljob.cpp:37 #, kde-format msgid "GetAcl" msgstr "GetAcl" #: getmetadatajob.cpp:43 #, kde-format msgid "GetMetaData" msgstr "GetMetaData" #: getmetadatajob.cpp:66 #, kde-format msgid "GetAnnotation" msgstr "GetAnnotation" #: getquotajob.cpp:35 #, kde-format msgid "GetQuota" msgstr "GetQuota" #: getquotarootjob.cpp:38 #, kde-format msgid "GetQuotaRoot" msgstr "GetQuotaRoot" #: idjob.cpp:35 #, fuzzy, kde-format #| msgctxt "name of the idle job" #| msgid "Idle" msgid "Id" msgstr "Be darbo" #: idlejob.cpp:65 #, kde-format msgctxt "name of the idle job" msgid "Idle" msgstr "Be darbo" #: job.cpp:19 #, kde-format msgid "Job" msgstr "Darbas" #: job.cpp:54 loginjob.cpp:574 #, kde-format msgid "Connection to server lost." msgstr "Ryšys su serveriu prarastas." #: job.cpp:65 loginjob.cpp:403 setmetadatajob.cpp:126 #, kde-format msgid "%1 failed, malformed reply from the server." msgstr "%1 nepavyko, klaidingai suformuotas atsakymas iš serverio." #: job.cpp:68 loginjob.cpp:277 setmetadatajob.cpp:109 setmetadatajob.cpp:129 #, kde-format msgid "%1 failed, server replied: %2" msgstr "%1 nepavyko, serverio atsakymas: %2" #: listjob.cpp:59 #, kde-format msgid "List" msgstr "Sąrašas" #: listrightsjob.cpp:38 #, kde-format msgid "ListRights" msgstr "ListRights" #: loginjob.cpp:129 loginjob.cpp:233 #, kde-format msgid "Login" msgstr "Prisijungti" #: loginjob.cpp:184 #, kde-format msgid "IMAP session in the wrong state for authentication" msgstr "IMAP sesija netinkamoje būsenoje kad autentifikuotis" #: loginjob.cpp:235 #, kde-format msgid "Capability" msgstr "Galimybė" #: loginjob.cpp:237 #, kde-format msgid "StartTls" msgstr "StartTls" #: loginjob.cpp:340 #, kde-format msgid "STARTTLS is not supported by the server, try using SSL/TLS instead." msgstr "" #: loginjob.cpp:353 #, kde-format msgid "Internal error, tried to login before encryption" msgstr "" #: loginjob.cpp:362 #, kde-format msgid "Login failed, plain login is disabled by the server." msgstr "" "Prisijungimas nepavyko, prisijungimas atviru tekstu išjungtas serveryje." #: loginjob.cpp:383 #, kde-format msgid "Login failed, authentication mode %1 is not supported by the server." msgstr "" "Prisijungimas nepavyko, autentikacijos metodas %1 nepalaikomas serverio." #: loginjob.cpp:413 #, kde-format msgid "Login failed, client cannot initialize the SASL library." msgstr "" "Prisijungimas nepavyko, klientui nepavyksta inicializuoti SASL bibliotekos." #: loginjob.cpp:512 #, kde-format msgid "Login failed, TLS negotiation failed." msgstr "Prisijungti nepavyko. TLS derybos nepavyko." #: loginjob.cpp:570 #, kde-format msgid "SSL handshake failed." msgstr "SSL derybos nepavyko." #: logoutjob.cpp:33 #, kde-format msgid "Logout" msgstr "Atsijungti" #: metadatajobbase.cpp:53 #, kde-format msgid "MetaDataJobBase" msgstr "MetaDataJobBase" #: movejob.cpp:42 #, kde-format msgid "Move" msgstr "" #: myrightsjob.cpp:37 #, kde-format msgid "MyRights" msgstr "MyRights" #: namespacejob.cpp:68 #, kde-format msgid "Namespace" msgstr "Vardų zona" #: quotajobbase.cpp:34 #, kde-format msgid "QuotaJobBase" msgstr "QuotaJobBase" #: renamejob.cpp:37 #, kde-format msgid "Rename" msgstr "Pervadinti" #: searchjob.cpp:361 #, kde-format msgctxt "Name of the search job" msgid "Search" msgstr "Ieškoti" #: selectjob.cpp:73 #, kde-format msgctxt "name of the select job" msgid "Select" msgstr "Žymėti" #: setacljob.cpp:34 #, kde-format msgid "SetAcl" msgstr "SetAcl" #: setmetadatajob.cpp:43 #, kde-format msgid "SetMetaData" msgstr "SetMetaData" #: setquotajob.cpp:37 #, kde-format msgid "SetQuota" msgstr "SetQuota" #: statusjob.cpp:40 #, kde-format msgctxt "name of the status job" msgid "Status" msgstr "" #: storejob.cpp:70 #, kde-format msgid "Store" msgstr "Saugoti" #: subscribejob.cpp:36 #, kde-format msgid "Subscribe" msgstr "Prenumeruoti" #: unsubscribejob.cpp:36 #, kde-format msgid "Unsubscribe" msgstr "Nebeprenumeruoti" #~ msgid "SetAnnotation" #~ msgstr "SetAnnotation" 07070100000079000041ED00000000000000000000000266FAD7C000000000000000000000000000000000000000000000002F00000000kimap-VERSIONgit.20240930T185424~db1f697/po/lv0707010000007A000081A400000000000000000000000166FAD7C000001716000000000000000000000000000000000000003C00000000kimap-VERSIONgit.20240930T185424~db1f697/po/lv/libkimap6.po# Copyright (C) YEAR This_file_is_part_of_KDE # This file is distributed under the same license as the PACKAGE package. # # SPDX-FileCopyrightText: 2024 Toms Trasūns <toms.trasuns@posteo.net> # Viesturs Zariņš <viesturs.zarins@mii.lu.lv>, 2009. # Viesturs Zarins <viesturs.zarins@mii.lu.lv>, 2010. # Māris Nartišs <maris.kde@gmail.com>, 2024. msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: https://bugs.kde.org\n" "POT-Creation-Date: 2022-05-11 00:45+0000\n" "PO-Revision-Date: 2024-01-27 16:20+0200\n" "Last-Translator: Māris Nartišs <maris.kde@gmail.com>\n" "Language-Team: \n" "Language: lv\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Generator: Lokalize 22.12.3\n" "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : " "2);\n" #: acljobbase.cpp:56 #, kde-format msgid "AclJobBase" msgstr "AclJobBase" #: appendjob.cpp:40 #, kde-format msgid "Append" msgstr "Pievienot" #: capabilitiesjob.cpp:35 #, kde-format msgid "Capabilities" msgstr "Iespējas" #: closejob.cpp:32 #, kde-format msgid "Close" msgstr "Aizvērt" #: copyjob.cpp:41 #, kde-format msgid "Copy" msgstr "Kopēt" #: createjob.cpp:36 #, kde-format msgid "Create" msgstr "Izveidot" #: deleteacljob.cpp:37 #, kde-format msgid "DeleteAclJob" msgstr "DeleteAclJob" #: deletejob.cpp:36 #, kde-format msgid "Delete" msgstr "Dzēst" #: enablejob.cpp:31 #, kde-format msgid "Enable" msgstr "Ieslēgt" #: expungejob.cpp:37 #, kde-format msgid "Expunge" msgstr "Izmest" #: fetchjob.cpp:97 #, kde-format msgid "Fetch" msgstr "Ielādēt" #: getacljob.cpp:37 #, kde-format msgid "GetAcl" msgstr "GetAcl" #: getmetadatajob.cpp:43 #, kde-format msgid "GetMetaData" msgstr "GetMetaData" #: getmetadatajob.cpp:66 #, kde-format msgid "GetAnnotation" msgstr "GetAnnotation" #: getquotajob.cpp:35 #, kde-format msgid "GetQuota" msgstr "GetQuota" #: getquotarootjob.cpp:38 #, kde-format msgid "GetQuotaRoot" msgstr "GetQuotaRoot" #: idjob.cpp:35 #, kde-format msgid "Id" msgstr "ID" #: idlejob.cpp:65 #, kde-format msgctxt "name of the idle job" msgid "Idle" msgstr "Dīkstāve" #: job.cpp:19 #, kde-format msgid "Job" msgstr "Darbs" #: job.cpp:54 loginjob.cpp:574 #, kde-format msgid "Connection to server lost." msgstr "Zudis savienojums ar serveri." #: job.cpp:65 loginjob.cpp:403 setmetadatajob.cpp:126 #, kde-format msgid "%1 failed, malformed reply from the server." msgstr "%1 kļūda, nekorekta atbilde no servera." #: job.cpp:68 loginjob.cpp:277 setmetadatajob.cpp:109 setmetadatajob.cpp:129 #, kde-format msgid "%1 failed, server replied: %2" msgstr "%1 kļūda, serveris atbildēja: %2" #: listjob.cpp:59 #, kde-format msgid "List" msgstr "Saraksts" #: listrightsjob.cpp:38 #, kde-format msgid "ListRights" msgstr "ListRights" #: loginjob.cpp:129 loginjob.cpp:233 #, kde-format msgid "Login" msgstr "Ierakstīties" #: loginjob.cpp:184 #, kde-format msgid "IMAP session in the wrong state for authentication" msgstr "IMAP sesija atrodas nepareizā autentifikācijas stāvoklī" #: loginjob.cpp:235 #, kde-format msgid "Capability" msgstr "Iespēja" #: loginjob.cpp:237 #, kde-format msgid "StartTls" msgstr "StartTls" #: loginjob.cpp:340 #, kde-format msgid "STARTTLS is not supported by the server, try using SSL/TLS instead." msgstr "Serveris neatbalsta STARTTLS, mēģiniet tā vietā SSL/TLS." #: loginjob.cpp:353 #, kde-format msgid "Internal error, tried to login before encryption" msgstr "Iekšēja kļūda, mēģināja ierakstīties pirms šifrēšanas" #: loginjob.cpp:362 #, kde-format msgid "Login failed, plain login is disabled by the server." msgstr "" "Neizdevās ierakstīties, serveris neatbalsta vienkārša teksta ierakstīšanos." #: loginjob.cpp:383 #, kde-format msgid "Login failed, authentication mode %1 is not supported by the server." msgstr "" "Neizdevās ierakstīties, serveris neatbalsta autentificēšanas režīmu „%1“." #: loginjob.cpp:413 #, kde-format msgid "Login failed, client cannot initialize the SASL library." msgstr "Neizdevās ierakstīties, klients nevarēja inicializēt SASL bibliotēku." #: loginjob.cpp:512 #, kde-format msgid "Login failed, TLS negotiation failed." msgstr "Neizdevās ierakstīties, neveiksmīga TLS vienošanās." #: loginjob.cpp:570 #, kde-format msgid "SSL handshake failed." msgstr "SSL rokasspiediens neizdevās." #: logoutjob.cpp:33 #, kde-format msgid "Logout" msgstr "Izrakstīties" #: metadatajobbase.cpp:53 #, kde-format msgid "MetaDataJobBase" msgstr "MetaDataJobBase" #: movejob.cpp:42 #, kde-format msgid "Move" msgstr "Pārvietot" #: myrightsjob.cpp:37 #, kde-format msgid "MyRights" msgstr "MyRights" #: namespacejob.cpp:68 #, kde-format msgid "Namespace" msgstr "Nosaukumvieta" #: quotajobbase.cpp:34 #, kde-format msgid "QuotaJobBase" msgstr "QuotaJobBase" #: renamejob.cpp:37 #, kde-format msgid "Rename" msgstr "Pārdēvēt" #: searchjob.cpp:361 #, kde-format msgctxt "Name of the search job" msgid "Search" msgstr "Meklēt" #: selectjob.cpp:73 #, kde-format msgctxt "name of the select job" msgid "Select" msgstr "Atlasīt" #: setacljob.cpp:34 #, kde-format msgid "SetAcl" msgstr "SetAcl" #: setmetadatajob.cpp:43 #, kde-format msgid "SetMetaData" msgstr "SetMetaData" #: setquotajob.cpp:37 #, kde-format msgid "SetQuota" msgstr "SetQuota" #: statusjob.cpp:40 #, kde-format msgctxt "name of the status job" msgid "Status" msgstr "Statuss" #: storejob.cpp:70 #, kde-format msgid "Store" msgstr "Saglabāt" #: subscribejob.cpp:36 #, kde-format msgid "Subscribe" msgstr "Abonēt" #: unsubscribejob.cpp:36 #, kde-format msgid "Unsubscribe" msgstr "Anulēt abonementu" #~ msgid "SetAnnotation" #~ msgstr "SetAnnotation" #~ msgctxt "NAME OF TRANSLATORS" #~ msgid "Your names" #~ msgstr "Viesturs Zariņš" #~ msgctxt "EMAIL OF TRANSLATORS" #~ msgid "Your emails" #~ msgstr "viesturs.zarins@mii.lu.lv" 0707010000007B000041ED00000000000000000000000266FAD7C000000000000000000000000000000000000000000000002F00000000kimap-VERSIONgit.20240930T185424~db1f697/po/mr0707010000007C000081A400000000000000000000000166FAD7C000001318000000000000000000000000000000000000003C00000000kimap-VERSIONgit.20240930T185424~db1f697/po/mr/libkimap6.po# Copyright (C) YEAR This_file_is_part_of_KDE # This file is distributed under the same license as the PACKAGE package. # # Chetan Khona <chetan@kompkin.com>, 2013. msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: https://bugs.kde.org\n" "POT-Creation-Date: 2022-05-11 00:45+0000\n" "PO-Revision-Date: 2013-03-13 15:14+0530\n" "Last-Translator: Chetan Khona <chetan@kompkin.com>\n" "Language-Team: Marathi <kde-i18n-doc@kde.org>\n" "Language: mr\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 1.5\n" #: acljobbase.cpp:56 #, kde-format msgid "AclJobBase" msgstr "" #: appendjob.cpp:40 #, kde-format msgid "Append" msgstr "" #: capabilitiesjob.cpp:35 #, kde-format msgid "Capabilities" msgstr "क्षमता" #: closejob.cpp:32 #, kde-format msgid "Close" msgstr "बंद करा" #: copyjob.cpp:41 #, kde-format msgid "Copy" msgstr "प्रत करा" #: createjob.cpp:36 #, kde-format msgid "Create" msgstr "निर्माण करा" #: deleteacljob.cpp:37 #, kde-format msgid "DeleteAclJob" msgstr "" #: deletejob.cpp:36 #, kde-format msgid "Delete" msgstr "काढून टाका" #: enablejob.cpp:31 #, kde-format msgid "Enable" msgstr "" #: expungejob.cpp:37 #, kde-format msgid "Expunge" msgstr "" #: fetchjob.cpp:97 #, kde-format msgid "Fetch" msgstr "" #: getacljob.cpp:37 #, kde-format msgid "GetAcl" msgstr "" #: getmetadatajob.cpp:43 #, kde-format msgid "GetMetaData" msgstr "" #: getmetadatajob.cpp:66 #, kde-format msgid "GetAnnotation" msgstr "" #: getquotajob.cpp:35 #, kde-format msgid "GetQuota" msgstr "" #: getquotarootjob.cpp:38 #, kde-format msgid "GetQuotaRoot" msgstr "" #: idjob.cpp:35 #, fuzzy, kde-format #| msgctxt "name of the idle job" #| msgid "Idle" msgid "Id" msgstr "रिकामे" #: idlejob.cpp:65 #, kde-format msgctxt "name of the idle job" msgid "Idle" msgstr "रिकामे" #: job.cpp:19 #, kde-format msgid "Job" msgstr "कार्य" #: job.cpp:54 loginjob.cpp:574 #, kde-format msgid "Connection to server lost." msgstr "" #: job.cpp:65 loginjob.cpp:403 setmetadatajob.cpp:126 #, kde-format msgid "%1 failed, malformed reply from the server." msgstr "" #: job.cpp:68 loginjob.cpp:277 setmetadatajob.cpp:109 setmetadatajob.cpp:129 #, kde-format msgid "%1 failed, server replied: %2" msgstr "" #: listjob.cpp:59 #, kde-format msgid "List" msgstr "यादी" #: listrightsjob.cpp:38 #, kde-format msgid "ListRights" msgstr "" #: loginjob.cpp:129 loginjob.cpp:233 #, kde-format msgid "Login" msgstr "प्रवेश" #: loginjob.cpp:184 #, kde-format msgid "IMAP session in the wrong state for authentication" msgstr "" #: loginjob.cpp:235 #, kde-format msgid "Capability" msgstr "" #: loginjob.cpp:237 #, kde-format msgid "StartTls" msgstr "" #: loginjob.cpp:340 #, kde-format msgid "STARTTLS is not supported by the server, try using SSL/TLS instead." msgstr "" #: loginjob.cpp:353 #, kde-format msgid "Internal error, tried to login before encryption" msgstr "" #: loginjob.cpp:362 #, kde-format msgid "Login failed, plain login is disabled by the server." msgstr "" #: loginjob.cpp:383 #, kde-format msgid "Login failed, authentication mode %1 is not supported by the server." msgstr "" #: loginjob.cpp:413 #, kde-format msgid "Login failed, client cannot initialize the SASL library." msgstr "" #: loginjob.cpp:512 #, kde-format msgid "Login failed, TLS negotiation failed." msgstr "" #: loginjob.cpp:570 #, kde-format msgid "SSL handshake failed." msgstr "" #: logoutjob.cpp:33 #, kde-format msgid "Logout" msgstr "बाहेर पडा" #: metadatajobbase.cpp:53 #, kde-format msgid "MetaDataJobBase" msgstr "" #: movejob.cpp:42 #, kde-format msgid "Move" msgstr "" #: myrightsjob.cpp:37 #, kde-format msgid "MyRights" msgstr "" #: namespacejob.cpp:68 #, kde-format msgid "Namespace" msgstr "नेमस्पेस" #: quotajobbase.cpp:34 #, kde-format msgid "QuotaJobBase" msgstr "" #: renamejob.cpp:37 #, kde-format msgid "Rename" msgstr "नाव बदला" #: searchjob.cpp:361 #, kde-format msgctxt "Name of the search job" msgid "Search" msgstr "शोधा" #: selectjob.cpp:73 #, kde-format msgctxt "name of the select job" msgid "Select" msgstr "निवडा" #: setacljob.cpp:34 #, kde-format msgid "SetAcl" msgstr "" #: setmetadatajob.cpp:43 #, kde-format msgid "SetMetaData" msgstr "" #: setquotajob.cpp:37 #, kde-format msgid "SetQuota" msgstr "" #: statusjob.cpp:40 #, kde-format msgctxt "name of the status job" msgid "Status" msgstr "" #: storejob.cpp:70 #, kde-format msgid "Store" msgstr "संचयन" #: subscribejob.cpp:36 #, kde-format msgid "Subscribe" msgstr "सबस्क्राइब" #: unsubscribejob.cpp:36 #, kde-format msgid "Unsubscribe" msgstr "" 0707010000007D000041ED00000000000000000000000266FAD7C000000000000000000000000000000000000000000000002F00000000kimap-VERSIONgit.20240930T185424~db1f697/po/nb0707010000007E000081A400000000000000000000000166FAD7C00000149D000000000000000000000000000000000000003C00000000kimap-VERSIONgit.20240930T185424~db1f697/po/nb/libkimap6.po# Translation of libkimap6 to Norwegian Bokmål # # Bjørn Steensrud <bjornst@skogkatt.homelinux.org>, 2009, 2010, 2014. msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: https://bugs.kde.org\n" "POT-Creation-Date: 2022-05-11 00:45+0000\n" "PO-Revision-Date: 2014-09-23 22:05+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" #: acljobbase.cpp:56 #, kde-format msgid "AclJobBase" msgstr "AclJobBase" #: appendjob.cpp:40 #, kde-format msgid "Append" msgstr "Legg til" #: capabilitiesjob.cpp:35 #, kde-format msgid "Capabilities" msgstr "Muligheter" #: closejob.cpp:32 #, kde-format msgid "Close" msgstr "Lukk" #: copyjob.cpp:41 #, kde-format msgid "Copy" msgstr "Kopier" #: createjob.cpp:36 #, kde-format msgid "Create" msgstr "Opprett" #: deleteacljob.cpp:37 #, kde-format msgid "DeleteAclJob" msgstr "DeleteAclJob" #: deletejob.cpp:36 #, kde-format msgid "Delete" msgstr "Slett" #: enablejob.cpp:31 #, kde-format msgid "Enable" msgstr "" #: expungejob.cpp:37 #, kde-format msgid "Expunge" msgstr "Slett fullstendig" #: fetchjob.cpp:97 #, kde-format msgid "Fetch" msgstr "Hent" #: getacljob.cpp:37 #, kde-format msgid "GetAcl" msgstr "GetAcl" #: getmetadatajob.cpp:43 #, kde-format msgid "GetMetaData" msgstr "GetMetaData" #: getmetadatajob.cpp:66 #, kde-format msgid "GetAnnotation" msgstr "GetAnnotation" #: getquotajob.cpp:35 #, kde-format msgid "GetQuota" msgstr "GetQuota" #: getquotarootjob.cpp:38 #, kde-format msgid "GetQuotaRoot" msgstr "GetQuotaRoot" #: idjob.cpp:35 #, kde-format msgid "Id" msgstr "" #: idlejob.cpp:65 #, kde-format msgctxt "name of the idle job" msgid "Idle" msgstr "Inaktiv" #: job.cpp:19 #, kde-format msgid "Job" msgstr "Jobb" #: job.cpp:54 loginjob.cpp:574 #, kde-format msgid "Connection to server lost." msgstr "Tilkobling til tjeneren er tapt." #: job.cpp:65 loginjob.cpp:403 setmetadatajob.cpp:126 #, kde-format msgid "%1 failed, malformed reply from the server." msgstr "%1 mislyktes, feil i svar fra tjeneren." #: job.cpp:68 loginjob.cpp:277 setmetadatajob.cpp:109 setmetadatajob.cpp:129 #, kde-format msgid "%1 failed, server replied: %2" msgstr "%1 mislyktes, tjeneren svarte: %2" #: listjob.cpp:59 #, kde-format msgid "List" msgstr "List" #: listrightsjob.cpp:38 #, kde-format msgid "ListRights" msgstr "ListRights" #: loginjob.cpp:129 loginjob.cpp:233 #, kde-format msgid "Login" msgstr "Logg inn" #: loginjob.cpp:184 #, kde-format msgid "IMAP session in the wrong state for authentication" msgstr "IMAP-økta er i feil tilstand for autentisering" #: loginjob.cpp:235 #, kde-format msgid "Capability" msgstr "Mulighet" #: loginjob.cpp:237 #, kde-format msgid "StartTls" msgstr "StartTls" #: loginjob.cpp:340 #, kde-format msgid "STARTTLS is not supported by the server, try using SSL/TLS instead." msgstr "" #: loginjob.cpp:353 #, kde-format msgid "Internal error, tried to login before encryption" msgstr "" #: loginjob.cpp:362 #, kde-format msgid "Login failed, plain login is disabled by the server." msgstr "Innlogging mislyktes, tjeneren tillater ikke enkel innlogging." #: loginjob.cpp:383 #, kde-format msgid "Login failed, authentication mode %1 is not supported by the server." msgstr "Innlogging mislyktes, tjeneren støtter ikke autentiseringsmåte %1." #: loginjob.cpp:413 #, kde-format msgid "Login failed, client cannot initialize the SASL library." msgstr "Innlogging mislyktes, klienten kan ikke klargjøre SASL-biblioteket." #: loginjob.cpp:512 #, kde-format msgid "Login failed, TLS negotiation failed." msgstr "Innlogging mislyktes, TLS-forhandling lyktes ikke." #: loginjob.cpp:570 #, kde-format msgid "SSL handshake failed." msgstr "SSL-håndtryk mislyktes." #: logoutjob.cpp:33 #, kde-format msgid "Logout" msgstr "Logg ut" #: metadatajobbase.cpp:53 #, kde-format msgid "MetaDataJobBase" msgstr "MetaDataJobBase" #: movejob.cpp:42 #, kde-format msgid "Move" msgstr "" #: myrightsjob.cpp:37 #, kde-format msgid "MyRights" msgstr "MyRights" #: namespacejob.cpp:68 #, kde-format msgid "Namespace" msgstr "Navnerom" #: quotajobbase.cpp:34 #, kde-format msgid "QuotaJobBase" msgstr "QuotaJobBase" #: renamejob.cpp:37 #, kde-format msgid "Rename" msgstr "Endre navn" #: searchjob.cpp:361 #, kde-format msgctxt "Name of the search job" msgid "Search" msgstr "Søk" #: selectjob.cpp:73 #, kde-format msgctxt "name of the select job" msgid "Select" msgstr "Velg" #: setacljob.cpp:34 #, kde-format msgid "SetAcl" msgstr "SetAcl" #: setmetadatajob.cpp:43 #, kde-format msgid "SetMetaData" msgstr "SetMetaData" #: setquotajob.cpp:37 #, kde-format msgid "SetQuota" msgstr "SetQuota" #: statusjob.cpp:40 #, kde-format msgctxt "name of the status job" msgid "Status" msgstr "" #: storejob.cpp:70 #, kde-format msgid "Store" msgstr "Lagre" #: subscribejob.cpp:36 #, kde-format msgid "Subscribe" msgstr "Abonner" #: unsubscribejob.cpp:36 #, kde-format msgid "Unsubscribe" msgstr "Stopp abonnement" 0707010000007F000041ED00000000000000000000000266FAD7C000000000000000000000000000000000000000000000003000000000kimap-VERSIONgit.20240930T185424~db1f697/po/nds07070100000080000081A400000000000000000000000166FAD7C0000015DF000000000000000000000000000000000000003D00000000kimap-VERSIONgit.20240930T185424~db1f697/po/nds/libkimap6.po# translation of libkimap.po to Low Saxon # Copyright (C) YEAR This_file_is_part_of_KDE # This file is distributed under the same license as the PACKAGE package. # Manfred Wiese <m.j.wiese@web.de>, 2009, 2010. # Sönke Dibbern <s_dibbern@web.de>, 2009, 2014. # msgid "" msgstr "" "Project-Id-Version: libkimap\n" "Report-Msgid-Bugs-To: https://bugs.kde.org\n" "POT-Creation-Date: 2022-05-11 00:45+0000\n" "PO-Revision-Date: 2014-08-14 00:19+0200\n" "Last-Translator: Sönke Dibbern <s_dibbern@web.de>\n" "Language-Team: Low Saxon <kde-i18n-nds@kde.org>\n" "Language: nds\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" #: acljobbase.cpp:56 #, kde-format msgid "AclJobBase" msgstr "TKL-Opgaven" #: appendjob.cpp:40 #, kde-format msgid "Append" msgstr "Anhangen" #: capabilitiesjob.cpp:35 #, kde-format msgid "Capabilities" msgstr "Könen" #: closejob.cpp:32 #, kde-format msgid "Close" msgstr "Tomaken" #: copyjob.cpp:41 #, kde-format msgid "Copy" msgstr "Koperen" #: createjob.cpp:36 #, kde-format msgid "Create" msgstr "Opstellen" #: deleteacljob.cpp:37 #, kde-format msgid "DeleteAclJob" msgstr "TKL-Opgaav Wegdoon" #: deletejob.cpp:36 #, kde-format msgid "Delete" msgstr "Wegdoon" #: enablejob.cpp:31 #, kde-format msgid "Enable" msgstr "" #: expungejob.cpp:37 #, kde-format msgid "Expunge" msgstr "Wegdoon" #: fetchjob.cpp:97 #, kde-format msgid "Fetch" msgstr "Halen" #: getacljob.cpp:37 #, kde-format msgid "GetAcl" msgstr "TKL halen" #: getmetadatajob.cpp:43 #, kde-format msgid "GetMetaData" msgstr "Metadaten halen" #: getmetadatajob.cpp:66 #, kde-format msgid "GetAnnotation" msgstr "Anmarken halen" #: getquotajob.cpp:35 #, kde-format msgid "GetQuota" msgstr "Bruukgrenz halen" #: getquotarootjob.cpp:38 #, kde-format msgid "GetQuotaRoot" msgstr "Wörtel för't Bruukgrenzhalen" #: idjob.cpp:35 #, fuzzy, kde-format #| msgctxt "name of the idle job" #| msgid "Idle" msgid "Id" msgstr "Nixdoon" #: idlejob.cpp:65 #, kde-format msgctxt "name of the idle job" msgid "Idle" msgstr "Nixdoon" #: job.cpp:19 #, kde-format msgid "Job" msgstr "Opgaav" #: job.cpp:54 loginjob.cpp:574 #, kde-format msgid "Connection to server lost." msgstr "Verbinnen na Server afbraken." #: job.cpp:65 loginjob.cpp:403 setmetadatajob.cpp:126 #, kde-format msgid "%1 failed, malformed reply from the server." msgstr "%1 fehlslaan. Leeg Serverantwoort kregen." #: job.cpp:68 loginjob.cpp:277 setmetadatajob.cpp:109 setmetadatajob.cpp:129 #, kde-format msgid "%1 failed, server replied: %2" msgstr "%1 fehlslaan. De Server anter: %2" #: listjob.cpp:59 #, kde-format msgid "List" msgstr "List" #: listrightsjob.cpp:38 #, kde-format msgid "ListRights" msgstr "Verlöven oplisten" #: loginjob.cpp:129 loginjob.cpp:233 #, kde-format msgid "Login" msgstr "Anmellen" #: loginjob.cpp:184 #, kde-format msgid "IMAP session in the wrong state for authentication" msgstr "IMAP-Törn in leeg Status för Identiteetprööv" #: loginjob.cpp:235 #, kde-format msgid "Capability" msgstr "Könen" #: loginjob.cpp:237 #, kde-format msgid "StartTls" msgstr "TIs starten" #: loginjob.cpp:340 #, kde-format msgid "STARTTLS is not supported by the server, try using SSL/TLS instead." msgstr "" #: loginjob.cpp:353 #, kde-format msgid "Internal error, tried to login before encryption" msgstr "" #: loginjob.cpp:362 #, kde-format msgid "Login failed, plain login is disabled by the server." msgstr "Anmellen fehlslaan. Nich verslötelt Anmellen is op den Server utmaakt." #: loginjob.cpp:383 #, kde-format msgid "Login failed, authentication mode %1 is not supported by the server." msgstr "" "Anmellen fehlslaan. De Server ünnerstütt de Metood \"%1\" för de " "Identiteetprööv nich." #: loginjob.cpp:413 #, kde-format msgid "Login failed, client cannot initialize the SASL library." msgstr "Anmellen fehlslaan. De SASL-Bibliotheek lett sik nich torechtmaken." #: loginjob.cpp:512 #, kde-format msgid "Login failed, TLS negotiation failed." msgstr "Anmellen fehlslaan. Uthanneln vun TLS fehlslaan." #: loginjob.cpp:570 #, kde-format msgid "SSL handshake failed." msgstr "SSL-Uthanneln is fehlslaan." #: logoutjob.cpp:33 #, kde-format msgid "Logout" msgstr "Afmellen" #: metadatajobbase.cpp:53 #, kde-format msgid "MetaDataJobBase" msgstr "Metadaten-Opgaven" #: movejob.cpp:42 #, kde-format msgid "Move" msgstr "" #: myrightsjob.cpp:37 #, kde-format msgid "MyRights" msgstr "Dien Verlöven" #: namespacejob.cpp:68 #, kde-format msgid "Namespace" msgstr "Naamruum" #: quotajobbase.cpp:34 #, kde-format msgid "QuotaJobBase" msgstr "Bruukgrenz-Opgaven" #: renamejob.cpp:37 #, kde-format msgid "Rename" msgstr "Ümnömen" #: searchjob.cpp:361 #, kde-format msgctxt "Name of the search job" msgid "Search" msgstr "Söök" #: selectjob.cpp:73 #, kde-format msgctxt "name of the select job" msgid "Select" msgstr "Utsöken" #: setacljob.cpp:34 #, kde-format msgid "SetAcl" msgstr "TKL setten" #: setmetadatajob.cpp:43 #, kde-format msgid "SetMetaData" msgstr "Metadaten setten" #: setquotajob.cpp:37 #, kde-format msgid "SetQuota" msgstr "Bruukgrenz setten" #: statusjob.cpp:40 #, kde-format msgctxt "name of the status job" msgid "Status" msgstr "" #: storejob.cpp:70 #, kde-format msgid "Store" msgstr "Sekern" #: subscribejob.cpp:36 #, kde-format msgid "Subscribe" msgstr "Bestellen" #: unsubscribejob.cpp:36 #, kde-format msgid "Unsubscribe" msgstr "Afbestellen" #~ msgid "SetAnnotation" #~ msgstr "Anmarken setten" #~ msgid "Mock" #~ msgstr "Namaken" 07070100000081000041ED00000000000000000000000266FAD7C000000000000000000000000000000000000000000000002F00000000kimap-VERSIONgit.20240930T185424~db1f697/po/nl07070100000082000081A400000000000000000000000166FAD7C000001758000000000000000000000000000000000000003C00000000kimap-VERSIONgit.20240930T185424~db1f697/po/nl/libkimap6.po# translation of libkimap.po to Dutch # 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>, 2009, 2010, 2013, 2014, 2016, 2018, 2020, 2022. msgid "" msgstr "" "Project-Id-Version: libkimap\n" "Report-Msgid-Bugs-To: https://bugs.kde.org\n" "POT-Creation-Date: 2022-05-11 00:45+0000\n" "PO-Revision-Date: 2022-01-28 11:12+0100\n" "Last-Translator: Freek de Kruijf <freekdekruijf@kde.nl>\n" "Language-Team: \n" "Language: nl\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Generator: Lokalize 21.12.1\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" #: acljobbase.cpp:56 #, kde-format msgid "AclJobBase" msgstr "AclJobBase" #: appendjob.cpp:40 #, kde-format msgid "Append" msgstr "Achteraan toevoegen" #: capabilitiesjob.cpp:35 #, kde-format msgid "Capabilities" msgstr "Functies" #: closejob.cpp:32 #, kde-format msgid "Close" msgstr "Sluiten" #: copyjob.cpp:41 #, kde-format msgid "Copy" msgstr "Kopiëren" #: createjob.cpp:36 #, kde-format msgid "Create" msgstr "Aanmaken" #: deleteacljob.cpp:37 #, kde-format msgid "DeleteAclJob" msgstr "DeleteAclJob" #: deletejob.cpp:36 #, kde-format msgid "Delete" msgstr "Verwijderen" #: enablejob.cpp:31 #, kde-format msgid "Enable" msgstr "Inschakelen" #: expungejob.cpp:37 #, kde-format msgid "Expunge" msgstr "Vernietigen" #: fetchjob.cpp:97 #, kde-format msgid "Fetch" msgstr "Ophalen" #: getacljob.cpp:37 #, kde-format msgid "GetAcl" msgstr "GetAcl" #: getmetadatajob.cpp:43 #, kde-format msgid "GetMetaData" msgstr "GetMetaData" #: getmetadatajob.cpp:66 #, kde-format msgid "GetAnnotation" msgstr "GetAnnotation" #: getquotajob.cpp:35 #, kde-format msgid "GetQuota" msgstr "GetQuota" #: getquotarootjob.cpp:38 #, kde-format msgid "GetQuotaRoot" msgstr "GetQuotaRoot" #: idjob.cpp:35 #, kde-format msgid "Id" msgstr "Id" #: idlejob.cpp:65 #, kde-format msgctxt "name of the idle job" msgid "Idle" msgstr "IJdel" #: job.cpp:19 #, kde-format msgid "Job" msgstr "Job" #: job.cpp:54 loginjob.cpp:574 #, kde-format msgid "Connection to server lost." msgstr "Verbinding met server verbroken." #: job.cpp:65 loginjob.cpp:403 setmetadatajob.cpp:126 #, kde-format msgid "%1 failed, malformed reply from the server." msgstr "%1 is mislukt, misvormd antwoord van de server." #: job.cpp:68 loginjob.cpp:277 setmetadatajob.cpp:109 setmetadatajob.cpp:129 #, kde-format msgid "%1 failed, server replied: %2" msgstr "%1 is mislukt, antwoord van server: %2" #: listjob.cpp:59 #, kde-format msgid "List" msgstr "Lijst" #: listrightsjob.cpp:38 #, kde-format msgid "ListRights" msgstr "ListRights" #: loginjob.cpp:129 loginjob.cpp:233 #, kde-format msgid "Login" msgstr "Aanmelden" #: loginjob.cpp:184 #, kde-format msgid "IMAP session in the wrong state for authentication" msgstr "IMAP-sessie in de verkeerde status voor authenticatie" #: loginjob.cpp:235 #, kde-format msgid "Capability" msgstr "Mogelijkheid" #: loginjob.cpp:237 #, kde-format msgid "StartTls" msgstr "StartTls" #: loginjob.cpp:340 #, kde-format msgid "STARTTLS is not supported by the server, try using SSL/TLS instead." msgstr "" "STARTTLS wordt niet ondersteund door de server, probeer in plaats daarvan " "SSL/TLS." #: loginjob.cpp:353 #, kde-format msgid "Internal error, tried to login before encryption" msgstr "Interne fout, geprobeerd aan te melden vóór versleuteling" #: loginjob.cpp:362 #, kde-format msgid "Login failed, plain login is disabled by the server." msgstr "Aanmelden is mislukt, plat aanmelden is uitgeschakeld door de server." #: loginjob.cpp:383 #, kde-format msgid "Login failed, authentication mode %1 is not supported by the server." msgstr "" "Aanmelden is mislukt, authenticatiemodus %1 wordt niet ondersteund door de " "server." #: loginjob.cpp:413 #, kde-format msgid "Login failed, client cannot initialize the SASL library." msgstr "" "Aanmelden is mislukt, client kan de SASL-bibliotheek niet initialiseren." #: loginjob.cpp:512 #, kde-format msgid "Login failed, TLS negotiation failed." msgstr "Aanmelden is mislukt, TLS-onderhandeling is mislukt." #: loginjob.cpp:570 #, kde-format msgid "SSL handshake failed." msgstr "SSL-handdruk is mislukt." #: logoutjob.cpp:33 #, kde-format msgid "Logout" msgstr "Afmelden" #: metadatajobbase.cpp:53 #, kde-format msgid "MetaDataJobBase" msgstr "MetaDataJobBase" #: movejob.cpp:42 #, kde-format msgid "Move" msgstr "Verplaatsen" #: myrightsjob.cpp:37 #, kde-format msgid "MyRights" msgstr "MyRights" #: namespacejob.cpp:68 #, kde-format msgid "Namespace" msgstr "Naamruimte" #: quotajobbase.cpp:34 #, kde-format msgid "QuotaJobBase" msgstr "QuotaJobBase" #: renamejob.cpp:37 #, kde-format msgid "Rename" msgstr "Hernoemen" #: searchjob.cpp:361 #, kde-format msgctxt "Name of the search job" msgid "Search" msgstr "Zoeken" #: selectjob.cpp:73 #, kde-format msgctxt "name of the select job" msgid "Select" msgstr "Selecteren" #: setacljob.cpp:34 #, kde-format msgid "SetAcl" msgstr "SetAcl" #: setmetadatajob.cpp:43 #, kde-format msgid "SetMetaData" msgstr "SetMetaData" #: setquotajob.cpp:37 #, kde-format msgid "SetQuota" msgstr "SetQuota" #: statusjob.cpp:40 #, kde-format msgctxt "name of the status job" msgid "Status" msgstr "Status" #: storejob.cpp:70 #, kde-format msgid "Store" msgstr "Opslaan" #: subscribejob.cpp:36 #, kde-format msgid "Subscribe" msgstr "Inschrijven" #: unsubscribejob.cpp:36 #, kde-format msgid "Unsubscribe" msgstr "Uitschrijven" #~ msgid "SetAnnotation" #~ msgstr "SetAnnotation" #~ msgid "Mock" #~ msgstr "Mock" #~ msgctxt "NAME OF TRANSLATORS" #~ msgid "Your names" #~ msgstr "Freek de Kruijf" #~ msgctxt "EMAIL OF TRANSLATORS" #~ msgid "Your emails" #~ msgstr "freekdekruijf@kde.nl" #~ msgctxt "Authentication method" #~ msgid "Clear text" #~ msgstr "Leesbare tekst" #~ msgctxt "Authentication method" #~ msgid "Anonymous" #~ msgstr "Anoniem" 07070100000083000041ED00000000000000000000000266FAD7C000000000000000000000000000000000000000000000002F00000000kimap-VERSIONgit.20240930T185424~db1f697/po/nn07070100000084000081A400000000000000000000000166FAD7C000001579000000000000000000000000000000000000003C00000000kimap-VERSIONgit.20240930T185424~db1f697/po/nn/libkimap6.po# Translation of libkimap6 to Norwegian Nynorsk # # Eirik U. Birkeland <eirbir@gmail.com>, 2009, 2010. # Karl Ove Hufthammer <karl@huftis.org>, 2010, 2020, 2022. msgid "" msgstr "" "Project-Id-Version: libkimap\n" "Report-Msgid-Bugs-To: https://bugs.kde.org\n" "POT-Creation-Date: 2022-05-11 00:45+0000\n" "PO-Revision-Date: 2022-07-02 13:33+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" "X-Generator: Lokalize 22.04.2\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" "X-Environment: kde\n" "X-Accelerator-Marker: &\n" "X-Text-Markup: kde4\n" #: acljobbase.cpp:56 #, kde-format msgid "AclJobBase" msgstr "AclJobBase" #: appendjob.cpp:40 #, kde-format msgid "Append" msgstr "Legg til" #: capabilitiesjob.cpp:35 #, kde-format msgid "Capabilities" msgstr "Funksjonar" #: closejob.cpp:32 #, kde-format msgid "Close" msgstr "Lukk" #: copyjob.cpp:41 #, kde-format msgid "Copy" msgstr "Kopier" #: createjob.cpp:36 #, kde-format msgid "Create" msgstr "Opprett" #: deleteacljob.cpp:37 #, kde-format msgid "DeleteAclJob" msgstr "Slett AclJob" #: deletejob.cpp:36 #, kde-format msgid "Delete" msgstr "Slett" #: enablejob.cpp:31 #, kde-format msgid "Enable" msgstr "Slå på" #: expungejob.cpp:37 #, kde-format msgid "Expunge" msgstr "Fjern" #: fetchjob.cpp:97 #, kde-format msgid "Fetch" msgstr "Hent" #: getacljob.cpp:37 #, kde-format msgid "GetAcl" msgstr "GetAcl" #: getmetadatajob.cpp:43 #, kde-format msgid "GetMetaData" msgstr "GetMetaData" #: getmetadatajob.cpp:66 #, kde-format msgid "GetAnnotation" msgstr "GetAnnotation" #: getquotajob.cpp:35 #, kde-format msgid "GetQuota" msgstr "GetQuota" #: getquotarootjob.cpp:38 #, kde-format msgid "GetQuotaRoot" msgstr "GetQuotaRoot" #: idjob.cpp:35 #, kde-format msgid "Id" msgstr "ID" #: idlejob.cpp:65 #, kde-format msgctxt "name of the idle job" msgid "Idle" msgstr "Inaktiv" #: job.cpp:19 #, kde-format msgid "Job" msgstr "Jobb" #: job.cpp:54 loginjob.cpp:574 #, kde-format msgid "Connection to server lost." msgstr "Tilkoplinga til tenaren vart avbroten." #: job.cpp:65 loginjob.cpp:403 setmetadatajob.cpp:126 #, kde-format msgid "%1 failed, malformed reply from the server." msgstr "%1 var mislukka. Svaret frå tenaren var ugyldig." #: job.cpp:68 loginjob.cpp:277 setmetadatajob.cpp:109 setmetadatajob.cpp:129 #, kde-format msgid "%1 failed, server replied: %2" msgstr "%1 var mislukka. Svaret frå tenaren var: %2" #: listjob.cpp:59 #, kde-format msgid "List" msgstr "Liste" #: listrightsjob.cpp:38 #, kde-format msgid "ListRights" msgstr "ListRights" #: loginjob.cpp:129 loginjob.cpp:233 #, kde-format msgid "Login" msgstr "Innlogging" #: loginjob.cpp:184 #, kde-format msgid "IMAP session in the wrong state for authentication" msgstr "IMAP-økta er i feil tilstand for autentisering" #: loginjob.cpp:235 #, kde-format msgid "Capability" msgstr "Funksjon" #: loginjob.cpp:237 #, kde-format msgid "StartTls" msgstr "StartTls" #: loginjob.cpp:340 #, kde-format msgid "STARTTLS is not supported by the server, try using SSL/TLS instead." msgstr "STARTTLS er ikkje støtta av tenaren. Prøver med SSL/TLS i staden." #: loginjob.cpp:353 #, kde-format msgid "Internal error, tried to login before encryption" msgstr "Intern feil – prøvde å logga inn før kryptering" #: loginjob.cpp:362 #, kde-format msgid "Login failed, plain login is disabled by the server." msgstr "Innlogginga var mislukka. Vanleg innlogging er slått av på tenaren." #: loginjob.cpp:383 #, kde-format msgid "Login failed, authentication mode %1 is not supported by the server." msgstr "" "Innlogginga var mislukka. Innloggingsmetoden %1 er ikkje støtta av tenaren." #: loginjob.cpp:413 #, kde-format msgid "Login failed, client cannot initialize the SASL library." msgstr "" "Innlogginga var mislukka. Klienten klarar ikkje starta SASL-biblioteket." #: loginjob.cpp:512 #, kde-format msgid "Login failed, TLS negotiation failed." msgstr "Innlogginga og TLS-forhandlinga var mislukka." #: loginjob.cpp:570 #, kde-format msgid "SSL handshake failed." msgstr "Feil ved SSL-handtrykk." #: logoutjob.cpp:33 #, kde-format msgid "Logout" msgstr "Logg ut" #: metadatajobbase.cpp:53 #, kde-format msgid "MetaDataJobBase" msgstr "MetaDataJobBase" #: movejob.cpp:42 #, kde-format msgid "Move" msgstr "Flytt" #: myrightsjob.cpp:37 #, kde-format msgid "MyRights" msgstr "MyRights" #: namespacejob.cpp:68 #, kde-format msgid "Namespace" msgstr "Namnerom" #: quotajobbase.cpp:34 #, kde-format msgid "QuotaJobBase" msgstr "QuotaJobBase" #: renamejob.cpp:37 #, kde-format msgid "Rename" msgstr "Endra namn" #: searchjob.cpp:361 #, kde-format msgctxt "Name of the search job" msgid "Search" msgstr "Søk" #: selectjob.cpp:73 #, kde-format msgctxt "name of the select job" msgid "Select" msgstr "Vel" #: setacljob.cpp:34 #, kde-format msgid "SetAcl" msgstr "SetAcl" #: setmetadatajob.cpp:43 #, kde-format msgid "SetMetaData" msgstr "SetMetaData" #: setquotajob.cpp:37 #, kde-format msgid "SetQuota" msgstr "SetQuota" #: statusjob.cpp:40 #, kde-format msgctxt "name of the status job" msgid "Status" msgstr "Status" #: storejob.cpp:70 #, kde-format msgid "Store" msgstr "Lagra" #: subscribejob.cpp:36 #, kde-format msgid "Subscribe" msgstr "Abonner" #: unsubscribejob.cpp:36 #, kde-format msgid "Unsubscribe" msgstr "Avslutt abonnement" 07070100000085000041ED00000000000000000000000266FAD7C000000000000000000000000000000000000000000000002F00000000kimap-VERSIONgit.20240930T185424~db1f697/po/pa07070100000086000081A400000000000000000000000166FAD7C00000149F000000000000000000000000000000000000003C00000000kimap-VERSIONgit.20240930T185424~db1f697/po/pa/libkimap6.po# Copyright (C) YEAR This_file_is_part_of_KDE # This file is distributed under the same license as the PACKAGE package. # # A S Alam <aalam@users.sf.net>, 2010. msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: https://bugs.kde.org\n" "POT-Creation-Date: 2022-05-11 00:45+0000\n" "PO-Revision-Date: 2010-01-16 08:29+0530\n" "Last-Translator: A S Alam <aalam@users.sf.net>\n" "Language-Team: ਪੰਜਾਬੀ <punjabi-users@lists.sf.net>\n" "Language: pa\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Generator: Lokalize 1.0\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" #: acljobbase.cpp:56 #, kde-format msgid "AclJobBase" msgstr "" #: appendjob.cpp:40 #, kde-format msgid "Append" msgstr "ਸ਼ਾਮਲ" #: capabilitiesjob.cpp:35 #, kde-format msgid "Capabilities" msgstr "ਸਮੱਰਥਾ" #: closejob.cpp:32 #, kde-format msgid "Close" msgstr "ਬੰਦ ਕਰੋ" #: copyjob.cpp:41 #, kde-format msgid "Copy" msgstr "ਕਾਪੀ" #: createjob.cpp:36 #, kde-format msgid "Create" msgstr "ਬਣਾਓ" #: deleteacljob.cpp:37 #, kde-format msgid "DeleteAclJob" msgstr "" #: deletejob.cpp:36 #, kde-format msgid "Delete" msgstr "ਹਟਾਓ" #: enablejob.cpp:31 #, kde-format msgid "Enable" msgstr "" #: expungejob.cpp:37 #, kde-format msgid "Expunge" msgstr "" #: fetchjob.cpp:97 #, kde-format msgid "Fetch" msgstr "" #: getacljob.cpp:37 #, kde-format msgid "GetAcl" msgstr "" #: getmetadatajob.cpp:43 #, kde-format msgid "GetMetaData" msgstr "" #: getmetadatajob.cpp:66 #, kde-format msgid "GetAnnotation" msgstr "" #: getquotajob.cpp:35 #, kde-format msgid "GetQuota" msgstr "" #: getquotarootjob.cpp:38 #, kde-format msgid "GetQuotaRoot" msgstr "" #: idjob.cpp:35 #, fuzzy, kde-format #| msgctxt "name of the idle job" #| msgid "Idle" msgid "Id" msgstr "ਵੇਹਲਾ" #: idlejob.cpp:65 #, kde-format msgctxt "name of the idle job" msgid "Idle" msgstr "ਵੇਹਲਾ" #: job.cpp:19 #, kde-format msgid "Job" msgstr "ਜਾਬ" #: job.cpp:54 loginjob.cpp:574 #, kde-format msgid "Connection to server lost." msgstr "" #: job.cpp:65 loginjob.cpp:403 setmetadatajob.cpp:126 #, kde-format msgid "%1 failed, malformed reply from the server." msgstr "" #: job.cpp:68 loginjob.cpp:277 setmetadatajob.cpp:109 setmetadatajob.cpp:129 #, kde-format msgid "%1 failed, server replied: %2" msgstr "" #: listjob.cpp:59 #, kde-format msgid "List" msgstr "ਲਿਸਟ" #: listrightsjob.cpp:38 #, kde-format msgid "ListRights" msgstr "" #: loginjob.cpp:129 loginjob.cpp:233 #, kde-format msgid "Login" msgstr "ਲਾਗਇਨ" #: loginjob.cpp:184 #, kde-format msgid "IMAP session in the wrong state for authentication" msgstr "" #: loginjob.cpp:235 #, kde-format msgid "Capability" msgstr "ਸਮੱਰਥਾ" #: loginjob.cpp:237 #, kde-format msgid "StartTls" msgstr "StartTls" #: loginjob.cpp:340 #, kde-format msgid "STARTTLS is not supported by the server, try using SSL/TLS instead." msgstr "" #: loginjob.cpp:353 #, kde-format msgid "Internal error, tried to login before encryption" msgstr "" #: loginjob.cpp:362 #, kde-format msgid "Login failed, plain login is disabled by the server." msgstr "" #: loginjob.cpp:383 #, kde-format msgid "Login failed, authentication mode %1 is not supported by the server." msgstr "" #: loginjob.cpp:413 #, kde-format msgid "Login failed, client cannot initialize the SASL library." msgstr "" #: loginjob.cpp:512 #, kde-format msgid "Login failed, TLS negotiation failed." msgstr "ਲਾਗਇਨ ਫੇਲ੍ਹ, TLS ਜਾਂਚ ਫੇਲ੍ਹ ਹੋਈ।" #: loginjob.cpp:570 #, kde-format msgid "SSL handshake failed." msgstr "" #: logoutjob.cpp:33 #, kde-format msgid "Logout" msgstr "ਲਾਗਆਉਟ" #: metadatajobbase.cpp:53 #, kde-format msgid "MetaDataJobBase" msgstr "" #: movejob.cpp:42 #, kde-format msgid "Move" msgstr "" #: myrightsjob.cpp:37 #, kde-format msgid "MyRights" msgstr "" #: namespacejob.cpp:68 #, kde-format msgid "Namespace" msgstr "" #: quotajobbase.cpp:34 #, kde-format msgid "QuotaJobBase" msgstr "" #: renamejob.cpp:37 #, kde-format msgid "Rename" msgstr "ਨਾਂ ਬਦਲੋ" #: searchjob.cpp:361 #, kde-format msgctxt "Name of the search job" msgid "Search" msgstr "ਖੋਜ" #: selectjob.cpp:73 #, kde-format msgctxt "name of the select job" msgid "Select" msgstr "ਚੁਣੋ" #: setacljob.cpp:34 #, kde-format msgid "SetAcl" msgstr "" #: setmetadatajob.cpp:43 #, kde-format msgid "SetMetaData" msgstr "" #: setquotajob.cpp:37 #, kde-format msgid "SetQuota" msgstr "ਕੋਟਾਸੈੱਟ" #: statusjob.cpp:40 #, kde-format msgctxt "name of the status job" msgid "Status" msgstr "" #: storejob.cpp:70 #, kde-format msgid "Store" msgstr "ਸਟੋਰ" #: subscribejob.cpp:36 #, kde-format msgid "Subscribe" msgstr "ਮੈਂਬਰ ਬਣੋ" #: unsubscribejob.cpp:36 #, kde-format msgid "Unsubscribe" msgstr "ਮੈਂਬਰੀ ਹਟਾਓ" #~ msgctxt "NAME OF TRANSLATORS" #~ msgid "Your names" #~ msgstr "ਅਮਨਪਰੀਤ ਸਿੰਘ ਆਲਮ" #~ msgctxt "EMAIL OF TRANSLATORS" #~ msgid "Your emails" #~ msgstr "aalam@users.sf.net" #, fuzzy #~| msgid "Create" #~ msgctxt "Authentication method" #~ msgid "Clear text" #~ msgstr "ਬਣਾਓ" 07070100000087000041ED00000000000000000000000266FAD7C000000000000000000000000000000000000000000000002F00000000kimap-VERSIONgit.20240930T185424~db1f697/po/pl07070100000088000081A400000000000000000000000166FAD7C000001690000000000000000000000000000000000000003C00000000kimap-VERSIONgit.20240930T185424~db1f697/po/pl/libkimap6.po# 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>, 2014, 2015, 2016, 2018, 2019, 2020, 2022. msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: https://bugs.kde.org\n" "POT-Creation-Date: 2022-05-11 00:45+0000\n" "PO-Revision-Date: 2022-02-07 20:22+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" #: acljobbase.cpp:56 #, kde-format msgid "AclJobBase" msgstr "BazaZadańAcl" #: appendjob.cpp:40 #, kde-format msgid "Append" msgstr "Dołącz" #: capabilitiesjob.cpp:35 #, kde-format msgid "Capabilities" msgstr "Możliwości" #: closejob.cpp:32 #, kde-format msgid "Close" msgstr "Zamknij" #: copyjob.cpp:41 #, kde-format msgid "Copy" msgstr "Skopiuj" #: createjob.cpp:36 #, kde-format msgid "Create" msgstr "Utwórz" #: deleteacljob.cpp:37 #, kde-format msgid "DeleteAclJob" msgstr "UsuńZadanieAcl" #: deletejob.cpp:36 #, kde-format msgid "Delete" msgstr "Usuń" #: enablejob.cpp:31 #, kde-format msgid "Enable" msgstr "Włącz" #: expungejob.cpp:37 #, kde-format msgid "Expunge" msgstr "Wymaż" #: fetchjob.cpp:97 #, kde-format msgid "Fetch" msgstr "Pobierz" #: getacljob.cpp:37 #, kde-format msgid "GetAcl" msgstr "PobierzAcl" #: getmetadatajob.cpp:43 #, kde-format msgid "GetMetaData" msgstr "PobierzMetadane" #: getmetadatajob.cpp:66 #, kde-format msgid "GetAnnotation" msgstr "PobierzKomentarz" #: getquotajob.cpp:35 #, kde-format msgid "GetQuota" msgstr "PobierzPrzydział" #: getquotarootjob.cpp:38 #, kde-format msgid "GetQuotaRoot" msgstr "PobierzPrzydziałRoot" #: idjob.cpp:35 #, kde-format msgid "Id" msgstr "Id" #: idlejob.cpp:65 #, kde-format msgctxt "name of the idle job" msgid "Idle" msgstr "Bezczynny" #: job.cpp:19 #, kde-format msgid "Job" msgstr "Zadanie" #: job.cpp:54 loginjob.cpp:574 #, kde-format msgid "Connection to server lost." msgstr "Utracono połączenie z serwerem." #: job.cpp:65 loginjob.cpp:403 setmetadatajob.cpp:126 #, kde-format msgid "%1 failed, malformed reply from the server." msgstr "%1 nie powiodło się, błędna odpowiedź serwera." #: job.cpp:68 loginjob.cpp:277 setmetadatajob.cpp:109 setmetadatajob.cpp:129 #, kde-format msgid "%1 failed, server replied: %2" msgstr "%1 nie powiodło się, odpowiedź serwera: %2" #: listjob.cpp:59 #, kde-format msgid "List" msgstr "Lista" #: listrightsjob.cpp:38 #, kde-format msgid "ListRights" msgstr "PrawaListy" #: loginjob.cpp:129 loginjob.cpp:233 #, kde-format msgid "Login" msgstr "Logowanie" #: loginjob.cpp:184 #, kde-format msgid "IMAP session in the wrong state for authentication" msgstr "Sesja IMAP w złym stanie uwierzytelniania" #: loginjob.cpp:235 #, kde-format msgid "Capability" msgstr "Możliwość" #: loginjob.cpp:237 #, kde-format msgid "StartTls" msgstr "StartTls" #: loginjob.cpp:340 #, kde-format msgid "STARTTLS is not supported by the server, try using SSL/TLS instead." msgstr "" "STARTTLS nie jest obsługiwany przez serwer, zamiast tego spróbuj użyć SSL/" "TLS." #: loginjob.cpp:353 #, kde-format msgid "Internal error, tried to login before encryption" msgstr "Błąd wewnętrzny, próbowano się zalogować przed zaszyfrowaniem" #: loginjob.cpp:362 #, kde-format msgid "Login failed, plain login is disabled by the server." msgstr "" "Logowanie nie powiodło się, zwykłe logowanie jest wyłączone na serwerze." #: loginjob.cpp:383 #, kde-format msgid "Login failed, authentication mode %1 is not supported by the server." msgstr "" "Logowanie nie powiodło się, tryb uwierzytelnienia %1 nie jest obsługiwany " "przez serwer." #: loginjob.cpp:413 #, kde-format msgid "Login failed, client cannot initialize the SASL library." msgstr "Logowanie nie powiodło się, nie można zainicjować biblioteki SASL." #: loginjob.cpp:512 #, kde-format msgid "Login failed, TLS negotiation failed." msgstr "Logowanie nie powiodło się, nie udała się negocjacja TLS." #: loginjob.cpp:570 #, kde-format msgid "SSL handshake failed." msgstr "Nieudany uścisk dłoni SSL." #: logoutjob.cpp:33 #, kde-format msgid "Logout" msgstr "Wylogowanie" #: metadatajobbase.cpp:53 #, kde-format msgid "MetaDataJobBase" msgstr "BazaMetadanychZadań" #: movejob.cpp:42 #, kde-format msgid "Move" msgstr "Przenoszenie" #: myrightsjob.cpp:37 #, kde-format msgid "MyRights" msgstr "MojePrawa" #: namespacejob.cpp:68 #, kde-format msgid "Namespace" msgstr "Przestrzeń nazw" #: quotajobbase.cpp:34 #, kde-format msgid "QuotaJobBase" msgstr "BazaZadańPrzydziałów" #: renamejob.cpp:37 #, kde-format msgid "Rename" msgstr "Zmień nazwę" #: searchjob.cpp:361 #, kde-format msgctxt "Name of the search job" msgid "Search" msgstr "Szukaj" #: selectjob.cpp:73 #, kde-format msgctxt "name of the select job" msgid "Select" msgstr "Wybierz" #: setacljob.cpp:34 #, kde-format msgid "SetAcl" msgstr "UstawAcl" #: setmetadatajob.cpp:43 #, kde-format msgid "SetMetaData" msgstr "UstawMetadane" #: setquotajob.cpp:37 #, kde-format msgid "SetQuota" msgstr "UstawPrzydział" #: statusjob.cpp:40 #, kde-format msgctxt "name of the status job" msgid "Status" msgstr "Stan" #: storejob.cpp:70 #, kde-format msgid "Store" msgstr "Przechowuj" #: subscribejob.cpp:36 #, kde-format msgid "Subscribe" msgstr "Subskrybuj" #: unsubscribejob.cpp:36 #, kde-format msgid "Unsubscribe" msgstr "Zaprzestań subskrypcji" #~ msgid "SetAnnotation" #~ msgstr "UstawKomentarz" #~ msgid "Mock" #~ msgstr "Mock" 07070100000089000041ED00000000000000000000000266FAD7C000000000000000000000000000000000000000000000002F00000000kimap-VERSIONgit.20240930T185424~db1f697/po/pt0707010000008A000081A400000000000000000000000166FAD7C00000173D000000000000000000000000000000000000003C00000000kimap-VERSIONgit.20240930T185424~db1f697/po/pt/libkimap6.po# 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: libkimap\n" "Report-Msgid-Bugs-To: https://bugs.kde.org\n" "POT-Creation-Date: 2022-05-11 00:45+0000\n" "PO-Revision-Date: 2022-03-27 00:06+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" "Plural-Forms: nplurals=2; plural=n != 1;\n" "X-POFile-SpellExtra: AclJobBase StartTls MinhasPermissões SetAcl\n" "X-POFile-SpellExtra: DeleteAclJob GetQuotaRoot SetQuota ListRights\n" "X-POFile-SpellExtra: GetQuota QuotaJobBase GetMetaData SetMetaData\n" "X-POFile-SpellExtra: SetAnnotation MetaDataJobBase GetAnnotation GetAcl Id\n" "X-POFile-SpellExtra: STARTTLS\n" #: acljobbase.cpp:56 #, kde-format msgid "AclJobBase" msgstr "AclJobBase" #: appendjob.cpp:40 #, kde-format msgid "Append" msgstr "Adicionar" #: capabilitiesjob.cpp:35 #, kde-format msgid "Capabilities" msgstr "Capacidades" #: closejob.cpp:32 #, kde-format msgid "Close" msgstr "Fechar" #: copyjob.cpp:41 #, kde-format msgid "Copy" msgstr "Copiar" #: createjob.cpp:36 #, kde-format msgid "Create" msgstr "Criar" #: deleteacljob.cpp:37 #, kde-format msgid "DeleteAclJob" msgstr "DeleteAclJob" #: deletejob.cpp:36 #, kde-format msgid "Delete" msgstr "Apagar" #: enablejob.cpp:31 #, kde-format msgid "Enable" msgstr "Activar" #: expungejob.cpp:37 #, kde-format msgid "Expunge" msgstr "Eliminar" #: fetchjob.cpp:97 #, kde-format msgid "Fetch" msgstr "Obter" #: getacljob.cpp:37 #, kde-format msgid "GetAcl" msgstr "GetAcl" #: getmetadatajob.cpp:43 #, kde-format msgid "GetMetaData" msgstr "GetMetaData" #: getmetadatajob.cpp:66 #, kde-format msgid "GetAnnotation" msgstr "GetAnnotation" #: getquotajob.cpp:35 #, kde-format msgid "GetQuota" msgstr "GetQuota" #: getquotarootjob.cpp:38 #, kde-format msgid "GetQuotaRoot" msgstr "GetQuotaRoot" #: idjob.cpp:35 #, kde-format msgid "Id" msgstr "Id" #: idlejob.cpp:65 #, kde-format msgctxt "name of the idle job" msgid "Idle" msgstr "Inactiva" #: job.cpp:19 #, kde-format msgid "Job" msgstr "Tarefa" #: job.cpp:54 loginjob.cpp:574 #, kde-format msgid "Connection to server lost." msgstr "Perdeu-se a ligação ao servidor." #: job.cpp:65 loginjob.cpp:403 setmetadatajob.cpp:126 #, kde-format msgid "%1 failed, malformed reply from the server." msgstr "O %1 foi mal-sucedido; a resposta do servidor é inválida." #: job.cpp:68 loginjob.cpp:277 setmetadatajob.cpp:109 setmetadatajob.cpp:129 #, kde-format msgid "%1 failed, server replied: %2" msgstr "O %1 foi mal-sucedido; a resposta do servidor foi: %2" #: listjob.cpp:59 #, kde-format msgid "List" msgstr "Lista" #: listrightsjob.cpp:38 #, kde-format msgid "ListRights" msgstr "ListRights" #: loginjob.cpp:129 loginjob.cpp:233 #, kde-format msgid "Login" msgstr "Utilizador" #: loginjob.cpp:184 #, kde-format msgid "IMAP session in the wrong state for authentication" msgstr "Sessão de IMAP num estado inválido para autenticação" #: loginjob.cpp:235 #, kde-format msgid "Capability" msgstr "Capacidade" #: loginjob.cpp:237 #, kde-format msgid "StartTls" msgstr "StartTls" #: loginjob.cpp:340 #, kde-format msgid "STARTTLS is not supported by the server, try using SSL/TLS instead." msgstr "" "O STARTTLS não é suportado pelo servidor; tente usar o SSL/TLS em " "alternativa." #: loginjob.cpp:353 #, kde-format msgid "Internal error, tried to login before encryption" msgstr "Erro interno; tentou-se a autenticação antes da encriptação" #: loginjob.cpp:362 #, kde-format msgid "Login failed, plain login is disabled by the server." msgstr "" "A autenticação foi mal-sucedida; a autenticação em texto livre está " "desactivada." #: loginjob.cpp:383 #, kde-format msgid "Login failed, authentication mode %1 is not supported by the server." msgstr "" "A autenticação foi mal-sucedida; o modo de autenticação %1 não é suportado " "pelo servidor." #: loginjob.cpp:413 #, kde-format msgid "Login failed, client cannot initialize the SASL library." msgstr "" "A autenticação foi mal-sucedida; o cliente não consegue inicializar a " "biblioteca SASL." #: loginjob.cpp:512 #, kde-format msgid "Login failed, TLS negotiation failed." msgstr "A autenticação foi mal-sucedida; a negociação de TLS foi mal-sucedida." #: loginjob.cpp:570 #, kde-format msgid "SSL handshake failed." msgstr "O protocolo inicial de SSL foi mal-sucedido." #: logoutjob.cpp:33 #, kde-format msgid "Logout" msgstr "Encerrar" #: metadatajobbase.cpp:53 #, kde-format msgid "MetaDataJobBase" msgstr "MetaDataJobBase" #: movejob.cpp:42 #, kde-format msgid "Move" msgstr "Mover" #: myrightsjob.cpp:37 #, kde-format msgid "MyRights" msgstr "MinhasPermissões" #: namespacejob.cpp:68 #, kde-format msgid "Namespace" msgstr "Espaço de nomes" #: quotajobbase.cpp:34 #, kde-format msgid "QuotaJobBase" msgstr "QuotaJobBase" #: renamejob.cpp:37 #, kde-format msgid "Rename" msgstr "Mudar o Nome" #: searchjob.cpp:361 #, kde-format msgctxt "Name of the search job" msgid "Search" msgstr "Procurar" #: selectjob.cpp:73 #, kde-format msgctxt "name of the select job" msgid "Select" msgstr "Seleccionar" #: setacljob.cpp:34 #, kde-format msgid "SetAcl" msgstr "SetAcl" #: setmetadatajob.cpp:43 #, kde-format msgid "SetMetaData" msgstr "SetMetaData" #: setquotajob.cpp:37 #, kde-format msgid "SetQuota" msgstr "SetQuota" #: statusjob.cpp:40 #, kde-format msgctxt "name of the status job" msgid "Status" msgstr "Estado" #: storejob.cpp:70 #, kde-format msgid "Store" msgstr "Gravar" #: subscribejob.cpp:36 #, kde-format msgid "Subscribe" msgstr "Subscrever" #: unsubscribejob.cpp:36 #, kde-format msgid "Unsubscribe" msgstr "Cancelar a Subscrição" 0707010000008B000041ED00000000000000000000000266FAD7C000000000000000000000000000000000000000000000003200000000kimap-VERSIONgit.20240930T185424~db1f697/po/pt_BR0707010000008C000081A400000000000000000000000166FAD7C00000163C000000000000000000000000000000000000003F00000000kimap-VERSIONgit.20240930T185424~db1f697/po/pt_BR/libkimap6.po# Translation of libkimap5.po to Brazilian Portuguese # Copyright (C) 2009-2018 This_file_is_part_of_KDE # This file is distributed under the same license as the PACKAGE package. # # Luiz Fernando Ranghetti <elchevive@opensuse.org>, 2009, 2020, 2022. # André Marcelo Alvarenga <alvarenga@kde.org>, 2009, 2010, 2011, 2014, 2016, 2018. msgid "" msgstr "" "Project-Id-Version: libkimap5\n" "Report-Msgid-Bugs-To: https://bugs.kde.org\n" "POT-Creation-Date: 2022-05-11 00:45+0000\n" "PO-Revision-Date: 2022-02-02 08:47-0300\n" "Last-Translator: Luiz Fernando Ranghetti <elchevive@opensuse.org>\n" "Language-Team: 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 20.04.2\n" #: acljobbase.cpp:56 #, kde-format msgid "AclJobBase" msgstr "AclJobBase" #: appendjob.cpp:40 #, kde-format msgid "Append" msgstr "Anexar" #: capabilitiesjob.cpp:35 #, kde-format msgid "Capabilities" msgstr "Recursos" #: closejob.cpp:32 #, kde-format msgid "Close" msgstr "Fechar" #: copyjob.cpp:41 #, kde-format msgid "Copy" msgstr "Copiar" #: createjob.cpp:36 #, kde-format msgid "Create" msgstr "Criar" #: deleteacljob.cpp:37 #, kde-format msgid "DeleteAclJob" msgstr "DeleteAclJob" #: deletejob.cpp:36 #, kde-format msgid "Delete" msgstr "Excluir" #: enablejob.cpp:31 #, kde-format msgid "Enable" msgstr "Habilitar" #: expungejob.cpp:37 #, kde-format msgid "Expunge" msgstr "Eliminar" #: fetchjob.cpp:97 #, kde-format msgid "Fetch" msgstr "Obter" #: getacljob.cpp:37 #, kde-format msgid "GetAcl" msgstr "GetAcl" #: getmetadatajob.cpp:43 #, kde-format msgid "GetMetaData" msgstr "GetMetaData" #: getmetadatajob.cpp:66 #, kde-format msgid "GetAnnotation" msgstr "GetAnnotation" #: getquotajob.cpp:35 #, kde-format msgid "GetQuota" msgstr "GetQuota" #: getquotarootjob.cpp:38 #, kde-format msgid "GetQuotaRoot" msgstr "GetQuotaRoot" #: idjob.cpp:35 #, kde-format msgid "Id" msgstr "ID" #: idlejob.cpp:65 #, kde-format msgctxt "name of the idle job" msgid "Idle" msgstr "Ocioso" #: job.cpp:19 #, kde-format msgid "Job" msgstr "Trabalho" #: job.cpp:54 loginjob.cpp:574 #, kde-format msgid "Connection to server lost." msgstr "A conexão com o servidor foi perdida." #: job.cpp:65 loginjob.cpp:403 setmetadatajob.cpp:126 #, kde-format msgid "%1 failed, malformed reply from the server." msgstr "%1 falhou, resposta mal formada do servidor." #: job.cpp:68 loginjob.cpp:277 setmetadatajob.cpp:109 setmetadatajob.cpp:129 #, kde-format msgid "%1 failed, server replied: %2" msgstr "%1 falhou, o servidor respondeu: %2" #: listjob.cpp:59 #, kde-format msgid "List" msgstr "Listar" #: listrightsjob.cpp:38 #, kde-format msgid "ListRights" msgstr "ListRights" #: loginjob.cpp:129 loginjob.cpp:233 #, kde-format msgid "Login" msgstr "Início de sessão" #: loginjob.cpp:184 #, kde-format msgid "IMAP session in the wrong state for authentication" msgstr "Sessão de IMAP num estado inválido para autenticação" #: loginjob.cpp:235 #, kde-format msgid "Capability" msgstr "Recurso" #: loginjob.cpp:237 #, kde-format msgid "StartTls" msgstr "StartTls" #: loginjob.cpp:340 #, kde-format msgid "STARTTLS is not supported by the server, try using SSL/TLS instead." msgstr "" "O STARTTLS não é suportado pelo servidor, tente usar o SSL/TLS como " "alternativa." #: loginjob.cpp:353 #, kde-format msgid "Internal error, tried to login before encryption" msgstr "Erro interno, tentou fazer login antes da criptografia" #: loginjob.cpp:362 #, kde-format msgid "Login failed, plain login is disabled by the server." msgstr "" "Falha no login. A autenticação em texto sem formatação será desabilitada " "pelo servidor." #: loginjob.cpp:383 #, kde-format msgid "Login failed, authentication mode %1 is not supported by the server." msgstr "" "Falha no login. O modo de autenticação %1 não é suportado pelo servidor." #: loginjob.cpp:413 #, kde-format msgid "Login failed, client cannot initialize the SASL library." msgstr "Falha no login, o cliente não consegue inicializar a biblioteca SASL." #: loginjob.cpp:512 #, kde-format msgid "Login failed, TLS negotiation failed." msgstr "Falha no login. A negociação TLS falhou." #: loginjob.cpp:570 #, kde-format msgid "SSL handshake failed." msgstr "A negociação de SSL falhou." #: logoutjob.cpp:33 #, kde-format msgid "Logout" msgstr "Encerrar sessão" #: metadatajobbase.cpp:53 #, kde-format msgid "MetaDataJobBase" msgstr "MetaDataJobBase" #: movejob.cpp:42 #, kde-format msgid "Move" msgstr "Mover" #: myrightsjob.cpp:37 #, kde-format msgid "MyRights" msgstr "MyRights" #: namespacejob.cpp:68 #, kde-format msgid "Namespace" msgstr "Espaço de nomes" #: quotajobbase.cpp:34 #, kde-format msgid "QuotaJobBase" msgstr "QuotaJobBase" #: renamejob.cpp:37 #, kde-format msgid "Rename" msgstr "Renomear" #: searchjob.cpp:361 #, kde-format msgctxt "Name of the search job" msgid "Search" msgstr "Pesquisar" #: selectjob.cpp:73 #, kde-format msgctxt "name of the select job" msgid "Select" msgstr "Selecionar" #: setacljob.cpp:34 #, kde-format msgid "SetAcl" msgstr "SetAcl" #: setmetadatajob.cpp:43 #, kde-format msgid "SetMetaData" msgstr "SetMetaData" #: setquotajob.cpp:37 #, kde-format msgid "SetQuota" msgstr "SetQuota" #: statusjob.cpp:40 #, kde-format msgctxt "name of the status job" msgid "Status" msgstr "Status" #: storejob.cpp:70 #, kde-format msgid "Store" msgstr "Armazenar" #: subscribejob.cpp:36 #, kde-format msgid "Subscribe" msgstr "Assinar" #: unsubscribejob.cpp:36 #, kde-format msgid "Unsubscribe" msgstr "Cancelar inscrição" 0707010000008D000041ED00000000000000000000000266FAD7C000000000000000000000000000000000000000000000002F00000000kimap-VERSIONgit.20240930T185424~db1f697/po/ro0707010000008E000081A400000000000000000000000166FAD7C000001387000000000000000000000000000000000000003C00000000kimap-VERSIONgit.20240930T185424~db1f697/po/ro/libkimap6.po# Copyright (C) YEAR This_file_is_part_of_KDE # This file is distributed under the same license as the PACKAGE package. # # Cristian Oneț <onet.cristian@gmail.com>, 2010. msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: https://bugs.kde.org\n" "POT-Creation-Date: 2022-05-11 00:45+0000\n" "PO-Revision-Date: 2010-11-28 17:14+0200\n" "Last-Translator: Cristian Oneț <onet.cristian@gmail.com>\n" "Language-Team: Romanian <kde-i18n-doc@kde.org>\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" #: acljobbase.cpp:56 #, kde-format msgid "AclJobBase" msgstr "" #: appendjob.cpp:40 #, kde-format msgid "Append" msgstr "Adaugă" #: capabilitiesjob.cpp:35 #, kde-format msgid "Capabilities" msgstr "Capacități" #: closejob.cpp:32 #, kde-format msgid "Close" msgstr "Închide" #: copyjob.cpp:41 #, kde-format msgid "Copy" msgstr "Copiază" #: createjob.cpp:36 #, kde-format msgid "Create" msgstr "Creează" #: deleteacljob.cpp:37 #, kde-format msgid "DeleteAclJob" msgstr "" #: deletejob.cpp:36 #, kde-format msgid "Delete" msgstr "Șterge" #: enablejob.cpp:31 #, kde-format msgid "Enable" msgstr "" #: expungejob.cpp:37 #, kde-format msgid "Expunge" msgstr "Elimină" #: fetchjob.cpp:97 #, kde-format msgid "Fetch" msgstr "Obține" #: getacljob.cpp:37 #, kde-format msgid "GetAcl" msgstr "" #: getmetadatajob.cpp:43 #, kde-format msgid "GetMetaData" msgstr "" #: getmetadatajob.cpp:66 #, kde-format msgid "GetAnnotation" msgstr "" #: getquotajob.cpp:35 #, kde-format msgid "GetQuota" msgstr "" #: getquotarootjob.cpp:38 #, kde-format msgid "GetQuotaRoot" msgstr "" #: idjob.cpp:35 #, fuzzy, kde-format #| msgctxt "name of the idle job" #| msgid "Idle" msgid "Id" msgstr "Inactiv" #: idlejob.cpp:65 #, kde-format msgctxt "name of the idle job" msgid "Idle" msgstr "Inactiv" #: job.cpp:19 #, kde-format msgid "Job" msgstr "Sarcină" #: job.cpp:54 loginjob.cpp:574 #, kde-format msgid "Connection to server lost." msgstr "Conexiunea la server a fost pierdută." #: job.cpp:65 loginjob.cpp:403 setmetadatajob.cpp:126 #, kde-format msgid "%1 failed, malformed reply from the server." msgstr "" #: job.cpp:68 loginjob.cpp:277 setmetadatajob.cpp:109 setmetadatajob.cpp:129 #, kde-format msgid "%1 failed, server replied: %2" msgstr "" #: listjob.cpp:59 #, kde-format msgid "List" msgstr "Listă" #: listrightsjob.cpp:38 #, kde-format msgid "ListRights" msgstr "" #: loginjob.cpp:129 loginjob.cpp:233 #, kde-format msgid "Login" msgstr "Autentificare" #: loginjob.cpp:184 #, kde-format msgid "IMAP session in the wrong state for authentication" msgstr "" #: loginjob.cpp:235 #, kde-format msgid "Capability" msgstr "Capacități" #: loginjob.cpp:237 #, kde-format msgid "StartTls" msgstr "" #: loginjob.cpp:340 #, kde-format msgid "STARTTLS is not supported by the server, try using SSL/TLS instead." msgstr "" #: loginjob.cpp:353 #, kde-format msgid "Internal error, tried to login before encryption" msgstr "" #: loginjob.cpp:362 #, kde-format msgid "Login failed, plain login is disabled by the server." msgstr "" "Autentificare eșuată. Autentificarea în clar este dezactivată de către " "server." #: loginjob.cpp:383 #, kde-format msgid "Login failed, authentication mode %1 is not supported by the server." msgstr "" "Autorizare eșuată, metoda de autentificare %1 nu este suportată de server." #: loginjob.cpp:413 #, kde-format msgid "Login failed, client cannot initialize the SASL library." msgstr "" #: loginjob.cpp:512 #, kde-format msgid "Login failed, TLS negotiation failed." msgstr "" #: loginjob.cpp:570 #, kde-format msgid "SSL handshake failed." msgstr "" #: logoutjob.cpp:33 #, kde-format msgid "Logout" msgstr "Deautentificare" #: metadatajobbase.cpp:53 #, kde-format msgid "MetaDataJobBase" msgstr "" #: movejob.cpp:42 #, kde-format msgid "Move" msgstr "" #: myrightsjob.cpp:37 #, kde-format msgid "MyRights" msgstr "" #: namespacejob.cpp:68 #, kde-format msgid "Namespace" msgstr "Domeniu de vizibilitate" #: quotajobbase.cpp:34 #, kde-format msgid "QuotaJobBase" msgstr "" #: renamejob.cpp:37 #, kde-format msgid "Rename" msgstr "Redenumește" #: searchjob.cpp:361 #, kde-format msgctxt "Name of the search job" msgid "Search" msgstr "Caută" #: selectjob.cpp:73 #, kde-format msgctxt "name of the select job" msgid "Select" msgstr "Alege" #: setacljob.cpp:34 #, kde-format msgid "SetAcl" msgstr "" #: setmetadatajob.cpp:43 #, kde-format msgid "SetMetaData" msgstr "" #: setquotajob.cpp:37 #, kde-format msgid "SetQuota" msgstr "" #: statusjob.cpp:40 #, kde-format msgctxt "name of the status job" msgid "Status" msgstr "" #: storejob.cpp:70 #, kde-format msgid "Store" msgstr "Stochează" #: subscribejob.cpp:36 #, kde-format msgid "Subscribe" msgstr "Abonează" #: unsubscribejob.cpp:36 #, kde-format msgid "Unsubscribe" msgstr "Dezabonează" 0707010000008F000041ED00000000000000000000000266FAD7C000000000000000000000000000000000000000000000002F00000000kimap-VERSIONgit.20240930T185424~db1f697/po/ru07070100000090000081A400000000000000000000000166FAD7C000002970000000000000000000000000000000000000003C00000000kimap-VERSIONgit.20240930T185424~db1f697/po/ru/libkimap6.po# 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>, 2011, 2014, 2015. # Alexander Lakhin <exclusion@gmail.com>, 2013. # Александр Яворский <yavorsky.a@t-rosta.com>, 2018. # Alexander Yavorsky <kekcuha@gmail.com>, 2020, 2022. msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: https://bugs.kde.org\n" "POT-Creation-Date: 2022-05-11 00:45+0000\n" "PO-Revision-Date: 2022-10-01 15:04+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" "X-Generator: Lokalize 21.08.3\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-Environment: kde\n" "X-Accelerator-Marker: &\n" "X-Text-Markup: kde4\n" # [JobPrivate::m_name] #: acljobbase.cpp:56 #, kde-format msgid "AclJobBase" msgstr "операцию с правами ACL" # [JobPrivate::m_name] # http://tools.ietf.org/html/rfc3501#section-6.3.11 #: appendjob.cpp:40 #, kde-format msgid "Append" msgstr "добавление письма в папку" # [JobPrivate::m_name] # http://tools.ietf.org/html/rfc3501#section-6.1.1 #: capabilitiesjob.cpp:35 #, kde-format msgid "Capabilities" msgstr "определение возможностей сервера" # [JobPrivate::m_name] # http://tools.ietf.org/html/rfc3501#section-6.4.2 #: closejob.cpp:32 #, kde-format msgid "Close" msgstr "закрытие сеанса" # [JobPrivate::m_name] # The proper translation here is "копирование", but we need a hack to hide this from the context menu for attachments in KMail. --aspotashev #: copyjob.cpp:41 #, kde-format msgid "Copy" msgstr "Копировать" # [JobPrivate::m_name] #: createjob.cpp:36 #, kde-format msgid "Create" msgstr "создание папки" # [JobPrivate::m_name] # http://tools.ietf.org/html/rfc4314#section-3.2 #: deleteacljob.cpp:37 #, kde-format msgid "DeleteAclJob" msgstr "удаление прав ACL" # [JobPrivate::m_name] # (BUGME: needs context to distinguish from other strings "Delete") # The proper translation here is "удаление папки", but we need a hack to hide this from the context menu for attachments in KMail. --aspotashev #: deletejob.cpp:36 #, kde-format msgid "Delete" msgstr "Удалить" #: enablejob.cpp:31 #, kde-format msgid "Enable" msgstr "Включить" # [JobPrivate::m_name] # http://tools.ietf.org/html/rfc3501#section-6.4.3 #: expungejob.cpp:37 #, kde-format msgid "Expunge" msgstr "стирание удалённых писем" # [JobPrivate::m_name] #: fetchjob.cpp:97 #, kde-format msgid "Fetch" msgstr "чтение письма" # [JobPrivate::m_name] # http://tools.ietf.org/html/rfc4314#section-3.3 #: getacljob.cpp:37 #, kde-format msgid "GetAcl" msgstr "определение прав ACL" # [JobPrivate::m_name] # http://tools.ietf.org/html/rfc5464#section-4.2 #: getmetadatajob.cpp:43 #, kde-format msgid "GetMetaData" msgstr "определение метаданных" # [JobPrivate::m_name] # http://tools.ietf.org/html/draft-daboo-imap-annotatemore-04#section-7.2 #: getmetadatajob.cpp:66 #, kde-format msgid "GetAnnotation" msgstr "получение примечаний к папке" # [JobPrivate::m_name] # http://tools.ietf.org/html/rfc2087#section-4.2 #: getquotajob.cpp:35 #, kde-format msgid "GetQuota" msgstr "определение ограничения объёма" # [JobPrivate::m_name] # http://tools.ietf.org/html/rfc2087#section-4.3 #: getquotarootjob.cpp:38 #, kde-format msgid "GetQuotaRoot" msgstr "определение ограничения объёма в папке" # [JobPrivate::m_name] #: idjob.cpp:35 #, kde-format msgid "Id" msgstr "определение идентификатора" # [JobPrivate::m_name] #: idlejob.cpp:65 #, kde-format msgctxt "name of the idle job" msgid "Idle" msgstr "задание бездействия" # [JobPrivate::m_name] #: job.cpp:19 #, kde-format msgid "Job" msgstr "задание" #: job.cpp:54 loginjob.cpp:574 #, kde-format msgid "Connection to server lost." msgstr "Соединение с сервером разорвано." # %1 = JobPrivate::m_name, в винительном падеже --aspotashev #: job.cpp:65 loginjob.cpp:403 setmetadatajob.cpp:126 #, kde-format msgid "%1 failed, malformed reply from the server." msgstr "Не удалось выполнить %1, неправильный формат ответа сервера." # %1 = JobPrivate::m_name, в винительном падеже --aspotashev #: job.cpp:68 loginjob.cpp:277 setmetadatajob.cpp:109 setmetadatajob.cpp:129 #, kde-format msgid "%1 failed, server replied: %2" msgstr "Не удалось выполнить %1, ответ сервера: %2" # [JobPrivate::m_name] # http://tools.ietf.org/html/rfc3501#section-6.3.8 #: listjob.cpp:59 #, kde-format msgid "List" msgstr "получение списка" # [JobPrivate::m_name] # http://tools.ietf.org/html/rfc4314#section-3.4 #: listrightsjob.cpp:38 #, kde-format msgid "ListRights" msgstr "получение списка возможных прав" # [JobPrivate::m_name] # http://tools.ietf.org/html/rfc3501#section-6.2.3 #: loginjob.cpp:129 loginjob.cpp:233 #, kde-format msgid "Login" msgstr "аутентификацию пользователя" #: loginjob.cpp:184 #, kde-format msgid "IMAP session in the wrong state for authentication" msgstr "Сессия IMAP в состоянии, не подходящем для аутентификации" # [JobPrivate::m_name] # http://tools.ietf.org/html/rfc3501#section-6.1.1 #: loginjob.cpp:235 #, kde-format msgid "Capability" msgstr "определение возможностей сервера" # [JobPrivate::m_name] # http://tools.ietf.org/html/rfc2595#section-3.1 #: loginjob.cpp:237 #, kde-format msgid "StartTls" msgstr "переход в режим шифрования TLS/SSL" #: loginjob.cpp:340 #, kde-format msgid "STARTTLS is not supported by the server, try using SSL/TLS instead." msgstr "" "Протокол установления защищённого соединения STARTTLS не поддерживается " "сервером, попробуйте использовать протокол SSL/TLS." #: loginjob.cpp:353 #, kde-format msgid "Internal error, tried to login before encryption" msgstr "Внутренняя ошибка: попытка входа до начала использования шифрования" #: loginjob.cpp:362 #, kde-format msgid "Login failed, plain login is disabled by the server." msgstr "Вход не удался (простая аутентификация запрещена на сервере)." #: loginjob.cpp:383 #, kde-format msgid "Login failed, authentication mode %1 is not supported by the server." msgstr "Вход не удался (сервер не поддерживает режим «%1»)." #: loginjob.cpp:413 #, kde-format msgid "Login failed, client cannot initialize the SASL library." msgstr "Вход не удался (клиент не смог инициализировать библиотеку SASL)." #: loginjob.cpp:512 #, kde-format msgid "Login failed, TLS negotiation failed." msgstr "Вход не удался (ошибка согласования TLS)." #: loginjob.cpp:570 #, kde-format msgid "SSL handshake failed." msgstr "Произошла ошибка во время обмена приветствиями SSL." # [JobPrivate::m_name] # http://tools.ietf.org/html/rfc3501#section-6.1.3 #: logoutjob.cpp:33 #, kde-format msgid "Logout" msgstr "закрытие соединения" # [JobPrivate::m_name] #: metadatajobbase.cpp:53 #, kde-format msgid "MetaDataJobBase" msgstr "операцию с метаданными" #: movejob.cpp:42 #, kde-format msgid "Move" msgstr "перемещение" # [JobPrivate::m_name] # http://tools.ietf.org/html/rfc4314#section-3.5 #: myrightsjob.cpp:37 #, kde-format msgid "MyRights" msgstr "определение прав пользователя" # [JobPrivate::m_name] # http://tools.ietf.org/html/rfc2342#section-5 #: namespacejob.cpp:68 #, kde-format msgid "Namespace" msgstr "определение пространств имён" # [JobPrivate::m_name] #: quotajobbase.cpp:34 #, kde-format msgid "QuotaJobBase" msgstr "операцию с ограничениями объёмов папок" # [JobPrivate::m_name] # http://tools.ietf.org/html/rfc3501#section-6.3.5 #: renamejob.cpp:37 #, kde-format msgid "Rename" msgstr "переименование папки" # [JobPrivate::m_name] # http://tools.ietf.org/html/rfc3501#section-6.4.4 #: searchjob.cpp:361 #, kde-format msgctxt "Name of the search job" msgid "Search" msgstr "поиск" # [JobPrivate::m_name] # http://tools.ietf.org/html/rfc3501#section-6.3.1 #: selectjob.cpp:73 #, kde-format msgctxt "name of the select job" msgid "Select" msgstr "выбор папки" # [JobPrivate::m_name] # http://tools.ietf.org/html/rfc4314#section-3.1 #: setacljob.cpp:34 #, kde-format msgid "SetAcl" msgstr "установку прав ACL" # [JobPrivate::m_name] # http://tools.ietf.org/html/rfc5464#section-4.3 #: setmetadatajob.cpp:43 #, kde-format msgid "SetMetaData" msgstr "установку метаданных" # [JobPrivate::m_name] # http://tools.ietf.org/html/rfc2087#section-4.1 #: setquotajob.cpp:37 #, kde-format msgid "SetQuota" msgstr "установку ограничения объёма в папке" #: statusjob.cpp:40 #, kde-format msgctxt "name of the status job" msgid "Status" msgstr "определение состояния" # [JobPrivate::m_name] # http://tools.ietf.org/html/rfc3501#section-6.4.6 #: storejob.cpp:70 #, kde-format msgid "Store" msgstr "запись данных в письмо" # [JobPrivate::m_name] # http://tools.ietf.org/html/rfc3501#section-6.3.6 #: subscribejob.cpp:36 #, kde-format msgid "Subscribe" msgstr "подписку на папку" # [JobPrivate::m_name] # http://tools.ietf.org/html/rfc3501#section-6.3.7 #: unsubscribejob.cpp:36 #, kde-format msgid "Unsubscribe" msgstr "отмену подписки на папку" # [JobPrivate::m_name] # http://tools.ietf.org/html/draft-daboo-imap-annotatemore-04#section-7.3 #~ msgid "SetAnnotation" #~ msgstr "установку примечаний к папке" 07070100000091000041ED00000000000000000000000266FAD7C000000000000000000000000000000000000000000000002F00000000kimap-VERSIONgit.20240930T185424~db1f697/po/sk07070100000092000081A400000000000000000000000166FAD7C00000158C000000000000000000000000000000000000003C00000000kimap-VERSIONgit.20240930T185424~db1f697/po/sk/libkimap6.po# translation of libkimap5.po to Slovak # Roman Paholík <wizzardsk@gmail.com>, 2014, 2016, 2022. # Matej Mrenica <matejm98mthw@gmail.com>, 2019. msgid "" msgstr "" "Project-Id-Version: libkimap5\n" "Report-Msgid-Bugs-To: https://bugs.kde.org\n" "POT-Creation-Date: 2022-05-11 00:45+0000\n" "PO-Revision-Date: 2022-04-09 20:15+0200\n" "Last-Translator: Roman Paholik <wizzardsk@gmail.com>\n" "Language-Team: Slovak <kde-sk@linux.sk>\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.3\n" "Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n" #: acljobbase.cpp:56 #, kde-format msgid "AclJobBase" msgstr "AclJobBase" #: appendjob.cpp:40 #, kde-format msgid "Append" msgstr "Pripojiť" #: capabilitiesjob.cpp:35 #, kde-format msgid "Capabilities" msgstr "Schopnosti" #: closejob.cpp:32 #, kde-format msgid "Close" msgstr "Zavrieť" #: copyjob.cpp:41 #, kde-format msgid "Copy" msgstr "Kopírovať" #: createjob.cpp:36 #, kde-format msgid "Create" msgstr "Vytvoriť" #: deleteacljob.cpp:37 #, kde-format msgid "DeleteAclJob" msgstr "DeleteAclJob" #: deletejob.cpp:36 #, kde-format msgid "Delete" msgstr "Vymazať" #: enablejob.cpp:31 #, kde-format msgid "Enable" msgstr "Povoliť" #: expungejob.cpp:37 #, kde-format msgid "Expunge" msgstr "Vyčistiť" #: fetchjob.cpp:97 #, kde-format msgid "Fetch" msgstr "Získať" #: getacljob.cpp:37 #, kde-format msgid "GetAcl" msgstr "GetAcl" #: getmetadatajob.cpp:43 #, kde-format msgid "GetMetaData" msgstr "GetMetaData" #: getmetadatajob.cpp:66 #, kde-format msgid "GetAnnotation" msgstr "GetAnnotation" #: getquotajob.cpp:35 #, kde-format msgid "GetQuota" msgstr "GetQuota" #: getquotarootjob.cpp:38 #, kde-format msgid "GetQuotaRoot" msgstr "GetQuotaRoot" #: idjob.cpp:35 #, kde-format msgid "Id" msgstr "Id" #: idlejob.cpp:65 #, kde-format msgctxt "name of the idle job" msgid "Idle" msgstr "Nečinný" #: job.cpp:19 #, kde-format msgid "Job" msgstr "Úloha" #: job.cpp:54 loginjob.cpp:574 #, kde-format msgid "Connection to server lost." msgstr "Spojenie k serveru bolo stratené." #: job.cpp:65 loginjob.cpp:403 setmetadatajob.cpp:126 #, kde-format msgid "%1 failed, malformed reply from the server." msgstr "%1 zlyhalo, neplatná odpoveď zo servera." #: job.cpp:68 loginjob.cpp:277 setmetadatajob.cpp:109 setmetadatajob.cpp:129 #, kde-format msgid "%1 failed, server replied: %2" msgstr "%1 zlyhalo, server odpovedal: %2" #: listjob.cpp:59 #, kde-format msgid "List" msgstr "Zoznam" #: listrightsjob.cpp:38 #, kde-format msgid "ListRights" msgstr "ListRights" #: loginjob.cpp:129 loginjob.cpp:233 #, kde-format msgid "Login" msgstr "Prihlásenie" #: loginjob.cpp:184 #, kde-format msgid "IMAP session in the wrong state for authentication" msgstr "IMAP sedenie v zlom stave na overenie" #: loginjob.cpp:235 #, kde-format msgid "Capability" msgstr "Schopnosti" #: loginjob.cpp:237 #, kde-format msgid "StartTls" msgstr "StartTls" #: loginjob.cpp:340 #, kde-format msgid "STARTTLS is not supported by the server, try using SSL/TLS instead." msgstr "" "STARTTLS nie je podporovaný serverom, skúste namiesto toho použiť SSL/TLS." #: loginjob.cpp:353 #, kde-format msgid "Internal error, tried to login before encryption" msgstr "Interná chyba, pokus o prihlásenie pred šifrovaním" #: loginjob.cpp:362 #, kde-format msgid "Login failed, plain login is disabled by the server." msgstr "Pihlásenie zlyhalo, čisté prihlásenie je zakázané na serveri." #: loginjob.cpp:383 #, kde-format msgid "Login failed, authentication mode %1 is not supported by the server." msgstr "Prihlásenie zlyhalo, režim overenia %1 nepodporovaný serverom." #: loginjob.cpp:413 #, kde-format msgid "Login failed, client cannot initialize the SASL library." msgstr "Prihlásenie zlyhalo, klient nemôže inicializovať knižnicu SASL." #: loginjob.cpp:512 #, kde-format msgid "Login failed, TLS negotiation failed." msgstr "Prihlásenie zlyhalo, TLS skúška zlyhala." #: loginjob.cpp:570 #, kde-format msgid "SSL handshake failed." msgstr "SSL handshake zlyhalo." #: logoutjob.cpp:33 #, kde-format msgid "Logout" msgstr "Odhlásenie" #: metadatajobbase.cpp:53 #, kde-format msgid "MetaDataJobBase" msgstr "MetaDataJobBase" #: movejob.cpp:42 #, kde-format msgid "Move" msgstr "Presunúť" #: myrightsjob.cpp:37 #, kde-format msgid "MyRights" msgstr "MyRights" #: namespacejob.cpp:68 #, kde-format msgid "Namespace" msgstr "Menný priestor" #: quotajobbase.cpp:34 #, kde-format msgid "QuotaJobBase" msgstr "QuotaJobBase" #: renamejob.cpp:37 #, kde-format msgid "Rename" msgstr "Premenovať" #: searchjob.cpp:361 #, kde-format msgctxt "Name of the search job" msgid "Search" msgstr "Hľadať" #: selectjob.cpp:73 #, kde-format msgctxt "name of the select job" msgid "Select" msgstr "Vybrať" #: setacljob.cpp:34 #, kde-format msgid "SetAcl" msgstr "SetAcl" #: setmetadatajob.cpp:43 #, kde-format msgid "SetMetaData" msgstr "SetMetaData" #: setquotajob.cpp:37 #, kde-format msgid "SetQuota" msgstr "SetQuota" #: statusjob.cpp:40 #, kde-format msgctxt "name of the status job" msgid "Status" msgstr "Stav" #: storejob.cpp:70 #, kde-format msgid "Store" msgstr "Uložiť" #: subscribejob.cpp:36 #, kde-format msgid "Subscribe" msgstr "Prihlásiť sa" #: unsubscribejob.cpp:36 #, kde-format msgid "Unsubscribe" msgstr "Odhlásiť" #~ msgid "SetAnnotation" #~ msgstr "SetAnnotation" #~ msgid "Mock" #~ msgstr "Posmech" 07070100000093000041ED00000000000000000000000266FAD7C000000000000000000000000000000000000000000000002F00000000kimap-VERSIONgit.20240930T185424~db1f697/po/sl07070100000094000081A400000000000000000000000166FAD7C0000015F0000000000000000000000000000000000000003C00000000kimap-VERSIONgit.20240930T185424~db1f697/po/sl/libkimap6.po# Slovenian translation of libkimap5 # Copyright (C) YEAR This_file_is_part_of_KDE # This file is distributed under the same license as the PACKAGE package. # # Andrej Mernik <andrejm@ubuntu.si>, 2014, 2016. # Matjaž Jeran <matjaz.jeran@amis.net>, 2019, 2020. msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: https://bugs.kde.org\n" "POT-Creation-Date: 2022-05-11 00:45+0000\n" "PO-Revision-Date: 2022-01-29 09:34+0100\n" "Last-Translator: Martin Srebotnjak <miles@filmsi.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" "Plural-Forms: nplurals=4; plural=(n%100==1 ? 1 : n%100==2 ? 2 : n%100==3 || n" "%100==4 ? 3 : 0);\n" "Translator: Andrej Mernik <andrejm@ubuntu.si>\n" "X-Generator: Poedit 3.0.1\n" #: acljobbase.cpp:56 #, kde-format msgid "AclJobBase" msgstr "AclJobBase" #: appendjob.cpp:40 #, kde-format msgid "Append" msgstr "Pripni" #: capabilitiesjob.cpp:35 #, kde-format msgid "Capabilities" msgstr "Zmožnosti" #: closejob.cpp:32 #, kde-format msgid "Close" msgstr "Zapri" #: copyjob.cpp:41 #, kde-format msgid "Copy" msgstr "Kopiraj" #: createjob.cpp:36 #, kde-format msgid "Create" msgstr "Ustvari" #: deleteacljob.cpp:37 #, kde-format msgid "DeleteAclJob" msgstr "DeleteAclJob" #: deletejob.cpp:36 #, kde-format msgid "Delete" msgstr "Izbriši" #: enablejob.cpp:31 #, kde-format msgid "Enable" msgstr "Omogoči" #: expungejob.cpp:37 #, kde-format msgid "Expunge" msgstr "Izbriši" #: fetchjob.cpp:97 #, kde-format msgid "Fetch" msgstr "Pridobi" #: getacljob.cpp:37 #, kde-format msgid "GetAcl" msgstr "DobiAcl" #: getmetadatajob.cpp:43 #, kde-format msgid "GetMetaData" msgstr "GetMetaData" #: getmetadatajob.cpp:66 #, kde-format msgid "GetAnnotation" msgstr "GetAnnotation" #: getquotajob.cpp:35 #, kde-format msgid "GetQuota" msgstr "GetQuota" #: getquotarootjob.cpp:38 #, kde-format msgid "GetQuotaRoot" msgstr "GetQuotaRoot" #: idjob.cpp:35 #, kde-format msgid "Id" msgstr "ID" #: idlejob.cpp:65 #, kde-format msgctxt "name of the idle job" msgid "Idle" msgstr "Nedejavno" #: job.cpp:19 #, kde-format msgid "Job" msgstr "Posel" #: job.cpp:54 loginjob.cpp:574 #, kde-format msgid "Connection to server lost." msgstr "Povezava s strežnikom je bila izgubljena." #: job.cpp:65 loginjob.cpp:403 setmetadatajob.cpp:126 #, kde-format msgid "%1 failed, malformed reply from the server." msgstr "%1 ni uspel, odgovor strežnika je napačno oblikovan." #: job.cpp:68 loginjob.cpp:277 setmetadatajob.cpp:109 setmetadatajob.cpp:129 #, kde-format msgid "%1 failed, server replied: %2" msgstr "%1 ni uspel, strežnik je odgovoril: %2" #: listjob.cpp:59 #, kde-format msgid "List" msgstr "Seznam" #: listrightsjob.cpp:38 #, kde-format msgid "ListRights" msgstr "ListRights" #: loginjob.cpp:129 loginjob.cpp:233 #, kde-format msgid "Login" msgstr "Prijava" #: loginjob.cpp:184 #, kde-format msgid "IMAP session in the wrong state for authentication" msgstr "Seja IMAP je v napačnem stanju za overitev" #: loginjob.cpp:235 #, kde-format msgid "Capability" msgstr "Zmožnost" #: loginjob.cpp:237 #, kde-format msgid "StartTls" msgstr "StartTls" #: loginjob.cpp:340 #, kde-format msgid "STARTTLS is not supported by the server, try using SSL/TLS instead." msgstr "" "Strežnik ne podpira STARTTLS, poskusite namesto tega uporabiti SSL/TLS." #: loginjob.cpp:353 #, kde-format msgid "Internal error, tried to login before encryption" msgstr "Notranja napaka, poskus prijave pred šifriranjem" #: loginjob.cpp:362 #, kde-format msgid "Login failed, plain login is disabled by the server." msgstr "Prijava ni uspela, strežnik je onemogočil običajno prijavo." #: loginjob.cpp:383 #, kde-format msgid "Login failed, authentication mode %1 is not supported by the server." msgstr "Prijava ni uspela, strežnik ne podpira načina za overitev %1." #: loginjob.cpp:413 #, kde-format msgid "Login failed, client cannot initialize the SASL library." msgstr "Prijava ni uspela, odjemalec ne more začeti knjižnice SASL." #: loginjob.cpp:512 #, kde-format msgid "Login failed, TLS negotiation failed." msgstr "Prijava ni uspela, pogajanja TLS so bila neuspešna." #: loginjob.cpp:570 #, kde-format msgid "SSL handshake failed." msgstr "Rokovanje SSL je spodletelo." #: logoutjob.cpp:33 #, kde-format msgid "Logout" msgstr "Odjava" #: metadatajobbase.cpp:53 #, kde-format msgid "MetaDataJobBase" msgstr "MetaDataJobBase" #: movejob.cpp:42 #, kde-format msgid "Move" msgstr "Premakni" #: myrightsjob.cpp:37 #, kde-format msgid "MyRights" msgstr "MyRights" #: namespacejob.cpp:68 #, kde-format msgid "Namespace" msgstr "Imenski prostor" #: quotajobbase.cpp:34 #, kde-format msgid "QuotaJobBase" msgstr "QuotaJobBase" #: renamejob.cpp:37 #, kde-format msgid "Rename" msgstr "Preimenuj" #: searchjob.cpp:361 #, kde-format msgctxt "Name of the search job" msgid "Search" msgstr "Poišči" #: selectjob.cpp:73 #, kde-format msgctxt "name of the select job" msgid "Select" msgstr "Izberi" #: setacljob.cpp:34 #, kde-format msgid "SetAcl" msgstr "NastaviAcl" #: setmetadatajob.cpp:43 #, kde-format msgid "SetMetaData" msgstr "SetMetaData" #: setquotajob.cpp:37 #, kde-format msgid "SetQuota" msgstr "SetQuota" #: statusjob.cpp:40 #, kde-format msgctxt "name of the status job" msgid "Status" msgstr "Stanje" #: storejob.cpp:70 #, kde-format msgid "Store" msgstr "Shrani" #: subscribejob.cpp:36 #, kde-format msgid "Subscribe" msgstr "Naroči se" #: unsubscribejob.cpp:36 #, kde-format msgid "Unsubscribe" msgstr "Prekliči naročnino" 07070100000095000041ED00000000000000000000000266FAD7C000000000000000000000000000000000000000000000002F00000000kimap-VERSIONgit.20240930T185424~db1f697/po/sq07070100000096000081A400000000000000000000000166FAD7C00000143C000000000000000000000000000000000000003C00000000kimap-VERSIONgit.20240930T185424~db1f697/po/sq/libkimap6.po# Albanian translation for kdepimlibs # Copyright (c) 2009 Rosetta Contributors and Canonical Ltd 2009 # This file is distributed under the same license as the kdepimlibs package. # FIRST AUTHOR <EMAIL@ADDRESS>, 2009. # msgid "" msgstr "" "Project-Id-Version: kdepimlibs\n" "Report-Msgid-Bugs-To: https://bugs.kde.org\n" "POT-Creation-Date: 2022-05-11 00:45+0000\n" "PO-Revision-Date: 2009-12-24 06:32+0000\n" "Last-Translator: Launchpad Translations Administrators <rosetta@launchpad." "net>\n" "Language-Team: Albanian <sq@li.org>\n" "Language: sq\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Launchpad-Export-Date: 2011-04-21 23:37+0000\n" "X-Generator: Launchpad (build 12883)\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" #: acljobbase.cpp:56 #, kde-format msgid "AclJobBase" msgstr "AclJobBase" #: appendjob.cpp:40 #, kde-format msgid "Append" msgstr "Mvare" #: capabilitiesjob.cpp:35 #, kde-format msgid "Capabilities" msgstr "Aftësi" #: closejob.cpp:32 #, kde-format msgid "Close" msgstr "Mbylle" #: copyjob.cpp:41 #, kde-format msgid "Copy" msgstr "Kopjo" #: createjob.cpp:36 #, kde-format msgid "Create" msgstr "Krijo" #: deleteacljob.cpp:37 #, kde-format msgid "DeleteAclJob" msgstr "DeleteAclJob" #: deletejob.cpp:36 #, kde-format msgid "Delete" msgstr "Fshije" #: enablejob.cpp:31 #, kde-format msgid "Enable" msgstr "" #: expungejob.cpp:37 #, kde-format msgid "Expunge" msgstr "Përzëre" #: fetchjob.cpp:97 #, kde-format msgid "Fetch" msgstr "Mblidh" #: getacljob.cpp:37 #, kde-format msgid "GetAcl" msgstr "GetAcl" #: getmetadatajob.cpp:43 #, kde-format msgid "GetMetaData" msgstr "GetMetaData" #: getmetadatajob.cpp:66 #, kde-format msgid "GetAnnotation" msgstr "GetAnnotation" #: getquotajob.cpp:35 #, kde-format msgid "GetQuota" msgstr "GetQuota" #: getquotarootjob.cpp:38 #, kde-format msgid "GetQuotaRoot" msgstr "GetQuotaRoot" #: idjob.cpp:35 #, kde-format msgid "Id" msgstr "" #: idlejob.cpp:65 #, kde-format msgctxt "name of the idle job" msgid "Idle" msgstr "" #: job.cpp:19 #, kde-format msgid "Job" msgstr "Puna" #: job.cpp:54 loginjob.cpp:574 #, kde-format msgid "Connection to server lost." msgstr "Lidhja me serverin humbi." #: job.cpp:65 loginjob.cpp:403 setmetadatajob.cpp:126 #, kde-format msgid "%1 failed, malformed reply from the server." msgstr "" #: job.cpp:68 loginjob.cpp:277 setmetadatajob.cpp:109 setmetadatajob.cpp:129 #, kde-format msgid "%1 failed, server replied: %2" msgstr "" #: listjob.cpp:59 #, kde-format msgid "List" msgstr "Lista" #: listrightsjob.cpp:38 #, kde-format msgid "ListRights" msgstr "ListRights" #: loginjob.cpp:129 loginjob.cpp:233 #, kde-format msgid "Login" msgstr "Hyrje" #: loginjob.cpp:184 #, kde-format msgid "IMAP session in the wrong state for authentication" msgstr "" #: loginjob.cpp:235 #, kde-format msgid "Capability" msgstr "Aftësia" #: loginjob.cpp:237 #, kde-format msgid "StartTls" msgstr "StartTls" #: loginjob.cpp:340 #, kde-format msgid "STARTTLS is not supported by the server, try using SSL/TLS instead." msgstr "" #: loginjob.cpp:353 #, kde-format msgid "Internal error, tried to login before encryption" msgstr "" #: loginjob.cpp:362 #, kde-format msgid "Login failed, plain login is disabled by the server." msgstr "" #: loginjob.cpp:383 #, kde-format msgid "Login failed, authentication mode %1 is not supported by the server." msgstr "" #: loginjob.cpp:413 #, kde-format msgid "Login failed, client cannot initialize the SASL library." msgstr "" #: loginjob.cpp:512 #, kde-format msgid "Login failed, TLS negotiation failed." msgstr "" #: loginjob.cpp:570 #, kde-format msgid "SSL handshake failed." msgstr "" #: logoutjob.cpp:33 #, kde-format msgid "Logout" msgstr "Dalja" #: metadatajobbase.cpp:53 #, kde-format msgid "MetaDataJobBase" msgstr "MetaDataJobBase" #: movejob.cpp:42 #, kde-format msgid "Move" msgstr "" #: myrightsjob.cpp:37 #, kde-format msgid "MyRights" msgstr "MyRights" #: namespacejob.cpp:68 #, kde-format msgid "Namespace" msgstr "" #: quotajobbase.cpp:34 #, kde-format msgid "QuotaJobBase" msgstr "QuotaJobBase" #: renamejob.cpp:37 #, kde-format msgid "Rename" msgstr "Riemërto" #: searchjob.cpp:361 #, kde-format msgctxt "Name of the search job" msgid "Search" msgstr "" #: selectjob.cpp:73 #, kde-format msgctxt "name of the select job" msgid "Select" msgstr "" #: setacljob.cpp:34 #, kde-format msgid "SetAcl" msgstr "SetAcl" #: setmetadatajob.cpp:43 #, kde-format msgid "SetMetaData" msgstr "SetMetaData" #: setquotajob.cpp:37 #, kde-format msgid "SetQuota" msgstr "SetQuota" #: statusjob.cpp:40 #, kde-format msgctxt "name of the status job" msgid "Status" msgstr "" #: storejob.cpp:70 #, kde-format msgid "Store" msgstr "Ruaje" #: subscribejob.cpp:36 #, kde-format msgid "Subscribe" msgstr "Regjistrimi" #: unsubscribejob.cpp:36 #, kde-format msgid "Unsubscribe" msgstr "Çregjistrohu" #~ msgid "SetAnnotation" #~ msgstr "SetAnnotation" #~ msgctxt "NAME OF TRANSLATORS" #~ msgid "Your names" #~ msgstr " ,Launchpad Contributions:,Vilson Gjeci" #~ msgctxt "EMAIL OF TRANSLATORS" #~ msgid "Your emails" #~ msgstr ",,vilsongjeci@gmail.com" 07070100000097000041ED00000000000000000000000266FAD7C000000000000000000000000000000000000000000000002F00000000kimap-VERSIONgit.20240930T185424~db1f697/po/sr07070100000098000081A400000000000000000000000166FAD7C0000019A5000000000000000000000000000000000000003C00000000kimap-VERSIONgit.20240930T185424~db1f697/po/sr/libkimap6.po# Translation of libkimap5.po into Serbian. # Chusslove Illich <caslav.ilic@gmx.net>, 2009, 2010, 2013, 2014, 2016. # Dalibor Djuric <dalibor.djuric@mozilla-srbija.org>, 2009. # Dalibor Djuric <daliborddjuric@gmail.com>, 2010. msgid "" msgstr "" "Project-Id-Version: libkimap5\n" "Report-Msgid-Bugs-To: https://bugs.kde.org\n" "POT-Creation-Date: 2022-05-11 00:45+0000\n" "PO-Revision-Date: 2016-11-28 01:33+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" #: acljobbase.cpp:56 #, kde-format msgid "AclJobBase" msgstr "AclJobBase" #: appendjob.cpp:40 #, kde-format msgid "Append" msgstr "Прикачивање" #: capabilitiesjob.cpp:35 #, kde-format msgid "Capabilities" msgstr "Одређивање могућности" #: closejob.cpp:32 #, kde-format msgid "Close" msgstr "Затварање" #: copyjob.cpp:41 #, kde-format msgid "Copy" msgstr "Копирање" #: createjob.cpp:36 #, kde-format msgid "Create" msgstr "Стварање" #: deleteacljob.cpp:37 #, kde-format msgid "DeleteAclJob" msgstr "Брисање АЦЛ‑а" #: deletejob.cpp:36 #, kde-format msgid "Delete" msgstr "Брисање" #: enablejob.cpp:31 #, kde-format msgid "Enable" msgstr "" #: expungejob.cpp:37 #, kde-format msgid "Expunge" msgstr "Прочишћавање" #: fetchjob.cpp:97 #, kde-format msgid "Fetch" msgstr "Добављање" #: getacljob.cpp:37 #, kde-format msgid "GetAcl" msgstr "Добављање АЦЛ‑а" #: getmetadatajob.cpp:43 #, kde-format msgid "GetMetaData" msgstr "Добављање метаподатака" #: getmetadatajob.cpp:66 #, kde-format msgid "GetAnnotation" msgstr "Добављање тумачења" #: getquotajob.cpp:35 #, kde-format msgid "GetQuota" msgstr "Добављање квоте" #: getquotarootjob.cpp:38 #, kde-format msgid "GetQuotaRoot" msgstr "Добављање квоте корена" #: idjob.cpp:35 #, kde-format msgid "Id" msgstr "ИД" #: idlejob.cpp:65 #, kde-format msgctxt "name of the idle job" msgid "Idle" msgstr "Мировање" #: job.cpp:19 #, kde-format msgid "Job" msgstr "Посао" #: job.cpp:54 loginjob.cpp:574 #, kde-format msgid "Connection to server lost." msgstr "Веза са сервером је изгубљена." # >> %1 is a job name, like 'Fetch', 'Delete', etc. #: job.cpp:65 loginjob.cpp:403 setmetadatajob.cpp:126 #, kde-format msgid "%1 failed, malformed reply from the server." msgstr "%1 неуспело, лоше формиран одговор са сервера." # >> %1 is a job name, like 'Fetch', 'Delete', etc. #: job.cpp:68 loginjob.cpp:277 setmetadatajob.cpp:109 setmetadatajob.cpp:129 #, kde-format msgid "%1 failed, server replied: %2" msgstr "%1 неуспело, сервер одговара: %2" # skip-rule: t-list #: listjob.cpp:59 #, kde-format msgid "List" msgstr "Листање" # skip-rule: t-list #: listrightsjob.cpp:38 #, kde-format msgid "ListRights" msgstr "Листање права" #: loginjob.cpp:129 loginjob.cpp:233 #, kde-format msgid "Login" msgstr "Пријављивање" #: loginjob.cpp:184 #, kde-format msgid "IMAP session in the wrong state for authentication" msgstr "ИМАП сесија је у погрешном стању за аутентификацију." #: loginjob.cpp:235 #, kde-format msgid "Capability" msgstr "Одређивање могућности" #: loginjob.cpp:237 #, kde-format msgid "StartTls" msgstr "Покретање ТЛС‑а" #: loginjob.cpp:340 #, kde-format msgid "STARTTLS is not supported by the server, try using SSL/TLS instead." msgstr "" #: loginjob.cpp:353 #, kde-format msgid "Internal error, tried to login before encryption" msgstr "" #: loginjob.cpp:362 #, kde-format msgid "Login failed, plain login is disabled by the server." msgstr "Пријављивање неуспело, сервер не дозвољава просто пријављивање." #: loginjob.cpp:383 #, kde-format msgid "Login failed, authentication mode %1 is not supported by the server." msgstr "Пријављивање неуспело, сервер не подржава режим аутентификације %1." #: loginjob.cpp:413 #, kde-format msgid "Login failed, client cannot initialize the SASL library." msgstr "Пријављивање неуспело, клијент не може да припреми САСЛ библиотеку." #: loginjob.cpp:512 #, kde-format msgid "Login failed, TLS negotiation failed." msgstr "Пријављивање неуспело, ТЛС преговори неуспешни." #: loginjob.cpp:570 #, kde-format msgid "SSL handshake failed." msgstr "ССЛ руковање пропало." #: logoutjob.cpp:33 #, kde-format msgid "Logout" msgstr "Одјављивање" #: metadatajobbase.cpp:53 #, kde-format msgid "MetaDataJobBase" msgstr "MetaDataJobBase" #: movejob.cpp:42 #, kde-format msgid "Move" msgstr "Премештање" #: myrightsjob.cpp:37 #, kde-format msgid "MyRights" msgstr "Добављање мојих права" #: namespacejob.cpp:68 #, kde-format msgid "Namespace" msgstr "Именски простор" #: quotajobbase.cpp:34 #, kde-format msgid "QuotaJobBase" msgstr "QuotaJobBase" #: renamejob.cpp:37 #, kde-format msgid "Rename" msgstr "Преименовање" #: searchjob.cpp:361 #, kde-format msgctxt "Name of the search job" msgid "Search" msgstr "Претраживање" #: selectjob.cpp:73 #, kde-format msgctxt "name of the select job" msgid "Select" msgstr "Бирање" #: setacljob.cpp:34 #, kde-format msgid "SetAcl" msgstr "Постављање АЦЛ‑а" #: setmetadatajob.cpp:43 #, kde-format msgid "SetMetaData" msgstr "Постављање метаподатака" #: setquotajob.cpp:37 #, kde-format msgid "SetQuota" msgstr "Постављање квоте" #: statusjob.cpp:40 #, kde-format msgctxt "name of the status job" msgid "Status" msgstr "Стање" #: storejob.cpp:70 #, kde-format msgid "Store" msgstr "Складиштење" #: subscribejob.cpp:36 #, kde-format msgid "Subscribe" msgstr "Претплаћивање" #: unsubscribejob.cpp:36 #, kde-format msgid "Unsubscribe" msgstr "Укидање претплате" 07070100000099000041ED00000000000000000000000266FAD7C000000000000000000000000000000000000000000000003900000000kimap-VERSIONgit.20240930T185424~db1f697/po/sr@ijekavian0707010000009A000081A400000000000000000000000166FAD7C0000019BF000000000000000000000000000000000000004600000000kimap-VERSIONgit.20240930T185424~db1f697/po/sr@ijekavian/libkimap6.po# Translation of libkimap5.po into Serbian. # Chusslove Illich <caslav.ilic@gmx.net>, 2009, 2010, 2013, 2014, 2016. # Dalibor Djuric <dalibor.djuric@mozilla-srbija.org>, 2009. # Dalibor Djuric <daliborddjuric@gmail.com>, 2010. msgid "" msgstr "" "Project-Id-Version: libkimap5\n" "Report-Msgid-Bugs-To: https://bugs.kde.org\n" "POT-Creation-Date: 2022-05-11 00:45+0000\n" "PO-Revision-Date: 2016-11-28 01:33+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" #: acljobbase.cpp:56 #, kde-format msgid "AclJobBase" msgstr "AclJobBase" #: appendjob.cpp:40 #, kde-format msgid "Append" msgstr "Прикачивање" #: capabilitiesjob.cpp:35 #, kde-format msgid "Capabilities" msgstr "Одређивање могућности" #: closejob.cpp:32 #, kde-format msgid "Close" msgstr "Затварање" #: copyjob.cpp:41 #, kde-format msgid "Copy" msgstr "Копирање" #: createjob.cpp:36 #, kde-format msgid "Create" msgstr "Стварање" #: deleteacljob.cpp:37 #, kde-format msgid "DeleteAclJob" msgstr "Брисање АЦЛ‑а" #: deletejob.cpp:36 #, kde-format msgid "Delete" msgstr "Брисање" #: enablejob.cpp:31 #, kde-format msgid "Enable" msgstr "" #: expungejob.cpp:37 #, kde-format msgid "Expunge" msgstr "Прочишћавање" #: fetchjob.cpp:97 #, kde-format msgid "Fetch" msgstr "Добављање" #: getacljob.cpp:37 #, kde-format msgid "GetAcl" msgstr "Добављање АЦЛ‑а" #: getmetadatajob.cpp:43 #, kde-format msgid "GetMetaData" msgstr "Добављање метаподатака" #: getmetadatajob.cpp:66 #, kde-format msgid "GetAnnotation" msgstr "Добављање тумачења" #: getquotajob.cpp:35 #, kde-format msgid "GetQuota" msgstr "Добављање квоте" #: getquotarootjob.cpp:38 #, kde-format msgid "GetQuotaRoot" msgstr "Добављање квоте коријена" #: idjob.cpp:35 #, kde-format msgid "Id" msgstr "ИД" #: idlejob.cpp:65 #, kde-format msgctxt "name of the idle job" msgid "Idle" msgstr "Мировање" #: job.cpp:19 #, kde-format msgid "Job" msgstr "Посао" #: job.cpp:54 loginjob.cpp:574 #, kde-format msgid "Connection to server lost." msgstr "Веза са сервером је изгубљена." # >> %1 is a job name, like 'Fetch', 'Delete', etc. #: job.cpp:65 loginjob.cpp:403 setmetadatajob.cpp:126 #, kde-format msgid "%1 failed, malformed reply from the server." msgstr "%1 неуспјело, лоше формиран одговор са сервера." # >> %1 is a job name, like 'Fetch', 'Delete', etc. #: job.cpp:68 loginjob.cpp:277 setmetadatajob.cpp:109 setmetadatajob.cpp:129 #, kde-format msgid "%1 failed, server replied: %2" msgstr "%1 неуспјело, сервер одговара: %2" # skip-rule: t-list #: listjob.cpp:59 #, kde-format msgid "List" msgstr "Листање" # skip-rule: t-list #: listrightsjob.cpp:38 #, kde-format msgid "ListRights" msgstr "Листање права" #: loginjob.cpp:129 loginjob.cpp:233 #, kde-format msgid "Login" msgstr "Пријављивање" #: loginjob.cpp:184 #, kde-format msgid "IMAP session in the wrong state for authentication" msgstr "ИМАП сесија је у погрешном стању за аутентификацију." #: loginjob.cpp:235 #, kde-format msgid "Capability" msgstr "Одређивање могућности" #: loginjob.cpp:237 #, kde-format msgid "StartTls" msgstr "Покретање ТЛС‑а" #: loginjob.cpp:340 #, kde-format msgid "STARTTLS is not supported by the server, try using SSL/TLS instead." msgstr "" #: loginjob.cpp:353 #, kde-format msgid "Internal error, tried to login before encryption" msgstr "" #: loginjob.cpp:362 #, kde-format msgid "Login failed, plain login is disabled by the server." msgstr "Пријављивање неуспјело, сервер не дозвољава просто пријављивање." #: loginjob.cpp:383 #, kde-format msgid "Login failed, authentication mode %1 is not supported by the server." msgstr "Пријављивање неуспјело, сервер не подржава режим аутентификације %1." #: loginjob.cpp:413 #, kde-format msgid "Login failed, client cannot initialize the SASL library." msgstr "Пријављивање неуспјело, клијент не може да припреми САСЛ библиотеку." #: loginjob.cpp:512 #, kde-format msgid "Login failed, TLS negotiation failed." msgstr "Пријављивање неуспјело, ТЛС преговори неуспешни." #: loginjob.cpp:570 #, kde-format msgid "SSL handshake failed." msgstr "ССЛ руковање пропало." #: logoutjob.cpp:33 #, kde-format msgid "Logout" msgstr "Одјављивање" #: metadatajobbase.cpp:53 #, kde-format msgid "MetaDataJobBase" msgstr "MetaDataJobBase" #: movejob.cpp:42 #, kde-format msgid "Move" msgstr "Премештање" #: myrightsjob.cpp:37 #, kde-format msgid "MyRights" msgstr "Добављање мојих права" #: namespacejob.cpp:68 #, kde-format msgid "Namespace" msgstr "Именски простор" #: quotajobbase.cpp:34 #, kde-format msgid "QuotaJobBase" msgstr "QuotaJobBase" #: renamejob.cpp:37 #, kde-format msgid "Rename" msgstr "Преименовање" #: searchjob.cpp:361 #, kde-format msgctxt "Name of the search job" msgid "Search" msgstr "Претраживање" #: selectjob.cpp:73 #, kde-format msgctxt "name of the select job" msgid "Select" msgstr "Бирање" #: setacljob.cpp:34 #, kde-format msgid "SetAcl" msgstr "Постављање АЦЛ‑а" #: setmetadatajob.cpp:43 #, kde-format msgid "SetMetaData" msgstr "Постављање метаподатака" #: setquotajob.cpp:37 #, kde-format msgid "SetQuota" msgstr "Постављање квоте" #: statusjob.cpp:40 #, kde-format msgctxt "name of the status job" msgid "Status" msgstr "Стање" #: storejob.cpp:70 #, kde-format msgid "Store" msgstr "Складиштење" #: subscribejob.cpp:36 #, kde-format msgid "Subscribe" msgstr "Претплаћивање" #: unsubscribejob.cpp:36 #, kde-format msgid "Unsubscribe" msgstr "Укидање претплате" 0707010000009B000041ED00000000000000000000000266FAD7C000000000000000000000000000000000000000000000003E00000000kimap-VERSIONgit.20240930T185424~db1f697/po/sr@ijekavianlatin0707010000009C000081A400000000000000000000000166FAD7C0000016F2000000000000000000000000000000000000004B00000000kimap-VERSIONgit.20240930T185424~db1f697/po/sr@ijekavianlatin/libkimap6.po# Translation of libkimap5.po into Serbian. # Chusslove Illich <caslav.ilic@gmx.net>, 2009, 2010, 2013, 2014, 2016. # Dalibor Djuric <dalibor.djuric@mozilla-srbija.org>, 2009. # Dalibor Djuric <daliborddjuric@gmail.com>, 2010. msgid "" msgstr "" "Project-Id-Version: libkimap5\n" "Report-Msgid-Bugs-To: https://bugs.kde.org\n" "POT-Creation-Date: 2022-05-11 00:45+0000\n" "PO-Revision-Date: 2016-11-28 01:33+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" #: acljobbase.cpp:56 #, kde-format msgid "AclJobBase" msgstr "AclJobBase" #: appendjob.cpp:40 #, kde-format msgid "Append" msgstr "Prikačivanje" #: capabilitiesjob.cpp:35 #, kde-format msgid "Capabilities" msgstr "Određivanje mogućnosti" #: closejob.cpp:32 #, kde-format msgid "Close" msgstr "Zatvaranje" #: copyjob.cpp:41 #, kde-format msgid "Copy" msgstr "Kopiranje" #: createjob.cpp:36 #, kde-format msgid "Create" msgstr "Stvaranje" #: deleteacljob.cpp:37 #, kde-format msgid "DeleteAclJob" msgstr "Brisanje ACL‑a" #: deletejob.cpp:36 #, kde-format msgid "Delete" msgstr "Brisanje" #: enablejob.cpp:31 #, kde-format msgid "Enable" msgstr "" #: expungejob.cpp:37 #, kde-format msgid "Expunge" msgstr "Pročišćavanje" #: fetchjob.cpp:97 #, kde-format msgid "Fetch" msgstr "Dobavljanje" #: getacljob.cpp:37 #, kde-format msgid "GetAcl" msgstr "Dobavljanje ACL‑a" #: getmetadatajob.cpp:43 #, kde-format msgid "GetMetaData" msgstr "Dobavljanje metapodataka" #: getmetadatajob.cpp:66 #, kde-format msgid "GetAnnotation" msgstr "Dobavljanje tumačenja" #: getquotajob.cpp:35 #, kde-format msgid "GetQuota" msgstr "Dobavljanje kvote" #: getquotarootjob.cpp:38 #, kde-format msgid "GetQuotaRoot" msgstr "Dobavljanje kvote korijena" #: idjob.cpp:35 #, kde-format msgid "Id" msgstr "ID" #: idlejob.cpp:65 #, kde-format msgctxt "name of the idle job" msgid "Idle" msgstr "Mirovanje" #: job.cpp:19 #, kde-format msgid "Job" msgstr "Posao" #: job.cpp:54 loginjob.cpp:574 #, kde-format msgid "Connection to server lost." msgstr "Veza sa serverom je izgubljena." # >> %1 is a job name, like 'Fetch', 'Delete', etc. #: job.cpp:65 loginjob.cpp:403 setmetadatajob.cpp:126 #, kde-format msgid "%1 failed, malformed reply from the server." msgstr "%1 neuspjelo, loše formiran odgovor sa servera." # >> %1 is a job name, like 'Fetch', 'Delete', etc. #: job.cpp:68 loginjob.cpp:277 setmetadatajob.cpp:109 setmetadatajob.cpp:129 #, kde-format msgid "%1 failed, server replied: %2" msgstr "%1 neuspjelo, server odgovara: %2" # skip-rule: t-list #: listjob.cpp:59 #, kde-format msgid "List" msgstr "Listanje" # skip-rule: t-list #: listrightsjob.cpp:38 #, kde-format msgid "ListRights" msgstr "Listanje prava" #: loginjob.cpp:129 loginjob.cpp:233 #, kde-format msgid "Login" msgstr "Prijavljivanje" #: loginjob.cpp:184 #, kde-format msgid "IMAP session in the wrong state for authentication" msgstr "IMAP sesija je u pogrešnom stanju za autentifikaciju." #: loginjob.cpp:235 #, kde-format msgid "Capability" msgstr "Određivanje mogućnosti" #: loginjob.cpp:237 #, kde-format msgid "StartTls" msgstr "Pokretanje TLS‑a" #: loginjob.cpp:340 #, kde-format msgid "STARTTLS is not supported by the server, try using SSL/TLS instead." msgstr "" #: loginjob.cpp:353 #, kde-format msgid "Internal error, tried to login before encryption" msgstr "" #: loginjob.cpp:362 #, kde-format msgid "Login failed, plain login is disabled by the server." msgstr "Prijavljivanje neuspjelo, server ne dozvoljava prosto prijavljivanje." #: loginjob.cpp:383 #, kde-format msgid "Login failed, authentication mode %1 is not supported by the server." msgstr "Prijavljivanje neuspjelo, server ne podržava režim autentifikacije %1." #: loginjob.cpp:413 #, kde-format msgid "Login failed, client cannot initialize the SASL library." msgstr "Prijavljivanje neuspjelo, klijent ne može da pripremi SASL biblioteku." #: loginjob.cpp:512 #, kde-format msgid "Login failed, TLS negotiation failed." msgstr "Prijavljivanje neuspjelo, TLS pregovori neuspešni." #: loginjob.cpp:570 #, kde-format msgid "SSL handshake failed." msgstr "SSL rukovanje propalo." #: logoutjob.cpp:33 #, kde-format msgid "Logout" msgstr "Odjavljivanje" #: metadatajobbase.cpp:53 #, kde-format msgid "MetaDataJobBase" msgstr "MetaDataJobBase" #: movejob.cpp:42 #, kde-format msgid "Move" msgstr "Premeštanje" #: myrightsjob.cpp:37 #, kde-format msgid "MyRights" msgstr "Dobavljanje mojih prava" #: namespacejob.cpp:68 #, kde-format msgid "Namespace" msgstr "Imenski prostor" #: quotajobbase.cpp:34 #, kde-format msgid "QuotaJobBase" msgstr "QuotaJobBase" #: renamejob.cpp:37 #, kde-format msgid "Rename" msgstr "Preimenovanje" #: searchjob.cpp:361 #, kde-format msgctxt "Name of the search job" msgid "Search" msgstr "Pretraživanje" #: selectjob.cpp:73 #, kde-format msgctxt "name of the select job" msgid "Select" msgstr "Biranje" #: setacljob.cpp:34 #, kde-format msgid "SetAcl" msgstr "Postavljanje ACL‑a" #: setmetadatajob.cpp:43 #, kde-format msgid "SetMetaData" msgstr "Postavljanje metapodataka" #: setquotajob.cpp:37 #, kde-format msgid "SetQuota" msgstr "Postavljanje kvote" #: statusjob.cpp:40 #, kde-format msgctxt "name of the status job" msgid "Status" msgstr "Stanje" #: storejob.cpp:70 #, kde-format msgid "Store" msgstr "Skladištenje" #: subscribejob.cpp:36 #, kde-format msgid "Subscribe" msgstr "Pretplaćivanje" #: unsubscribejob.cpp:36 #, kde-format msgid "Unsubscribe" msgstr "Ukidanje pretplate" 0707010000009D000041ED00000000000000000000000266FAD7C000000000000000000000000000000000000000000000003500000000kimap-VERSIONgit.20240930T185424~db1f697/po/sr@latin0707010000009E000081A400000000000000000000000166FAD7C0000016E1000000000000000000000000000000000000004200000000kimap-VERSIONgit.20240930T185424~db1f697/po/sr@latin/libkimap6.po# Translation of libkimap5.po into Serbian. # Chusslove Illich <caslav.ilic@gmx.net>, 2009, 2010, 2013, 2014, 2016. # Dalibor Djuric <dalibor.djuric@mozilla-srbija.org>, 2009. # Dalibor Djuric <daliborddjuric@gmail.com>, 2010. msgid "" msgstr "" "Project-Id-Version: libkimap5\n" "Report-Msgid-Bugs-To: https://bugs.kde.org\n" "POT-Creation-Date: 2022-05-11 00:45+0000\n" "PO-Revision-Date: 2016-11-28 01:33+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" #: acljobbase.cpp:56 #, kde-format msgid "AclJobBase" msgstr "AclJobBase" #: appendjob.cpp:40 #, kde-format msgid "Append" msgstr "Prikačivanje" #: capabilitiesjob.cpp:35 #, kde-format msgid "Capabilities" msgstr "Određivanje mogućnosti" #: closejob.cpp:32 #, kde-format msgid "Close" msgstr "Zatvaranje" #: copyjob.cpp:41 #, kde-format msgid "Copy" msgstr "Kopiranje" #: createjob.cpp:36 #, kde-format msgid "Create" msgstr "Stvaranje" #: deleteacljob.cpp:37 #, kde-format msgid "DeleteAclJob" msgstr "Brisanje ACL‑a" #: deletejob.cpp:36 #, kde-format msgid "Delete" msgstr "Brisanje" #: enablejob.cpp:31 #, kde-format msgid "Enable" msgstr "" #: expungejob.cpp:37 #, kde-format msgid "Expunge" msgstr "Pročišćavanje" #: fetchjob.cpp:97 #, kde-format msgid "Fetch" msgstr "Dobavljanje" #: getacljob.cpp:37 #, kde-format msgid "GetAcl" msgstr "Dobavljanje ACL‑a" #: getmetadatajob.cpp:43 #, kde-format msgid "GetMetaData" msgstr "Dobavljanje metapodataka" #: getmetadatajob.cpp:66 #, kde-format msgid "GetAnnotation" msgstr "Dobavljanje tumačenja" #: getquotajob.cpp:35 #, kde-format msgid "GetQuota" msgstr "Dobavljanje kvote" #: getquotarootjob.cpp:38 #, kde-format msgid "GetQuotaRoot" msgstr "Dobavljanje kvote korena" #: idjob.cpp:35 #, kde-format msgid "Id" msgstr "ID" #: idlejob.cpp:65 #, kde-format msgctxt "name of the idle job" msgid "Idle" msgstr "Mirovanje" #: job.cpp:19 #, kde-format msgid "Job" msgstr "Posao" #: job.cpp:54 loginjob.cpp:574 #, kde-format msgid "Connection to server lost." msgstr "Veza sa serverom je izgubljena." # >> %1 is a job name, like 'Fetch', 'Delete', etc. #: job.cpp:65 loginjob.cpp:403 setmetadatajob.cpp:126 #, kde-format msgid "%1 failed, malformed reply from the server." msgstr "%1 neuspelo, loše formiran odgovor sa servera." # >> %1 is a job name, like 'Fetch', 'Delete', etc. #: job.cpp:68 loginjob.cpp:277 setmetadatajob.cpp:109 setmetadatajob.cpp:129 #, kde-format msgid "%1 failed, server replied: %2" msgstr "%1 neuspelo, server odgovara: %2" # skip-rule: t-list #: listjob.cpp:59 #, kde-format msgid "List" msgstr "Listanje" # skip-rule: t-list #: listrightsjob.cpp:38 #, kde-format msgid "ListRights" msgstr "Listanje prava" #: loginjob.cpp:129 loginjob.cpp:233 #, kde-format msgid "Login" msgstr "Prijavljivanje" #: loginjob.cpp:184 #, kde-format msgid "IMAP session in the wrong state for authentication" msgstr "IMAP sesija je u pogrešnom stanju za autentifikaciju." #: loginjob.cpp:235 #, kde-format msgid "Capability" msgstr "Određivanje mogućnosti" #: loginjob.cpp:237 #, kde-format msgid "StartTls" msgstr "Pokretanje TLS‑a" #: loginjob.cpp:340 #, kde-format msgid "STARTTLS is not supported by the server, try using SSL/TLS instead." msgstr "" #: loginjob.cpp:353 #, kde-format msgid "Internal error, tried to login before encryption" msgstr "" #: loginjob.cpp:362 #, kde-format msgid "Login failed, plain login is disabled by the server." msgstr "Prijavljivanje neuspelo, server ne dozvoljava prosto prijavljivanje." #: loginjob.cpp:383 #, kde-format msgid "Login failed, authentication mode %1 is not supported by the server." msgstr "Prijavljivanje neuspelo, server ne podržava režim autentifikacije %1." #: loginjob.cpp:413 #, kde-format msgid "Login failed, client cannot initialize the SASL library." msgstr "Prijavljivanje neuspelo, klijent ne može da pripremi SASL biblioteku." #: loginjob.cpp:512 #, kde-format msgid "Login failed, TLS negotiation failed." msgstr "Prijavljivanje neuspelo, TLS pregovori neuspešni." #: loginjob.cpp:570 #, kde-format msgid "SSL handshake failed." msgstr "SSL rukovanje propalo." #: logoutjob.cpp:33 #, kde-format msgid "Logout" msgstr "Odjavljivanje" #: metadatajobbase.cpp:53 #, kde-format msgid "MetaDataJobBase" msgstr "MetaDataJobBase" #: movejob.cpp:42 #, kde-format msgid "Move" msgstr "Premeštanje" #: myrightsjob.cpp:37 #, kde-format msgid "MyRights" msgstr "Dobavljanje mojih prava" #: namespacejob.cpp:68 #, kde-format msgid "Namespace" msgstr "Imenski prostor" #: quotajobbase.cpp:34 #, kde-format msgid "QuotaJobBase" msgstr "QuotaJobBase" #: renamejob.cpp:37 #, kde-format msgid "Rename" msgstr "Preimenovanje" #: searchjob.cpp:361 #, kde-format msgctxt "Name of the search job" msgid "Search" msgstr "Pretraživanje" #: selectjob.cpp:73 #, kde-format msgctxt "name of the select job" msgid "Select" msgstr "Biranje" #: setacljob.cpp:34 #, kde-format msgid "SetAcl" msgstr "Postavljanje ACL‑a" #: setmetadatajob.cpp:43 #, kde-format msgid "SetMetaData" msgstr "Postavljanje metapodataka" #: setquotajob.cpp:37 #, kde-format msgid "SetQuota" msgstr "Postavljanje kvote" #: statusjob.cpp:40 #, kde-format msgctxt "name of the status job" msgid "Status" msgstr "Stanje" #: storejob.cpp:70 #, kde-format msgid "Store" msgstr "Skladištenje" #: subscribejob.cpp:36 #, kde-format msgid "Subscribe" msgstr "Pretplaćivanje" #: unsubscribejob.cpp:36 #, kde-format msgid "Unsubscribe" msgstr "Ukidanje pretplate" 0707010000009F000041ED00000000000000000000000266FAD7C000000000000000000000000000000000000000000000002F00000000kimap-VERSIONgit.20240930T185424~db1f697/po/sv070701000000A0000081A400000000000000000000000166FAD7C0000017A3000000000000000000000000000000000000003C00000000kimap-VERSIONgit.20240930T185424~db1f697/po/sv/libkimap6.po# translation of libkimap.po to Swedish # 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@gmail.com>, 2009, 2010, 2013, 2014, 2016, 2018, 2020, 2022. msgid "" msgstr "" "Project-Id-Version: libkimap\n" "Report-Msgid-Bugs-To: https://bugs.kde.org\n" "POT-Creation-Date: 2022-05-11 00:45+0000\n" "PO-Revision-Date: 2022-01-28 23:03+0100\n" "Last-Translator: Stefan Asserhäll <stefan.asserhall@gmail.com>\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" "X-Generator: Lokalize 20.08.1\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" #: acljobbase.cpp:56 #, kde-format msgid "AclJobBase" msgstr "ACL-jobbas" #: appendjob.cpp:40 #, kde-format msgid "Append" msgstr "Lägg till" #: capabilitiesjob.cpp:35 #, kde-format msgid "Capabilities" msgstr "Egenskaper" #: closejob.cpp:32 #, kde-format msgid "Close" msgstr "Stäng" #: copyjob.cpp:41 #, kde-format msgid "Copy" msgstr "Kopiera" #: createjob.cpp:36 #, kde-format msgid "Create" msgstr "Skapa" #: deleteacljob.cpp:37 #, kde-format msgid "DeleteAclJob" msgstr "Ta bort ACL-jobb" #: deletejob.cpp:36 #, kde-format msgid "Delete" msgstr "Ta bort" #: enablejob.cpp:31 #, kde-format msgid "Enable" msgstr "Aktivera" #: expungejob.cpp:37 #, kde-format msgid "Expunge" msgstr "Förstör" #: fetchjob.cpp:97 #, kde-format msgid "Fetch" msgstr "Hämta" #: getacljob.cpp:37 #, kde-format msgid "GetAcl" msgstr "Hämta ACL" #: getmetadatajob.cpp:43 #, kde-format msgid "GetMetaData" msgstr "Hämta metadata" #: getmetadatajob.cpp:66 #, kde-format msgid "GetAnnotation" msgstr "Hämta kommentar" #: getquotajob.cpp:35 #, kde-format msgid "GetQuota" msgstr "Hämta kvot" #: getquotarootjob.cpp:38 #, kde-format msgid "GetQuotaRoot" msgstr "Hämta kvotrot" #: idjob.cpp:35 #, kde-format msgid "Id" msgstr "Id" #: idlejob.cpp:65 #, kde-format msgctxt "name of the idle job" msgid "Idle" msgstr "Overksam" #: job.cpp:19 #, kde-format msgid "Job" msgstr "Jobb" #: job.cpp:54 loginjob.cpp:574 #, kde-format msgid "Connection to server lost." msgstr "Anslutningen till servern gick förlorad." #: job.cpp:65 loginjob.cpp:403 setmetadatajob.cpp:126 #, kde-format msgid "%1 failed, malformed reply from the server." msgstr "%1 misslyckades. Felformaterat svar från servern." #: job.cpp:68 loginjob.cpp:277 setmetadatajob.cpp:109 setmetadatajob.cpp:129 #, kde-format msgid "%1 failed, server replied: %2" msgstr "%1 misslyckades. Servern svarade: %2" #: listjob.cpp:59 #, kde-format msgid "List" msgstr "Lista" #: listrightsjob.cpp:38 #, kde-format msgid "ListRights" msgstr "Listrättigheter" #: loginjob.cpp:129 loginjob.cpp:233 #, kde-format msgid "Login" msgstr "Logga in" #: loginjob.cpp:184 #, kde-format msgid "IMAP session in the wrong state for authentication" msgstr "IMAP-session har felaktigt tillstånd för behörighetskontroll" #: loginjob.cpp:235 #, kde-format msgid "Capability" msgstr "Kapabilitet" #: loginjob.cpp:237 #, kde-format msgid "StartTls" msgstr "Starta TLS" #: loginjob.cpp:340 #, kde-format msgid "STARTTLS is not supported by the server, try using SSL/TLS instead." msgstr "STARTTLS stöds inte av servern. Försök använda SSL/TLS istället." #: loginjob.cpp:353 #, kde-format msgid "Internal error, tried to login before encryption" msgstr "Internt fel, försökte logga in innan kryptering" #: loginjob.cpp:362 #, kde-format msgid "Login failed, plain login is disabled by the server." msgstr "Inloggning misslyckades. Enkel inloggning är inaktiverad av servern." #: loginjob.cpp:383 #, kde-format msgid "Login failed, authentication mode %1 is not supported by the server." msgstr "" "Inloggning misslyckades. Behörighetskontroll med läget %1 stöds inte av " "servern." #: loginjob.cpp:413 #, kde-format msgid "Login failed, client cannot initialize the SASL library." msgstr "Inloggning misslyckades. Klienten kan inte initiera SASL-biblioteket." #: loginjob.cpp:512 #, kde-format msgid "Login failed, TLS negotiation failed." msgstr "Inloggning misslyckades. TLS-förhandling misslyckades." #: loginjob.cpp:570 #, kde-format msgid "SSL handshake failed." msgstr "SSL-handskakning misslyckades." #: logoutjob.cpp:33 #, kde-format msgid "Logout" msgstr "Logga ut" #: metadatajobbase.cpp:53 #, kde-format msgid "MetaDataJobBase" msgstr "Metadata-jobbas" #: movejob.cpp:42 #, kde-format msgid "Move" msgstr "Flytta" #: myrightsjob.cpp:37 #, kde-format msgid "MyRights" msgstr "Mina rättigheter" #: namespacejob.cpp:68 #, kde-format msgid "Namespace" msgstr "Namnrymd" #: quotajobbase.cpp:34 #, kde-format msgid "QuotaJobBase" msgstr "Kvotjobbas" #: renamejob.cpp:37 #, kde-format msgid "Rename" msgstr "Byt namn" #: searchjob.cpp:361 #, kde-format msgctxt "Name of the search job" msgid "Search" msgstr "Sök" #: selectjob.cpp:73 #, kde-format msgctxt "name of the select job" msgid "Select" msgstr "Markera" #: setacljob.cpp:34 #, kde-format msgid "SetAcl" msgstr "Ställ in ACL" #: setmetadatajob.cpp:43 #, kde-format msgid "SetMetaData" msgstr "Ange metadata" #: setquotajob.cpp:37 #, kde-format msgid "SetQuota" msgstr "Ställ in kvot" #: statusjob.cpp:40 #, kde-format msgctxt "name of the status job" msgid "Status" msgstr "Status" #: storejob.cpp:70 #, kde-format msgid "Store" msgstr "Lagra" #: subscribejob.cpp:36 #, kde-format msgid "Subscribe" msgstr "Prenumerera" #: unsubscribejob.cpp:36 #, kde-format msgid "Unsubscribe" msgstr "Säg upp prenumeration" #~ msgid "SetAnnotation" #~ msgstr "Ange kommentar" #~ msgid "Mock" #~ msgstr "Fingerat" #~ msgctxt "NAME OF TRANSLATORS" #~ msgid "Your names" #~ msgstr "Stefan Asserhäll" #~ msgctxt "EMAIL OF TRANSLATORS" #~ msgid "Your emails" #~ msgstr "stefan.asserhall@gmail.com" #~ msgctxt "Authentication method" #~ msgid "Clear text" #~ msgstr "Rensa text" #~ msgctxt "Authentication method" #~ msgid "Anonymous" #~ msgstr "Anonym" 070701000000A1000041ED00000000000000000000000266FAD7C000000000000000000000000000000000000000000000002F00000000kimap-VERSIONgit.20240930T185424~db1f697/po/ta070701000000A2000081A400000000000000000000000166FAD7C00000120B000000000000000000000000000000000000003C00000000kimap-VERSIONgit.20240930T185424~db1f697/po/ta/libkimap6.po# Copyright (C) 2024 This file is copyright: # This file is distributed under the same license as the kimap package. # # SPDX-FileCopyrightText: 2024 Kishore G <kishore96@gmail.com> msgid "" msgstr "" "Project-Id-Version: kimap\n" "Report-Msgid-Bugs-To: https://bugs.kde.org\n" "POT-Creation-Date: 2022-05-11 00:45+0000\n" "PO-Revision-Date: 2024-05-05 14:19+0530\n" "Last-Translator: Kishore G <kishore96@gmail.com>\n" "Language-Team: Tamil <kde-i18n-doc@kde.org>\n" "Language: ta\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 24.02.2\n" #: acljobbase.cpp:56 #, kde-format msgid "AclJobBase" msgstr "" #: appendjob.cpp:40 #, kde-format msgid "Append" msgstr "" #: capabilitiesjob.cpp:35 #, kde-format msgid "Capabilities" msgstr "" #: closejob.cpp:32 #, kde-format msgid "Close" msgstr "மூடு" #: copyjob.cpp:41 #, kde-format msgid "Copy" msgstr "நகலெடு" #: createjob.cpp:36 #, kde-format msgid "Create" msgstr "உருவாக்கு" #: deleteacljob.cpp:37 #, kde-format msgid "DeleteAclJob" msgstr "" #: deletejob.cpp:36 #, kde-format msgid "Delete" msgstr "நீக்கு" #: enablejob.cpp:31 #, kde-format msgid "Enable" msgstr "இயக்கு" #: expungejob.cpp:37 #, kde-format msgid "Expunge" msgstr "" #: fetchjob.cpp:97 #, kde-format msgid "Fetch" msgstr "கொணர்" #: getacljob.cpp:37 #, kde-format msgid "GetAcl" msgstr "" #: getmetadatajob.cpp:43 #, kde-format msgid "GetMetaData" msgstr "" #: getmetadatajob.cpp:66 #, kde-format msgid "GetAnnotation" msgstr "" #: getquotajob.cpp:35 #, kde-format msgid "GetQuota" msgstr "" #: getquotarootjob.cpp:38 #, kde-format msgid "GetQuotaRoot" msgstr "" #: idjob.cpp:35 #, kde-format msgid "Id" msgstr "" #: idlejob.cpp:65 #, kde-format msgctxt "name of the idle job" msgid "Idle" msgstr "" #: job.cpp:19 #, kde-format msgid "Job" msgstr "" #: job.cpp:54 loginjob.cpp:574 #, kde-format msgid "Connection to server lost." msgstr "" #: job.cpp:65 loginjob.cpp:403 setmetadatajob.cpp:126 #, kde-format msgid "%1 failed, malformed reply from the server." msgstr "" #: job.cpp:68 loginjob.cpp:277 setmetadatajob.cpp:109 setmetadatajob.cpp:129 #, kde-format msgid "%1 failed, server replied: %2" msgstr "" #: listjob.cpp:59 #, kde-format msgid "List" msgstr "" #: listrightsjob.cpp:38 #, kde-format msgid "ListRights" msgstr "" #: loginjob.cpp:129 loginjob.cpp:233 #, kde-format msgid "Login" msgstr "" #: loginjob.cpp:184 #, kde-format msgid "IMAP session in the wrong state for authentication" msgstr "" #: loginjob.cpp:235 #, kde-format msgid "Capability" msgstr "" #: loginjob.cpp:237 #, kde-format msgid "StartTls" msgstr "" #: loginjob.cpp:340 #, kde-format msgid "STARTTLS is not supported by the server, try using SSL/TLS instead." msgstr "" #: loginjob.cpp:353 #, kde-format msgid "Internal error, tried to login before encryption" msgstr "" #: loginjob.cpp:362 #, kde-format msgid "Login failed, plain login is disabled by the server." msgstr "" #: loginjob.cpp:383 #, kde-format msgid "Login failed, authentication mode %1 is not supported by the server." msgstr "" #: loginjob.cpp:413 #, kde-format msgid "Login failed, client cannot initialize the SASL library." msgstr "" #: loginjob.cpp:512 #, kde-format msgid "Login failed, TLS negotiation failed." msgstr "" #: loginjob.cpp:570 #, kde-format msgid "SSL handshake failed." msgstr "" #: logoutjob.cpp:33 #, kde-format msgid "Logout" msgstr "" #: metadatajobbase.cpp:53 #, kde-format msgid "MetaDataJobBase" msgstr "" #: movejob.cpp:42 #, kde-format msgid "Move" msgstr "" #: myrightsjob.cpp:37 #, kde-format msgid "MyRights" msgstr "" #: namespacejob.cpp:68 #, kde-format msgid "Namespace" msgstr "" #: quotajobbase.cpp:34 #, kde-format msgid "QuotaJobBase" msgstr "" #: renamejob.cpp:37 #, kde-format msgid "Rename" msgstr "" #: searchjob.cpp:361 #, kde-format msgctxt "Name of the search job" msgid "Search" msgstr "" #: selectjob.cpp:73 #, kde-format msgctxt "name of the select job" msgid "Select" msgstr "" #: setacljob.cpp:34 #, kde-format msgid "SetAcl" msgstr "" #: setmetadatajob.cpp:43 #, kde-format msgid "SetMetaData" msgstr "" #: setquotajob.cpp:37 #, kde-format msgid "SetQuota" msgstr "" #: statusjob.cpp:40 #, kde-format msgctxt "name of the status job" msgid "Status" msgstr "" #: storejob.cpp:70 #, kde-format msgid "Store" msgstr "" #: subscribejob.cpp:36 #, kde-format msgid "Subscribe" msgstr "" #: unsubscribejob.cpp:36 #, kde-format msgid "Unsubscribe" msgstr "" 070701000000A3000041ED00000000000000000000000266FAD7C000000000000000000000000000000000000000000000002F00000000kimap-VERSIONgit.20240930T185424~db1f697/po/tr070701000000A4000081A400000000000000000000000166FAD7C0000017F1000000000000000000000000000000000000003C00000000kimap-VERSIONgit.20240930T185424~db1f697/po/tr/libkimap6.po# Copyright (C) YEAR This_file_is_part_of_KDE # This file is distributed under the same license as the PACKAGE package. # # Serdar Soytetir <tulliana@gmail.com>, 2009. # H. İbrahim Güngör <ibrahim@pardus.org.tr>, 2011. # Volkan Gezer <volkangezer@gmail.com>, 2014, 2017. # Kaan Ozdincer <kaanozdincer@gmail.com>, 2014. # Emir SARI <emir_sari@icloud.com>, 2022, 2023. msgid "" msgstr "" "Project-Id-Version: libkimap\n" "Report-Msgid-Bugs-To: https://bugs.kde.org\n" "POT-Creation-Date: 2022-05-11 00:45+0000\n" "PO-Revision-Date: 2023-02-08 19:39+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 22.12.2\n" #: acljobbase.cpp:56 #, kde-format msgid "AclJobBase" msgstr "AclJobBase" #: appendjob.cpp:40 #, kde-format msgid "Append" msgstr "Ekle" #: capabilitiesjob.cpp:35 #, kde-format msgid "Capabilities" msgstr "Yetenekler" #: closejob.cpp:32 #, kde-format msgid "Close" msgstr "Kapat" #: copyjob.cpp:41 #, kde-format msgid "Copy" msgstr "Kopyala" #: createjob.cpp:36 #, kde-format msgid "Create" msgstr "Oluştur" #: deleteacljob.cpp:37 #, kde-format msgid "DeleteAclJob" msgstr "DeleteAclJob" #: deletejob.cpp:36 #, kde-format msgid "Delete" msgstr "Sil" #: enablejob.cpp:31 #, kde-format msgid "Enable" msgstr "Etkinleştir" #: expungejob.cpp:37 #, kde-format msgid "Expunge" msgstr "Çıkar" #: fetchjob.cpp:97 #, kde-format msgid "Fetch" msgstr "Getir" #: getacljob.cpp:37 #, kde-format msgid "GetAcl" msgstr "GetAcl" #: getmetadatajob.cpp:43 #, kde-format msgid "GetMetaData" msgstr "GetMetaData" #: getmetadatajob.cpp:66 #, kde-format msgid "GetAnnotation" msgstr "GetAnnotation" #: getquotajob.cpp:35 #, kde-format msgid "GetQuota" msgstr "Kotayı Al" #: getquotarootjob.cpp:38 #, kde-format msgid "GetQuotaRoot" msgstr "GetQuotaRoot" #: idjob.cpp:35 #, kde-format msgid "Id" msgstr "Kimlik" #: idlejob.cpp:65 #, kde-format msgctxt "name of the idle job" msgid "Idle" msgstr "Boşta" #: job.cpp:19 #, kde-format msgid "Job" msgstr "Görev" #: job.cpp:54 loginjob.cpp:574 #, kde-format msgid "Connection to server lost." msgstr "Sunucuya yapılan bağlantı koptu." #: job.cpp:65 loginjob.cpp:403 setmetadatajob.cpp:126 #, kde-format msgid "%1 failed, malformed reply from the server." msgstr "%1 başarısız oldu, sunucudan bozuk yanıt alındı." #: job.cpp:68 loginjob.cpp:277 setmetadatajob.cpp:109 setmetadatajob.cpp:129 #, kde-format msgid "%1 failed, server replied: %2" msgstr "%1 başarısız oldu, sunucunun yanıtı: %2" #: listjob.cpp:59 #, kde-format msgid "List" msgstr "Listele" #: listrightsjob.cpp:38 #, kde-format msgid "ListRights" msgstr "Hakları Listele" #: loginjob.cpp:129 loginjob.cpp:233 #, kde-format msgid "Login" msgstr "Oturumu Aç" #: loginjob.cpp:184 #, kde-format msgid "IMAP session in the wrong state for authentication" msgstr "IMAP oturumu kimlik denetimi için yanlış durumda" #: loginjob.cpp:235 #, kde-format msgid "Capability" msgstr "Yetenek" #: loginjob.cpp:237 #, kde-format msgid "StartTls" msgstr "TLS'yi Başlat" #: loginjob.cpp:340 #, kde-format msgid "STARTTLS is not supported by the server, try using SSL/TLS instead." msgstr "STARTTLS sunucu tarafından desteklenmiyor, SSL/TLS kullanmayı deneyin." #: loginjob.cpp:353 #, kde-format msgid "Internal error, tried to login before encryption" msgstr "İç hata, şifreleme öncesi oturum açma denendi" #: loginjob.cpp:362 #, kde-format msgid "Login failed, plain login is disabled by the server." msgstr "" "Oturum açma başarısız, düz oturum açma yöntemi sunucu tarafından devre dışı " "bırakılmış." #: loginjob.cpp:383 #, kde-format msgid "Login failed, authentication mode %1 is not supported by the server." msgstr "" "Oturum açma başarısız; %1 kimlik doğrulama yöntemi sunucu tarafından " "desteklenmiyor." #: loginjob.cpp:413 #, kde-format msgid "Login failed, client cannot initialize the SASL library." msgstr "İstemci SASL kitaplığını başlatamadığından oturum açılamadı." #: loginjob.cpp:512 #, kde-format msgid "Login failed, TLS negotiation failed." msgstr "TLS antlaşması başarısız olduğundan oturum açılamadı." #: loginjob.cpp:570 #, kde-format msgid "SSL handshake failed." msgstr "SSL el sıkışması başarısız." #: logoutjob.cpp:33 #, kde-format msgid "Logout" msgstr "Oturumu Kapat" #: metadatajobbase.cpp:53 #, kde-format msgid "MetaDataJobBase" msgstr "Üst Veri İş Tabanı " #: movejob.cpp:42 #, kde-format msgid "Move" msgstr "Taşı" #: myrightsjob.cpp:37 #, kde-format msgid "MyRights" msgstr "Haklarım" #: namespacejob.cpp:68 #, kde-format msgid "Namespace" msgstr "Ad Alanı" #: quotajobbase.cpp:34 #, kde-format msgid "QuotaJobBase" msgstr "QuotaJobBase" #: renamejob.cpp:37 #, kde-format msgid "Rename" msgstr "Yeniden Adlandır" #: searchjob.cpp:361 #, kde-format msgctxt "Name of the search job" msgid "Search" msgstr "Ara" #: selectjob.cpp:73 #, kde-format msgctxt "name of the select job" msgid "Select" msgstr "Seç" #: setacljob.cpp:34 #, kde-format msgid "SetAcl" msgstr "SetAcl" #: setmetadatajob.cpp:43 #, kde-format msgid "SetMetaData" msgstr "Üst Veriyi Ayarla" #: setquotajob.cpp:37 #, kde-format msgid "SetQuota" msgstr "Kotayı Ayarla" #: statusjob.cpp:40 #, kde-format msgctxt "name of the status job" msgid "Status" msgstr "Durum" #: storejob.cpp:70 #, kde-format msgid "Store" msgstr "Kaydet" #: subscribejob.cpp:36 #, kde-format msgid "Subscribe" msgstr "Abone Ol" #: unsubscribejob.cpp:36 #, kde-format msgid "Unsubscribe" msgstr "Abonelikten Çık" #~ msgid "SetAnnotation" #~ msgstr "SetAnnotation" #~ msgid "Mock" #~ msgstr "Sahte" #~ msgctxt "NAME OF TRANSLATORS" #~ msgid "Your names" #~ msgstr "Serdar Soytetir" #~ msgctxt "EMAIL OF TRANSLATORS" #~ msgid "Your emails" #~ msgstr "tulliana@gmail.com" #, fuzzy #~| msgid "Create" #~ msgctxt "Authentication method" #~ msgid "Clear text" #~ msgstr "Oluştur" 070701000000A5000041ED00000000000000000000000266FAD7C000000000000000000000000000000000000000000000002F00000000kimap-VERSIONgit.20240930T185424~db1f697/po/ug070701000000A6000081A400000000000000000000000166FAD7C0000012FB000000000000000000000000000000000000003C00000000kimap-VERSIONgit.20240930T185424~db1f697/po/ug/libkimap6.po# Uyghur translation for libkimap. # Copyright (C) YEAR This_file_is_part_of_KDE # This file is distributed under the same license as the PACKAGE package. # Sahran <sahran.ug@gmail.com>, 2011. # msgid "" msgstr "" "Project-Id-Version: libkimap\n" "Report-Msgid-Bugs-To: https://bugs.kde.org\n" "POT-Creation-Date: 2022-05-11 00:45+0000\n" "PO-Revision-Date: 2013-09-08 07:05+0900\n" "Last-Translator: Gheyret Kenji <gheyret@gmail.com>\n" "Language-Team: Uyghur Computer Science Association <UKIJ@yahoogroups.com>\n" "Language: ug\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" #: acljobbase.cpp:56 #, kde-format msgid "AclJobBase" msgstr "AclJobBase" #: appendjob.cpp:40 #, kde-format msgid "Append" msgstr "قوش" #: capabilitiesjob.cpp:35 #, kde-format msgid "Capabilities" msgstr "ئىقتىدارى" #: closejob.cpp:32 #, kde-format msgid "Close" msgstr "ياپ" #: copyjob.cpp:41 #, kde-format msgid "Copy" msgstr "كۆچۈر" #: createjob.cpp:36 #, kde-format msgid "Create" msgstr "ياسا" #: deleteacljob.cpp:37 #, kde-format msgid "DeleteAclJob" msgstr "" #: deletejob.cpp:36 #, kde-format msgid "Delete" msgstr "ئۆچۈر" #: enablejob.cpp:31 #, kde-format msgid "Enable" msgstr "" #: expungejob.cpp:37 #, kde-format msgid "Expunge" msgstr "" #: fetchjob.cpp:97 #, kde-format msgid "Fetch" msgstr "تۇت" #: getacljob.cpp:37 #, kde-format msgid "GetAcl" msgstr "" #: getmetadatajob.cpp:43 #, kde-format msgid "GetMetaData" msgstr "" #: getmetadatajob.cpp:66 #, kde-format msgid "GetAnnotation" msgstr "" #: getquotajob.cpp:35 #, kde-format msgid "GetQuota" msgstr "" #: getquotarootjob.cpp:38 #, kde-format msgid "GetQuotaRoot" msgstr "" #: idjob.cpp:35 #, fuzzy, kde-format #| msgctxt "name of the idle job" #| msgid "Idle" msgid "Id" msgstr "بىكار" #: idlejob.cpp:65 #, kde-format msgctxt "name of the idle job" msgid "Idle" msgstr "بىكار" #: job.cpp:19 #, kde-format msgid "Job" msgstr "ۋەزىپە" #: job.cpp:54 loginjob.cpp:574 #, kde-format msgid "Connection to server lost." msgstr "" #: job.cpp:65 loginjob.cpp:403 setmetadatajob.cpp:126 #, kde-format msgid "%1 failed, malformed reply from the server." msgstr "" #: job.cpp:68 loginjob.cpp:277 setmetadatajob.cpp:109 setmetadatajob.cpp:129 #, kde-format msgid "%1 failed, server replied: %2" msgstr "" #: listjob.cpp:59 #, kde-format msgid "List" msgstr "تىزىم" #: listrightsjob.cpp:38 #, kde-format msgid "ListRights" msgstr "" #: loginjob.cpp:129 loginjob.cpp:233 #, kde-format msgid "Login" msgstr "كىرىش" #: loginjob.cpp:184 #, kde-format msgid "IMAP session in the wrong state for authentication" msgstr "" #: loginjob.cpp:235 #, kde-format msgid "Capability" msgstr "" #: loginjob.cpp:237 #, kde-format msgid "StartTls" msgstr "" #: loginjob.cpp:340 #, kde-format msgid "STARTTLS is not supported by the server, try using SSL/TLS instead." msgstr "" #: loginjob.cpp:353 #, kde-format msgid "Internal error, tried to login before encryption" msgstr "" #: loginjob.cpp:362 #, kde-format msgid "Login failed, plain login is disabled by the server." msgstr "" #: loginjob.cpp:383 #, kde-format msgid "Login failed, authentication mode %1 is not supported by the server." msgstr "" #: loginjob.cpp:413 #, kde-format msgid "Login failed, client cannot initialize the SASL library." msgstr "" #: loginjob.cpp:512 #, kde-format msgid "Login failed, TLS negotiation failed." msgstr "" #: loginjob.cpp:570 #, kde-format msgid "SSL handshake failed." msgstr "" #: logoutjob.cpp:33 #, kde-format msgid "Logout" msgstr "تىزىمدىن چىقىش" #: metadatajobbase.cpp:53 #, kde-format msgid "MetaDataJobBase" msgstr "" #: movejob.cpp:42 #, kde-format msgid "Move" msgstr "" #: myrightsjob.cpp:37 #, kde-format msgid "MyRights" msgstr "" #: namespacejob.cpp:68 #, kde-format msgid "Namespace" msgstr "ئات بوشلۇقى" #: quotajobbase.cpp:34 #, kde-format msgid "QuotaJobBase" msgstr "" #: renamejob.cpp:37 #, kde-format msgid "Rename" msgstr "ئات ئۆزگەرت" #: searchjob.cpp:361 #, kde-format msgctxt "Name of the search job" msgid "Search" msgstr "ئىزدە" #: selectjob.cpp:73 #, kde-format msgctxt "name of the select job" msgid "Select" msgstr "تاللا" #: setacljob.cpp:34 #, kde-format msgid "SetAcl" msgstr "" #: setmetadatajob.cpp:43 #, kde-format msgid "SetMetaData" msgstr "" #: setquotajob.cpp:37 #, kde-format msgid "SetQuota" msgstr "" #: statusjob.cpp:40 #, kde-format msgctxt "name of the status job" msgid "Status" msgstr "" #: storejob.cpp:70 #, kde-format msgid "Store" msgstr "ساقلا" #: subscribejob.cpp:36 #, kde-format msgid "Subscribe" msgstr "مۇشتەرى" #: unsubscribejob.cpp:36 #, kde-format msgid "Unsubscribe" msgstr "مۇشتەرىلىكتىن ئايرىلىش" 070701000000A7000041ED00000000000000000000000266FAD7C000000000000000000000000000000000000000000000002F00000000kimap-VERSIONgit.20240930T185424~db1f697/po/uk070701000000A8000081A400000000000000000000000166FAD7C000001C84000000000000000000000000000000000000003C00000000kimap-VERSIONgit.20240930T185424~db1f697/po/uk/libkimap6.po# Translation of libkimap5.po to Ukrainian # Copyright (C) 2018-2020 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>, 2009, 2010, 2013, 2014, 2016, 2018, 2020, 2022. msgid "" msgstr "" "Project-Id-Version: libkimap5\n" "Report-Msgid-Bugs-To: https://bugs.kde.org\n" "POT-Creation-Date: 2022-05-11 00:45+0000\n" "PO-Revision-Date: 2022-01-28 08:37+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" "X-Generator: Lokalize 20.12.0\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" #: acljobbase.cpp:56 #, kde-format msgid "AclJobBase" msgstr "AclJobBase" #: appendjob.cpp:40 #, kde-format msgid "Append" msgstr "Додати" #: capabilitiesjob.cpp:35 #, kde-format msgid "Capabilities" msgstr "Можливості" #: closejob.cpp:32 #, kde-format msgid "Close" msgstr "Закрити" #: copyjob.cpp:41 #, kde-format msgid "Copy" msgstr "Копіювати" #: createjob.cpp:36 #, kde-format msgid "Create" msgstr "Створити" #: deleteacljob.cpp:37 #, kde-format msgid "DeleteAclJob" msgstr "DeleteAclJob" #: deletejob.cpp:36 #, kde-format msgid "Delete" msgstr "Вилучити" #: enablejob.cpp:31 #, kde-format msgid "Enable" msgstr "Увімкнути" #: expungejob.cpp:37 #, kde-format msgid "Expunge" msgstr "Витерти" #: fetchjob.cpp:97 #, kde-format msgid "Fetch" msgstr "Отримати" #: getacljob.cpp:37 #, kde-format msgid "GetAcl" msgstr "GetAcl" #: getmetadatajob.cpp:43 #, kde-format msgid "GetMetaData" msgstr "GetMetaData" #: getmetadatajob.cpp:66 #, kde-format msgid "GetAnnotation" msgstr "GetAnnotation" #: getquotajob.cpp:35 #, kde-format msgid "GetQuota" msgstr "GetQuota" #: getquotarootjob.cpp:38 #, kde-format msgid "GetQuotaRoot" msgstr "GetQuotaRoot" #: idjob.cpp:35 #, kde-format msgid "Id" msgstr "Ід." #: idlejob.cpp:65 #, kde-format msgctxt "name of the idle job" msgid "Idle" msgstr "Простій" #: job.cpp:19 #, kde-format msgid "Job" msgstr "Завдання" #: job.cpp:54 loginjob.cpp:574 #, kde-format msgid "Connection to server lost." msgstr "З’єднання з сервером розірвано." #: job.cpp:65 loginjob.cpp:403 setmetadatajob.cpp:126 #, kde-format msgid "%1 failed, malformed reply from the server." msgstr "" "Спроба виконання дії %1 завершилася невдало, некоректно сформована відповідь " "сервера." #: job.cpp:68 loginjob.cpp:277 setmetadatajob.cpp:109 setmetadatajob.cpp:129 #, kde-format msgid "%1 failed, server replied: %2" msgstr "Спроба виконання дії %1 завершилася невдало, відповідь сервера: %2" #: listjob.cpp:59 #, kde-format msgid "List" msgstr "Список" #: listrightsjob.cpp:38 #, kde-format msgid "ListRights" msgstr "ListRights" #: loginjob.cpp:129 loginjob.cpp:233 #, kde-format msgid "Login" msgstr "Увійти" #: loginjob.cpp:184 #, kde-format msgid "IMAP session in the wrong state for authentication" msgstr "Сеанс IMAP перебуває у стані, непридатному для розпізнавання" #: loginjob.cpp:235 #, kde-format msgid "Capability" msgstr "Можливість" #: loginjob.cpp:237 #, kde-format msgid "StartTls" msgstr "StartTls" #: loginjob.cpp:340 #, kde-format msgid "STARTTLS is not supported by the server, try using SSL/TLS instead." msgstr "" "Не сервері не передбачено підтримки STARTTLS, спробуйте скористатися SSL/TLS." #: loginjob.cpp:353 #, kde-format msgid "Internal error, tried to login before encryption" msgstr "Внутрішня помилка, спроба увійти до встановлення шифрування" #: loginjob.cpp:362 #, kde-format msgid "Login failed, plain login is disabled by the server." msgstr "" "Спроба реєстрації завершилася невдало, нешифровані паролі не приймаються " "сервером." #: loginjob.cpp:383 #, kde-format msgid "Login failed, authentication mode %1 is not supported by the server." msgstr "" "Спроба реєстрації завершилася невдало, режим розпізнавання %1 не " "підтримується цим сервером." #: loginjob.cpp:413 #, kde-format msgid "Login failed, client cannot initialize the SASL library." msgstr "" "Спроба реєстрації завершилася невдало, клієнтові не вдалося ініціалізувати " "бібліотеку SASL." #: loginjob.cpp:512 #, kde-format msgid "Login failed, TLS negotiation failed." msgstr "" "Спроба реєстрації завершилася невдало, не вдалося встановити режим " "шифрування TLS." #: loginjob.cpp:570 #, kde-format msgid "SSL handshake failed." msgstr "Помилка під час спроби встановлення з’єднання SSL." #: logoutjob.cpp:33 #, kde-format msgid "Logout" msgstr "Вийти" #: metadatajobbase.cpp:53 #, kde-format msgid "MetaDataJobBase" msgstr "MetaDataJobBase" #: movejob.cpp:42 #, kde-format msgid "Move" msgstr "Пересунути" #: myrightsjob.cpp:37 #, kde-format msgid "MyRights" msgstr "MyRights" #: namespacejob.cpp:68 #, kde-format msgid "Namespace" msgstr "Простір назв" #: quotajobbase.cpp:34 #, kde-format msgid "QuotaJobBase" msgstr "QuotaJobBase" #: renamejob.cpp:37 #, kde-format msgid "Rename" msgstr "Перейменувати" #: searchjob.cpp:361 #, kde-format msgctxt "Name of the search job" msgid "Search" msgstr "Пошук" #: selectjob.cpp:73 #, kde-format msgctxt "name of the select job" msgid "Select" msgstr "Вибір" #: setacljob.cpp:34 #, kde-format msgid "SetAcl" msgstr "SetAcl" #: setmetadatajob.cpp:43 #, kde-format msgid "SetMetaData" msgstr "SetMetaData" #: setquotajob.cpp:37 #, kde-format msgid "SetQuota" msgstr "SetQuota" #: statusjob.cpp:40 #, kde-format msgctxt "name of the status job" msgid "Status" msgstr "Стан" #: storejob.cpp:70 #, kde-format msgid "Store" msgstr "Зберегти" #: subscribejob.cpp:36 #, kde-format msgid "Subscribe" msgstr "Підписатися" #: unsubscribejob.cpp:36 #, kde-format msgid "Unsubscribe" msgstr "Скасувати підписку" #~ msgid "SetAnnotation" #~ msgstr "SetAnnotation" #~ msgid "Mock" #~ msgstr "Макет" #~ msgctxt "NAME OF TRANSLATORS" #~ msgid "Your names" #~ msgstr "Юрій Чорноіван" #~ msgctxt "EMAIL OF TRANSLATORS" #~ msgid "Your emails" #~ msgstr "yurchor@ukr.net" #~ msgctxt "Authentication method" #~ msgid "Clear text" #~ msgstr "Звичайний текст" #~ msgctxt "Authentication method" #~ msgid "Anonymous" #~ msgstr "Анонімний" #~ msgid "Check" #~ msgstr "Перевірити" #~ msgid "Noop" #~ msgstr "Порожній" 070701000000A9000041ED00000000000000000000000266FAD7C000000000000000000000000000000000000000000000003200000000kimap-VERSIONgit.20240930T185424~db1f697/po/zh_CN070701000000AA000081A400000000000000000000000166FAD7C0000014A2000000000000000000000000000000000000003F00000000kimap-VERSIONgit.20240930T185424~db1f697/po/zh_CN/libkimap6.pomsgid "" msgstr "" "Project-Id-Version: kdeorg\n" "Report-Msgid-Bugs-To: https://bugs.kde.org\n" "POT-Creation-Date: 2022-05-11 00:45+0000\n" "PO-Revision-Date: 2024-04-22 15:58\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: /kf6-trunk/messages/kimap/libkimap6.pot\n" "X-Crowdin-File-ID: 48980\n" #: acljobbase.cpp:56 #, kde-format msgid "AclJobBase" msgstr "AclJobBase" #: appendjob.cpp:40 #, kde-format msgid "Append" msgstr "追加" #: capabilitiesjob.cpp:35 #, kde-format msgid "Capabilities" msgstr "特性" #: closejob.cpp:32 #, kde-format msgid "Close" msgstr "关闭" #: copyjob.cpp:41 #, kde-format msgid "Copy" msgstr "复制" #: createjob.cpp:36 #, kde-format msgid "Create" msgstr "创建" #: deleteacljob.cpp:37 #, kde-format msgid "DeleteAclJob" msgstr "DeleteAclJob" #: deletejob.cpp:36 #, kde-format msgid "Delete" msgstr "删除" #: enablejob.cpp:31 #, kde-format msgid "Enable" msgstr "启用" #: expungejob.cpp:37 #, kde-format msgid "Expunge" msgstr "除去" #: fetchjob.cpp:97 #, kde-format msgid "Fetch" msgstr "获取" #: getacljob.cpp:37 #, kde-format msgid "GetAcl" msgstr "获取访问控制列表" #: getmetadatajob.cpp:43 #, kde-format msgid "GetMetaData" msgstr "获取元数据" #: getmetadatajob.cpp:66 #, kde-format msgid "GetAnnotation" msgstr "获取批注" #: getquotajob.cpp:35 #, kde-format msgid "GetQuota" msgstr "获取配额信息" #: getquotarootjob.cpp:38 #, kde-format msgid "GetQuotaRoot" msgstr "获取配额根" #: idjob.cpp:35 #, kde-format msgid "Id" msgstr "编号" #: idlejob.cpp:65 #, kde-format msgctxt "name of the idle job" msgid "Idle" msgstr "空闲" #: job.cpp:19 #, kde-format msgid "Job" msgstr "任务" #: job.cpp:54 loginjob.cpp:574 #, kde-format msgid "Connection to server lost." msgstr "与服务器的连接丢失。" #: job.cpp:65 loginjob.cpp:403 setmetadatajob.cpp:126 #, kde-format msgid "%1 failed, malformed reply from the server." msgstr "%1 失败,服务器的响应数据格式不正常。" #: job.cpp:68 loginjob.cpp:277 setmetadatajob.cpp:109 setmetadatajob.cpp:129 #, kde-format msgid "%1 failed, server replied: %2" msgstr "%1 失败,服务器响应:%2" #: listjob.cpp:59 #, kde-format msgid "List" msgstr "列表" #: listrightsjob.cpp:38 #, kde-format msgid "ListRights" msgstr "列出权限" #: loginjob.cpp:129 loginjob.cpp:233 #, kde-format msgid "Login" msgstr "登录" #: loginjob.cpp:184 #, kde-format msgid "IMAP session in the wrong state for authentication" msgstr "IMAP 会话在进行身份验证时状态出错" #: loginjob.cpp:235 #, kde-format msgid "Capability" msgstr "特性" #: loginjob.cpp:237 #, kde-format msgid "StartTls" msgstr "开启 TLS" #: loginjob.cpp:340 #, kde-format msgid "STARTTLS is not supported by the server, try using SSL/TLS instead." msgstr "服务器不支持 STARTTLS,请尝试使用 SSL/TLS 代替。" #: loginjob.cpp:353 #, kde-format msgid "Internal error, tried to login before encryption" msgstr "内部错误,尝试在加密前登录" #: loginjob.cpp:362 #, kde-format msgid "Login failed, plain login is disabled by the server." msgstr "登录失败,服务器已禁用纯文本登录。" #: loginjob.cpp:383 #, kde-format msgid "Login failed, authentication mode %1 is not supported by the server." msgstr "登录失败,服务器不支持 %1 验证模式。" #: loginjob.cpp:413 #, kde-format msgid "Login failed, client cannot initialize the SASL library." msgstr "登录失败,客户端无法初始化 SASL 类库。" #: loginjob.cpp:512 #, kde-format msgid "Login failed, TLS negotiation failed." msgstr "登录失败,TLS 协商失败。" #: loginjob.cpp:570 #, kde-format msgid "SSL handshake failed." msgstr "SSL 握手失败。" #: logoutjob.cpp:33 #, kde-format msgid "Logout" msgstr "注销" #: metadatajobbase.cpp:53 #, kde-format msgid "MetaDataJobBase" msgstr "MetaDataJobBase" #: movejob.cpp:42 #, kde-format msgid "Move" msgstr "移动" #: myrightsjob.cpp:37 #, kde-format msgid "MyRights" msgstr "我的权限" #: namespacejob.cpp:68 #, kde-format msgid "Namespace" msgstr "命名空间" #: quotajobbase.cpp:34 #, kde-format msgid "QuotaJobBase" msgstr "QuotaJobBase" #: renamejob.cpp:37 #, kde-format msgid "Rename" msgstr "重命名" #: searchjob.cpp:361 #, kde-format msgctxt "Name of the search job" msgid "Search" msgstr "搜索" #: selectjob.cpp:73 #, kde-format msgctxt "name of the select job" msgid "Select" msgstr "选择" #: setacljob.cpp:34 #, kde-format msgid "SetAcl" msgstr "设定访问控制列表" #: setmetadatajob.cpp:43 #, kde-format msgid "SetMetaData" msgstr "设定元数据" #: setquotajob.cpp:37 #, kde-format msgid "SetQuota" msgstr "设定配额" #: statusjob.cpp:40 #, kde-format msgctxt "name of the status job" msgid "Status" msgstr "状态" #: storejob.cpp:70 #, kde-format msgid "Store" msgstr "存储" #: subscribejob.cpp:36 #, kde-format msgid "Subscribe" msgstr "订阅" #: unsubscribejob.cpp:36 #, kde-format msgid "Unsubscribe" msgstr "退订" 070701000000AB000041ED00000000000000000000000266FAD7C000000000000000000000000000000000000000000000003200000000kimap-VERSIONgit.20240930T185424~db1f697/po/zh_TW070701000000AC000081A400000000000000000000000166FAD7C00000159C000000000000000000000000000000000000003F00000000kimap-VERSIONgit.20240930T185424~db1f697/po/zh_TW/libkimap6.po# Copyright (C) YEAR This_file_is_part_of_KDE # This file is distributed under the same license as the PACKAGE package. # # Frank Weng (a.k.a. Franklin) <franklin at goodhorse dot idv dot tw>, 2009, 2010, 2014. # pan93412 <pan93412@gmail.com>, 2019. # SPDX-FileCopyrightText: 2023 Kisaragi Hiu <mail@kisaragi-hiu.com> msgid "" msgstr "" "Project-Id-Version: libkimap\n" "Report-Msgid-Bugs-To: https://bugs.kde.org\n" "POT-Creation-Date: 2022-05-11 00:45+0000\n" "PO-Revision-Date: 2023-12-13 04:59+0900\n" "Last-Translator: Kisaragi Hiu <mail@kisaragi-hiu.com>\n" "Language-Team: Traditional Chinese <zh-l10n@lists.slat.org>\n" "Language: zh_TW\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "dot tw>\n" "X-Generator: Lokalize 23.08.4\n" "Plural-Forms: nplurals=1; plural=0;\n" #: acljobbase.cpp:56 #, kde-format msgid "AclJobBase" msgstr "AclJobBase" #: appendjob.cpp:40 #, kde-format msgid "Append" msgstr "附加" #: capabilitiesjob.cpp:35 #, kde-format msgid "Capabilities" msgstr "性能" #: closejob.cpp:32 #, kde-format msgid "Close" msgstr "關閉" #: copyjob.cpp:41 #, kde-format msgid "Copy" msgstr "複製" #: createjob.cpp:36 #, kde-format msgid "Create" msgstr "建立" #: deleteacljob.cpp:37 #, kde-format msgid "DeleteAclJob" msgstr "DeleteAclJob" #: deletejob.cpp:36 #, kde-format msgid "Delete" msgstr "刪除" #: enablejob.cpp:31 #, kde-format msgid "Enable" msgstr "啟用" #: expungejob.cpp:37 #, kde-format msgid "Expunge" msgstr "刪去" #: fetchjob.cpp:97 #, kde-format msgid "Fetch" msgstr "抓取" #: getacljob.cpp:37 #, kde-format msgid "GetAcl" msgstr "取得權限清單" #: getmetadatajob.cpp:43 #, kde-format msgid "GetMetaData" msgstr "取得中繼資料" #: getmetadatajob.cpp:66 #, kde-format msgid "GetAnnotation" msgstr "取得狀態註記" #: getquotajob.cpp:35 #, kde-format msgid "GetQuota" msgstr "取得大小限制" #: getquotarootjob.cpp:38 #, kde-format msgid "GetQuotaRoot" msgstr "GetQuotaRoot" #: idjob.cpp:35 #, kde-format msgid "Id" msgstr "編號" #: idlejob.cpp:65 #, kde-format msgctxt "name of the idle job" msgid "Idle" msgstr "閒置" #: job.cpp:19 #, kde-format msgid "Job" msgstr "工作" #: job.cpp:54 loginjob.cpp:574 #, kde-format msgid "Connection to server lost." msgstr "到伺服器的連線遺失" #: job.cpp:65 loginjob.cpp:403 setmetadatajob.cpp:126 #, kde-format msgid "%1 failed, malformed reply from the server." msgstr "%1 失敗,伺服器的回應不正確。" #: job.cpp:68 loginjob.cpp:277 setmetadatajob.cpp:109 setmetadatajob.cpp:129 #, kde-format msgid "%1 failed, server replied: %2" msgstr "%1 失敗,伺服器回應:%2" #: listjob.cpp:59 #, kde-format msgid "List" msgstr "清單" #: listrightsjob.cpp:38 #, kde-format msgid "ListRights" msgstr "清單權限" #: loginjob.cpp:129 loginjob.cpp:233 #, kde-format msgid "Login" msgstr "登入" #: loginjob.cpp:184 #, kde-format msgid "IMAP session in the wrong state for authentication" msgstr "IMAP 工作階段在認證時的狀態錯誤" #: loginjob.cpp:235 #, kde-format msgid "Capability" msgstr "相容性" #: loginjob.cpp:237 #, kde-format msgid "StartTls" msgstr "StartTls" #: loginjob.cpp:340 #, kde-format msgid "STARTTLS is not supported by the server, try using SSL/TLS instead." msgstr "伺服器不支援 STARTTLS,嘗試使用 SSL/TLS 取代。" #: loginjob.cpp:353 #, kde-format msgid "Internal error, tried to login before encryption" msgstr "內部錯誤,在加密前嘗試登入" #: loginjob.cpp:362 #, kde-format msgid "Login failed, plain login is disabled by the server." msgstr "登入失敗,plain login 已由伺服器關閉" #: loginjob.cpp:383 #, kde-format msgid "Login failed, authentication mode %1 is not supported by the server." msgstr "登入失敗,伺服器未支援認證模式 %1。" #: loginjob.cpp:413 #, kde-format msgid "Login failed, client cannot initialize the SASL library." msgstr "登入失敗,用戶端無法初始化 SASL 函式庫。" #: loginjob.cpp:512 #, kde-format msgid "Login failed, TLS negotiation failed." msgstr "登入失敗,TLS 溝通失敗。" #: loginjob.cpp:570 #, kde-format msgid "SSL handshake failed." msgstr "SSL 交換連線資訊失敗。" #: logoutjob.cpp:33 #, kde-format msgid "Logout" msgstr "登出" #: metadatajobbase.cpp:53 #, kde-format msgid "MetaDataJobBase" msgstr "MetaDataJobBase" #: movejob.cpp:42 #, kde-format msgid "Move" msgstr "移動" #: myrightsjob.cpp:37 #, kde-format msgid "MyRights" msgstr "MyRights" #: namespacejob.cpp:68 #, kde-format msgid "Namespace" msgstr "命名空間" #: quotajobbase.cpp:34 #, kde-format msgid "QuotaJobBase" msgstr "QuotaJobBase" #: renamejob.cpp:37 #, kde-format msgid "Rename" msgstr "重新命名" #: searchjob.cpp:361 #, kde-format msgctxt "Name of the search job" msgid "Search" msgstr "搜尋" #: selectjob.cpp:73 #, kde-format msgctxt "name of the select job" msgid "Select" msgstr "選取" #: setacljob.cpp:34 #, kde-format msgid "SetAcl" msgstr "設定權限清單" #: setmetadatajob.cpp:43 #, kde-format msgid "SetMetaData" msgstr "設定中繼資料" #: setquotajob.cpp:37 #, kde-format msgid "SetQuota" msgstr "設定大小限制" #: statusjob.cpp:40 #, kde-format msgctxt "name of the status job" msgid "Status" msgstr "狀態" #: storejob.cpp:70 #, kde-format msgid "Store" msgstr "儲存" #: subscribejob.cpp:36 #, kde-format msgid "Subscribe" msgstr "訂閱" #: unsubscribejob.cpp:36 #, kde-format msgid "Unsubscribe" msgstr "取消訂閱" 070701000000AD000081A400000000000000000000000166FAD7C000000222000000000000000000000000000000000000004000000000kimap-VERSIONgit.20240930T185424~db1f697/readme-build-ftime.txt# Analyzing Build Performance For debug build time: We need ClangBuildAnalyzer ` git clone https://github.com/aras-p/ClangBuildAnalyzer mkdir build cd build cmake -DCMAKE_INSTALL_PREFIX=<path> ../ make install ` ## Command line cmake -preset ftime-trace ClangBuildAnalyzer --start $PWD/build-ftime-trace cmake --build --preset ftime-trace ClangBuildAnalyzer --stop $PWD/build-ftime-trace build-ftime.txt ClangBuildAnalyzer --analyze build-ftime.txt > analyze-build-ftime.txt see https://aras-p.info/blog/2019/09/28/Clang-Build-Analyzer/ 070701000000AE000081A400000000000000000000000166FAD7C0000001BF000000000000000000000000000000000000003900000000kimap-VERSIONgit.20240930T185424~db1f697/sanitizers.supp# SPDX-FileCopyrightText: 2021-2024 Laurent Montel <montel@kde.org> # SPDX-License-Identifier: CC0-1.0 # Suppression file for ASAN/LSAN leak:libspeechd leak:getdelim leak:g_malloc leak:libfontconfig leak:libdbus leak:QEasingCurve:: leak:QtSharedPointer::ExternalRefCountData::getAndRef leak:QArrayData::allocate leak:QObject::QObject leak:QObjectPrivate::addConnection leak:QObjectPrivate::connectImpl leak:QPropertyAnimation::QPropertyAnimation 070701000000AF000041ED00000000000000000000000266FAD7C000000000000000000000000000000000000000000000002D00000000kimap-VERSIONgit.20240930T185424~db1f697/src070701000000B0000081A400000000000000000000000166FAD7C0000012B3000000000000000000000000000000000000003C00000000kimap-VERSIONgit.20240930T185424~db1f697/src/CMakeLists.txt# SPDX-FileCopyrightText: none # SPDX-License-Identifier: BSD-3-Clause # Turn exceptions on kde_enable_exceptions() add_library(KPim6IMAP) add_library(KPim6::IMAP ALIAS KPim6IMAP) target_sources(KPim6IMAP PRIVATE acl.cpp acljobbase.cpp appendjob.cpp capabilitiesjob.cpp closejob.cpp copyjob.cpp createjob.cpp deleteacljob.cpp deletejob.cpp enablejob.cpp expungejob.cpp fetchjob.cpp getacljob.cpp getmetadatajob.cpp getquotajob.cpp getquotarootjob.cpp idjob.cpp idlejob.cpp imapset.cpp imapstreamparser.cpp job.cpp listjob.cpp listrightsjob.cpp loginjob.cpp logoutjob.cpp metadatajobbase.cpp movejob.cpp myrightsjob.cpp namespacejob.cpp quotajobbase.cpp renamejob.cpp rfccodecs.cpp searchjob.cpp selectjob.cpp session.cpp sessionlogger.cpp sessionthread.cpp sessionuiproxy.cpp setacljob.cpp setmetadatajob.cpp setquotajob.cpp statusjob.cpp storejob.cpp subscribejob.cpp unsubscribejob.cpp deletejob.h getquotarootjob.h fetchjob.h listrightsjob.h sessionlogger_p.h unsubscribejob.h loginjob.h response_p.h sessionthread_p.h imapset.h closejob.h getacljob.h acl.h idjob.h capabilitiesjob.h quotajobbase_p.h enablejob.h metadatajobbase_p.h copyjob.h session_p.h storejob.h selectjob.h idlejob.h setquotajob.h job.h subscribejob.h namespacejob.h session.h metadatajobbase.h sessionuiproxy.h createjob.h movejob.h acljobbase_p.h expungejob.h imapstreamparser.h getmetadatajob.h rfccodecs.h getquotajob.h listjob.h deleteacljob.h quotajobbase.h myrightsjob.h common.h renamejob.h statusjob.h setacljob.h job_p.h searchjob.h acljobbase.h appendjob.h setmetadatajob.h logoutjob.h ) ecm_qt_declare_logging_category(KPim6IMAP HEADER kimap_debug.h IDENTIFIER KIMAP_LOG CATEGORY_NAME org.kde.pim.kimap OLD_CATEGORY_NAMES log_kimap DESCRIPTION "kimap (pim lib)" EXPORT KIMAP) if(COMPILE_WITH_UNITY_CMAKE_SUPPORT) set_target_properties(KPim6IMAP PROPERTIES UNITY_BUILD ON) endif() ecm_generate_export_header(KPim6IMAP BASE_NAME kimap VERSION ${KIMAP_VERSION} DEPRECATED_BASE_VERSION 0 USE_VERSION_HEADER ) target_include_directories(KPim6IMAP INTERFACE "$<INSTALL_INTERFACE:${KDE_INSTALL_INCLUDEDIR}/KPim6/KIMAP>") target_include_directories(KPim6IMAP PUBLIC "$<BUILD_INTERFACE:${KIMAP_SOURCE_DIR}/src;${KIMAP_BINARY_DIR}/src>") if(WIN32) set(extra_LIBS ws2_32) endif() target_link_libraries(KPim6IMAP PUBLIC KPim6::Mime KF6::CoreAddons Qt::Network PRIVATE KF6::KIOCore KF6::I18n Sasl2::Sasl2 ${extra_LIBS} ) set_property(TARGET KPim6IMAP PROPERTY POSITION_INDEPENDENT_CODE ON) set_target_properties(KPim6IMAP PROPERTIES VERSION ${KIMAP_VERSION} SOVERSION ${KIMAP_SOVERSION} EXPORT_NAME IMAP ) ecm_generate_headers(KIMAP_CamelCase_HEADERS HEADER_NAMES Acl AclJobBase AppendJob CapabilitiesJob CloseJob CopyJob CreateJob DeleteAclJob DeleteJob EnableJob ExpungeJob FetchJob GetAclJob GetMetaDataJob GetQuotaJob GetQuotaRootJob IdJob IdleJob ImapSet Job ListJob ListRightsJob LoginJob LogoutJob MetaDataJobBase MoveJob MyRightsJob NamespaceJob QuotaJobBase RenameJob RFCCodecs SearchJob SelectJob Session SessionUiProxy SetAclJob SetMetaDataJob SetQuotaJob StatusJob StoreJob SubscribeJob UnsubscribeJob PREFIX KIMAP REQUIRED_HEADERS KIMAP_HEADERS ) install(TARGETS KPim6IMAP EXPORT KPim6IMAPTargets ${KDE_INSTALL_TARGETS_DEFAULT_ARGS}) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/kimap_export.h ${KIMAP_HEADERS} ${KIMAP_CamelCase_HEADERS} DESTINATION ${KDE_INSTALL_INCLUDEDIR}/KPim6/KIMAP/kimap COMPONENT Devel ) install(FILES ${KIMAP_CamelCase_HEADERS} DESTINATION ${KDE_INSTALL_INCLUDEDIR}/KPim6/KIMAP/KIMAP COMPONENT Devel ) ecm_qt_install_logging_categories(EXPORT KIMAP FILE kimap.categories DESTINATION ${KDE_INSTALL_LOGGINGCATEGORIESDIR}) if(BUILD_QCH) ecm_add_qch( KPim6Imap_QCH NAME KImap BASE_NAME KPim6Imap VERSION ${PIM_VERSION} ORG_DOMAIN org.kde SOURCES # using only public headers, to cover only public API ${KIMAP_HEADERS} MD_MAINPAGE "${CMAKE_SOURCE_DIR}/README.md" #IMAGE_DIRS "${CMAKE_SOURCE_DIR}/docs/pics" LINK_QCHS Qt6Core_QCH INCLUDE_DIRS ${CMAKE_CURRENT_BINARY_DIR} BLANK_MACROS KIMAP_EXPORT TAGFILE_INSTALL_DESTINATION ${KDE_INSTALL_QTQCHDIR} QCH_INSTALL_DESTINATION ${KDE_INSTALL_QTQCHDIR} COMPONENT Devel ) endif() 070701000000B1000081ED00000000000000000000000166FAD7C00000009A000000000000000000000000000000000000003900000000kimap-VERSIONgit.20240930T185424~db1f697/src/Messages.sh#! /bin/sh # SPDX-FileCopyrightText: none # SPDX-License-Identifier: BSD-3-Clause $XGETTEXT `find . -name "*.cpp" -o -name "*.h"` -o $podir/libkimap6.pot 070701000000B2000081A400000000000000000000000166FAD7C0000009EB000000000000000000000000000000000000003500000000kimap-VERSIONgit.20240930T185424~db1f697/src/acl.cpp/* SPDX-FileCopyrightText: 2009 Andras Mantia <amantia@kde.org> SPDX-License-Identifier: LGPL-2.0-or-later */ #include "acl.h" #include <QByteArray> #include <QMap> namespace KIMAP { namespace Acl { class RightsMap { public: RightsMap() { map['l'] = Lookup; map['r'] = Read; map['s'] = KeepSeen; map['w'] = Write; map['i'] = Insert; map['p'] = Post; map['c'] = Create; // TODO: obsolete, keep it? map['d'] = Delete; // TODO: obsolete, keep it? map['k'] = CreateMailbox; map['x'] = DeleteMailbox; map['t'] = DeleteMessage; map['e'] = Expunge; map['a'] = Admin; map['n'] = WriteShared; map['0'] = Custom0; map['1'] = Custom1; map['2'] = Custom2; map['3'] = Custom3; map['4'] = Custom4; map['5'] = Custom5; map['6'] = Custom6; map['7'] = Custom7; map['8'] = Custom8; map['9'] = Custom9; } QMap<char, Right> map; }; Q_GLOBAL_STATIC(RightsMap, globalRights) } } KIMAP::Acl::Rights KIMAP::Acl::rightsFromString(const QByteArray &string) { Rights result; if (string.isEmpty()) { return result; } int pos = 0; if (string[0] == '+' || string[0] == '-') { // Skip modifier if any pos++; } for (int i = pos; i < string.size(); i++) { if (globalRights->map.contains(string[i])) { result |= globalRights->map[string[i]]; } } return result; } QByteArray KIMAP::Acl::rightsToString(Rights rights) { QByteArray result; for (int right = Lookup; right <= Custom9; right <<= 1) { if (rights & right) { result += globalRights->map.key(static_cast<Right>(right)); } } return result; } KIMAP::Acl::Rights KIMAP::Acl::normalizedRights(KIMAP::Acl::Rights rights) { Rights normalized = rights; if (normalized & Create) { normalized |= (CreateMailbox | DeleteMailbox); normalized &= ~Create; } if (normalized & Delete) { normalized |= (DeleteMessage | Expunge); normalized &= ~Delete; } return normalized; } KIMAP::Acl::Rights KIMAP::Acl::denormalizedRights(KIMAP::Acl::Rights rights) { Rights denormalized = normalizedRights(rights); if (denormalized & (CreateMailbox | DeleteMailbox)) { denormalized |= Create; } if (denormalized & (DeleteMessage | Expunge)) { denormalized |= Delete; } return denormalized; } 070701000000B3000081A400000000000000000000000166FAD7C000000F1A000000000000000000000000000000000000003300000000kimap-VERSIONgit.20240930T185424~db1f697/src/acl.h/* SPDX-FileCopyrightText: 2009 Andras Mantia <amantia@kde.org> SPDX-License-Identifier: LGPL-2.0-or-later */ #pragma once #include "kimap_export.h" #include <qglobal.h> namespace KIMAP { /** * Operations for dealing with mailbox permissions. */ namespace Acl { /** * Possible rights that can be held on a mailbox */ enum Right { None = 0x000000, /** Mailbox is visible to LIST/LSUB commands, SUBSCRIBE mailbox */ Lookup = 0x000001, /** SELECT the mailbox, perform STATUS */ Read = 0x000002, /** Set or clear the \Seen flag on messages in the mailbox, and keep it across sessions */ KeepSeen = 0x000004, /** Set or clear flags other than \Seen and \Deleted on messages in the mailbox */ Write = 0x000008, /** Perform APPEND and COPY with the mailbox as the target */ Insert = 0x000010, /** Send mail to the submission address for the mailbox * * Note: this is not enforced by IMAP4, but is purely advisory. */ Post = 0x000020, /** Obsolete as of RFC 4314, replaced by CreateMailbox and DeleteMailbox */ Create = 0x000040, /** Create new child mailboxes, or move a mailbox with this mailbox as the new parent * * Note that what constitutes a "child" mailbox is implementation-defined, but * . or / are usually used as separaters. */ CreateMailbox = 0x000080, /** Delete or move the mailbox */ DeleteMailbox = 0x000100, /** Set or clear the \Deleted flag on messages in the mailbox */ DeleteMessage = 0x000200, /** Obsolete as of RFC 4314, replaced by DeleteMessage and Expunge*/ Delete = 0x000400, /** View and modify the access control list for the mailbox */ Admin = 0x000800, /** Expunge the messages in this mailbox * * Note that if this right is not held on a mailbox, closing the mailbox * (see CloseJob) will succeed, but will not expunge the messages. */ Expunge = 0x001000, /** Write shared annotations * * See <a href="https://tools.ietf.org/html/rfc5257" title="IMAP ANNOTATE extension">RFC * 5257</a>. Only supported by servers that implement the ANNOTATE extension. */ WriteShared = 0x002000, Custom0 = 0x004000, /**< Server-specific right 0 */ Custom1 = 0x008000, /**< Server-specific right 1 */ Custom2 = 0x010000, /**< Server-specific right 2 */ Custom3 = 0x020000, /**< Server-specific right 3 */ Custom4 = 0x040000, /**< Server-specific right 4 */ Custom5 = 0x080000, /**< Server-specific right 5 */ Custom6 = 0x100000, /**< Server-specific right 6 */ Custom7 = 0x200000, /**< Server-specific right 7 */ Custom8 = 0x400000, /**< Server-specific right 8 */ Custom9 = 0x800000 /**< Server-specific right 9 */ }; Q_DECLARE_FLAGS(Rights, Right) /** * Returns a rights mask that has no obsolete members anymore, i.e. obsolete flags are removed and * replaced by their successors. * @param rights set of #Rights flags to normalize * @since 4.6 */ [[nodiscard]] KIMAP_EXPORT Rights normalizedRights(Rights rights); /** * Returns a rights mask that contains both obsolete and new flags if one of them is set. * @param rights set of #Rights flags to augment * @since 4.6 */ [[nodiscard]] KIMAP_EXPORT Rights denormalizedRights(Rights rights); /** * Convert a set of rights into text format * * No modifier flag ('+' or '-') will be included. */ [[nodiscard]] KIMAP_EXPORT QByteArray rightsToString(Rights rights); /** * Convert the text form of a set of rights into a Rights bitflag * * Modifier flags ('+' and '-') are ignored, as are any unknown * characters. This method will not complain if you give it * something that is not a list of rights. */ [[nodiscard]] KIMAP_EXPORT Rights rightsFromString(const QByteArray &string); } } Q_DECLARE_OPERATORS_FOR_FLAGS(KIMAP::Acl::Rights) 070701000000B4000081A400000000000000000000000166FAD7C0000005EF000000000000000000000000000000000000003C00000000kimap-VERSIONgit.20240930T185424~db1f697/src/acljobbase.cpp/* SPDX-FileCopyrightText: 2009 Andras Mantia <amantia@kde.org> SPDX-License-Identifier: LGPL-2.0-or-later */ #include "acljobbase.h" #include "acljobbase_p.h" #include "response_p.h" #include "session_p.h" #include <KLocalizedString> using namespace KIMAP; void AclJobBasePrivate::setIdentifier(const QByteArray &identifier) { id = identifier; } QByteArray AclJobBasePrivate::identifier() const { return id; } bool AclJobBasePrivate::hasRightEnabled(Acl::Right right) const { return rightList & right; } void AclJobBasePrivate::setRights(const QByteArray &rights) { switch (rights[0]) { case '+': modifier = AclJobBase::Add; break; case '-': modifier = AclJobBase::Remove; break; default: modifier = AclJobBase::Change; break; } rightList = Acl::rightsFromString(rights); } void AclJobBasePrivate::setRights(AclJobBase::AclModifier _modifier, Acl::Rights rights) { modifier = _modifier; // XXX: [alexmerry, 2010-07-24]: this is REALLY unintuitive behaviour rightList |= rights; } AclJobBase::AclJobBase(Session *session) : Job(*new AclJobBasePrivate(session, i18n("AclJobBase"))) { } AclJobBase::AclJobBase(JobPrivate &dd) : Job(dd) { } AclJobBase::~AclJobBase() { } void AclJobBase::setMailBox(const QString &mailBox) { Q_D(AclJobBase); d->mailBox = mailBox; } QString AclJobBase::mailBox() const { Q_D(const AclJobBase); return d->mailBox; } #include "moc_acljobbase.cpp" 070701000000B5000081A400000000000000000000000166FAD7C0000004E5000000000000000000000000000000000000003A00000000kimap-VERSIONgit.20240930T185424~db1f697/src/acljobbase.h/* SPDX-FileCopyrightText: 2009 Andras Mantia <amantia@kde.org> SPDX-License-Identifier: LGPL-2.0-or-later */ #pragma once #include "kimap_export.h" #include "acl.h" #include "job.h" namespace KIMAP { class Session; struct Response; class AclJobBasePrivate; /** * Base class for jobs that operate on mailbox ACLs * * Provides support for the IMAP ACL extension, as defined by * <a href="https://tools.ietf.org/html/rfc4314" title="IMAP ACL extension">RFC 4314</a>. * * This class cannot be used directly, you must subclass it and reimplement * at least the doStart() method. */ class KIMAP_EXPORT AclJobBase : public Job { Q_OBJECT Q_DECLARE_PRIVATE(AclJobBase) friend class SessionPrivate; public: AclJobBase(Session *session); ~AclJobBase() override; /** * Used when subclassing to specify how the ACL will be modified. */ enum AclModifier { Add = 0, Remove, Change }; /** * Set the mailbox to act on * * @param mailBox the name of an existing mailbox */ void setMailBox(const QString &mailBox); /** * The mailbox that will be acted upon. */ [[nodiscard]] QString mailBox() const; protected: explicit AclJobBase(JobPrivate &dd); }; } 070701000000B6000081A400000000000000000000000166FAD7C000000378000000000000000000000000000000000000003C00000000kimap-VERSIONgit.20240930T185424~db1f697/src/acljobbase_p.h/* SPDX-FileCopyrightText: 2009 Andras Mantia <amantia@kde.org> SPDX-License-Identifier: LGPL-2.0-or-later */ #pragma once #include "acljobbase.h" #include "job_p.h" #include "session.h" namespace KIMAP { class AclJobBasePrivate : public JobPrivate { public: AclJobBasePrivate(Session *session, const QString &name) : JobPrivate(session, name) , rightList(Acl::None) , modifier(AclJobBase::Change) { } ~AclJobBasePrivate() { } void setIdentifier(const QByteArray &identifier); [[nodiscard]] QByteArray identifier() const; [[nodiscard]] bool hasRightEnabled(Acl::Right right) const; void setRights(const QByteArray &rights); void setRights(AclJobBase::AclModifier modifier, Acl::Rights rights); QString mailBox; QByteArray id; Acl::Rights rightList; AclJobBase::AclModifier modifier; }; } 070701000000B7000081A400000000000000000000000166FAD7C000000C31000000000000000000000000000000000000003B00000000kimap-VERSIONgit.20240930T185424~db1f697/src/appendjob.cpp/* SPDX-FileCopyrightText: 2009 Kevin Ottens <ervin@kde.org> SPDX-License-Identifier: LGPL-2.0-or-later */ #include "appendjob.h" #include <KLocalizedString> #include "job_p.h" #include "response_p.h" #include "rfccodecs.h" #include "session_p.h" namespace KIMAP { class AppendJobPrivate : public JobPrivate { public: AppendJobPrivate(Session *session, const QString &name) : JobPrivate(session, name) { } ~AppendJobPrivate() { } QString mailBox; QList<QByteArray> flags; QDateTime internalDate; QByteArray content; qint64 uid = 0; }; } using namespace KIMAP; AppendJob::AppendJob(Session *session) : Job(*new AppendJobPrivate(session, i18n("Append"))) { } AppendJob::~AppendJob() { } void AppendJob::setMailBox(const QString &mailBox) { Q_D(AppendJob); d->mailBox = mailBox; } QString AppendJob::mailBox() const { Q_D(const AppendJob); return d->mailBox; } void AppendJob::setFlags(const QList<QByteArray> &flags) { Q_D(AppendJob); d->flags = flags; } QList<QByteArray> AppendJob::flags() const { Q_D(const AppendJob); return d->flags; } void AppendJob::setInternalDate(const QDateTime &internalDate) { Q_D(AppendJob); d->internalDate = internalDate; } QDateTime AppendJob::internalDate() const { Q_D(const AppendJob); return d->internalDate; } void AppendJob::setContent(const QByteArray &content) { Q_D(AppendJob); d->content = content; } QByteArray AppendJob::content() const { Q_D(const AppendJob); return d->content; } qint64 AppendJob::uid() const { Q_D(const AppendJob); return d->uid; } void AppendJob::doStart() { Q_D(AppendJob); QByteArray parameters = '\"' + KIMAP::encodeImapFolderName(d->mailBox.toUtf8()) + '\"'; if (!d->flags.isEmpty()) { parameters += " ("; for (const QByteArray &flag : std::as_const(d->flags)) { parameters += flag + ' '; } parameters.chop(1); parameters += ')'; } if (!d->internalDate.isNull()) { const QDateTime utcDateTime = d->internalDate.toUTC(); parameters += " \"" + QLocale::c().toString(utcDateTime, QStringLiteral("dd-MMM-yyyy hh:mm:ss")).toLatin1() + " +0000" + '\"'; } parameters += " {" + QByteArray::number(d->content.size()) + '}'; d->tags << d->sessionInternal()->sendCommand("APPEND", parameters); } void AppendJob::handleResponse(const Response &response) { Q_D(AppendJob); const QList<Response::Part>::ConstIterator end(response.responseCode.end()); for (QList<Response::Part>::ConstIterator it = response.responseCode.begin(); it != end; ++it) { if (it->toString() == "APPENDUID") { it = it + 2; if (it != end) { d->uid = it->toString().toLongLong(); } break; } } if (handleErrorReplies(response) == NotHandled) { if (!response.content.isEmpty() && response.content[0].toString() == "+") { d->sessionInternal()->sendData(d->content); } } } #include "moc_appendjob.cpp" 070701000000B8000081A400000000000000000000000166FAD7C000000B77000000000000000000000000000000000000003900000000kimap-VERSIONgit.20240930T185424~db1f697/src/appendjob.h/* SPDX-FileCopyrightText: 2009 Kevin Ottens <ervin@kde.org> SPDX-License-Identifier: LGPL-2.0-or-later */ #pragma once #include "kimap_export.h" #include "job.h" #include <QDateTime> namespace KIMAP { class Session; struct Response; class AppendJobPrivate; /** * Appends a message to a mailbox. * * This job can only be run when the session is in the * authenticated (or selected) state. * * If the server supports ACLs, the user will need the * Acl::Insert right on the mailbox. */ class KIMAP_EXPORT AppendJob : public Job { Q_OBJECT Q_DECLARE_PRIVATE(AppendJob) friend class SessionPrivate; public: explicit AppendJob(Session *session); ~AppendJob() override; /** * Set the mailbox to append the message to. * * If the mailbox does not exist, it will not automatically * be created and the command will fail. * * @param mailBox the (unquoted) name of the mailbox */ void setMailBox(const QString &mailBox); /** * The mailbox that the message will be appended to. */ [[nodiscard]] QString mailBox() const; /** * Set the flags that should be applied to the appended message. * * @param flags a list of flags */ void setFlags(const QList<QByteArray> &flags); /** * The flags that will be set on the appended message. */ [[nodiscard]] QList<QByteArray> flags() const; /** * Set the internal date that should be applied to the appended message. * * This is the date/time the IMAP server should set internally for the appended message. * See https://tools.ietf.org/html/rfc3501#section-6.3.11 * * If this is not set, the server will use the current date/time. * * @param internalDate the internal date * * @since 4.13 */ void setInternalDate(const QDateTime &internalDate); /** * The internal date that will be set on the appended message. * * @since 4.13 */ [[nodiscard]] QDateTime internalDate() const; /** * The content of the message. * * This should be in RFC-2822 format, although some required header * lines may be omitted in certain cases, for example when appending * to a Drafts folder. * * @param content usually an RFC-2822 message */ void setContent(const QByteArray &content); /** * The content that the message will have. */ [[nodiscard]] QByteArray content() const; /** * The UID of the new message. * * This will be zero if it is unknown. * * The UID will not be known until the job has been successfully * executed, and it will only be known at all if the server * supports the UIDPLUS extension (RFC 4315). */ [[nodiscard]] qint64 uid() const; protected: void doStart() override; void handleResponse(const Response &response) override; }; } 070701000000B9000081A400000000000000000000000166FAD7C0000005E2000000000000000000000000000000000000004100000000kimap-VERSIONgit.20240930T185424~db1f697/src/capabilitiesjob.cpp/* SPDX-FileCopyrightText: 2009 Kevin Ottens <ervin@kde.org> SPDX-License-Identifier: LGPL-2.0-or-later */ #include "capabilitiesjob.h" #include <KLocalizedString> #include "job_p.h" #include "response_p.h" #include "session_p.h" namespace KIMAP { class CapabilitiesJobPrivate : public JobPrivate { public: CapabilitiesJobPrivate(Session *session, const QString &name) : JobPrivate(session, name) { } ~CapabilitiesJobPrivate() { } QStringList capabilities; }; } using namespace KIMAP; CapabilitiesJob::CapabilitiesJob(Session *session) : Job(*new CapabilitiesJobPrivate(session, i18n("Capabilities"))) { } CapabilitiesJob::~CapabilitiesJob() { } QStringList CapabilitiesJob::capabilities() const { Q_D(const CapabilitiesJob); return d->capabilities; } void CapabilitiesJob::doStart() { Q_D(CapabilitiesJob); d->tags << d->sessionInternal()->sendCommand("CAPABILITY"); } void CapabilitiesJob::handleResponse(const Response &response) { Q_D(CapabilitiesJob); if (handleErrorReplies(response) == NotHandled) { const int responseSize(response.content.size()); if (responseSize >= 2 && response.content[1].toString() == "CAPABILITY") { for (int i = 2; i < responseSize; ++i) { d->capabilities << QLatin1StringView(response.content[i].toString().toUpper()); } Q_EMIT capabilitiesReceived(d->capabilities); } } } #include "moc_capabilitiesjob.cpp" 070701000000BA000081A400000000000000000000000166FAD7C00000059B000000000000000000000000000000000000003F00000000kimap-VERSIONgit.20240930T185424~db1f697/src/capabilitiesjob.h/* SPDX-FileCopyrightText: 2009 Kevin Ottens <ervin@kde.org> SPDX-License-Identifier: LGPL-2.0-or-later */ #pragma once #include "kimap_export.h" #include "job.h" namespace KIMAP { class Session; struct Response; class CapabilitiesJobPrivate; /** * Checks server capabilities. * * This job can be run in any open session. * * This simply asks the server what capabilities it supports * (using the CAPABILITY command) and returns the list * provided by the server. The list may, therefore, be * inaccurate: the server may claim to support something * it does not implement properly, or it may omit a feature * that it does, in reality, support. */ class KIMAP_EXPORT CapabilitiesJob : public Job { Q_OBJECT Q_DECLARE_PRIVATE(CapabilitiesJob) friend class SessionPrivate; public: CapabilitiesJob(Session *session); ~CapabilitiesJob() override; /** * The capabilities the server claims to support. * * This will return an empty list until the job has completed. */ [[nodiscard]] QStringList capabilities() const; Q_SIGNALS: /** * Notifies listeners that the capabilities have been fetched. * * @param capabilities The capabilities the server claims to support. */ void capabilitiesReceived(const QStringList &capabilities); protected: void doStart() override; void handleResponse(const Response &response) override; }; } 070701000000BB000081A400000000000000000000000166FAD7C000000462000000000000000000000000000000000000003A00000000kimap-VERSIONgit.20240930T185424~db1f697/src/closejob.cpp/* SPDX-FileCopyrightText: 2009 Andras Mantia <amantia@kde.org> SPDX-License-Identifier: LGPL-2.0-or-later */ #include "closejob.h" #include <KLocalizedString> #include "job_p.h" #include "response_p.h" #include "session_p.h" namespace KIMAP { class CloseJobPrivate : public JobPrivate { public: CloseJobPrivate(Session *session, const QString &name) : JobPrivate(session, name) { } quint64 highestModSeq = 0; }; } using namespace KIMAP; CloseJob::CloseJob(Session *session) : Job(*new CloseJobPrivate(session, i18n("Close"))) { } void CloseJob::doStart() { Q_D(CloseJob); d->tags << d->sessionInternal()->sendCommand("CLOSE"); } quint64 CloseJob::newHighestModSeq() const { Q_D(const CloseJob); return d->highestModSeq; } void CloseJob::handleResponse(const Response &response) { Q_D(CloseJob); if (response.responseCode.size() >= 2 && response.responseCode[0].toString() == "HIGHESTMODSEQ") { d->highestModSeq = response.responseCode[1].toString().toULongLong(); } Job::handleErrorReplies(response); } #include "moc_closejob.cpp" 070701000000BC000081A400000000000000000000000166FAD7C00000070A000000000000000000000000000000000000003800000000kimap-VERSIONgit.20240930T185424~db1f697/src/closejob.h/* SPDX-FileCopyrightText: 2009 Andras Mantia <amantia@kde.org> SPDX-License-Identifier: LGPL-2.0-or-later */ #pragma once #include "kimap_export.h" #include "job.h" namespace KIMAP { class Session; struct Response; class CloseJobPrivate; /** * Closes the current mailbox. * * This job can only be run when the session is in the selected state. * * Permanently removes all messages that have the \\Deleted * flag set from the currently selected mailbox, and returns * to the authenticated state from the selected state. * * The server will not provide any notifications of which * messages were expunged, so this is quicker than doing * an expunge and then implicitly closing the mailbox * (by selecting or examining another mailbox or logging * out). If the QRESYNC extension (RFC5162) is available on the * server and has been enabled, the job will provide a new * modification sequence after expunging the deleted messages. * * No messages are removed if the mailbox is open in a read-only * state, or if the server supports ACLs and the user does not * have the Acl::Expunge right on the mailbox. */ class KIMAP_EXPORT CloseJob : public Job { Q_OBJECT Q_DECLARE_PRIVATE(CloseJob) friend class SessionPrivate; public: explicit CloseJob(Session *session); ~CloseJob() override = default; /** * Returns new modification sequence number after expunging messages. * * This value is only valid when server supports the QRESYNC extension * (RFC5162) and it has been explicitly enabled on this session. * * @see KIMAP::EnableJob * @since 5.16 */ [[nodiscard]] quint64 newHighestModSeq() const; protected: void doStart() override; void handleResponse(const Response &response) override; }; } 070701000000BD000081A400000000000000000000000166FAD7C0000003EE000000000000000000000000000000000000003600000000kimap-VERSIONgit.20240930T185424~db1f697/src/common.h/* This file is part of the KDE project SPDX-FileCopyrightText: 2008 Jarosław Staniek <staniek@kde.org> SPDX-License-Identifier: LGPL-2.0-or-later */ #pragma once #include <QCoreApplication> #include <QDir> #include <QFile> #include <stdio.h> extern "C" { #include <sasl/sasl.h> } inline bool initSASL() { #ifdef Q_OS_WIN // krazy:exclude=cpp for (const auto &path : QCoreApplication::libraryPaths()) { QDir dir(path); if (dir.exists(QStringLiteral("sasl2"))) { auto libInstallPath = QFile::encodeName(dir.absoluteFilePath(QStringLiteral("sasl2"))); if (sasl_set_path(SASL_PATH_TYPE_PLUGIN, libInstallPath.data()) != SASL_OK) { fprintf(stderr, "SASL path initialization failed!\n"); return false; } break; } } #endif if (sasl_client_init(nullptr) != SASL_OK) { fprintf(stderr, "SASL library initialization failed!\n"); return false; } return true; } 070701000000BE000081A400000000000000000000000166FAD7C00000091B000000000000000000000000000000000000003900000000kimap-VERSIONgit.20240930T185424~db1f697/src/copyjob.cpp/* SPDX-FileCopyrightText: 2009 Andras Mantia <amantia@kde.org> SPDX-License-Identifier: LGPL-2.0-or-later */ #include "copyjob.h" #include <KLocalizedString> #include "job_p.h" #include "response_p.h" #include "rfccodecs.h" #include "session_p.h" // TODO: when custom error codes are introduced, handle the NO [TRYCREATE] response namespace KIMAP { class CopyJobPrivate : public JobPrivate { public: CopyJobPrivate(Session *session, const QString &name) : JobPrivate(session, name) { } ~CopyJobPrivate() { } QString mailBox; ImapSet set; bool uidBased = false; ImapSet resultingUids; }; } using namespace KIMAP; CopyJob::CopyJob(Session *session) : Job(*new CopyJobPrivate(session, i18n("Copy"))) { Q_D(CopyJob); d->uidBased = false; } CopyJob::~CopyJob() { } void CopyJob::setMailBox(const QString &mailBox) { Q_D(CopyJob); d->mailBox = mailBox; } QString CopyJob::mailBox() const { Q_D(const CopyJob); return d->mailBox; } void CopyJob::setSequenceSet(const ImapSet &set) { Q_D(CopyJob); d->set = set; } ImapSet CopyJob::sequenceSet() const { Q_D(const CopyJob); return d->set; } void CopyJob::setUidBased(bool uidBased) { Q_D(CopyJob); d->uidBased = uidBased; } bool CopyJob::isUidBased() const { Q_D(const CopyJob); return d->uidBased; } ImapSet CopyJob::resultingUids() const { Q_D(const CopyJob); return d->resultingUids; } void CopyJob::doStart() { Q_D(CopyJob); d->set.optimize(); QByteArray parameters = d->set.toImapSequenceSet() + ' '; parameters += '\"' + KIMAP::encodeImapFolderName(d->mailBox.toUtf8()) + '\"'; QByteArray command = "COPY"; if (d->uidBased) { command = "UID " + command; } d->tags << d->sessionInternal()->sendCommand(command, parameters); } void CopyJob::handleResponse(const Response &response) { Q_D(CopyJob); for (auto it = response.responseCode.cbegin(), end = response.responseCode.cend(); it != end; ++it) { if (it->toString() == "COPYUID") { it = it + 3; if (it < end) { d->resultingUids = ImapSet::fromImapSequenceSet(it->toString()); } break; } } handleErrorReplies(response); } #include "moc_copyjob.cpp" 070701000000BF000081A400000000000000000000000166FAD7C000000C31000000000000000000000000000000000000003700000000kimap-VERSIONgit.20240930T185424~db1f697/src/copyjob.h/* SPDX-FileCopyrightText: 2009 Andras Mantia <amantia@kde.org> SPDX-License-Identifier: LGPL-2.0-or-later */ #pragma once #include "kimap_export.h" #include "imapset.h" #include "job.h" namespace KIMAP { class Session; struct Message; class CopyJobPrivate; /** * Copies one or more messages to another mailbox. * * This job can only be run when the session is in the selected state. * * If the server supports ACLs, the user will need the * Acl::Insert right on the target mailbox. * In order to preserve message flags, the user may also need * some combination of Acl::DeleteMessage, * Acl::KeepSeen and Acl::Write on the * target mailbox. */ class KIMAP_EXPORT CopyJob : public Job { Q_OBJECT Q_DECLARE_PRIVATE(CopyJob) friend class SessionPrivate; public: explicit CopyJob(Session *session); ~CopyJob() override; /** * Sets the destination mailbox. * * If the mailbox does not exist, the server should not create * it automatically and the job should fail. Note, however, * that a conforming server may create the mailbox automatically. * * @param mailBox the (unquoted) name of the mailbox where the * messages should be copied to */ void setMailBox(const QString &mailBox); /** * The destination mailbox */ [[nodiscard]] QString mailBox() const; /** * Sets the messages to be copied * * If sequence numbers are given, isUidBased() should be false. If UIDs * are given, isUidBased() should be true. * * RFC 3501 is unclear as to what should happen if invalid sequence numbers * are passed. If non-existent UIDs are passed, they will be ignored. * * @param set the sequence numbers or UIDs of the messages to be copied */ void setSequenceSet(const ImapSet &set); /** * The messages that will be copied. * * isUidBased() can be used to check whether the ImapSet contains * sequence numbers or UIDs. * * @return the sequence numbers or UIDs of the messages to be copied */ [[nodiscard]] ImapSet sequenceSet() const; /** * Set how the sequence set should be interpreted. * * @param uidBased if @c true the argument to setSequenceSet will be * interpreted as UIDs, if @c false it will be interpreted * as sequence numbers */ void setUidBased(bool uidBased); /** * How to interpret the sequence set. * * @return if @c true the result of sequenceSet() should be * interpreted as UIDs, if @c false it should be interpreted * as sequence numbers */ [[nodiscard]] bool isUidBased() const; /** * The UIDs of the new copies of the messages * * This will be an empty set if no messages have been copied yet * or if the server does not support the UIDPLUS extension. */ [[nodiscard]] ImapSet resultingUids() const; protected: void doStart() override; void handleResponse(const Response &response) override; }; } 070701000000C0000081A400000000000000000000000166FAD7C0000007F7000000000000000000000000000000000000003B00000000kimap-VERSIONgit.20240930T185424~db1f697/src/createjob.cpp/* SPDX-FileCopyrightText: 2009 Andras Mantia <amantia@kde.org> SPDX-License-Identifier: LGPL-2.0-or-later */ #include "createjob.h" #include <KLocalizedString> #include "job_p.h" #include "response_p.h" #include "rfccodecs.h" #include "session_p.h" namespace KIMAP { class CreateJobPrivate : public JobPrivate { public: CreateJobPrivate(Session *session, const QString &name) : JobPrivate(session, name) { } ~CreateJobPrivate() { } QString mailBox; }; } using namespace KIMAP; CreateJob::CreateJob(Session *session) : Job(*new CreateJobPrivate(session, i18n("Create"))) { } CreateJob::~CreateJob() { } void CreateJob::doStart() { Q_D(CreateJob); d->tags << d->sessionInternal()->sendCommand("CREATE", '\"' + KIMAP::encodeImapFolderName(d->mailBox.toUtf8()) + '\"'); } void CreateJob::handleResponse(const Response &response) { Q_D(CreateJob); if (!response.content.isEmpty() && d->tags.contains(response.content.first().toString())) { if (response.content.size() >= 2 && response.content[1].toString() == "NO") { for (auto it = response.responseCode.cbegin(), end = response.responseCode.cend(); it != end; ++it) { // ALREADYEXISTS can be considered a success during CREATE // cf. https://tools.ietf.org/html/rfc5530#section-3 if (it->toString() == "ALREADYEXISTS") { // Code copied from handleErrorReplies: d->tags.removeAll(response.content.first().toString()); if (d->tags.isEmpty()) { // Only emit result when the last command returned emitResult(); } return; } } } } handleErrorReplies(response); } void CreateJob::setMailBox(const QString &mailBox) { Q_D(CreateJob); d->mailBox = mailBox; } QString CreateJob::mailBox() const { Q_D(const CreateJob); return d->mailBox; } #include "moc_createjob.cpp" 070701000000C1000081A400000000000000000000000166FAD7C00000052C000000000000000000000000000000000000003900000000kimap-VERSIONgit.20240930T185424~db1f697/src/createjob.h/* SPDX-FileCopyrightText: 2009 Andras Mantia <amantia@kde.org> SPDX-License-Identifier: LGPL-2.0-or-later */ #pragma once #include "kimap_export.h" #include "job.h" namespace KIMAP { class Session; struct Response; class CreateJobPrivate; /** * Creates a new mailbox * * This job can only be run when the session is in the * authenticated (or selected) state. * * This job will fail if the mailbox already exists. * * If the server supports ACLs, the user must have the * Acl::CreateMailbox permission on the parent * mailbox. Note that what is meant by "parent mailbox" * depends on the server: . and / are typical hierarchy * delimiters. */ class KIMAP_EXPORT CreateJob : public Job { Q_OBJECT Q_DECLARE_PRIVATE(CreateJob) friend class SessionPrivate; public: explicit CreateJob(Session *session); ~CreateJob() override; /** * Set the name of the new mailbox * * @param mailBox an (unquoted) identifier that does not correspond * to an existing mailbox name */ void setMailBox(const QString &mailBox); /** * The name of the mailbox that will be created */ [[nodiscard]] QString mailBox() const; protected: void doStart() override; void handleResponse(const Response &response) override; }; } 070701000000C2000081A400000000000000000000000166FAD7C000000488000000000000000000000000000000000000003E00000000kimap-VERSIONgit.20240930T185424~db1f697/src/deleteacljob.cpp/* SPDX-FileCopyrightText: 2009 Andras Mantia <amantia@kde.org> SPDX-License-Identifier: LGPL-2.0-or-later */ #include "deleteacljob.h" #include <KLocalizedString> #include "acljobbase_p.h" #include "response_p.h" #include "rfccodecs.h" #include "session_p.h" namespace KIMAP { class DeleteAclJobPrivate : public AclJobBasePrivate { public: DeleteAclJobPrivate(Session *session, const QString &name) : AclJobBasePrivate(session, name) { } ~DeleteAclJobPrivate() { } }; } using namespace KIMAP; DeleteAclJob::DeleteAclJob(Session *session) : AclJobBase(session) { Q_D(DeleteAclJob); d->m_name = i18n("DeleteAclJob"); } DeleteAclJob::~DeleteAclJob() { } void DeleteAclJob::doStart() { Q_D(DeleteAclJob); d->tags << d->sessionInternal()->sendCommand("DELETEACL", '\"' + KIMAP::encodeImapFolderName(d->mailBox.toUtf8()) + "\" \"" + d->id); } void DeleteAclJob::setIdentifier(const QByteArray &identifier) { Q_D(DeleteAclJob); d->setIdentifier(identifier); } QByteArray DeleteAclJob::identifier() { Q_D(DeleteAclJob); return d->identifier(); } #include "moc_deleteacljob.cpp" 070701000000C3000081A400000000000000000000000166FAD7C000000487000000000000000000000000000000000000003C00000000kimap-VERSIONgit.20240930T185424~db1f697/src/deleteacljob.h/* SPDX-FileCopyrightText: 2009 Andras Mantia <amantia@kde.org> SPDX-License-Identifier: LGPL-2.0-or-later */ #pragma once #include "kimap_export.h" #include "acljobbase.h" namespace KIMAP { class Session; struct Response; class DeleteAclJobPrivate; /** * Removes an identifier from the ACL of a mailbox. * * This job can only be run when the session is in the * authenticated (or selected) state. * * The user must have the Acl::Admin permission * on the mailbox for this job to succeed (see * MyRightsJob). * * This job requires that the server supports the ACL * capability, defined in * <a href="https://tools.ietf.org/html/rfc4314">RFC 4314</a>. */ class KIMAP_EXPORT DeleteAclJob : public AclJobBase { Q_OBJECT Q_DECLARE_PRIVATE(DeleteAclJob) friend class SessionPrivate; public: explicit DeleteAclJob(Session *session); ~DeleteAclJob() override; /** * Sets the identifier to remove */ void setIdentifier(const QByteArray &identifier); /** * The identifier that will be removed */ [[nodiscard]] QByteArray identifier(); protected: void doStart() override; }; } 070701000000C4000081A400000000000000000000000166FAD7C0000007F3000000000000000000000000000000000000003B00000000kimap-VERSIONgit.20240930T185424~db1f697/src/deletejob.cpp/* SPDX-FileCopyrightText: 2009 Andras Mantia <amantia@kde.org> SPDX-License-Identifier: LGPL-2.0-or-later */ #include "deletejob.h" #include <KLocalizedString> #include "job_p.h" #include "response_p.h" #include "rfccodecs.h" #include "session_p.h" namespace KIMAP { class DeleteJobPrivate : public JobPrivate { public: DeleteJobPrivate(Session *session, const QString &name) : JobPrivate(session, name) { } ~DeleteJobPrivate() { } QString mailBox; }; } using namespace KIMAP; DeleteJob::DeleteJob(Session *session) : Job(*new DeleteJobPrivate(session, i18n("Delete"))) { } DeleteJob::~DeleteJob() { } void DeleteJob::doStart() { Q_D(DeleteJob); d->tags << d->sessionInternal()->sendCommand("DELETE", '\"' + KIMAP::encodeImapFolderName(d->mailBox.toUtf8()) + '\"'); } void DeleteJob::handleResponse(const Response &response) { Q_D(DeleteJob); if (!response.content.isEmpty() && d->tags.contains(response.content.first().toString())) { if (response.content.size() >= 2 && response.content[1].toString() == "NO") { for (auto it = response.responseCode.cbegin(), end = response.responseCode.cend(); it != end; ++it) { // NONEXISTENT can be considered a success during DELETE // cf. https://tools.ietf.org/html/rfc5530#section-3 if (it->toString() == "NONEXISTENT") { // Code copied from handleErrorReplies: d->tags.removeAll(response.content.first().toString()); if (d->tags.isEmpty()) { // Only emit result when the last command returned emitResult(); } return; } } } } handleErrorReplies(response); } void DeleteJob::setMailBox(const QString &mailBox) { Q_D(DeleteJob); d->mailBox = mailBox; } QString DeleteJob::mailBox() const { Q_D(const DeleteJob); return d->mailBox; } #include "moc_deletejob.cpp" 070701000000C5000081A400000000000000000000000166FAD7C000000476000000000000000000000000000000000000003900000000kimap-VERSIONgit.20240930T185424~db1f697/src/deletejob.h/* SPDX-FileCopyrightText: 2009 Andras Mantia <amantia@kde.org> SPDX-License-Identifier: LGPL-2.0-or-later */ #pragma once #include "kimap_export.h" #include "job.h" namespace KIMAP { class Session; class DeleteJobPrivate; /** * Delete a mailbox * * Note that some servers will refuse to delete a * mailbox unless it is empty (ie: all mails have * had their \Deleted flag set, and then the * mailbox has been expunged). * * This job can only be run when the session is in the * authenticated (or selected) state. * * If the server supports ACLs, you will need the * Acl::DeleteMailbox right on the mailbox. */ class KIMAP_EXPORT DeleteJob : public Job { Q_OBJECT Q_DECLARE_PRIVATE(DeleteJob) friend class SessionPrivate; public: explicit DeleteJob(Session *session); ~DeleteJob() override; /** * Set the mailbox to delete. */ void setMailBox(const QString &mailBox); /** * The mailbox that will be deleted. */ [[nodiscard]] QString mailBox() const; protected: void doStart() override; void handleResponse(const Response &response) override; }; } 070701000000C6000081A400000000000000000000000166FAD7C0000005DC000000000000000000000000000000000000003B00000000kimap-VERSIONgit.20240930T185424~db1f697/src/enablejob.cpp/* SPDX-FileCopyrightText: 2020 Daniel Vrátil <dvratil@kde.org> SPDX-License-Identifier: LGPL-2.0-or-later */ #include "enablejob.h" #include <KLocalizedString> #include "job_p.h" #include "kimap_debug.h" #include "response_p.h" #include "session_p.h" namespace KIMAP { class EnableJobPrivate : public JobPrivate { public: using JobPrivate::JobPrivate; QStringList reqCapabilities; QStringList enabledCapabilities; }; } using namespace KIMAP; EnableJob::EnableJob(Session *session) : Job(*new EnableJobPrivate(session, i18n("Enable"))) { } EnableJob::~EnableJob() = default; void EnableJob::setCapabilities(const QStringList &capabilities) { Q_D(EnableJob); d->reqCapabilities = capabilities; } QStringList EnableJob::enabledCapabilities() const { Q_D(const EnableJob); return d->enabledCapabilities; } void EnableJob::doStart() { Q_D(EnableJob); d->tags << d->sessionInternal()->sendCommand("ENABLE", d->reqCapabilities.join(QLatin1Char{' '}).toLatin1()); } void EnableJob::handleResponse(const Response &response) { Q_D(EnableJob); if (handleErrorReplies(response) == NotHandled) { if (response.content.size() >= 2) { for (int i = 2; i < response.content.size(); ++i) { d->enabledCapabilities.push_back(QString::fromLatin1(response.content[i].toString())); } } else { qCDebug(KIMAP_LOG) << response.toString(); } } } #include "moc_enablejob.cpp" 070701000000C7000081A400000000000000000000000166FAD7C0000004F9000000000000000000000000000000000000003900000000kimap-VERSIONgit.20240930T185424~db1f697/src/enablejob.h/* SPDX-FileCopyrightText: 2020 Daniel Vrátil <dvratil@kde.org> SPDX-License-Identifier: LGPL-2.0-or-later */ #pragma once #include "kimap_export.h" #include "job.h" #include <QStringList> namespace KIMAP { class Session; struct Response; class EnableJobPrivate; /** * Job to enable additional IMAP capabilities. * * Requires server to implement the IMAP ENABLE Extension (RFC5161). The * new capabilities to enable will be specified by the user. The user is * responsible for making sure the capabilities are supported by the server. * * The example usecase for this job is to enable support for the QRESYNC * extension (RFC5162) on the server. * * @since 5.16 */ class KIMAP_EXPORT EnableJob : public Job { Q_OBJECT Q_DECLARE_PRIVATE(EnableJob) friend class SessionPrivate; public: explicit EnableJob(Session *session); ~EnableJob() override; /** * List of server capabilities to enable. */ void setCapabilities(const QStringList &capabilities); /** * List of capabilities that were successfully enabled on the server. */ [[nodiscard]] QStringList enabledCapabilities() const; protected: void doStart() override; void handleResponse(const Response &response) override; }; } 070701000000C8000081A400000000000000000000000166FAD7C0000008C1000000000000000000000000000000000000003C00000000kimap-VERSIONgit.20240930T185424~db1f697/src/expungejob.cpp/* SPDX-FileCopyrightText: 2009 Andras Mantia <amantia@kde.org> SPDX-License-Identifier: LGPL-2.0-or-later */ #include "expungejob.h" #include "kimap_debug.h" #include <KLocalizedString> #include "imapset.h" #include "job_p.h" #include "response_p.h" #include "session_p.h" namespace KIMAP { class ExpungeJobPrivate : public JobPrivate { public: ExpungeJobPrivate(Session *session, const QString &name) : JobPrivate(session, name) { } #if 0 QList< int > items; #endif KIMAP::ImapSet vanished; quint64 highestModSeq = 0; }; } using namespace KIMAP; ExpungeJob::ExpungeJob(Session *session) : Job(*new ExpungeJobPrivate(session, i18n("Expunge"))) { } KIMAP::ImapSet ExpungeJob::vanishedMessages() const { Q_D(const ExpungeJob); return d->vanished; } quint64 ExpungeJob::newHighestModSeq() const { Q_D(const ExpungeJob); return d->highestModSeq; } void ExpungeJob::doStart() { Q_D(ExpungeJob); d->tags << d->sessionInternal()->sendCommand("EXPUNGE"); } void ExpungeJob::handleResponse(const Response &response) { Q_D(ExpungeJob); // Must be handler before handleErrorReplies(), so the value is available // before the result is emitted. if (response.responseCode.size() >= 2) { if (response.responseCode[0].toString() == "HIGHESTMODSEQ") { d->highestModSeq = response.responseCode[1].toString().toULongLong(); } } if (handleErrorReplies(response) == NotHandled) { if (response.content.size() >= 3) { if (response.content[1].toString() == "VANISHED") { d->vanished = KIMAP::ImapSet::fromImapSequenceSet(response.content[2].toString()); return; } else if (response.content[2].toString() == "EXPUNGE") { #if 0 QByteArray s = response.content[1].toString(); bool ok = true; int id = s.toInt(&ok); if (ok) { d->items.append(id); } //TODO error handling #endif return; } } qCDebug(KIMAP_LOG) << "Unhandled response: " << response.toString().constData(); } } #include "moc_expungejob.cpp" 070701000000C9000081A400000000000000000000000166FAD7C000000657000000000000000000000000000000000000003A00000000kimap-VERSIONgit.20240930T185424~db1f697/src/expungejob.h/* SPDX-FileCopyrightText: 2009 Andras Mantia <amantia@kde.org> SPDX-License-Identifier: LGPL-2.0-or-later */ #pragma once #include "kimap_export.h" #include "job.h" namespace KIMAP { class Session; struct Response; class ImapSet; class ExpungeJobPrivate; /** * Expunges the deleted messages in the selected mailbox. * * This permanently removes any messages that have the * \Deleted flag set in the selected mailbox. * * This job can only be run when the session is in the * selected state. * * If the server supports ACLs, the user will need the * Acl::Expunge right on the mailbox. */ class KIMAP_EXPORT ExpungeJob : public Job { Q_OBJECT Q_DECLARE_PRIVATE(ExpungeJob) friend class SessionPrivate; public: explicit ExpungeJob(Session *session); ~ExpungeJob() override = default; /** * Returns UIDs of messages that have been expunged. * * This feature is only available when QRESYNC capability (RFC5162) is * supported by the server and have been enabled on the current session. * * @see KIMAP::EnableJob * @since 5.16 */ [[nodiscard]] KIMAP::ImapSet vanishedMessages() const; /** * Returns new highest modification sequence number. * * This feature is only available when QRESYNC capability (RFC5162) is * supported by the server and have been enabled on the current session. * * @see KIMAP::EnableJob * @since 5.16 */ [[nodiscard]] quint64 newHighestModSeq() const; protected: void doStart() override; void handleResponse(const Response &response) override; }; } 070701000000CA000081A400000000000000000000000166FAD7C00000486D000000000000000000000000000000000000003A00000000kimap-VERSIONgit.20240930T185424~db1f697/src/fetchjob.cpp/* SPDX-FileCopyrightText: 2009 Kevin Ottens <ervin@kde.org> SPDX-License-Identifier: LGPL-2.0-or-later */ #include "fetchjob.h" #include "kimap_debug.h" #include <KLocalizedString> #include <QTimer> #include "job_p.h" #include "response_p.h" #include "session_p.h" namespace KIMAP { class FetchJobPrivate : public JobPrivate { public: FetchJobPrivate(FetchJob *job, Session *session, const QString &name) : JobPrivate(session, name) , q(job) { } ~FetchJobPrivate() { } void parseBodyStructure(const QByteArray &structure, int &pos, KMime::Content *content); void parsePart(const QByteArray &structure, int &pos, KMime::Content *content); QByteArray parseString(const QByteArray &structure, int &pos); QByteArray parseSentence(const QByteArray &structure, int &pos); void skipLeadingSpaces(const QByteArray &structure, int &pos); void emitPendings() { if (pendingMsgs.isEmpty()) { return; } Q_EMIT q->messagesAvailable(pendingMsgs); if (!pendingParts.isEmpty()) { Q_EMIT q->partsReceived(selectedMailBox, pendingUids, pendingParts); Q_EMIT q->partsReceived(selectedMailBox, pendingUids, pendingAttributes, pendingParts); } if (!pendingSizes.isEmpty() || !pendingFlags.isEmpty() || !pendingMessages.isEmpty()) { Q_EMIT q->headersReceived(selectedMailBox, pendingUids, pendingSizes, pendingFlags, pendingMessages); Q_EMIT q->headersReceived(selectedMailBox, pendingUids, pendingSizes, pendingAttributes, pendingFlags, pendingMessages); } if (!pendingMessages.isEmpty()) { Q_EMIT q->messagesReceived(selectedMailBox, pendingUids, pendingMessages); Q_EMIT q->messagesReceived(selectedMailBox, pendingUids, pendingAttributes, pendingMessages); } pendingUids.clear(); pendingMessages.clear(); pendingParts.clear(); pendingSizes.clear(); pendingFlags.clear(); pendingAttributes.clear(); pendingMsgs.clear(); } FetchJob *const q; ImapSet set; bool uidBased = false; FetchJob::FetchScope scope; QString selectedMailBox; bool gmailEnabled = false; QTimer emitPendingsTimer; QMap<qint64, MessagePtr> pendingMessages; QMap<qint64, MessageParts> pendingParts; QMap<qint64, MessageFlags> pendingFlags; QMap<qint64, MessageAttribute> pendingAttributes; QMap<qint64, qint64> pendingSizes; QMap<qint64, qint64> pendingUids; QMap<qint64, Message> pendingMsgs; }; } using namespace KIMAP; FetchJob::FetchScope::FetchScope() : mode(FetchScope::Content) , changedSince(0) , qresync(false) { } FetchJob::FetchJob(Session *session) : Job(*new FetchJobPrivate(this, session, i18n("Fetch"))) { Q_D(FetchJob); connect(&d->emitPendingsTimer, &QTimer::timeout, this, [d]() { d->emitPendings(); }); } void FetchJob::setSequenceSet(const ImapSet &set) { Q_D(FetchJob); Q_ASSERT(!set.isEmpty()); d->set = set; } ImapSet FetchJob::sequenceSet() const { Q_D(const FetchJob); return d->set; } void FetchJob::setUidBased(bool uidBased) { Q_D(FetchJob); d->uidBased = uidBased; } bool FetchJob::isUidBased() const { Q_D(const FetchJob); return d->uidBased; } void FetchJob::setScope(const FetchScope &scope) { Q_D(FetchJob); d->scope = scope; } FetchJob::FetchScope FetchJob::scope() const { Q_D(const FetchJob); return d->scope; } bool FetchJob::setGmailExtensionsEnabled() const { Q_D(const FetchJob); return d->gmailEnabled; } void FetchJob::setGmailExtensionsEnabled(bool enabled) { Q_D(FetchJob); d->gmailEnabled = enabled; } QString FetchJob::mailBox() const { Q_D(const FetchJob); return d->selectedMailBox; } void FetchJob::doStart() { Q_D(FetchJob); d->set.optimize(); QByteArray parameters = d->set.toImapSequenceSet() + ' '; Q_ASSERT(!parameters.trimmed().isEmpty()); switch (d->scope.mode) { case FetchScope::Headers: if (d->scope.parts.isEmpty()) { parameters += "(RFC822.SIZE INTERNALDATE BODY.PEEK[HEADER.FIELDS (TO FROM MESSAGE-ID REFERENCES IN-REPLY-TO SUBJECT DATE)] FLAGS UID"; } else { parameters += '('; for (const QByteArray &part : std::as_const(d->scope.parts)) { parameters += "BODY.PEEK[" + part + ".MIME] "; } parameters += "UID"; } break; case FetchScope::Flags: parameters += "(FLAGS UID"; break; case FetchScope::Structure: parameters += "(BODYSTRUCTURE UID"; break; case FetchScope::Content: if (d->scope.parts.isEmpty()) { parameters += "(BODY.PEEK[] UID"; } else { parameters += '('; for (const QByteArray &part : std::as_const(d->scope.parts)) { parameters += "BODY.PEEK[" + part + "] "; } parameters += "UID"; } break; case FetchScope::Full: parameters += "(RFC822.SIZE INTERNALDATE BODY.PEEK[] FLAGS UID"; break; case FetchScope::HeaderAndContent: if (d->scope.parts.isEmpty()) { parameters += "(BODY.PEEK[] FLAGS UID"; } else { parameters += "(BODY.PEEK[HEADER.FIELDS (TO FROM MESSAGE-ID REFERENCES IN-REPLY-TO SUBJECT DATE)]"; for (const QByteArray &part : std::as_const(d->scope.parts)) { parameters += " BODY.PEEK[" + part + ".MIME] BODY.PEEK[" + part + "]"; // krazy:exclude=doublequote_chars } parameters += " FLAGS UID"; } break; case FetchScope::FullHeaders: parameters += "(RFC822.SIZE INTERNALDATE BODY.PEEK[HEADER] FLAGS UID"; break; } if (d->gmailEnabled) { parameters += " X-GM-LABELS X-GM-MSGID X-GM-THRID"; } parameters += ")"; if (d->scope.changedSince > 0) { parameters += " (CHANGEDSINCE " + QByteArray::number(d->scope.changedSince); if (d->scope.qresync) { parameters += " VANISHED"; } parameters += ")"; } QByteArray command = "FETCH"; if (d->uidBased) { command = "UID " + command; } d->emitPendingsTimer.start(100); d->selectedMailBox = d->m_session->selectedMailBox(); d->tags << d->sessionInternal()->sendCommand(command, parameters); } void FetchJob::handleResponse(const Response &response) { Q_D(FetchJob); // We can predict it'll be handled by handleErrorReplies() so stop // the timer now so that result() will really be the last emitted signal. if (!response.content.isEmpty() && d->tags.size() == 1 && d->tags.contains(response.content.first().toString())) { d->emitPendingsTimer.stop(); d->emitPendings(); } if (handleErrorReplies(response) == NotHandled) { if (response.content.size() == 4 && response.content[1].toString() == "VANISHED") { const auto vanishedSet = ImapSet::fromImapSequenceSet(response.content[3].toString()); Q_EMIT messagesVanished(vanishedSet); } else if (response.content.size() == 4 && response.content[2].toString() == "FETCH" && response.content[3].type() == Response::Part::List) { const qint64 id = response.content[1].toString().toLongLong(); const QList<QByteArray> content = response.content[3].toList(); Message msg; MessagePtr message(new KMime::Message); bool shouldParseMessage = false; MessageParts parts; for (QList<QByteArray>::ConstIterator it = content.constBegin(); it != content.constEnd(); ++it) { QByteArray str = *it; ++it; if (it == content.constEnd()) { // Uh oh, message was truncated? qCWarning(KIMAP_LOG) << "FETCH reply got truncated, skipping."; break; } if (str == "UID") { d->pendingUids[id] = msg.uid = it->toLongLong(); } else if (str == "RFC822.SIZE") { d->pendingSizes[id] = msg.size = it->toLongLong(); } else if (str == "INTERNALDATE") { message->date()->setDateTime(QDateTime::fromString(QLatin1StringView(*it), Qt::RFC2822Date)); } else if (str == "FLAGS") { if ((*it).startsWith('(') && (*it).endsWith(')')) { QByteArray str = *it; str.chop(1); str.remove(0, 1); const auto flags = str.split(' '); d->pendingFlags[id] = flags; msg.flags = flags; } else { d->pendingFlags[id] << *it; msg.flags << *it; } } else if (str == "X-GM-LABELS") { d->pendingAttributes.insert(id, {"X-GM-LABELS", *it}); msg.attributes.insert("X-GM-LABELS", *it); } else if (str == "X-GM-THRID") { d->pendingAttributes.insert(id, {"X-GM-THRID", *it}); msg.attributes.insert("X-GM-THRID", *it); } else if (str == "X-GM-MSGID") { d->pendingAttributes.insert(id, {"X-GM-MSGID", *it}); msg.attributes.insert("X-GM-MSGID", *it); } else if (str == "BODYSTRUCTURE") { int pos = 0; d->parseBodyStructure(*it, pos, message.data()); message->assemble(); d->pendingMessages[id] = message; msg.message = message; } else if (str.startsWith("BODY[")) { // krazy:exclude=strings if (!str.endsWith(']')) { // BODY[ ... ] might have been split, skip until we find the ] while (!(*it).endsWith(']')) { ++it; } ++it; } int index; if ((index = str.indexOf("HEADER")) > 0 || (index = str.indexOf("MIME")) > 0) { // headers if (str[index - 1] == '.') { QByteArray partId = str.mid(5, index - 6); if (!parts.contains(partId)) { parts[partId] = ContentPtr(new KMime::Content); } parts[partId]->setHead(*it); parts[partId]->parse(); d->pendingParts[id] = parts; msg.parts = parts; } else { message->setHead(*it); shouldParseMessage = true; } } else { // full payload if (str == "BODY[]") { message->setContent(KMime::CRLFtoLF(*it)); shouldParseMessage = true; d->pendingMessages[id] = message; msg.message = message; } else { QByteArray partId = str.mid(5, str.size() - 6); if (!parts.contains(partId)) { parts[partId] = ContentPtr(new KMime::Content); } parts[partId]->setBody(*it); parts[partId]->parse(); d->pendingParts[id] = parts; msg.parts = parts; } } } } if (shouldParseMessage) { message->parse(); } // For the headers mode the message is built in several // steps, hence why we wait it to be done until putting it // in the pending queue. if (d->scope.mode == FetchScope::Headers || d->scope.mode == FetchScope::HeaderAndContent || d->scope.mode == FetchScope::FullHeaders) { d->pendingMessages[id] = message; msg.message = message; } d->pendingMsgs[id] = msg; } } } void FetchJobPrivate::parseBodyStructure(const QByteArray &structure, int &pos, KMime::Content *content) { skipLeadingSpaces(structure, pos); if (structure[pos] != '(') { return; } pos++; if (structure[pos] != '(') { // simple part pos--; parsePart(structure, pos, content); } else { // multi part content->contentType()->setMimeType("MULTIPART/MIXED"); while (pos < structure.size() && structure[pos] == '(') { auto child = new KMime::Content; content->appendContent(child); parseBodyStructure(structure, pos, child); child->assemble(); } QByteArray subType = parseString(structure, pos); content->contentType()->setMimeType("MULTIPART/" + subType); QByteArray parameters = parseSentence(structure, pos); // FIXME: Read the charset if (parameters.contains("BOUNDARY")) { content->contentType()->setBoundary(parameters.remove(0, parameters.indexOf("BOUNDARY") + 11).split('\"')[0]); } QByteArray disposition = parseSentence(structure, pos); if (disposition.contains("INLINE")) { content->contentDisposition()->setDisposition(KMime::Headers::CDinline); } else if (disposition.contains("ATTACHMENT")) { content->contentDisposition()->setDisposition(KMime::Headers::CDattachment); } parseSentence(structure, pos); // Ditch the body language } // Consume what's left while (pos < structure.size() && structure[pos] != ')') { skipLeadingSpaces(structure, pos); parseSentence(structure, pos); skipLeadingSpaces(structure, pos); } pos++; } void FetchJobPrivate::parsePart(const QByteArray &structure, int &pos, KMime::Content *content) { if (structure[pos] != '(') { return; } pos++; QByteArray mainType = parseString(structure, pos); QByteArray subType = parseString(structure, pos); content->contentType()->setMimeType(mainType + '/' + subType); parseSentence(structure, pos); // Ditch the parameters... FIXME: Read it to get charset and name parseString(structure, pos); // ... and the id content->contentDescription()->from7BitString(parseString(structure, pos)); parseString(structure, pos); // Ditch the encoding too parseString(structure, pos); // ... and the size parseString(structure, pos); // ... and the line count QByteArray disposition = parseSentence(structure, pos); if (disposition.contains("INLINE")) { content->contentDisposition()->setDisposition(KMime::Headers::CDinline); } else if (disposition.contains("ATTACHMENT")) { content->contentDisposition()->setDisposition(KMime::Headers::CDattachment); } if ((content->contentDisposition()->disposition() == KMime::Headers::CDattachment || content->contentDisposition()->disposition() == KMime::Headers::CDinline) && disposition.contains("FILENAME")) { QByteArray filename = disposition.remove(0, disposition.indexOf("FILENAME") + 11).split('\"')[0]; content->contentDisposition()->setFilename(QLatin1StringView(filename)); } // Consume what's left while (pos < structure.size() && structure[pos] != ')') { skipLeadingSpaces(structure, pos); parseSentence(structure, pos); skipLeadingSpaces(structure, pos); } } QByteArray FetchJobPrivate::parseSentence(const QByteArray &structure, int &pos) { QByteArray result; int stack = 0; skipLeadingSpaces(structure, pos); if (structure[pos] != '(') { return parseString(structure, pos); } int start = pos; do { switch (structure[pos]) { case '(': pos++; stack++; break; case ')': pos++; stack--; break; case '[': pos++; stack++; break; case ']': pos++; stack--; break; default: skipLeadingSpaces(structure, pos); parseString(structure, pos); skipLeadingSpaces(structure, pos); break; } } while (pos < structure.size() && stack != 0); result = structure.mid(start, pos - start); return result; } QByteArray FetchJobPrivate::parseString(const QByteArray &structure, int &pos) { QByteArray result; skipLeadingSpaces(structure, pos); int start = pos; bool foundSlash = false; // quoted string if (structure[pos] == '"') { pos++; for (;;) { if (structure[pos] == '\\') { pos += 2; foundSlash = true; continue; } if (structure[pos] == '"') { result = structure.mid(start + 1, pos - start - 1); pos++; break; } pos++; } } else { // unquoted string for (;;) { if (structure[pos] == ' ' || structure[pos] == '(' || structure[pos] == ')' || structure[pos] == '[' || structure[pos] == ']' || structure[pos] == '\n' || structure[pos] == '\r' || structure[pos] == '"') { break; } if (structure[pos] == '\\') { foundSlash = true; } pos++; } result = structure.mid(start, pos - start); // transform unquoted NIL if (result == "NIL") { result.clear(); } } // simplify slashes if (foundSlash) { while (result.contains("\\\"")) { result.replace("\\\"", "\""); } while (result.contains("\\\\")) { result.replace("\\\\", "\\"); } } return result; } void FetchJobPrivate::skipLeadingSpaces(const QByteArray &structure, int &pos) { while (pos < structure.size() && structure[pos] == ' ') { pos++; } } #include "moc_fetchjob.cpp" 070701000000CB000081A400000000000000000000000166FAD7C000004397000000000000000000000000000000000000003800000000kimap-VERSIONgit.20240930T185424~db1f697/src/fetchjob.h/* SPDX-FileCopyrightText: 2009 Kevin Ottens <ervin@kde.org> SPDX-License-Identifier: LGPL-2.0-or-later */ #pragma once #include "kimap_export.h" #include "imapset.h" #include "job.h" #include <KMime/Content> #include <KMime/Message> #include <tuple> namespace KIMAP { class Session; struct Response; class FetchJobPrivate; using ContentPtr = QSharedPointer<KMime::Content>; using MessageParts = QMap<QByteArray, ContentPtr>; using MessagePtr = QSharedPointer<KMime::Message>; using MessageFlags = QList<QByteArray>; using MessageAttribute = QPair<QByteArray, QVariant>; struct Message { inline bool operator==(const Message &other) const { return std::tie(uid, size, flags, attributes, parts, message) == std::tie(other.uid, other.size, other.flags, other.attributes, other.parts, other.message); } qint64 uid = -1; qint64 size = 0; MessageFlags flags; QMap<QByteArray, QVariant> attributes; MessageParts parts; MessagePtr message; }; /** * Fetch message data from the server * * All data is returned using the signals, so you need to connect to * the relevant signal (or all of them) before starting the job. * * This job will always use BODY.PEEK rather than BODY to fetch message * content, so it will not set the \Seen flag. * * This job can only be run when the session is in the selected state. */ class KIMAP_EXPORT FetchJob : public Job { Q_OBJECT Q_DECLARE_PRIVATE(FetchJob) friend class SessionPrivate; public: /** * Used to indicate what message data should be fetched. * * This doesn't provide the same fine-grained control over * what is fetched that the IMAP FETCH command normally * does, but the common cases are catered for. */ class KIMAP_EXPORT FetchScope { public: FetchScope(); /** * Used to indicate what part of the message should be fetched. */ enum Mode { /** * Fetch RFC-2822 or MIME message headers. * * To fetch MIME headers for a MIME part, populate the @p parts field. * * If the RFC-2822 headers are requested (so @p parts is empty), the * returned information is: * - To, From, Message-id, References In-Reply-To, Subject and Date headers * - The message size (in octets) * - The internal date of the message * - The message flags * - The message UID */ Headers, /** * Fetch the message flags (the UID is also fetched) */ Flags, /** * Fetch the MIME message body structure (the UID is also fetched) */ Structure, /** * Fetch the message content (the UID is also fetched) * * To fetch only certain MIME parts (see Structure), populate the * @p parts field. */ Content, /** * Fetch the complete message. */ Full, /** * Fetch the message MIME headers and the content of parts specified in the @p parts * field. * * If @p parts is empty, this mode will return the full message, just like * FetchScope::Content * * Use case: * -# Start a FetchJob with the FetchScope::Structure mode to retrieve the structure * of the message. * -# Parse the structure to identify the parts that are interesting (ie: probably * everything but attachments). * -# Start another FetchJob with FetchScope::HeaderAndContent to fetch those parts. * -# At the request of the user, you can repeat the step above to fetch the attachments. * * @since 4.7 */ HeaderAndContent, /** * Fetch message size (in octets), internal date of the message, flags, UID * and all RFC822 headers. * * The @p parts field is ignored when using this scope * * @since 4.12 */ FullHeaders }; /** * Specify which message parts to operate on. * * This refers to multipart-MIME message parts or MIME-IMB encapsulated * message parts. * * Note that this is ignored unless @p mode is Headers or Content. * * If @p mode is Headers, this sets the parts to get the MIME headers * for. If this list is empty, the headers for the whole message * (the RFC-2822 headers) are fetched. * * If @p mode is Content, this sets the parts to fetch. Parts are * fetched wholesale. If this list is empty, the whole message body * is fetched (all MIME parts together). */ QList<QByteArray> parts; /** * Specify what message data should be fetched. */ Mode mode = Content; /** * Specify to fetch only items with mod-sequence higher then @p changedSince. * * The server must have CONDSTORE capability (RFC4551). * * Default value is 0 (ignored). * * @since 4.12 */ quint64 changedSince = 0; /** * Specify whether QRESYNC is supported and should be used. * * When enabled, the @p changedSince parameter must be specified as * well. The server will then also return list of messages that have * been deleted from the mailbox since the specified modification sequence. * * The server must have QRESYNC capability (RFC5162) and it must have * explicitly been enabled via ENABLE command (see @EnableJob). * * QRESYNC can only be used in UID FETCH (@see setUidBased()) * * @since 5.16 */ bool qresync = false; }; explicit FetchJob(Session *session); ~FetchJob() override = default; /** * Set which messages to fetch data for. * * If sequence numbers are given, isUidBased() should be false. If UIDs * are given, isUidBased() should be true. * * @param set the sequence numbers or UIDs of the messages to fetch data for */ void setSequenceSet(const ImapSet &set); /** * The messages that will be fetched. */ [[nodiscard]] ImapSet sequenceSet() const; /** * Set how the sequence set should be interpreted. * * @param uidBased if @c true the argument to setSequenceSet will be * interpreted as UIDs, if @c false it will be interpreted * as sequence numbers */ void setUidBased(bool uidBased); /** * How to interpret the sequence set. * * @return if @c true the result of sequenceSet() should be * interpreted as UIDs, if @c false it should be interpreted * as sequence numbers */ [[nodiscard]] bool isUidBased() const; /** * Sets what data should be fetched. * * The default scope is FetchScope::Content (all content parts). * * @param scope a FetchScope object describing what data * should be fetched */ void setScope(const FetchScope &scope); /** * Specifies what data will be fetched. */ [[nodiscard]] FetchScope scope() const; // TODO: KF6: Move this to FetchScope /** * Enables retrieving of Gmail-specific extensions * * The FETCH response will contain X-GM-MSGID, X-GM-THRID and X-GM-LABELS * * Do NOT enable this, unless talking to Gmail servers, otherwise the * request may fail. * * @param enabled Whether the Gmail support should be enabled * @since 4.14 */ void setGmailExtensionsEnabled(bool enabled); /** * Returns whether Gmail support is enabled * * @since 4.14 * @see setGmailExtensionsEnabled() */ [[nodiscard]] bool setGmailExtensionsEnabled() const; /** * Returns the name of the mailbox the fetch job is executed on. * * Can only be accessed after the job is actually started, before that * returns an empty string. * * @since 5.6 */ [[nodiscard]] QString mailBox() const; Q_SIGNALS: /** * Provides header and message results. * * This signal will be emitted if the requested scope mode * was FetchScope::Full, FetchScope::Flags or * FetchScope::Headers with no parts specified * * This signal may be emitted any number of times before * the result() signal is emitted. The result() signal will * only be emitted once all results have been reported via * one of the signals. * * Note that, depending on the scope, some of the parameters * of this signal may be empty maps. * * @param mailBox the name of the mailbox the fetch job was * executed on * @param uids a map from message sequence numbers to message UIDs; * this will always be populated * @param sizes a map from message sequence numbers to message sizes * (sizes are in octets and refer to the transfer encoding of * the message); populated if the scope is FetchScope::Full or * FetchScope::Headers * @param flags a map from message sequence numbers to message flags; * populated if the scope is FetchScope::Flags, FetchScope::Full * of FetchScope::Headers * @param messages a map from message sequence numbers to message contents (including * headers); populated if the scope is FetchScope::Full, * FetchScope::Headers or FetchScope::Structure * * @deprecated Use messagesAvailable() instead. */ KIMAP_DEPRECATED void headersReceived(const QString &mailBox, const QMap<qint64, qint64> &uids, const QMap<qint64, qint64> &sizes, const QMap<qint64, KIMAP::MessageFlags> &flags, const QMap<qint64, KIMAP::MessagePtr> &messages); /** * An overloaded version of headersReceived(), which includes additional attribute * specified in the FETCH response, but that don't belong to actual content of the * message. * * @param mailBox the name of the mailbox the fetch job was * executed on * @param uids a map from message sequence numbers to message UIDs; * this will always be populated * @param attrs a map from message sequence numbers to a pair of attribute * name and value * @param sizes a map from message sequence numbers to message sizes * (sizes are in octets and refer to the transfer encoding of * the message); populated if the scope is FetchScope::Full or * FetchScope::Headers * @param flags a map from message sequence numbers to message flags; * populated if the scope is FetchScope::Flags, FetchScope::Full * of FetchScope::Headers * @param messages a map from message sequence numbers to message contents (including * headers); populated if the scope is FetchScope::Full, * FetchScope::Headers or FetchScope::Structure * * @overload * @since 4.14 * @deprecated Use messagesAvailable() instead. */ KIMAP_DEPRECATED void headersReceived(const QString &mailBox, const QMap<qint64, qint64> &uids, const QMap<qint64, qint64> &sizes, const QMap<qint64, KIMAP::MessageAttribute> &attrs, const QMap<qint64, KIMAP::MessageFlags> &flags, const QMap<qint64, KIMAP::MessagePtr> &messages); /** * Provides header and message results. * * This signal will be emitted if the requested scope mode * was FetchScope::Content or FetchScope::Headers with no * parts specified or FetchScope::Structure. * * This signal may be emitted any number of times before * the result() signal is emitted. The result() signal will * only be emitted once all results have been reported via * one of the signals. * * * @param mailBox the name of the mailbox the fetch job was * executed on * @param uids a map from message sequence numbers to message UIDs * @param messages a map from message sequence numbers to message contents * * @deprecated Use messagesAvailable() instead. */ KIMAP_DEPRECATED void messagesReceived(const QString &mailBox, const QMap<qint64, qint64> &uids, const QMap<qint64, KIMAP::MessagePtr> &messages); /** * An overloaded version of messagesReceived(), which includes additional attribute * specified in the FETCH response, but that don't belong to actual content of the * message. * * @param mailBox the name of the mailbox the fetch job was * executed on * @param uids a map from message sequence numbers to message UIDs * @param attrs a map from message sequence numbers to pair of attribute * name and it's value * @param messages a map from message sequence numbers to message contents * * @overload * @since 4.14 * * @deprecated Use messagesAvailable() instead. */ KIMAP_DEPRECATED void messagesReceived(const QString &mailBox, const QMap<qint64, qint64> &uids, const QMap<qint64, KIMAP::MessageAttribute> &attrs, const QMap<qint64, KIMAP::MessagePtr> &messages); /** * Provides header and message results. * * This signal will be emitted if the requested scope mode * was FetchScope::Content or FetchScope::Headers with * specified parts. * * This signal may be emitted any number of times before * the result() signal is emitted. The result() signal will * only be emitted once all results have been reported via * one of the signals. * * @param mailBox the name of the mailbox the fetch job was * executed on * @param uids a map from message sequence numbers to message UIDs * @param parts a map from message sequence numbers to message part collections * * @deprecated Use messagesAvailable() instead. */ KIMAP_DEPRECATED void partsReceived(const QString &mailBox, const QMap<qint64, qint64> &uids, const QMap<qint64, KIMAP::MessageParts> &parts); /** * An overloaded version of partsReceived(), which includes additional attribute * specified in the FETCH response, but that don't belong to actual content of the * message. * * @param mailBox the name of the mailbox the fetch job was * executed on * @param uids a map from message sequence numbers to message UIDs * @param attrs a map from message sequence numbers to pair of attribute * @param parts a map from message sequence numbers to message part collections * * @overload * @since 4.14 * * @deprecated Use messagesAvailable() instead. */ KIMAP_DEPRECATED void partsReceived(const QString &mailBox, const QMap<qint64, qint64> &uids, const QMap<qint64, KIMAP::MessageAttribute> &attrs, const QMap<qint64, KIMAP::MessageParts> &parts); /** * Provides received messages. * * This signal is emitted when some data are received. The signal can be * emitted multiple times as the messages are being received. * * @param messages A map from message sequence number to message. Not all * fields may be populated, depending on the fetch scope. * * @since 5.6 */ void messagesAvailable(const QMap<qint64, KIMAP::Message> &messages); /** * Provides vanished messages. * * This signal is emitted when QRESYNC capability (RFC5162) is available and has * bee enabled on the server, and @p FetchScope::qresync has been set to @p true. * It contains a list of messages that have vanished from the mailbox since the * last modification sequence specified in @p FetchScope::changedSince. * * @param uids UIDs of messages that have been removed from the mailbox since * the specified modification sequence. * * @since 5.16 */ void messagesVanished(const KIMAP::ImapSet &uids); protected: void doStart() override; void handleResponse(const Response &response) override; private: Q_PRIVATE_SLOT(d_func(), void emitPendings()) }; } 070701000000CC000081A400000000000000000000000166FAD7C0000008F6000000000000000000000000000000000000003B00000000kimap-VERSIONgit.20240930T185424~db1f697/src/getacljob.cpp/* SPDX-FileCopyrightText: 2009 Andras Mantia <amantia@kde.org> SPDX-License-Identifier: LGPL-2.0-or-later */ #include "getacljob.h" #include "kimap_debug.h" #include <KLocalizedString> #include "acljobbase_p.h" #include "response_p.h" #include "rfccodecs.h" #include "session_p.h" namespace KIMAP { class GetAclJobPrivate : public AclJobBasePrivate { public: GetAclJobPrivate(Session *session, const QString &name) : AclJobBasePrivate(session, name) { } ~GetAclJobPrivate() { } QMap<QByteArray, Acl::Rights> userRights; }; } using namespace KIMAP; GetAclJob::GetAclJob(Session *session) : AclJobBase(*new GetAclJobPrivate(session, i18n("GetAcl"))) { } GetAclJob::~GetAclJob() { } void GetAclJob::doStart() { Q_D(GetAclJob); d->tags << d->sessionInternal()->sendCommand("GETACL", '\"' + KIMAP::encodeImapFolderName(d->mailBox.toUtf8()) + '\"'); } void GetAclJob::handleResponse(const Response &response) { Q_D(GetAclJob); // qCDebug(KIMAP_LOG) << response.toString(); if (handleErrorReplies(response) == NotHandled) { if (response.content.size() >= 4 && response.content[1].toString() == "ACL") { int i = 3; while (i < response.content.size() - 1) { QByteArray id = response.content[i].toString(); QByteArray rights = response.content[i + 1].toString(); d->userRights[id] = Acl::rightsFromString(rights); i += 2; } } } } QList<QByteArray> GetAclJob::identifiers() const { Q_D(const GetAclJob); return d->userRights.keys(); } bool GetAclJob::hasRightEnabled(const QByteArray &identifier, Acl::Right right) const { Q_D(const GetAclJob); if (d->userRights.contains(identifier)) { Acl::Rights rights = d->userRights[identifier]; return rights & right; } return false; } Acl::Rights GetAclJob::rights(const QByteArray &identifier) const { Q_D(const GetAclJob); Acl::Rights result; if (d->userRights.contains(identifier)) { result = d->userRights[identifier]; } return result; } QMap<QByteArray, Acl::Rights> GetAclJob::allRights() const { Q_D(const GetAclJob); return d->userRights; } #include "moc_getacljob.cpp" 070701000000CD000081A400000000000000000000000166FAD7C000000E5B000000000000000000000000000000000000003900000000kimap-VERSIONgit.20240930T185424~db1f697/src/getacljob.h/* SPDX-FileCopyrightText: 2009 Andras Mantia <amantia@kde.org> SPDX-License-Identifier: LGPL-2.0-or-later */ #pragma once #include "kimap_export.h" #include "acljobbase.h" namespace KIMAP { class Session; struct Response; class GetAclJobPrivate; /** * Gets the ACL for a mailbox * * This job can only be run when the session is in the * authenticated (or selected) state. * * The user must have the Acl::Admin permission * on the mailbox for this job to succeed (see * MyRightsJob). * * This job requires that the server supports the ACL * capability, defined in * <a href="https://tools.ietf.org/html/rfc4314">RFC 4314</a>. * * The meaning of identifiers depends on the server implementation, * with the following restrictions: * * - "anyone" means any authenticated user, including anonymous * - an identifier starting with a minus sign ('-') indicates * "negative rights": rights that should be taken away from * matching users * * Other than the above restrictions, ACL identifiers are usually * IMAP usernames, but could potentially be group names as well. * * Note that negative rights override positive rights: if * "fred" and "-fred" are both assigned the 'w' right, the * user "fred" will not have the 'w' right. */ class KIMAP_EXPORT GetAclJob : public AclJobBase { Q_OBJECT Q_DECLARE_PRIVATE(GetAclJob) friend class SessionPrivate; public: explicit GetAclJob(Session *session); ~GetAclJob() override; /** * The identifiers present in the ACL. * * This method will return an empty list if the job has * not yet been run. * * See the GetAclJob documentation for an explanation of * identifiers; in particular, identifiers starting with * '-' specify negative rights. */ [[nodiscard]] QList<QByteArray> identifiers() const; /** * Check whether an identifier has a given right set * * The result of this method is undefined if the job has * not yet completed. * * See the GetAclJob documentation for an explanation of * identifiers; in particular, identifiers starting with * '-' specify negative rights. * * Note that this will not tell you whether the net result * of all the ACL entries means that a given user has * a certain right. * * @param identifier the identifier to check the rights for * @param right the right to check for */ [[nodiscard]] bool hasRightEnabled(const QByteArray &identifier, Acl::Right right) const; /** * Get the rights associated with an identifier. * * The result of this method is undefined if the job has * not yet completed. * * See the GetAclJob documentation for an explanation of * identifiers; in particular, identifiers starting with * '-' specify negative rights. * * Note that this will not tell you the rights that a * given user will have once all the ACL entries have * been taken into account. * * @param identifier the identifier to check the rights for */ [[nodiscard]] Acl::Rights rights(const QByteArray &identifier) const; /** * Gets the full access control list. * * The result of this method is undefined if the job has * not yet completed. * * See the GetAclJob documentation for an explanation of * identifiers; in particular, identifiers starting with * '-' specify negative rights. */ [[nodiscard]] QMap<QByteArray, Acl::Rights> allRights() const; protected: void doStart() override; void handleResponse(const Response &response) override; }; } 070701000000CE000081A400000000000000000000000166FAD7C00000208E000000000000000000000000000000000000004000000000kimap-VERSIONgit.20240930T185424~db1f697/src/getmetadatajob.cpp/* SPDX-FileCopyrightText: 2009 Andras Mantia <amantia@kde.org> SPDX-License-Identifier: LGPL-2.0-or-later */ #include "getmetadatajob.h" #include "kimap_debug.h" #include <KLocalizedString> #include "metadatajobbase_p.h" #include "response_p.h" #include "rfccodecs.h" #include "session_p.h" namespace KIMAP { class GetMetaDataJobPrivate : public MetaDataJobBasePrivate { public: GetMetaDataJobPrivate(Session *session, const QString &name) : MetaDataJobBasePrivate(session, name) , depth("0") { } ~GetMetaDataJobPrivate() { } qint64 maxSize = -1; QByteArray depth; QSet<QByteArray> entries; QSet<QByteArray> attributes; QMap<QString, QMap<QByteArray, QMap<QByteArray, QByteArray>>> metadata; // ^ mailbox ^ entry ^attribute ^ value }; } using namespace KIMAP; GetMetaDataJob::GetMetaDataJob(Session *session) : MetaDataJobBase(*new GetMetaDataJobPrivate(session, i18n("GetMetaData"))) { } GetMetaDataJob::~GetMetaDataJob() { } static QList<QByteArray> sort(const QSet<QByteArray> &set) { QList<QByteArray> sortedEntries = set.values(); std::sort(sortedEntries.begin(), sortedEntries.end()); return sortedEntries; } void GetMetaDataJob::doStart() { Q_D(GetMetaDataJob); QByteArray parameters; parameters = '\"' + KIMAP::encodeImapFolderName(d->mailBox.toUtf8()) + "\" "; QByteArray command = "GETMETADATA"; if (d->serverCapability == Annotatemore) { d->m_name = i18n("GetAnnotation"); command = "GETANNOTATION"; if (d->entries.size() > 1) { parameters += '('; } const auto sortedEntries = sort(d->entries); for (const QByteArray &entry : sortedEntries) { parameters += '\"' + entry + "\" "; } if (d->entries.size() > 1) { parameters[parameters.length() - 1] = ')'; parameters += ' '; } if (d->attributes.size() > 1) { parameters += '('; } const auto sortedAttributes = sort(d->attributes); for (const QByteArray &attribute : sortedAttributes) { parameters += '\"' + attribute + "\" "; } if (d->attributes.size() > 1) { parameters[parameters.length() - 1] = ')'; } else { parameters.chop(1); } } else { QByteArray options; if (d->depth != "0") { options = "DEPTH " + d->depth; } if (d->maxSize != -1) { if (!options.isEmpty()) { options += ' '; } options += "MAXSIZE " + QByteArray::number(d->maxSize); } if (!options.isEmpty()) { parameters = "(" + options + ") " + parameters; } if (d->entries.size() >= 1) { parameters += '('; const auto sortedEntries = sort(d->entries); for (const QByteArray &entry : sortedEntries) { parameters += entry + " "; } parameters[parameters.length() - 1] = ')'; } else { parameters.chop(1); } } d->tags << d->sessionInternal()->sendCommand(command, parameters); // qCDebug(KIMAP_LOG) << "SENT: " << command << " " << parameters; } void GetMetaDataJob::handleResponse(const Response &response) { Q_D(GetMetaDataJob); // qCDebug(KIMAP_LOG) << "GOT: " << response.toString(); // TODO: handle NO error messages having [METADATA MAXSIZE NNN], [METADATA TOOMANY], [METADATA NOPRIVATE] (see rfc5464) // or [ANNOTATEMORE TOOBIG], [ANNOTATEMORE TOOMANY] respectively if (handleErrorReplies(response) == NotHandled) { if (response.content.size() >= 4) { if (d->serverCapability == Annotatemore && response.content[1].toString() == "ANNOTATION") { QString mailBox = QString::fromUtf8(KIMAP::decodeImapFolderName(response.content[2].toString())); int i = 3; while (i < response.content.size() - 1) { QByteArray entry = response.content[i].toString(); QList<QByteArray> attributes = response.content[i + 1].toList(); int j = 0; while (j < attributes.size() - 1) { d->metadata[mailBox][entry][attributes[j]] = attributes[j + 1]; j += 2; } i += 2; } } else if (d->serverCapability == Metadata && response.content[1].toString() == "METADATA") { QString mailBox = QString::fromUtf8(KIMAP::decodeImapFolderName(response.content[2].toString())); const QList<QByteArray> &entries = response.content[3].toList(); int i = 0; while (i < entries.size() - 1) { const QByteArray &value = entries[i + 1]; QByteArray &targetValue = d->metadata[mailBox][entries[i]][""]; if (value != "NIL") { // This just indicates no value targetValue = value; } i += 2; } } } } } void GetMetaDataJob::addEntry(const QByteArray &entry, const QByteArray &attribute) { Q_D(GetMetaDataJob); if (d->serverCapability == Annotatemore && attribute.isNull()) { qCWarning(KIMAP_LOG) << "In ANNOTATEMORE mode an attribute must be specified with addEntry!"; } d->entries.insert(entry); d->attributes.insert(attribute); } void GetMetaDataJob::addRequestedEntry(const QByteArray &entry) { Q_D(GetMetaDataJob); d->entries.insert(d->removePrefix(entry)); d->attributes.insert(d->getAttribute(entry)); } void GetMetaDataJob::setMaximumSize(qint64 size) { Q_D(GetMetaDataJob); d->maxSize = size; } void GetMetaDataJob::setDepth(Depth depth) { Q_D(GetMetaDataJob); switch (depth) { case OneLevel: d->depth = "1"; // krazy:exclude=doublequote_chars break; case AllLevels: d->depth = "infinity"; break; default: d->depth = "0"; // krazy:exclude=doublequote_chars } } QByteArray GetMetaDataJob::metaData(const QString &mailBox, const QByteArray &entry, const QByteArray &attribute) const { Q_D(const GetMetaDataJob); QByteArray attr = attribute; if (d->serverCapability == Metadata) { attr = ""; } QByteArray result; if (d->metadata.contains(mailBox)) { if (d->metadata[mailBox].contains(entry)) { result = d->metadata[mailBox][entry].value(attr); } } return result; } QByteArray GetMetaDataJob::metaData(const QByteArray &entry) const { qCDebug(KIMAP_LOG) << entry; Q_D(const GetMetaDataJob); return d->metadata.value(d->mailBox).value(d->removePrefix(entry)).value(d->getAttribute(entry)); } QMap<QByteArray, QMap<QByteArray, QByteArray>> GetMetaDataJob::allMetaData(const QString &mailBox) const { Q_D(const GetMetaDataJob); return d->metadata[mailBox]; } QMap<QByteArray, QByteArray> GetMetaDataJob::allMetaData() const { Q_D(const GetMetaDataJob); return allMetaDataForMailbox(d->mailBox); } QMap<QByteArray, QByteArray> GetMetaDataJob::allMetaDataForMailbox(const QString &mailbox) const { Q_D(const GetMetaDataJob); const QMap<QByteArray, QMap<QByteArray, QByteArray>> &entries = d->metadata[mailbox]; QMap<QByteArray, QByteArray> map; const auto entriesKeys = entries.keys(); for (const QByteArray &entry : entriesKeys) { const QMap<QByteArray, QByteArray> &values = entries[entry]; const auto valuesKeys = values.keys(); for (const QByteArray &attribute : valuesKeys) { map.insert(d->addPrefix(entry, attribute), values[attribute]); } } return map; } QHash<QString, QMap<QByteArray, QByteArray>> GetMetaDataJob::allMetaDataForMailboxes() const { Q_D(const GetMetaDataJob); QHash<QString, QMap<QByteArray, QByteArray>> mailboxHash; QMapIterator<QString, QMap<QByteArray, QMap<QByteArray, QByteArray>>> i(d->metadata); while (i.hasNext()) { i.next(); mailboxHash.insert(i.key(), allMetaDataForMailbox(i.key())); } return mailboxHash; } #include "moc_getmetadatajob.cpp" 070701000000CF000081A400000000000000000000000166FAD7C00000231A000000000000000000000000000000000000003E00000000kimap-VERSIONgit.20240930T185424~db1f697/src/getmetadatajob.h/* SPDX-FileCopyrightText: 2009 Andras Mantia <amantia@kde.org> SPDX-License-Identifier: LGPL-2.0-or-later */ #pragma once #include "kimap_export.h" #include "metadatajobbase.h" namespace KIMAP { class Session; struct Response; class GetMetaDataJobPrivate; /** * Fetches mailbox metadata. * * Provides support for the IMAP METADATA extension; both the * final RFC version * (<a href="https://tools.ietf.org/html/rfc5464">RFC 5464</a>) * and the older, incompatible draft version (known as ANNOTATEMORE) * (<a * href="https://tools.ietf.org/html/draft-daboo-imap-annotatemore-07" * >draft-daboo-imap-annotatemore-07</a>). See setServerCompatibility(). * * This job can only be run when the session is in the * authenticated (or selected) state. * * If the server supports ACLs, the user will need the * Acl::Lookup right on the mailbox, as well as one of * - Acl::Read * - Acl::KeepSeen * - Acl::Write * - Acl::Insert * - Acl::Post * Otherwise, the user must be able to list the mailbox * and either read or write the message content. * * Note also that on servers that implement the Annotatemore * version of the extension, only Acl::Lookup rights are * required (ie: the user must be able to list the mailbox). */ class KIMAP_EXPORT GetMetaDataJob : public MetaDataJobBase { Q_OBJECT Q_DECLARE_PRIVATE(GetMetaDataJob) friend class SessionPrivate; public: explicit GetMetaDataJob(Session *session); ~GetMetaDataJob() override; /** * Used to specify the depth of the metadata hierarchy to walk. */ enum Depth { NoDepth = 0, /**< Only the requested entries */ OneLevel, /**< The requested entries and all their direct children */ AllLevels /**< The requested entries and all their descendants */ }; Q_DECLARE_FLAGS(Depths, Depth) /** * Add an entry to the query list. * * See SetMetaDataJob for a description of metadata entry names. * * When operating in Annotatemore mode, you should provide an attribute * name. Typically this will be "value", "value.priv" or "value.shared", * although you might want to fetch the "content-type" or * "content-language" attributes as well. * * @param entry the metadata entry name * @param attribute the attribute name, in Annotatemore mode * * @deprecated use addRequestedEntry(QByteArray) instead */ KIMAP_DEPRECATED void addEntry(const QByteArray &entry, const QByteArray &attribute = QByteArray()); /** * Add an entry to the query list. * * See SetMetaDataJob for a description of metadata entry names. * * Note that this expects METADATA style entries (with a /shared or /private prefix typically). * In ANNOTATEMORE mode, this prefix is automatically replaced with an appropriate attribute. * * @param entry the metadata entry name */ void addRequestedEntry(const QByteArray &entry); /** * Limits the size of returned metadata entries. * * In order to save time or bandwidth, it is possible to prevent the * server from returning metadata entries that are larger than a * certain size. These entries will simply not appear in the * list returned by allMetaData(), and will not be accessible using * metaData(). * * Note that this is only used when the server capability mode is * Metadata. * * The default is no limit (-1). A value of less than -1 will cause * the job to fail. * * @param size the entry size limit, in octets, or -1 for no limit */ void setMaximumSize(qint64 size); /** * Sets whether to retrieve children or descendants of the requested entries. * * Metadata entry names are hierarchical, much like UNIX path names. * It therefore makes sense to ask for an entry and all its children * (OneLevel) or an entry and all its descendants (AllLevels). * * For example, /shared/foo/bar/baz is a child of /shared/foo/bar and a * descendent of /shared/foo. So if you request the entry "/shared/foo" * with depth NoDepth, you will only get the "/shared/foo" entry. If * you set the depth to OneLevel, you will also get "/shared/foo/bar". * If you set the depth to AllLevels, you will also get * "/shared/foo/bar/baz", and every other metadata entry that starts * with "/shared/foo/". * * Note that this is only used when the server capability mode is * Metadata. * * @param depth the depth of the metadata tree to return */ void setDepth(Depth depth); /** * Get a single metadata entry. * * The metadata must have been requested using addEntry(), and * the job must have completed successfully, or this method * will not return anything. * * Note that if setMaximumSize() was used to limit the size of * returned metadata, this method may return an empty QByteArray * even if the metadata entry was requested and exists on the * server. This will happen when the metadata entry is larger * than the size limit given to setMaximumSize(). * * @param mailBox the mailbox the metadata is attached to, or * an empty string for server metadata * @param entry the entry to get * @param attribute (only in Annotatemore mode) the attribute to get * @return the metadata entry value * * @deprecated use metaData(QByteArray entry) instead */ // XXX: what's with the mailBox argument in a class that has setMailBox()? // KJobs are not intended to be run more than once KIMAP_DEPRECATED QByteArray metaData(const QString &mailBox, const QByteArray &entry, const QByteArray &attribute = QByteArray()) const; /** * Get a single metadata entry. * * The metadata must have been requested using addEntry(), and * the job must have completed successfully, or this method * will not return anything. * * Note that if setMaximumSize() was used to limit the size of * returned metadata, this method may return an empty QByteArray * even if the metadata entry was requested and exists on the * server. This will happen when the metadata entry is larger * than the size limit given to setMaximumSize(). * * Note that this expects METADATA style entries (with a /shared or /private prefix typically). * In ANNOTATEMORE mode, this prefix is automatically replaced with an appropriate attribute. * * @param entry the entry to get * @return the metadata entry value */ [[nodiscard]] QByteArray metaData(const QByteArray &entry) const; /** * Get all the metadata for a given mailbox. * * The returned map is from metadata entry names to attributes or values. * * If operating in Metadata mode, the metadata value is stored against the * empty QByteArray: * @code * map = job.allMetaData( "INBOX" ); * QByteArray value = map[ "/shared/comment" ].value( QByteArray() ); * @endcode * * The equivalent in Annotatemore mode would be: * @code * map = job.allMetaData( "INBOX" ); * QByteArray value = map[ "/comment" ].value( "value.shared" ); * @endcode * * @param mailBox a mailbox name or an empty string for server metadata * @return a map from metadata entry names to attributes or values */ // XXX: what's with the mailBox argument in a class that has setMailBox()? // KJobs are not intended to be run more than once [[nodiscard]] QMap<QByteArray, QMap<QByteArray, QByteArray>> allMetaData(const QString &mailBox) const; /** * Get all the metadata for the mailbox set with setMailBox(). * * Note that the returned map uses METADATA style entries (with a /shared or /private prefix typically), * also in ANNOTATEMORE mode. * * @return a map from metadata entry names to values */ [[nodiscard]] QMap<QByteArray, QByteArray> allMetaData() const; /** * Get all the metadata for the mailbox. * * Note that the returned map uses METADATA style entries (with a /shared or /private prefix typically), * also in ANNOTATEMORE mode. * * @return a map from metadata entry names to values */ QMap<QByteArray, QByteArray> allMetaDataForMailbox(const QString &mailbox) const; /** * Get all the metadata for for all mailboxes. * * Note that the returned map uses METADATA style entries (with a /shared or /private prefix typically), * also in ANNOTATEMORE mode. * * @return a map in the form (mailbox, (entry, value)) */ [[nodiscard]] QHash<QString, QMap<QByteArray, QByteArray>> allMetaDataForMailboxes() const; protected: void doStart() override; void handleResponse(const Response &response) override; }; } 070701000000D0000081A400000000000000000000000166FAD7C000000593000000000000000000000000000000000000003D00000000kimap-VERSIONgit.20240930T185424~db1f697/src/getquotajob.cpp/* SPDX-FileCopyrightText: 2009 Andras Mantia <amantia@kde.org> SPDX-License-Identifier: LGPL-2.0-or-later */ #include "getquotajob.h" #include <KLocalizedString> #include "quotajobbase_p.h" #include "response_p.h" #include "session_p.h" namespace KIMAP { class GetQuotaJobPrivate : public QuotaJobBasePrivate { public: GetQuotaJobPrivate(Session *session, const QString &name) : QuotaJobBasePrivate(session, name) { } ~GetQuotaJobPrivate() { } QByteArray root; }; } using namespace KIMAP; GetQuotaJob::GetQuotaJob(Session *session) : QuotaJobBase(*new GetQuotaJobPrivate(session, i18n("GetQuota"))) { } GetQuotaJob::~GetQuotaJob() { } void GetQuotaJob::doStart() { Q_D(GetQuotaJob); // XXX: [alexmerry, 2010-07-24]: should d->root be quoted properly? d->tags << d->sessionInternal()->sendCommand("GETQUOTA", '\"' + d->root + '\"'); } void GetQuotaJob::handleResponse(const Response &response) { Q_D(GetQuotaJob); if (handleErrorReplies(response) == NotHandled) { if (response.content.size() >= 4 && response.content[1].toString() == "QUOTA") { d->quota = d->readQuota(response.content[3]); } } } void GetQuotaJob::setRoot(const QByteArray &root) { Q_D(GetQuotaJob); d->root = root; } QByteArray GetQuotaJob::root() const { Q_D(const GetQuotaJob); return d->root; } #include "moc_getquotajob.cpp" 070701000000D1000081A400000000000000000000000166FAD7C00000069A000000000000000000000000000000000000003B00000000kimap-VERSIONgit.20240930T185424~db1f697/src/getquotajob.h/* SPDX-FileCopyrightText: 2009 Andras Mantia <amantia@kde.org> SPDX-License-Identifier: LGPL-2.0-or-later */ #pragma once #include "quotajobbase.h" namespace KIMAP { class Session; struct Message; class GetQuotaJobPrivate; /** * Gets resource limits for a quota root. * * Quotas are defined with respect to "resources" and "quota roots". * A resource is a numerical property that can be limited, such * as the octet size of all the messages in a mailbox, or the * number of messages in a mailbox. Each mailbox has one or more * quota roots, which are where the resource limits are defined. * A quota root may or may not be a mailbox name, and an empty * string is a valid quota root. All mailboxes with the same quota * root share the resource limits of the quota root. * * This job can only be run when the session is in the * authenticated (or selected) state. * * This job requires that the server supports the QUOTA * capability, defined in * <a href="https://tools.ietf.org/html/rfc2087">RFC 2087</a>. */ class KIMAP_EXPORT GetQuotaJob : public QuotaJobBase { Q_OBJECT Q_DECLARE_PRIVATE(GetQuotaJob) friend class SessionPrivate; public: explicit GetQuotaJob(Session *session); ~GetQuotaJob() override; /** * Set the quota root to get the resource limits for. * @param root the quota root to set * @see GetQuotaRootJob */ void setRoot(const QByteArray &root); /** * The quota root that resource limit information will be fetched for. */ [[nodiscard]] QByteArray root() const; protected: void doStart() override; void handleResponse(const Response &response) override; }; } 070701000000D2000081A400000000000000000000000166FAD7C000001256000000000000000000000000000000000000004100000000kimap-VERSIONgit.20240930T185424~db1f697/src/getquotarootjob.cpp/* SPDX-FileCopyrightText: 2009 Andras Mantia <amantia@kde.org> SPDX-License-Identifier: LGPL-2.0-or-later */ #include "getquotarootjob.h" #include <KLocalizedString> #include "quotajobbase_p.h" #include "response_p.h" #include "rfccodecs.h" #include "session_p.h" namespace KIMAP { class GetQuotaRootJobPrivate : public QuotaJobBasePrivate { public: GetQuotaRootJobPrivate(Session *session, const QString &name) : QuotaJobBasePrivate(session, name) { } ~GetQuotaRootJobPrivate() { } QString mailBox; QList<QByteArray> rootList; QMap<QByteArray, QMap<QByteArray, QPair<qint64, qint64>>> quotas; }; } using namespace KIMAP; GetQuotaRootJob::GetQuotaRootJob(Session *session) : QuotaJobBase(*new GetQuotaRootJobPrivate(session, i18n("GetQuotaRoot"))) { } GetQuotaRootJob::~GetQuotaRootJob() { } void GetQuotaRootJob::doStart() { Q_D(GetQuotaRootJob); d->tags << d->sessionInternal()->sendCommand("GETQUOTAROOT", '\"' + KIMAP::encodeImapFolderName(d->mailBox.toUtf8()) + '\"'); } void GetQuotaRootJob::handleResponse(const Response &response) { Q_D(GetQuotaRootJob); if (handleErrorReplies(response) == NotHandled) { if (response.content.size() >= 3) { if (response.content[1].toString() == "QUOTAROOT") { d->rootList.clear(); // some impls don't give the root a name which for us seems as if // there were no message part if (response.content.size() == 3) { d->rootList.append(""); } else { int i = 3; while (i < response.content.size()) { d->rootList.append(response.content[i].toString()); i++; } } } else if (response.content[1].toString() == "QUOTA") { QByteArray rootName; int quotaContentIndex = 3; // some impls don't give the root a name in the response if (response.content.size() == 3) { quotaContentIndex = 2; } else { rootName = response.content[2].toString(); } const QMap<QByteArray, QPair<qint64, qint64>> "a = d->readQuota(response.content[quotaContentIndex]); if (d->quotas.contains(rootName)) { d->quotas[rootName].insert(quota); } else { d->quotas[rootName] = quota; } } } } } void GetQuotaRootJob::setMailBox(const QString &mailBox) { Q_D(GetQuotaRootJob); d->mailBox = mailBox; } QString GetQuotaRootJob::mailBox() const { Q_D(const GetQuotaRootJob); return d->mailBox; } QList<QByteArray> GetQuotaRootJob::roots() const { Q_D(const GetQuotaRootJob); return d->rootList; } qint64 GetQuotaRootJob::usage(const QByteArray &root, const QByteArray &resource) const { Q_D(const GetQuotaRootJob); QByteArray r = resource.toUpper(); if (d->quotas.contains(root) && d->quotas[root].contains(r)) { return d->quotas[root][r].first; } return -1; } qint64 GetQuotaRootJob::limit(const QByteArray &root, const QByteArray &resource) const { Q_D(const GetQuotaRootJob); QByteArray r = resource.toUpper(); if (d->quotas.contains(root) && d->quotas[root].contains(r)) { return d->quotas[root][r].second; } return -1; } QMap<QByteArray, qint64> GetQuotaRootJob::allUsages(const QByteArray &root) const { Q_D(const GetQuotaRootJob); QMap<QByteArray, qint64> result; if (d->quotas.contains(root)) { const QMap<QByteArray, QPair<qint64, qint64>> quota = d->quotas[root]; QMap<QByteArray, QPair<qint64, qint64>>::const_iterator it = quota.cbegin(); const QMap<QByteArray, QPair<qint64, qint64>>::const_iterator itEnd = quota.cend(); for (; it != itEnd; ++it) { result[it.key()] = it.value().first; } } return result; } QMap<QByteArray, qint64> GetQuotaRootJob::allLimits(const QByteArray &root) const { Q_D(const GetQuotaRootJob); QMap<QByteArray, qint64> result; if (d->quotas.contains(root)) { const QMap<QByteArray, QPair<qint64, qint64>> quota = d->quotas[root]; QMap<QByteArray, QPair<qint64, qint64>>::const_iterator it = quota.cbegin(); const QMap<QByteArray, QPair<qint64, qint64>>::const_iterator itEnd = quota.cend(); for (; it != itEnd; ++it) { result[it.key()] = it.value().second; } } return result; } #include "moc_getquotarootjob.cpp" 070701000000D3000081A400000000000000000000000166FAD7C000000D60000000000000000000000000000000000000003F00000000kimap-VERSIONgit.20240930T185424~db1f697/src/getquotarootjob.h/* SPDX-FileCopyrightText: 2009 Andras Mantia <amantia@kde.org> SPDX-License-Identifier: LGPL-2.0-or-later */ #pragma once #include "quotajobbase.h" namespace KIMAP { class Session; struct Message; class GetQuotaRootJobPrivate; /** * Gets the quota root and resource limits for a mailbox. * * Quotas are defined with respect to "resources" and "quota roots". * A resource is a numerical property that can be limited, such * as the octet size of all the messages in a mailbox, or the * number of messages in a mailbox. Each mailbox has one or more * quota roots, which are where the resource limits are defined. * A quota root may or may not be a mailbox name, and an empty * string is a valid quota root. All mailboxes with the same quota * root share the resource limits of the quota root. * * This job can only be run when the session is in the * authenticated (or selected) state. * * This job requires that the server supports the QUOTA * capability, defined in * <a href="https://tools.ietf.org/html/rfc2087">RFC 2087</a>. */ class KIMAP_EXPORT GetQuotaRootJob : public QuotaJobBase { Q_OBJECT Q_DECLARE_PRIVATE(GetQuotaRootJob) friend class SessionPrivate; public: explicit GetQuotaRootJob(Session *session); ~GetQuotaRootJob() override; /** * Set the mailbox to get the quota roots for. * * @param mailBox the name of an existing mailbox */ void setMailBox(const QString &mailBox); /** * The mailbox that the quota roots will be fetched for. */ [[nodiscard]] QString mailBox() const; /** * The quota roots for the mailbox. */ [[nodiscard]] QList<QByteArray> roots() const; /** * Get the current usage for a resource. * * Note that if there is no limit for a resource, the * server will not provide information about resource * usage. * * @param root the quota root to get the resource usage for * @param resource the resource to get the usage for * @return the resource usage in appropriate units, or -1 * if the usage is unknown or there is no * limit on the resource */ [[nodiscard]] qint64 usage(const QByteArray &root, const QByteArray &resource) const; /** * Get the current limit for a resource. * * @param root the quota root to get the resource limit for * @param resource the resource to get the limit for * @return the resource limit in appropriate units, or -1 * if the limit is unknown or there is no * limit on the resource */ [[nodiscard]] qint64 limit(const QByteArray &root, const QByteArray &resource) const; /** * Get a map containing all resource usage figures for a quota root. * * @param root the quota root to get resource usage figures for * @return a map from resource names to usage figures */ [[nodiscard]] QMap<QByteArray, qint64> allUsages(const QByteArray &root) const; /** * Get a map containing all resource limits for a quota root. * * @param root the quota root to get resource limits for * @return a map from resource names to limits */ [[nodiscard]] QMap<QByteArray, qint64> allLimits(const QByteArray &root) const; protected: void doStart() override; void handleResponse(const Response &response) override; }; } 070701000000D4000081A400000000000000000000000166FAD7C000000524000000000000000000000000000000000000003700000000kimap-VERSIONgit.20240930T185424~db1f697/src/idjob.cpp/* SPDX-FileCopyrightText: 2015 Christian Mollekopf <mollekopf@kolabsys.com> SPDX-License-Identifier: LGPL-2.0-or-later */ #include "idjob.h" #include <KLocalizedString> #include "job_p.h" #include "response_p.h" #include "session_p.h" namespace KIMAP { class IdJobPrivate : public JobPrivate { public: IdJobPrivate(Session *session, const QString &name) : JobPrivate(session, name) { } ~IdJobPrivate() { } QMap<QByteArray, QByteArray> fields; }; } using namespace KIMAP; IdJob::IdJob(Session *session) : Job(*new IdJobPrivate(session, i18n("Id"))) { } IdJob::~IdJob() { } void IdJob::setField(const QByteArray &name, const QByteArray &value) { Q_D(IdJob); d->fields.insert(name, value); } void IdJob::doStart() { Q_D(IdJob); QByteArray command = "ID"; command += " ("; QMapIterator<QByteArray, QByteArray> i(d->fields); while (i.hasNext()) { i.next(); command += "\"" + i.key() + "\" \"" + i.value() + "\" "; } command.chop(1); command += ")"; d->tags << d->sessionInternal()->sendCommand(command); } void IdJob::handleResponse(const Response &response) { // Q_D(IdJob); if (handleErrorReplies(response) == NotHandled) { // Ignore the response } } #include "moc_idjob.cpp" 070701000000D5000081A400000000000000000000000166FAD7C0000002B4000000000000000000000000000000000000003500000000kimap-VERSIONgit.20240930T185424~db1f697/src/idjob.h/* SPDX-FileCopyrightText: 2015 Christian Mollekopf <mollekopf@kolabsys.com> SPDX-License-Identifier: LGPL-2.0-or-later */ #pragma once #include "kimap_export.h" #include "job.h" namespace KIMAP { class Session; struct Message; class IdJobPrivate; /** * Reports client id. * * This job can be run in any open session. */ class KIMAP_EXPORT IdJob : public Job { Q_OBJECT Q_DECLARE_PRIVATE(IdJob) friend class SessionPrivate; public: IdJob(Session *session); ~IdJob() override; void setField(const QByteArray &name, const QByteArray &field); protected: void doStart() override; void handleResponse(const Response &response) override; }; } 070701000000D6000081A400000000000000000000000166FAD7C000000EFC000000000000000000000000000000000000003900000000kimap-VERSIONgit.20240930T185424~db1f697/src/idlejob.cpp/* SPDX-FileCopyrightText: 2009 Kevin Ottens <ervin@kde.org> SPDX-License-Identifier: LGPL-2.0-or-later */ #include "idlejob.h" #include <KLocalizedString> #include <QTimer> #include "job_p.h" #include "response_p.h" #include "session_p.h" namespace KIMAP { class IdleJobPrivate : public JobPrivate { public: IdleJobPrivate(IdleJob *job, Session *session, const QString &name) : JobPrivate(session, name) , q(job) { } ~IdleJobPrivate() { } void emitStats() { emitStatsTimer.stop(); Q_EMIT q->mailBoxStats(q, m_session->selectedMailBox(), messageCount, recentCount); lastMessageCount = messageCount; lastRecentCount = recentCount; messageCount = -1; recentCount = -1; } void resetTimeout() { sessionInternal()->setSocketTimeout(originalSocketTimeout); } IdleJob *const q; QTimer emitStatsTimer; int messageCount = -1; int recentCount = -1; int lastMessageCount = -1; int lastRecentCount = -1; int originalSocketTimeout = -1; }; } using namespace KIMAP; IdleJob::IdleJob(Session *session) : Job(*new IdleJobPrivate(this, session, i18nc("name of the idle job", "Idle"))) { Q_D(IdleJob); connect(&d->emitStatsTimer, &QTimer::timeout, this, [d]() { d->emitStats(); }); connect(this, &KJob::result, this, [d]() { d->resetTimeout(); }); } IdleJob::~IdleJob() { } void KIMAP::IdleJob::stop() { Q_D(IdleJob); d->sessionInternal()->setSocketTimeout(d->originalSocketTimeout); d->sessionInternal()->sendData("DONE"); } void IdleJob::doStart() { Q_D(IdleJob); d->originalSocketTimeout = d->sessionInternal()->socketTimeout(); d->sessionInternal()->setSocketTimeout(-1); d->tags << d->sessionInternal()->sendCommand("IDLE"); } void IdleJob::handleResponse(const Response &response) { Q_D(IdleJob); // We can predict it'll be handled by handleErrorReplies() so Q_EMIT // pending signals now (if needed) so that result() will really be // the last emitted signal. if (!response.content.isEmpty() && d->tags.size() == 1 && d->tags.contains(response.content.first().toString()) && (d->messageCount >= 0 || d->recentCount >= 0)) { d->emitStats(); } if (handleErrorReplies(response) == NotHandled) { if (!response.content.isEmpty() && response.content[0].toString() == "+") { // Got the continuation all is fine return; } else if (response.content.size() > 2) { const QByteArray ba = response.content[2].toString(); if (ba == "EXISTS") { if (d->messageCount >= 0) { d->emitStats(); } d->messageCount = response.content[1].toString().toInt(); } else if (ba == "RECENT") { if (d->recentCount >= 0) { d->emitStats(); } d->recentCount = response.content[1].toString().toInt(); } else if (ba == "FETCH") { const qint64 uid = response.content[1].toString().toLongLong(); Q_EMIT mailBoxMessageFlagsChanged(this, uid); } } if (d->messageCount >= 0 && d->recentCount >= 0) { d->emitStats(); } else if (d->messageCount >= 0 || d->recentCount >= 0) { d->emitStatsTimer.start(200); } } } QString KIMAP::IdleJob::lastMailBox() const { Q_D(const IdleJob); return d->m_session->selectedMailBox(); } int KIMAP::IdleJob::lastMessageCount() const { Q_D(const IdleJob); return d->lastMessageCount; } int KIMAP::IdleJob::lastRecentCount() const { Q_D(const IdleJob); return d->lastRecentCount; } #include "moc_idlejob.cpp" 070701000000D7000081A400000000000000000000000166FAD7C000000DBE000000000000000000000000000000000000003700000000kimap-VERSIONgit.20240930T185424~db1f697/src/idlejob.h/* SPDX-FileCopyrightText: 2009 Kevin Ottens <ervin@kde.org> SPDX-License-Identifier: LGPL-2.0-or-later */ #pragma once #include "kimap_export.h" #include "imapset.h" #include "job.h" #include <KMime/Content> #include <KMime/Message> namespace KIMAP { class Session; struct Response; class IdleJobPrivate; /** * Idles the connection to the IMAP server. * * This job can be run while the client has no other use * for the connection, and the server will send updates * about the selected mailbox. * * Note that although the server may send a variety of * responses while the job is running (including EXPUNGE, * for example), only RECENT and EXISTS responses are * actually reported by this job. * * The job also processes updates in pairs - if the server * sends an EXISTS update but not a RECENT one (because * another client is changing the mailbox contents), this * job will not report the update. * * It only makes sense to run this job when the session is * in the selected state. * * This job requires that the server supports the IDLE * capability, defined in * <a href="https://tools.ietf.org/html/rfc2177">RFC 2177</a>. */ class KIMAP_EXPORT IdleJob : public Job { Q_OBJECT Q_DECLARE_PRIVATE(IdleJob) public: explicit IdleJob(Session *session); ~IdleJob() override; /** * The last mailbox status that was reported. * * This is just the session's selected mailbox. */ [[nodiscard]] QString lastMailBox() const; /** * The last message count that was reported. * * The server will send updates about the number of * messages in the mailbox when that number changes. * This is the last number it reported. * * @return the last message count the server reported, * or -1 if it has not reported a message count * since the job started. */ [[nodiscard]] int lastMessageCount() const; /** * The last recent message count that was reported. * * The server will send updates about the number of * messages in the mailbox that are tagged with \Recent * when that number changes. This is the last number it * reported. * * @return the last recent message count the server reported, * or -1 if it has not reported a recent message count * since the job started. */ [[nodiscard]] int lastRecentCount() const; public Q_SLOTS: /** * Stops the idle job. */ void stop(); Q_SIGNALS: /** * Signals that the server has notified that the total and * recent message counts have changed. * * @param job this object * @param mailBox the selected mailbox * @param messageCount the new total message count reported by the server * @param recentCount the new "recent message" count reported by the server */ void mailBoxStats(KIMAP::IdleJob *job, const QString &mailBox, int messageCount, int recentCount); /** * Signals that the server has notified that the some messages flags * have changed * * @param job this object * @param uid UID of message that has changed * @since 4.12 */ void mailBoxMessageFlagsChanged(KIMAP::IdleJob *job, qint64 uid); protected: void doStart() override; void handleResponse(const Response &response) override; private: Q_PRIVATE_SLOT(d_func(), void emitStats()) Q_PRIVATE_SLOT(d_func(), void resetTimeout()) }; } 070701000000D8000081A400000000000000000000000166FAD7C000001BD1000000000000000000000000000000000000003900000000kimap-VERSIONgit.20240930T185424~db1f697/src/imapset.cpp/* SPDX-FileCopyrightText: 2007 Volker Krause <vkrause@kde.org> SPDX-License-Identifier: LGPL-2.0-or-later */ #include "imapset.h" #include <QSharedData> using namespace KIMAP; class ImapInterval::Private : public QSharedData { public: Private() : QSharedData() , begin(0) , end(0) { } Private(const Private &other) : QSharedData(other) , begin(other.begin) , end(other.end) { } Id begin; Id end; }; class ImapSet::Private : public QSharedData { public: Private() : QSharedData() { } Private(const Private &other) : QSharedData(other) , intervals(other.intervals) { } ImapInterval::List intervals; }; ImapInterval::ImapInterval() : d(new Private) { } ImapInterval::ImapInterval(const ImapInterval &other) : d(other.d) { } ImapInterval::ImapInterval(Id begin, Id end) : d(new Private) { d->begin = begin; d->end = end; } ImapInterval::~ImapInterval() { } ImapInterval &ImapInterval::operator=(const ImapInterval &other) { if (this != &other) { d = other.d; } return *this; } bool ImapInterval::operator==(const ImapInterval &other) const { return (d->begin == other.d->begin && d->end == other.d->end); } ImapInterval::Id ImapInterval::size() const { if (!d->begin && !d->end) { return 0; } if (d->begin && !d->end) { return Q_INT64_C(0x7FFFFFFFFFFFFFFF) - d->begin + 1; } return d->end - d->begin + 1; } bool ImapInterval::hasDefinedBegin() const { return d->begin != 0; } ImapInterval::Id ImapInterval::begin() const { return d->begin; } bool ImapInterval::hasDefinedEnd() const { return d->end != 0; } ImapInterval::Id ImapInterval::end() const { if (hasDefinedEnd()) { return d->end; } return std::numeric_limits<qint64>::max(); } void ImapInterval::setBegin(Id value) { Q_ASSERT(value >= 0); Q_ASSERT(value <= d->end || !hasDefinedEnd()); d->begin = value; } void ImapInterval::setEnd(Id value) { Q_ASSERT(value >= 0); Q_ASSERT(value >= d->begin || !hasDefinedBegin()); d->end = value; } QByteArray ImapInterval::toImapSequence() const { if (size() == 0) { return QByteArray(); } if (size() == 1) { return QByteArray::number(d->begin); } QByteArray rv = QByteArray::number(d->begin) + ':'; if (hasDefinedEnd()) { rv += QByteArray::number(d->end); } else { rv += '*'; } return rv; } ImapInterval ImapInterval::fromImapSequence(const QByteArray &sequence) { QList<QByteArray> values = sequence.split(':'); if (values.isEmpty() || values.size() > 2) { return ImapInterval(); } bool ok = false; Id begin = values[0].toLongLong(&ok); if (!ok) { return ImapInterval(); } Id end; if (values.size() == 1) { end = begin; } else if (values[1] == QByteArray("*")) { end = 0; } else { ok = false; end = values[1].toLongLong(&ok); if (!ok) { return ImapInterval(); } } return ImapInterval(begin, end); } ImapSet::ImapSet() : d(new Private) { } ImapSet::ImapSet(Id begin, Id end) : d(new Private) { add(ImapInterval(begin, end)); } ImapSet::ImapSet(Id value) : d(new Private) { add(QList<Id>() << value); } ImapSet::ImapSet(const ImapSet &other) : d(other.d) { } ImapSet::~ImapSet() { } ImapSet &ImapSet::operator=(const ImapSet &other) { if (this != &other) { d = other.d; } return *this; } bool ImapSet::operator==(const ImapSet &other) const { if (d->intervals.size() != other.d->intervals.size()) { return false; } for (const ImapInterval &interval : std::as_const(d->intervals)) { if (!other.d->intervals.contains(interval)) { return false; } } return true; } void ImapSet::add(Id value) { add(QList<Id>() << value); } void ImapSet::add(const QList<Id> &values) { QList<Id> vals = values; std::sort(vals.begin(), vals.end()); for (int i = 0; i < vals.count(); ++i) { const Id begin = vals[i]; Q_ASSERT(begin >= 0); if (i == vals.count() - 1) { d->intervals << ImapInterval(begin, begin); break; } do { ++i; Q_ASSERT(vals[i] >= 0); if (vals[i] != (vals[i - 1] + 1)) { --i; break; } } while (i < vals.count() - 1); d->intervals << ImapInterval(begin, vals[i]); } } void ImapSet::add(const ImapInterval &interval) { d->intervals << interval; } QByteArray ImapSet::toImapSequenceSet() const { QList<QByteArray> rv; rv.reserve(d->intervals.count()); for (const ImapInterval &interval : std::as_const(d->intervals)) { rv << interval.toImapSequence(); } QByteArray result; if (!rv.isEmpty()) { result = rv.first(); QList<QByteArray>::ConstIterator it = rv.constBegin(); const QList<QByteArray>::ConstIterator end = rv.constEnd(); ++it; for (; it != end; ++it) { result += ',' + (*it); } } return result; } ImapSet ImapSet::fromImapSequenceSet(const QByteArray &sequence) { ImapSet result; const QList<QByteArray> intervals = sequence.split(','); for (const QByteArray &interval : std::as_const(intervals)) { if (!interval.isEmpty()) { result.add(ImapInterval::fromImapSequence(interval)); } } return result; } ImapInterval::List ImapSet::intervals() const { return d->intervals; } bool ImapSet::isEmpty() const { return d->intervals.isEmpty(); } void ImapSet::optimize() { // There's nothing to optimize if we have fewer than 2 intervals if (d->intervals.size() < 2) { return; } // Sort the intervals in ascending order by their beginning value std::sort(d->intervals.begin(), d->intervals.end(), [](const ImapInterval &lhs, const ImapInterval &rhs) { return lhs.begin() < rhs.begin(); }); auto it = d->intervals.begin(); while (it != d->intervals.end() && it != std::prev(d->intervals.end())) { auto next = std::next(it); // +1 so that we also merge neighbouring intervals, e.g. 1:2,3:4 -> 1:4 if (it->hasDefinedEnd() && it->end() + 1 >= next->begin()) { next->setBegin(it->begin()); if (next->hasDefinedEnd() && it->end() > next->end()) { next->setEnd(it->end()); } it = d->intervals.erase(it); } else if (!it->hasDefinedEnd()) { // We can eat up all the remaining intervals it = d->intervals.erase(next, d->intervals.end()); } else { ++it; } } } QDebug &operator<<(QDebug &d, const ImapInterval &interval) { d << interval.toImapSequence(); return d; } QDebug &operator<<(QDebug &d, const ImapSet &set) { d << set.toImapSequenceSet(); return d; } 070701000000D9000081A400000000000000000000000166FAD7C0000014B2000000000000000000000000000000000000003700000000kimap-VERSIONgit.20240930T185424~db1f697/src/imapset.h/* SPDX-FileCopyrightText: 2007 Volker Krause <vkrause@kde.org> SPDX-License-Identifier: LGPL-2.0-or-later */ #pragma once #include "kimap_export.h" #include <QByteArray> #include <QDebug> #include <QList> #include <QMetaType> #include <QSharedDataPointer> namespace KIMAP { /** Represents a single interval in an ImapSet. This class is implicitly shared. */ class KIMAP_EXPORT ImapInterval { public: /** * Describes the ids stored in the interval. */ using Id = qint64; /** A list of ImapInterval objects. */ using List = QList<ImapInterval>; /** Constructs an interval that covers all positive numbers. */ ImapInterval(); /** Copy constructor. */ ImapInterval(const ImapInterval &other); /** Create a new interval. @param begin The begin of the interval. @param end Keep default (0) to just set the interval begin */ explicit ImapInterval(Id begin, Id end = 0); /** Destructor. */ ~ImapInterval(); /** Assignment operator. */ ImapInterval &operator=(const ImapInterval &other); /** Comparison operator. */ bool operator==(const ImapInterval &other) const; /** Returns the size of this interval. Size is only defined for finite intervals. */ Id size() const; /** Returns true if this interval has a defined begin. */ bool hasDefinedBegin() const; /** Returns the begin of this interval. The value is the smallest value part of the interval. Only valid if begin is defined. */ Id begin() const; /** Returns true if this intercal has been defined. */ bool hasDefinedEnd() const; /** Returns the end of this interval. This value is the largest value part of the interval. Only valid if hasDefinedEnd() returned true. */ Id end() const; /** Sets the begin of the interval. */ void setBegin(Id value); /** Sets the end of this interval. */ void setEnd(Id value); /** Converts this set into an IMAP compatible sequence. */ [[nodiscard]] QByteArray toImapSequence() const; /** Return the interval corresponding to the given IMAP-compatible QByteArray representation */ static ImapInterval fromImapSequence(const QByteArray &sequence); private: class Private; QSharedDataPointer<Private> d; }; /** Represents a set of natural numbers (1->∞) in a as compact as possible form. Used to address Akonadi items via the IMAP protocol or in the database. This class is implicitly shared. */ class KIMAP_EXPORT ImapSet { public: /** * Describes the ids stored in the set. */ using Id = qint64; /** Constructs an empty set. */ ImapSet(); /** Constructs a set containing a single interval. */ ImapSet(Id begin, Id end); /** Constructs a set containing a single value. */ explicit ImapSet(Id value); /** Copy constructor. */ ImapSet(const ImapSet &other); /** Destructor. */ ~ImapSet(); /** Assignment operator. */ ImapSet &operator=(const ImapSet &other); /** Comparison operator. */ bool operator==(const ImapSet &other) const; /** Adds a single positive integer numbers to the set. The list is sorted and split into as large as possible intervals. No interval merging is performed. @param value A positive integer number */ void add(Id value); /** Adds the given list of positive integer numbers to the set. The list is sorted and split into as large as possible intervals. No interval merging is performed. @param values List of positive integer numbers in arbitrary order */ void add(const QList<Id> &values); /** Adds the given ImapInterval to this set. No interval merging is performed. @param interval the interval to add */ void add(const ImapInterval &interval); /** Returns a IMAP-compatible QByteArray representation of this set. */ [[nodiscard]] QByteArray toImapSequenceSet() const; /** Return the set corresponding to the given IMAP-compatible QByteArray representation */ static ImapSet fromImapSequenceSet(const QByteArray &sequence); /** Returns the intervals this set consists of. */ [[nodiscard]] ImapInterval::List intervals() const; /** Returns true if this set doesn't contains any values. */ [[nodiscard]] bool isEmpty() const; /** * Optimizes the ImapSet by sorting and merging overlapping intervals. * * Normally you shouldn't need to call this method. KIMAP will make sure * to opimize the ImapSet before serializing it to string and sending it * to the IMAP server. */ void optimize(); private: class Private; QSharedDataPointer<Private> d; }; } KIMAP_EXPORT QDebug &operator<<(QDebug &d, const KIMAP::ImapInterval &interval); KIMAP_EXPORT QDebug &operator<<(QDebug &d, const KIMAP::ImapSet &set); Q_DECLARE_METATYPE(KIMAP::ImapInterval) Q_DECLARE_METATYPE(KIMAP::ImapInterval::List) Q_DECLARE_METATYPE(KIMAP::ImapSet) 070701000000DA000081A400000000000000000000000166FAD7C000003A1E000000000000000000000000000000000000004200000000kimap-VERSIONgit.20240930T185424~db1f697/src/imapstreamparser.cpp/* SPDX-FileCopyrightText: 2006-2007 Volker Krause <vkrause@kde.org> SPDX-FileCopyrightText: 2009 Andras Mantia <amantia@kde.org> SPDX-FileCopyrightText: 2010 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com> SPDX-FileContributor: Kevin Ottens <kevin@kdab.com> SPDX-License-Identifier: LGPL-2.0-or-later */ #include "imapstreamparser.h" #include <QIODevice> #include <ctype.h> using namespace KIMAP; ImapStreamParser::ImapStreamParser(QIODevice *socket, bool serverModeEnabled) : m_position(0) , m_literalSize(0) { m_socket = socket; m_isServerModeEnabled = serverModeEnabled; } QString ImapStreamParser::readUtf8String() { QByteArray tmp; tmp = readString(); QString result = QString::fromUtf8(tmp); return result; } QByteArray ImapStreamParser::readString() { QByteArray result; if (!waitForMoreData(m_data.isEmpty())) { throw ImapParserException("Unable to read more data"); } stripLeadingSpaces(); if (!waitForMoreData(m_position >= m_data.length())) { throw ImapParserException("Unable to read more data"); } // literal string // TODO: error handling if (hasLiteral()) { while (!atLiteralEnd()) { result += readLiteralPart(); } return result; } // quoted string return parseQuotedString(); } bool ImapStreamParser::hasString() { if (!waitForMoreData(m_position >= m_data.length())) { throw ImapParserException("Unable to read more data"); } int savedPos = m_position; stripLeadingSpaces(); int pos = m_position; m_position = savedPos; const char dataChar = m_data.at(pos); if (dataChar == '{') { return true; // literal string } else if (dataChar == '"') { return true; // quoted string } else if (dataChar != ' ' && dataChar != '(' && dataChar != ')' && dataChar != '[' && dataChar != ']' && dataChar != '\n' && dataChar != '\r') { return true; // unquoted string } return false; // something else, not a string } bool ImapStreamParser::hasLiteral() { if (!waitForMoreData(m_position >= m_data.length())) { throw ImapParserException("Unable to read more data"); } int savedPos = m_position; stripLeadingSpaces(); if (m_data.at(m_position) == '{') { int end = -1; do { end = m_data.indexOf('}', m_position); if (!waitForMoreData(end == -1)) { throw ImapParserException("Unable to read more data"); } } while (end == -1); Q_ASSERT(end > m_position); m_literalSize = m_data.mid(m_position + 1, end - m_position - 1).toInt(); // strip CRLF m_position = end + 1; // ensure that the CRLF is available if (!waitForMoreData(m_position + 1 >= m_data.length())) { throw ImapParserException("Unable to read more data"); } if (m_position < m_data.length() && m_data.at(m_position) == '\r') { ++m_position; } if (m_position < m_data.length() && m_data.at(m_position) == '\n') { ++m_position; } // FIXME: Makes sense only on the server side? if (m_isServerModeEnabled && m_literalSize > 0) { sendContinuationResponse(m_literalSize); } return true; } else { m_position = savedPos; return false; } } bool ImapStreamParser::atLiteralEnd() const { return (m_literalSize == 0); } QByteArray ImapStreamParser::readLiteralPart() { static const qint64 maxLiteralPartSize = 4096; int size = qMin(maxLiteralPartSize, m_literalSize); if (!waitForMoreData(m_data.length() < m_position + size)) { throw ImapParserException("Unable to read more data"); } if (m_data.length() < m_position + size) { // Still not enough data // Take what's already there size = m_data.length() - m_position; } QByteArray result = m_data.mid(m_position, size); m_position += size; m_literalSize -= size; Q_ASSERT(m_literalSize >= 0); trimBuffer(); return result; } bool ImapStreamParser::hasList() { if (!waitForMoreData(m_position >= m_data.length())) { throw ImapParserException("Unable to read more data"); } int savedPos = m_position; stripLeadingSpaces(); int pos = m_position; m_position = savedPos; if (m_data.at(pos) == '(') { return true; } return false; } bool ImapStreamParser::atListEnd() { if (!waitForMoreData(m_position >= m_data.length())) { throw ImapParserException("Unable to read more data"); } int savedPos = m_position; stripLeadingSpaces(); int pos = m_position; m_position = savedPos; if (m_data.at(pos) == ')') { m_position = pos + 1; return true; } return false; } QList<QByteArray> ImapStreamParser::readParenthesizedList() { QList<QByteArray> result; if (!waitForMoreData(m_data.length() <= m_position)) { throw ImapParserException("Unable to read more data"); } stripLeadingSpaces(); if (m_data.at(m_position) != '(') { return result; // no list found } bool concatToLast = false; int count = 0; int sublistbegin = m_position; int i = m_position + 1; for (;;) { if (!waitForMoreData(m_data.length() <= i)) { m_position = i; throw ImapParserException("Unable to read more data"); } if (m_data.at(i) == '(') { ++count; if (count == 1) { sublistbegin = i; } ++i; continue; } if (m_data.at(i) == ')') { if (count <= 0) { m_position = i + 1; return result; } if (count == 1) { result.append(m_data.mid(sublistbegin, i - sublistbegin + 1)); } --count; ++i; continue; } if (m_data.at(i) == ' ') { ++i; continue; } if (m_data.at(i) == '"') { if (count > 0) { m_position = i; parseQuotedString(); i = m_position; continue; } } if (m_data.at(i) == '[') { concatToLast = true; if (result.isEmpty()) { result.append(QByteArray()); } result.last() += '['; ++i; continue; } if (m_data.at(i) == ']') { concatToLast = false; result.last() += ']'; ++i; continue; } if (count == 0) { m_position = i; QByteArray ba; if (hasLiteral()) { while (!atLiteralEnd()) { ba += readLiteralPart(); } } else { ba = readString(); } // We might sometime get some unwanted CRLF, but we're still not at the end // of the list, would make further string reads fail so eat the CRLFs. while ((m_position < m_data.size()) && (m_data.at(m_position) == '\r' || m_data.at(m_position) == '\n')) { m_position++; } i = m_position - 1; if (concatToLast) { result.last() += ba; } else { result.append(ba); } } ++i; } throw ImapParserException("Something went very very wrong!"); } bool ImapStreamParser::hasResponseCode() { if (!waitForMoreData(m_position >= m_data.length())) { throw ImapParserException("Unable to read more data"); } int savedPos = m_position; stripLeadingSpaces(); int pos = m_position; m_position = savedPos; if (m_data.at(pos) == '[') { m_position = pos + 1; return true; } return false; } bool ImapStreamParser::atResponseCodeEnd() { if (!waitForMoreData(m_position >= m_data.length())) { throw ImapParserException("Unable to read more data"); } int savedPos = m_position; stripLeadingSpaces(); int pos = m_position; m_position = savedPos; if (m_data.at(pos) == ']') { m_position = pos + 1; return true; } return false; } QByteArray ImapStreamParser::parseQuotedString() { QByteArray result; if (!waitForMoreData(m_data.length() == 0)) { throw ImapParserException("Unable to read more data"); } stripLeadingSpaces(); int end = m_position; result.clear(); if (!waitForMoreData(m_position >= m_data.length())) { throw ImapParserException("Unable to read more data"); } if (!waitForMoreData(m_position >= m_data.length())) { throw ImapParserException("Unable to read more data"); } bool foundSlash = false; // quoted string if (m_data.at(m_position) == '"') { ++m_position; int i = m_position; for (;;) { if (!waitForMoreData(m_data.length() <= i)) { m_position = i; throw ImapParserException("Unable to read more data"); } if (m_data.at(i) == '\\') { i += 2; foundSlash = true; continue; } if (m_data.at(i) == '"') { result = m_data.mid(m_position, i - m_position); end = i + 1; // skip the '"' break; } ++i; } } // unquoted string else { bool reachedInputEnd = true; int i = m_position; for (;;) { if (!waitForMoreData(m_data.length() <= i)) { m_position = i; throw ImapParserException("Unable to read more data"); } if (m_data.at(i) == ' ' || m_data.at(i) == '(' || m_data.at(i) == ')' || m_data.at(i) == '[' || m_data.at(i) == ']' || m_data.at(i) == '\n' || m_data.at(i) == '\r' || m_data.at(i) == '"') { end = i; reachedInputEnd = false; break; } if (m_data.at(i) == '\\') { foundSlash = true; } i++; } if (reachedInputEnd) { // FIXME: how can it get here? end = m_data.length(); } result = m_data.mid(m_position, end - m_position); } // strip quotes if (foundSlash) { while (result.contains("\\\"")) { result.replace("\\\"", "\""); } while (result.contains("\\\\")) { result.replace("\\\\", "\\"); } } m_position = end; return result; } qint64 ImapStreamParser::readNumber(bool *ok) { qint64 result; if (ok) { *ok = false; } if (!waitForMoreData(m_data.length() == 0)) { throw ImapParserException("Unable to read more data"); } stripLeadingSpaces(); if (!waitForMoreData(m_position >= m_data.length())) { throw ImapParserException("Unable to read more data"); } if (m_position >= m_data.length()) { throw ImapParserException("Unable to read more data"); } int i = m_position; for (;;) { if (!waitForMoreData(m_data.length() <= i)) { m_position = i; throw ImapParserException("Unable to read more data"); } if (!isdigit(m_data.at(i))) { break; } ++i; } const auto tmp = QByteArrayView(m_data).mid(m_position, i - m_position); result = tmp.toLongLong(ok); m_position = i; return result; } void ImapStreamParser::stripLeadingSpaces() { for (int i = m_position; i < m_data.length(); ++i) { if (m_data.at(i) != ' ') { m_position = i; return; } } m_position = m_data.length(); } bool ImapStreamParser::waitForMoreData(bool wait) { if (wait) { if (m_socket->bytesAvailable() > 0 || m_socket->waitForReadyRead(30000)) { m_data.append(m_socket->readAll()); } else { return false; } } return true; } void ImapStreamParser::setData(const QByteArray &data) { m_data = data; } QByteArray ImapStreamParser::readRemainingData() { return m_data.mid(m_position); } int ImapStreamParser::availableDataSize() const { return m_socket->bytesAvailable() + m_data.size() - m_position; } bool ImapStreamParser::atCommandEnd() { int savedPos = m_position; do { if (!waitForMoreData(m_position >= m_data.length())) { throw ImapParserException("Unable to read more data"); } stripLeadingSpaces(); } while (m_position >= m_data.size()); if (m_data.at(m_position) == '\n' || m_data.at(m_position) == '\r') { if (m_data.at(m_position) == '\r') { ++m_position; } if (m_position < m_data.length() && m_data.at(m_position) == '\n') { ++m_position; } // We'd better empty m_data from time to time before it grows out of control trimBuffer(); return true; // command end } m_position = savedPos; return false; // something else } QByteArray ImapStreamParser::readUntilCommandEnd() { QByteArray result; int i = m_position; int paranthesisBalance = 0; for (;;) { if (!waitForMoreData(m_data.length() <= i)) { m_position = i; throw ImapParserException("Unable to read more data"); } if (m_data.at(i) == '{') { m_position = i - 1; hasLiteral(); // init literal size result.append(QByteArrayView(m_data).mid(i, m_position + 1)); while (!atLiteralEnd()) { result.append(readLiteralPart()); } i = m_position; } if (m_data.at(i) == '(') { paranthesisBalance++; } if (m_data.at(i) == ')') { paranthesisBalance--; } if ((i == m_data.length() && paranthesisBalance == 0) || m_data.at(i) == '\n' || m_data.at(i) == '\r') { break; // command end } result.append(m_data.at(i)); ++i; } m_position = i; atCommandEnd(); return result; } void ImapStreamParser::sendContinuationResponse(qint64 size) { QByteArray block = "+ Ready for literal data (expecting " + QByteArray::number(size) + " bytes)\r\n"; m_socket->write(block); m_socket->waitForBytesWritten(30000); } void ImapStreamParser::trimBuffer() { if (m_position < 4096) { // right() is expensive, so don't do it for every line return; } m_data = std::move(m_data).right(m_data.size() - m_position); m_position = 0; } 070701000000DB000081A400000000000000000000000166FAD7C000001639000000000000000000000000000000000000004000000000kimap-VERSIONgit.20240930T185424~db1f697/src/imapstreamparser.h/* SPDX-FileCopyrightText: 2006-2007 Volker Krause <vkrause@kde.org> SPDX-FileCopyrightText: 2009 Andras Mantia <amantia@kde.org> SPDX-License-Identifier: LGPL-2.0-or-later */ #pragma once #include "kimap_export.h" #include <exception> #include <QByteArray> #include <QList> #include <QString> class QIODevice; namespace KIMAP { class ImapParserException : public std::exception { public: explicit ImapParserException(const char *what) throw() : mWhat(what) { } explicit ImapParserException(const QByteArray &what) throw() : mWhat(what) { } explicit ImapParserException(const QString &what) throw() : mWhat(what.toUtf8()) { } ImapParserException(const ImapParserException &other) throw() : std::exception(other) , mWhat(other.what()) { } ~ImapParserException() throw() override { } const char *what() const throw() override { return mWhat.constData(); } virtual const char *type() const throw() { return "ImapParserException"; } private: QByteArray mWhat; }; /** Parser for IMAP messages that operates on a local socket stream. */ class KIMAP_EXPORT ImapStreamParser { public: /** * Construct the parser. * @param socket the local socket to work with. * @param serverModeEnabled true if the parser has to assume we're writing a server (e.g. sends * continuation message automatically) */ explicit ImapStreamParser(QIODevice *socket, bool serverModeEnabled = false); /** * Get a string from the message. If the upcoming data is not a quoted string, unquoted string or a literal, * the behavior is undefined. Use @ref hasString to be sure a string comes. This call might block. * @return the next string from the message as an utf8 string */ QString readUtf8String(); /** * Same as above, but without decoding it to utf8. * @return the next string from the message */ QByteArray readString(); /** * Get he next parenthesized list. If the upcoming data is not a parenthesized list, * the behavior is undefined. Use @ref hasList to be sure a string comes. This call might block. * @return the next parenthesized list. */ QList<QByteArray> readParenthesizedList(); /** * Get the next data as a number. This call might block. * @param ok true if the data found was a number * @return the number */ qint64 readNumber(bool *ok = nullptr); /** * Check if the next data is a string or not. This call might block. * @return true if a string follows */ bool hasString(); /** * Check if the next data is a literal data or not. If a literal is found, the * internal position pointer is set to the beginning of the literal data. * This call might block. * @return true if a literal follows */ bool hasLiteral(); /** * Read the next literal sequence. This might or might not be the full data. Example code to read a literal would be: * @code * ImapStreamParser parser; * ... * if (parser.hasLiteral()) * { * while (!parser.atLiteralEnd()) * { * QByteArray data = parser.readLiteralPart(); * // do something with the data * } * } * @endcode * * This call might block. * * @return part of a literal data */ QByteArray readLiteralPart(); /** * Check if the literal data end was reached. See @ref hasLiteral and @ref readLiteralPart . * @return true if the literal was completely read. */ bool atLiteralEnd() const; /** * Check if the next data is a parenthesized list. This call might block. * @return true if a parenthesized list comes. */ bool hasList(); /** * Check if the next data is a parenthesized list end. This call might block. * @return true if a parenthesized list end. */ bool atListEnd(); /** * Check if the next data is a response code. This call might block. * @return true if a response code comes. */ bool hasResponseCode(); /** * Check if the next data is a response code end. This call might block. * @return true if a response code end. */ bool atResponseCodeEnd(); /** * Check if the command end was reached * @return true if the end of command is reached */ bool atCommandEnd(); /** * Return everything that remained from the command. * @return the remaining command data */ QByteArray readUntilCommandEnd(); /** * Return all the data that was read from the socket, but not processed yet. * @return the remaining unprocessed data */ QByteArray readRemainingData(); int availableDataSize() const; void setData(const QByteArray &data); private: void stripLeadingSpaces(); QByteArray parseQuotedString(); /** * If the condition is true, wait for more data to be available from the socket. * If no data comes after a timeout (30000ms), it aborts and returns false. * @param wait the condition * @return true if more data is available */ bool waitForMoreData(bool wait); /** * Inform the client to send more literal data. */ void sendContinuationResponse(qint64 size); /** * Remove already read data from the internal buffer if necessary. */ void trimBuffer(); QIODevice *m_socket = nullptr; bool m_isServerModeEnabled = false; QByteArray m_data; int m_position = -1; qint64 m_literalSize = -1; }; } 070701000000DC000081A400000000000000000000000166FAD7C0000006D5000000000000000000000000000000000000003500000000kimap-VERSIONgit.20240930T185424~db1f697/src/job.cpp/* SPDX-FileCopyrightText: 2009 Kevin Ottens <ervin@kde.org> SPDX-License-Identifier: LGPL-2.0-or-later */ #include "job.h" #include "job_p.h" #include "response_p.h" #include "session_p.h" #include "kimap_debug.h" #include <KLocalizedString> using namespace KIMAP; Job::Job(Session *session) : KJob(session) , d_ptr(new JobPrivate(session, i18n("Job"))) { } Job::Job(JobPrivate &dd) : KJob(dd.m_session) , d_ptr(&dd) { } Job::~Job() { delete d_ptr; } Session *Job::session() const { Q_D(const Job); return d->m_session; } void Job::start() { Q_D(Job); d->sessionInternal()->addJob(this); } void Job::handleResponse(const Response &response) { handleErrorReplies(response); } void Job::connectionLost() { setError(KJob::UserDefinedError); setErrorText(i18n("Connection to server lost.")); emitResult(); } Job::HandlerResponse Job::handleErrorReplies(const Response &response) { Q_D(Job); // qCDebug(KIMAP_LOG) << response.toString(); if (!response.content.isEmpty() && d->tags.contains(response.content.first().toString())) { if (response.content.size() < 2) { setErrorText(i18n("%1 failed, malformed reply from the server.", d->m_name)); } else if (response.content[1].toString() != "OK") { setError(UserDefinedError); setErrorText(i18n("%1 failed, server replied: %2", d->m_name, QLatin1StringView(response.toString().constData()))); } d->tags.removeAll(response.content.first().toString()); if (d->tags.isEmpty()) { // Only emit result when the last command returned emitResult(); } return Handled; } return NotHandled; } #include "moc_job.cpp" 070701000000DD000081A400000000000000000000000166FAD7C00000034C000000000000000000000000000000000000003300000000kimap-VERSIONgit.20240930T185424~db1f697/src/job.h/* SPDX-FileCopyrightText: 2009 Kevin Ottens <ervin@kde.org> SPDX-License-Identifier: LGPL-2.0-or-later */ #pragma once #include "kimap_export.h" #include <KJob> namespace KIMAP { class Session; class SessionPrivate; class JobPrivate; struct Response; class KIMAP_EXPORT Job : public KJob { Q_OBJECT Q_DECLARE_PRIVATE(Job) friend class SessionPrivate; public: ~Job() override; Session *session() const; void start() override; private: virtual void doStart() = 0; virtual void handleResponse(const Response &response); virtual void connectionLost(); protected: enum HandlerResponse { Handled = 0, NotHandled }; HandlerResponse handleErrorReplies(const Response &response); explicit Job(Session *session); explicit Job(JobPrivate &dd); JobPrivate *const d_ptr; }; } 070701000000DE000081A400000000000000000000000166FAD7C000000365000000000000000000000000000000000000003500000000kimap-VERSIONgit.20240930T185424~db1f697/src/job_p.h/* SPDX-FileCopyrightText: 2009 Kevin Ottens <ervin@kde.org> SPDX-License-Identifier: LGPL-2.0-or-later */ #pragma once #include "session.h" #include <QAbstractSocket> namespace KIMAP { class SessionPrivate; class JobPrivate { public: JobPrivate(Session *session, const QString &name) : m_session(session) , m_name(name) { } virtual ~JobPrivate() { } inline SessionPrivate *sessionInternal() { return m_session->d; } inline const SessionPrivate *sessionInternal() const { return m_session->d; } void setSocketError(QAbstractSocket::SocketError error) { m_socketError = error; } QList<QByteArray> tags; Session *m_session = nullptr; QString m_name; QAbstractSocket::SocketError m_socketError = QAbstractSocket::UnknownSocketError; }; } 070701000000DF000081A400000000000000000000000166FAD7C000001685000000000000000000000000000000000000003900000000kimap-VERSIONgit.20240930T185424~db1f697/src/listjob.cpp/* SPDX-FileCopyrightText: 2009 Kevin Ottens <ervin@kde.org> SPDX-License-Identifier: LGPL-2.0-or-later */ #include "listjob.h" #include <KLocalizedString> #include <QTimer> #include "job_p.h" #include "response_p.h" #include "rfccodecs.h" #include "session_p.h" namespace KIMAP { class ListJobPrivate : public JobPrivate { public: ListJobPrivate(ListJob *job, Session *session, const QString &name) : JobPrivate(session, name) , q(job) , option(ListJob::NoOption) { } ~ListJobPrivate() { } void emitPendings() { if (pendingDescriptors.isEmpty()) { return; } Q_EMIT q->mailBoxesReceived(pendingDescriptors, pendingFlags); pendingDescriptors.clear(); pendingFlags.clear(); } ListJob *const q; ListJob::Option option; QList<MailBoxDescriptor> namespaces; QByteArray command; QTimer emitPendingsTimer; QList<MailBoxDescriptor> pendingDescriptors; QList<QList<QByteArray>> pendingFlags; }; } using namespace KIMAP; ListJob::ListJob(Session *session) : Job(*new ListJobPrivate(this, session, i18n("List"))) { Q_D(ListJob); connect(&d->emitPendingsTimer, &QTimer::timeout, this, [d]() { d->emitPendings(); }); } ListJob::~ListJob() { } void ListJob::setIncludeUnsubscribed(bool include) { Q_D(ListJob); if (include) { d->option = ListJob::IncludeUnsubscribed; } else { d->option = ListJob::NoOption; } } bool ListJob::isIncludeUnsubscribed() const { Q_D(const ListJob); return (d->option == ListJob::IncludeUnsubscribed); } void ListJob::setOption(Option option) { Q_D(ListJob); d->option = option; } ListJob::Option ListJob::option() const { Q_D(const ListJob); return d->option; } void ListJob::setQueriedNamespaces(const QList<MailBoxDescriptor> &namespaces) { Q_D(ListJob); d->namespaces = namespaces; } QList<MailBoxDescriptor> ListJob::queriedNamespaces() const { Q_D(const ListJob); return d->namespaces; } QList<MailBoxDescriptor> ListJob::mailBoxes() const { return QList<MailBoxDescriptor>(); } QMap<MailBoxDescriptor, QList<QByteArray>> ListJob::flags() const { return QMap<MailBoxDescriptor, QList<QByteArray>>(); } void ListJob::doStart() { Q_D(ListJob); switch (d->option) { case IncludeUnsubscribed: d->command = "LIST"; break; case IncludeFolderRoleFlags: d->command = "XLIST"; break; case NoOption: d->command = "LSUB"; } d->emitPendingsTimer.start(100); if (d->namespaces.isEmpty()) { d->tags << d->sessionInternal()->sendCommand(d->command, "\"\" *"); } else { for (const MailBoxDescriptor &descriptor : std::as_const(d->namespaces)) { QString parameters = QStringLiteral("\"\" \"%1\""); if (descriptor.name.endsWith(descriptor.separator)) { QString name = encodeImapFolderName(descriptor.name); name.chop(1); d->tags << d->sessionInternal()->sendCommand(d->command, parameters.arg(name).toUtf8()); } d->tags << d->sessionInternal()->sendCommand(d->command, parameters.arg(descriptor.name + QLatin1Char('*')).toUtf8()); } } } void ListJob::handleResponse(const Response &response) { Q_D(ListJob); // We can predict it'll be handled by handleErrorReplies() so stop // the timer now so that result() will really be the last emitted signal. if (!response.content.isEmpty() && d->tags.size() == 1 && d->tags.contains(response.content.first().toString())) { d->emitPendingsTimer.stop(); d->emitPendings(); } if (handleErrorReplies(response) == NotHandled) { if (response.content.size() >= 5 && response.content[1].toString() == d->command) { QList<QByteArray> flags = response.content[2].toList(); for (QList<QByteArray>::iterator it = flags.begin(), itEnd = flags.end(); it != itEnd; ++it) { *it = it->toLower(); } QByteArray separator = response.content[3].toString(); if (separator.isEmpty()) { // Defaults to / for servers reporting an empty list // it's supposedly not a problem as servers doing that // only do it for mailboxes with no child. separator = "/"; // krazy:exclude=doublequote_chars since a QByteArray } Q_ASSERT(separator.size() == 1); QByteArray fullName; for (int i = 4; i < response.content.size(); i++) { fullName += response.content[i].toString() + ' '; } fullName.chop(1); fullName = decodeImapFolderName(fullName); MailBoxDescriptor mailBoxDescriptor; mailBoxDescriptor.separator = QLatin1Char(separator[0]); mailBoxDescriptor.name = QString::fromUtf8(fullName); convertInboxName(mailBoxDescriptor); d->pendingDescriptors << mailBoxDescriptor; d->pendingFlags << flags; } } } void ListJob::convertInboxName(KIMAP::MailBoxDescriptor &descriptor) { // Inbox must be case sensitive, according to the RFC, so make it always uppercase QStringList pathParts = descriptor.name.split(descriptor.separator); if (!pathParts.isEmpty() && pathParts[0].compare(QLatin1StringView("INBOX"), Qt::CaseInsensitive) == 0) { pathParts.removeAt(0); descriptor.name = QStringLiteral("INBOX"); if (!pathParts.isEmpty()) { descriptor.name += descriptor.separator + pathParts.join(descriptor.separator); } } } #include "moc_listjob.cpp" 070701000000E0000081A400000000000000000000000166FAD7C000000983000000000000000000000000000000000000003700000000kimap-VERSIONgit.20240930T185424~db1f697/src/listjob.h/* SPDX-FileCopyrightText: 2009 Kevin Ottens <ervin@kde.org> SPDX-License-Identifier: LGPL-2.0-or-later */ #pragma once #include "kimap_export.h" #include "job.h" namespace KIMAP { class Session; struct Response; class ListJobPrivate; struct KIMAP_EXPORT MailBoxDescriptor { QString name; QChar separator; inline bool operator==(const MailBoxDescriptor &other) const { return other.name == name && other.separator == separator; } inline bool operator<(const MailBoxDescriptor &other) const { return other.name < name || (other.name == name && other.separator < separator); } }; class KIMAP_EXPORT ListJob : public Job { Q_OBJECT Q_DECLARE_PRIVATE(ListJob) friend class SessionPrivate; public: enum Option { NoOption = 0x0, /**< List only subscribed mailboxes. (Uses the LSUB IMAP command.) */ IncludeUnsubscribed, /**< List subscribed and unsubscribed mailboxes. (Uses the LIST IMAP command.) */ IncludeFolderRoleFlags /**< List subscribed and unsubscribed mailboxes with flags to identify standard mailboxes whose name may be localized. The server must support the XLIST extension. */ }; explicit ListJob(Session *session); ~ListJob() override; KIMAP_DEPRECATED void setIncludeUnsubscribed(bool include); KIMAP_DEPRECATED bool isIncludeUnsubscribed() const; void setOption(Option option); [[nodiscard]] Option option() const; void setQueriedNamespaces(const QList<MailBoxDescriptor> &namespaces); [[nodiscard]] QList<MailBoxDescriptor> queriedNamespaces() const; KIMAP_DEPRECATED QList<MailBoxDescriptor> mailBoxes() const; KIMAP_DEPRECATED QMap<MailBoxDescriptor, QList<QByteArray>> flags() const; Q_SIGNALS: void mailBoxesReceived(const QList<KIMAP::MailBoxDescriptor> &descriptors, const QList<QList<QByteArray>> &flags); protected: void doStart() override; void handleResponse(const Response &response) override; private: Q_PRIVATE_SLOT(d_func(), void emitPendings()) /** * @brief Converts a mailbox descriptor's name to uppercase if it is the Inbox or an Inbox subfolder. * This is according to the RFC3501, 5.1. Mailbox Naming section. * * @param descriptor the descriptor to convert, conversion happens in place **/ void convertInboxName(KIMAP::MailBoxDescriptor &descriptor); }; } 070701000000E1000081A400000000000000000000000166FAD7C000000825000000000000000000000000000000000000003F00000000kimap-VERSIONgit.20240930T185424~db1f697/src/listrightsjob.cpp/* SPDX-FileCopyrightText: 2009 Andras Mantia <amantia@kde.org> SPDX-License-Identifier: LGPL-2.0-or-later */ #include "listrightsjob.h" #include <KLocalizedString> #include "acljobbase_p.h" #include "response_p.h" #include "rfccodecs.h" #include "session_p.h" namespace KIMAP { class ListRightsJobPrivate : public AclJobBasePrivate { public: ListRightsJobPrivate(Session *session, const QString &name) : AclJobBasePrivate(session, name) , defaultRights(Acl::None) { } ~ListRightsJobPrivate() { } QList<Acl::Rights> possibleRights; Acl::Rights defaultRights; }; } using namespace KIMAP; ListRightsJob::ListRightsJob(Session *session) : AclJobBase(*new ListRightsJobPrivate(session, i18n("ListRights"))) { } ListRightsJob::~ListRightsJob() { } void ListRightsJob::doStart() { Q_D(ListRightsJob); d->tags << d->sessionInternal()->sendCommand("LISTRIGHTS", '\"' + KIMAP::encodeImapFolderName(d->mailBox.toUtf8()) + "\" \"" + d->id + "\""); } void ListRightsJob::handleResponse(const Response &response) { Q_D(ListRightsJob); if (handleErrorReplies(response) == NotHandled) { if (response.content.size() >= 4 && response.content[1].toString() == "LISTRIGHTS") { QByteArray s = response.content[4].toString(); d->defaultRights = Acl::rightsFromString(s); int i = 5; while (i < response.content.size()) { s = response.content[i].toString(); d->possibleRights.append(Acl::rightsFromString(s)); i++; } } } } void ListRightsJob::setIdentifier(const QByteArray &identifier) { Q_D(ListRightsJob); d->setIdentifier(identifier); } QByteArray ListRightsJob::identifier() { Q_D(ListRightsJob); return d->identifier(); } Acl::Rights ListRightsJob::defaultRights() { Q_D(ListRightsJob); return d->defaultRights; } QList<Acl::Rights> ListRightsJob::possibleRights() { Q_D(ListRightsJob); return d->possibleRights; } #include "moc_listrightsjob.cpp" 070701000000E2000081A400000000000000000000000166FAD7C000000B93000000000000000000000000000000000000003D00000000kimap-VERSIONgit.20240930T185424~db1f697/src/listrightsjob.h/* SPDX-FileCopyrightText: 2009 Andras Mantia <amantia@kde.org> SPDX-License-Identifier: LGPL-2.0-or-later */ #pragma once #include "kimap_export.h" #include "acljobbase.h" namespace KIMAP { class Session; struct Response; class ListRightsJobPrivate; /** * Lists the possible and automatic rights for * an identifier on a mailbox * * This job can only be run when the session is in the * authenticated (or selected) state. * * The user must have the Acl::Admin permission * on the mailbox for this job to succeed (see * MyRightsJob). * * This job requires that the server supports the ACL * capability, defined in * <a href="https://tools.ietf.org/html/rfc4314">RFC 4314</a>. */ class KIMAP_EXPORT ListRightsJob : public AclJobBase { Q_OBJECT Q_DECLARE_PRIVATE(ListRightsJob) friend class SessionPrivate; public: explicit ListRightsJob(Session *session); ~ListRightsJob() override; /** * Sets the identifier that should be looked up * * The meaning of identifiers depends on the server implementation, * with the following restrictions: * * - "anyone" means any authenticated user, including anonymous * - an identifier starting with a minus sign ('-') indicates * "negative rights": rights that should be taken away from * matching users * * Other than the above restrictions, ACL identifiers are usually * IMAP usernames, but could potentially be group names as well. * * Note that negative rights override positive rights: if * "fred" and "-fred" are both assigned the 'w' right, the * user "fred" will not have the 'w' right. * * @param identifier the identifier to list the rights for */ void setIdentifier(const QByteArray &identifier); /** * The identifier that will be looked up */ [[nodiscard]] QByteArray identifier(); /** * The rights that will always be assigned to the identifier, * regardless of the access control list. * * For example, under the UNIX permission model, the owner * of a mailbox will always have the Acl::Admin right. */ [[nodiscard]] Acl::Rights defaultRights(); /** * The rights it is possible to assign to the identifier. * * The rights are grouped by those that are tied together. * For each set of rights in the returned list, either all * or none of those rights may be set, but not only some of * them. * * For example, under the UNIX permission model, the following * rights are all controlled by the "write" flag, and hence * must either all be set or all be not set: * - Acl::KeepSeen * - Acl::Write * - Acl::Insert * - Acl::DeleteMessage * - Acl::Expunge */ [[nodiscard]] QList<Acl::Rights> possibleRights(); protected: void doStart() override; void handleResponse(const Response &response) override; }; } 070701000000E3000081A400000000000000000000000166FAD7C000004E3E000000000000000000000000000000000000003A00000000kimap-VERSIONgit.20240930T185424~db1f697/src/loginjob.cpp/* SPDX-FileCopyrightText: 2009 Kevin Ottens <ervin@kde.org> SPDX-FileCopyrightText: 2009 Andras Mantia <amantia@kde.org> SPDX-License-Identifier: LGPL-2.0-or-later */ #include "loginjob.h" #include <KLocalizedString> #include "kimap_debug.h" #include "capabilitiesjob.h" #include "job_p.h" #include "response_p.h" #include "rfccodecs.h" #include "session_p.h" #include "common.h" extern "C" { #include <sasl/sasl.h> } static const sasl_callback_t callbacks[] = {{SASL_CB_ECHOPROMPT, nullptr, nullptr}, {SASL_CB_NOECHOPROMPT, nullptr, nullptr}, {SASL_CB_GETREALM, nullptr, nullptr}, {SASL_CB_USER, nullptr, nullptr}, {SASL_CB_AUTHNAME, nullptr, nullptr}, {SASL_CB_PASS, nullptr, nullptr}, {SASL_CB_CANON_USER, nullptr, nullptr}, {SASL_CB_LIST_END, nullptr, nullptr}}; namespace KIMAP { class LoginJobPrivate : public JobPrivate { public: enum AuthState { PreStartTlsCapability = 0, StartTls, Capability, Login, Authenticate }; LoginJobPrivate(LoginJob *job, Session *session, const QString &name) : JobPrivate(session, name) , q(job) , encryptionMode(LoginJob::Unencrypted) , authState(Login) , plainLoginDisabled(false) { conn = nullptr; client_interact = nullptr; } ~LoginJobPrivate() { } bool sasl_interact(); bool startAuthentication(); bool answerChallenge(const QByteArray &data); void sslResponse(bool response); void saveServerGreeting(const Response &response); LoginJob *const q; QString userName; QString authorizationName; QString password; QString serverGreeting; LoginJob::EncryptionMode encryptionMode; QString authMode; AuthState authState; QStringList capabilities; bool plainLoginDisabled; sasl_conn_t *conn; sasl_interact_t *client_interact; }; } using namespace KIMAP; bool LoginJobPrivate::sasl_interact() { qCDebug(KIMAP_LOG) << "sasl_interact"; sasl_interact_t *interact = client_interact; // some mechanisms do not require username && pass, so it doesn't need a popup // window for getting this info for (; interact->id != SASL_CB_LIST_END; interact++) { if (interact->id == SASL_CB_AUTHNAME || interact->id == SASL_CB_PASS) { // TODO: dialog for use name?? break; } } interact = client_interact; while (interact->id != SASL_CB_LIST_END) { qCDebug(KIMAP_LOG) << "SASL_INTERACT id:" << interact->id; switch (interact->id) { case SASL_CB_AUTHNAME: if (!authorizationName.isEmpty()) { qCDebug(KIMAP_LOG) << "SASL_CB_[AUTHNAME]: '" << authorizationName << "'"; interact->result = strdup(authorizationName.toUtf8().constData()); interact->len = strlen((const char *)interact->result); break; } [[fallthrough]]; case SASL_CB_USER: qCDebug(KIMAP_LOG) << "SASL_CB_[USER|AUTHNAME]: '" << userName << "'"; interact->result = strdup(userName.toUtf8().constData()); interact->len = strlen((const char *)interact->result); break; case SASL_CB_PASS: qCDebug(KIMAP_LOG) << "SASL_CB_PASS: [hidden]"; interact->result = strdup(password.toUtf8().constData()); interact->len = strlen((const char *)interact->result); break; default: interact->result = nullptr; interact->len = 0; break; } interact++; } return true; } LoginJob::LoginJob(Session *session) : Job(*new LoginJobPrivate(this, session, i18n("Login"))) { Q_D(LoginJob); qCDebug(KIMAP_LOG) << this; } LoginJob::~LoginJob() { qCDebug(KIMAP_LOG) << this; } QString LoginJob::userName() const { Q_D(const LoginJob); return d->userName; } void LoginJob::setUserName(const QString &userName) { Q_D(LoginJob); d->userName = userName; } QString LoginJob::authorizationName() const { Q_D(const LoginJob); return d->authorizationName; } void LoginJob::setAuthorizationName(const QString &authorizationName) { Q_D(LoginJob); d->authorizationName = authorizationName; } QString LoginJob::password() const { Q_D(const LoginJob); return d->password; } void LoginJob::setPassword(const QString &password) { Q_D(LoginJob); d->password = password; } void LoginJob::doStart() { Q_D(LoginJob); qCDebug(KIMAP_LOG) << this; // Don't authenticate on a session in the authenticated state if (session()->state() == Session::Authenticated || session()->state() == Session::Selected) { setError(UserDefinedError); setErrorText(i18n("IMAP session in the wrong state for authentication")); emitResult(); return; } // Get notified once encryption is successfully negotiated connect(d->sessionInternal(), &KIMAP::SessionPrivate::encryptionNegotiationResult, this, [d](bool result) { d->sslResponse(result); }); // Trigger encryption negotiation only if needed EncryptionMode encryptionMode = d->encryptionMode; const auto negotiatedEncryption = d->sessionInternal()->negotiatedEncryption(); if (negotiatedEncryption != QSsl::UnknownProtocol) { // If the socket is already encrypted, proceed to the next state d->sslResponse(true); return; } if (encryptionMode == SSLorTLS) { // Negotiation got started by Session, but didn't complete yet. Continue in sslResponse. } else if (encryptionMode == STARTTLS) { // Check if STARTTLS is supported d->authState = LoginJobPrivate::PreStartTlsCapability; d->tags << d->sessionInternal()->sendCommand("CAPABILITY"); } else if (encryptionMode == Unencrypted) { if (d->authMode.isEmpty()) { d->authState = LoginJobPrivate::Login; qCDebug(KIMAP_LOG) << "sending LOGIN"; d->tags << d->sessionInternal()->sendCommand("LOGIN", '"' + quoteIMAP(d->userName).toUtf8() + '"' + ' ' + '"' + quoteIMAP(d->password).toUtf8() + '"'); } else { if (!d->startAuthentication()) { emitResult(); } } } } void LoginJob::handleResponse(const Response &response) { Q_D(LoginJob); if (response.content.isEmpty()) { return; } // set the actual command name for standard responses QString commandName = i18n("Login"); if (d->authState == LoginJobPrivate::Capability) { commandName = i18n("Capability"); } else if (d->authState == LoginJobPrivate::StartTls) { commandName = i18n("StartTls"); } enum ResponseCode { OK, ERR, UNTAGGED, CONTINUATION, MALFORMED }; QByteArray tag = response.content.first().toString(); ResponseCode code = OK; qCDebug(KIMAP_LOG) << commandName << tag; if (tag == "+") { code = CONTINUATION; } else if (tag == "*") { if (response.content.size() < 2) { code = MALFORMED; // Received empty untagged response } else { code = UNTAGGED; } } else if (d->tags.contains(tag)) { if (response.content.size() < 2) { code = MALFORMED; } else if (response.content[1].toString() == "OK") { code = OK; } else { code = ERR; } } switch (code) { case MALFORMED: // We'll handle it later break; case ERR: // server replied with NO or BAD for SASL authentication if (d->authState == LoginJobPrivate::Authenticate) { sasl_dispose(&d->conn); } setError(UserDefinedError); setErrorText(i18n("%1 failed, server replied: %2", commandName, QLatin1StringView(response.toString().constData()))); emitResult(); return; case UNTAGGED: // The only untagged response interesting for us here is CAPABILITY if (response.content[1].toString() == "CAPABILITY") { d->capabilities.clear(); QList<Response::Part>::const_iterator p = response.content.begin() + 2; while (p != response.content.end()) { QString capability = QLatin1StringView(p->toString()); d->capabilities << capability; if (capability == QLatin1StringView("LOGINDISABLED")) { d->plainLoginDisabled = true; } ++p; } qCDebug(KIMAP_LOG) << "Capabilities updated: " << d->capabilities; } break; case CONTINUATION: if (d->authState != LoginJobPrivate::Authenticate) { // Received unexpected continuation response for something // other than AUTHENTICATE command code = MALFORMED; break; } if (d->authMode == QLatin1StringView("PLAIN")) { if (response.content.size() > 1 && response.content.at(1).toString() == "OK") { return; } QByteArray challengeResponse; if (!d->authorizationName.isEmpty()) { challengeResponse += d->authorizationName.toUtf8(); } challengeResponse += '\0'; challengeResponse += d->userName.toUtf8(); challengeResponse += '\0'; challengeResponse += d->password.toUtf8(); challengeResponse = challengeResponse.toBase64(); d->sessionInternal()->sendData(challengeResponse); } else if (response.content.size() >= 2) { if (!d->answerChallenge(QByteArray::fromBase64(response.content[1].toString()))) { emitResult(); // error, we're done } } else { // Received empty continuation for authMode other than PLAIN code = MALFORMED; } break; case OK: switch (d->authState) { case LoginJobPrivate::PreStartTlsCapability: if (d->capabilities.contains(QLatin1StringView("STARTTLS"))) { d->authState = LoginJobPrivate::StartTls; d->tags << d->sessionInternal()->sendCommand("STARTTLS"); } else { qCWarning(KIMAP_LOG) << "STARTTLS not supported by server!"; setError(UserDefinedError); setErrorText(i18n("STARTTLS is not supported by the server, try using SSL/TLS instead.")); emitResult(); } break; case LoginJobPrivate::StartTls: d->sessionInternal()->startSsl(QSsl::SecureProtocols); break; case LoginJobPrivate::Capability: // If encryption was requested, verify that it's negotiated before logging in if (d->encryptionMode != Unencrypted && d->sessionInternal()->negotiatedEncryption() == QSsl::UnknownProtocol) { setError(LoginJob::UserDefinedError); setErrorText(i18n("Internal error, tried to login before encryption")); emitResult(); break; } // cleartext login, if enabled if (d->authMode.isEmpty()) { if (d->plainLoginDisabled) { setError(UserDefinedError); setErrorText(i18n("Login failed, plain login is disabled by the server.")); emitResult(); } else { d->authState = LoginJobPrivate::Login; d->tags << d->sessionInternal()->sendCommand("LOGIN", '"' + quoteIMAP(d->userName).toUtf8() + '"' + ' ' + '"' + quoteIMAP(d->password).toUtf8() + '"'); } } else { bool authModeSupported = false; // find the selected SASL authentication method for (const QString &capability : std::as_const(d->capabilities)) { if (capability.startsWith(QLatin1StringView("AUTH="))) { if (QStringView(capability).mid(5) == d->authMode) { authModeSupported = true; break; } } } if (!authModeSupported) { setError(UserDefinedError); setErrorText(i18n("Login failed, authentication mode %1 is not supported by the server.", d->authMode)); emitResult(); } else if (!d->startAuthentication()) { emitResult(); // problem, we're done } } break; case LoginJobPrivate::Authenticate: sasl_dispose(&d->conn); // SASL authentication done // Fall through [[fallthrough]]; case LoginJobPrivate::Login: d->saveServerGreeting(response); emitResult(); // got an OK, command done break; } } if (code == MALFORMED) { setErrorText(i18n("%1 failed, malformed reply from the server.", commandName)); emitResult(); } } bool LoginJobPrivate::startAuthentication() { // SASL authentication if (!initSASL()) { q->setError(LoginJob::UserDefinedError); q->setErrorText(i18n("Login failed, client cannot initialize the SASL library.")); return false; } authState = LoginJobPrivate::Authenticate; const char *out = nullptr; uint outlen = 0; const char *mechusing = nullptr; int result = sasl_client_new("imap", m_session->hostName().toLatin1().constData(), nullptr, nullptr, callbacks, 0, &conn); if (result != SASL_OK) { const QString saslError = QString::fromUtf8(sasl_errdetail(conn)); qCWarning(KIMAP_LOG) << "sasl_client_new failed with:" << result << saslError; q->setError(LoginJob::UserDefinedError); q->setErrorText(saslError); return false; } do { qCDebug(KIMAP_LOG) << "Trying authmod" << authMode.toLatin1(); result = sasl_client_start(conn, authMode.toLatin1().constData(), &client_interact, capabilities.contains(QLatin1StringView("SASL-IR")) ? &out : nullptr, &outlen, &mechusing); if (result == SASL_INTERACT) { if (!sasl_interact()) { sasl_dispose(&conn); q->setError(LoginJob::UserDefinedError); // TODO: check up the actual error return false; } } } while (result == SASL_INTERACT); if (result != SASL_CONTINUE && result != SASL_OK) { const QString saslError = QString::fromUtf8(sasl_errdetail(conn)); qCWarning(KIMAP_LOG) << "sasl_client_start failed with:" << result << saslError; q->setError(LoginJob::UserDefinedError); q->setErrorText(saslError); sasl_dispose(&conn); return false; } QByteArray tmp = QByteArray::fromRawData(out, outlen); QByteArray challenge = tmp.toBase64(); if (challenge.isEmpty()) { tags << sessionInternal()->sendCommand("AUTHENTICATE", authMode.toLatin1()); } else { tags << sessionInternal()->sendCommand("AUTHENTICATE", authMode.toLatin1() + ' ' + challenge); } return true; } bool LoginJobPrivate::answerChallenge(const QByteArray &data) { QByteArray challenge = data; int result = -1; const char *out = nullptr; uint outlen = 0; do { result = sasl_client_step(conn, challenge.isEmpty() ? nullptr : challenge.data(), challenge.size(), &client_interact, &out, &outlen); if (result == SASL_INTERACT) { if (!sasl_interact()) { q->setError(LoginJob::UserDefinedError); // TODO: check up the actual error sasl_dispose(&conn); return false; } } } while (result == SASL_INTERACT); if (result != SASL_CONTINUE && result != SASL_OK) { const QString saslError = QString::fromUtf8(sasl_errdetail(conn)); qCWarning(KIMAP_LOG) << "sasl_client_step failed with:" << result << saslError; q->setError(LoginJob::UserDefinedError); // TODO: check up the actual error q->setErrorText(saslError); sasl_dispose(&conn); return false; } QByteArray tmp = QByteArray::fromRawData(out, outlen); challenge = tmp.toBase64(); sessionInternal()->sendData(challenge); return true; } void LoginJobPrivate::sslResponse(bool response) { if (response) { authState = LoginJobPrivate::Capability; tags << sessionInternal()->sendCommand("CAPABILITY"); } else { q->setError(LoginJob::UserDefinedError); q->setErrorText(i18n("Login failed, TLS negotiation failed.")); encryptionMode = LoginJob::Unencrypted; q->emitResult(); } } void LoginJob::setEncryptionMode(EncryptionMode mode) { Q_D(LoginJob); d->encryptionMode = mode; } LoginJob::EncryptionMode LoginJob::encryptionMode() { Q_D(LoginJob); return d->encryptionMode; } void LoginJob::setAuthenticationMode(AuthenticationMode mode) { Q_D(LoginJob); switch (mode) { case ClearText: d->authMode = QLatin1StringView(""); break; case Login: d->authMode = QStringLiteral("LOGIN"); break; case Plain: d->authMode = QStringLiteral("PLAIN"); break; case CramMD5: d->authMode = QStringLiteral("CRAM-MD5"); break; case DigestMD5: d->authMode = QStringLiteral("DIGEST-MD5"); break; case GSSAPI: d->authMode = QStringLiteral("GSSAPI"); break; case Anonymous: d->authMode = QStringLiteral("ANONYMOUS"); break; case XOAuth2: d->authMode = QStringLiteral("XOAUTH2"); break; default: d->authMode = QString(); } } void LoginJob::connectionLost() { Q_D(LoginJob); qCWarning(KIMAP_LOG) << "Connection to server lost " << d->m_socketError; if (d->m_socketError == QAbstractSocket::SslHandshakeFailedError) { setError(KJob::UserDefinedError); setErrorText(i18n("SSL handshake failed.")); emitResult(); } else { setError(ERR_COULD_NOT_CONNECT); setErrorText(i18n("Connection to server lost.")); emitResult(); } } void LoginJobPrivate::saveServerGreeting(const Response &response) { // Concatenate the parts of the server response into a string, while dropping the first two parts // (the response tag and the "OK" code), and being careful not to add useless extra whitespace. for (int i = 2; i < response.content.size(); i++) { if (response.content.at(i).type() == Response::Part::List) { serverGreeting += QLatin1Char('('); const QList<QByteArray> itemLst = response.content.at(i).toList(); for (const QByteArray &item : itemLst) { serverGreeting += QLatin1StringView(item) + QLatin1Char(' '); } serverGreeting.chop(1); serverGreeting += QStringLiteral(") "); } else { serverGreeting += QLatin1StringView(response.content.at(i).toString()) + QLatin1Char(' '); } } serverGreeting.chop(1); } QString LoginJob::serverGreeting() const { Q_D(const LoginJob); return d->serverGreeting; } #include "moc_loginjob.cpp" 070701000000E4000081A400000000000000000000000166FAD7C000000D36000000000000000000000000000000000000003800000000kimap-VERSIONgit.20240930T185424~db1f697/src/loginjob.h/* SPDX-FileCopyrightText: 2009 Kevin Ottens <ervin@kde.org> SPDX-FileCopyrightText: 2009 Andras Mantia <amantia@kde.org> SPDX-License-Identifier: LGPL-2.0-or-later */ #pragma once #include "kimap_export.h" #include "job.h" namespace KIMAP { class Session; struct Response; class LoginJobPrivate; class KIMAP_EXPORT LoginJob : public Job { Q_OBJECT Q_DECLARE_PRIVATE(LoginJob) friend class SessionPrivate; public: enum EncryptionMode { Unencrypted = 0, SSLorTLS, /*!< Use SSL/TLS encryption, KIMAP will automatically negotiate the best supported encryption protocol. */ STARTTLS /*!< Use STARTTLS to upgrade an initially plaintext connection to encrypted connection. KIMAP will automatically negotiate the best supported encryption protocol. */ }; Q_ENUM(EncryptionMode) enum AuthenticationMode { ClearText = 0, Login, Plain, CramMD5, DigestMD5, NTLM, GSSAPI, Anonymous, XOAuth2, }; Q_ENUM(AuthenticationMode) enum ErrorCode { ERR_COULD_NOT_CONNECT = KJob::UserDefinedError + 23 // same as in kio }; explicit LoginJob(Session *session); ~LoginJob() override; [[nodiscard]] QString userName() const; void setUserName(const QString &userName); /** * Get the authorization identity. * @since 4.10 */ [[nodiscard]] QString authorizationName() const; /** * Set the authorization identity. * * If set, proxy-authentication according to RFC4616 will be used. * * Note that this feature only works with the "PLAIN" AuthenticationMode. * * The @param authorizationName will be used together with the password() to get authenticated as userName() by the authorization of the provided * credentials. This allows to login as a user using the admin credentials and the users name. * @since 4.10 */ void setAuthorizationName(const QString &authorizationName); [[nodiscard]] QString password() const; void setPassword(const QString &password); /** * Returns the server greeting, in case of a successful login. * If the login wasn't successful, this method returns an empty string. Use errorString() to * get the error message in this case. * * Note that the content of this response is not defined by the IMAP protocol and is * implementation-dependent. * @since 4.7 */ [[nodiscard]] QString serverGreeting() const; /** * Set the encryption mode for the connection. In case an encryption mode is set, the caller * MUST check the encryptionMode() result after executing the job, to see if the connection is * encrypted or not (e.g handshaking failed). * @param mode the encryption mode, see EncryptionModes */ void setEncryptionMode(EncryptionMode mode); /** Get the encryption mode. @return the currently active encryption mode */ [[nodiscard]] EncryptionMode encryptionMode(); void setAuthenticationMode(AuthenticationMode mode); protected: void doStart() override; void handleResponse(const Response &response) override; void connectionLost() override; private: Q_PRIVATE_SLOT(d_func(), void sslResponse(bool)) }; } 070701000000E5000081A400000000000000000000000166FAD7C000000329000000000000000000000000000000000000003B00000000kimap-VERSIONgit.20240930T185424~db1f697/src/logoutjob.cpp/* SPDX-FileCopyrightText: 2009 Kevin Ottens <ervin@kde.org> SPDX-License-Identifier: LGPL-2.0-or-later */ #include "logoutjob.h" #include <KLocalizedString> #include "job_p.h" #include "response_p.h" #include "session_p.h" namespace KIMAP { class LogoutJobPrivate : public JobPrivate { public: LogoutJobPrivate(Session *session, const QString &name) : JobPrivate(session, name) { } ~LogoutJobPrivate() { } }; } using namespace KIMAP; LogoutJob::LogoutJob(Session *session) : Job(*new LogoutJobPrivate(session, i18n("Logout"))) { } LogoutJob::~LogoutJob() { } void LogoutJob::doStart() { Q_D(LogoutJob); d->tags << d->sessionInternal()->sendCommand("LOGOUT"); } void LogoutJob::connectionLost() { emitResult(); } #include "moc_logoutjob.cpp" 070701000000E6000081A400000000000000000000000166FAD7C000000207000000000000000000000000000000000000003900000000kimap-VERSIONgit.20240930T185424~db1f697/src/logoutjob.h/* SPDX-FileCopyrightText: 2009 Kevin Ottens <ervin@kde.org> SPDX-License-Identifier: LGPL-2.0-or-later */ #pragma once #include "kimap_export.h" #include "job.h" namespace KIMAP { class Session; class LogoutJobPrivate; class KIMAP_EXPORT LogoutJob : public Job { Q_OBJECT Q_DECLARE_PRIVATE(LogoutJob) friend class SessionPrivate; public: explicit LogoutJob(Session *session); ~LogoutJob() override; protected: void doStart() override; void connectionLost() override; }; } 070701000000E7000081A400000000000000000000000166FAD7C0000008B5000000000000000000000000000000000000004100000000kimap-VERSIONgit.20240930T185424~db1f697/src/metadatajobbase.cpp/* SPDX-FileCopyrightText: 2009 Andras Mantia <amantia@kde.org> SPDX-License-Identifier: LGPL-2.0-or-later */ #include "metadatajobbase.h" #include "metadatajobbase_p.h" #include "response_p.h" #include "session_p.h" #include <KLocalizedString> using namespace KIMAP; QByteArray MetaDataJobBasePrivate::addPrefix(const QByteArray &entry, const QByteArray &attribute) const { if (serverCapability == MetaDataJobBase::Annotatemore) { if (attribute == "value.shared") { return QByteArray("/shared").append(entry); } else if (attribute == "value.priv") { return QByteArray("/private").append(entry); } } return entry; } QByteArray MetaDataJobBasePrivate::removePrefix(const QByteArray &entry) const { if (serverCapability == MetaDataJobBase::Annotatemore) { if (entry.startsWith("/shared")) { return entry.mid(QByteArray("/shared").size()); } else if (entry.startsWith("/private")) { return entry.mid(QByteArray("/private").size()); } } return entry; } QByteArray MetaDataJobBasePrivate::getAttribute(const QByteArray &entry) const { if (serverCapability == MetaDataJobBase::Annotatemore) { if (entry.startsWith("/shared")) { return QByteArray("value.shared"); } else if (entry.startsWith("/private")) { return QByteArray("value.priv"); } } return QByteArray(); } MetaDataJobBase::MetaDataJobBase(Session *session) : Job(*new MetaDataJobBasePrivate(session, i18n("MetaDataJobBase"))) { } MetaDataJobBase::MetaDataJobBase(JobPrivate &dd) : Job(dd) { } MetaDataJobBase::~MetaDataJobBase() { } void MetaDataJobBase::setMailBox(const QString &mailBox) { Q_D(MetaDataJobBase); d->mailBox = mailBox; } QString MetaDataJobBase::mailBox() const { Q_D(const MetaDataJobBase); return d->mailBox; } void MetaDataJobBase::setServerCapability(ServerCapability capability) { Q_D(MetaDataJobBase); d->serverCapability = capability; } MetaDataJobBase::ServerCapability MetaDataJobBase::serverCapability() const { Q_D(const MetaDataJobBase); return d->serverCapability; } #include "moc_metadatajobbase.cpp" 070701000000E8000081A400000000000000000000000166FAD7C000000C54000000000000000000000000000000000000003F00000000kimap-VERSIONgit.20240930T185424~db1f697/src/metadatajobbase.h/* SPDX-FileCopyrightText: 2009 Andras Mantia <amantia@kde.org> SPDX-License-Identifier: LGPL-2.0-or-later */ #pragma once #include "kimap_export.h" #include "job.h" namespace KIMAP { class Session; struct Response; class MetaDataJobBasePrivate; /** * Base class for jobs that operate on mailbox metadata * * Provides support for the IMAP METADATA extension; both the * final RFC version * (<a href="https://tools.ietf.org/html/rfc5464">RFC 5464</a>) * and the older, incompatible draft version (known as ANNOTATEMORE) * (<a * href="https://tools.ietf.org/html/draft-daboo-imap-annotatemore-07" * >draft-daboo-imap-annotatemore-07</a>). * * This class cannot be used directly, you must subclass it and reimplement * at least the doStart() method. */ class KIMAP_EXPORT MetaDataJobBase : public Job { Q_OBJECT Q_DECLARE_PRIVATE(MetaDataJobBase) friend class SessionPrivate; public: explicit MetaDataJobBase(Session *session); ~MetaDataJobBase() override; /** * Represents the capability level of the server. */ enum ServerCapability { /** * Used to indicate that the server supports the RFC 5464 version * of the extension. * * This corresponds to the METADATA server capability. */ Metadata = 0, /** * Used to indicate that the server supports the * draft-daboo-imap-annotatemore-07 version of the extension. * * This corresponds to the ANNOTATEMORE server capability. */ Annotatemore }; /** * Set the mailbox to act on * * This may be an empty string, in which case metadata for the * server (rather than a specific mailbox) will be retrieved. * * @param mailBox the name of an existing mailbox, or an empty string */ void setMailBox(const QString &mailBox); /** * The mailbox that will be acted upon. * * If this is an empty string, server metadata will be retrieved. * * @return a mailbox name, or an empty string */ [[nodiscard]] QString mailBox() const; /** * Set what version of the metadata extension to be compatible with. * * This will determine the commands that will be sent to the server. * * The draft for the metadata extension changed in an incompatible * way between versions 7 and 8, and some servers support version 7. * It should be possible to check which version the server supports * using CapabilityJob: servers implementing * draft-daboo-imap-annotatemore-07 should advertise the * ANNOTATEMORE capability, whereas servers implementing the final * RFC 5464 should advertise the METADATA capability. * * The default mode is Metadata. * * @param capability the version of the extension implemented by the server */ void setServerCapability(ServerCapability capability); /** * The version of the metadata extension that will be used. */ [[nodiscard]] ServerCapability serverCapability() const; protected: MetaDataJobBase(JobPrivate &dd); }; } 070701000000E9000081A400000000000000000000000166FAD7C000000322000000000000000000000000000000000000004100000000kimap-VERSIONgit.20240930T185424~db1f697/src/metadatajobbase_p.h/* SPDX-FileCopyrightText: 2009 Andras Mantia <amantia@kde.org> SPDX-License-Identifier: LGPL-2.0-or-later */ #pragma once #include "job_p.h" #include "metadatajobbase.h" #include "response_p.h" #include "session.h" namespace KIMAP { class MetaDataJobBasePrivate : public JobPrivate { public: MetaDataJobBasePrivate(Session *session, const QString &name) : JobPrivate(session, name) , serverCapability(MetaDataJobBase::Metadata) { } ~MetaDataJobBasePrivate() { } QByteArray addPrefix(const QByteArray &entry, const QByteArray &attribute) const; QByteArray removePrefix(const QByteArray &) const; QByteArray getAttribute(const QByteArray &entry) const; MetaDataJobBase::ServerCapability serverCapability; QString mailBox; }; } 070701000000EA000081A400000000000000000000000166FAD7C00000091E000000000000000000000000000000000000003900000000kimap-VERSIONgit.20240930T185424~db1f697/src/movejob.cpp/* SPDX-FileCopyrightText: 2016 Daniel Vrátil <dvratil@kde.org> SPDX-License-Identifier: LGPL-2.0-or-later */ #include "movejob.h" #include "job_p.h" #include "response_p.h" #include "rfccodecs.h" #include "session_p.h" #include <KLocalizedString> // TODO: when custom error codes are introduced, handle the NO [TRYCREATE] response namespace KIMAP { class MoveJobPrivate : public JobPrivate { public: MoveJobPrivate(Session *session, const QString &name) : JobPrivate(session, name) { } ~MoveJobPrivate() { } QString mailBox; ImapSet set; ImapSet resultingUids; bool uidBased = false; }; } using namespace KIMAP; MoveJob::MoveJob(Session *session) : Job(*new MoveJobPrivate(session, i18n("Move"))) { Q_D(MoveJob); d->uidBased = false; } MoveJob::~MoveJob() { } void MoveJob::setMailBox(const QString &mailBox) { Q_D(MoveJob); d->mailBox = mailBox; } QString MoveJob::mailBox() const { Q_D(const MoveJob); return d->mailBox; } void MoveJob::setSequenceSet(const ImapSet &set) { Q_D(MoveJob); d->set = set; } ImapSet MoveJob::sequenceSet() const { Q_D(const MoveJob); return d->set; } void MoveJob::setUidBased(bool uidBased) { Q_D(MoveJob); d->uidBased = uidBased; } bool MoveJob::isUidBased() const { Q_D(const MoveJob); return d->uidBased; } ImapSet MoveJob::resultingUids() const { Q_D(const MoveJob); return d->resultingUids; } void MoveJob::doStart() { Q_D(MoveJob); d->set.optimize(); QByteArray parameters = d->set.toImapSequenceSet() + ' '; parameters += '\"' + KIMAP::encodeImapFolderName(d->mailBox.toUtf8()) + '\"'; QByteArray command = "MOVE"; if (d->uidBased) { command = "UID " + command; } d->tags << d->sessionInternal()->sendCommand(command, parameters); } void MoveJob::handleResponse(const Response &response) { Q_D(MoveJob); for (auto it = response.responseCode.cbegin(), end = response.responseCode.cend(); it != end; ++it) { if (it->toString() == "COPYUID") { it = it + 3; if (it < end) { d->resultingUids = ImapSet::fromImapSequenceSet(it->toString()); } break; } } handleErrorReplies(response); } #include "moc_movejob.cpp" 070701000000EB000081A400000000000000000000000166FAD7C000000BBD000000000000000000000000000000000000003700000000kimap-VERSIONgit.20240930T185424~db1f697/src/movejob.h/* SPDX-FileCopyrightText: 2016 Daniel Vrátil <dvratil@kde.org> SPDX-License-Identifier: LGPL-2.0-or-later */ #pragma once #include "kimap_export.h" #include "imapset.h" #include "job.h" namespace KIMAP { class MoveJobPrivate; /** * Moves messages from current mailbox to another * * Note that move functionality is not specified in the base IMAP * protocol and is defined as an extension in RFC6851. That means * that the MoveJob can only be used when the server lists "MOVE" * in response to CAPABILITY command. * * Unlike the traditional emulation of moving messages, i.e. COPY + STORE + EXPUNGE, * MOVE guarantees the transaction to be atomic on the server. * * @since 5.4 */ class KIMAP_EXPORT MoveJob : public Job { Q_OBJECT Q_DECLARE_PRIVATE(MoveJob) friend class SessionPrivate; public: explicit MoveJob(Session *session); ~MoveJob() override; /** * Set the destination mailbox * * If the mailbox does not exist, the server should not create * it automatically and the job should fail. Note, however, * that a conforming server may create the mailbox automatically. * * @param mailBox the (unquoted) name of the mailbox where the * messages should be moved to */ void setMailBox(const QString &mailbox); /** * The destination mailbox */ [[nodiscard]] QString mailBox() const; /** * Sets the messages to be moved, * * If sequence numbers are given, isUidBased() should be false. If UIDs * are given, isUidBased() should be true. * * @param set the sequence numbers or UIDs of the messages to be moved */ void setSequenceSet(const ImapSet &set); /** * The messages that will be moved. * * isUidBased() can be used to check whether the ImapSet contains * sequence numbers or UIDs. * * @return the sequence numbers or UIDs of the messages to be moved */ [[nodiscard]] ImapSet sequenceSet() const; /** * Set how the sequence set should be interpreted. * * @param uidBased if @c true the argument to setSequenceSet will be * interpreted as UIDs, if @c false it will be interpreted * as sequence numbers */ void setUidBased(bool uidBased); /** * How to interpret the sequence set. * * @return if @c true the result of sequenceSet() should be * interpreted as UIDs, if @c false it should be interpreted * as sequence numbers */ [[nodiscard]] bool isUidBased() const; /** * The UIDs of the moved messages in the destination mailbox. * * This will be an empty set if no messages have been moved yet * or if the server does not support the UIDPLUS extension. */ [[nodiscard]] ImapSet resultingUids() const; protected: void doStart() override; void handleResponse(const Response &response) override; }; } 070701000000EC000081A400000000000000000000000166FAD7C0000005CB000000000000000000000000000000000000003D00000000kimap-VERSIONgit.20240930T185424~db1f697/src/myrightsjob.cpp/* SPDX-FileCopyrightText: 2009 Andras Mantia <amantia@kde.org> SPDX-License-Identifier: LGPL-2.0-or-later */ #include "myrightsjob.h" #include <KLocalizedString> #include "acljobbase_p.h" #include "response_p.h" #include "rfccodecs.h" #include "session_p.h" namespace KIMAP { class MyRightsJobPrivate : public AclJobBasePrivate { public: MyRightsJobPrivate(Session *session, const QString &name) : AclJobBasePrivate(session, name) , myRights(Acl::None) { } ~MyRightsJobPrivate() { } Acl::Rights myRights; }; } using namespace KIMAP; MyRightsJob::MyRightsJob(Session *session) : AclJobBase(*new MyRightsJobPrivate(session, i18n("MyRights"))) { } MyRightsJob::~MyRightsJob() { } void MyRightsJob::doStart() { Q_D(MyRightsJob); d->tags << d->sessionInternal()->sendCommand("MYRIGHTS", '\"' + KIMAP::encodeImapFolderName(d->mailBox.toUtf8()) + '\"'); } void MyRightsJob::handleResponse(const Response &response) { Q_D(MyRightsJob); if (handleErrorReplies(response) == NotHandled) { if (response.content.size() == 4 && response.content[1].toString() == "MYRIGHTS") { d->myRights = Acl::rightsFromString(response.content[3].toString()); } } } bool MyRightsJob::hasRightEnabled(Acl::Right right) { Q_D(MyRightsJob); return d->myRights & right; } Acl::Rights MyRightsJob::rights() { Q_D(MyRightsJob); return d->myRights; } #include "moc_myrightsjob.cpp" 070701000000ED000081A400000000000000000000000166FAD7C0000006C1000000000000000000000000000000000000003B00000000kimap-VERSIONgit.20240930T185424~db1f697/src/myrightsjob.h/* SPDX-FileCopyrightText: 2009 Andras Mantia <amantia@kde.org> SPDX-License-Identifier: LGPL-2.0-or-later */ #pragma once #include "kimap_export.h" #include "acljobbase.h" namespace KIMAP { class Session; struct Response; class MyRightsJobPrivate; /** * Determine the rights the currently-logged-in user * has on the current mailbox. * * This should take into account the full access control * list. * * This job can only be run when the session is in the * authenticated (or selected) state. * * The current user must have one of the following rights * on the mailbox for this job to succeed: * - Acl::Lookup * - Acl::Read * - Acl::Insert * - Acl::CreateMailbox * - Acl::DeleteMailbox * - Acl::Admin * * This job requires that the server supports the ACL * capability, defined in * <a href="https://tools.ietf.org/html/rfc4314">RFC 4314</a>. */ class KIMAP_EXPORT MyRightsJob : public AclJobBase { Q_OBJECT Q_DECLARE_PRIVATE(MyRightsJob) friend class SessionPrivate; public: explicit MyRightsJob(Session *session); ~MyRightsJob() override; /** * Check whether the current user has the a particular right * on the mailbox. * * The result of this method is undefined if the job has * not yet completed. * * @param right the right to check for */ [[nodiscard]] bool hasRightEnabled(Acl::Right right); /** * Get the rights for the current user on the mailbox. * * The result of this method is undefined if the job has * not yet completed. */ [[nodiscard]] Acl::Rights rights(); protected: void doStart() override; void handleResponse(const Response &response) override; }; } 070701000000EE000081A400000000000000000000000166FAD7C000000D66000000000000000000000000000000000000003E00000000kimap-VERSIONgit.20240930T185424~db1f697/src/namespacejob.cpp/* SPDX-FileCopyrightText: 2009 Kevin Ottens <ervin@kde.org> SPDX-License-Identifier: LGPL-2.0-or-later */ #include "namespacejob.h" #include "kimap_debug.h" #include <KLocalizedString> #include "imapstreamparser.h" #include "job_p.h" #include "listjob.h" #include "response_p.h" #include "rfccodecs.h" #include "session_p.h" namespace KIMAP { class NamespaceJobPrivate : public JobPrivate { public: NamespaceJobPrivate(Session *session, const QString &name) : JobPrivate(session, name) { } ~NamespaceJobPrivate() { } QList<MailBoxDescriptor> processNamespaceList(const QList<QByteArray> &namespaceList) { QList<MailBoxDescriptor> result; for (const QByteArray &namespaceItem : namespaceList) { ImapStreamParser parser(nullptr); parser.setData(namespaceItem); try { QList<QByteArray> parts = parser.readParenthesizedList(); if (parts.size() < 2) { continue; } MailBoxDescriptor descriptor; descriptor.name = QString::fromUtf8(decodeImapFolderName(parts[0])); descriptor.separator = QLatin1Char(parts[1][0]); result << descriptor; } catch (const KIMAP::ImapParserException &e) { qCWarning(KIMAP_LOG) << "The stream parser raised an exception during namespace list parsing:" << e.what(); qCWarning(KIMAP_LOG) << "namespacelist:" << namespaceList; } } return result; } QList<MailBoxDescriptor> personalNamespaces; QList<MailBoxDescriptor> userNamespaces; QList<MailBoxDescriptor> sharedNamespaces; }; } using namespace KIMAP; NamespaceJob::NamespaceJob(Session *session) : Job(*new NamespaceJobPrivate(session, i18n("Namespace"))) { } NamespaceJob::~NamespaceJob() { } QList<MailBoxDescriptor> NamespaceJob::personalNamespaces() const { Q_D(const NamespaceJob); return d->personalNamespaces; } QList<MailBoxDescriptor> NamespaceJob::userNamespaces() const { Q_D(const NamespaceJob); return d->userNamespaces; } QList<MailBoxDescriptor> NamespaceJob::sharedNamespaces() const { Q_D(const NamespaceJob); return d->sharedNamespaces; } bool NamespaceJob::containsEmptyNamespace() const { Q_D(const NamespaceJob); const QList<MailBoxDescriptor> completeList = d->personalNamespaces + d->userNamespaces + d->sharedNamespaces; for (const MailBoxDescriptor &descriptor : completeList) { if (descriptor.name.isEmpty()) { return true; } } return false; } void NamespaceJob::doStart() { Q_D(NamespaceJob); d->tags << d->sessionInternal()->sendCommand("NAMESPACE"); } void NamespaceJob::handleResponse(const Response &response) { Q_D(NamespaceJob); if (handleErrorReplies(response) == NotHandled) { if (response.content.size() >= 5 && response.content[1].toString() == "NAMESPACE") { // Personal namespaces d->personalNamespaces = d->processNamespaceList(response.content[2].toList()); // User namespaces d->userNamespaces = d->processNamespaceList(response.content[3].toList()); // Shared namespaces d->sharedNamespaces = d->processNamespaceList(response.content[4].toList()); } } } #include "moc_namespacejob.cpp" 070701000000EF000081A400000000000000000000000166FAD7C000000358000000000000000000000000000000000000003C00000000kimap-VERSIONgit.20240930T185424~db1f697/src/namespacejob.h/* SPDX-FileCopyrightText: 2009 Kevin Ottens <ervin@kde.org> SPDX-License-Identifier: LGPL-2.0-or-later */ #pragma once #include "kimap_export.h" #include "job.h" namespace KIMAP { class Session; struct Response; struct MailBoxDescriptor; class NamespaceJobPrivate; class KIMAP_EXPORT NamespaceJob : public Job { Q_OBJECT Q_DECLARE_PRIVATE(NamespaceJob) friend class SessionPrivate; public: NamespaceJob(Session *session); ~NamespaceJob() override; [[nodiscard]] QList<MailBoxDescriptor> personalNamespaces() const; [[nodiscard]] QList<MailBoxDescriptor> userNamespaces() const; [[nodiscard]] QList<MailBoxDescriptor> sharedNamespaces() const; [[nodiscard]] bool containsEmptyNamespace() const; protected: void doStart() override; void handleResponse(const Response &response) override; }; } 070701000000F0000081A400000000000000000000000166FAD7C0000005A7000000000000000000000000000000000000003E00000000kimap-VERSIONgit.20240930T185424~db1f697/src/quotajobbase.cpp/* SPDX-FileCopyrightText: 2009 Andras Mantia <amantia@kde.org> SPDX-License-Identifier: LGPL-2.0-or-later */ #include "quotajobbase.h" #include "quotajobbase_p.h" #include "response_p.h" #include "session_p.h" #include <KLocalizedString> using namespace KIMAP; QMap<QByteArray, QPair<qint64, qint64>> QuotaJobBasePrivate::readQuota(const Response::Part &content) { QMap<QByteArray, QPair<qint64, qint64>> quotaMap; QList<QByteArray> quotas = content.toList(); int i = 0; while (i < quotas.size() - 2) { QByteArray resource = quotas[i].toUpper(); qint64 usage = quotas[i + 1].toInt(); qint64 limit = quotas[i + 2].toInt(); quotaMap[resource] = qMakePair(usage, limit); i += 3; } return quotaMap; } QuotaJobBase::QuotaJobBase(Session *session) : Job(*new QuotaJobBasePrivate(session, i18n("QuotaJobBase"))) { } QuotaJobBase::QuotaJobBase(JobPrivate &dd) : Job(dd) { } QuotaJobBase::~QuotaJobBase() { } qint64 QuotaJobBase::usage(const QByteArray &resource) { Q_D(QuotaJobBase); QByteArray r = resource.toUpper(); if (d->quota.contains(r)) { return d->quota[r].first; } return -1; } qint64 QuotaJobBase::limit(const QByteArray &resource) { Q_D(QuotaJobBase); QByteArray r = resource.toUpper(); if (d->quota.contains(r)) { return d->quota[r].second; } return -1; } #include "moc_quotajobbase.cpp" 070701000000F1000081A400000000000000000000000166FAD7C000000908000000000000000000000000000000000000003C00000000kimap-VERSIONgit.20240930T185424~db1f697/src/quotajobbase.h/* SPDX-FileCopyrightText: 2009 Andras Mantia <amantia@kde.org> SPDX-License-Identifier: LGPL-2.0-or-later */ #pragma once #include "kimap_export.h" #include "job.h" namespace KIMAP { class Session; struct Response; class QuotaJobBasePrivate; /** * Base class for jobs that operate on mailbox quotas * * Provides support for the IMAP QUOTA extension, as defined by * <a href="https://tools.ietf.org/html/rfc2087" title="IMAP QUOTA extension">RFC 2087</a>. * * This class cannot be used directly, you must subclass it and reimplement * at least the doStart() method. */ class KIMAP_EXPORT QuotaJobBase : public Job { Q_OBJECT Q_DECLARE_PRIVATE(QuotaJobBase) friend class SessionPrivate; public: explicit QuotaJobBase(Session *session); ~QuotaJobBase() override; /** * Get the current usage for a resource. * * All quota jobs will normally cause the server to return * details of resource usage for all resources that were * queried or modified by the job. * * Note that RFC 2087 is slightly ambiguous about whether * SETQUOTA will cause this information to be sent by the * server. * * Note that if there is no limit for a resource, the * server will not provide information about resource * usage. * * @param resource the resource to get the usage for * @return the resource usage in appropriate units, or -1 * if the usage is unknown or there is no * limit on the resource */ [[nodiscard]] qint64 usage(const QByteArray &resource); /** * Get the current limit for a resource. * * All quota jobs will normally cause the server to return * details of resource limits for all resources that were * queried or modified by the job. * * Note that RFC 2087 is slightly ambiguous about whether * SETQUOTA will cause this information to be sent by the * server. * * @param resource the resource to get the limit for * @return the resource limit in appropriate units, or -1 * if the limit is unknown or there is no limit * on the resource */ [[nodiscard]] qint64 limit(const QByteArray &resource); protected: QuotaJobBase(JobPrivate &dd); }; } 070701000000F2000081A400000000000000000000000166FAD7C00000024F000000000000000000000000000000000000003E00000000kimap-VERSIONgit.20240930T185424~db1f697/src/quotajobbase_p.h/* SPDX-FileCopyrightText: 2009 Andras Mantia <amantia@kde.org> SPDX-License-Identifier: LGPL-2.0-or-later */ #pragma once #include "job_p.h" #include "response_p.h" #include "session.h" #include <QMap> namespace KIMAP { class QuotaJobBasePrivate : public JobPrivate { public: QuotaJobBasePrivate(Session *session, const QString &name) : JobPrivate(session, name) { } ~QuotaJobBasePrivate() { } static QMap<QByteArray, QPair<qint64, qint64>> readQuota(const Response::Part &content); QMap<QByteArray, QPair<qint64, qint64>> quota; }; } 070701000000F3000081A400000000000000000000000166FAD7C0000005FD000000000000000000000000000000000000003B00000000kimap-VERSIONgit.20240930T185424~db1f697/src/renamejob.cpp/* SPDX-FileCopyrightText: 2009 Andras Mantia <amantia@kde.org> SPDX-License-Identifier: LGPL-2.0-or-later */ #include "renamejob.h" #include <KLocalizedString> #include "job_p.h" #include "response_p.h" #include "rfccodecs.h" #include "session_p.h" namespace KIMAP { class RenameJobPrivate : public JobPrivate { public: RenameJobPrivate(Session *session, const QString &name) : JobPrivate(session, name) { } ~RenameJobPrivate() { } QString sourceMailBox; QString destinationMailBox; }; } using namespace KIMAP; RenameJob::RenameJob(Session *session) : Job(*new RenameJobPrivate(session, i18n("Rename"))) { } RenameJob::~RenameJob() { } void RenameJob::doStart() { Q_D(RenameJob); d->tags << d->sessionInternal()->sendCommand("RENAME", '\"' + KIMAP::encodeImapFolderName(d->sourceMailBox.toUtf8()) + "\" \"" + KIMAP::encodeImapFolderName(d->destinationMailBox.toUtf8()) + '\"'); } void RenameJob::setSourceMailBox(const QString &mailBox) { Q_D(RenameJob); d->sourceMailBox = mailBox; } QString RenameJob::sourceMailBox() const { Q_D(const RenameJob); return d->sourceMailBox; } void RenameJob::setDestinationMailBox(const QString &mailBox) { Q_D(RenameJob); d->destinationMailBox = mailBox; } QString RenameJob::destinationMailBox() const { Q_D(const RenameJob); return d->destinationMailBox; } #include "moc_renamejob.cpp" 070701000000F4000081A400000000000000000000000166FAD7C0000003A9000000000000000000000000000000000000003900000000kimap-VERSIONgit.20240930T185424~db1f697/src/renamejob.h/* SPDX-FileCopyrightText: 2009 Andras Mantia <amantia@kde.org> SPDX-License-Identifier: LGPL-2.0-or-later */ #pragma once #include "kimap_export.h" #include "job.h" namespace KIMAP { class Session; class RenameJobPrivate; class KIMAP_EXPORT RenameJob : public Job { Q_OBJECT Q_DECLARE_PRIVATE(RenameJob) friend class SessionPrivate; public: explicit RenameJob(Session *session); ~RenameJob() override; /** * Set the name of the mailbox that will be renamed. * @param mailBox the original name of the mailbox */ void setSourceMailBox(const QString &mailBox); [[nodiscard]] QString sourceMailBox() const; /** * The new name of the mailbox, see setMailBox. * @param mailBox the new mailbox name */ void setDestinationMailBox(const QString &mailBox); [[nodiscard]] QString destinationMailBox() const; protected: void doStart() override; }; } 070701000000F5000081A400000000000000000000000166FAD7C000000906000000000000000000000000000000000000003A00000000kimap-VERSIONgit.20240930T185424~db1f697/src/response_p.h/* SPDX-FileCopyrightText: 2009 Kevin Ottens <ervin@kde.org> SPDX-License-Identifier: LGPL-2.0-or-later */ #pragma once #include <QByteArray> #include <QList> #include <QMetaType> namespace KIMAP { struct Response { class Part { public: enum Type { String = 0, List }; explicit Part(const QByteArray &string) : m_type(String) , m_string(string) { } explicit Part(const QList<QByteArray> &list) : m_type(List) , m_list(list) { } inline Type type() const { return m_type; } inline QByteArray toString() const { return m_string; } inline QList<QByteArray> toList() const { return m_list; } private: Type m_type; QByteArray m_string; QList<QByteArray> m_list; }; inline QByteArray toString() const { QByteArray result; for (const Part &part : std::as_const(content)) { if (part.type() == Part::List) { result += '('; const QList<QByteArray> lstBa = part.toList(); for (const QByteArray &item : lstBa) { result += ' '; result += item; } result += " ) "; } else { result += part.toString() + ' '; } } if (!responseCode.isEmpty()) { result += "[ "; for (const Part &part : std::as_const(responseCode)) { if (part.type() == Part::List) { result += '('; const QList<QByteArray> lstBa = part.toList(); for (const QByteArray &item : lstBa) { result += ' '; result += item; } result += " ) "; } else { result += part.toString() + ' '; } } result += " ]"; } return result; } QList<Part> content; QList<Part> responseCode; }; } Q_DECLARE_METATYPE(KIMAP::Response) static const int _kimap_messageTypeId = qRegisterMetaType<KIMAP::Response>(); 070701000000F6000081A400000000000000000000000166FAD7C0000021DD000000000000000000000000000000000000003B00000000kimap-VERSIONgit.20240930T185424~db1f697/src/rfccodecs.cpp/********************************************************************** * * rfccodecs.cpp - handler for various rfc/mime encodings * SPDX-FileCopyrightText: 2000 s .carstens@gmx.de * * SPDX-License-Identifier: LGPL-2.0-or-later * *********************************************************************/ /** * @file * This file is part of the IMAP support library and defines the * RfcCodecs class. * * @brief * Defines the RfcCodecs class. * * @author Sven Carstens */ #include "rfccodecs.h" #include <ctype.h> #include <sys/types.h> #include <stdio.h> #include <stdlib.h> #include <QByteArray> #include <QLatin1Char> using namespace KIMAP; // This part taken from rfc 2192 IMAP URL Scheme. C. Newman. September 1997. // adapted to QT-Toolkit by Sven Carstens <s.carstens@gmx.de> 2000 //@cond PRIVATE static const unsigned char base64chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+,"; #define UNDEFINED 64 #define MAXLINE 76 static const char especials[17] = "()<>@,;:\"/[]?.= "; /* UTF16 definitions */ #define UTF16MASK 0x03FFUL #define UTF16SHIFT 10 #define UTF16BASE 0x10000UL #define UTF16HIGHSTART 0xD800UL #define UTF16HIGHEND 0xDBFFUL #define UTF16LOSTART 0xDC00UL #define UTF16LOEND 0xDFFFUL //@endcond //----------------------------------------------------------------------------- QByteArray KIMAP::decodeImapFolderName(const QByteArray &inSrc) { unsigned char c; unsigned char i; unsigned char bitcount; unsigned long ucs4; unsigned long utf16; unsigned long bitbuf; unsigned char base64[256]; unsigned char utf8[6]; unsigned int srcPtr = 0; QByteArray dst; QByteArray src = inSrc; uint srcLen = inSrc.length(); /* initialize modified base64 decoding table */ memset(base64, UNDEFINED, sizeof(base64)); for (i = 0; i < sizeof(base64chars); ++i) { base64[(int)base64chars[i]] = i; } /* loop until end of string */ while (srcPtr < srcLen) { c = src[srcPtr++]; /* deal with literal characters and &- */ if (c != '&' || src[srcPtr] == '-') { /* encode literally */ dst += c; /* skip over the '-' if this is an &- sequence */ if (c == '&') { srcPtr++; } } else { /* convert modified UTF-7 -> UTF-16 -> UCS-4 -> UTF-8 -> HEX */ bitbuf = 0; bitcount = 0; ucs4 = 0; while ((c = base64[(unsigned char)src[srcPtr]]) != UNDEFINED) { ++srcPtr; bitbuf = (bitbuf << 6) | c; bitcount += 6; /* enough bits for a UTF-16 character? */ if (bitcount >= 16) { bitcount -= 16; utf16 = (bitcount ? bitbuf >> bitcount : bitbuf) & 0xffff; /* convert UTF16 to UCS4 */ if (utf16 >= UTF16HIGHSTART && utf16 <= UTF16HIGHEND) { ucs4 = (utf16 - UTF16HIGHSTART) << UTF16SHIFT; continue; } else if (utf16 >= UTF16LOSTART && utf16 <= UTF16LOEND) { ucs4 += utf16 - UTF16LOSTART + UTF16BASE; } else { ucs4 = utf16; } /* convert UTF-16 range of UCS4 to UTF-8 */ if (ucs4 <= 0x7fUL) { utf8[0] = ucs4; i = 1; } else if (ucs4 <= 0x7ffUL) { utf8[0] = 0xc0 | (ucs4 >> 6); utf8[1] = 0x80 | (ucs4 & 0x3f); i = 2; } else if (ucs4 <= 0xffffUL) { utf8[0] = 0xe0 | (ucs4 >> 12); utf8[1] = 0x80 | ((ucs4 >> 6) & 0x3f); utf8[2] = 0x80 | (ucs4 & 0x3f); i = 3; } else { utf8[0] = 0xf0 | (ucs4 >> 18); utf8[1] = 0x80 | ((ucs4 >> 12) & 0x3f); utf8[2] = 0x80 | ((ucs4 >> 6) & 0x3f); utf8[3] = 0x80 | (ucs4 & 0x3f); i = 4; } /* copy it */ for (c = 0; c < i; ++c) { dst += utf8[c]; } } } /* skip over trailing '-' in modified UTF-7 encoding */ if (src[srcPtr] == '-') { ++srcPtr; } } } return dst; } QString KIMAP::decodeImapFolderName(const QString &inSrc) { return QString::fromUtf8(decodeImapFolderName(inSrc.toUtf8()).constData()); } //----------------------------------------------------------------------------- QByteArray KIMAP::quoteIMAP(const QByteArray &src) { int len = src.length(); QByteArray result; result.reserve(2 * len); for (int i = 0; i < len; i++) { if (src[i] == '"' || src[i] == '\\') { result += '\\'; } result += src[i]; } result.squeeze(); return result; } QString KIMAP::quoteIMAP(const QString &src) { uint len = src.length(); QString result; result.reserve(2 * len); for (unsigned int i = 0; i < len; i++) { if (src[i] == QLatin1Char('"') || src[i] == QLatin1Char('\\')) { result += QLatin1Char('\\'); } result += src[i]; } // result.squeeze(); - unnecessary and slow return result; } //----------------------------------------------------------------------------- QString KIMAP::encodeImapFolderName(const QString &inSrc) { return QString::fromUtf8(encodeImapFolderName(inSrc.toUtf8()).constData()); } QByteArray KIMAP::encodeImapFolderName(const QByteArray &inSrc) { unsigned int utf8pos; unsigned int utf8total; unsigned int c; unsigned int utf7mode; unsigned int bitstogo; unsigned int utf16flag; unsigned int ucs4; unsigned int bitbuf; QByteArray src = inSrc; QByteArray dst; int srcPtr = 0; utf7mode = 0; utf8total = 0; bitstogo = 0; utf8pos = 0; bitbuf = 0; ucs4 = 0; while (srcPtr < src.length()) { c = (unsigned char)src[srcPtr++]; /* normal character? */ if (c >= ' ' && c <= '~') { /* switch out of UTF-7 mode */ if (utf7mode) { if (bitstogo) { dst += base64chars[(bitbuf << (6 - bitstogo)) & 0x3F]; bitstogo = 0; } dst += '-'; utf7mode = 0; } dst += c; /* encode '&' as '&-' */ if (c == '&') { dst += '-'; } continue; } /* switch to UTF-7 mode */ if (!utf7mode) { dst += '&'; utf7mode = 1; } /* Encode US-ASCII characters as themselves */ if (c < 0x80) { ucs4 = c; utf8total = 1; } else if (utf8total) { /* save UTF8 bits into UCS4 */ ucs4 = (ucs4 << 6) | (c & 0x3FUL); if (++utf8pos < utf8total) { continue; } } else { utf8pos = 1; if (c < 0xE0) { utf8total = 2; ucs4 = c & 0x1F; } else if (c < 0xF0) { utf8total = 3; ucs4 = c & 0x0F; } else { /* NOTE: can't convert UTF8 sequences longer than 4 */ utf8total = 4; ucs4 = c & 0x03; } continue; } /* loop to split ucs4 into two utf16 chars if necessary */ utf8total = 0; do { if (ucs4 >= UTF16BASE) { ucs4 -= UTF16BASE; bitbuf = (bitbuf << 16) | ((ucs4 >> UTF16SHIFT) + UTF16HIGHSTART); ucs4 = (ucs4 & UTF16MASK) + UTF16LOSTART; utf16flag = 1; } else { bitbuf = (bitbuf << 16) | ucs4; utf16flag = 0; } bitstogo += 16; /* spew out base64 */ while (bitstogo >= 6) { bitstogo -= 6; dst += base64chars[(bitstogo ? (bitbuf >> bitstogo) : bitbuf) & 0x3F]; } } while (utf16flag); } /* if in UTF-7 mode, finish in ASCII */ if (utf7mode) { if (bitstogo) { dst += base64chars[(bitbuf << (6 - bitstogo)) & 0x3F]; } dst += '-'; } return quoteIMAP(dst); } 070701000000F7000081A400000000000000000000000166FAD7C000000749000000000000000000000000000000000000003900000000kimap-VERSIONgit.20240930T185424~db1f697/src/rfccodecs.h/********************************************************************** * * rfccodecs - handler for various rfc/mime encodings * SPDX-FileCopyrightText: 2000 s .carstens@gmx.de * * SPDX-License-Identifier: LGPL-2.0-or-later * *********************************************************************/ /** * @file * This file is part of the IMAP support library and defines the * RfcCodecs class. * * @brief * Provides handlers for various RFC/MIME encodings. * * @author Sven Carstens */ #pragma once #include <QString> #include "kimap_export.h" namespace KIMAP { /** Converts an Unicode IMAP mailbox to a QByteArray which can be used in IMAP communication. @param src is the QByteArray containing the IMAP mailbox. @since 4.3 */ [[nodiscard]] KIMAP_EXPORT QByteArray encodeImapFolderName(const QByteArray &src); /** Converts an UTF-7 encoded IMAP mailbox to a QByteArray @param inSrc is the QByteArray containing the Unicode path. @since 4.3 */ [[nodiscard]] KIMAP_EXPORT QByteArray decodeImapFolderName(const QByteArray &inSrc); /** Converts an Unicode IMAP mailbox to a QString which can be used in IMAP communication. @param src is the QString containing the IMAP mailbox. */ [[nodiscard]] KIMAP_EXPORT QString encodeImapFolderName(const QString &src); /** Converts an UTF-7 encoded IMAP mailbox to a Unicode QString. @param inSrc is the QString containing the Unicode path. */ [[nodiscard]] KIMAP_EXPORT QString decodeImapFolderName(const QString &inSrc); /** Replaces " with \" and \ with \\ " and \ characters. @param src is the QString to quote. */ [[nodiscard]] KIMAP_EXPORT QString quoteIMAP(const QString &src); /** Replaces " with \" and \ with \\ " and \ characters. @param src is the QString to quote. @since 4.3 */ [[nodiscard]] KIMAP_EXPORT QByteArray quoteIMAP(const QByteArray &src); } 070701000000F8000081A400000000000000000000000166FAD7C000003911000000000000000000000000000000000000003B00000000kimap-VERSIONgit.20240930T185424~db1f697/src/searchjob.cpp/* SPDX-FileCopyrightText: 2009 Andras Mantia <amantia@kde.org> SPDX-License-Identifier: LGPL-2.0-or-later */ #include "searchjob.h" #include "kimap_debug.h" #include <KLocalizedString> #include <QDate> #include "imapset.h" #include "job_p.h" #include "response_p.h" #include "session_p.h" namespace KIMAP { class Term::Private : public QSharedData { public: Private() : QSharedData() , isFuzzy(false) , isNegated(false) , isNull(false) { } Private(const Private &other) : QSharedData(other) , command(other.command) , isFuzzy(other.isFuzzy) , isNegated(other.isNegated) , isNull(other.isNull) { } Private &operator=(const Private &other) { command = other.command; isFuzzy = other.isFuzzy; isNegated = other.isNegated; isNull = other.isNull; return *this; } QByteArray command; bool isFuzzy; bool isNegated; bool isNull; }; Term::Term() : d(new Term::Private) { d->isNull = true; } Term::Term(Term::Relation relation, const QList<Term> &subterms) : d(new Term::Private) { if (subterms.size() >= 2) { if (relation == KIMAP::Term::Or) { for (int i = 0; i < subterms.size() - 1; ++i) { d->command += "(OR " + subterms[i].serialize() + " "; } d->command += subterms.back().serialize(); for (int i = 0; i < subterms.size() - 1; ++i) { d->command += ")"; } } else { d->command += "("; for (const Term &t : subterms) { d->command += t.serialize() + ' '; } if (!subterms.isEmpty()) { d->command.chop(1); } d->command += ")"; } } else if (subterms.size() == 1) { d->command += subterms.first().serialize(); } else { d->isNull = true; } } Term::Term(Term::SearchKey key, const QString &value) : d(new Term::Private) { switch (key) { case All: d->command += "ALL"; break; case Bcc: d->command += "BCC"; break; case Cc: d->command += "CC"; break; case Body: d->command += "BODY"; break; case From: d->command += "FROM"; break; case Keyword: d->command += "KEYWORD"; break; case Subject: d->command += "SUBJECT"; break; case Text: d->command += "TEXT"; break; case To: d->command += "TO"; break; } if (key != All) { d->command += " \"" + QByteArray(value.toUtf8().constData()) + "\""; } } Term::Term(const QString &header, const QString &value) : d(new Term::Private) { d->command += "HEADER"; d->command += ' ' + QByteArray(header.toUtf8().constData()); d->command += " \"" + QByteArray(value.toUtf8().constData()) + "\""; } Term::Term(Term::BooleanSearchKey key) : d(new Term::Private) { switch (key) { case Answered: d->command = "ANSWERED"; break; case Deleted: d->command = "DELETED"; break; case Draft: d->command = "DRAFT"; break; case Flagged: d->command = "FLAGGED"; break; case New: d->command = "NEW"; break; case Old: d->command = "OLD"; break; case Recent: d->command = "RECENT"; break; case Seen: d->command = "SEEN"; break; } } static QByteArray monthName(int month) { static const char *names[12] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; return (month >= 1 && month <= 12) ? QByteArray(names[month - 1]) : QByteArray(); } Term::Term(Term::DateSearchKey key, const QDate &date) : d(new Term::Private) { switch (key) { case Before: d->command = "BEFORE"; break; case On: d->command = "ON"; break; case SentBefore: d->command = "SENTBEFORE"; break; case SentOn: d->command = "SENTON"; break; case SentSince: d->command = "SENTSINCE"; break; case Since: d->command = "SINCE"; break; } d->command += " \""; d->command += QByteArray::number(date.day()) + '-'; d->command += monthName(date.month()) + '-'; d->command += QByteArray::number(date.year()); d->command += '\"'; } Term::Term(Term::NumberSearchKey key, int value) : d(new Term::Private) { switch (key) { case Larger: d->command = "LARGER"; break; case Smaller: d->command = "SMALLER"; break; } d->command += " " + QByteArray::number(value); } Term::Term(Term::SequenceSearchKey key, const ImapSet &set) : d(new Term::Private) { switch (key) { case Uid: d->command = "UID"; break; case SequenceNumber: break; } auto optimizedSet = set; optimizedSet.optimize(); d->command += " " + optimizedSet.toImapSequenceSet(); } Term::Term(const Term &other) : d(new Term::Private) { *d = *other.d; } Term::~Term() { } Term &Term::operator=(const Term &other) { *d = *other.d; return *this; } bool Term::operator==(const Term &other) const { return d->command == other.d->command && d->isNegated == other.d->isNegated && d->isFuzzy == other.d->isFuzzy; } QByteArray Term::serialize() const { QByteArray command; if (d->isFuzzy) { command = "FUZZY "; } if (d->isNegated) { command = "NOT "; } return command + d->command; } Term &Term::setFuzzy(bool fuzzy) { d->isFuzzy = fuzzy; return *this; } Term &Term::setNegated(bool negated) { d->isNegated = negated; return *this; } bool Term::isNull() const { return d->isNull; } // TODO: when custom error codes are introduced, handle the NO [TRYCREATE] response class SearchJobPrivate : public JobPrivate { public: SearchJobPrivate(Session *session, const QString &name) : JobPrivate(session, name) , logic(SearchJob::And) { criteriaMap[SearchJob::All] = "ALL"; criteriaMap[SearchJob::Answered] = "ANSWERED"; criteriaMap[SearchJob::BCC] = "BCC"; criteriaMap[SearchJob::Before] = "BEFORE"; criteriaMap[SearchJob::Body] = "BODY"; criteriaMap[SearchJob::CC] = "CC"; criteriaMap[SearchJob::Deleted] = "DELETED"; criteriaMap[SearchJob::Draft] = "DRAFT"; criteriaMap[SearchJob::Flagged] = "FLAGGED"; criteriaMap[SearchJob::From] = "FROM"; criteriaMap[SearchJob::Header] = "HEADER"; criteriaMap[SearchJob::Keyword] = "KEYWORD"; criteriaMap[SearchJob::Larger] = "LARGER"; criteriaMap[SearchJob::New] = "NEW"; criteriaMap[SearchJob::Old] = "OLD"; criteriaMap[SearchJob::On] = "ON"; criteriaMap[SearchJob::Recent] = "RECENT"; criteriaMap[SearchJob::Seen] = "SEEN"; criteriaMap[SearchJob::SentBefore] = "SENTBEFORE"; criteriaMap[SearchJob::SentOn] = "SENTON"; criteriaMap[SearchJob::SentSince] = "SENTSINCE"; criteriaMap[SearchJob::Since] = "SINCE"; criteriaMap[SearchJob::Smaller] = "SMALLER"; criteriaMap[SearchJob::Subject] = "SUBJECT"; criteriaMap[SearchJob::Text] = "TEXT"; criteriaMap[SearchJob::To] = "TO"; criteriaMap[SearchJob::Uid] = "UID"; criteriaMap[SearchJob::Unanswered] = "UNANSWERED"; criteriaMap[SearchJob::Undeleted] = "UNDELETED"; criteriaMap[SearchJob::Undraft] = "UNDRAFT"; criteriaMap[SearchJob::Unflagged] = "UNFLAGGED"; criteriaMap[SearchJob::Unkeyword] = "UNKEYWORD"; criteriaMap[SearchJob::Unseen] = "UNSEEN"; // don't use QDate::shortMonthName(), it returns a localized month name months[1] = "Jan"; months[2] = "Feb"; months[3] = "Mar"; months[4] = "Apr"; months[5] = "May"; months[6] = "Jun"; months[7] = "Jul"; months[8] = "Aug"; months[9] = "Sep"; months[10] = "Oct"; months[11] = "Nov"; months[12] = "Dec"; nextContent = 0; uidBased = false; } ~SearchJobPrivate() { } QByteArray charset; QList<QByteArray> criterias; QMap<SearchJob::SearchCriteria, QByteArray> criteriaMap; QMap<int, QByteArray> months; SearchJob::SearchLogic logic; QList<QByteArray> contents; QList<qint64> results; uint nextContent; bool uidBased; Term term; }; } using namespace KIMAP; SearchJob::SearchJob(Session *session) : Job(*new SearchJobPrivate(session, i18nc("Name of the search job", "Search"))) { } SearchJob::~SearchJob() { } void SearchJob::setTerm(const Term &term) { Q_D(SearchJob); d->term = term; } void SearchJob::doStart() { Q_D(SearchJob); QByteArray searchKey; if (!d->charset.isEmpty()) { searchKey = "CHARSET " + d->charset; } if (!d->term.isNull()) { const QByteArray term = d->term.serialize(); if (term.startsWith('(')) { searchKey += term.mid(1, term.size() - 2); } else { searchKey += term; } } else { if (d->logic == SearchJob::Not) { searchKey += "NOT "; } else if (d->logic == SearchJob::Or && d->criterias.size() > 1) { searchKey += "OR "; } if (d->logic == SearchJob::And) { const int numberCriterias(d->criterias.size()); for (int i = 0; i < numberCriterias; i++) { const QByteArray key = d->criterias.at(i); if (i > 0) { searchKey += ' '; } searchKey += key; } } else { const int numberCriterias(d->criterias.size()); for (int i = 0; i < numberCriterias; i++) { const QByteArray key = d->criterias.at(i); if (i > 0) { searchKey += ' '; } searchKey += '(' + key + ')'; } } } QByteArray command = "SEARCH"; if (d->uidBased) { command = "UID " + command; } d->tags << d->sessionInternal()->sendCommand(command, searchKey); } void SearchJob::handleResponse(const Response &response) { Q_D(SearchJob); if (handleErrorReplies(response) == NotHandled) { if (response.content.size() >= 1 && response.content[0].toString() == "+") { if (d->term.isNull()) { d->sessionInternal()->sendData(d->contents[d->nextContent]); } else { qCWarning(KIMAP_LOG) << "The term API only supports inline strings."; } d->nextContent++; } else if (response.content.size() >= 2 && response.content[1].toString() == "SEARCH") { for (int i = 2; i < response.content.size(); i++) { d->results.append(response.content[i].toString().toInt()); } } } } void SearchJob::setCharset(const QByteArray &charset) { Q_D(SearchJob); d->charset = charset; } QByteArray SearchJob::charset() const { Q_D(const SearchJob); return d->charset; } void SearchJob::setSearchLogic(SearchLogic logic) { Q_D(SearchJob); d->logic = logic; } void SearchJob::addSearchCriteria(SearchCriteria criteria) { Q_D(SearchJob); switch (criteria) { case All: case Answered: case Deleted: case Draft: case Flagged: case New: case Old: case Recent: case Seen: case Unanswered: case Undeleted: case Undraft: case Unflagged: case Unseen: d->criterias.append(d->criteriaMap[criteria]); break; default: // TODO Discuss if we keep error checking here, or accept anything, even if it is wrong qCDebug(KIMAP_LOG) << "Criteria " << d->criteriaMap[criteria] << " needs an argument, but none was specified."; break; } } void SearchJob::addSearchCriteria(SearchCriteria criteria, int argument) { Q_D(SearchJob); switch (criteria) { case Larger: case Smaller: d->criterias.append(d->criteriaMap[criteria] + ' ' + QByteArray::number(argument)); break; default: // TODO Discuss if we keep error checking here, or accept anything, even if it is wrong qCDebug(KIMAP_LOG) << "Criteria " << d->criteriaMap[criteria] << " doesn't accept an integer as an argument."; break; } } void SearchJob::addSearchCriteria(SearchCriteria criteria, const QByteArray &argument) { Q_D(SearchJob); switch (criteria) { case BCC: case Body: case CC: case From: case Subject: case Text: case To: d->contents.append(argument); d->criterias.append(d->criteriaMap[criteria] + " {" + QByteArray::number(argument.size()) + '}'); break; case Keyword: case Unkeyword: case Header: case Uid: d->criterias.append(d->criteriaMap[criteria] + ' ' + argument); break; default: // TODO Discuss if we keep error checking here, or accept anything, even if it is wrong qCDebug(KIMAP_LOG) << "Criteria " << d->criteriaMap[criteria] << " doesn't accept any argument."; break; } } void SearchJob::addSearchCriteria(SearchCriteria criteria, const QDate &argument) { Q_D(SearchJob); switch (criteria) { case Before: case On: case SentBefore: case SentSince: case Since: { QByteArray date = QByteArray::number(argument.day()) + '-'; date += d->months[argument.month()] + '-'; date += QByteArray::number(argument.year()); d->criterias.append(d->criteriaMap[criteria] + " \"" + date + '\"'); break; } default: // TODO Discuss if we keep error checking here, or accept anything, even if it is wrong qCDebug(KIMAP_LOG) << "Criteria " << d->criteriaMap[criteria] << " doesn't accept a date as argument."; break; } } void SearchJob::addSearchCriteria(const QByteArray &searchCriteria) { Q_D(SearchJob); d->criterias.append(searchCriteria); } void SearchJob::setUidBased(bool uidBased) { Q_D(SearchJob); d->uidBased = uidBased; } bool SearchJob::isUidBased() const { Q_D(const SearchJob); return d->uidBased; } QList<qint64> SearchJob::results() const { Q_D(const SearchJob); return d->results; } #include "moc_searchjob.cpp" 070701000000F9000081A400000000000000000000000166FAD7C0000013A3000000000000000000000000000000000000003900000000kimap-VERSIONgit.20240930T185424~db1f697/src/searchjob.h/* SPDX-FileCopyrightText: 2009 Andras Mantia <amantia@kde.org> SPDX-FileCopyrightText: 2014 Christian Mollekopf <mollekopf@kolabsys.com> SPDX-License-Identifier: LGPL-2.0-or-later */ #pragma once #include "kimap_export.h" #include "job.h" #include <QSharedDataPointer> class QDate; namespace KIMAP { class ImapSet; class Session; struct Response; class SearchJobPrivate; /** * A query term. * Refer to the IMAP RFC for the meaning of the individual terms. * @since 4.13 */ class KIMAP_EXPORT Term { public: enum Relation { And, Or }; enum SearchKey { All, Bcc, Body, Cc, From, Subject, Text, To, Keyword }; enum BooleanSearchKey { New, Old, Recent, Seen, Draft, Deleted, Flagged, Answered }; enum DateSearchKey { Before, On, Since, SentBefore, SentOn, SentSince }; enum NumberSearchKey { Larger, Smaller }; enum SequenceSearchKey { Uid, SequenceNumber }; Term(); ~Term(); Term(Relation relation, const QList<Term> &subterms); Term(SearchKey key, const QString &value); Term(BooleanSearchKey key); Term(DateSearchKey key, const QDate &date); Term(NumberSearchKey key, int value); Term(SequenceSearchKey key, const KIMAP::ImapSet &); Term(const QString &header, const QString &value); Term(const Term &other); Term &operator=(const Term &other); bool operator==(const Term &other) const; [[nodiscard]] bool isNull() const; Term &setFuzzy(bool fuzzy); Term &setNegated(bool negated); [[nodiscard]] QByteArray serialize() const; private: class Private; QSharedDataPointer<Private> d; }; class KIMAP_EXPORT SearchJob : public Job { Q_OBJECT Q_DECLARE_PRIVATE(SearchJob) friend class SessionPrivate; public: enum SearchLogic { And = 0, Or, Not }; enum SearchCriteria { All = 0, Answered, BCC, Before, Body, CC, Deleted, Draft, Flagged, From, Header, Keyword, Larger, New, Old, On, Recent, Seen, SentBefore, SentOn, SentSince, Since, Smaller, Subject, Text, To, Uid, Unanswered, Undeleted, Undraft, Unflagged, Unkeyword, Unseen }; explicit SearchJob(Session *session); ~SearchJob() override; void setUidBased(bool uidBased); bool isUidBased() const; void setCharset(const QByteArray &charSet); QByteArray charset() const; /** * Get the search result, as a list of sequence numbers or UIDs, based on the isUidBased status * @return the found items * @since 4.6 */ QList<qint64> results() const; /** * Add a search criteria that doesn't have an argument. Passing a criteria that * should have an argument will be ignored. * @param criteria a criteria from SearchCriterias * @deprecated since 4.13 */ KIMAP_DEPRECATED void addSearchCriteria(SearchCriteria criteria); /** * Add a search criteria that has one or more space separate string arguments. * Passing a criteria that accepts a different type or argument or no * argument will be ignored. * @param criteria a criteria from SearchCriterias * @param argument the arguments * @deprecated since 4.13 */ KIMAP_DEPRECATED void addSearchCriteria(SearchCriteria criteria, const QByteArray &argument); /** * Add a search criteria that has an integer argument. * Passing a criteria that accepts a different type or argument or no * argument will be ignored. * @param criteria a criteria from SearchCriterias * @param argument a number argument * @deprecated since 4.13 */ KIMAP_DEPRECATED void addSearchCriteria(SearchCriteria criteria, int argument); /** * Add a search criteria that has a date as argument. * Passing a criteria that accepts a different type or argument or no * argument will be ignored. * @param criteria a criteria from SearchCriterias * @param argument a date * @deprecated since 4.13 */ KIMAP_DEPRECATED void addSearchCriteria(SearchCriteria criteria, const QDate &argument); /** * Add a custom criteria. No checks are done, the data is sent as it is * to the server. * @param searchCriteria free form search criteria. * @deprecated since 4.13 */ KIMAP_DEPRECATED void addSearchCriteria(const QByteArray &searchCriteria); /** * Set the logic combining the search criteria. * @param logic AND (the default), OR, NOT. See SearchLogics. * @deprecated since 4.13 */ KIMAP_DEPRECATED void setSearchLogic(SearchLogic logic); /** * Sets the search term. * @param term The search term. * @since 4.13 */ void setTerm(const Term &); protected: void doStart() override; void handleResponse(const Response &response) override; }; } 070701000000FA000081A400000000000000000000000166FAD7C000002371000000000000000000000000000000000000003B00000000kimap-VERSIONgit.20240930T185424~db1f697/src/selectjob.cpp/* SPDX-FileCopyrightText: 2009 Kevin Ottens <ervin@kde.org> SPDX-License-Identifier: LGPL-2.0-or-later */ #include "selectjob.h" #include "kimap_debug.h" #include "imapset.h" #include "job_p.h" #include "response_p.h" #include "rfccodecs.h" #include "session_p.h" #include <KLocalizedString> #include <QMap> #include <QTimer> namespace KIMAP { class SelectJobPrivate : public JobPrivate { public: SelectJobPrivate(SelectJob *q, Session *session, const QString &name) : JobPrivate(session, name) , q(q) { QObject::connect(&emitPendingsTimer, &QTimer::timeout, [this]() { emitPendings(); }); } void emitPendings() { if (pendingMessages.empty()) { return; } Q_EMIT q->modified(pendingMessages); pendingMessages.clear(); } QString mailBox; bool readOnly = false; QMap<qint64, Message> pendingMessages; QTimer emitPendingsTimer; QList<QByteArray> flags; QList<QByteArray> permanentFlags; int messageCount = -1; int recentCount = -1; int firstUnseenIndex = -1; qint64 uidValidity = -1; qint64 nextUid = -1; quint64 highestmodseq = 0; qint64 lastUidvalidity = -1; quint64 lastModseq = 0; ImapSet knownUids; bool condstoreEnabled = false; SelectJob *const q; }; } using namespace KIMAP; SelectJob::SelectJob(Session *session) : Job(*new SelectJobPrivate(this, session, i18nc("name of the select job", "Select"))) { } SelectJob::~SelectJob() { } void SelectJob::setMailBox(const QString &mailBox) { Q_D(SelectJob); d->mailBox = mailBox; } QString SelectJob::mailBox() const { Q_D(const SelectJob); return d->mailBox; } void SelectJob::setOpenReadOnly(bool readOnly) { Q_D(SelectJob); d->readOnly = readOnly; } bool SelectJob::isOpenReadOnly() const { Q_D(const SelectJob); return d->readOnly; } QList<QByteArray> SelectJob::flags() const { Q_D(const SelectJob); return d->flags; } QList<QByteArray> SelectJob::permanentFlags() const { Q_D(const SelectJob); return d->permanentFlags; } int SelectJob::messageCount() const { Q_D(const SelectJob); return d->messageCount; } int SelectJob::recentCount() const { Q_D(const SelectJob); return d->recentCount; } int SelectJob::firstUnseenIndex() const { Q_D(const SelectJob); return d->firstUnseenIndex; } qint64 SelectJob::uidValidity() const { Q_D(const SelectJob); return d->uidValidity; } qint64 SelectJob::nextUid() const { Q_D(const SelectJob); return d->nextUid; } quint64 SelectJob::highestModSequence() const { Q_D(const SelectJob); return d->highestmodseq; } void SelectJob::setCondstoreEnabled(bool enable) { Q_D(SelectJob); d->condstoreEnabled = enable; } bool SelectJob::condstoreEnabled() const { Q_D(const SelectJob); return d->condstoreEnabled; } void SelectJob::setQResync(qint64 lastUidvalidity, quint64 lastModseq, const ImapSet &knownUids) { Q_D(SelectJob); d->lastUidvalidity = lastUidvalidity; d->lastModseq = lastModseq; d->knownUids = knownUids; setCondstoreEnabled(true); } void SelectJob::doStart() { Q_D(SelectJob); QByteArray command = "SELECT"; if (d->readOnly) { command = "EXAMINE"; } QByteArray params = '\"' + KIMAP::encodeImapFolderName(d->mailBox.toUtf8()) + '\"'; if (d->condstoreEnabled) { // Check whether we only do CONDSTORE, or QRESYNC if (d->lastUidvalidity == -1 && d->lastModseq == 0) { params += " (CONDSTORE)"; } else { params += " (QRESYNC (" + QByteArray::number(d->lastUidvalidity) + " " + QByteArray::number(d->lastModseq); if (!d->knownUids.isEmpty()) { params += " " + d->knownUids.toImapSequenceSet(); } params += "))"; } } d->emitPendingsTimer.start(100); d->tags << d->sessionInternal()->sendCommand(command, params); } void SelectJob::handleResponse(const Response &response) { Q_D(SelectJob); // Check for [READ-ONLY] response in final tagged OK // This must be checked before handleErrorReplies(), because that calls emitResult() // right away if (!response.content.isEmpty() && d->tags.contains(response.content.first().toString())) { if (response.responseCode.size() >= 1 && response.responseCode[0].toString() == "READ-ONLY") { d->readOnly = true; } } // We can predict it'll be handled by handleErrorReplies() so stop // the timer now so that result() will really be the last emitted signal. if (!response.content.isEmpty() && d->tags.size() == 1 && d->tags.contains(response.content.first().toString())) { d->emitPendingsTimer.stop(); d->emitPendings(); } if (handleErrorReplies(response) == NotHandled) { if (response.content.size() >= 2) { QByteArray code = response.content[1].toString(); if (code == "OK") { if (response.responseCode.size() < 2) { return; } code = response.responseCode[0].toString(); if (code == "PERMANENTFLAGS") { d->permanentFlags = response.responseCode[1].toList(); } else if (code == "HIGHESTMODSEQ") { bool isInt; quint64 value = response.responseCode[1].toString().toULongLong(&isInt); if (!isInt) { return; } d->highestmodseq = value; } else { bool isInt; qint64 value = response.responseCode[1].toString().toLongLong(&isInt); if (!isInt) { return; } if (code == "UIDVALIDITY") { d->uidValidity = value; } else if (code == "UNSEEN") { d->firstUnseenIndex = value; } else if (code == "UIDNEXT") { d->nextUid = value; } } } else if (code == "FLAGS") { d->flags = response.content[2].toList(); } else if (code == "VANISHED" && response.content.size() == 4) { // VANISHED response in SELECT is RFC5162 (QRESYNC) extension const auto vanishedSet = ImapSet::fromImapSequenceSet(response.content[3].toString()); Q_EMIT vanished(vanishedSet); } else { bool isInt = false; int value = response.content[1].toString().toInt(&isInt); if (!isInt || response.content.size() < 3) { return; } code = response.content[2].toString(); if (code == "FETCH") { // FETCH response in SELECT is RFC5162 (QRESYNC) extension Message msg{}; const auto content = response.content[3].toList(); for (auto it = content.cbegin(), end = content.cend(); it != end; ++it) { const auto name = *it; ++it; if (it == content.constEnd()) { // Uh oh, message was truncated? qCWarning(KIMAP_LOG) << "SELECT reply got truncated, skipping."; break; } if (name == "UID") { msg.uid = it->toLongLong(); } else if (name == "FLAGS") { if ((*it).startsWith('(') && (*it).endsWith(')')) { QByteArray str = *it; str.chop(1); str.remove(0, 1); const auto flags = str.split(' '); msg.flags = flags; } else { msg.flags << *it; } } else if (name == "MODSEQ") { QByteArray modseq = *it; if (modseq.startsWith('(') && modseq.endsWith(')')) { modseq.chop(1); modseq.remove(0, 1); } msg.attributes.insert(name, modseq.toULongLong()); } } d->pendingMessages.insert(value, msg); } else if (code == "EXISTS") { d->messageCount = value; } else if (code == "RECENT") { d->recentCount = value; } } } else { qCDebug(KIMAP_LOG) << response.toString(); } } else { Q_ASSERT(error() || d->m_session->selectedMailBox() == d->mailBox); } } #include "moc_selectjob.cpp" 070701000000FB000081A400000000000000000000000166FAD7C000000E6D000000000000000000000000000000000000003900000000kimap-VERSIONgit.20240930T185424~db1f697/src/selectjob.h/* SPDX-FileCopyrightText: 2009 Kevin Ottens <ervin@kde.org> SPDX-License-Identifier: LGPL-2.0-or-later */ #pragma once #include "kimap_export.h" #include "fetchjob.h" #include "job.h" namespace KIMAP { class Session; struct Response; class SelectJobPrivate; class ImapSet; class KIMAP_EXPORT SelectJob : public Job { Q_OBJECT Q_DECLARE_PRIVATE(SelectJob) friend class SessionPrivate; public: explicit SelectJob(Session *session); ~SelectJob() override; void setMailBox(const QString &mailBox); [[nodiscard]] QString mailBox() const; void setOpenReadOnly(bool readOnly); /** * @return Returns whether the mailbox is opened in read-only mode. Note * that this can return true even if setOpenReadOnly() was set to false, * as the mailbox may be read-only on the server. */ [[nodiscard]] bool isOpenReadOnly() const; [[nodiscard]] QList<QByteArray> flags() const; [[nodiscard]] QList<QByteArray> permanentFlags() const; [[nodiscard]] int messageCount() const; [[nodiscard]] int recentCount() const; [[nodiscard]] int firstUnseenIndex() const; [[nodiscard]] qint64 uidValidity() const; [[nodiscard]] qint64 nextUid() const; /** * @return Highest mod-sequence value of all messages in the mailbox or 0 * if the server does not have CONDSTORE capability (RFC4551) or does not * support persistent storage of mod-sequences. * * @since 4.12 */ [[nodiscard]] quint64 highestModSequence() const; /** * Whether to append CONDSTORE parameter to the SELECT command. * * This option is false by default and can be enabled only when server * has CONDSTORE capability (RFC4551), otherwise the SELECT command will * fail. * * @since 4.12 */ void setCondstoreEnabled(bool enable); /** * Returns whether the CONDSTORE parameter will be appended to SELECT command * * @since 4.12 */ [[nodiscard]] bool condstoreEnabled() const; /** * Set Quick Resynchronization parameters. * * Requires that the server supports the QRESYNC extension as defined in RFC5162 * and the QRESYNC extension has been enabled via EnableJob. * * Using this option implies enabling CONDSTORE. * * @param lastUidvalidity Last UIDValidity value known to the client * @param lastModseq Last modification sequence number known to the client * @param knownUids List of all UIDs known to the client (optional). * * @see KIMAP::EnableJob */ void setQResync(qint64 lastUidvalidity, quint64 lastModseq, const ImapSet &knownUids = ImapSet{}); Q_SIGNALS: /** * Emitted when the server provides a list of UIDs that have vanished since last sync. * * This feature requires that the QRESYNC parameters have been provided * to the SELECT command. This signal may not be emitted if no messages * have been expunged since the last check. * * @see setQResync() * @since 5.16 */ void vanished(const KIMAP::ImapSet &set); /** * Emitted when the server provides a list of messages that have changed or appeared * in the mailbox since the last sync. * * This feature requires that the QRESYNC parameters have been provided * to the SELECT command. The signal may not be emitted if no messages * have been modified or appended to the mailbox. * * @see setQResync() * @since 5.16 */ void modified(const QMap<qint64, KIMAP::Message> &messages); protected: void doStart() override; void handleResponse(const Response &response) override; }; } 070701000000FC000081A400000000000000000000000166FAD7C0000031A3000000000000000000000000000000000000003900000000kimap-VERSIONgit.20240930T185424~db1f697/src/session.cpp/* SPDX-FileCopyrightText: 2009 Kevin Ottens <ervin@kde.org> SPDX-FileCopyrightText: 2010 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com> SPDX-FileContributor: Kevin Ottens <kevin@kdab.com> SPDX-License-Identifier: LGPL-2.0-or-later */ #include "session.h" #include "session_p.h" #include <QPointer> #include <QTimer> #include "kimap_debug.h" #include "job.h" #include "job_p.h" #include "loginjob.h" #include "response_p.h" #include "rfccodecs.h" #include "sessionlogger_p.h" #include "sessionthread_p.h" Q_DECLARE_METATYPE(QSsl::SslProtocol) Q_DECLARE_METATYPE(QSslSocket::SslMode) static const int _kimap_sslVersionId = qRegisterMetaType<QSsl::SslProtocol>(); using namespace KIMAP; Session::Session(const QString &hostName, quint16 port, QObject *parent) : QObject(parent) , d(new SessionPrivate(this)) { if (!qEnvironmentVariableIsEmpty("KIMAP_LOGFILE")) { d->logger = new SessionLogger; } d->isSocketConnected = false; d->state = Disconnected; d->jobRunning = false; d->thread = new SessionThread(hostName, port); connect(d->thread, &SessionThread::encryptionNegotiationResult, d, &SessionPrivate::onEncryptionNegotiationResult); connect(d->thread, &SessionThread::sslError, d, &SessionPrivate::handleSslError); connect(d->thread, &SessionThread::socketDisconnected, d, &SessionPrivate::socketDisconnected); connect(d->thread, &SessionThread::responseReceived, d, &SessionPrivate::responseReceived); connect(d->thread, &SessionThread::socketConnected, d, &SessionPrivate::socketConnected); connect(d->thread, &SessionThread::socketActivity, d, &SessionPrivate::socketActivity); connect(d->thread, &SessionThread::socketError, d, &SessionPrivate::socketError); d->socketTimer.setSingleShot(true); connect(&d->socketTimer, &QTimer::timeout, d, &SessionPrivate::onSocketTimeout); d->startSocketTimer(); } Session::~Session() { // Make sure all jobs know we're done d->socketDisconnected(); delete d->thread; d->thread = nullptr; } void Session::setUiProxy(const SessionUiProxy::Ptr &proxy) { d->uiProxy = proxy; } void Session::setUiProxy(SessionUiProxy *proxy) { setUiProxy(SessionUiProxy::Ptr(proxy)); } QString Session::hostName() const { return d->thread->hostName(); } quint16 Session::port() const { return d->thread->port(); } void Session::setUseNetworkProxy(bool useProxy) { d->thread->setUseNetworkProxy(useProxy); } Session::State Session::state() const { return d->state; } QString Session::userName() const { return d->userName; } QByteArray Session::serverGreeting() const { return d->greeting; } int Session::jobQueueSize() const { return d->queue.size() + (d->jobRunning ? 1 : 0); } void KIMAP::Session::close() { d->thread->closeSocket(); } void SessionPrivate::handleSslError(const KSslErrorUiData &errorData) { // ignoreSslError is async, so the thread might already be gone when it returns QPointer<SessionThread> _t = thread; const bool ignoreSslError = uiProxy && uiProxy->ignoreSslError(errorData); if (_t) { _t->sslErrorHandlerResponse(ignoreSslError); } } SessionPrivate::SessionPrivate(Session *session) : QObject(session) , q(session) , isSocketConnected(false) , state(Session::Disconnected) , logger(nullptr) , thread(nullptr) , jobRunning(false) , currentJob(nullptr) , tagCount(0) , sslVersion(QSsl::UnknownProtocol) , socketTimerInterval(30000) // By default timeouts on 30s { } SessionPrivate::~SessionPrivate() { delete logger; } void SessionPrivate::addJob(Job *job) { queue.append(job); Q_EMIT q->jobQueueSizeChanged(q->jobQueueSize()); QObject::connect(job, &KJob::result, this, &SessionPrivate::jobDone); QObject::connect(job, &QObject::destroyed, this, &SessionPrivate::jobDestroyed); if (state != Session::Disconnected) { startNext(); } } void SessionPrivate::startNext() { QMetaObject::invokeMethod(this, &SessionPrivate::doStartNext); } void SessionPrivate::doStartNext() { if (queue.isEmpty() || jobRunning || !isSocketConnected) { return; } restartSocketTimer(); jobRunning = true; currentJob = queue.dequeue(); currentJob->doStart(); } void SessionPrivate::jobDone(KJob *job) { Q_UNUSED(job) Q_ASSERT(job == currentJob); stopSocketTimer(); jobRunning = false; currentJob = nullptr; Q_EMIT q->jobQueueSizeChanged(q->jobQueueSize()); startNext(); } void SessionPrivate::jobDestroyed(QObject *job) { queue.removeAll(static_cast<KIMAP::Job *>(job)); if (currentJob == job) { currentJob = nullptr; } } void SessionPrivate::responseReceived(const Response &response) { if (logger && isConnected()) { logger->dataReceived(response.toString()); } QByteArray tag; QByteArray code; if (response.content.size() >= 1) { tag = response.content[0].toString(); } if (response.content.size() >= 2) { code = response.content[1].toString(); } // BYE may arrive as part of a LOGOUT sequence or before the server closes the connection after an error. // In any case we should wait until the server closes the connection, so we don't have to do anything. if (code == "BYE") { Response simplified = response; if (simplified.content.size() >= 2) { simplified.content.removeFirst(); // Strip the tag simplified.content.removeFirst(); // Strip the code } qCDebug(KIMAP_LOG) << "Received BYE: " << simplified.toString(); return; } switch (state) { case Session::Disconnected: if (socketTimer.isActive()) { stopSocketTimer(); } if (code == "OK") { setState(Session::NotAuthenticated); Response simplified = response; simplified.content.removeFirst(); // Strip the tag simplified.content.removeFirst(); // Strip the code greeting = simplified.toString().trimmed(); // Save the server greeting startNext(); } else if (code == "PREAUTH") { setState(Session::Authenticated); Response simplified = response; simplified.content.removeFirst(); // Strip the tag simplified.content.removeFirst(); // Strip the code greeting = simplified.toString().trimmed(); // Save the server greeting startNext(); } else { thread->closeSocket(); } return; case Session::NotAuthenticated: if (code == "OK" && tag == authTag) { setState(Session::Authenticated); } break; case Session::Authenticated: if (code == "OK" && tag == selectTag) { setState(Session::Selected); currentMailBox = upcomingMailBox; } break; case Session::Selected: if ((code == "OK" && tag == closeTag) || (code != "OK" && tag == selectTag)) { setState(Session::Authenticated); currentMailBox = QByteArray(); } else if (code == "OK" && tag == selectTag) { currentMailBox = upcomingMailBox; } break; } if (tag == authTag) { authTag.clear(); } if (tag == selectTag) { selectTag.clear(); } if (tag == closeTag) { closeTag.clear(); } // If a job is running forward it the response if (currentJob != nullptr) { restartSocketTimer(); currentJob->handleResponse(response); } else { qCWarning(KIMAP_LOG) << "A message was received from the server with no job to handle it:" << response.toString() << '(' + response.toString().toHex() + ')'; } } void SessionPrivate::setState(Session::State s) { if (s != state) { Session::State oldState = state; state = s; Q_EMIT q->stateChanged(state, oldState); } } QByteArray SessionPrivate::sendCommand(const QByteArray &command, const QByteArray &args) { QByteArray tag = 'A' + QByteArray::number(++tagCount).rightJustified(6, '0'); QByteArray payload = tag + ' ' + command; if (!args.isEmpty()) { payload += ' ' + args; } sendData(payload); if (command == "LOGIN" || command == "AUTHENTICATE") { authTag = tag; } else if (command == "SELECT" || command == "EXAMINE") { selectTag = tag; upcomingMailBox = args; upcomingMailBox.remove(0, 1); upcomingMailBox = upcomingMailBox.left(upcomingMailBox.indexOf('\"')); upcomingMailBox = KIMAP::decodeImapFolderName(upcomingMailBox); } else if (command == "CLOSE") { closeTag = tag; } return tag; } void SessionPrivate::sendData(const QByteArray &data) { restartSocketTimer(); if (logger && isConnected()) { logger->dataSent(data); } thread->sendData(data + "\r\n"); } void SessionPrivate::socketConnected() { stopSocketTimer(); isSocketConnected = true; bool willUseSsl = false; if (!queue.isEmpty()) { auto login = qobject_cast<KIMAP::LoginJob *>(queue.first()); if (login) { willUseSsl = (login->encryptionMode() == KIMAP::LoginJob::SSLorTLS); userName = login->userName(); } } if (state == Session::Disconnected && willUseSsl) { startSsl(QSsl::SecureProtocols); } else { startSocketTimer(); } } bool SessionPrivate::isConnected() const { return state == Session::Authenticated || state == Session::Selected; } void SessionPrivate::socketDisconnected() { if (socketTimer.isActive()) { stopSocketTimer(); } if (logger && isConnected()) { logger->disconnectionOccured(); } if (isSocketConnected) { setState(Session::Disconnected); Q_EMIT q->connectionLost(); } else { Q_EMIT q->connectionFailed(); } isSocketConnected = false; clearJobQueue(); } void SessionPrivate::socketActivity() { restartSocketTimer(); } void SessionPrivate::socketError(QAbstractSocket::SocketError error) { if (socketTimer.isActive()) { stopSocketTimer(); } if (currentJob) { currentJob->d_ptr->setSocketError(error); } else if (!queue.isEmpty()) { currentJob = queue.takeFirst(); currentJob->d_ptr->setSocketError(error); } if (isSocketConnected) { thread->closeSocket(); } else { Q_EMIT q->connectionFailed(); clearJobQueue(); } } void SessionPrivate::clearJobQueue() { if (currentJob) { currentJob->connectionLost(); } else if (!queue.isEmpty()) { currentJob = queue.takeFirst(); currentJob->connectionLost(); } QQueue<Job *> queueCopy = queue; // copy because jobDestroyed calls removeAll qDeleteAll(queueCopy); queue.clear(); Q_EMIT q->jobQueueSizeChanged(0); } void SessionPrivate::startSsl(QSsl::SslProtocol protocol) { thread->startSsl(protocol); } QString Session::selectedMailBox() const { return QString::fromUtf8(d->currentMailBox); } void SessionPrivate::onEncryptionNegotiationResult(bool isEncrypted, QSsl::SslProtocol protocol) { if (isEncrypted) { sslVersion = protocol; } else { sslVersion = QSsl::UnknownProtocol; } Q_EMIT encryptionNegotiationResult(isEncrypted); } QSsl::SslProtocol SessionPrivate::negotiatedEncryption() const { return sslVersion; } void SessionPrivate::setSocketTimeout(int ms) { bool timerActive = socketTimer.isActive(); if (timerActive) { stopSocketTimer(); } socketTimerInterval = ms; if (timerActive) { startSocketTimer(); } } int SessionPrivate::socketTimeout() const { return socketTimerInterval; } void SessionPrivate::startSocketTimer() { if (socketTimerInterval < 0) { return; } Q_ASSERT(!socketTimer.isActive()); socketTimer.start(socketTimerInterval); } void SessionPrivate::stopSocketTimer() { if (socketTimerInterval < 0) { return; } socketTimer.stop(); } void SessionPrivate::restartSocketTimer() { if (socketTimer.isActive()) { stopSocketTimer(); } startSocketTimer(); } void SessionPrivate::onSocketTimeout() { qCDebug(KIMAP_LOG) << "Socket timeout!"; thread->closeSocket(); } void Session::setTimeout(int timeout) { d->setSocketTimeout(timeout * 1000); } int Session::timeout() const { return d->socketTimeout() / 1000; } #include "moc_session.cpp" #include "moc_session_p.cpp" 070701000000FD000081A400000000000000000000000166FAD7C000000E70000000000000000000000000000000000000003700000000kimap-VERSIONgit.20240930T185424~db1f697/src/session.h/* SPDX-FileCopyrightText: 2009 Kevin Ottens <ervin@kde.org> SPDX-License-Identifier: LGPL-2.0-or-later */ #pragma once #include "kimap_export.h" #include <QObject> #include "sessionuiproxy.h" namespace KIMAP { class SessionPrivate; class JobPrivate; struct Response; class KIMAP_EXPORT Session : public QObject { Q_OBJECT friend class JobPrivate; public: enum State { Disconnected = 0, NotAuthenticated, Authenticated, Selected }; Q_ENUM(State) Session(const QString &hostName, quint16 port, QObject *parent = nullptr); ~Session(); [[nodiscard]] QString hostName() const; [[nodiscard]] quint16 port() const; [[nodiscard]] State state() const; /** * Returns the name that has been set with LoginJob::setUserName() * The user name is useful to uniquely identify an IMAP resource, in combination with the host name * @note If the Session was pre-authenticated, userName() will return an empty string * @since 4.7 */ [[nodiscard]] QString userName() const; [[nodiscard]] QByteArray serverGreeting() const; /** * Sets an ui proxy that displays the error messages and waits for user feedback. * @param proxy the ui proxy object */ void setUiProxy(const SessionUiProxy::Ptr &proxy); /** * Sets an ui proxy that displays the error messages and waits for user feedback. * @param proxy the ui proxy object * @deprecated Use the shared pointer version instead */ KIMAP_DEPRECATED void setUiProxy(SessionUiProxy *proxy); /** * Set the session timeout. The default is 30 seconds. * @param timeout The socket timeout in seconds, negative values disable the timeout. * @since 4.6 */ void setTimeout(int timeout); /** * Returns the session timeout. * @since 4.12 */ [[nodiscard]] int timeout() const; /** * Returns the currently selected mailbox. * @since 4.5 */ [[nodiscard]] QString selectedMailBox() const; /** * Sets whether the IMAP network connection should use the system proxy settings. * * @param useProxy @c true if the proxy is to be used * The default is to not use the proxy. * @since 5.11.41 * * @note If the session is currently connected to the IMAP server, calling this * function will disconnect and reconnect to it with the changed proxy setting. */ void setUseNetworkProxy(bool useProxy); [[nodiscard]] int jobQueueSize() const; void close(); Q_SIGNALS: void jobQueueSizeChanged(int queueSize); /** Emitted when we lose a previously established connection Likely reasons: server closed the connection, loss of internet connectivity, etc... */ void connectionLost(); /** Emitted when the Session couldn't connect to the host. Likely reasons: invalid host address, no internet connectivity, firewall blocking rules, etc... Pending jobs in the queue will be deleted, and the first job in the queue will be failed. (ie: it will have its result signal emitted with a non-zero error code.) @since 4.7 */ void connectionFailed(); /** Emitted when the session's state changes. Not very useful after all... :-) If you want to receive the stateChanged arguments in your slot, you must register the State enum with @c Q_DECLARE_METATYPE(KIMAP::Session::State) and @c qRegisterMetaType<KIMAP::Session::State>(); @since 4.7 */ void stateChanged(KIMAP::Session::State newState, KIMAP::Session::State oldState); private: friend class SessionPrivate; SessionPrivate *const d; }; } 070701000000FE000081A400000000000000000000000166FAD7C0000008B7000000000000000000000000000000000000003900000000kimap-VERSIONgit.20240930T185424~db1f697/src/session_p.h/* SPDX-FileCopyrightText: 2009 Kevin Ottens <ervin@kde.org> SPDX-License-Identifier: LGPL-2.0-or-later */ #pragma once #include "session.h" #include "sessionuiproxy.h" #include <QObject> #include <QQueue> #include <QSslSocket> #include <QString> #include <QTimer> class KJob; namespace KIMAP { class Job; struct Response; class SessionLogger; class SessionThread; class KIMAP_EXPORT SessionPrivate : public QObject { Q_OBJECT friend class Session; public: explicit SessionPrivate(Session *session); ~SessionPrivate() override; void addJob(Job *job); QByteArray sendCommand(const QByteArray &command, const QByteArray &args = QByteArray()); void startSsl(QSsl::SslProtocol protocol); void sendData(const QByteArray &data); QSsl::SslProtocol negotiatedEncryption() const; void setSocketTimeout(int ms); int socketTimeout() const; Q_SIGNALS: void encryptionNegotiationResult(bool); private Q_SLOTS: void onEncryptionNegotiationResult(bool isEncrypted, QSsl::SslProtocol sslVersion); void onSocketTimeout(); void doStartNext(); void jobDone(KJob *); void jobDestroyed(QObject *); void responseReceived(const KIMAP::Response &); void socketConnected(); void socketDisconnected(); void socketError(QAbstractSocket::SocketError error); void socketActivity(); void handleSslError(const KSslErrorUiData &errorData); private: void startNext(); void clearJobQueue(); void setState(Session::State state); void startSocketTimer(); void stopSocketTimer(); void restartSocketTimer(); bool isConnected() const; Session *const q; bool isSocketConnected = false; Session::State state; SessionLogger *logger = nullptr; SessionThread *thread = nullptr; SessionUiProxy::Ptr uiProxy; bool jobRunning = false; Job *currentJob = nullptr; QQueue<Job *> queue; QByteArray authTag; QByteArray selectTag; QByteArray closeTag; QString userName; QByteArray greeting; QByteArray currentMailBox; QByteArray upcomingMailBox; quint16 tagCount; QSsl::SslProtocol sslVersion; int socketTimerInterval = 0; QTimer socketTimer; }; } 070701000000FF000081A400000000000000000000000166FAD7C000000478000000000000000000000000000000000000003F00000000kimap-VERSIONgit.20240930T185424~db1f697/src/sessionlogger.cpp/* SPDX-FileCopyrightText: 2010 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com> SPDX-FileContributor: Kevin Ottens <kevin@kdab.com> SPDX-License-Identifier: LGPL-2.0-or-later */ #include "sessionlogger_p.h" #include "kimap_debug.h" #include <QCoreApplication> using namespace KIMAP; SessionLogger::SessionLogger() { static qint64 nextId = 0; m_id = ++nextId; m_file.setFileName(QLatin1StringView(qgetenv("KIMAP_LOGFILE")) + QLatin1Char('.') + QString::number(QCoreApplication::applicationPid()) + QLatin1Char('.') + QString::number(m_id)); if (!m_file.open(QFile::WriteOnly)) { qCWarning(KIMAP_LOG) << "Could not open log file for writing:" << m_file.fileName(); } } SessionLogger::~SessionLogger() { m_file.close(); } void SessionLogger::dataSent(const QByteArray &data) { m_file.write("C: " + data.trimmed() + '\n'); m_file.flush(); } void SessionLogger::dataReceived(const QByteArray &data) { m_file.write("S: " + data.trimmed() + '\n'); m_file.flush(); } void SessionLogger::disconnectionOccured() { m_file.write("X\n"); } 07070100000100000081A400000000000000000000000166FAD7C000000241000000000000000000000000000000000000003F00000000kimap-VERSIONgit.20240930T185424~db1f697/src/sessionlogger_p.h/* SPDX-FileCopyrightText: 2010 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com> SPDX-FileContributor: Kevin Ottens <kevin@kdab.com> SPDX-License-Identifier: LGPL-2.0-or-later */ #pragma once #include <QFile> namespace KIMAP { class SessionLoggerPrivate; class SessionLogger { public: SessionLogger(); ~SessionLogger(); void dataSent(const QByteArray &data); void dataReceived(const QByteArray &data); void disconnectionOccured(); private: Q_DISABLE_COPY(SessionLogger) qint64 m_id = 0; QFile m_file; }; } 07070100000101000081A400000000000000000000000166FAD7C000002746000000000000000000000000000000000000003F00000000kimap-VERSIONgit.20240930T185424~db1f697/src/sessionthread.cpp/* SPDX-FileCopyrightText: 2009 Kevin Ottens <ervin@kde.org> SPDX-License-Identifier: LGPL-2.0-or-later */ #include "sessionthread_p.h" #include <KSslErrorUiData> #include "kimap_debug.h" #include <QDebug> #include <QNetworkProxy> #include <QSslCipher> #include <QThread> #include "imapstreamparser.h" #include "response_p.h" using namespace KIMAP; Q_DECLARE_METATYPE(KSslErrorUiData) namespace { static const int _kimap_abstractSocketError = qRegisterMetaType<QAbstractSocket::SocketError>(); static const int _kimap_sslErrorUiData = qRegisterMetaType<KSslErrorUiData>(); } SessionThread::SessionThread(const QString &hostName, quint16 port) : QObject() , m_hostName(hostName) , m_port(port) { // Just like the Qt docs now recommend, for event-driven threads: // don't derive from QThread, create one directly and move the object to it. auto thread = new QThread(); moveToThread(thread); thread->start(); QMetaObject::invokeMethod(this, &SessionThread::threadInit); } SessionThread::~SessionThread() { QMetaObject::invokeMethod(this, &SessionThread::threadQuit); if (!thread()->wait(10 * 1000)) { qCWarning(KIMAP_LOG) << "Session thread refuses to die, killing harder..."; thread()->terminate(); // Make sure to wait until it's done, otherwise it can crash when the pthread callback is called thread()->wait(); } delete thread(); } // Called in primary thread, passes setting to secondary thread void SessionThread::setUseNetworkProxy(bool useProxy) { QMetaObject::invokeMethod( this, [this, useProxy]() { setUseProxyInternal(useProxy); }, Qt::QueuedConnection); } // Called in primary thread void SessionThread::sendData(const QByteArray &payload) { QMutexLocker locker(&m_mutex); m_dataQueue.enqueue(payload); QMetaObject::invokeMethod(this, &SessionThread::writeDataQueue); } // Called in secondary thread void SessionThread::writeDataQueue() { Q_ASSERT(QThread::currentThread() == thread()); if (!m_socket) { return; } QMutexLocker locker(&m_mutex); while (!m_dataQueue.isEmpty()) { m_socket->write(m_dataQueue.dequeue()); } } // Called in secondary thread void SessionThread::readMessage() { Q_ASSERT(QThread::currentThread() == thread()); if (!m_stream || m_stream->availableDataSize() == 0) { return; } Response message; QList<Response::Part> *payload = &message.content; try { while (!m_stream->atCommandEnd()) { if (m_stream->hasString()) { QByteArray string = m_stream->readString(); if (string == "NIL") { *payload << Response::Part(QList<QByteArray>()); } else { *payload << Response::Part(string); } } else if (m_stream->hasList()) { *payload << Response::Part(m_stream->readParenthesizedList()); } else if (m_stream->hasResponseCode()) { payload = &message.responseCode; } else if (m_stream->atResponseCodeEnd()) { payload = &message.content; } else if (m_stream->hasLiteral()) { QByteArray literal; while (!m_stream->atLiteralEnd()) { literal += m_stream->readLiteralPart(); } *payload << Response::Part(literal); } else { // Oops! Something really bad happened, we won't be able to recover // so close the socket immediately qWarning("Inconsistent state, probably due to some packet loss"); doCloseSocket(); return; } } Q_EMIT responseReceived(message); } catch (const KIMAP::ImapParserException &e) { qCWarning(KIMAP_LOG) << "The stream parser raised an exception:" << e.what(); } if (m_stream->availableDataSize() > 1) { QMetaObject::invokeMethod(this, &SessionThread::readMessage, Qt::QueuedConnection); } } // Called in main thread void SessionThread::closeSocket() { QMetaObject::invokeMethod(this, &SessionThread::doCloseSocket, Qt::QueuedConnection); } // Called in secondary thread void SessionThread::doCloseSocket() { Q_ASSERT(QThread::currentThread() == thread()); if (!m_socket) { return; } m_encryptedMode = false; qCDebug(KIMAP_LOG) << "close"; m_socket->close(); } // Called in secondary thread void SessionThread::reconnect() { Q_ASSERT(QThread::currentThread() == thread()); if (m_socket == nullptr) { // threadQuit already called return; } if (m_socket->state() != QSslSocket::ConnectedState && m_socket->state() != QSslSocket::ConnectingState) { QNetworkProxy proxy; if (!m_useProxy) { qCDebug(KIMAP_LOG) << "Connecting to IMAP server with no proxy"; proxy.setType(QNetworkProxy::NoProxy); } else { qCDebug(KIMAP_LOG) << "Connecting to IMAP server using default system proxy"; proxy.setType(QNetworkProxy::DefaultProxy); } m_socket->setProxy(proxy); if (m_encryptedMode) { qCDebug(KIMAP_LOG) << "connectToHostEncrypted" << m_hostName << m_port; m_socket->connectToHostEncrypted(m_hostName, m_port); } else { qCDebug(KIMAP_LOG) << "connectToHost" << m_hostName << m_port; m_socket->connectToHost(m_hostName, m_port); } } } // Called in secondary thread void SessionThread::threadInit() { Q_ASSERT(QThread::currentThread() == thread()); m_socket = std::make_unique<QSslSocket>(); m_stream = std::make_unique<ImapStreamParser>(m_socket.get()); connect(m_socket.get(), &QIODevice::readyRead, this, &SessionThread::readMessage, Qt::QueuedConnection); // Delay the call to slotSocketDisconnected so that it finishes disconnecting before we call reconnect() connect(m_socket.get(), &QSslSocket::disconnected, this, &SessionThread::slotSocketDisconnected, Qt::QueuedConnection); connect(m_socket.get(), &QSslSocket::connected, this, &SessionThread::socketConnected); connect(m_socket.get(), &QAbstractSocket::errorOccurred, this, &SessionThread::slotSocketError); connect(m_socket.get(), &QIODevice::bytesWritten, this, &SessionThread::socketActivity); connect(m_socket.get(), &QSslSocket::encryptedBytesWritten, this, &SessionThread::socketActivity); connect(m_socket.get(), &QIODevice::readyRead, this, &SessionThread::socketActivity); QMetaObject::invokeMethod(this, &SessionThread::reconnect, Qt::QueuedConnection); } // Called in secondary thread void SessionThread::threadQuit() { Q_ASSERT(QThread::currentThread() == thread()); m_stream.reset(); m_socket.reset(); thread()->quit(); } // Called in secondary thread void SessionThread::setUseProxyInternal(bool useProxy) { m_useProxy = useProxy; if (m_socket != nullptr) { if (m_socket->state() != QSslSocket::UnconnectedState) { m_socket->disconnectFromHost(); QMetaObject::invokeMethod(this, &SessionThread::reconnect, Qt::QueuedConnection); } } } // Called in primary thread void SessionThread::startSsl(QSsl::SslProtocol protocol) { QMetaObject::invokeMethod(this, [this, protocol]() { doStartSsl(protocol); }); } // Called in secondary thread (via invokeMethod) void SessionThread::doStartSsl(QSsl::SslProtocol protocol) { Q_ASSERT(QThread::currentThread() == thread()); if (!m_socket) { return; } m_socket->setProtocol(protocol); m_socket->ignoreSslErrors(); // Don't worry, errors are handled manually below connect(m_socket.get(), &QSslSocket::encrypted, this, &SessionThread::sslConnected); m_socket->startClientEncryption(); } // Called in secondary thread void SessionThread::slotSocketDisconnected() { Q_ASSERT(QThread::currentThread() == thread()); Q_EMIT socketDisconnected(); } // Called in secondary thread void SessionThread::slotSocketError(QAbstractSocket::SocketError error) { Q_ASSERT(QThread::currentThread() == thread()); if (!m_socket) { return; } Q_EMIT socketError(error); } // Called in secondary thread void SessionThread::sslConnected() { Q_ASSERT(QThread::currentThread() == thread()); if (!m_socket) { return; } QSslCipher cipher = m_socket->sessionCipher(); if (!m_socket->sslHandshakeErrors().isEmpty() || !m_socket->isEncrypted() || cipher.isNull() || cipher.usedBits() == 0) { qCDebug(KIMAP_LOG) << "Initial SSL handshake failed. cipher.isNull() is" << cipher.isNull() << ", cipher.usedBits() is" << cipher.usedBits() << ", the socket says:" << m_socket->errorString() << "and the list of SSL errors contains" << m_socket->sslHandshakeErrors().count() << "items."; KSslErrorUiData errorData(m_socket.get()); Q_EMIT sslError(errorData); } else { qCDebug(KIMAP_LOG) << "TLS negotiation done, the negotiated protocol is" << cipher.protocolString(); m_encryptedMode = true; Q_EMIT encryptionNegotiationResult(true, m_socket->sessionProtocol()); } } void SessionThread::sslErrorHandlerResponse(bool response) { QMetaObject::invokeMethod(this, [this, response]() { doSslErrorHandlerResponse(response); }); } // Called in secondary thread (via invokeMethod) void SessionThread::doSslErrorHandlerResponse(bool response) { Q_ASSERT(QThread::currentThread() == thread()); if (!m_socket) { return; } if (response) { m_encryptedMode = true; Q_EMIT encryptionNegotiationResult(true, m_socket->sessionProtocol()); } else { m_encryptedMode = false; Q_EMIT socketError(QAbstractSocket::SslInvalidUserDataError); m_socket->disconnectFromHost(); } } #include "moc_sessionthread_p.cpp" 07070100000102000081A400000000000000000000000166FAD7C000000729000000000000000000000000000000000000003F00000000kimap-VERSIONgit.20240930T185424~db1f697/src/sessionthread_p.h/* SPDX-FileCopyrightText: 2009 Kevin Ottens <ervin@kde.org> SPDX-License-Identifier: LGPL-2.0-or-later */ #pragma once #include <QMutex> #include <QQueue> #include <QSslSocket> #include <memory> class KSslErrorUiData; namespace KIMAP { class ImapStreamParser; struct Response; class SessionThread : public QObject { Q_OBJECT public: explicit SessionThread(const QString &hostName, quint16 port); ~SessionThread(); inline QString hostName() { return m_hostName; } inline quint16 port() { return m_port; } void setUseNetworkProxy(bool useProxy); void sendData(const QByteArray &payload); public Q_SLOTS: void closeSocket(); void startSsl(QSsl::SslProtocol protocol); void sslErrorHandlerResponse(bool result); Q_SIGNALS: void socketConnected(); void socketDisconnected(); void socketActivity(); void socketError(QAbstractSocket::SocketError); void responseReceived(const KIMAP::Response &response); void encryptionNegotiationResult(bool, QSsl::SslProtocol); void sslError(const KSslErrorUiData &); private Q_SLOTS: void reconnect(); void threadInit(); void threadQuit(); void readMessage(); void writeDataQueue(); void sslConnected(); void doCloseSocket(); void slotSocketError(QAbstractSocket::SocketError); void slotSocketDisconnected(); void doStartSsl(QSsl::SslProtocol); void doSslErrorHandlerResponse(bool result); void setUseProxyInternal(bool useProxy); private: QString m_hostName; quint16 m_port; std::unique_ptr<QSslSocket> m_socket; std::unique_ptr<ImapStreamParser> m_stream; QQueue<QByteArray> m_dataQueue; // Protects m_dataQueue QMutex m_mutex; bool m_encryptedMode = false; bool m_useProxy = false; }; } 07070100000103000081A400000000000000000000000166FAD7C0000000C2000000000000000000000000000000000000004000000000kimap-VERSIONgit.20240930T185424~db1f697/src/sessionuiproxy.cpp/* SPDX-FileCopyrightText: 2009 Andras Mantia <amantia@kde.org> SPDX-License-Identifier: LGPL-2.0-or-later */ #include "sessionuiproxy.h" KIMAP::SessionUiProxy::~SessionUiProxy() { } 07070100000104000081A400000000000000000000000166FAD7C0000004FA000000000000000000000000000000000000003E00000000kimap-VERSIONgit.20240930T185424~db1f697/src/sessionuiproxy.h/* SPDX-FileCopyrightText: 2009 Andras Mantia <amantia@kde.org> SPDX-License-Identifier: LGPL-2.0-or-later */ #pragma once #include "kimap_export.h" #include "job.h" #include <QSharedPointer> class KSslErrorUiData; namespace KIMAP { /** @short Interface to display communication errors and wait for user feedback. */ class KIMAP_EXPORT SessionUiProxy { public: using Ptr = QSharedPointer<SessionUiProxy>; virtual ~SessionUiProxy(); /** * Show an SSL error and ask the user whether it should be ignored or not. * The recommended KDE UI is the following: * @code * #include <kio/ksslui.h> * class UiProxy: public SessionUiProxy { * public: * bool ignoreSslError(const KSslErrorUiData& errorData) { * if (KIO::SslUi::askIgnoreSslErrors(errorData)) { * return true; * } else { * return false; * } * } * }; * [...] * Session session(server, port); * UiProxy *proxy = new UiProxy(); * session.setUiProxy(proxy); * @endcode * @param errorData contains details about the error. * @return true if the error can be ignored */ virtual bool ignoreSslError(const KSslErrorUiData &errorData) = 0; }; } 07070100000105000081A400000000000000000000000166FAD7C000000589000000000000000000000000000000000000003B00000000kimap-VERSIONgit.20240930T185424~db1f697/src/setacljob.cpp/* SPDX-FileCopyrightText: 2009 Andras Mantia <amantia@kde.org> SPDX-License-Identifier: LGPL-2.0-or-later */ #include "setacljob.h" #include <KLocalizedString> #include "acljobbase_p.h" #include "response_p.h" #include "rfccodecs.h" #include "session_p.h" namespace KIMAP { class SetAclJobPrivate : public AclJobBasePrivate { public: SetAclJobPrivate(Session *session, const QString &name) : AclJobBasePrivate(session, name) { } ~SetAclJobPrivate() { } }; } using namespace KIMAP; SetAclJob::SetAclJob(Session *session) : AclJobBase(*new SetAclJobPrivate(session, i18n("SetAcl"))) { } SetAclJob::~SetAclJob() { } void SetAclJob::doStart() { Q_D(SetAclJob); QByteArray r = Acl::rightsToString(d->rightList); if (d->modifier == Add) { r.prepend('+'); } else if (d->modifier == Remove) { r.prepend('-'); } d->tags << d->sessionInternal()->sendCommand("SETACL", '\"' + KIMAP::encodeImapFolderName(d->mailBox.toUtf8()) + "\" \"" + d->id + "\" \"" + r + '\"'); } void SetAclJob::setRights(AclModifier modifier, Acl::Rights rights) { Q_D(SetAclJob); d->setRights(modifier, rights); } void SetAclJob::setIdentifier(const QByteArray &identifier) { Q_D(SetAclJob); d->setIdentifier(identifier); } QByteArray SetAclJob::identifier() { Q_D(SetAclJob); return d->identifier(); } #include "moc_setacljob.cpp" 07070100000106000081A400000000000000000000000166FAD7C000000BA1000000000000000000000000000000000000003900000000kimap-VERSIONgit.20240930T185424~db1f697/src/setacljob.h/* SPDX-FileCopyrightText: 2009 Andras Mantia <amantia@kde.org> SPDX-License-Identifier: LGPL-2.0-or-later */ #pragma once #include "kimap_export.h" #include "acljobbase.h" namespace KIMAP { class Session; struct Response; class SetAclJobPrivate; /** * Sets the rights that correspond to an identifier on a mailbox * * This job can only be run when the session is in the * authenticated (or selected) state. * * This job requires that the server supports the ACL * capability, defined in * <a href="https://tools.ietf.org/html/rfc4314">RFC 4314</a>. */ class KIMAP_EXPORT SetAclJob : public AclJobBase { Q_OBJECT Q_DECLARE_PRIVATE(SetAclJob) friend class SessionPrivate; public: explicit SetAclJob(Session *session); ~SetAclJob() override; /** * Sets the rights that will be changed for the identifier * * Note that multiple calls to this method will have a * non-intuitive effect: the @p modifier value of the most * recent call will be used, but the OR'd-together values * of all calls to setRights() will be used. * * If the server does not recognise any of the rights, * the job will fail and the ACL for the mailbox will * remain unchanged. * * Note that some rights may be tied together, and must be set * or removed as a group. See ListRightsJob::possibleRights() * for more details. The server will only set a tied group * of rights if you have requested that all the rights in that * group should be set. * * @param modifier determines whether the rights will be * added to the identifier, removed from * the identifier or will replace any * existing rights assigned to the * identifier * @param rights the rights to be added, removed or set */ void setRights(AclModifier modifier, Acl::Rights rights); /** * Sets the identifier the rights will be modified for * * The meaning of identifiers depends on the server implementation, * with the following restrictions: * * - "anyone" means any authenticated user, including anonymous * - an identifier starting with a minus sign ('-') indicates * "negative rights": rights that should be taken away from * matching users * * Other than the above restrictions, ACL identifiers are usually * IMAP usernames, but could potentially be group names as well. * * Note that negative rights override positive rights: if * "fred" and "-fred" are both assigned the 'w' right, the * user "fred" will not have the 'w' right. * @param identifier the identifier to set */ void setIdentifier(const QByteArray &identifier); /** * The identifier that rights will be associated with */ [[nodiscard]] QByteArray identifier(); protected: void doStart() override; }; } 07070100000107000081A400000000000000000000000166FAD7C000001758000000000000000000000000000000000000004000000000kimap-VERSIONgit.20240930T185424~db1f697/src/setmetadatajob.cpp/* SPDX-FileCopyrightText: 2009 Andras Mantia <amantia@kde.org> SPDX-License-Identifier: LGPL-2.0-or-later */ #include "setmetadatajob.h" #include "kimap_debug.h" #include <KLocalizedString> #include "metadatajobbase_p.h" #include "response_p.h" #include "rfccodecs.h" #include "session_p.h" namespace KIMAP { class SetMetaDataJobPrivate : public MetaDataJobBasePrivate { public: SetMetaDataJobPrivate(Session *session, const QString &name) : MetaDataJobBasePrivate(session, name) , metaDataErrors({}) , maxAcceptedSize(-1) { } ~SetMetaDataJobPrivate() { } QMap<QByteArray, QByteArray> entries; QMap<QByteArray, QByteArray>::ConstIterator entriesIt; QByteArray entryName; SetMetaDataJob::MetaDataErrors metaDataErrors; qint64 maxAcceptedSize; }; } using namespace KIMAP; SetMetaDataJob::SetMetaDataJob(Session *session) : MetaDataJobBase(*new SetMetaDataJobPrivate(session, i18n("SetMetaData"))) { } SetMetaDataJob::~SetMetaDataJob() { } void SetMetaDataJob::doStart() { Q_D(SetMetaDataJob); QByteArray parameters = '\"' + KIMAP::encodeImapFolderName(d->mailBox.toUtf8()) + "\" "; d->entriesIt = d->entries.constBegin(); QByteArray command = "SETMETADATA"; bool bSimpleData = true; if (d->serverCapability == Annotatemore) { command = "SETANNOTATION"; parameters += '\"' + d->entryName + "\" "; } else { for (; d->entriesIt != d->entries.constEnd(); ++d->entriesIt) { if (d->entriesIt.value().contains('\r') || d->entriesIt.value().contains('\n')) { bSimpleData = false; break; } } d->entriesIt = d->entries.constBegin(); } parameters += '('; if (bSimpleData == true) { for (; d->entriesIt != d->entries.constEnd(); ++d->entriesIt) { parameters += '\"' + d->entriesIt.key() + "\" "; if (d->entriesIt.value().isEmpty()) { parameters += "NIL"; } else { parameters += "\"" + d->entriesIt.value() + "\""; } parameters += " "; } parameters[parameters.length() - 1] = ')'; } else { if (!d->entries.isEmpty()) { parameters += '\"' + d->entriesIt.key() + "\""; int size = d->entriesIt.value().size(); parameters += " {" + QByteArray::number(size == 0 ? 3 : size) + '}'; } } if (d->entries.isEmpty()) { parameters += ')'; } d->tags << d->sessionInternal()->sendCommand(command, parameters); // qCDebug(KIMAP_LOG) << "SENT: " << command << " " << parameters; } void SetMetaDataJob::handleResponse(const Response &response) { Q_D(SetMetaDataJob); // TODO: Test if a server can really return more then one untagged NO response. If not, no need to OR the error codes if (!response.content.isEmpty() && d->tags.contains(response.content.first().toString())) { if (response.content[1].toString() == "NO") { setError(UserDefinedError); setErrorText(i18n("%1 failed, server replied: %2", d->m_name, QLatin1StringView(response.toString().constData()))); const QByteArray responseBa = response.content[2].toString(); if (responseBa == "[ANNOTATEMORE TOOMANY]" || responseBa == "[METADATA TOOMANY]") { d->metaDataErrors |= TooMany; } else if (responseBa == "[ANNOTATEMORE TOOBIG]" || responseBa.startsWith("[METADATA MAXSIZE")) { // krazy:exclude=strings d->metaDataErrors |= TooBig; d->maxAcceptedSize = -1; if (responseBa.startsWith("[METADATA MAXSIZE")) { // krazy:exclude=strings QByteArray max = responseBa; max.replace("[METADATA MAXSIZE", ""); // krazy:exclude=doublequote_chars max.replace("]", ""); // krazy:exclude=doublequote_chars d->maxAcceptedSize = max.toLongLong(); } } else if (responseBa == "[METADATA NOPRIVATE]") { d->metaDataErrors |= NoPrivate; } } else if (response.content.size() < 2) { setErrorText(i18n("%1 failed, malformed reply from the server.", d->m_name)); } else if (response.content[1].toString() != "OK") { setError(UserDefinedError); setErrorText(i18n("%1 failed, server replied: %2", d->m_name, QLatin1StringView(response.toString().constData()))); } emitResult(); } else if (d->serverCapability == Metadata && response.content[0].toString() == "+") { QByteArray content = ""; if (d->entriesIt.value().isEmpty()) { content += "NIL"; } else { content += d->entriesIt.value(); } ++d->entriesIt; if (d->entriesIt == d->entries.constEnd()) { content += ')'; } else { content += " \"" + d->entriesIt.key() + '\"'; int size = d->entriesIt.value().size(); content += " {" + QByteArray::number(size == 0 ? 3 : size) + '}'; } // qCDebug(KIMAP_LOG) << "SENT: " << content; d->sessionInternal()->sendData(content); } } void SetMetaDataJob::addMetaData(const QByteArray &name, const QByteArray &value) { Q_D(SetMetaDataJob); if (d->serverCapability == Annotatemore && (name.startsWith("/shared") || name.startsWith("/private"))) { const QByteArray &attribute = d->getAttribute(name); d->entries[attribute] = value; d->entryName = d->removePrefix(name); } else { d->entries[name] = value; } } void SetMetaDataJob::setEntry(const QByteArray &entry) { Q_D(SetMetaDataJob); d->entryName = entry; } SetMetaDataJob::MetaDataErrors SetMetaDataJob::metaDataErrors() const { Q_D(const SetMetaDataJob); return d->metaDataErrors; } #include "moc_setmetadatajob.cpp" 07070100000108000081A400000000000000000000000166FAD7C000001BC7000000000000000000000000000000000000003E00000000kimap-VERSIONgit.20240930T185424~db1f697/src/setmetadatajob.h/* SPDX-FileCopyrightText: 2009 Andras Mantia <amantia@kde.org> SPDX-License-Identifier: LGPL-2.0-or-later */ #pragma once #include "kimap_export.h" #include "metadatajobbase.h" namespace KIMAP { class Session; struct Response; class SetMetaDataJobPrivate; /** * Sets mailbox metadata. * * Provides support for the IMAP METADATA extension; both the * final RFC version * (<a href="https://tools.ietf.org/html/rfc5464">RFC 5464</a>) * and the older, incompatible draft version (known as ANNOTATEMORE) * (<a * href="https://tools.ietf.org/html/draft-daboo-imap-annotatemore-07" * >draft-daboo-imap-annotatemore-07</a>). See setServerCompatibility(). * * Note that in Annotatemore mode, this job can only operate on * one metadata entry at once. * * This job can only be run when the session is in the * authenticated (or selected) state. * * If the server supports ACLs, the user will need the * Acl::Lookup right on the mailbox, as well as one of * - Acl::Read * - Acl::KeepSeen * - Acl::Write * - Acl::Insert * - Acl::Post * Otherwise, the user must be able to list the mailbox * and either read or write the message content. * * Note that even if the user has these permissions, the * server may refuse to allow the user to write metadata * based on some other criteria. * * Note also that on servers that implement the Annotatemore * version of the extension, only Acl::Lookup rights are * required (ie: the user must be able to list the mailbox). */ class KIMAP_EXPORT SetMetaDataJob : public MetaDataJobBase { Q_OBJECT Q_DECLARE_PRIVATE(SetMetaDataJob) friend class SessionPrivate; public: explicit SetMetaDataJob(Session *session); ~SetMetaDataJob() override; /** * Adds a metadata entry or attribute to the list of modifications to make * * When in Metadata mode, this method adds a metadata * entry to the list of metadata additions and updates that * will be performed when the job is run. * * @p name must be a valid ASCII string and may not contain two * consecutive forward slashes ('/'), must not end with '/' and * must not contain '*', '%', non-ASCII characters or characters * in the ASCII range 0x00 to 0x19 (in practice, all control * characters should be avoided). The name is case-insensitive. * * The first part of the entry name should be "/private" or * "/shared", indicating the scope of the entry. Note that * private metadata may not be supported by all servers. * * Server metadata entry names include: * - /shared/comment * - /shared/admin - a URI for contacting the server administrator * (eg: a mailto: or tel: URI) * - /shared/vendor/<vendor-token>/something * - /private/vendor/<vendor-token>/something * * Mailbox metadata entry names include: * - /shared/comment * - /private/comment * - /shared/vendor/<vendor-token>/something * - /private/vendor/<vendor-token>/something * * @p value can be any data, although if it is a multi-line string * value, CRLF line-endings must be used. * * In Annotatemore mode it is possible to prefix the entry name with a /shared or /private prefix, that is automatically translated * to an appropriate value.shared|priv attribute. * * Annotatemore legacy mode: * When in Annotatemore mode, this method adds an attribute * entry to the list of additions and updates that will be * performed on the metadata entry when the job is run. * * @p name must be a valid UTF-8 string, and may not contain the * '%' or '*' characters, or NUL. Use of non-visible UTF-8 characters * is strongly discouraged. * * Possible attribute name prefixes are: * - value - the data value of the attribute * - content-type - a MIME content type and subtype * - content-language - a RFC 3282 language code * - vendor.<vendor-token> - a vendor-specific attribute * * Attribute names an attribute name prefix followed by ".priv" for * private attributes or ".shared" for shared attributes. Note that * the attributes "size.priv" and "size.shared" are read-only * attributes set by the server, and so cannot be used with * SetMetaDataJob. * * @param name the metadata entry name (Metadata or Annotatemore mode) in ASCII or * attribute name (Annotatemore mode, if used without /shared or /private prefix) in UTF-8 * @param value the value of the entry or attribute */ // KDE5: drop ANNOTATEMORE support void addMetaData(const QByteArray &name, const QByteArray &value); /** * Sets the metadata entry name to operate on (in Annotatemore mode) * * In Annotatemore mode, this specifies the metadata entry name to * operate on. For server metadata, this is one of: * - /comment * - /motd * - /admin * - /vendor/<vendor-token>/something * * For mailbox metadata, this is one of: * - /comment * - /sort * - /thread * - /check * - /checkperiod * - /vendor/<vendor-token>/something * * Entry names must be valid UTF-8 strings that do not contain the * '%' or '*' characters, or NUL. Use of non-visible UTF-8 * characters is strongly discouraged. * * In Metadata mode, this has no effect. Metadata entry names * should instead be specified as the first argument to addMetaData(). * * @see setServerCapability() * * @param entry the metadata entry name in UTF-8 * * @deprecated Use a /shared or /private prefix with addMetaData instead. */ // KDE5: remove KIMAP_DEPRECATED void setEntry(const QByteArray &entry); /** * Possible error codes that may be returned by the server. */ enum MetaDataError { NoError = 0, /**< Used to indicate that no errors have been received */ TooMany = 1, /**< Cannot add a new metadata item, because the limit has already been reached */ TooBig = 2, /**< A metadata value was too big (see maxAcceptedSize()) */ NoPrivate = 4 /**< The server does not support private metadata entries */ }; // Q_DECLARE_WHATEVER_THAT_WAS missing Q_DECLARE_FLAGS(MetaDataErrors, MetaDataError) /** * The metadata errors received from the server. * * @return a set of error codes */ [[nodiscard]] MetaDataErrors metaDataErrors() const; /** * The maximum accepted metadata size. * * If the server replied that one of the metadata values was too * large (see metaDataErrors), this should indicate what the * maximum size accepted by the server is. * * @return the maximum value size in octets, or -1 if the limit is unknown */ [[nodiscard]] qint64 maxAcceptedSize(); protected: void doStart() override; void handleResponse(const Response &response) override; }; } Q_DECLARE_OPERATORS_FOR_FLAGS(KIMAP::SetMetaDataJob::MetaDataErrors) 07070100000109000081A400000000000000000000000166FAD7C0000007FB000000000000000000000000000000000000003D00000000kimap-VERSIONgit.20240930T185424~db1f697/src/setquotajob.cpp/* SPDX-FileCopyrightText: 2009 Andras Mantia <amantia@kde.org> SPDX-License-Identifier: LGPL-2.0-or-later */ #include "setquotajob.h" #include "kimap_debug.h" #include <KLocalizedString> #include "quotajobbase_p.h" #include "response_p.h" #include "session_p.h" namespace KIMAP { class SetQuotaJobPrivate : public QuotaJobBasePrivate { public: SetQuotaJobPrivate(Session *session, const QString &name) : QuotaJobBasePrivate(session, name) { } ~SetQuotaJobPrivate() { } QMap<QByteArray, qint64> setList; QByteArray root; }; } using namespace KIMAP; SetQuotaJob::SetQuotaJob(Session *session) : QuotaJobBase(*new SetQuotaJobPrivate(session, i18n("SetQuota"))) { } SetQuotaJob::~SetQuotaJob() { } void SetQuotaJob::doStart() { Q_D(SetQuotaJob); QByteArray s; s += '('; for (QMap<QByteArray, qint64>::ConstIterator it = d->setList.constBegin(), end = d->setList.constEnd(); it != end; ++it) { s += it.key() + ' ' + QByteArray::number(it.value()) + ' '; } if (d->setList.isEmpty()) { s += ')'; } else { s[s.length() - 1] = ')'; } qCDebug(KIMAP_LOG) << "SETQUOTA " << '\"' + d->root + "\" " + s; // XXX: [alexmerry, 2010-07-24]: should d->root be quoted properly? d->tags << d->sessionInternal()->sendCommand("SETQUOTA", '\"' + d->root + "\" " + s); } void SetQuotaJob::handleResponse(const Response &response) { Q_D(SetQuotaJob); if (handleErrorReplies(response) == NotHandled) { if (response.content.size() >= 4 && response.content[1].toString() == "QUOTA") { d->quota = d->readQuota(response.content[3]); } } } void SetQuotaJob::setQuota(const QByteArray &resource, qint64 limit) { Q_D(SetQuotaJob); d->setList[resource.toUpper()] = limit; } void SetQuotaJob::setRoot(const QByteArray &root) { Q_D(SetQuotaJob); d->root = root; } QByteArray SetQuotaJob::root() const { Q_D(const SetQuotaJob); return d->root; } #include "moc_setquotajob.cpp" 0707010000010A000081A400000000000000000000000166FAD7C000000A53000000000000000000000000000000000000003B00000000kimap-VERSIONgit.20240930T185424~db1f697/src/setquotajob.h/* SPDX-FileCopyrightText: 2009 Andras Mantia <amantia@kde.org> SPDX-License-Identifier: LGPL-2.0-or-later */ #pragma once #include "quotajobbase.h" namespace KIMAP { class Session; struct Response; class SetQuotaJobPrivate; /** * Sets resource limits on a quota root. * * Quotas are defined with respect to "resources" and "quota roots". * A resource is a numerical property that can be limited, such * as the octet size of all the messages in a mailbox, or the * number of messages in a mailbox. Each mailbox has one or more * quota roots, which are where the resource limits are defined. * A quota root may or may not be a mailbox name, and an empty * string is a valid quota root. All mailboxes with the same quota * root share the resource limits of the quota root. * * This job can only be run when the session is in the * authenticated (or selected) state. * * This job requires that the server supports the QUOTA * capability, defined in * <a href="https://tools.ietf.org/html/rfc2087">RFC 2087</a>. */ class KIMAP_EXPORT SetQuotaJob : public QuotaJobBase { Q_OBJECT Q_DECLARE_PRIVATE(SetQuotaJob) friend class SessionPrivate; public: explicit SetQuotaJob(Session *session); ~SetQuotaJob() override; /** * Set a limit for a quota resource. * * For example, you might set the limit for "STORAGE" to * 512 to limit the sum of the messages' RFC822.SIZE to * 512*1024 octets (ie: 512 kb), or the limit for "MESSAGE" * to 100 to limit the number of messages to 100. * * Note that although RFC 2087 allows a resource name to * be any string, this API actually limits resource names * to upper-case atoms. In practice, resource names will * almost certainly be composed entirely of upper-case latin * letters (A-Z). * * @param resource the resource name * @param limit the maximum value the resource may take */ void setQuota(const QByteArray &resource, qint64 limit); /** * Set the quota root the resource limits should be set for. * * Note: if the quota root does not already exist, the server * may create it and change the quota roots for any number of * existing mailboxes in an implementation-defined manner. * * @param root the quota root to set, in bytes * @see GetQuotaRootJob */ void setRoot(const QByteArray &root); /** * The quota root that will be modified. */ [[nodiscard]] QByteArray root() const; protected: void doStart() override; void handleResponse(const Response &response) override; }; } 0707010000010B000081A400000000000000000000000166FAD7C0000008FB000000000000000000000000000000000000003B00000000kimap-VERSIONgit.20240930T185424~db1f697/src/statusjob.cpp/* SPDX-FileCopyrightText: 2016 Daniel Vrátil <dvratil@kde.org> SPDX-License-Identifier: LGPL-2.0-or-later */ #include "statusjob.h" #include "job_p.h" #include "kimap_debug.h" #include "response_p.h" #include "rfccodecs.h" #include "session_p.h" #include <KLocalizedString> namespace KIMAP { class StatusJobPrivate : public JobPrivate { public: explicit StatusJobPrivate(Session *session, const QString &name) : JobPrivate(session, name) { } ~StatusJobPrivate() { } QString mailBox; QList<QByteArray> dataItems; QList<QPair<QByteArray, qint64>> status; }; } using namespace KIMAP; StatusJob::StatusJob(Session *session) : Job(*new StatusJobPrivate(session, i18nc("name of the status job", "Status"))) { } StatusJob::~StatusJob() { } void StatusJob::setMailBox(const QString &mailBox) { Q_D(StatusJob); d->mailBox = mailBox; } QString StatusJob::mailBox() const { Q_D(const StatusJob); return d->mailBox; } void StatusJob::setDataItems(const QList<QByteArray> &dataItems) { Q_D(StatusJob); d->dataItems = dataItems; } QList<QByteArray> StatusJob::dataItems() const { Q_D(const StatusJob); return d->dataItems; } QList<QPair<QByteArray, qint64>> StatusJob::status() const { Q_D(const StatusJob); return d->status; } void StatusJob::doStart() { Q_D(StatusJob); const QByteArray params = '\"' + KIMAP::encodeImapFolderName(d->mailBox.toUtf8()) + "\" (" + d->dataItems.join(' ') + ')'; d->tags << d->sessionInternal()->sendCommand("STATUS", params); } void StatusJob::handleResponse(const Response &response) { Q_D(StatusJob); if (handleErrorReplies(response) == NotHandled) { if (response.content.size() >= 3) { const QByteArray code = response.content[1].toString(); if (code == "STATUS") { const QList<QByteArray> resp = response.content[3].toList(); for (int i = 0; i < resp.size(); i += 2) { d->status << (qMakePair(resp[i], resp[i + 1].toLongLong())); } } else if (code == "OK") { return; } else { qCDebug(KIMAP_LOG) << response.toString(); } } } } #include "moc_statusjob.cpp" 0707010000010C000081A400000000000000000000000166FAD7C000000346000000000000000000000000000000000000003900000000kimap-VERSIONgit.20240930T185424~db1f697/src/statusjob.h/* SPDX-FileCopyrightText: 2016 Daniel Vrátil <dvratil@kde.org> SPDX-License-Identifier: LGPL-2.0-or-later */ #pragma once #include "kimap_export.h" #include "job.h" #include <QList> namespace KIMAP { class Session; class StatusJobPrivate; class KIMAP_EXPORT StatusJob : public Job { Q_OBJECT Q_DECLARE_PRIVATE(StatusJob) friend class StatusJobPrivate; public: explicit StatusJob(Session *session); ~StatusJob() override; void setMailBox(const QString &mailBox); [[nodiscard]] QString mailBox() const; void setDataItems(const QList<QByteArray> &dataItems); [[nodiscard]] QList<QByteArray> dataItems() const; [[nodiscard]] QList<QPair<QByteArray, qint64>> status() const; protected: void doStart() override; void handleResponse(const Response &response) override; }; } 0707010000010D000081A400000000000000000000000166FAD7C0000013D4000000000000000000000000000000000000003A00000000kimap-VERSIONgit.20240930T185424~db1f697/src/storejob.cpp/* SPDX-FileCopyrightText: 2009 Kevin Ottens <ervin@kde.org> SPDX-License-Identifier: LGPL-2.0-or-later */ #include "storejob.h" #include "kimap_debug.h" #include <KLocalizedString> #include "job_p.h" #include "response_p.h" #include "session_p.h" namespace KIMAP { class StoreJobPrivate : public JobPrivate { public: StoreJobPrivate(Session *session, const QString &name) : JobPrivate(session, name) , uidBased(false) { } ~StoreJobPrivate() { } QByteArray addFlags(const QByteArray ¶m, const MessageFlags &flags) { QByteArray parameters; switch (mode) { case StoreJob::SetFlags: parameters += param; break; case StoreJob::AppendFlags: parameters += "+" + param; break; case StoreJob::RemoveFlags: parameters += "-" + param; break; } parameters += " ("; for (const QByteArray &flag : flags) { parameters += flag + ' '; } if (!flags.isEmpty()) { parameters.chop(1); } parameters += ')'; return parameters; } ImapSet set; bool uidBased; StoreJob::StoreMode mode; MessageFlags flags; MessageFlags gmLabels; QMap<int, MessageFlags> resultingFlags; }; } using namespace KIMAP; StoreJob::StoreJob(Session *session) : Job(*new StoreJobPrivate(session, i18n("Store"))) { Q_D(StoreJob); d->uidBased = false; d->mode = SetFlags; } StoreJob::~StoreJob() { } void StoreJob::setSequenceSet(const ImapSet &set) { Q_D(StoreJob); d->set = set; } ImapSet StoreJob::sequenceSet() const { Q_D(const StoreJob); return d->set; } void StoreJob::setUidBased(bool uidBased) { Q_D(StoreJob); d->uidBased = uidBased; } bool StoreJob::isUidBased() const { Q_D(const StoreJob); return d->uidBased; } void StoreJob::setFlags(const MessageFlags &flags) { Q_D(StoreJob); d->flags = flags; } MessageFlags StoreJob::flags() const { Q_D(const StoreJob); return d->flags; } void StoreJob::setGMLabels(const MessageFlags &gmLabels) { Q_D(StoreJob); d->gmLabels = gmLabels; } MessageFlags StoreJob::gmLabels() const { Q_D(const StoreJob); return d->gmLabels; } void StoreJob::setMode(StoreMode mode) { Q_D(StoreJob); d->mode = mode; } StoreJob::StoreMode StoreJob::mode() const { Q_D(const StoreJob); return d->mode; } QMap<int, MessageFlags> StoreJob::resultingFlags() const { Q_D(const StoreJob); return d->resultingFlags; } void StoreJob::doStart() { Q_D(StoreJob); if (d->set.isEmpty()) { qCWarning(KIMAP_LOG) << "Empty uid set passed to store job"; setError(KJob::UserDefinedError); setErrorText(QStringLiteral("Empty uid set passed to store job")); emitResult(); return; } d->set.optimize(); QByteArray parameters = d->set.toImapSequenceSet() + ' '; if (!d->flags.isEmpty()) { parameters += d->addFlags("FLAGS", d->flags); } if (!d->gmLabels.isEmpty()) { if (!d->flags.isEmpty()) { parameters += ' '; } parameters += d->addFlags("X-GM-LABELS", d->gmLabels); } qCDebug(KIMAP_LOG) << parameters; QByteArray command = "STORE"; if (d->uidBased) { command = "UID " + command; } d->tags << d->sessionInternal()->sendCommand(command, parameters); } void StoreJob::handleResponse(const Response &response) { Q_D(StoreJob); if (handleErrorReplies(response) == NotHandled) { if (response.content.size() == 4 && response.content[2].toString() == "FETCH" && response.content[3].type() == Response::Part::List) { int id = response.content[1].toString().toInt(); qint64 uid = 0; bool uidFound = false; QList<QByteArray> resultingFlags; QList<QByteArray> content = response.content[3].toList(); for (QList<QByteArray>::ConstIterator it = content.constBegin(); it != content.constEnd(); ++it) { QByteArray str = *it; ++it; if (str == "FLAGS") { if ((*it).startsWith('(') && (*it).endsWith(')')) { QByteArray str = *it; str.chop(1); str.remove(0, 1); resultingFlags = str.split(' '); } else { resultingFlags << *it; } } else if (str == "UID") { uid = it->toLongLong(&uidFound); } } if (!d->uidBased) { d->resultingFlags[id] = resultingFlags; } else if (uidFound) { d->resultingFlags[uid] = resultingFlags; } else { qCWarning(KIMAP_LOG) << "We asked for UID but the server didn't give it back, resultingFlags not stored."; } } } } #include "moc_storejob.cpp" 0707010000010E000081A400000000000000000000000166FAD7C0000004A6000000000000000000000000000000000000003800000000kimap-VERSIONgit.20240930T185424~db1f697/src/storejob.h/* SPDX-FileCopyrightText: 2009 Kevin Ottens <ervin@kde.org> SPDX-License-Identifier: LGPL-2.0-or-later */ #pragma once #include "kimap_export.h" #include "imapset.h" #include "job.h" namespace KIMAP { class Session; struct Response; class StoreJobPrivate; using MessageFlags = QList<QByteArray>; class KIMAP_EXPORT StoreJob : public Job { Q_OBJECT Q_DECLARE_PRIVATE(StoreJob) friend class SessionPrivate; public: enum StoreMode { SetFlags, AppendFlags, RemoveFlags }; explicit StoreJob(Session *session); ~StoreJob() override; void setSequenceSet(const ImapSet &set); [[nodiscard]] ImapSet sequenceSet() const; void setUidBased(bool uidBased); [[nodiscard]] bool isUidBased() const; void setFlags(const MessageFlags &flags); [[nodiscard]] MessageFlags flags() const; void setGMLabels(const MessageFlags &gmLabels); [[nodiscard]] MessageFlags gmLabels() const; void setMode(StoreMode mode); [[nodiscard]] StoreMode mode() const; [[nodiscard]] QMap<int, MessageFlags> resultingFlags() const; protected: void doStart() override; void handleResponse(const Response &response) override; }; } 0707010000010F000081A400000000000000000000000166FAD7C000000456000000000000000000000000000000000000003E00000000kimap-VERSIONgit.20240930T185424~db1f697/src/subscribejob.cpp/* SPDX-FileCopyrightText: 2009 Andras Mantia <amantia@kde.org> SPDX-License-Identifier: LGPL-2.0-or-later */ #include "subscribejob.h" #include <KLocalizedString> #include "job_p.h" #include "response_p.h" #include "rfccodecs.h" #include "session_p.h" namespace KIMAP { class SubscribeJobPrivate : public JobPrivate { public: SubscribeJobPrivate(Session *session, const QString &name) : JobPrivate(session, name) { } ~SubscribeJobPrivate() { } QString mailBox; }; } using namespace KIMAP; SubscribeJob::SubscribeJob(Session *session) : Job(*new SubscribeJobPrivate(session, i18n("Subscribe"))) { } SubscribeJob::~SubscribeJob() { } void SubscribeJob::doStart() { Q_D(SubscribeJob); d->tags << d->sessionInternal()->sendCommand("SUBSCRIBE", '\"' + KIMAP::encodeImapFolderName(d->mailBox.toUtf8()) + '\"'); } void SubscribeJob::setMailBox(const QString &mailBox) { Q_D(SubscribeJob); d->mailBox = mailBox; } QString SubscribeJob::mailBox() const { Q_D(const SubscribeJob); return d->mailBox; } #include "moc_subscribejob.cpp" 07070100000110000081A400000000000000000000000166FAD7C00000024E000000000000000000000000000000000000003C00000000kimap-VERSIONgit.20240930T185424~db1f697/src/subscribejob.h/* SPDX-FileCopyrightText: 2009 Andras Mantia <amantia@kde.org> SPDX-License-Identifier: LGPL-2.0-or-later */ #pragma once #include "kimap_export.h" #include "job.h" namespace KIMAP { class Session; class SubscribeJobPrivate; class KIMAP_EXPORT SubscribeJob : public Job { Q_OBJECT Q_DECLARE_PRIVATE(SubscribeJob) friend class SessionPrivate; public: explicit SubscribeJob(Session *session); ~SubscribeJob() override; void setMailBox(const QString &mailBox); [[nodiscard]] QString mailBox() const; protected: void doStart() override; }; } 07070100000111000081A400000000000000000000000166FAD7C00000047A000000000000000000000000000000000000004000000000kimap-VERSIONgit.20240930T185424~db1f697/src/unsubscribejob.cpp/* SPDX-FileCopyrightText: 2009 Andras Mantia <amantia@kde.org> SPDX-License-Identifier: LGPL-2.0-or-later */ #include "unsubscribejob.h" #include <KLocalizedString> #include "job_p.h" #include "response_p.h" #include "rfccodecs.h" #include "session_p.h" namespace KIMAP { class UnsubscribeJobPrivate : public JobPrivate { public: UnsubscribeJobPrivate(Session *session, const QString &name) : JobPrivate(session, name) { } ~UnsubscribeJobPrivate() { } QString mailBox; }; } using namespace KIMAP; UnsubscribeJob::UnsubscribeJob(Session *session) : Job(*new UnsubscribeJobPrivate(session, i18n("Unsubscribe"))) { } UnsubscribeJob::~UnsubscribeJob() { } void UnsubscribeJob::doStart() { Q_D(UnsubscribeJob); d->tags << d->sessionInternal()->sendCommand("UNSUBSCRIBE", '\"' + KIMAP::encodeImapFolderName(d->mailBox.toUtf8()) + '\"'); } void UnsubscribeJob::setMailBox(const QString &mailBox) { Q_D(UnsubscribeJob); d->mailBox = mailBox; } QString UnsubscribeJob::mailBox() const { Q_D(const UnsubscribeJob); return d->mailBox; } #include "moc_unsubscribejob.cpp" 07070100000112000081A400000000000000000000000166FAD7C000000258000000000000000000000000000000000000003E00000000kimap-VERSIONgit.20240930T185424~db1f697/src/unsubscribejob.h/* SPDX-FileCopyrightText: 2009 Andras Mantia <amantia@kde.org> SPDX-License-Identifier: LGPL-2.0-or-later */ #pragma once #include "kimap_export.h" #include "job.h" namespace KIMAP { class Session; class UnsubscribeJobPrivate; class KIMAP_EXPORT UnsubscribeJob : public Job { Q_OBJECT Q_DECLARE_PRIVATE(UnsubscribeJob) friend class SessionPrivate; public: explicit UnsubscribeJob(Session *session); ~UnsubscribeJob() override; void setMailBox(const QString &mailBox); [[nodiscard]] QString mailBox() const; protected: void doStart() override; }; } 07070100000113000041ED00000000000000000000000266FAD7C000000000000000000000000000000000000000000000002F00000000kimap-VERSIONgit.20240930T185424~db1f697/tests07070100000114000081A400000000000000000000000166FAD7C000000163000000000000000000000000000000000000003E00000000kimap-VERSIONgit.20240930T185424~db1f697/tests/CMakeLists.txt# SPDX-FileCopyrightText: none # SPDX-License-Identifier: BSD-3-Clause kde_enable_exceptions() add_executable(testimapidle testimapidle.cpp) target_link_libraries(testimapidle KPim6IMAP Qt::Test KF6::KIOCore Qt::Network) add_executable(testimapserver testimapserver.cpp) target_link_libraries(testimapserver KPim6IMAP Qt::Test KF6::KIOCore Qt::Network) 07070100000115000081A400000000000000000000000166FAD7C000000E8D000000000000000000000000000000000000004000000000kimap-VERSIONgit.20240930T185424~db1f697/tests/testimapidle.cpp/** * This file is part of the KDE project * SPDX-FileCopyrightText: 2009 Kevin Ottens <ervin@kde.org> * * SPDX-License-Identifier: LGPL-2.0-or-later */ #include <QCoreApplication> #include <QDebug> #include "capabilitiesjob.h" #include "closejob.h" #include "idlejob.h" #include "loginjob.h" #include "logoutjob.h" #include "selectjob.h" #include "session.h" #include "sessionuiproxy.h" using namespace KIMAP; class UiProxy : public SessionUiProxy { public: bool ignoreSslError(const KSslErrorUiData &errorData) override { Q_UNUSED(errorData) return true; } }; int main(int argc, char **argv) { QCoreApplication::setApplicationName(QStringLiteral("TestImapIdle")); if (argc < 4) { qCritical() << "Not enough parameters, expecting: <server> <user> <password>"; } QString server = QString::fromLocal8Bit(argv[1]); int port = 143; if (server.count(QLatin1Char(':')) == 1) { const QStringList lstSplit = server.split(QLatin1Char(':')); port = lstSplit.last().toInt(); server = lstSplit.first(); } QString user = QString::fromLocal8Bit(argv[2]); QString password = QString::fromLocal8Bit(argv[3]); qDebug() << "Listening:" << server << port << user << password; qDebug(); QCoreApplication app(argc, argv); Session session(server, port); auto proxy = new UiProxy(); session.setUiProxy(UiProxy::Ptr(proxy)); qDebug() << "Logging in..."; auto login = new LoginJob(&session); login->setUserName(user); login->setPassword(password); login->exec(); Q_ASSERT_X(login->error() == 0, "LoginJob", login->errorString().toLocal8Bit().constData()); Q_ASSERT(session.state() == Session::Authenticated); qDebug(); qDebug() << "Asking for capabilities:"; auto capabilities = new CapabilitiesJob(&session); capabilities->exec(); Q_ASSERT_X(capabilities->error() == 0, "CapabilitiesJob", capabilities->errorString().toLocal8Bit().constData()); Q_ASSERT(session.state() == Session::Authenticated); qDebug() << capabilities->capabilities(); qDebug(); Q_ASSERT(capabilities->capabilities().contains(QLatin1StringView("IDLE"))); qDebug() << "Selecting INBOX:"; auto select = new SelectJob(&session); select->setMailBox(QStringLiteral("INBOX")); select->exec(); Q_ASSERT_X(select->error() == 0, "SelectJob", select->errorString().toLocal8Bit().constData()); Q_ASSERT(session.state() == Session::Selected); qDebug() << "Flags:" << select->flags(); qDebug() << "Permanent flags:" << select->permanentFlags(); qDebug() << "Total Number of Messages:" << select->messageCount(); qDebug() << "Number of recent Messages:" << select->recentCount(); qDebug() << "First Unseen Message Index:" << select->firstUnseenIndex(); qDebug() << "UID validity:" << select->uidValidity(); qDebug() << "Next UID:" << select->nextUid(); qDebug(); qDebug() << "Start idling..."; auto idle = new IdleJob(&session); QObject::connect(idle, &KIMAP::IdleJob::mailBoxStats, idle, &KIMAP::IdleJob::stop); idle->exec(); qDebug() << "Idling done for" << idle->lastMailBox() << "message count:" << idle->lastMessageCount() << "recent count:" << idle->lastRecentCount(); qDebug() << "Closing INBOX:"; auto close = new CloseJob(&session); close->exec(); Q_ASSERT(session.state() == Session::Authenticated); qDebug(); qDebug() << "Logging out..."; auto logout = new LogoutJob(&session); logout->exec(); Q_ASSERT_X(logout->error() == 0, "LogoutJob", logout->errorString().toLocal8Bit().constData()); Q_ASSERT(session.state() == Session::Disconnected); return 0; } 07070100000116000081A400000000000000000000000166FAD7C0000062CB000000000000000000000000000000000000004200000000kimap-VERSIONgit.20240930T185424~db1f697/tests/testimapserver.cpp/** * This file is part of the KDE project * SPDX-FileCopyrightText: 2009 Kevin Ottens <ervin@kde.org> * SPDX-FileCopyrightText: 2009 Andras Mantia <amantia@kde.org> * * SPDX-License-Identifier: LGPL-2.0-or-later */ #include <QCoreApplication> #include <QDebug> #include "acl.h" #include "appendjob.h" #include "capabilitiesjob.h" #include "closejob.h" #include "createjob.h" #include "deleteacljob.h" #include "deletejob.h" #include "expungejob.h" #include "fetchjob.h" #include "getacljob.h" #include "getmetadatajob.h" #include "listjob.h" #include "listrightsjob.h" #include "loginjob.h" #include "logoutjob.h" #include "myrightsjob.h" #include "namespacejob.h" #include "renamejob.h" #include "selectjob.h" #include "session.h" #include "sessionuiproxy.h" #include "setacljob.h" #include "setmetadatajob.h" #include "storejob.h" #include "subscribejob.h" #include "unsubscribejob.h" using namespace KIMAP; using PartsReceivedSignal = void (FetchJob::*)(const QString &, const QMap<qint64, qint64> &, const QMap<qint64, MessageParts> &); using HeadersReceivedSignal = void (FetchJob::*)(const QString &, const QMap<qint64, qint64> &, const QMap<qint64, qint64> &, const QMap<qint64, MessageFlags> &, const QMap<qint64, MessagePtr> &); class UiProxy : public SessionUiProxy { public: bool ignoreSslError(const KSslErrorUiData &errorData) override { Q_UNUSED(errorData) return true; } }; void dumpContentHelper(KMime::Content *part, const QString &partId = QString()) { if (partId.isEmpty()) { qDebug() << "** Message root **"; } else { qDebug() << "** Part" << partId << "**"; } qDebug() << part->head(); KMime::Content::List children = part->contents(); for (int i = 0; i < children.size(); i++) { QString newId = partId; if (!newId.isEmpty()) { newId += QLatin1StringView("."); } newId += QString::number(i + 1); dumpContentHelper(children[i], newId); } } void listFolders(Session *session, bool includeUnsubscribed = false, const QString &nameFilter = QLatin1StringView("")) { auto list = new ListJob(session); list->setOption(includeUnsubscribed ? KIMAP::ListJob::IncludeUnsubscribed : KIMAP::ListJob::NoOption); list->exec(); Q_ASSERT_X(list->error() == 0, "ListJob", list->errorString().toLocal8Bit().constData()); int count = list->mailBoxes().size(); for (int i = 0; i < count; ++i) { MailBoxDescriptor descriptor = list->mailBoxes()[i]; if (descriptor.name.endsWith(nameFilter)) { qDebug() << descriptor.separator << descriptor.name; } } } void testMetaData(Session *session) { qDebug() << "TESTING: METADATA commands"; auto create = new CreateJob(session); create->setMailBox(QStringLiteral("INBOX/TestFolder")); create->exec(); auto setmetadata = new SetMetaDataJob(session); setmetadata->setMailBox(QStringLiteral("INBOX/TestFolder")); setmetadata->setServerCapability(SetMetaDataJob::Annotatemore); setmetadata->setEntry("/comment"); setmetadata->addMetaData("value.priv", "My new comment"); setmetadata->exec(); setmetadata = new SetMetaDataJob(session); setmetadata->setMailBox(QStringLiteral("INBOX/TestFolder")); setmetadata->setServerCapability(SetMetaDataJob::Annotatemore); setmetadata->setEntry("/check"); setmetadata->addMetaData("value.priv", "true"); setmetadata->exec(); auto getmetadata = new GetMetaDataJob(session); getmetadata->setMailBox(QStringLiteral("INBOX/TestFolder")); getmetadata->setServerCapability(SetMetaDataJob::Annotatemore); getmetadata->addEntry("/*", "value.priv"); getmetadata->exec(); Q_ASSERT_X(getmetadata->metaData(QLatin1StringView("INBOX/TestFolder"), "/check", "value.priv") == "true", "", "/check metadata should be true"); Q_ASSERT_X(getmetadata->metaData(QLatin1StringView("INBOX/TestFolder"), "/comment", "value.priv") == "My new comment", "", "/check metadata should be My new comment"); // cleanup auto deletejob = new DeleteJob(session); deletejob->setMailBox(QLatin1StringView("INBOX/TestFolder")); deletejob->exec(); } void testAcl(Session *session, const QString &user) { qDebug() << "TESTING: ACL commands"; auto create = new CreateJob(session); create->setMailBox(QStringLiteral("INBOX/TestFolder")); create->exec(); auto listRights = new ListRightsJob(session); listRights->setMailBox(QStringLiteral("INBOX/TestFolder")); listRights->setIdentifier(user.toLatin1()); listRights->exec(); qDebug() << "Default rights on INBOX/TestFolder: " << Acl::rightsToString(listRights->defaultRights()); const QList<Acl::Rights> possible = listRights->possibleRights(); QStringList strList; for (Acl::Rights r : std::as_const(possible)) { strList << QString::fromLatin1(Acl::rightsToString(r)); } qDebug() << "Possible rights on INBOX/TestFolder: " << strList; auto myRights = new MyRightsJob(session); myRights->setMailBox(QStringLiteral("INBOX/TestFolder")); myRights->exec(); Acl::Rights mine = myRights->rights(); qDebug() << "My rights on INBOX/TestFolder: " << Acl::rightsToString(mine); qDebug() << "Reading INBOX/TestFolder is possible: " << myRights->hasRightEnabled(Acl::Read); Q_ASSERT_X(myRights->hasRightEnabled(Acl::Read), "Reading INBOX is NOT possible", ""); auto getAcl = new GetAclJob(session); getAcl->setMailBox(QStringLiteral("INBOX/TestFolder")); getAcl->exec(); qDebug() << "Anyone rights on INBOX/TestFolder: " << getAcl->rights("anyone"); Acl::Rights users = getAcl->rights(user.toLatin1()); qDebug() << user << " rights on INBOX/TestFolder: " << Acl::rightsToString(users); Q_ASSERT_X(mine == users, "GETACL returns different rights for the same user", ""); qDebug() << "Removing Delete right "; mine = Acl::Delete; auto setAcl = new SetAclJob(session); setAcl->setMailBox(QStringLiteral("INBOX/TestFolder")); setAcl->setIdentifier(user.toLatin1()); setAcl->setRights(AclJobBase::Remove, mine); setAcl->exec(); getAcl = new GetAclJob(session); getAcl->setMailBox(QStringLiteral("INBOX/TestFolder")); getAcl->exec(); users = getAcl->rights(user.toLatin1()); qDebug() << user << " rights on INBOX/TestFolder: " << Acl::rightsToString(users); qDebug() << "Adding back Delete right "; mine = Acl::Delete; setAcl = new SetAclJob(session); setAcl->setMailBox(QStringLiteral("INBOX/TestFolder")); setAcl->setIdentifier(user.toLatin1()); setAcl->setRights(AclJobBase::Add, mine); setAcl->exec(); getAcl = new GetAclJob(session); getAcl->setMailBox(QStringLiteral("INBOX/TestFolder")); getAcl->exec(); users = getAcl->rights(user.toLatin1()); qDebug() << user << " rights on INBOX/TestFolder: " << Acl::rightsToString(users); // cleanup auto deletejob = new DeleteJob(session); deletejob->setMailBox(QStringLiteral("INBOX/TestFolder")); deletejob->exec(); } void testAppendAndStore(Session *session) { qDebug() << "TESTING: APPEND and STORE"; // setup auto create = new CreateJob(session); create->setMailBox(QStringLiteral("INBOX/TestFolder")); create->exec(); QByteArray testMailContent = "Date: Mon, 7 Feb 1994 21:52:25 -0800 (PST)\r\n" "From: Fred Foobar <foobar@Blurdybloop.COM>\r\n" "Subject: afternoon meeting\r\n" "To: mooch@owatagu.siam.edu\r\n" "Message-Id: <B27397-0100000@Blurdybloop.COM>\r\n" "MIME-Version: 1.0\r\n" "Content-Type: TEXT/PLAIN; CHARSET=US-ASCII\r\n" "\r\n" "Hello Joe, do you think we can meet at 3:30 tomorrow?\r\n"; qDebug() << "Append a message in INBOX/TestFolder..."; auto append = new AppendJob(session); append->setMailBox(QStringLiteral("INBOX/TestFolder")); append->setContent(testMailContent); append->exec(); Q_ASSERT_X(append->error() == 0, "AppendJob", append->errorString().toLocal8Bit().constData()); qDebug() << "Read the message back and compare..."; auto select = new SelectJob(session); select->setMailBox(QStringLiteral("INBOX/TestFolder")); select->exec(); auto fetch = new FetchJob(session); FetchJob::FetchScope scope; fetch->setSequenceSet(ImapSet(1)); scope.parts.clear(); scope.mode = FetchJob::FetchScope::Content; fetch->setScope(scope); MessagePtr message; QObject::connect(fetch, static_cast<HeadersReceivedSignal>(&FetchJob::headersReceived), fetch, [&](const QString &, const QMap<qint64, qint64> &, const QMap<qint64, qint64> &, const QMap<qint64, MessageFlags> &, const QMap<qint64, MessagePtr> &msgs) { message = msgs[1]; }); fetch->exec(); Q_ASSERT_X(fetch->error() == 0, "FetchJob", fetch->errorString().toLocal8Bit().constData()); testMailContent.replace("\r\n", "\n"); Q_ASSERT_X(testMailContent == message->head() + "\n" + message->body(), "Message differs from reference", QByteArray(message->head() + "\n" + message->body()).constData()); fetch = new FetchJob(session); fetch->setSequenceSet(ImapSet(1)); scope.parts.clear(); scope.mode = FetchJob::FetchScope::Flags; fetch->setScope(scope); MessageFlags expectedFlags; QObject::connect(fetch, static_cast<HeadersReceivedSignal>(&FetchJob::headersReceived), fetch, [&](const QString &, const QMap<qint64, qint64> &, const QMap<qint64, qint64> &, const QMap<qint64, MessageFlags> &flags, const QMap<qint64, MessagePtr> &) { expectedFlags = flags[1]; }); fetch->exec(); qDebug() << "Read the message flags:" << expectedFlags; qDebug() << "Add the \\Deleted flag..."; expectedFlags << "\\Deleted"; std::sort(expectedFlags.begin(), expectedFlags.end()); auto store = new StoreJob(session); store->setSequenceSet(ImapSet(1)); store->setMode(StoreJob::AppendFlags); store->setFlags(QList<QByteArray>() << "\\Deleted"); store->exec(); Q_ASSERT_X(store->error() == 0, "StoreJob", store->errorString().toLocal8Bit().constData()); QList<QByteArray> resultingFlags = store->resultingFlags()[1]; std::sort(resultingFlags.begin(), resultingFlags.end()); if (expectedFlags != resultingFlags) { qDebug() << resultingFlags; } Q_ASSERT(expectedFlags == resultingFlags); select = new SelectJob(session); select->setMailBox(QStringLiteral("INBOX")); select->exec(); // cleanup auto deletejob = new DeleteJob(session); deletejob->setMailBox(QStringLiteral("INBOX/TestFolder")); deletejob->exec(); deletejob = new DeleteJob(session); deletejob->setMailBox(QStringLiteral("INBOX/RenamedTestFolder")); deletejob->exec(); } void testRename(Session *session) { qDebug() << "TESTING: RENAME"; // setup auto create = new CreateJob(session); create->setMailBox(QStringLiteral("INBOX/TestFolder")); create->exec(); qDebug() << "Listing mailboxes with name TestFolder:"; listFolders(session, true, QStringLiteral("TestFolder")); // actual tests qDebug() << "Renaming to RenamedTestFolder"; auto rename = new RenameJob(session); rename->setSourceMailBox(QStringLiteral("INBOX/TestFolder")); rename->setDestinationMailBox(QStringLiteral("INBOX/RenamedTestFolder")); rename->exec(); qDebug() << "Listing mailboxes with name TestFolder:"; listFolders(session, true, QStringLiteral("TestFolder")); qDebug() << "Listing mailboxes with name RenamedTestFolder:"; listFolders(session, true, QStringLiteral("RenamedTestFolder")); // cleanup auto deletejob = new DeleteJob(session); deletejob->setMailBox(QStringLiteral("INBOX/TestFolder")); deletejob->exec(); deletejob = new DeleteJob(session); deletejob->setMailBox(QStringLiteral("INBOX/RenamedTestFolder")); deletejob->exec(); } void testSubscribe(Session *session) { qDebug() << "TESTING: SUBSCRIBE/UNSUBSCRIBE"; // setup auto create = new CreateJob(session); create->setMailBox(QStringLiteral("INBOX/TestFolder")); create->exec(); qDebug() << "Listing subscribed mailboxes with name TestFolder:"; listFolders(session, false, QStringLiteral("TestFolder")); // actual tests qDebug() << "Subscribing to INBOX/TestFolder"; auto subscribe = new SubscribeJob(session); subscribe->setMailBox(QStringLiteral("INBOX/TestFolder")); subscribe->exec(); qDebug() << "Listing subscribed mailboxes with name TestFolder:"; listFolders(session, false, QStringLiteral("TestFolder")); qDebug() << "Unsubscribing from INBOX/TestFolder"; auto unsubscribe = new UnsubscribeJob(session); unsubscribe->setMailBox(QStringLiteral("INBOX/TestFolder")); unsubscribe->exec(); qDebug() << "Listing subscribed mailboxes with name TestFolder:"; listFolders(session, false, QStringLiteral("TestFolder")); // cleanup auto deletejob = new DeleteJob(session); deletejob->setMailBox(QStringLiteral("INBOX/TestFolder")); deletejob->exec(); } void testDelete(Session *session) { qDebug() << "TESTING: DELETE"; qDebug() << "Creating INBOX/TestFolder:"; auto create = new CreateJob(session); create->setMailBox(QStringLiteral("INBOX/TestFolder")); create->exec(); qDebug() << "Listing with name TestFolder before DELETE:"; listFolders(session, true, QStringLiteral("TestFolder")); qDebug() << "Deleting INBOX/TestFolder"; auto deletejob = new DeleteJob(session); deletejob->setMailBox(QStringLiteral("INBOX/TestFolder")); deletejob->exec(); qDebug() << "Listing with name TestFolder after DELETE:"; listFolders(session, true, QStringLiteral("TestFolder")); } int main(int argc, char **argv) { QCoreApplication::setApplicationName(QStringLiteral("TestImapServer")); if (argc < 4) { qCritical() << "Not enough parameters, expecting: <server> <user> <password>"; } QString server = QString::fromLocal8Bit(argv[1]); int port = 143; if (server.count(QLatin1Char(':')) == 1) { const QStringList lstSplit = server.split(QLatin1Char(':')); port = lstSplit.last().toInt(); server = lstSplit.first(); } QString user = QString::fromLocal8Bit(argv[2]); QString password = QString::fromLocal8Bit(argv[3]); qDebug() << "Querying:" << server << port << user << password; qDebug(); QCoreApplication app(argc, argv); Session session(server, port); UiProxy::Ptr proxy(new UiProxy()); session.setUiProxy(proxy); qDebug() << "Logging in..."; auto login = new LoginJob(&session); // login->setEncryptionMode( LoginJob::TlsV1 ); // login->setAuthenticationMode( LoginJob::Plain ); login->setUserName(user); login->setPassword(password); login->exec(); qDebug(); /*if (login->encryptionMode() == LoginJob::Unencrypted) { qDebug() << "Encrypted login not possible, try to log in without encryption"; login = new LoginJob( &session ); login->setUserName( user ); login->setPassword( password ); login->exec(); Q_ASSERT_X( login->error() == 0, "LoginJob", login->errorString().toLocal8Bit().constData() ); Q_ASSERT( session.state() == Session::Authenticated ); qDebug(); }*/ qDebug() << "Server greeting:" << session.serverGreeting(); qDebug() << "Asking for capabilities:"; auto capabilities = new CapabilitiesJob(&session); capabilities->exec(); Q_ASSERT_X(capabilities->error() == 0, "CapabilitiesJob", capabilities->errorString().toLocal8Bit().constData()); Q_ASSERT(session.state() == Session::Authenticated); qDebug() << capabilities->capabilities(); qDebug(); qDebug() << "Asking for namespaces:"; auto namespaces = new NamespaceJob(&session); namespaces->exec(); Q_ASSERT_X(namespaces->error() == 0, "CapabilitiesJob", namespaces->errorString().toLocal8Bit().constData()); Q_ASSERT(session.state() == Session::Authenticated); qDebug() << "Contains empty namespace:" << namespaces->containsEmptyNamespace(); qDebug() << "Personal:"; const auto personalNamespaces = namespaces->personalNamespaces(); for (MailBoxDescriptor ns : personalNamespaces) { qDebug() << ns.separator << ns.name; } qDebug() << "User: "; const auto userNamespaces = namespaces->userNamespaces(); for (MailBoxDescriptor ns : userNamespaces) { qDebug() << ns.separator << ns.name; } qDebug() << "Shared: "; const auto sharedNamespaces = namespaces->sharedNamespaces(); for (MailBoxDescriptor ns : sharedNamespaces) { qDebug() << ns.separator << ns.name; } qDebug(); qDebug() << "Listing mailboxes:"; listFolders(&session); Q_ASSERT(session.state() == Session::Authenticated); qDebug() << "Selecting INBOX:"; auto select = new SelectJob(&session); select->setMailBox(QStringLiteral("INBOX")); select->exec(); Q_ASSERT_X(select->error() == 0, "SelectJob", select->errorString().toLocal8Bit().constData()); Q_ASSERT(session.state() == Session::Selected); qDebug() << "Flags:" << select->flags(); qDebug() << "Permanent flags:" << select->permanentFlags(); qDebug() << "Total Number of Messages:" << select->messageCount(); qDebug() << "Number of recent Messages:" << select->recentCount(); qDebug() << "First Unseen Message Index:" << select->firstUnseenIndex(); qDebug() << "UID validity:" << select->uidValidity(); qDebug() << "Next UID:" << select->nextUid(); qDebug(); qDebug() << "Fetching first 3 messages headers:"; auto fetch = new FetchJob(&session); FetchJob::FetchScope scope; fetch->setSequenceSet(ImapSet(1, 3)); scope.parts.clear(); scope.mode = FetchJob::FetchScope::Headers; fetch->setScope(scope); QMap<qint64, qint64> sizes; QMap<qint64, MessagePtr> messages; QObject::connect(fetch, static_cast<HeadersReceivedSignal>(&FetchJob::headersReceived), fetch, [&](const QString &, const QMap<qint64, qint64> &, const QMap<qint64, qint64> &sizes_, const QMap<qint64, MessageFlags> &, const QMap<qint64, MessagePtr> &msgs_) { sizes = sizes_; messages = msgs_; }); fetch->exec(); Q_ASSERT_X(fetch->error() == 0, "FetchJob", fetch->errorString().toLocal8Bit().constData()); Q_ASSERT(session.state() == Session::Selected); const auto messagesKey = messages.keys(); for (qint64 id : messagesKey) { qDebug() << "* Message" << id << "(" << sizes[id] << "bytes )"; qDebug() << " From :" << messages[id]->from()->asUnicodeString(); qDebug() << " To :" << messages[id]->to()->asUnicodeString(); qDebug() << " Date :" << messages[id]->date()->asUnicodeString(); qDebug() << " Subject :" << messages[id]->subject()->asUnicodeString(); qDebug() << " Message-ID:" << messages[id]->messageID()->asUnicodeString(); } qDebug(); qDebug() << "Fetching first 3 messages flags:"; fetch = new FetchJob(&session); fetch->setSequenceSet(ImapSet(1, 3)); scope.parts.clear(); scope.mode = FetchJob::FetchScope::Flags; fetch->setScope(scope); QMap<qint64, MessageFlags> flags; QObject::connect(fetch, static_cast<HeadersReceivedSignal>(&FetchJob::headersReceived), fetch, [&](const QString &, const QMap<qint64, qint64> &, const QMap<qint64, qint64> &, const QMap<qint64, MessageFlags> &flags_, const QMap<qint64, MessagePtr> &) { flags = flags_; }); fetch->exec(); Q_ASSERT_X(fetch->error() == 0, "FetchJob", fetch->errorString().toLocal8Bit().constData()); Q_ASSERT(session.state() == Session::Selected); const auto flagsKey = flags.keys(); for (qint64 id : flagsKey) { qDebug() << "* Message" << id << "flags:" << flags[id]; } qDebug(); qDebug() << "Fetching first message structure:"; fetch = new FetchJob(&session); fetch->setSequenceSet(ImapSet(1)); scope.parts.clear(); scope.mode = FetchJob::FetchScope::Structure; fetch->setScope(scope); QObject::connect(fetch, static_cast<HeadersReceivedSignal>(&FetchJob::headersReceived), fetch, [&](const QString &, const QMap<qint64, qint64> &, const QMap<qint64, qint64> &, const QMap<qint64, MessageFlags> &, const QMap<qint64, MessagePtr> &msgs_) { messages = msgs_; }); fetch->exec(); Q_ASSERT_X(fetch->error() == 0, "FetchJob", fetch->errorString().toLocal8Bit().constData()); Q_ASSERT(session.state() == Session::Selected); MessagePtr message = messages[1]; dumpContentHelper(message.data()); qDebug(); qDebug() << "Fetching first message second part headers:"; fetch = new FetchJob(&session); fetch->setSequenceSet(ImapSet(1)); scope.parts.clear(); scope.parts << "2"; scope.mode = FetchJob::FetchScope::Headers; fetch->setScope(scope); QMap<qint64, MessageParts> allParts; QObject::connect(fetch, static_cast<PartsReceivedSignal>(&FetchJob::partsReceived), fetch, [&](const QString &, const QMap<qint64, qint64> &, const QMap<qint64, MessageParts> &parts_) { allParts = parts_; }); fetch->exec(); Q_ASSERT_X(fetch->error() == 0, "FetchJob", fetch->errorString().toLocal8Bit().constData()); Q_ASSERT(session.state() == Session::Selected); const auto allkeys = allParts.keys(); for (qint64 id : allkeys) { qDebug() << "* Message" << id << "parts headers"; MessageParts parts = allParts[id]; const auto parsKeys = parts.keys(); for (const QByteArray &partId : parsKeys) { qDebug() << " ** Part" << partId; qDebug() << " Name :" << parts[partId]->contentType()->name(); qDebug() << " Mimetype :" << parts[partId]->contentType()->mimeType(); qDebug() << " Description:" << parts[partId]->contentDescription()->asUnicodeString().simplified(); } } qDebug(); qDebug() << "Fetching first message second part content:"; fetch = new FetchJob(&session); fetch->setSequenceSet(ImapSet(1)); scope.parts.clear(); scope.parts << "2"; scope.mode = FetchJob::FetchScope::Content; fetch->setScope(scope); QObject::connect(fetch, static_cast<PartsReceivedSignal>(&FetchJob::partsReceived), fetch, [&](const QString &, const QMap<qint64, qint64> &, const QMap<qint64, MessageParts> &parts_) { allParts = parts_; }); fetch->exec(); Q_ASSERT_X(fetch->error() == 0, "FetchJob", fetch->errorString().toLocal8Bit().constData()); Q_ASSERT(session.state() == Session::Selected); const auto allpartskeys = allParts.keys(); for (int id : allpartskeys) { MessageParts parts = allParts[id]; const auto partsKeys = parts.keys(); for (const QByteArray &partId : partsKeys) { qDebug() << "* Message" << id << "part" << partId << "content:"; qDebug() << parts[partId]->body(); } } qDebug(); testDelete(&session); testSubscribe(&session); testRename(&session); testAppendAndStore(&session); testAcl(&session, user); testMetaData(&session); qDebug() << "Expunge INBOX:"; auto expunge = new ExpungeJob(&session); expunge->exec(); qDebug() << "Closing INBOX:"; auto close = new CloseJob(&session); close->exec(); Q_ASSERT(session.state() == Session::Authenticated); qDebug(); qDebug() << "Logging out..."; auto logout = new LogoutJob(&session); logout->exec(); Q_ASSERT_X(logout->error() == 0, "LogoutJob", logout->errorString().toLocal8Bit().constData()); Q_ASSERT(session.state() == Session::Disconnected); return 0; } 07070100000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000B00000000TRAILER!!!1981 blocks
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor